refactor: dtos validation

This commit is contained in:
Ahmed Bouhuolia
2025-03-20 05:42:19 +02:00
parent fd65ee9428
commit 136cc907bb
105 changed files with 1641 additions and 366 deletions

View File

@@ -25,12 +25,12 @@ export class CreateAccountDTO {
@IsString() @IsString()
@MinLength(3) @MinLength(3)
@MaxLength(255) // Assuming DATATYPES_LENGTH.STRING is 255 @MaxLength(255)
accountType: string; accountType: string;
@IsOptional() @IsOptional()
@IsString() @IsString()
@MaxLength(65535) // Assuming DATATYPES_LENGTH.TEXT is 65535 @MaxLength(65535)
description?: string; description?: string;
@IsOptional() @IsOptional()

View File

@@ -18,6 +18,13 @@ import { TenantModelProxy } from '../System/models/TenantBaseModel';
@Injectable() @Injectable()
export class CreateAccountService { export class CreateAccountService {
/**
* @param {TenantModelProxy<typeof Account>} accountModel - The account model proxy.
* @param {EventEmitter2} eventEmitter - The event emitter.
* @param {UnitOfWork} uow - The unit of work.
* @param {CommandAccountValidators} validator - The command account validators.
* @param {TenancyContext} tenancyContext - The tenancy context.
*/
constructor( constructor(
@Inject(Account.name) @Inject(Account.name)
private readonly accountModel: TenantModelProxy<typeof Account>, private readonly accountModel: TenantModelProxy<typeof Account>,

View File

@@ -3,6 +3,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
import { EventEmitterModule } from '@nestjs/event-emitter'; import { EventEmitterModule } from '@nestjs/event-emitter';
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core'; import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { join } from 'path'; import { join } from 'path';
import { RedisModule } from '@liaoliaots/nestjs-redis';
import { import {
AcceptLanguageResolver, AcceptLanguageResolver,
CookieResolver, CookieResolver,
@@ -71,7 +72,7 @@ import { StripePaymentModule } from '../StripePayment/StripePayment.module';
import { FeaturesModule } from '../Features/Features.module'; import { FeaturesModule } from '../Features/Features.module';
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module'; import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
import { WarehousesTransfersModule } from '../WarehousesTransfers/WarehouseTransfers.module'; import { WarehousesTransfersModule } from '../WarehousesTransfers/WarehouseTransfers.module';
import { RedisModule } from '@liaoliaots/nestjs-redis';
@Module({ @Module({
imports: [ imports: [

View File

@@ -0,0 +1,8 @@
import { IsNotEmpty, IsString } from "class-validator";
export class AttachmentLinkDto {
@IsString()
@IsNotEmpty()
key: string;
}

View File

@@ -12,6 +12,8 @@ import { BankRulesApplication } from './BankRulesApplication';
import { ICreateBankRuleDTO, IEditBankRuleDTO } from './types'; import { ICreateBankRuleDTO, IEditBankRuleDTO } from './types';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { BankRule } from './models/BankRule'; import { BankRule } from './models/BankRule';
import { CreateBankRuleDto } from './dtos/BankRule.dto';
import { EditBankRuleDto } from './dtos/BankRule.dto';
@Controller('banking/rules') @Controller('banking/rules')
@ApiTags('bank-rules') @ApiTags('bank-rules')
@@ -22,7 +24,7 @@ export class BankRulesController {
@Post() @Post()
@ApiOperation({ summary: 'Create a new bank rule.' }) @ApiOperation({ summary: 'Create a new bank rule.' })
async createBankRule( async createBankRule(
@Body() createRuleDTO: ICreateBankRuleDTO, @Body() createRuleDTO: CreateBankRuleDto,
): Promise<BankRule> { ): Promise<BankRule> {
return this.bankRulesApplication.createBankRule(createRuleDTO); return this.bankRulesApplication.createBankRule(createRuleDTO);
} }
@@ -31,7 +33,7 @@ export class BankRulesController {
@ApiOperation({ summary: 'Edit the given bank rule.' }) @ApiOperation({ summary: 'Edit the given bank rule.' })
async editBankRule( async editBankRule(
@Param('id') ruleId: number, @Param('id') ruleId: number,
@Body() editRuleDTO: IEditBankRuleDTO, @Body() editRuleDTO: EditBankRuleDto,
): Promise<void> { ): Promise<void> {
return this.bankRulesApplication.editBankRule(ruleId, editRuleDTO); return this.bankRulesApplication.editBankRule(ruleId, editRuleDTO);
} }

View File

@@ -4,8 +4,8 @@ import { DeleteBankRuleService } from './commands/DeleteBankRule.service';
import { EditBankRuleService } from './commands/EditBankRule.service'; import { EditBankRuleService } from './commands/EditBankRule.service';
import { GetBankRuleService } from './queries/GetBankRule.service'; import { GetBankRuleService } from './queries/GetBankRule.service';
import { GetBankRulesService } from './queries/GetBankRules.service'; import { GetBankRulesService } from './queries/GetBankRules.service';
import { ICreateBankRuleDTO, IEditBankRuleDTO } from './types';
import { BankRule } from './models/BankRule'; import { BankRule } from './models/BankRule';
import { CreateBankRuleDto, EditBankRuleDto } from './dtos/BankRule.dto';
@Injectable() @Injectable()
export class BankRulesApplication { export class BankRulesApplication {
@@ -23,7 +23,7 @@ export class BankRulesApplication {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
public createBankRule( public createBankRule(
createRuleDTO: ICreateBankRuleDTO, createRuleDTO: CreateBankRuleDto,
): Promise<BankRule> { ): Promise<BankRule> {
return this.createBankRuleService.createBankRule(createRuleDTO); return this.createBankRuleService.createBankRule(createRuleDTO);
} }
@@ -31,12 +31,12 @@ export class BankRulesApplication {
/** /**
* Edits the given bank rule. * Edits the given bank rule.
* @param {number} ruleId - Bank rule identifier. * @param {number} ruleId - Bank rule identifier.
* @param {IEditBankRuleDTO} editRuleDTO - Bank rule data. * @param {EditBankRuleDto} editRuleDTO - Bank rule data.
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
public editBankRule( public editBankRule(
ruleId: number, ruleId: number,
editRuleDTO: IEditBankRuleDTO, editRuleDTO: EditBankRuleDto,
): Promise<void> { ): Promise<void> {
return this.editBankRuleService.editBankRule(ruleId, editRuleDTO); return this.editBankRuleService.editBankRule(ruleId, editRuleDTO);
} }

View File

@@ -1,3 +1,4 @@
import { ModelObject } from 'objection';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { import {
@@ -9,6 +10,7 @@ import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
import { EventEmitter2 } from '@nestjs/event-emitter'; import { EventEmitter2 } from '@nestjs/event-emitter';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { BankRule } from '../models/BankRule'; import { BankRule } from '../models/BankRule';
import { CreateBankRuleDto } from '../dtos/BankRule.dto';
@Injectable() @Injectable()
export class CreateBankRuleService { export class CreateBankRuleService {
@@ -23,10 +25,10 @@ export class CreateBankRuleService {
* Transforms the DTO to model. * Transforms the DTO to model.
* @param {ICreateBankRuleDTO} createDTO * @param {ICreateBankRuleDTO} createDTO
*/ */
private transformDTO(createDTO: ICreateBankRuleDTO) { private transformDTO(createDTO: CreateBankRuleDto): ModelObject<BankRule> {
return { return {
...createDTO, ...createDTO,
}; } as ModelObject<BankRule>;
} }
/** /**
@@ -35,7 +37,7 @@ export class CreateBankRuleService {
* @returns {Promise<BankRule>} * @returns {Promise<BankRule>}
*/ */
public async createBankRule( public async createBankRule(
createRuleDTO: ICreateBankRuleDTO, createRuleDTO: CreateBankRuleDto,
): Promise<BankRule> { ): Promise<BankRule> {
const transformDTO = this.transformDTO(createRuleDTO); const transformDTO = this.transformDTO(createRuleDTO);

View File

@@ -9,6 +9,8 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service'; import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditBankRuleDto } from '../dtos/BankRule.dto';
import { ModelObject } from 'objection';
@Injectable() @Injectable()
export class EditBankRuleService { export class EditBankRuleService {
@@ -25,10 +27,10 @@ export class EditBankRuleService {
* @param createDTO * @param createDTO
* @returns * @returns
*/ */
private transformDTO(createDTO: IEditBankRuleDTO) { private transformDTO(createDTO: EditBankRuleDto): ModelObject<BankRule> {
return { return {
...createDTO, ...createDTO,
}; } as ModelObject<BankRule>;
} }
/** /**
@@ -36,7 +38,7 @@ export class EditBankRuleService {
* @param {number} ruleId - * @param {number} ruleId -
* @param {IEditBankRuleDTO} editBankDTO * @param {IEditBankRuleDTO} editBankDTO
*/ */
public async editBankRule(ruleId: number, editRuleDTO: IEditBankRuleDTO) { public async editBankRule(ruleId: number, editRuleDTO: EditBankRuleDto) {
const oldBankRule = await this.bankRuleModel() const oldBankRule = await this.bankRuleModel()
.query() .query()
.findById(ruleId) .findById(ruleId)

View File

@@ -0,0 +1,81 @@
import { Type } from 'class-transformer';
import {
IsString,
IsInt,
Min,
IsOptional,
IsIn,
IsArray,
ValidateNested,
ArrayMinSize,
IsNotEmpty,
} from 'class-validator';
import { BankRuleComparator } from '../types';
class BankRuleConditionDto {
@IsNotEmpty()
@IsIn(['description', 'amount'])
field: string;
@IsNotEmpty()
@IsIn([
'equals',
'equal',
'contains',
'not_contain',
'bigger',
'bigger_or_equal',
'smaller',
'smaller_or_equal',
])
comparator: BankRuleComparator = 'contains';
@IsNotEmpty()
value: string;
}
export class CommandBankRuleDto {
@IsString()
@IsNotEmpty()
name: string;
@IsInt()
@Min(0)
order: number;
@IsOptional()
@IsInt()
@Min(0)
applyIfAccountId?: number;
@IsIn(['deposit', 'withdrawal'])
applyIfTransactionType: 'deposit' | 'withdrawal';
@IsString()
@IsIn(['and', 'or'])
conditionsType: 'and' | 'or' = 'and';
@IsArray()
@ArrayMinSize(1)
@ValidateNested({ each: true })
@Type(() => BankRuleConditionDto)
conditions: BankRuleConditionDto[];
@IsString()
assignCategory: string;
@IsInt()
@Min(0)
assignAccountId: number;
@IsOptional()
@IsString()
assignPayee?: string;
@IsOptional()
@IsString()
assignMemo?: string;
}
export class CreateBankRuleDto extends CommandBankRuleDto {}
export class EditBankRuleDto extends CommandBankRuleDto {}

View File

@@ -4,18 +4,18 @@ import { BankRuleCondition } from './BankRuleCondition';
import { BankRuleAssignCategory, BankRuleConditionType } from '../types'; import { BankRuleAssignCategory, BankRuleConditionType } from '../types';
export class BankRule extends BaseModel { export class BankRule extends BaseModel {
public id!: number; public readonly id!: number;
public name!: string; public readonly name!: string;
public order!: number; public readonly order!: number;
public applyIfAccountId!: number; public readonly applyIfAccountId!: number;
public applyIfTransactionType!: string; public readonly applyIfTransactionType!: string;
public assignCategory!: BankRuleAssignCategory; public readonly assignCategory!: BankRuleAssignCategory;
public assignAccountId!: number; public readonly assignAccountId!: number;
public assignPayee!: string; public readonly assignPayee!: string;
public assignMemo!: string; public readonly assignMemo!: string;
public conditionsType!: BankRuleConditionType; public readonly conditionsType!: BankRuleConditionType;
conditions!: BankRuleCondition[]; public readonly conditions!: BankRuleCondition[];
/** /**
* Table name * Table name
@@ -27,7 +27,7 @@ export class BankRule extends BaseModel {
/** /**
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { static get timestamps() {
return ['created_at', 'updated_at']; return ['created_at', 'updated_at'];
} }

View File

@@ -1,5 +1,6 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { BankRule } from './models/BankRule'; import { BankRule } from './models/BankRule';
import { CreateBankRuleDto, EditBankRuleDto } from './dtos/BankRule.dto';
export enum BankRuleConditionField { export enum BankRuleConditionField {
Amount = 'amount', Amount = 'amount',
@@ -94,11 +95,11 @@ export interface ICreateBankRuleDTO extends IBankRuleCommonDTO {}
export interface IEditBankRuleDTO extends IBankRuleCommonDTO {} export interface IEditBankRuleDTO extends IBankRuleCommonDTO {}
export interface IBankRuleEventCreatingPayload { export interface IBankRuleEventCreatingPayload {
createRuleDTO: ICreateBankRuleDTO; createRuleDTO: CreateBankRuleDto;
trx?: Knex.Transaction; trx?: Knex.Transaction;
} }
export interface IBankRuleEventCreatedPayload { export interface IBankRuleEventCreatedPayload {
createRuleDTO: ICreateBankRuleDTO; createRuleDTO: CreateBankRuleDto;
bankRule: BankRule; bankRule: BankRule;
trx?: Knex.Transaction; trx?: Knex.Transaction;
} }
@@ -106,13 +107,13 @@ export interface IBankRuleEventCreatedPayload {
export interface IBankRuleEventEditingPayload { export interface IBankRuleEventEditingPayload {
ruleId: number; ruleId: number;
oldBankRule: any; oldBankRule: any;
editRuleDTO: IEditBankRuleDTO; editRuleDTO: EditBankRuleDto;
trx?: Knex.Transaction; trx?: Knex.Transaction;
} }
export interface IBankRuleEventEditedPayload { export interface IBankRuleEventEditedPayload {
oldBankRule: BankRule; oldBankRule: BankRule;
bankRule: BankRule; bankRule: BankRule;
editRuleDTO: IEditBankRuleDTO; editRuleDTO: EditBankRuleDto;
trx?: Knex.Transaction; trx?: Knex.Transaction;
} }

View File

@@ -1,7 +1,8 @@
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common'; import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
import { BankingMatchingApplication } from './BankingMatchingApplication'; import { BankingMatchingApplication } from './BankingMatchingApplication';
import { GetMatchedTransactionsFilter, IMatchTransactionDTO } from './types'; import { GetMatchedTransactionsFilter, IMatchTransactionDTO } from './types';
import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { MatchBankTransactionDto } from './dtos/MatchBankTransaction.dto';
@Controller('banking/matching') @Controller('banking/matching')
@ApiTags('banking-transactions-matching') @ApiTags('banking-transactions-matching')
@@ -26,7 +27,7 @@ export class BankingMatchingController {
@ApiOperation({ summary: 'Match the given uncategorized transaction.' }) @ApiOperation({ summary: 'Match the given uncategorized transaction.' })
async matchTransaction( async matchTransaction(
@Param('uncategorizedTransactionId') uncategorizedTransactionId: number | number[], @Param('uncategorizedTransactionId') uncategorizedTransactionId: number | number[],
@Body() matchedTransactions: IMatchTransactionDTO[] @Body() matchedTransactions: MatchBankTransactionDto
) { ) {
return this.bankingMatchingApplication.matchTransaction( return this.bankingMatchingApplication.matchTransaction(
uncategorizedTransactionId, uncategorizedTransactionId,

View File

@@ -3,13 +3,14 @@ import { GetMatchedTransactions } from './queries/GetMatchedTransactions.service
import { MatchBankTransactions } from './commands/MatchTransactions'; import { MatchBankTransactions } from './commands/MatchTransactions';
import { UnmatchMatchedBankTransaction } from './commands/UnmatchMatchedTransaction.service'; import { UnmatchMatchedBankTransaction } from './commands/UnmatchMatchedTransaction.service';
import { GetMatchedTransactionsFilter, IMatchTransactionDTO } from './types'; import { GetMatchedTransactionsFilter, IMatchTransactionDTO } from './types';
import { MatchBankTransactionDto } from './dtos/MatchBankTransaction.dto';
@Injectable() @Injectable()
export class BankingMatchingApplication { export class BankingMatchingApplication {
constructor( constructor(
private readonly getMatchedTransactionsService: GetMatchedTransactions, private readonly getMatchedTransactionsService: GetMatchedTransactions,
private readonly matchTransactionService: MatchBankTransactions, private readonly matchTransactionService: MatchBankTransactions,
private readonly unmatchMatchedTransactionService: UnmatchMatchedBankTransaction private readonly unmatchMatchedTransactionService: UnmatchMatchedBankTransaction,
) {} ) {}
/** /**
@@ -20,11 +21,11 @@ export class BankingMatchingApplication {
*/ */
public getMatchedTransactions( public getMatchedTransactions(
uncategorizedTransactionsIds: Array<number>, uncategorizedTransactionsIds: Array<number>,
filter: GetMatchedTransactionsFilter filter: GetMatchedTransactionsFilter,
) { ) {
return this.getMatchedTransactionsService.getMatchedTransactions( return this.getMatchedTransactionsService.getMatchedTransactions(
uncategorizedTransactionsIds, uncategorizedTransactionsIds,
filter filter,
); );
} }
@@ -36,11 +37,11 @@ export class BankingMatchingApplication {
*/ */
public matchTransaction( public matchTransaction(
uncategorizedTransactionId: number | Array<number>, uncategorizedTransactionId: number | Array<number>,
matchedTransactions: Array<IMatchTransactionDTO> matchedTransactions: MatchBankTransactionDto,
): Promise<void> { ): Promise<void> {
return this.matchTransactionService.matchTransaction( return this.matchTransactionService.matchTransaction(
uncategorizedTransactionId, uncategorizedTransactionId,
matchedTransactions matchedTransactions,
); );
} }
@@ -49,11 +50,9 @@ export class BankingMatchingApplication {
* @param {number} uncategorizedTransactionId - Uncategorized transaction id. * @param {number} uncategorizedTransactionId - Uncategorized transaction id.
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
public unmatchMatchedTransaction( public unmatchMatchedTransaction(uncategorizedTransactionId: number) {
uncategorizedTransactionId: number
) {
return this.unmatchMatchedTransactionService.unmatchMatchedTransaction( return this.unmatchMatchedTransactionService.unmatchMatchedTransaction(
uncategorizedTransactionId uncategorizedTransactionId,
); );
} }
} }

View File

@@ -21,6 +21,7 @@ import { ServiceError } from '@/modules/Items/ServiceError';
import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction'; import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { MatchBankTransactionDto } from '../dtos/MatchBankTransaction.dto';
@Injectable() @Injectable()
export class MatchBankTransactions { export class MatchBankTransactions {
@@ -112,9 +113,10 @@ export class MatchBankTransactions {
*/ */
public async matchTransaction( public async matchTransaction(
uncategorizedTransactionId: number | Array<number>, uncategorizedTransactionId: number | Array<number>,
matchedTransactions: Array<IMatchTransactionDTO>, matchedTransactionsDto: MatchBankTransactionDto,
): Promise<void> { ): Promise<void> {
const uncategorizedTransactionIds = castArray(uncategorizedTransactionId); const uncategorizedTransactionIds = castArray(uncategorizedTransactionId);
const matchedTransactions = matchedTransactionsDto.entries;
// Validates the given matching transactions DTO. // Validates the given matching transactions DTO.
await this.validate(uncategorizedTransactionIds, matchedTransactions); await this.validate(uncategorizedTransactionIds, matchedTransactions);

View File

@@ -0,0 +1,25 @@
import {
IsArray,
IsNotEmpty,
IsNumber,
IsString,
ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';
export class MatchTransactionEntryDto {
@IsString()
@IsNotEmpty()
referenceType: string;
@IsNumber()
@IsNotEmpty()
referenceId: number;
}
export class MatchBankTransactionDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => MatchTransactionEntryDto)
entries: MatchTransactionEntryDto[];
}

View File

@@ -10,10 +10,10 @@ import {
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType'; import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
import { CreateBillPaymentService } from '@/modules/BillPayments/commands/CreateBillPayment.service'; import { CreateBillPaymentService } from '@/modules/BillPayments/commands/CreateBillPayment.service';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service'; import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { IBillPaymentDTO } from '@/modules/BillPayments/types/BillPayments.types';
import { Bill } from '@/modules/Bills/models/Bill'; import { Bill } from '@/modules/Bills/models/Bill';
import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction'; import { UncategorizedBankTransaction } from '@/modules/BankingTransactions/models/UncategorizedBankTransaction';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateBillPaymentDto } from '@/modules/BillPayments/dtos/BillPayment.dto';
@Injectable() @Injectable()
export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType { export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType {
@@ -110,7 +110,7 @@ export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType
.findById(matchTransactionDTO.referenceId) .findById(matchTransactionDTO.referenceId)
.throwIfNotFound(); .throwIfNotFound();
const createPaymentMadeDTO: IBillPaymentDTO = { const createPaymentMadeDTO: CreateBillPaymentDto = {
vendorId: bill.vendorId, vendorId: bill.vendorId,
paymentAccountId: uncategorizedTransaction.accountId, paymentAccountId: uncategorizedTransaction.accountId,
paymentDate: uncategorizedTransaction.date, paymentDate: uncategorizedTransaction.date,

View File

@@ -14,6 +14,7 @@ import {
} from './types/BankingTransactions.types'; } from './types/BankingTransactions.types';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { CreateBankTransactionDto } from './dtos/CreateBankTransaction.dto';
@Controller('banking/transactions') @Controller('banking/transactions')
@ApiTags('banking-transactions') @ApiTags('banking-transactions')
@@ -29,7 +30,7 @@ export class BankingTransactionsController {
} }
@Post() @Post()
async createTransaction(@Body() transactionDTO: ICashflowNewCommandDTO) { async createTransaction(@Body() transactionDTO: CreateBankTransactionDto) {
return this.bankingTransactionsApplication.createTransaction( return this.bankingTransactionsApplication.createTransaction(
transactionDTO, transactionDTO,
); );

View File

@@ -1,10 +1,12 @@
import { Knex } from 'knex'; import { Injectable } from '@nestjs/common';
import { DeleteCashflowTransaction } from './commands/DeleteCashflowTransaction.service'; import { DeleteCashflowTransaction } from './commands/DeleteCashflowTransaction.service';
import { CreateBankTransactionService } from './commands/CreateBankTransaction.service'; import { CreateBankTransactionService } from './commands/CreateBankTransaction.service';
import { GetBankTransactionService } from './queries/GetBankTransaction.service'; import { GetBankTransactionService } from './queries/GetBankTransaction.service';
import { IBankAccountsFilter, ICashflowNewCommandDTO } from './types/BankingTransactions.types'; import {
import { Injectable } from '@nestjs/common'; IBankAccountsFilter,
} from './types/BankingTransactions.types';
import { GetBankAccountsService } from './queries/GetBankAccounts.service'; import { GetBankAccountsService } from './queries/GetBankAccounts.service';
import { CreateBankTransactionDto } from './dtos/CreateBankTransaction.dto';
@Injectable() @Injectable()
export class BankingTransactionsApplication { export class BankingTransactionsApplication {
@@ -20,7 +22,7 @@ export class BankingTransactionsApplication {
* @param {ICashflowNewCommandDTO} transactionDTO * @param {ICashflowNewCommandDTO} transactionDTO
* @returns * @returns
*/ */
public createTransaction(transactionDTO: ICashflowNewCommandDTO) { public createTransaction(transactionDTO: CreateBankTransactionDto) {
return this.createTransactionService.newCashflowTransaction(transactionDTO); return this.createTransactionService.newCashflowTransaction(transactionDTO);
} }

View File

@@ -18,6 +18,7 @@ import {
ICommandCashflowCreatingPayload, ICommandCashflowCreatingPayload,
} from '../types/BankingTransactions.types'; } from '../types/BankingTransactions.types';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateBankTransactionDto } from '../dtos/CreateBankTransaction.dto';
@Injectable() @Injectable()
export class CreateBankTransactionService { export class CreateBankTransactionService {
@@ -62,7 +63,7 @@ export class CreateBankTransactionService {
* @returns {ICashflowTransactionInput} - Cashflow transaction object. * @returns {ICashflowTransactionInput} - Cashflow transaction object.
*/ */
private transformCashflowTransactionDTO = async ( private transformCashflowTransactionDTO = async (
newCashflowTransactionDTO: ICashflowNewCommandDTO, newCashflowTransactionDTO: CreateBankTransactionDto,
cashflowAccount: Account, cashflowAccount: Account,
userId: number, userId: number,
): Promise<BankTransaction> => { ): Promise<BankTransaction> => {

View File

@@ -0,0 +1,58 @@
import {
IsBoolean,
IsDate,
IsNumber,
IsOptional,
IsString,
} from 'class-validator';
export class CreateBankTransactionDto {
@IsDate()
date: Date;
@IsString()
transactionNumber: string;
@IsString()
referenceNo: string;
@IsString()
transactionType: string;
@IsString()
description: string;
@IsNumber()
amount: number;
@IsNumber()
exchangeRate: number;
@IsString()
currencyCode: string;
@IsNumber()
creditAccountId: number;
@IsNumber()
cashflowAccountId: number;
@IsBoolean()
publish: boolean;
@IsOptional()
@IsNumber()
branchId?: number;
@IsOptional()
@IsString()
plaidTransactionId?: string;
@IsOptional()
@IsString()
plaidAccountId?: string;
@IsOptional()
@IsNumber()
uncategorizedTransactionId?: number;
}

View File

@@ -1,6 +1,7 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction'; import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
import { BankTransaction } from '../models/BankTransaction'; import { BankTransaction } from '../models/BankTransaction';
import { CreateBankTransactionDto } from '../dtos/CreateBankTransaction.dto';
export interface IPendingTransactionRemovingEventPayload { export interface IPendingTransactionRemovingEventPayload {
uncategorizedTransactionId: number; uncategorizedTransactionId: number;
@@ -67,7 +68,7 @@ export interface ICommandCashflowCreatingPayload {
} }
export interface ICommandCashflowCreatedPayload { export interface ICommandCashflowCreatedPayload {
newTransactionDTO: ICashflowNewCommandDTO; newTransactionDTO: CreateBankTransactionDto;
cashflowTransaction: BankTransaction; cashflowTransaction: BankTransaction;
trx: Knex.Transaction; trx: Knex.Transaction;
} }

View File

@@ -8,8 +8,11 @@ import {
Put, Put,
} from '@nestjs/common'; } from '@nestjs/common';
import { BillPaymentsApplication } from './BillPaymentsApplication.service'; import { BillPaymentsApplication } from './BillPaymentsApplication.service';
import { IBillPaymentDTO } from './types/BillPayments.types';
import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
import {
CreateBillPaymentDto,
EditBillPaymentDto,
} from './dtos/BillPayment.dto';
@Controller('bill-payments') @Controller('bill-payments')
@ApiTags('bill-payments') @ApiTags('bill-payments')
@@ -18,7 +21,7 @@ export class BillPaymentsController {
@Post() @Post()
@ApiOperation({ summary: 'Create a new bill payment.' }) @ApiOperation({ summary: 'Create a new bill payment.' })
public createBillPayment(@Body() billPaymentDTO: IBillPaymentDTO) { public createBillPayment(@Body() billPaymentDTO: CreateBillPaymentDto) {
return this.billPaymentsApplication.createBillPayment(billPaymentDTO); return this.billPaymentsApplication.createBillPayment(billPaymentDTO);
} }
@@ -46,7 +49,7 @@ export class BillPaymentsController {
}) })
public editBillPayment( public editBillPayment(
@Param('billPaymentId') billPaymentId: string, @Param('billPaymentId') billPaymentId: string,
@Body() billPaymentDTO: IBillPaymentDTO, @Body() billPaymentDTO: EditBillPaymentDto,
) { ) {
return this.billPaymentsApplication.editBillPayment( return this.billPaymentsApplication.editBillPayment(
Number(billPaymentId), Number(billPaymentId),

View File

@@ -5,8 +5,8 @@ import { EditBillPayment } from './commands/EditBillPayment.service';
// import { GetBillPayments } from './GetBillPayments'; // import { GetBillPayments } from './GetBillPayments';
import { GetBillPayment } from './queries/GetBillPayment.service'; import { GetBillPayment } from './queries/GetBillPayment.service';
import { GetPaymentBills } from './queries/GetPaymentBills.service'; import { GetPaymentBills } from './queries/GetPaymentBills.service';
import { IBillPaymentDTO } from './types/BillPayments.types';
import { GetBillPayments } from '../Bills/queries/GetBillPayments'; import { GetBillPayments } from '../Bills/queries/GetBillPayments';
import { CreateBillPaymentDto, EditBillPaymentDto } from './dtos/BillPayment.dto';
/** /**
* Bill payments application. * Bill payments application.
@@ -28,7 +28,7 @@ export class BillPaymentsApplication {
* @param {IBillPaymentDTO} billPaymentDTO * @param {IBillPaymentDTO} billPaymentDTO
* @returns {Promise<IBillPayment>} * @returns {Promise<IBillPayment>}
*/ */
public createBillPayment(billPaymentDTO: IBillPaymentDTO) { public createBillPayment(billPaymentDTO: CreateBillPaymentDto) {
return this.createBillPaymentService.createBillPayment(billPaymentDTO); return this.createBillPaymentService.createBillPayment(billPaymentDTO);
} }
@@ -48,7 +48,7 @@ export class BillPaymentsApplication {
*/ */
public editBillPayment( public editBillPayment(
billPaymentId: number, billPaymentId: number,
billPaymentDTO: IBillPaymentDTO, billPaymentDTO: EditBillPaymentDto,
) { ) {
return this.editBillPaymentService.editBillPayment( return this.editBillPaymentService.editBillPayment(
billPaymentId, billPaymentId,

View File

@@ -1,10 +1,11 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { Bill } from '../../Bills/models/Bill'; import { Bill } from '../../Bills/models/Bill';
import { IBillPaymentEntryDTO } from '../types/BillPayments.types';
import { entriesAmountDiff } from '@/utils/entries-amount-diff'; import { entriesAmountDiff } from '@/utils/entries-amount-diff';
import Objection from 'objection'; import Objection, { ModelObject } from 'objection';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { BillPaymentEntryDto } from '../dtos/BillPayment.dto';
import { BillPaymentEntry } from '../models/BillPaymentEntry';
@Injectable() @Injectable()
export class BillPaymentBillSync { export class BillPaymentBillSync {
@@ -20,8 +21,8 @@ export class BillPaymentBillSync {
* @param {IBillPaymentEntryDTO[]} oldPaymentMadeEntries - * @param {IBillPaymentEntryDTO[]} oldPaymentMadeEntries -
*/ */
public async saveChangeBillsPaymentAmount( public async saveChangeBillsPaymentAmount(
paymentMadeEntries: IBillPaymentEntryDTO[], paymentMadeEntries: BillPaymentEntryDto[],
oldPaymentMadeEntries?: IBillPaymentEntryDTO[], oldPaymentMadeEntries?: ModelObject<BillPaymentEntry>[],
trx?: Knex.Transaction, trx?: Knex.Transaction,
): Promise<void> { ): Promise<void> {
const opers: Objection.QueryBuilder<Bill, Bill[]>[] = []; const opers: Objection.QueryBuilder<Bill, Bill[]>[] = [];

View File

@@ -1,9 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { sumBy, difference } from 'lodash'; import { sumBy, difference } from 'lodash';
import {
IBillPaymentDTO,
IBillPaymentEntryDTO,
} from '../types/BillPayments.types';
import { ERRORS } from '../constants'; import { ERRORS } from '../constants';
import { Bill } from '../../Bills/models/Bill'; import { Bill } from '../../Bills/models/Bill';
import { BillPayment } from '../models/BillPayment'; import { BillPayment } from '../models/BillPayment';
@@ -12,6 +8,10 @@ import { ServiceError } from '../../Items/ServiceError';
import { ACCOUNT_TYPE } from '@/constants/accounts'; import { ACCOUNT_TYPE } from '@/constants/accounts';
import { Account } from '../../Accounts/models/Account.model'; import { Account } from '../../Accounts/models/Account.model';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import {
BillPaymentEntryDto,
EditBillPaymentDto,
} from '../dtos/BillPayment.dto';
@Injectable() @Injectable()
export class BillPaymentValidators { export class BillPaymentValidators {
@@ -141,11 +141,11 @@ export class BillPaymentValidators {
* @return {void} * @return {void}
*/ */
public async validateBillsDueAmount( public async validateBillsDueAmount(
billPaymentEntries: IBillPaymentEntryDTO[], billPaymentEntries: BillPaymentEntryDto[],
oldPaymentEntries: BillPaymentEntry[] = [], oldPaymentEntries: BillPaymentEntry[] = [],
) { ) {
const billsIds = billPaymentEntries.map( const billsIds = billPaymentEntries.map(
(entry: IBillPaymentEntryDTO) => entry.billId, (entry: BillPaymentEntryDto) => entry.billId,
); );
const storedBills = await this.billModel().query().whereIn('id', billsIds); const storedBills = await this.billModel().query().whereIn('id', billsIds);
@@ -168,7 +168,7 @@ export class BillPaymentValidators {
} }
const hasWrongPaymentAmount: invalidPaymentAmountError[] = []; const hasWrongPaymentAmount: invalidPaymentAmountError[] = [];
billPaymentEntries.forEach((entry: IBillPaymentEntryDTO, index: number) => { billPaymentEntries.forEach((entry: BillPaymentEntryDto, index: number) => {
const entryBill = storedBillsMap.get(entry.billId); const entryBill = storedBillsMap.get(entry.billId);
const { dueAmount } = entryBill; const { dueAmount } = entryBill;
@@ -212,7 +212,7 @@ export class BillPaymentValidators {
* @param {string} billPaymentNo * @param {string} billPaymentNo
*/ */
public validateVendorNotModified( public validateVendorNotModified(
billPaymentDTO: IBillPaymentDTO, billPaymentDTO: EditBillPaymentDto,
oldBillPayment: BillPayment, oldBillPayment: BillPayment,
) { ) {
if (billPaymentDTO.vendorId !== oldBillPayment.vendorId) { if (billPaymentDTO.vendorId !== oldBillPayment.vendorId) {

View File

@@ -2,11 +2,14 @@ import { Injectable } from '@nestjs/common';
import * as R from 'ramda'; import * as R from 'ramda';
import { omit, sumBy } from 'lodash'; import { omit, sumBy } from 'lodash';
import { formatDateFields } from '@/utils/format-date-fields'; import { formatDateFields } from '@/utils/format-date-fields';
import { IBillPaymentDTO } from '../types/BillPayments.types';
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index'; import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform'; import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
import { Vendor } from '@/modules/Vendors/models/Vendor'; import { Vendor } from '@/modules/Vendors/models/Vendor';
import { BillPayment } from '../models/BillPayment'; import { BillPayment } from '../models/BillPayment';
import {
CreateBillPaymentDto,
EditBillPaymentDto,
} from '../dtos/BillPayment.dto';
@Injectable() @Injectable()
export class CommandBillPaymentDTOTransformer { export class CommandBillPaymentDTOTransformer {
@@ -22,7 +25,7 @@ export class CommandBillPaymentDTOTransformer {
* @return {Promise<IBillPayment>} * @return {Promise<IBillPayment>}
*/ */
public async transformDTOToModel( public async transformDTOToModel(
billPaymentDTO: IBillPaymentDTO, billPaymentDTO: CreateBillPaymentDto | EditBillPaymentDto,
vendor: Vendor, vendor: Vendor,
oldBillPayment?: BillPayment, oldBillPayment?: BillPayment,
): Promise<BillPayment> { ): Promise<BillPayment> {

View File

@@ -1,6 +1,5 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { import {
IBillPaymentDTO,
IBillPaymentEventCreatedPayload, IBillPaymentEventCreatedPayload,
IBillPaymentCreatingPayload, IBillPaymentCreatingPayload,
} from '../types/BillPayments.types'; } from '../types/BillPayments.types';
@@ -14,6 +13,7 @@ import { TenancyContext } from '../../Tenancy/TenancyContext.service';
import { BillPayment } from '../models/BillPayment'; import { BillPayment } from '../models/BillPayment';
import { Vendor } from '../../Vendors/models/Vendor'; import { Vendor } from '../../Vendors/models/Vendor';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateBillPaymentDto } from '../dtos/BillPayment.dto';
@Injectable() @Injectable()
export class CreateBillPaymentService { export class CreateBillPaymentService {
@@ -56,7 +56,7 @@ export class CreateBillPaymentService {
* @param {BillPaymentDTO} billPayment - Bill payment object. * @param {BillPaymentDTO} billPayment - Bill payment object.
*/ */
public async createBillPayment( public async createBillPayment(
billPaymentDTO: IBillPaymentDTO, billPaymentDTO: CreateBillPaymentDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
): Promise<BillPayment> { ): Promise<BillPayment> {
const tenantMeta = await this.tenancyContext.getTenant(true); const tenantMeta = await this.tenancyContext.getTenant(true);

View File

@@ -13,6 +13,7 @@ import { Vendor } from '@/modules/Vendors/models/Vendor';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditBillPaymentDto } from '../dtos/BillPayment.dto';
@Injectable() @Injectable()
export class EditBillPayment { export class EditBillPayment {
@@ -43,14 +44,13 @@ export class EditBillPayment {
* - Update the diff vendor balance. * - Update the diff vendor balance.
* - Update the diff bill payment amount. * - Update the diff bill payment amount.
* ------ * ------
* @param {number} tenantId - Tenant id
* @param {Integer} billPaymentId * @param {Integer} billPaymentId
* @param {BillPaymentDTO} billPayment * @param {EditBillPaymentDto} billPayment
* @param {IBillPayment} oldBillPayment * @param {BillPayment} oldBillPayment
*/ */
public async editBillPayment( public async editBillPayment(
billPaymentId: number, billPaymentId: number,
billPaymentDTO, billPaymentDTO: EditBillPaymentDto,
): Promise<BillPayment> { ): Promise<BillPayment> {
const tenantMeta = await this.tenancyContext.getTenant(true); const tenantMeta = await this.tenancyContext.getTenant(true);

View File

@@ -0,0 +1,68 @@
import { Type } from 'class-transformer';
import {
IsArray,
IsDate,
IsNumber,
IsOptional,
IsString,
ValidateNested,
} from 'class-validator';
import { AttachmentLinkDto } from '@/modules/Attachments/dtos/Attachment.dto';
export class BillPaymentEntryDto {
@IsNumber()
billId: number;
@IsNumber()
paymentAmount: number;
}
export class CommandBillPaymentDTO {
@IsNumber()
vendorId: number;
@IsNumber()
@IsOptional()
amount?: number;
@IsNumber()
paymentAccountId: number;
@IsString()
@IsOptional()
paymentNumber?: string;
@IsDate()
@Type(() => Date)
paymentDate: Date | string;
@IsNumber()
@IsOptional()
exchangeRate?: number;
@IsString()
@IsOptional()
statement?: string;
@IsString()
@IsOptional()
reference?: string;
@IsArray()
@ValidateNested({ each: true })
@Type(() => BillPaymentEntryDto)
entries: BillPaymentEntryDto[];
@IsNumber()
@IsOptional()
branchId?: number;
@IsArray()
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AttachmentLinkDto)
attachments?: AttachmentLinkDto[];
}
export class CreateBillPaymentDto extends CommandBillPaymentDTO {}
export class EditBillPaymentDto extends CommandBillPaymentDTO {}

View File

@@ -1,25 +1,7 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { BillPayment } from '../models/BillPayment'; import { BillPayment } from '../models/BillPayment';
import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types'; import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
import { CreateBillPaymentDto, EditBillPaymentDto } from '../dtos/BillPayment.dto';
export interface IBillPaymentEntryDTO {
billId: number;
paymentAmount: number;
}
export interface IBillPaymentDTO {
vendorId: number;
amount?: number;
paymentAccountId: number;
paymentNumber?: string;
paymentDate: Date | string;
exchangeRate?: number;
statement?: string;
reference?: string;
entries: IBillPaymentEntryDTO[];
branchId?: number;
attachments?: AttachmentLinkDTO[];
}
export interface IBillReceivePageEntry { export interface IBillReceivePageEntry {
billId: number; billId: number;
@@ -35,18 +17,18 @@ export interface IBillReceivePageEntry {
export interface IBillPaymentEventCreatedPayload { export interface IBillPaymentEventCreatedPayload {
billPayment: BillPayment; billPayment: BillPayment;
billPaymentDTO: IBillPaymentDTO; billPaymentDTO: CreateBillPaymentDto;
billPaymentId: number; billPaymentId: number;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillPaymentCreatingPayload { export interface IBillPaymentCreatingPayload {
billPaymentDTO: IBillPaymentDTO; billPaymentDTO: CreateBillPaymentDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillPaymentEditingPayload { export interface IBillPaymentEditingPayload {
billPaymentDTO: IBillPaymentDTO; billPaymentDTO: EditBillPaymentDto;
oldBillPayment: BillPayment; oldBillPayment: BillPayment;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
@@ -54,7 +36,7 @@ export interface IBillPaymentEventEditedPayload {
billPaymentId: number; billPaymentId: number;
billPayment: BillPayment; billPayment: BillPayment;
oldBillPayment: BillPayment; oldBillPayment: BillPayment;
billPaymentDTO: IBillPaymentDTO; billPaymentDTO: EditBillPaymentDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }

View File

@@ -7,6 +7,7 @@ import { GetDueBills } from './queries/GetDueBills.service';
import { OpenBillService } from './commands/OpenBill.service'; 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 { GetBillPayments } from './queries/GetBillPayments'; // import { GetBillPayments } from './queries/GetBillPayments';
// import { GetBills } from './queries/GetBills'; // import { GetBills } from './queries/GetBills';
@@ -28,7 +29,7 @@ export class BillsApplication {
* @param {IBillDTO} billDTO * @param {IBillDTO} billDTO
* @returns * @returns
*/ */
public createBill(billDTO: IBillDTO) { public createBill(billDTO: CreateBillDto) {
return this.createBillService.createBill(billDTO); return this.createBillService.createBill(billDTO);
} }
@@ -38,7 +39,7 @@ export class BillsApplication {
* @param {IBillEditDTO} billDTO * @param {IBillEditDTO} billDTO
* @returns * @returns
*/ */
public editBill(billId: number, billDTO: IBillEditDTO) { public editBill(billId: number, billDTO: EditBillDto) {
return this.editBillService.editBill(billId, billDTO); return this.editBillService.editBill(billId, billDTO);
} }

View File

@@ -10,8 +10,9 @@ import {
Query, Query,
} from '@nestjs/common'; } from '@nestjs/common';
import { BillsApplication } from './Bills.application'; import { BillsApplication } from './Bills.application';
import { IBillDTO, IBillEditDTO, IBillsFilter } from './Bills.types'; import { IBillsFilter } from './Bills.types';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { CreateBillDto, EditBillDto } from './dtos/Bill.dto';
@Controller('bills') @Controller('bills')
@ApiTags('bills') @ApiTags('bills')
@@ -21,7 +22,7 @@ export class BillsController {
@Post() @Post()
@ApiOperation({ summary: 'Create a new bill.' }) @ApiOperation({ summary: 'Create a new bill.' })
createBill(@Body() billDTO: IBillDTO) { createBill(@Body() billDTO: CreateBillDto) {
return this.billsApplication.createBill(billDTO); return this.billsApplication.createBill(billDTO);
} }
@@ -33,7 +34,7 @@ export class BillsController {
type: Number, type: Number,
description: 'The bill id', description: 'The bill id',
}) })
editBill(@Param('id') billId: number, @Body() billDTO: IBillEditDTO) { editBill(@Param('id') billId: number, @Body() billDTO: EditBillDto) {
return this.billsApplication.editBill(billId, billDTO); return this.billsApplication.editBill(billId, billDTO);
} }

View File

@@ -3,6 +3,7 @@ import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types';
import { AttachmentLinkDTO } from '../Attachments/Attachments.types'; import { AttachmentLinkDTO } from '../Attachments/Attachments.types';
import { Bill } from './models/Bill'; import { Bill } from './models/Bill';
import { IDynamicListFilter } from '../DynamicListing/DynamicFilter/DynamicFilter.types'; import { IDynamicListFilter } from '../DynamicListing/DynamicFilter/DynamicFilter.types';
import { CreateBillDto, EditBillDto } from './dtos/Bill.dto';
export interface IBillDTO { export interface IBillDTO {
vendorId: number; vendorId: number;
@@ -51,29 +52,25 @@ export interface IBillsFilter extends IDynamicListFilter {
} }
export interface IBillCreatedPayload { export interface IBillCreatedPayload {
// tenantId: number;
bill: Bill; bill: Bill;
billDTO: IBillDTO; billDTO: CreateBillDto;
// billId: number;
trx?: Knex.Transaction; trx?: Knex.Transaction;
} }
export interface IBillCreatingPayload { export interface IBillCreatingPayload {
// tenantId: number; billDTO: CreateBillDto;
billDTO: IBillDTO;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillEditingPayload { export interface IBillEditingPayload {
// tenantId: number;
oldBill: Bill; oldBill: Bill;
billDTO: IBillEditDTO; billDTO: EditBillDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IBillEditedPayload { export interface IBillEditedPayload {
oldBill: Bill; oldBill: Bill;
bill: Bill; bill: Bill;
billDTO: IBillDTO; billDTO: EditBillDto;
trx?: Knex.Transaction; trx?: Knex.Transaction;
} }

View File

@@ -15,6 +15,7 @@ import { Bill } from '../models/Bill';
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index'; import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateBillDto } from '../dtos/Bill.dto';
@Injectable() @Injectable()
export class BillDTOTransformer { export class BillDTOTransformer {
@@ -40,10 +41,10 @@ export class BillDTOTransformer {
/** /**
* Retrieve the bill landed cost amount. * Retrieve the bill landed cost amount.
* @param {IBillDTO} billDTO * @param {CreateBillDto} billDTO
* @returns {number} * @returns {number}
*/ */
private getBillLandedCostAmount(billDTO: IBillDTO): number { private getBillLandedCostAmount(billDTO: CreateBillDto): number {
const costEntries = billDTO.entries.filter((entry) => entry.landedCost); const costEntries = billDTO.entries.filter((entry) => entry.landedCost);
// return this.getBillEntriesTotal(costEntries); // return this.getBillEntriesTotal(costEntries);
@@ -58,7 +59,7 @@ export class BillDTOTransformer {
* @returns {IBill} * @returns {IBill}
*/ */
public async billDTOToModel( public async billDTOToModel(
billDTO: IBillDTO, billDTO: CreateBillDto,
vendor: Vendor, vendor: Vendor,
oldBill?: Bill, oldBill?: Bill,
): Promise<Bill> { ): Promise<Bill> {

View File

@@ -9,6 +9,8 @@ import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost'
import { VendorCreditAppliedBill } from '@/modules/VendorCreditsApplyBills/models/VendorCreditAppliedBill'; import { VendorCreditAppliedBill } from '@/modules/VendorCreditsApplyBills/models/VendorCreditAppliedBill';
import { transformToMap } from '@/utils/transform-to-key'; import { transformToMap } from '@/utils/transform-to-key';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { BillEntryDto } from '../dtos/Bill.dto';
@Injectable() @Injectable()
export class BillsValidators { export class BillsValidators {
@@ -123,7 +125,7 @@ export class BillsValidators {
* @param {IItemEntryDTO[]} newEntriesDTO - * @param {IItemEntryDTO[]} newEntriesDTO -
*/ */
public async validateCostEntriesShouldBeInventoryItems( public async validateCostEntriesShouldBeInventoryItems(
newEntriesDTO: IItemEntryDTO[], newEntriesDTO: BillEntryDto[],
) { ) {
const entriesItemsIds = newEntriesDTO.map((e) => e.itemId); const entriesItemsIds = newEntriesDTO.map((e) => e.itemId);
const entriesItems = await this.itemModel() const entriesItems = await this.itemModel()

View File

@@ -14,6 +14,7 @@ import { Bill } from '../models/Bill';
import { Vendor } from '@/modules/Vendors/models/Vendor'; import { Vendor } from '@/modules/Vendors/models/Vendor';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateBillDto } from '../dtos/Bill.dto';
@Injectable() @Injectable()
export class CreateBill { export class CreateBill {
@@ -46,7 +47,7 @@ export class CreateBill {
* @return {Promise<IBill>} * @return {Promise<IBill>}
*/ */
public async createBill( public async createBill(
billDTO: IBillDTO, billDTO: CreateBillDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
): Promise<Bill> { ): Promise<Bill> {
// Retrieves the given bill vendor or throw not found error. // Retrieves the given bill vendor or throw not found error.

View File

@@ -15,6 +15,7 @@ import { Vendor } from '@/modules/Vendors/models/Vendor';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { TransactionLandedCostEntriesService } from '@/modules/BillLandedCosts/TransactionLandedCostEntries.service'; import { TransactionLandedCostEntriesService } from '@/modules/BillLandedCosts/TransactionLandedCostEntries.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditBillDto } from '../dtos/Bill.dto';
@Injectable() @Injectable()
export class EditBillService { export class EditBillService {
@@ -46,7 +47,7 @@ export class EditBillService {
* @param {IBillEditDTO} billDTO - The given new bill details. * @param {IBillEditDTO} billDTO - The given new bill details.
* @return {Promise<IBill>} * @return {Promise<IBill>}
*/ */
public async editBill(billId: number, billDTO: IBillEditDTO): Promise<Bill> { public async editBill(billId: number, billDTO: EditBillDto): Promise<Bill> {
// Retrieve the given bill or throw not found error. // Retrieve the given bill or throw not found error.
const oldBill = await this.billModel() const oldBill = await this.billModel()
.query() .query()

View File

@@ -0,0 +1,106 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsDate,
IsEnum,
IsInt,
IsNumber,
IsOptional,
IsPositive,
IsString,
Min,
MinLength,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
export class BillEntryDto extends ItemEntryDto {
@IsOptional()
@IsBoolean()
landedCost?: boolean;
}
class AttachmentDto {
@IsString()
key: string;
}
export class CommandBillDto {
@IsString()
billNumber: string;
@IsOptional()
@IsString()
referenceNo?: string;
@IsDate()
@Type(() => Date)
billDate: Date;
@IsOptional()
@IsDate()
@Type(() => Date)
dueDate?: Date;
@IsInt()
vendorId: number;
@IsOptional()
@IsNumber()
@IsPositive()
exchangeRate?: number;
@IsOptional()
@IsInt()
warehouseId?: number;
@IsOptional()
@IsInt()
branchId?: number;
@IsOptional()
@IsInt()
projectId?: number;
@IsOptional()
@IsString()
note?: string;
@IsBoolean()
open: boolean = false;
@IsBoolean()
isInclusiveTax: boolean = false;
@IsArray()
@ValidateNested({ each: true })
@Type(() => BillEntryDto)
@MinLength(1)
entries: BillEntryDto[];
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AttachmentDto)
attachments?: AttachmentDto[];
@IsEnum(DiscountType)
discountType: DiscountType = DiscountType.Amount;
@IsOptional()
@IsNumber()
discount?: number;
@IsOptional()
@IsNumber()
adjustment?: number;
}
export class CreateBillDto extends CommandBillDto {}
export class EditBillDto extends CommandBillDto {}

View File

@@ -1,5 +1,6 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { import {
IsBoolean,
IsEmail, IsEmail,
IsNotEmpty, IsNotEmpty,
IsOptional, IsOptional,
@@ -13,6 +14,11 @@ class CommandBranchDto {
@IsString() @IsString()
name: string; name: string;
@ApiPropertyOptional({ description: 'Branch code' })
@IsOptional()
@IsBoolean()
primary?: boolean;
@ApiPropertyOptional({ description: 'Branch code' }) @ApiPropertyOptional({ description: 'Branch code' })
@IsOptional() @IsOptional()
@IsString() @IsString()

View File

@@ -3,6 +3,7 @@ import { Body, Controller, Delete, Param, Post } from '@nestjs/common';
import { ICreditNoteRefundDTO } from '../CreditNotes/types/CreditNotes.types'; import { ICreditNoteRefundDTO } from '../CreditNotes/types/CreditNotes.types';
import { CreditNotesRefundsApplication } from './CreditNotesRefundsApplication.service'; import { CreditNotesRefundsApplication } from './CreditNotesRefundsApplication.service';
import { RefundCreditNote } from './models/RefundCreditNote'; import { RefundCreditNote } from './models/RefundCreditNote';
import { CreditNoteRefundDto } from './dto/CreditNoteRefund.dto';
@Controller('credit-notes') @Controller('credit-notes')
@ApiTags('credit-notes-refunds') @ApiTags('credit-notes-refunds')
@@ -21,7 +22,7 @@ export class CreditNoteRefundsController {
@ApiOperation({ summary: 'Create a refund for the given credit note.' }) @ApiOperation({ summary: 'Create a refund for the given credit note.' })
createRefundCreditNote( createRefundCreditNote(
@Param('creditNoteId') creditNoteId: number, @Param('creditNoteId') creditNoteId: number,
@Body() creditNoteDTO: ICreditNoteRefundDTO, @Body() creditNoteDTO: CreditNoteRefundDto,
): Promise<RefundCreditNote> { ): Promise<RefundCreditNote> {
return this.creditNotesRefundsApplication.createRefundCreditNote( return this.creditNotesRefundsApplication.createRefundCreditNote(
creditNoteId, creditNoteId,

View File

@@ -4,6 +4,7 @@ import { CreateRefundCreditNoteService } from './commands/CreateRefundCreditNote
import { DeleteRefundCreditNoteService } from './commands/DeleteRefundCreditNote.service'; import { DeleteRefundCreditNoteService } from './commands/DeleteRefundCreditNote.service';
import { RefundCreditNoteService } from './commands/RefundCreditNote.service'; import { RefundCreditNoteService } from './commands/RefundCreditNote.service';
import { RefundSyncCreditNoteBalanceService } from './commands/RefundSyncCreditNoteBalance'; import { RefundSyncCreditNoteBalanceService } from './commands/RefundSyncCreditNoteBalance';
import { CreditNoteRefundDto } from './dto/CreditNoteRefund.dto';
@Injectable() @Injectable()
export class CreditNotesRefundsApplication { export class CreditNotesRefundsApplication {
@@ -17,12 +18,12 @@ export class CreditNotesRefundsApplication {
/** /**
* Create a refund credit note. * Create a refund credit note.
* @param {number} creditNoteId - The credit note ID. * @param {number} creditNoteId - The credit note ID.
* @param {ICreditNoteRefundDTO} creditNoteDTO - The credit note DTO. * @param {CreditNoteRefundDto} creditNoteDTO - The credit note DTO.
* @returns {Promise<RefundCreditNote>} * @returns {Promise<RefundCreditNote>}
*/ */
public createRefundCreditNote( public createRefundCreditNote(
creditNoteId: number, creditNoteId: number,
creditNoteDTO: ICreditNoteRefundDTO, creditNoteDTO: CreditNoteRefundDto,
) { ) {
return this.createRefundCreditNoteService.createCreditNoteRefund( return this.createRefundCreditNoteService.createCreditNoteRefund(
creditNoteId, creditNoteId,

View File

@@ -13,6 +13,7 @@ import { CommandCreditNoteDTOTransform } from '@/modules/CreditNotes/commands/Co
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote'; import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreditNoteRefundDto } from '../dto/CreditNoteRefund.dto';
@Injectable() @Injectable()
export class CreateRefundCreditNoteService { export class CreateRefundCreditNoteService {
@@ -47,7 +48,7 @@ export class CreateRefundCreditNoteService {
*/ */
public async createCreditNoteRefund( public async createCreditNoteRefund(
creditNoteId: number, creditNoteId: number,
newCreditNoteDTO: ICreditNoteRefundDTO, newCreditNoteDTO: CreditNoteRefundDto,
): Promise<RefundCreditNote> { ): Promise<RefundCreditNote> {
// Retrieve the credit note or throw not found service error. // Retrieve the credit note or throw not found service error.
const creditNote = await this.creditNoteModel() const creditNote = await this.creditNoteModel()
@@ -85,7 +86,6 @@ export class CreateRefundCreditNoteService {
.insertAndFetch({ .insertAndFetch({
...this.transformDTOToModel(creditNote, newCreditNoteDTO), ...this.transformDTOToModel(creditNote, newCreditNoteDTO),
}); });
// Triggers `onCreditNoteRefundCreated` event. // Triggers `onCreditNoteRefundCreated` event.
await this.eventPublisher.emitAsync(events.creditNote.onRefundCreated, { await this.eventPublisher.emitAsync(events.creditNote.onRefundCreated, {
trx, trx,
@@ -99,13 +99,13 @@ export class CreateRefundCreditNoteService {
/** /**
* Transformes the refund credit note DTO to model. * Transformes the refund credit note DTO to model.
* @param {number} creditNoteId * @param {CreditNote} creditNote - The credit note.
* @param {ICreditNoteRefundDTO} creditNoteDTO * @param {CreditNoteRefundDto} creditNoteDTO - The credit note refund DTO.
* @returns {ICreditNote} * @returns {Partial<RefundCreditNote>}
*/ */
private transformDTOToModel = ( private transformDTOToModel = (
creditNote: CreditNote, creditNote: CreditNote,
creditNoteDTO: ICreditNoteRefundDTO, creditNoteDTO: CreditNoteRefundDto,
): Partial<RefundCreditNote> => { ): Partial<RefundCreditNote> => {
return { return {
creditNoteId: creditNote.id, creditNoteId: creditNote.id,

View File

@@ -0,0 +1,35 @@
import { IsNotEmpty, IsOptional, IsPositive, IsString } from 'class-validator';
import { IsDate } from 'class-validator';
import { IsNumber } from 'class-validator';
export class CreditNoteRefundDto {
@IsNumber()
@IsNotEmpty()
fromAccountId: number;
@IsNumber()
@IsPositive()
@IsNotEmpty()
amount: number;
@IsNumber()
@IsOptional()
@IsPositive()
exchangeRate?: number;
@IsString()
@IsNotEmpty()
referenceNo: string;
@IsString()
@IsNotEmpty()
description: string;
@IsDate()
@IsNotEmpty()
date: Date;
@IsNumber()
@IsOptional()
branchId?: number;
}

View File

@@ -1,6 +1,7 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { RefundCreditNote } from '../models/RefundCreditNote'; import { RefundCreditNote } from '../models/RefundCreditNote';
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote'; import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
import { CreditNoteRefundDto } from '../dto/CreditNoteRefund.dto';
export interface ICreditNoteRefundDTO { export interface ICreditNoteRefundDTO {
fromAccountId: number; fromAccountId: number;
@@ -31,7 +32,7 @@ export interface IRefundCreditNoteDeletingPayload {
export interface IRefundCreditNoteCreatingPayload { export interface IRefundCreditNoteCreatingPayload {
trx: Knex.Transaction; trx: Knex.Transaction;
creditNote: CreditNote; creditNote: CreditNote;
newCreditNoteDTO: ICreditNoteRefundDTO; newCreditNoteDTO: CreditNoteRefundDto;
} }
export interface IRefundCreditNoteCreatedPayload { export interface IRefundCreditNoteCreatedPayload {

View File

@@ -4,12 +4,9 @@ import { DeleteCreditNoteService } from './commands/DeleteCreditNote.service';
import { EditCreditNoteService } from './commands/EditCreditNote.service'; import { EditCreditNoteService } from './commands/EditCreditNote.service';
import { OpenCreditNoteService } from './commands/OpenCreditNote.service'; import { OpenCreditNoteService } from './commands/OpenCreditNote.service';
import { GetCreditNotePdf } from './queries/GetCreditNotePdf.serivce'; import { GetCreditNotePdf } from './queries/GetCreditNotePdf.serivce';
import { import { ICreditNotesQueryDTO } from './types/CreditNotes.types';
ICreditNoteEditDTO,
ICreditNoteNewDTO,
ICreditNotesQueryDTO,
} from './types/CreditNotes.types';
import { GetCreditNotesService } from './queries/GetCreditNotes.service'; import { GetCreditNotesService } from './queries/GetCreditNotes.service';
import { CreateCreditNoteDto, EditCreditNoteDto } from './dtos/CreditNote.dto';
@Injectable() @Injectable()
export class CreditNoteApplication { export class CreditNoteApplication {
@@ -24,20 +21,20 @@ export class CreditNoteApplication {
/** /**
* Creates a new credit note. * Creates a new credit note.
* @param {ICreditNoteNewDTO} creditNoteDTO * @param {CreateCreditNoteDto} creditNoteDTO
* @returns {Promise<CreditNote>} * @returns {Promise<CreditNote>}
*/ */
createCreditNote(creditNoteDTO: ICreditNoteNewDTO) { createCreditNote(creditNoteDTO: CreateCreditNoteDto) {
return this.createCreditNoteService.creditCreditNote(creditNoteDTO); return this.createCreditNoteService.creditCreditNote(creditNoteDTO);
} }
/** /**
* Edits a credit note. * Edits a credit note.
* @param {number} creditNoteId * @param {number} creditNoteId
* @param {ICreditNoteEditDTO} creditNoteDTO * @param {EditCreditNoteDto} creditNoteDTO
* @returns {Promise<CreditNote>} * @returns {Promise<CreditNote>}
*/ */
editCreditNote(creditNoteId: number, creditNoteDTO: ICreditNoteEditDTO) { editCreditNote(creditNoteId: number, creditNoteDTO: EditCreditNoteDto) {
return this.editCreditNoteService.editCreditNote( return this.editCreditNoteService.editCreditNote(
creditNoteId, creditNoteId,
creditNoteDTO, creditNoteDTO,

View File

@@ -9,13 +9,10 @@ import {
Query, Query,
} from '@nestjs/common'; } from '@nestjs/common';
import { CreditNoteApplication } from './CreditNoteApplication.service'; import { CreditNoteApplication } from './CreditNoteApplication.service';
import { import { ICreditNotesQueryDTO } from './types/CreditNotes.types';
ICreditNoteEditDTO,
ICreditNoteNewDTO,
ICreditNotesQueryDTO,
} from './types/CreditNotes.types';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { CreateCreditNoteDto, EditCreditNoteDto } from './dtos/CreditNote.dto';
@Controller('credit-notes') @Controller('credit-notes')
@ApiTags('credit-notes') @ApiTags('credit-notes')
@@ -27,7 +24,7 @@ export class CreditNotesController {
constructor(private creditNoteApplication: CreditNoteApplication) {} constructor(private creditNoteApplication: CreditNoteApplication) {}
@Post() @Post()
createCreditNote(@Body() creditNoteDTO: ICreditNoteNewDTO) { createCreditNote(@Body() creditNoteDTO: CreateCreditNoteDto) {
return this.creditNoteApplication.createCreditNote(creditNoteDTO); return this.creditNoteApplication.createCreditNote(creditNoteDTO);
} }
@@ -39,7 +36,7 @@ export class CreditNotesController {
@Put(':id') @Put(':id')
editCreditNote( editCreditNote(
@Param('id') creditNoteId: number, @Param('id') creditNoteId: number,
@Body() creditNoteDTO: ICreditNoteEditDTO, @Body() creditNoteDTO: EditCreditNoteDto,
) { ) {
return this.creditNoteApplication.editCreditNote( return this.creditNoteApplication.editCreditNote(
creditNoteId, creditNoteId,

View File

@@ -17,6 +17,7 @@ import { BrandingTemplateDTOTransformer } from '../../PdfTemplate/BrandingTempla
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index'; import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
import { CreditNoteAutoIncrementService } from './CreditNoteAutoIncrement.service'; import { CreditNoteAutoIncrementService } from './CreditNoteAutoIncrement.service';
import { CreditNote } from '../models/CreditNote'; import { CreditNote } from '../models/CreditNote';
import { CreateCreditNoteDto, EditCreditNoteDto } from '../dtos/CreditNote.dto';
@Injectable() @Injectable()
export class CommandCreditNoteDTOTransform { export class CommandCreditNoteDTOTransform {
@@ -41,7 +42,7 @@ export class CommandCreditNoteDTOTransform {
* @param {string} customerCurrencyCode - * @param {string} customerCurrencyCode -
*/ */
public transformCreateEditDTOToModel = async ( public transformCreateEditDTOToModel = async (
creditNoteDTO: ICreditNoteNewDTO | ICreditNoteEditDTO, creditNoteDTO: CreateCreditNoteDto | EditCreditNoteDto,
customerCurrencyCode: string, customerCurrencyCode: string,
oldCreditNote?: CreditNote, oldCreditNote?: CreditNote,
): Promise<CreditNote> => { ): Promise<CreditNote> => {

View File

@@ -3,7 +3,6 @@ import { Inject, Injectable } from '@nestjs/common';
import { import {
ICreditNoteCreatedPayload, ICreditNoteCreatedPayload,
ICreditNoteCreatingPayload, ICreditNoteCreatingPayload,
ICreditNoteNewDTO,
} from '../types/CreditNotes.types'; } from '../types/CreditNotes.types';
import { CreditNote } from '../models/CreditNote'; import { CreditNote } from '../models/CreditNote';
import { Contact } from '../../Contacts/models/Contact'; import { Contact } from '../../Contacts/models/Contact';
@@ -13,6 +12,7 @@ import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { EventEmitter2 } from '@nestjs/event-emitter'; import { EventEmitter2 } from '@nestjs/event-emitter';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateCreditNoteDto } from '../dtos/CreditNote.dto';
@Injectable() @Injectable()
export class CreateCreditNoteService { export class CreateCreditNoteService {
@@ -42,7 +42,7 @@ export class CreateCreditNoteService {
* @param creditNoteDTO * @param creditNoteDTO
*/ */
public creditCreditNote = async ( public creditCreditNote = async (
creditNoteDTO: ICreditNoteNewDTO, creditNoteDTO: CreateCreditNoteDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
) => { ) => {
// Triggers `onCreditNoteCreate` event. // Triggers `onCreditNoteCreate` event.

View File

@@ -1,6 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { import {
ICreditNoteEditDTO,
ICreditNoteEditedPayload, ICreditNoteEditedPayload,
ICreditNoteEditingPayload, ICreditNoteEditingPayload,
} from '../types/CreditNotes.types'; } from '../types/CreditNotes.types';
@@ -13,6 +12,7 @@ import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { CommandCreditNoteDTOTransform } from './CommandCreditNoteDTOTransform.service'; import { CommandCreditNoteDTOTransform } from './CommandCreditNoteDTOTransform.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditCreditNoteDto } from '../dtos/CreditNote.dto';
@Injectable() @Injectable()
export class EditCreditNoteService { export class EditCreditNoteService {
@@ -27,6 +27,7 @@ export class EditCreditNoteService {
constructor( constructor(
@Inject(CreditNote.name) @Inject(CreditNote.name)
private creditNoteModel: TenantModelProxy<typeof CreditNote>, private creditNoteModel: TenantModelProxy<typeof CreditNote>,
@Inject(Contact.name) @Inject(Contact.name)
private contactModel: TenantModelProxy<typeof Contact>, private contactModel: TenantModelProxy<typeof Contact>,
@@ -42,7 +43,7 @@ export class EditCreditNoteService {
*/ */
public async editCreditNote( public async editCreditNote(
creditNoteId: number, creditNoteId: number,
creditNoteEditDTO: ICreditNoteEditDTO, creditNoteEditDTO: EditCreditNoteDto,
) { ) {
// Retrieve the sale invoice or throw not found service error. // Retrieve the sale invoice or throw not found service error.
const oldCreditNote = await this.creditNoteModel() const oldCreditNote = await this.creditNoteModel()

View File

@@ -0,0 +1,98 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsDate,
IsEnum,
IsInt,
IsNumber,
IsOptional,
IsPositive,
IsString,
Min,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
class CreditNoteEntryDto extends ItemEntryDto {}
class AttachmentDto {
@IsString()
key: string;
}
export class CommandCreditNoteDto {
@IsInt()
customerId: number;
@IsOptional()
@IsPositive()
exchangeRate?: number;
@IsDate()
@Type(() => Date)
creditNoteDate: Date;
@IsOptional()
@IsString()
referenceNo?: string;
@IsOptional()
@IsString()
creditNoteNumber?: string;
@IsOptional()
@IsString()
note?: string;
@IsOptional()
@IsString()
termsConditions?: string;
@IsBoolean()
open: boolean = false;
@IsOptional()
@IsInt()
warehouseId?: number;
@IsOptional()
@IsInt()
branchId?: number;
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreditNoteEntryDto)
@Min(1)
entries: CreditNoteEntryDto[];
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AttachmentDto)
attachments?: AttachmentDto[];
@IsOptional()
@IsInt()
pdfTemplateId?: number;
@IsOptional()
@IsNumber()
discount?: number;
@IsOptional()
@IsEnum(DiscountType)
discountType?: DiscountType;
@IsOptional()
@IsNumber()
adjustment?: number;
}
export class CreateCreditNoteDto extends CommandCreditNoteDto {}
export class EditCreditNoteDto extends CommandCreditNoteDto {}

View File

@@ -0,0 +1,12 @@
import {
IsDate,
IsInt,
IsNumber,
IsOptional,
IsPositive,
IsString,
} from 'class-validator';
export class RefundCreditNoteDto {
}

View File

@@ -6,6 +6,7 @@ import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model'; import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types'; import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types'; import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
import { EditCreditNoteDto } from '../dtos/CreditNote.dto';
export interface ICreditNoteEntryNewDTO extends IItemEntryDTO {} export interface ICreditNoteEntryNewDTO extends IItemEntryDTO {}
@@ -60,17 +61,16 @@ export interface ICreditNoteDeletedPayload {
} }
export interface ICreditNoteEditingPayload { export interface ICreditNoteEditingPayload {
trx: Knex.Transaction;
oldCreditNote: CreditNote; oldCreditNote: CreditNote;
creditNoteEditDTO: ICreditNoteEditDTO; creditNoteEditDTO: EditCreditNoteDto;
tenantId: number; trx?: Knex.Transaction;
} }
export interface ICreditNoteEditedPayload { export interface ICreditNoteEditedPayload {
trx: Knex.Transaction; trx?: Knex.Transaction;
oldCreditNote: CreditNote; oldCreditNote: CreditNote;
creditNote: CreditNote; creditNote: CreditNote;
creditNoteEditDTO: ICreditNoteEditDTO; creditNoteEditDTO: EditCreditNoteDto;
} }
export interface ICreditNoteCreatedPayload { export interface ICreditNoteCreatedPayload {

View File

@@ -6,6 +6,11 @@ import { Injectable } from '@nestjs/common';
@Injectable() @Injectable()
export class TrialBalanceSheetApplication { export class TrialBalanceSheetApplication {
/**
* @param {TrialBalanceSheetService} sheetService - The trial balance sheet service.
* @param {TrialBalanceSheetTableInjectable} tablable - The trial balance sheet table injectable.
* @param {TrialBalanceExportInjectable} exportable - The trial balance export injectable.
*/
constructor( constructor(
private readonly sheetService: TrialBalanceSheetService, private readonly sheetService: TrialBalanceSheetService,
private readonly tablable: TrialBalanceSheetTableInjectable, private readonly tablable: TrialBalanceSheetTableInjectable,

View File

@@ -17,6 +17,7 @@ import { InventoryAdjustment } from './models/InventoryAdjustment';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { IPaginationMeta } from '@/interfaces/Model'; import { IPaginationMeta } from '@/interfaces/Model';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CreateQuickInventoryAdjustmentDto } from './dtos/CreateQuickInventoryAdjustment.dto';
@Controller('inventory-adjustments') @Controller('inventory-adjustments')
@ApiTags('inventory-adjustments') @ApiTags('inventory-adjustments')
@@ -33,7 +34,7 @@ export class InventoryAdjustmentsController {
description: 'The inventory adjustment has been successfully created.', description: 'The inventory adjustment has been successfully created.',
}) })
public async createQuickInventoryAdjustment( public async createQuickInventoryAdjustment(
@Body() quickAdjustmentDTO: IQuickInventoryAdjustmentDTO, @Body() quickAdjustmentDTO: CreateQuickInventoryAdjustmentDto,
): Promise<InventoryAdjustment> { ): Promise<InventoryAdjustment> {
return this.inventoryAdjustmentsApplicationService.createQuickInventoryAdjustment( return this.inventoryAdjustmentsApplicationService.createQuickInventoryAdjustment(
quickAdjustmentDTO, quickAdjustmentDTO,

View File

@@ -10,6 +10,7 @@ import { InventoryAdjustment } from './models/InventoryAdjustment';
import { GetInventoryAdjustmentService } from './queries/GetInventoryAdjustment.service'; import { GetInventoryAdjustmentService } from './queries/GetInventoryAdjustment.service';
import { GetInventoryAdjustmentsService } from './queries/GetInventoryAdjustments.service'; import { GetInventoryAdjustmentsService } from './queries/GetInventoryAdjustments.service';
import { IPaginationMeta } from '@/interfaces/Model'; import { IPaginationMeta } from '@/interfaces/Model';
import { CreateQuickInventoryAdjustmentDto } from './dtos/CreateQuickInventoryAdjustment.dto';
@Injectable() @Injectable()
export class InventoryAdjustmentsApplicationService { export class InventoryAdjustmentsApplicationService {
@@ -39,7 +40,7 @@ export class InventoryAdjustmentsApplicationService {
* @param {IQuickInventoryAdjustmentDTO} quickAdjustmentDTO - Quick inventory adjustment DTO. * @param {IQuickInventoryAdjustmentDTO} quickAdjustmentDTO - Quick inventory adjustment DTO.
*/ */
public async createQuickInventoryAdjustment( public async createQuickInventoryAdjustment(
quickAdjustmentDTO: IQuickInventoryAdjustmentDTO, quickAdjustmentDTO: CreateQuickInventoryAdjustmentDto,
): Promise<InventoryAdjustment> { ): Promise<InventoryAdjustment> {
return this.createQuickInventoryAdjustmentService.createQuickAdjustment( return this.createQuickInventoryAdjustmentService.createQuickAdjustment(
quickAdjustmentDTO, quickAdjustmentDTO,

View File

@@ -17,6 +17,7 @@ import { Item } from '@/modules/Items/models/Item';
import { Account } from '@/modules/Accounts/models/Account.model'; import { Account } from '@/modules/Accounts/models/Account.model';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform'; import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform'; import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
import { CreateQuickInventoryAdjustmentDto } from '../dtos/CreateQuickInventoryAdjustment.dto';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { ERRORS } from '../constants/InventoryAdjustments.constants'; import { ERRORS } from '../constants/InventoryAdjustments.constants';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@@ -89,7 +90,7 @@ export class CreateQuickInventoryAdjustmentService {
* @param {IQuickInventoryAdjustmentDTO} quickAdjustmentDTO - qucik adjustment DTO. * @param {IQuickInventoryAdjustmentDTO} quickAdjustmentDTO - qucik adjustment DTO.
*/ */
public async createQuickAdjustment( public async createQuickAdjustment(
quickAdjustmentDTO: IQuickInventoryAdjustmentDTO, quickAdjustmentDTO: CreateQuickInventoryAdjustmentDto,
): Promise<InventoryAdjustment> { ): Promise<InventoryAdjustment> {
// Retrieve the adjustment account or throw not found error. // Retrieve the adjustment account or throw not found error.
const adjustmentAccount = await this.accountModel() const adjustmentAccount = await this.accountModel()

View File

@@ -0,0 +1,86 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
IsBoolean,
IsDate,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
IsPositive,
IsString,
} from 'class-validator';
import { Type } from 'class-transformer';
enum IAdjustmentTypes {
INCREMENT = 'increment',
DECREMENT = 'decrement',
}
export class CreateQuickInventoryAdjustmentDto {
@ApiProperty({ description: 'Date of the inventory adjustment' })
@IsNotEmpty()
@IsDate()
@Type(() => Date)
date: Date;
@ApiProperty({ description: 'Type of adjustment', enum: IAdjustmentTypes })
@IsNotEmpty()
@IsEnum(IAdjustmentTypes)
type: 'increment' | 'decrement';
@ApiProperty({ description: 'ID of the adjustment account' })
@IsNotEmpty()
@IsNumber()
@IsPositive()
adjustmentAccountId: number;
@ApiProperty({ description: 'Reason for the adjustment' })
@IsNotEmpty()
@IsString()
reason: string;
@ApiProperty({ description: 'Description of the adjustment' })
@IsNotEmpty()
@IsString()
description: string;
@ApiProperty({ description: 'Reference number' })
@IsNotEmpty()
@IsString()
referenceNo: string;
@ApiProperty({ description: 'ID of the item being adjusted' })
@IsNotEmpty()
@IsNumber()
@IsPositive()
itemId: number;
@ApiProperty({ description: 'Quantity to adjust' })
@IsNotEmpty()
@IsNumber()
@IsPositive()
quantity: number;
@ApiProperty({ description: 'Cost of the item' })
@IsNotEmpty()
@IsNumber()
@IsPositive()
cost: number;
@ApiProperty({ description: 'Whether to publish the adjustment immediately' })
@IsNotEmpty()
@IsBoolean()
publish: boolean;
@ApiPropertyOptional({ description: 'ID of the warehouse (optional)' })
@IsOptional()
@IsNumber()
@IsPositive()
warehouseId?: number;
@ApiPropertyOptional({ description: 'ID of the branch (optional)' })
@IsOptional()
@IsNumber()
@IsPositive()
branchId?: number;
}

View File

@@ -1,5 +1,6 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { InventoryAdjustment } from '../models/InventoryAdjustment'; import { InventoryAdjustment } from '../models/InventoryAdjustment';
import { CreateQuickInventoryAdjustmentDto } from '../dtos/CreateQuickInventoryAdjustment.dto';
type IAdjustmentTypes = 'increment' | 'decrement'; type IAdjustmentTypes = 'increment' | 'decrement';
@@ -29,7 +30,7 @@ export interface IInventoryAdjustmentEventCreatedPayload {
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IInventoryAdjustmentCreatingPayload { export interface IInventoryAdjustmentCreatingPayload {
quickAdjustmentDTO: IQuickInventoryAdjustmentDTO; quickAdjustmentDTO: CreateQuickInventoryAdjustmentDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }

View File

@@ -118,7 +118,6 @@ export class ItemsController extends TenantController {
description: 'The item has been successfully updated.', description: 'The item has been successfully updated.',
}) })
@ApiResponse({ status: 404, description: 'The item not found.' }) @ApiResponse({ status: 404, description: 'The item not found.' })
// @UsePipes(new ZodValidationPipe(createItemSchema))
async editItem( async editItem(
@Param('id') id: string, @Param('id') id: string,
@Body() editItemDto: EditItemDto, @Body() editItemDto: EditItemDto,

View File

@@ -7,6 +7,7 @@ import { ServiceError } from './ServiceError';
import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types'; import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types';
import { TenantModelProxy } from '../System/models/TenantBaseModel'; import { TenantModelProxy } from '../System/models/TenantBaseModel';
import { entriesAmountDiff } from '@/utils/entries-amount-diff'; import { entriesAmountDiff } from '@/utils/entries-amount-diff';
import { ItemEntryDto } from '../TransactionItemEntry/dto/ItemEntry.dto';
const ERRORS = { const ERRORS = {
ITEMS_NOT_FOUND: 'ITEMS_NOT_FOUND', ITEMS_NOT_FOUND: 'ITEMS_NOT_FOUND',
@@ -83,7 +84,7 @@ export class ItemsEntriesService {
* @param {IItemEntryDTO[]} itemEntries - Items entries. * @param {IItemEntryDTO[]} itemEntries - Items entries.
* @returns {Promise<Item[]>} * @returns {Promise<Item[]>}
*/ */
public async validateItemsIdsExistance(itemEntries: IItemEntryDTO[]) { public async validateItemsIdsExistance(itemEntries: Array<{ itemId: number }>) {
const itemsIds = itemEntries.map((e) => e.itemId); const itemsIds = itemEntries.map((e) => e.itemId);
const foundItems = await this.itemModel().query().whereIn('id', itemsIds); const foundItems = await this.itemModel().query().whereIn('id', itemsIds);
@@ -106,7 +107,7 @@ export class ItemsEntriesService {
public async validateEntriesIdsExistance( public async validateEntriesIdsExistance(
referenceId: number, referenceId: number,
referenceType: string, referenceType: string,
billEntries: IItemEntryDTO[], billEntries: ItemEntryDto[],
) { ) {
const entriesIds = billEntries const entriesIds = billEntries
.filter((e: ItemEntry) => e.id) .filter((e: ItemEntry) => e.id)
@@ -130,9 +131,9 @@ export class ItemsEntriesService {
* @param {IItemEntryDTO[]} itemEntries - * @param {IItemEntryDTO[]} itemEntries -
*/ */
public async validateNonPurchasableEntriesItems( public async validateNonPurchasableEntriesItems(
itemEntries: IItemEntryDTO[], itemEntries: ItemEntryDto[],
) { ) {
const itemsIds = itemEntries.map((e: IItemEntryDTO) => e.itemId); const itemsIds = itemEntries.map((e: ItemEntryDto) => e.itemId);
const purchasbleItems = await this.itemModel() const purchasbleItems = await this.itemModel()
.query() .query()
.where('purchasable', true) .where('purchasable', true)
@@ -150,8 +151,8 @@ export class ItemsEntriesService {
* Validate the entries items that not sell-able. * Validate the entries items that not sell-able.
* @param {IItemEntryDTO[]} itemEntries - * @param {IItemEntryDTO[]} itemEntries -
*/ */
public async validateNonSellableEntriesItems(itemEntries: IItemEntryDTO[]) { public async validateNonSellableEntriesItems(itemEntries: ItemEntryDto[]) {
const itemsIds = itemEntries.map((e: IItemEntryDTO) => e.itemId); const itemsIds = itemEntries.map((e: ItemEntryDto) => e.itemId);
const sellableItems = await this.itemModel() const sellableItems = await this.itemModel()
.query() .query()
@@ -218,7 +219,7 @@ export class ItemsEntriesService {
/** /**
* Sets the cost/sell accounts to the invoice entries. * Sets the cost/sell accounts to the invoice entries.
*/ */
public setItemsEntriesDefaultAccounts = async (entries: IItemEntryDTO[]) => { public setItemsEntriesDefaultAccounts = async (entries: ItemEntryDto[]) => {
const entriesItemsIds = entries.map((e) => e.itemId); const entriesItemsIds = entries.map((e) => e.itemId);
const items = await this.itemModel().query().whereIn('id', entriesItemsIds); const items = await this.itemModel().query().whereIn('id', entriesItemsIds);
@@ -240,7 +241,7 @@ export class ItemsEntriesService {
* @param {ItemEntry[]} entries - Items entries. * @param {ItemEntry[]} entries - Items entries.
* @returns {number} * @returns {number}
*/ */
public getTotalItemsEntries(entries: IItemEntryDTO[]): number { public getTotalItemsEntries(entries: ItemEntryDto[]): number {
return sumBy(entries, (e) => ItemEntry.calcAmount(e)); return sumBy(entries, (e) => ItemEntry.calcAmount(e));
} }

View File

@@ -14,6 +14,10 @@ import { GetPaymentReceivedPdfService } from './queries/GetPaymentReceivedPdf.se
import { GetPaymentReceivedStateService } from './queries/GetPaymentReceivedState.service'; import { GetPaymentReceivedStateService } from './queries/GetPaymentReceivedState.service';
import { GetPaymentsReceivedService } from './queries/GetPaymentsReceived.service'; import { GetPaymentsReceivedService } from './queries/GetPaymentsReceived.service';
import { SendPaymentReceiveMailNotification } from './commands/PaymentReceivedMailNotification'; import { SendPaymentReceiveMailNotification } from './commands/PaymentReceivedMailNotification';
import {
CreatePaymentReceivedDto,
EditPaymentReceivedDto,
} from './dtos/PaymentReceived.dto';
@Injectable() @Injectable()
export class PaymentReceivesApplication { export class PaymentReceivesApplication {
@@ -31,10 +35,10 @@ export class PaymentReceivesApplication {
/** /**
* Creates a new payment receive. * Creates a new payment receive.
* @param {IPaymentReceivedCreateDTO} paymentReceiveDTO * @param {CreatePaymentReceivedDto} paymentReceiveDTO
* @returns * @returns
*/ */
public createPaymentReceived(paymentReceiveDTO: IPaymentReceivedCreateDTO) { public createPaymentReceived(paymentReceiveDTO: CreatePaymentReceivedDto) {
return this.createPaymentReceivedService.createPaymentReceived( return this.createPaymentReceivedService.createPaymentReceived(
paymentReceiveDTO, paymentReceiveDTO,
); );
@@ -43,12 +47,12 @@ export class PaymentReceivesApplication {
/** /**
* Edit details the given payment receive with associated entries. * Edit details the given payment receive with associated entries.
* @param {number} paymentReceiveId - Payment receive id. * @param {number} paymentReceiveId - Payment receive id.
* @param {IPaymentReceivedEditDTO} paymentReceiveDTO - Payment receive data. * @param {EditPaymentReceivedDto} paymentReceiveDTO - Payment receive data.
* @returns * @returns
*/ */
public editPaymentReceive( public editPaymentReceive(
paymentReceiveId: number, paymentReceiveId: number,
paymentReceiveDTO: IPaymentReceivedEditDTO, paymentReceiveDTO: EditPaymentReceivedDto,
) { ) {
return this.editPaymentReceivedService.editPaymentReceive( return this.editPaymentReceivedService.editPaymentReceive(
paymentReceiveId, paymentReceiveId,
@@ -130,17 +134,17 @@ export class PaymentReceivesApplication {
* @param {PaymentReceive} paymentReceive * @param {PaymentReceive} paymentReceive
* @returns * @returns
*/ */
public getPaymentReceivePdf = (paymentReceiveId: number) => { public getPaymentReceivePdf(paymentReceiveId: number) {
return this.getPaymentReceivePdfService.getPaymentReceivePdf( return this.getPaymentReceivePdfService.getPaymentReceivePdf(
paymentReceiveId, paymentReceiveId,
); );
}; }
/** /**
* Retrieves the create/edit initial state of the payment received. * Retrieves the create/edit initial state of the payment received.
* @returns {Promise<IPaymentReceivedState>} * @returns {Promise<IPaymentReceivedState>}
*/ */
public getPaymentReceivedState = () => { public getPaymentReceivedState() {
return this.getPaymentReceivedStateService.getPaymentReceivedState(); return this.getPaymentReceivedStateService.getPaymentReceivedState();
}; }
} }

View File

@@ -14,6 +14,7 @@ import { Customer } from '@/modules/Customers/models/Customer';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreatePaymentReceivedDto } from '../dtos/PaymentReceived.dto';
@Injectable() @Injectable()
export class CreatePaymentReceivedService { export class CreatePaymentReceivedService {
@@ -38,7 +39,7 @@ export class CreatePaymentReceivedService {
* @param {Knex.Transaction} trx - Database transaction. * @param {Knex.Transaction} trx - Database transaction.
*/ */
public async createPaymentReceived( public async createPaymentReceived(
paymentReceiveDTO: IPaymentReceivedCreateDTO, paymentReceiveDTO: CreatePaymentReceivedDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
) { ) {
const tenant = await this.tenancyContext.getTenant(true); const tenant = await this.tenancyContext.getTenant(true);

View File

@@ -14,6 +14,7 @@ import { events } from '@/common/events/events';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditPaymentReceivedDto } from '../dtos/PaymentReceived.dto';
@Injectable() @Injectable()
export class EditPaymentReceivedService { export class EditPaymentReceivedService {
@@ -49,7 +50,7 @@ export class EditPaymentReceivedService {
*/ */
public async editPaymentReceive( public async editPaymentReceive(
paymentReceiveId: number, paymentReceiveId: number,
paymentReceiveDTO: IPaymentReceivedEditDTO, paymentReceiveDTO: EditPaymentReceivedDto,
) { ) {
const tenant = await this.tenancyContext.getTenant(true); const tenant = await this.tenancyContext.getTenant(true);
@@ -151,7 +152,7 @@ export class EditPaymentReceivedService {
*/ */
private transformEditDTOToModel = async ( private transformEditDTOToModel = async (
customer: Customer, customer: Customer,
paymentReceiveDTO: IPaymentReceivedEditDTO, paymentReceiveDTO: EditPaymentReceivedDto,
oldPaymentReceive: PaymentReceived, oldPaymentReceive: PaymentReceived,
) => { ) => {
return this.transformer.transformPaymentReceiveDTOToModel( return this.transformer.transformPaymentReceiveDTOToModel(

View File

@@ -12,6 +12,7 @@ import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
import { ServiceError } from '@/modules/Items/ServiceError'; import { ServiceError } from '@/modules/Items/ServiceError';
import { ACCOUNT_TYPE } from '@/constants/accounts'; import { ACCOUNT_TYPE } from '@/constants/accounts';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditPaymentReceivedDto } from '../dtos/PaymentReceived.dto';
@Injectable() @Injectable()
export class PaymentReceivedValidators { export class PaymentReceivedValidators {
@@ -191,11 +192,11 @@ export class PaymentReceivedValidators {
/** /**
* Validate the payment customer whether modified. * Validate the payment customer whether modified.
* @param {IPaymentReceivedEditDTO} paymentReceiveDTO * @param {EditPaymentReceivedDto} paymentReceiveDTO
* @param {IPaymentReceived} oldPaymentReceive * @param {PaymentReceived} oldPaymentReceive
*/ */
public validateCustomerNotModified( public validateCustomerNotModified(
paymentReceiveDTO: IPaymentReceivedEditDTO, paymentReceiveDTO: EditPaymentReceivedDto,
oldPaymentReceive: PaymentReceived, oldPaymentReceive: PaymentReceived,
) { ) {
if (paymentReceiveDTO.customerId !== oldPaymentReceive.customerId) { if (paymentReceiveDTO.customerId !== oldPaymentReceive.customerId) {

View File

@@ -0,0 +1,75 @@
import { AttachmentLinkDto } from '@/modules/Attachments/dtos/Attachment.dto';
import { Type } from 'class-transformer';
import { IsArray, ValidateNested } from 'class-validator';
import { IsString } from 'class-validator';
import { IsDateString, IsNumber, IsOptional } from 'class-validator';
import { IsInt } from 'class-validator';
export class PaymentReceivedEntryDto {
@IsOptional()
@IsInt()
id?: number;
@IsOptional()
@IsInt()
index?: number;
@IsOptional()
@IsInt()
paymentReceiveId?: number;
@IsInt()
invoiceId: number;
@IsNumber()
paymentAmount: number;
}
export class CommandPaymentReceivedDto {
@IsInt()
customerId: number;
@IsDateString()
paymentDate: Date | string;
@IsOptional()
@IsNumber()
amount?: number;
@IsOptional()
@IsNumber()
exchangeRate?: number;
@IsOptional()
@IsString()
referenceNo?: string;
@IsInt()
depositAccountId: number;
@IsOptional()
@IsString()
paymentReceiveNo?: string;
@IsOptional()
@IsString()
statement?: string;
@IsArray()
@ValidateNested({ each: true })
@Type(() => PaymentReceivedEntryDto)
entries: PaymentReceivedEntryDto[];
@IsOptional()
@IsInt()
branchId?: number;
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AttachmentLinkDto)
attachments?: AttachmentLinkDto[];
}
export class CreatePaymentReceivedDto extends CommandPaymentReceivedDto {}
export class EditPaymentReceivedDto extends CommandPaymentReceivedDto {}

View File

@@ -7,6 +7,17 @@ import {
CommonMailOptionsDTO, CommonMailOptionsDTO,
} from '@/modules/MailNotification/MailNotification.types'; } from '@/modules/MailNotification/MailNotification.types';
import { TenantJobPayload } from '@/interfaces/Tenant'; import { TenantJobPayload } from '@/interfaces/Tenant';
import { EditPaymentReceivedDto } from '../dtos/PaymentReceived.dto';
export interface IPaymentReceivedEntryDTO {
id?: number;
index?: number;
paymentReceiveId?: number;
invoiceId: number;
paymentAmount: number;
}
export interface IPaymentReceivedCreateDTO { export interface IPaymentReceivedCreateDTO {
customerId: number; customerId: number;
@@ -37,14 +48,6 @@ export interface IPaymentReceivedEditDTO {
attachments?: AttachmentLinkDTO[]; attachments?: AttachmentLinkDTO[];
} }
export interface IPaymentReceivedEntryDTO {
id?: number;
index?: number;
paymentReceiveId?: number;
invoiceId: number;
paymentAmount: number;
}
export interface IPaymentsReceivedFilter extends IDynamicListFilter { export interface IPaymentsReceivedFilter extends IDynamicListFilter {
stringifiedFilterRoles?: string; stringifiedFilterRoles?: string;
filterQuery?: (trx: Knex.Transaction) => void; filterQuery?: (trx: Knex.Transaction) => void;
@@ -96,32 +99,26 @@ export interface IPaymentReceivedCreatedPayload {
} }
export interface IPaymentReceivedEditedPayload { export interface IPaymentReceivedEditedPayload {
// tenantId: number;
paymentReceiveId: number; paymentReceiveId: number;
paymentReceive: PaymentReceived; paymentReceive: PaymentReceived;
oldPaymentReceive: PaymentReceived; oldPaymentReceive: PaymentReceived;
paymentReceiveDTO: IPaymentReceivedEditDTO; paymentReceiveDTO: EditPaymentReceivedDto;
// authorizedUser: ISystemUser;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IPaymentReceivedEditingPayload { export interface IPaymentReceivedEditingPayload {
// tenantId: number;
oldPaymentReceive: PaymentReceived; oldPaymentReceive: PaymentReceived;
paymentReceiveDTO: IPaymentReceivedEditDTO; paymentReceiveDTO: IPaymentReceivedEditDTO;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IPaymentReceivedDeletingPayload { export interface IPaymentReceivedDeletingPayload {
// tenantId: number;
oldPaymentReceive: PaymentReceived; oldPaymentReceive: PaymentReceived;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IPaymentReceivedDeletedPayload { export interface IPaymentReceivedDeletedPayload {
// tenantId: number;
paymentReceiveId: number; paymentReceiveId: number;
oldPaymentReceive: PaymentReceived; oldPaymentReceive: PaymentReceived;
// authorizedUser: ISystemUser;
trx: Knex.Transaction; trx: Knex.Transaction;
} }

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { CreateSaleEstimate } from './commands/CreateSaleEstimate.service'; import { CreateSaleEstimate } from './commands/CreateSaleEstimate.service';
import { import {
ISaleEstimateDTO,
ISalesEstimatesFilter, ISalesEstimatesFilter,
SaleEstimateMailOptionsDTO, SaleEstimateMailOptionsDTO,
} from './types/SaleEstimates.types'; } from './types/SaleEstimates.types';
@@ -10,12 +10,14 @@ import { GetSaleEstimate } from './queries/GetSaleEstimate.service';
import { DeliverSaleEstimateService } from './commands/DeliverSaleEstimate.service'; import { DeliverSaleEstimateService } from './commands/DeliverSaleEstimate.service';
import { ApproveSaleEstimateService } from './commands/ApproveSaleEstimate.service'; import { ApproveSaleEstimateService } from './commands/ApproveSaleEstimate.service';
import { RejectSaleEstimateService } from './commands/RejectSaleEstimate.service'; import { RejectSaleEstimateService } from './commands/RejectSaleEstimate.service';
// import { SaleEstimateNotifyBySms } from './commands/SaleEstimateSmsNotify';
import { SendSaleEstimateMail } from './commands/SendSaleEstimateMail'; import { SendSaleEstimateMail } from './commands/SendSaleEstimateMail';
import { GetSaleEstimateState } from './queries/GetSaleEstimateState.service'; import { GetSaleEstimateState } from './queries/GetSaleEstimateState.service';
import { GetSaleEstimatesService } from './queries/GetSaleEstimates.service'; import { GetSaleEstimatesService } from './queries/GetSaleEstimates.service';
import { Injectable } from '@nestjs/common';
import { GetSaleEstimatePdf } from './queries/GetSaleEstimatePdf'; import { GetSaleEstimatePdf } from './queries/GetSaleEstimatePdf';
import {
CreateSaleEstimateDto,
EditSaleEstimateDto,
} from './dtos/SaleEstimate.dto';
@Injectable() @Injectable()
export class SaleEstimatesApplication { export class SaleEstimatesApplication {
@@ -31,25 +33,27 @@ export class SaleEstimatesApplication {
private readonly sendEstimateMailService: SendSaleEstimateMail, private readonly sendEstimateMailService: SendSaleEstimateMail,
private readonly getSaleEstimateStateService: GetSaleEstimateState, private readonly getSaleEstimateStateService: GetSaleEstimateState,
private readonly saleEstimatesPdfService: GetSaleEstimatePdf, private readonly saleEstimatesPdfService: GetSaleEstimatePdf,
// private readonly saleEstimateNotifyBySmsService: SaleEstimateNotifyBySms,
) {} ) {}
/** /**
* Create a sale estimate. * Create a sale estimate.
* @param {EstimateDTO} estimate - Estimate DTO. * @param {CreateSaleEstimateDto} estimate - Estimate DTO.
* @return {Promise<ISaleEstimate>} * @return {Promise<ISaleEstimate>}
*/ */
public createSaleEstimate(estimateDTO: ISaleEstimateDTO) { public createSaleEstimate(estimateDTO: CreateSaleEstimateDto) {
return this.createSaleEstimateService.createEstimate(estimateDTO); return this.createSaleEstimateService.createEstimate(estimateDTO);
} }
/** /**
* Edit the given sale estimate. * Edit the given sale estimate.
* @param {number} estimateId - Sale estimate ID. * @param {number} estimateId - Sale estimate ID.
* @param {EstimateDTO} estimate - Estimate DTO. * @param {EditSaleEstimateDto} estimate - Estimate DTO.
* @return {Promise<ISaleEstimate>} * @return {Promise<ISaleEstimate>}
*/ */
public editSaleEstimate(estimateId: number, estimateDTO: ISaleEstimateDTO) { public editSaleEstimate(
estimateId: number,
estimateDTO: EditSaleEstimateDto,
) {
return this.editSaleEstimateService.editEstimate(estimateId, estimateDTO); return this.editSaleEstimateService.editEstimate(estimateId, estimateDTO);
} }

View File

@@ -13,12 +13,15 @@ import {
} from '@nestjs/common'; } from '@nestjs/common';
import { SaleEstimatesApplication } from './SaleEstimates.application'; import { SaleEstimatesApplication } from './SaleEstimates.application';
import { import {
ISaleEstimateDTO,
ISalesEstimatesFilter, ISalesEstimatesFilter,
SaleEstimateMailOptionsDTO, SaleEstimateMailOptionsDTO,
} from './types/SaleEstimates.types'; } from './types/SaleEstimates.types';
import { SaleEstimate } from './models/SaleEstimate'; import { SaleEstimate } from './models/SaleEstimate';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import {
CreateSaleEstimateDto,
EditSaleEstimateDto,
} from './dtos/SaleEstimate.dto';
@Controller('sale-estimates') @Controller('sale-estimates')
@ApiTags('sale-estimates') @ApiTags('sale-estimates')
@@ -38,7 +41,7 @@ export class SaleEstimatesController {
description: 'Sale estimate created successfully', description: 'Sale estimate created successfully',
}) })
public createSaleEstimate( public createSaleEstimate(
@Body() estimateDTO: ISaleEstimateDTO, @Body() estimateDTO: CreateSaleEstimateDto,
): Promise<SaleEstimate> { ): Promise<SaleEstimate> {
return this.saleEstimatesApplication.createSaleEstimate(estimateDTO); return this.saleEstimatesApplication.createSaleEstimate(estimateDTO);
} }
@@ -61,7 +64,7 @@ export class SaleEstimatesController {
}) })
public editSaleEstimate( public editSaleEstimate(
@Param('id', ParseIntPipe) estimateId: number, @Param('id', ParseIntPipe) estimateId: number,
@Body() estimateDTO: ISaleEstimateDTO, @Body() estimateDTO: EditSaleEstimateDto,
): Promise<SaleEstimate> { ): Promise<SaleEstimate> {
return this.saleEstimatesApplication.editSaleEstimate( return this.saleEstimatesApplication.editSaleEstimate(
estimateId, estimateId,

View File

@@ -14,6 +14,7 @@ import { events } from '@/common/events/events';
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service'; import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateSaleEstimateDto } from '../dtos/SaleEstimate.dto';
@Injectable() @Injectable()
export class CreateSaleEstimate { export class CreateSaleEstimate {
@@ -37,7 +38,7 @@ export class CreateSaleEstimate {
* @return {Promise<ISaleEstimate>} * @return {Promise<ISaleEstimate>}
*/ */
public async createEstimate( public async createEstimate(
estimateDTO: ISaleEstimateDTO, estimateDTO: CreateSaleEstimateDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
): Promise<SaleEstimate> { ): Promise<SaleEstimate> {
// Retrieve the given customer or throw not found service error. // Retrieve the given customer or throw not found service error.

View File

@@ -14,6 +14,7 @@ import { SaleEstimate } from '../models/SaleEstimate';
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service'; import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditSaleEstimateDto } from '../dtos/SaleEstimate.dto';
@Injectable() @Injectable()
export class EditSaleEstimate { export class EditSaleEstimate {
@@ -40,7 +41,7 @@ export class EditSaleEstimate {
*/ */
public async editEstimate( public async editEstimate(
estimateId: number, estimateId: number,
estimateDTO: ISaleEstimateDTO, estimateDTO: EditSaleEstimateDto,
): Promise<SaleEstimate> { ): Promise<SaleEstimate> {
// Retrieve details of the given sale estimate id. // Retrieve details of the given sale estimate id.
const oldSaleEstimate = await this.saleEstimateModel() const oldSaleEstimate = await this.saleEstimateModel()

View File

@@ -2,10 +2,7 @@ import * as R from 'ramda';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { omit, sumBy } from 'lodash'; import { omit, sumBy } from 'lodash';
import * as composeAsync from 'async/compose'; import * as composeAsync from 'async/compose';
// import { ICustomer, ISaleEstimate, ISaleEstimateDTO } from '../types/SaleEstimates.types';
import { SaleEstimateValidators } from './SaleEstimateValidators.service'; import { SaleEstimateValidators } from './SaleEstimateValidators.service';
// import { BranchTransactionDTOTransform } from '@/services/Branches/Integrations/BranchTransactionDTOTransform';
// import { WarehouseTransactionDTOTransform } from '@/services/Warehouses/Integrations/WarehouseTransactionDTOTransform';
import { formatDateFields } from '@/utils/format-date-fields'; import { formatDateFields } from '@/utils/format-date-fields';
import * as moment from 'moment'; import * as moment from 'moment';
import { SaleEstimateIncrement } from './SaleEstimateIncrement.service'; import { SaleEstimateIncrement } from './SaleEstimateIncrement.service';
@@ -18,8 +15,7 @@ import { SaleEstimate } from '../models/SaleEstimate';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { ISaleEstimateDTO } from '../types/SaleEstimates.types'; import { ISaleEstimateDTO } from '../types/SaleEstimates.types';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
// import { assocItemEntriesDefaultIndex } from '@/services/Items/utils'; import { CommandSaleEstimateDto } from '../dtos/SaleEstimate.dto';
// import { BrandingTemplateDTOTransformer } from '@/services/PdfTemplate/BrandingTemplateDTOTransformer';
@Injectable() @Injectable()
export class SaleEstimateDTOTransformer { export class SaleEstimateDTOTransformer {
@@ -42,7 +38,7 @@ export class SaleEstimateDTOTransformer {
* @return {ISaleEstimate} * @return {ISaleEstimate}
*/ */
async transformDTOToModel( async transformDTOToModel(
estimateDTO: ISaleEstimateDTO, estimateDTO: CommandSaleEstimateDto,
paymentCustomer: Customer, paymentCustomer: Customer,
oldSaleEstimate?: SaleEstimate, oldSaleEstimate?: SaleEstimate,
): Promise<SaleEstimate> { ): Promise<SaleEstimate> {

View File

@@ -0,0 +1,104 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsDate,
IsEnum,
IsNumber,
IsOptional,
IsString,
Min,
MinLength,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
class SaleEstimateEntryDto extends ItemEntryDto {}
class AttachmentDto {
@IsString()
key: string;
}
export class CommandSaleEstimateDto {
@IsNumber()
customerId: number;
@IsDate()
@Type(() => Date)
estimateDate: Date;
@IsDate()
@Type(() => Date)
expirationDate: Date;
@IsString()
@IsOptional()
reference?: string;
@IsString()
@IsOptional()
estimateNumber?: string;
@IsBoolean()
delivered: boolean = false;
@IsNumber()
@Min(0.01)
@IsOptional()
exchangeRate?: number;
@IsNumber()
@IsOptional()
warehouseId?: number;
@IsNumber()
@IsOptional()
branchId?: number;
@IsArray()
@MinLength(1)
@ValidateNested({ each: true })
@Type(() => SaleEstimateEntryDto)
entries: SaleEstimateEntryDto[];
@IsString()
@IsOptional()
note?: string;
@IsString()
@IsOptional()
termsConditions?: string;
@IsString()
@IsOptional()
sendToEmail?: string;
@IsArray()
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AttachmentDto)
attachments?: AttachmentDto[];
@IsNumber()
@IsOptional()
pdfTemplateId?: number;
@IsNumber()
@IsOptional()
discount?: number;
@IsEnum(DiscountType)
discountType: DiscountType = DiscountType.Amount;
@IsNumber()
@IsOptional()
adjustment?: number;
}
export class CreateSaleEstimateDto extends CommandSaleEstimateDto {}
export class EditSaleEstimateDto extends CommandSaleEstimateDto {}

View File

@@ -7,6 +7,7 @@ import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types'; import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
import { CommonMailOptionsDTO } from '@/modules/MailNotification/MailNotification.types'; import { CommonMailOptionsDTO } from '@/modules/MailNotification/MailNotification.types';
import { CommonMailOptions } from '@/modules/MailNotification/MailNotification.types'; import { CommonMailOptions } from '@/modules/MailNotification/MailNotification.types';
import { EditSaleEstimateDto } from '../dtos/SaleEstimate.dto';
export const SendSaleEstimateMailQueue = 'SendSaleEstimateMailProcessor'; export const SendSaleEstimateMailQueue = 'SendSaleEstimateMailProcessor';
export const SendSaleEstimateMailJob = 'SendSaleEstimateMailProcess'; export const SendSaleEstimateMailJob = 'SendSaleEstimateMailProcess';
@@ -34,7 +35,6 @@ export interface ISalesEstimatesFilter extends IDynamicListFilter {
} }
export interface ISaleEstimateCreatedPayload { export interface ISaleEstimateCreatedPayload {
// tenantId: number;
saleEstimate: SaleEstimate; saleEstimate: SaleEstimate;
saleEstimateId: number; saleEstimateId: number;
saleEstimateDTO: ISaleEstimateDTO; saleEstimateDTO: ISaleEstimateDTO;
@@ -43,12 +43,10 @@ export interface ISaleEstimateCreatedPayload {
export interface ISaleEstimateCreatingPayload { export interface ISaleEstimateCreatingPayload {
estimateDTO: ISaleEstimateDTO; estimateDTO: ISaleEstimateDTO;
tenantId: number;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleEstimateEditedPayload { export interface ISaleEstimateEditedPayload {
// tenantId: number;
estimateId: number; estimateId: number;
saleEstimate: SaleEstimate; saleEstimate: SaleEstimate;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
@@ -57,33 +55,28 @@ export interface ISaleEstimateEditedPayload {
} }
export interface ISaleEstimateEditingPayload { export interface ISaleEstimateEditingPayload {
// tenantId: number;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
estimateDTO: ISaleEstimateDTO; estimateDTO: EditSaleEstimateDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleEstimateDeletedPayload { export interface ISaleEstimateDeletedPayload {
// tenantId: number;
saleEstimateId: number; saleEstimateId: number;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleEstimateDeletingPayload { export interface ISaleEstimateDeletingPayload {
// tenantId: number;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleEstimateEventDeliveredPayload { export interface ISaleEstimateEventDeliveredPayload {
// tenantId: number;
saleEstimate: SaleEstimate; saleEstimate: SaleEstimate;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleEstimateEventDeliveringPayload { export interface ISaleEstimateEventDeliveringPayload {
// tenantId: number;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
@@ -97,13 +90,11 @@ export enum SaleEstimateAction {
} }
export interface ISaleEstimateApprovingEvent { export interface ISaleEstimateApprovingEvent {
// tenantId: number;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleEstimateApprovedEvent { export interface ISaleEstimateApprovedEvent {
// tenantId: number;
oldSaleEstimate: SaleEstimate; oldSaleEstimate: SaleEstimate;
saleEstimate: SaleEstimate; saleEstimate: SaleEstimate;
trx: Knex.Transaction; trx: Knex.Transaction;

View File

@@ -8,13 +8,7 @@ import {
CommonMailOptionsDTO, CommonMailOptionsDTO,
} from '../MailNotification/MailNotification.types'; } from '../MailNotification/MailNotification.types';
import { TenantJobPayload } from '@/interfaces/Tenant'; import { TenantJobPayload } from '@/interfaces/Tenant';
// import SaleInvoice from './models/SaleInvoice'; import { CreateSaleInvoiceDto, EditSaleInvoiceDto } from './dtos/SaleInvoice.dto';
// import { SystemUser } from '../System/models/SystemUser';
// import { ISystemUser, IAccount, ITaxTransaction } from '@/interfaces';
// import { CommonMailOptions, CommonMailOptionsDTO } from './Mailable';
// import { IDynamicListFilter } from '@/interfaces/DynamicFilter';
// import { IItemEntry, IItemEntryDTO } from './ItemEntry';
// import { AttachmentLinkDTO } from './Attachments';
export interface PaymentIntegrationTransactionLink { export interface PaymentIntegrationTransactionLink {
id: number; id: number;
@@ -89,27 +83,27 @@ export type InvoiceNotificationType = 'details' | 'reminder';
export interface ISaleInvoiceCreatedPayload { export interface ISaleInvoiceCreatedPayload {
saleInvoice: SaleInvoice; saleInvoice: SaleInvoice;
saleInvoiceDTO: ISaleInvoiceCreateDTO; saleInvoiceDTO: CreateSaleInvoiceDto;
saleInvoiceId: number; saleInvoiceId: number;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleInvoiceCreatingPaylaod { export interface ISaleInvoiceCreatingPaylaod {
tenantId: number; tenantId: number;
saleInvoiceDTO: ISaleInvoiceCreateDTO; saleInvoiceDTO: CreateSaleInvoiceDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleInvoiceEditedPayload { export interface ISaleInvoiceEditedPayload {
saleInvoice: SaleInvoice; saleInvoice: SaleInvoice;
oldSaleInvoice: SaleInvoice; oldSaleInvoice: SaleInvoice;
saleInvoiceDTO: ISaleInvoiceEditDTO; saleInvoiceDTO: EditSaleInvoiceDto;
saleInvoiceId: number; saleInvoiceId: number;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface ISaleInvoiceEditingPayload { export interface ISaleInvoiceEditingPayload {
saleInvoiceDTO: ISaleInvoiceEditDTO; saleInvoiceDTO: EditSaleInvoiceDto;
oldSaleInvoice: SaleInvoice; oldSaleInvoice: SaleInvoice;
trx: Knex.Transaction; trx: Knex.Transaction;
} }

View File

@@ -11,8 +11,6 @@ import { GetInvoicePaymentsService } from './queries/GetInvoicePayments.service'
import { GetSaleInvoiceState } from './queries/GetSaleInvoiceState.service'; import { GetSaleInvoiceState } from './queries/GetSaleInvoiceState.service';
import { GetSaleInvoiceMailState } from './queries/GetSaleInvoiceMailState.service'; import { GetSaleInvoiceMailState } from './queries/GetSaleInvoiceMailState.service';
import { import {
ISaleInvoiceCreateDTO,
ISaleInvoiceEditDTO,
ISaleInvoiceWriteoffDTO, ISaleInvoiceWriteoffDTO,
ISalesInvoicesFilter, ISalesInvoicesFilter,
SaleInvoiceMailState, SaleInvoiceMailState,
@@ -20,6 +18,10 @@ import {
} from './SaleInvoice.types'; } from './SaleInvoice.types';
import { GetSaleInvoicesService } from './queries/GetSaleInvoices'; import { GetSaleInvoicesService } from './queries/GetSaleInvoices';
import { SendSaleInvoiceMail } from './commands/SendSaleInvoiceMail'; import { SendSaleInvoiceMail } from './commands/SendSaleInvoiceMail';
import {
CreateSaleInvoiceDto,
EditSaleInvoiceDto,
} from './dtos/SaleInvoice.dto';
@Injectable() @Injectable()
export class SaleInvoiceApplication { export class SaleInvoiceApplication {
@@ -44,7 +46,7 @@ export class SaleInvoiceApplication {
* @param {ISaleInvoiceCreateDTO} saleInvoiceDTO * @param {ISaleInvoiceCreateDTO} saleInvoiceDTO
* @returns {Promise<ISaleInvoice>} * @returns {Promise<ISaleInvoice>}
*/ */
public createSaleInvoice(saleInvoiceDTO: ISaleInvoiceCreateDTO) { public createSaleInvoice(saleInvoiceDTO: CreateSaleInvoiceDto) {
return this.createSaleInvoiceService.createSaleInvoice(saleInvoiceDTO); return this.createSaleInvoiceService.createSaleInvoice(saleInvoiceDTO);
} }
@@ -55,7 +57,7 @@ export class SaleInvoiceApplication {
*/ */
public editSaleInvoice( public editSaleInvoice(
saleInvoiceId: number, saleInvoiceId: number,
saleInvoiceDTO: ISaleInvoiceEditDTO, saleInvoiceDTO: EditSaleInvoiceDto,
) { ) {
return this.editSaleInvoiceService.editSaleInvoice( return this.editSaleInvoiceService.editSaleInvoice(
saleInvoiceId, saleInvoiceId,

View File

@@ -11,8 +11,6 @@ import {
Query, Query,
} from '@nestjs/common'; } from '@nestjs/common';
import { import {
ISaleInvoiceCreateDTO,
ISaleInvoiceEditDTO,
ISaleInvoiceWriteoffDTO, ISaleInvoiceWriteoffDTO,
ISalesInvoicesFilter, ISalesInvoicesFilter,
SaleInvoiceMailState, SaleInvoiceMailState,
@@ -27,6 +25,10 @@ import {
ApiResponse, ApiResponse,
ApiTags, ApiTags,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import {
CreateSaleInvoiceDto,
EditSaleInvoiceDto,
} from './dtos/SaleInvoice.dto';
@Controller('sale-invoices') @Controller('sale-invoices')
@ApiTags('sale-invoices') @ApiTags('sale-invoices')
@@ -50,7 +52,7 @@ export class SaleInvoicesController {
status: 201, status: 201,
description: 'Sale invoice created successfully', description: 'Sale invoice created successfully',
}) })
createSaleInvoice(@Body() saleInvoiceDTO: ISaleInvoiceCreateDTO) { createSaleInvoice(@Body() saleInvoiceDTO: CreateSaleInvoiceDto) {
return this.saleInvoiceApplication.createSaleInvoice(saleInvoiceDTO); return this.saleInvoiceApplication.createSaleInvoice(saleInvoiceDTO);
} }
@@ -89,7 +91,7 @@ export class SaleInvoicesController {
}) })
editSaleInvoice( editSaleInvoice(
@Param('id', ParseIntPipe) id: number, @Param('id', ParseIntPipe) id: number,
@Body() saleInvoiceDTO: ISaleInvoiceEditDTO, @Body() saleInvoiceDTO: EditSaleInvoiceDto,
) { ) {
return this.saleInvoiceApplication.editSaleInvoice(id, saleInvoiceDTO); return this.saleInvoiceApplication.editSaleInvoice(id, saleInvoiceDTO);
} }

View File

@@ -4,10 +4,6 @@ import * as R from 'ramda';
import * as moment from 'moment'; import * as moment from 'moment';
import '../../../utils/moment-mysql'; import '../../../utils/moment-mysql';
import * as composeAsync from 'async/compose'; import * as composeAsync from 'async/compose';
import {
ISaleInvoiceCreateDTO,
ISaleInvoiceEditDTO,
} from '../SaleInvoice.types';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform'; import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform'; import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
@@ -21,6 +17,10 @@ import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-ind
import { formatDateFields } from '@/utils/format-date-fields'; import { formatDateFields } from '@/utils/format-date-fields';
import { ItemEntriesTaxTransactions } from '@/modules/TaxRates/ItemEntriesTaxTransactions.service'; import { ItemEntriesTaxTransactions } from '@/modules/TaxRates/ItemEntriesTaxTransactions.service';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import {
CreateSaleInvoiceDto,
EditSaleInvoiceDto,
} from '../dtos/SaleInvoice.dto';
@Injectable() @Injectable()
export class CommandSaleInvoiceDTOTransformer { export class CommandSaleInvoiceDTOTransformer {
@@ -54,7 +54,7 @@ export class CommandSaleInvoiceDTOTransformer {
*/ */
public async transformDTOToModel( public async transformDTOToModel(
customer: Customer, customer: Customer,
saleInvoiceDTO: ISaleInvoiceCreateDTO | ISaleInvoiceEditDTO, saleInvoiceDTO: CreateSaleInvoiceDto | EditSaleInvoiceDto,
oldSaleInvoice?: SaleInvoice, oldSaleInvoice?: SaleInvoice,
): Promise<SaleInvoice> { ): Promise<SaleInvoice> {
const entriesModels = this.transformDTOEntriesToModels(saleInvoiceDTO); const entriesModels = this.transformDTOEntriesToModels(saleInvoiceDTO);
@@ -140,7 +140,7 @@ export class CommandSaleInvoiceDTOTransformer {
* @returns {IItemEntry[]} * @returns {IItemEntry[]}
*/ */
private transformDTOEntriesToModels = ( private transformDTOEntriesToModels = (
saleInvoiceDTO: ISaleInvoiceCreateDTO | ISaleInvoiceEditDTO, saleInvoiceDTO: CreateSaleInvoiceDto | EditSaleInvoiceDto,
): ItemEntry[] => { ): ItemEntry[] => {
return saleInvoiceDTO.entries.map((entry) => { return saleInvoiceDTO.entries.map((entry) => {
return ItemEntry.fromJson({ return ItemEntry.fromJson({

View File

@@ -16,6 +16,7 @@ import { SaleEstimate } from '@/modules/SaleEstimates/models/SaleEstimate';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateSaleInvoiceDto } from '../dtos/SaleInvoice.dto';
@Injectable() @Injectable()
export class CreateSaleInvoice { export class CreateSaleInvoice {
@@ -57,8 +58,7 @@ export class CreateSaleInvoice {
* @return {Promise<ISaleInvoice>} * @return {Promise<ISaleInvoice>}
*/ */
public createSaleInvoice = async ( public createSaleInvoice = async (
saleInvoiceDTO: ISaleInvoiceCreateDTO, saleInvoiceDTO: CreateSaleInvoiceDto,
// authorizedUser: ITenantUser,
trx?: Knex.Transaction, trx?: Knex.Transaction,
): Promise<SaleInvoice> => { ): Promise<SaleInvoice> => {
// Validate customer existance. // Validate customer existance.
@@ -132,7 +132,7 @@ export class CreateSaleInvoice {
*/ */
private transformCreateDTOToModel = async ( private transformCreateDTOToModel = async (
customer: Customer, customer: Customer,
saleInvoiceDTO: ISaleInvoiceCreateDTO, saleInvoiceDTO: CreateSaleInvoiceDto,
) => { ) => {
return this.transformerDTO.transformDTOToModel(customer, saleInvoiceDTO); return this.transformerDTO.transformDTOToModel(customer, saleInvoiceDTO);
}; };

View File

@@ -14,6 +14,7 @@ import { events } from '@/common/events/events';
import { SaleInvoice } from '../models/SaleInvoice'; import { SaleInvoice } from '../models/SaleInvoice';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditSaleInvoiceDto } from '../dtos/SaleInvoice.dto';
@Injectable() @Injectable()
export class EditSaleInvoice { export class EditSaleInvoice {
@@ -49,7 +50,7 @@ export class EditSaleInvoice {
*/ */
public async editSaleInvoice( public async editSaleInvoice(
saleInvoiceId: number, saleInvoiceId: number,
saleInvoiceDTO: ISaleInvoiceEditDTO, saleInvoiceDTO: EditSaleInvoiceDto,
): Promise<SaleInvoice> { ): Promise<SaleInvoice> {
// Retrieve the sale invoice or throw not found service error. // Retrieve the sale invoice or throw not found service error.
const oldSaleInvoice = await this.saleInvoiceModel() const oldSaleInvoice = await this.saleInvoiceModel()
@@ -139,15 +140,13 @@ export class EditSaleInvoice {
*/ */
private tranformEditDTOToModel = async ( private tranformEditDTOToModel = async (
customer: Customer, customer: Customer,
saleInvoiceDTO: ISaleInvoiceEditDTO, saleInvoiceDTO: EditSaleInvoiceDto,
oldSaleInvoice: SaleInvoice, oldSaleInvoice: SaleInvoice,
// authorizedUser: ITenantUser,
) => { ) => {
return this.transformerDTO.transformDTOToModel( return this.transformerDTO.transformDTOToModel(
customer, customer,
saleInvoiceDTO, saleInvoiceDTO,
oldSaleInvoice, oldSaleInvoice,
// authorizedUser,
); );
}; };
} }

View File

@@ -0,0 +1,121 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsDate,
IsEnum,
IsInt,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
Min,
MinLength,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
class PaymentMethodDto {
@IsInt()
paymentIntegrationId: number;
@IsBoolean()
enable: boolean;
}
class CommandSaleInvoiceDto {
@IsInt()
@IsNotEmpty()
customerId: number;
@IsDate()
@Type(() => Date)
@IsNotEmpty()
invoiceDate: Date;
@IsDate()
@Type(() => Date)
@IsNotEmpty()
dueDate: Date;
@IsOptional()
@IsString()
invoiceNo?: string;
@IsOptional()
@IsString()
referenceNo?: string;
@IsOptional()
@IsBoolean()
delivered: boolean = false;
@IsOptional()
@IsString()
invoiceMessage?: string;
@IsOptional()
@IsString()
termsConditions?: string;
@IsOptional()
@IsNumber()
@Min(0)
exchangeRate?: number;
@IsOptional()
@IsInt()
warehouseId?: number;
@IsOptional()
@IsInt()
branchId?: number;
@IsOptional()
@IsInt()
projectId?: number;
@IsOptional()
@IsBoolean()
isInclusiveTax?: boolean;
@IsArray()
@ValidateNested({ each: true })
@Type(() => ItemEntryDto)
@MinLength(1)
entries: ItemEntryDto[];
@IsOptional()
@IsInt()
pdfTemplateId?: number;
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => PaymentMethodDto)
paymentMethods?: PaymentMethodDto[];
@IsOptional()
@IsNumber()
discount?: number;
@IsOptional()
@IsEnum(DiscountType)
discountType?: DiscountType;
@IsOptional()
@IsNumber()
adjustment?: number;
@IsOptional()
@IsInt()
fromEstimateId?: number;
}
export class CreateSaleInvoiceDto extends CommandSaleInvoiceDto {}
export class EditSaleInvoiceDto extends CommandSaleInvoiceDto {}

View File

@@ -4,12 +4,10 @@ import { CreateSaleReceipt } from './commands/CreateSaleReceipt.service';
import { GetSaleReceiptState } from './queries/GetSaleReceiptState.service'; import { GetSaleReceiptState } from './queries/GetSaleReceiptState.service';
import { SaleReceiptsPdfService } from './queries/SaleReceiptsPdf.service'; import { SaleReceiptsPdfService } from './queries/SaleReceiptsPdf.service';
import { CloseSaleReceipt } from './commands/CloseSaleReceipt.service'; import { CloseSaleReceipt } from './commands/CloseSaleReceipt.service';
// import { GetSaleReceipts } from './queries/GetSaleReceipts';
import { DeleteSaleReceipt } from './commands/DeleteSaleReceipt.service'; import { DeleteSaleReceipt } from './commands/DeleteSaleReceipt.service';
import { GetSaleReceipt } from './queries/GetSaleReceipt.service'; import { GetSaleReceipt } from './queries/GetSaleReceipt.service';
import { EditSaleReceipt } from './commands/EditSaleReceipt.service'; import { EditSaleReceipt } from './commands/EditSaleReceipt.service';
import { import {
ISaleReceiptDTO,
ISaleReceiptState, ISaleReceiptState,
ISalesReceiptsFilter, ISalesReceiptsFilter,
SaleReceiptMailOpts, SaleReceiptMailOpts,
@@ -19,6 +17,7 @@ import { GetSaleReceiptsService } from './queries/GetSaleReceipts.service';
import { SaleReceipt } from './models/SaleReceipt'; import { SaleReceipt } from './models/SaleReceipt';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model'; import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { SaleReceiptMailNotification } from './commands/SaleReceiptMailNotification'; import { SaleReceiptMailNotification } from './commands/SaleReceiptMailNotification';
import { CreateSaleReceiptDto, EditSaleReceiptDto } from './dtos/SaleReceipt.dto';
@Injectable() @Injectable()
export class SaleReceiptApplication { export class SaleReceiptApplication {
@@ -40,7 +39,7 @@ export class SaleReceiptApplication {
* @returns {Promise<ISaleReceipt>} * @returns {Promise<ISaleReceipt>}
*/ */
public async createSaleReceipt( public async createSaleReceipt(
saleReceiptDTO: ISaleReceiptDTO, saleReceiptDTO: CreateSaleReceiptDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
) { ) {
return this.createSaleReceiptService.createSaleReceipt(saleReceiptDTO, trx); return this.createSaleReceiptService.createSaleReceipt(saleReceiptDTO, trx);
@@ -55,7 +54,7 @@ export class SaleReceiptApplication {
*/ */
public async editSaleReceipt( public async editSaleReceipt(
saleReceiptId: number, saleReceiptId: number,
saleReceiptDTO: ISaleReceiptDTO, saleReceiptDTO: EditSaleReceiptDto,
) { ) {
return this.editSaleReceiptService.editSaleReceipt( return this.editSaleReceiptService.editSaleReceipt(
saleReceiptId, saleReceiptId,

View File

@@ -9,10 +9,13 @@ import {
Post, Post,
Put, Put,
} from '@nestjs/common'; } from '@nestjs/common';
import { ISaleReceiptDTO } from './types/SaleReceipts.types';
import { SaleReceiptApplication } from './SaleReceiptApplication.service'; import { SaleReceiptApplication } from './SaleReceiptApplication.service';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
import {
CreateSaleReceiptDto,
EditSaleReceiptDto,
} from './dtos/SaleReceipt.dto';
@Controller('sale-receipts') @Controller('sale-receipts')
@ApiTags('sale-receipts') @ApiTags('sale-receipts')
@@ -22,7 +25,7 @@ export class SaleReceiptsController {
@Post() @Post()
@ApiOperation({ summary: 'Create a new sale receipt.' }) @ApiOperation({ summary: 'Create a new sale receipt.' })
createSaleReceipt(@Body() saleReceiptDTO: ISaleReceiptDTO) { createSaleReceipt(@Body() saleReceiptDTO: CreateSaleReceiptDto) {
return this.saleReceiptApplication.createSaleReceipt(saleReceiptDTO); return this.saleReceiptApplication.createSaleReceipt(saleReceiptDTO);
} }
@@ -62,7 +65,7 @@ export class SaleReceiptsController {
}) })
editSaleReceipt( editSaleReceipt(
@Param('id', ParseIntPipe) id: number, @Param('id', ParseIntPipe) id: number,
@Body() saleReceiptDTO: ISaleReceiptDTO, @Body() saleReceiptDTO: EditSaleReceiptDto,
) { ) {
return this.saleReceiptApplication.editSaleReceipt(id, saleReceiptDTO); return this.saleReceiptApplication.editSaleReceipt(id, saleReceiptDTO);
} }

View File

@@ -14,6 +14,7 @@ import { SaleReceipt } from '../models/SaleReceipt';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateSaleReceiptDto } from '../dtos/SaleReceipt.dto';
@Injectable() @Injectable()
export class CreateSaleReceipt { export class CreateSaleReceipt {
@@ -47,7 +48,7 @@ export class CreateSaleReceipt {
* @return {Promise<ISaleReceipt>} * @return {Promise<ISaleReceipt>}
*/ */
public async createSaleReceipt( public async createSaleReceipt(
saleReceiptDTO: ISaleReceiptDTO, saleReceiptDTO: CreateSaleReceiptDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
): Promise<SaleReceipt> { ): Promise<SaleReceipt> {
// Retrieves the payment customer model. // Retrieves the payment customer model.

View File

@@ -14,6 +14,7 @@ import { Contact } from '@/modules/Contacts/models/Contact';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditSaleReceiptDto } from '../dtos/SaleReceipt.dto';
@Injectable() @Injectable()
export class EditSaleReceipt { export class EditSaleReceipt {
@@ -37,7 +38,10 @@ export class EditSaleReceipt {
* @param {ISaleReceipt} saleReceipt * @param {ISaleReceipt} saleReceipt
* @return {void} * @return {void}
*/ */
public async editSaleReceipt(saleReceiptId: number, saleReceiptDTO: any) { public async editSaleReceipt(
saleReceiptId: number,
saleReceiptDTO: EditSaleReceiptDto,
) {
// Retrieve sale receipt or throw not found service error. // Retrieve sale receipt or throw not found service error.
const oldSaleReceipt = await this.saleReceiptModel() const oldSaleReceipt = await this.saleReceiptModel()
.query() .query()

View File

@@ -13,9 +13,9 @@ import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
import { formatDateFields } from '@/utils/format-date-fields'; import { formatDateFields } from '@/utils/format-date-fields';
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index'; import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
import { SaleReceipt } from '../models/SaleReceipt'; import { SaleReceipt } from '../models/SaleReceipt';
import { ISaleReceiptDTO } from '../types/SaleReceipts.types';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateSaleReceiptDto, EditSaleReceiptDto } from '../dtos/SaleReceipt.dto';
@Injectable() @Injectable()
export class SaleReceiptDTOTransformer { export class SaleReceiptDTOTransformer {
@@ -47,7 +47,7 @@ export class SaleReceiptDTOTransformer {
* @returns {ISaleReceipt} * @returns {ISaleReceipt}
*/ */
async transformDTOToModel( async transformDTOToModel(
saleReceiptDTO: ISaleReceiptDTO, saleReceiptDTO: CreateSaleReceiptDto | EditSaleReceiptDto,
paymentCustomer: Customer, paymentCustomer: Customer,
oldSaleReceipt?: SaleReceipt, oldSaleReceipt?: SaleReceipt,
): Promise<SaleReceipt> { ): Promise<SaleReceipt> {

View File

@@ -0,0 +1,100 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsDate,
IsEnum,
IsNumber,
IsOptional,
IsPositive,
IsString,
Min,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
class SaleReceiptEntryDto extends ItemEntryDto {}
class AttachmentDto {
@IsString()
key: string;
}
export class CommandSaleReceiptDto {
@IsNumber()
customerId: number;
@IsOptional()
@IsNumber()
@IsPositive()
exchangeRate?: number;
@IsNumber()
depositAccountId: number;
@IsDate()
receiptDate: Date;
@IsOptional()
@IsString()
receiptNumber?: string;
@IsOptional()
@IsString()
referenceNo?: string;
@IsBoolean()
closed: boolean = false;
@IsOptional()
@IsNumber()
warehouseId?: number;
@IsOptional()
@IsNumber()
branchId?: number;
@IsArray()
@ValidateNested({ each: true })
@Type(() => SaleReceiptEntryDto)
@Min(1)
entries: SaleReceiptEntryDto[];
@IsOptional()
@IsString()
receiptMessage?: string;
@IsOptional()
@IsString()
statement?: string;
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AttachmentDto)
attachments?: AttachmentDto[];
@IsOptional()
@IsNumber()
pdfTemplateId?: number;
@IsOptional()
@IsNumber()
discount?: number;
@IsOptional()
@IsEnum(DiscountType)
discountType?: DiscountType;
@IsOptional()
@IsNumber()
adjustment?: number;
}
export class CreateSaleReceiptDto extends CommandSaleReceiptDto {}
export class EditSaleReceiptDto extends CommandSaleReceiptDto {}

View File

@@ -8,6 +8,7 @@ import { Injectable } from '@nestjs/common';
import { ServiceError } from '@/modules/Items/ServiceError'; import { ServiceError } from '@/modules/Items/ServiceError';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types'; import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
@Injectable() @Injectable()
export class CommandTaxRatesValidators { export class CommandTaxRatesValidators {
@@ -67,11 +68,10 @@ export class CommandTaxRatesValidators {
/** /**
* Validates the tax codes of the given item entries DTO. * Validates the tax codes of the given item entries DTO.
* @param {number} tenantId
* @param {IItemEntryDTO[]} itemEntriesDTO * @param {IItemEntryDTO[]} itemEntriesDTO
* @throws {ServiceError} * @throws {ServiceError}
*/ */
public async validateItemEntriesTaxCode(itemEntriesDTO: IItemEntryDTO[]) { public async validateItemEntriesTaxCode(itemEntriesDTO: ItemEntryDto[]) {
const filteredTaxEntries = itemEntriesDTO.filter((e) => e.taxCode); const filteredTaxEntries = itemEntriesDTO.filter((e) => e.taxCode);
const taxCodes = filteredTaxEntries.map((e) => e.taxCode); const taxCodes = filteredTaxEntries.map((e) => e.taxCode);
@@ -92,10 +92,10 @@ export class CommandTaxRatesValidators {
/** /**
* Validates the tax rate id of the given item entries DTO. * Validates the tax rate id of the given item entries DTO.
* @param {IItemEntryDTO[]} itemEntriesDTO * @param {ItemEntryDto[]} itemEntriesDTO
* @throws {ServiceError} * @throws {ServiceError}
*/ */
public async validateItemEntriesTaxCodeId(itemEntriesDTO: IItemEntryDTO[]) { public async validateItemEntriesTaxCodeId(itemEntriesDTO: ItemEntryDto[]) {
const filteredTaxEntries = itemEntriesDTO.filter((e) => e.taxRateId); const filteredTaxEntries = itemEntriesDTO.filter((e) => e.taxRateId);
const taxRatesIds = filteredTaxEntries.map((e) => e.taxRateId); const taxRatesIds = filteredTaxEntries.map((e) => e.taxRateId);

View File

@@ -0,0 +1,76 @@
import { DiscountType } from '@/common/types/Discount';
import {
IsEnum,
IsIn,
IsInt,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
} from 'class-validator';
export class ItemEntryDto {
@IsInt()
index: number;
@IsInt()
@IsNotEmpty()
itemId: number;
@IsNumber()
@IsNotEmpty()
rate: number;
@IsNumber()
@IsNotEmpty()
quantity: number;
@IsOptional()
@IsNumber()
discount?: number;
@IsOptional()
@IsEnum(DiscountType)
discountType?: DiscountType = DiscountType.Percentage;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsString()
taxCode?: string;
@IsOptional()
@IsInt()
taxRateId?: number;
@IsOptional()
@IsInt()
warehouseId?: number;
@IsOptional()
@IsInt()
projectId?: number;
@IsOptional()
@IsInt()
projectRefId?: number;
@IsOptional()
@IsString()
@IsIn(['TASK', 'BILL', 'EXPENSE'])
projectRefType?: string;
@IsOptional()
@IsNumber()
projectRefInvoicedAmount?: number;
@IsOptional()
@IsInt()
sellAccountId?: number;
@IsOptional()
@IsInt()
costAccountId?: number;
}

View File

@@ -8,6 +8,7 @@ import { QueryTransactionsLocking } from './queries/QueryTransactionsLocking';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { ApiOperation } from '@nestjs/swagger'; import { ApiOperation } from '@nestjs/swagger';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { CancelTransactionsLockingDto, TransactionsLockingDto, UnlockTransactionsLockingDto } from './dtos/TransactionsLocking.dto';
@Controller('transactions-locking') @Controller('transactions-locking')
@ApiTags('Transactions Locking') @ApiTags('Transactions Locking')
@@ -22,7 +23,7 @@ export class TransactionsLockingController {
@ApiOperation({ summary: 'Lock all transactions for a module or all modules' }) @ApiOperation({ summary: 'Lock all transactions for a module or all modules' })
async commandTransactionsLocking( async commandTransactionsLocking(
@Body('module') module: TransactionsLockingGroup, @Body('module') module: TransactionsLockingGroup,
@Body() transactionLockingDTO: ITransactionsLockingAllDTO, @Body() transactionLockingDTO: TransactionsLockingDto,
) { ) {
const transactionMeta = const transactionMeta =
await this.transactionsLockingService.commandTransactionsLocking( await this.transactionsLockingService.commandTransactionsLocking(
@@ -39,7 +40,7 @@ export class TransactionsLockingController {
@ApiOperation({ summary: 'Cancel all transactions locking for a module or all modules' }) @ApiOperation({ summary: 'Cancel all transactions locking for a module or all modules' })
async cancelTransactionLocking( async cancelTransactionLocking(
@Body('module') module: TransactionsLockingGroup, @Body('module') module: TransactionsLockingGroup,
@Body() cancelLockingDTO: ICancelTransactionsLockingDTO, @Body() cancelLockingDTO: CancelTransactionsLockingDto,
) { ) {
const data = await this.transactionsLockingService.cancelTransactionLocking( const data = await this.transactionsLockingService.cancelTransactionLocking(
module, module,
@@ -55,7 +56,7 @@ export class TransactionsLockingController {
@ApiOperation({ summary: 'Partial unlock all transactions locking for a module or all modules' }) @ApiOperation({ summary: 'Partial unlock all transactions locking for a module or all modules' })
async unlockTransactionsLockingBetweenPeriod( async unlockTransactionsLockingBetweenPeriod(
@Body('module') module: TransactionsLockingGroup, @Body('module') module: TransactionsLockingGroup,
@Body() unlockDTO: ITransactionLockingPartiallyDTO, @Body() unlockDTO: UnlockTransactionsLockingDto,
) { ) {
const transactionMeta = const transactionMeta =
await this.transactionsLockingService.unlockTransactionsLockingPartially( await this.transactionsLockingService.unlockTransactionsLockingPartially(

View File

@@ -15,6 +15,7 @@ import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter'; import { EventEmitter2 } from '@nestjs/event-emitter';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { ServiceError } from '@/modules/Items/ServiceError'; import { ServiceError } from '@/modules/Items/ServiceError';
import { CancelTransactionsLockingDto, TransactionsLockingDto } from '../dtos/TransactionsLocking.dto';
const Modules = ['all', 'sales', 'purchases', 'financial']; const Modules = ['all', 'sales', 'purchases', 'financial'];
@@ -33,7 +34,7 @@ export class TransactionsLockingService {
*/ */
public commandTransactionsLocking = async ( public commandTransactionsLocking = async (
module: TransactionsLockingGroup = TransactionsLockingGroup.All, module: TransactionsLockingGroup = TransactionsLockingGroup.All,
transactionLockingDTO: Partial<ITransactionsLockingAllDTO>, transactionLockingDTO: TransactionsLockingDto,
): Promise<ITransactionMeta> => { ): Promise<ITransactionMeta> => {
// Validate the transaction locking module. // Validate the transaction locking module.
this.validateTransactionsLockingModule(module); this.validateTransactionsLockingModule(module);
@@ -70,7 +71,7 @@ export class TransactionsLockingService {
*/ */
public cancelTransactionLocking = async ( public cancelTransactionLocking = async (
module: TransactionsLockingGroup = TransactionsLockingGroup.All, module: TransactionsLockingGroup = TransactionsLockingGroup.All,
cancelLockingDTO: ICancelTransactionsLockingDTO, cancelLockingDTO: CancelTransactionsLockingDto,
): Promise<ITransactionMeta> => { ): Promise<ITransactionMeta> => {
// Validate the transaction locking module. // Validate the transaction locking module.
this.validateTransactionsLockingModule(module); this.validateTransactionsLockingModule(module);
@@ -137,10 +138,11 @@ export class TransactionsLockingService {
this.validateTransactionsLockingModule(module); this.validateTransactionsLockingModule(module);
// Saves transactions locking settings. // Saves transactions locking settings.
await this.transactionsLockingRepo.saveTransactionsLocking( await this.transactionsLockingRepo.saveTransactionsLocking(module, {
module, unlockFromDate: '',
{ unlockFromDate: '', unlockToDate: '', partialUnlockReason: '' }, unlockToDate: '',
); partialUnlockReason: '',
});
}; };
/** /**

View File

@@ -0,0 +1,25 @@
import { IsString } from 'class-validator';
import { IsNotEmpty } from 'class-validator';
import { IsDate } from 'class-validator';
export class TransactionsLockingDto {
@IsDate()
@IsNotEmpty()
lockToDate: Date;
@IsString()
@IsNotEmpty()
reason: string;
}
export class CancelTransactionsLockingDto {
@IsString()
@IsNotEmpty()
reason: string;
}
export class UnlockTransactionsLockingDto {
@IsDate()
@IsNotEmpty()
unlockFromDate: Date;
}

View File

@@ -9,13 +9,13 @@ import {
Query, Query,
} from '@nestjs/common'; } from '@nestjs/common';
import { VendorCreditsApplicationService } from './VendorCreditsApplication.service'; import { VendorCreditsApplicationService } from './VendorCreditsApplication.service';
import { import { IVendorCreditsQueryDTO } from './types/VendorCredit.types';
IVendorCreditCreateDTO,
IVendorCreditEditDTO,
IVendorCreditsQueryDTO,
} from './types/VendorCredit.types';
import { PublicRoute } from '../Auth/Jwt.guard'; import { PublicRoute } from '../Auth/Jwt.guard';
import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiTags } from '@nestjs/swagger';
import {
CreateVendorCreditDto,
EditVendorCreditDto,
} from './dtos/VendorCredit.dto';
@Controller('vendor-credits') @Controller('vendor-credits')
@ApiTags('vendor-credits') @ApiTags('vendor-credits')
@@ -27,7 +27,7 @@ export class VendorCreditsController {
@Post() @Post()
@ApiOperation({ summary: 'Create a new vendor credit.' }) @ApiOperation({ summary: 'Create a new vendor credit.' })
async createVendorCredit(@Body() dto: IVendorCreditCreateDTO) { async createVendorCredit(@Body() dto: CreateVendorCreditDto) {
return this.vendorCreditsApplication.createVendorCredit(dto); return this.vendorCreditsApplication.createVendorCredit(dto);
} }
@@ -47,7 +47,7 @@ export class VendorCreditsController {
@ApiOperation({ summary: 'Edit the given vendor credit.' }) @ApiOperation({ summary: 'Edit the given vendor credit.' })
async editVendorCredit( async editVendorCredit(
@Param('id') vendorCreditId: number, @Param('id') vendorCreditId: number,
@Body() dto: IVendorCreditEditDTO, @Body() dto: EditVendorCreditDto,
) { ) {
return this.vendorCreditsApplication.editVendorCredit(vendorCreditId, dto); return this.vendorCreditsApplication.editVendorCredit(vendorCreditId, dto);
} }

View File

@@ -8,6 +8,7 @@ import { IVendorCreditCreateDTO } from './types/VendorCredit.types';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { OpenVendorCreditService } from './commands/OpenVendorCredit.service'; import { OpenVendorCreditService } from './commands/OpenVendorCredit.service';
import { GetVendorCreditsService } from './queries/GetVendorCredits.service'; import { GetVendorCreditsService } from './queries/GetVendorCredits.service';
import { CreateVendorCreditDto, EditVendorCreditDto } from './dtos/VendorCredit.dto';
@Injectable() @Injectable()
export class VendorCreditsApplicationService { export class VendorCreditsApplicationService {
@@ -28,11 +29,11 @@ export class VendorCreditsApplicationService {
/** /**
* Creates a new vendor credit. * Creates a new vendor credit.
* @param {IVendorCreditCreateDTO} dto - The vendor credit create DTO. * @param {CreateVendorCreditDto} dto - The vendor credit create DTO.
* @param {Knex.Transaction} trx - The transaction. * @param {Knex.Transaction} trx - The transaction.
* @returns {Promise<VendorCredit>} The created vendor credit. * @returns {Promise<VendorCredit>} The created vendor credit.
*/ */
createVendorCredit(dto: IVendorCreditCreateDTO, trx?: Knex.Transaction) { createVendorCredit(dto: CreateVendorCreditDto, trx?: Knex.Transaction) {
return this.createVendorCreditService.newVendorCredit(dto, trx); return this.createVendorCreditService.newVendorCredit(dto, trx);
} }
@@ -48,13 +49,13 @@ export class VendorCreditsApplicationService {
/** /**
* Edits the given vendor credit. * Edits the given vendor credit.
* @param {number} vendorCreditId - The vendor credit id. * @param {number} vendorCreditId - The vendor credit id.
* @param {IVendorCreditEditDTO} dto - The vendor credit edit DTO. * @param {EditVendorCreditDto} dto - The vendor credit edit DTO.
* @param {Knex.Transaction} trx - The transaction. * @param {Knex.Transaction} trx - The transaction.
* @returns {Promise<VendorCredit>} The edited vendor credit. * @returns {Promise<VendorCredit>} The edited vendor credit.
*/ */
editVendorCredit( editVendorCredit(
vendorCreditId: number, vendorCreditId: number,
dto: IVendorCreditEditDTO, dto: EditVendorCreditDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
) { ) {
return this.editVendorCreditService.editVendorCredit( return this.editVendorCreditService.editVendorCredit(

View File

@@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { import {
IVendorCreditCreatedPayload, IVendorCreditCreatedPayload,
IVendorCreditCreateDTO,
IVendorCreditCreatingPayload, IVendorCreditCreatingPayload,
} from '@/modules/VendorCredit/types/VendorCredit.types'; } from '@/modules/VendorCredit/types/VendorCredit.types';
import { VendorCredit } from '../models/VendorCredit'; import { VendorCredit } from '../models/VendorCredit';
@@ -13,6 +12,7 @@ import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service'; import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service'; import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateVendorCreditDto } from '../dtos/VendorCredit.dto';
@Injectable() @Injectable()
export class CreateVendorCreditService { export class CreateVendorCreditService {
@@ -42,7 +42,7 @@ export class CreateVendorCreditService {
* @param {Knex.Transaction} trx - * @param {Knex.Transaction} trx -
*/ */
public newVendorCredit = async ( public newVendorCredit = async (
vendorCreditCreateDTO: IVendorCreditCreateDTO, vendorCreditCreateDTO: CreateVendorCreditDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
) => { ) => {
// Triggers `onVendorCreditCreate` event. // Triggers `onVendorCreditCreate` event.

View File

@@ -13,6 +13,7 @@ import { events } from '@/common/events/events';
import { Knex } from 'knex'; import { Knex } from 'knex';
import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service'; import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { EditVendorCreditDto } from '../dtos/VendorCredit.dto';
@Injectable() @Injectable()
export class EditVendorCreditService { export class EditVendorCreditService {
@@ -39,10 +40,11 @@ export class EditVendorCreditService {
/** /**
* Deletes the given vendor credit. * Deletes the given vendor credit.
* @param {number} vendorCreditId - Vendor credit id. * @param {number} vendorCreditId - Vendor credit id.
* @param {EditVendorCreditDto} vendorCreditDto -
*/ */
public editVendorCredit = async ( public editVendorCredit = async (
vendorCreditId: number, vendorCreditId: number,
vendorCreditDTO: IVendorCreditEditDTO, vendorCreditDTO: EditVendorCreditDto,
trx?: Knex.Transaction, trx?: Knex.Transaction,
) => { ) => {
// Retrieve the vendor credit or throw not found service error. // Retrieve the vendor credit or throw not found service error.

View File

@@ -2,11 +2,7 @@ import * as moment from 'moment';
import { omit } from 'lodash'; import { omit } from 'lodash';
import * as R from 'ramda'; import * as R from 'ramda';
import { ERRORS } from '../constants'; import { ERRORS } from '../constants';
import { import { IVendorCreditEntryDTO } from '../types/VendorCredit.types';
IVendorCreditCreateDTO,
IVendorCreditEditDTO,
IVendorCreditEntryDTO,
} from '../types/VendorCredit.types';
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service'; import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform'; import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform'; import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
@@ -15,6 +11,10 @@ import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-ind
import { VendorCreditAutoIncrementService } from './VendorCreditAutoIncrement.service'; import { VendorCreditAutoIncrementService } from './VendorCreditAutoIncrement.service';
import { ServiceError } from '@/modules/Items/ServiceError'; import { ServiceError } from '@/modules/Items/ServiceError';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import {
CreateVendorCreditDto,
EditVendorCreditDto,
} from '../dtos/VendorCredit.dto';
@Injectable() @Injectable()
export class VendorCreditDTOTransformService { export class VendorCreditDTOTransformService {
@@ -39,7 +39,7 @@ export class VendorCreditDTOTransformService {
* @returns {VendorCredit} * @returns {VendorCredit}
*/ */
public transformCreateEditDTOToModel = async ( public transformCreateEditDTOToModel = async (
vendorCreditDTO: IVendorCreditCreateDTO | IVendorCreditEditDTO, vendorCreditDTO: CreateVendorCreditDto | EditVendorCreditDto,
vendorCurrencyCode: string, vendorCurrencyCode: string,
oldVendorCredit?: VendorCredit, oldVendorCredit?: VendorCredit,
): Promise<VendorCredit> => { ): Promise<VendorCredit> => {

View File

@@ -0,0 +1,83 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer';
import {
IsArray,
IsEnum,
IsNumber,
IsOptional,
IsString,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
class VendorCreditEntryDto extends ItemEntryDto {}
class AttachmentDto {
@IsString()
key: string;
}
export class CommandVendorCreditDto {
@IsNumber()
vendorId: number;
@IsNumber()
@IsOptional()
exchangeRate?: number;
@IsString()
@IsOptional()
vendorCreditNumber?: string;
@IsString()
@IsOptional()
referenceNo?: string;
@IsString() // ISO8601 date string
vendorCreditDate: string;
@IsString()
@IsOptional()
note?: string;
@IsOptional()
open: boolean = false;
@IsNumber()
@IsOptional()
warehouseId?: number;
@IsNumber()
@IsOptional()
branchId?: number;
@IsArray()
@ValidateNested({ each: true })
@Type(() => VendorCreditEntryDto)
entries: VendorCreditEntryDto[];
@IsArray()
@ValidateNested({ each: true })
@Type(() => AttachmentDto)
@IsOptional()
attachments?: AttachmentDto[];
@IsNumber()
@IsOptional()
discount?: number;
@IsEnum(DiscountType)
@IsOptional()
discountType?: DiscountType;
@IsNumber()
@IsOptional()
adjustment?: number;
}
export class CreateVendorCreditDto extends CommandVendorCreditDto {}
export class EditVendorCreditDto extends CommandVendorCreditDto {}

View File

@@ -5,6 +5,10 @@ import { IRefundVendorCreditDTO } from '@/modules/VendorCreditsRefund/types/Vend
import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types'; import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
import { DiscountType } from '@/common/types/Discount'; import { DiscountType } from '@/common/types/Discount';
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types'; import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
import {
CreateVendorCreditDto,
EditVendorCreditDto,
} from '../dtos/VendorCredit.dto';
export enum VendorCreditAction { export enum VendorCreditAction {
Create = 'Create', Create = 'Create',
@@ -39,7 +43,7 @@ export interface IVendorCreditDTO {
discount?: number; discount?: number;
discountType?: DiscountType; discountType?: DiscountType;
adjustment?: number; adjustment?: number;
} }
@@ -54,14 +58,13 @@ export interface IVendorCreditCreatePayload {
export interface IVendorCreditCreatingPayload { export interface IVendorCreditCreatingPayload {
vendorCredit: VendorCredit; vendorCredit: VendorCredit;
vendorCreditId: number; vendorCreditId: number;
vendorCreditCreateDTO: IVendorCreditCreateDTO; vendorCreditCreateDTO: CreateVendorCreditDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IVendorCreditCreatedPayload { export interface IVendorCreditCreatedPayload {
// tenantId: number;
vendorCredit: VendorCredit; vendorCredit: VendorCredit;
vendorCreditCreateDTO: IVendorCreditCreateDTO; vendorCreditCreateDTO: CreateVendorCreditDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
@@ -83,18 +86,15 @@ export interface IVendorCreditDeletingPayload {
// Edit Vendor Credit Events // Edit Vendor Credit Events
// ------------------------ // ------------------------
export interface IVendorCreditEditingPayload { export interface IVendorCreditEditingPayload {
// tenantId: number;
oldVendorCredit: VendorCredit; oldVendorCredit: VendorCredit;
vendorCreditDTO: IVendorCreditEditDTO; vendorCreditDTO: EditVendorCreditDto;
trx: Knex.Transaction; trx: Knex.Transaction;
} }
export interface IVendorCreditEditedPayload { export interface IVendorCreditEditedPayload {
// tenantId: number;
oldVendorCredit: VendorCredit; oldVendorCredit: VendorCredit;
vendorCredit: VendorCredit; vendorCredit: VendorCredit;
// vendorCreditId: number; vendorCreditDTO: EditVendorCreditDto;
vendorCreditDTO: IVendorCreditEditDTO;
trx: Knex.Transaction; trx: Knex.Transaction;
} }

View File

@@ -41,8 +41,7 @@ export class WarehousesDTOValidators {
/** /**
* Validate the warehouse existance of * Validate the warehouse existance of
* @param {number} tenantId * @param {IWarehouseTransactionDTO} saleInvoiceDTO
* @param {IWarehouseTransactionDTO} saleInvoiceDTO
* @returns * @returns
*/ */
public validateDTOWarehouseWhenActive = async ( public validateDTOWarehouseWhenActive = async (

View File

@@ -1,8 +1,6 @@
import { import { Injectable } from '@nestjs/common';
ICreateWarehouseTransferDTO, import { ModelObject } from 'objection';
IEditWarehouseTransferDTO, import { IGetWarehousesTransfersFilterDTO } from '@/modules/Warehouses/Warehouse.types';
IGetWarehousesTransfersFilterDTO,
} from '@/modules/Warehouses/Warehouse.types';
import { CreateWarehouseTransfer } from './commands/CreateWarehouseTransfer'; import { CreateWarehouseTransfer } from './commands/CreateWarehouseTransfer';
import { DeleteWarehouseTransfer } from './commands/DeleteWarehouseTransfer'; import { DeleteWarehouseTransfer } from './commands/DeleteWarehouseTransfer';
import { EditWarehouseTransfer } from './commands/EditWarehouseTransfer'; import { EditWarehouseTransfer } from './commands/EditWarehouseTransfer';
@@ -10,9 +8,11 @@ import { GetWarehouseTransfer } from './queries/GetWarehouseTransfer';
import { GetWarehouseTransfers } from './queries/GetWarehouseTransfers'; import { GetWarehouseTransfers } from './queries/GetWarehouseTransfers';
import { InitiateWarehouseTransfer } from './commands/InitiateWarehouseTransfer'; import { InitiateWarehouseTransfer } from './commands/InitiateWarehouseTransfer';
import { TransferredWarehouseTransfer } from './commands/TransferredWarehouseTransfer'; import { TransferredWarehouseTransfer } from './commands/TransferredWarehouseTransfer';
import { Injectable } from '@nestjs/common';
import { WarehouseTransfer } from './models/WarehouseTransfer'; import { WarehouseTransfer } from './models/WarehouseTransfer';
import { ModelObject } from 'objection'; import {
CreateWarehouseTransferDto,
EditWarehouseTransferDto,
} from './dtos/WarehouseTransfer.dto';
@Injectable() @Injectable()
export class WarehouseTransferApplication { export class WarehouseTransferApplication {
@@ -32,7 +32,7 @@ export class WarehouseTransferApplication {
* @returns {Promise<ModelObject<WarehouseTransfer>>} * @returns {Promise<ModelObject<WarehouseTransfer>>}
*/ */
public createWarehouseTransfer = ( public createWarehouseTransfer = (
createWarehouseTransferDTO: ICreateWarehouseTransferDTO, createWarehouseTransferDTO: CreateWarehouseTransferDto,
): Promise<ModelObject<WarehouseTransfer>> => { ): Promise<ModelObject<WarehouseTransfer>> => {
return this.createWarehouseTransferService.createWarehouseTransfer( return this.createWarehouseTransferService.createWarehouseTransfer(
createWarehouseTransferDTO, createWarehouseTransferDTO,
@@ -46,7 +46,7 @@ export class WarehouseTransferApplication {
*/ */
public editWarehouseTransfer = ( public editWarehouseTransfer = (
warehouseTransferId: number, warehouseTransferId: number,
editWarehouseTransferDTO: IEditWarehouseTransferDTO, editWarehouseTransferDTO: EditWarehouseTransferDto,
): Promise<ModelObject<WarehouseTransfer>> => { ): Promise<ModelObject<WarehouseTransfer>> => {
return this.editWarehouseTransferService.editWarehouseTransfer( return this.editWarehouseTransferService.editWarehouseTransfer(
warehouseTransferId, warehouseTransferId,
@@ -69,8 +69,8 @@ export class WarehouseTransferApplication {
/** /**
* Retrieves warehouse transfer transaction. * Retrieves warehouse transfer transaction.
* @param {number} warehouseTransferId * @param {number} warehouseTransferId - Warehouse transfer id.
* @returns {Promise<IWarehouseTransfer>} * @returns {Promise<ModelObject<WarehouseTransfer>>}
*/ */
public getWarehouseTransfer = ( public getWarehouseTransfer = (
warehouseTransferId: number, warehouseTransferId: number,

Some files were not shown because too many files have changed in this diff Show More