356 lines
13 KiB
C#
356 lines
13 KiB
C#
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
|
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(SbmUserContext userContext)
|
|
{
|
|
UserContext = userContext;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
public SbmUserContext 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;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
|
|
//=======================================================================
|
|
}
|