Browse Source

Timberline export for Purchase Orders

Kenric Nugteren 1 year ago
parent
commit
9f7f3808b2

+ 6 - 5
prs.classes/Entities/Bill/Bill.cs

@@ -21,8 +21,12 @@ namespace Comal.Classes
         
         [EditorSequence(4)]
         [DateEditor]
-        public DateTime PaymentDate { get; set; } 
-        
+        public DateTime PaymentDate { get; set; }
+
+        [EditorSequence(5)]
+        [DateEditor]
+        public DateTime AccountingDate { get; set; }
+
         [EditorSequence("Additional",1)]
         [TimestampEditor]
         public DateTime Checked { get; set; }
@@ -31,9 +35,6 @@ namespace Comal.Classes
         [TimestampEditor]
         public DateTime Approved { get; set; }
         
-        [EditorSequence("Additional",3)]
-        [DateEditor]
-        public DateTime AccountingDate { get; set; }
         
         [DoubleEditor(Editable = Editable.Hidden, Summary = Summary.Sum)]
         [Aggregate(typeof(BillExTax))]

+ 13 - 2
prs.classes/Entities/PurchaseOrder/PurchaseOrder.cs

@@ -76,7 +76,7 @@ namespace Comal.Classes
 
     [UserTracking(typeof(Bill))]
     public class PurchaseOrder : Entity, IRemotable, IPersistent, IStringAutoIncrement<PurchaseOrder>, IOneToMany<Supplier>,
-        ILicense<AccountsPayableLicense>, IScannable
+        ILicense<AccountsPayableLicense>, IScannable, IPostable
     {
         private bool bChanging;
 
@@ -149,7 +149,18 @@ namespace Comal.Classes
         [DoNotPersist]
         [DoNotSerialize]
         public static string PONumberPrefix { get; set; }
-        
+
+        [NullEditor]
+        [LoggableProperty]
+        public DateTime Posted { get; set; }
+
+        [NullEditor]
+        [LoggableProperty]
+        public PostedStatus PostedStatus { get; set; }
+
+        [NullEditor]
+        public string PostedNote { get; set; }
+
         public Expression<Func<PurchaseOrder, string>> AutoIncrementField() => x => x.PONumber;
         public Filter<PurchaseOrder> AutoIncrementFilter() => null;
         public string AutoIncrementPrefix() => PONumberPrefix;

+ 4 - 1
prs.desktop/Panels/Suppliers/SupplierPurchaseOrderPanel.xaml.cs

@@ -55,7 +55,10 @@ namespace PRSDesktop
 
         public void CreateToolbarButtons(IPanelHost host)
         {
-            //
+            PostUtils.CreateToolbarButtons(host,
+                () => (DataModel(Selection.Selected) as IDataModel<PurchaseOrder>)!,
+                () => Orders.Refresh(false, true),
+                true);
         }
 
         public string SectionName => "Purchase Orders";

+ 315 - 0
prs.shared/Posters/Timberline/PurchaseOrderTimberlinePoster.cs

@@ -0,0 +1,315 @@
+using Comal.Classes;
+using CsvHelper.Configuration.Attributes;
+using CsvHelper;
+using InABox.Core.Postable;
+using InABox.Core;
+using InABox.Poster.Timberline;
+using InABox.Scripting;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Win32;
+
+namespace PRS.Shared
+{
+    public class PurchaseOrderTimberlineHeader
+    {
+        [Ignore]
+        public List<PurchaseOrderTimberlineLine> Lines { get; set; } = new();
+
+        [Index(1)]
+        public string RecordID { get; set; } = "APIF";
+
+        [Index(2)]
+        public string Vendor { get; set; }
+
+        [Index(3)]
+        public string Invoice { get; set; }
+
+        [Index(4)]
+        public string Description { get; set; }
+
+        [Index(5)]
+        public double Amount { get; set; }
+
+        [Index(6)]
+        public double Tax { get; set; }
+
+        [Index(7)]
+        public double DiscountOffered { get; set; }
+
+        [Index(8)]
+        public double MiscDeduction { get; set; }
+
+        [Index(9)]
+        public DateTime InvoiceDate { get; set; }
+
+        [Index(10)]
+        public DateTime DateReceived { get; set; }
+
+        [Index(11)]
+        public DateTime DiscountDate { get; set; }
+
+        [Index(12)]
+        public DateTime PaymentDate { get; set; }
+
+        [Index(13)]
+        public DateTime AccountingDate { get; set; }
+
+        [Index(14)]
+        public string InvoiceCode1 { get; set; }
+
+        [Index(15)]
+        public string InvoiceCode2 { get; set; }
+
+        [Index(16)]
+        public string SmryPayeeName { get; set; }
+
+        [Index(17)]
+        public string SmryPayeeAddress1 { get; set; }
+
+        [Index(18)]
+        public string SmryPayeeAddress2 { get; set; }
+
+        [Index(19)]
+        public string SmryPayeeCity { get; set; }
+
+        [Index(20)]
+        public string SmryPayeeState { get; set; }
+
+        [Index(21)]
+        public string SmryPayeeZip { get; set; }
+    }
+
+    public class PurchaseOrderTimberlineLine
+    {
+        [Index(1)]
+        public string RecordID { get; set; } = "APDF";
+
+        [Index(2)]
+        public string Commitment { get; set; }
+
+        [Index(3)]
+        public int CommitmentLineItem { get; set; }
+
+        [Index(4)]
+        public string Equipment { get; set; }
+
+        [Index(5)]
+        public string EQCostCode { get; set; }
+
+        [Index(6)]
+        public string Job { get; set; }
+
+        [Index(7)]
+        public string Extra { get; set; }
+
+        [Index(8)]
+        public string CostCode { get; set; }
+
+        [Index(9)]
+        public string Category { get; set; }
+
+        [Index(10)]
+        public string BLStdItem { get; set; }
+
+        [Index(11)]
+        public string Reserved { get; set; }
+
+        [Index(12)]
+        public string ExpenseAccount { get; set; }
+
+        [Index(13)]
+        public string APAccount { get; set; }
+
+        [Index(14)]
+        public double TaxablePayments { get; set; }
+
+        [Index(15)]
+        public string TaxGroup { get; set; }
+
+        [Index(16)]
+        public double Units { get; set; }
+
+        [Index(17)]
+        public double UnitCost { get; set; }
+
+        [Index(18)]
+        public double Amount { get; set; }
+
+        [Index(19)]
+        public double Tax { get; set; }
+
+        [Index(20)]
+        public double TaxLiability { get; set; }
+
+        [Index(21)]
+        public double DiscountOffered { get; set; }
+
+        [Index(22)]
+        public double Retainage { get; set; }
+
+        [Index(23)]
+        public double MiscDeduction { get; set; }
+
+        [Index(24)]
+        [BooleanTrueValues("t", "T", "1", "Y", "y")]
+        [BooleanFalseValues("f", "F", "0", "N", "n")]
+        public bool TaxablePaymentsExempt { get; set; }
+
+        [Index(25)]
+        public string DistCode { get; set; }
+
+        [Index(26)]
+        public string MiscEntry1 { get; set; }
+
+        [Index(27)]
+        public double MiscEntryUnits1 { get; set; }
+
+        [Index(28)]
+        public string MiscEntry2 { get; set; }
+
+        [Index(29)]
+        public double MiscEntryUnits2 { get; set; }
+
+        [Index(30)]
+        public double MeterOdometer { get; set; }
+
+        [Index(31)]
+        public string Description { get; set; }
+
+        [Index(32)]
+        public string Authorization { get; set; }
+
+        [Index(33)]
+        public string JointPayee { get; set; }
+    }
+
+    public class PurchaseOrderTimberlineSettings : TimberlinePosterSettings<PurchaseOrder>
+    {
+        protected override string DefaultScript()
+        {
+            return @"
+using PRS.Shared;
+using InABox.Core;
+using System.Collections.Generic;
+
+public class Module
+{
+    public void BeforePost(IDataModel<PurchaseOrder> model)
+    {
+        // Perform pre-processing
+    }
+
+    public void ProcessHeader(IDataModel<PurchaseOrder> model, PurchaseOrder purchaseOrder, PurchaseOrderTimberlineHeader header)
+    {
+        // Do extra processing for a purchase order
+    }
+
+    public void ProcessLine(IDataModel<PurchaseOrder> model, PurchaseOrderItem purchaseOrderItem, PurchaseOrderTimberlineLine line)
+    {
+        // Do extra processing for a purchase order line
+    }
+
+    public void AfterPost(IDataModel<PurchaseOrder> model)
+    {
+        // Perform post-processing
+    }
+}";
+        }
+    }
+
+    public class PurchaseOrderTimberlinePoster : ITimberlinePoster<PurchaseOrder, PurchaseOrderTimberlineSettings>
+    {
+        public ScriptDocument? Script { get; set; }
+
+        public bool BeforePost(IDataModel<PurchaseOrder> model)
+        {
+            model.SetIsDefault<Document>(false, alias: "CompanyLogo");
+            model.SetIsDefault<CoreTable>(false, alias: "CompanyInformation");
+            model.SetIsDefault<Employee>(false);
+
+            Script?.Execute(methodname: "BeforePost", parameters: new object[] { model });
+            return true;
+        }
+
+        private void ProcessHeader(IDataModel<PurchaseOrder> model, PurchaseOrder bill, PurchaseOrderTimberlineHeader header)
+        {
+            Script?.Execute(methodname: "ProcessHeader", parameters: new object[] { model, bill, header });
+        }
+        private void ProcessLine(IDataModel<PurchaseOrder> model, PurchaseOrderItem purchaseOrderItem, PurchaseOrderTimberlineLine line)
+        {
+            Script?.Execute(methodname: "ProcessLine", parameters: new object[] { model, purchaseOrderItem, line });
+        }
+
+        private List<PurchaseOrderTimberlineHeader> DoProcess(IDataModel<PurchaseOrder> model)
+        {
+            var cs = new List<PurchaseOrderTimberlineHeader>();
+
+            var lines = model.GetTable<PurchaseOrderItem>("PurchaseOrder_PurchaseOrderItem").ToObjects<PurchaseOrderItem>()
+                .GroupBy(x => x.PurchaseOrderLink.ID).ToDictionary(x => x.Key, x => x.ToList());
+            foreach (var purchaseOrder in model.GetTable<PurchaseOrder>().ToObjects<PurchaseOrder>())
+            {
+                var c = new PurchaseOrderTimberlineHeader
+                {
+                };
+                ProcessHeader(model, purchaseOrder, c);
+
+                foreach (var purchaseOrderItem in lines.GetValueOrDefault(purchaseOrder.ID) ?? Enumerable.Empty<PurchaseOrderItem>())
+                {
+                    var ci = new PurchaseOrderTimberlineLine
+                    {
+                    };
+
+                    ProcessLine(model, purchaseOrderItem, ci);
+                    c.Lines.Add(ci);
+                }
+                cs.Add(c);
+            }
+            return cs;
+        }
+
+        public bool Process(IDataModel<PurchaseOrder> model)
+        {
+            var cs = DoProcess(model);
+
+            var dlg = new SaveFileDialog()
+            {
+                Filter = "CSV Files (*.csv)|*.csv"
+            };
+
+            if (dlg.ShowDialog() == true)
+            {
+                using var writer = new StreamWriter(dlg.FileName);
+                using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
+                foreach (var c in cs)
+                {
+                    csv.WriteRecord(c);
+                    csv.NextRecord();
+                    foreach (var ci in c.Lines)
+                    {
+                        csv.WriteRecord(ci);
+                        csv.NextRecord();
+                    }
+                }
+                return true;
+            }
+            else
+            {
+                throw new PostCancelledException();
+            }
+        }
+        public void AfterPost(IDataModel<PurchaseOrder> model)
+        {
+            Script?.Execute(methodname: "AfterPost", parameters: new object[] { model });
+        }
+    }
+
+    public class PurchaseOrderTimberlinePosterEngine<T> : TimberlinePosterEngine<PurchaseOrder, PurchaseOrderTimberlineSettings>
+    {
+    }
+}