feat: deleteIfNoRelations

This commit is contained in:
Ahmed Bouhuolia
2025-06-28 22:35:29 +02:00
parent 0ca98c7ae4
commit fa5c3bd955
11 changed files with 229 additions and 143 deletions

View File

@@ -39,9 +39,6 @@ export class DeleteBranchService {
.query()
.findById(branchId)
.throwIfNotFound();
// .queryAndThrowIfHasRelations({
// type: ERRORS.BRANCH_HAS_ASSOCIATED_TRANSACTIONS,
// });
// Authorize the branch before deleting.
await this.authorize(branchId);
@@ -54,8 +51,10 @@ export class DeleteBranchService {
trx,
} as IBranchDeletePayload);
await this.branchModel().query().findById(branchId).delete();
await this.branchModel().query().findById(branchId).deleteIfNoRelations({
type: ERRORS.BRANCH_HAS_ASSOCIATED_TRANSACTIONS,
message: 'Branch has associated transactions',
});
// Triggers `onBranchCreate` event.
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
oldBranch,

View File

@@ -9,6 +9,7 @@ import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
import { Customer } from '../models/Customer';
import { events } from '@/common/events/events';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { ERRORS } from '../constants';
@Injectable()
export class DeleteCustomer {
@@ -36,9 +37,6 @@ export class DeleteCustomer {
.query()
.findById(customerId)
.throwIfNotFound();
// .queryAndThrowIfHasRelations({
// type: ERRORS.CUSTOMER_HAS_TRANSACTIONS,
// });
// Triggers `onCustomerDeleting` event.
await this.eventPublisher.emitAsync(events.customers.onDeleting, {
@@ -49,8 +47,13 @@ export class DeleteCustomer {
// Deletes the customer and associated entities under UOW transaction.
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
// Delete the customer from the storage.
await this.customerModel().query(trx).findById(customerId).delete();
await this.customerModel()
.query(trx)
.findById(customerId)
.deleteIfNoRelations({
type: ERRORS.CUSTOMER_HAS_TRANSACTIONS,
message: 'Customer has associated transactions',
});
// Throws `onCustomerDeleted` event.
await this.eventPublisher.emitAsync(events.customers.onDeleted, {
customerId,

View File

@@ -39,11 +39,8 @@ export class DeleteItemService {
// Retrieve the given item or throw not found service error.
const oldItem = await this.itemModel()
.query()
.findById(itemId)
.throwIfNotFound();
// .queryAndThrowIfHasRelations({
// type: ERRORS.ITEM_HAS_ASSOCIATED_TRANSACTIONS,
// });
.findOne('id', itemId)
.deleteIfNoRelations();
// Delete item in unit of work.
return this.uow.withTransaction(async (trx: Knex.Transaction) => {

View File

@@ -9,6 +9,7 @@ import {
IVendorEventDeletingPayload,
} from '../types/Vendors.types';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { ERRORS } from '../constants';
@Injectable()
export class DeleteVendorService {
@@ -34,9 +35,6 @@ export class DeleteVendorService {
.query()
.findById(vendorId)
.throwIfNotFound();
// .queryAndThrowIfHasRelations({
// type: ERRORS.VENDOR_HAS_TRANSACTIONS,
// });
// Triggers `onVendorDeleting` event.
await this.eventPublisher.emitAsync(events.vendors.onDeleting, {
@@ -47,8 +45,13 @@ export class DeleteVendorService {
// Deletes vendor contact under unit-of-work.
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
// Deletes the vendor contact from the storage.
await this.vendorModel().query(trx).findById(vendorId).delete();
await this.vendorModel()
.query(trx)
.findById(vendorId)
.deleteIfNoRelations({
type: ERRORS.VENDOR_HAS_TRANSACTIONS,
message: 'Vendor has associated transactions',
});
// Triggers `onVendorDeleted` event.
await this.eventPublisher.emitAsync(events.vendors.onDeleted, {
vendorId,

View File

@@ -49,9 +49,6 @@ export class DeleteWarehouseService {
.query()
.findById(warehouseId)
.throwIfNotFound();
// .queryAndThrowIfHasRelations({
// type: ERRORS.WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS,
// });
// Validates the given warehouse before deleting.
await this.authorize(warehouseId);
@@ -70,8 +67,13 @@ export class DeleteWarehouseService {
eventPayload,
);
// Deletes the given warehouse from the storage.
await this.warehouseModel().query().findById(warehouseId).delete();
await this.warehouseModel()
.query()
.findById(warehouseId)
.deleteIfNoRelations({
type: ERRORS.WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS,
message: 'Warehouse has associated transactions',
});
// Triggers `onWarehouseCreated`.
await this.eventPublisher.emitAsync(
events.warehouse.onDeleted,

View File

@@ -1,6 +1,7 @@
// import { Model } from 'objection';
import { BaseModel } from '@/models/Model';
import { BaseModel, BaseQueryBuilder } from '@/models/Model';
import { Item } from '@/modules/Items/models/Item';
import { Model } from 'objection';
export class Warehouse extends BaseModel {
name!: string;
@@ -45,128 +46,134 @@ export class Warehouse extends BaseModel {
/**
* Relationship mapping.
*/
// static get relationMappings() {
// const SaleInvoice = require('models/SaleInvoice');
// const SaleEstimate = require('models/SaleEstimate');
// const SaleReceipt = require('models/SaleReceipt');
// const Bill = require('models/Bill');
// const VendorCredit = require('models/VendorCredit');
// const CreditNote = require('models/CreditNote');
// const InventoryTransaction = require('models/InventoryTransaction');
// const WarehouseTransfer = require('models/WarehouseTransfer');
// const InventoryAdjustment = require('models/InventoryAdjustment');
static get relationMappings() {
const { SaleInvoice } = require('../../SaleInvoices/models/SaleInvoice');
const { SaleEstimate } = require('../../SaleEstimates/models/SaleEstimate');
const { SaleReceipt } = require('../../SaleReceipts/models/SaleReceipt');
const { Bill } = require('../../Bills/models/Bill');
const { VendorCredit } = require('../../VendorCredit/models/VendorCredit');
const { CreditNote } = require('../../CreditNotes/models/CreditNote');
const {
InventoryTransaction,
} = require('../../InventoryCost/models/InventoryTransaction');
const {
WarehouseTransfer,
} = require('../../WarehousesTransfers/models/WarehouseTransfer');
const {
InventoryAdjustment,
} = require('../../InventoryAdjutments/models/InventoryAdjustment');
// return {
// /**
// * Warehouse may belongs to associated sale invoices.
// */
// invoices: {
// relation: Model.HasManyRelation,
// modelClass: SaleInvoice.default,
// join: {
// from: 'warehouses.id',
// to: 'sales_invoices.warehouseId',
// },
// },
return {
/**
* Warehouse may belongs to associated sale invoices.
*/
invoices: {
relation: Model.HasManyRelation,
modelClass: SaleInvoice,
join: {
from: 'warehouses.id',
to: 'sales_invoices.warehouseId',
},
},
// /**
// * Warehouse may belongs to associated sale estimates.
// */
// estimates: {
// relation: Model.HasManyRelation,
// modelClass: SaleEstimate.default,
// join: {
// from: 'warehouses.id',
// to: 'sales_estimates.warehouseId',
// },
// },
/**
* Warehouse may belongs to associated sale estimates.
*/
estimates: {
relation: Model.HasManyRelation,
modelClass: SaleEstimate,
join: {
from: 'warehouses.id',
to: 'sales_estimates.warehouseId',
},
},
// /**
// * Warehouse may belongs to associated sale receipts.
// */
// receipts: {
// relation: Model.HasManyRelation,
// modelClass: SaleReceipt.default,
// join: {
// from: 'warehouses.id',
// to: 'sales_receipts.warehouseId',
// },
// },
/**
* Warehouse may belongs to associated sale receipts.
*/
receipts: {
relation: Model.HasManyRelation,
modelClass: SaleReceipt,
join: {
from: 'warehouses.id',
to: 'sales_receipts.warehouseId',
},
},
// /**
// * Warehouse may belongs to associated bills.
// */
// bills: {
// relation: Model.HasManyRelation,
// modelClass: Bill.default,
// join: {
// from: 'warehouses.id',
// to: 'bills.warehouseId',
// },
// },
/**
* Warehouse may belongs to associated bills.
*/
bills: {
relation: Model.HasManyRelation,
modelClass: Bill,
join: {
from: 'warehouses.id',
to: 'bills.warehouseId',
},
},
// /**
// * Warehouse may belongs to associated credit notes.
// */
// creditNotes: {
// relation: Model.HasManyRelation,
// modelClass: CreditNote.default,
// join: {
// from: 'warehouses.id',
// to: 'credit_notes.warehouseId',
// },
// },
/**
* Warehouse may belongs to associated credit notes.
*/
creditNotes: {
relation: Model.HasManyRelation,
modelClass: CreditNote,
join: {
from: 'warehouses.id',
to: 'credit_notes.warehouseId',
},
},
// /**
// * Warehouse may belongs to associated to vendor credits.
// */
// vendorCredit: {
// relation: Model.HasManyRelation,
// modelClass: VendorCredit.default,
// join: {
// from: 'warehouses.id',
// to: 'vendor_credits.warehouseId',
// },
// },
/**
* Warehouse may belongs to associated to vendor credits.
*/
vendorCredit: {
relation: Model.HasManyRelation,
modelClass: VendorCredit,
join: {
from: 'warehouses.id',
to: 'vendor_credits.warehouseId',
},
},
// /**
// * Warehouse may belongs to associated to inventory transactions.
// */
// inventoryTransactions: {
// relation: Model.HasManyRelation,
// modelClass: InventoryTransaction.default,
// join: {
// from: 'warehouses.id',
// to: 'inventory_transactions.warehouseId',
// },
// },
/**
* Warehouse may belongs to associated to inventory transactions.
*/
inventoryTransactions: {
relation: Model.HasManyRelation,
modelClass: InventoryTransaction,
join: {
from: 'warehouses.id',
to: 'inventory_transactions.warehouseId',
},
},
// warehouseTransferTo: {
// relation: Model.HasManyRelation,
// modelClass: WarehouseTransfer.default,
// join: {
// from: 'warehouses.id',
// to: 'warehouses_transfers.toWarehouseId',
// },
// },
warehouseTransferTo: {
relation: Model.HasManyRelation,
modelClass: WarehouseTransfer,
join: {
from: 'warehouses.id',
to: 'warehouses_transfers.toWarehouseId',
},
},
// warehouseTransferFrom: {
// relation: Model.HasManyRelation,
// modelClass: WarehouseTransfer.default,
// join: {
// from: 'warehouses.id',
// to: 'warehouses_transfers.fromWarehouseId',
// },
// },
warehouseTransferFrom: {
relation: Model.HasManyRelation,
modelClass: WarehouseTransfer,
join: {
from: 'warehouses.id',
to: 'warehouses_transfers.fromWarehouseId',
},
},
// inventoryAdjustment: {
// relation: Model.HasManyRelation,
// modelClass: InventoryAdjustment.default,
// join: {
// from: 'warehouses.id',
// to: 'inventory_adjustments.warehouseId',
// },
// },
// };
// }
inventoryAdjustment: {
relation: Model.HasManyRelation,
modelClass: InventoryAdjustment,
join: {
from: 'warehouses.id',
to: 'inventory_adjustments.warehouseId',
},
},
};
}
}