123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- using Comal.Classes;
- using InABox.Core;
- using InABox.Core.Postable;
- using InABox.Poster.MYOB;
- using InABox.Scripting;
- using MYOB.AccountRight.SDK.Contracts.Version2.Sale;
- using MYOB.AccountRight.SDK.Services.GeneralLedger;
- using MYOB.AccountRight.SDK.Services.Purchase;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using MYOBPurchaseOrder = MYOB.AccountRight.SDK.Contracts.Version2.Purchase.ServicePurchaseOrder;
- using MYOBPurchaseOrderItem = MYOB.AccountRight.SDK.Contracts.Version2.Purchase.ServicePurchaseOrderLine;
- using MYOBTaxCode = MYOB.AccountRight.SDK.Contracts.Version2.GeneralLedger.TaxCode;
- namespace PRS.Shared.Posters.MYOB;
- public class PurchaseOrderMYOBPosterSettings : MYOBPosterSettings
- {
- public override string DefaultScript(Type TPostable)
- {
- return @"using MYOBPurchaseOrder = MYOB.AccountRight.SDK.Contracts.Version2.Purchase.ServicePurchaseOrder;
- using MYOBPurchaseOrderItem = MYOB.AccountRight.SDK.Contracts.Version2.Purchase.ServicePurchaseOrderLine;
- public class Module
- {
- public void BeforePost(IDataModel<PurchaseOrder> model)
- {
- // Perform pre-processing
- }
- public void ProcessPurchaseOrder(IDataModel<PurchaseOrder> model, PurchaseOrder purchaseOrder, MYOBPurchaseOrder myobPurchaseOrder)
- {
- // Do extra processing for a purchase order; throw an exception to fail this purchase order.
- }
- public void ProcessPurchaseOrderItem(IDataModel<PurchaseOrder> model, PurchaseOrderItem purchaseOrderItem, MYOBPurchaseOrderItem myobPurchaseOrderItem)
- {
- // Do extra processing for a purchase order item; throw an exception to fail this purchase order item (and thus fail the entire purchase order)
- }
- }";
- }
- }
- public class PurchaseOrderMYOBPoster : IMYOBPoster<PurchaseOrder, PurchaseOrderMYOBPosterSettings>
- {
- public ScriptDocument? Script { get; set; }
- public MYOBConnectionData ConnectionData { get; set; }
- public PurchaseOrderMYOBPosterSettings Settings { get; set; }
- public MYOBGlobalPosterSettings GlobalSettings { get; set; }
- public bool BeforePost(IDataModel<PurchaseOrder> model)
- {
- foreach (var (_, table) in model.ModelTables)
- {
- table.IsDefault = false;
- }
- model.SetIsDefault<PurchaseOrder>(true);
- model.SetColumns<PurchaseOrder>(RequiredPurchaseOrderColumns());
- model.SetIsDefault<PurchaseOrderItem>(true, alias: "PurchaseOrder_PurchaseOrderItem");
- model.SetColumns<PurchaseOrderItem>(RequiredPurchaseOrderItemColumns(), alias: "PurchaseOrder_PurchaseOrderItem");
- model.SetIsDefault<Supplier>(true, alias: "PurchaseOrder_Supplier");
- model.SetColumns<Supplier>(RequiredSupplierColumns(), alias: "PurchaseOrder_Supplier");
- Script?.Execute(methodname: "BeforePost", parameters: new object[] { model });
- return true;
- }
- #region Script Functions
- private Result<Exception> ProcessPurchaseOrder(IDataModel<PurchaseOrder> model, PurchaseOrder po, MYOBPurchaseOrder myobPO)
- {
- return this.WrapScript("ProcessPurchaseOrder", model, po, myobPO);
- }
- private Result<Exception> ProcessPurchaseOrderItem(IDataModel<PurchaseOrder> model, PurchaseOrderItem poItem, MYOBPurchaseOrderItem myobPOItem)
- {
- return this.WrapScript("ProcessPurchaseOrderItem", model, poItem, myobPOItem);
- }
- #endregion
- private static Columns<PurchaseOrder> RequiredPurchaseOrderColumns()
- {
- return Columns.None<PurchaseOrder>()
- .Add(x => x.ID)
- .Add(x => x.PostedReference)
- .Add(x => x.IssuedDate)
- .Add(x => x.PONumber)
- .Add(x => x.SupplierLink.ID)
- .Add(x => x.Description);
- }
- private static Columns<PurchaseOrderItem> RequiredPurchaseOrderItemColumns()
- {
- return Columns.None<PurchaseOrderItem>()
- .Add(x => x.ID)
- .Add(x => x.PurchaseOrderLink.ID)
- .Add(x => x.Description)
- .Add(x => x.IncTax)
- .Add(x => x.PurchaseGL.ID)
- .Add(x => x.PurchaseGL.Code)
- .Add(x => x.PurchaseGL.PostedReference)
- .Add(x => x.TaxCode.ID)
- .Add(x => x.TaxCode.Code)
- .Add(x => x.TaxCode.PostedReference);
- }
- private static Columns<Supplier> RequiredSupplierColumns()
- {
- return SupplierMYOBPoster.RequiredColumns();
- }
- public IPostResult<PurchaseOrder> Process(IDataModel<PurchaseOrder> model)
- {
- var results = new PostResult<PurchaseOrder>();
- var service = new ServicePurchaseOrderService(ConnectionData.Configuration, null, ConnectionData.AuthKey);
- var pos = model.GetTable<PurchaseOrder>().ToArray<PurchaseOrder>();
- if(pos.Any(x => x.IssuedDate.IsEmpty()))
- {
- throw new PostFailedMessageException($"We can't process unissued purchase orders; please set [{nameof(PurchaseOrder.IssuedDate)}] for" +
- $" all purchase orders before processing.");
- }
- var poItems = model.GetTable<PurchaseOrderItem>("PurchaseOrder_PurchaseOrderItem")
- .ToObjects<PurchaseOrderItem>().GroupBy(x => x.PurchaseOrderLink.ID).ToDictionary(x => x.Key, x => x.ToArray());
- var suppliers = model.GetTable<Supplier>("PurchaseOrder_Supplier")
- .ToObjects<Supplier>().ToDictionary(x => x.ID);
- foreach(var po in pos)
- {
- MYOBPurchaseOrder myobPO;
- Exception? error;
- bool isNew;
- if(Guid.TryParse(po.PostedReference, out var myobID))
- {
- if(!service.Get(ConnectionData, myobID).Get(out var newPO, out error))
- {
- CoreUtils.LogException("", error, $"Failed to find Purchase Order in MYOB with id {myobID}");
- results.AddFailed(po, $"Failed to find Purchase Order in MYOB with id {myobID}: {error.Message}");
- continue;
- }
- myobPO = newPO;
- isNew = false;
- }
- else
- {
- myobPO = new MYOBPurchaseOrder();
- isNew = true;
- }
- myobPO.Number = po.PONumber.Truncate(13);
- myobPO.Date = po.IssuedDate;
- // myobPO.SupplierInvoiceNumber
- if(suppliers.TryGetValue(po.SupplierLink.ID, out var supplier))
- {
- if(!SupplierMYOBPoster.MapSupplier(ConnectionData, supplier, GlobalSettings).Get(out var supplierID, out error))
- {
- CoreUtils.LogException("", error, $"Error while posting purchase order {po.ID}");
- results.AddFailed(po, error.Message);
- continue;
- }
- myobPO.Supplier ??= new();
- myobPO.Supplier.UID = supplierID;
- results.AddFragment(supplier, supplier.PostedStatus);
- }
- // myobPO.ShipToAddress =
- // myobPO.Terms =
- myobPO.IsTaxInclusive = true;
- myobPO.IsReportable = true;
- // myobPO.Freight =
- // myobPO.FreightForeign =
- if (isNew)
- {
- if(!this.GetDefaultTaxCode().Get(out var taxCodeID, out error))
- {
- results.AddFailed(po, error.Message);
- continue;
- }
- myobPO.FreightTaxCode ??= new();
- myobPO.FreightTaxCode.UID = taxCodeID;
- }
- // myobPO.Category =
- myobPO.Comment = po.Description.Truncate(2000);
- // myobPO.ShippingMethod =
- // myobPO.PromisedDate =
- // myobPO.JournalMemo =
- // myobPO.OrderDeliveryStatus =
- if(poItems.TryGetValue(po.ID, out var lines))
- {
- var newLines = new MYOBPurchaseOrderItem[lines.Length];
- string? failed = null;
- for(int i = 0; i < lines.Length; ++i)
- {
- var poItem = lines[i];
- var line = new MYOBPurchaseOrderItem();
- line.Type = OrderLineType.Transaction;
- line.Description = poItem.Description.Truncate(1000);
- if(poItem.PurchaseGL.ID == Guid.Empty)
- {
- failed = "Not all lines have a PurchaseGL code set.";
- break;
- }
- if(!Guid.TryParse(poItem.PurchaseGL.PostedReference, out var accountID))
- {
- if(AccountMYOBUtils.GetAccount(ConnectionData, poItem.PurchaseGL.Code).Get(out accountID, out error))
- {
- results.AddFragment(new GLCode { ID = poItem.PurchaseGL.ID, PostedReference = accountID.ToString() });
- }
- else
- {
- CoreUtils.LogException("", error);
- failed = error.Message;
- break;
- }
- }
- line.Account ??= new();
- line.Account.UID = accountID;
- line.Total = Math.Round(Convert.ToDecimal(poItem.IncTax), 2);
- line.TotalForeign = 0;
- // line.UnitsOfMeasure =
- // line.UnitCount =
- // line.UnitPrice =
- // line.UnitPriceForeign =
- // line.DiscountPercent =
- // line.Job =
- if(poItem.TaxCode.ID == Guid.Empty)
- {
- failed = "Not all lines have a TaxCode set.";
- break;
- }
- if(!Guid.TryParse(poItem.TaxCode.PostedReference, out var taxCodeID))
- {
- if (!ConnectionData.GetUID<TaxCodeService, MYOBTaxCode>(
- new Filter<MYOBTaxCode>(x => x.Code).IsEqualTo(poItem.TaxCode.Code))
- .Get(out taxCodeID, out error))
- {
- CoreUtils.LogException("", error, $"Failed to find TaxCode in MYOB with code {poItem.TaxCode.Code}");
- failed = $"Failed to find TaxCode in MYOB with code {poItem.TaxCode.Code}: {error.Message}";
- break;
- }
- else if (taxCodeID == Guid.Empty)
- {
- failed = $"Failed to find TaxCode in MYOB with code {poItem.TaxCode.Code}";
- break;
- }
- results.AddFragment(new TaxCode { ID = taxCodeID, PostedReference = taxCodeID.ToString() });
- }
- line.TaxCode ??= new();
- line.TaxCode.UID = taxCodeID;
- if(!ProcessPurchaseOrderItem(model, poItem, line).Get(out error))
- {
- failed = error.Message;
- break;
- }
- newLines[i] = line;
- }
- if(failed is not null)
- {
- results.AddFailed(po, failed);
- continue;
- }
- myobPO.Lines = newLines;
- }
- else
- {
- myobPO.Lines = [];
- }
- if(!ProcessPurchaseOrder(model, po, myobPO).Get(out error))
- {
- results.AddFailed(po, error.Message);
- continue;
- }
- if(service.Save(ConnectionData, myobPO).Get(out var result, out error))
- {
- po.PostedReference = result.UID.ToString();
- results.AddSuccess(po);
- }
- else
- {
- CoreUtils.LogException("", error, $"Error while posting purchase order {po.ID}");
- results.AddFailed(po, error.Message);
- }
- }
- return results;
- }
- }
- public class PurchaseOrderMYOBPosterEngine : MYOBPosterEngine<PurchaseOrder, PurchaseOrderMYOBPoster, PurchaseOrderMYOBPosterSettings>
- {
- }
|