mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 07:40:32 +00:00
feat: add sale receipt number.
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
@@ -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[],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user