mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
feat(server): sales by items table
This commit is contained in:
@@ -1,18 +1,17 @@
|
|||||||
import { Router, Request, Response, NextFunction } from 'express';
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
import { query, ValidationChain } from 'express-validator';
|
import { query, ValidationChain, ValidationSchema } from 'express-validator';
|
||||||
import moment from 'moment';
|
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
||||||
import BaseFinancialReportController from './BaseFinancialReportController';
|
import BaseFinancialReportController from './BaseFinancialReportController';
|
||||||
import SalesByItemsReportService from '@/services/FinancialStatements/SalesByItems/SalesByItemsService';
|
|
||||||
import { AbilitySubject, ReportsAction } from '@/interfaces';
|
import { AbilitySubject, ReportsAction } from '@/interfaces';
|
||||||
import CheckPolicies from '@/api/middleware/CheckPolicies';
|
import CheckPolicies from '@/api/middleware/CheckPolicies';
|
||||||
import { ACCEPT_TYPE } from '@/interfaces/Http';
|
import { ACCEPT_TYPE } from '@/interfaces/Http';
|
||||||
|
import { SalesByItemsApplication } from '@/services/FinancialStatements/SalesByItems/SalesByItemsApplication';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SalesByItemsReportController extends BaseFinancialReportController {
|
export default class SalesByItemsReportController extends BaseFinancialReportController {
|
||||||
@Inject()
|
@Inject()
|
||||||
salesByItemsService: SalesByItemsReportService;
|
salesByItemsApp: SalesByItemsApplication;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router constructor.
|
* Router constructor.
|
||||||
@@ -32,6 +31,7 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validation schema.
|
* Validation schema.
|
||||||
|
* @returns {ValidationChain[]}
|
||||||
*/
|
*/
|
||||||
private get validationSchema(): ValidationChain[] {
|
private get validationSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
@@ -68,7 +68,6 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
|
|||||||
) {
|
) {
|
||||||
const { tenantId } = req;
|
const { tenantId } = req;
|
||||||
const filter = this.matchedQueryData(req);
|
const filter = this.matchedQueryData(req);
|
||||||
|
|
||||||
const accept = this.accepts(req);
|
const accept = this.accepts(req);
|
||||||
|
|
||||||
const acceptType = accept.types([
|
const acceptType = accept.types([
|
||||||
@@ -77,13 +76,33 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
|
|||||||
ACCEPT_TYPE.APPLICATION_CSV,
|
ACCEPT_TYPE.APPLICATION_CSV,
|
||||||
ACCEPT_TYPE.APPLICATION_XLSX,
|
ACCEPT_TYPE.APPLICATION_XLSX,
|
||||||
]);
|
]);
|
||||||
|
// Retrieves the csv format.
|
||||||
if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
|
if (ACCEPT_TYPE.APPLICATION_CSV === acceptType) {
|
||||||
|
const buffer = await this.salesByItemsApp.csv(tenantId, filter);
|
||||||
|
|
||||||
|
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
|
||||||
|
res.setHeader('Content-Type', 'text/csv');
|
||||||
|
|
||||||
|
return res.send(buffer);
|
||||||
|
// Retrieves the json table format.
|
||||||
|
} else if (ACCEPT_TYPE.APPLICATION_JSON_TABLE === acceptType) {
|
||||||
|
const table = await this.salesByItemsApp.table(tenantId, filter);
|
||||||
|
|
||||||
|
return res.status(200).send(table);
|
||||||
|
// Retrieves the xlsx format.
|
||||||
} else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
|
} else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
|
||||||
} else if (ACCEPT_TYPE.APPLICATION_XLSX === acceptType) {
|
const buffer = this.salesByItemsApp.xlsx(tenantId, filter);
|
||||||
|
|
||||||
|
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
|
||||||
|
res.setHeader(
|
||||||
|
'Content-Type',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
);
|
||||||
|
return res.send(buffer);
|
||||||
|
// Retrieves the json format.
|
||||||
} else {
|
} else {
|
||||||
await this.salesByItemsService.salesByItems(tenantId, filter);
|
const sheet = await this.salesByItemsApp.sheet(tenantId, filter);
|
||||||
return res.status(200).send({ meta, data, query });
|
return res.status(200).send(sheet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export class SalesByItemsApplication {
|
|||||||
public sheet(tenantId: number, filter: ISalesByItemsReportQuery) {
|
public sheet(tenantId: number, filter: ISalesByItemsReportQuery) {
|
||||||
return this.salesByItemsSheet.salesByItems(tenantId, filter);
|
return this.salesByItemsSheet.salesByItems(tenantId, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the sales by items report in table format.
|
* Retrieves the sales by items report in table format.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -33,6 +34,7 @@ export class SalesByItemsApplication {
|
|||||||
public table(tenantId: number, filter: ISalesByItemsReportQuery) {
|
public table(tenantId: number, filter: ISalesByItemsReportQuery) {
|
||||||
return this.salesByItemsTable.table(tenantId, filter);
|
return this.salesByItemsTable.table(tenantId, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the sales by items report in csv format.
|
* Retrieves the sales by items report in csv format.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -42,6 +44,7 @@ export class SalesByItemsApplication {
|
|||||||
public csv(tenantId: number, filter: ISalesByItemsReportQuery) {
|
public csv(tenantId: number, filter: ISalesByItemsReportQuery) {
|
||||||
return this.salesByItemsExport.csv(tenantId, filter);
|
return this.salesByItemsExport.csv(tenantId, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the sales by items report in xlsx format.
|
* Retrieves the sales by items report in xlsx format.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
|
|||||||
@@ -1,47 +1,72 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { ISalesByItemsSheetStatement, ITableColumn, ITableData, ITableRow } from '@/interfaces';
|
import {
|
||||||
|
ISalesByItemsItem,
|
||||||
|
ISalesByItemsSheetStatement,
|
||||||
|
ISalesByItemsTotal,
|
||||||
|
ITableColumn,
|
||||||
|
ITableRow,
|
||||||
|
} from '@/interfaces';
|
||||||
import { tableRowMapper } from '@/utils';
|
import { tableRowMapper } from '@/utils';
|
||||||
|
|
||||||
export class SalesByItemsTable {
|
export class SalesByItemsTable {
|
||||||
private readonly data: ISalesByItemsSheetStatement;
|
private readonly data: ISalesByItemsSheetStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {ISalesByItemsSheetStatement} data
|
||||||
|
*/
|
||||||
constructor(data: ISalesByItemsSheetStatement) {
|
constructor(data: ISalesByItemsSheetStatement) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the common table accessors.
|
||||||
|
* @returns {ITableColumn[]}
|
||||||
|
*/
|
||||||
private commonTableAccessors() {
|
private commonTableAccessors() {
|
||||||
return [
|
return [
|
||||||
{ key: 'item_name', accessor: 'name' },
|
{ key: 'item_name', accessor: 'name' },
|
||||||
{ key: 'quantity', accessor: 'quantitySoldFormatted' },
|
{ key: 'sold_quantity', accessor: 'quantitySoldFormatted' },
|
||||||
{ key: 'sold', accessor: 'soldCostFormatted' },
|
{ key: 'sold_amount', accessor: 'soldCostFormatted' },
|
||||||
|
{ key: 'average_price', accessor: 'averageSellPriceFormatted' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private itemMap(item: any) {
|
/**
|
||||||
|
* Maps the given item node to table row.
|
||||||
|
* @param {ISalesByItemsItem} item
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private itemMap = (item: ISalesByItemsItem): ITableRow => {
|
||||||
const columns = this.commonTableAccessors();
|
const columns = this.commonTableAccessors();
|
||||||
const meta = {};
|
const meta = {};
|
||||||
|
|
||||||
return tableRowMapper(item, columns, meta);
|
return tableRowMapper(item, columns, meta);
|
||||||
}
|
};
|
||||||
|
|
||||||
private itemsMap(items: any[]) {
|
|
||||||
return R.map(this.itemMap, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Maps the given items nodes to table rows.
|
||||||
* @param total
|
* @param {ISalesByItemsItem[]} items
|
||||||
* @returns
|
* @returns {ITableRow[]}
|
||||||
*/
|
*/
|
||||||
private totalMap(total: any) {
|
private itemsMap = (items: ISalesByItemsItem[]): ITableRow[] => {
|
||||||
|
return R.map(this.itemMap, items);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the given total node to table row.
|
||||||
|
* @param {ISalesByItemsTotal} total
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
private totalMap = (total: ISalesByItemsTotal) => {
|
||||||
const columns = this.commonTableAccessors();
|
const columns = this.commonTableAccessors();
|
||||||
const meta = {};
|
const meta = {};
|
||||||
|
|
||||||
return tableRowMapper(total, columns, meta);
|
return tableRowMapper(total, columns, meta);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the table rows.
|
||||||
* @returns {ITableRow[]}
|
* @returns {ITableRow[]}
|
||||||
*/
|
*/
|
||||||
public tableData(): ITableRow[] {
|
public tableData(): ITableRow[] {
|
||||||
@@ -57,9 +82,10 @@ export class SalesByItemsTable {
|
|||||||
*/
|
*/
|
||||||
public tableColumns(): ITableColumn[] {
|
public tableColumns(): ITableColumn[] {
|
||||||
return [
|
return [
|
||||||
{ key: 'item_name', label: 'Item Name' },
|
{ key: 'item_name', label: 'Item name' },
|
||||||
{ key: 'quantity', label: 'Quantity' },
|
{ key: 'sold_quantity', label: 'Sold quantity' },
|
||||||
{ key: 'sold_cost', label: 'Sold Cost' },
|
{ key: 'sold_amount', label: 'Sold amount' },
|
||||||
|
{ key: 'average_price', label: 'Average price' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user