using Comal.Classes; using InABox.Core; using InABox.Poster.MYOB; using MYOB.AccountRight.SDK.Contracts.Version2.Sale; using MYOB.AccountRight.SDK.Services.Contact; using MYOB.AccountRight.SDK.Services.GeneralLedger; using MYOB.AccountRight.SDK.Services.Sale; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Invoice = Comal.Classes.Invoice; using InvoiceLine = Comal.Classes.InvoiceLine; using MYOBAccount = MYOB.AccountRight.SDK.Contracts.Version2.GeneralLedger.Account; using MYOBInvoice = MYOB.AccountRight.SDK.Contracts.Version2.Sale.ServiceInvoice; using MYOBInvoiceLine = MYOB.AccountRight.SDK.Contracts.Version2.Sale.ServiceInvoiceLine; using MYOBTaxCode = MYOB.AccountRight.SDK.Contracts.Version2.GeneralLedger.TaxCode; namespace PRS.Shared.Posters.MYOB; public class InvoiceMYOBPosterSettings : MYOBPosterSettings { } public class InvoiceMYOBPoster : IMYOBPoster { public MYOBConnectionData ConnectionData { get; set; } public InvoiceMYOBPosterSettings Settings { get; set; } public MYOBGlobalPosterSettings GlobalSettings { get; set; } public bool BeforePost(IDataModel model) { foreach (var (_, table) in model.ModelTables) { table.IsDefault = false; } model.SetIsDefault(true); model.SetColumns(RequiredInvoiceColumns()); model.SetIsDefault(true, alias: "Invoice_InvoiceLine"); model.SetColumns(RequiredInvoiceLineColumns()); model.SetIsDefault(true, alias: "Invoice_Customer"); model.SetColumns(RequiredCustomerColumns()); return true; } private static Columns RequiredInvoiceColumns() { return Columns.None() .Add(x => x.ID) .Add(x => x.PostedReference) .Add(x => x.Number) .Add(x => x.Date) .Add(x => x.CustomerLink.ID) .Add(x => x.Description); } private static Columns RequiredInvoiceLineColumns() { return Columns.None() .Add(x => x.ID) .Add(x => x.InvoiceLink.ID) .Add(x => x.Description) .Add(x => x.IncTax) .Add(x => x.SellGL.ID) .Add(x => x.SellGL.Code) .Add(x => x.SellGL.PostedReference) .Add(x => x.TaxCode.ID) .Add(x => x.TaxCode.Code) .Add(x => x.TaxCode.PostedReference); } private static Columns RequiredCustomerColumns() { return CustomerMYOBPoster.RequiredColumns(); } public IPostResult Process(IDataModel model) { // Documentation: https://developer.myob.com/api/myob-business-api/v2/sale/invoice/invoice_service/ var results = new PostResult(); var service = new ServiceInvoiceService(ConnectionData.Configuration, null, ConnectionData.AuthKey); var invoices = model.GetTable().ToArray(); var customers = model.GetTable("Invoice_Customer") .ToObjects().ToDictionary(x => x.ID); var invoiceLines = model.GetTable("Invoice_InvoiceLine") .ToObjects() .GroupBy(x => x.InvoiceLink.ID) .ToDictionary(x => x.Key, x => x.ToArray()); foreach(var invoice in invoices) { MYOBInvoice myobInvoice; if(Guid.TryParse(invoice.PostedReference, out var myobID)) { if(!service.Get(ConnectionData, myobID).Get(out var newInvoice, out var error)) { CoreUtils.LogException("", error, $"Failed to find Invoice in MYOB with id {myobID}"); results.AddFailed(invoice, $"Failed to find Invoice in MYOB with id {myobID}: {error.Message}"); continue; } myobInvoice = newInvoice; } else { myobInvoice = new MYOBInvoice(); } myobInvoice.Number = invoice.Number.ToString().Truncate(13); myobInvoice.Date = invoice.Date; // myobInvoice.CustomerPurchaseOrderNumber = if(customers.TryGetValue(invoice.CustomerLink.ID, out var customer)) { if(!CustomerMYOBPoster.MapCustomer(ConnectionData, customer).Get(out var customerID, out var error)) { CoreUtils.LogException("", error, $"Error while posting invoice {invoice.ID}"); results.AddFailed(invoice, error.Message); continue; } myobInvoice.Customer.UID = customerID; } // myobInvoice.PromisedDate = if(invoiceLines.TryGetValue(invoice.ID, out var lines)) { var newLines = new MYOBInvoiceLine[lines.Length]; string? failed = null; for(int i = 0; i < lines.Length; ++i) { var item = lines[i]; var line = new MYOBInvoiceLine(); line.Type = InvoiceLineType.Transaction; line.Description = item.Description; // line.UnitOfMeasure = // line.UnitCount = // line.UnitPrice = // line.UnitPriceForeign = // line.DiscountPercent = line.Total = (decimal)item.IncTax; line.TotalForeign = 0; if(item.SellGL.ID == Guid.Empty) { failed = "Not all lines have a SellGL code set."; break; } if(!Guid.TryParse(item.SellGL.PostedReference, out var accountID)) { if (!ConnectionData.GetUID( new Filter(x => x.DisplayID).IsEqualTo(item.SellGL.Code)) .Get(out accountID, out var error)) { CoreUtils.LogException("", error, $"Failed to find Account in MYOB with code {item.SellGL.Code}"); failed = $"Failed to find Account in MYOB with code {item.SellGL.Code}: {error.Message}"; break; } else if (accountID == Guid.Empty) { failed = $"Failed to find Account in MYOB with code {item.SellGL.Code}"; break; } else { results.AddFragment(new GLCode { ID = item.SellGL.ID, PostedReference = accountID.ToString() }); } } line.Account.UID = accountID; if(item.TaxCode.ID == Guid.Empty) { failed = "Not all lines have a TaxCode set."; break; } if(!Guid.TryParse(item.TaxCode.PostedReference, out var taxCodeID)) { if (!ConnectionData.GetUID( new Filter(x => x.Code).IsEqualTo(item.TaxCode.Code)) .Get(out taxCodeID, out var error)) { CoreUtils.LogException("", error, $"Failed to find TaxCode in MYOB with code {item.TaxCode.Code}"); failed = $"Failed to find TaxCode in MYOB with code {item.TaxCode.Code}: {error.Message}"; break; } else if (taxCodeID == Guid.Empty) { failed = $"Failed to find TaxCode in MYOB with code {item.TaxCode.Code}"; break; } results.AddFragment(new TaxCode { ID = taxCodeID, PostedReference = taxCodeID.ToString() }); } line.TaxCode.UID = taxCodeID; newLines[i] = line; } if(failed is not null) { results.AddFailed(invoice, failed); continue; } myobInvoice.Lines = newLines; } else { myobInvoice.Lines = []; } // ShipToAddress // Terms myobInvoice.IsTaxInclusive = true; // Freight // FreightTaxCode // Category // Salesperson myobInvoice.Comment = invoice.Description; // ShippingMethod // JournalMemo // ReferralSource // InvoiceDeliveryStatus // CanApplySurcharge myobInvoice.InvoiceType = InvoiceLayoutType.Service; // Order // OnlinePaymentMethod try { var result = service.Update(ConnectionData.CompanyFile, myobInvoice, ConnectionData.CompanyFileCredentials); results.AddSuccess(invoice); } catch (Exception e) { CoreUtils.LogException("", e, $"Error while posting invoice {invoice.ID}"); results.AddFailed(invoice, e.Message); } } return results; } } public class InvoiceMYOBPosterEngine : MYOBPosterEngine { }