mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
refactor: migrate credit note and vendor credit services to nestjs
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
import { Module } from "@nestjs/common";
|
||||
import { ApplyVendorCreditSyncBillsService } from "./command/ApplyVendorCreditSyncBills.service";
|
||||
import { ApplyVendorCreditSyncInvoicedService } from "./command/ApplyVendorCreditSyncInvoiced.service";
|
||||
import { DeleteApplyVendorCreditToBillService } from "./command/DeleteApplyVendorCreditToBill.service";
|
||||
import { ApplyVendorCreditToBillsService } from "./command/ApplyVendorCreditToBills.service";
|
||||
import { GetAppliedBillsToVendorCreditService } from "./queries/GetAppliedBillsToVendorCredit.service";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ApplyVendorCreditSyncBillsService,
|
||||
ApplyVendorCreditSyncInvoicedService,
|
||||
ApplyVendorCreditToBillsService,
|
||||
DeleteApplyVendorCreditToBillService,
|
||||
GetAppliedBillsToVendorCreditService
|
||||
],
|
||||
controllers: [],
|
||||
})
|
||||
export class VendorCreditApplyBillsModule {}
|
||||
@@ -0,0 +1,12 @@
|
||||
export const ERRORS = {
|
||||
VENDOR_CREDIT_NOT_FOUND: 'VENDOR_CREDIT_NOT_FOUND',
|
||||
VENDOR_CREDIT_ALREADY_OPENED: 'VENDOR_CREDIT_ALREADY_OPENED',
|
||||
VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT:
|
||||
'VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT',
|
||||
VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND:
|
||||
'VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND',
|
||||
BILLS_HAS_NO_REMAINING_AMOUNT: 'BILLS_HAS_NO_REMAINING_AMOUNT',
|
||||
VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS:
|
||||
'VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS',
|
||||
VENDOR_CREDIT_HAS_APPLIED_BILLS: 'VENDOR_CREDIT_HAS_APPLIED_BILLS',
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import Bluebird from 'bluebird';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { IVendorCreditAppliedBill } from '../types/VendorCreditApplyBills.types';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
|
||||
@Injectable()
|
||||
export class ApplyVendorCreditSyncBillsService {
|
||||
constructor(
|
||||
@Inject(Bill.name)
|
||||
private readonly billModel: typeof Bill,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Increment bills credited amount.
|
||||
* @param {IVendorCreditAppliedBill[]} vendorCreditAppliedBills
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public incrementBillsCreditedAmount = async (
|
||||
vendorCreditAppliedBills: IVendorCreditAppliedBill[],
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
await Bluebird.each(
|
||||
vendorCreditAppliedBills,
|
||||
(vendorCreditAppliedBill: IVendorCreditAppliedBill) => {
|
||||
return this.billModel
|
||||
.query(trx)
|
||||
.where('id', vendorCreditAppliedBill.billId)
|
||||
.increment('creditedAmount', vendorCreditAppliedBill.amount);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrement bill credited amount.
|
||||
* @param {IVendorCreditAppliedBill} vendorCreditAppliedBill
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public decrementBillCreditedAmount = async (
|
||||
vendorCreditAppliedBill: IVendorCreditAppliedBill,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
await this.billModel
|
||||
.query(trx)
|
||||
.findById(vendorCreditAppliedBill.billId)
|
||||
.decrement('creditedAmount', vendorCreditAppliedBill.amount);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
|
||||
@Injectable()
|
||||
export class ApplyVendorCreditSyncInvoicedService {
|
||||
constructor(
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: typeof VendorCredit,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Increment vendor credit invoiced amount.
|
||||
* @param {number} vendorCreditId - Vendor credit id.
|
||||
* @param {number} amount - Amount to increment.
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
*/
|
||||
public incrementVendorCreditInvoicedAmount = async (
|
||||
vendorCreditId: number,
|
||||
amount: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
await this.vendorCreditModel.query(trx)
|
||||
.findById(vendorCreditId)
|
||||
.increment('invoicedAmount', amount);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrement credit note invoiced amount.
|
||||
* @param {number} vendorCreditId - Vendor credit id.
|
||||
* @param {number} amount - Amount to decrement.
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
*/
|
||||
public decrementVendorCreditInvoicedAmount = async (
|
||||
vendorCreditId: number,
|
||||
amount: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
await this.vendorCreditModel.query(trx)
|
||||
.findById(vendorCreditId)
|
||||
.decrement('invoicedAmount', amount);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { sumBy } from 'lodash';
|
||||
import {
|
||||
IVendorCreditApplyToBillsCreatedPayload,
|
||||
IVendorCreditApplyToInvoicesDTO,
|
||||
IVendorCreditApplyToInvoicesModel,
|
||||
} from '../types/VendorCreditApplyBills.types';
|
||||
import { ERRORS } from '../VendorCreditsApplyBills.constants';
|
||||
import { VendorCreditAppliedBill } from '../models/VendorCreditAppliedBill';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
import { BillPaymentValidators } from '@/modules/BillPayments/commands/BillPaymentValidators.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
|
||||
@Injectable()
|
||||
export class ApplyVendorCreditToBillsService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - The unit of work service.
|
||||
* @param {EventEmitter2} eventPublisher - The event emitter service.
|
||||
* @param {BillPaymentValidators} billPaymentValidators - The bill payment validators service.
|
||||
* @param {typeof VendorCreditAppliedBill} vendorCreditAppliedBillModel - The vendor credit applied bill model.
|
||||
* @param {typeof VendorCredit} vendorCreditModel - The vendor credit model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly billPaymentValidators: BillPaymentValidators,
|
||||
private readonly vendorCreditAppliedBillModel: typeof VendorCreditAppliedBill,
|
||||
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: typeof VendorCredit,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Apply credit note to the given invoices.
|
||||
* @param {number} creditNoteId
|
||||
* @param {IApplyCreditToInvoicesDTO} applyCreditToInvoicesDTO
|
||||
*/
|
||||
public applyVendorCreditToBills = async (
|
||||
vendorCreditId: number,
|
||||
applyCreditToBillsDTO: IVendorCreditApplyToInvoicesDTO,
|
||||
): Promise<void> => {
|
||||
// Retrieves the vendor credit or throw not found service error.
|
||||
const vendorCredit = await this.vendorCreditModel
|
||||
.query()
|
||||
.findById(vendorCreditId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Transfomes credit apply to bills DTO to model object.
|
||||
const vendorCreditAppliedModel = this.transformApplyDTOToModel(
|
||||
applyCreditToBillsDTO,
|
||||
vendorCredit,
|
||||
);
|
||||
|
||||
// Validate bills entries existance.
|
||||
const appliedBills =
|
||||
await this.billPaymentValidators.validateBillsExistance(
|
||||
vendorCreditAppliedModel.entries,
|
||||
vendorCredit.vendorId,
|
||||
);
|
||||
|
||||
// Validate bills has remaining amount to apply.
|
||||
this.validateBillsRemainingAmount(
|
||||
appliedBills,
|
||||
vendorCreditAppliedModel.amount,
|
||||
);
|
||||
// Validate vendor credit remaining credit amount.
|
||||
this.validateCreditRemainingAmount(
|
||||
vendorCredit,
|
||||
vendorCreditAppliedModel.amount,
|
||||
);
|
||||
|
||||
// Saves vendor credit applied to bills under unit-of-work envirement.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Inserts vendor credit applied to bills graph to the storage layer.
|
||||
const vendorCreditAppliedBills = await this.vendorCreditAppliedBillModel
|
||||
.query(trx)
|
||||
.insertGraph(vendorCreditAppliedModel.entries);
|
||||
|
||||
// Triggers `IVendorCreditApplyToBillsCreatedPayload` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.vendorCredit.onApplyToInvoicesCreated,
|
||||
{
|
||||
trx,
|
||||
vendorCredit,
|
||||
vendorCreditAppliedBills,
|
||||
} as IVendorCreditApplyToBillsCreatedPayload,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes apply DTO to model.
|
||||
* @param {IApplyCreditToInvoicesDTO} applyDTO
|
||||
* @param {ICreditNote} creditNote
|
||||
* @returns {IVendorCreditApplyToInvoicesModel}
|
||||
*/
|
||||
private transformApplyDTOToModel = (
|
||||
applyDTO: IVendorCreditApplyToInvoicesDTO,
|
||||
vendorCredit: VendorCredit,
|
||||
): IVendorCreditApplyToInvoicesModel => {
|
||||
const entries = applyDTO.entries.map((entry) => ({
|
||||
billId: entry.billId,
|
||||
amount: entry.amount,
|
||||
vendorCreditId: vendorCredit.id,
|
||||
}));
|
||||
const amount = sumBy(applyDTO.entries, 'amount');
|
||||
|
||||
return {
|
||||
amount,
|
||||
entries,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate bills remaining amount.
|
||||
* @param {IBill[]} bills
|
||||
* @param {number} amount
|
||||
*/
|
||||
private validateBillsRemainingAmount = (bills: Bill[], amount: number) => {
|
||||
const invalidBills = bills.filter((bill) => bill.dueAmount < amount);
|
||||
if (invalidBills.length > 0) {
|
||||
throw new ServiceError(ERRORS.BILLS_HAS_NO_REMAINING_AMOUNT);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IVendorCreditApplyToBillDeletedPayload } from '../types/VendorCreditApplyBills.types';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
import { ERRORS } from '../VendorCreditsApplyBills.constants';
|
||||
import { VendorCreditAppliedBill } from '../models/VendorCreditAppliedBill';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteApplyVendorCreditToBillService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - The unit of work service.
|
||||
* @param {EventEmitter2} eventPublisher - The event emitter service.
|
||||
* @param {typeof VendorCreditAppliedBill} vendorCreditAppliedBillModel - The vendor credit applied bill model.
|
||||
* @param {typeof VendorCredit} vendorCreditModel - The vendor credit model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly vendorCreditAppliedBillModel: typeof VendorCreditAppliedBill,
|
||||
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: typeof VendorCredit,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Delete apply vendor credit to bill transaction.
|
||||
* @param {number} appliedCreditToBillId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async deleteApplyVendorCreditToBills(appliedCreditToBillId: number) {
|
||||
const oldCreditAppliedToBill = await this.vendorCreditAppliedBillModel
|
||||
.query()
|
||||
.findById(appliedCreditToBillId);
|
||||
|
||||
if (!oldCreditAppliedToBill) {
|
||||
throw new ServiceError(ERRORS.VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND);
|
||||
}
|
||||
// Retrieve the vendor credit or throw not found service error.
|
||||
const vendorCredit = await this.vendorCreditModel
|
||||
.query()
|
||||
.findById(oldCreditAppliedToBill.vendorCreditId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Deletes vendor credit apply under unit-of-work environment.
|
||||
return this.uow.withTransaction(async (trx) => {
|
||||
// Delete vendor credit applied to bill transaction.
|
||||
await this.vendorCreditAppliedBillModel
|
||||
.query(trx)
|
||||
.findById(appliedCreditToBillId)
|
||||
.delete();
|
||||
|
||||
// Triggers `onVendorCreditApplyToInvoiceDeleted` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.vendorCredit.onApplyToInvoicesDeleted,
|
||||
{
|
||||
vendorCredit,
|
||||
oldCreditAppliedToBill,
|
||||
trx,
|
||||
} as IVendorCreditApplyToBillDeletedPayload,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Model } from 'objection';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import ModelSetting from './ModelSetting';
|
||||
// import CustomViewBaseModel from './CustomViewBaseModel';
|
||||
// import ModelSearchable from './ModelSearchable';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
import { VendorCredit } from '../../VendorCredit/models/VendorCredit';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
|
||||
export class VendorCreditAppliedBill extends BaseModel {
|
||||
public amount!: number;
|
||||
public billId!: number;
|
||||
public vendorCreditId!: number;
|
||||
|
||||
public vendorCredit!: VendorCredit;
|
||||
public bill!: Bill;
|
||||
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'vendor_credit_applied_bill';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
public get timestamps() {
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { Bill } = require('../../Bills/models/Bill');
|
||||
const { VendorCredit } = require('../../VendorCredit/models/VendorCredit');
|
||||
|
||||
return {
|
||||
bill: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Bill,
|
||||
join: {
|
||||
from: 'vendor_credit_applied_bill.billId',
|
||||
to: 'bills.id',
|
||||
},
|
||||
},
|
||||
|
||||
vendorCredit: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: VendorCredit,
|
||||
join: {
|
||||
from: 'vendor_credit_applied_bill.vendorCreditId',
|
||||
to: 'vendor_credits.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { VendorCreditAppliedBillTransformer } from './VendorCreditAppliedBillTransformer';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { VendorCreditAppliedBill } from '@/modules/VendorCreditsApplyBills/models/VendorCreditAppliedBill';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
|
||||
@Injectable()
|
||||
export class GetAppliedBillsToVendorCreditService {
|
||||
constructor(
|
||||
private readonly transformer: TransformerInjectable,
|
||||
private readonly vendorCreditAppliedBillModel: typeof VendorCreditAppliedBill,
|
||||
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: typeof VendorCredit,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get applied bills to vendor credit.
|
||||
* @param {number} vendorCreditId
|
||||
* @returns
|
||||
*/
|
||||
public getAppliedBills = async (vendorCreditId: number) => {
|
||||
const vendorCredit = await this.vendorCreditModel
|
||||
.query()
|
||||
.findById(vendorCreditId)
|
||||
.throwIfNotFound();
|
||||
|
||||
const appliedToBills = await this.vendorCreditAppliedBillModel
|
||||
.query()
|
||||
.where('vendorCreditId', vendorCreditId)
|
||||
.withGraphFetched('bill')
|
||||
.withGraphFetched('vendorCredit');
|
||||
|
||||
// Transforms the models to POJO.
|
||||
return this.transformer.transform(
|
||||
appliedToBills,
|
||||
new VendorCreditAppliedBillTransformer(),
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { VendorCreditToApplyBillTransformer } from './VendorCreditToApplyBillTransformer';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
|
||||
@Injectable()
|
||||
export class GetVendorCreditToApplyBills {
|
||||
/**
|
||||
* @param {TransformerService} transformerService - The transformer service.
|
||||
* @param {typeof Bill} billModel - The bill model.
|
||||
* @param {typeof VendorCredit} vendorCreditModel - The vendor credit model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly transformerService: TransformerInjectable,
|
||||
@Inject(Bill.name) private readonly billModel: typeof Bill,
|
||||
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: typeof VendorCredit,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve bills that valid apply to the given vendor credit.
|
||||
* @param {number} vendorCreditId
|
||||
* @returns {Promise<any[]>}
|
||||
*/
|
||||
public async getCreditToApplyBills(vendorCreditId: number) {
|
||||
// Retrieve vendor credit or throw not found service error.
|
||||
const vendorCredit = await this.vendorCreditModel
|
||||
.query()
|
||||
.findById(vendorCreditId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Retrieve open bills associated to the given vendor.
|
||||
const openBills = await this.billModel
|
||||
.query()
|
||||
.where('vendor_id', vendorCredit.vendorId)
|
||||
.modify('dueBills')
|
||||
.modify('published');
|
||||
|
||||
// Transform the bills to POJO.
|
||||
return this.transformerService.transform(
|
||||
openBills,
|
||||
new VendorCreditToApplyBillTransformer(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Transformer } from "@/modules/Transformer/Transformer";
|
||||
import { VendorCreditAppliedBill } from "@/modules/VendorCreditsApplyBills/models/VendorCreditAppliedBill";
|
||||
|
||||
export class VendorCreditAppliedBillTransformer extends Transformer {
|
||||
/**
|
||||
* Includeded attributes.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return [
|
||||
'formattedAmount',
|
||||
'vendorCreditNumber',
|
||||
'vendorCreditDate',
|
||||
'billNumber',
|
||||
'billReferenceNo',
|
||||
'formattedVendorCreditDate',
|
||||
'formattedBillDate',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Exclude attributes.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['bill', 'vendorCredit'];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param item
|
||||
* @returns
|
||||
*/
|
||||
protected formattedAmount = (item: VendorCreditAppliedBill) => {
|
||||
return this.formatNumber(item.amount, {
|
||||
currencyCode: item.vendorCredit.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
protected vendorCreditNumber = (item) => {
|
||||
return item.vendorCredit.vendorCreditNumber;
|
||||
};
|
||||
|
||||
protected vendorCreditDate = (item) => {
|
||||
return item.vendorCredit.vendorCreditDate;
|
||||
};
|
||||
|
||||
protected formattedVendorCreditDate = (item) => {
|
||||
return this.formatDate(item.vendorCredit.vendorCreditDate);
|
||||
};
|
||||
|
||||
protected billNumber = (item) => {
|
||||
return item.bill.billNo;
|
||||
};
|
||||
|
||||
protected billReferenceNo = (item) => {
|
||||
return item.bill.referenceNo;
|
||||
};
|
||||
|
||||
protected BillDate = (item) => {
|
||||
return item.bill.billDate;
|
||||
};
|
||||
|
||||
protected formattedBillDate = (item) => {
|
||||
return this.formatDate(item.bill.billDate);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||
|
||||
export class VendorCreditToApplyBillTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return [
|
||||
'formattedBillDate',
|
||||
'formattedDueDate',
|
||||
'formattedAmount',
|
||||
'formattedDueAmount',
|
||||
'formattedPaymentAmount',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill date.
|
||||
* @param {Bill} bill
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedBillDate = (bill: Bill): string => {
|
||||
return this.formatDate(bill.billDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted due date.
|
||||
* @param {Bill} bill
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedDueDate = (bill: Bill): string => {
|
||||
return this.formatDate(bill.dueDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill amount.
|
||||
* @param {Bill} bill
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (bill: Bill): string => {
|
||||
return this.formatNumber(bill.amount, {
|
||||
currencyCode: bill.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill due amount.
|
||||
* @param {Bill} bill
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedDueAmount = (bill: Bill): string => {
|
||||
return this.formatNumber(bill.dueAmount, {
|
||||
currencyCode: bill.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted payment amount.
|
||||
* @param {Bill} bill
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedPaymentAmount = (bill: Bill): string => {
|
||||
return this.formatNumber(bill.paymentAmount, {
|
||||
currencyCode: bill.currencyCode,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/objection';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IVendorCreditApplyToBillDeletedPayload,
|
||||
IVendorCreditApplyToBillsCreatedPayload,
|
||||
} from '@/interfaces';
|
||||
import { ApplyVendorCreditSyncBillsService } from '../command/ApplyVendorCreditSyncBills.service';
|
||||
import { VendorCreditApplyToBill } from '../models/VendorCreditApplyToBill';
|
||||
|
||||
@Injectable()
|
||||
export default class ApplyVendorCreditSyncBillsSubscriber {
|
||||
constructor(
|
||||
private readonly syncBillsWithVendorCredit: ApplyVendorCreditSyncBillsService,
|
||||
@InjectModel(VendorCreditApplyToBill)
|
||||
private readonly vendorCreditApplyToBillModel: typeof VendorCreditApplyToBill,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Attaches events with handlers.
|
||||
*/
|
||||
attach(bus) {
|
||||
bus.subscribe(
|
||||
events.vendorCredit.onApplyToInvoicesCreated,
|
||||
this.incrementAppliedBillsOnceCreditCreated
|
||||
);
|
||||
bus.subscribe(
|
||||
events.vendorCredit.onApplyToInvoicesDeleted,
|
||||
this.decrementAppliedBillsOnceCreditDeleted
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment credited amount of applied bills once the vendor credit transaction created.
|
||||
* @param {IVendorCreditApplyToBillsCreatedPayload} paylaod -
|
||||
*/
|
||||
private incrementAppliedBillsOnceCreditCreated = async ({
|
||||
vendorCreditAppliedBills,
|
||||
trx,
|
||||
}: IVendorCreditApplyToBillsCreatedPayload) => {
|
||||
await this.syncBillsWithVendorCredit.incrementBillsCreditedAmount(
|
||||
vendorCreditAppliedBills,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrement credited amount of applied bills once the vendor credit
|
||||
* transaction delted.
|
||||
* @param {IVendorCreditApplyToBillDeletedPayload} payload
|
||||
*/
|
||||
private decrementAppliedBillsOnceCreditDeleted = async ({
|
||||
oldCreditAppliedToBill,
|
||||
trx,
|
||||
}: IVendorCreditApplyToBillDeletedPayload) => {
|
||||
await this.syncBillsWithVendorCredit.decrementBillCreditedAmount(
|
||||
oldCreditAppliedToBill,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { sumBy } from 'lodash';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import ApplyVendorCreditSyncInvoiced from '../command/ApplyVendorCreditSyncInvoiced.service';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IVendorCreditApplyToBillDeletedPayload,
|
||||
IVendorCreditApplyToBillsCreatedPayload,
|
||||
} from '@/interfaces';
|
||||
|
||||
@Service()
|
||||
export default class ApplyVendorCreditSyncInvoicedSubscriber {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
syncCreditWithInvoiced: ApplyVendorCreditSyncInvoiced;
|
||||
|
||||
/**
|
||||
* Attaches events with handlers.
|
||||
*/
|
||||
attach(bus) {
|
||||
bus.subscribe(
|
||||
events.vendorCredit.onApplyToInvoicesCreated,
|
||||
this.incrementBillInvoicedOnceCreditApplied
|
||||
);
|
||||
bus.subscribe(
|
||||
events.vendorCredit.onApplyToInvoicesDeleted,
|
||||
this.decrementBillInvoicedOnceCreditApplyDeleted
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment vendor credit invoiced amount once the apply transaction created.
|
||||
* @param {IVendorCreditApplyToBillsCreatedPayload} payload -
|
||||
*/
|
||||
private incrementBillInvoicedOnceCreditApplied = async ({
|
||||
vendorCredit,
|
||||
tenantId,
|
||||
vendorCreditAppliedBills,
|
||||
trx,
|
||||
}: IVendorCreditApplyToBillsCreatedPayload) => {
|
||||
const amount = sumBy(vendorCreditAppliedBills, 'amount');
|
||||
|
||||
await this.syncCreditWithInvoiced.incrementVendorCreditInvoicedAmount(
|
||||
tenantId,
|
||||
vendorCredit.id,
|
||||
amount,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrement vendor credit invoiced amount once the apply transaction deleted.
|
||||
* @param {IVendorCreditApplyToBillDeletedPayload} payload -
|
||||
*/
|
||||
private decrementBillInvoicedOnceCreditApplyDeleted = async ({
|
||||
tenantId,
|
||||
vendorCredit,
|
||||
oldCreditAppliedToBill,
|
||||
trx,
|
||||
}: IVendorCreditApplyToBillDeletedPayload) => {
|
||||
await this.syncCreditWithInvoiced.decrementVendorCreditInvoicedAmount(
|
||||
tenantId,
|
||||
oldCreditAppliedToBill.vendorCreditId,
|
||||
oldCreditAppliedToBill.amount,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Knex } from 'knex';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
|
||||
export interface IVendorCreditApplyToBillsCreatedPayload {
|
||||
vendorCredit: VendorCredit;
|
||||
vendorCreditAppliedBills: IVendorCreditAppliedBill[];
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToBillsCreatingPayload {
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToBillsCreatePayload {
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToBillDeletedPayload {
|
||||
vendorCredit: VendorCredit;
|
||||
oldCreditAppliedToBill: IVendorCreditAppliedBill;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToInvoiceDTO {
|
||||
amount: number;
|
||||
billId: number;
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToInvoicesDTO {
|
||||
entries: IVendorCreditApplyToInvoiceDTO[];
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToInvoiceModel {
|
||||
billId: number;
|
||||
amount: number;
|
||||
vendorCreditId: number;
|
||||
}
|
||||
|
||||
export interface IVendorCreditApplyToInvoicesModel {
|
||||
entries: IVendorCreditApplyToInvoiceModel[];
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export interface IVendorCreditAppliedBill {
|
||||
billId: number;
|
||||
amount: number;
|
||||
vendorCreditId: number;
|
||||
}
|
||||
Reference in New Issue
Block a user