feat: invoice, estimate and receipt printing.

This commit is contained in:
a.bouhuolia
2021-08-17 10:47:04 +02:00
parent 70939c5741
commit 160b8b6a1b
50 changed files with 3607 additions and 120 deletions

View File

@@ -111,8 +111,6 @@ export default class BaseController {
return response;
}
/**
* Async middleware.
* @param {function} callback
@@ -129,4 +127,14 @@ export default class BaseController {
protected accepts(req) {
return accepts(req);
}
/**
*
* @param {Request} req
* @param {string[]} types
* @returns {string}
*/
protected acceptTypes(req: Request, types: string[]) {
return this.accepts(req).types(types);
}
}

View File

@@ -165,11 +165,12 @@ export default class PaymentReceivesController extends BaseController {
const paymentReceive: IPaymentReceiveDTO = this.matchedBodyData(req);
try {
const storedPaymentReceive = await this.paymentReceiveService.createPaymentReceive(
tenantId,
paymentReceive,
user
);
const storedPaymentReceive =
await this.paymentReceiveService.createPaymentReceive(
tenantId,
paymentReceive,
user
);
return res.status(200).send({
id: storedPaymentReceive.id,
message: 'The payment receive has been created successfully.',
@@ -247,11 +248,13 @@ export default class PaymentReceivesController extends BaseController {
const { id: paymentReceiveId } = req.params;
try {
const invoices = await this.paymentReceiveService.getPaymentReceiveInvoices(
tenantId,
paymentReceiveId
);
return res.status(200).send({ sale_invoices: invoices });
const saleInvoices =
await this.paymentReceiveService.getPaymentReceiveInvoices(
tenantId,
paymentReceiveId
);
return res.status(200).send(this.transfromToResponse({ saleInvoices }));
} catch (error) {
next(error);
}
@@ -274,17 +277,11 @@ export default class PaymentReceivesController extends BaseController {
};
try {
const {
paymentReceives,
pagination,
filterMeta,
} = await this.paymentReceiveService.listPaymentReceives(
tenantId,
filter
);
const { paymentReceives, pagination, filterMeta } =
await this.paymentReceiveService.listPaymentReceives(tenantId, filter);
return res.status(200).send({
payment_receives: paymentReceives,
payment_receives: this.transfromToResponse(paymentReceives),
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});
@@ -334,14 +331,12 @@ export default class PaymentReceivesController extends BaseController {
const { id: paymentReceiveId } = req.params;
try {
const {
paymentReceive,
entries,
} = await this.PaymentReceivesPages.getPaymentReceiveEditPage(
tenantId,
paymentReceiveId,
user
);
const { paymentReceive, entries } =
await this.PaymentReceivesPages.getPaymentReceiveEditPage(
tenantId,
paymentReceiveId,
user
);
return res.status(200).send({
payment_receive: this.transfromToResponse({ ...paymentReceive }),
@@ -442,9 +437,10 @@ export default class PaymentReceivesController extends BaseController {
type: 'INVOICES_NOT_DELIVERED_YET',
code: 200,
data: {
not_delivered_invoices_ids: error.payload.notDeliveredInvoices.map(
(invoice) => invoice.id
),
not_delivered_invoices_ids:
error.payload.notDeliveredInvoices.map(
(invoice) => invoice.id
),
},
},
],

View File

@@ -7,7 +7,12 @@ import asyncMiddleware from 'api/middleware/asyncMiddleware';
import SaleEstimateService from 'services/Sales/SalesEstimate';
import DynamicListingService from 'services/DynamicListing/DynamicListService';
import { ServiceError } from 'exceptions';
import SaleEstimatesPdfService from 'services/Sales/Estimates/SaleEstimatesPdf';
const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf',
APPLICATION_JSON: 'application/json',
};
@Service()
export default class SalesEstimatesController extends BaseController {
@Inject()
@@ -16,6 +21,9 @@ export default class SalesEstimatesController extends BaseController {
@Inject()
dynamicListService: DynamicListingService;
@Inject()
saleEstimatesPdf: SaleEstimatesPdfService;
/**
* Router constructor.
*/
@@ -135,7 +143,7 @@ export default class SalesEstimatesController extends BaseController {
query('sort_order').optional().isIn(['desc', 'asc']),
query('page').optional().isNumeric().toInt(),
query('page_size').optional().isNumeric().toInt(),
query('search_keyword').optional({ nullable: true }).isString().trim()
query('search_keyword').optional({ nullable: true }).isString().trim(),
];
}
@@ -292,8 +300,25 @@ export default class SalesEstimatesController extends BaseController {
tenantId,
estimateId
);
return res.status(200).send({ estimate });
// Response formatter.
res.format({
// PDF content type.
[ACCEPT_TYPE.APPLICATION_PDF]: async () => {
const pdfContent = await this.saleEstimatesPdf.saleEstimatePdf(
tenantId,
estimate
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
},
// JSON content type.
default: () => {
return res.status(200).send(this.transfromToResponse({ estimate }));
},
});
} catch (error) {
next(error);
}
@@ -318,10 +343,16 @@ export default class SalesEstimatesController extends BaseController {
const { salesEstimates, pagination, filterMeta } =
await this.saleEstimateService.estimatesList(tenantId, filter);
return res.status(200).send({
sales_estimates: this.transfromToResponse(salesEstimates),
pagination,
filter_meta: this.transfromToResponse(filterMeta),
res.format({
[ACCEPT_TYPE.APPLICATION_JSON]: () => {
return res.status(200).send(
this.transfromToResponse({
salesEstimates,
pagination,
filterMeta,
})
);
},
});
} catch (error) {
next(error);

View File

@@ -8,7 +8,12 @@ import ItemsService from 'services/Items/ItemsService';
import DynamicListingService from 'services/DynamicListing/DynamicListService';
import { ServiceError } from 'exceptions';
import { ISaleInvoiceDTO, ISaleInvoiceCreateDTO } from 'interfaces';
import SaleInvoicePdf from 'services/Sales/SaleInvoicePdf';
const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf',
APPLICATION_JSON: 'application/json',
};
@Service()
export default class SaleInvoicesController extends BaseController {
@Inject()
@@ -20,6 +25,9 @@ export default class SaleInvoicesController extends BaseController {
@Inject()
dynamicListService: DynamicListingService;
@Inject()
saleInvoicePdf: SaleInvoicePdf;
/**
* Router constructor.
*/
@@ -254,8 +262,8 @@ export default class SaleInvoicesController extends BaseController {
/**
* Retrieve the sale invoice with associated entries.
* @param {Request} req
* @param {Response} res
* @param {Request} req - Request object.
* @param {Response} res - Response object.
*/
async getSaleInvoice(req: Request, res: Response, next: NextFunction) {
const { id: saleInvoiceId } = req.params;
@@ -267,7 +275,25 @@ export default class SaleInvoicesController extends BaseController {
saleInvoiceId,
user
);
return res.status(200).send({ sale_invoice: saleInvoice });
// Response formatter.
res.format({
// PDF content type.
[ACCEPT_TYPE.APPLICATION_PDF]: async () => {
const pdfContent = await this.saleInvoicePdf.saleInvoicePdf(
tenantId,
saleInvoice
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
},
// JSON content type.
[ACCEPT_TYPE.APPLICATION_JSON]: () => {
return res.status(200).send(this.transfromToResponse({ saleInvoice }));
},
});
} catch (error) {
next(error);
}
@@ -296,7 +322,7 @@ export default class SaleInvoicesController extends BaseController {
await this.saleInvoiceService.salesInvoicesList(tenantId, filter);
return res.status(200).send({
sales_invoices: salesInvoices,
sales_invoices: this.transfromToResponse(salesInvoices),
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});

View File

@@ -3,6 +3,7 @@ import { check, param, query } from 'express-validator';
import { Inject, Service } from 'typedi';
import asyncMiddleware from 'api/middleware/asyncMiddleware';
import SaleReceiptService from 'services/Sales/SalesReceipts';
import SaleReceiptsPdfService from 'services/Sales/Receipts/SaleReceiptsPdfService';
import BaseController from '../BaseController';
import { ISaleReceiptDTO } from 'interfaces/SaleReceipt';
import { ServiceError } from 'exceptions';
@@ -13,6 +14,9 @@ export default class SalesReceiptsController extends BaseController {
@Inject()
saleReceiptService: SaleReceiptService;
@Inject()
saleReceiptsPdf: SaleReceiptsPdfService;
@Inject()
dynamicListService: DynamicListingService;
@@ -239,17 +243,13 @@ export default class SalesReceiptsController extends BaseController {
};
try {
const {
salesReceipts,
pagination,
filterMeta,
} = await this.saleReceiptService.salesReceiptsList(tenantId, filter);
const { salesReceipts, pagination, filterMeta } =
await this.saleReceiptService.salesReceiptsList(tenantId, filter);
return res.status(200).send({
sale_receipts: salesReceipts,
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
const response = this.transfromToResponse({
salesReceipts, pagination, filterMeta
});
return res.status(200).send(response);
} catch (error) {
next(error);
}
@@ -271,9 +271,22 @@ export default class SalesReceiptsController extends BaseController {
saleReceiptId
);
return res.status(200).send({
sale_receipt: saleReceipt,
});
res.format({
'application/pdf': async () => {
const pdfContent = await this.saleReceiptsPdf.saleReceiptPdf(
tenantId,
saleReceipt
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
},
'application/json': () => {
return res.status(200).send(this.transfromToResponse({ saleReceipt }));
}
})
} catch (error) {
next(error);
}