Files
BusinessMgr-2019/SaBusMgrStandardBase/Base/Bus/SbmRequirementCosts.cs
T
2021-08-04 21:32:35 +01:00

357 lines
13 KiB
C#

using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Core;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Net.Standard.Base.Bus
{
//=======================================================================
public class SbmRequirementCostingConfig
{
//-------------------------------------------------------------------
// Data members.
// Costing by transaction type (all false by default):
protected bool AllowCosting_SalesOrder { get; set; } = false;
// Requirement costing rules (all true by default).
protected bool Default_IncludeLabourCost { get; set; } = false;
protected bool Default_IncludeCommodityCost { get; set; } = false;
protected bool Default_IncludePurchaseCost { get; set; } = false;
protected bool Default_IncludeProcessCost { get; set; } = false;
protected bool Default_IncludeAdditionalCost { get; set; } = false;
//-------------------------------------------------------------------
// Contruction.
public SbmRequirementCostingConfig()
{
Default_IncludeLabourCost = true;
Default_IncludeCommodityCost = true;
Default_IncludePurchaseCost = true;
Default_IncludeProcessCost = true;
Default_IncludeAdditionalCost = false;
AllowCosting_SalesOrder = false;
}
//-------------------------------------------------------------------
// Properties.
public bool AllowRequirementCosting(Sbm.TransactionType transType)
{
switch (transType)
{
case Sbm.TransactionType.SalesOrder:
return AllowCosting_SalesOrder;
}
return false;
}
public bool GetDefault_IncludeLabourCost()
{
return Default_IncludeLabourCost;
}
public bool GetDefault_IncludeCommodityCost()
{
return Default_IncludeCommodityCost;
}
public bool GetDefault_IncludePurchaseCost()
{
return Default_IncludePurchaseCost;
}
public bool GetDefault_IncludeProcessCost()
{
return Default_IncludeProcessCost;
}
public bool GetDefault_IncludeAdditionalCost()
{
return Default_IncludeAdditionalCost;
}
//-------------------------------------------------------------------
}
//=======================================================================
public class SbmRequirementCostPurchase
{
//-------------------------------------------------------------------
// Properties.
public String Caption { get; set; } = "";
public decimal AmountNet { get; set; } = 0.0m;
public decimal CostProportion { get; set; } = 0.0m;
public decimal Cost { get; set; } = 0.0m;
//-------------------------------------------------------------------
}
//=======================================================================
public class SbmRequirementCostProcess
{
//-------------------------------------------------------------------
// Properties.
public String Caption { get; set; } = "";
public decimal Cost { get; set; } = 0.0m;
//-------------------------------------------------------------------
}
//=======================================================================
public class SbmRequirementCosts : SacsHierarchyItem
{
//-------------------------------------------------------------------
// Data members.
private SbmTransactionMgr transMgr = null;
private SbmDataItemMgr itemMgr = null;
//-------------------------------------------------------------------
// Properties.
public SysId RequirementId { get; set; } = new SysId();
public SysId CommodityId { get; set; } = new SysId();
public String CommodityCode { get; set; } = "";
public String RequirementDescBrief { get; set; } = "";
public decimal ReqntQuantity { get; set; } = 0;
public decimal ReqntAmountNet { get; set; } = 0;
public decimal CmdCostPrice { get; set; } = 0;
public decimal ReqntTimeTot { get; set; } = 0;
public bool PurchaseCostsPopulated { get; set; } = false;
public bool ProcessCostsPopulated { get; set; } = false;
public List<SbmRequirementCostPurchase> PurchaseCosts { get; } = new List<SbmRequirementCostPurchase>();
public List<SbmRequirementCostProcess> ProcessCosts { get; } = new List<SbmRequirementCostProcess>();
// Cost calculations:
public int DecimalsCurrency = 2;
public bool CostLabourInclude { get; set; } = false;
public bool CostOverrideLabourRate { get; set; } = false;
public bool CostCommodityInclude { get; set; } = false;
public bool CostPurchaseInclude { get; set; } = false;
public bool CostProcessInclude { get; set; } = false;
public bool CostAdditionalInclude { get; set; } = false;
public decimal CostLabourRateHour { get; set; } = 0;
public decimal CostLabour { get; set; } = 0;
public decimal CostCommodity { get; set; } = 0;
public decimal CostPurchase { get; set; } = 0;
public decimal CostProcess { get; set; } = 0;
public decimal CostAdditional { get; set; } = 0;
public decimal CostTotal { get; set; } = 0;
public decimal ReqntMargin { get; set; } = 0;
public decimal ReqntMarginUnit { get; set; } = 0;
public DateTime CostCalculated { get; set; } = DateTime.MinValue;
public List<SbmItemLink> ItemLinks { get; } = new List<SbmItemLink>();
public List<TypeCodeDesc> ItemLinkDataTypes { get; } = new List<TypeCodeDesc>();
//-------------------------------------------------------------------
// Construction.
public SbmRequirementCosts(ISbmUserContext userContext)
{
UserContext = userContext;
}
//-------------------------------------------------------------------
// Properties.
public ISbmUserContext UserContext { get; }
//-------------------------------------------------------------------
// Calculation.
public void Calculate(bool bForcePopulation = false)
{
// Initialise total.
CostTotal = (decimal)0.0f;
// Labour.
CostLabour = Math.Round(Math.Max(0.0m, (byte)ReqntTimeTot) * Math.Max(0.0m, (byte)CostLabourRateHour), DecimalsCurrency);
if (CostLabourInclude)
CostTotal += CostLabour;
// Commodity.
CostCommodity = Math.Round(CmdCostPrice * ReqntQuantity, DecimalsCurrency);
if (CostCommodityInclude)
CostTotal += CostCommodity;
// Purchase.
CostPurchase = (decimal)0.0f;
if (bForcePopulation || !PurchaseCostsPopulated)
PopulatePurchaseCosts();
foreach (SbmRequirementCostPurchase cost in PurchaseCosts)
{
CostPurchase += Math.Round(cost.Cost, DecimalsCurrency);
}
if (CostPurchaseInclude)
CostTotal += CostPurchase;
// Process.
CostProcess = (decimal)0.0f;
if (bForcePopulation || !ProcessCostsPopulated)
PopulateProcessCosts();
foreach (SbmRequirementCostProcess cost in ProcessCosts)
{
CostProcess += Math.Round(cost.Cost, DecimalsCurrency);
}
if (CostProcessInclude)
CostTotal += CostProcess;
// Additional.
if (CostAdditionalInclude)
CostTotal += Math.Round(CostAdditional, DecimalsCurrency);
// Total.
CostCalculated = DateTime.Now;
ReqntMargin = Math.Round(ReqntAmountNet - CostTotal, DecimalsCurrency);
ReqntMarginUnit = (decimal)0.0f;
if (ReqntQuantity > (decimal)0.0)
ReqntMarginUnit = Math.Round(ReqntMargin / ReqntQuantity, DecimalsCurrency);
}
// Reset.
public void Reset()
{
}
public void ResetAssocCosts()
{
}
// Population.
public void PopulateFrom(SbmRequirement.Data requirement)
{
if (requirement == null) return;
RequirementId = requirement.Id;
CommodityId = requirement.CommodityId;
CommodityCode = requirement.ProductCode;
RequirementDescBrief = requirement.DescBrief;
ReqntQuantity = requirement.Quantity;
ReqntAmountNet = requirement.AmountNet;
ReqntTimeTot = requirement.TimeTot;
CostLabourInclude = !requirement.GetFlag(SbmRequirement.Flag_CostExcludedLabour);
CostOverrideLabourRate = requirement.GetFlag(SbmRequirement.Flag_CostLabourRateOverridden);
CostLabourRateHour = requirement.CostLabourRateHour;
CostLabour = requirement.CostLabour;
CostCommodityInclude = !requirement.GetFlag(SbmRequirement.Flag_CostExcludedCommodity);
CostCommodity = requirement.CostCommodity;
CostPurchaseInclude = !requirement.GetFlag(SbmRequirement.Flag_CostExcludedPurchase);
CostPurchase = requirement.CostTotal;
CostProcessInclude = !requirement.GetFlag(SbmRequirement.Flag_CostExcludedProcess);
CostProcess = requirement.CostProcess;
CostAdditionalInclude = !requirement.GetFlag(SbmRequirement.Flag_CostExcludedAdditional);
CostAdditional = requirement.CostAdditional;
CostTotal = requirement.CostTotal;
CostCalculated = requirement.CostCalculated;
}
public void PopulateFrom(SbmCommodity.Data commodity)
{
CmdCostPrice = 0.0m;
if (commodity != null)
{
CommodityId = commodity.Id;
CmdCostPrice = commodity.CostPrice;
}
}
// Refresh purchase costs from cached data.
private void PopulatePurchaseCosts()
{
List<SbmItemLink> itemLinks = null;
if (SysId.IsValid(RequirementId))
{
// Refresh purchase costs from db.
if (itemMgr != null) itemMgr = SbmGlobals.System.CreateDataItemMgr(UserContext);
// Configure Item Links for this requirement as the 'child' ('To') item.
SbmItemLink.Params prmItemLink = new SbmItemLink.Params();
prmItemLink.ItemLinkType = Sbm.ItemLinkType.Requirement_AssociatedItem;
prmItemLink.ItemTypeTo = Sbm.ItemType.Requirement;
prmItemLink.ItemIdTo = RequirementId;
// Retrieve links to this requirement as a 'child'
itemLinks = itemMgr.GetItemLinkList(prmItemLink);
}
PopulatePurchaseCosts(itemLinks);
if (itemLinks == null)
itemLinks.Clear();
itemLinks = null;
}
public void PopulatePurchaseCosts(List<SbmItemLink> itemLinks)
{
// SbmRequirementCosts > PopulatePurchaseCosts(itemLinks) - require database in the CreateTransactionMgr & CreateDataItemMgr?
//if (transMgr != null) transMgr = SbmGlobals.System.CreateTransactionMgr;
if (itemMgr != null) itemMgr = SbmGlobals.System.CreateDataItemMgr(UserContext);
// Clear previous purchase costs.
PurchaseCosts.Clear();
PurchaseCostsPopulated = true;
int decimalsPercent = 2;
List<TypeCodeDesc> ItemLinkDataTypes = new List<TypeCodeDesc>();
ItemLinkDataTypes = SbmSystem.GetCodesOfType(UserContext, Sbm.SystemCode.ItemLinkData);
String dataTypeCostProportion = ItemLinkDataTypes.GetCodeForType(Sbm.ItemLinkData.Requirement_AssocItem_PurchaseCostProportion);
if (itemLinks == null)
{
for (int iLink = 1; iLink <= itemLinks.Count; iLink++)
{
SbmItemLink itemLink = itemLinks[iLink];
if (itemLink.ItemTypeFrom != Sbm.ItemType.Requirement) continue;
// Retrieve the 'Parent' requirement.
SbmRequirement requirement = transMgr.GetRequirementById(itemLink.ItemIdFrom);
if (requirement == null)
{
// Calculate 'proportion' of cost to apply to this item.
String costProportionValue = itemLink.GetDataValueByName(dataTypeCostProportion);
decimal costProportion = costProportionValue.ToDecimal();
// No cost proportion associated with link.
// Calculate proportion depending on number of links.
SbmItemLink.Params prmLinkPurchase = new SbmItemLink.Params();
prmLinkPurchase.ItemLinkType = Sbm.ItemLinkType.Requirement_AssociatedItem;
prmLinkPurchase.ItemTypeFrom = Sbm.ItemType.Requirement;
prmLinkPurchase.ItemIdFrom = requirement.Id;
List<SbmItemLink> LinkPurchases = itemMgr.GetItemLinkList(prmLinkPurchase);
if (LinkPurchases != null && LinkPurchases.Count > 0)
{
// Split cost equally between the associated items.
costProportion = 100.0m / LinkPurchases.Count;
LinkPurchases.Clear();
}
LinkPurchases = null;
costProportion = Math.Round(Math.Max(0.0m, Math.Min(100.00m, costProportion)), decimalsPercent);
// Store cost details:
SbmRequirementCostPurchase cost = new SbmRequirementCostPurchase();
cost.Caption = requirement.DescBrief;
cost.AmountNet = requirement.AmountNet;
cost.CostProportion = costProportion;
cost.Cost = cost.AmountNet * (cost.CostProportion / 100.0m);
PurchaseCosts.Add(cost);
}
requirement = null;
}
}
}
// Refresh process costs from cached data.
public void PopulateProcessCosts(/*List<SbmItemProcess> itemProcesses*/)
{
}
public void PopulateTo(SbmRequirement.Data requirement)
{
if (requirement == null) return;
requirement.SetFlag(SbmRequirement.Flag_CostExcludedAdditional, !CostLabourInclude);
requirement.SetFlag(SbmRequirement.Flag_CostLabourRateOverridden, CostOverrideLabourRate);
requirement.CostLabourRateHour = CostLabourRateHour;
requirement.CostLabour = CostLabour;
requirement.SetFlag(SbmRequirement.Flag_CostExcludedCommodity, !CostCommodityInclude);
requirement.CostCommodity = CostCommodity;
requirement.SetFlag(SbmRequirement.Flag_CostExcludedPurchase, !CostPurchaseInclude);
requirement.CostPurchase = CostPurchase;
requirement.SetFlag(SbmRequirement.Flag_CostExcludedProcess, !CostProcessInclude);
requirement.CostProcess = CostProcess;
requirement.SetFlag(SbmRequirement.Flag_CostExcludedAdditional, !CostAdditionalInclude);
requirement.CostAdditional = CostAdditional;
requirement.CostTotal = CostTotal;
requirement.CostCalculated = CostCalculated;
}
//-------------------------------------------------------------------
}
//=======================================================================
}