ReceiptMYOBPoster.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using Comal.Classes;
  2. using InABox.Core;
  3. using InABox.Core.Postable;
  4. using InABox.Poster.MYOB;
  5. using MYOB.AccountRight.SDK.Contracts.Version2.Sale;
  6. using MYOB.AccountRight.SDK.Services.Sale;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Windows.Markup.Localizer;
  13. using Invoice = Comal.Classes.Invoice;
  14. using MYOBReceipt = MYOB.AccountRight.SDK.Contracts.Version2.Sale.CustomerPayment;
  15. namespace PRS.Shared.Posters.MYOB;
  16. public class ReceiptMYOBPosterSettings : MYOBPosterSettings
  17. {
  18. [EditorSequence(1)]
  19. [TextBoxEditor(ToolTip = "The MYOB account code for receipts")]
  20. public string Account { get; set; }
  21. }
  22. public class ReceiptMYOBPoster : IMYOBPoster<Receipt, ReceiptMYOBPosterSettings>
  23. {
  24. public MYOBConnectionData ConnectionData { get; set; }
  25. public ReceiptMYOBPosterSettings Settings { get; set; }
  26. public MYOBGlobalPosterSettings GlobalSettings { get; set; }
  27. public bool BeforePost(IDataModel<Receipt> model)
  28. {
  29. foreach(var (_, table) in model.ModelTables)
  30. {
  31. table.IsDefault = false;
  32. }
  33. model.SetIsDefault<Receipt>(true);
  34. model.SetColumns<Receipt>(RequiredReceiptColumns());
  35. model.SetIsDefault<InvoiceReceipt>(true, alias: "Receipt_InvoiceReceipt");
  36. model.SetColumns<InvoiceReceipt>(RequiredInvoiceReceiptColumns(), alias: "Receipt_InvoiceReceipt");
  37. model.SetIsDefault<Customer>(true, alias: "Receipt_Customer");
  38. model.SetColumns<Customer>(RequiredCustomerColumns(), alias: "Receipt_Customer");
  39. return true;
  40. }
  41. private static Columns<Receipt> RequiredReceiptColumns()
  42. {
  43. return Columns.None<Receipt>()
  44. .Add(x => x.ID)
  45. .Add(x => x.PostedReference)
  46. .Add(x => x.PostedStatus)
  47. .Add(x => x.CustomerLink.ID)
  48. .Add(x => x.Date)
  49. .Add(x => x.Total)
  50. .Add(x => x.Notes);
  51. }
  52. private static Columns<InvoiceReceipt> RequiredInvoiceReceiptColumns()
  53. {
  54. return Columns.None<InvoiceReceipt>()
  55. .Add(x => x.ID)
  56. .Add(x => x.Amount)
  57. .Add(x => x.ReceiptLink.ID)
  58. .Add(x => x.InvoiceLink.Number)
  59. .Add(x => x.InvoiceLink.PostedReference);
  60. }
  61. private static Columns<Customer> RequiredCustomerColumns()
  62. {
  63. return CustomerMYOBPoster.RequiredColumns();
  64. }
  65. public IPostResult<Receipt> Process(IDataModel<Receipt> model)
  66. {
  67. // https://developer.myob.com/api/myob-business-api/v2/sale/customerpayment/
  68. var results = new PostResult<Receipt>();
  69. var service = new CustomerPaymentService(ConnectionData.Configuration, null, ConnectionData.AuthKey);
  70. var receipts = model.GetTable<Receipt>().ToArray<Receipt>();
  71. var customers = model.GetTable<Customer>("Receipt_Customer")
  72. .ToObjects<Customer>().ToDictionary(x => x.ID);
  73. var invoices = model.GetTable<InvoiceReceipt>("Receipt_InvoiceReceipt")
  74. .ToObjects<InvoiceReceipt>().GroupBy(x => x.ReceiptLink.ID).ToDictionary(x => x.Key, x => x.ToArray());
  75. foreach(var receipt in receipts)
  76. {
  77. // For receipts, always create a new one, so we cannot posted already posted stuff.
  78. if(receipt.PostedStatus == PostedStatus.Posted)
  79. {
  80. continue;
  81. }
  82. var myobReceipt = new MYOBReceipt();
  83. myobReceipt.DepositTo = DepositTo.Account;
  84. // Setting this to null right now.
  85. myobReceipt.Account ??= new();
  86. if (Settings.Account.IsNullOrWhiteSpace())
  87. {
  88. throw new MissingSettingException<ReceiptMYOBPosterSettings>(x => x.Account);
  89. }
  90. else if(AccountMYOBUtils.GetAccount(ConnectionData, Settings.Account).Get(out var accountID, out var error))
  91. {
  92. myobReceipt.Account.UID = accountID;
  93. }
  94. else
  95. {
  96. CoreUtils.LogException("", error);
  97. results.AddFailed(receipt, error.Message);
  98. continue;
  99. }
  100. if(customers.TryGetValue(receipt.CustomerLink.ID, out var customer))
  101. {
  102. if(!CustomerMYOBPoster.MapCustomer(ConnectionData, customer, GlobalSettings).Get(out var customerID, out var error))
  103. {
  104. CoreUtils.LogException("", error, $"Error while posting receipt {receipt.ID}");
  105. results.AddFailed(receipt, error.Message);
  106. continue;
  107. }
  108. myobReceipt.Customer ??= new();
  109. myobReceipt.Customer.UID = customerID;
  110. results.AddFragment(customer);
  111. }
  112. // myobReceipt.ReceiptNumber =
  113. myobReceipt.Date = receipt.Date;
  114. myobReceipt.AmountReceived = (decimal)receipt.Total;
  115. // myobReceipt.AmountReceivedForeign = 0;
  116. // myobReceipt.PaymentMethod =
  117. myobReceipt.Memo = receipt.Notes.Truncate(255);
  118. if(invoices.TryGetValue(receipt.ID, out var receiptInvoices))
  119. {
  120. var myobInvoices = new CustomerPaymentLine[receiptInvoices.Length];
  121. string? failed = null;
  122. for(int i = 0; i < receiptInvoices.Length; ++i)
  123. {
  124. var invoice = receiptInvoices[i];
  125. var line = new CustomerPaymentLine();
  126. // line.RowID = i + 1;
  127. line.Number = invoice.InvoiceLink.Number.ToString().Truncate(8);
  128. line.AmountApplied = (decimal)invoice.Amount;
  129. line.Type = CustomerPaymentLineType.Invoice;
  130. if(Guid.TryParse(invoice.InvoiceLink.PostedReference, out var myobInvoiceID))
  131. {
  132. line.UID = myobInvoiceID;
  133. }
  134. else
  135. {
  136. failed = $"Invoice {invoice.InvoiceLink.Number} hasn't been posted yet; it must be posted before this receipt can be.";
  137. break;
  138. }
  139. myobInvoices[i] = line;
  140. }
  141. if(failed is not null)
  142. {
  143. results.AddFailed(receipt, failed);
  144. continue;
  145. }
  146. myobReceipt.Invoices = myobInvoices;
  147. }
  148. else
  149. {
  150. myobReceipt.Invoices = [];
  151. }
  152. if(service.Save(ConnectionData, myobReceipt).Get(out var result, out var e))
  153. {
  154. receipt.PostedReference = result.UID.ToString();
  155. results.AddSuccess(receipt);
  156. }
  157. else
  158. {
  159. CoreUtils.LogException("", e, $"Error while posting receipt {receipt.ID}");
  160. results.AddFailed(receipt, e.Message);
  161. }
  162. }
  163. return results;
  164. }
  165. }
  166. public class ReceiptMYOBPosterEngine<T> : MYOBPosterEngine<Receipt, ReceiptMYOBPosterSettings> { }