Jelajahi Sumber

Added some TImberline export formats to prs.media.
Changed logic in stockmovement export to think about whole transactions.
Started to write code for loading Bill Export Reject file

Kenric Nugteren 1 tahun lalu
induk
melakukan
71cbc0a3fa

+ 130 - 0
prs.media/TimberlineExportFiles/AP Import field table.pdf

@@ -0,0 +1,130 @@
+Import Invoices Format journal example (Fixed format)                  Page 1 of 3
+
+Import Invoices Format journal example (Fixed format)
+
+Accounts Payable Import Invoices
+
+APIF, Vendor, Invoice, Description, Amount, Tax, Discount Offered, Misc Deduction, Invoice Date, Date Received, Discount
+Date, Payment Date, Accounting Date, Invoice Code 1, Invoice Code 2, Smry Payee Name, Smry Payee Address 1, Smry
+Payee Address 2, Smry Payee City, Smry Payee State, Smry Payee ZIP
+
+APDF, Commitment, Commitment Line Item, Equipment, EQ Cost Code, Job, Extra, Cost Code, Category, BL Std Item,
+Property, Expense Account, Accounts Payable Account, Taxable Payments, Tax Group, Units, Unit Cost, Amount, Tax, Tax
+Liability, Discount Offered, , Misc Deduction, Taxable Payments Exempt, Dist Code, Draw, Misc Entry #1, Misc Entry Units #1,
+Misc Entry #2, Misc Entry Units #2, Meter/Odometer, Description, Authorization, Joint Payee
+
+APTXF, Tax Item, Tax Amount, Tax Liability
+
+Description                     Field type             Maximum length  Usage notes
+
+Record ID 'APIF' – API invoice
+
+APIF                            Alpha                  4               Always Required
+Vendor                                                                 Always Required
+Invoice                         Alpha                  10              Always Required
+Description
+Amount                          Alpha                  15
+Tax
+Discount Offered                Alpha                  30
+Misc. Deduction
+Invoice Date                    Numeric                -9.2
+Date Received
+Discount Date                   Numeric                -7.2
+Payment Date
+Accounting Date                 Numeric                -7.2
+Invoice Code 1
+Invoice Code 2                  Numeric                -7.2
+Smry Payee Name
+Smry Payee Address 1            Date
+Smry Payee Address 2
+Smry Payee City                 Date
+
+                                Date
+
+                                Date
+
+                                Date
+
+                                Alpha                  10
+
+                                Alpha                  10
+
+                                Alpha                  30
+
+                                Alpha                  33
+
+                                Alpha                  33
+
+                                Alpha                  15
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\AP.c... 7/08/2023
+Import Invoices Format journal example (Fixed format)                    Page 2 of 3
+
+   Smry Payee State                  Alpha             4        Always required
+   Smry Payee Zip                                               xx-xxxx
+Record ID 'APDF' – API distribution  Alpha             10       xx-xxx
+   APDF                                                         xx-xxx
+   Commitment                        Alpha             4        xx-xxx
+   Commitment Line Item              Alpha             12       Not used.
+   Equipment                         Numeric                    xx-xxxx
+   EQ Cost Code                      Alpha-Numeric        5     xx-xxxx
+   Job                               Alpha-Numeric        7
+   Extra                             Alpha-Numeric        6     Formats can be:
+   Cost Code                         Alpha                6     t, T, 1, Y, y, f, F, N, n, 0
+   Category                          Alpha-Numeric        10
+   BL Std Item                       Alpha                6
+   Reserved                          Alpha                3
+   Expense Account                   Alpha-Numeric        10
+   AP Account                        Alpha                8
+   Taxable Payments                  Alpha                7
+   Tax Group                         Numeric              7
+   Units                             Alpha                2.3
+   Unit Cost                         Numeric              6
+   Amount                            Numeric              -8.4
+   Tax                               Numeric              -6.4
+   Tax Liability                     Numeric              -9.2
+   Discount Offered                  Numeric              -7.2
+   Retainage                         Numeric              -7.2
+   Misc Deduction                    Numeric              -7.2
+   Taxable Payments Exempt           Numeric              -7.2
+                                     Check Box            -7.2
+   Dist Code
+                                     Alpha                10
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\AP.c... 7/08/2023
+Import Invoices Format journal example (Fixed format)        Page 3 of 3
+
+                                          Alpha        10
+
+Misc Entry #1                             Alpha        10
+
+Misc Entry Units #1                       Alpha        -8.4
+
+Misc Entry #2                             Alpha        10
+
+Misc Entry Units #2                       Numeric      -8.4
+
+Meter/Odometer                            Numeric      7.2
+
+Description                               Alpha        30
+
+Authorization                             Alpha        10
+
+Joint Payee                               Alpha        30
+
+Record ID 'APTXF' – API tax distribution
+
+APTXF                                     Alpha        5
+Tax Intern
+Tax Amount                                Alpha        6
+Tax Liability
+                                          Numeric      -7.2
+
+                                          Numeric      -7.2
+
+ More resources
+You can visit Sage City to join product discussions, search articles in the Sage knowledgebase, or chat online with an expert.
+For additional training on Sage products, visit Sage University.
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\AP.c... 7/08/2023
+

+ 66 - 0
prs.media/TimberlineExportFiles/JC - Direct cost Import layout.pdf

@@ -0,0 +1,66 @@
+Direct cost                                                             Page 1 of 2
+
+Direct cost
+
+Items required to be entered are marked as such in the Comment column.
+
+Number       Type     Length  Item                                      Comment
+1            alpha    2       record ID                                 required, must be DC. In a GL only entry, must
+                                                                        be GL.
+2            alpha    10      job ID                                    required, ID separators can be entered or omitted
+                                                                        ID separators can be entered or omitted
+3            alpha    10      extra ID                                  required, ID separators can be entered or omitted
+                                                                        required, if using categories
+4            alpha    12      cost code                                 see 1st Note below
+                                                                        if blank, system date is used
+5            alpha    3       category                                  if blank, the Job Cost period end date is used
+                                                                        leave blank to retrieve from
+6            list     1       transaction type                          standard item, if used
+                                                                        required if unit cost entered
+7            date     10      transaction date                          required only if no amount; leave
+                                                                        blank to retrieve from units-based
+8            date     10      accounting date                           standard item, if used
+                                                                        required, defaults to units times unit cost if not
+9            alpha    30      description                               entered; leave
+                                                                        blank to retrieve from amounts-
+10           numeric  8.4     units                                     based standard item, if used
+                                                                        required if interfacing with GL and
+11           numeric  6.4     unit cost                                 account cannot be retrieved
+
+12           numeric  9.2     amount                                    when importing inventory costs from Purchasing
+                                                                        & Inventory (PO/IV), the Posting Sequence is
+13           alpha    25      debit account                             used
+
+                              see Notes below                           if used, must be setup in the Billing application
+
+14           alpha    25      credit account
+
+                              see Notes below
+
+15           alpha    10      reference 1
+
+16           alpha    10      reference 2
+
+17           alpha    10      standard item
+
+        Notes:
+
+               Transaction types: 1 = AP Cost, 2 = JC Cost, 3 = PR Cost, 4 = EQ Cost, and 5 = IV Cost.
+               The default is AP Cost. Also, if extras and/or categories are not used, they must still be represented by
+               comma separators.
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\JC.... 29/11/2023
+Direct cost  Page 2 of 2
+
+                   If you have specified in the GL Entry Settings window that the cost account is to be retrieved, no debit
+                   account is required. If no valid debit account can be retrieved, you must enter the debit account or the
+                   transaction is rejected.
+                   If you have specified in the Import Settings window that a balanced import file is required, then total debits
+                   must equal total credits in the import file or all records are rejected.
+
+ More resources
+You can visit Sage City to join product discussions, search articles in the Sage knowledgebase, or chat online with an expert.
+For additional training on Sage products, visit Sage University.
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\JC.... 29/11/2023
+

+ 21 - 0
prs.media/TimberlineExportFiles/JC -GL entry Import layout.pdf

@@ -0,0 +1,21 @@
+GL-only entry                                                                    Page 1 of 1
+
+GL-only entry
+
+Number         Type     Length  Item              Comment
+1              alpha    2       record ID         required, must be GL
+2              date     10      transaction date  if blank, system date is used
+3              date     10      accounting date   if blank, JC End date is used
+4              alpha    30      description       optional
+5              numeric  9.2     amount            required
+6              alpha    25      debit account     required if no credit account
+7              alpha    25      credit account    required if no debit account
+8              alpha    10      reference 1
+9              alpha    10      reference 2
+
+ More resources
+You can visit Sage City to join product discussions, search articles in the Sage knowledgebase, or chat online with an expert.
+For additional training on Sage products, visit Sage University.
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\JC.... 29/11/2023
+

+ 20 - 0
prs.media/TimberlineExportFiles/JC-Import direct cost example.pdf

@@ -0,0 +1,20 @@
+Import direct costs example  Page 1 of 1
+
+Import direct costs example
+
+;This is a comment in a sample import file
+;The next line is purposely split over two physical lines
+DC, 93120, , 01100, MAT, 2, 09/14/1995, 09/30/1995, +
+"weatherstripping, 12 ft.", 12, 2.2, 26.40, 01-825, 01-101
+;The next line wraps by itself
+DC, 93-433, , 02-100, LAB, 3, 091295, 093095, OT for Perry,3.25, 19.5, 63.38, 01-224, 01-835
+;The next line is a GL-only entry
+GL, 092395, 093095, Interco xfer, 1539.25, 01-830, 02-830, 5017
+
+  More resources
+ You can visit Sage City to join product discussions, search articles in the Sage knowledgebase, or chat online with an
+ expert.
+ For additional training on Sage products, visit Sage University.
+
+mk:@MSITStore:C:\Program%20Files%20(x86)\Timberline%20Office\Shared\Help\JC.... 29/11/2023
+

+ 122 - 46
prs.shared/Posters/Timberline/StockMovementTimberlinePoster.cs

@@ -16,6 +16,7 @@ using System.Threading.Tasks;
 using System.Windows;
 using Microsoft.Win32;
 using CsvHelper.TypeConversion;
+using NPOI.SS.Formula.Functions;
 
 namespace PRS.Shared
 {
@@ -283,7 +284,7 @@ public class Module
 
             var firstMovements = model.GetTable<StockMovement>();
             var full = model.GetTable<StockMovement>("FullTransactions")
-                .ToObjects<StockMovement>();
+                .ToObjects<StockMovement>().GroupBy(x => x.Transaction);
             var products = model.GetTable<Product>().ToObjects<Product>()
                 .ToDictionary(x => x.ID, x => x);
             var jobs = model.GetTable<Job>().ToObjects<Job>()
@@ -291,66 +292,141 @@ public class Module
             var batches = model.GetTable<StockMovementBatch>().ToObjects<StockMovementBatch>()
                 .ToDictionary(x => x.ID, x => x);
 
-            foreach (var movement in full)
+            StockMovementTimberlineDirectCost CreateDirectCost(StockMovement movement)
             {
-                if (!movement.IsTransfer)
-                {
-                    result.AddSuccess(movement, null);
-                    continue;
-                }
+                var job = jobs[movement.Job.ID];
+                var product = products[movement.Product.ID];
 
-                var batch = batches.GetValueOrDefault(movement.Batch.ID);
-                if (batch is not null && batch.Type == StockMovementBatchType.Receipt)
+                var directCost = new StockMovementTimberlineDirectCost
                 {
-                    result.AddSuccess(movement, null);
-                    continue;
-                }
-
-                IStockMovementTimberlineLine line;
+                    Job = job.JobNumber,
+                    Extra = "",
+                    CostCode = product.CostCentre.Code,
+                    Category = "",
+                    Units = movement.Units,
+                    UnitCost = movement.Cost,
+                    // TransactionType = ???
+                };
+                return ModifyLine(directCost, movement);
+            }
+            T ModifyLine<T>(T line, StockMovement movement)
+                where T : IStockMovementTimberlineLine
+            {
                 var product = products[movement.Product.ID];
-                if (movement.Job.ID != Guid.Empty)
-                {
-                    var job = jobs[movement.Job.ID];
-                    var directCost = new StockMovementTimberlineDirectCost
-                    {
-                        Job = job.JobNumber,
-                        Extra = "",
-                        CostCode = product.CostCentre.Code,
-                        Category = "",
-                        Units = movement.Units,
-                        UnitCost = movement.Cost,
-                        // TransactionType = ???
-                    };
-                    line = directCost;
-                }
-                else
-                {
-                    line = new StockMovementTimberlineGL
-                    {
-                    };
-                }
+                var batch = batches.GetValueOrDefault(movement.Batch.ID);
+
                 line.TransactionDate = movement.Date;
                 line.Description = product.Name;
                 line.Amount = movement.Value;
                 line.CreditAccount = product.PurchaseGL.Code;
                 line.BatchType = batch?.Type ?? StockMovementBatchType.Transfer;
+                return line;
+            }
 
-                bool success = true;
-                if (line is StockMovementTimberlineDirectCost dc)
-                {
-                    success = ProcessDirectCostLine(model, movement, dc);
-                }
-                else if (line is StockMovementTimberlineGL gl)
+            foreach (var transaction in full)
+            {
+                var movements = new List<StockMovement>();
+                foreach(var movement in transaction)
                 {
-                    success = ProcessGLLine(model, movement, gl);
+                    if (!movement.IsTransfer)
+                    {
+                        // Ignore these ones.
+                        result.AddSuccess(movement, null);
+                    }
+                    else
+                    {
+                        movements.Add(movement);
+                    }
                 }
-                if (success)
+
+                if(movements.Count == 1)
                 {
-                    result.AddSuccess(movement, line);
+                    var mvt = movements[0];
+                    var batch = batches.GetValueOrDefault(mvt.Batch.ID);
+                    if(batch is null)
+                    {
+                        // What to do?
+                    }
+
+                    if(batch?.Type == StockMovementBatchType.Stocktake)
+                    {
+                        if(mvt.Job.ID == Guid.Empty)
+                        {
+                            var gl = new StockMovementTimberlineGL { };
+                            gl = ModifyLine(gl, mvt);
+                            if (ProcessGLLine(model, mvt, gl))
+                            {
+                                result.AddSuccess(mvt, gl);
+                            }
+                            else
+                            {
+                                result.AddFailed(mvt, "Failed by script.");
+                            }
+                        }
+                        else
+                        {
+                            var dc = CreateDirectCost(mvt);
+                            if (ProcessDirectCostLine(model, mvt, dc))
+                            {
+                                result.AddSuccess(mvt, dc);
+                            }
+                            else
+                            {
+                                result.AddFailed(mvt, "Failed by script.");
+                            }
+                        }
+                    }
+                    else
+                    {
+                        result.AddSuccess(mvt, null);
+                    }
                 }
-                else
+                else if(movements.Count == 2)
                 {
-                    result.AddFailed(movement, "Failed by script.");
+                    var mvtFrom = movements[0];
+                    var mvtTo = movements[1];
+                    if(mvtFrom.Job.ID == mvtTo.Job.ID)
+                    {
+                        // Ignore these ones.
+                        result.AddSuccess(mvtFrom, null);
+                        result.AddSuccess(mvtTo, null);
+                    }
+                    else if(mvtFrom.Job.ID == Guid.Empty || mvtTo.Job.ID == Guid.Empty)
+                    {
+                        var jobMvt = mvtFrom.Job.ID == Guid.Empty ? mvtTo : mvtFrom;
+
+                        var directCost = CreateDirectCost(jobMvt);
+                        if(ProcessDirectCostLine(model, jobMvt, directCost))
+                        {
+                            result.AddSuccess(jobMvt, directCost);
+                        }
+                        else
+                        {
+                            result.AddFailed(jobMvt, "Failed by script.");
+                        }
+                    }
+                    else
+                    {
+                        var directCostFrom = CreateDirectCost(mvtFrom);
+                        var directCostTo = CreateDirectCost(mvtTo);
+
+                        if (ProcessDirectCostLine(model, mvtFrom, directCostFrom))
+                        {
+                            result.AddSuccess(mvtFrom, directCostFrom);
+                        }
+                        else
+                        {
+                            result.AddFailed(mvtFrom, "Failed by script.");
+                        }
+                        if (ProcessDirectCostLine(model, mvtTo, directCostTo))
+                        {
+                            result.AddSuccess(mvtTo, directCostTo);
+                        }
+                        else
+                        {
+                            result.AddFailed(mvtTo, "Failed by script.");
+                        }
+                    }
                 }
             }