feat(nestjs): migrate to NestJS

This commit is contained in:
Ahmed Bouhuolia
2025-04-07 11:51:24 +02:00
parent f068218a16
commit 55fcc908ef
3779 changed files with 631 additions and 195332 deletions

View File

@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { TransactionLandedCostEntriesService } from './TransactionLandedCostEntries.service';
@Module({
providers: [TransactionLandedCostEntriesService],
exports: [TransactionLandedCostEntriesService],
})
export class BillLandedCostsModule {}

View File

@@ -0,0 +1,75 @@
import { Injectable } from '@nestjs/common';
import { ServiceError } from '../Items/ServiceError';
import { transformToMap } from '@/utils/transform-to-key';
import { ICommonLandedCostEntry, ICommonLandedCostEntryDTO } from './types/BillLandedCosts.types';
const ERRORS = {
ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED:
'ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED',
LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES:
'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES',
};
@Injectable()
export class TransactionLandedCostEntriesService {
/**
* Validates bill entries that has allocated landed cost amount not deleted.
* @param {ICommonLandedCostEntry[]} oldCommonEntries -
* @param {ICommonLandedCostEntryDTO[]} newBillEntries -
*/
public getLandedCostEntriesDeleted(
oldCommonEntries: ICommonLandedCostEntry[],
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
): ICommonLandedCostEntry[] {
const newBillEntriesById = transformToMap(newCommonEntriesDTO, 'id');
return oldCommonEntries.filter((entry) => {
const newEntry = newBillEntriesById.get(entry.id);
if (entry.allocatedCostAmount > 0 && typeof newEntry === 'undefined') {
return true;
}
return false;
});
}
/**
* Validates the bill entries that have located cost amount should not be deleted.
* @param {ICommonLandedCostEntry[]} oldCommonEntries - Old bill entries.
* @param {ICommonLandedCostEntryDTO[]} newBillEntries - New DTO bill entries.
*/
public validateLandedCostEntriesNotDeleted(
oldCommonEntries: ICommonLandedCostEntry[],
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
): void {
const entriesDeleted = this.getLandedCostEntriesDeleted(
oldCommonEntries,
newCommonEntriesDTO
);
if (entriesDeleted.length > 0) {
throw new ServiceError(ERRORS.ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED);
}
}
/**
* Validate allocated cost amount entries should be smaller than new entries amount.
* @param {ICommonLandedCostEntry[]} oldCommonEntries - Old bill entries.
* @param {ICommonLandedCostEntryDTO[]} newBillEntries - New DTO bill entries.
*/
public validateLocatedCostEntriesSmallerThanNewEntries(
oldCommonEntries: ICommonLandedCostEntry[],
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
): void {
const oldBillEntriesById = transformToMap(oldCommonEntries, 'id');
newCommonEntriesDTO.forEach((entry) => {
const oldEntry = oldBillEntriesById.get(entry.id);
if (oldEntry && oldEntry.allocatedCostAmount > entry.amount) {
throw new ServiceError(
ERRORS.LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES
);
}
});
}
}

View File

@@ -0,0 +1,107 @@
import { Model } from 'objection';
import { lowerCase } from 'lodash';
// import TenantModel from 'models/TenantModel';
import { BaseModel } from '@/models/Model';
export class BillLandedCost extends BaseModel {
amount!: number;
fromTransactionId!: number;
fromTransactionType!: string;
fromTransactionEntryId!: number;
allocationMethod!: string;
costAccountId!: number;
description!: string;
billId!: number;
exchangeRate!: number;
/**
* Table name
*/
static get tableName() {
return 'bill_located_costs';
}
/**
* Model timestamps.
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
/**
* Virtual attributes.
*/
static get virtualAttributes() {
return ['localAmount', 'allocationMethodFormatted'];
}
/**
* Retrieves the cost local amount.
* @returns {number}
*/
get localAmount() {
return this.amount * this.exchangeRate;
}
/**
* Allocation method formatted.
*/
get allocationMethodFormatted() {
const allocationMethod = lowerCase(this.allocationMethod);
const keyLabelsPairs = {
value: 'allocation_method.value.label',
quantity: 'allocation_method.quantity.label',
};
return keyLabelsPairs[allocationMethod] || '';
}
/**
* Relationship mapping.
*/
static get relationMappings() {
const { BillLandedCostEntry } = require('./BillLandedCostEntry');
const { Bill } = require('../../Bills/models/Bill');
const {
ItemEntry,
} = require('../../TransactionItemEntry/models/ItemEntry');
const {
ExpenseCategory,
} = require('../../Expenses/models/ExpenseCategory.model');
return {
bill: {
relation: Model.BelongsToOneRelation,
modelClass: Bill,
join: {
from: 'bill_located_costs.billId',
to: 'bills.id',
},
},
allocateEntries: {
relation: Model.HasManyRelation,
modelClass: BillLandedCostEntry,
join: {
from: 'bill_located_costs.id',
to: 'bill_located_cost_entries.billLocatedCostId',
},
},
allocatedFromBillEntry: {
relation: Model.BelongsToOneRelation,
modelClass: ItemEntry,
join: {
from: 'bill_located_costs.fromTransactionEntryId',
to: 'items_entries.id',
},
},
allocatedFromExpenseEntry: {
relation: Model.BelongsToOneRelation,
modelClass: ExpenseCategory,
join: {
from: 'bill_located_costs.fromTransactionEntryId',
to: 'expense_transaction_categories.id',
},
},
};
}
}

View File

@@ -0,0 +1,38 @@
import { BaseModel } from '@/models/Model';
import { Model } from 'objection';
export class BillLandedCostEntry extends BaseModel {
cost!: number;
entryId!: number;
billLocatedCostId!: number;
/**
* Table name
*/
static get tableName() {
return 'bill_located_cost_entries';
}
/**
* Relationship mapping.
*/
static get relationMappings() {
const {
ItemEntry,
} = require('../../TransactionItemEntry/models/ItemEntry');
return {
itemEntry: {
relation: Model.BelongsToOneRelation,
modelClass: ItemEntry,
join: {
from: 'bill_located_cost_entries.entryId',
to: 'items_entries.id',
},
filter(builder) {
builder.where('reference_type', 'Bill');
},
},
};
}
}

View File

@@ -0,0 +1,144 @@
import { Knex } from 'knex';
import { Bill } from '@/modules/Bills/models/Bill';
export interface ILandedCostItemDTO {
entryId: number;
cost: number;
}
export type ILandedCostType = 'Expense' | 'Bill';
export interface ILandedCostDTO {
transactionType: ILandedCostType;
transactionId: number;
transactionEntryId: number;
allocationMethod: string;
description: string;
items: ILandedCostItemDTO[];
}
export interface ILandedCostQueryDTO {
vendorId: number;
fromDate: Date;
toDate: Date;
}
export interface IUnallocatedListCost {
costNumber: string;
costAmount: number;
unallocatedAmount: number;
}
export interface ILandedCostTransactionsQueryDTO {
transactionType: string;
date: Date;
}
export interface ILandedCostEntriesQueryDTO {
transactionType: string;
transactionId: number;
}
export interface ILandedCostTransaction {
id: number;
name: string;
amount: number;
allocatedCostAmount: number;
unallocatedCostAmount: number;
currencyCode: string;
exchangeRate: number;
// formattedAllocatedCostAmount: string;
// formattedAmount: string;
// formattedUnallocatedCostAmount: string;
transactionType: string;
entries?: ILandedCostTransactionEntry[];
}
export interface ILandedCostTransactionEntry {
id: number;
name: string;
code: string;
amount: number;
unallocatedCostAmount: number;
allocatedCostAmount: number;
description: string;
costAccountId: number;
}
export interface ILandedCostTransactionEntryDOJO
extends ILandedCostTransactionEntry {
formattedAmount: string;
formattedUnallocatedCostAmount: string;
formattedAllocatedCostAmount: string;
}
export interface ILandedCostTransactionDOJO extends ILandedCostTransaction {
formattedAmount: string;
formattedUnallocatedCostAmount: string;
formattedAllocatedCostAmount: string;
}
interface ILandedCostEntry {
id: number;
landedCost?: boolean;
}
export interface IBillLandedCostTransaction {
id: number;
fromTransactionId: number;
fromTransactionType: string;
fromTransactionEntryId: number;
billId: number;
allocationMethod: string;
costAccountId: number;
description: string;
amount: number;
localAmount?: number;
currencyCode: string;
exchangeRate: number;
allocateEntries?: IBillLandedCostTransactionEntry[];
}
export interface IBillLandedCostTransactionEntry {
cost: number;
entryId: number;
billLocatedCostId: number;
}
export interface IAllocatedLandedCostDeletedPayload {
tenantId: number;
oldBillLandedCost: IBillLandedCostTransaction;
billId: number;
trx: Knex.Transaction;
}
export interface IAllocatedLandedCostCreatedPayload {
tenantId: number;
bill: Bill;
billLandedCostId: number;
billLandedCost: IBillLandedCostTransaction;
trx: Knex.Transaction;
}
export interface IBillAssociatedLandedCostTransactions {}
interface ICommonEntry {
id?: number;
amount: number;
}
export interface ICommonLandedCostEntry extends ICommonEntry {
landedCost: boolean;
allocatedCostAmount: number;
}
interface ICommonEntryDTO {
id?: number;
amount: number;
}
export interface ICommonLandedCostEntryDTO extends ICommonEntryDTO {
landedCost?: boolean;
}