mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
refactor: wip to nestjs
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ERRORS } from '../constants';
|
||||
import { PaymentReceiveTransfromer } from './PaymentReceivedTransformer';
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
import { TransformerInjectable } from '../../Transformer/TransformerInjectable.service';
|
||||
import { ServiceError } from '../../Items/ServiceError';
|
||||
|
||||
@Injectable()
|
||||
export class GetPaymentReceived {
|
||||
constructor(
|
||||
private readonly paymentReceiveModel: typeof PaymentReceived,
|
||||
private readonly transformer: TransformerInjectable,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve payment receive details.
|
||||
* @param {number} paymentReceiveId - Payment receive id.
|
||||
* @return {Promise<IPaymentReceived>}
|
||||
*/
|
||||
public async getPaymentReceive(
|
||||
paymentReceiveId: number
|
||||
): Promise<PaymentReceived> {
|
||||
const paymentReceive = await this.paymentReceiveModel.query()
|
||||
.withGraphFetched('customer')
|
||||
.withGraphFetched('depositAccount')
|
||||
.withGraphFetched('entries.invoice')
|
||||
.withGraphFetched('transactions')
|
||||
.withGraphFetched('branch')
|
||||
.findById(paymentReceiveId);
|
||||
|
||||
if (!paymentReceive) {
|
||||
throw new ServiceError(ERRORS.PAYMENT_RECEIVE_NOT_EXISTS);
|
||||
}
|
||||
return this.transformer.transform(
|
||||
paymentReceive,
|
||||
new PaymentReceiveTransfromer()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { PaymentReceivedValidators } from '../commands/PaymentReceivedValidators.service';
|
||||
import { SaleInvoice } from '../../SaleInvoices/models/SaleInvoice';
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
|
||||
@Injectable()
|
||||
export class GetPaymentReceivedInvoices {
|
||||
constructor(
|
||||
@Inject(PaymentReceived.name)
|
||||
private paymentReceiveModel: typeof PaymentReceived,
|
||||
private validators: PaymentReceivedValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve sale invoices that associated to the given payment receive.
|
||||
* @param {number} paymentReceiveId - Payment receive id.
|
||||
* @return {Promise<ISaleInvoice>}
|
||||
*/
|
||||
public async getPaymentReceiveInvoices(paymentReceiveId: number) {
|
||||
const paymentReceive = await this.paymentReceiveModel
|
||||
.query()
|
||||
.findById(paymentReceiveId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Validates the payment receive existence.
|
||||
this.validators.validatePaymentExistance(paymentReceive);
|
||||
|
||||
const paymentReceiveInvoicesIds = paymentReceive.entries.map(
|
||||
(entry) => entry.invoiceId,
|
||||
);
|
||||
const saleInvoices = await SaleInvoice.query().whereIn(
|
||||
'id',
|
||||
paymentReceiveInvoicesIds,
|
||||
);
|
||||
return saleInvoices;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { GetPaymentReceived } from './GetPaymentReceived.service';
|
||||
import { PaymentReceivedBrandingTemplate } from './PaymentReceivedBrandingTemplate.service';
|
||||
import { transformPaymentReceivedToPdfTemplate } from '../utils';
|
||||
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
import { PdfTemplateModel } from '@/modules/PdfTemplate/models/PdfTemplate';
|
||||
import { ChromiumlyTenancy } from '@/modules/ChromiumlyTenancy/ChromiumlyTenancy.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { TemplateInjectable } from '@/modules/TemplateInjectable/TemplateInjectable.service';
|
||||
import { PaymentReceivedPdfTemplateAttributes } from '../types/PaymentReceived.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export default class GetPaymentReceivedPdf {
|
||||
constructor(
|
||||
private chromiumlyTenancy: ChromiumlyTenancy,
|
||||
private templateInjectable: TemplateInjectable,
|
||||
private getPaymentService: GetPaymentReceived,
|
||||
private paymentBrandingTemplateService: PaymentReceivedBrandingTemplate,
|
||||
private eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(PaymentReceived.name)
|
||||
private paymentReceiveModel: typeof PaymentReceived,
|
||||
|
||||
@Inject(PdfTemplateModel.name)
|
||||
private pdfTemplateModel: typeof PdfTemplateModel,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve sale invoice pdf content.
|
||||
* @param {number} tenantId -
|
||||
* @param {IPaymentReceived} paymentReceive -
|
||||
* @returns {Promise<Buffer>}
|
||||
*/
|
||||
async getPaymentReceivePdf(
|
||||
paymentReceivedId: number,
|
||||
): Promise<[Buffer, string]> {
|
||||
const brandingAttributes =
|
||||
await this.getPaymentBrandingAttributes(paymentReceivedId);
|
||||
|
||||
const htmlContent = await this.templateInjectable.render(
|
||||
'modules/payment-receive-standard',
|
||||
brandingAttributes,
|
||||
);
|
||||
const filename = await this.getPaymentReceivedFilename(paymentReceivedId);
|
||||
// Converts the given html content to pdf document.
|
||||
const content =
|
||||
await this.chromiumlyTenancy.convertHtmlContent(htmlContent);
|
||||
const eventPayload = { paymentReceivedId };
|
||||
|
||||
// Triggers the `onCreditNotePdfViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.paymentReceive.onPdfViewed,
|
||||
eventPayload,
|
||||
);
|
||||
return [content, filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the filename of the given payment.
|
||||
* @param {number} tenantId
|
||||
* @param {number} paymentReceivedId
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
private async getPaymentReceivedFilename(
|
||||
paymentReceivedId: number,
|
||||
): Promise<string> {
|
||||
const payment = await this.paymentReceiveModel
|
||||
.query()
|
||||
.findById(paymentReceivedId);
|
||||
|
||||
return `Payment-${payment.paymentReceiveNo}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the given payment received branding attributes.
|
||||
* @param {number} paymentReceivedId - Payment received identifier.
|
||||
* @returns {Promise<PaymentReceivedPdfTemplateAttributes>}
|
||||
*/
|
||||
async getPaymentBrandingAttributes(
|
||||
paymentReceivedId: number,
|
||||
): Promise<PaymentReceivedPdfTemplateAttributes> {
|
||||
const paymentReceived =
|
||||
await this.getPaymentService.getPaymentReceive(paymentReceivedId);
|
||||
|
||||
const templateId =
|
||||
paymentReceived?.pdfTemplateId ??
|
||||
(
|
||||
await this.pdfTemplateModel.query().findOne({
|
||||
resource: 'PaymentReceive',
|
||||
default: true,
|
||||
})
|
||||
)?.id;
|
||||
|
||||
const brandingTemplate =
|
||||
await this.paymentBrandingTemplateService.getPaymentReceivedPdfTemplate(
|
||||
templateId,
|
||||
);
|
||||
|
||||
return {
|
||||
...brandingTemplate.attributes,
|
||||
...transformPaymentReceivedToPdfTemplate(paymentReceived),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { PdfTemplateModel } from '@/modules/PdfTemplate/models/PdfTemplate';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IPaymentReceivedState } from '../types/PaymentReceived.types';
|
||||
|
||||
@Injectable()
|
||||
export class GetPaymentReceivedState {
|
||||
constructor(private pdfTemplateModel: typeof PdfTemplateModel) {}
|
||||
|
||||
/**
|
||||
* Retrieves the create/edit initial state of the payment received.
|
||||
* @returns {Promise<IPaymentReceivedState>} - A promise resolving to the payment received state.
|
||||
*/
|
||||
public async getPaymentReceivedState(): Promise<IPaymentReceivedState> {
|
||||
const defaultPdfTemplate = await this.pdfTemplateModel
|
||||
.query()
|
||||
.findOne({ resource: 'PaymentReceive' })
|
||||
.modify('default');
|
||||
|
||||
return {
|
||||
defaultTemplateId: defaultPdfTemplate?.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import * as R from 'ramda';
|
||||
// import {
|
||||
// IFilterMeta,
|
||||
// IPaginationMeta,
|
||||
// IPaymentReceived,
|
||||
// IPaymentsReceivedFilter,
|
||||
// } from '@/interfaces';
|
||||
// import { PaymentReceiveTransfromer } from './PaymentReceivedTransformer';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||
// import DynamicListingService from '@/services/DynamicListing/DynamicListService';
|
||||
|
||||
// @Service()
|
||||
// export class GetPaymentReceives {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
|
||||
// @Inject()
|
||||
// private dynamicListService: DynamicListingService;
|
||||
|
||||
// @Inject()
|
||||
// private transformer: TransformerInjectable;
|
||||
|
||||
// /**
|
||||
// * Retrieve payment receives paginated and filterable list.
|
||||
// * @param {number} tenantId
|
||||
// * @param {IPaymentsReceivedFilter} paymentReceivesFilter
|
||||
// */
|
||||
// public async getPaymentReceives(
|
||||
// tenantId: number,
|
||||
// filterDTO: IPaymentsReceivedFilter
|
||||
// ): Promise<{
|
||||
// paymentReceives: IPaymentReceived[];
|
||||
// pagination: IPaginationMeta;
|
||||
// filterMeta: IFilterMeta;
|
||||
// }> {
|
||||
// const { PaymentReceive } = this.tenancy.models(tenantId);
|
||||
|
||||
// // Parses filter DTO.
|
||||
// const filter = this.parseListFilterDTO(filterDTO);
|
||||
|
||||
// // Dynamic list service.
|
||||
// const dynamicList = await this.dynamicListService.dynamicList(
|
||||
// tenantId,
|
||||
// PaymentReceive,
|
||||
// filter
|
||||
// );
|
||||
// const { results, pagination } = await PaymentReceive.query()
|
||||
// .onBuild((builder) => {
|
||||
// builder.withGraphFetched('customer');
|
||||
// builder.withGraphFetched('depositAccount');
|
||||
|
||||
// dynamicList.buildQuery()(builder);
|
||||
// filterDTO?.filterQuery && filterDTO.filterQuery(builder);
|
||||
// })
|
||||
// .pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
// // Transformer the payment receives models to POJO.
|
||||
// const transformedPayments = await this.transformer.transform(
|
||||
// tenantId,
|
||||
// results,
|
||||
// new PaymentReceiveTransfromer()
|
||||
// );
|
||||
// return {
|
||||
// paymentReceives: transformedPayments,
|
||||
// pagination,
|
||||
// filterMeta: dynamicList.getResponseMeta(),
|
||||
// };
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Parses payments receive list filter DTO.
|
||||
// * @param filterDTO
|
||||
// */
|
||||
// private parseListFilterDTO(filterDTO) {
|
||||
// return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { defaultPaymentReceivedPdfTemplateAttributes } from '../constants';
|
||||
import { GetPdfTemplateService } from '../../PdfTemplate/queries/GetPdfTemplate.service';
|
||||
import { GetOrganizationBrandingAttributesService } from '../../PdfTemplate/queries/GetOrganizationBrandingAttributes.service';
|
||||
import { PdfTemplateModel } from '../../PdfTemplate/models/PdfTemplate';
|
||||
import { mergePdfTemplateWithDefaultAttributes } from '../../SaleInvoices/utils';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentReceivedBrandingTemplate {
|
||||
constructor(
|
||||
private readonly getPdfTemplateService: GetPdfTemplateService,
|
||||
private readonly getOrgBrandingAttributes: GetOrganizationBrandingAttributesService,
|
||||
|
||||
@Inject(PdfTemplateModel.name)
|
||||
private readonly pdfTemplateModel: typeof PdfTemplateModel,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves the payment received pdf template.
|
||||
* @param {number} paymentTemplateId
|
||||
* @returns
|
||||
*/
|
||||
public async getPaymentReceivedPdfTemplate(paymentTemplateId: number) {
|
||||
const template = await this.getPdfTemplateService.getPdfTemplate(
|
||||
paymentTemplateId
|
||||
);
|
||||
// Retrieves the organization branding attributes.
|
||||
const commonOrgBrandingAttrs =
|
||||
await this.getOrgBrandingAttributes.getOrganizationBrandingAttributes();
|
||||
|
||||
// Merges the default branding attributes with common organization branding attrs.
|
||||
const organizationBrandingAttrs = {
|
||||
...defaultPaymentReceivedPdfTemplateAttributes,
|
||||
...commonOrgBrandingAttrs,
|
||||
};
|
||||
const brandingTemplateAttrs = {
|
||||
...template.attributes,
|
||||
companyLogoUri: template.companyLogoUri,
|
||||
};
|
||||
const attributes = mergePdfTemplateWithDefaultAttributes(
|
||||
brandingTemplateAttrs,
|
||||
organizationBrandingAttrs
|
||||
);
|
||||
return {
|
||||
...template,
|
||||
attributes,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { SaleInvoiceTransformer } from "@/modules/SaleInvoices/queries/SaleInvoice.transformer";
|
||||
import { Transformer } from "@/modules/Transformer/Transformer";
|
||||
|
||||
|
||||
export class PaymentReceivedEntryTransfromer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to payment receive entry object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['paymentAmountFormatted', 'invoice'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retreives the payment amount formatted.
|
||||
* @param entry
|
||||
* @returns {string}
|
||||
*/
|
||||
protected paymentAmountFormatted(entry) {
|
||||
return this.formatNumber(entry.paymentAmount, { money: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives the transformed invoice.
|
||||
*/
|
||||
protected invoice(entry) {
|
||||
return this.item(entry.invoice, new SaleInvoiceTransformer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { Transformer } from '../../Transformer/Transformer';
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
import { PaymentReceivedEntry } from '../models/PaymentReceivedEntry';
|
||||
import { PaymentReceivedEntryTransfromer } from './PaymentReceivedEntryTransformer';
|
||||
|
||||
export class PaymentReceiveTransfromer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to payment receive object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return [
|
||||
'subtotalFormatted',
|
||||
'formattedPaymentDate',
|
||||
'formattedCreatedAt',
|
||||
'formattedAmount',
|
||||
'formattedExchangeRate',
|
||||
'entries',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted payment receive date.
|
||||
* @param {PaymentReceived} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedPaymentDate = (payment: PaymentReceived): string => {
|
||||
return this.formatDate(payment.paymentDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the formatted created at date.
|
||||
* @param {PaymentReceived} payment
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedCreatedAt = (payment: PaymentReceived): string => {
|
||||
return this.formatDate(payment.createdAt);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the formatted payment subtotal.
|
||||
* @param {PaymentReceived} payment
|
||||
* @returns {string}
|
||||
*/
|
||||
protected subtotalFormatted = (payment: PaymentReceived): string => {
|
||||
return this.formatNumber(payment.amount, {
|
||||
currencyCode: payment.currencyCode,
|
||||
money: false,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted payment amount.
|
||||
* @param {PaymentReceived} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (payment: PaymentReceived): string => {
|
||||
return this.formatNumber(payment.amount, {
|
||||
currencyCode: payment.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the formatted exchange rate.
|
||||
* @param {PaymentReceived} payment
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedExchangeRate = (payment: PaymentReceived): string => {
|
||||
return this.formatNumber(payment.exchangeRate, { money: false });
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the payment entries.
|
||||
* @param {PaymentReceived} payment
|
||||
* @returns {IPaymentReceivedEntry[]}
|
||||
*/
|
||||
protected entries = (payment: PaymentReceived): PaymentReceivedEntry[] => {
|
||||
return this.item(payment.entries, new PaymentReceivedEntryTransfromer());
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { omit } from 'lodash';
|
||||
import { IPaymentReceivePageEntry } from '../types/PaymentReceived.types';
|
||||
import { ERRORS } from '../constants';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
|
||||
/**
|
||||
* Payment receives edit/new pages service.
|
||||
*/
|
||||
@Injectable()
|
||||
export class PaymentsReceivedPagesService {
|
||||
constructor(
|
||||
@Inject(SaleInvoice.name)
|
||||
private readonly saleInvoice: typeof SaleInvoice,
|
||||
|
||||
@Inject(PaymentReceived.name)
|
||||
private readonly paymentReceived: typeof PaymentReceived,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrive page invoices entries from the given sale invoices models.
|
||||
* @param {ISaleInvoice[]} invoices - Invoices.
|
||||
* @return {IPaymentReceivePageEntry}
|
||||
*/
|
||||
private invoiceToPageEntry(invoice: SaleInvoice): IPaymentReceivePageEntry {
|
||||
return {
|
||||
entryType: 'invoice',
|
||||
invoiceId: invoice.id,
|
||||
invoiceNo: invoice.invoiceNo,
|
||||
amount: invoice.balance,
|
||||
dueAmount: invoice.dueAmount,
|
||||
paymentAmount: invoice.paymentAmount,
|
||||
totalPaymentAmount: invoice.paymentAmount,
|
||||
currencyCode: invoice.currencyCode,
|
||||
date: invoice.invoiceDate,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve payment receive new page receivable entries.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} vendorId - Vendor id.
|
||||
* @return {IPaymentReceivePageEntry[]}
|
||||
*/
|
||||
public async getNewPageEntries(tenantId: number, customerId: number) {
|
||||
// Retrieve due invoices.
|
||||
const entries = await this.saleInvoice
|
||||
.query()
|
||||
.modify('delivered')
|
||||
.modify('dueInvoices')
|
||||
.where('customer_id', customerId)
|
||||
.orderBy('invoice_date', 'ASC');
|
||||
|
||||
return entries.map(this.invoiceToPageEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the payment receive details of the given id.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {Integer} paymentReceiveId - Payment receive id.
|
||||
*/
|
||||
public async getPaymentReceiveEditPage(
|
||||
tenantId: number,
|
||||
paymentReceiveId: number,
|
||||
): Promise<{
|
||||
paymentReceive: Omit<PaymentReceived, 'entries'>;
|
||||
entries: IPaymentReceivePageEntry[];
|
||||
}> {
|
||||
// Retrieve payment receive.
|
||||
const paymentReceive = await this.paymentReceived
|
||||
.query()
|
||||
.findById(paymentReceiveId)
|
||||
.withGraphFetched('entries.invoice')
|
||||
.withGraphFetched('attachments');
|
||||
|
||||
// Throw not found the payment receive.
|
||||
if (!paymentReceive) {
|
||||
throw new ServiceError(ERRORS.PAYMENT_RECEIVE_NOT_EXISTS);
|
||||
}
|
||||
const paymentEntries = paymentReceive.entries.map((entry) => ({
|
||||
...this.invoiceToPageEntry(entry.invoice),
|
||||
dueAmount: entry.invoice.dueAmount + entry.paymentAmount,
|
||||
paymentAmount: entry.paymentAmount,
|
||||
index: entry.index,
|
||||
}));
|
||||
// Retrieves all receivable bills that associated to the payment receive transaction.
|
||||
const restReceivableInvoices = await this.saleInvoice
|
||||
.query()
|
||||
.modify('delivered')
|
||||
.modify('dueInvoices')
|
||||
.where('customer_id', paymentReceive.customerId)
|
||||
.whereNotIn(
|
||||
'id',
|
||||
paymentReceive.entries.map((entry) => entry.invoiceId),
|
||||
)
|
||||
.orderBy('invoice_date', 'ASC');
|
||||
|
||||
const restReceivableEntries = restReceivableInvoices.map(
|
||||
this.invoiceToPageEntry,
|
||||
);
|
||||
const entries = [...paymentEntries, ...restReceivableEntries];
|
||||
|
||||
return {
|
||||
paymentReceive: omit(paymentReceive, ['entries']),
|
||||
entries,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user