mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 23:00:34 +00:00
feat(server): wip sales tax liability summary report
This commit is contained in:
@@ -20,6 +20,7 @@ import InventoryDetailsController from './FinancialStatements/InventoryDetails';
|
|||||||
import TransactionsByReferenceController from './FinancialStatements/TransactionsByReference';
|
import TransactionsByReferenceController from './FinancialStatements/TransactionsByReference';
|
||||||
import CashflowAccountTransactions from './FinancialStatements/CashflowAccountTransactions';
|
import CashflowAccountTransactions from './FinancialStatements/CashflowAccountTransactions';
|
||||||
import ProjectProfitabilityController from './FinancialStatements/ProjectProfitabilitySummary';
|
import ProjectProfitabilityController from './FinancialStatements/ProjectProfitabilitySummary';
|
||||||
|
import SalesTaxLiabilitySummary from './FinancialStatements/SalesTaxLiabilitySummary';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class FinancialStatementsService {
|
export default class FinancialStatementsService {
|
||||||
@@ -68,40 +69,44 @@ export default class FinancialStatementsService {
|
|||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/customer-balance-summary',
|
'/customer-balance-summary',
|
||||||
Container.get(CustomerBalanceSummaryController).router(),
|
Container.get(CustomerBalanceSummaryController).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/vendor-balance-summary',
|
'/vendor-balance-summary',
|
||||||
Container.get(VendorBalanceSummaryController).router(),
|
Container.get(VendorBalanceSummaryController).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/transactions-by-customers',
|
'/transactions-by-customers',
|
||||||
Container.get(TransactionsByCustomers).router(),
|
Container.get(TransactionsByCustomers).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/transactions-by-vendors',
|
'/transactions-by-vendors',
|
||||||
Container.get(TransactionsByVendors).router(),
|
Container.get(TransactionsByVendors).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/cash-flow',
|
'/cash-flow',
|
||||||
Container.get(CashFlowStatementController).router(),
|
Container.get(CashFlowStatementController).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/inventory-item-details',
|
'/inventory-item-details',
|
||||||
Container.get(InventoryDetailsController).router(),
|
Container.get(InventoryDetailsController).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/transactions-by-reference',
|
'/transactions-by-reference',
|
||||||
Container.get(TransactionsByReferenceController).router(),
|
Container.get(TransactionsByReferenceController).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/cashflow-account-transactions',
|
'/cashflow-account-transactions',
|
||||||
Container.get(CashflowAccountTransactions).router(),
|
Container.get(CashflowAccountTransactions).router()
|
||||||
);
|
);
|
||||||
router.use(
|
router.use(
|
||||||
'/project-profitability-summary',
|
'/project-profitability-summary',
|
||||||
Container.get(ProjectProfitabilityController).router(),
|
Container.get(ProjectProfitabilityController).router()
|
||||||
)
|
);
|
||||||
|
router.use(
|
||||||
|
'/sales-tax-liability-summary',
|
||||||
|
Container.get(SalesTaxLiabilitySummary).router()
|
||||||
|
);
|
||||||
return router;
|
return router;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
|
import { query } from 'express-validator';
|
||||||
|
import { Inject } from 'typedi';
|
||||||
|
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
||||||
|
import BaseFinancialReportController from '../BaseFinancialReportController';
|
||||||
|
import { AbilitySubject, ReportsAction } from '@/interfaces';
|
||||||
|
import CheckPolicies from '@/api/middleware/CheckPolicies';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import { SalesTaxLiabilitySummaryService } from '@/services/FinancialStatements/SalesTaxLiabilitySummary/SalesTaxLiabilitySummaryService';
|
||||||
|
|
||||||
|
export default class SalesTaxLiabilitySummary extends BaseFinancialReportController {
|
||||||
|
@Inject()
|
||||||
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private salesTaxLiabilitySummaryService: SalesTaxLiabilitySummaryService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Router constructor.
|
||||||
|
*/
|
||||||
|
router() {
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/',
|
||||||
|
CheckPolicies(
|
||||||
|
ReportsAction.READ_SALES_TAX_LIABILITY_SUMMARY,
|
||||||
|
AbilitySubject.Report
|
||||||
|
),
|
||||||
|
this.validationSchema,
|
||||||
|
asyncMiddleware(this.salesTaxLiabilitySummary.bind(this))
|
||||||
|
);
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation schema.
|
||||||
|
*/
|
||||||
|
get validationSchema() {
|
||||||
|
return [
|
||||||
|
query('from_date').optional().isISO8601(),
|
||||||
|
query('to_date').optional().isISO8601(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* @param {Request} req -
|
||||||
|
* @param {Response} res -
|
||||||
|
* @param {NextFunction} next -
|
||||||
|
*/
|
||||||
|
async salesTaxLiabilitySummary(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
) {
|
||||||
|
const { tenantId, settings } = req;
|
||||||
|
const filter = this.matchedQueryData(req);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accept = this.accepts(req);
|
||||||
|
const acceptType = accept.types(['json', 'application/json+table']);
|
||||||
|
|
||||||
|
switch (acceptType) {
|
||||||
|
case 'application/json+table':
|
||||||
|
const salesTaxLiabilityTable =
|
||||||
|
await this.salesTaxLiabilitySummaryService.salesTaxLiabilitySummaryTable(
|
||||||
|
tenantId,
|
||||||
|
filter
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
data: salesTaxLiabilityTable
|
||||||
|
});
|
||||||
|
case 'json':
|
||||||
|
default:
|
||||||
|
const salesTaxLiability =
|
||||||
|
await this.salesTaxLiabilitySummaryService.salesTaxLiability(
|
||||||
|
tenantId,
|
||||||
|
filter
|
||||||
|
);
|
||||||
|
return res.status(200).send({
|
||||||
|
data: salesTaxLiability,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ exports.up = (knex) => {
|
|||||||
table.timestamps();
|
table.timestamps();
|
||||||
})
|
})
|
||||||
.table('items_entries', (table) => {
|
.table('items_entries', (table) => {
|
||||||
table.boolean('is_tax_exclusive');
|
table.boolean('is_inclusive_tax').defaultTo(false);
|
||||||
table
|
table
|
||||||
.integer('tax_rate_id')
|
.integer('tax_rate_id')
|
||||||
.unsigned()
|
.unsigned()
|
||||||
@@ -21,7 +21,7 @@ exports.up = (knex) => {
|
|||||||
table.decimal('tax_rate');
|
table.decimal('tax_rate');
|
||||||
})
|
})
|
||||||
.table('sales_invoices', (table) => {
|
.table('sales_invoices', (table) => {
|
||||||
table.boolean('is_tax_exclusive');
|
table.boolean('is_inclusive_tax').defaultTo(false);
|
||||||
table.decimal('tax_amount_withheld');
|
table.decimal('tax_amount_withheld');
|
||||||
})
|
})
|
||||||
.createTable('tax_rate_transactions', (table) => {
|
.createTable('tax_rate_transactions', (table) => {
|
||||||
@@ -35,6 +35,13 @@ exports.up = (knex) => {
|
|||||||
table.integer('reference_id');
|
table.integer('reference_id');
|
||||||
table.decimal('tax_amount');
|
table.decimal('tax_amount');
|
||||||
table.integer('tax_account_id').unsigned();
|
table.integer('tax_account_id').unsigned();
|
||||||
|
})
|
||||||
|
.table('accounts_transactions', (table) => {
|
||||||
|
table
|
||||||
|
.integer('tax_rate_id')
|
||||||
|
.unsigned()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tax_rates');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export enum ReportsAction {
|
|||||||
READ_INVENTORY_ITEM_DETAILS = 'read-inventory-item-details',
|
READ_INVENTORY_ITEM_DETAILS = 'read-inventory-item-details',
|
||||||
READ_CASHFLOW_ACCOUNT_TRANSACTION = 'read-cashflow-account-transactions',
|
READ_CASHFLOW_ACCOUNT_TRANSACTION = 'read-cashflow-account-transactions',
|
||||||
READ_PROJECT_PROFITABILITY_SUMMARY = 'read-project-profitability-summary',
|
READ_PROJECT_PROFITABILITY_SUMMARY = 'read-project-profitability-summary',
|
||||||
|
READ_SALES_TAX_LIABILITY_SUMMARY = 'read-sales-tax-liability-summary',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFinancialSheetBranchesQuery {
|
export interface IFinancialSheetBranchesQuery {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export interface ILedgerEntry {
|
|||||||
itemId?: number;
|
itemId?: number;
|
||||||
branchId?: number;
|
branchId?: number;
|
||||||
projectId?: number;
|
projectId?: number;
|
||||||
|
taxRateId?: number;
|
||||||
|
|
||||||
entryId?: number;
|
entryId?: number;
|
||||||
createdAt?: Date;
|
createdAt?: Date;
|
||||||
|
|||||||
33
packages/server/src/interfaces/SalesTaxLiabilitySummary.ts
Normal file
33
packages/server/src/interfaces/SalesTaxLiabilitySummary.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export interface SalesTaxLiabilitySummaryQuery {
|
||||||
|
fromDate: Date;
|
||||||
|
toDate: Date;
|
||||||
|
basis: 'cash' | 'accrual';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SalesTaxLiabilitySummaryAmount {
|
||||||
|
amount: number;
|
||||||
|
formattedAmount: string;
|
||||||
|
currencyCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SalesTaxLiabilitySummaryTotal {
|
||||||
|
taxableAmount: SalesTaxLiabilitySummaryAmount;
|
||||||
|
taxAmount: SalesTaxLiabilitySummaryAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SalesTaxLiabilitySummaryRate {
|
||||||
|
taxName: string;
|
||||||
|
taxCode: string;
|
||||||
|
taxableAmount: SalesTaxLiabilitySummaryAmount;
|
||||||
|
taxAmount: SalesTaxLiabilitySummaryAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SalesTaxLiabilitySummaryTableRowType {
|
||||||
|
TaxRate = 'TaxRate',
|
||||||
|
Total = 'Total',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SalesTaxLiabilitySummaryReportData {
|
||||||
|
taxRates: SalesTaxLiabilitySummaryRate[];
|
||||||
|
total: SalesTaxLiabilitySummaryTotal;
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
|
|
||||||
export interface ITaxRate {}
|
export interface ITaxRate {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
rate: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ICommonTaxRateDTO {
|
export interface ICommonTaxRateDTO {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { ITaxRate } from '@/interfaces';
|
||||||
|
import {
|
||||||
|
SalesTaxLiabilitySummaryQuery,
|
||||||
|
SalesTaxLiabilitySummaryRate,
|
||||||
|
SalesTaxLiabilitySummaryReportData,
|
||||||
|
SalesTaxLiabilitySummaryTotal,
|
||||||
|
} from '@/interfaces/SalesTaxLiabilitySummary';
|
||||||
|
import { sumBy } from 'lodash';
|
||||||
|
import FinancialSheet from '../FinancialSheet';
|
||||||
|
|
||||||
|
export class SalesTaxLiabilitySummary extends FinancialSheet {
|
||||||
|
query: SalesTaxLiabilitySummaryQuery;
|
||||||
|
taxRates: ITaxRate[];
|
||||||
|
payableTaxesById: any;
|
||||||
|
salesTaxesById: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary constructor.
|
||||||
|
* @param {SalesTaxLiabilitySummaryQuery} query
|
||||||
|
* @param {ITaxRate[]} taxRates
|
||||||
|
* @param payableTaxesById
|
||||||
|
* @param salesTaxesById
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
query: SalesTaxLiabilitySummaryQuery,
|
||||||
|
taxRates: ITaxRate[],
|
||||||
|
payableTaxesById: Record<
|
||||||
|
string,
|
||||||
|
{ taxRateId: number; credit: number; debit: number }
|
||||||
|
>,
|
||||||
|
salesTaxesById: Record<
|
||||||
|
string,
|
||||||
|
{ taxRateId: number; credit: number; debit: number }
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.query = query;
|
||||||
|
this.taxRates = taxRates;
|
||||||
|
this.payableTaxesById = payableTaxesById;
|
||||||
|
this.salesTaxesById = salesTaxesById;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tax rate liability node.
|
||||||
|
* @param {ITaxRate} taxRate
|
||||||
|
* @returns {SalesTaxLiabilitySummaryRate}
|
||||||
|
*/
|
||||||
|
private taxRateLiability = (
|
||||||
|
taxRate: ITaxRate
|
||||||
|
): SalesTaxLiabilitySummaryRate => {
|
||||||
|
return {
|
||||||
|
taxName: taxRate.name,
|
||||||
|
taxCode: taxRate.code,
|
||||||
|
taxableAmount: this.getAmountMeta(0),
|
||||||
|
taxAmount: this.getAmountMeta(0),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tax rates liability nodes.
|
||||||
|
* @returns {SalesTaxLiabilitySummaryRate[]}
|
||||||
|
*/
|
||||||
|
private taxRatesLiability = (): SalesTaxLiabilitySummaryRate[] => {
|
||||||
|
return this.taxRates.map(this.taxRateLiability);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tax rates total node.
|
||||||
|
* @param {SalesTaxLiabilitySummaryRate[]} nodes
|
||||||
|
* @returns {SalesTaxLiabilitySummaryTotal}
|
||||||
|
*/
|
||||||
|
private taxRatesTotal = (
|
||||||
|
nodes: SalesTaxLiabilitySummaryRate[]
|
||||||
|
): SalesTaxLiabilitySummaryTotal => {
|
||||||
|
const taxableAmount = sumBy(nodes, 'taxableAmount.total');
|
||||||
|
const taxAmount = sumBy(nodes, 'taxAmount.total');
|
||||||
|
|
||||||
|
return {
|
||||||
|
taxableAmount: this.getTotalAmountMeta(taxableAmount),
|
||||||
|
taxAmount: this.getTotalAmountMeta(taxAmount),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the report data.
|
||||||
|
* @returns {SalesTaxLiabilitySummaryReportData}
|
||||||
|
*/
|
||||||
|
public reportData = (): SalesTaxLiabilitySummaryReportData => {
|
||||||
|
const taxRates = this.taxRatesLiability();
|
||||||
|
const total = this.taxRatesTotal(taxRates);
|
||||||
|
|
||||||
|
return { taxRates, total };
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import { keyBy } from 'lodash';
|
||||||
|
import { Inject, Service } from 'typedi';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class SalesTaxLiabilitySummaryRepository {
|
||||||
|
@Inject()
|
||||||
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve tax rates.
|
||||||
|
* @param tenantId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public taxRates = (tenantId: number) => {
|
||||||
|
const { TaxRate } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
return TaxRate.query().orderBy('name', 'desc');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve taxes payable sum grouped by tax rate id.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async taxesPayableSumGroupedByRateId(
|
||||||
|
tenantId: number
|
||||||
|
): Promise<
|
||||||
|
Record<string, { taxRateId: number; credit: number; debit: number }>
|
||||||
|
> {
|
||||||
|
const { AccountTransaction } = this.tenancy.models(tenantId);
|
||||||
|
const { accountRepository } = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
|
const receivableAccount =
|
||||||
|
await accountRepository.findOrCreateAccountReceivable();
|
||||||
|
|
||||||
|
const groupedTaxesById = await AccountTransaction.query()
|
||||||
|
.where('account_id', receivableAccount.id)
|
||||||
|
.groupBy('tax_rate_id')
|
||||||
|
.select(['tax_rate_id'])
|
||||||
|
.sum('credit as credit')
|
||||||
|
.sum('debit as debit');
|
||||||
|
|
||||||
|
return keyBy(groupedTaxesById, 'taxRateId');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve taxes sales sum grouped by tax rate id.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public taxesSalesSumGroupedByRateId = async (tenantId: number) => {
|
||||||
|
const { AccountTransaction, Account } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const incomeAccounts = await Account.query().whereIn('accountType', [
|
||||||
|
ACCOUNT_TYPE.INCOME,
|
||||||
|
ACCOUNT_TYPE.OTHER_INCOME,
|
||||||
|
]);
|
||||||
|
const incomeAccountsIds = incomeAccounts.map((account) => account.id);
|
||||||
|
|
||||||
|
const groupedTaxesById = await AccountTransaction.query()
|
||||||
|
.whereIn('account_id', incomeAccountsIds)
|
||||||
|
.groupBy('tax_rate_id')
|
||||||
|
.select(['tax_rate_id'])
|
||||||
|
.sum('credit as credit')
|
||||||
|
.sum('debit as debit');
|
||||||
|
|
||||||
|
return keyBy(groupedTaxesById, 'taxRateId');
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
|
import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository';
|
||||||
|
import { SalesTaxLiabilitySummaryQuery } from '@/interfaces/SalesTaxLiabilitySummary';
|
||||||
|
import { SalesTaxLiabilitySummary } from './SalesTaxLiabilitySummary';
|
||||||
|
import { SalesTaxLiabilitySummaryTable } from './SalesTaxLiabilitySummaryTable';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class SalesTaxLiabilitySummaryService {
|
||||||
|
@Inject()
|
||||||
|
private repostiory: SalesTaxLiabilitySummaryRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param tenantId
|
||||||
|
* @param query
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async salesTaxLiability(
|
||||||
|
tenantId: number,
|
||||||
|
query: SalesTaxLiabilitySummaryQuery
|
||||||
|
) {
|
||||||
|
const payableByRateId =
|
||||||
|
await this.repostiory.taxesPayableSumGroupedByRateId(tenantId);
|
||||||
|
|
||||||
|
const salesByRateId = await this.repostiory.taxesSalesSumGroupedByRateId(
|
||||||
|
tenantId
|
||||||
|
);
|
||||||
|
const taxRates = await this.repostiory.taxRates(tenantId);
|
||||||
|
|
||||||
|
const taxLiabilitySummary = new SalesTaxLiabilitySummary(
|
||||||
|
query,
|
||||||
|
taxRates,
|
||||||
|
payableByRateId,
|
||||||
|
salesByRateId
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
data: taxLiabilitySummary.reportData(),
|
||||||
|
query,
|
||||||
|
meta: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param tenantId
|
||||||
|
* @param query
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async salesTaxLiabilitySummaryTable(
|
||||||
|
tenantId: number,
|
||||||
|
query: SalesTaxLiabilitySummaryQuery
|
||||||
|
) {
|
||||||
|
const report = await this.salesTaxLiability(tenantId, query);
|
||||||
|
|
||||||
|
const table = new SalesTaxLiabilitySummaryTable(report.data, query);
|
||||||
|
|
||||||
|
return {
|
||||||
|
table: {
|
||||||
|
rows: table.tableRows(),
|
||||||
|
columns: table.tableColumns(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
import * as R from 'ramda';
|
||||||
|
import {
|
||||||
|
SalesTaxLiabilitySummaryQuery,
|
||||||
|
SalesTaxLiabilitySummaryRate,
|
||||||
|
SalesTaxLiabilitySummaryReportData,
|
||||||
|
SalesTaxLiabilitySummaryTotal,
|
||||||
|
} from '@/interfaces/SalesTaxLiabilitySummary';
|
||||||
|
import { tableRowMapper } from '@/utils';
|
||||||
|
import { ITableColumn, ITableColumnAccessor, ITableRow } from '@/interfaces';
|
||||||
|
|
||||||
|
enum IROW_TYPE {
|
||||||
|
TaxRate = 'TaxRate',
|
||||||
|
Total = 'Total',
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SalesTaxLiabilitySummaryTable {
|
||||||
|
data: SalesTaxLiabilitySummaryReportData;
|
||||||
|
query: SalesTaxLiabilitySummaryQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales tax liability summary table constructor.
|
||||||
|
* @param {SalesTaxLiabilitySummaryReportData} data
|
||||||
|
* @param {SalesTaxLiabilitySummaryQuery} query
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
data: SalesTaxLiabilitySummaryReportData,
|
||||||
|
query: SalesTaxLiabilitySummaryQuery
|
||||||
|
) {
|
||||||
|
this.data = data;
|
||||||
|
this.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the tax rate row accessors.
|
||||||
|
* @returns {ITableColumnAccessor[]}
|
||||||
|
*/
|
||||||
|
private get taxRateRowAccessor() {
|
||||||
|
return [
|
||||||
|
{ key: 'taxName', value: 'taxName' },
|
||||||
|
{ key: 'taxCode', accessor: 'taxCode' },
|
||||||
|
{ key: 'taxableAmount', accessor: 'taxableAmount.formattedAmount' },
|
||||||
|
{ key: 'taxAmount', accessor: 'taxAmount.formattedAmount' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the tax rate total row accessors.
|
||||||
|
* @returns {ITableColumnAccessor[]}
|
||||||
|
*/
|
||||||
|
private get taxRateTotalRowAccessors() {
|
||||||
|
return [
|
||||||
|
{ key: 'taxName', value: '' },
|
||||||
|
{ key: 'taxCode', accessor: 'taxCode' },
|
||||||
|
{ key: 'taxableAmount', accessor: 'taxableAmount.formattedAmount' },
|
||||||
|
{ key: 'taxAmount', accessor: 'taxAmount.formattedAmount' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the tax rate node to table row.
|
||||||
|
* @param {SalesTaxLiabilitySummaryRate} node
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private taxRateTableRowMapper = (
|
||||||
|
node: SalesTaxLiabilitySummaryRate
|
||||||
|
): ITableRow => {
|
||||||
|
const columns = this.taxRateRowAccessor;
|
||||||
|
const meta = {
|
||||||
|
rowTypes: [IROW_TYPE.TaxRate],
|
||||||
|
id: node.id,
|
||||||
|
};
|
||||||
|
return tableRowMapper(node, columns, meta);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the tax rates nodes to table rows.
|
||||||
|
* @param {SalesTaxLiabilitySummaryRate[]} nodes
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
private taxRatesTableRowsMapper = (
|
||||||
|
nodes: SalesTaxLiabilitySummaryRate[]
|
||||||
|
): ITableRow[] => {
|
||||||
|
return nodes.map(this.taxRateTableRowMapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the tax rate total node to table row.
|
||||||
|
* @param {SalesTaxLiabilitySummaryTotal} node
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private taxRateTotalRowMapper = (node: SalesTaxLiabilitySummaryTotal) => {
|
||||||
|
const columns = this.taxRateTotalRowAccessors;
|
||||||
|
const meta = {
|
||||||
|
rowTypes: [IROW_TYPE.Total],
|
||||||
|
id: node.key,
|
||||||
|
};
|
||||||
|
return tableRowMapper(node, columns, meta);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tax rate total row.
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private get taxRateTotalRow(): ITableRow {
|
||||||
|
return this.taxRateTotalRowMapper(this.data.total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tax rates rows.
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
private get taxRatesRows(): ITableRow[] {
|
||||||
|
return this.taxRatesTableRowsMapper(this.data.taxRates);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the table rows.
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
public tableRows(): ITableRow[] {
|
||||||
|
return R.compose(
|
||||||
|
R.concat(this.taxRatesRows),
|
||||||
|
R.prepend(this.taxRateTotalRow)
|
||||||
|
)([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the table columns.
|
||||||
|
* @returns {ITableColumn[]}
|
||||||
|
*/
|
||||||
|
public tableColumns(): ITableColumn[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: 'Tax Name',
|
||||||
|
key: 'taxName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Tax Code',
|
||||||
|
key: 'taxCode',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Taxable Amount',
|
||||||
|
key: 'taxableAmount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Tax Rate',
|
||||||
|
key: 'taxRate',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user