fix: delete sale invoice with associated payment entries.

This commit is contained in:
a.bouhuolia
2021-01-02 11:32:15 +02:00
parent 717747981e
commit cdee2e5314
2 changed files with 44 additions and 10 deletions

View File

@@ -338,7 +338,7 @@ export default class SaleInvoicesController extends BaseController {
if (error instanceof ServiceError) { if (error instanceof ServiceError) {
if (error.errorType === 'INVOICE_NUMBER_NOT_UNIQUE') { if (error.errorType === 'INVOICE_NUMBER_NOT_UNIQUE') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'SALE.INVOICE.NUMBER.IS.EXISTS', code: 200 }], errors: [{ type: 'SALE.INVOICE.NUMBER.IS.EXISTS', code: 100 }],
}); });
} }
if (error.errorType === 'SALE_INVOICE_NOT_FOUND') { if (error.errorType === 'SALE_INVOICE_NOT_FOUND') {
@@ -348,42 +348,47 @@ export default class SaleInvoicesController extends BaseController {
} }
if (error.errorType === 'ENTRIES_ITEMS_IDS_NOT_EXISTS') { if (error.errorType === 'ENTRIES_ITEMS_IDS_NOT_EXISTS') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'ENTRIES_ITEMS_IDS_NOT_EXISTS', code: 200 }], errors: [{ type: 'ENTRIES_ITEMS_IDS_NOT_EXISTS', code: 300 }],
}); });
} }
if (error.errorType === 'NOT_SELLABLE_ITEMS') { if (error.errorType === 'NOT_SELLABLE_ITEMS') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'NOT_SELLABLE_ITEMS', code: 200 }], errors: [{ type: 'NOT_SELLABLE_ITEMS', code: 400 }],
}); });
} }
if (error.errorType === 'SALE_INVOICE_NO_NOT_UNIQUE') { if (error.errorType === 'SALE_INVOICE_NO_NOT_UNIQUE') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'SALE_INVOICE_NO_NOT_UNIQUE', code: 200 }], errors: [{ type: 'SALE_INVOICE_NO_NOT_UNIQUE', code: 500 }],
}); });
} }
if (error.errorType === 'ITEMS_NOT_FOUND') { if (error.errorType === 'ITEMS_NOT_FOUND') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'ITEMS_NOT_FOUND', code: 200 }], errors: [{ type: 'ITEMS_NOT_FOUND', code: 600 }],
}); });
} }
if (error.errorType === 'ENTRIES_IDS_NOT_FOUND') { if (error.errorType === 'ENTRIES_IDS_NOT_FOUND') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'ENTRIES_IDS_NOT_FOUND', code: 200 }], errors: [{ type: 'ENTRIES_IDS_NOT_FOUND', code: 700 }],
}); });
} }
if (error.errorType === 'NOT_SELL_ABLE_ITEMS') { if (error.errorType === 'NOT_SELL_ABLE_ITEMS') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'NOT_SELL_ABLE_ITEMS', code: 200 }], errors: [{ type: 'NOT_SELL_ABLE_ITEMS', code: 800 }],
}); });
} }
if (error.errorType === 'contact_not_found') { if (error.errorType === 'contact_not_found') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'CUSTOMER_NOT_FOUND', code: 200 }], errors: [{ type: 'CUSTOMER_NOT_FOUND', code: 900 }],
}); });
} }
if (error.errorType === 'SALE_INVOICE_ALREADY_DELIVERED') { if (error.errorType === 'SALE_INVOICE_ALREADY_DELIVERED') {
return res.boom.badRequest(null, { return res.boom.badRequest(null, {
errors: [{ type: 'SALE_INVOICE_ALREADY_DELIVERED', code: 200 }], errors: [{ type: 'SALE_INVOICE_ALREADY_DELIVERED', code: 1000 }],
});
}
if (error.errorType === 'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES') {
return res.boom.badRequest(null, {
errors: [{ type: 'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES', code: 1100 }],
}); });
} }
} }

View File

@@ -24,6 +24,7 @@ import ItemsService from 'services/Items/ItemsService';
import ItemsEntriesService from 'services/Items/ItemsEntriesService'; import ItemsEntriesService from 'services/Items/ItemsEntriesService';
import CustomersService from 'services/Contacts/CustomersService'; import CustomersService from 'services/Contacts/CustomersService';
import SaleEstimateService from 'services/Sales/SalesEstimate'; import SaleEstimateService from 'services/Sales/SalesEstimate';
import { PaymentReceiveEntry } from 'models';
const ERRORS = { const ERRORS = {
INVOICE_NUMBER_NOT_UNIQUE: 'INVOICE_NUMBER_NOT_UNIQUE', INVOICE_NUMBER_NOT_UNIQUE: 'INVOICE_NUMBER_NOT_UNIQUE',
@@ -32,6 +33,7 @@ const ERRORS = {
ENTRIES_ITEMS_IDS_NOT_EXISTS: 'ENTRIES_ITEMS_IDS_NOT_EXISTS', ENTRIES_ITEMS_IDS_NOT_EXISTS: 'ENTRIES_ITEMS_IDS_NOT_EXISTS',
NOT_SELLABLE_ITEMS: 'NOT_SELLABLE_ITEMS', NOT_SELLABLE_ITEMS: 'NOT_SELLABLE_ITEMS',
SALE_INVOICE_NO_NOT_UNIQUE: 'SALE_INVOICE_NO_NOT_UNIQUE', SALE_INVOICE_NO_NOT_UNIQUE: 'SALE_INVOICE_NO_NOT_UNIQUE',
INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES: 'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES',
}; };
/** /**
@@ -312,6 +314,28 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
); );
} }
/**
* Validate the sale invoice has no payment entries.
* @param {number} tenantId
* @param {number} saleInvoiceId
*/
async validateInvoiceHasNoPaymentEntries(
tenantId: number,
saleInvoiceId: number
) {
const { PaymentReceiveEntry } = this.tenancy.models(tenantId);
// Retrieve the sale invoice associated payment receive entries.
const entries = await PaymentReceiveEntry.query().where(
'invoice_id',
saleInvoiceId,
);
if (entries.length > 0) {
throw new ServiceError(ERRORS.INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES);
}
return entries;
}
/** /**
* Deletes the given sale invoice with associated entries * Deletes the given sale invoice with associated entries
* and journal transactions. * and journal transactions.
@@ -329,6 +353,9 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
tenantId, tenantId,
saleInvoiceId saleInvoiceId
); );
// Validate the sale invoice has no associated payment entries.
await this.validateInvoiceHasNoPaymentEntries(tenantId, saleInvoiceId);
// Triggers `onSaleInvoiceDelete` event. // Triggers `onSaleInvoiceDelete` event.
await this.eventDispatcher.dispatch(events.saleInvoice.onDelete, { await this.eventDispatcher.dispatch(events.saleInvoice.onDelete, {
tenantId, tenantId,
@@ -454,7 +481,9 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
tenantId: number, tenantId: number,
saleInvoiceId: number saleInvoiceId: number
): Promise<void> { ): Promise<void> {
const { inventoryTransactionRepository } = this.tenancy.repositories(tenantId); const { inventoryTransactionRepository } = this.tenancy.repositories(
tenantId
);
// Retrieve the inventory transactions of the given sale invoice. // Retrieve the inventory transactions of the given sale invoice.
const oldInventoryTransactions = await inventoryTransactionRepository.find({ const oldInventoryTransactions = await inventoryTransactionRepository.find({