mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
refactor(nestjs): landed cost
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { difference, sumBy } from 'lodash';
|
||||
import {
|
||||
ILandedCostItemDTO,
|
||||
ILandedCostDTO,
|
||||
IBillLandedCostTransaction,
|
||||
ILandedCostTransaction,
|
||||
ILandedCostTransactionEntry,
|
||||
LandedCostTransactionModel,
|
||||
LandedCostTransactionType,
|
||||
} from './types/BillLandedCosts.types';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
import { BillLandedCost } from './models/BillLandedCost';
|
||||
@@ -14,13 +13,19 @@ import { CONFIG, ERRORS } from './utils';
|
||||
import { ItemEntry } from '../TransactionItemEntry/models/ItemEntry';
|
||||
import { Bill } from '../Bills/models/Bill';
|
||||
import { TransactionLandedCost } from './commands/TransctionLandedCost.service';
|
||||
import {
|
||||
AllocateBillLandedCostDto,
|
||||
AllocateBillLandedCostItemDto,
|
||||
} from './dtos/AllocateBillLandedCost.dto';
|
||||
|
||||
export class BaseLandedCostService {
|
||||
@Inject()
|
||||
public readonly transactionLandedCost: TransactionLandedCost;
|
||||
protected readonly transactionLandedCost: TransactionLandedCost;
|
||||
|
||||
@Inject(BillLandedCost.name)
|
||||
private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>;
|
||||
protected readonly billLandedCostModel: TenantModelProxy<
|
||||
typeof BillLandedCost
|
||||
>;
|
||||
|
||||
/**
|
||||
* Validates allocate cost items association with the purchase invoice entries.
|
||||
@@ -29,7 +34,7 @@ export class BaseLandedCostService {
|
||||
*/
|
||||
protected validateAllocateCostItems = (
|
||||
purchaseInvoiceEntries: ItemEntry[],
|
||||
landedCostItems: ILandedCostItemDTO[],
|
||||
landedCostItems: AllocateBillLandedCostItemDto[],
|
||||
): void => {
|
||||
// Purchase invoice entries items ids.
|
||||
const purchaseInvoiceItems = purchaseInvoiceEntries.map((e) => e.id);
|
||||
@@ -55,7 +60,7 @@ export class BaseLandedCostService {
|
||||
* @returns
|
||||
*/
|
||||
protected transformToBillLandedCost(
|
||||
landedCostDTO: ILandedCostDTO,
|
||||
landedCostDTO: AllocateBillLandedCostDto,
|
||||
bill: Bill,
|
||||
costTransaction: ILandedCostTransaction,
|
||||
costTransactionEntry: ILandedCostTransactionEntry,
|
||||
@@ -88,20 +93,18 @@ export class BaseLandedCostService {
|
||||
* @param {transactionId} transactionId -
|
||||
*/
|
||||
public getLandedCostOrThrowError = async (
|
||||
transactionType: string,
|
||||
transactionType: LandedCostTransactionType,
|
||||
transactionId: number,
|
||||
) => {
|
||||
const Model = this.transactionLandedCost.getModel(
|
||||
transactionType,
|
||||
);
|
||||
const model = await Model.query().findById(transactionId);
|
||||
const Model = await this.transactionLandedCost.getModel(transactionType);
|
||||
const model = await Model().query().findById(transactionId);
|
||||
|
||||
if (!model) {
|
||||
throw new ServiceError(ERRORS.LANDED_COST_TRANSACTION_NOT_FOUND);
|
||||
}
|
||||
return this.transactionLandedCost.transformToLandedCost(
|
||||
transactionType,
|
||||
model,
|
||||
model as LandedCostTransactionModel,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -117,13 +120,11 @@ export class BaseLandedCostService {
|
||||
transactionId: number,
|
||||
transactionEntryId: number,
|
||||
): Promise<any> => {
|
||||
const Model = this.transactionLandedCost.getModel(
|
||||
tenantId,
|
||||
transactionType,
|
||||
);
|
||||
const Model = await this.transactionLandedCost.getModel(transactionType);
|
||||
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
||||
|
||||
const entry = await Model.relatedQuery(relation)
|
||||
const entry = await Model()
|
||||
.relatedQuery(relation)
|
||||
.for(transactionId)
|
||||
.findOne('id', transactionEntryId)
|
||||
.where('landedCost', true)
|
||||
@@ -139,7 +140,7 @@ export class BaseLandedCostService {
|
||||
throw new ServiceError(ERRORS.LANDED_COST_ENTRY_NOT_FOUND);
|
||||
}
|
||||
return this.transactionLandedCost.transformToLandedCostEntry(
|
||||
transactionType,
|
||||
transactionType as LandedCostTransactionType,
|
||||
entry,
|
||||
);
|
||||
};
|
||||
@@ -150,7 +151,7 @@ export class BaseLandedCostService {
|
||||
* @returns {number}
|
||||
*/
|
||||
protected getAllocateItemsCostTotal = (
|
||||
landedCostDTO: ILandedCostDTO,
|
||||
landedCostDTO: AllocateBillLandedCostDto,
|
||||
): number => {
|
||||
return sumBy(landedCostDTO.items, 'cost');
|
||||
};
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { forwardRef, Module } from '@nestjs/common';
|
||||
import { TransactionLandedCostEntriesService } from './TransactionLandedCostEntries.service';
|
||||
import { AllocateLandedCostService } from './commands/AllocateLandedCost.service';
|
||||
import { LandedCostGLEntriesSubscriber } from './commands/LandedCostGLEntries.subscriber';
|
||||
import { LandedCostGLEntries } from './commands/LandedCostGLEntries.service';
|
||||
// import { LandedCostGLEntries } from './commands/LandedCostGLEntries.service';
|
||||
import { LandedCostSyncCostTransactions } from './commands/LandedCostSyncCostTransactions.service';
|
||||
import { LandedCostSyncCostTransactionsSubscriber } from './commands/LandedCostSyncCostTransactions.subscriber';
|
||||
import { BillAllocatedLandedCostTransactions } from './commands/BillAllocatedLandedCostTransactions.service';
|
||||
import { BillAllocateLandedCostController } from './LandedCost.controller';
|
||||
import { RevertAllocatedLandedCost } from './commands/RevertAllocatedLandedCost.service';
|
||||
import LandedCostTranasctions from './commands/LandedCostTransactions.service';
|
||||
import { LandedCostTranasctions } from './commands/LandedCostTransactions.service';
|
||||
import { LandedCostInventoryTransactions } from './commands/LandedCostInventoryTransactions.service';
|
||||
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
||||
import { TransactionLandedCost } from './commands/TransctionLandedCost.service';
|
||||
import { ExpenseLandedCost } from './commands/ExpenseLandedCost.service';
|
||||
import { BillLandedCost } from './commands/BillLandedCost.service';
|
||||
|
||||
@Module({
|
||||
imports: [InventoryCostModule],
|
||||
imports: [forwardRef(() => InventoryCostModule)],
|
||||
providers: [
|
||||
AllocateLandedCostService,
|
||||
TransactionLandedCostEntriesService,
|
||||
BillAllocatedLandedCostTransactions,
|
||||
LandedCostGLEntriesSubscriber,
|
||||
LandedCostGLEntries,
|
||||
TransactionLandedCost,
|
||||
BillLandedCost,
|
||||
ExpenseLandedCost,
|
||||
LandedCostSyncCostTransactions,
|
||||
RevertAllocatedLandedCost,
|
||||
LandedCostInventoryTransactions,
|
||||
|
||||
@@ -7,32 +7,45 @@ import {
|
||||
Post,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
|
||||
import { AllocateBillLandedCostDto } from './dtos/AllocateBillLandedCost.dto';
|
||||
import { AllocateLandedCostService } from './commands/AllocateLandedCost.service';
|
||||
import { BillAllocatedLandedCostTransactions } from './commands/BillAllocatedLandedCostTransactions.service';
|
||||
import { RevertAllocatedLandedCost } from './commands/RevertAllocatedLandedCost.service';
|
||||
import { LandedCostTranasctions } from './commands/LandedCostTransactions.service';
|
||||
import { LandedCostTransactionsQueryDto } from './dtos/LandedCostTransactionsQuery.dto';
|
||||
|
||||
@ApiTags('Landed Cost')
|
||||
@Controller('landed-cost')
|
||||
export class BillAllocateLandedCostController {
|
||||
constructor(
|
||||
private allocateLandedCost: AllocateLandedCostService,
|
||||
private billAllocatedCostTransactions: BillAllocatedLandedCostTransactions,
|
||||
private revertAllocatedLandedCost: RevertAllocatedLandedCost,
|
||||
private landedCostTranasctions: LandedCostTranasctions,
|
||||
private landedCostTransactions: LandedCostTranasctions,
|
||||
) {}
|
||||
|
||||
@Get('/transactions')
|
||||
@ApiOperation({ summary: 'Get landed cost transactions' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'List of landed cost transactions.',
|
||||
})
|
||||
async getLandedCostTransactions(
|
||||
@Query('transaction_type') transactionType: string,
|
||||
@Query() query: LandedCostTransactionsQueryDto,
|
||||
) {
|
||||
const transactions =
|
||||
await this.landedCostTranasctions.getLandedCostTransactions(transactionType);
|
||||
await this.landedCostTransactions.getLandedCostTransactions(query);
|
||||
|
||||
return transactions;
|
||||
}
|
||||
|
||||
@Post('/bills/:billId/allocate')
|
||||
@ApiOperation({ summary: 'Allocate landed cost to bill items' })
|
||||
@ApiResponse({
|
||||
status: 201,
|
||||
description: 'Landed cost allocated successfully.',
|
||||
})
|
||||
public async calculateLandedCost(
|
||||
@Param('billId') billId: number,
|
||||
@Body() landedCostDTO: AllocateBillLandedCostDto,
|
||||
@@ -48,37 +61,37 @@ export class BillAllocateLandedCostController {
|
||||
}
|
||||
|
||||
@Delete('/:allocatedLandedCostId')
|
||||
@ApiOperation({ summary: 'Delete allocated landed cost' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Allocated landed cost deleted successfully.',
|
||||
})
|
||||
public async deleteAllocatedLandedCost(
|
||||
@Param('allocatedLandedCostId') allocatedLandedCostId: number,
|
||||
) {
|
||||
await this.revertAllocatedLandedCost.deleteAllocatedLandedCost(
|
||||
allocatedLandedCostId,
|
||||
);
|
||||
|
||||
return {
|
||||
id: allocatedLandedCostId,
|
||||
message: 'The allocated landed cost are delete successfully.',
|
||||
};
|
||||
}
|
||||
|
||||
public async listLandedCosts(
|
||||
) {
|
||||
const transactions =
|
||||
await this.landedCostTranasctions.getLandedCostTransactions(query);
|
||||
|
||||
return transactions;
|
||||
};
|
||||
|
||||
@Get('/bills/:billId/transactions')
|
||||
@ApiOperation({ summary: 'Get bill landed cost transactions' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'List of bill landed cost transactions.',
|
||||
})
|
||||
async getBillLandedCostTransactions(@Param('billId') billId: number) {
|
||||
const transactions =
|
||||
const data =
|
||||
await this.billAllocatedCostTransactions.getBillLandedCostTransactions(
|
||||
billId,
|
||||
);
|
||||
|
||||
return {
|
||||
billId,
|
||||
transactions,
|
||||
data,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export class AllocateLandedCostService extends BaseLandedCostService {
|
||||
private readonly billModel: TenantModelProxy<typeof Bill>,
|
||||
|
||||
@Inject(BillLandedCost.name)
|
||||
private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>
|
||||
protected readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -54,7 +54,7 @@ export class AllocateLandedCostService extends BaseLandedCostService {
|
||||
const amount = this.getAllocateItemsCostTotal(allocateCostDTO);
|
||||
|
||||
// Retrieve the purchase invoice or throw not found error.
|
||||
const bill = await Bill.query()
|
||||
const bill = await this.billModel().query()
|
||||
.findById(billId)
|
||||
.withGraphFetched('entries')
|
||||
.throwIfNotFound();
|
||||
|
||||
@@ -6,6 +6,8 @@ import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { BillLandedCost } from '../models/BillLandedCost';
|
||||
import { IBillLandedCostTransaction } from '../types/BillLandedCosts.types';
|
||||
import { ModelObject } from 'objection';
|
||||
import { formatNumber } from '@/utils/format-number';
|
||||
|
||||
@Injectable()
|
||||
export class BillAllocatedLandedCostTransactions {
|
||||
@@ -23,19 +25,17 @@ export class BillAllocatedLandedCostTransactions {
|
||||
|
||||
/**
|
||||
* Retrieve the bill associated landed cost transactions.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} billId - Bill id.
|
||||
* @return {Promise<IBillLandedCostTransaction>}
|
||||
*/
|
||||
public getBillLandedCostTransactions = async (
|
||||
billId: number,
|
||||
): Promise<IBillLandedCostTransaction> => {
|
||||
): Promise<Array<IBillLandedCostTransaction>> => {
|
||||
// Retrieve the given bill id or throw not found service error.
|
||||
const bill = await this.billModel()
|
||||
.query()
|
||||
.findById(billId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Retrieve the bill associated allocated landed cost with bill and expense entry.
|
||||
const landedCostTransactions = await this.billLandedCostModel()
|
||||
.query()
|
||||
@@ -45,11 +45,8 @@ export class BillAllocatedLandedCostTransactions {
|
||||
.withGraphFetched('allocatedFromExpenseEntry.expenseAccount')
|
||||
.withGraphFetched('bill');
|
||||
|
||||
const transactionsJson = this.i18nService.i18nApply(
|
||||
[[qim.$each, 'allocationMethodFormatted']],
|
||||
landedCostTransactions.map((a) => a.toJSON()),
|
||||
tenantId,
|
||||
);
|
||||
const transactionsJson = landedCostTransactions.map((a) => a.toJSON());
|
||||
|
||||
return this.transformBillLandedCostTransactions(transactionsJson);
|
||||
};
|
||||
|
||||
@@ -59,7 +56,7 @@ export class BillAllocatedLandedCostTransactions {
|
||||
* @returns
|
||||
*/
|
||||
private transformBillLandedCostTransactions = (
|
||||
landedCostTransactions: IBillLandedCostTransaction[],
|
||||
landedCostTransactions: ModelObject<BillLandedCost>[],
|
||||
) => {
|
||||
return landedCostTransactions.map(this.transformBillLandedCostTransaction);
|
||||
};
|
||||
@@ -70,15 +67,16 @@ export class BillAllocatedLandedCostTransactions {
|
||||
* @returns
|
||||
*/
|
||||
private transformBillLandedCostTransaction = (
|
||||
transaction: IBillLandedCostTransaction,
|
||||
) => {
|
||||
const getTransactionName = R.curry(this.condBillLandedTransactionName)(
|
||||
transaction: ModelObject<BillLandedCost>,
|
||||
): IBillLandedCostTransaction => {
|
||||
const name = this.condBillLandedTransactionName(
|
||||
transaction.fromTransactionType,
|
||||
transaction,
|
||||
);
|
||||
const description = this.condBillLandedTransactionDescription(
|
||||
transaction.fromTransactionType,
|
||||
transaction,
|
||||
);
|
||||
const getTransactionDesc = R.curry(
|
||||
this.condBillLandedTransactionDescription,
|
||||
)(transaction.fromTransactionType);
|
||||
|
||||
return {
|
||||
formattedAmount: formatNumber(transaction.amount, {
|
||||
currencyCode: transaction.currencyCode,
|
||||
@@ -87,8 +85,8 @@ export class BillAllocatedLandedCostTransactions {
|
||||
'allocatedFromBillEntry',
|
||||
'allocatedFromExpenseEntry',
|
||||
]),
|
||||
name: getTransactionName(transaction),
|
||||
description: getTransactionDesc(transaction),
|
||||
name,
|
||||
description,
|
||||
formattedLocalAmount: formatNumber(transaction.localAmount, {
|
||||
currencyCode: 'USD',
|
||||
}),
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
import {
|
||||
ILandedCostTransactionEntry,
|
||||
ILandedCostTransaction,
|
||||
} from '../types/BillLandedCosts.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
import { ModelObject } from 'objection';
|
||||
|
||||
@Injectable()
|
||||
export class BillLandedCost {
|
||||
/**
|
||||
* Retrieve the landed cost transaction from the given bill transaction.
|
||||
* @param {IBill} bill - Bill transaction.
|
||||
* @returns {ILandedCostTransaction} - Landed cost transaction.
|
||||
*/
|
||||
public transformToLandedCost = (
|
||||
bill: ModelObject<Bill>,
|
||||
): ILandedCostTransaction => {
|
||||
const name = bill.billNumber || bill.referenceNo;
|
||||
|
||||
return {
|
||||
id: bill.id,
|
||||
name,
|
||||
allocatedCostAmount: bill.allocatedCostAmount,
|
||||
amount: bill.landedCostAmount,
|
||||
unallocatedCostAmount: bill.unallocatedCostAmount,
|
||||
transactionType: 'Bill',
|
||||
currencyCode: bill.currencyCode,
|
||||
exchangeRate: bill.exchangeRate,
|
||||
|
||||
...(!isEmpty(bill.entries) && {
|
||||
entries: bill.entries.map(this.transformToLandedCostEntry),
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes bill entry to landed cost entry.
|
||||
* @param {IBill} bill - Bill model.
|
||||
* @param {IItemEntry} billEntry - Bill entry.
|
||||
* @return {ILandedCostTransactionEntry}
|
||||
*/
|
||||
public transformToLandedCostEntry(
|
||||
billEntry: ItemEntry & { item: Item },
|
||||
): ILandedCostTransactionEntry {
|
||||
return {
|
||||
id: billEntry.id,
|
||||
name: billEntry.item.name,
|
||||
code: billEntry.item.code,
|
||||
amount: billEntry.amount,
|
||||
|
||||
unallocatedCostAmount: billEntry.unallocatedCostAmount,
|
||||
allocatedCostAmount: billEntry.allocatedCostAmount,
|
||||
description: billEntry.description,
|
||||
costAccountId: billEntry.costAccountId || billEntry.item.costAccountId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { ModelObject } from 'objection';
|
||||
import {
|
||||
ILandedCostTransaction,
|
||||
ILandedCostTransactionEntry,
|
||||
} from '../types/BillLandedCosts.types';
|
||||
import { ExpenseCategory } from '@/modules/Expenses/models/ExpenseCategory.model';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
|
||||
@Injectable()
|
||||
export class ExpenseLandedCost {
|
||||
/**
|
||||
* Retrieve the landed cost transaction from the given expense transaction.
|
||||
* @param {IExpense} expense
|
||||
* @returns {ILandedCostTransaction}
|
||||
*/
|
||||
public transformToLandedCost = (
|
||||
expense: ModelObject<Expense>,
|
||||
): ILandedCostTransaction => {
|
||||
const name = 'EXP-100';
|
||||
|
||||
return {
|
||||
id: expense.id,
|
||||
name,
|
||||
amount: expense.landedCostAmount,
|
||||
allocatedCostAmount: expense.allocatedCostAmount,
|
||||
unallocatedCostAmount: expense.unallocatedCostAmount,
|
||||
transactionType: 'Expense',
|
||||
currencyCode: expense.currencyCode,
|
||||
exchangeRate: expense.exchangeRate || 1,
|
||||
|
||||
...(!isEmpty(expense.categories) && {
|
||||
entries: expense.categories.map(this.transformToLandedCostEntry),
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes expense entry to landed cost entry.
|
||||
* @param {IExpenseCategory & { expenseAccount: IAccount }} expenseEntry -
|
||||
* @return {ILandedCostTransactionEntry}
|
||||
*/
|
||||
public transformToLandedCostEntry = (
|
||||
expenseEntry: ExpenseCategory & { expenseAccount: Account },
|
||||
): ILandedCostTransactionEntry => {
|
||||
return {
|
||||
id: expenseEntry.id,
|
||||
name: expenseEntry.expenseAccount.name,
|
||||
code: expenseEntry.expenseAccount.code,
|
||||
amount: expenseEntry.amount,
|
||||
description: expenseEntry.description,
|
||||
allocatedCostAmount: expenseEntry.allocatedCostAmount,
|
||||
unallocatedCostAmount: expenseEntry.unallocatedCostAmount,
|
||||
costAccountId: expenseEntry.expenseAccount.id,
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,234 +1,236 @@
|
||||
import * as R from 'ramda';
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { BaseLandedCostService } from '../BaseLandedCost.service';
|
||||
import { BillLandedCost } from '../models/BillLandedCost';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
||||
import { ILedger, ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||
// import * as R from 'ramda';
|
||||
// import { Knex } from 'knex';
|
||||
// import { Inject, Injectable } from '@nestjs/common';
|
||||
// import { BaseLandedCostService } from '../BaseLandedCost.service';
|
||||
// import { BillLandedCost } from '../models/BillLandedCost';
|
||||
// import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
// import { Bill } from '@/modules/Bills/models/Bill';
|
||||
// import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
||||
// import { ILedger, ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||
// import { Ledger } from '@/modules/Ledger/Ledger';
|
||||
// import { AccountNormal } from '@/interfaces/Account';
|
||||
// import { ILandedCostTransactionEntry } from '../types/BillLandedCosts.types';
|
||||
|
||||
@Injectable()
|
||||
export class LandedCostGLEntries extends BaseLandedCostService {
|
||||
constructor(
|
||||
private readonly journalService: JournalPosterService,
|
||||
private readonly ledgerRepository: LedgerRepository,
|
||||
// @Injectable()
|
||||
// export class LandedCostGLEntries extends BaseLandedCostService {
|
||||
// constructor(
|
||||
// private readonly journalService: JournalPosterService,
|
||||
// private readonly ledgerRepository: LedgerRepository,
|
||||
|
||||
@Inject(BillLandedCost.name)
|
||||
private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
// @Inject(BillLandedCost.name)
|
||||
// private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>,
|
||||
// ) {
|
||||
// super();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Retrieves the landed cost GL common entry.
|
||||
* @param {IBill} bill
|
||||
* @param {IBillLandedCost} allocatedLandedCost
|
||||
* @returns
|
||||
*/
|
||||
private getLandedCostGLCommonEntry = (
|
||||
bill: Bill,
|
||||
allocatedLandedCost: BillLandedCost
|
||||
) => {
|
||||
return {
|
||||
date: bill.billDate,
|
||||
currencyCode: allocatedLandedCost.currencyCode,
|
||||
exchangeRate: allocatedLandedCost.exchangeRate,
|
||||
// /**
|
||||
// * Retrieves the landed cost GL common entry.
|
||||
// * @param {IBill} bill
|
||||
// * @param {IBillLandedCost} allocatedLandedCost
|
||||
// * @returns
|
||||
// */
|
||||
// private getLandedCostGLCommonEntry = (
|
||||
// bill: Bill,
|
||||
// allocatedLandedCost: BillLandedCost
|
||||
// ) => {
|
||||
// return {
|
||||
// date: bill.billDate,
|
||||
// currencyCode: allocatedLandedCost.currencyCode,
|
||||
// exchangeRate: allocatedLandedCost.exchangeRate,
|
||||
|
||||
transactionType: 'LandedCost',
|
||||
transactionId: allocatedLandedCost.id,
|
||||
transactionNumber: bill.billNumber,
|
||||
// transactionType: 'LandedCost',
|
||||
// transactionId: allocatedLandedCost.id,
|
||||
// transactionNumber: bill.billNumber,
|
||||
|
||||
referenceNumber: bill.referenceNo,
|
||||
// referenceNumber: bill.referenceNo,
|
||||
|
||||
credit: 0,
|
||||
debit: 0,
|
||||
};
|
||||
};
|
||||
// credit: 0,
|
||||
// debit: 0,
|
||||
// };
|
||||
// };
|
||||
|
||||
/**
|
||||
* Retrieves the landed cost GL inventory entry.
|
||||
* @param {IBill} bill
|
||||
* @param {IBillLandedCost} allocatedLandedCost
|
||||
* @param {IBillLandedCostEntry} allocatedEntry
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getLandedCostGLInventoryEntry = (
|
||||
bill: Bill,
|
||||
allocatedLandedCost: BillLandedCost,
|
||||
allocatedEntry: BillLandedCostEntry
|
||||
): ILedgerEntry => {
|
||||
const commonEntry = this.getLandedCostGLCommonEntry(
|
||||
bill,
|
||||
allocatedLandedCost
|
||||
);
|
||||
return {
|
||||
...commonEntry,
|
||||
debit: allocatedLandedCost.localAmount,
|
||||
accountId: allocatedEntry.itemEntry.item.inventoryAccountId,
|
||||
index: 1,
|
||||
accountNormal: AccountNormal.DEBIT,
|
||||
};
|
||||
};
|
||||
// /**
|
||||
// * Retrieves the landed cost GL inventory entry.
|
||||
// * @param {IBill} bill
|
||||
// * @param {IBillLandedCost} allocatedLandedCost
|
||||
// * @param {IBillLandedCostEntry} allocatedEntry
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getLandedCostGLInventoryEntry = (
|
||||
// bill: Bill,
|
||||
// allocatedLandedCost: BillLandedCost,
|
||||
// allocatedEntry: BillLandedCostEntry
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getLandedCostGLCommonEntry(
|
||||
// bill,
|
||||
// allocatedLandedCost
|
||||
// );
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// debit: allocatedLandedCost.localAmount,
|
||||
// accountId: allocatedEntry.itemEntry.item.inventoryAccountId,
|
||||
// index: 1,
|
||||
// accountNormal: AccountNormal.DEBIT,
|
||||
// };
|
||||
// };
|
||||
|
||||
/**
|
||||
* Retrieves the landed cost GL cost entry.
|
||||
* @param {IBill} bill
|
||||
* @param {IBillLandedCost} allocatedLandedCost
|
||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getLandedCostGLCostEntry = (
|
||||
bill: Bill,
|
||||
allocatedLandedCost: BillLandedCost,
|
||||
fromTransactionEntry: ILandedCostTransactionEntry
|
||||
): ILedgerEntry => {
|
||||
const commonEntry = this.getLandedCostGLCommonEntry(
|
||||
bill,
|
||||
allocatedLandedCost
|
||||
);
|
||||
return {
|
||||
...commonEntry,
|
||||
credit: allocatedLandedCost.localAmount,
|
||||
accountId: fromTransactionEntry.costAccountId,
|
||||
index: 2,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
};
|
||||
};
|
||||
// /**
|
||||
// * Retrieves the landed cost GL cost entry.
|
||||
// * @param {IBill} bill
|
||||
// * @param {IBillLandedCost} allocatedLandedCost
|
||||
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getLandedCostGLCostEntry = (
|
||||
// bill: Bill,
|
||||
// allocatedLandedCost: BillLandedCost,
|
||||
// fromTransactionEntry: ILandedCostTransactionEntry
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getLandedCostGLCommonEntry(
|
||||
// bill,
|
||||
// allocatedLandedCost
|
||||
// );
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// credit: allocatedLandedCost.localAmount,
|
||||
// accountId: fromTransactionEntry.costAccountId,
|
||||
// index: 2,
|
||||
// accountNormal: AccountNormal.CREDIT,
|
||||
// };
|
||||
// };
|
||||
|
||||
/**
|
||||
* Retrieve allocated landed cost entry GL entries.
|
||||
* @param {IBill} bill
|
||||
* @param {IBillLandedCost} allocatedLandedCost
|
||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
* @param {IBillLandedCostEntry} allocatedEntry
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getLandedCostGLAllocateEntry = R.curry(
|
||||
(
|
||||
bill: Bill,
|
||||
allocatedLandedCost: BillLandedCost,
|
||||
fromTransactionEntry: LandedCostTransactionEntry,
|
||||
allocatedEntry: BillLandedCostEntry
|
||||
): ILedgerEntry[] => {
|
||||
const inventoryEntry = this.getLandedCostGLInventoryEntry(
|
||||
bill,
|
||||
allocatedLandedCost,
|
||||
allocatedEntry
|
||||
);
|
||||
const costEntry = this.getLandedCostGLCostEntry(
|
||||
bill,
|
||||
allocatedLandedCost,
|
||||
fromTransactionEntry
|
||||
);
|
||||
return [inventoryEntry, costEntry];
|
||||
}
|
||||
);
|
||||
// /**
|
||||
// * Retrieve allocated landed cost entry GL entries.
|
||||
// * @param {IBill} bill
|
||||
// * @param {IBillLandedCost} allocatedLandedCost
|
||||
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
// * @param {IBillLandedCostEntry} allocatedEntry
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getLandedCostGLAllocateEntry = R.curry(
|
||||
// (
|
||||
// bill: Bill,
|
||||
// allocatedLandedCost: BillLandedCost,
|
||||
// fromTransactionEntry: ILandedCostTransactionEntry,
|
||||
// allocatedEntry: BillLandedCostEntry
|
||||
// ): ILedgerEntry[] => {
|
||||
// const inventoryEntry = this.getLandedCostGLInventoryEntry(
|
||||
// bill,
|
||||
// allocatedLandedCost,
|
||||
// allocatedEntry
|
||||
// );
|
||||
// const costEntry = this.getLandedCostGLCostEntry(
|
||||
// bill,
|
||||
// allocatedLandedCost,
|
||||
// fromTransactionEntry
|
||||
// );
|
||||
// return [inventoryEntry, costEntry];
|
||||
// }
|
||||
// );
|
||||
|
||||
/**
|
||||
* Compose the landed cost GL entries.
|
||||
* @param {BillLandedCost} allocatedLandedCost
|
||||
* @param {Bill} bill
|
||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
* @returns {ILedgerEntry[]}
|
||||
*/
|
||||
public getLandedCostGLEntries = (
|
||||
allocatedLandedCost: BillLandedCost,
|
||||
bill: Bill,
|
||||
fromTransactionEntry: LandedCostTransactionEntry
|
||||
): ILedgerEntry[] => {
|
||||
const getEntry = this.getLandedCostGLAllocateEntry(
|
||||
bill,
|
||||
allocatedLandedCost,
|
||||
fromTransactionEntry
|
||||
);
|
||||
return allocatedLandedCost.allocateEntries.map(getEntry).flat();
|
||||
};
|
||||
// /**
|
||||
// * Compose the landed cost GL entries.
|
||||
// * @param {BillLandedCost} allocatedLandedCost
|
||||
// * @param {Bill} bill
|
||||
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
// * @returns {ILedgerEntry[]}
|
||||
// */
|
||||
// public getLandedCostGLEntries = (
|
||||
// allocatedLandedCost: BillLandedCost,
|
||||
// bill: Bill,
|
||||
// fromTransactionEntry: ILandedCostTransactionEntry
|
||||
// ): ILedgerEntry[] => {
|
||||
// const getEntry = this.getLandedCostGLAllocateEntry(
|
||||
// bill,
|
||||
// allocatedLandedCost,
|
||||
// fromTransactionEntry
|
||||
// );
|
||||
// return allocatedLandedCost.allocateEntries.map(getEntry).flat();
|
||||
// };
|
||||
|
||||
/**
|
||||
* Retrieves the landed cost GL ledger.
|
||||
* @param {IBillLandedCost} allocatedLandedCost
|
||||
* @param {Bill} bill
|
||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
* @returns {ILedger}
|
||||
*/
|
||||
public getLandedCostLedger = (
|
||||
allocatedLandedCost: BillLandedCost,
|
||||
bill: Bill,
|
||||
fromTransactionEntry: LandedCostTransactionEntry
|
||||
): ILedger => {
|
||||
const entries = this.getLandedCostGLEntries(
|
||||
allocatedLandedCost,
|
||||
bill,
|
||||
fromTransactionEntry
|
||||
);
|
||||
return new Ledger(entries);
|
||||
};
|
||||
// /**
|
||||
// * Retrieves the landed cost GL ledger.
|
||||
// * @param {BillLandedCost} allocatedLandedCost
|
||||
// * @param {Bill} bill
|
||||
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||
// * @returns {ILedger}
|
||||
// */
|
||||
// public getLandedCostLedger = (
|
||||
// allocatedLandedCost: BillLandedCost,
|
||||
// bill: Bill,
|
||||
// fromTransactionEntry: ILandedCostTransactionEntry
|
||||
// ): ILedger => {
|
||||
// const entries = this.getLandedCostGLEntries(
|
||||
// allocatedLandedCost,
|
||||
// bill,
|
||||
// fromTransactionEntry
|
||||
// );
|
||||
// return new Ledger(entries);
|
||||
// };
|
||||
|
||||
/**
|
||||
* Writes landed cost GL entries to the storage layer.
|
||||
* @param {number} tenantId -
|
||||
*/
|
||||
public writeLandedCostGLEntries = async (
|
||||
allocatedLandedCost: BillLandedCost,
|
||||
bill: Bill,
|
||||
fromTransactionEntry: ILandedCostTransactionEntry,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
const ledgerEntries = this.getLandedCostGLEntries(
|
||||
allocatedLandedCost,
|
||||
bill,
|
||||
fromTransactionEntry
|
||||
);
|
||||
await this.ledgerRepository.saveLedgerEntries(ledgerEntries, trx);
|
||||
};
|
||||
// /**
|
||||
// * Writes landed cost GL entries to the storage layer.
|
||||
// * @param {number} tenantId -
|
||||
// */
|
||||
// public writeLandedCostGLEntries = async (
|
||||
// allocatedLandedCost: BillLandedCost,
|
||||
// bill: Bill,
|
||||
// fromTransactionEntry: ILandedCostTransactionEntry,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// const ledgerEntries = this.getLandedCostGLEntries(
|
||||
// allocatedLandedCost,
|
||||
// bill,
|
||||
// fromTransactionEntry
|
||||
// );
|
||||
// await this.ledgerRepository.saveLedgerEntries(ledgerEntries, trx);
|
||||
// };
|
||||
|
||||
/**
|
||||
* Generates and writes GL entries of the given landed cost.
|
||||
* @param {number} billLandedCostId
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public createLandedCostGLEntries = async (
|
||||
billLandedCostId: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
// Retrieve the bill landed cost transacion with associated
|
||||
// allocated entries and items.
|
||||
const allocatedLandedCost = await this.billLandedCostModel().query(trx)
|
||||
.findById(billLandedCostId)
|
||||
.withGraphFetched('bill')
|
||||
.withGraphFetched('allocateEntries.itemEntry.item');
|
||||
// /**
|
||||
// * Generates and writes GL entries of the given landed cost.
|
||||
// * @param {number} billLandedCostId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public createLandedCostGLEntries = async (
|
||||
// billLandedCostId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// // Retrieve the bill landed cost transacion with associated
|
||||
// // allocated entries and items.
|
||||
// const allocatedLandedCost = await this.billLandedCostModel().query(trx)
|
||||
// .findById(billLandedCostId)
|
||||
// .withGraphFetched('bill')
|
||||
// .withGraphFetched('allocateEntries.itemEntry.item');
|
||||
|
||||
// Retrieve the allocated from transactione entry.
|
||||
const transactionEntry = await this.getLandedCostEntry(
|
||||
allocatedLandedCost.fromTransactionType,
|
||||
allocatedLandedCost.fromTransactionId,
|
||||
allocatedLandedCost.fromTransactionEntryId
|
||||
);
|
||||
// Writes the given landed cost GL entries to the storage layer.
|
||||
await this.writeLandedCostGLEntries(
|
||||
allocatedLandedCost,
|
||||
allocatedLandedCost.bill,
|
||||
transactionEntry,
|
||||
trx
|
||||
);
|
||||
};
|
||||
// // Retrieve the allocated from transactione entry.
|
||||
// const transactionEntry = await this.getLandedCostEntry(
|
||||
// allocatedLandedCost.fromTransactionType,
|
||||
// allocatedLandedCost.fromTransactionId,
|
||||
// allocatedLandedCost.fromTransactionEntryId
|
||||
// );
|
||||
// // Writes the given landed cost GL entries to the storage layer.
|
||||
// await this.writeLandedCostGLEntries(
|
||||
// allocatedLandedCost,
|
||||
// allocatedLandedCost.bill,
|
||||
// transactionEntry,
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
|
||||
/**
|
||||
* Reverts GL entries of the given allocated landed cost transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} landedCostId
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public revertLandedCostGLEntries = async (
|
||||
landedCostId: number,
|
||||
trx: Knex.Transaction
|
||||
) => {
|
||||
await this.journalService.revertJournalTransactions(
|
||||
landedCostId,
|
||||
'LandedCost',
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
// /**
|
||||
// * Reverts GL entries of the given allocated landed cost transaction.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} landedCostId
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public revertLandedCostGLEntries = async (
|
||||
// landedCostId: number,
|
||||
// trx: Knex.Transaction
|
||||
// ) => {
|
||||
// await this.journalService.revertJournalTransactions(
|
||||
// landedCostId,
|
||||
// 'LandedCost',
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
// }
|
||||
@@ -3,15 +3,14 @@ import {
|
||||
IAllocatedLandedCostDeletedPayload,
|
||||
} from '../types/BillLandedCosts.types';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { LandedCostGLEntries } from './LandedCostGLEntries.service';
|
||||
// import { LandedCostGLEntries } from './LandedCostGLEntries.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class LandedCostGLEntriesSubscriber {
|
||||
constructor(
|
||||
private readonly billLandedCostGLEntries: LandedCostGLEntries,
|
||||
) {}
|
||||
constructor() // private readonly billLandedCostGLEntries: LandedCostGLEntries,
|
||||
{}
|
||||
|
||||
/**
|
||||
* Writes GL entries once landed cost transaction created.
|
||||
@@ -22,11 +21,11 @@ export class LandedCostGLEntriesSubscriber {
|
||||
billLandedCost,
|
||||
trx,
|
||||
}: IAllocatedLandedCostCreatedPayload) {
|
||||
await this.billLandedCostGLEntries.createLandedCostGLEntries(
|
||||
billLandedCost.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
// await this.billLandedCostGLEntries.createLandedCostGLEntries(
|
||||
// billLandedCost.id,
|
||||
// trx
|
||||
// );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts GL entries associated to landed cost transaction once deleted.
|
||||
@@ -37,9 +36,9 @@ export class LandedCostGLEntriesSubscriber {
|
||||
oldBillLandedCost,
|
||||
trx,
|
||||
}: IAllocatedLandedCostDeletedPayload) {
|
||||
await this.billLandedCostGLEntries.revertLandedCostGLEntries(
|
||||
oldBillLandedCost.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
// await this.billLandedCostGLEntries.revertLandedCostGLEntries(
|
||||
// oldBillLandedCost.id,
|
||||
// trx
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,8 @@ export class LandedCostSyncCostTransactions {
|
||||
|
||||
/**
|
||||
* Allocate the landed cost amount to cost transactions.
|
||||
* @param {number} tenantId -
|
||||
* @param {string} transactionType
|
||||
* @param {number} transactionId
|
||||
* @param {string} transactionType - Transaction type.
|
||||
* @param {number} transactionId - Transaction id.
|
||||
*/
|
||||
public incrementLandedCostAmount = async (
|
||||
transactionType: string,
|
||||
@@ -22,18 +21,18 @@ export class LandedCostSyncCostTransactions {
|
||||
amount: number,
|
||||
trx?: Knex.Transaction
|
||||
): Promise<void> => {
|
||||
const Model = this.transactionLandedCost.getModel(
|
||||
const Model = await this.transactionLandedCost.getModel(
|
||||
transactionType
|
||||
);
|
||||
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
||||
|
||||
// Increment the landed cost transaction amount.
|
||||
await Model.query(trx)
|
||||
await Model().query(trx)
|
||||
.where('id', transactionId)
|
||||
.increment('allocatedCostAmount', amount);
|
||||
|
||||
// Increment the landed cost entry.
|
||||
await Model.relatedQuery(relation, trx)
|
||||
await Model().relatedQuery(relation, trx)
|
||||
.for(transactionId)
|
||||
.where('id', transactionEntryId)
|
||||
.increment('allocatedCostAmount', amount);
|
||||
@@ -54,18 +53,18 @@ export class LandedCostSyncCostTransactions {
|
||||
amount: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
const Model = this.transactionLandedCost.getModel(
|
||||
const Model = await this.transactionLandedCost.getModel(
|
||||
transactionType
|
||||
);
|
||||
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
||||
|
||||
// Decrement the allocate cost amount of cost transaction.
|
||||
await Model.query(trx)
|
||||
await Model().query(trx)
|
||||
.where('id', transactionId)
|
||||
.decrement('allocatedCostAmount', amount);
|
||||
|
||||
// Decrement the allocated cost amount cost transaction entry.
|
||||
await Model.relatedQuery(relation, trx)
|
||||
await Model().relatedQuery(relation, trx)
|
||||
.for(transactionId)
|
||||
.where('id', transactionEntryId)
|
||||
.decrement('allocatedCostAmount', amount);
|
||||
|
||||
@@ -1,70 +1,73 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ref } from 'objection';
|
||||
import { curry, pipe, map } from 'lodash/fp';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
ILandedCostTransactionsQueryDTO,
|
||||
ILandedCostTransaction,
|
||||
ILandedCostTransactionDOJO,
|
||||
ILandedCostTransactionEntry,
|
||||
ILandedCostTransactionEntryDOJO,
|
||||
} from '@/interfaces';
|
||||
import TransactionLandedCost from './TransctionLandedCost';
|
||||
import { formatNumber } from 'utils';
|
||||
} from '../types/BillLandedCosts.types';
|
||||
import { TransactionLandedCost } from './TransctionLandedCost.service';
|
||||
import { formatNumber } from '@/utils/format-number';
|
||||
import { LandedCostTransactionsQueryDto } from '../dtos/LandedCostTransactionsQuery.dto';
|
||||
|
||||
@Service()
|
||||
export default class LandedCostTranasctions {
|
||||
@Inject()
|
||||
private transactionLandedCost: TransactionLandedCost;
|
||||
@Injectable()
|
||||
export class LandedCostTranasctions {
|
||||
constructor(private readonly transactionLandedCost: TransactionLandedCost) {}
|
||||
|
||||
/**
|
||||
* Retrieve the landed costs based on the given query.
|
||||
* @param {number} tenantId
|
||||
* @param {ILandedCostTransactionsQueryDTO} query
|
||||
* @param {LandedCostTransactionsQueryDto} query -
|
||||
* @returns {Promise<ILandedCostTransaction[]>}
|
||||
*/
|
||||
public getLandedCostTransactions = async (
|
||||
query: ILandedCostTransactionsQueryDTO
|
||||
query: LandedCostTransactionsQueryDto,
|
||||
): Promise<ILandedCostTransaction[]> => {
|
||||
const { transactionType } = query;
|
||||
const Model = this.transactionLandedCost.getModel(
|
||||
query.transactionType
|
||||
const Model = await this.transactionLandedCost.getModel(
|
||||
query.transactionType,
|
||||
);
|
||||
// Retrieve the model entities.
|
||||
const transactions = await Model.query().onBuild((q) => {
|
||||
q.where('allocated_cost_amount', '<', ref('landed_cost_amount'));
|
||||
const transactions = await Model()
|
||||
.query()
|
||||
.onBuild((q) => {
|
||||
q.where('allocated_cost_amount', '<', ref('landed_cost_amount'));
|
||||
|
||||
if (query.transactionType === 'Bill') {
|
||||
q.withGraphFetched('entries.item');
|
||||
} else if (query.transactionType === 'Expense') {
|
||||
q.withGraphFetched('categories.expenseAccount');
|
||||
}
|
||||
});
|
||||
const transformLandedCost =
|
||||
this.transactionLandedCost.transformToLandedCost(transactionType);
|
||||
if (query.transactionType === 'Bill') {
|
||||
q.withGraphFetched('entries.item');
|
||||
} else if (query.transactionType === 'Expense') {
|
||||
q.withGraphFetched('categories.expenseAccount');
|
||||
}
|
||||
});
|
||||
const transformLandedCost = curry(
|
||||
this.transactionLandedCost.transformToLandedCost,
|
||||
)(transactionType);
|
||||
|
||||
return R.compose(
|
||||
return pipe(
|
||||
this.transformLandedCostTransactions,
|
||||
R.map(transformLandedCost)
|
||||
R.map(transformLandedCost),
|
||||
)(transactions);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param transactions
|
||||
* @returns
|
||||
* Transformes the landed cost transactions.
|
||||
* @param {ILandedCostTransaction[]} transactions
|
||||
* @returns {ILandedCostTransactionDOJO[]}
|
||||
*/
|
||||
public transformLandedCostTransactions = (
|
||||
transactions: ILandedCostTransaction[]
|
||||
transactions: ILandedCostTransaction[],
|
||||
) => {
|
||||
return R.map(this.transformLandedCostTransaction)(transactions);
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes the landed cost transaction.
|
||||
* @param {ILandedCostTransaction} transaction
|
||||
* @param {ILandedCostTransaction} transaction - Landed cost transaction.
|
||||
* @returns {ILandedCostTransactionDOJO}
|
||||
*/
|
||||
public transformLandedCostTransaction = (
|
||||
transaction: ILandedCostTransaction
|
||||
transaction: ILandedCostTransaction,
|
||||
): ILandedCostTransactionDOJO => {
|
||||
const { currencyCode } = transaction;
|
||||
|
||||
@@ -74,57 +77,60 @@ export default class LandedCostTranasctions {
|
||||
// Formatted transaction unallocated cost amount.
|
||||
const formattedUnallocatedCostAmount = formatNumber(
|
||||
transaction.unallocatedCostAmount,
|
||||
{ currencyCode }
|
||||
{ currencyCode },
|
||||
);
|
||||
// Formatted transaction allocated cost amount.
|
||||
const formattedAllocatedCostAmount = formatNumber(
|
||||
transaction.allocatedCostAmount,
|
||||
{ currencyCode }
|
||||
{ currencyCode },
|
||||
);
|
||||
const transformLandedCostEntry = R.curry(this.transformLandedCostEntry)(
|
||||
transaction,
|
||||
);
|
||||
const entries = R.map<
|
||||
ILandedCostTransactionEntry,
|
||||
ILandedCostTransactionEntryDOJO
|
||||
>(transformLandedCostEntry)(transaction.entries);
|
||||
|
||||
return {
|
||||
...transaction,
|
||||
formattedAmount,
|
||||
formattedUnallocatedCostAmount,
|
||||
formattedAllocatedCostAmount,
|
||||
entries: R.map(this.transformLandedCostEntry(transaction))(
|
||||
transaction.entries
|
||||
),
|
||||
entries,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {ILandedCostTransaction} transaction
|
||||
* @param {ILandedCostTransactionEntry} entry
|
||||
* Transformes the landed cost transaction entry.
|
||||
* @param {ILandedCostTransaction} transaction - Landed cost transaction.
|
||||
* @param {ILandedCostTransactionEntry} entry - Landed cost transaction entry.
|
||||
* @returns {ILandedCostTransactionEntryDOJO}
|
||||
*/
|
||||
public transformLandedCostEntry = R.curry(
|
||||
(
|
||||
transaction: ILandedCostTransaction,
|
||||
entry: ILandedCostTransactionEntry
|
||||
): ILandedCostTransactionEntryDOJO => {
|
||||
const { currencyCode } = transaction;
|
||||
public transformLandedCostEntry = (
|
||||
transaction: ILandedCostTransaction,
|
||||
entry: ILandedCostTransactionEntry,
|
||||
): ILandedCostTransactionEntryDOJO => {
|
||||
const { currencyCode } = transaction;
|
||||
|
||||
// Formatted entry amount.
|
||||
const formattedAmount = formatNumber(entry.amount, { currencyCode });
|
||||
// Formatted entry amount.
|
||||
const formattedAmount = formatNumber(entry.amount, { currencyCode });
|
||||
|
||||
// Formatted entry unallocated cost amount.
|
||||
const formattedUnallocatedCostAmount = formatNumber(
|
||||
entry.unallocatedCostAmount,
|
||||
{ currencyCode }
|
||||
);
|
||||
// Formatted entry allocated cost amount.
|
||||
const formattedAllocatedCostAmount = formatNumber(
|
||||
entry.allocatedCostAmount,
|
||||
{ currencyCode }
|
||||
);
|
||||
return {
|
||||
...entry,
|
||||
formattedAmount,
|
||||
formattedUnallocatedCostAmount,
|
||||
formattedAllocatedCostAmount,
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
// Formatted entry unallocated cost amount.
|
||||
const formattedUnallocatedCostAmount = formatNumber(
|
||||
entry.unallocatedCostAmount,
|
||||
{ currencyCode },
|
||||
);
|
||||
// Formatted entry allocated cost amount.
|
||||
const formattedAllocatedCostAmount = formatNumber(
|
||||
entry.allocatedCostAmount,
|
||||
{ currencyCode },
|
||||
);
|
||||
return {
|
||||
...entry,
|
||||
formattedAmount,
|
||||
formattedUnallocatedCostAmount,
|
||||
formattedAllocatedCostAmount,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { events } from '@/common/events/events';
|
||||
import { IAllocatedLandedCostDeletedPayload } from '../types/BillLandedCosts.types';
|
||||
import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { BillLandedCost } from '../models/BillLandedCost';
|
||||
|
||||
@Injectable()
|
||||
export class RevertAllocatedLandedCost extends BaseLandedCostService {
|
||||
@@ -15,11 +14,6 @@ export class RevertAllocatedLandedCost extends BaseLandedCostService {
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly uow: UnitOfWork,
|
||||
|
||||
@Inject(BillLandedCost.name)
|
||||
private readonly billLandedCostModel: TenantModelProxy<
|
||||
typeof BillLandedCost
|
||||
>,
|
||||
|
||||
@Inject(BillLandedCostEntry.name)
|
||||
private readonly billLandedCostEntryModel: TenantModelProxy<
|
||||
typeof BillLandedCostEntry
|
||||
|
||||
@@ -3,35 +3,46 @@ import { Model } from 'objection';
|
||||
import {
|
||||
ILandedCostTransaction,
|
||||
ILandedCostTransactionEntry,
|
||||
LandedCostTransactionModel,
|
||||
LandedCostTransactionType,
|
||||
} from '../types/BillLandedCosts.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { BillLandedCost } from '../models/BillLandedCost';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { ContextIdFactory, ModuleRef } from '@nestjs/core';
|
||||
import { sanitizeModelName } from '@/utils/sanitize-model-name';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ExpenseLandedCost } from './ExpenseLandedCost.service';
|
||||
import { BillLandedCost } from './BillLandedCost.service';
|
||||
import { ERRORS } from '../utils';
|
||||
import { ExpenseLandedCost } from '../models/ExpenseLandedCost';
|
||||
|
||||
@Injectable()
|
||||
export class TransactionLandedCost {
|
||||
constructor(
|
||||
private readonly billLandedCost: BillLandedCost,
|
||||
private readonly expenseLandedCost: ExpenseLandedCost,
|
||||
private readonly moduleRef: ModuleRef,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve the cost transaction code model.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {string} transactionType - Transaction type.
|
||||
* @returns
|
||||
*/
|
||||
public getModel = (tenantId: number, transactionType: string): Model => {
|
||||
const Models = this.tenancy.models(tenantId);
|
||||
const Model = Models[transactionType];
|
||||
public getModel = async (
|
||||
transactionType: string,
|
||||
): Promise<TenantModelProxy<typeof Model>> => {
|
||||
const contextId = ContextIdFactory.create();
|
||||
const modelName = sanitizeModelName(transactionType);
|
||||
|
||||
if (!Model) {
|
||||
const instance = await this.moduleRef.resolve(modelName, contextId, {
|
||||
strict: false,
|
||||
});
|
||||
if (!instance) {
|
||||
throw new ServiceError(ERRORS.COST_TYPE_UNDEFINED);
|
||||
}
|
||||
return Model;
|
||||
return instance;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -40,10 +51,10 @@ export class TransactionLandedCost {
|
||||
* @param {IBill|IExpense} transaction - Expense or bill transaction.
|
||||
* @returns {ILandedCostTransaction}
|
||||
*/
|
||||
public transformToLandedCost = R.curry(
|
||||
public transformToLandedCost =
|
||||
(
|
||||
transactionType: string,
|
||||
transaction: Bill | Expense,
|
||||
transactionType: LandedCostTransactionType,
|
||||
transaction: LandedCostTransactionModel,
|
||||
): ILandedCostTransaction => {
|
||||
return R.compose(
|
||||
R.when(
|
||||
@@ -54,9 +65,8 @@ export class TransactionLandedCost {
|
||||
R.always(transactionType === 'Expense'),
|
||||
this.expenseLandedCost.transformToLandedCost,
|
||||
),
|
||||
)(transaction);
|
||||
},
|
||||
);
|
||||
)(transaction) as ILandedCostTransaction;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes the given expense or bill entry to landed cost transaction entry.
|
||||
@@ -65,7 +75,7 @@ export class TransactionLandedCost {
|
||||
* @returns {ILandedCostTransactionEntry}
|
||||
*/
|
||||
public transformToLandedCostEntry = (
|
||||
transactionType: 'Bill' | 'Expense',
|
||||
transactionType: LandedCostTransactionType,
|
||||
transactionEntry,
|
||||
): ILandedCostTransactionEntry => {
|
||||
return R.compose(
|
||||
@@ -77,6 +87,6 @@ export class TransactionLandedCost {
|
||||
R.always(transactionType === 'Expense'),
|
||||
this.expenseLandedCost.transformToLandedCostEntry,
|
||||
),
|
||||
)(transactionEntry);
|
||||
)(transactionEntry) as ILandedCostTransactionEntry;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@ import {
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ToNumber } from '@/common/decorators/Validators';
|
||||
import { LandedCostTransactionType } from '../types/BillLandedCosts.types';
|
||||
|
||||
class AllocateBillLandedCostItemDto {
|
||||
export class AllocateBillLandedCostItemDto {
|
||||
@IsInt()
|
||||
@ToNumber()
|
||||
entryId: number;
|
||||
@@ -26,7 +27,7 @@ export class AllocateBillLandedCostDto {
|
||||
transactionId: number;
|
||||
|
||||
@IsIn(['Expense', 'Bill'])
|
||||
transactionType: string;
|
||||
transactionType: LandedCostTransactionType;
|
||||
|
||||
@IsInt()
|
||||
transactionEntryId: number;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { IsDateString, IsEnum, IsIn, IsNotEmpty, IsOptional, IsString } from "class-validator";
|
||||
import { LandedCostTransactionType } from "../types/BillLandedCosts.types";
|
||||
|
||||
|
||||
export class LandedCostTransactionsQueryDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@IsIn(['Expense', 'Bill'])
|
||||
transactionType: LandedCostTransactionType;
|
||||
|
||||
@IsDateString()
|
||||
@IsOptional()
|
||||
date: string;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { ModelObject } from 'objection';
|
||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||
|
||||
export interface ILandedCostItemDTO {
|
||||
entryId: number;
|
||||
@@ -140,3 +142,7 @@ interface ICommonEntryDTO {
|
||||
export interface ICommonLandedCostEntryDTO extends ICommonEntryDTO {
|
||||
landedCost?: boolean;
|
||||
}
|
||||
|
||||
|
||||
export type LandedCostTransactionType = 'Bill' | 'Expense';
|
||||
export type LandedCostTransactionModel = Bill | Expense;
|
||||
@@ -1,5 +1,7 @@
|
||||
import { IItemEntry, IBillLandedCostTransactionEntry } from '@/interfaces';
|
||||
import { transformToMap } from 'utils';
|
||||
import { ModelObject } from 'objection';
|
||||
import { transformToMap } from '@/utils/transform-to-key';
|
||||
import { IBillLandedCostTransactionEntry } from './types/BillLandedCosts.types';
|
||||
import { ItemEntry } from '../TransactionItemEntry/models/ItemEntry';
|
||||
|
||||
export const ERRORS = {
|
||||
COST_TYPE_UNDEFINED: 'COST_TYPE_UNDEFINED',
|
||||
@@ -23,8 +25,8 @@ export const ERRORS = {
|
||||
*/
|
||||
export const mergeLocatedWithBillEntries = (
|
||||
locatedEntries: IBillLandedCostTransactionEntry[],
|
||||
billEntries: IItemEntry[]
|
||||
): (IBillLandedCostTransactionEntry & { entry: IItemEntry })[] => {
|
||||
billEntries: ModelObject<ItemEntry>[]
|
||||
): (IBillLandedCostTransactionEntry & { entry: ModelObject<ItemEntry> })[] => {
|
||||
const billEntriesByEntryId = transformToMap(billEntries, 'id');
|
||||
|
||||
return locatedEntries.map((entry) => ({
|
||||
|
||||
Reference in New Issue
Block a user