mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
feat: invoice, estimate and receipt printing.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -42,12 +42,14 @@ import Subscription from 'api/controllers/Subscription';
|
||||
import Licenses from 'api/controllers/Subscription/Licenses';
|
||||
import InventoryAdjustments from 'api/controllers/Inventory/InventoryAdjustments';
|
||||
import Setup from 'api/controllers/Setup';
|
||||
import asyncRenderMiddleware from './middleware/AsyncRenderMiddleware';
|
||||
|
||||
export default () => {
|
||||
const app = Router();
|
||||
|
||||
// - Global routes.
|
||||
// ---------------------------
|
||||
app.use(asyncRenderMiddleware);
|
||||
app.use(i18n.init);
|
||||
app.use(I18nMiddleware);
|
||||
|
||||
|
||||
23
server/src/api/middleware/AsyncRenderMiddleware.ts
Normal file
23
server/src/api/middleware/AsyncRenderMiddleware.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Request, Response } from 'express';
|
||||
|
||||
const asyncRender = (app) => (path: string, attributes = {}) =>
|
||||
new Promise((resolve, reject) => {
|
||||
app.render(path, attributes, (error, data) => {
|
||||
if (error) { reject(error); }
|
||||
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Injects `asyncRender` method to response object.
|
||||
* @param {Request} req Express req Object
|
||||
* @param {Response} res Express res Object
|
||||
* @param {NextFunction} next Express next Function
|
||||
*/
|
||||
const asyncRenderMiddleware = (req: Request, res: Response, next: Function) => {
|
||||
res.asyncRender = asyncRender(req.app);
|
||||
next();
|
||||
};
|
||||
|
||||
export default asyncRenderMiddleware;
|
||||
@@ -162,6 +162,13 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Puppeteer remote browserless connection.
|
||||
*/
|
||||
puppeteer: {
|
||||
browserWSEndpoint: process.env.BROWSER_WS_ENDPOINT,
|
||||
},
|
||||
|
||||
protocol: '',
|
||||
hostname: '',
|
||||
scheduleComputeItemCost: 'in 5 seconds'
|
||||
|
||||
64
server/src/lib/Transformer/Transformer.ts
Normal file
64
server/src/lib/Transformer/Transformer.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import moment from "moment";
|
||||
import { isEmpty, isObject, isUndefined } from 'lodash';
|
||||
|
||||
export class Transformer {
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public transform = (object: any) => {
|
||||
if (Array.isArray(object)) {
|
||||
return object.map(this.getTransformation);
|
||||
} else if (isObject(object)) {
|
||||
return this.getTransformation(object);
|
||||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param item
|
||||
* @returns
|
||||
*/
|
||||
protected getTransformation = (item) => {
|
||||
const attributes = this.getIncludeAttributesTransformed(item);
|
||||
|
||||
return {
|
||||
...!isUndefined(item.toJSON) ? item.toObject() : item,
|
||||
...attributes
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param item
|
||||
* @returns
|
||||
*/
|
||||
protected getIncludeAttributesTransformed = (item) => {
|
||||
const attributes = this.includeAttributes();
|
||||
|
||||
return attributes
|
||||
.filter((attribute) => !isUndefined(this[attribute]))
|
||||
.reduce((acc, attribute: string) => {
|
||||
acc[attribute] = this[attribute](item);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
* @returns
|
||||
*/
|
||||
protected formatDate(date) {
|
||||
return date ? moment(date).format('YYYY/MM/DD') : '';
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,16 @@ import AgendashController from 'api/controllers/Agendash';
|
||||
import ConvertEmptyStringsToNull from 'api/middleware/ConvertEmptyStringsToNull';
|
||||
import RateLimiterMiddleware from 'api/middleware/RateLimiterMiddleware'
|
||||
import config from 'config';
|
||||
import path from 'path';
|
||||
|
||||
export default ({ app }) => {
|
||||
// Express configuration.
|
||||
app.set('port', 3000);
|
||||
|
||||
// Template engine configuration.
|
||||
app.set('views', path.join(__dirname, '../resources/views'));
|
||||
app.set('view engine', 'pug');
|
||||
|
||||
// Helmet helps you secure your Express apps by setting various HTTP headers.
|
||||
app.use(helmet());
|
||||
|
||||
|
||||
@@ -159,5 +159,32 @@
|
||||
"Liabilities and Equity": "Liabilities and Equity",
|
||||
"Closing balance": "Closing balance",
|
||||
"Opening Balance": "Opening balance",
|
||||
"Total {{accountName}}": "Total {{accountName}}"
|
||||
"Total {{accountName}}": "Total {{accountName}}",
|
||||
"invoice.paper.invoice": "Invoice",
|
||||
"invoice.paper.billed_to": "Billed to",
|
||||
"invoice.paper.invoice_date": "Invoice date",
|
||||
"invoice.paper.invoice_number": "Invoice No.",
|
||||
"invoice.paper.due_date": "Due date",
|
||||
"invoice.paper.conditions_title": "Conditions & terms",
|
||||
"invoice.paper.notes_title": "Notes",
|
||||
"item_entry.paper.item_name": "Item name",
|
||||
"item_entry.paper.rate": "Rate",
|
||||
"item_entry.paper.quantity": "Quantity",
|
||||
"item_entry.paper.total": "Total",
|
||||
"estimate.paper.estimate": "Estimate",
|
||||
"estimate.paper.billed_to": "Billed to",
|
||||
"estimate.paper.estimate_date": "Estimate date",
|
||||
"estimate.paper.estimate_number": "Estimate number",
|
||||
"estimate.paper.expiration_date": "Expiration date",
|
||||
"estimate.paper.conditions_title": "Conditions & terms",
|
||||
"estimate.paper.notes_title": "Notes",
|
||||
"estimate.paper.due_amount": "Due amount",
|
||||
"receipt.paper.receipt": "Receipt",
|
||||
"receipt.paper.billed_to": "Billed to",
|
||||
"receipt.paper.receipt_date": "Receipt date",
|
||||
"receipt.paper.receipt_number": "Receipt number",
|
||||
"receipt.paper.expiration_date": "Expiration date",
|
||||
"receipt.paper.conditions_title": "Conditions & terms",
|
||||
"receipt.paper.notes_title": "Notes",
|
||||
"receipt.paper.receipt_amount": "Receipt amount"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Model, mixin } from 'objection';
|
||||
import { snakeCase } from 'lodash';
|
||||
import { snakeCase, transform } from 'lodash';
|
||||
import { mapKeysDeep } from 'utils';
|
||||
import PaginationQueryBuilder from 'models/Pagination';
|
||||
import DateSession from 'models/DateSession';
|
||||
@@ -47,4 +47,9 @@ export default class ModelBase extends mixin(Model, [DateSession]) {
|
||||
static relationBindKnex(model) {
|
||||
return this.knexBinded ? model.bindKnex(this.knexBinded) : model;
|
||||
}
|
||||
|
||||
toObject(opt) {
|
||||
const parsedJson = super.$formatJson(this, opt);
|
||||
return parsedJson;
|
||||
}
|
||||
}
|
||||
|
||||
26
server/src/services/PDF/PdfService.ts
Normal file
26
server/src/services/PDF/PdfService.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Service } from 'typedi';
|
||||
import puppeteer from 'puppeteer';
|
||||
import config from 'config';
|
||||
|
||||
@Service()
|
||||
export default class PdfService {
|
||||
|
||||
/**
|
||||
* Pdf document.
|
||||
* @param content
|
||||
* @returns
|
||||
*/
|
||||
async pdfDocument(content: string) {
|
||||
const browser = await puppeteer.connect({
|
||||
browserWSEndpoint: config.puppeteer.browserWSEndpoint,
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
await page.setContent(content);
|
||||
|
||||
const pdf = await page.pdf({ format: 'a4' });
|
||||
|
||||
await browser.close();
|
||||
|
||||
return pdf;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Service } from 'typedi';
|
||||
import { IBill, IBillPayment } from 'interfaces';
|
||||
import { Transformer } from 'lib/Transformer/Transformer';
|
||||
import { formatNumber } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class BillPaymentTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return ['formattedPaymentDate', 'formattedAmount'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice date.
|
||||
* @param {IBill} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedPaymentDate = (billPayment: IBillPayment): string => {
|
||||
return this.formatDate(billPayment.paymentDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill amount.
|
||||
* @param {IBill} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (billPayment: IBillPayment): string => {
|
||||
return formatNumber(billPayment.amount, {
|
||||
currencyCode: billPayment.currencyCode,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import { entriesAmountDiff, formatDateFields } from 'utils';
|
||||
import { ServiceError } from 'exceptions';
|
||||
import { ACCOUNT_TYPE } from 'data/AccountTypes';
|
||||
import VendorsService from 'services/Contacts/VendorsService';
|
||||
import BillPaymentTransformer from './BillPaymentTransformer';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
/**
|
||||
@@ -57,6 +58,9 @@ export default class BillPaymentsService implements IBillPaymentsService {
|
||||
@Inject('logger')
|
||||
logger: any;
|
||||
|
||||
@Inject()
|
||||
billPaymentTransformer: BillPaymentTransformer;
|
||||
|
||||
/**
|
||||
* Validate whether the bill payment vendor exists on the storage.
|
||||
* @param {Request} req
|
||||
@@ -546,7 +550,7 @@ export default class BillPaymentsService implements IBillPaymentsService {
|
||||
if (!billPayment) {
|
||||
throw new ServiceError(ERRORS.PAYMENT_MADE_NOT_FOUND);
|
||||
}
|
||||
return billPayment;
|
||||
return this.billPaymentTransformer.transform(billPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -680,7 +684,7 @@ export default class BillPaymentsService implements IBillPaymentsService {
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
return {
|
||||
billPayments: results,
|
||||
billPayments: this.billPaymentTransformer.transform(results),
|
||||
pagination,
|
||||
filterMeta: dynamicList.getResponseMeta(),
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ import JournalPosterService from 'services/Sales/JournalPosterService';
|
||||
import VendorsService from 'services/Contacts/VendorsService';
|
||||
import { ERRORS } from './constants';
|
||||
import EntriesService from 'services/Entries';
|
||||
import PurchaseInvoiceTransfromer from './PurchaseInvoices/PurchaseInvoiceTransformer';
|
||||
|
||||
/**
|
||||
* Vendor bills services.
|
||||
@@ -78,6 +79,9 @@ export default class BillsService
|
||||
@Inject()
|
||||
entriesService: EntriesService;
|
||||
|
||||
@Inject()
|
||||
purchaseInvoiceTransformer: PurchaseInvoiceTransfromer;
|
||||
|
||||
/**
|
||||
* Validates whether the vendor is exist.
|
||||
* @async
|
||||
@@ -568,7 +572,7 @@ export default class BillsService
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
return {
|
||||
bills: results,
|
||||
bills: this.purchaseInvoiceTransformer.transform(results),
|
||||
pagination,
|
||||
filterMeta: dynamicFilter.getResponseMeta(),
|
||||
};
|
||||
@@ -616,7 +620,7 @@ export default class BillsService
|
||||
if (!bill) {
|
||||
throw new ServiceError(ERRORS.BILL_NOT_FOUND);
|
||||
}
|
||||
return bill;
|
||||
return this.purchaseInvoiceTransformer.transform(bill);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Service } from 'typedi';
|
||||
import { IBill } from 'interfaces';
|
||||
import { Transformer } from 'lib/Transformer/Transformer';
|
||||
import { formatNumber } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class PurchaseInvoiceTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return [
|
||||
'formattedBillDate',
|
||||
'formattedDueDate',
|
||||
'formattedAmount',
|
||||
'formattedPaymentAmount',
|
||||
'formattedDueAmount',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice date.
|
||||
* @param {IBill} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedBillDate = (bill: IBill): string => {
|
||||
return this.formatDate(bill.billDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice date.
|
||||
* @param {IBill} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedDueDate = (bill: IBill): string => {
|
||||
return this.formatDate(bill.dueDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill amount.
|
||||
* @param {IBill} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (bill): string => {
|
||||
return formatNumber(bill.amount, { currencyCode: bill.currencyCode });
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill amount.
|
||||
* @param {IBill} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedPaymentAmount = (bill): string => {
|
||||
return formatNumber(bill.paymentAmount, { currencyCode: bill.currencyCode});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted bill amount.
|
||||
* @param {IBill} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedDueAmount = (bill): string => {
|
||||
return formatNumber(bill.dueAmount, { currencyCode: bill.currencyCode });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { Service } from 'typedi';
|
||||
import { ISaleEstimate } from 'interfaces';
|
||||
import { Transformer } from 'lib/Transformer/Transformer';
|
||||
import { formatNumber } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class SaleEstimateTransfromer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return [
|
||||
'formattedAmount',
|
||||
'formattedEstimateDate',
|
||||
'formattedExpirationDate',
|
||||
'formattedDeliveredAtDate',
|
||||
'formattedApprovedAtDate',
|
||||
'formattedRejectedAtDate',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted estimate date.
|
||||
* @param {ISaleEstimate} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedEstimateDate = (estimate: ISaleEstimate): string => {
|
||||
return this.formatDate(estimate.estimateDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted estimate date.
|
||||
* @param {ISaleEstimate} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedExpirationDate = (estimate: ISaleEstimate): string => {
|
||||
return this.formatDate(estimate.expirationDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted estimate date.
|
||||
* @param {ISaleEstimate} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedDeliveredAtDate = (estimate: ISaleEstimate): string => {
|
||||
return this.formatDate(estimate.deliveredAt);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted estimate date.
|
||||
* @param {ISaleEstimate} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedApprovedAtDate = (estimate: ISaleEstimate): string => {
|
||||
return this.formatDate(estimate.approvedAt);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted estimate date.
|
||||
* @param {ISaleEstimate} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedRejectedAtDate = (estimate: ISaleEstimate): string => {
|
||||
return this.formatDate(estimate.rejectedAt);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice amount.
|
||||
* @param {ISaleEstimate} estimate
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (estimate: ISaleEstimate): string => {
|
||||
return formatNumber(estimate.amount, {
|
||||
currencyCode: estimate.currencyCode,
|
||||
});
|
||||
};
|
||||
}
|
||||
43
server/src/services/Sales/Estimates/SaleEstimatesPdf.ts
Normal file
43
server/src/services/Sales/Estimates/SaleEstimatesPdf.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import PdfService from 'services/PDF/PdfService';
|
||||
import { templateRender } from 'utils';
|
||||
import HasTenancyService from 'services/Tenancy/TenancyService';
|
||||
|
||||
@Service()
|
||||
export default class SaleEstimatesPdf {
|
||||
@Inject()
|
||||
pdfService: PdfService;
|
||||
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
/**
|
||||
* Retrieve sale invoice pdf content.
|
||||
* @param {} saleInvoice -
|
||||
*/
|
||||
async saleEstimatePdf(tenantId: number, saleEstimate) {
|
||||
const i18n = this.tenancy.i18n(tenantId);
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
|
||||
const organizationName = settings.get({
|
||||
group: 'organization',
|
||||
key: 'name',
|
||||
});
|
||||
const organizationEmail = settings.get({
|
||||
group: 'organization',
|
||||
key: 'email',
|
||||
});
|
||||
const htmlContent = templateRender('modules/estimate-regular', {
|
||||
saleEstimate,
|
||||
organizationName,
|
||||
organizationEmail,
|
||||
...i18n,
|
||||
});
|
||||
|
||||
console.log(htmlContent, 'XXX');
|
||||
|
||||
const pdfContent = await this.pdfService.pdfDocument(htmlContent);
|
||||
|
||||
return pdfContent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Service } from 'typedi';
|
||||
import { IPaymentReceive } from 'interfaces';
|
||||
import { Transformer } from 'lib/Transformer/Transformer';
|
||||
import { formatNumber } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class PaymentReceiveTransfromer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to payment receive object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return [
|
||||
'formattedPaymentDate',
|
||||
'formattedAmount',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted payment receive date.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedPaymentDate = (payment: IPaymentReceive): string => {
|
||||
return this.formatDate(payment.paymentDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted payment amount.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (payment: IPaymentReceive): string => {
|
||||
return formatNumber(payment.amount, { currencyCode: payment.currencyCode });
|
||||
};
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import JournalCommands from 'services/Accounting/JournalCommands';
|
||||
import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from 'data/AccountTypes';
|
||||
import AutoIncrementOrdersService from '../AutoIncrementOrdersService';
|
||||
import { ERRORS } from './constants';
|
||||
import PaymentReceiveTransfromer from './PaymentReceiveTransformer';
|
||||
|
||||
/**
|
||||
* Payment receive service.
|
||||
@@ -68,6 +69,9 @@ export default class PaymentReceiveService implements IPaymentsReceiveService {
|
||||
@EventDispatcher()
|
||||
eventDispatcher: EventDispatcherInterface;
|
||||
|
||||
@Inject()
|
||||
paymentReceiveTransformer: PaymentReceiveTransfromer;
|
||||
|
||||
/**
|
||||
* Validates the payment receive number existance.
|
||||
* @param {number} tenantId -
|
||||
@@ -584,7 +588,7 @@ export default class PaymentReceiveService implements IPaymentsReceiveService {
|
||||
throw new ServiceError(ERRORS.PAYMENT_RECEIVE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
return paymentReceive;
|
||||
return this.paymentReceiveTransformer.transform(paymentReceive);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -661,7 +665,7 @@ export default class PaymentReceiveService implements IPaymentsReceiveService {
|
||||
);
|
||||
|
||||
return {
|
||||
paymentReceives: results,
|
||||
paymentReceives: this.paymentReceiveTransformer.transform(results),
|
||||
pagination,
|
||||
filterMeta: dynamicList.getResponseMeta(),
|
||||
};
|
||||
|
||||
44
server/src/services/Sales/Receipts/SaleReceiptTransformer.ts
Normal file
44
server/src/services/Sales/Receipts/SaleReceiptTransformer.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { Service } from 'typedi';
|
||||
import { ISaleReceipt } from 'interfaces';
|
||||
import { Transformer } from 'lib/Transformer/Transformer';
|
||||
import { formatNumber } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class SaleReceiptTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return ['formattedAmount', 'formattedReceiptDate', 'formattedClosedAtDate'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted receipt date.
|
||||
* @param {ISaleReceipt} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedReceiptDate = (receipt: ISaleReceipt): string => {
|
||||
return this.formatDate(receipt.receiptDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted estimate closed at date.
|
||||
* @param {ISaleReceipt} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedClosedAtDate = (receipt: ISaleReceipt): string => {
|
||||
return this.formatDate(receipt.closedAt);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice amount.
|
||||
* @param {ISaleReceipt} estimate
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (receipt: ISaleReceipt): string => {
|
||||
return formatNumber(receipt.amount, {
|
||||
currencyCode: receipt.currencyCode,
|
||||
});
|
||||
};
|
||||
}
|
||||
41
server/src/services/Sales/Receipts/SaleReceiptsPdfService.ts
Normal file
41
server/src/services/Sales/Receipts/SaleReceiptsPdfService.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import PdfService from 'services/PDF/PdfService';
|
||||
import { templateRender } from 'utils';
|
||||
import HasTenancyService from 'services/Tenancy/TenancyService';
|
||||
|
||||
@Service()
|
||||
export default class SaleReceiptsPdf {
|
||||
@Inject()
|
||||
pdfService: PdfService;
|
||||
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
/**
|
||||
* Retrieve sale invoice pdf content.
|
||||
* @param {} saleInvoice -
|
||||
*/
|
||||
async saleReceiptPdf(tenantId: number, saleReceipt) {
|
||||
const i18n = this.tenancy.i18n(tenantId);
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
|
||||
const organizationName = settings.get({
|
||||
group: 'organization',
|
||||
key: 'name',
|
||||
});
|
||||
const organizationEmail = settings.get({
|
||||
group: 'organization',
|
||||
key: 'email',
|
||||
});
|
||||
|
||||
const htmlContent = templateRender('modules/receipt-regular', {
|
||||
saleReceipt,
|
||||
organizationEmail,
|
||||
organizationName,
|
||||
...i18n,
|
||||
});
|
||||
const pdfContent = await this.pdfService.pdfDocument(htmlContent);
|
||||
|
||||
return pdfContent;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
export const ERRORS = {
|
||||
SALE_RECEIPT_NOT_FOUND: 'SALE_RECEIPT_NOT_FOUND',
|
||||
DEPOSIT_ACCOUNT_NOT_FOUND: 'DEPOSIT_ACCOUNT_NOT_FOUND',
|
||||
DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET: 'DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET',
|
||||
SALE_RECEIPT_NUMBER_NOT_UNIQUE: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE',
|
||||
SALE_RECEIPT_IS_ALREADY_CLOSED: 'SALE_RECEIPT_IS_ALREADY_CLOSED',
|
||||
SALE_RECEIPT_NO_IS_REQUIRED: 'SALE_RECEIPT_NO_IS_REQUIRED',
|
||||
CUSTOMER_HAS_SALES_INVOICES: 'CUSTOMER_HAS_SALES_INVOICES',
|
||||
};
|
||||
|
||||
export const DEFAULT_VIEW_COLUMNS = [];
|
||||
export const DEFAULT_VIEWS = [
|
||||
{
|
||||
|
||||
35
server/src/services/Sales/SaleInvoicePdf.ts
Normal file
35
server/src/services/Sales/SaleInvoicePdf.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import PdfService from 'services/PDF/PdfService';
|
||||
import { templateRender } from 'utils';
|
||||
import HasTenancyService from 'services/Tenancy/TenancyService';
|
||||
|
||||
@Service()
|
||||
export default class SaleInvoicePdf {
|
||||
@Inject()
|
||||
pdfService: PdfService
|
||||
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
/**
|
||||
* Retrieve sale invoice pdf content.
|
||||
* @param {} saleInvoice -
|
||||
*/
|
||||
async saleInvoicePdf(tenantId: number, saleInvoice) {
|
||||
const i18n = this.tenancy.i18n(tenantId);
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
|
||||
const organizationName = settings.get({ group: 'organization', key: 'name' });
|
||||
const organizationEmail = settings.get({ group: 'organization', key: 'email' });
|
||||
|
||||
const htmlContent = templateRender('modules/invoice-regular', {
|
||||
organizationName,
|
||||
organizationEmail,
|
||||
saleInvoice,
|
||||
...i18n
|
||||
});
|
||||
const pdfContent = await this.pdfService.pdfDocument(htmlContent);
|
||||
|
||||
return pdfContent;
|
||||
}
|
||||
}
|
||||
60
server/src/services/Sales/SaleInvoiceTransformer.ts
Normal file
60
server/src/services/Sales/SaleInvoiceTransformer.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Service } from 'typedi';
|
||||
import { ISaleInvoice } from 'interfaces';
|
||||
import { Transformer } from 'lib/Transformer/Transformer';
|
||||
import { formatNumber } from 'utils';
|
||||
|
||||
@Service()
|
||||
export default class SaleInvoiceTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
protected includeAttributes = (): string[] => {
|
||||
return [
|
||||
'formattedInvoiceDate',
|
||||
'formattedDueDate',
|
||||
'formattedAmount',
|
||||
'formattedDueAmount',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice date.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {String}
|
||||
*/
|
||||
protected formattedInvoiceDate = (invoice): string => {
|
||||
return this.formatDate(invoice.invoiceDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted due date.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedDueDate = (invoice): string => {
|
||||
return this.formatDate(invoice.dueDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice amount.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedAmount = (invoice): string => {
|
||||
return formatNumber(invoice.balance, {
|
||||
currencyCode: invoice.currencyCode,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve formatted invoice due amount.
|
||||
* @param {ISaleInvoice} invoice
|
||||
* @returns {string}
|
||||
*/
|
||||
protected formattedDueAmount(invoice) {
|
||||
return formatNumber(invoice.dueAmount, {
|
||||
currencyCode: invoice.currencyCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -22,20 +22,8 @@ import { ServiceError } from 'exceptions';
|
||||
import CustomersService from 'services/Contacts/CustomersService';
|
||||
import moment from 'moment';
|
||||
import AutoIncrementOrdersService from './AutoIncrementOrdersService';
|
||||
|
||||
const ERRORS = {
|
||||
SALE_ESTIMATE_NOT_FOUND: 'SALE_ESTIMATE_NOT_FOUND',
|
||||
CUSTOMER_NOT_FOUND: 'CUSTOMER_NOT_FOUND',
|
||||
SALE_ESTIMATE_NUMBER_EXISTANCE: 'SALE_ESTIMATE_NUMBER_EXISTANCE',
|
||||
ITEMS_IDS_NOT_EXISTS: 'ITEMS_IDS_NOT_EXISTS',
|
||||
SALE_ESTIMATE_ALREADY_DELIVERED: 'SALE_ESTIMATE_ALREADY_DELIVERED',
|
||||
SALE_ESTIMATE_CONVERTED_TO_INVOICE: 'SALE_ESTIMATE_CONVERTED_TO_INVOICE',
|
||||
SALE_ESTIMATE_ALREADY_REJECTED: 'SALE_ESTIMATE_ALREADY_REJECTED',
|
||||
SALE_ESTIMATE_ALREADY_APPROVED: 'SALE_ESTIMATE_ALREADY_APPROVED',
|
||||
SALE_ESTIMATE_NOT_DELIVERED: 'SALE_ESTIMATE_NOT_DELIVERED',
|
||||
SALE_ESTIMATE_NO_IS_REQUIRED: 'SALE_ESTIMATE_NO_IS_REQUIRED',
|
||||
CUSTOMER_HAS_SALES_ESTIMATES: 'CUSTOMER_HAS_SALES_ESTIMATES',
|
||||
};
|
||||
import { ERRORS } from './constants';
|
||||
import SaleEstimateTransfromer from './Estimates/SaleEstimateTransformer';
|
||||
|
||||
/**
|
||||
* Sale estimate service.
|
||||
@@ -64,6 +52,9 @@ export default class SaleEstimateService implements ISalesEstimatesService{
|
||||
@Inject()
|
||||
autoIncrementOrdersService: AutoIncrementOrdersService;
|
||||
|
||||
@Inject()
|
||||
saleEstimateTransformer: SaleEstimateTransfromer;
|
||||
|
||||
/**
|
||||
* Retrieve sale estimate or throw service error.
|
||||
* @param {number} tenantId
|
||||
@@ -404,13 +395,13 @@ export default class SaleEstimateService implements ISalesEstimatesService{
|
||||
const { SaleEstimate } = this.tenancy.models(tenantId);
|
||||
const estimate = await SaleEstimate.query()
|
||||
.findById(estimateId)
|
||||
.withGraphFetched('entries')
|
||||
.withGraphFetched('entries.item')
|
||||
.withGraphFetched('customer');
|
||||
|
||||
if (!estimate) {
|
||||
throw new ServiceError(ERRORS.SALE_ESTIMATE_NOT_FOUND);
|
||||
}
|
||||
return estimate;
|
||||
return this.saleEstimateTransformer.transform(estimate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +448,7 @@ export default class SaleEstimateService implements ISalesEstimatesService{
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
return {
|
||||
salesEstimates: results,
|
||||
salesEstimates: this.saleEstimateTransformer.transform(results),
|
||||
pagination,
|
||||
filterMeta: dynamicFilter.getResponseMeta(),
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@ import CustomersService from 'services/Contacts/CustomersService';
|
||||
import SaleEstimateService from 'services/Sales/SalesEstimate';
|
||||
import JournalPosterService from './JournalPosterService';
|
||||
import AutoIncrementOrdersService from './AutoIncrementOrdersService';
|
||||
import SaleInvoiceTransfromer from './SaleInvoiceTransformer';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
/**
|
||||
@@ -74,6 +75,9 @@ export default class SaleInvoicesService implements ISalesInvoicesService {
|
||||
@Inject()
|
||||
autoIncrementOrdersService: AutoIncrementOrdersService;
|
||||
|
||||
@Inject()
|
||||
saleInvoiceTransformer: SaleInvoiceTransfromer;
|
||||
|
||||
/**
|
||||
* Validate whether sale invoice number unqiue on the storage.
|
||||
*/
|
||||
@@ -639,13 +643,13 @@ export default class SaleInvoicesService implements ISalesInvoicesService {
|
||||
|
||||
const saleInvoice = await SaleInvoice.query()
|
||||
.findById(saleInvoiceId)
|
||||
.withGraphFetched('entries')
|
||||
.withGraphFetched('entries.item')
|
||||
.withGraphFetched('customer');
|
||||
|
||||
if (!saleInvoice) {
|
||||
throw new ServiceError(ERRORS.SALE_INVOICE_NOT_FOUND);
|
||||
}
|
||||
return saleInvoice;
|
||||
return this.saleInvoiceTransformer.transform(saleInvoice);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +702,7 @@ export default class SaleInvoicesService implements ISalesInvoicesService {
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
return {
|
||||
salesInvoices: results,
|
||||
salesInvoices: this.saleInvoiceTransformer.transform(results),
|
||||
pagination,
|
||||
filterMeta: dynamicFilter.getResponseMeta(),
|
||||
};
|
||||
|
||||
@@ -29,16 +29,8 @@ import InventoryService from 'services/Inventory/Inventory';
|
||||
import { ACCOUNT_PARENT_TYPE } from 'data/AccountTypes';
|
||||
import AutoIncrementOrdersService from './AutoIncrementOrdersService';
|
||||
import CustomersService from 'services/Contacts/CustomersService';
|
||||
|
||||
const ERRORS = {
|
||||
SALE_RECEIPT_NOT_FOUND: 'SALE_RECEIPT_NOT_FOUND',
|
||||
DEPOSIT_ACCOUNT_NOT_FOUND: 'DEPOSIT_ACCOUNT_NOT_FOUND',
|
||||
DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET: 'DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET',
|
||||
SALE_RECEIPT_NUMBER_NOT_UNIQUE: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE',
|
||||
SALE_RECEIPT_IS_ALREADY_CLOSED: 'SALE_RECEIPT_IS_ALREADY_CLOSED',
|
||||
SALE_RECEIPT_NO_IS_REQUIRED: 'SALE_RECEIPT_NO_IS_REQUIRED',
|
||||
CUSTOMER_HAS_SALES_INVOICES: 'CUSTOMER_HAS_SALES_INVOICES',
|
||||
};
|
||||
import { ERRORS } from './Receipts/constants';
|
||||
import SaleReceiptTransfromer from './Receipts/SaleReceiptTransformer';
|
||||
|
||||
@Service('SalesReceipts')
|
||||
export default class SalesReceiptService implements ISalesReceiptsService {
|
||||
@@ -69,6 +61,9 @@ export default class SalesReceiptService implements ISalesReceiptsService {
|
||||
@Inject()
|
||||
customersService: CustomersService;
|
||||
|
||||
@Inject()
|
||||
saleReceiptTransformer: SaleReceiptTransfromer;
|
||||
|
||||
/**
|
||||
* Validate whether sale receipt exists on the storage.
|
||||
* @param {number} tenantId -
|
||||
@@ -397,14 +392,14 @@ export default class SalesReceiptService implements ISalesReceiptsService {
|
||||
|
||||
const saleReceipt = await SaleReceipt.query()
|
||||
.findById(saleReceiptId)
|
||||
.withGraphFetched('entries')
|
||||
.withGraphFetched('entries.item')
|
||||
.withGraphFetched('customer')
|
||||
.withGraphFetched('depositAccount');
|
||||
|
||||
if (!saleReceipt) {
|
||||
throw new ServiceError(ERRORS.SALE_RECEIPT_NOT_FOUND);
|
||||
}
|
||||
return saleReceipt;
|
||||
return this.saleReceiptTransformer.transform(saleReceipt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -456,7 +451,7 @@ export default class SalesReceiptService implements ISalesReceiptsService {
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
return {
|
||||
salesReceipts: results,
|
||||
salesReceipts: this.saleReceiptTransformer.transform(results),
|
||||
pagination,
|
||||
filterMeta: dynamicFilter.getResponseMeta(),
|
||||
};
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import bcrypt from 'bcryptjs';
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
import accounting from 'accounting';
|
||||
import pug from 'pug';
|
||||
import Currencies from 'js-money/lib/currency';
|
||||
import definedOptions from 'data/options';
|
||||
|
||||
@@ -378,7 +380,13 @@ const mergeObjectsBykey = (object1, object2, key) => {
|
||||
return _.values(merged);
|
||||
}
|
||||
|
||||
function templateRender(filePath, options) {
|
||||
const basePath = path.join(__dirname, '../../resources/views');
|
||||
return pug.renderFile(`${basePath}/${filePath}.pug`, options);
|
||||
}
|
||||
|
||||
export {
|
||||
templateRender,
|
||||
accumSum,
|
||||
increment,
|
||||
hashPassword,
|
||||
|
||||
Reference in New Issue
Block a user