mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-14 20:00:33 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { Body, Controller, Delete, Param, Post } from '@nestjs/common';
|
||||
import { ICreditNoteRefundDTO } from '../CreditNotes/types/CreditNotes.types';
|
||||
import { CreditNotesRefundsApplication } from './CreditNotesRefundsApplication.service';
|
||||
import { RefundCreditNote } from './models/RefundCreditNote';
|
||||
import { CreditNoteRefundDto } from './dto/CreditNoteRefund.dto';
|
||||
|
||||
@Controller('credit-notes')
|
||||
@ApiTags('credit-notes-refunds')
|
||||
export class CreditNoteRefundsController {
|
||||
constructor(
|
||||
private readonly creditNotesRefundsApplication: CreditNotesRefundsApplication,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Create a refund credit note.
|
||||
* @param {number} creditNoteId - The credit note ID.
|
||||
* @param {ICreditNoteRefundDTO} creditNoteDTO - The credit note DTO.
|
||||
* @returns {Promise<RefundCreditNote>}
|
||||
*/
|
||||
@Post(':creditNoteId/refunds')
|
||||
@ApiOperation({ summary: 'Create a refund for the given credit note.' })
|
||||
createRefundCreditNote(
|
||||
@Param('creditNoteId') creditNoteId: number,
|
||||
@Body() creditNoteDTO: CreditNoteRefundDto,
|
||||
): Promise<RefundCreditNote> {
|
||||
return this.creditNotesRefundsApplication.createRefundCreditNote(
|
||||
creditNoteId,
|
||||
creditNoteDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a refund credit note.
|
||||
* @param {number} refundCreditId - The refund credit ID.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@Delete('refunds/:refundCreditId')
|
||||
@ApiOperation({ summary: 'Delete a refund for the given credit note.' })
|
||||
deleteRefundCreditNote(
|
||||
@Param('refundCreditId') refundCreditId: number,
|
||||
): Promise<void> {
|
||||
return this.creditNotesRefundsApplication.deleteRefundCreditNote(
|
||||
refundCreditId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CreateRefundCreditNoteService } from './commands/CreateRefundCreditNote.service';
|
||||
import { DeleteRefundCreditNoteService } from './commands/DeleteRefundCreditNote.service';
|
||||
import { RefundCreditNoteService } from './commands/RefundCreditNote.service';
|
||||
import { RefundSyncCreditNoteBalanceService } from './commands/RefundSyncCreditNoteBalance';
|
||||
import { CreditNotesRefundsApplication } from './CreditNotesRefundsApplication.service';
|
||||
import { CreditNoteRefundsController } from './CreditNoteRefunds.controller';
|
||||
import { CreditNotesModule } from '../CreditNotes/CreditNotes.module';
|
||||
|
||||
@Module({
|
||||
imports: [CreditNotesModule],
|
||||
providers: [
|
||||
CreateRefundCreditNoteService,
|
||||
DeleteRefundCreditNoteService,
|
||||
RefundCreditNoteService,
|
||||
RefundSyncCreditNoteBalanceService,
|
||||
CreditNotesRefundsApplication,
|
||||
],
|
||||
controllers: [CreditNoteRefundsController],
|
||||
})
|
||||
export class CreditNoteRefundsModule {}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ICreditNoteRefundDTO } from '../CreditNotes/types/CreditNotes.types';
|
||||
import { CreateRefundCreditNoteService } from './commands/CreateRefundCreditNote.service';
|
||||
import { DeleteRefundCreditNoteService } from './commands/DeleteRefundCreditNote.service';
|
||||
import { RefundCreditNoteService } from './commands/RefundCreditNote.service';
|
||||
import { RefundSyncCreditNoteBalanceService } from './commands/RefundSyncCreditNoteBalance';
|
||||
import { CreditNoteRefundDto } from './dto/CreditNoteRefund.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNotesRefundsApplication {
|
||||
constructor(
|
||||
private readonly createRefundCreditNoteService: CreateRefundCreditNoteService,
|
||||
private readonly deleteRefundCreditNoteService: DeleteRefundCreditNoteService,
|
||||
private readonly refundCreditNoteService: RefundCreditNoteService,
|
||||
private readonly refundSyncCreditNoteBalanceService: RefundSyncCreditNoteBalanceService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Create a refund credit note.
|
||||
* @param {number} creditNoteId - The credit note ID.
|
||||
* @param {CreditNoteRefundDto} creditNoteDTO - The credit note DTO.
|
||||
* @returns {Promise<RefundCreditNote>}
|
||||
*/
|
||||
public createRefundCreditNote(
|
||||
creditNoteId: number,
|
||||
creditNoteDTO: CreditNoteRefundDto,
|
||||
) {
|
||||
return this.createRefundCreditNoteService.createCreditNoteRefund(
|
||||
creditNoteId,
|
||||
creditNoteDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a refund credit note.
|
||||
* @param {number} refundCreditId - The refund credit ID.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteRefundCreditNote(refundCreditId: number) {
|
||||
return this.deleteRefundCreditNoteService.deleteCreditNoteRefund(
|
||||
refundCreditId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
ICreditNoteRefundDTO,
|
||||
IRefundCreditNoteCreatedPayload,
|
||||
IRefundCreditNoteCreatingPayload,
|
||||
} from '../types/CreditNoteRefunds.types';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { RefundCreditNote } from '@/modules/CreditNoteRefunds/models/RefundCreditNote';
|
||||
import { CommandCreditNoteDTOTransform } from '@/modules/CreditNotes/commands/CommandCreditNoteDTOTransform.service';
|
||||
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { CreditNoteRefundDto } from '../dto/CreditNoteRefund.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateRefundCreditNoteService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - The unit of work service.
|
||||
* @param {EventEmitter2} eventPublisher - The event emitter service.
|
||||
* @param {CommandCreditNoteDTOTransform} commandCreditNoteDTOTransform - The command credit note DTO transform service.
|
||||
* @param {TenantModelProxy<typeof RefundCreditNote>} refundCreditNoteModel - The refund credit note model.
|
||||
* @param {TenantModelProxy<typeof Account>} accountModel - The account model.
|
||||
* @param {TenantModelProxy<typeof CreditNote>} creditNoteModel - The credit note model.
|
||||
*/
|
||||
constructor(
|
||||
private uow: UnitOfWork,
|
||||
private eventPublisher: EventEmitter2,
|
||||
private commandCreditNoteDTOTransform: CommandCreditNoteDTOTransform,
|
||||
|
||||
@Inject(RefundCreditNote.name)
|
||||
private refundCreditNoteModel: TenantModelProxy<typeof RefundCreditNote>,
|
||||
|
||||
@Inject(Account.name)
|
||||
private accountModel: TenantModelProxy<typeof Account>,
|
||||
|
||||
@Inject(CreditNote.name)
|
||||
private creditNoteModel: TenantModelProxy<typeof CreditNote>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve the credit note graph.
|
||||
* @param {number} creditNoteId
|
||||
* @param {ICreditNoteRefundDTO} newCreditNoteDTO
|
||||
* @returns {Promise<IRefundCreditNote>}
|
||||
*/
|
||||
public async createCreditNoteRefund(
|
||||
creditNoteId: number,
|
||||
newCreditNoteDTO: CreditNoteRefundDto,
|
||||
): Promise<RefundCreditNote> {
|
||||
// Retrieve the credit note or throw not found service error.
|
||||
const creditNote = await this.creditNoteModel()
|
||||
.query()
|
||||
.findById(creditNoteId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Retrieve the withdrawal account or throw not found service error.
|
||||
const fromAccount = await this.accountModel()
|
||||
.query()
|
||||
.findById(newCreditNoteDTO.fromAccountId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Validate the credit note remaining amount.
|
||||
this.commandCreditNoteDTOTransform?.validateCreditRemainingAmount(
|
||||
creditNote,
|
||||
newCreditNoteDTO.amount,
|
||||
);
|
||||
// Validate the refund withdrawal account type.
|
||||
// this.commandCreditNoteDTOTransform.validateRefundWithdrawwalAccountType(
|
||||
// fromAccount,
|
||||
// );
|
||||
// Creates a refund credit note transaction.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onCreditNoteRefundCreating` event.
|
||||
await this.eventPublisher.emitAsync(events.creditNote.onRefundCreating, {
|
||||
trx,
|
||||
creditNote,
|
||||
newCreditNoteDTO,
|
||||
} as IRefundCreditNoteCreatingPayload);
|
||||
|
||||
// Stores the refund credit note graph to the storage layer.
|
||||
const refundCreditNote = await this.refundCreditNoteModel()
|
||||
.query(trx)
|
||||
.insertAndFetch({
|
||||
...this.transformDTOToModel(creditNote, newCreditNoteDTO),
|
||||
});
|
||||
// Triggers `onCreditNoteRefundCreated` event.
|
||||
await this.eventPublisher.emitAsync(events.creditNote.onRefundCreated, {
|
||||
trx,
|
||||
refundCreditNote,
|
||||
creditNote,
|
||||
} as IRefundCreditNoteCreatedPayload);
|
||||
|
||||
return refundCreditNote;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transformes the refund credit note DTO to model.
|
||||
* @param {CreditNote} creditNote - The credit note.
|
||||
* @param {CreditNoteRefundDto} creditNoteDTO - The credit note refund DTO.
|
||||
* @returns {Partial<RefundCreditNote>}
|
||||
*/
|
||||
private transformDTOToModel = (
|
||||
creditNote: CreditNote,
|
||||
creditNoteDTO: CreditNoteRefundDto,
|
||||
): Partial<RefundCreditNote> => {
|
||||
return {
|
||||
creditNoteId: creditNote.id,
|
||||
currencyCode: creditNote.currencyCode,
|
||||
...creditNoteDTO,
|
||||
exchangeRate: creditNoteDTO.exchangeRate || 1,
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IRefundCreditNoteDeletedPayload,
|
||||
IRefundCreditNoteDeletingPayload,
|
||||
} from '../types/CreditNoteRefunds.types';
|
||||
import { RefundCreditNote } from '../models/RefundCreditNote';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteRefundCreditNoteService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter.
|
||||
* @param {typeof RefundCreditNote} refundCreditNoteModel - Refund credit note model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(RefundCreditNote.name)
|
||||
private readonly refundCreditNoteModel: TenantModelProxy<
|
||||
typeof RefundCreditNote
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve the credit note graph.
|
||||
* @param {number} refundCreditId - Refund credit note ID.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteCreditNoteRefund = async (refundCreditId: number) => {
|
||||
// Retrieve the old credit note or throw not found service error.
|
||||
const oldRefundCredit = await this.refundCreditNoteModel()
|
||||
.query()
|
||||
.findById(refundCreditId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Triggers `onCreditNoteRefundDeleted` event.
|
||||
await this.eventPublisher.emitAsync(events.creditNote.onRefundDelete, {
|
||||
refundCreditId,
|
||||
oldRefundCredit,
|
||||
} as IRefundCreditNoteDeletedPayload);
|
||||
|
||||
// Deletes refund credit note transactions with associated entries.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
const eventPayload = {
|
||||
trx,
|
||||
refundCreditId,
|
||||
oldRefundCredit,
|
||||
} as IRefundCreditNoteDeletedPayload | IRefundCreditNoteDeletingPayload;
|
||||
|
||||
// Triggers `onCreditNoteRefundDeleting` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.creditNote.onRefundDeleting,
|
||||
eventPayload,
|
||||
);
|
||||
// Deletes the refund credit note graph from the storage.
|
||||
await this.refundCreditNoteModel()
|
||||
.query(trx)
|
||||
.findById(refundCreditId)
|
||||
.delete();
|
||||
|
||||
// Triggers `onCreditNoteRefundDeleted` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.creditNote.onRefundDeleted,
|
||||
eventPayload as IRefundCreditNoteDeletedPayload,
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ERRORS } from '../../CreditNotes/constants';
|
||||
import { RefundCreditNote } from '../models/RefundCreditNote';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class RefundCreditNoteService {
|
||||
/**
|
||||
* @param {TenantModelProxy<typeof RefundCreditNote>} refundCreditNoteModel - The refund credit note model.
|
||||
*/
|
||||
constructor(
|
||||
@Inject(RefundCreditNote.name)
|
||||
private readonly refundCreditNoteModel: TenantModelProxy<
|
||||
typeof RefundCreditNote
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve the credit note graph.
|
||||
* @param {number} refundCreditId
|
||||
* @returns {Promise<RefundCreditNote>}
|
||||
*/
|
||||
public getCreditNoteRefundOrThrowError = async (
|
||||
refundCreditId: number,
|
||||
): Promise<RefundCreditNote> => {
|
||||
const refundCreditNote = await this.refundCreditNoteModel()
|
||||
.query()
|
||||
.findById(refundCreditId);
|
||||
if (!refundCreditNote) {
|
||||
throw new ServiceError(ERRORS.REFUND_CREDIT_NOTE_NOT_FOUND);
|
||||
}
|
||||
return refundCreditNote;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the refund account type.
|
||||
* @param {Account} account
|
||||
*/
|
||||
public validateRefundWithdrawwalAccountType = (account: Account): void => {
|
||||
const supportedTypes = ['bank', 'cash', 'fixed-asset'];
|
||||
|
||||
if (supportedTypes.indexOf(account.accountType) === -1) {
|
||||
throw new ServiceError(ERRORS.ACCOUNT_INVALID_TYPE);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import { Knex } from 'knex';
|
||||
// import { AccountNormal, ILedgerEntry, IRefundCreditNote } from '@/interfaces';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
||||
// import Ledger from '@/services/Accounting/Ledger';
|
||||
|
||||
// @Service()
|
||||
// export default class RefundCreditNoteGLEntries {
|
||||
// @Inject()
|
||||
// ledgerStorage: LedgerStorageService;
|
||||
|
||||
// @Inject()
|
||||
// tenancy: HasTenancyService;
|
||||
|
||||
// /**
|
||||
// * Retrieves the refund credit common GL entry.
|
||||
// * @param {IRefundCreditNote} refundCreditNote
|
||||
// * @returns
|
||||
// */
|
||||
// private getRefundCreditCommonGLEntry = (
|
||||
// refundCreditNote: IRefundCreditNote
|
||||
// ) => {
|
||||
// return {
|
||||
// currencyCode: refundCreditNote.currencyCode,
|
||||
// exchangeRate: refundCreditNote.exchangeRate,
|
||||
|
||||
// transactionType: 'RefundCreditNote',
|
||||
// transactionId: refundCreditNote.id,
|
||||
// date: refundCreditNote.date,
|
||||
// userId: refundCreditNote.userId,
|
||||
|
||||
// referenceNumber: refundCreditNote.referenceNo,
|
||||
|
||||
// createdAt: refundCreditNote.createdAt,
|
||||
// indexGroup: 10,
|
||||
|
||||
// credit: 0,
|
||||
// debit: 0,
|
||||
|
||||
// note: refundCreditNote.description,
|
||||
// branchId: refundCreditNote.branchId,
|
||||
// };
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Retrieves the refudn credit receivable GL entry.
|
||||
// * @param {IRefundCreditNote} refundCreditNote
|
||||
// * @param {number} ARAccountId
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getRefundCreditGLReceivableEntry = (
|
||||
// refundCreditNote: IRefundCreditNote,
|
||||
// ARAccountId: number
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getRefundCreditCommonGLEntry(refundCreditNote);
|
||||
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// debit: refundCreditNote.amount,
|
||||
// accountId: ARAccountId,
|
||||
// contactId: refundCreditNote.creditNote.customerId,
|
||||
// index: 1,
|
||||
// accountNormal: AccountNormal.DEBIT,
|
||||
// };
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Retrieves the refund credit withdrawal GL entry.
|
||||
// * @param {number} refundCreditNote
|
||||
// * @returns {ILedgerEntry}
|
||||
// */
|
||||
// private getRefundCreditGLWithdrawalEntry = (
|
||||
// refundCreditNote: IRefundCreditNote
|
||||
// ): ILedgerEntry => {
|
||||
// const commonEntry = this.getRefundCreditCommonGLEntry(refundCreditNote);
|
||||
|
||||
// return {
|
||||
// ...commonEntry,
|
||||
// credit: refundCreditNote.amount,
|
||||
// accountId: refundCreditNote.fromAccountId,
|
||||
// index: 2,
|
||||
// accountNormal: AccountNormal.DEBIT,
|
||||
// };
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Retrieve the refund credit note GL entries.
|
||||
// * @param {IRefundCreditNote} refundCreditNote
|
||||
// * @param {number} receivableAccount
|
||||
// * @returns {ILedgerEntry[]}
|
||||
// */
|
||||
// public getRefundCreditGLEntries(
|
||||
// refundCreditNote: IRefundCreditNote,
|
||||
// ARAccountId: number
|
||||
// ): ILedgerEntry[] {
|
||||
// const receivableEntry = this.getRefundCreditGLReceivableEntry(
|
||||
// refundCreditNote,
|
||||
// ARAccountId
|
||||
// );
|
||||
// const withdrawalEntry =
|
||||
// this.getRefundCreditGLWithdrawalEntry(refundCreditNote);
|
||||
|
||||
// return [receivableEntry, withdrawalEntry];
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Creates refund credit GL entries.
|
||||
// * @param {number} tenantId
|
||||
// * @param {IRefundCreditNote} refundCreditNote
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public createRefundCreditGLEntries = async (
|
||||
// tenantId: number,
|
||||
// refundCreditNoteId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// const { Account, RefundCreditNote } = this.tenancy.models(tenantId);
|
||||
|
||||
// // Retrieve the refund with associated credit note.
|
||||
// const refundCreditNote = await RefundCreditNote.query(trx)
|
||||
// .findById(refundCreditNoteId)
|
||||
// .withGraphFetched('creditNote');
|
||||
|
||||
// // Receivable account A/R.
|
||||
// const receivableAccount = await Account.query().findOne(
|
||||
// 'slug',
|
||||
// 'accounts-receivable'
|
||||
// );
|
||||
// // Retrieve refund credit GL entries.
|
||||
// const refundGLEntries = this.getRefundCreditGLEntries(
|
||||
// refundCreditNote,
|
||||
// receivableAccount.id
|
||||
// );
|
||||
// const ledger = new Ledger(refundGLEntries);
|
||||
|
||||
// // Saves refund ledger entries.
|
||||
// await this.ledgerStorage.commit(tenantId, ledger, trx);
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Reverts refund credit note GL entries.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} refundCreditNoteId
|
||||
// * @param {number} receivableAccount
|
||||
// * @param {Knex.Transaction} trx
|
||||
// */
|
||||
// public revertRefundCreditGLEntries = async (
|
||||
// tenantId: number,
|
||||
// refundCreditNoteId: number,
|
||||
// trx?: Knex.Transaction
|
||||
// ) => {
|
||||
// await this.ledgerStorage.deleteByReference(
|
||||
// tenantId,
|
||||
// refundCreditNoteId,
|
||||
// 'RefundCreditNote',
|
||||
// trx
|
||||
// );
|
||||
// };
|
||||
// }
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class RefundSyncCreditNoteBalanceService {
|
||||
/**
|
||||
* @param {TenantModelProxy<typeof CreditNote>} creditNoteModel - The credit note model.
|
||||
*/
|
||||
constructor(
|
||||
@Inject(CreditNote.name)
|
||||
private readonly creditNoteModel: TenantModelProxy<typeof CreditNote>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Increments the refund amount of the credit note.
|
||||
* @param {number} creditNoteId - The credit note ID.
|
||||
* @param {number} amount - The amount to increment.
|
||||
* @param {Knex.Transaction} trx - The knex transaction.
|
||||
*/
|
||||
public incrementCreditNoteRefundAmount = async (
|
||||
creditNoteId: number,
|
||||
amount: number,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
await this.creditNoteModel()
|
||||
.query(trx)
|
||||
.findById(creditNoteId)
|
||||
.increment('refunded_amount', amount);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrements the refund amount of the credit note.
|
||||
* @param {number} creditNoteId - The credit note ID.
|
||||
* @param {number} amount - The amount to decrement.
|
||||
* @param {Knex.Transaction} trx - The knex transaction.
|
||||
*/
|
||||
public decrementCreditNoteRefundAmount = async (
|
||||
creditNoteId: number,
|
||||
amount: number,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
await this.creditNoteModel()
|
||||
.query(trx)
|
||||
.findById(creditNoteId)
|
||||
.decrement('refunded_amount', amount);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsOptional, IsPositive, IsString } from 'class-validator';
|
||||
import { IsDate } from 'class-validator';
|
||||
import { IsNumber } from 'class-validator';
|
||||
|
||||
export class CreditNoteRefundDto {
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The id of the from account',
|
||||
example: 1,
|
||||
})
|
||||
fromAccountId: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsPositive()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The amount of the credit note refund',
|
||||
example: 100,
|
||||
})
|
||||
amount: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@IsPositive()
|
||||
@ApiProperty({
|
||||
description: 'The exchange rate of the credit note refund',
|
||||
example: 1,
|
||||
})
|
||||
exchangeRate?: number;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The reference number of the credit note refund',
|
||||
example: '123456',
|
||||
})
|
||||
referenceNo: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The description of the credit note refund',
|
||||
example: 'Credit note refund',
|
||||
})
|
||||
description: string;
|
||||
|
||||
@IsDate()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({
|
||||
description: 'The date of the credit note refund',
|
||||
example: '2021-01-01',
|
||||
})
|
||||
date: Date;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'The id of the branch',
|
||||
example: 1,
|
||||
})
|
||||
branchId?: number;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Model, mixin } from 'objection';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import ModelSetting from './ModelSetting';
|
||||
// import CustomViewBaseModel from './CustomViewBaseModel';
|
||||
// import ModelSearchable from './ModelSearchable';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
|
||||
export class RefundCreditNote extends BaseModel{
|
||||
date: Date;
|
||||
referenceNo: string;
|
||||
amount: number;
|
||||
currencyCode: string;
|
||||
exchangeRate: number;
|
||||
fromAccountId: number;
|
||||
description: string;
|
||||
creditNoteId: number;
|
||||
|
||||
userId?: number;
|
||||
branchId?: number;
|
||||
|
||||
createdAt?: Date | null;
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'refund_credit_note_transactions';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { Account } = require('../../Accounts/models/Account.model');
|
||||
const { CreditNote } = require('../../CreditNotes/models/CreditNote');
|
||||
|
||||
return {
|
||||
fromAccount: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Account,
|
||||
join: {
|
||||
from: 'refund_credit_note_transactions.fromAccountId',
|
||||
to: 'accounts.id',
|
||||
},
|
||||
},
|
||||
creditNote: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: CreditNote,
|
||||
join: {
|
||||
from: 'refund_credit_note_transactions.creditNoteId',
|
||||
to: 'credit_notes.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { RefundCreditNote } from '../models/RefundCreditNote';
|
||||
import { RefundCreditNoteTransformer } from '@/modules/CreditNotes/queries/RefundCreditNoteTransformer';
|
||||
import { IRefundCreditNotePOJO } from '../types/CreditNoteRefunds.types';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class ListCreditNoteRefunds {
|
||||
constructor(
|
||||
private readonly transformer: TransformerInjectable,
|
||||
|
||||
@Inject(RefundCreditNote.name)
|
||||
private readonly refundCreditNoteModel: TenantModelProxy<
|
||||
typeof RefundCreditNote
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve the credit note graph.
|
||||
* @param {number} creditNoteId
|
||||
* @returns {Promise<IRefundCreditNotePOJO[]>}
|
||||
*/
|
||||
public async getCreditNoteRefunds(
|
||||
creditNoteId: number,
|
||||
): Promise<IRefundCreditNotePOJO[]> {
|
||||
// Retrieve refund credit notes associated to the given credit note.
|
||||
const refundCreditTransactions = await this.refundCreditNoteModel()
|
||||
.query()
|
||||
.where('creditNoteId', creditNoteId)
|
||||
.withGraphFetched('creditNote')
|
||||
.withGraphFetched('fromAccount');
|
||||
|
||||
// Transforms refund credit note models to POJO objects.
|
||||
return this.transformer.transform(
|
||||
refundCreditTransactions,
|
||||
new RefundCreditNoteTransformer(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { RefundCreditNote } from '../models/RefundCreditNote';
|
||||
import { RefundCreditNoteTransformer } from '../../CreditNotes/queries/RefundCreditNoteTransformer';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class GetRefundCreditNoteTransaction {
|
||||
/**
|
||||
* @param {RefundCreditNoteTransformer} transformer
|
||||
* @param {typeof RefundCreditNote} refundCreditNoteModel
|
||||
*/
|
||||
constructor(
|
||||
private readonly transformer: RefundCreditNoteTransformer,
|
||||
|
||||
@Inject(RefundCreditNote.name)
|
||||
private readonly refundCreditNoteModel: TenantModelProxy<
|
||||
typeof RefundCreditNote
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve credit note associated invoices to apply.
|
||||
* @param {number} refundCreditId
|
||||
* @returns {Promise<IRefundCreditNote>}
|
||||
*/
|
||||
public async getRefundCreditTransaction(
|
||||
refundCreditId: number,
|
||||
): Promise<RefundCreditNote> {
|
||||
const refundCreditNote = await this.refundCreditNoteModel()
|
||||
.query()
|
||||
.findById(refundCreditId)
|
||||
.withGraphFetched('fromAccount')
|
||||
.withGraphFetched('creditNote')
|
||||
.throwIfNotFound();
|
||||
|
||||
return this.transformer.transform(refundCreditNote);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Knex } from 'knex';
|
||||
import { RefundCreditNote } from '../models/RefundCreditNote';
|
||||
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { CreditNoteRefundDto } from '../dto/CreditNoteRefund.dto';
|
||||
|
||||
export interface ICreditNoteRefundDTO {
|
||||
fromAccountId: number;
|
||||
amount: number;
|
||||
exchangeRate?: number;
|
||||
referenceNo: string;
|
||||
description: string;
|
||||
date: Date;
|
||||
branchId?: number;
|
||||
}
|
||||
|
||||
export interface IRefundCreditNotePOJO {
|
||||
formattedAmount: string;
|
||||
}
|
||||
|
||||
export interface IRefundCreditNoteDeletedPayload {
|
||||
trx: Knex.Transaction;
|
||||
refundCreditId: number;
|
||||
oldRefundCredit: RefundCreditNote;
|
||||
}
|
||||
|
||||
export interface IRefundCreditNoteDeletingPayload {
|
||||
trx: Knex.Transaction;
|
||||
refundCreditId: number;
|
||||
oldRefundCredit: RefundCreditNote;
|
||||
}
|
||||
|
||||
export interface IRefundCreditNoteCreatingPayload {
|
||||
trx: Knex.Transaction;
|
||||
creditNote: CreditNote;
|
||||
newCreditNoteDTO: CreditNoteRefundDto;
|
||||
}
|
||||
|
||||
export interface IRefundCreditNoteCreatedPayload {
|
||||
trx: Knex.Transaction;
|
||||
refundCreditNote: RefundCreditNote;
|
||||
creditNote: CreditNote;
|
||||
}
|
||||
|
||||
export interface IRefundCreditNoteOpenedPayload {
|
||||
creditNoteId: number;
|
||||
oldCreditNote: CreditNote;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
Reference in New Issue
Block a user