diff --git a/onprc_billing/resources/queries/onprc_billing/LeaseFeeIncomeRevenueAlias.sql b/onprc_billing/resources/queries/onprc_billing/LeaseFeeIncomeRevenueAlias.sql
new file mode 100644
index 000000000..90044e465
--- /dev/null
+++ b/onprc_billing/resources/queries/onprc_billing/LeaseFeeIncomeRevenueAlias.sql
@@ -0,0 +1,10 @@
+Select
+i.rowID,
+i.project,
+i.startDate,
+i.enddate,
+i.comment,
+p.account
+from projectLeaseIncomeEligibility i
+ left join projectAccountHistory p on i.project = p.project
+where p.isActive = true
\ No newline at end of file
diff --git a/onprc_billing/resources/queries/onprc_billing/gdj_NewLeaseFeeCTE_original.sql b/onprc_billing/resources/queries/onprc_billing/gdj_NewLeaseFeeCTE_original.sql
new file mode 100644
index 000000000..0f8e639ce
--- /dev/null
+++ b/onprc_billing/resources/queries/onprc_billing/gdj_NewLeaseFeeCTE_original.sql
@@ -0,0 +1,364 @@
+PARAMETERS (StartDate TIMESTAMP, EndDate TIMESTAMP)
+-- ========================================================
+-- This is the QUery using CTES that was AI Generated for revised lease fees
+-- Date: 2025-11-22
+-- Step 1 Assignments has bene modified to use LabkeySQL structure.
+-- THis was moved to the onprc_billing query section
+-- Working thru each CTE for code updates - Works as Designed in Dev
+-- =========================================================
+WITH
+-- =========================================================
+-- 1) Base assignments in date range
+--This was modified to use LabkeySQL structure.
+-- 2025-11-24 Validation of this CTE
+-- =========================================================
+assignments AS (
+ SELECT
+ a.Id,
+ -- create an identifer as assignment ID
+ a.lsid as assignmentId,
+ a.date AS assignmentDate,
+ a.enddate AS assignmentEndDate,
+ a.project,
+ --Create a sub query for resource ID
+ (Select r.project.displayName from study.resourceAssigned r where r.id = a.id) as resourceCode,
+ a.assignCondition,
+ a.releaseCondition,
+ a.projectedRelease,
+ --Create a looklup for is a research project
+ Case when a.id in (Select ra.id from study.researchAssigned ra where ra.id = a.id) then 1
+ Else 0
+ End as isResearchAssignment,
+ -- a.isResearchAssignment, -- 1 = research, 0 = resource (or derive later)
+ (Select b.dam from study.birth b where b.id = a.id) as damId, -- dam of infant, if applicable
+ a.id.dataset.Demographics.gender as sex,
+ -- Using the release code assign a value for is terminal
+ Case when a.projectedReleaseCondition in (206,207) then 1
+ Else 0
+ End as isTerminalAssignment, -- 1 = terminal, 0 = non-terminal
+ a.container
+ FROM study.assignment a
+ WHERE a.date >= StartDate
+ AND a.date < EndDate
+),
+--Select * from assignment,
+
+-- =========================================================
+-- 2) Animal age / infant vs adult
+-- (You may already have an ageAtTime dataset; this is illustrative)
+-- change this to age in years
+-- 2025-11-24 Starting Validation Review
+-- =========================================================
+age_at_assignment AS (
+ SELECT
+ aa.Id,
+ aa.assignmentId,
+ aa.assignmentDate,
+ aa.assignmentEndDate,
+ aa.project,
+ aa.resourceCode,
+ aa.assignCondition,
+ aa.releaseCondition,
+ aa.projectedRelease,
+ aa.damId,
+ aa.sex,
+ aa.isTerminalAssignment,
+ aa.isResearchAssignment,
+ aa.container,
+ d.birth,
+ -- change this to accepted Labkey Code
+ TIMESTAMPDIFF('SQL_TSI_day', d.birth, aa.assignmentDate) AS ageDays,
+ CASE
+ WHEN TIMESTAMPDIFF('SQL_TSI_YEAR', d.birth, aa.assignmentDate) <= 1 THEN 1 -- infant threshold example
+ ELSE 0
+ END AS isInfant
+ FROM assignments aa
+ LEFT JOIN study.demographics d
+ ON d.Id = aa.Id
+)
+--Select * from age_at_assignment
+
+,
+
+-- =========================================================
+-- 3) PI purchase flag (for research assignments)
+-- =========================================================
+pi_purchase AS (
+ SELECT DISTINCT
+ f.Id,
+ f.value,
+ 1 AS hasPIPurchase
+ FROM study.flags f
+ WHERE f.flag.value = 'PI Purchased NHP'
+ --AND f.isActive = true
+),
+
+assign_with_pi AS (
+ SELECT
+ a.*,
+ p.value,
+ COALESCE(p.hasPIPurchase, 0) AS hasPIPurchase
+ FROM age_at_assignment a
+ LEFT JOIN pi_purchase p
+ ON a.Id = p.Id
+)
+--select * from pi_purchase
+ ,
+
+-- =========================================================
+-- 4) Assignment length & condition change
+ --This is returening total days assigned to the project
+-- =========================================================
+assignment_length AS (
+ SELECT
+ a.*,
+ TIMESTAMPDIFF('SQL_TSI_day', a.assignmentDate, COALESCE(a.projectedRelease, a.assignmentenddate)) AS assignmentDays,
+ --DATEDIFF('day', a.assignmentDate, COALESCE(a.proposedReleaseDate, a.assignmentEndDate)) AS assignmentDays,
+ CASE
+ WHEN a.assignCondition = a.releaseCondition
+ OR a.releaseCondition IS NULL
+ THEN 0
+ ELSE 1
+ END AS hasConditionChange
+ FROM assign_with_pi a
+)
+-- select * from assignment_length
+
+ ,
+
+-- =========================================================
+-- 5) Resource type classification
+-- =========================================================
+resource_type AS (
+ SELECT
+ a.*,
+ CASE
+ WHEN a.resourceCode = '0300' THEN 'TMB'
+ WHEN a.resourceCode = '0456' THEN 'AGING'
+ WHEN a.resourceCode = '0833' THEN 'OBESE'
+ WHEN a.resourceCode = '0492-03' THEN 'SPF9'
+ WHEN a.resourceCode = '1092-50' THEN 'AMR'
+ WHEN a.resourceCode = '0492' THEN 'COLONY'
+ WHEN a.resourceCode = '0492-02' THEN 'U42'
+ WHEN a.resourceCode = '0492-45' THEN 'JMR'
+ ELSE 'OTHER'
+ END AS resourceGroup
+ FROM assignment_length a
+)
+ -- select * from resource_type
+
+ ,
+
+-- =========================================================
+-- 6) Dam/resource match (for infant/resource rules)
+-- You may need a proper housing/resource history join here.
+-- =========================================================
+dam_resource AS (
+ SELECT
+ r.Id,
+ r.assignmentId,
+ r.resourceCode AS damResourceCode
+ FROM resource_type r
+ WHERE r.damId IS NOT NULL
+ -- join to housing/resource assignments if needed
+),
+
+with_dam_match AS (
+ SELECT
+ a.*,
+ CASE
+ WHEN a.isInfant = 1
+ AND dr.damResourceCode = a.resourceCode
+ THEN 1
+ ELSE 0
+ END AS infantSameDamResource
+ FROM resource_type a
+ LEFT JOIN dam_resource dr
+ ON dr.Id = a.damId
+ AND dr.assignmentId = a.assignmentId -- or appropriate key
+)
+-- Select * from with_dam_match
+
+,
+-- =========================================================
+-- 7) Determine lease type (core rule engine)
+-- =========================================================
+lease_type AS (
+ SELECT
+ a.*,
+
+ -- Main lease type decision
+ CASE
+ -- ------------------------------
+ -- 1) Resource assignments
+ -- ------------------------------
+ WHEN a.isResearchAssignment = 0 THEN
+ CASE
+ -- 1.1 Infant, dam in same resource → no lease
+ WHEN a.isInfant = 1
+ AND a.infantSameDamResource = 1
+ THEN 'NONE'
+
+ -- 1.2 TMB (0300)
+ WHEN a.resourceGroup = 'TMB' THEN
+ CASE
+ -- TMB dam always charged a TMB lease
+ WHEN a.isInfant = 0
+ AND a.sex = 'F' -- example for dam logic
+ THEN 'TMB_LEASE'
+
+ -- infant from assigned TMB dam → no lease
+ WHEN a.isInfant = 1
+ AND a.infantSameDamResource = 1
+ THEN 'NONE'
+
+ -- infant from unassigned TMB dam → P51 lease, credit TMB
+ WHEN a.isInfant = 1
+ THEN 'P51_FULL'
+
+ -- male assigned from TMB resource → P51 rate
+ WHEN a.sex = 'M'
+ THEN 'P51_FULL'
+
+ -- day lease to TMB
+ ELSE 'DAY_LEASE'
+ END
+
+ -- 1.3 Aging (0456) → no lease for assignments
+ WHEN a.resourceGroup = 'AGING' THEN 'NONE'
+
+ -- 1.4 OBESE (0833)
+ WHEN a.resourceGroup = 'OBESE' THEN
+ CASE
+ WHEN a.assignmentDays BETWEEN 1 AND 14
+ AND a.hasConditionChange = 0
+ THEN 'OBESE_DAY' -- ONR01
+ WHEN a.isTerminalAssignment = 1
+ THEN 'OBESE_ADULT_TERM' -- ONR45
+ ELSE 'OBESE_ADULT' -- ONR25
+ END
+
+ -- 1.5 SPF9 (0492-03)
+ WHEN a.resourceGroup = 'SPF9'
+ THEN 'SPF9_EXPANDED'
+
+ -- 1.6 AMR (1092-50) – no lease when assigned to AMR
+ WHEN a.resourceGroup = 'AMR'
+ THEN 'NONE'
+
+ -- 1.7 Colony / U42 / JMR / Other resource → P51 rules
+ ELSE 'P51_FULL'
+ END
+
+ -- ------------------------------
+ -- 2) Research assignments
+ -- ------------------------------
+ ELSE
+ CASE
+ -- 2.1 PI Purchased → no lease
+ WHEN a.hasPIPurchase = 1
+ THEN 'NONE'
+
+ -- 2.2 One day – 14 days
+ WHEN a.assignmentDays BETWEEN 1 AND 14 THEN
+ CASE
+ WHEN a.hasConditionChange = 0
+ THEN 'DAY_LEASE'
+ ELSE 'FULL_LEASE'
+ END
+
+ -- 2.3 > 14 days → full lease
+ WHEN a.assignmentDays > 14
+ THEN 'FULL_LEASE'
+
+ ELSE 'NONE'
+ END
+ END AS leaseType
+ FROM with_dam_match a
+)
+ --select * from lease_type
+ ,
+-- ++++++++ 2025-11-24 All CTEs above return results as expected
+-- =========================================================
+-- 8) Map leaseType to itemCodes & credit aliases
+-- =========================================================
+lease_mapping AS (
+ SELECT
+ l.*,
+
+ -- Item code mapping (example codes – replace with real ones)
+ CASE l.leaseType
+ WHEN 'DAY_LEASE' THEN 'DAY01' -- generic day lease
+ WHEN 'FULL_LEASE' THEN 'FULL01'
+ WHEN 'P51_FULL' THEN 'P51'
+ WHEN 'OBESE_DAY' THEN 'ONR01'
+ WHEN 'OBESE_ADULT' THEN 'ONR25'
+ WHEN 'OBESE_ADULT_TERM' THEN 'ONR45'
+ WHEN 'SPF9_EXPANDED' THEN 'SPF9X'
+ WHEN 'TMB_LEASE' THEN 'TMB01'
+ ELSE NULL
+ END AS leaseItemCode,
+
+ -- Credit resource mapping
+ CASE
+ WHEN l.leaseType = 'NONE' THEN NULL
+
+ -- Aging never gets credit; credit colony
+ WHEN l.resourceGroup = 'AGING' THEN 'COLONY_ALIAS'
+
+ -- Obese always credits Obese resource
+ WHEN l.resourceGroup = 'OBESE' THEN 'OBESE_ALIAS'
+
+ -- SPF9 credits U42e funding
+ WHEN l.resourceGroup = 'SPF9' THEN 'U42E_ALIAS'
+
+ -- TMB credits TMB resource
+ WHEN l.resourceGroup = 'TMB' THEN 'TMB_ALIAS'
+
+ -- AMR → credit colony or original resource
+ WHEN l.resourceGroup = 'AMR' THEN 'COLONY_ALIAS'
+
+ -- Colony/U42/JMR map to their own aliases
+ WHEN l.resourceGroup = 'COLONY' THEN 'COLONY_ALIAS'
+ WHEN l.resourceGroup = 'U42' THEN 'U42_ALIAS'
+ WHEN l.resourceGroup = 'JMR' THEN 'JMR_ALIAS'
+
+ -- fallback: credit the originating resource
+ ELSE 'ORIGIN_RESOURCE_ALIAS'
+ END AS creditAlias
+ FROM lease_type l
+)
+--Select * from lease_mapping
+,
+-- =========================================================
+-- 9) Final output
+-- =========================================================
+final AS (
+ SELECT
+ f.Id,
+ f.assignmentId,
+ f.assignmentDate,
+ f.assignmentEndDate,
+ f.project,
+ f.resourceCode,
+ f.resourceGroup,
+ f.isResearchAssignment,
+ f.isInfant,
+ f.assignmentDays,
+ f.hasConditionChange,
+ f.hasPIPurchase,
+ f.isTerminalAssignment,
+ f.leaseType,
+ f.leaseItemCode,
+ f.creditAlias,
+ CASE
+ WHEN f.leaseType = 'NONE'
+ THEN 'No lease per business rules'
+ ELSE ('Lease generated per leaseType=' || f.leaseType)
+ END AS leaseNote
+ FROM lease_mapping f
+)
+
+SELECT *
+FROM final
+ORDER BY assignmentDate, Id, assignmentId;
diff --git a/onprc_billing/resources/queries/onprc_billing/leaseFeeRates.sql b/onprc_billing/resources/queries/onprc_billing/leaseFeeRates.sql
deleted file mode 100644
index 9ae0ec136..000000000
--- a/onprc_billing/resources/queries/onprc_billing/leaseFeeRates.sql
+++ /dev/null
@@ -1,366 +0,0 @@
-
-/*
- * Copyright (c) 2013 LabKey Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-SELECT
- t.id,
- t.date,
- t.enddate,
- t.project,
- t.account,
- t.projectedReleaseCondition,
- t.releaseCondition,
- t.assignCondition,
- t.releaseType,
- t.ageAtTime,
- t.category,
- t.chargeId,
- t.serviceCenter,
- t.item,
-
- t.leaseCharge1,
- t.leaseCharge2,
- t.sourceRecord,
- t.chargeCategory,
-
- round(CAST(CASE
- WHEN t.displayName = javaConstant('org.labkey.onprc_ehr.ONPRC_EHRManager.BASE_GRANT_PROJECT') THEN 0
- --handle adjustments and non-adjustments separately
- WHEN (t.isAdjustment IS NULL) THEN t.unitCost1
- --note: we take the amount that should have been paid and subtract what was predicted to have been paid
- ELSE (t.unitCost3 - t.unitCost2)
- END AS DOUBLE), 2) as unitCost,
- CAST(CASE
- --handle adjustments and non-adjustments separately
- WHEN (t.isAdjustment IS NULL) THEN t.nihRate1
- --note: we take the amount that should have been paid and subtract what was predicted to have been paid
- ELSE (t.nihRate3 - t.nihRate2)
- END AS DOUBLE) as nihRate,
-
- t.unitCost1,
- t.nihRate1,
- t.unitCost2,
- t.nihRate2,
- t.unitCost3,
- t.nihRate3,
-
- t.quantity,
- t.creditAccount,
- t.creditAccountId,
- t.comment,
- t.investigatorId,
- t.isExemption,
- t.isNonStandardRate,
- t.lacksRate,
- t.rateId,
- t.exemptionId,
- t.isMiscCharge,
- t.isAdjustment,
- t.isMissingAccount,
- t.isMissingFaid,
- t.isAcceptingCharges,
- t.isExpiredAccount,
- t.isOldCharge,
- t.currentActiveAlias,
- t.datefinalized,
- t.enddatefinalized
-
-
-FROM (
-SELECT
- p.id,
- p.date,
- p.enddate,
- p.project,
- alias.alias as account,
- p.project.displayName as displayName,
- p.projectedReleaseCondition,
- p.releaseCondition,
- p.assignCondition,
- p.releaseType,
- p.ageAtTime,
- p.category,
- p.chargeId,
- p.chargeId.departmentCode as serviceCenter,
- p.chargeId.name as item,
-
- p.leaseCharge1,
- p.leaseCharge2,
- p.sourceRecord,
- p.chargeCategory,
-
- --this is the cost of the original lease, based on projected release type
- CAST(CASE
- --order of priority for unit cost:
- --project-level exemption: pay this value
- WHEN (e.unitCost IS NOT NULL) THEN e.unitCost
- --project-level multiplier: multiply NIH rate by this value
- WHEN (pm.multiplier IS NOT NULL AND cr.unitCost IS NOT NULL) THEN (cr.unitCost * pm.multiplier)
- --if there is not a known rate, we dont know what do to
- WHEN (cr.unitCost IS NULL) THEN null
- --for non-OGA aliases, we always use the NIH rate
- WHEN (alias.category IS NOT NULL AND alias.category != 'OGA') THEN cr.unitCost
- --if we dont know the aliasType, we also dont know what do to
- WHEN (alias.aliasType.aliasType IS NULL) THEN null
- --remove both subsidy and raise F&A if needed
- WHEN (alias.aliasType.removeSubsidy = true AND (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true)) THEN ((cr.unitCost / (1 - COALESCE(cr.subsidy, 0))) * (CASE WHEN (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.indirectRate AS DOUBLE)) THEN ((1 + (CAST(ir.IndirectRate AS DOUBLE) / (1 + alias.faRate)))) ELSE 1 END))
- --remove subsidy only
- WHEN (alias.aliasType.removeSubsidy = true AND alias.aliasType.canRaiseFA = false) THEN (cr.unitCost / (1 - COALESCE(cr.subsidy, 0)))
- --raise F&A on ly
- WHEN (alias.aliasType.removeSubsidy = false AND (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true)) THEN (cr.unitCost * (CASE WHEN (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.indirectRate AS DOUBLE)) THEN ((1 + (CAST(ir.indirectRate AS DOUBLE)))/(1+ alias.faRate)) ELSE 1 END))
- --the NIH rate
- ELSE cr.unitCost
- END AS DOUBLE) as unitCost1,
- cr.unitCost as nihRate1,
-
- --for adjustments, this is the first lease charge
- CAST(CASE
- --order of priority for unit cost:
- --project-level exemption: pay this value
- WHEN (e2.unitCost IS NOT NULL) THEN e2.unitCost
- --project-level multiplier: multiply NIH rate by this value
- WHEN (pm.multiplier IS NOT NULL AND cr2.unitCost IS NOT NULL) THEN (cr2.unitCost * pm.multiplier)
- --if there is not a known rate, we dont know what do to
- WHEN (cr2.unitCost IS NULL) THEN null
- --for non-OGA aliases, we always use the NIH rate
- WHEN (alias.category IS NOT NULL AND alias.category != 'OGA') THEN cr2.unitCost
- --if we dont know the aliasType, we also dont know what do to
- WHEN (alias.aliasType.aliasType IS NULL) THEN null
- --remove both subsidy and raise F&A if needed
- WHEN (alias.aliasType.removeSubsidy = true AND (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true)) THEN ((cr2.unitCost / (1 - COALESCE(cr2.subsidy, 0))) * (CASE WHEN (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.indirectRate AS DOUBLE)) THEN (1 + (CAST(ir.indirectRate AS DOUBLE) / (1 + alias.faRate))) ELSE 1 END))
- --remove subsidy only
- WHEN (alias.aliasType.removeSubsidy = true AND alias.aliasType.canRaiseFA = false) THEN (cr2.unitCost / (1 - COALESCE(cr2.subsidy, 0)))
- --raise F&A only
- WHEN (alias.aliasType.removeSubsidy = false AND (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true)) THEN (cr2.unitCost * (CASE WHEN (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.indirectRate AS DOUBLE)) THEN (1 + (CAST(ir.IndirectRate AS DOUBLE) / (1 + alias.faRate))) ELSE 1 END))
- --the NIH rate
- ELSE cr2.unitCost
- END AS DOUBLE) as unitCost2,
- cr2.unitCost as nihRate2,
-
- --for adjustments, this is the second lease charge
- CAST(CASE
- --order of priority for unit cost:
- --project-level exemption: pay this value
- WHEN (e3.unitCost IS NOT NULL) THEN e3.unitCost
- --project-level multiplier: multiply NIH rate by this value
- WHEN (pm.multiplier IS NOT NULL AND cr3.unitCost IS NOT NULL) THEN (cr3.unitCost * pm.multiplier)
- --if there is not a known rate, we dont know what do to
- WHEN (cr3.unitCost IS NULL) THEN null
- --for non-OGA aliases, we always use the NIH rate
- WHEN (alias.category IS NOT NULL AND alias.category != 'OGA') THEN cr3.unitCost
- --if we dont know the aliasType, we also dont know what do to
- WHEN (alias.aliasType.aliasType IS NULL) THEN null
- --remove both subsidy and raise F&A if needed
- WHEN (alias.aliasType.removeSubsidy = true AND (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true)) THEN ((cr3.unitCost / (1 - COALESCE(cr3.subsidy, 0))) * (CASE WHEN (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.indirectRate AS DOUBLE)) THEN (1 + (CAST(ir.indirectRate AS DOUBLE) / ( 1 + alias.faRate))) ELSE 1 END))
- --remove subsidy only
- WHEN (alias.aliasType.removeSubsidy = true AND alias.aliasType.canRaiseFA = false) THEN (cr3.unitCost / (1 - COALESCE(cr3.subsidy, 0)))
- --raise F&A only
- WHEN (alias.aliasType.removeSubsidy = false AND (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true)) THEN (cr3.unitCost * (CASE WHEN (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.IndirectRate AS DOUBLE)) THEN (1 + (CAST(ir.IndirectRate AS DOUBLE) / (1 + alias.faRate))) ELSE 1 END))
- --the NIH rate
- ELSE cr3.unitCost
- END AS DOUBLE) as unitCost3,
- cr3.unitCost as nihRate3,
-
- p.quantity,
- cast(ce.account as varchar(200)) as creditAccount,
- ce.rowid as creditAccountId,
- null as comment,
- coalesce(alias.investigatorId, p.project.investigatorId) as investigatorId,
- CASE
- WHEN (e.rowid IS NOT NULL OR e2.rowid IS NOT NULL OR e3.rowid IS NOT NULL) THEN 'Y'
- WHEN (pm.multiplier IS NOT NULL) THEN ('Multiplier: ' || CAST(pm.multiplier AS varchar(100)))
- ELSE null
- END as isExemption,
- CASE
- WHEN (e.unitCost IS NOT NULL) THEN null --ignore project-level exemptions
- WHEN (cr.unitCost IS NULL) THEN null --will be flagged for other reasons
- WHEN (pm.multiplier IS NOT NULL) THEN null --also ignore project-level multipliers
- WHEN (alias.aliasType.aliasType IS NULL) THEN null --unknown alias type, will be flagged elsewhere
- WHEN (alias.aliasType.removeSubsidy = true AND COALESCE(cr.subsidy, 0) > 0) THEN 'Removed NIH Subsidy'
- WHEN (alias.aliasType.canRaiseFA = true AND p.chargeId.canRaiseFA = true AND (alias.faRate IS NOT NULL AND alias.faRate < CAST(ir.IndirectRate AS DOUBLE))) THEN ('Reduced F&A: ' || CAST(alias.faRate as varchar(20)))
- ELSE null
- END as isNonStandardRate,
- CASE WHEN (alias.alias IS NOT NULL AND alias.aliasType.aliasType IS NULL) THEN ('Unknown Type: ' || alias.aliasType) ELSE null END as isUnknownAliasType,
- CASE
- --handle adjustments and non-adjustments separately
- WHEN (p.isAdjustment IS NULL AND coalesce(e.unitCost, cr.unitCost) is null) THEN 'Y'
- WHEN (p.isAdjustment IS NOT NULL AND (coalesce(e3.unitCost, cr3.unitCost) IS NULL OR coalesce(e2.unitCost, cr2.unitCost) IS NULL)) THEN 'Y'
- ELSE null
- END as lacksRate,
- CASE
- WHEN (p.category = 'Lease Fees' or p.category = 'Lease Setup Fee' or p.category = 'Lease Setup Fees') AND e.rowid IS NULL THEN cr.rowId
- ELSE null
- END as rateId,
- CASE
- WHEN (p.category = 'Lease Fees' or p.category = 'Lease Setup Fee' or p.category = 'Lease Setup Fees') THEN e.rowid
- ELSE null
- END as exemptionId,
- null as isMiscCharge,
- p.isAdjustment,
- CASE WHEN alias.alias IS NULL THEN 'Y' ELSE null END as isMissingAccount,
- CASE WHEN alias.fiscalAuthority.faid IS NULL THEN 'Y' ELSE null END as isMissingFaid,
- CASE
- WHEN alias.aliasEnabled IS NULL THEN 'N'
- WHEN alias.aliasEnabled != 'Y' THEN 'N'
- ELSE null
- END as isAcceptingCharges,
- CASE
- WHEN (alias.budgetStartDate IS NOT NULL AND CAST(alias.budgetStartDate as date) > CAST(p.date as date)) THEN 'Prior To Budget Start'
- WHEN (alias.budgetEndDate IS NOT NULL AND CAST(alias.budgetEndDate as date) < CAST(p.date as date)) THEN 'After Budget End'
- WHEN (alias.projectStatus IS NOT NULL AND alias.projectStatus != 'ACTIVE' AND alias.projectStatus != 'No Cost Ext' AND alias.projectStatus != 'Partial Setup') THEN 'Grant Project Not Active'
- ELSE null
- END as isExpiredAccount,
-
- CASE WHEN (TIMESTAMPDIFF('SQL_TSI_DAY', p.date, curdate()) > 45) THEN 'Y' ELSE null END as isOldCharge,
- p.project.account as currentActiveAlias,
- p.datefinalized,
- p.enddatefinalized
-
-FROM onprc_billing.leaseFees p
-
---the primary charge. this will be based on transaction date
-LEFT JOIN onprc_billing_public.chargeRates cr ON (
- CAST(p.assignmentStart AS DATE) >= CAST(cr.startDate AS DATE) AND
- (CAST(p.assignmentStart AS DATE) <= cr.enddateCoalesced OR cr.enddate IS NULL) AND
- p.chargeId = cr.chargeId
-)
-
-LEFT JOIN onprc_billing_public.chargeRateExemptions e ON (
- CAST(p.assignmentStart AS DATE) >= CAST(e.startDate AS DATE) AND
- (CAST(p.assignmentStart AS DATE) <= e.enddateCoalesced OR e.enddate IS NULL) AND
- p.chargeId = e.chargeId AND
- p.project = e.project
-)
-
---the original charge (for adjustments)
---NOTE: the adjustment will use the lease end as the transaction date; however, we need to calculate this unit cost
---based on the original date of assignment
-LEFT JOIN onprc_billing_public.chargeRates cr2 ON (
- CAST(p.assignmentStart AS DATE) >= CAST(cr2.startDate AS DATE) AND
- (CAST(p.assignmentStart AS DATE) <= cr2.enddateCoalesced OR cr2.enddate IS NULL) AND
- p.leaseCharge1 = cr2.chargeId
-)
-
-LEFT JOIN onprc_billing_public.chargeRateExemptions e2 ON (
- CAST(p.assignmentStart AS DATE) >= CAST(e2.startDate AS DATE) AND
- (CAST(p.assignmentStart AS DATE) <= e2.enddateCoalesced OR e2.enddate IS NULL) AND
- p.leaseCharge1 = e2.chargeId AND
- p.project = e2.project
-)
---EO original charge
-
---the final charge (for adjustments)
---this is the what we should have charges, based on the true release condition.
---this is also based on the date of assignment, which will differ from transaction date
-LEFT JOIN onprc_billing_public.chargeRates cr3 ON (
- CAST(p.assignmentStart AS DATE) >= CAST(cr3.startDate AS DATE) AND
- (CAST(p.assignmentStart AS DATE) <= cr3.enddateCoalesced OR cr3.enddate IS NULL) AND
- p.leaseCharge2 = cr3.chargeId
-)
-
-LEFT JOIN onprc_billing_public.chargeRateExemptions e3 ON (
- CAST(p.assignmentStart AS DATE) >= CAST(e3.startDate AS DATE) AND
- (CAST(p.assignmentStart AS DATE) <= e3.enddateCoalesced OR e3.enddate IS NULL) AND
- p.leaseCharge2 = e3.chargeId AND
- p.project = e3.project
-)
-
---EO final charge
-
-LEFT JOIN onprc_billing_public.creditAccount ce ON (
- CAST(p.date AS DATE) >= CAST(ce.startDate AS DATE) AND
- (CAST(p.date AS DATE) <= ce.enddateCoalesced OR ce.enddate IS NULL) AND
- p.chargeId = ce.chargeId
-)
-
-LEFT JOIN onprc_billing_public.projectAccountHistory aliasAtTime ON (
- aliasAtTime.project = p.project AND
- aliasAtTime.startDate <= cast(p.date as date) AND
- aliasAtTime.endDate >= cast(p.date as date)
-)
-
-LEFT JOIN onprc_billing_public.aliases alias ON (
- aliasAtTime.account = alias.alias
-)
-
-LEFT JOIN onprc_billing_public.projectMultipliers pm ON (
- CAST(p.date AS DATE) >= CASt(pm.startDate AS DATE) AND
- (CAST(p.date AS DATE) <= pm.enddateCoalesced OR pm.enddate IS NULL) AND
- alias.alias = pm.account
-)
-LEFT JOIN onprc_billing.ogaSynchIR ir
- on ir.alias = alias.alias
-
-) t
-where t.id.demographics.species Not IN ('Rabbit','Guinea Pig')
-UNION ALL
-
---add misc charges
-SELECT
- mc.id,
- mc.date,
- null as enddate,
- mc.project,
- mc.account,
- null as projectedReleaseCondition,
- null as releaseCondition,
- null as assignCondition,
- null as releaseType,
- null as ageAtTime,
- mc.category,
- mc.chargeId,
- mc.serviceCenter,
- mc.item,
-
- null as leaseCharge1,
- null as leaseCharge2,
- mc.sourceRecord,
- mc.chargeCategory,
-
- mc.unitcost,
- mc.nihRate,
-
- null as unitCost1,
- null as nihRate1,
- null as unitCost2,
- null as nihRate2,
- null as unitCost3,
- null as nihRate3,
-
- mc.quantity,
-
- mc.creditAccount,
- mc.creditAccountId,
- mc.comment,
- mc.investigatorId,
- mc.isExemption,
- mc.isNonStandardRate,
- mc.lacksRate,
- mc.rateId,
- mc.exemptionId,
- 'Y' as isMiscCharge,
- mc.isAdjustment,
- mc.isMissingAccount,
- mc.isMissingFaid,
- mc.isAcceptingCharges,
- mc.isExpiredAccount,
- mc.isOldCharge,
- mc.currentActiveAlias,
- null as datefinalized,
- null as enddatefinalized
-
-FROM onprc_billing.miscChargesFeeRateData mc
-WHERE cast(mc.billingDate as date) >= CAST(StartDate as date) AND cast(mc.billingDate as date) <= CAST(EndDate as date)
-AND mc.category IN ('Lease Fees', 'Lease Setup Fee', 'Lease Setup Fees')
diff --git a/onprc_billing/resources/queries/onprc_billing/leasefeerates.sql b/onprc_billing/resources/queries/onprc_billing/leasefeerates.sql
new file mode 100644
index 000000000..2c2c1bb74
--- /dev/null
+++ b/onprc_billing/resources/queries/onprc_billing/leasefeerates.sql
@@ -0,0 +1,321 @@
+PARAMETERS (StartDate TIMESTAMP, EndDate TIMESTAMP)
+
+WITH
+-- =====================================================================================
+-- 1) Base Lease Fees
+-- =====================================================================================
+base_lease AS (
+ SELECT
+ p.id,
+ p.date,
+ p.enddate,
+ p.assignmentStart,
+ p.project,
+ p.project.displayName AS projectDisplayName,
+ p.projectedReleaseCondition,
+ p.releaseCondition,
+ p.assignCondition,
+ p.releaseType,
+ p.ageAtTime,
+ p.category,
+ p.chargeId,
+ p.leaseCharge1,
+ p.leaseCharge2,
+ p.sourceRecord,
+ p.chargeCategory,
+ p.quantity,
+ p.isAdjustment,
+ p.datefinalized,
+ p.enddatefinalized
+ FROM onprc_billing.leaseFees p
+ WHERE CAST(p.date AS DATE)
+ BETWEEN CAST(StartDate AS DATE) AND CAST(EndDate AS DATE)
+ AND p.category = 'Lease Fees'
+),
+
+-- =====================================================================================
+-- 2) Alias / Account Context
+
+-- =====================================================================================
+alias_context AS (
+ SELECT
+ bl.*,
+ da.DualProjectCategory,
+ da.project1 as InitialProject,
+ a.alias AS account,
+ a.category AS aliasCategory,
+ a.faRate AS faRate,
+ a.aliasType.aliasType AS aliasType,
+ a.aliasType.removeSubsidy AS removeSubsidy,
+ a.aliasType.canRaiseFA AS canRaiseFA,
+ a.fiscalAuthority.faid AS faid,
+ a.aliasEnabled AS aliasEnabled,
+ a.budgetStartDate AS budgetStartDate,
+ a.budgetEndDate AS budgetEndDate,
+ a.projectStatus AS projectStatus,
+ COALESCE(a.investigatorId,
+ bl.project.investigatorId) AS investigatorId
+ FROM base_lease bl
+
+ LEFT JOIN onprc_billing_public.projectAccountHistory pah
+ ON pah.project = bl.project
+ AND pah.startDate <= CAST(bl.date AS DATE)
+ AND pah.endDate >= CAST(bl.date AS DATE)
+ LEFT JOIN onprc_billing_public.aliases a
+ ON pah.account = a.alias
+ Left JOIN study.dualAssigned da
+ on bl.id = da.id
+ AND da.dualendDate >= CAST(bl.date AS DATE)
+ AND da.dualstartDate <= CAST(bl.date AS DATE)
+
+
+--Select * from alias_context
+),
+-- =====================================================================================
+-- 2a lookup to determine credit to for each lease fee
+-- when an assignment creates a dual assignment and the original assignment is an
+
+-- 3) Rates / Exemptions / Multipliers / Indirect Rate
+-- =====================================================================================
+
+rate_context AS (
+ SELECT
+ ac.*,
+ LI.project as CreditTo,
+
+ cr.unitCost AS nihRate1,
+ cr.subsidy AS subsidy1,
+ e.unitCost AS exemptRate1,
+ e.rowid AS exemptionId1,
+
+ cr2.unitCost AS nihRate2,
+ cr2.subsidy AS subsidy2,
+ e2.unitCost AS exemptRate2,
+ e2.rowid AS exemptionId2,
+
+ cr3.unitCost AS nihRate3,
+ cr3.subsidy AS subsidy3,
+ e3.unitCost AS exemptRate3,
+ e3.rowid AS exemptionId3,
+
+ pm.multiplier AS multiplier,
+ ir.indirectRate AS indirectRate
+ FROM alias_context ac
+
+ LEFT JOIN onprc_billing_public.chargeRates cr
+ ON ac.assignmentStart >= cr.startDate
+ AND (ac.assignmentStart <= cr.enddateCoalesced OR cr.enddate IS NULL)
+ AND ac.chargeId = cr.chargeId
+
+ LEFT JOIN onprc_billing_public.chargeRateExemptions e
+ ON ac.assignmentStart >= e.startDate
+ AND (ac.assignmentStart <= e.enddateCoalesced OR e.enddate IS NULL)
+ AND ac.chargeId = e.chargeId
+ AND ac.project = e.project
+
+ LEFT JOIN onprc_billing_public.chargeRates cr2
+ ON ac.assignmentStart >= cr2.startDate
+ AND (ac.assignmentStart <= cr2.enddateCoalesced OR cr2.enddate IS NULL)
+ AND ac.leaseCharge1 = cr2.chargeId
+
+ LEFT JOIN onprc_billing_public.chargeRateExemptions e2
+ ON ac.assignmentStart >= e2.startDate
+ AND (ac.assignmentStart <= e2.enddateCoalesced OR e2.enddate IS NULL)
+ AND ac.leaseCharge1 = e2.chargeId
+ AND ac.project = e2.project
+
+ LEFT JOIN onprc_billing_public.chargeRates cr3
+ ON ac.assignmentStart >= cr3.startDate
+ AND (ac.assignmentStart <= cr3.enddateCoalesced OR cr3.enddate IS NULL)
+ AND ac.leaseCharge2 = cr3.chargeId
+
+ LEFT JOIN onprc_billing_public.chargeRateExemptions e3
+ ON ac.assignmentStart >= e3.startDate
+ AND (ac.assignmentStart <= e3.enddateCoalesced OR e3.enddate IS NULL)
+ AND ac.leaseCharge2 = e3.chargeId
+ AND ac.project = e3.project
+
+ LEFT JOIN onprc_billing_public.projectMultipliers pm
+ ON ac.date >= pm.startDate
+ AND (ac.date <= pm.enddateCoalesced OR pm.enddate IS NULL)
+ AND ac.account = pm.account
+
+ LEFT JOIN onprc_billing.ogaSynchIR ir
+ ON ir.alias = ac.account
+ Left Join onprc_Billing.ProjectLeaseIncomeEligibility Li
+ on ac.InitialProject = Li.Project
+),
+
+
+ -- =====================================================================================
+-- 4) Unit Cost Calculation (Parser-Safe)
+-- =====================================================================================
+calculated_costs AS (
+ SELECT
+ rc.*,
+
+ CAST(
+ CASE
+ WHEN exemptRate1 IS NOT NULL THEN exemptRate1
+
+ WHEN multiplier IS NOT NULL AND nihRate1 IS NOT NULL
+ THEN (CAST(nihRate1 AS DOUBLE) * CAST(multiplier AS DOUBLE))
+
+ WHEN nihRate1 IS NULL THEN NULL
+
+ WHEN aliasCategory IS NOT NULL AND aliasCategory <> 'OGA'
+ THEN nihRate1
+
+ WHEN aliasType IS NULL THEN NULL
+
+ WHEN removeSubsidy = TRUE
+ AND canRaiseFA = TRUE
+ AND chargeId.canRaiseFA = TRUE
+ THEN (
+ (CAST(nihRate1 AS DOUBLE) / NULLIF((1 - COALESCE(subsidy1, 0)), 0))
+ *
+ (
+ 1 +
+ CASE
+ WHEN faRate IS NOT NULL
+ AND indirectRate IS NOT NULL
+ AND faRate < CAST(indirectRate AS DOUBLE)
+ THEN (CAST(indirectRate AS DOUBLE) / (1 + faRate))
+ ELSE 0
+ END
+ )
+ )
+
+ WHEN removeSubsidy = TRUE AND canRaiseFA = FALSE
+ THEN (CAST(nihRate1 AS DOUBLE) / NULLIF((1 - COALESCE(subsidy1, 0)), 0))
+
+ WHEN removeSubsidy = FALSE
+ AND canRaiseFA = TRUE
+ AND chargeId.canRaiseFA = TRUE
+ THEN (
+ CAST(nihRate1 AS DOUBLE)
+ *
+ (
+ 1 +
+ CASE
+ WHEN faRate IS NOT NULL
+ AND indirectRate IS NOT NULL
+ AND faRate < CAST(indirectRate AS DOUBLE)
+ THEN ((CAST(indirectRate AS DOUBLE) - faRate) / (1 + faRate))
+ ELSE 0
+ END
+ )
+ )
+
+ ELSE nihRate1
+ END
+ AS DOUBLE) AS unitCost
+ FROM rate_context rc
+),
+--Select * from calculated_costs
+-- =====================================================================================
+-- 5) Final Lease Charges (Billing Review)
+-- =====================================================================================
+
+
+lease_final AS (
+ SELECT
+ id,
+ date AS assignmentStartDate,
+ enddate AS assignmentEndDate,
+ datefinalized AS dateFinalized,
+ project,
+ account,
+ projectedReleaseCondition,
+ releaseCondition,
+ assignCondition,
+ releaseType,
+ ageAtTime,
+ category,
+ chargeId,
+ chargeId.departmentCode AS serviceCenter,
+ chargeId.name AS item,
+ leaseCharge1.name as InitialLEaseType,
+ leaseCharge2.name as FinalLEaseType,
+ sourceRecord,
+ chargeCategory,
+-- Add the action to get the correct alias for the credit account
+-- This is based on whether there is a value in Credit to field
+ CAST(creditto as varchar) AS creditAccount,
+ CAST(NULL AS INTEGER) AS creditAccountId,
+
+ unitCost,
+ quantity,
+
+ CASE
+ WHEN isAdjustment IS NOT NULL
+ THEN ROUND(CAST(unitCost AS DOUBLE), 2)
+ ELSE
+ ROUND(
+ CAST(unitCost AS DOUBLE)
+ * COALESCE(CAST(quantity AS DOUBLE), 1),
+ 2
+ )
+ END AS totalCost,
+
+ investigatorId,
+
+ NULL AS isMiscCharge,
+ isAdjustment
+ FROM calculated_costs
+ WHERE id.demographics.species NOT IN ('Rabbit','Guinea Pig')
+),
+
+-- ... existing code ...
+
+misc_charges AS (
+ SELECT
+ mc.id,
+ mc.billingDate AS assignmentStartDate,
+ NULL AS assignmentEndDate,
+ NULL AS dateFinalized,
+ mc.project,
+ mc.account,
+ NULL AS projectedReleaseCondition,
+ NULL AS releaseCondition,
+ NULL AS assignCondition,
+ NULL AS releaseType,
+ NULL AS ageAtTime,
+ mc.category,
+ mc.chargeId,
+ mc.serviceCenter,
+ mc.item,
+ NULL AS leaseCharge1,
+ NULL AS leaseCharge2,
+ mc.sourceRecord,
+ mc.chargeCategory,
+
+ mc.creditAccount AS creditAccount,
+ mc.creditAccountId AS creditAccountId,
+
+ mc.unitCost,
+ mc.quantity,
+
+ ROUND(
+ CAST(mc.unitCost AS DOUBLE)
+ * COALESCE(CAST(mc.quantity AS DOUBLE), 1),
+ 2
+ ) AS totalCost,
+
+ mc.investigatorId,
+
+ 'Y' AS isMiscCharge,
+ mc.isAdjustment
+ FROM onprc_billing.miscChargesFeeRateData mc
+ WHERE CAST(mc.billingDate AS DATE)
+ BETWEEN CAST(StartDate AS DATE) AND CAST(EndDate AS DATE)
+ AND mc.category = 'Lease Fees'
+)
+
+-- ... existing code ...
+-- =====================================================================================
+-- FINAL BILLING-REVIEW OUTPUT
+-- =====================================================================================
+SELECT * FROM lease_final
+UNION ALL
+SELECT * FROM misc_charges;
diff --git a/onprc_billing/resources/schemas/dbscripts/sqlserver/onprc_billing-25.006-25.007.sql b/onprc_billing/resources/schemas/dbscripts/sqlserver/onprc_billing-25.006-25.007.sql
new file mode 100644
index 000000000..33347b754
--- /dev/null
+++ b/onprc_billing/resources/schemas/dbscripts/sqlserver/onprc_billing-25.006-25.007.sql
@@ -0,0 +1,8 @@
+CREATE TABLE onprc_billing.ProjectLeaseIncomeEligibility (
+ rowId INT IDENTITY(1,1) NOT NULL,
+ project INT NOT NULL,
+ startDate DATE NOT NULL,
+ endDate DATE NULL,
+ comment NVARCHAR(4000) NULL,
+ CONSTRAINT PK_ProjectLeaseIncomeEligibility PRIMARY KEY (rowId)
+);
\ No newline at end of file
diff --git a/onprc_billing/resources/schemas/onprc_billing.xml b/onprc_billing/resources/schemas/onprc_billing.xml
index 2bb09f73b..95d3e9b09 100644
--- a/onprc_billing/resources/schemas/onprc_billing.xml
+++ b/onprc_billing/resources/schemas/onprc_billing.xml
@@ -1641,4 +1641,7 @@
+
+
+
\ No newline at end of file
diff --git a/onprc_billing/resources/schemas/pf_publicFinance.template.xml b/onprc_billing/resources/schemas/pf_publicFinance.template.xml
index e3c842a20..4a3b73524 100644
--- a/onprc_billing/resources/schemas/pf_publicFinance.template.xml
+++ b/onprc_billing/resources/schemas/pf_publicFinance.template.xml
@@ -4,6 +4,7 @@
aliases
dataAccess
projectAccountHistory
+ ProjectLeaseIncomeEligibility
@@ -20,6 +21,10 @@
Project Account History
+
+
+ Project Lease Income Eligibility
+
\ No newline at end of file
diff --git a/onprc_billing/resources/views/financeManagement.html b/onprc_billing/resources/views/financeManagement.html
index c7d05adbc..db1989351 100644
--- a/onprc_billing/resources/views/financeManagement.html
+++ b/onprc_billing/resources/views/financeManagement.html
@@ -81,7 +81,7 @@
{name: 'SLA Per Diem Fee Structure', url: LABKEY.ActionURL.buildURL(queryController, queryAction, null, {schemaName: 'onprc_billing', 'query.queryName': 'slaPerDiemFeeDefinition'})},
{name: 'ONPRC Annual Rate Change', url: LABKEY.ActionURL.buildURL(queryController, queryAction, null, {schemaName: 'onprc_billing', 'query.queryName': 'AnnualRateChange',showImport: true})},
{name: 'ONPRC Indirect Rate', url: LABKEY.ActionURL.buildURL(queryController, queryAction, null, {schemaName: 'onprc_billing', 'query.queryName': 'IndirectRates',showImport: true})}, /*Added to provide access to indirect Rate*/
-
+ {name: 'Project receive Credit for Lease', url: LABKEY.ActionURL.buildURL(queryController, queryAction, null, {schemaName: 'onprc_billing', 'query.queryName': 'LeaseFeeIncomeRevenueAlias',showImport: true})}, /*update to Define who receives lease fee credit*/
]
}]
}]
diff --git a/onprc_billing/src/org/labkey/onprc_billing/ONPRC_BillingModule.java b/onprc_billing/src/org/labkey/onprc_billing/ONPRC_BillingModule.java
index d46499053..ca944815f 100644
--- a/onprc_billing/src/org/labkey/onprc_billing/ONPRC_BillingModule.java
+++ b/onprc_billing/src/org/labkey/onprc_billing/ONPRC_BillingModule.java
@@ -83,7 +83,7 @@ public String getName()
@Override
public @Nullable Double getSchemaVersion()
{
- return 25.006;
+ return 25.007;
}
@Override