Introduce footer totals for department allocations:
- Add `buildDepartmentAllocationFooterTotals` utility to compute department footer totals, excluding customer prices from the total column. - Update department allocation summaries to prioritize actual distributions for fixed and subscription amounts. - Adjust distribution metrics calculation logic and related tests for consistency. - Enhance footer visuals with clearly marked totals and accompanying notes. - Expand `buildDepartmentAllocations` to properly account for totals in UI rendering. - Update associated unit tests to cover footer totals and exclude customer price impacts.
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
getMonthRange,
|
||||
buildMonthSummary,
|
||||
buildDepartmentAllocations,
|
||||
buildDepartmentAllocationFooterTotals,
|
||||
buildCustomerAllocationRows,
|
||||
buildMonthComparison,
|
||||
buildSourceComposition,
|
||||
@@ -62,9 +63,56 @@ describe('invoice distribution calculations', () => {
|
||||
expect(summary.fixedPricingAmount).toBe(40);
|
||||
expect(summary.subscriptionAmount).toBe(20);
|
||||
expect(summary.customerPriceAmount).toBe(15);
|
||||
expect(summary.distributionAmount).toBe(75);
|
||||
expect(summary.distributionAmount).toBe(60);
|
||||
expect(summary.otherBookedAmount).toBe(25);
|
||||
expect(summary.totalAmount).toBe(175);
|
||||
expect(summary.totalAmount).toBe(160);
|
||||
});
|
||||
|
||||
it('prefers actually distributed fixed and subscription amounts for summary totals', () => {
|
||||
const summary = buildMonthSummary({
|
||||
year: 2026,
|
||||
month: 2,
|
||||
periodData: {
|
||||
types: {
|
||||
all: [
|
||||
{
|
||||
transactions: [
|
||||
{ amount: 200, booked: true, excluded: false },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
fixedDistribution: {
|
||||
collective_results: {
|
||||
total_fixed_price: 50,
|
||||
total_department_totals_relative_parsed: {
|
||||
Alpha: 30,
|
||||
Beta: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
subscriptionDistribution: {
|
||||
collective_results: {
|
||||
total_subscription_price: 120,
|
||||
subscription_price_department_distribution_parsed: {
|
||||
Alpha: 70,
|
||||
Beta: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
customerPriceDistribution: {
|
||||
collective_results: {
|
||||
total_customer_price: 15,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(summary.fixedPricingAmount).toBe(40);
|
||||
expect(summary.subscriptionAmount).toBe(90);
|
||||
expect(summary.customerPriceAmount).toBe(15);
|
||||
expect(summary.distributionAmount).toBe(130);
|
||||
expect(summary.totalAmount).toBe(330);
|
||||
});
|
||||
|
||||
it('builds department allocations with percentages and booked estimate', () => {
|
||||
@@ -105,8 +153,33 @@ describe('invoice distribution calculations', () => {
|
||||
expect(rows).toHaveLength(2);
|
||||
expect(rows[0].departmentName).toBe('Alpha');
|
||||
expect(rows[0].totalAmount).toBe(90);
|
||||
expect(rows[0].sharePercent).toBe(64.29);
|
||||
expect(rows[0].estimatedBookedAllocation).toBe(192.86);
|
||||
expect(rows[0].sharePercent).toBe(69.23);
|
||||
expect(rows[0].estimatedBookedAllocation).toBe(207.69);
|
||||
expect(rows[1].departmentName).toBe('Beta');
|
||||
expect(rows[1].customerPriceAmount).toBe(10);
|
||||
expect(rows[1].totalAmount).toBe(40);
|
||||
});
|
||||
|
||||
it('builds department footer totals without adding customer prices to the total column', () => {
|
||||
const totals = buildDepartmentAllocationFooterTotals([
|
||||
{
|
||||
fixedAmount: 120000,
|
||||
subscriptionAmount: 80000,
|
||||
customerPriceAmount: 15000,
|
||||
totalAmount: 215000,
|
||||
},
|
||||
{
|
||||
fixedAmount: 40000,
|
||||
subscriptionAmount: 57000,
|
||||
customerPriceAmount: 12000,
|
||||
totalAmount: 109000,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(totals.fixedAmount).toBe(160000);
|
||||
expect(totals.subscriptionAmount).toBe(137000);
|
||||
expect(totals.customerPriceAmount).toBe(27000);
|
||||
expect(totals.totalAmount).toBe(297000);
|
||||
});
|
||||
|
||||
it('builds customer rows and respects creation date filter', () => {
|
||||
@@ -196,6 +269,7 @@ describe('invoice distribution calculations', () => {
|
||||
expect(normalized).toEqual({
|
||||
compareMonth: '2026-02',
|
||||
compareMode: 'line_by_line',
|
||||
compareVisibility: 'all',
|
||||
customerSearch: 'acme',
|
||||
customerSource: 'customer_prices',
|
||||
customerDepartment: 'Ops',
|
||||
@@ -241,7 +315,7 @@ describe('invoice distribution calculations', () => {
|
||||
fixedPricingAmount: 60,
|
||||
subscriptionAmount: 40,
|
||||
customerPriceAmount: 20,
|
||||
distributionAmount: 120,
|
||||
distributionAmount: 100,
|
||||
});
|
||||
expect(composition.fixedPercent).toBe(50);
|
||||
expect(composition.subscriptionPercent).toBe(33.33);
|
||||
|
||||
Reference in New Issue
Block a user