MYOBPosterUtils.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. using InABox.Core;
  2. using InABox.Core.Postable;
  3. using InABox.Poster.Shared;
  4. using MYOB.AccountRight.SDK;
  5. using MYOB.AccountRight.SDK.Contracts.Version2;
  6. using MYOB.AccountRight.SDK.Services;
  7. using MYOB.AccountRight.SDK.Services.GeneralLedger;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using MYOBBaseEntity = MYOB.AccountRight.SDK.Contracts.Version2.BaseEntity;
  15. using MYOBTaxCode = MYOB.AccountRight.SDK.Contracts.Version2.GeneralLedger.TaxCode;
  16. namespace InABox.Poster.MYOB;
  17. public static class MYOBPosterUtils
  18. {
  19. public class QueryResult<T> : Result<PagedCollection<T>, Exception>
  20. {
  21. public QueryResult(PagedCollection<T> value) : base(value)
  22. {
  23. }
  24. public QueryResult(Exception error) : base(error)
  25. {
  26. }
  27. public static QueryResult<T> Ok(PagedCollection<T> collection) => new QueryResult<T>(collection);
  28. public static QueryResult<T> Error(Exception e) => new QueryResult<T>(e);
  29. }
  30. public class GetResult<T> : Result<T, Exception>
  31. {
  32. public GetResult(T value) : base(value)
  33. {
  34. }
  35. public GetResult(Exception error) : base(error)
  36. {
  37. }
  38. public static GetResult<T> Ok(T value) => new GetResult<T>(value);
  39. public static GetResult<T> Error(Exception e) => new GetResult<T>(e);
  40. }
  41. public static Result<PagedCollection<T>, Exception> Query<T>(
  42. this MutableService<T> service, MYOBConnectionData data,
  43. Filter<T>? filter,
  44. int? top = null, int? skip = null
  45. )
  46. where T : MYOBBaseEntity
  47. {
  48. var queries = new List<string>();
  49. if(filter is not null)
  50. {
  51. queries.Add($"$filter={Uri.EscapeDataString(filter.AsOData())}");
  52. }
  53. if (top.HasValue)
  54. {
  55. queries.Add($"$top={top.Value}");
  56. }
  57. if (skip.HasValue)
  58. {
  59. queries.Add($"$skip={skip.Value}");
  60. }
  61. try
  62. {
  63. var values = service.GetRange(data.CompanyFile, string.Join('&', queries), data.CompanyFileCredentials);
  64. return QueryResult<T>.Ok(values);
  65. }
  66. catch(ApiCommunicationException e)
  67. {
  68. return QueryResult<T>.Error(new Exception(FormatApiException(e), e));
  69. }
  70. catch(Exception e)
  71. {
  72. return QueryResult<T>.Error(e);
  73. }
  74. }
  75. public static Result<T, Exception> Save<T>(
  76. this MutableService<T> service, MYOBConnectionData data,
  77. T entity)
  78. where T : MYOBBaseEntity
  79. {
  80. try
  81. {
  82. if(entity.UID == Guid.Empty)
  83. {
  84. return Result.Ok(service.InsertEx(data.CompanyFile, entity, data.CompanyFileCredentials));
  85. }
  86. else
  87. {
  88. return Result.Ok(service.UpdateEx(data.CompanyFile, entity, data.CompanyFileCredentials));
  89. }
  90. }
  91. catch(ApiCommunicationException e)
  92. {
  93. return Result.Error(new Exception(FormatApiException(e), e));
  94. }
  95. catch(Exception e)
  96. {
  97. return Result.Error(e);
  98. }
  99. }
  100. public static GetResult<T> Get<T>(this MutableService<T> service, MYOBConnectionData data, Guid id)
  101. where T : MYOBBaseEntity
  102. {
  103. try
  104. {
  105. var value = service.Get(data.CompanyFile, id, data.CompanyFileCredentials);
  106. return GetResult<T>.Ok(value);
  107. }
  108. catch(ApiCommunicationException e)
  109. {
  110. return GetResult<T>.Error(new Exception(FormatApiException(e), e));
  111. }
  112. catch(Exception e)
  113. {
  114. return GetResult<T>.Error(e);
  115. }
  116. }
  117. public static TService CreateService<TService, TEntity>(this MYOBConnectionData data)
  118. where TService : MutableService<TEntity>
  119. where TEntity : MYOBBaseEntity
  120. {
  121. return (Activator.CreateInstance(typeof(TService), data.Configuration, null, data.AuthKey) as TService)!;
  122. }
  123. public static Result<Guid, Exception> GetUID<TService, TEntity>(this MYOBConnectionData data, Filter<TEntity> filter)
  124. where TService : MutableService<TEntity>
  125. where TEntity : MYOBBaseEntity
  126. {
  127. var service = data.CreateService<TService, TEntity>();
  128. var result = service.Query(data, filter, top: 1);
  129. if(!result.Get(out var items, out var error))
  130. {
  131. return Result.Error(error);
  132. }
  133. if(items.Items.Length == 0)
  134. {
  135. return Result.Ok(Guid.Empty);
  136. }
  137. return Result.Ok(items.Items[0].UID);
  138. }
  139. public static string FormatApiException(ApiCommunicationException e)
  140. {
  141. if(e.Errors is not null && e.Errors.Count > 0)
  142. {
  143. var message = string.Join('\n', e.Errors.Select(x =>
  144. {
  145. return $"{x.Name}: {x.Message} ({x.AdditionalDetails})";
  146. }));
  147. return message;
  148. }
  149. else
  150. {
  151. return e.Message;
  152. }
  153. }
  154. public static Result<Guid, Exception> GetMYOBTaxCodeUID(this MYOBConnectionData data, string code)
  155. => data.GetUID<TaxCodeService, MYOBTaxCode>(new Filter<MYOBTaxCode>(x => x.Code).IsEqualTo(code));
  156. public static Result<Guid, Exception> GetDefaultTaxCode(MYOBConnectionData data, MYOBGlobalPosterSettings settings)
  157. {
  158. if (settings.DefaultTaxCode.IsNullOrWhiteSpace())
  159. {
  160. throw new MissingSettingException<MYOBGlobalPosterSettings>(x => x.DefaultTaxCode);
  161. }
  162. else if(data.GetMYOBTaxCodeUID(settings.DefaultTaxCode).Get(out var taxID, out var error))
  163. {
  164. if (taxID == Guid.Empty)
  165. {
  166. return Result.Error(new Exception($"Failed to find TaxCode in MYOB with code '{settings.DefaultTaxCode}'"));
  167. }
  168. return Result.Ok(taxID);
  169. }
  170. else
  171. {
  172. CoreUtils.LogException("", error, $"Failed to find TaxCode in MYOB with code '{settings.DefaultTaxCode}'");
  173. return Result.Error(new Exception($"Failed to find TaxCode in MYOB with code '{settings.DefaultTaxCode}': {error.Message}", error));
  174. }
  175. }
  176. public static Result<Guid, Exception> GetDefaultTaxCode<TPostable, TSettings>(this IMYOBPoster<TPostable, TSettings> poster)
  177. where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
  178. where TSettings : MYOBPosterSettings
  179. {
  180. return GetDefaultTaxCode(poster.ConnectionData, poster.GlobalSettings);
  181. }
  182. public static Result<Exception> WrapScript<TPostable, TSettings>(
  183. this IMYOBPoster<TPostable, TSettings> poster,
  184. string methodname,
  185. params object?[] parameters
  186. )
  187. where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
  188. where TSettings : MYOBPosterSettings
  189. {
  190. if (poster.Script is null) return Result.Ok();
  191. try
  192. {
  193. if(poster.Script.Execute(methodname: methodname, parameters: parameters))
  194. {
  195. return Result.Ok();
  196. }
  197. else
  198. {
  199. throw new PostCancelledException();
  200. }
  201. }
  202. catch(TargetInvocationException e)
  203. {
  204. if(e.InnerException is not null)
  205. {
  206. return Result.Error(e.InnerException);
  207. }
  208. else
  209. {
  210. return Result.Error<Exception>(e);
  211. }
  212. }
  213. catch(Exception e)
  214. {
  215. return Result.Error(e);
  216. }
  217. }
  218. }