using System; using System.Collections.Generic; using InABox.Core; namespace Comal.Classes { [UserTracking("Accounts Payable")] public class Bill : Entity, IPersistent, IRemotable, ILicense, IDataEntryInstance, IPostable, IExportable, IProblems { [RequiredColumn] [EditorSequence(1)] [EntityRelationship(DeleteAction.Cascade)] public SupplierLink SupplierLink { get; set; } [EditorSequence(2)] [CodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)] public string Number { get; set; } [EditorSequence(3)] [MemoEditor] public string Description { get; set; } [EditorSequence(4)] [DateEditor] public DateTime BillDate { get; set; } [EditorSequence(5)] [LookupDefinition(typeof(AccountsPayablePaymentTermsLookup))] public PaymentTermsLink Terms { get; set; } [EditorSequence(6)] [DateEditor] public DateTime PaymentDate { get; set; } [EditorSequence(7)] [DateEditor] public DateTime AccountingDate { get; set; } [EditorSequence("Additional",1)] [TimestampEditor] public DateTime DataEntered { get; set; } [EditorSequence("Additional",2)] [TimestampEditor] [Security(typeof(CanCheckBills), Editable = Editable.Disabled)] public DateTime Checked { get; set; } [EditorSequence("Additional", 4)] [Editable(Editable.Disabled)] [RequiredColumn] public BillApprovalSetLink ApprovalSet { get; set; } private class IsApprovedFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => If(x => x.Count( x => x.Property(x => x.ID), filter: new Filter(x => x.Approved).IsEqualTo(DateTime.MinValue)) .WithLink(x => x.Bill.ID, x => x.ID), Condition.Equals, x => x.Constant(0)) .Then(Constant(true)) .Else(Constant(false)); } [Editable(Editable.Hidden)] [ComplexFormula(typeof(IsApprovedFormula))] public bool IsApproved { get; set; } private class ExTaxFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Aggregate(AggregateCalculation.Sum, x => x.Property(x => x.ExTax)) .WithLink(x => x.BillLink.ID, x => x.ID); } [DoubleEditor(Editable = Editable.Hidden, Summary = Summary.Sum)] [ComplexFormula(typeof(ExTaxFormula))] public double ExTax { get; set; } private class TaxFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Aggregate(AggregateCalculation.Sum, x => x.Property(x => x.Tax)) .WithLink(x => x.BillLink.ID, x => x.ID); } [DoubleEditor(Editable = Editable.Hidden, Summary = Summary.Sum)] [ComplexFormula(typeof(TaxFormula))] public double Tax { get; set; } private class IncTaxFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Aggregate(AggregateCalculation.Sum, x => x.Property(x => x.IncTax)) .WithLink(x => x.BillLink.ID, x => x.ID); } [DoubleEditor(Editable = Editable.Hidden, Summary = Summary.Sum)] [ComplexFormula(typeof(IncTaxFormula))] public double IncTax { get; set; } private class AmountPaidFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Aggregate(AggregateCalculation.Sum, x => x.Property(x => x.Amount)) .WithLink(x => x.BillLink.ID, x => x.ID); } [CurrencyEditor(Editable = Editable.Hidden, Summary = Summary.Sum)] [ComplexFormula(typeof(AmountPaidFormula))] public double AmountPaid { get; set; } private class BalanceFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Formula(FormulaOperator.Subtract, Property(x => x.IncTax), Property(x => x.AmountPaid)); } [CurrencyEditor(Editable = Editable.Hidden, Summary = Summary.Sum)] [ComplexFormula(typeof(BalanceFormula))] public double Balance { get; set; } private class DocumentsFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Count(x => x.Property(x => x.ID)) .WithLink(x => x.EntityLink.ID, x => x.ID); } [ComplexFormula(typeof(DocumentsFormula))] [IntegerEditor(Editable = Editable.Hidden)] public int Documents { get; set; } private class OutstandingApprovalsFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Aggregate(AggregateCalculation.Concat, x => x.Property(x => x.Employee.Code), filter: new Filter(x => x.Approved).IsEqualTo(DateTime.MinValue)) .WithLink(x => x.Bill.ID, x => x.ID); } [ComplexFormula(typeof(OutstandingApprovalsFormula))] [Editable(Editable.Hidden)] public string OutstandingApprovals { get; set; } [NullEditor] [LoggableProperty] public DateTime Posted { get; set; } [NullEditor] [LoggableProperty] [RequiredColumn] public PostedStatus PostedStatus { get; set; } [NullEditor] public string PostedNote { get; set; } [NullEditor] public string PostedReference { get; set; } private static string BILLDATE = CoreUtils.GetFullPropertyName(x => x.BillDate, "."); private static string TERMSCALCULATION = CoreUtils.GetFullPropertyName(x => x.Terms.Calculation, "."); private static string SUPPLIERLINKTERMSCALCULATION = CoreUtils.GetFullPropertyName(x => x.SupplierLink.Terms.Calculation, "."); private static string AMOUNTPAID = CoreUtils.GetFullPropertyName(x => x.AmountPaid, "."); private static string INCTAX = CoreUtils.GetFullPropertyName(x => x.IncTax, "."); protected override void DoPropertyChanged(string name, object? before, object? after) { base.DoPropertyChanged(name, before, after); if (name.Equals(AMOUNTPAID)) Balance = IncTax - (double)(after ?? 0.0); else if (name.Equals(INCTAX)) Balance = (double)(after ?? 0.0) - AmountPaid; else if (name.Equals(BILLDATE)) PaymentDate = CalculateTerms((DateTime)(after ?? ""),Terms.Calculation); else if (name.Equals(TERMSCALCULATION)) PaymentDate = CalculateTerms(BillDate, (string)(after ?? "")); else if (name.Equals(SUPPLIERLINKTERMSCALCULATION)) PaymentDate = CalculateTerms(BillDate, (string)(after ?? "")); } private DateTime CalculateTerms(DateTime date, string calculation) { if (string.IsNullOrWhiteSpace(calculation)) return date; var variables = new Dictionary() { { "Date", date } }; try { var expr = new CoreExpression(calculation); var eval = expr.Evaluate(variables); return (DateTime)(CoreUtils.ChangeType(eval, typeof(DateTime)) ?? date); } catch (Exception e) { Logger.Send(LogType.Information, "", $"Error in Formula: [{calculation}] ({e.Message})"); return date; } } static Bill() { LinkedProperties.Register(x=>x.SupplierLink.Terms,x=>x.ID, x=>x.Terms.ID); LinkedProperties.Register(x=>x.SupplierLink.Terms,x=>x.Code, x=>x.Terms.Code); LinkedProperties.Register(x=>x.SupplierLink.Terms,x=>x.Description, x=>x.Terms.Description); LinkedProperties.Register(x=>x.SupplierLink.Terms,x=>x.Calculation, x=>x.Terms.Calculation); } //[NullEditor] //public string Issues { get; set; } [EditorSequence("Issues", 1)] public ManagedProblem Problem { get; set; } [Obsolete("Replaced with IsApproved aggregate")] public DateTime Approved { get; set; } } }