internal static decimal GetLineCost(IRoomBilling item) { int cleanRoomId = 6; int organicsBayId = 6; // [2015-11-13 jg] this is identical to the logic originally in: // 1) sselFinOps.AppCode.BLL.FormulaBL.ApplyRoomFormula (for External Invoice) // 2) sselIndReports.AppCode.Bll.RoomBillingBL.GetRoomBillingDataByClientID (for User Usage Summary) // 3) LNF.WebApi.Billing.Models.ReportUtility.ApplyRoomFormula (for SUB reports) decimal result; //1. Find out all Monthly type users and apply to Clean room if (BillingTypes.IsMonthlyUserBillingType(item.BillingTypeID)) { if (item.RoomID == cleanRoomId) //Clean Room { result = item.MonthlyRoomCharge; } else { result = item.TotalCharge; } } //2. The growers are charged with room fee only when they reserve and activate a tool else if (BillingTypes.IsGrowerUserBillingType(item.BillingTypeID)) { if (item.RoomID == organicsBayId) //Organics Bay { result = item.RoomCharge; //organics bay must be charged for growers as well } else { result = item.AccountDays * item.RoomRate + item.EntryCharge; } } else if (item.BillingTypeID == BillingTypes.Other) { result = 0; } else if (item.BillingTypeID == BillingTypes.Grower_Observer) { result = item.TotalCharge; } else { //Per Use types result = item.TotalCharge; } return(result); }
public static void ApplyRoomFormula(DataTable dt) { if (!dt.Columns.Contains("LineCost")) { dt.Columns.Add("LineCost", typeof(double)); } int billingTypeId; int roomId = 0; foreach (DataRow dr in dt.Rows) { billingTypeId = dr.Field <int>("BillingTypeID"); roomId = dr.Field <int>("RoomID"); //1. Find out all Monthly type users and apply to Clean room if (BillingTypes.IsMonthlyUserBillingType(billingTypeId)) { if (roomId == 6) { dr["LineCost"] = dr.Field <decimal>("MonthlyRoomCharge"); } else { dr["LineCost"] = dr.Field <decimal>("RoomCharge") + dr.Field <decimal>("EntryCharge"); } } //2. The growers are charged with room fee only when they reserve and activate a tool else if (BillingTypes.IsGrowerUserBillingType(billingTypeId)) { if (roomId == 4) { dr["LineCost"] = dr.Field <decimal>("RoomCharge"); //Organics bay must be charged for growers as well } else { dr["LineCost"] = (dr.Field <decimal>("AccountDays") * dr.Field <decimal>("RoomRate")) + dr.Field <decimal>("EntryCharge"); } } else if (billingTypeId == BillingTypes.Other) { dr["LineCost"] = 0; } else { //Per Use types dr["LineCost"] = dr.Field <decimal>("RoomCharge") + dr.Field <decimal>("EntryCharge"); } } }
private DataTable GetRoomBillingDataByClientID(DateTime period, int clientId) { DataTable dt; if (period.Month == DateTime.Now.Month && period.Year == DateTime.Now.Year) { dt = RoomBillingDA.GetRoomBillingTempDataByClientID(period, clientId); } else { dt = RoomBillingDA.GetRoomBillingDataByClientID(period, clientId); } if (!dt.Columns.Contains("LineCost")) { dt.Columns.Add("LineCost", typeof(double)); } // Part I: Get the true cost based on billing types foreach (DataRow dr in dt.Rows) { int billingTypeId = dr.Field <int>("BillingTypeID"); var room = Rooms.GetRoom(dr.Field <int>("RoomID")); if (billingTypeId == BillingTypes.Other) { dr["LineCost"] = 0; } else if (BillingTypes.IsGrowerUserBillingType(billingTypeId)) { if (room == LabRoom.OrganicsBay) { //Organics bay must be charged for growers as well dr["LineCost"] = dr.Field <decimal>("RoomCharge"); } else { dr["LineCost"] = dr.Field <decimal>("AccountDays") * dr.Field <decimal>("RoomRate") + dr.Field <decimal>("EntryCharge"); } } else { //Per Use types dr["LineCost"] = dr.Field <decimal>("RoomCharge") + dr.Field <decimal>("EntryCharge"); } } return(dt); }
public static void ApplyRoomFormula(DataTable dtIn) { int billingTypeId; LabRoom room; foreach (DataRow dr in dtIn.Rows) { billingTypeId = dr.Field<int>("BillingTypeID"); room = (LabRoom)dr.Field<int>("RoomID"); //1. Find out all Monthly type users and apply to Clean room if (BillingTypes.IsMonthlyUserBillingType(billingTypeId)) { if (room == LabRoom.CleanRoom) dr["LineCost"] = dr["MonthlyRoomCharge"]; else dr["LineCost"] = dr.Field<decimal>("RoomCharge") + dr.Field<decimal>("EntryCharge"); } //2. The growers are charged with room fee only when they reserve and activate a tool else if (BillingTypes.IsGrowerUserBillingType(billingTypeId)) { if (room == LabRoom.Organics) { //Organics bay must be charged for growers as well dr["LineCost"] = dr["RoomCharge"]; } else dr["LineCost"] = (dr.Field<decimal>("AccountDays") * dr.Field<decimal>("RoomRate")) + dr.Field<decimal>("EntryCharge"); } else if (billingTypeId == BillingTypes.Other) { dr["LineCost"] = 0; } else { //Per Use types dr["LineCost"] = dr.Field<decimal>("RoomCharge") + dr.Field<decimal>("EntryCharge"); } } }
// Call this function if period is between 2011-04-01 and 2011-06-01 public static DataSet GetToolBillingDataByClientID20110401(HttpContextBase context, DateTime period, int clientId) { DataSet ds = null; DataTable dt1, dt2, dt3; DateTime CutOffDate20110401 = new DateTime(2011, 4, 1); if (period.Month == DateTime.Now.Month && period.Year == DateTime.Now.Year) { //Viewing current month data ds = ToolBillingDA.GetToolBillingTempDataByClientID(period, clientId); } else { ds = new DataSet(); BillingTableType t1, t2, t3; if (period < CutOffDate20110401) { t1 = BillingTableType.ToolBillingActivated; t2 = BillingTableType.ToolBillingUncancelled; t3 = BillingTableType.ToolBillingForgiven; } else { t1 = BillingTableType.ToolBilling20110401Reservations; t2 = BillingTableType.ToolBilling20110401Cancelled; t3 = BillingTableType.ToolBilling20110401Forgiven; } dt1 = BillingTablesBL.GetMultipleTables(context, period.Year, period.Month, clientId, t1); dt2 = BillingTablesBL.GetMultipleTables(context, period.Year, period.Month, clientId, t2); dt3 = BillingTablesBL.GetMultipleTables(context, period.Year, period.Month, clientId, t3); ds.Tables.Add(dt1.Copy()); ds.Tables.Add(dt2.Copy()); ds.Tables.Add(dt3.Copy()); } if (period < CutOffDate20110401) { //Part I : calculate the true Line Cost based on billing type, reservation status foreach (DataTable dt in ds.Tables) { dt.Columns.Add("LineCost", typeof(double)); foreach (DataRow dr in dt.Rows) { int billingTypeId = dr.Field <int>("BillingTypeID"); var room = Rooms.All().FirstOrDefault(x => x.RoomID == dr.Field <int>("RoomID")); bool isStarted = dr.Field <bool>("IsStarted"); if (BillingTypes.IsMonthlyUserBillingType(billingTypeId)) { if (period >= new DateTime(2010, 7, 1)) { //Monthly User, so we have flat fee for clean room if (room == Rooms.CleanRoom) { if (dr.Field <int>("ResourceID") == 56000) { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("ReservationFee"); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee"); } } else { dr["LineCost"] = 0; } } else { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("ReservationFee"); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee"); } } } else { //Monthly User, so we have flat fee for clean room if (room == Rooms.CleanRoom) { if (dr.Field <int>("ResourceID") == 56000) { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("ReservationFee"); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee"); } } else { dr["LineCost"] = 0; } } else { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("ReservationFee"); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee"); } } } } else if (billingTypeId == BillingTypes.Other) { dr["LineCost"] = 0; } else { if (period >= new DateTime(2010, 7, 1)) { //Per Use types if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("ReservationFee"); } else { dr["LineCost"] = dr["UncancelledPenaltyFee"]; } } else { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("ReservationFee"); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee"); } } } //if the tool rate is 0, then everything should be 0 bool hasPerUseRateColumn = dt.Columns.Contains("PerUseRate"); var resourceRate = dr.Field <decimal>("ResourceRate"); var perUserRate = hasPerUseRateColumn ? dr.Field <decimal>("PerUseRate") : 0M; if (resourceRate + perUserRate == 0) { dr["LineCost"] = 0; } } } } else { //2011-04-01 foreach (DataTable dt in ds.Tables) { dt.Columns.Add("LineCost", typeof(double)); foreach (DataRow dr in dt.Rows) { int billingTypeId = dr.Field <int>("BillingTypeID"); bool isCancelledBeforeAllowedTime = dr.Field <bool>("IsCancelledBeforeAllowedTime"); if (billingTypeId == BillingTypes.Other) { dr["LineCost"] = 0; } else { if (period >= new DateTime(2010, 7, 1)) { //Per Use types if (!isCancelledBeforeAllowedTime) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("BookingFee"); } else { dr["LineCost"] = dr.Field <decimal>("BookingFee"); //Cancelled before two hours } } } //if the tool rate is 0, then everything should be 0 decimal rateTotal = dr.Field <decimal>("ResourceRate") + dr.Field <decimal>("PerUserRate"); if (rateTotal == 0) { dr["LineCost"] = 0; } } } } return(ds); }
protected override void FillDataTable(DataTable dt) { BillingUnit summaryUnit = summaryUnits.First(); Compile mCompile = new Compile(); DataTable dtRoomDB = mCompile.CalcCost("Room", string.Empty, "ChargeTypeID", 5, EndPeriod.AddMonths(-1), 0, 0, Compile.AggType.CliAcctType); DataTable dtClientWithCharges = mCompile.GetTable(1); double roomCapCost = mCompile.CapCost; //***************************************************************************** //2008-01-22 The code below is an EXTRA step for calculating the cost of room charge // Right now the strategy is not to change Compile.CalcCost at all and if I want to // add new features that would affect CalcCost, I would rather do it after CalcCost is called. // But future new design is required else the system will get too complicated. //2208-05-15 the reason why we are doing this extra step is to show NAP rooms (as of now, it's DC Test lab and Chem room) //with correct monthly fee on the JE //dtNAPRoomForAllChargeType's columns //CostID //ChargeTypeID //TableNameOrDescript //RoomID //AcctPer //AddVal //RoomCost //effDate //Get all active NAP Rooms with their costs, all chargetypes are returned //This is a temporary table, it's used to derive the really useful table below DataTable dtNAPRoomForAllChargeType = BLL.RoomManager.GetAllNAPRoomsWithCosts(EndPeriod); //filter out the chargetype so that we only have Internal costs with each NAP room DataRow[] drsNAPRoomForInternal = dtNAPRoomForAllChargeType.Select("ChargeTypeID = 5"); //Loop through each room and find out this specified month's apportionment data. foreach (DataRow dr1 in drsNAPRoomForInternal) { DataTable dtApportionData = BLL.RoomApportionDataManager.GetNAPRoomApportionDataByPeriod(StartPeriod, EndPeriod, dr1.Field <int>("RoomID")); foreach (DataRow dr2 in dtApportionData.Rows) { DataRow[] drs = dtRoomDB.Select(string.Format("ClientID = {0} AND AccountID = {1} AND RoomID = {2}", dr2["ClientID"], dr2["AccountID"], dr2["RoomID"])); if (drs.Length == 1) { drs[0].SetField("TotalCalcCost", (dr2.Field <double>("Percentage") * dr1.Field <double>("RoomCost")) / 100); } } } dtRoomDB.Columns.Add("DebitAccount", typeof(string)); dtRoomDB.Columns.Add("CreditAccount", typeof(string)); dtRoomDB.Columns.Add("LineDesc", typeof(string)); dtRoomDB.Columns.Add("TotalAllAccountCost", typeof(double)); //dtRoom - ClientID, AccountID, RoomID, TotalCalCost, TotalEntries, TotalHours // cap costs - capping is per clientorg, thus apportion cappeing across charges // note that this assumes that there is only one org for internal academic!!! object temp; double totalRoomCharges; foreach (DataRow drCWC in dtClientWithCharges.Rows) { temp = dtRoomDB.Compute("SUM(TotalCalcCost)", string.Format("ClientID = {0}", drCWC["ClientID"])); if (temp == null || temp == DBNull.Value) { totalRoomCharges = 0; } else { totalRoomCharges = Convert.ToDouble(temp); } if (totalRoomCharges > roomCapCost) { DataRow[] fdr = dtRoomDB.Select(string.Format("ClientID = {0}", drCWC["ClientID"])); for (int i = 0; i < fdr.Length; i++) { fdr[i].SetField("TotalCalcCost", fdr[i].Field <double>("TotalCalcCost") * roomCapCost / totalRoomCharges); } } } DataTable dtClient = ClientDA.GetAllClient(StartPeriod, EndPeriod); DataTable dtAccount = AccountDA.GetAllInternalAccount(StartPeriod, EndPeriod); DataTable dtClientAccount = ClientDA.GetAllClientAccountWithManagerName(StartPeriod, EndPeriod); //used to find out manager's name //Get the general lab account ID and lab credit account ID GlobalCost gc = GlobalCostDA.GetGlobalCost(); //2008-05-15 very complicated code - trying to figure out the percentage distribution for monthly users, since the "TotalCalcCost" has //been calculated based on percentage in the CalcCost function, so we need to figure out the percentage here again by findind out the total //and divide the individual record's "TotalCalcCost' foreach (DataRow drCWC in dtClientWithCharges.Rows) { DataRow[] fdr = dtRoomDB.Select(string.Format("ClientID = {0} AND RoomID = {1}", drCWC["ClientID"], (int)BLL.LabRoom.CleanRoom)); if (fdr.Length > 1) { //this user has multiple account for the clean room usage, so we have to find out the total of all accounts on this clean room double tempTotal = Convert.ToDouble(dtRoomDB.Compute("SUM(TotalCalcCost)", string.Format("ClientID = {0} AND RoomID = {1}", drCWC["ClientID"], (int)BLL.LabRoom.CleanRoom))); DataRow[] fdrRoom = dtRoomDB.Select(string.Format("ClientID = {0} AND RoomID = {1}", drCWC["ClientID"], (int)BLL.LabRoom.CleanRoom)); for (int i = 0; i < fdrRoom.Length; i++) { fdrRoom[i].SetField("TotalAllAccountCost", tempTotal); //assign the total to each record } } } //2008-08-28 Get Billing Type DataTable dtBillingType = BillingTypeDA.GetAllBillingTypes(); foreach (DataRow dr in dtRoomDB.Rows) { dr["DebitAccount"] = dtAccount.Rows.Find(dr.Field <int>("AccountID"))["Number"]; dr["CreditAccount"] = dtAccount.Rows.Find(gc.LabCreditAccountID)["Number"]; //2007-06-19 financial manager may not be an administrator, but their username must be on JE dr["LineDesc"] = GetLineDesc(dr, dtClient, dtBillingType); //2008-05-15 the code below handles the clean room monthly users - it's special code that we have to get rid of when all //billingtype are all gone int billingTypeId = dr.Field <int>("BillingType"); if (dr.Field <BLL.LabRoom>("RoomID") == BLL.LabRoom.CleanRoom) //6 is clean room { if (BillingTypes.IsMonthlyUserBillingType(billingTypeId)) { if (dr["TotalAllAccountCost"] == DBNull.Value) { //if TotalAllAccountCost is nothing, it means this user has only one account //2008-10-27 but it might also that the user has only one internal account, and he apportion all hours to his external accouts //so we must also check 'TotalHours' to make sure the user has more than 0 hours if (dr.Field <double>("TotalHours") != 0) { dr.SetField("TotalCalcCost", BLL.BillingTypeManager.GetTotalCostByBillingType(billingTypeId, 0, 0, BLL.LabRoom.CleanRoom, 1315)); } } else { double total = dr.Field <double>("TotalAllAccountCost"); dr.SetField("TotalCalcCost", (dr.Field <double>("TotalCalcCost") / total) * BLL.BillingTypeManager.GetTotalCostByBillingType(billingTypeId, 0, 0, BLL.LabRoom.CleanRoom, 1315)); } } } } //****** apply filters ****** //Get the list below so that we can exclude users who spent less than X minutes in lab(Clean or Chem) in this month DataTable dtlistClean = RoomUsageData.GetUserListLessThanXMin(StartPeriod, EndPeriod, int.Parse(ConfigurationManager.AppSettings["CleanRoomMinTimeMinute"]), "CleanRoom"); DataTable dtlistChem = RoomUsageData.GetUserListLessThanXMin(StartPeriod, EndPeriod, int.Parse(ConfigurationManager.AppSettings["ChemRoomMinTimeMinute"]), "ChemRoom"); //For performance issue, we have to calculate something first, since it's used on all rows string depRefNum = string.Empty; double fTotal = 0; string creditAccount = dtAccount.Rows.Find(gc.LabCreditAccountID)["Number"].ToString(); string creditAccountShortCode = dtAccount.Rows.Find(gc.LabCreditAccountID)["ShortCode"].ToString(); //Do not show an item if the charge and xcharge accounts are the 'same' - can only happen for 941975 //Do not show items that are associated with specific accounts - need to allow users to add manually here in future foreach (DataRow sdr in dtRoomDB.Rows) { if (sdr.Field <double>("TotalCalcCost") > 0) { var excludedAccounts = new[] { gc.LabAccountID, 143, 179, 188 }; if (!excludedAccounts.Contains(sdr.Field <int>("AccountID")) && sdr.Field <int>("BillingType") != BillingTypes.Other) { //2006-12-21 get rid of people who stayed in the lab less than 30 minutes in a month string expression = string.Format("ClientID = {0}", sdr["ClientID"]); DataRow[] foundRows; bool flag = false; if (sdr.Field <BLL.LabRoom>("RoomID") == BLL.LabRoom.CleanRoom) //6 = clean room { foundRows = dtlistClean.Select(expression); } else if (sdr.Field <BLL.LabRoom>("RoomID") == BLL.LabRoom.ChemRoom) //25 = chem room { foundRows = dtlistChem.Select(expression); } else //DCLab { foundRows = null; } if (foundRows == null) { flag = true; //add to the SUB } else { if (foundRows.Length == 0) { flag = true; } } if (flag) //if no foundrow, we can add this client to JE { DataRow ndr = dt.NewRow(); DataRow drAccount = dtAccount.Rows.Find(sdr.Field <int>("AccountID")); string debitAccount = drAccount["Number"].ToString(); string shortCode = drAccount["ShortCode"].ToString(); //get manager's name DataRow[] drClientAccount = dtClientAccount.Select(string.Format("AccountID = {0}", sdr["AccountID"])); if (drClientAccount.Length > 0) { depRefNum = drClientAccount[0]["ManagerName"].ToString(); } else { depRefNum = "No Manager Found"; } AccountNumber debitAccountNum = AccountNumber.Parse(debitAccount); ndr["CardType"] = 1; ndr["ShortCode"] = shortCode; ndr["Account"] = debitAccountNum.Account; ndr["FundCode"] = debitAccountNum.FundCode; ndr["DeptID"] = debitAccountNum.DeptID; ndr["ProgramCode"] = debitAccountNum.ProgramCode; ndr["Class"] = debitAccountNum.Class; ndr["ProjectGrant"] = debitAccountNum.ProjectGrant; ndr["VendorID"] = "0000456136"; ndr["InvoiceDate"] = EndPeriod.AddMonths(-1).ToString("yyyy/MM/dd"); ndr["InvoiceID"] = $"{ReportSettings.CompanyName} Room Charge"; ndr["Uniqname"] = dtClient.Rows.Find(sdr.Field <int>("ClientID"))["UserName"]; ndr["DepartmentalReferenceNumber"] = depRefNum; ndr["ItemDescription"] = GetItemDesc(sdr, dtClient, dtBillingType); ndr["QuantityVouchered"] = "1.0000"; double chargeAmount = Math.Round(sdr.Field <double>("TotalCalcCost"), 5); ndr["UnitOfMeasure"] = chargeAmount; ndr["MerchandiseAmount"] = Math.Round(chargeAmount, 2); ndr["CreditAccount"] = creditAccount; //Used to calculate the total credit amount fTotal += chargeAmount; dt.Rows.Add(ndr); } } } } //Summary row summaryUnit.CardType = 1; summaryUnit.ShortCode = creditAccountShortCode; summaryUnit.Account = creditAccount.Substring(0, 6); summaryUnit.FundCode = creditAccount.Substring(6, 5); summaryUnit.DeptID = creditAccount.Substring(11, 6); summaryUnit.ProgramCode = creditAccount.Substring(17, 5); summaryUnit.ClassName = creditAccount.Substring(22, 5); summaryUnit.ProjectGrant = creditAccount.Substring(27, 7); summaryUnit.InvoiceDate = EndPeriod.AddMonths(-1).ToString("yyyy/MM/dd"); summaryUnit.Uniqname = ReportSettings.FinancialManagerUserName; summaryUnit.DepartmentalReferenceNumber = depRefNum; summaryUnit.ItemDescription = ReportSettings.FinancialManagerUserName; summaryUnit.MerchandiseAmount = Math.Round(-fTotal, 2); summaryUnit.CreditAccount = creditAccount; //Clean things up manually might help performance in general dtRoomDB.Clear(); dtClient.Clear(); dtAccount.Clear(); }
public static void ApplyToolFormula(DataTable dt, DateTime startPeriod, DateTime endPeriod) { if (!dt.Columns.Contains("LineCost")) { dt.Columns.Add("LineCost", typeof(decimal)); } int billingTypeId; int roomId = 0; bool isStarted = true; foreach (DataRow dr in dt.Rows) { billingTypeId = dr.Field <int>("BillingTypeID"); roomId = dr.Field <int>("RoomID"); isStarted = dr.Field <bool>("IsStarted"); if (BillingTypes.IsMonthlyUserBillingType(billingTypeId)) { //Monthly User, charge mask maker for everyone if (roomId == 6) { if (dr.Field <int>("ResourceID") == 56000) { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + (dr.Field <decimal>("ResourceRate") == 0 ? 0 : dr.Field <decimal>("ReservationFee2")); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee2"); } } else { dr["LineCost"] = 0; } } else { //non clean room tools are always charged for usage fee if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + (dr.Field <decimal>("ResourceRate") == 0 ? 0 : dr.Field <decimal>("ReservationFee2")); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee2"); } } } //Per Use types if (startPeriod >= new DateTime(2010, 7, 1)) { //dr("LineCost") = dr("UsageFee") + dr("OverTimePenaltyFee") + dr("UncancelledPenaltyFee") + dr("ReservationFee2") //2011-05 New tool billing started on 2011-04 if (startPeriod >= new DateTime(2011, 4, 1)) { if (!dr.Field <bool>("IsCancelledBeforeAllowedTime")) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + dr.Field <decimal>("BookingFee"); //IIf(dr("ResourceRate") = 0, 0, dr("ReservationFee")) } else { dr["LineCost"] = dr.Field <decimal>("BookingFee"); //Cancelled before two hours } } else { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + (dr.Field <decimal>("ResourceRate") == 0 ? 0 : dr.Field <decimal>("ReservationFee2")); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee"); //+ dr("ReservationFee") } } //If BillingTypeID = BillingType.Remote Then // '2010-12-06 Sandrine doesn't want Remote to be shown // 'dr("LineCost") = 0 //End If } else { if (isStarted) { dr["LineCost"] = dr.Field <decimal>("UsageFeeCharged") + dr.Field <decimal>("OverTimePenaltyFee") + (dr.Field <decimal>("ResourceRate") == 0 ? 0 : dr.Field <decimal>("ReservationFee2")); } else { dr["LineCost"] = dr.Field <decimal>("UncancelledPenaltyFee") + dr.Field <decimal>("ReservationFee2"); } } //If isStarted Then // dr("LineCost") = dr("UsageFee") + dr("OverTimePenaltyFee") + dr("ReservationFee2") //Else // dr("LineCost") = dr("UncancelledPenaltyFee") + dr("ReservationFee2") //End If //if resource rate is 0 , everything must be 0 (what about per use charge) if (dr.Field <decimal>("ResourceRate") == 0) { dr["LineCost"] = 0; } } }
/// <summary> /// This method computes the total amount charged for tool usage. This is used in all billing reports sent to UofM FinOps /// </summary> public static decimal GetLineCost(ToolLineCostParameters p) { // [2015-11-13 jg] this is identical to the logic originally in: // 1) sselFinOps.AppCode.BLL.FormulaBL.ApplyToolFormula (for External Invoice) // 2) sselIndReports.AppCode.Bll.ToolBillingBL.GetToolBillingDataByClientID20110701 (for User Usage Summary) // 3) LNF.WebApi.Billing.Models.ReportUtility.ApplyToolFormula (for SUB reports, note: this is the replacement for the Billing WCF service) // // I think at this point all the formulas can be replaced by GetTotalCharge() // because each value used by the formula should correctly reflect the rules // in place during the given period (or at least that is the goal). decimal result; //if rates are 0 everything must be 0 (this was at the end, but why not do it at the beginning?) if (p.ResourceRate + p.PerUseRate == 0) { return(0); } int cleanRoomId = 6; int maskMakerId = 56000; if (BillingTypes.IsMonthlyUserBillingType(p.BillingTypeID)) //not used at this point but maybe in the future { // Monthly User, charge mask maker for everyone if (p.RoomID == cleanRoomId) //Clean Room { if (p.ResourceID == maskMakerId) //Mask Maker { if (p.IsStarted) { result = p.UsageFeeCharged + p.OverTimePenaltyFee + (p.ResourceRate == 0 ? 0 : p.ReservationFee2); } else { result = p.UncancelledPenaltyFee + p.ReservationFee2; } } else { result = 0; } } else { //non clean room tools are always charged for usage fee if (p.IsStarted) { result = p.UsageFeeCharged + p.OverTimePenaltyFee + (p.ResourceRate == 0 ? 0 : p.ReservationFee2); } else { result = p.UncancelledPenaltyFee + p.ReservationFee2; } } } else if (p.BillingTypeID == BillingTypes.Other) { //based on sselIndReports.AppCode.BLL.ToolBillingBL.GetToolBillingDataByClientID20110701 the Other billing type is not set to zero any longer result = ToolBillingItem.GetTotalCharge(p.UsageFeeCharged, p.OverTimePenaltyFee, p.BookingFee, p.UncancelledPenaltyFee, p.ReservationFee2); } else { //Per Use types if (p.Period >= new DateTime(2010, 7, 1)) { //2022-04 New tool billing started on 2022-03 if (p.Period >= new DateTime(2022, 3, 1)) { // [2022-04-08 jg] Use the new "audit friendly" method. This way of calculating makes it easy to break out the constituent parts and // do the math to verify the line cost. The User Usage Summary report has been updated to display these parts. result = GetLineCostAuditFriendlyVersion(p); } //2011-05 New tool billing started on 2011-04 else if (p.Period >= new DateTime(2011, 4, 1)) { if (!p.IsCancelledBeforeAllowedTime) { result = p.UsageFeeCharged + p.OverTimePenaltyFee + p.BookingFee; //should be the same as GetTotalCharge() } else { result = p.BookingFee; //Cancelled before two hours - should be the same as GetTotalCharge() } } else { if (p.IsStarted) { result = p.UsageFeeCharged + p.OverTimePenaltyFee + (p.ResourceRate == 0 ? 0 : p.ReservationFee2); //should be the same as GetTotalCharge() } else { result = p.UncancelledPenaltyFee; //should be the same as GetTotalCharge() } } } else { if (p.IsStarted) { result = p.UsageFeeCharged + p.OverTimePenaltyFee + (p.ResourceRate == 0 ? 0 : p.ReservationFee2); //should be the same as GetTotalCharge() } else { result = p.UncancelledPenaltyFee + p.ReservationFee2; //should be the same as GetTotalCharge() } } } return(result); }