This commit is contained in:
2021-05-26 23:05:07 +00:00
parent 5a477b8312
commit 7cf7f25019
3 changed files with 173 additions and 8 deletions

View File

@@ -2522,11 +2522,150 @@ namespace AyaNova.Biz
////////////////////////////////////////////////////////////////////////////////////////////////
//VIZ POPULATE
//
private async Task LoanPopulateVizFields(WorkOrderItemLoan o)
private async Task LoanPopulateVizFields(WorkOrderItemLoan o, List<NameIdItem> loanUnitRateEnumList = null)
{
await Task.CompletedTask;
// if (o.WorkOrderOverseerId != null)
// o.WorkOrderOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.WorkOrderOverseerId).Select(x => x.Name).FirstOrDefaultAsync();
if (loanUnitRateEnumList == null)
loanUnitRateEnumList = await AyaNova.Api.Controllers.EnumListController.GetEnumList(
StringUtil.TrimTypeName(typeof(LoanUnitRateUnit).ToString()),
UserTranslationId,
CurrentUserRoles);
o.UnitOfMeasureViz = loanUnitRateEnumList.Where(x => x.Id == (long)o.Rate).Select(x => x.Name).First();
LoanUnit loanUnit = await ct.LoanUnit.AsNoTracking().FirstOrDefaultAsync(x => x.Id == o.LoanUnitId);
TaxCode Tax = null;
if (o.TaxCodeId != null)
Tax = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == o.TaxCodeId);
if (Tax != null)
o.TaxCodeViz = Tax.Name;
o.PriceViz = 0;
if (loanUnit != null)
{
switch(o.Rate){
case LoanUnitRateUnit.None:
o.PriceViz=0;
break;
}
}
//manual price overrides anything
if (o.PriceOverride != null)
o.PriceViz = (decimal)o.PriceOverride;
else
{
//not manual so could potentially have a contract adjustment
var c = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, o.WorkOrderItemId);
if (c != null)
{
decimal pct = 0;
ContractOverrideType cot = ContractOverrideType.PriceDiscount;
bool TaggedAdjustmentInEffect = false;
//POTENTIAL CONTRACT ADJUSTMENTS
//First check if there is a matching tagged contract discount, that takes precedence
if (c.ContractPartOverrideItems.Count > 0)
{
//Iterate all contract tagged items in order of ones with the most tags first
foreach (var cp in c.ContractPartOverrideItems.OrderByDescending(z => z.Tags.Count))
if (cp.Tags.All(z => part.Tags.Any(x => x == z)))
{
if (cp.OverridePct != 0)
{
pct = cp.OverridePct / 100;
cot = cp.OverrideType;
TaggedAdjustmentInEffect = true;
}
}
}
//Generic discount?
if (!TaggedAdjustmentInEffect && c.ServiceRatesOverridePct != 0)
{
pct = c.ServiceRatesOverridePct / 100;
cot = c.ServiceRatesOverrideType;
}
//apply if discount found
if (pct != 0)
{
if (cot == ContractOverrideType.CostMarkup)
o.PriceViz = o.Cost + (o.Cost * pct);
else if (cot == ContractOverrideType.PriceDiscount)
o.PriceViz = o.ListPrice - (o.ListPrice * pct);
}
}
}
//Calculate totals and taxes
//NET
o.NetViz = o.PriceViz * o.Quantity;
//TAX
o.TaxAViz = 0;
o.TaxBViz = 0;
if (Tax != null)
{
if (Tax.TaxAPct != 0)
{
o.TaxAViz = o.NetViz * (Tax.TaxAPct / 100);
}
if (Tax.TaxBPct != 0)
{
if (Tax.TaxOnTax)
{
o.TaxBViz = (o.NetViz + o.TaxAViz) * (Tax.TaxBPct / 100);
}
else
{
o.TaxBViz = o.NetViz * (Tax.TaxBPct / 100);
}
}
}
o.LineTotalViz = o.NetViz + o.TaxAViz + o.TaxBViz;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//BIZ ACTIONS
//
//
private async Task LoanUnitBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemLoan newObj, WorkOrderItemLoan 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;
//SNAPSHOT PRICING
bool SnapshotPricing = true;
//if modifed, see what has changed and should be re-applied
if (ayaEvent == AyaEvent.Modified)
{
//If it wasn't a complete part change there is no need to set pricing
if (newObj.LoanUnitId == oldObj.LoanUnitId && newObj.Rate==oldObj.Rate)
{
SnapshotPricing = false;
}
}
//Pricing
if (SnapshotPricing)
{
//default in case nothing to apply
newObj.Charges = 0;
LoanUnit loanUnit = await ct.LoanUnit.AsNoTracking().FirstOrDefaultAsync(x => x.Id == newObj.LoanUnitId);
if (loanUnit != null)
{
newObj.Charges = s.Cost;
newObj.ListPrice = s.Retail;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -15,16 +15,41 @@ namespace AyaNova.Models
public DateTime? OutDate { get; set; }
public DateTime? DueDate { get; set; }
public DateTime? ReturnDate { get; set; }
[Required]
public decimal Charges { get; set; }
// [Required]
// public decimal Charges { get; set; }//removed in favor of ListPRice snapshot which normalizes fields to other objects
public long? TaxCodeId { get; set; }
[NotMapped]
public string TaxCodeViz { get; set; }
[Required]
public long LoanUnitId { get; set; }
[NotMapped]
public string LoanUnitViz { get; set; }
[Required]
public decimal Quantity { get; set; }
[Required]
public LoanUnitRateUnit Rate { get; set; }
public decimal Cost { get; set; }//cost from source record (e.g. serviceRate) or zero if no cost entered
public decimal ListPrice { get; set; }//List price from source record (e.g. serviceRate) or zero if no cost entered
//Standard pricing fields (mostly to support printed reports though some show in UI)
//some not to be sent with record depending on role (i.e. cost and charge in some cases)
public decimal? PriceOverride { get; set; }//user entered manually overridden price, if null then ignored in calcs otherwise this *is* the price even if zero
[NotMapped]
public string UnitOfMeasureViz { get; set; }//"each", "hour" etc
[NotMapped]
public decimal PriceViz { get; set; }//per unit price used in calcs after discounts or manual price if non-null or just ListPrice if no discount or manual override
[NotMapped]
public decimal NetViz { get; set; }//quantity * price (before taxes line total essentially)
[NotMapped]
public decimal TaxAViz { get; set; }//total amount of taxA
[NotMapped]
public decimal TaxBViz { get; set; }//total amount of taxB
[NotMapped]
public decimal LineTotalViz { get; set; }//line total netViz + taxes
//UTILITY FIELDS
[NotMapped]

View File

@@ -724,6 +724,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("CREATE TABLE aloanunit (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, "
+ "serial TEXT, unitid BIGINT NULL REFERENCES aunit(id), defaultrate INTEGER NOT NULL, "
+ "ratehourcost DECIMAL(38,18) NOT NULL DEFAULT 0, ratehalfdaycost DECIMAL(38,18) NOT NULL DEFAULT 0, ratedaycost DECIMAL(38,18) NOT NULL DEFAULT 0, rateweekcost DECIMAL(38,18) NOT NULL DEFAULT 0, ratemonthcost DECIMAL(38,18) NOT NULL DEFAULT 0, rateyearcost DECIMAL(38,18) NOT NULL DEFAULT 0, "
+ "ratehour DECIMAL(38,18) NOT NULL, ratehalfday DECIMAL(38,18) NOT NULL, rateday DECIMAL(38,18) NOT NULL, rateweek DECIMAL(38,18) NOT NULL, ratemonth DECIMAL(38,18) NOT NULL, rateyear DECIMAL(38,18) NOT NULL "
+ ")");
@@ -791,8 +792,8 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
//WORKORDERITEM LOAN
await ExecQueryAsync("CREATE TABLE aworkorderitemloan (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, workorderitemid BIGINT NOT NULL REFERENCES aworkorderitem (id), "
+ "notes TEXT, outdate TIMESTAMP, duedate TIMESTAMP, returndate TIMESTAMP, charges DECIMAL(38,18) NOT NULL default 0, taxcodeid BIGINT REFERENCES ataxcode, "
+ "loanunitid BIGINT NOT NULL REFERENCES aloanunit, quantity DECIMAL(19,5) NOT NULL default 0, rate INTEGER NOT NULL"
+ "notes TEXT, outdate TIMESTAMP, duedate TIMESTAMP, returndate TIMESTAMP,cost DECIMAL(38,18) NOT NULL default 0, listprice DECIMAL(38,18) NOT NULL default 0, priceoverride DECIMAL(38,18), "
+ "taxcodeid BIGINT REFERENCES ataxcode, loanunitid BIGINT NOT NULL REFERENCES aloanunit, quantity DECIMAL(19,5) NOT NULL default 0, rate INTEGER NOT NULL"
+ ")");
await ExecQueryAsync("ALTER TABLE aloanunit ADD column workorderitemloanid BIGINT NULL REFERENCES aworkorderitemloan");