mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 15:50:32 +00:00
refactor(nestjs): landed cost
This commit is contained in:
@@ -92,6 +92,7 @@ import { ContactsModule } from '../Contacts/Contacts.module';
|
|||||||
import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
|
import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module';
|
||||||
import { BankingCategorizeModule } from '../BankingCategorize/BankingCategorize.module';
|
import { BankingCategorizeModule } from '../BankingCategorize/BankingCategorize.module';
|
||||||
import { TenantModelsInitializeModule } from '../Tenancy/TenantModelsInitialize.module';
|
import { TenantModelsInitializeModule } from '../Tenancy/TenantModelsInitialize.module';
|
||||||
|
import { BillLandedCostsModule } from '../BillLandedCosts/BillLandedCosts.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -174,6 +175,7 @@ import { TenantModelsInitializeModule } from '../Tenancy/TenantModelsInitialize.
|
|||||||
SaleEstimatesModule,
|
SaleEstimatesModule,
|
||||||
SaleReceiptsModule,
|
SaleReceiptsModule,
|
||||||
BillsModule,
|
BillsModule,
|
||||||
|
BillLandedCostsModule,
|
||||||
ManualJournalsModule,
|
ManualJournalsModule,
|
||||||
CreditNotesModule,
|
CreditNotesModule,
|
||||||
VendorCreditsModule,
|
VendorCreditsModule,
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { Inject } from '@nestjs/common';
|
import { Inject } from '@nestjs/common';
|
||||||
import { difference, sumBy } from 'lodash';
|
import { difference, sumBy } from 'lodash';
|
||||||
import {
|
import {
|
||||||
ILandedCostItemDTO,
|
|
||||||
ILandedCostDTO,
|
|
||||||
IBillLandedCostTransaction,
|
|
||||||
ILandedCostTransaction,
|
ILandedCostTransaction,
|
||||||
ILandedCostTransactionEntry,
|
ILandedCostTransactionEntry,
|
||||||
|
LandedCostTransactionModel,
|
||||||
|
LandedCostTransactionType,
|
||||||
} from './types/BillLandedCosts.types';
|
} from './types/BillLandedCosts.types';
|
||||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||||
import { BillLandedCost } from './models/BillLandedCost';
|
import { BillLandedCost } from './models/BillLandedCost';
|
||||||
@@ -14,13 +13,19 @@ import { CONFIG, ERRORS } from './utils';
|
|||||||
import { ItemEntry } from '../TransactionItemEntry/models/ItemEntry';
|
import { ItemEntry } from '../TransactionItemEntry/models/ItemEntry';
|
||||||
import { Bill } from '../Bills/models/Bill';
|
import { Bill } from '../Bills/models/Bill';
|
||||||
import { TransactionLandedCost } from './commands/TransctionLandedCost.service';
|
import { TransactionLandedCost } from './commands/TransctionLandedCost.service';
|
||||||
|
import {
|
||||||
|
AllocateBillLandedCostDto,
|
||||||
|
AllocateBillLandedCostItemDto,
|
||||||
|
} from './dtos/AllocateBillLandedCost.dto';
|
||||||
|
|
||||||
export class BaseLandedCostService {
|
export class BaseLandedCostService {
|
||||||
@Inject()
|
@Inject()
|
||||||
public readonly transactionLandedCost: TransactionLandedCost;
|
protected readonly transactionLandedCost: TransactionLandedCost;
|
||||||
|
|
||||||
@Inject(BillLandedCost.name)
|
@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.
|
* Validates allocate cost items association with the purchase invoice entries.
|
||||||
@@ -29,7 +34,7 @@ export class BaseLandedCostService {
|
|||||||
*/
|
*/
|
||||||
protected validateAllocateCostItems = (
|
protected validateAllocateCostItems = (
|
||||||
purchaseInvoiceEntries: ItemEntry[],
|
purchaseInvoiceEntries: ItemEntry[],
|
||||||
landedCostItems: ILandedCostItemDTO[],
|
landedCostItems: AllocateBillLandedCostItemDto[],
|
||||||
): void => {
|
): void => {
|
||||||
// Purchase invoice entries items ids.
|
// Purchase invoice entries items ids.
|
||||||
const purchaseInvoiceItems = purchaseInvoiceEntries.map((e) => e.id);
|
const purchaseInvoiceItems = purchaseInvoiceEntries.map((e) => e.id);
|
||||||
@@ -55,7 +60,7 @@ export class BaseLandedCostService {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
protected transformToBillLandedCost(
|
protected transformToBillLandedCost(
|
||||||
landedCostDTO: ILandedCostDTO,
|
landedCostDTO: AllocateBillLandedCostDto,
|
||||||
bill: Bill,
|
bill: Bill,
|
||||||
costTransaction: ILandedCostTransaction,
|
costTransaction: ILandedCostTransaction,
|
||||||
costTransactionEntry: ILandedCostTransactionEntry,
|
costTransactionEntry: ILandedCostTransactionEntry,
|
||||||
@@ -88,20 +93,18 @@ export class BaseLandedCostService {
|
|||||||
* @param {transactionId} transactionId -
|
* @param {transactionId} transactionId -
|
||||||
*/
|
*/
|
||||||
public getLandedCostOrThrowError = async (
|
public getLandedCostOrThrowError = async (
|
||||||
transactionType: string,
|
transactionType: LandedCostTransactionType,
|
||||||
transactionId: number,
|
transactionId: number,
|
||||||
) => {
|
) => {
|
||||||
const Model = this.transactionLandedCost.getModel(
|
const Model = await this.transactionLandedCost.getModel(transactionType);
|
||||||
transactionType,
|
const model = await Model().query().findById(transactionId);
|
||||||
);
|
|
||||||
const model = await Model.query().findById(transactionId);
|
|
||||||
|
|
||||||
if (!model) {
|
if (!model) {
|
||||||
throw new ServiceError(ERRORS.LANDED_COST_TRANSACTION_NOT_FOUND);
|
throw new ServiceError(ERRORS.LANDED_COST_TRANSACTION_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return this.transactionLandedCost.transformToLandedCost(
|
return this.transactionLandedCost.transformToLandedCost(
|
||||||
transactionType,
|
transactionType,
|
||||||
model,
|
model as LandedCostTransactionModel,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,13 +120,11 @@ export class BaseLandedCostService {
|
|||||||
transactionId: number,
|
transactionId: number,
|
||||||
transactionEntryId: number,
|
transactionEntryId: number,
|
||||||
): Promise<any> => {
|
): Promise<any> => {
|
||||||
const Model = this.transactionLandedCost.getModel(
|
const Model = await this.transactionLandedCost.getModel(transactionType);
|
||||||
tenantId,
|
|
||||||
transactionType,
|
|
||||||
);
|
|
||||||
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
||||||
|
|
||||||
const entry = await Model.relatedQuery(relation)
|
const entry = await Model()
|
||||||
|
.relatedQuery(relation)
|
||||||
.for(transactionId)
|
.for(transactionId)
|
||||||
.findOne('id', transactionEntryId)
|
.findOne('id', transactionEntryId)
|
||||||
.where('landedCost', true)
|
.where('landedCost', true)
|
||||||
@@ -139,7 +140,7 @@ export class BaseLandedCostService {
|
|||||||
throw new ServiceError(ERRORS.LANDED_COST_ENTRY_NOT_FOUND);
|
throw new ServiceError(ERRORS.LANDED_COST_ENTRY_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return this.transactionLandedCost.transformToLandedCostEntry(
|
return this.transactionLandedCost.transformToLandedCostEntry(
|
||||||
transactionType,
|
transactionType as LandedCostTransactionType,
|
||||||
entry,
|
entry,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -150,7 +151,7 @@ export class BaseLandedCostService {
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
protected getAllocateItemsCostTotal = (
|
protected getAllocateItemsCostTotal = (
|
||||||
landedCostDTO: ILandedCostDTO,
|
landedCostDTO: AllocateBillLandedCostDto,
|
||||||
): number => {
|
): number => {
|
||||||
return sumBy(landedCostDTO.items, 'cost');
|
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 { TransactionLandedCostEntriesService } from './TransactionLandedCostEntries.service';
|
||||||
import { AllocateLandedCostService } from './commands/AllocateLandedCost.service';
|
import { AllocateLandedCostService } from './commands/AllocateLandedCost.service';
|
||||||
import { LandedCostGLEntriesSubscriber } from './commands/LandedCostGLEntries.subscriber';
|
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 { LandedCostSyncCostTransactions } from './commands/LandedCostSyncCostTransactions.service';
|
||||||
import { LandedCostSyncCostTransactionsSubscriber } from './commands/LandedCostSyncCostTransactions.subscriber';
|
import { LandedCostSyncCostTransactionsSubscriber } from './commands/LandedCostSyncCostTransactions.subscriber';
|
||||||
import { BillAllocatedLandedCostTransactions } from './commands/BillAllocatedLandedCostTransactions.service';
|
import { BillAllocatedLandedCostTransactions } from './commands/BillAllocatedLandedCostTransactions.service';
|
||||||
import { BillAllocateLandedCostController } from './LandedCost.controller';
|
import { BillAllocateLandedCostController } from './LandedCost.controller';
|
||||||
import { RevertAllocatedLandedCost } from './commands/RevertAllocatedLandedCost.service';
|
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 { LandedCostInventoryTransactions } from './commands/LandedCostInventoryTransactions.service';
|
||||||
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
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({
|
@Module({
|
||||||
imports: [InventoryCostModule],
|
imports: [forwardRef(() => InventoryCostModule)],
|
||||||
providers: [
|
providers: [
|
||||||
AllocateLandedCostService,
|
AllocateLandedCostService,
|
||||||
TransactionLandedCostEntriesService,
|
TransactionLandedCostEntriesService,
|
||||||
BillAllocatedLandedCostTransactions,
|
BillAllocatedLandedCostTransactions,
|
||||||
LandedCostGLEntriesSubscriber,
|
LandedCostGLEntriesSubscriber,
|
||||||
LandedCostGLEntries,
|
TransactionLandedCost,
|
||||||
|
BillLandedCost,
|
||||||
|
ExpenseLandedCost,
|
||||||
LandedCostSyncCostTransactions,
|
LandedCostSyncCostTransactions,
|
||||||
RevertAllocatedLandedCost,
|
RevertAllocatedLandedCost,
|
||||||
LandedCostInventoryTransactions,
|
LandedCostInventoryTransactions,
|
||||||
|
|||||||
@@ -7,32 +7,45 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Query,
|
Query,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
|
||||||
import { AllocateBillLandedCostDto } from './dtos/AllocateBillLandedCost.dto';
|
import { AllocateBillLandedCostDto } from './dtos/AllocateBillLandedCost.dto';
|
||||||
import { AllocateLandedCostService } from './commands/AllocateLandedCost.service';
|
import { AllocateLandedCostService } from './commands/AllocateLandedCost.service';
|
||||||
import { BillAllocatedLandedCostTransactions } from './commands/BillAllocatedLandedCostTransactions.service';
|
import { BillAllocatedLandedCostTransactions } from './commands/BillAllocatedLandedCostTransactions.service';
|
||||||
import { RevertAllocatedLandedCost } from './commands/RevertAllocatedLandedCost.service';
|
import { RevertAllocatedLandedCost } from './commands/RevertAllocatedLandedCost.service';
|
||||||
import { LandedCostTranasctions } from './commands/LandedCostTransactions.service';
|
import { LandedCostTranasctions } from './commands/LandedCostTransactions.service';
|
||||||
|
import { LandedCostTransactionsQueryDto } from './dtos/LandedCostTransactionsQuery.dto';
|
||||||
|
|
||||||
|
@ApiTags('Landed Cost')
|
||||||
@Controller('landed-cost')
|
@Controller('landed-cost')
|
||||||
export class BillAllocateLandedCostController {
|
export class BillAllocateLandedCostController {
|
||||||
constructor(
|
constructor(
|
||||||
private allocateLandedCost: AllocateLandedCostService,
|
private allocateLandedCost: AllocateLandedCostService,
|
||||||
private billAllocatedCostTransactions: BillAllocatedLandedCostTransactions,
|
private billAllocatedCostTransactions: BillAllocatedLandedCostTransactions,
|
||||||
private revertAllocatedLandedCost: RevertAllocatedLandedCost,
|
private revertAllocatedLandedCost: RevertAllocatedLandedCost,
|
||||||
private landedCostTranasctions: LandedCostTranasctions,
|
private landedCostTransactions: LandedCostTranasctions,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get('/transactions')
|
@Get('/transactions')
|
||||||
|
@ApiOperation({ summary: 'Get landed cost transactions' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: 200,
|
||||||
|
description: 'List of landed cost transactions.',
|
||||||
|
})
|
||||||
async getLandedCostTransactions(
|
async getLandedCostTransactions(
|
||||||
@Query('transaction_type') transactionType: string,
|
@Query() query: LandedCostTransactionsQueryDto,
|
||||||
) {
|
) {
|
||||||
const transactions =
|
const transactions =
|
||||||
await this.landedCostTranasctions.getLandedCostTransactions(transactionType);
|
await this.landedCostTransactions.getLandedCostTransactions(query);
|
||||||
|
|
||||||
return transactions;
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/bills/:billId/allocate')
|
@Post('/bills/:billId/allocate')
|
||||||
|
@ApiOperation({ summary: 'Allocate landed cost to bill items' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: 201,
|
||||||
|
description: 'Landed cost allocated successfully.',
|
||||||
|
})
|
||||||
public async calculateLandedCost(
|
public async calculateLandedCost(
|
||||||
@Param('billId') billId: number,
|
@Param('billId') billId: number,
|
||||||
@Body() landedCostDTO: AllocateBillLandedCostDto,
|
@Body() landedCostDTO: AllocateBillLandedCostDto,
|
||||||
@@ -48,37 +61,37 @@ export class BillAllocateLandedCostController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete('/:allocatedLandedCostId')
|
@Delete('/:allocatedLandedCostId')
|
||||||
|
@ApiOperation({ summary: 'Delete allocated landed cost' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: 200,
|
||||||
|
description: 'Allocated landed cost deleted successfully.',
|
||||||
|
})
|
||||||
public async deleteAllocatedLandedCost(
|
public async deleteAllocatedLandedCost(
|
||||||
@Param('allocatedLandedCostId') allocatedLandedCostId: number,
|
@Param('allocatedLandedCostId') allocatedLandedCostId: number,
|
||||||
) {
|
) {
|
||||||
await this.revertAllocatedLandedCost.deleteAllocatedLandedCost(
|
await this.revertAllocatedLandedCost.deleteAllocatedLandedCost(
|
||||||
allocatedLandedCostId,
|
allocatedLandedCostId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: allocatedLandedCostId,
|
id: allocatedLandedCostId,
|
||||||
message: 'The allocated landed cost are delete successfully.',
|
message: 'The allocated landed cost are delete successfully.',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async listLandedCosts(
|
|
||||||
) {
|
|
||||||
const transactions =
|
|
||||||
await this.landedCostTranasctions.getLandedCostTransactions(query);
|
|
||||||
|
|
||||||
return transactions;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Get('/bills/:billId/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) {
|
async getBillLandedCostTransactions(@Param('billId') billId: number) {
|
||||||
const transactions =
|
const data =
|
||||||
await this.billAllocatedCostTransactions.getBillLandedCostTransactions(
|
await this.billAllocatedCostTransactions.getBillLandedCostTransactions(
|
||||||
billId,
|
billId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
billId,
|
billId,
|
||||||
transactions,
|
data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class AllocateLandedCostService extends BaseLandedCostService {
|
|||||||
private readonly billModel: TenantModelProxy<typeof Bill>,
|
private readonly billModel: TenantModelProxy<typeof Bill>,
|
||||||
|
|
||||||
@Inject(BillLandedCost.name)
|
@Inject(BillLandedCost.name)
|
||||||
private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>
|
protected readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ export class AllocateLandedCostService extends BaseLandedCostService {
|
|||||||
const amount = this.getAllocateItemsCostTotal(allocateCostDTO);
|
const amount = this.getAllocateItemsCostTotal(allocateCostDTO);
|
||||||
|
|
||||||
// Retrieve the purchase invoice or throw not found error.
|
// Retrieve the purchase invoice or throw not found error.
|
||||||
const bill = await Bill.query()
|
const bill = await this.billModel().query()
|
||||||
.findById(billId)
|
.findById(billId)
|
||||||
.withGraphFetched('entries')
|
.withGraphFetched('entries')
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
|||||||
import { Bill } from '@/modules/Bills/models/Bill';
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
import { BillLandedCost } from '../models/BillLandedCost';
|
import { BillLandedCost } from '../models/BillLandedCost';
|
||||||
import { IBillLandedCostTransaction } from '../types/BillLandedCosts.types';
|
import { IBillLandedCostTransaction } from '../types/BillLandedCosts.types';
|
||||||
|
import { ModelObject } from 'objection';
|
||||||
|
import { formatNumber } from '@/utils/format-number';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BillAllocatedLandedCostTransactions {
|
export class BillAllocatedLandedCostTransactions {
|
||||||
@@ -23,19 +25,17 @@ export class BillAllocatedLandedCostTransactions {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the bill associated landed cost transactions.
|
* Retrieve the bill associated landed cost transactions.
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {number} billId - Bill id.
|
* @param {number} billId - Bill id.
|
||||||
* @return {Promise<IBillLandedCostTransaction>}
|
* @return {Promise<IBillLandedCostTransaction>}
|
||||||
*/
|
*/
|
||||||
public getBillLandedCostTransactions = async (
|
public getBillLandedCostTransactions = async (
|
||||||
billId: number,
|
billId: number,
|
||||||
): Promise<IBillLandedCostTransaction> => {
|
): Promise<Array<IBillLandedCostTransaction>> => {
|
||||||
// Retrieve the given bill id or throw not found service error.
|
// Retrieve the given bill id or throw not found service error.
|
||||||
const bill = await this.billModel()
|
const bill = await this.billModel()
|
||||||
.query()
|
.query()
|
||||||
.findById(billId)
|
.findById(billId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
// Retrieve the bill associated allocated landed cost with bill and expense entry.
|
// Retrieve the bill associated allocated landed cost with bill and expense entry.
|
||||||
const landedCostTransactions = await this.billLandedCostModel()
|
const landedCostTransactions = await this.billLandedCostModel()
|
||||||
.query()
|
.query()
|
||||||
@@ -45,11 +45,8 @@ export class BillAllocatedLandedCostTransactions {
|
|||||||
.withGraphFetched('allocatedFromExpenseEntry.expenseAccount')
|
.withGraphFetched('allocatedFromExpenseEntry.expenseAccount')
|
||||||
.withGraphFetched('bill');
|
.withGraphFetched('bill');
|
||||||
|
|
||||||
const transactionsJson = this.i18nService.i18nApply(
|
const transactionsJson = landedCostTransactions.map((a) => a.toJSON());
|
||||||
[[qim.$each, 'allocationMethodFormatted']],
|
|
||||||
landedCostTransactions.map((a) => a.toJSON()),
|
|
||||||
tenantId,
|
|
||||||
);
|
|
||||||
return this.transformBillLandedCostTransactions(transactionsJson);
|
return this.transformBillLandedCostTransactions(transactionsJson);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,7 +56,7 @@ export class BillAllocatedLandedCostTransactions {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
private transformBillLandedCostTransactions = (
|
private transformBillLandedCostTransactions = (
|
||||||
landedCostTransactions: IBillLandedCostTransaction[],
|
landedCostTransactions: ModelObject<BillLandedCost>[],
|
||||||
) => {
|
) => {
|
||||||
return landedCostTransactions.map(this.transformBillLandedCostTransaction);
|
return landedCostTransactions.map(this.transformBillLandedCostTransaction);
|
||||||
};
|
};
|
||||||
@@ -70,15 +67,16 @@ export class BillAllocatedLandedCostTransactions {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
private transformBillLandedCostTransaction = (
|
private transformBillLandedCostTransaction = (
|
||||||
transaction: IBillLandedCostTransaction,
|
transaction: ModelObject<BillLandedCost>,
|
||||||
) => {
|
): IBillLandedCostTransaction => {
|
||||||
const getTransactionName = R.curry(this.condBillLandedTransactionName)(
|
const name = this.condBillLandedTransactionName(
|
||||||
transaction.fromTransactionType,
|
transaction.fromTransactionType,
|
||||||
|
transaction,
|
||||||
|
);
|
||||||
|
const description = this.condBillLandedTransactionDescription(
|
||||||
|
transaction.fromTransactionType,
|
||||||
|
transaction,
|
||||||
);
|
);
|
||||||
const getTransactionDesc = R.curry(
|
|
||||||
this.condBillLandedTransactionDescription,
|
|
||||||
)(transaction.fromTransactionType);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
formattedAmount: formatNumber(transaction.amount, {
|
formattedAmount: formatNumber(transaction.amount, {
|
||||||
currencyCode: transaction.currencyCode,
|
currencyCode: transaction.currencyCode,
|
||||||
@@ -87,8 +85,8 @@ export class BillAllocatedLandedCostTransactions {
|
|||||||
'allocatedFromBillEntry',
|
'allocatedFromBillEntry',
|
||||||
'allocatedFromExpenseEntry',
|
'allocatedFromExpenseEntry',
|
||||||
]),
|
]),
|
||||||
name: getTransactionName(transaction),
|
name,
|
||||||
description: getTransactionDesc(transaction),
|
description,
|
||||||
formattedLocalAmount: formatNumber(transaction.localAmount, {
|
formattedLocalAmount: formatNumber(transaction.localAmount, {
|
||||||
currencyCode: 'USD',
|
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 * as R from 'ramda';
|
||||||
import { Knex } from 'knex';
|
// import { Knex } from 'knex';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
// import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { BaseLandedCostService } from '../BaseLandedCost.service';
|
// import { BaseLandedCostService } from '../BaseLandedCost.service';
|
||||||
import { BillLandedCost } from '../models/BillLandedCost';
|
// import { BillLandedCost } from '../models/BillLandedCost';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
// import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { Bill } from '@/modules/Bills/models/Bill';
|
// import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
// import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
||||||
import { ILedger, ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
// import { ILedger, ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||||
import { Ledger } from '@/modules/Ledger/Ledger';
|
// import { Ledger } from '@/modules/Ledger/Ledger';
|
||||||
|
// import { AccountNormal } from '@/interfaces/Account';
|
||||||
|
// import { ILandedCostTransactionEntry } from '../types/BillLandedCosts.types';
|
||||||
|
|
||||||
@Injectable()
|
// @Injectable()
|
||||||
export class LandedCostGLEntries extends BaseLandedCostService {
|
// export class LandedCostGLEntries extends BaseLandedCostService {
|
||||||
constructor(
|
// constructor(
|
||||||
private readonly journalService: JournalPosterService,
|
// private readonly journalService: JournalPosterService,
|
||||||
private readonly ledgerRepository: LedgerRepository,
|
// private readonly ledgerRepository: LedgerRepository,
|
||||||
|
|
||||||
@Inject(BillLandedCost.name)
|
// @Inject(BillLandedCost.name)
|
||||||
private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>,
|
// private readonly billLandedCostModel: TenantModelProxy<typeof BillLandedCost>,
|
||||||
) {
|
// ) {
|
||||||
super();
|
// super();
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Retrieves the landed cost GL common entry.
|
// * Retrieves the landed cost GL common entry.
|
||||||
* @param {IBill} bill
|
// * @param {IBill} bill
|
||||||
* @param {IBillLandedCost} allocatedLandedCost
|
// * @param {IBillLandedCost} allocatedLandedCost
|
||||||
* @returns
|
// * @returns
|
||||||
*/
|
// */
|
||||||
private getLandedCostGLCommonEntry = (
|
// private getLandedCostGLCommonEntry = (
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
allocatedLandedCost: BillLandedCost
|
// allocatedLandedCost: BillLandedCost
|
||||||
) => {
|
// ) => {
|
||||||
return {
|
// return {
|
||||||
date: bill.billDate,
|
// date: bill.billDate,
|
||||||
currencyCode: allocatedLandedCost.currencyCode,
|
// currencyCode: allocatedLandedCost.currencyCode,
|
||||||
exchangeRate: allocatedLandedCost.exchangeRate,
|
// exchangeRate: allocatedLandedCost.exchangeRate,
|
||||||
|
|
||||||
transactionType: 'LandedCost',
|
// transactionType: 'LandedCost',
|
||||||
transactionId: allocatedLandedCost.id,
|
// transactionId: allocatedLandedCost.id,
|
||||||
transactionNumber: bill.billNumber,
|
// transactionNumber: bill.billNumber,
|
||||||
|
|
||||||
referenceNumber: bill.referenceNo,
|
// referenceNumber: bill.referenceNo,
|
||||||
|
|
||||||
credit: 0,
|
// credit: 0,
|
||||||
debit: 0,
|
// debit: 0,
|
||||||
};
|
// };
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Retrieves the landed cost GL inventory entry.
|
// * Retrieves the landed cost GL inventory entry.
|
||||||
* @param {IBill} bill
|
// * @param {IBill} bill
|
||||||
* @param {IBillLandedCost} allocatedLandedCost
|
// * @param {IBillLandedCost} allocatedLandedCost
|
||||||
* @param {IBillLandedCostEntry} allocatedEntry
|
// * @param {IBillLandedCostEntry} allocatedEntry
|
||||||
* @returns {ILedgerEntry}
|
// * @returns {ILedgerEntry}
|
||||||
*/
|
// */
|
||||||
private getLandedCostGLInventoryEntry = (
|
// private getLandedCostGLInventoryEntry = (
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
allocatedLandedCost: BillLandedCost,
|
// allocatedLandedCost: BillLandedCost,
|
||||||
allocatedEntry: BillLandedCostEntry
|
// allocatedEntry: BillLandedCostEntry
|
||||||
): ILedgerEntry => {
|
// ): ILedgerEntry => {
|
||||||
const commonEntry = this.getLandedCostGLCommonEntry(
|
// const commonEntry = this.getLandedCostGLCommonEntry(
|
||||||
bill,
|
// bill,
|
||||||
allocatedLandedCost
|
// allocatedLandedCost
|
||||||
);
|
// );
|
||||||
return {
|
// return {
|
||||||
...commonEntry,
|
// ...commonEntry,
|
||||||
debit: allocatedLandedCost.localAmount,
|
// debit: allocatedLandedCost.localAmount,
|
||||||
accountId: allocatedEntry.itemEntry.item.inventoryAccountId,
|
// accountId: allocatedEntry.itemEntry.item.inventoryAccountId,
|
||||||
index: 1,
|
// index: 1,
|
||||||
accountNormal: AccountNormal.DEBIT,
|
// accountNormal: AccountNormal.DEBIT,
|
||||||
};
|
// };
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Retrieves the landed cost GL cost entry.
|
// * Retrieves the landed cost GL cost entry.
|
||||||
* @param {IBill} bill
|
// * @param {IBill} bill
|
||||||
* @param {IBillLandedCost} allocatedLandedCost
|
// * @param {IBillLandedCost} allocatedLandedCost
|
||||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||||
* @returns {ILedgerEntry}
|
// * @returns {ILedgerEntry}
|
||||||
*/
|
// */
|
||||||
private getLandedCostGLCostEntry = (
|
// private getLandedCostGLCostEntry = (
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
allocatedLandedCost: BillLandedCost,
|
// allocatedLandedCost: BillLandedCost,
|
||||||
fromTransactionEntry: ILandedCostTransactionEntry
|
// fromTransactionEntry: ILandedCostTransactionEntry
|
||||||
): ILedgerEntry => {
|
// ): ILedgerEntry => {
|
||||||
const commonEntry = this.getLandedCostGLCommonEntry(
|
// const commonEntry = this.getLandedCostGLCommonEntry(
|
||||||
bill,
|
// bill,
|
||||||
allocatedLandedCost
|
// allocatedLandedCost
|
||||||
);
|
// );
|
||||||
return {
|
// return {
|
||||||
...commonEntry,
|
// ...commonEntry,
|
||||||
credit: allocatedLandedCost.localAmount,
|
// credit: allocatedLandedCost.localAmount,
|
||||||
accountId: fromTransactionEntry.costAccountId,
|
// accountId: fromTransactionEntry.costAccountId,
|
||||||
index: 2,
|
// index: 2,
|
||||||
accountNormal: AccountNormal.CREDIT,
|
// accountNormal: AccountNormal.CREDIT,
|
||||||
};
|
// };
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Retrieve allocated landed cost entry GL entries.
|
// * Retrieve allocated landed cost entry GL entries.
|
||||||
* @param {IBill} bill
|
// * @param {IBill} bill
|
||||||
* @param {IBillLandedCost} allocatedLandedCost
|
// * @param {IBillLandedCost} allocatedLandedCost
|
||||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||||
* @param {IBillLandedCostEntry} allocatedEntry
|
// * @param {IBillLandedCostEntry} allocatedEntry
|
||||||
* @returns {ILedgerEntry}
|
// * @returns {ILedgerEntry}
|
||||||
*/
|
// */
|
||||||
private getLandedCostGLAllocateEntry = R.curry(
|
// private getLandedCostGLAllocateEntry = R.curry(
|
||||||
(
|
// (
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
allocatedLandedCost: BillLandedCost,
|
// allocatedLandedCost: BillLandedCost,
|
||||||
fromTransactionEntry: LandedCostTransactionEntry,
|
// fromTransactionEntry: ILandedCostTransactionEntry,
|
||||||
allocatedEntry: BillLandedCostEntry
|
// allocatedEntry: BillLandedCostEntry
|
||||||
): ILedgerEntry[] => {
|
// ): ILedgerEntry[] => {
|
||||||
const inventoryEntry = this.getLandedCostGLInventoryEntry(
|
// const inventoryEntry = this.getLandedCostGLInventoryEntry(
|
||||||
bill,
|
// bill,
|
||||||
allocatedLandedCost,
|
// allocatedLandedCost,
|
||||||
allocatedEntry
|
// allocatedEntry
|
||||||
);
|
// );
|
||||||
const costEntry = this.getLandedCostGLCostEntry(
|
// const costEntry = this.getLandedCostGLCostEntry(
|
||||||
bill,
|
// bill,
|
||||||
allocatedLandedCost,
|
// allocatedLandedCost,
|
||||||
fromTransactionEntry
|
// fromTransactionEntry
|
||||||
);
|
// );
|
||||||
return [inventoryEntry, costEntry];
|
// return [inventoryEntry, costEntry];
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Compose the landed cost GL entries.
|
// * Compose the landed cost GL entries.
|
||||||
* @param {BillLandedCost} allocatedLandedCost
|
// * @param {BillLandedCost} allocatedLandedCost
|
||||||
* @param {Bill} bill
|
// * @param {Bill} bill
|
||||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||||
* @returns {ILedgerEntry[]}
|
// * @returns {ILedgerEntry[]}
|
||||||
*/
|
// */
|
||||||
public getLandedCostGLEntries = (
|
// public getLandedCostGLEntries = (
|
||||||
allocatedLandedCost: BillLandedCost,
|
// allocatedLandedCost: BillLandedCost,
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
fromTransactionEntry: LandedCostTransactionEntry
|
// fromTransactionEntry: ILandedCostTransactionEntry
|
||||||
): ILedgerEntry[] => {
|
// ): ILedgerEntry[] => {
|
||||||
const getEntry = this.getLandedCostGLAllocateEntry(
|
// const getEntry = this.getLandedCostGLAllocateEntry(
|
||||||
bill,
|
// bill,
|
||||||
allocatedLandedCost,
|
// allocatedLandedCost,
|
||||||
fromTransactionEntry
|
// fromTransactionEntry
|
||||||
);
|
// );
|
||||||
return allocatedLandedCost.allocateEntries.map(getEntry).flat();
|
// return allocatedLandedCost.allocateEntries.map(getEntry).flat();
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Retrieves the landed cost GL ledger.
|
// * Retrieves the landed cost GL ledger.
|
||||||
* @param {IBillLandedCost} allocatedLandedCost
|
// * @param {BillLandedCost} allocatedLandedCost
|
||||||
* @param {Bill} bill
|
// * @param {Bill} bill
|
||||||
* @param {ILandedCostTransactionEntry} fromTransactionEntry
|
// * @param {ILandedCostTransactionEntry} fromTransactionEntry
|
||||||
* @returns {ILedger}
|
// * @returns {ILedger}
|
||||||
*/
|
// */
|
||||||
public getLandedCostLedger = (
|
// public getLandedCostLedger = (
|
||||||
allocatedLandedCost: BillLandedCost,
|
// allocatedLandedCost: BillLandedCost,
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
fromTransactionEntry: LandedCostTransactionEntry
|
// fromTransactionEntry: ILandedCostTransactionEntry
|
||||||
): ILedger => {
|
// ): ILedger => {
|
||||||
const entries = this.getLandedCostGLEntries(
|
// const entries = this.getLandedCostGLEntries(
|
||||||
allocatedLandedCost,
|
// allocatedLandedCost,
|
||||||
bill,
|
// bill,
|
||||||
fromTransactionEntry
|
// fromTransactionEntry
|
||||||
);
|
// );
|
||||||
return new Ledger(entries);
|
// return new Ledger(entries);
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Writes landed cost GL entries to the storage layer.
|
// * Writes landed cost GL entries to the storage layer.
|
||||||
* @param {number} tenantId -
|
// * @param {number} tenantId -
|
||||||
*/
|
// */
|
||||||
public writeLandedCostGLEntries = async (
|
// public writeLandedCostGLEntries = async (
|
||||||
allocatedLandedCost: BillLandedCost,
|
// allocatedLandedCost: BillLandedCost,
|
||||||
bill: Bill,
|
// bill: Bill,
|
||||||
fromTransactionEntry: ILandedCostTransactionEntry,
|
// fromTransactionEntry: ILandedCostTransactionEntry,
|
||||||
trx?: Knex.Transaction
|
// trx?: Knex.Transaction
|
||||||
) => {
|
// ) => {
|
||||||
const ledgerEntries = this.getLandedCostGLEntries(
|
// const ledgerEntries = this.getLandedCostGLEntries(
|
||||||
allocatedLandedCost,
|
// allocatedLandedCost,
|
||||||
bill,
|
// bill,
|
||||||
fromTransactionEntry
|
// fromTransactionEntry
|
||||||
);
|
// );
|
||||||
await this.ledgerRepository.saveLedgerEntries(ledgerEntries, trx);
|
// await this.ledgerRepository.saveLedgerEntries(ledgerEntries, trx);
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Generates and writes GL entries of the given landed cost.
|
// * Generates and writes GL entries of the given landed cost.
|
||||||
* @param {number} billLandedCostId
|
// * @param {number} billLandedCostId
|
||||||
* @param {Knex.Transaction} trx
|
// * @param {Knex.Transaction} trx
|
||||||
*/
|
// */
|
||||||
public createLandedCostGLEntries = async (
|
// public createLandedCostGLEntries = async (
|
||||||
billLandedCostId: number,
|
// billLandedCostId: number,
|
||||||
trx?: Knex.Transaction
|
// trx?: Knex.Transaction
|
||||||
) => {
|
// ) => {
|
||||||
// Retrieve the bill landed cost transacion with associated
|
// // Retrieve the bill landed cost transacion with associated
|
||||||
// allocated entries and items.
|
// // allocated entries and items.
|
||||||
const allocatedLandedCost = await this.billLandedCostModel().query(trx)
|
// const allocatedLandedCost = await this.billLandedCostModel().query(trx)
|
||||||
.findById(billLandedCostId)
|
// .findById(billLandedCostId)
|
||||||
.withGraphFetched('bill')
|
// .withGraphFetched('bill')
|
||||||
.withGraphFetched('allocateEntries.itemEntry.item');
|
// .withGraphFetched('allocateEntries.itemEntry.item');
|
||||||
|
|
||||||
// Retrieve the allocated from transactione entry.
|
// // Retrieve the allocated from transactione entry.
|
||||||
const transactionEntry = await this.getLandedCostEntry(
|
// const transactionEntry = await this.getLandedCostEntry(
|
||||||
allocatedLandedCost.fromTransactionType,
|
// allocatedLandedCost.fromTransactionType,
|
||||||
allocatedLandedCost.fromTransactionId,
|
// allocatedLandedCost.fromTransactionId,
|
||||||
allocatedLandedCost.fromTransactionEntryId
|
// allocatedLandedCost.fromTransactionEntryId
|
||||||
);
|
// );
|
||||||
// Writes the given landed cost GL entries to the storage layer.
|
// // Writes the given landed cost GL entries to the storage layer.
|
||||||
await this.writeLandedCostGLEntries(
|
// await this.writeLandedCostGLEntries(
|
||||||
allocatedLandedCost,
|
// allocatedLandedCost,
|
||||||
allocatedLandedCost.bill,
|
// allocatedLandedCost.bill,
|
||||||
transactionEntry,
|
// transactionEntry,
|
||||||
trx
|
// trx
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Reverts GL entries of the given allocated landed cost transaction.
|
// * Reverts GL entries of the given allocated landed cost transaction.
|
||||||
* @param {number} tenantId
|
// * @param {number} tenantId
|
||||||
* @param {number} landedCostId
|
// * @param {number} landedCostId
|
||||||
* @param {Knex.Transaction} trx
|
// * @param {Knex.Transaction} trx
|
||||||
*/
|
// */
|
||||||
public revertLandedCostGLEntries = async (
|
// public revertLandedCostGLEntries = async (
|
||||||
landedCostId: number,
|
// landedCostId: number,
|
||||||
trx: Knex.Transaction
|
// trx: Knex.Transaction
|
||||||
) => {
|
// ) => {
|
||||||
await this.journalService.revertJournalTransactions(
|
// await this.journalService.revertJournalTransactions(
|
||||||
landedCostId,
|
// landedCostId,
|
||||||
'LandedCost',
|
// 'LandedCost',
|
||||||
trx
|
// trx
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
@@ -3,15 +3,14 @@ import {
|
|||||||
IAllocatedLandedCostDeletedPayload,
|
IAllocatedLandedCostDeletedPayload,
|
||||||
} from '../types/BillLandedCosts.types';
|
} from '../types/BillLandedCosts.types';
|
||||||
import { OnEvent } from '@nestjs/event-emitter';
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
import { LandedCostGLEntries } from './LandedCostGLEntries.service';
|
// import { LandedCostGLEntries } from './LandedCostGLEntries.service';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LandedCostGLEntriesSubscriber {
|
export class LandedCostGLEntriesSubscriber {
|
||||||
constructor(
|
constructor() // private readonly billLandedCostGLEntries: LandedCostGLEntries,
|
||||||
private readonly billLandedCostGLEntries: LandedCostGLEntries,
|
{}
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes GL entries once landed cost transaction created.
|
* Writes GL entries once landed cost transaction created.
|
||||||
@@ -22,11 +21,11 @@ export class LandedCostGLEntriesSubscriber {
|
|||||||
billLandedCost,
|
billLandedCost,
|
||||||
trx,
|
trx,
|
||||||
}: IAllocatedLandedCostCreatedPayload) {
|
}: IAllocatedLandedCostCreatedPayload) {
|
||||||
await this.billLandedCostGLEntries.createLandedCostGLEntries(
|
// await this.billLandedCostGLEntries.createLandedCostGLEntries(
|
||||||
billLandedCost.id,
|
// billLandedCost.id,
|
||||||
trx
|
// trx
|
||||||
);
|
// );
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts GL entries associated to landed cost transaction once deleted.
|
* Reverts GL entries associated to landed cost transaction once deleted.
|
||||||
@@ -37,9 +36,9 @@ export class LandedCostGLEntriesSubscriber {
|
|||||||
oldBillLandedCost,
|
oldBillLandedCost,
|
||||||
trx,
|
trx,
|
||||||
}: IAllocatedLandedCostDeletedPayload) {
|
}: IAllocatedLandedCostDeletedPayload) {
|
||||||
await this.billLandedCostGLEntries.revertLandedCostGLEntries(
|
// await this.billLandedCostGLEntries.revertLandedCostGLEntries(
|
||||||
oldBillLandedCost.id,
|
// oldBillLandedCost.id,
|
||||||
trx
|
// trx
|
||||||
);
|
// );
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ export class LandedCostSyncCostTransactions {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate the landed cost amount to cost transactions.
|
* Allocate the landed cost amount to cost transactions.
|
||||||
* @param {number} tenantId -
|
* @param {string} transactionType - Transaction type.
|
||||||
* @param {string} transactionType
|
* @param {number} transactionId - Transaction id.
|
||||||
* @param {number} transactionId
|
|
||||||
*/
|
*/
|
||||||
public incrementLandedCostAmount = async (
|
public incrementLandedCostAmount = async (
|
||||||
transactionType: string,
|
transactionType: string,
|
||||||
@@ -22,18 +21,18 @@ export class LandedCostSyncCostTransactions {
|
|||||||
amount: number,
|
amount: number,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const Model = this.transactionLandedCost.getModel(
|
const Model = await this.transactionLandedCost.getModel(
|
||||||
transactionType
|
transactionType
|
||||||
);
|
);
|
||||||
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
||||||
|
|
||||||
// Increment the landed cost transaction amount.
|
// Increment the landed cost transaction amount.
|
||||||
await Model.query(trx)
|
await Model().query(trx)
|
||||||
.where('id', transactionId)
|
.where('id', transactionId)
|
||||||
.increment('allocatedCostAmount', amount);
|
.increment('allocatedCostAmount', amount);
|
||||||
|
|
||||||
// Increment the landed cost entry.
|
// Increment the landed cost entry.
|
||||||
await Model.relatedQuery(relation, trx)
|
await Model().relatedQuery(relation, trx)
|
||||||
.for(transactionId)
|
.for(transactionId)
|
||||||
.where('id', transactionEntryId)
|
.where('id', transactionEntryId)
|
||||||
.increment('allocatedCostAmount', amount);
|
.increment('allocatedCostAmount', amount);
|
||||||
@@ -54,18 +53,18 @@ export class LandedCostSyncCostTransactions {
|
|||||||
amount: number,
|
amount: number,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
) => {
|
) => {
|
||||||
const Model = this.transactionLandedCost.getModel(
|
const Model = await this.transactionLandedCost.getModel(
|
||||||
transactionType
|
transactionType
|
||||||
);
|
);
|
||||||
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
const relation = CONFIG.COST_TYPES[transactionType].entries;
|
||||||
|
|
||||||
// Decrement the allocate cost amount of cost transaction.
|
// Decrement the allocate cost amount of cost transaction.
|
||||||
await Model.query(trx)
|
await Model().query(trx)
|
||||||
.where('id', transactionId)
|
.where('id', transactionId)
|
||||||
.decrement('allocatedCostAmount', amount);
|
.decrement('allocatedCostAmount', amount);
|
||||||
|
|
||||||
// Decrement the allocated cost amount cost transaction entry.
|
// Decrement the allocated cost amount cost transaction entry.
|
||||||
await Model.relatedQuery(relation, trx)
|
await Model().relatedQuery(relation, trx)
|
||||||
.for(transactionId)
|
.for(transactionId)
|
||||||
.where('id', transactionEntryId)
|
.where('id', transactionEntryId)
|
||||||
.decrement('allocatedCostAmount', amount);
|
.decrement('allocatedCostAmount', amount);
|
||||||
|
|||||||
@@ -1,70 +1,73 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ref } from 'objection';
|
import { ref } from 'objection';
|
||||||
|
import { curry, pipe, map } from 'lodash/fp';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import {
|
import {
|
||||||
ILandedCostTransactionsQueryDTO,
|
|
||||||
ILandedCostTransaction,
|
ILandedCostTransaction,
|
||||||
ILandedCostTransactionDOJO,
|
ILandedCostTransactionDOJO,
|
||||||
ILandedCostTransactionEntry,
|
ILandedCostTransactionEntry,
|
||||||
ILandedCostTransactionEntryDOJO,
|
ILandedCostTransactionEntryDOJO,
|
||||||
} from '@/interfaces';
|
} from '../types/BillLandedCosts.types';
|
||||||
import TransactionLandedCost from './TransctionLandedCost';
|
import { TransactionLandedCost } from './TransctionLandedCost.service';
|
||||||
import { formatNumber } from 'utils';
|
import { formatNumber } from '@/utils/format-number';
|
||||||
|
import { LandedCostTransactionsQueryDto } from '../dtos/LandedCostTransactionsQuery.dto';
|
||||||
|
|
||||||
@Service()
|
@Injectable()
|
||||||
export default class LandedCostTranasctions {
|
export class LandedCostTranasctions {
|
||||||
@Inject()
|
constructor(private readonly transactionLandedCost: TransactionLandedCost) {}
|
||||||
private transactionLandedCost: TransactionLandedCost;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the landed costs based on the given query.
|
* Retrieve the landed costs based on the given query.
|
||||||
* @param {number} tenantId
|
* @param {LandedCostTransactionsQueryDto} query -
|
||||||
* @param {ILandedCostTransactionsQueryDTO} query
|
|
||||||
* @returns {Promise<ILandedCostTransaction[]>}
|
* @returns {Promise<ILandedCostTransaction[]>}
|
||||||
*/
|
*/
|
||||||
public getLandedCostTransactions = async (
|
public getLandedCostTransactions = async (
|
||||||
query: ILandedCostTransactionsQueryDTO
|
query: LandedCostTransactionsQueryDto,
|
||||||
): Promise<ILandedCostTransaction[]> => {
|
): Promise<ILandedCostTransaction[]> => {
|
||||||
const { transactionType } = query;
|
const { transactionType } = query;
|
||||||
const Model = this.transactionLandedCost.getModel(
|
const Model = await this.transactionLandedCost.getModel(
|
||||||
query.transactionType
|
query.transactionType,
|
||||||
);
|
);
|
||||||
// Retrieve the model entities.
|
// Retrieve the model entities.
|
||||||
const transactions = await Model.query().onBuild((q) => {
|
const transactions = await Model()
|
||||||
q.where('allocated_cost_amount', '<', ref('landed_cost_amount'));
|
.query()
|
||||||
|
.onBuild((q) => {
|
||||||
|
q.where('allocated_cost_amount', '<', ref('landed_cost_amount'));
|
||||||
|
|
||||||
if (query.transactionType === 'Bill') {
|
if (query.transactionType === 'Bill') {
|
||||||
q.withGraphFetched('entries.item');
|
q.withGraphFetched('entries.item');
|
||||||
} else if (query.transactionType === 'Expense') {
|
} else if (query.transactionType === 'Expense') {
|
||||||
q.withGraphFetched('categories.expenseAccount');
|
q.withGraphFetched('categories.expenseAccount');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const transformLandedCost =
|
const transformLandedCost = curry(
|
||||||
this.transactionLandedCost.transformToLandedCost(transactionType);
|
this.transactionLandedCost.transformToLandedCost,
|
||||||
|
)(transactionType);
|
||||||
|
|
||||||
return R.compose(
|
return pipe(
|
||||||
this.transformLandedCostTransactions,
|
this.transformLandedCostTransactions,
|
||||||
R.map(transformLandedCost)
|
R.map(transformLandedCost),
|
||||||
)(transactions);
|
)(transactions);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Transformes the landed cost transactions.
|
||||||
* @param transactions
|
* @param {ILandedCostTransaction[]} transactions
|
||||||
* @returns
|
* @returns {ILandedCostTransactionDOJO[]}
|
||||||
*/
|
*/
|
||||||
public transformLandedCostTransactions = (
|
public transformLandedCostTransactions = (
|
||||||
transactions: ILandedCostTransaction[]
|
transactions: ILandedCostTransaction[],
|
||||||
) => {
|
) => {
|
||||||
return R.map(this.transformLandedCostTransaction)(transactions);
|
return R.map(this.transformLandedCostTransaction)(transactions);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformes the landed cost transaction.
|
* Transformes the landed cost transaction.
|
||||||
* @param {ILandedCostTransaction} transaction
|
* @param {ILandedCostTransaction} transaction - Landed cost transaction.
|
||||||
|
* @returns {ILandedCostTransactionDOJO}
|
||||||
*/
|
*/
|
||||||
public transformLandedCostTransaction = (
|
public transformLandedCostTransaction = (
|
||||||
transaction: ILandedCostTransaction
|
transaction: ILandedCostTransaction,
|
||||||
): ILandedCostTransactionDOJO => {
|
): ILandedCostTransactionDOJO => {
|
||||||
const { currencyCode } = transaction;
|
const { currencyCode } = transaction;
|
||||||
|
|
||||||
@@ -74,57 +77,60 @@ export default class LandedCostTranasctions {
|
|||||||
// Formatted transaction unallocated cost amount.
|
// Formatted transaction unallocated cost amount.
|
||||||
const formattedUnallocatedCostAmount = formatNumber(
|
const formattedUnallocatedCostAmount = formatNumber(
|
||||||
transaction.unallocatedCostAmount,
|
transaction.unallocatedCostAmount,
|
||||||
{ currencyCode }
|
{ currencyCode },
|
||||||
);
|
);
|
||||||
// Formatted transaction allocated cost amount.
|
// Formatted transaction allocated cost amount.
|
||||||
const formattedAllocatedCostAmount = formatNumber(
|
const formattedAllocatedCostAmount = formatNumber(
|
||||||
transaction.allocatedCostAmount,
|
transaction.allocatedCostAmount,
|
||||||
{ currencyCode }
|
{ currencyCode },
|
||||||
);
|
);
|
||||||
|
const transformLandedCostEntry = R.curry(this.transformLandedCostEntry)(
|
||||||
|
transaction,
|
||||||
|
);
|
||||||
|
const entries = R.map<
|
||||||
|
ILandedCostTransactionEntry,
|
||||||
|
ILandedCostTransactionEntryDOJO
|
||||||
|
>(transformLandedCostEntry)(transaction.entries);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...transaction,
|
...transaction,
|
||||||
formattedAmount,
|
formattedAmount,
|
||||||
formattedUnallocatedCostAmount,
|
formattedUnallocatedCostAmount,
|
||||||
formattedAllocatedCostAmount,
|
formattedAllocatedCostAmount,
|
||||||
entries: R.map(this.transformLandedCostEntry(transaction))(
|
entries,
|
||||||
transaction.entries
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Transformes the landed cost transaction entry.
|
||||||
* @param {ILandedCostTransaction} transaction
|
* @param {ILandedCostTransaction} transaction - Landed cost transaction.
|
||||||
* @param {ILandedCostTransactionEntry} entry
|
* @param {ILandedCostTransactionEntry} entry - Landed cost transaction entry.
|
||||||
* @returns {ILandedCostTransactionEntryDOJO}
|
* @returns {ILandedCostTransactionEntryDOJO}
|
||||||
*/
|
*/
|
||||||
public transformLandedCostEntry = R.curry(
|
public transformLandedCostEntry = (
|
||||||
(
|
transaction: ILandedCostTransaction,
|
||||||
transaction: ILandedCostTransaction,
|
entry: ILandedCostTransactionEntry,
|
||||||
entry: ILandedCostTransactionEntry
|
): ILandedCostTransactionEntryDOJO => {
|
||||||
): ILandedCostTransactionEntryDOJO => {
|
const { currencyCode } = transaction;
|
||||||
const { currencyCode } = transaction;
|
|
||||||
|
|
||||||
// Formatted entry amount.
|
// Formatted entry amount.
|
||||||
const formattedAmount = formatNumber(entry.amount, { currencyCode });
|
const formattedAmount = formatNumber(entry.amount, { currencyCode });
|
||||||
|
|
||||||
// Formatted entry unallocated cost amount.
|
// Formatted entry unallocated cost amount.
|
||||||
const formattedUnallocatedCostAmount = formatNumber(
|
const formattedUnallocatedCostAmount = formatNumber(
|
||||||
entry.unallocatedCostAmount,
|
entry.unallocatedCostAmount,
|
||||||
{ currencyCode }
|
{ currencyCode },
|
||||||
);
|
);
|
||||||
// Formatted entry allocated cost amount.
|
// Formatted entry allocated cost amount.
|
||||||
const formattedAllocatedCostAmount = formatNumber(
|
const formattedAllocatedCostAmount = formatNumber(
|
||||||
entry.allocatedCostAmount,
|
entry.allocatedCostAmount,
|
||||||
{ currencyCode }
|
{ currencyCode },
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
...entry,
|
...entry,
|
||||||
formattedAmount,
|
formattedAmount,
|
||||||
formattedUnallocatedCostAmount,
|
formattedUnallocatedCostAmount,
|
||||||
formattedAllocatedCostAmount,
|
formattedAllocatedCostAmount,
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { events } from '@/common/events/events';
|
|||||||
import { IAllocatedLandedCostDeletedPayload } from '../types/BillLandedCosts.types';
|
import { IAllocatedLandedCostDeletedPayload } from '../types/BillLandedCosts.types';
|
||||||
import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
import { BillLandedCostEntry } from '../models/BillLandedCostEntry';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { BillLandedCost } from '../models/BillLandedCost';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RevertAllocatedLandedCost extends BaseLandedCostService {
|
export class RevertAllocatedLandedCost extends BaseLandedCostService {
|
||||||
@@ -15,11 +14,6 @@ export class RevertAllocatedLandedCost extends BaseLandedCostService {
|
|||||||
private readonly eventPublisher: EventEmitter2,
|
private readonly eventPublisher: EventEmitter2,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
|
|
||||||
@Inject(BillLandedCost.name)
|
|
||||||
private readonly billLandedCostModel: TenantModelProxy<
|
|
||||||
typeof BillLandedCost
|
|
||||||
>,
|
|
||||||
|
|
||||||
@Inject(BillLandedCostEntry.name)
|
@Inject(BillLandedCostEntry.name)
|
||||||
private readonly billLandedCostEntryModel: TenantModelProxy<
|
private readonly billLandedCostEntryModel: TenantModelProxy<
|
||||||
typeof BillLandedCostEntry
|
typeof BillLandedCostEntry
|
||||||
|
|||||||
@@ -3,35 +3,46 @@ import { Model } from 'objection';
|
|||||||
import {
|
import {
|
||||||
ILandedCostTransaction,
|
ILandedCostTransaction,
|
||||||
ILandedCostTransactionEntry,
|
ILandedCostTransactionEntry,
|
||||||
|
LandedCostTransactionModel,
|
||||||
|
LandedCostTransactionType,
|
||||||
} from '../types/BillLandedCosts.types';
|
} from '../types/BillLandedCosts.types';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { BillLandedCost } from '../models/BillLandedCost';
|
|
||||||
import { Bill } from '@/modules/Bills/models/Bill';
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
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 { ERRORS } from '../utils';
|
||||||
import { ExpenseLandedCost } from '../models/ExpenseLandedCost';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TransactionLandedCost {
|
export class TransactionLandedCost {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly billLandedCost: BillLandedCost,
|
private readonly billLandedCost: BillLandedCost,
|
||||||
private readonly expenseLandedCost: ExpenseLandedCost,
|
private readonly expenseLandedCost: ExpenseLandedCost,
|
||||||
|
private readonly moduleRef: ModuleRef,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the cost transaction code model.
|
* Retrieve the cost transaction code model.
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {string} transactionType - Transaction type.
|
* @param {string} transactionType - Transaction type.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public getModel = (tenantId: number, transactionType: string): Model => {
|
public getModel = async (
|
||||||
const Models = this.tenancy.models(tenantId);
|
transactionType: string,
|
||||||
const Model = Models[transactionType];
|
): 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);
|
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.
|
* @param {IBill|IExpense} transaction - Expense or bill transaction.
|
||||||
* @returns {ILandedCostTransaction}
|
* @returns {ILandedCostTransaction}
|
||||||
*/
|
*/
|
||||||
public transformToLandedCost = R.curry(
|
public transformToLandedCost =
|
||||||
(
|
(
|
||||||
transactionType: string,
|
transactionType: LandedCostTransactionType,
|
||||||
transaction: Bill | Expense,
|
transaction: LandedCostTransactionModel,
|
||||||
): ILandedCostTransaction => {
|
): ILandedCostTransaction => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
@@ -54,9 +65,8 @@ export class TransactionLandedCost {
|
|||||||
R.always(transactionType === 'Expense'),
|
R.always(transactionType === 'Expense'),
|
||||||
this.expenseLandedCost.transformToLandedCost,
|
this.expenseLandedCost.transformToLandedCost,
|
||||||
),
|
),
|
||||||
)(transaction);
|
)(transaction) as ILandedCostTransaction;
|
||||||
},
|
};
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformes the given expense or bill entry to landed cost transaction entry.
|
* Transformes the given expense or bill entry to landed cost transaction entry.
|
||||||
@@ -65,7 +75,7 @@ export class TransactionLandedCost {
|
|||||||
* @returns {ILandedCostTransactionEntry}
|
* @returns {ILandedCostTransactionEntry}
|
||||||
*/
|
*/
|
||||||
public transformToLandedCostEntry = (
|
public transformToLandedCostEntry = (
|
||||||
transactionType: 'Bill' | 'Expense',
|
transactionType: LandedCostTransactionType,
|
||||||
transactionEntry,
|
transactionEntry,
|
||||||
): ILandedCostTransactionEntry => {
|
): ILandedCostTransactionEntry => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
@@ -77,6 +87,6 @@ export class TransactionLandedCost {
|
|||||||
R.always(transactionType === 'Expense'),
|
R.always(transactionType === 'Expense'),
|
||||||
this.expenseLandedCost.transformToLandedCostEntry,
|
this.expenseLandedCost.transformToLandedCostEntry,
|
||||||
),
|
),
|
||||||
)(transactionEntry);
|
)(transactionEntry) as ILandedCostTransactionEntry;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import {
|
|||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { ToNumber } from '@/common/decorators/Validators';
|
import { ToNumber } from '@/common/decorators/Validators';
|
||||||
|
import { LandedCostTransactionType } from '../types/BillLandedCosts.types';
|
||||||
|
|
||||||
class AllocateBillLandedCostItemDto {
|
export class AllocateBillLandedCostItemDto {
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@ToNumber()
|
@ToNumber()
|
||||||
entryId: number;
|
entryId: number;
|
||||||
@@ -26,7 +27,7 @@ export class AllocateBillLandedCostDto {
|
|||||||
transactionId: number;
|
transactionId: number;
|
||||||
|
|
||||||
@IsIn(['Expense', 'Bill'])
|
@IsIn(['Expense', 'Bill'])
|
||||||
transactionType: string;
|
transactionType: LandedCostTransactionType;
|
||||||
|
|
||||||
@IsInt()
|
@IsInt()
|
||||||
transactionEntryId: number;
|
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 { Knex } from 'knex';
|
||||||
import { Bill } from '@/modules/Bills/models/Bill';
|
import { Bill } from '@/modules/Bills/models/Bill';
|
||||||
|
import { ModelObject } from 'objection';
|
||||||
|
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||||
|
|
||||||
export interface ILandedCostItemDTO {
|
export interface ILandedCostItemDTO {
|
||||||
entryId: number;
|
entryId: number;
|
||||||
@@ -140,3 +142,7 @@ interface ICommonEntryDTO {
|
|||||||
export interface ICommonLandedCostEntryDTO extends ICommonEntryDTO {
|
export interface ICommonLandedCostEntryDTO extends ICommonEntryDTO {
|
||||||
landedCost?: boolean;
|
landedCost?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type LandedCostTransactionType = 'Bill' | 'Expense';
|
||||||
|
export type LandedCostTransactionModel = Bill | Expense;
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { IItemEntry, IBillLandedCostTransactionEntry } from '@/interfaces';
|
import { ModelObject } from 'objection';
|
||||||
import { transformToMap } from 'utils';
|
import { transformToMap } from '@/utils/transform-to-key';
|
||||||
|
import { IBillLandedCostTransactionEntry } from './types/BillLandedCosts.types';
|
||||||
|
import { ItemEntry } from '../TransactionItemEntry/models/ItemEntry';
|
||||||
|
|
||||||
export const ERRORS = {
|
export const ERRORS = {
|
||||||
COST_TYPE_UNDEFINED: 'COST_TYPE_UNDEFINED',
|
COST_TYPE_UNDEFINED: 'COST_TYPE_UNDEFINED',
|
||||||
@@ -23,8 +25,8 @@ export const ERRORS = {
|
|||||||
*/
|
*/
|
||||||
export const mergeLocatedWithBillEntries = (
|
export const mergeLocatedWithBillEntries = (
|
||||||
locatedEntries: IBillLandedCostTransactionEntry[],
|
locatedEntries: IBillLandedCostTransactionEntry[],
|
||||||
billEntries: IItemEntry[]
|
billEntries: ModelObject<ItemEntry>[]
|
||||||
): (IBillLandedCostTransactionEntry & { entry: IItemEntry })[] => {
|
): (IBillLandedCostTransactionEntry & { entry: ModelObject<ItemEntry> })[] => {
|
||||||
const billEntriesByEntryId = transformToMap(billEntries, 'id');
|
const billEntriesByEntryId = transformToMap(billEntries, 'id');
|
||||||
|
|
||||||
return locatedEntries.map((entry) => ({
|
return locatedEntries.map((entry) => ({
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { OpenBillService } from './commands/OpenBill.service';
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { GetBillsService } from './queries/GetBills.service';
|
import { GetBillsService } from './queries/GetBills.service';
|
||||||
import { CreateBillDto, EditBillDto } from './dtos/Bill.dto';
|
import { CreateBillDto, EditBillDto } from './dtos/Bill.dto';
|
||||||
|
import { GetBillPaymentTransactionsService } from './queries/GetBillPayments';
|
||||||
// import { GetBillPayments } from './queries/GetBillPayments';
|
// import { GetBillPayments } from './queries/GetBillPayments';
|
||||||
// import { GetBills } from './queries/GetBills';
|
// import { GetBills } from './queries/GetBills';
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ export class BillsApplication {
|
|||||||
private getDueBillsService: GetDueBills,
|
private getDueBillsService: GetDueBills,
|
||||||
private openBillService: OpenBillService,
|
private openBillService: OpenBillService,
|
||||||
private getBillsService: GetBillsService,
|
private getBillsService: GetBillsService,
|
||||||
// private getBillPaymentsService: GetBillPayments,
|
private getBillPaymentTransactionsService: GetBillPaymentTransactionsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +72,6 @@ export class BillsApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the given bill.
|
* Open the given bill.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} billId
|
* @param {number} billId
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
@@ -91,10 +91,11 @@ export class BillsApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the specific bill associated payment transactions.
|
* Retrieve the specific bill associated payment transactions.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} billId
|
* @param {number} billId
|
||||||
*/
|
*/
|
||||||
// public getBillPayments(billId: number) {
|
public getBillPaymentTransactions(billId: number) {
|
||||||
// return this.getBillPaymentsService.getBillPayments(billId);
|
return this.getBillPaymentTransactionsService.getBillPaymentTransactions(
|
||||||
// }
|
billId,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,18 @@ export class BillsController {
|
|||||||
return this.billsApplication.getBills(filterDTO);
|
return this.billsApplication.getBills(filterDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get(':id/payment-transactions')
|
||||||
|
@ApiOperation({ summary: 'Retrieve the specific bill associated payment transactions.' })
|
||||||
|
@ApiParam({
|
||||||
|
name: 'id',
|
||||||
|
required: true,
|
||||||
|
type: Number,
|
||||||
|
description: 'The bill id',
|
||||||
|
})
|
||||||
|
getBillPaymentTransactions(@Param('id') billId: number) {
|
||||||
|
return this.billsApplication.getBillPaymentTransactions(billId);
|
||||||
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@ApiOperation({ summary: 'Retrieves the bill details.' })
|
@ApiOperation({ summary: 'Retrieves the bill details.' })
|
||||||
@ApiParam({
|
@ApiParam({
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
||||||
import { BillsExportable } from './commands/BillsExportable';
|
import { BillsExportable } from './commands/BillsExportable';
|
||||||
import { BillsImportable } from './commands/BillsImportable';
|
import { BillsImportable } from './commands/BillsImportable';
|
||||||
|
import { GetBillPaymentTransactionsService } from './queries/GetBillPayments';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -60,7 +61,8 @@ import { BillsImportable } from './commands/BillsImportable';
|
|||||||
BillInventoryTransactions,
|
BillInventoryTransactions,
|
||||||
BillWriteInventoryTransactionsSubscriber,
|
BillWriteInventoryTransactionsSubscriber,
|
||||||
BillsExportable,
|
BillsExportable,
|
||||||
BillsImportable
|
BillsImportable,
|
||||||
|
GetBillPaymentTransactionsService,
|
||||||
],
|
],
|
||||||
controllers: [BillsController],
|
controllers: [BillsController],
|
||||||
exports: [BillsExportable, BillsImportable],
|
exports: [BillsExportable, BillsImportable],
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import { Inject, Injectable } from '@nestjs/common';
|
|||||||
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
import { BillPaymentEntry } from '@/modules/BillPayments/models/BillPaymentEntry';
|
||||||
import { BillPaymentTransactionTransformer } from '@/modules/BillPayments/queries/BillPaymentTransactionTransformer';
|
import { BillPaymentTransactionTransformer } from '@/modules/BillPayments/queries/BillPaymentTransactionTransformer';
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetBillPayments {
|
export class GetBillPaymentTransactionsService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(BillPaymentEntry.name)
|
@Inject(BillPaymentEntry.name)
|
||||||
private billPaymentEntryModel: typeof BillPaymentEntry,
|
private billPaymentEntryModel: TenantModelProxy<typeof BillPaymentEntry>,
|
||||||
private transformer: TransformerInjectable,
|
private transformer: TransformerInjectable,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -15,8 +16,8 @@ export class GetBillPayments {
|
|||||||
* Retrieve the specific bill associated payment transactions.
|
* Retrieve the specific bill associated payment transactions.
|
||||||
* @param {number} billId - Bill id.
|
* @param {number} billId - Bill id.
|
||||||
*/
|
*/
|
||||||
public getBillPayments = async (billId: number) => {
|
public getBillPaymentTransactions = async (billId: number) => {
|
||||||
const billsEntries = await this.billPaymentEntryModel
|
const billsEntries = await this.billPaymentEntryModel()
|
||||||
.query()
|
.query()
|
||||||
.where('billId', billId)
|
.where('billId', billId)
|
||||||
.withGraphJoined('payment.paymentAccount')
|
.withGraphJoined('payment.paymentAccount')
|
||||||
|
|||||||
@@ -162,6 +162,14 @@ export class ItemEntry extends BaseModel {
|
|||||||
: getExlusiveTaxAmount(this.amount, this.taxRate);
|
: getExlusiveTaxAmount(this.amount, this.taxRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remain unallocated landed cost.
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
get unallocatedCostAmount() {
|
||||||
|
return Math.max(this.amount - this.allocatedCostAmount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static calcAmount(itemEntry) {
|
static calcAmount(itemEntry) {
|
||||||
const { discount, quantity, rate } = itemEntry;
|
const { discount, quantity, rate } = itemEntry;
|
||||||
const total = quantity * rate;
|
const total = quantity * rate;
|
||||||
|
|||||||
5
packages/server/src/utils/sanitize-model-name.ts
Normal file
5
packages/server/src/utils/sanitize-model-name.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { camelCase, upperFirst } from 'lodash';
|
||||||
|
|
||||||
|
export const sanitizeModelName = (modelName: string) => {
|
||||||
|
return upperFirst(camelCase(modelName));
|
||||||
|
}
|
||||||
@@ -27,6 +27,8 @@ function BillDrawerProvider({ billId, ...props }) {
|
|||||||
enabled: !!billId,
|
enabled: !!billId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(transactions, 'ahmed');
|
||||||
|
|
||||||
//provider.
|
//provider.
|
||||||
const provider = {
|
const provider = {
|
||||||
billId,
|
billId,
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ function LocatedLandedCostTable({
|
|||||||
// Bill drawer context.
|
// Bill drawer context.
|
||||||
const { transactions, billId } = useBillDrawerContext();
|
const { transactions, billId } = useBillDrawerContext();
|
||||||
|
|
||||||
|
console.log(transactions, 'ahmed');
|
||||||
|
|
||||||
// Handle the transaction delete action.
|
// Handle the transaction delete action.
|
||||||
const handleDeleteTransaction = ({ id }) => {
|
const handleDeleteTransaction = ({ id }) => {
|
||||||
openAlert('bill-located-cost-delete', { BillId: id });
|
openAlert('bill-located-cost-delete', { BillId: id });
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export function useBill(id, props) {
|
|||||||
[t.BILL, id],
|
[t.BILL, id],
|
||||||
{ method: 'get', url: `/bills/${id}` },
|
{ method: 'get', url: `/bills/${id}` },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.bill,
|
select: (res) => res.data,
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
@@ -208,7 +208,7 @@ export function useBillPaymentTransactions(id, props) {
|
|||||||
url: `bills/${id}/payment-transactions`,
|
url: `bills/${id}/payment-transactions`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
select: (res) => res.data.data,
|
select: (res) => res.data,
|
||||||
defaultData: [],
|
defaultData: [],
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function useCreateLandedCost(props) {
|
|||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
([id, values]) =>
|
([id, values]) =>
|
||||||
apiRequest.post(`purchases/landed-cost/bills/${id}/allocate`, values),
|
apiRequest.post(`landed-cost/bills/${id}/allocate`, values),
|
||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
// Common invalidate queries.
|
// Common invalidate queries.
|
||||||
@@ -43,7 +43,7 @@ export function useDeleteLandedCost(props) {
|
|||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
(landedCostId) =>
|
(landedCostId) =>
|
||||||
apiRequest.delete(`purchases/landed-cost/${landedCostId}`),
|
apiRequest.delete(`landed-cost/${landedCostId}`),
|
||||||
{
|
{
|
||||||
onSuccess: (res, id) => {
|
onSuccess: (res, id) => {
|
||||||
// Common invalidate queries.
|
// Common invalidate queries.
|
||||||
@@ -62,7 +62,7 @@ export function useLandedCostTransaction(query, props) {
|
|||||||
[t.LANDED_COST, query],
|
[t.LANDED_COST, query],
|
||||||
{
|
{
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: 'purchases/landed-cost/transactions',
|
url: 'landed-cost/transactions',
|
||||||
params: { transaction_type: query },
|
params: { transaction_type: query },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -81,10 +81,10 @@ export function useLandedCostTransaction(query, props) {
|
|||||||
export function useBillLocatedLandedCost(id, props) {
|
export function useBillLocatedLandedCost(id, props) {
|
||||||
return useRequestQuery(
|
return useRequestQuery(
|
||||||
[t.LANDED_COST_TRANSACTION, id],
|
[t.LANDED_COST_TRANSACTION, id],
|
||||||
{ method: 'get', url: `purchases/landed-cost/bills/${id}/transactions` },
|
{ method: 'get', url: `landed-cost/bills/${id}/transactions` },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.transactions,
|
select: (res) => res.data?.data,
|
||||||
defaultData: {},
|
defaultData: [],
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user