using InABox.Core; using InABox.Core.Postable; using InABox.Poster.Shared; using MYOB.AccountRight.SDK; using MYOB.AccountRight.SDK.Contracts.Version2; using MYOB.AccountRight.SDK.Services; using MYOB.AccountRight.SDK.Services.GeneralLedger; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using MYOBBaseEntity = MYOB.AccountRight.SDK.Contracts.Version2.BaseEntity; using MYOBTaxCode = MYOB.AccountRight.SDK.Contracts.Version2.GeneralLedger.TaxCode; namespace InABox.Poster.MYOB; public static class MYOBPosterUtils { public class QueryResult : Result, Exception> { public QueryResult(PagedCollection value) : base(value) { } public QueryResult(Exception error) : base(error) { } public static QueryResult Ok(PagedCollection collection) => new QueryResult(collection); public static QueryResult Error(Exception e) => new QueryResult(e); } public class GetResult : Result { public GetResult(T value) : base(value) { } public GetResult(Exception error) : base(error) { } public static GetResult Ok(T value) => new GetResult(value); public static GetResult Error(Exception e) => new GetResult(e); } public static Result, Exception> Query( this MutableService service, MYOBConnectionData data, Filter? filter, int? top = null, int? skip = null ) where T : MYOBBaseEntity { var queries = new List(); if(filter is not null) { queries.Add($"$filter={Uri.EscapeDataString(filter.AsOData())}"); } if (top.HasValue) { queries.Add($"$top={top.Value}"); } if (skip.HasValue) { queries.Add($"$skip={skip.Value}"); } try { var values = service.GetRange(data.CompanyFile, string.Join('&', queries), data.CompanyFileCredentials); return QueryResult.Ok(values); } catch(ApiCommunicationException e) { return QueryResult.Error(new Exception(FormatApiException(e), e)); } catch(Exception e) { return QueryResult.Error(e); } } public static Result Save( this MutableService service, MYOBConnectionData data, T entity) where T : MYOBBaseEntity { try { if(entity.UID == Guid.Empty) { return Result.Ok(service.InsertEx(data.CompanyFile, entity, data.CompanyFileCredentials)); } else { return Result.Ok(service.UpdateEx(data.CompanyFile, entity, data.CompanyFileCredentials)); } } catch(ApiCommunicationException e) { return Result.Error(new Exception(FormatApiException(e), e)); } catch(Exception e) { return Result.Error(e); } } public static GetResult Get(this MutableService service, MYOBConnectionData data, Guid id) where T : MYOBBaseEntity { try { var value = service.Get(data.CompanyFile, id, data.CompanyFileCredentials); return GetResult.Ok(value); } catch(ApiCommunicationException e) { return GetResult.Error(new Exception(FormatApiException(e), e)); } catch(Exception e) { return GetResult.Error(e); } } public static TService CreateService(this MYOBConnectionData data) where TService : MutableService where TEntity : MYOBBaseEntity { return (Activator.CreateInstance(typeof(TService), data.Configuration, null, data.AuthKey) as TService)!; } public static Result GetUID(this MYOBConnectionData data, Filter filter) where TService : MutableService where TEntity : MYOBBaseEntity { var service = data.CreateService(); var result = service.Query(data, filter, top: 1); if(!result.Get(out var items, out var error)) { return Result.Error(error); } if(items.Items.Length == 0) { return Result.Ok(Guid.Empty); } return Result.Ok(items.Items[0].UID); } public static string FormatApiException(ApiCommunicationException e) { if(e.Errors is not null && e.Errors.Count > 0) { var message = string.Join('\n', e.Errors.Select(x => { return $"{x.Name}: {x.Message} ({x.AdditionalDetails})"; })); return message; } else { return e.Message; } } public static Result GetMYOBTaxCodeUID(this MYOBConnectionData data, string code) => data.GetUID(new Filter(x => x.Code).IsEqualTo(code)); public static Result GetDefaultTaxCode(MYOBConnectionData data, MYOBGlobalPosterSettings settings) { if (settings.DefaultTaxCode.IsNullOrWhiteSpace()) { throw new MissingSettingException(x => x.DefaultTaxCode); } else if(data.GetMYOBTaxCodeUID(settings.DefaultTaxCode).Get(out var taxID, out var error)) { if (taxID == Guid.Empty) { return Result.Error(new Exception($"Failed to find TaxCode in MYOB with code '{settings.DefaultTaxCode}'")); } return Result.Ok(taxID); } else { CoreUtils.LogException("", error, $"Failed to find TaxCode in MYOB with code '{settings.DefaultTaxCode}'"); return Result.Error(new Exception($"Failed to find TaxCode in MYOB with code '{settings.DefaultTaxCode}': {error.Message}", error)); } } public static Result GetDefaultTaxCode(this IMYOBPoster poster) where TPostable : Entity, IPostable, IRemotable, IPersistent, new() where TSettings : MYOBPosterSettings { return GetDefaultTaxCode(poster.ConnectionData, poster.GlobalSettings); } public static Result WrapScript( this IMYOBPoster poster, string methodname, params object?[] parameters ) where TPostable : Entity, IPostable, IRemotable, IPersistent, new() where TSettings : MYOBPosterSettings { if (poster.Script is null) return Result.Ok(); try { if(poster.Script.Execute(methodname: methodname, parameters: parameters)) { return Result.Ok(); } else { throw new PostCancelledException(); } } catch(TargetInvocationException e) { if(e.InnerException is not null) { return Result.Error(e.InnerException); } else { return Result.Error(e); } } catch(Exception e) { return Result.Error(e); } } }