| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 | 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<T> : Result<PagedCollection<T>, Exception>    {        public QueryResult(PagedCollection<T> value) : base(value)        {        }        public QueryResult(Exception error) : base(error)        {        }        public static QueryResult<T> Ok(PagedCollection<T> collection) => new QueryResult<T>(collection);        public static QueryResult<T> Error(Exception e) => new QueryResult<T>(e);    }    public class GetResult<T> : Result<T, Exception>    {        public GetResult(T value) : base(value)        {        }        public GetResult(Exception error) : base(error)        {        }        public static GetResult<T> Ok(T value) => new GetResult<T>(value);        public static GetResult<T> Error(Exception e) => new GetResult<T>(e);    }    public static Result<PagedCollection<T>, Exception> Query<T>(        this MutableService<T> service, MYOBConnectionData data,        Filter<T>? filter,        int? top = null, int? skip = null    )        where T : MYOBBaseEntity    {        var queries = new List<string>();        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<T>.Ok(values);        }        catch(ApiCommunicationException e)        {            return QueryResult<T>.Error(new Exception(FormatApiException(e), e));        }        catch(Exception e)        {            return QueryResult<T>.Error(e);        }    }    public static Result<T, Exception> Save<T>(        this MutableService<T> 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<T> Get<T>(this MutableService<T> service, MYOBConnectionData data, Guid id)        where T : MYOBBaseEntity    {        try        {            var value = service.Get(data.CompanyFile, id, data.CompanyFileCredentials);            return GetResult<T>.Ok(value);        }        catch(ApiCommunicationException e)        {            return GetResult<T>.Error(new Exception(FormatApiException(e), e));        }        catch(Exception e)        {            return GetResult<T>.Error(e);        }    }    public static TService CreateService<TService, TEntity>(this MYOBConnectionData data)        where TService : MutableService<TEntity>        where TEntity : MYOBBaseEntity    {        return (Activator.CreateInstance(typeof(TService), data.Configuration, null, data.AuthKey) as TService)!;    }    public static Result<Guid, Exception> GetUID<TService, TEntity>(this MYOBConnectionData data, Filter<TEntity> filter)        where TService : MutableService<TEntity>        where TEntity : MYOBBaseEntity    {        var service = data.CreateService<TService, TEntity>();        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<Guid, Exception> GetMYOBTaxCodeUID(this MYOBConnectionData data, string code)        => data.GetUID<TaxCodeService, MYOBTaxCode>(new Filter<MYOBTaxCode>(x => x.Code).IsEqualTo(code));    public static Result<Guid, Exception> GetDefaultTaxCode(MYOBConnectionData data, MYOBGlobalPosterSettings settings)    {        if (settings.DefaultTaxCode.IsNullOrWhiteSpace())        {            throw new MissingSettingException<MYOBGlobalPosterSettings>(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<Guid, Exception> GetDefaultTaxCode<TPostable, TSettings>(this IMYOBPoster<TPostable, TSettings> poster)        where TPostable : Entity, IPostable, IRemotable, IPersistent, new()        where TSettings : MYOBPosterSettings    {        return GetDefaultTaxCode(poster.ConnectionData, poster.GlobalSettings);    }    public static Result<Exception> WrapScript<TPostable, TSettings>(        this IMYOBPoster<TPostable, TSettings> 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<Exception>(e);            }        }        catch(Exception e)        {            return Result.Error(e);        }    }}
 |