Compare commits

...

14 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
84445d4bac fix(server): date format of filtering transactions by date range 2023-08-29 02:41:40 +02:00
Ahmed Bouhuolia
75d8864aae Merge remote-tracking branch 'refs/remotes/origin/develop' into develop 2023-08-28 21:03:23 +02:00
Ahmed Bouhuolia
cb6dab08d8 chore: remove un-used methods 2023-08-28 21:01:34 +02:00
Ahmed Bouhuolia
5112ef9b64 Merge pull request #230 from bigcapitalhq/abouhuolia/big-60-fromto-date-is-not-showing-up-on-inventory-items-details
fix: change the default from/date date value of reports
2023-08-28 20:59:02 +02:00
Ahmed Bouhuolia
a630e8a612 fix: change the default from/to dates of customers/vendors transactions 2023-08-28 20:53:52 +02:00
Ahmed Bouhuolia
4df63561cf fix(webapp): change the default from/to date values of reports 2023-08-27 16:00:54 +02:00
Ahmed Bouhuolia
c7a3bac44c fix(server): change the default from/date date value of reports 2023-08-27 15:50:52 +02:00
Ahmed Bouhuolia
251c54be60 Merge pull request #229 from bigcapitalhq/abouhuolia/big-45-receivablepayable-again-report-issue
fix AP/AR aging summary issue
2023-08-27 00:58:17 +02:00
Ahmed Bouhuolia
5dec4a7df0 chore(server): document methods 2023-08-27 00:56:14 +02:00
Ahmed Bouhuolia
0d57ca88bf fix(server): avoid return total row on aging summary reports if no customers 2023-08-27 00:45:12 +02:00
Ahmed Bouhuolia
b9be83dc2b fix(webapp): add validation to aging summary customize form 2023-08-27 00:44:37 +02:00
Ahmed Bouhuolia
321de4d327 refactor(webapp): AR/AP aging summary table columns 2023-08-26 02:16:35 +02:00
Ahmed Bouhuolia
4e66d1ac98 feat(server): AP/AR aging summary table transformer 2023-08-24 23:24:05 +02:00
Ahmed Bouhuolia
b5fe5a8bcb Merge pull request #227 from bigcapitalhq/fix-spelling-a-char
Fix spelling words start with `A` letter
2023-08-22 22:56:23 +02:00
66 changed files with 738 additions and 360 deletions

View File

@@ -33,10 +33,13 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
return [
...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(),
query('aging_days_before').optional().isNumeric().toInt(),
query('aging_periods').optional().isNumeric().toInt(),
query('aging_days_before').default(30).isInt({ max: 500 }).toInt(),
query('aging_periods').default(3).isInt({ max: 12 }).toInt(),
query('vendors_ids').optional().isArray({ min: 1 }),
query('vendors_ids.*').isInt({ min: 1 }).toInt(),
query('none_zero').default(true).isBoolean().toBoolean(),
// Filtering by branches.
@@ -53,15 +56,36 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
const filter = this.matchedQueryData(req);
try {
const { data, columns, query, meta } =
await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
return res.status(200).send({
data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
switch (acceptType) {
case 'application/json+table':
const table = await this.APAgingSummaryService.APAgingSummaryTable(
tenantId,
filter
);
return res.status(200).send({
table: {
rows: table.rows,
columns: table.columns,
},
meta: table.meta,
query: table.query,
});
break;
default:
const { data, columns, query, meta } =
await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
return res.status(200).send({
data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
break;
}
} catch (error) {
next(error);
}

View File

@@ -36,8 +36,8 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
query('as_date').optional().isISO8601(),
query('aging_days_before').optional().isInt({ max: 500 }).toInt(),
query('aging_periods').optional().isInt({ max: 12 }).toInt(),
query('aging_days_before').default(30).isInt({ max: 500 }).toInt(),
query('aging_periods').default(3).isInt({ max: 12 }).toInt(),
query('customers_ids').optional().isArray({ min: 1 }),
query('customers_ids.*').isInt({ min: 1 }).toInt(),
@@ -58,15 +58,36 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
const filter = this.matchedQueryData(req);
try {
const { data, columns, query, meta } =
await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
return res.status(200).send({
data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
switch (acceptType) {
case 'application/json+table':
const table = await this.ARAgingSummaryService.ARAgingSummaryTable(
tenantId,
filter
);
return res.status(200).send({
table: {
rows: table.rows,
columns: table.columns,
},
meta: table.meta,
query: table.query,
});
break;
default:
const { data, columns, query, meta } =
await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
return res.status(200).send({
data: this.transfromToResponse(data),
columns: this.transfromToResponse(columns),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
break;
}
} catch (error) {
console.log(error);
}

View File

@@ -1,51 +1,36 @@
import {
IAgingPeriod,
IAgingPeriodTotal,
IAgingAmount
IAgingAmount,
IAgingSummaryQuery,
IAgingSummaryTotal,
IAgingSummaryContact,
IAgingSummaryData,
} from './AgingReport';
import {
INumberFormatQuery
} from './FinancialStatements';
import { INumberFormatQuery } from './FinancialStatements';
export interface IAPAgingSummaryQuery {
asDate: Date | string;
agingDaysBefore: number;
agingPeriods: number;
numberFormat: INumberFormatQuery;
export interface IAPAgingSummaryQuery extends IAgingSummaryQuery {
vendorsIds: number[];
noneZero: boolean;
branchesIds?: number[]
}
export interface IAPAgingSummaryVendor {
vendorName: string,
current: IAgingAmount,
aging: IAgingPeriodTotal[],
total: IAgingAmount,
};
export interface IAPAgingSummaryVendor extends IAgingSummaryContact {
vendorName: string;
}
export interface IAPAgingSummaryTotal {
current: IAgingAmount,
aging: IAgingPeriodTotal[],
total: IAgingAmount,
};
export interface IAPAgingSummaryTotal extends IAgingSummaryTotal {}
export interface IAPAgingSummaryData {
vendors: IAPAgingSummaryVendor[],
total: IAPAgingSummaryTotal,
};
export interface IAPAgingSummaryData extends IAgingSummaryData {
vendors: IAPAgingSummaryVendor[];
}
export type IAPAgingSummaryColumns = IAgingPeriod[];
export interface IARAgingSummaryMeta {
baseCurrency: string,
organizationName: string,
baseCurrency: string;
organizationName: string;
}
export interface IAPAgingSummaryMeta {
baseCurrency: string,
organizationName: string,
}
baseCurrency: string;
organizationName: string;
}

View File

@@ -1,37 +1,28 @@
import { IAgingPeriod, IAgingPeriodTotal, IAgingAmount } from './AgingReport';
import { INumberFormatQuery } from './FinancialStatements';
import {
IAgingPeriod,
IAgingSummaryQuery,
IAgingSummaryTotal,
IAgingSummaryContact,
IAgingSummaryData,
} from './AgingReport';
export interface IARAgingSummaryQuery {
asDate: Date | string;
agingDaysBefore: number;
agingPeriods: number;
numberFormat: INumberFormatQuery;
export interface IARAgingSummaryQuery extends IAgingSummaryQuery {
customersIds: number[];
branchesIds: number[];
noneZero: boolean;
}
export interface IARAgingSummaryCustomer {
export interface IARAgingSummaryCustomer extends IAgingSummaryContact {
customerName: string;
current: IAgingAmount;
aging: IAgingPeriodTotal[];
total: IAgingAmount;
}
export interface IARAgingSummaryTotal {
current: IAgingAmount;
aging: IAgingPeriodTotal[];
total: IAgingAmount;
}
export interface IARAgingSummaryTotal extends IAgingSummaryTotal {}
export interface IARAgingSummaryData {
export interface IARAgingSummaryData extends IAgingSummaryData {
customers: IARAgingSummaryCustomer[];
total: IARAgingSummaryTotal;
}
export type IARAgingSummaryColumns = IAgingPeriod[];
export interface IARAgingSummaryMeta {
organizationName: string,
baseCurrency: string,
}
organizationName: string;
baseCurrency: string;
}

View File

@@ -1,6 +1,9 @@
import { INumberFormatQuery } from './FinancialStatements';
export interface IAgingPeriodTotal extends IAgingPeriod {
total: IAgingAmount;
};
}
export interface IAgingAmount {
amount: number;
@@ -20,3 +23,22 @@ export interface IAgingSummaryContact {
aging: IAgingPeriodTotal[];
total: IAgingAmount;
}
export interface IAgingSummaryQuery {
asDate: Date | string;
agingDaysBefore: number;
agingPeriods: number;
numberFormat: INumberFormatQuery;
branchesIds: number[];
noneZero: boolean;
}
export interface IAgingSummaryTotal {
current: IAgingAmount;
aging: IAgingPeriodTotal[];
total: IAgingAmount;
}
export interface IAgingSummaryData {
total: IAgingSummaryTotal;
}

View File

@@ -59,15 +59,9 @@ export default class AccountTransaction extends TenantModel {
}
},
filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const fromDate = moment(startDate)
.utcOffset(0)
.startOf(type)
.format(dateFormat);
const toDate = moment(endDate)
.utcOffset(0)
.endOf(type)
.format(dateFormat);
const dateFormat = 'YYYY-MM-DD';
const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat);
if (startDate) {
query.where('date', '>=', fromDate);
@@ -111,7 +105,6 @@ export default class AccountTransaction extends TenantModel {
query.modify('filterDateRange', null, toDate);
query.modify('sumationCreditDebit');
},
contactsOpeningBalance(
query,
openingDate,

View File

@@ -33,7 +33,7 @@ export default class InventoryCostLotTracker extends TenantModel {
query.groupBy('item_id');
},
filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const dateFormat = 'YYYY-MM-DD';
const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat);

View File

@@ -36,7 +36,7 @@ export default class InventoryTransaction extends TenantModel {
static get modifiers() {
return {
filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const dateFormat = 'YYYY-MM-DD';
const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat);

View File

@@ -176,7 +176,7 @@ export default class SaleInvoice extends mixin(TenantModel, [
* Filters the invoices between the given date range.
*/
filterDateRange(query, startDate, endDate, type = 'day') {
const dateFormat = 'YYYY-MM-DD HH:mm:ss';
const dateFormat = 'YYYY-MM-DD';
const fromDate = moment(startDate).startOf(type).format(dateFormat);
const toDate = moment(endDate).endOf(type).format(dateFormat);

View File

@@ -1,17 +1,12 @@
import { Service, Inject } from 'typedi';
import { includes, difference, camelCase, upperFirst } from 'lodash';
import { ACCOUNT_TYPE } from '@/data/AccountTypes';
import { IAccount, ICashflowTransactionLine } from '@/interfaces';
import { Service } from 'typedi';
import { includes, camelCase, upperFirst } from 'lodash';
import { IAccount } from '@/interfaces';
import { getCashflowTransactionType } from './utils';
import { ServiceError } from '@/exceptions';
import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants';
import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service()
export class CommandCashflowValidator {
@Inject()
private tenancy: HasTenancyService;
/**
* Validates the lines accounts type should be cash or bank account.
* @param {IAccount} accounts -

View File

@@ -1,14 +0,0 @@
import { difference, includes } from 'lodash';
import { ICashflowTransactionLine } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import { Inject, Service } from 'typedi';
import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants';
import { IAccount } from '@/interfaces';
import HasTenancyService from '@/services/Tenancy/TenancyService';
@Service()
export default class CommandCashflowTransaction {
@Inject()
private tenancy: HasTenancyService;
}

View File

@@ -5,6 +5,7 @@ import TenancyService from '@/services/Tenancy/TenancyService';
import APAgingSummarySheet from './APAgingSummarySheet';
import { Tenant } from '@/system/models';
import { isEmpty } from 'lodash';
import APAgingSummaryTable from './APAgingSummaryTable';
@Service()
export default class PayableAgingSummaryService {
@@ -84,7 +85,7 @@ export default class PayableAgingSummaryService {
// Common query.
const commonQuery = (query) => {
if (isEmpty(filter.branchesIds)) {
if (!isEmpty(filter.branchesIds)) {
query.modify('filterByBranches', filter.branchesIds);
}
};
@@ -118,4 +119,21 @@ export default class PayableAgingSummaryService {
meta: this.reportMetadata(tenantId),
};
}
/**
* Retrieves A/P aging summary in table format.
* @param {number} tenantId
* @param {IAPAgingSummaryQuery} query
*/
async APAgingSummaryTable(tenantId: number, query: IAPAgingSummaryQuery) {
const report = await this.APAgingSummary(tenantId, query);
const table = new APAgingSummaryTable(report.data, query, {});
return {
columns: table.tableColumns(),
rows: table.tableRows(),
meta: report.meta,
query: report.query,
};
}
}

View File

@@ -91,7 +91,7 @@ export default class APAgingSummarySheet extends AgingSummaryReport {
return {
vendorName: vendor.displayName,
current: this.formatTotalAmount(currentTotal),
current: this.formatAmount(currentTotal),
aging: agingPeriods,
total: this.formatTotalAmount(amount),
};

View File

@@ -0,0 +1,46 @@
import {
IAPAgingSummaryData,
IAgingSummaryQuery,
ITableColumn,
ITableColumnAccessor,
ITableRow,
} from '@/interfaces';
import AgingSummaryTable from './AgingSummaryTable';
export default class APAgingSummaryTable extends AgingSummaryTable {
readonly report: IAPAgingSummaryData;
/**
* Constructor method.
* @param {IARAgingSummaryData} data
* @param {IAgingSummaryQuery} query
* @param {any} i18n
*/
constructor(data: IAPAgingSummaryData, query: IAgingSummaryQuery, i18n: any) {
super(data, query, i18n);
}
/**
* Retrieves the contacts table rows.
* @returns {ITableRow[]}
*/
get contactsRows(): ITableRow[] {
return this.contactsNodes(this.report.vendors);
}
/**
* Contact name node accessor.
* @returns {ITableColumnAccessor}
*/
get contactNameNodeAccessor(): ITableColumnAccessor {
return { key: 'vendor_name', accessor: 'vendorName' };
}
/**
* Retrieves the contact name table column.
* @returns {ITableColumn}
*/
contactNameTableColumn = (): ITableColumn => {
return { label: 'Vendor name', key: 'vendor_name' };
};
}

View File

@@ -5,6 +5,7 @@ import { IARAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces';
import TenancyService from '@/services/Tenancy/TenancyService';
import ARAgingSummarySheet from './ARAgingSummarySheet';
import { Tenant } from '@/system/models';
import ARAgingSummaryTable from './ARAgingSummaryTable';
@Service()
export default class ARAgingSummaryService {
@@ -89,12 +90,12 @@ export default class ARAgingSummaryService {
};
// Retrieve all overdue sale invoices.
const overdueSaleInvoices = await SaleInvoice.query()
.modify('dueInvoicesFromDate', filter.asDate)
.modify('overdueInvoicesFromDate', filter.asDate)
.onBuild(commonQuery);
// Retrieve all due sale invoices.
const currentInvoices = await SaleInvoice.query()
.modify('overdueInvoicesFromDate', filter.asDate)
.modify('dueInvoicesFromDate', filter.asDate)
.onBuild(commonQuery);
// AR aging summary report instance.
@@ -117,4 +118,21 @@ export default class ARAgingSummaryService {
meta: this.reportMetadata(tenantId),
};
}
/**
* Retrieves A/R aging summary in table format.
* @param {number} tenantId
* @param {IARAgingSummaryQuery} query
*/
async ARAgingSummaryTable(tenantId: number, query: IARAgingSummaryQuery) {
const report = await this.ARAgingSummary(tenantId, query);
const table = new ARAgingSummaryTable(report.data, query, {});
return {
columns: table.tableColumns(),
rows: table.tableRows(),
meta: report.meta,
query,
};
}
}

View File

@@ -1,4 +1,4 @@
import { groupBy, isEmpty, sum } from 'lodash';
import { Dictionary, groupBy, isEmpty, sum } from 'lodash';
import * as R from 'ramda';
import {
ICustomer,
@@ -54,7 +54,6 @@ export default class ARAgingSummarySheet extends AgingSummaryReport {
currentSaleInvoices,
'customerId'
);
// Initializes the aging periods.
this.agingPeriods = this.agingRangePeriods(
this.query.asDate,
@@ -189,7 +188,7 @@ export default class ARAgingSummarySheet extends AgingSummaryReport {
};
/**
* Retrieve AR aging summary report columns.
* Retrieve A/R aging summary report columns.
* @return {IARAgingSummaryColumns}
*/
public reportColumns(): IARAgingSummaryColumns {

View File

@@ -0,0 +1,38 @@
import {
IARAgingSummaryData,
IAgingSummaryData,
IAgingSummaryQuery,
ITableColumnAccessor,
ITableRow,
} from '@/interfaces';
import AgingSummaryTable from './AgingSummaryTable';
export default class ARAgingSummaryTable extends AgingSummaryTable {
readonly report: IARAgingSummaryData;
/**
* Constructor method.
* @param {IARAgingSummaryData} data
* @param {IAgingSummaryQuery} query
* @param {any} i18n
*/
constructor(data: IARAgingSummaryData, query: IAgingSummaryQuery, i18n: any) {
super(data, query, i18n);
}
/**
* Retrieves the contacts table rows.
* @returns {ITableRow[]}
*/
get contactsRows(): ITableRow[] {
return this.contactsNodes(this.report.customers);
}
/**
* Contact name node accessor.
* @returns {ITableColumnAccessor}
*/
get contactNameNodeAccessor(): ITableColumnAccessor {
return { key: 'customer_name', accessor: 'customerName' };
}
}

View File

@@ -0,0 +1,211 @@
import * as R from 'ramda';
import {
IAgingPeriod,
IAgingSummaryContact,
IAgingSummaryData,
IAgingSummaryQuery,
IAgingSummaryTotal,
ITableColumn,
ITableColumnAccessor,
ITableRow,
} from '@/interfaces';
import { tableRowMapper } from '@/utils';
import AgingReport from './AgingReport';
import { AgingSummaryRowType } from './_constants';
import { FinancialTable } from '../FinancialTable';
import { FinancialSheetStructure } from '../FinancialSheetStructure';
export default abstract class AgingSummaryTable extends R.compose(
FinancialSheetStructure,
FinancialTable
)(AgingReport) {
protected readonly report: IAgingSummaryData;
protected readonly query: IAgingSummaryQuery;
protected readonly agingPeriods: IAgingPeriod[];
protected readonly i18n: any;
/**
* Constructor method.
* @param {IARAgingSummaryData} data
* @param {IAgingSummaryQuery} query
* @param {any} i18n
*/
constructor(data: IAgingSummaryData, query: IAgingSummaryQuery, i18n: any) {
super();
this.report = data;
this.i18n = i18n;
this.query = query;
this.agingPeriods = this.agingRangePeriods(
this.query.asDate,
this.query.agingDaysBefore,
this.query.agingPeriods
);
}
// -------------------------
// # Accessors.
// -------------------------
/**
* Aging accessors of contact and total nodes.
* @param {IAgingSummaryContact | IAgingSummaryTotal} node
* @returns {ITableColumnAccessor[]}
*/
protected agingNodeAccessors = (
node: IAgingSummaryContact | IAgingSummaryTotal
): ITableColumnAccessor[] => {
return node.aging.map((aging, index) => ({
key: 'aging',
accessor: `aging[${index}].total.formattedAmount`,
}));
};
/**
* Contact name node accessor.
* @returns {ITableColumnAccessor}
*/
protected get contactNameNodeAccessor(): ITableColumnAccessor {
return { key: 'customer_name', accessor: 'customerName' };
}
/**
* Retrieves the common columns for all report nodes.
* @param {IAgingSummaryContact}
* @returns {ITableColumnAccessor[]}
*/
protected contactNodeAccessors = (
node: IAgingSummaryContact
): ITableColumnAccessor[] => {
return R.compose(
R.concat([
this.contactNameNodeAccessor,
{ key: 'current', accessor: 'current.formattedAmount' },
...this.agingNodeAccessors(node),
{ key: 'total', accessor: 'total.formattedAmount' },
])
)([]);
};
/**
* Retrieves the contact name table row.
* @param {IAgingSummaryContact} node -
* @return {ITableRow}
*/
protected contactNameNode = (node: IAgingSummaryContact): ITableRow => {
const columns = this.contactNodeAccessors(node);
const meta = {
rowTypes: [AgingSummaryRowType.Contact],
};
return tableRowMapper(node, columns, meta);
};
/**
* Maps the customers nodes to table rows.
* @param {IAgingSummaryContact[]} nodes
* @returns {ITableRow[]}
*/
protected contactsNodes = (nodes: IAgingSummaryContact[]): ITableRow[] => {
return nodes.map(this.contactNameNode);
};
/**
* Retrieves the common columns for all report nodes.
* @param {IAgingSummaryTotal}
* @returns {ITableColumnAccessor[]}
*/
protected totalNodeAccessors = (
node: IAgingSummaryTotal
): ITableColumnAccessor[] => {
return R.compose(
R.concat([
{ key: 'blank', value: '' },
{ key: 'current', accessor: 'current.formattedAmount' },
...this.agingNodeAccessors(node),
{ key: 'total', accessor: 'total.formattedAmount' },
])
)([]);
};
/**
* Retrieves the total row of the given report total node.
* @param {IAgingSummaryTotal} node
* @returns {ITableRow}
*/
protected totalNode = (node: IAgingSummaryTotal): ITableRow => {
const columns = this.totalNodeAccessors(node);
const meta = {
rowTypes: [AgingSummaryRowType.Total],
};
return tableRowMapper(node, columns, meta);
};
// -------------------------
// # Computed Rows.
// -------------------------
/**
* Retrieves the contacts table rows.
* @returns {ITableRow[]}
*/
protected get contactsRows(): ITableRow[] {
return [];
}
/**
* Table total row.
* @returns {ITableRow}
*/
protected get totalRow(): ITableRow {
return this.totalNode(this.report.total);
}
/**
* Retrieves the table rows.
* @returns {ITableRow[]}
*/
public tableRows = (): ITableRow[] => {
return R.compose(
R.unless(R.isEmpty, R.append(this.totalRow)),
R.concat(this.contactsRows)
)([]);
};
// -------------------------
// # Columns.
// -------------------------
/**
* Retrieves the aging table columns.
* @returns {ITableColumn[]}
*/
protected agingTableColumns = (): ITableColumn[] => {
return this.agingPeriods.map((agingPeriod) => {
return {
label: `${agingPeriod.beforeDays} - ${
agingPeriod.toDays || 'And Over'
}`,
key: 'aging_period',
};
});
};
/**
* Retrieves the contact name table column.
* @returns {ITableColumn}
*/
protected contactNameTableColumn = (): ITableColumn => {
return { label: 'Customer name', key: 'customer_name' };
};
/**
* Retrieves the report columns.
* @returns {ITableColumn}
*/
public tableColumns = (): ITableColumn[] => {
return R.compose(this.tableColumnsCellIndexing)([
this.contactNameTableColumn(),
{ label: 'Current', key: 'current' },
...this.agingTableColumns(),
{ label: 'Total', key: 'total' },
]);
};
}

View File

@@ -0,0 +1,4 @@
export enum AgingSummaryRowType {
Contact = 'contact',
Total = 'total',
}

View File

@@ -37,7 +37,7 @@ export default class BalanceSheetStatementService
displayColumnsBy: 'month',
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
numberFormat: {
precision: 2,

View File

@@ -40,7 +40,7 @@ export default class CashFlowStatementService
displayColumnsType: 'total',
displayColumnsBy: 'day',
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
numberFormat: {
precision: 2,
divideOn1000: false,

View File

@@ -12,7 +12,7 @@ export const FinancialTable = (Base) =>
* @param {ITableColumn[]} columns
* @returns {ITableColumn[]}
*/
protected tableColumnsCellIndexing = (
public tableColumnsCellIndexing = (
columns: ITableColumn[]
): ITableColumn[] => {
const cellIndex = increment(-1);

View File

@@ -31,8 +31,8 @@ export default class GeneralLedgerService {
*/
get defaultQuery() {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
basis: 'cash',
numberFormat: {
noCents: false,

View File

@@ -16,13 +16,13 @@ import { Tenant } from '@/system/models';
@Service()
export default class InventoryDetailsService extends FinancialSheet {
@Inject()
tenancy: TenancyService;
private tenancy: TenancyService;
@Inject()
reportRepo: InventoryDetailsRepository;
private reportRepo: InventoryDetailsRepository;
@Inject()
inventoryService: InventoryService;
private inventoryService: InventoryService;
/**
* Defaults balance sheet filter query.
@@ -30,8 +30,8 @@ export default class InventoryDetailsService extends FinancialSheet {
*/
private get defaultQuery(): IInventoryDetailsQuery {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
itemsIds: [],
numberFormat: {
precision: 2,

View File

@@ -27,7 +27,7 @@ export default class InventoryValuationSheetService {
*/
get defaultQuery(): IInventoryValuationReportQuery {
return {
asDate: moment().endOf('year').format('YYYY-MM-DD'),
asDate: moment().format('YYYY-MM-DD'),
itemsIds: [],
numberFormat: {
precision: 2,

View File

@@ -25,8 +25,8 @@ export default class JournalSheetService {
*/
get defaultQuery() {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
fromRange: null,
toRange: null,
accountsIds: [],

View File

@@ -8,7 +8,7 @@ import { IProfitLossSheetQuery } from '@/interfaces';
*/
export const getDefaultPLQuery = (): IProfitLossSheetQuery => ({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
numberFormat: {
divideOn1000: false,

View File

@@ -12,10 +12,7 @@ import { Tenant } from '@/system/models';
@Service()
export default class InventoryValuationReportService {
@Inject()
tenancy: TenancyService;
@Inject('logger')
logger: any;
private tenancy: TenancyService;
/**
* Defaults balance sheet filter query.
@@ -23,8 +20,8 @@ export default class InventoryValuationReportService {
*/
get defaultQuery(): IInventoryValuationReportQuery {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
itemsIds: [],
numberFormat: {
precision: 2,
@@ -73,9 +70,9 @@ export default class InventoryValuationReportService {
tenantId: number,
query: IInventoryValuationReportQuery
): Promise<{
data: IInventoryValuationStatement,
query: IInventoryValuationReportQuery,
meta: IInventoryValuationSheetMeta,
data: IInventoryValuationStatement;
query: IInventoryValuationReportQuery;
meta: IInventoryValuationSheetMeta;
}> {
const { Item, InventoryTransaction } = this.tenancy.models(tenantId);
@@ -87,7 +84,7 @@ export default class InventoryValuationReportService {
...this.defaultQuery,
...query,
};
const inventoryItems = await Item.query().onBuild(q => {
const inventoryItems = await Item.query().onBuild((q) => {
q.where('type', 'inventory');
if (filter.itemsIds.length > 0) {
@@ -106,7 +103,7 @@ export default class InventoryValuationReportService {
builder.whereIn('itemId', inventoryItemsIds);
// Filter the date range of the sheet.
builder.modify('filterDateRange', filter.fromDate, filter.toDate)
builder.modify('filterDateRange', filter.fromDate, filter.toDate);
}
);

View File

@@ -23,8 +23,8 @@ export default class SalesByItemsReportService {
*/
get defaultQuery(): ISalesByItemsReportQuery {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
itemsIds: [],
numberFormat: {
precision: 2,

View File

@@ -31,8 +31,8 @@ export default class TransactionsByCustomersService
*/
get defaultQuery(): ITransactionsByCustomersFilter {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
numberFormat: {
precision: 2,
divideOn1000: false,

View File

@@ -32,7 +32,7 @@ export default class TransactionsByVendorsService
*/
get defaultQuery(): ITransactionsByVendorsFilter {
return {
fromDate: moment().format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
numberFormat: {
precision: 2,

View File

@@ -27,7 +27,7 @@ export default class TrialBalanceSheetService extends FinancialSheet {
get defaultQuery(): ITrialBalanceSheetQuery {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
numberFormat: {
divideOn1000: false,
negativeFormat: 'mines',

View File

@@ -9,13 +9,9 @@ import HasTenancyService from '@/services/Tenancy/TenancyService';
import UnitOfWork from '@/services/UnitOfWork';
import events from '@/subscribers/events';
import { ERRORS } from './constants';
import { ItemsValidators } from './ItemValidators';
@Service()
export class DeleteItem {
@Inject()
private validators: ItemsValidators;
@Inject()
private tenancy: HasTenancyService;

View File

@@ -1,5 +0,0 @@
export default class ItemsCostService {
}

View File

@@ -1,13 +1,13 @@
import { Service, Inject } from 'typedi';
import Knex from 'knex';
import { Knex } from 'knex';
import Bluebird from 'bluebird';
import { IVendorCreditAppliedBill } from '@/interfaces';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import Bluebird from 'bluebird';
@Service()
export default class ApplyVendorCreditSyncBills {
@Inject()
tenancy: HasTenancyService;
private tenancy: HasTenancyService;
/**
* Increment bills credited amount.
@@ -49,4 +49,4 @@ export default class ApplyVendorCreditSyncBills {
.findById(vendorCreditAppliedBill.billId)
.decrement('creditedAmount', vendorCreditAppliedBill.amount);
};
}
}

View File

@@ -18,11 +18,11 @@ function APAgingSummaryBodyJSX({
// #withCurrentOrganization
organizationName,
}) {
const { isLoading } = useAPAgingSummaryContext();
const { isAPAgingLoading } = useAPAgingSummaryContext();
return (
<FinancialReportBody>
{isLoading ? (
{isAPAgingLoading ? (
<FinancialSheetSkeleton />
) : (
<APAgingSummaryTable organizationName={organizationName} />

View File

@@ -20,7 +20,7 @@ export default function APAgingSummaryTable({
}) {
// AP aging summary report content.
const {
APAgingSummary: { tableRows },
APAgingSummary: { table, query },
isAPAgingLoading,
} = useAPAgingSummaryContext();
@@ -31,12 +31,12 @@ export default function APAgingSummaryTable({
<FinancialSheet
companyName={organizationName}
sheetType={intl.get('payable_aging_summary')}
asDate={new Date()}
asDate={query.as_date}
loading={isAPAgingLoading}
>
<APAgingSummaryDataTable
columns={columns}
data={tableRows}
data={table.rows}
rowClassNames={tableRowTypesToClassnames}
noInitialFetch={true}
sticky={true}
@@ -54,6 +54,24 @@ const APAgingSummaryDataTable = styled(ReportDataTable)`
padding-top: 0.32rem;
padding-bottom: 0.32rem;
}
&:not(.no-results) {
.td {
border-bottom: 0;
padding-top: 0.4rem;
padding-bottom: 0.4rem;
}
&:not(:first-child) .td {
border-top: 1px solid transparent;
}
&.row_type--total {
font-weight: 500;
.td {
border-top: 1px solid #bbb;
border-bottom: 3px double #333;
}
}
}
}
}
`;

View File

@@ -36,19 +36,23 @@ export const getAPAgingSummaryQuerySchema = () => {
.required()
.integer()
.positive()
.label('agingBeforeDays'),
.label('Aging days before')
.min(1)
.max(500),
agingPeriods: Yup.number()
.required()
.integer()
.positive()
.label('agingPeriods'),
.max(12)
.min(1)
.label('Aging periods'),
});
};
/**
* Parses the AP aging summary query state.
* @param locationQuery
* @returns
* @param locationQuery
* @returns
*/
const parseAPAgingSummaryQuery = (locationQuery) => {
const defaultQuery = getDefaultAPAgingSummaryQuery();

View File

@@ -1,57 +1,20 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import intl from 'react-intl-universal';
import { If, FormattedMessage as T } from '@/components';
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
import { getColumnWidth } from '@/utils';
import { If } from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
/**
* Retrieve AP aging summary columns.
*/
export const useAPAgingSummaryColumns = () => {
const {
APAgingSummary: { tableRows, columns },
APAgingSummary: { table },
} = useAPAgingSummaryContext();
const agingColumns = React.useMemo(() => {
return columns.map(
(agingColumn) =>
`${agingColumn.before_days} - ${
agingColumn.to_days || intl.get('and_over')
}`,
);
}, [columns]);
return useMemo(
() => [
{
Header: <T id={'vendor_name'} />,
accessor: 'name',
className: 'vendor_name',
width: 240,
sticky: 'left',
textOverview: true,
},
{
Header: <T id={'current'} />,
accessor: 'current',
className: 'current',
width: getColumnWidth(tableRows, `current`, { minWidth: 120 }),
},
...agingColumns.map((agingColumn, index) => ({
Header: agingColumn,
accessor: `aging-${index}`,
width: getColumnWidth(tableRows, `aging-${index}`, { minWidth: 120 }),
})),
{
Header: <T id={'total'} />,
accessor: 'total',
width: getColumnWidth(tableRows, 'total', { minWidth: 120 }),
},
],
[tableRows, agingColumns],
);
return agingSummaryDynamicColumns(table.columns, table.rows);
};
/**

View File

@@ -11,7 +11,10 @@ const ARAgingSummaryContext = createContext();
*/
function ARAgingSummaryProvider({ filter, ...props }) {
// Transformes the filter from to the url query.
const query = useMemo(() => transformFilterFormToQuery(filter), [filter]);
const requestQuery = useMemo(
() => transformFilterFormToQuery(filter),
[filter],
);
// A/R aging summary sheet context.
const {
@@ -19,11 +22,10 @@ function ARAgingSummaryProvider({ filter, ...props }) {
isLoading: isARAgingLoading,
isFetching: isARAgingFetching,
refetch,
} = useARAgingSummaryReport(query, { keepPreviousData: true });
} = useARAgingSummaryReport(requestQuery, { keepPreviousData: true });
const provider = {
ARAgingSummary,
isARAgingLoading,
isARAgingFetching,
refetch,

View File

@@ -19,7 +19,10 @@ export default function ReceivableAgingSummaryTable({
organizationName,
}) {
// AR aging summary report context.
const { ARAgingSummary, isARAgingLoading } = useARAgingSummaryContext();
const {
ARAgingSummary: { table, query },
isARAgingLoading,
} = useARAgingSummaryContext();
// AR aging summary columns.
const columns = useARAgingSummaryColumns();
@@ -28,12 +31,12 @@ export default function ReceivableAgingSummaryTable({
<FinancialSheet
companyName={organizationName}
sheetType={intl.get('receivable_aging_summary')}
asDate={new Date()}
asDate={query.as_date}
loading={isARAgingLoading}
>
<ARAgingSummaryDataTable
columns={columns}
data={ARAgingSummary.tableRows}
data={table.rows}
rowClassNames={tableRowTypesToClassnames}
noInitialFetch={true}
sticky={true}

View File

@@ -35,12 +35,16 @@ export const getARAgingSummaryQuerySchema = () => {
.required()
.integer()
.positive()
.label('agingDaysBefore'),
.label('Aging days before')
.min(1)
.max(500),
agingPeriods: Yup.number()
.required()
.integer()
.positive()
.label('agingPeriods'),
.max(12)
.min(1)
.label('Aging periods'),
});
};

View File

@@ -1,71 +1,20 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
import { If, FormattedMessage as T } from '@/components';
import { getColumnWidth } from '@/utils';
import { Align } from '@/constants';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
/**
* Retrieve AR aging summary columns.
*/
export const useARAgingSummaryColumns = () => {
const {
ARAgingSummary: { tableRows, columns },
ARAgingSummary: { table },
} = useARAgingSummaryContext();
const agingColumns = React.useMemo(() => {
return columns.map(
(agingColumn) =>
`${agingColumn.before_days} - ${
agingColumn.to_days || intl.get('and_over')
}`,
);
}, [columns]);
return React.useMemo(
() => [
{
Header: <T id={'customer_name'} />,
accessor: 'name',
className: 'customer_name',
sticky: 'left',
width: 240,
textOverview: true,
},
{
Header: <T id={'current'} />,
accessor: 'current',
className: 'current',
width: getColumnWidth(tableRows, `current`, {
minWidth: 120,
}),
align: Align.Right
},
...agingColumns.map((agingColumn, index) => ({
Header: agingColumn,
accessor: `aging-${index}`,
width: getColumnWidth(tableRows, `aging-${index}`, {
minWidth: 120,
}),
align: Align.Right
})),
{
Header: <T id={'total'} />,
id: 'total',
accessor: 'total',
className: 'total',
width: getColumnWidth(tableRows, 'total', {
minWidth: 120,
}),
align: Align.Right
},
],
[tableRows, agingColumns],
);
return agingSummaryDynamicColumns(table.columns, table.rows);
};
/**

View File

@@ -0,0 +1,74 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import * as R from 'ramda';
import { getColumnWidth } from '@/utils';
import { Align } from '@/constants';
const getTableCellValueAccessor = (index) => `cells[${index}].value`;
const contactNameAccessor = R.curry((data, column) => ({
key: column.key,
Header: column.label,
accessor: getTableCellValueAccessor(column.cell_index),
sticky: 'left',
width: 240,
textOverview: true,
}));
const currentAccessor = R.curry((data, column) => {
const accessor = getTableCellValueAccessor(column.cell_index);
return {
key: column.key,
Header: column.label,
accessor,
className: column.id,
width: getColumnWidth(data, accessor, { minWidth: 120 }),
align: Align.Right,
};
});
const totalAccessor = R.curry((data, column) => {
const accessor = getTableCellValueAccessor(column.cell_index);
return {
Header: column.label,
id: column.key,
accessor: getTableCellValueAccessor(column.cell_index),
className: column.key,
width: getColumnWidth(data, accessor, { minWidth: 120 }),
align: Align.Right,
};
});
const agingPeriodAccessor = R.curry((data, column) => {
const accessor = getTableCellValueAccessor(column.cell_index);
return {
Header: column.label,
id: `${column.key}-${column.cell_index}`,
accessor,
className: column.key,
width: getColumnWidth(data, accessor, { minWidth: 120 }),
align: Align.Right,
};
});
const dynamicColumnMapper = R.curry((data, column) => {
const totalAccessorColumn = totalAccessor(data);
const currentAccessorColumn = currentAccessor(data);
const customerNameAccessorColumn = contactNameAccessor(data);
const agingPeriodAccessorColumn = agingPeriodAccessor(data);
return R.compose(
R.when(R.pathEq(['key'], 'total'), totalAccessorColumn),
R.when(R.pathEq(['key'], 'current'), currentAccessorColumn),
R.when(R.pathEq(['key'], 'customer_name'), customerNameAccessorColumn),
R.when(R.pathEq(['key'], 'vendor_name'), customerNameAccessorColumn),
R.when(R.pathEq(['key'], 'aging_period'), agingPeriodAccessorColumn),
)(column);
});
export const agingSummaryDynamicColumns = (columns, data) => {
return R.map(dynamicColumnMapper(data), columns);
};

View File

@@ -15,7 +15,7 @@ import { useAppQueryString } from '@/hooks';
*/
export const getDefaultBalanceSheetQuery = () => ({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
basis: 'cash',
displayColumnsType: 'total',
filterByOption: 'without-zero-balance',

View File

@@ -12,7 +12,7 @@ import { useAppQueryString } from '@/hooks';
export const getDefaultCashFlowSheetQuery = () => {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
basis: 'cash',
displayColumnsType: 'total',
filterByOption: 'with-transactions',

View File

@@ -18,7 +18,7 @@ export default function CustomersBalanceSummaryTable({
companyName,
}) {
const {
CustomerBalanceSummary: { table },
CustomerBalanceSummary: { table, query },
} = useCustomersBalanceSummaryContext();
// Retrieves the customers summary columns.
@@ -28,7 +28,7 @@ export default function CustomersBalanceSummaryTable({
<FinancialSheet
companyName={companyName}
sheetType={intl.get('customers_balance_summary')}
asDate={new Date()}
asDate={query.as_date}
>
<CustomerBalanceDataTable
columns={columns}

View File

@@ -13,6 +13,7 @@ import { CustomersTransactionsBody } from './CustomersTransactionsBody';
import { CustomersTransactionsProvider } from './CustomersTransactionsProvider';
import { compose } from '@/utils';
import { useCustomersTransactionsQuery } from './_utils';
/**
* Customers transactions.
@@ -22,11 +23,7 @@ function CustomersTransactions({
toggleCustomersTransactionsFilterDrawer,
}) {
// filter
const [filter, setFilter] = useState({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
filterByOption: 'with-transactions',
});
const [filter, setFilter] = useCustomersTransactionsQuery();
const handleFilterSubmit = (filter) => {
const _filter = {

View File

@@ -14,7 +14,7 @@ function CustomersTransactionsProvider({ filter, ...props }) {
filter,
]);
// fetches the customers transactions.
// Fetches the customers transactions.
const {
data: customersTransactions,
isFetching: isCustomersTransactionsFetching,

View File

@@ -1,6 +1,11 @@
// @ts-nocheck
import * as Yup from 'yup';
import intl from 'react-intl-universal';
import moment from 'moment';
import { transformToForm } from '@/utils';
import { castArray } from 'lodash';
import { useMemo } from 'react';
import { useAppQueryString } from '@/hooks';
export const getCustomersTransactionsQuerySchema = () => {
return Yup.object().shape({
@@ -13,7 +18,31 @@ export const getCustomersTransactionsQuerySchema = () => {
};
export const getCustomersTransactionsDefaultQuery = () => ({
fromDate: moment().toDate(),
toDate: moment().toDate(),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
customersIds: [],
filterByOption: 'with-transactions',
});
const parseCustomersTransactionsQuery = (query) => {
const defaultQuery = getCustomersTransactionsDefaultQuery();
const transformedQuery = {
...defaultQuery,
...transformToForm(query, defaultQuery),
};
return {
...transformedQuery,
customersIds: castArray(transformedQuery.customersIds),
};
};
export const useCustomersTransactionsQuery = () => {
const [locationQuery, setLocationQuery] = useAppQueryString();
const query = useMemo(
() => parseCustomersTransactionsQuery(locationQuery),
[locationQuery],
);
return [query, setLocationQuery];
};

View File

@@ -28,8 +28,8 @@ export const filterAccountsOptions = [
* Retrieves the default general ledger query.
*/
export const getDefaultGeneralLedgerQuery = () => ({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
basis: 'accrual',
filterByOption: 'with-transactions',
branchesIds: [],

View File

@@ -35,8 +35,8 @@ export function InventoryItemDetailsTable({
companyName={companyName}
sheetType={intl.get('inventory_item_details')}
loading={isInventoryItemDetailsLoading}
fromDate={query.from_date}
toDate={query.to_date}
fromDate={query.fromDate}
toDate={query.toDate}
fullWidth={true}
>
<InventoryItemDetailsDataTable

View File

@@ -31,9 +31,6 @@ const numericColumn = R.curry((data, index, column) => ({
align: Align.Right,
}));
/**
* columns mapper.
*/
const columnsMapper = R.curry((data, index, column) => ({
id: column.key,
key: column.key,

View File

@@ -12,8 +12,8 @@ import { transformToForm } from '@/utils';
* Retrieves inventory item details default query.
*/
export const getInventoryItemDetailsDefaultQuery = () => ({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
itemsIds: [],
warehousesIds: [],
branchesIds: [],

View File

@@ -19,7 +19,7 @@ export default function InventoryValuationTable({
}) {
// inventory valuation context.
const {
inventoryValuation: { tableRows },
inventoryValuation: { tableRows, query },
isLoading,
} = useInventoryValuationContext();
@@ -30,7 +30,7 @@ export default function InventoryValuationTable({
<InventoryValuationSheet
companyName={companyName}
sheetType={intl.get('inventory_valuation')}
asDate={new Date()}
asDate={query.as_date}
loading={isLoading}
>
<InventoryValuationDataTable

View File

@@ -20,7 +20,7 @@ export const getInventoryValuationQuerySchema = () => {
* Retrieves the inventory valuation sheet default query.
*/
export const getInventoryValuationQuery = () => ({
asDate: moment().endOf('day').format('YYYY-MM-DD'),
asDate: moment().format('YYYY-MM-DD'),
filterByOption: 'with-transactions',
itemsIds: [],
branchesIds: [],

View File

@@ -11,17 +11,16 @@ import { transformToForm } from '@/utils';
*/
export const getDefaultJournalQuery = () => {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
basis: 'accrual',
};
};
/**
* Parses balance sheet query.
*/
const parseJournalQuery = (locationQuery) => {
const parseJournalQuery = (locationQuery) => {
const defaultQuery = getDefaultJournalQuery();
return {

View File

@@ -23,7 +23,7 @@ export default function ProfitLossSheetTable({
} = useProfitLossSheetContext();
// Retrieves the profit/loss table columns.
const tableColumns = useProfitLossSheetColumns();
const columns = useProfitLossSheetColumns();
// Retrieve default expanded rows of balance sheet.
const expandedRows = React.useMemo(
@@ -40,7 +40,7 @@ export default function ProfitLossSheetTable({
basis={query.basis}
>
<ProfitLossDataTable
columns={tableColumns}
columns={columns}
data={table.rows}
noInitialFetch={true}
expanded={expandedRows}

View File

@@ -16,7 +16,7 @@ import { castArray } from 'lodash';
export const getDefaultProfitLossQuery = () => ({
basis: 'cash',
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
displayColumnsType: 'total',
filterByOption: 'with-transactions',

View File

@@ -11,8 +11,8 @@ import { castArray } from 'lodash';
* Retrieves the purchases by items query.
*/
export const getDefaultPurchasesByItemsQuery = () => ({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
filterByOption: 'with-transactions',
itemsIds: [],
});

View File

@@ -25,8 +25,8 @@ export const getSalesByItemsQueryShema = () => {
* Retrieves the default query.
*/
export const getDefaultSalesByItemsQuery = () => ({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
filterByOption: 'with-transactions',
itemsIds: [],
});

View File

@@ -12,7 +12,7 @@ import { transformToForm } from '@/utils';
export function getDefaultTrialBalanceQuery() {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
basis: 'accrual',
filterByOption: 'with-transactions',
branchesIds: [],

View File

@@ -9,7 +9,6 @@ import { tableRowTypesToClassnames } from '@/utils';
import { useVendorsBalanceColumns } from './components';
import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
/**
* Vendors balance summary table.
*/
@@ -18,7 +17,7 @@ export default function VendorsBalanceSummaryTable({
organizationName,
}) {
const {
VendorBalanceSummary: { table },
VendorBalanceSummary: { table, query },
} = useVendorsBalanceSummaryContext();
// vendors balance summary columns.
@@ -28,7 +27,7 @@ export default function VendorsBalanceSummaryTable({
<VendorBalanceFinancialSheet
companyName={organizationName}
sheetType={intl.get('vendors_balance_summary')}
asDate={new Date()}
asDate={query.as_date}
>
<VendorBalanceDataTable
columns={columns}

View File

@@ -13,6 +13,7 @@ import VendorsTransactionsActionsBar from './VendorsTransactionsActionsBar';
import withVendorsTransactionsActions from './withVendorsTransactionsActions';
import { compose } from '@/utils';
import { useVendorsTransactionsQuery } from './_utils';
/**
* Vendors transactions.
@@ -22,11 +23,7 @@ function VendorsTransactions({
toggleVendorsTransactionsFilterDrawer,
}) {
// filter
const [filter, setFilter] = useState({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
filterByOption: 'with-transactions',
});
const [filter, setFilter] = useVendorsTransactionsQuery();
const handleFilterSubmit = (filter) => {
const _filter = {

View File

@@ -1,6 +1,10 @@
// @ts-nocheck
import * as Yup from 'yup';
import intl from 'react-intl-universal';
import moment from 'moment';
import { useMemo } from 'react';
import { transformToForm } from '@/utils';
import { useAppQueryString } from '@/hooks';
/**
* The validation schema of vendors transactions.
@@ -19,7 +23,35 @@ export const getVendorTransactionsQuerySchema = () => {
* Retrieves the default query of vendors transactions.
*/
export const getVendorsTransactionsDefaultQuery = () => ({
fromDate: moment().toDate(),
toDate: moment().toDate(),
fromDate: moment().startOf('month').format('YYYY-MM-DD'),
toDate: moment().format('YYYY-MM-DD'),
vendorsIds: [],
});
/**
* Parses the query of vendors transactions.
*/
const parseVendorsTransactionsQuery = (query) => {
const defaultQuery = getVendorsTransactionsDefaultQuery();
const transformed = {
...defaultQuery,
...transformToForm(query, defaultQuery),
};
return {
...transformed,
vendorsIds: transformed.vendorsIds ? transformed.vendorsIds : [],
};
};
/**
* Retrieves the query of vendors transactions.
*/
export const useVendorsTransactionsQuery = () => {
const [locationQuery, setLocationQuery] = useAppQueryString();
const query = useMemo(
() => parseVendorsTransactionsQuery(locationQuery),
[locationQuery],
);
return [query, setLocationQuery];
};

View File

@@ -138,26 +138,12 @@ export function useARAgingSummaryReport(query, props) {
method: 'get',
url: '/financial_statements/receivable_aging_summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => ({
columns: res.data.columns,
data: res.data.data,
query: res.data.query,
tableRows: ARAgingSummaryTableRowsMapper({
customers: res.data.data.customers,
total: res.data.data.total,
columns: res.data.columns,
}),
}),
defaultData: {
data: {
customers: [],
total: {},
},
columns: [],
tableRows: [],
},
select: (res) => res.data,
...props,
},
);
@@ -173,26 +159,12 @@ export function useAPAgingSummaryReport(query, props) {
method: 'get',
url: '/financial_statements/payable_aging_summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => ({
columns: res.data.columns,
data: res.data.data,
query: res.data.query,
tableRows: APAgingSummaryTableRowsMapper({
vendors: res.data.data.vendors,
total: res.data.data.total,
columns: res.data.columns,
}),
}),
defaultData: {
data: {
vendors: [],
total: {},
},
columns: [],
tableRows: [],
},
select: (res) => res.data,
...props,
},
);