fix(Currencies): Currency code in services.

This commit is contained in:
a.bouhuolia
2021-03-30 16:18:57 +02:00
parent 78d4b56e92
commit 1ba67f183b
37 changed files with 160 additions and 73 deletions

View File

@@ -14,6 +14,7 @@ import classNames from 'classnames';
import { CLASSES } from 'common/classes'; import { CLASSES } from 'common/classes';
import { DateInput } from '@blueprintjs/datetime'; import { DateInput } from '@blueprintjs/datetime';
import { FieldRequiredHint, Col, Row } from 'components'; import { FieldRequiredHint, Col, Row } from 'components';
import { ACCOUNT_TYPE } from 'common/accountTypes';
import { import {
AccountsSuggestField, AccountsSuggestField,
InputPrependText, InputPrependText,
@@ -164,6 +165,11 @@ export default function QuickPaymentMadeFormFields() {
id: 'select_account', id: 'select_account',
}), }),
}} }}
filterByTypes={[
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]}
/> />
</FormGroup> </FormGroup>
)} )}

View File

@@ -20,7 +20,7 @@ import {
MoneyInputGroup, MoneyInputGroup,
Icon, Icon,
} from 'components'; } from 'components';
import { ACCOUNT_TYPE } from 'common/accountTypes';
import { import {
inputIntent, inputIntent,
momentFormatter, momentFormatter,
@@ -166,6 +166,11 @@ export default function QuickPaymentReceiveFormFields({}) {
id: 'select_account', id: 'select_account',
}), }),
}} }}
filterByTypes={[
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]}
/> />
</FormGroup> </FormGroup>
)} )}

View File

@@ -15,16 +15,16 @@ const ExpenseFormPageContext = createContext();
* Accounts chart data provider. * Accounts chart data provider.
*/ */
function ExpenseFormPageProvider({ expenseId, ...props }) { function ExpenseFormPageProvider({ expenseId, ...props }) {
const { data: currencies, isFetching: isCurrenciesLoading } = useCurrencies(); const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
// Fetches customers list. // Fetches customers list.
const { const {
data: { customers }, data: { customers },
isFetching: isFieldsLoading, isLoading: isCustomersLoading,
} = useCustomers(); } = useCustomers();
// Fetch the expense details. // Fetch the expense details.
const { data: expense, isFetching: isExpenseLoading } = useExpense( const { data: expense, isLoading: isExpenseLoading } = useExpense(
expenseId, expenseId,
{ {
enabled: !!expenseId, enabled: !!expenseId,
@@ -32,7 +32,7 @@ function ExpenseFormPageProvider({ expenseId, ...props }) {
); );
// Fetch accounts list. // Fetch accounts list.
const { data: accounts, isFetching: isAccountsLoading } = useAccounts(); const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
// Create and edit expense mutate. // Create and edit expense mutate.
const { mutateAsync: createExpenseMutate } = useCreateExpense(); const { mutateAsync: createExpenseMutate } = useCreateExpense();
@@ -57,7 +57,7 @@ function ExpenseFormPageProvider({ expenseId, ...props }) {
isCurrenciesLoading, isCurrenciesLoading,
isExpenseLoading, isExpenseLoading,
isFieldsLoading, isCustomersLoading,
isAccountsLoading, isAccountsLoading,
createExpenseMutate, createExpenseMutate,
@@ -70,7 +70,7 @@ function ExpenseFormPageProvider({ expenseId, ...props }) {
loading={ loading={
isCurrenciesLoading || isCurrenciesLoading ||
isExpenseLoading || isExpenseLoading ||
isFieldsLoading || isCustomersLoading ||
isAccountsLoading isAccountsLoading
} }
name={'expense-form'} name={'expense-form'}

View File

@@ -56,6 +56,7 @@ export default function InventoryValuationTable({
expandColumnSpace={1} expandColumnSpace={1}
sticky={true} sticky={true}
rowClassNames={rowClassNames} rowClassNames={rowClassNames}
noResults={'There were no inventory transactions during the selected date range.'}
/> />
</FinancialSheet> </FinancialSheet>
); );

View File

@@ -29,7 +29,7 @@ export const useJournalTableColumns = () => {
}, },
{ {
Header: formatMessage({ id: 'num' }), Header: formatMessage({ id: 'num' }),
accessor: 'reference_id', accessor: 'transaction_number',
className: 'reference_id', className: 'reference_id',
width: 70, width: 70,
}, },

View File

@@ -55,6 +55,7 @@ export default function PurchasesByItemsTable({ companyName }) {
expandColumnSpace={1} expandColumnSpace={1}
sticky={true} sticky={true}
rowClassNames={rowClassNames} rowClassNames={rowClassNames}
noResults={'There were no purchases during the selected date range.'}
/> />
</FinancialSheet> </FinancialSheet>
); );

View File

@@ -53,6 +53,7 @@ export default function SalesByItemsTable({ companyName }) {
expandColumnSpace={1} expandColumnSpace={1}
sticky={true} sticky={true}
rowClassNames={rowClassNames} rowClassNames={rowClassNames}
noResults={'There were no sales during the selected date range.'}
/> />
</FinancialSheet> </FinancialSheet>
); );

View File

@@ -25,6 +25,7 @@ import {
} from 'components'; } from 'components';
import withSettings from 'containers/Settings/withSettings'; import withSettings from 'containers/Settings/withSettings';
import { usePaymentMadeFormContext } from './PaymentMadeFormProvider'; import { usePaymentMadeFormContext } from './PaymentMadeFormProvider';
import { ACCOUNT_TYPE } from 'common/accountTypes';
import { import {
momentFormatter, momentFormatter,
tansformDateValue, tansformDateValue,
@@ -205,6 +206,11 @@ function PaymentMadeFormHeaderFields({ baseCurrency }) {
}} }}
defaultSelectText={<T id={'select_payment_account'} />} defaultSelectText={<T id={'select_payment_account'} />}
selectedAccountId={value} selectedAccountId={value}
filterByTypes={[
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]}
/> />
</FormGroup> </FormGroup>
)} )}

View File

@@ -33,6 +33,7 @@ import {
Money, Money,
} from 'components'; } from 'components';
import { usePaymentReceiveFormContext } from './PaymentReceiveFormProvider'; import { usePaymentReceiveFormContext } from './PaymentReceiveFormProvider';
import { ACCOUNT_TYPE } from 'common/accountTypes';
import withDialogActions from 'containers/Dialog/withDialogActions'; import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettings from 'containers/Settings/withSettings'; import withSettings from 'containers/Settings/withSettings';
@@ -263,6 +264,11 @@ function PaymentReceiveHeaderFields({
}} }}
defaultSelectText={<T id={'select_deposit_account'} />} defaultSelectText={<T id={'select_deposit_account'} />}
selectedAccountId={value} selectedAccountId={value}
filterByTypes={[
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]}
/> />
</FormGroup> </FormGroup>
)} )}

View File

@@ -19,6 +19,7 @@ import {
} from 'components'; } from 'components';
import withSettings from 'containers/Settings/withSettings'; import withSettings from 'containers/Settings/withSettings';
import withDialogActions from 'containers/Dialog/withDialogActions'; import withDialogActions from 'containers/Dialog/withDialogActions';
import { ACCOUNT_TYPE } from 'common/accountTypes';
import { import {
momentFormatter, momentFormatter,
compose, compose,
@@ -113,8 +114,12 @@ function ReceiptFormHeader({
}} }}
defaultSelectText={<T id={'select_deposit_account'} />} defaultSelectText={<T id={'select_deposit_account'} />}
selectedAccountId={value} selectedAccountId={value}
// filterByTypes={['current_asset']}
popoverFill={true} popoverFill={true}
filterByTypes={[
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]}
/> />
</FormGroup> </FormGroup>
)} )}

View File

@@ -26,7 +26,7 @@
font-weight: 500; font-weight: 500;
.td{ .td{
border-top: 1px solid #333; border-top: 1px solid #BBB;
border-bottom: 3px double #333; border-bottom: 3px double #333;
} }
} }

View File

@@ -26,7 +26,7 @@
font-weight: 500; font-weight: 500;
.td{ .td{
border-top: 1px solid #333; border-top: 1px solid #BBB;
border-bottom: 3px double #333; border-bottom: 3px double #333;
} }
} }

View File

@@ -19,7 +19,7 @@
padding-bottom: 0.4rem; padding-bottom: 0.4rem;
} }
.tr.row_type--total .td { .tr.row_type--total .td {
border-top: 1px solid #000; border-top: 1px solid #BBB;
font-weight: 500; font-weight: 500;
border-bottom: 3px double #000; border-bottom: 3px double #000;
} }

View File

@@ -22,7 +22,7 @@
border-top-color: #000; border-top-color: #000;
} }
.tr.row_type--total .td{ .tr.row_type--total .td{
border-top: 1px solid #000; border-top: 1px solid #bbb;
font-weight: 500; font-weight: 500;
border-bottom: 3px double #000; border-bottom: 3px double #000;
} }

View File

@@ -16,6 +16,7 @@ exports.up = function (knex) {
table.integer('transaction_id').unsigned().index(); table.integer('transaction_id').unsigned().index();
table.integer('entry_id').unsigned().index(); table.integer('entry_id').unsigned().index();
table.integer('cost_account_id').unsigned();
table.timestamps(); table.timestamps();
}); });
}; };

View File

@@ -14,6 +14,8 @@ exports.up = function (knex) {
table.integer('transaction_id').unsigned().index(); table.integer('transaction_id').unsigned().index();
table.integer('entry_id').unsigned().index(); table.integer('entry_id').unsigned().index();
table.integer('cost_account_id').unsigned();
table.datetime('created_at').index(); table.datetime('created_at').index();
}); });
}; };

View File

@@ -28,6 +28,10 @@ export interface IAccount {
accountParentType: string, accountParentType: string,
}; };
export interface IAccountResponse extends IAccount {
}
export interface IAccountsFilter extends IDynamicListFilterDTO { export interface IAccountsFilter extends IDynamicListFilterDTO {
stringifiedFilterRoles?: string, stringifiedFilterRoles?: string,
}; };

View File

@@ -14,6 +14,6 @@ export interface IFormatNumberSettings {
thousand?: string; thousand?: string;
decimal?: string; decimal?: string;
zeroSign?: string; zeroSign?: string;
symbol?: string; currencyCode?: string;
money?: boolean, money?: boolean,
} }

View File

@@ -12,6 +12,7 @@ export interface IInventoryValuationReportQuery {
export interface IInventoryValuationSheetMeta { export interface IInventoryValuationSheetMeta {
organizationName: string, organizationName: string,
baseCurrency: string, baseCurrency: string,
isCostComputeRunning: boolean
}; };
export interface IInventoryValuationItem { export interface IInventoryValuationItem {
@@ -35,8 +36,8 @@ export interface IInventoryValuationTotal {
quantityFormatted: string, quantityFormatted: string,
} }
export interface IInventoryValuationStatement { export type IInventoryValuationStatement = {
items: IInventoryValuationItem[], items: IInventoryValuationItem[],
total: IInventoryValuationTotal total: IInventoryValuationTotal
}; } | {};

View File

@@ -11,6 +11,7 @@ export interface IInventoryTransaction {
transactionType: string, transactionType: string,
transactionId: number, transactionId: number,
entryId: number, entryId: number,
costAccountId: number,
createdAt?: Date, createdAt?: Date,
updatedAt?: Date, updatedAt?: Date,
}; };
@@ -27,7 +28,6 @@ export interface IInventoryLotCost {
transactionType: string, transactionType: string,
transactionId: number, transactionId: number,
costAccountId: number, costAccountId: number,
sellAccountId: number,
entryId: number, entryId: number,
createdAt: Date, createdAt: Date,
}; };

View File

@@ -36,8 +36,8 @@ export interface ISalesByItemsTotal {
currencyCode: string, currencyCode: string,
}; };
export interface ISalesByItemsSheetStatement { export type ISalesByItemsSheetStatement = {
items: ISalesByItemsItem[], items: ISalesByItemsItem[],
total: ISalesByItemsTotal total: ISalesByItemsTotal
}; } | {};

View File

@@ -350,7 +350,7 @@ export default class JournalCommands {
const costEntry = new JournalEntry({ const costEntry = new JournalEntry({
...commonEntry, ...commonEntry,
debit: inventoryCostLot.cost, debit: inventoryCostLot.cost,
account: inventoryCostLot.itemEntry.costAccountId, account: inventoryCostLot.costAccountId,
itemId: inventoryCostLot.itemId, itemId: inventoryCostLot.itemId,
index: getIndexIncrement(), index: getIndexIncrement(),
}); });

View File

@@ -8,6 +8,7 @@ import {
IAccount, IAccount,
IAccountsFilter, IAccountsFilter,
IFilterMeta, IFilterMeta,
IAccountResponse
} from 'interfaces'; } from 'interfaces';
import { import {
EventDispatcher, EventDispatcher,
@@ -38,11 +39,9 @@ export default class AccountsService {
* @param {number} accountTypeId - * @param {number} accountTypeId -
* @return {IAccountType} * @return {IAccountType}
*/ */
private getAccountTypeOrThrowError( private getAccountTypeOrThrowError(accountTypeKey: string) {
accountTypeKey: string
) {
this.logger.info('[accounts] validating account type existance.', { this.logger.info('[accounts] validating account type existance.', {
accountTypeKey accountTypeKey,
}); });
const accountType = AccountTypesUtils.getType(accountTypeKey); const accountType = AccountTypesUtils.getType(accountTypeKey);
@@ -298,7 +297,7 @@ export default class AccountsService {
} }
// Update the account on the storage. // Update the account on the storage.
const account = await accountRepository.update( const account = await accountRepository.update(
{ ...accountDTO, }, { ...accountDTO },
{ id: oldAccount.id } { id: oldAccount.id }
); );
this.logger.info('[account] account edited successfully.', { this.logger.info('[account] account edited successfully.', {
@@ -549,9 +548,9 @@ export default class AccountsService {
{ accountsIds } { accountsIds }
); );
// Activate or inactivate the given accounts ids in bulk. // Activate or inactivate the given accounts ids in bulk.
(activate) ? activate
await accountRepository.activateByIds(patchAccountsIds) : ? await accountRepository.activateByIds(patchAccountsIds)
await accountRepository.inactivateByIds(patchAccountsIds); : await accountRepository.inactivateByIds(patchAccountsIds);
this.logger.info('[account] accounts have been activated successfully.', { this.logger.info('[account] accounts have been activated successfully.', {
tenantId, tenantId,
@@ -587,9 +586,9 @@ export default class AccountsService {
const patchAccountsIds = [...dependenciesAccounts, accountId]; const patchAccountsIds = [...dependenciesAccounts, accountId];
// Activate and inactivate the given accounts ids. // Activate and inactivate the given accounts ids.
(activate) ? activate
await accountRepository.activateByIds(patchAccountsIds) : ? await accountRepository.activateByIds(patchAccountsIds)
await accountRepository.inactivateByIds(patchAccountsIds); : await accountRepository.inactivateByIds(patchAccountsIds);
this.logger.info('[account] account have been activated successfully.', { this.logger.info('[account] account have been activated successfully.', {
tenantId, tenantId,
@@ -607,7 +606,7 @@ export default class AccountsService {
public async getAccountsList( public async getAccountsList(
tenantId: number, tenantId: number,
filter: IAccountsFilter filter: IAccountsFilter
): Promise<{ accounts: IAccount[]; filterMeta: IFilterMeta }> { ): Promise<{ accounts: IAccountResponse[]; filterMeta: IFilterMeta }> {
const { Account } = this.tenancy.models(tenantId); const { Account } = this.tenancy.models(tenantId);
const dynamicList = await this.dynamicListService.dynamicList( const dynamicList = await this.dynamicListService.dynamicList(
tenantId, tenantId,
@@ -624,11 +623,27 @@ export default class AccountsService {
}); });
return { return {
accounts, accounts: this.transformAccountsResponse(tenantId, accounts),
filterMeta: dynamicList.getResponseMeta(), filterMeta: dynamicList.getResponseMeta(),
}; };
} }
/**
* Transformes the accounts models to accounts response.
*/
private transformAccountsResponse(tenantId: number, accounts: IAccount[]) {
const settings = this.tenancy.settings(tenantId);
const baseCurrency = settings.get({
group: 'organization',
key: 'base_currency',
});
return accounts.map((account) => ({
...account,
currencyCode: baseCurrency,
}));
}
/** /**
* Closes the given account. * Closes the given account.
* ----------- * -----------
@@ -655,9 +670,7 @@ export default class AccountsService {
deleteAfterClosing, deleteAfterClosing,
}); });
const { AccountTransaction } = this.tenancy.models(tenantId); const { AccountTransaction } = this.tenancy.models(tenantId);
const { const { accountRepository } = this.tenancy.repositories(tenantId);
accountRepository,
} = this.tenancy.repositories(tenantId);
const account = await this.getAccountOrThrowError(tenantId, accountId); const account = await this.getAccountOrThrowError(tenantId, accountId);
const toAccount = await this.getAccountOrThrowError(tenantId, toAccountId); const toAccount = await this.getAccountOrThrowError(tenantId, toAccountId);

View File

@@ -8,6 +8,7 @@ import {
IAccount, IAccount,
IJournalPoster, IJournalPoster,
IAccountType, IAccountType,
INumberFormatQuery,
} from 'interfaces'; } from 'interfaces';
import { dateRangeCollection, flatToNestedArray } from 'utils'; import { dateRangeCollection, flatToNestedArray } from 'utils';
import BalanceSheetStructure from 'data/BalanceSheetStructure'; import BalanceSheetStructure from 'data/BalanceSheetStructure';
@@ -21,6 +22,7 @@ export default class BalanceSheetStatement extends FinancialSheet {
readonly comparatorDateType: string; readonly comparatorDateType: string;
readonly dateRangeSet: string[]; readonly dateRangeSet: string[];
readonly baseCurrency: string; readonly baseCurrency: string;
readonly numberFormat: INumberFormatQuery;
/** /**
* Constructor method. * Constructor method.

View File

@@ -2,7 +2,8 @@ import { IFormatNumberSettings, INumberFormatQuery } from 'interfaces';
import { formatNumber } from 'utils'; import { formatNumber } from 'utils';
export default class FinancialSheet { export default class FinancialSheet {
numberFormat: INumberFormatQuery; readonly numberFormat: INumberFormatQuery;
readonly baseCurrency: string;
/** /**
* Transformes the number format query to settings * Transformes the number format query to settings
@@ -16,6 +17,7 @@ export default class FinancialSheet {
excerptZero: !numberFormat.showZero, excerptZero: !numberFormat.showZero,
negativeFormat: numberFormat.negativeFormat, negativeFormat: numberFormat.negativeFormat,
money: numberFormat.formatMoney === 'always', money: numberFormat.formatMoney === 'always',
currencyCode: this.baseCurrency,
}; };
} }

View File

@@ -48,7 +48,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* @param {number} itemId * @param {number} itemId
* @returns * @returns
*/ */
getItemTransaction( private getItemTransaction(
transactionsMap: Map<number, InventoryCostLotTracker[]>, transactionsMap: Map<number, InventoryCostLotTracker[]>,
itemId: number, itemId: number,
): { cost: number, quantity: number } { ): { cost: number, quantity: number } {
@@ -64,7 +64,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* Retrieve the cost and quantity of the givne item from `IN` transactions. * Retrieve the cost and quantity of the givne item from `IN` transactions.
* @param {number} itemId - * @param {number} itemId -
*/ */
getItemINTransaction( private getItemINTransaction(
itemId: number, itemId: number,
): { cost: number, quantity: number } { ): { cost: number, quantity: number } {
return this.getItemTransaction(this.INInventoryCostLots, itemId); return this.getItemTransaction(this.INInventoryCostLots, itemId);
@@ -74,7 +74,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* Retrieve the cost and quantity of the given item from `OUT` transactions. * Retrieve the cost and quantity of the given item from `OUT` transactions.
* @param {number} itemId - * @param {number} itemId -
*/ */
getItemOUTTransaction( private getItemOUTTransaction(
itemId: number, itemId: number,
): { cost: number, quantity: number } { ): { cost: number, quantity: number } {
return this.getItemTransaction(this.OUTInventoryCostLots, itemId); return this.getItemTransaction(this.OUTInventoryCostLots, itemId);
@@ -84,7 +84,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* Retrieve the item closing valuation. * Retrieve the item closing valuation.
* @param {number} itemId - Item id. * @param {number} itemId - Item id.
*/ */
getItemValuation(itemId: number): number { private getItemValuation(itemId: number): number {
const { cost: INValuation } = this.getItemINTransaction(itemId); const { cost: INValuation } = this.getItemINTransaction(itemId);
const { cost: OUTValuation } = this.getItemOUTTransaction(itemId); const { cost: OUTValuation } = this.getItemOUTTransaction(itemId);
@@ -95,7 +95,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* Retrieve the item closing quantity. * Retrieve the item closing quantity.
* @param {number} itemId - Item id. * @param {number} itemId - Item id.
*/ */
getItemQuantity(itemId: number): number { private getItemQuantity(itemId: number): number {
const { quantity: INQuantity } = this.getItemINTransaction(itemId); const { quantity: INQuantity } = this.getItemINTransaction(itemId);
const { quantity: OUTQuantity } = this.getItemOUTTransaction(itemId); const { quantity: OUTQuantity } = this.getItemOUTTransaction(itemId);
@@ -108,7 +108,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* @param {number} quantity * @param {number} quantity
* @returns {number} * @returns {number}
*/ */
calcAverage(valuation: number, quantity: number): number { private calcAverage(valuation: number, quantity: number): number {
return quantity ? valuation / quantity : 0; return quantity ? valuation / quantity : 0;
} }
@@ -117,7 +117,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* @param {IItem} item * @param {IItem} item
* @returns {IInventoryValuationItem} * @returns {IInventoryValuationItem}
*/ */
itemMapper(item: IItem): IInventoryValuationItem { private itemMapper(item: IItem): IInventoryValuationItem {
const valuation = this.getItemValuation(item.id); const valuation = this.getItemValuation(item.id);
const quantity = this.getItemQuantity(item.id); const quantity = this.getItemQuantity(item.id);
const average = this.calcAverage(valuation, quantity); const average = this.calcAverage(valuation, quantity);
@@ -140,7 +140,7 @@ export default class InventoryValuationSheet extends FinancialSheet {
* Retrieve the inventory valuation items. * Retrieve the inventory valuation items.
* @returns {IInventoryValuationItem[]} * @returns {IInventoryValuationItem[]}
*/ */
itemsSection(): IInventoryValuationItem[] { private itemsSection(): IInventoryValuationItem[] {
return this.items.map(this.itemMapper.bind(this)); return this.items.map(this.itemMapper.bind(this));
} }
@@ -149,15 +149,15 @@ export default class InventoryValuationSheet extends FinancialSheet {
* @param {IInventoryValuationItem[]} items * @param {IInventoryValuationItem[]} items
* @returns {IInventoryValuationTotal} * @returns {IInventoryValuationTotal}
*/ */
totalSection(items: IInventoryValuationItem[]): IInventoryValuationTotal { private totalSection(items: IInventoryValuationItem[]): IInventoryValuationTotal {
const valuation = sumBy(items, item => item.valuation); const valuation = sumBy(items, item => item.valuation);
const quantity = sumBy(items, item => item.quantity); const quantity = sumBy(items, item => item.quantity);
return { return {
valuation, valuation,
quantity, quantity,
valuationFormatted: this.formatNumber(valuation), valuationFormatted: this.formatTotalNumber(valuation),
quantityFormatted: this.formatNumber(quantity, { money: false }), quantityFormatted: this.formatTotalNumber(quantity, { money: false }),
}; };
} }
@@ -165,10 +165,10 @@ export default class InventoryValuationSheet extends FinancialSheet {
* Retrieve the inventory valuation report data. * Retrieve the inventory valuation report data.
* @returns {IInventoryValuationStatement} * @returns {IInventoryValuationStatement}
*/ */
reportData(): IInventoryValuationStatement { public reportData(): IInventoryValuationStatement {
const items = this.itemsSection(); const items = this.itemsSection();
const total = this.totalSection(items); const total = this.totalSection(items);
return { items, total }; return items.length > 0 ? { items, total } : {};
} }
} }

View File

@@ -6,6 +6,7 @@ import {
} from 'interfaces'; } from 'interfaces';
import TenancyService from 'services/Tenancy/TenancyService'; import TenancyService from 'services/Tenancy/TenancyService';
import InventoryValuationSheet from './InventoryValuationSheet'; import InventoryValuationSheet from './InventoryValuationSheet';
import InventoryService from 'services/Inventory/Inventory';
@Service() @Service()
export default class InventoryValuationSheetService { export default class InventoryValuationSheetService {
@@ -15,6 +16,9 @@ export default class InventoryValuationSheetService {
@Inject('logger') @Inject('logger')
logger: any; logger: any;
@Inject()
inventoryService: InventoryService;
/** /**
* Defaults balance sheet filter query. * Defaults balance sheet filter query.
* @return {IBalanceSheetQuery} * @return {IBalanceSheetQuery}
@@ -41,6 +45,9 @@ export default class InventoryValuationSheetService {
reportMetadata(tenantId: number): IInventoryValuationSheetMeta { reportMetadata(tenantId: number): IInventoryValuationSheetMeta {
const settings = this.tenancy.settings(tenantId); const settings = this.tenancy.settings(tenantId);
const isCostComputeRunning = this.inventoryService
.isItemsCostComputeRunning(tenantId);
const organizationName = settings.get({ const organizationName = settings.get({
group: 'organization', group: 'organization',
key: 'name', key: 'name',
@@ -53,6 +60,7 @@ export default class InventoryValuationSheetService {
return { return {
organizationName, organizationName,
baseCurrency, baseCurrency,
isCostComputeRunning
}; };
} }

View File

@@ -10,10 +10,10 @@ import {
import FinancialSheet from '../FinancialSheet'; import FinancialSheet from '../FinancialSheet';
export default class JournalSheet extends FinancialSheet { export default class JournalSheet extends FinancialSheet {
tenantId: number; readonly tenantId: number;
journal: IJournalPoster; readonly journal: IJournalPoster;
query: IJournalReportQuery; readonly query: IJournalReportQuery;
baseCurrency: string; readonly baseCurrency: string;
readonly contactsById: Map<number | string, IContact>; readonly contactsById: Map<number | string, IContact>;
/** /**

View File

@@ -76,6 +76,8 @@ export default class JournalSheetService {
contactRepository, contactRepository,
} = this.tenancy.repositories(tenantId); } = this.tenancy.repositories(tenantId);
const { AccountTransaction } = this.tenancy.models(tenantId);
const filter = { const filter = {
...this.defaultQuery, ...this.defaultQuery,
...query, ...query,
@@ -98,12 +100,12 @@ export default class JournalSheetService {
const contactsByIdMap = transformToMap(contacts, 'id'); const contactsByIdMap = transformToMap(contacts, 'id');
// Retrieve all journal transactions based on the given query. // Retrieve all journal transactions based on the given query.
const transactions = await transactionsRepository.journal({ const transactions = await AccountTransaction.query().onBuild((query) => {
fromDate: filter.fromDate, if (filter.fromRange || filter.toRange) {
toDate: filter.toDate, query.modify('filterAmountRange', filter.fromRange, filter.toRange);
transactionsTypes: filter.transactionTypes, }
fromAmount: filter.fromRange, query.modify('filterDateRange', filter.fromDate, filter.toDate);
toAmount: filter.toRange, query.orderBy(['date', 'createdAt', 'indexGroup', 'index']);
}); });
// Transform the transactions array to journal collection. // Transform the transactions array to journal collection.
const transactionsJournal = Journal.fromTransactions( const transactionsJournal = Journal.fromTransactions(

View File

@@ -99,10 +99,10 @@ export default class InventoryValuationReport extends FinancialSheet {
return { return {
quantityPurchased, quantityPurchased,
purchaseCost, purchaseCost,
quantityPurchasedFormatted: this.formatNumber(quantityPurchased, { quantityPurchasedFormatted: this.formatTotalNumber(quantityPurchased, {
money: false, money: false,
}), }),
purchaseCostFormatted: this.formatNumber(purchaseCost), purchaseCostFormatted: this.formatTotalNumber(purchaseCost),
currencyCode: this.baseCurrency, currencyCode: this.baseCurrency,
}; };
} }
@@ -115,6 +115,6 @@ export default class InventoryValuationReport extends FinancialSheet {
const items = this.itemsSection(); const items = this.itemsSection();
const total = this.totalSection(items); const total = this.totalSection(items);
return { items, total }; return items.length > 0 ? { items, total } : {};
} }
} }

View File

@@ -99,10 +99,10 @@ export default class SalesByItemsReport extends FinancialSheet {
return { return {
quantitySold, quantitySold,
soldCost, soldCost,
quantitySoldFormatted: this.formatNumber(quantitySold, { quantitySoldFormatted: this.formatTotalNumber(quantitySold, {
money: false, money: false,
}), }),
soldCostFormatted: this.formatNumber(soldCost), soldCostFormatted: this.formatTotalNumber(soldCost),
currencyCode: this.baseCurrency, currencyCode: this.baseCurrency,
}; };
} }
@@ -115,6 +115,6 @@ export default class SalesByItemsReport extends FinancialSheet {
const items = this.itemsSection(); const items = this.itemsSection();
const total = this.totalSection(items); const total = this.totalSection(items);
return { items, total }; return items.length > 0 ? { items, total } : {};
} }
} }

View File

@@ -55,6 +55,7 @@ export default class InventoryService {
date: transaction.date, date: transaction.date,
entryId: entry.id, entryId: entry.id,
createdAt: transaction.createdAt, createdAt: transaction.createdAt,
costAccountId: entry.costAccountId,
})); }));
} }

View File

@@ -20,7 +20,6 @@ import ItemsService from 'services/Items/ItemsService';
import DynamicListingService from 'services/DynamicListing/DynamicListService'; import DynamicListingService from 'services/DynamicListing/DynamicListService';
import HasTenancyService from 'services/Tenancy/TenancyService'; import HasTenancyService from 'services/Tenancy/TenancyService';
import InventoryService from './Inventory'; import InventoryService from './Inventory';
import { increment } from 'utils';
const ERRORS = { const ERRORS = {
INVENTORY_ADJUSTMENT_NOT_FOUND: 'INVENTORY_ADJUSTMENT_NOT_FOUND', INVENTORY_ADJUSTMENT_NOT_FOUND: 'INVENTORY_ADJUSTMENT_NOT_FOUND',

View File

@@ -165,6 +165,8 @@ export default class InventoryAverageCostMethod
'transactionId', 'transactionId',
'transactionType', 'transactionType',
'createdAt', 'createdAt',
'costAccountId',
]), ]),
}; };
switch (invTransaction.direction) { switch (invTransaction.direction) {

View File

@@ -25,7 +25,7 @@ import TenancyService from 'services/Tenancy/TenancyService';
import DynamicListingService from 'services/DynamicListing/DynamicListService'; import DynamicListingService from 'services/DynamicListing/DynamicListService';
import { entriesAmountDiff, formatDateFields } from 'utils'; import { entriesAmountDiff, formatDateFields } from 'utils';
import { ServiceError } from 'exceptions'; import { ServiceError } from 'exceptions';
import { ACCOUNT_PARENT_TYPE } from 'data/AccountTypes'; import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from 'data/AccountTypes';
import VendorsService from 'services/Contacts/VendorsService'; import VendorsService from 'services/Contacts/VendorsService';
import { ERRORS } from './constants'; import { ERRORS } from './constants';
@@ -113,7 +113,14 @@ export default class BillPaymentsService implements IBillPaymentsService {
if (!paymentAccount) { if (!paymentAccount) {
throw new ServiceError(ERRORS.PAYMENT_ACCOUNT_NOT_FOUND); throw new ServiceError(ERRORS.PAYMENT_ACCOUNT_NOT_FOUND);
} }
if (!paymentAccount.isParentType(ACCOUNT_PARENT_TYPE.CURRENT_ASSET)) { // Validate the payment account type.
if (
!paymentAccount.isAccountType([
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
])
) {
throw new ServiceError(ERRORS.PAYMENT_ACCOUNT_NOT_CURRENT_ASSET_TYPE); throw new ServiceError(ERRORS.PAYMENT_ACCOUNT_NOT_CURRENT_ASSET_TYPE);
} }
return paymentAccount; return paymentAccount;

View File

@@ -30,7 +30,7 @@ import { ServiceError } from 'exceptions';
import CustomersService from 'services/Contacts/CustomersService'; import CustomersService from 'services/Contacts/CustomersService';
import ItemsEntriesService from 'services/Items/ItemsEntriesService'; import ItemsEntriesService from 'services/Items/ItemsEntriesService';
import JournalCommands from 'services/Accounting/JournalCommands'; import JournalCommands from 'services/Accounting/JournalCommands';
import { ACCOUNT_PARENT_TYPE } from 'data/AccountTypes'; import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from 'data/AccountTypes';
import AutoIncrementOrdersService from '../AutoIncrementOrdersService'; import AutoIncrementOrdersService from '../AutoIncrementOrdersService';
import { ERRORS } from './constants'; import { ERRORS } from './constants';
@@ -129,8 +129,14 @@ export default class PaymentReceiveService implements IPaymentsReceiveService {
if (!depositAccount) { if (!depositAccount) {
throw new ServiceError(ERRORS.DEPOSIT_ACCOUNT_NOT_FOUND); throw new ServiceError(ERRORS.DEPOSIT_ACCOUNT_NOT_FOUND);
} }
// Detarmines whether the account is cash equivalents. // Detarmines whether the account is cash, bank or other current asset.
if (!depositAccount.isParentType(ACCOUNT_PARENT_TYPE.CURRENT_ASSET)) { if (
!depositAccount.isAccountType([
ACCOUNT_TYPE.CASH,
ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
])
) {
throw new ServiceError(ERRORS.DEPOSIT_ACCOUNT_INVALID_TYPE); throw new ServiceError(ERRORS.DEPOSIT_ACCOUNT_INVALID_TYPE);
} }
return depositAccount; return depositAccount;

View File

@@ -2,6 +2,7 @@ import bcrypt from 'bcryptjs';
import moment from 'moment'; import moment from 'moment';
import _ from 'lodash'; import _ from 'lodash';
import accounting from 'accounting'; import accounting from 'accounting';
import Currencies from 'js-money/lib/currency';
import definedOptions from 'data/options'; import definedOptions from 'data/options';
const hashPassword = (password) => const hashPassword = (password) =>
@@ -224,6 +225,10 @@ const getNegativeFormat = (formatName) => {
} }
}; };
const getCurrencySign = (currencyCode) => {
return _.get(Currencies, `${currencyCode}.symbol`);
};
const formatNumber = ( const formatNumber = (
balance, balance,
{ {
@@ -234,10 +239,11 @@ const formatNumber = (
thousand = ',', thousand = ',',
decimal = '.', decimal = '.',
zeroSign = '', zeroSign = '',
symbol = '$',
money = true, money = true,
currencyCode
} }
) => { ) => {
const symbol = getCurrencySign(currencyCode);
const negForamt = getNegativeFormat(negativeFormat); const negForamt = getNegativeFormat(negativeFormat);
const format = '%s%v'; const format = '%s%v';