From 96b78856da6f61aa5988dcc99153dc15e33793d1 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 20 May 2021 19:50:58 +0000 Subject: [PATCH] --- server/AyaNova/biz/FormFieldReference.cs | 12 ++- server/AyaNova/biz/WorkOrderBiz.cs | 84 +++++++++++++++++-- server/AyaNova/models/WorkOrderItemExpense.cs | 19 ++++- server/AyaNova/models/WorkOrderItemLabor.cs | 3 +- server/AyaNova/util/AySchema.cs | 9 +- 5 files changed, 111 insertions(+), 16 deletions(-) diff --git a/server/AyaNova/biz/FormFieldReference.cs b/server/AyaNova/biz/FormFieldReference.cs index fbfa9bb3..dcef304c 100644 --- a/server/AyaNova/biz/FormFieldReference.cs +++ b/server/AyaNova/biz/FormFieldReference.cs @@ -922,6 +922,12 @@ namespace AyaNova.Biz l.Add(new FormField { TKey = "WorkOrderItemExpenseReimburseUser", FieldKey = "WorkOrderItemExpenseReimburseUser", TKeySection = "WorkOrderItemExpense" }); l.Add(new FormField { TKey = "WorkOrderItemExpenseTotalCost", FieldKey = "WorkOrderItemExpenseTotalCost", TKeySection = "WorkOrderItemExpense" }); l.Add(new FormField { TKey = "WorkOrderItemExpenseUserID", FieldKey = "WorkOrderItemExpenseUserID", TKeySection = "WorkOrderItemExpense" }); + l.Add(new FormField { TKey = "TaxCodeTaxA", FieldKey = "ExpenseTaxAPct", TKeySection = "WorkOrderItemExpense" }); + l.Add(new FormField { TKey = "TaxCodeTaxB", FieldKey = "ExpenseTaxBPct", TKeySection = "WorkOrderItemExpense" }); + l.Add(new FormField { TKey = "TaxCodeTaxOnTax", FieldKey = "ExpenseTaxOnTax", TKeySection = "WorkOrderItemExpense" }); + l.Add(new FormField { TKey = "TaxAAmt", FieldKey = "ExpenseTaxAViz", TKeySection = "WorkOrderItemExpense" }); + l.Add(new FormField { TKey = "TaxBAmt", FieldKey = "ExpenseTaxBViz", TKeySection = "WorkOrderItemExpense" }); + l.Add(new FormField { TKey = "LineTotal", FieldKey = "ExpenseLineTotalViz", TKeySection = "WorkOrderItemExpense" }); @@ -934,12 +940,12 @@ namespace AyaNova.Biz l.Add(new FormField { TKey = "WorkOrderItemLaborUserID", FieldKey = "WorkOrderItemLaborUserID", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "WorkOrderItemLaborNoChargeQuantity", FieldKey = "WorkOrderItemLaborNoChargeQuantity", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "WorkOrderItemLaborTaxRateSaleID", FieldKey = "WorkOrderItemLaborTaxRateSaleID", TKeySection = "WorkOrderItemLabors" }); - + //STANDARD PRICING FIELDS l.Add(new FormField { TKey = "Cost", FieldKey = "LaborCost", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "ListPrice", FieldKey = "LaborListPrice", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "Price", FieldKey = "LaborPrice", TKeySection = "WorkOrderItemLabors" }); - //DUPLICATE OF ABOVE l.Add(new FormField { TKey = "Tax", FieldKey = "LaborTaxName", TKeySection = "WorkOrderItemLabors" }); + l.Add(new FormField { TKey = "TaxCodeTaxA", FieldKey = "LaborTaxAPct", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "TaxCodeTaxB", FieldKey = "LaborTaxBPct", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "TaxCodeTaxOnTax", FieldKey = "LaborTaxOnTax", TKeySection = "WorkOrderItemLabors" }); @@ -947,7 +953,7 @@ namespace AyaNova.Biz l.Add(new FormField { TKey = "TaxBAmt", FieldKey = "LaborTaxBViz", TKeySection = "WorkOrderItemLabors" }); l.Add(new FormField { TKey = "LineTotal", FieldKey = "LaborLineTotalViz", TKeySection = "WorkOrderItemLabors" }); - + diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 5b839050..dae995b3 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -1019,7 +1019,7 @@ namespace AyaNova.Biz private async Task StatePopulateVizFields(WorkOrderState o) { - o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync(); + o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync(); // if (o.WorkOrderOverseerId != null) // o.WorkOrderOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.WorkOrderOverseerId).Select(x => x.Name).FirstOrDefaultAsync(); } @@ -1543,6 +1543,7 @@ namespace AyaNova.Biz return null; else { + await ExpenseBizActionsAsync(AyaEvent.Created, newObject, null, null); // newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); // newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemExpense.AddAsync(newObject); @@ -1587,6 +1588,7 @@ namespace AyaNova.Biz // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); await ExpenseValidateAsync(putObject, dbObject); if (HasErrors) return null; + await ExpenseBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null); ct.Replace(dbObject, putObject); try { @@ -1672,10 +1674,84 @@ namespace AyaNova.Biz { if (o.UserId != null) o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync(); - if (o.ChargeTaxCodeId != null) - o.ChargeTaxCodeViz = await ct.TaxCode.AsNoTracking().Where(x => x.Id == o.ChargeTaxCodeId).Select(x => x.Name).FirstOrDefaultAsync(); + // if (o.ChargeTaxCodeId != null) + // o.ChargeTaxCodeViz = await ct.TaxCode.AsNoTracking().Where(x => x.Id == o.ChargeTaxCodeId).Select(x => x.Name).FirstOrDefaultAsync(); + + //Calculate totals and taxes + o.TaxAViz = 0; + o.TaxBViz = 0; + + if (o.TaxAPct != 0) + { + o.TaxAViz = o.ChargeAmount * (o.TaxAPct / 100); + } + if (o.TaxBPct != 0) + { + if (o.TaxOnTax) + { + o.TaxBViz = (o.ChargeAmount + o.TaxAViz) * (o.TaxBPct / 100); + } + else + { + o.TaxBViz = o.ChargeAmount * (o.TaxBPct / 100); + } + } + o.LineTotalViz = o.ChargeAmount + o.TaxAViz + o.TaxBViz; } + + //////////////////////////////////////////////////////////////////////////////////////////////// + //BIZ ACTIONS + // + // + private async Task ExpenseBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemExpense newObj, WorkOrderItemExpense oldObj, IDbContextTransaction transaction) + { + //automatic actions on record change, called AFTER validation + + //currently no processing required except for created or modified at this time + if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified) + return; + + //SET TAXES AND PRICING + + //by default apply all automatic actions with further restrictions possible below + bool ApplyTax = true; + + + //if modifed, see what has changed and should be re-applied + if (ayaEvent == AyaEvent.Modified) + { + + //If taxes haven't change then no need to update taxes + if (newObj.ChargeTaxCodeId == oldObj.ChargeTaxCodeId) + ApplyTax = false; + } + + //Tax code + if (ApplyTax) + { + //Default in case nothing to apply + newObj.TaxAPct = 0; + newObj.TaxBPct = 0; + newObj.TaxOnTax = false; + newObj.TaxName = ""; + + if (newObj.ChargeTaxCodeId != null) + { + var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.ChargeTaxCodeId); + if (t != null) + { + newObj.TaxAPct = t.TaxAPct; + newObj.TaxBPct = t.TaxBPct; + newObj.TaxOnTax = t.TaxOnTax; + newObj.TaxName = t.Name; + } + } + } + } + + + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -1940,8 +2016,6 @@ namespace AyaNova.Biz o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync(); if (o.ServiceRateId != null) o.ServiceRateViz = await ct.ServiceRate.AsNoTracking().Where(x => x.Id == o.ServiceRateId).Select(x => x.Name).FirstOrDefaultAsync(); - if (o.TaxCodeSaleId != null) - o.TaxCodeSaleViz = await ct.TaxCode.AsNoTracking().Where(x => x.Id == o.TaxCodeSaleId).Select(x => x.Name).FirstOrDefaultAsync(); //Calculate totals and taxes o.TaxAViz = 0; diff --git a/server/AyaNova/models/WorkOrderItemExpense.cs b/server/AyaNova/models/WorkOrderItemExpense.cs index 762066eb..9d1e3fb6 100644 --- a/server/AyaNova/models/WorkOrderItemExpense.cs +++ b/server/AyaNova/models/WorkOrderItemExpense.cs @@ -20,8 +20,7 @@ namespace AyaNova.Models [Required] public decimal TaxPaid { get; set; } public long? ChargeTaxCodeId { get; set; } - [NotMapped] - public string ChargeTaxCodeViz { get; set; } + public bool ReimburseUser { get; set; } = false; public long? UserId { get; set; } [NotMapped] @@ -29,6 +28,22 @@ namespace AyaNova.Models public bool ChargeToCustomer { get; set; } = false; + //TAX AND TOTAL FIELDS + public string TaxName { get; set; } + [Required] + public decimal TaxAPct { get; set; } + [Required] + public decimal TaxBPct { get; set; } + [Required] + public bool TaxOnTax { get; set; } + [NotMapped] + public decimal TaxAViz { get; set; } + [NotMapped] + public decimal TaxBViz { get; set; } + [NotMapped] + public decimal LineTotalViz { get; set; } + + //UTILITY FIELDS [NotMapped] public bool IsDirty { get; set; } = false;//never dirty coming from the server diff --git a/server/AyaNova/models/WorkOrderItemLabor.cs b/server/AyaNova/models/WorkOrderItemLabor.cs index 50777183..c5288c3c 100644 --- a/server/AyaNova/models/WorkOrderItemLabor.cs +++ b/server/AyaNova/models/WorkOrderItemLabor.cs @@ -25,8 +25,7 @@ namespace AyaNova.Models public decimal NoChargeQuantity { get; set; } public long? ServiceBankId { get; set; } public long? TaxCodeSaleId { get; set; } - [NotMapped] - public string TaxCodeSaleViz { get; set; } + /* diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 7aada73b..7bf07c64 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -22,16 +22,16 @@ namespace AyaNova.Util //!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!! private const int DESIRED_SCHEMA_LEVEL = 1; - internal const long EXPECTED_COLUMN_COUNT = 951; + internal const long EXPECTED_COLUMN_COUNT = 955; internal const long EXPECTED_INDEX_COUNT = 141; - internal const long EXPECTED_CHECK_CONSTRAINTS = 441; + internal const long EXPECTED_CHECK_CONSTRAINTS = 444; internal const long EXPECTED_FOREIGN_KEY_CONSTRAINTS = 115; internal const long EXPECTED_VIEWS = 6; internal const long EXPECTED_ROUTINES = 2; //!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!! - ///////////////////////////////////////////////////////////////// C951:I141:CC441:FC115:V6:R2 + ///////////////////////////////////////////////////////////////// (C955:I141:CC444:FC115:V6:R2) /* @@ -778,7 +778,8 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); //WORKORDERITEM EXPENSE await ExecQueryAsync("CREATE TABLE aworkorderitemexpense (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, workorderitemid BIGINT NOT NULL REFERENCES aworkorderitem (id), " + "description TEXT, name TEXT, totalcost DECIMAL(38,18) NOT NULL default 0, chargeamount DECIMAL(38,18) NOT NULL default 0, taxpaid DECIMAL(38,18) NOT NULL default 0, " - + "chargetaxcodeid BIGINT REFERENCES ataxcode, reimburseuser BOOL NOT NULL, userid BIGINT REFERENCES auser, chargetocustomer BOOL NOT NULL" + + "chargetaxcodeid BIGINT REFERENCES ataxcode ON DELETE SET NULL, reimburseuser BOOL NOT NULL, userid BIGINT REFERENCES auser, chargetocustomer BOOL NOT NULL, " + + "taxapct DECIMAL(8,5) NOT NULL default 0, taxbpct DECIMAL(8,5) NOT NULL default 0, taxontax BOOL NOT NULL default false, taxname TEXT " + ")"); //WORKORDERITEM LABOR