mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
fix: value property in inventory item details.
This commit is contained in:
@@ -59,11 +59,12 @@ export default class InventoryDetailsController extends BaseController {
|
||||
* @param {ICashFlowStatement} cashFlow -
|
||||
*/
|
||||
private transformJsonResponse(inventoryDetails) {
|
||||
const { data, query } = inventoryDetails;
|
||||
const { data, query, meta } = inventoryDetails;
|
||||
|
||||
return {
|
||||
data: this.transfromToResponse(data),
|
||||
meta: this.transfromToResponse(query),
|
||||
query: this.transfromToResponse(query),
|
||||
meta: this.transfromToResponse(meta),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,7 +79,8 @@ export default class InventoryDetailsController extends BaseController {
|
||||
data: inventoryDetailsTable.tableData(),
|
||||
columns: inventoryDetailsTable.tableColumns(),
|
||||
},
|
||||
meta: this.transfromToResponse(inventoryDetails.query),
|
||||
query: this.transfromToResponse(inventoryDetails.query),
|
||||
meta: this.transfromToResponse(inventoryDetails.meta),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -58,8 +58,9 @@ export interface IInventoryDetailsItemTransaction {
|
||||
valueMovement: IInventoryDetailsNumber;
|
||||
|
||||
quantity: IInventoryDetailsNumber;
|
||||
value: IInventoryDetailsNumber;
|
||||
total: IInventoryDetailsNumber;
|
||||
cost: IInventoryDetailsNumber;
|
||||
value: IInventoryDetailsNumber;
|
||||
profitMargin: IInventoryDetailsNumber;
|
||||
|
||||
rate: IInventoryDetailsNumber;
|
||||
@@ -74,3 +75,16 @@ export type IInventoryDetailsNode =
|
||||
| IInventoryDetailsItem
|
||||
| IInventoryDetailsItemTransaction;
|
||||
export type IInventoryDetailsData = IInventoryDetailsItem[];
|
||||
|
||||
|
||||
export interface IInventoryItemDetailMeta {
|
||||
isCostComputeRunning: boolean;
|
||||
organizationName: string;
|
||||
baseCurrency: string;
|
||||
}
|
||||
|
||||
export interface IInvetoryItemDetailDOO {
|
||||
data: IInventoryDetailsData;
|
||||
query: IInventoryDetailsQuery;
|
||||
meta: IInventoryItemDetailMeta;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as R from 'ramda';
|
||||
import { defaultTo, sumBy, get } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
IInventoryDetailsQuery,
|
||||
IItem,
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
import FinancialSheet from '../FinancialSheet';
|
||||
import { transformToMapBy, transformToMapKeyValue } from 'utils';
|
||||
import { filterDeep } from 'utils/deepdash';
|
||||
import moment from 'moment';
|
||||
|
||||
const MAP_CONFIG = { childrenPath: 'children', pathFormat: 'array' };
|
||||
|
||||
@@ -159,7 +159,8 @@ export default class InventoryDetails extends FinancialSheet {
|
||||
const initial = this.getNumberMeta(0);
|
||||
|
||||
const mapAccumAppender = (a, b) => {
|
||||
const total = a.runningValuation.number + b.valueMovement.number;
|
||||
const adjusmtent = b.direction === 'OUT' ? -1 : 1;
|
||||
const total = a.runningValuation.number + b.cost.number * adjusmtent;
|
||||
const totalMeta = this.getNumberMeta(total, { excerptZero: false });
|
||||
const accum = { ...b, runningValuation: totalMeta };
|
||||
|
||||
@@ -182,19 +183,22 @@ export default class InventoryDetails extends FinancialSheet {
|
||||
item: IItem,
|
||||
transaction: IInventoryTransaction
|
||||
): IInventoryDetailsItemTransaction {
|
||||
const value = transaction.quantity * transaction.rate;
|
||||
const total = transaction.quantity * transaction.rate;
|
||||
const amountMovement = R.curry(this.adjustAmountMovement)(
|
||||
transaction.direction
|
||||
);
|
||||
// Quantity movement.
|
||||
const quantityMovement = amountMovement(transaction.quantity);
|
||||
const valueMovement = amountMovement(value);
|
||||
const cost = defaultTo(transaction?.costLotAggregated.cost, 0);
|
||||
|
||||
// Profit margin.
|
||||
const profitMargin = Math.max(
|
||||
value - transaction.costLotAggregated.cost,
|
||||
0
|
||||
);
|
||||
// Profit margin.
|
||||
const profitMargin = total - cost;
|
||||
|
||||
// Value from computed cost in `OUT` or from total sell price in `IN` transaction.
|
||||
const value = transaction.direction === 'OUT' ? cost : total;
|
||||
|
||||
// Value movement depends on transaction direction.
|
||||
const valueMovement = amountMovement(value);
|
||||
|
||||
return {
|
||||
nodeType: INodeTypes.TRANSACTION,
|
||||
@@ -207,10 +211,11 @@ export default class InventoryDetails extends FinancialSheet {
|
||||
valueMovement: this.getNumberMeta(valueMovement),
|
||||
|
||||
quantity: this.getNumberMeta(transaction.quantity),
|
||||
value: this.getNumberMeta(value),
|
||||
total: this.getNumberMeta(total),
|
||||
|
||||
rate: this.getNumberMeta(transaction.rate),
|
||||
cost: this.getNumberMeta(transaction.costLotAggregated.cost),
|
||||
value: this.getNumberMeta(value),
|
||||
|
||||
profitMargin: this.getNumberMeta(profitMargin),
|
||||
|
||||
@@ -314,14 +319,12 @@ export default class InventoryDetails extends FinancialSheet {
|
||||
const value = sumBy(transactions, 'valueMovement.number');
|
||||
const quantity = sumBy(transactions, 'quantityMovement.number');
|
||||
const profitMargin = sumBy(transactions, 'profitMargin.number');
|
||||
const cost = sumBy(transactions, 'cost.number');
|
||||
|
||||
return {
|
||||
nodeType: INodeTypes.CLOSING_ENTRY,
|
||||
date: this.getDateMeta(this.query.toDate),
|
||||
quantity: this.getTotalNumberMeta(quantity),
|
||||
value: this.getTotalNumberMeta(value),
|
||||
cost: this.getTotalNumberMeta(cost),
|
||||
profitMargin: this.getTotalNumberMeta(profitMargin),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { Inject } from 'typedi';
|
||||
import { raw } from 'objection';
|
||||
import moment from 'moment';
|
||||
import { IItem, IInventoryDetailsQuery, IInventoryTransaction } from 'interfaces';
|
||||
import {
|
||||
IItem,
|
||||
IInventoryDetailsQuery,
|
||||
IInventoryTransaction,
|
||||
} from 'interfaces';
|
||||
import HasTenancyService from 'services/Tenancy/TenancyService';
|
||||
|
||||
export default class InventoryDetailsRepository {
|
||||
@@ -10,7 +14,7 @@ export default class InventoryDetailsRepository {
|
||||
|
||||
/**
|
||||
* Retrieve inventory items.
|
||||
* @param {number} tenantId -
|
||||
* @param {number} tenantId -
|
||||
* @returns {Promise<IItem>}
|
||||
*/
|
||||
public getInventoryItems(tenantId: number): Promise<IItem[]> {
|
||||
@@ -47,6 +51,7 @@ export default class InventoryDetailsRepository {
|
||||
raw("IF(`DIRECTION` = 'OUT', `QUANTITY` * `RATE`, 0) as 'VALUE_OUT'")
|
||||
)
|
||||
.modify('filterDateRange', null, openingBalanceDate)
|
||||
.orderBy('date', 'ASC')
|
||||
.as('inventory_transactions');
|
||||
|
||||
const openingBalanceTransactions = await InventoryTransaction.query()
|
||||
@@ -79,6 +84,7 @@ export default class InventoryDetailsRepository {
|
||||
|
||||
const inventoryTransactions = InventoryTransaction.query()
|
||||
.modify('filterDateRange', filter.fromDate, filter.toDate)
|
||||
.orderBy('date', 'ASC')
|
||||
.withGraphFetched('meta')
|
||||
.withGraphFetched('costLotAggregated');
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import moment from 'moment';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { raw } from 'objection';
|
||||
import { IInventoryDetailsQuery, IInventoryTransaction } from 'interfaces';
|
||||
import {
|
||||
IInventoryDetailsQuery,
|
||||
IInvetoryItemDetailDOO,
|
||||
IInventoryItemDetailMeta,
|
||||
} from 'interfaces';
|
||||
import TenancyService from 'services/Tenancy/TenancyService';
|
||||
import InventoryDetails from './InventoryDetails';
|
||||
import FinancialSheet from '../FinancialSheet';
|
||||
import InventoryDetailsRepository from './InventoryDetailsRepository';
|
||||
import InventoryService from 'services/Inventory/Inventory';
|
||||
import { parseBoolean } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class InventoryDetailsService extends FinancialSheet {
|
||||
@@ -15,11 +20,14 @@ export default class InventoryDetailsService extends FinancialSheet {
|
||||
@Inject()
|
||||
reportRepo: InventoryDetailsRepository;
|
||||
|
||||
@Inject()
|
||||
inventoryService: InventoryService;
|
||||
|
||||
/**
|
||||
* Defaults balance sheet filter query.
|
||||
* @return {IBalanceSheetQuery}
|
||||
*/
|
||||
get defaultQuery(): IInventoryDetailsQuery {
|
||||
private get defaultQuery(): IInventoryDetailsQuery {
|
||||
return {
|
||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||
@@ -34,15 +42,43 @@ export default class InventoryDetailsService extends FinancialSheet {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the balance sheet meta.
|
||||
* @param {number} tenantId -
|
||||
* @returns {IInventoryItemDetailMeta}
|
||||
*/
|
||||
private reportMetadata(tenantId: number): IInventoryItemDetailMeta {
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
|
||||
const isCostComputeRunning =
|
||||
this.inventoryService.isItemsCostComputeRunning(tenantId);
|
||||
|
||||
const organizationName = settings.get({
|
||||
group: 'organization',
|
||||
key: 'name',
|
||||
});
|
||||
const baseCurrency = settings.get({
|
||||
group: 'organization',
|
||||
key: 'base_currency',
|
||||
});
|
||||
|
||||
return {
|
||||
isCostComputeRunning: parseBoolean(isCostComputeRunning, false),
|
||||
organizationName,
|
||||
baseCurrency,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the inventory details report data.
|
||||
* @param {number} tenantId -
|
||||
* @param {IInventoryDetailsQuery} query -
|
||||
* @return {Promise<IInvetoryItemDetailDOO>}
|
||||
*/
|
||||
public async inventoryDetails(
|
||||
tenantId: number,
|
||||
query: IInventoryDetailsQuery
|
||||
): Promise<any> {
|
||||
): Promise<IInvetoryItemDetailDOO> {
|
||||
// Settings tenant service.
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
const baseCurrency = settings.get({
|
||||
@@ -76,6 +112,8 @@ export default class InventoryDetailsService extends FinancialSheet {
|
||||
|
||||
return {
|
||||
data: inventoryDetailsInstance.reportData(),
|
||||
query: filter,
|
||||
meta: this.reportMetadata(tenantId),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ const MAP_CONFIG = { childrenPath: 'children', pathFormat: 'array' };
|
||||
|
||||
export default class InventoryDetailsTable {
|
||||
/**
|
||||
* Constructor methiod.
|
||||
* @param {ICashFlowStatement} reportStatement
|
||||
* Constructor method.
|
||||
* @param {ICashFlowStatement} reportStatement - Report statement.
|
||||
*/
|
||||
constructor(reportStatement) {
|
||||
this.report = reportStatement;
|
||||
@@ -59,8 +59,8 @@ export default class InventoryDetailsTable {
|
||||
accessor: 'quantityMovement.formattedNumber',
|
||||
},
|
||||
{ key: 'rate', accessor: 'rate.formattedNumber' },
|
||||
{ key: 'value_movement', accessor: 'valueMovement.formattedNumber' },
|
||||
{ key: 'cost', accessor: 'cost.formattedNumber' },
|
||||
{ key: 'total', accessor: 'total.formattedNumber' },
|
||||
{ key: 'value', accessor: 'valueMovement.formattedNumber' },
|
||||
{ key: 'profit_margin', accessor: 'profitMargin.formattedNumber' },
|
||||
{ key: 'running_quantity', accessor: 'runningQuantity.formattedNumber' },
|
||||
{ key: 'running_valuation', accessor: 'runningValuation.formattedNumber' },
|
||||
@@ -82,9 +82,9 @@ export default class InventoryDetailsTable {
|
||||
{ key: 'empty' },
|
||||
{ key: 'quantity', accessor: 'quantity.formattedNumber' },
|
||||
{ key: 'empty' },
|
||||
{ key: 'empty' },
|
||||
{ key: 'value', accessor: 'value.formattedNumber' },
|
||||
];
|
||||
|
||||
return tableRowMapper(transaction, columns, {
|
||||
rowTypes: [IROW_TYPE.OPENING_ENTRY],
|
||||
});
|
||||
@@ -102,8 +102,8 @@ export default class InventoryDetailsTable {
|
||||
{ key: 'empty' },
|
||||
{ key: 'quantity', accessor: 'quantity.formattedNumber' },
|
||||
{ key: 'empty' },
|
||||
{ key: 'empty' },
|
||||
{ key: 'value', accessor: 'value.formattedNumber' },
|
||||
{ key: 'cost', accessor: 'cost.formattedNumber' },
|
||||
{ key: 'profitMargin', accessor: 'profitMargin.formattedNumber' },
|
||||
];
|
||||
|
||||
@@ -171,13 +171,13 @@ export default class InventoryDetailsTable {
|
||||
{ key: 'date', label: 'Date' },
|
||||
{ key: 'transaction_type', label: 'Transaction type' },
|
||||
{ key: 'transaction_id', label: 'Transaction #' },
|
||||
{ key: 'quantity_movement', label: 'Quantity' },
|
||||
{ key: 'quantity', label: 'Quantity' },
|
||||
{ key: 'rate', label: 'Rate' },
|
||||
{ key: 'value_movement', label: 'Value' },
|
||||
{ key: 'cost', label: 'Cost' },
|
||||
{ key: 'total', label: 'Total' },
|
||||
{ key: 'value', label: 'Value' },
|
||||
{ key: 'profit_margin', label: 'Profit Margin' },
|
||||
{ key: 'quantity_on_hand', label: 'Running quantity' },
|
||||
{ key: 'value', label: 'Running Value' },
|
||||
{ key: 'running_quantity', label: 'Running quantity' },
|
||||
{ key: 'running_value', label: 'Running Value' },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
ITransactionsByContactsFilter,
|
||||
IContact,
|
||||
ILedger,
|
||||
ILedgerEntry,
|
||||
} from 'interfaces';
|
||||
import FinancialSheet from '../FinancialSheet';
|
||||
|
||||
@@ -20,20 +21,20 @@ export default class TransactionsByContact extends FinancialSheet {
|
||||
* @return {Omit<ITransactionsByContactsTransaction, 'runningBalance'>}
|
||||
*/
|
||||
protected contactTransactionMapper(
|
||||
transaction
|
||||
entry: ILedgerEntry,
|
||||
): Omit<ITransactionsByContactsTransaction, 'runningBalance'> {
|
||||
const account = this.accountsGraph.getNodeData(transaction.accountId);
|
||||
const account = this.accountsGraph.getNodeData(entry.accountId);
|
||||
const currencyCode = 'USD';
|
||||
|
||||
return {
|
||||
credit: this.getContactAmount(transaction.credit, currencyCode),
|
||||
debit: this.getContactAmount(transaction.debit, currencyCode),
|
||||
credit: this.getContactAmount(entry.credit, currencyCode),
|
||||
debit: this.getContactAmount(entry.debit, currencyCode),
|
||||
accountName: account.name,
|
||||
currencyCode: 'USD',
|
||||
transactionNumber: transaction.transactionNumber,
|
||||
transactionType: transaction.transactionType,
|
||||
date: transaction.date,
|
||||
createdAt: transaction.createdAt,
|
||||
transactionNumber: entry.transactionNumber,
|
||||
transactionType: entry.referenceTypeFormatted,
|
||||
date: entry.date,
|
||||
createdAt: entry.createdAt,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user