mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
fix: delete sale invoice with associated payment entries.
This commit is contained in:
@@ -338,7 +338,7 @@ export default class SaleInvoicesController extends BaseController {
|
||||
if (error instanceof ServiceError) {
|
||||
if (error.errorType === 'INVOICE_NUMBER_NOT_UNIQUE') {
|
||||
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') {
|
||||
@@ -348,42 +348,47 @@ export default class SaleInvoicesController extends BaseController {
|
||||
}
|
||||
if (error.errorType === 'ENTRIES_ITEMS_IDS_NOT_EXISTS') {
|
||||
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') {
|
||||
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') {
|
||||
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') {
|
||||
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') {
|
||||
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') {
|
||||
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') {
|
||||
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') {
|
||||
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 }],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import ItemsService from 'services/Items/ItemsService';
|
||||
import ItemsEntriesService from 'services/Items/ItemsEntriesService';
|
||||
import CustomersService from 'services/Contacts/CustomersService';
|
||||
import SaleEstimateService from 'services/Sales/SalesEstimate';
|
||||
import { PaymentReceiveEntry } from 'models';
|
||||
|
||||
const ERRORS = {
|
||||
INVOICE_NUMBER_NOT_UNIQUE: 'INVOICE_NUMBER_NOT_UNIQUE',
|
||||
@@ -32,6 +33,7 @@ const ERRORS = {
|
||||
ENTRIES_ITEMS_IDS_NOT_EXISTS: 'ENTRIES_ITEMS_IDS_NOT_EXISTS',
|
||||
NOT_SELLABLE_ITEMS: 'NOT_SELLABLE_ITEMS',
|
||||
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
|
||||
* and journal transactions.
|
||||
@@ -329,6 +353,9 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
tenantId,
|
||||
saleInvoiceId
|
||||
);
|
||||
// Validate the sale invoice has no associated payment entries.
|
||||
await this.validateInvoiceHasNoPaymentEntries(tenantId, saleInvoiceId);
|
||||
|
||||
// Triggers `onSaleInvoiceDelete` event.
|
||||
await this.eventDispatcher.dispatch(events.saleInvoice.onDelete, {
|
||||
tenantId,
|
||||
@@ -454,7 +481,9 @@ export default class SaleInvoicesService extends SalesInvoicesCost {
|
||||
tenantId: number,
|
||||
saleInvoiceId: number
|
||||
): Promise<void> {
|
||||
const { inventoryTransactionRepository } = this.tenancy.repositories(tenantId);
|
||||
const { inventoryTransactionRepository } = this.tenancy.repositories(
|
||||
tenantId
|
||||
);
|
||||
|
||||
// Retrieve the inventory transactions of the given sale invoice.
|
||||
const oldInventoryTransactions = await inventoryTransactionRepository.find({
|
||||
|
||||
Reference in New Issue
Block a user