feat: add sale receipt number.

This commit is contained in:
Ahmed Bouhuolia
2020-10-26 13:47:42 +02:00
parent 1c842662ab
commit d0785c65db
5 changed files with 51 additions and 4 deletions

View File

@@ -66,6 +66,7 @@ export default class SalesReceiptsController extends BaseController{
check('deposit_account_id').exists().isNumeric().toInt(), check('deposit_account_id').exists().isNumeric().toInt(),
check('receipt_date').exists().isISO8601(), check('receipt_date').exists().isISO8601(),
check('send_to_email').optional().isEmail(), check('send_to_email').optional().isEmail(),
check('receipt_number').optional().trim().escape(),
check('reference_no').optional().trim().escape(), check('reference_no').optional().trim().escape(),
check('entries').exists().isArray({ min: 1 }), check('entries').exists().isArray({ min: 1 }),
@@ -262,8 +263,12 @@ export default class SalesReceiptsController extends BaseController{
errors: [{ type: 'DEPOSIT.ACCOUNT.NOT.EXISTS', code: 800 }], errors: [{ type: 'DEPOSIT.ACCOUNT.NOT.EXISTS', code: 800 }],
}); });
} }
if (error.errorType === 'SALE_RECEIPT_NUMBER_NOT_UNIQUE') {
return res.boom.badRequest(null, {
errors: [{ type: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE', code: 900 }],
});
}
} }
console.log(error);
next(error); next(error);
} }
}; };

View File

@@ -6,6 +6,7 @@ exports.up = function(knex) {
table.integer('deposit_account_id').unsigned().index().references('id').inTable('accounts'); table.integer('deposit_account_id').unsigned().index().references('id').inTable('accounts');
table.integer('customer_id').unsigned().index().references('id').inTable('contacts'); table.integer('customer_id').unsigned().index().references('id').inTable('contacts');
table.date('receipt_date').index(); table.date('receipt_date').index();
table.string('receipt_number');
table.string('reference_no'); table.string('reference_no');
table.string('email_send_to'); table.string('email_send_to');
table.text('receipt_message'); table.text('receipt_message');

View File

@@ -9,6 +9,7 @@ export interface ISaleReceipt {
sendToEmail: string, sendToEmail: string,
referenceNo: string, referenceNo: string,
receiptMessage: string, receiptMessage: string,
receiptNumber: string,
statement: string, statement: string,
entries: any[], entries: any[],
}; };

View File

@@ -66,9 +66,6 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
/** /**
* *
* Validate whether sale invoice number unqiue on the storage. * Validate whether sale invoice number unqiue on the storage.
* @param {Request} req
* @param {Response} res
* @param {Function} next
*/ */
async validateInvoiceNumberUnique(tenantId: number, invoiceNumber: string, notInvoiceId?: number) { async validateInvoiceNumberUnique(tenantId: number, invoiceNumber: string, notInvoiceId?: number) {
const { SaleInvoice } = this.tenancy.models(tenantId); const { SaleInvoice } = this.tenancy.models(tenantId);

View File

@@ -19,6 +19,7 @@ const ERRORS = {
SALE_RECEIPT_NOT_FOUND: 'SALE_RECEIPT_NOT_FOUND', SALE_RECEIPT_NOT_FOUND: 'SALE_RECEIPT_NOT_FOUND',
DEPOSIT_ACCOUNT_NOT_FOUND: 'DEPOSIT_ACCOUNT_NOT_FOUND', DEPOSIT_ACCOUNT_NOT_FOUND: 'DEPOSIT_ACCOUNT_NOT_FOUND',
DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET: 'DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET', DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET: 'DEPOSIT_ACCOUNT_NOT_CURRENT_ASSET',
SALE_RECEIPT_NUMBER_NOT_UNIQUE: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE'
}; };
@Service() @Service()
export default class SalesReceiptService { export default class SalesReceiptService {
@@ -77,6 +78,30 @@ export default class SalesReceiptService {
} }
} }
/**
* Validate sale receipt number uniquiness on the storage.
* @param {number} tenantId -
* @param {string} receiptNumber -
* @param {number} notReceiptId -
*/
async validateReceiptNumberUnique(tenantId: number, receiptNumber: string, notReceiptId?: number) {
const { SaleReceipt } = this.tenancy.models(tenantId);
this.logger.info('[sale_receipt] validate receipt number uniquiness.', { tenantId, receiptNumber });
const saleReceipt = await SaleReceipt.query()
.findOne('receipt_number', receiptNumber)
.onBuild((builder) => {
if (notReceiptId) {
builder.whereNot('id', notReceiptId);
}
});
if (saleReceipt) {
this.logger.info('[sale_receipt] sale receipt number not unique.', { tenantId });
throw new ServiceError(ERRORS.SALE_RECEIPT_NUMBER_NOT_UNIQUE);
}
}
/** /**
* Creates a new sale receipt with associated entries. * Creates a new sale receipt with associated entries.
* @async * @async
@@ -91,10 +116,19 @@ export default class SalesReceiptService {
amount, amount,
...formatDateFields(saleReceiptDTO, ['receipt_date']) ...formatDateFields(saleReceiptDTO, ['receipt_date'])
}; };
// Validate receipt deposit account existance and type.
await this.validateReceiptDepositAccountExistance(tenantId, saleReceiptDTO.depositAccountId); await this.validateReceiptDepositAccountExistance(tenantId, saleReceiptDTO.depositAccountId);
// Validate items IDs existance on the storage.
await this.itemsEntriesService.validateItemsIdsExistance(tenantId, saleReceiptDTO.entries); await this.itemsEntriesService.validateItemsIdsExistance(tenantId, saleReceiptDTO.entries);
// Validate the sellable items.
await this.itemsEntriesService.validateNonSellableEntriesItems(tenantId, saleReceiptDTO.entries); await this.itemsEntriesService.validateNonSellableEntriesItems(tenantId, saleReceiptDTO.entries);
// Validate sale receipt number uniuqiness.
await this.validateReceiptNumberUnique(tenantId, saleReceiptDTO.receiptNumber);
this.logger.info('[sale_receipt] trying to insert sale receipt graph.', { tenantId, saleReceiptDTO }); this.logger.info('[sale_receipt] trying to insert sale receipt graph.', { tenantId, saleReceiptDTO });
const saleReceipt = await SaleReceipt.query() const saleReceipt = await SaleReceipt.query()
.insertGraphAndFetch({ .insertGraphAndFetch({
@@ -126,12 +160,21 @@ export default class SalesReceiptService {
amount, amount,
...formatDateFields(saleReceiptDTO, ['receipt_date']) ...formatDateFields(saleReceiptDTO, ['receipt_date'])
}; };
// Retrieve sale receipt or throw not found service error.
const oldSaleReceipt = await this.getSaleReceiptOrThrowError(tenantId, saleReceiptId); const oldSaleReceipt = await this.getSaleReceiptOrThrowError(tenantId, saleReceiptId);
// Validate receipt deposit account existance and type.
await this.validateReceiptDepositAccountExistance(tenantId, saleReceiptDTO.depositAccountId); await this.validateReceiptDepositAccountExistance(tenantId, saleReceiptDTO.depositAccountId);
// Validate items IDs existance on the storage.
await this.itemsEntriesService.validateItemsIdsExistance(tenantId, saleReceiptDTO.entries); await this.itemsEntriesService.validateItemsIdsExistance(tenantId, saleReceiptDTO.entries);
// Validate the sellable items.
await this.itemsEntriesService.validateNonSellableEntriesItems(tenantId, saleReceiptDTO.entries); await this.itemsEntriesService.validateNonSellableEntriesItems(tenantId, saleReceiptDTO.entries);
// Validate sale receipt number uniuqiness.
await this.validateReceiptNumberUnique(tenantId, saleReceiptDTO.receiptNumber, saleReceiptId);
const saleReceipt = await SaleReceipt.query() const saleReceipt = await SaleReceipt.query()
.upsertGraphAndFetch({ .upsertGraphAndFetch({
id: saleReceiptId, id: saleReceiptId,