mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 12:20:31 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
// import { Request, Response, NextFunction } from 'express';
|
||||
// import { ServiceError } from '@/exceptions';
|
||||
|
||||
// /**
|
||||
// * Handles branches integration service errors.
|
||||
// * @param {Error} error
|
||||
// * @param {Request} req
|
||||
// * @param {Response} res
|
||||
// * @param {NextFunction} next
|
||||
// */
|
||||
// export function BranchIntegrationErrorsMiddleware(
|
||||
// error: Error,
|
||||
// req: Request,
|
||||
// res: Response,
|
||||
// next: NextFunction
|
||||
// ) {
|
||||
// if (error instanceof ServiceError) {
|
||||
// if (error.errorType === 'WAREHOUSE_ID_NOT_FOUND') {
|
||||
// return res.boom.badRequest(null, {
|
||||
// errors: [{ type: 'WAREHOUSE_ID_NOT_FOUND', code: 5000 }],
|
||||
// });
|
||||
// }
|
||||
// if (error.errorType === 'BRANCH_ID_REQUIRED') {
|
||||
// return res.boom.badRequest(null, {
|
||||
// errors: [{ type: 'BRANCH_ID_REQUIRED', code: 5100 }],
|
||||
// });
|
||||
// }
|
||||
// if (error.errorType === 'BRANCH_ID_NOT_FOUND') {
|
||||
// return res.boom.badRequest(null, {
|
||||
// errors: [{ type: 'BRANCH_ID_NOT_FOUND', code: 5300 }],
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// next(error);
|
||||
// }
|
||||
93
packages/server/src/modules/Branches/Branches.controller.ts
Normal file
93
packages/server/src/modules/Branches/Branches.controller.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
} from '@nestjs/common';
|
||||
import { BranchesApplication } from './BranchesApplication.service';
|
||||
import { CreateBranchDto, EditBranchDto } from './dtos/Branch.dto';
|
||||
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@Controller('branches')
|
||||
@ApiTags('branches')
|
||||
export class BranchesController {
|
||||
constructor(private readonly branchesApplication: BranchesApplication) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Retrieves the branches.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branches have been successfully retrieved.',
|
||||
})
|
||||
getBranches() {
|
||||
return this.branchesApplication.getBranches();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: 'Retrieves the branch details.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branch details have been successfully retrieved.',
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'The branch not found.' })
|
||||
getBranch(@Param('id') id: string) {
|
||||
return this.branchesApplication.getBranch(Number(id));
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new branch.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branch has been successfully created.',
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'The branch not found.' })
|
||||
createBranch(@Body() createBranchDTO: CreateBranchDto) {
|
||||
return this.branchesApplication.createBranch(createBranchDTO);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@ApiOperation({ summary: 'Edit the given branch.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branch has been successfully edited.',
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'The branch not found.' })
|
||||
editBranch(@Param('id') id: string, @Body() editBranchDTO: EditBranchDto) {
|
||||
return this.branchesApplication.editBranch(Number(id), editBranchDTO);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@ApiOperation({ summary: 'Delete the given branch.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branch has been successfully deleted.',
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'The branch not found.' })
|
||||
deleteBranch(@Param('id') id: string) {
|
||||
return this.branchesApplication.deleteBranch(Number(id));
|
||||
}
|
||||
|
||||
@Post('activate')
|
||||
@ApiOperation({ summary: 'Activate the branches feature.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branches feature has been successfully activated.',
|
||||
})
|
||||
activateBranches() {
|
||||
return this.branchesApplication.activateBranches();
|
||||
}
|
||||
|
||||
@Put(':id/mark-as-primary')
|
||||
@ApiOperation({ summary: 'Mark the given branch as primary.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The branch has been successfully marked as primary.',
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'The branch not found.' })
|
||||
markBranchAsPrimary(@Param('id') id: string) {
|
||||
return this.branchesApplication.markBranchAsPrimary(Number(id));
|
||||
}
|
||||
}
|
||||
77
packages/server/src/modules/Branches/Branches.module.ts
Normal file
77
packages/server/src/modules/Branches/Branches.module.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||
import { TenancyDatabaseModule } from '../Tenancy/TenancyDB/TenancyDB.module';
|
||||
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
||||
import { BranchesController } from './Branches.controller';
|
||||
import { CreateBranchService } from './commands/CreateBranch.service';
|
||||
import { DeleteBranchService } from './commands/DeleteBranch.service';
|
||||
import { EditBranchService } from './commands/EditBranch.service';
|
||||
import { MarkBranchAsPrimaryService } from './commands/MarkBranchAsPrimary.service';
|
||||
import { GetBranchService } from './queries/GetBranch.service';
|
||||
import { GetBranchesService } from './queries/GetBranches.service';
|
||||
import { ActivateBranches } from './commands/ActivateBranchesFeature.service';
|
||||
import { BranchesApplication } from './BranchesApplication.service';
|
||||
import { BranchesSettingsService } from './BranchesSettings';
|
||||
import { BranchCommandValidator } from './commands/BranchCommandValidator.service';
|
||||
import { BranchTransactionDTOTransformer } from './integrations/BranchTransactionDTOTransform';
|
||||
import { ManualJournalBranchesDTOTransformer } from './integrations/ManualJournals/ManualJournalDTOTransformer.service';
|
||||
import { BillBranchValidateSubscriber } from './subscribers/Validators/BillBranchSubscriber';
|
||||
import { InventoryAdjustmentBranchValidateSubscriber } from './subscribers/Validators/InventoryAdjustmentBranchValidatorSubscriber';
|
||||
import { ExpenseBranchValidateSubscriber } from './subscribers/Validators/ExpenseBranchSubscriber';
|
||||
import { CreditNoteBranchValidateSubscriber } from './subscribers/Validators/CreditNoteBranchesSubscriber';
|
||||
import { CreditNoteRefundBranchValidateSubscriber } from './subscribers/Validators/CreditNoteRefundBranchSubscriber';
|
||||
import { ContactBranchValidateSubscriber } from './subscribers/Validators/ContactOpeningBalanceBranchSubscriber';
|
||||
import { ManualJournalBranchValidateSubscriber } from './subscribers/Validators/ManualJournalBranchSubscriber';
|
||||
import { SaleEstimateBranchValidateSubscriber } from './subscribers/Validators/SaleEstimateMultiBranchesSubscriber';
|
||||
import { PaymentMadeBranchValidateSubscriber } from './subscribers/Validators/PaymentMadeBranchSubscriber';
|
||||
import { PaymentReceiveBranchValidateSubscriber } from './subscribers/Validators/PaymentReceiveBranchSubscriber';
|
||||
import { SaleReceiptBranchValidateSubscriber } from './subscribers/Validators/SaleReceiptBranchesSubscriber';
|
||||
import { VendorCreditBranchValidateSubscriber } from './subscribers/Validators/VendorCreditBranchSubscriber';
|
||||
import { ValidateBranchExistance } from './Integrations/ValidateBranchExistance';
|
||||
import { ManualJournalBranchesValidator } from './Integrations/ManualJournals/ManualJournalsBranchesValidator';
|
||||
import { CashflowTransactionsActivateBranches } from './integrations/Cashflow/CashflowActivateBranches';
|
||||
import { ExpensesActivateBranches } from './integrations/Expense/ExpensesActivateBranches';
|
||||
import { FeaturesModule } from '../Features/Features.module';
|
||||
|
||||
@Module({
|
||||
imports: [TenancyDatabaseModule, FeaturesModule],
|
||||
controllers: [BranchesController],
|
||||
providers: [
|
||||
CreateBranchService,
|
||||
EditBranchService,
|
||||
DeleteBranchService,
|
||||
GetBranchService,
|
||||
GetBranchesService,
|
||||
MarkBranchAsPrimaryService,
|
||||
ActivateBranches,
|
||||
BranchesApplication,
|
||||
BranchesSettingsService,
|
||||
TenancyContext,
|
||||
TransformerInjectable,
|
||||
BranchCommandValidator,
|
||||
BranchTransactionDTOTransformer,
|
||||
ManualJournalBranchesDTOTransformer,
|
||||
BillBranchValidateSubscriber,
|
||||
CreditNoteBranchValidateSubscriber,
|
||||
CreditNoteRefundBranchValidateSubscriber,
|
||||
ContactBranchValidateSubscriber,
|
||||
ExpenseBranchValidateSubscriber,
|
||||
InventoryAdjustmentBranchValidateSubscriber,
|
||||
ManualJournalBranchValidateSubscriber,
|
||||
PaymentMadeBranchValidateSubscriber,
|
||||
PaymentReceiveBranchValidateSubscriber,
|
||||
SaleEstimateBranchValidateSubscriber,
|
||||
SaleReceiptBranchValidateSubscriber,
|
||||
VendorCreditBranchValidateSubscriber,
|
||||
ValidateBranchExistance,
|
||||
ManualJournalBranchesValidator,
|
||||
CashflowTransactionsActivateBranches,
|
||||
ExpensesActivateBranches
|
||||
],
|
||||
exports: [
|
||||
BranchesSettingsService,
|
||||
BranchTransactionDTOTransformer,
|
||||
ManualJournalBranchesDTOTransformer,
|
||||
],
|
||||
})
|
||||
export class BranchesModule {}
|
||||
46
packages/server/src/modules/Branches/Branches.types.ts
Normal file
46
packages/server/src/modules/Branches/Branches.types.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Branch } from './models/Branch.model';
|
||||
|
||||
export interface ICreateBranchDTO {
|
||||
name: string;
|
||||
code: string;
|
||||
primary?: boolean;
|
||||
}
|
||||
export interface IEditBranchDTO {
|
||||
code: string;
|
||||
}
|
||||
|
||||
export interface IBranchCreatePayload {
|
||||
// tenantId: number;
|
||||
createBranchDTO: ICreateBranchDTO;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IBranchCreatedPayload {}
|
||||
|
||||
export interface IBranchEditPayload {}
|
||||
export interface IBranchEditedPayload {}
|
||||
|
||||
export interface IBranchDeletePayload {}
|
||||
export interface IBranchDeletedPayload {}
|
||||
|
||||
export interface IBranchesActivatePayload {
|
||||
// tenantId: number;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IBranchesActivatedPayload {
|
||||
// tenantId: number;
|
||||
primaryBranch: Branch;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IBranchMarkAsPrimaryPayload {
|
||||
// tenantId: number;
|
||||
oldBranch: Branch;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IBranchMarkedAsPrimaryPayload {
|
||||
// tenantId: number;
|
||||
oldBranch: Branch;
|
||||
markedBranch: Branch;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { ICreateBranchDTO, IEditBranchDTO } from './Branches.types';
|
||||
import { ActivateBranches } from './commands/ActivateBranchesFeature.service';
|
||||
import {
|
||||
CreateBranchService,
|
||||
} from './commands/CreateBranch.service';
|
||||
import {
|
||||
DeleteBranchService,
|
||||
} from './commands/DeleteBranch.service';
|
||||
import { EditBranchService } from './commands/EditBranch.service';
|
||||
import { GetBranchService } from './queries/GetBranch.service';
|
||||
import { GetBranchesService } from './queries/GetBranches.service';
|
||||
import { MarkBranchAsPrimaryService } from './commands/MarkBranchAsPrimary.service';
|
||||
import { Branch } from './models/Branch.model';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateBranchDto, EditBranchDto } from './dtos/Branch.dto';
|
||||
|
||||
@Injectable()
|
||||
export class BranchesApplication {
|
||||
/**
|
||||
* @param {CreateBranchService} createBranchService - Create branch service.
|
||||
* @param {EditBranchService} editBranchService - Edit branch service.
|
||||
* @param {DeleteBranchService} deleteBranchService - Delete branch service.
|
||||
* @param {GetBranchService} getBranchService - Get branch service.
|
||||
* @param {GetBranchesService} getBranchesService - Get branches service.
|
||||
* @param {ActivateBranches} activateBranchesService - Activate branches service.
|
||||
* @param {MarkBranchAsPrimaryService} markBranchAsPrimaryService - Mark branch as primary service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly createBranchService: CreateBranchService,
|
||||
private readonly editBranchService: EditBranchService,
|
||||
private readonly deleteBranchService: DeleteBranchService,
|
||||
private readonly getBranchService: GetBranchService,
|
||||
private readonly getBranchesService: GetBranchesService,
|
||||
private readonly activateBranchesService: ActivateBranches,
|
||||
private readonly markBranchAsPrimaryService: MarkBranchAsPrimaryService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves branches list.
|
||||
* @returns {Branch[]}
|
||||
*/
|
||||
public getBranches = (): Promise<Branch[]> => {
|
||||
return this.getBranchesService.getBranches();
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the given branch details.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public getBranch = (branchId: number): Promise<Branch> => {
|
||||
return this.getBranchService.getBranch(branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new branch.
|
||||
* @param {number} tenantId -
|
||||
* @param {ICreateBranchDTO} createBranchDTO
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public createBranch = (
|
||||
createBranchDTO: CreateBranchDto,
|
||||
): Promise<Branch> => {
|
||||
return this.createBranchService.createBranch(createBranchDTO);
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits the given branch.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @param {IEditBranchDTO} editBranchDTO - Edit branch DTO.
|
||||
* @returns {Promise<Branch>}
|
||||
*/
|
||||
public editBranch = (
|
||||
branchId: number,
|
||||
editBranchDTO: EditBranchDto,
|
||||
): Promise<Branch> => {
|
||||
return this.editBranchService.editBranch(branchId, editBranchDTO);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the given branch.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteBranch = (branchId: number): Promise<void> => {
|
||||
return this.deleteBranchService.deleteBranch(branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Activates the given branches.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public activateBranches = (): Promise<void> => {
|
||||
return this.activateBranchesService.activateBranches();
|
||||
};
|
||||
|
||||
/**
|
||||
* Marks the given branch as primary.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public markBranchAsPrimary = async (
|
||||
branchId: number,
|
||||
): Promise<Branch> => {
|
||||
return this.markBranchAsPrimaryService.markAsPrimary(branchId);
|
||||
};
|
||||
}
|
||||
30
packages/server/src/modules/Branches/BranchesSettings.ts
Normal file
30
packages/server/src/modules/Branches/BranchesSettings.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { SettingsStore } from '../Settings/SettingsStore';
|
||||
import { SETTINGS_PROVIDER } from '../Settings/Settings.types';
|
||||
import { Features } from '@/common/types/Features';
|
||||
|
||||
@Injectable()
|
||||
export class BranchesSettingsService {
|
||||
constructor(
|
||||
@Inject(SETTINGS_PROVIDER)
|
||||
private readonly settingsStore: () => SettingsStore,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Marks multi-branches as activated.
|
||||
*/
|
||||
public markMultiBranchesAsActivated = async () => {
|
||||
const settingsStore = await this.settingsStore();
|
||||
|
||||
settingsStore.set({ group: 'features', key: Features.BRANCHES, value: 1 });
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves whether multi-branches is active.
|
||||
*/
|
||||
public isMultiBranchesActive = async () => {
|
||||
const settingsStore = await this.settingsStore();
|
||||
|
||||
return settingsStore.get({ group: 'features', key: Features.BRANCHES });
|
||||
};
|
||||
}
|
||||
30
packages/server/src/modules/Branches/CRUDBranch.ts
Normal file
30
packages/server/src/modules/Branches/CRUDBranch.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// import { Inject } from "typedi";
|
||||
// import { ServiceError } from "exceptions";
|
||||
// import HasTenancyService from "services/Tenancy/TenancyService";
|
||||
// import { ERRORS } from "./constants";
|
||||
|
||||
// export class CURDBranch {
|
||||
// @Inject()
|
||||
// tenancy: HasTenancyService;
|
||||
|
||||
// /**
|
||||
// *
|
||||
// * @param branch
|
||||
// */
|
||||
// throwIfBranchNotFound = (branch) => {
|
||||
// if (!branch) {
|
||||
// throw new ServiceError(ERRORS.BRANCH_NOT_FOUND);
|
||||
// }
|
||||
// }
|
||||
|
||||
// getBranchOrThrowNotFound = async (tenantId: number, branchId: number) => {
|
||||
// const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
// const foundBranch = await Branch.query().findById(branchId);
|
||||
|
||||
// if (!foundBranch) {
|
||||
// throw new ServiceError(ERRORS.BRANCH_NOT_FOUND);
|
||||
// }
|
||||
// return foundBranch;
|
||||
// }
|
||||
// }
|
||||
50
packages/server/src/modules/Branches/EventsProvider.ts
Normal file
50
packages/server/src/modules/Branches/EventsProvider.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
// import {
|
||||
// CreditNoteActivateBranchesSubscriber,
|
||||
// PaymentReceiveActivateBranchesSubscriber,
|
||||
// SaleEstimatesActivateBranchesSubscriber,
|
||||
// SaleInvoicesActivateBranchesSubscriber,
|
||||
// PaymentMadeActivateBranchesSubscriber,
|
||||
// SaleReceiptsActivateBranchesSubscriber,
|
||||
// } from './Subscribers/Activate';
|
||||
// import {
|
||||
// BillBranchValidateSubscriber,
|
||||
// VendorCreditBranchValidateSubscriber,
|
||||
// PaymentMadeBranchValidateSubscriber,
|
||||
// SaleEstimateBranchValidateSubscriber,
|
||||
// CreditNoteBranchValidateSubscriber,
|
||||
// ExpenseBranchValidateSubscriber,
|
||||
// SaleReceiptBranchValidateSubscriber,
|
||||
// ManualJournalBranchValidateSubscriber,
|
||||
// PaymentReceiveBranchValidateSubscriber,
|
||||
// CreditNoteRefundBranchValidateSubscriber,
|
||||
// CashflowBranchDTOValidatorSubscriber,
|
||||
// VendorCreditRefundBranchValidateSubscriber,
|
||||
// InvoiceBranchValidateSubscriber,
|
||||
// ContactBranchValidateSubscriber,
|
||||
// InventoryAdjustmentBranchValidateSubscriber
|
||||
// } from './Subscribers/Validators';
|
||||
|
||||
// export default () => [
|
||||
// BillBranchValidateSubscriber,
|
||||
// CreditNoteBranchValidateSubscriber,
|
||||
// ExpenseBranchValidateSubscriber,
|
||||
// PaymentMadeBranchValidateSubscriber,
|
||||
// SaleReceiptBranchValidateSubscriber,
|
||||
// VendorCreditBranchValidateSubscriber,
|
||||
// SaleEstimateBranchValidateSubscriber,
|
||||
// ManualJournalBranchValidateSubscriber,
|
||||
// PaymentReceiveBranchValidateSubscriber,
|
||||
// CreditNoteRefundBranchValidateSubscriber,
|
||||
// VendorCreditRefundBranchValidateSubscriber,
|
||||
|
||||
// CreditNoteActivateBranchesSubscriber,
|
||||
// PaymentReceiveActivateBranchesSubscriber,
|
||||
// SaleEstimatesActivateBranchesSubscriber,
|
||||
// SaleInvoicesActivateBranchesSubscriber,
|
||||
// PaymentMadeActivateBranchesSubscriber,
|
||||
// SaleReceiptsActivateBranchesSubscriber,
|
||||
// CashflowBranchDTOValidatorSubscriber,
|
||||
// InvoiceBranchValidateSubscriber,
|
||||
// ContactBranchValidateSubscriber,
|
||||
// InventoryAdjustmentBranchValidateSubscriber
|
||||
// ];
|
||||
@@ -0,0 +1,78 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { I18nService } from 'nestjs-i18n';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ERRORS } from '../constants';
|
||||
import {
|
||||
IBranchesActivatedPayload,
|
||||
IBranchesActivatePayload,
|
||||
} from '../Branches.types';
|
||||
import { CreateBranchService } from './CreateBranch.service';
|
||||
import { BranchesSettingsService } from '../BranchesSettings';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class ActivateBranches {
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly createBranch: CreateBranchService,
|
||||
private readonly branchesSettings: BranchesSettingsService,
|
||||
private readonly i18n: I18nService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Throws service error if multi-branches feature is already activated.
|
||||
*/
|
||||
private throwIfMultiBranchesActivated = (isActivated: boolean) => {
|
||||
if (isActivated) {
|
||||
throw new ServiceError(ERRORS.MUTLI_BRANCHES_ALREADY_ACTIVATED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new initial branch.
|
||||
*/
|
||||
private createInitialBranch = () => {
|
||||
return this.createBranch.createBranch({
|
||||
name: this.i18n.t('branches.head_branch'),
|
||||
code: '10001',
|
||||
primary: true,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate multi-branches feature.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public activateBranches = async (): Promise<void> => {
|
||||
const isActivated = await this.branchesSettings.isMultiBranchesActive();
|
||||
|
||||
// Throw error if mutli-branches is already activated.
|
||||
this.throwIfMultiBranchesActivated(isActivated);
|
||||
|
||||
// Activate multi-branches under unit-of-work environment.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchActivate` branch.
|
||||
await this.eventPublisher.emitAsync(events.branch.onActivate, {
|
||||
trx,
|
||||
} as IBranchesActivatePayload);
|
||||
|
||||
// Create a new branch as primary branch.
|
||||
const primaryBranch = await this.createInitialBranch();
|
||||
|
||||
// Mark the mutli-branches is activated.
|
||||
await this.branchesSettings.markMultiBranchesAsActivated();
|
||||
|
||||
// Triggers `onBranchActivated` branch.
|
||||
await this.eventPublisher.emitAsync(events.branch.onActivated, {
|
||||
primaryBranch,
|
||||
trx,
|
||||
} as IBranchesActivatedPayload);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ERRORS } from '../constants';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
|
||||
import { ServiceError } from '../../Items/ServiceError';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
@Injectable()
|
||||
export class BranchCommandValidator {
|
||||
constructor(
|
||||
@Inject(Branch.name)
|
||||
private readonly branchModel: TenantModelProxy<typeof Branch>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validates the given branch whether is not only warehouse.
|
||||
* @param {number} branchId
|
||||
*/
|
||||
public validateBranchNotOnlyWarehouse = async (branchId: number) => {
|
||||
const warehouses = await this.branchModel()
|
||||
.query()
|
||||
.whereNot('id', branchId);
|
||||
|
||||
if (warehouses.length === 0) {
|
||||
throw new ServiceError(ERRORS.COULD_NOT_DELETE_ONLY_BRANCH);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the given branch whether is unique.
|
||||
* @param {string} code - Branch code.
|
||||
* @param {number} exceptBranchId - Branch id to except.
|
||||
*/
|
||||
public validateBranchCodeUnique = async (
|
||||
code: string,
|
||||
exceptBranchId?: number,
|
||||
): Promise<void> => {
|
||||
const branch = await this.branchModel()
|
||||
.query()
|
||||
.onBuild((query) => {
|
||||
query.select(['id']);
|
||||
query.where('code', code);
|
||||
|
||||
if (exceptBranchId) {
|
||||
query.whereNot('id', exceptBranchId);
|
||||
}
|
||||
})
|
||||
.first();
|
||||
|
||||
if (branch) {
|
||||
throw new ServiceError(ERRORS.BRANCH_CODE_NOT_UNIQUE);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { IBranchCreatedPayload, IBranchCreatePayload } from '../Branches.types';
|
||||
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { CreateBranchDto } from '../dtos/Branch.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateBranchService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of Work for tenant database transactions.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter for publishing branch creation events.
|
||||
* @param {typeof Branch} branchModel - The Branch model class for database operations.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(Branch.name)
|
||||
private readonly branchModel: TenantModelProxy<typeof Branch>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates a new branch.
|
||||
* @param {CreateBranchDto} createBranchDTO
|
||||
* @returns {Promise<Branch>}
|
||||
*/
|
||||
public createBranch = async (
|
||||
createBranchDTO: CreateBranchDto,
|
||||
): Promise<Branch> => {
|
||||
// Creates a new branch under unit-of-work.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
createBranchDTO,
|
||||
trx,
|
||||
} as IBranchCreatePayload);
|
||||
|
||||
const branch = await this.branchModel()
|
||||
.query()
|
||||
.insertAndFetch({
|
||||
...createBranchDTO,
|
||||
});
|
||||
// Triggers `onBranchCreated` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
createBranchDTO,
|
||||
branch,
|
||||
trx,
|
||||
} as IBranchCreatedPayload);
|
||||
|
||||
return branch;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { IBranchDeletedPayload, IBranchDeletePayload } from '../Branches.types';
|
||||
import { BranchCommandValidator } from './BranchCommandValidator.service';
|
||||
import { ERRORS } from '../constants';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteBranchService {
|
||||
constructor(
|
||||
@Inject(Branch.name)
|
||||
private readonly branchModel: TenantModelProxy<typeof Branch>,
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly validator: BranchCommandValidator,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validates the branch deleting.
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
private authorize = async (branchId: number): Promise<void> => {
|
||||
await this.validator.validateBranchNotOnlyWarehouse(branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes branch.
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteBranch = async (branchId: number): Promise<void> => {
|
||||
// Retrieves the old branch or throw not found service error.
|
||||
const oldBranch = await this.branchModel()
|
||||
.query()
|
||||
.findById(branchId)
|
||||
.throwIfNotFound();
|
||||
// .queryAndThrowIfHasRelations({
|
||||
// type: ERRORS.BRANCH_HAS_ASSOCIATED_TRANSACTIONS,
|
||||
// });
|
||||
|
||||
// Authorize the branch before deleting.
|
||||
await this.authorize(branchId);
|
||||
|
||||
// Deletes branch under unit-of-work.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchDeletePayload);
|
||||
|
||||
await this.branchModel().query().findById(branchId).delete();
|
||||
|
||||
// Triggers `onBranchCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchDeletedPayload);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { IBranchEditedPayload, IBranchEditPayload } from '../Branches.types';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { EditBranchDto } from '../dtos/Branch.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EditBranchService {
|
||||
constructor(
|
||||
@Inject(Branch.name)
|
||||
private readonly branchModel: TenantModelProxy<typeof Branch>,
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Edits branch.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @param {IEditBranchDTO} editBranchDTO - Edit branch data.
|
||||
*/
|
||||
public editBranch = async (
|
||||
branchId: number,
|
||||
editBranchDTO: EditBranchDto,
|
||||
) => {
|
||||
// Retrieves the old branch or throw not found service error.
|
||||
const oldBranch = await this.branchModel()
|
||||
.query()
|
||||
.findById(branchId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Deletes branch under unit-of-work.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchEdit` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchEditPayload);
|
||||
|
||||
// Edits the branch on the storage.
|
||||
const branch = await this.branchModel()
|
||||
.query()
|
||||
.patchAndFetchById(branchId, {
|
||||
...editBranchDTO,
|
||||
});
|
||||
|
||||
// Triggers `onBranchEdited` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
oldBranch,
|
||||
branch,
|
||||
trx,
|
||||
} as IBranchEditedPayload);
|
||||
|
||||
return branch;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IBranchMarkAsPrimaryPayload,
|
||||
IBranchMarkedAsPrimaryPayload,
|
||||
} from '../Branches.types';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class MarkBranchAsPrimaryService {
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(Branch.name)
|
||||
private readonly branchModel: TenantModelProxy<typeof Branch>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Marks the given branch as primary.
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public async markAsPrimary(branchId: number): Promise<Branch> {
|
||||
// Retrieves the old branch or throw not found service error.
|
||||
const oldBranch = await this.branchModel()
|
||||
.query()
|
||||
.findById(branchId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Updates the branches under unit-of-work environment.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchMarkPrimary` event.
|
||||
await this.eventPublisher.emitAsync(events.branch.onMarkPrimary, {
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchMarkAsPrimaryPayload);
|
||||
|
||||
// Updates all branches as not primary.
|
||||
await this.branchModel().query(trx).update({ primary: false });
|
||||
|
||||
// Updates the given branch as primary.
|
||||
const markedBranch = await this.branchModel()
|
||||
.query(trx)
|
||||
.patchAndFetchById(branchId, {
|
||||
primary: true,
|
||||
});
|
||||
|
||||
// Triggers `onBranchMarkedPrimary` event.
|
||||
await this.eventPublisher.emitAsync(events.branch.onMarkedPrimary, {
|
||||
markedBranch,
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchMarkedAsPrimaryPayload);
|
||||
|
||||
return markedBranch;
|
||||
});
|
||||
}
|
||||
}
|
||||
7
packages/server/src/modules/Branches/constants.ts
Normal file
7
packages/server/src/modules/Branches/constants.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const ERRORS = {
|
||||
BRANCH_NOT_FOUND: 'BRANCH_NOT_FOUND',
|
||||
MUTLI_BRANCHES_ALREADY_ACTIVATED: 'MUTLI_BRANCHES_ALREADY_ACTIVATED',
|
||||
COULD_NOT_DELETE_ONLY_BRANCH: 'COULD_NOT_DELETE_ONLY_BRANCH',
|
||||
BRANCH_CODE_NOT_UNIQUE: 'BRANCH_CODE_NOT_UNIQUE',
|
||||
BRANCH_HAS_ASSOCIATED_TRANSACTIONS: 'BRANCH_HAS_ASSOCIATED_TRANSACTIONS'
|
||||
};
|
||||
89
packages/server/src/modules/Branches/dtos/Branch.dto.ts
Normal file
89
packages/server/src/modules/Branches/dtos/Branch.dto.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUrl,
|
||||
} from 'class-validator';
|
||||
|
||||
class CommandBranchDto {
|
||||
@ApiProperty({
|
||||
description: 'Branch name',
|
||||
example: 'Main Branch',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Whether this is the primary branch',
|
||||
example: true,
|
||||
default: false,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
primary?: boolean;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch code',
|
||||
example: 'BR001',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
code?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch address',
|
||||
example: '123 Main Street',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
address?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch city',
|
||||
example: 'New York',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
city?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch country',
|
||||
example: 'USA',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
country?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch phone number',
|
||||
example: '+1-555-123-4567',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone_number?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch email',
|
||||
example: 'branch@example.com',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
@IsString()
|
||||
email?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Branch website',
|
||||
example: 'https://www.example.com/branch',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsUrl()
|
||||
@IsString()
|
||||
website?: string;
|
||||
}
|
||||
|
||||
export class CreateBranchDto extends CommandBranchDto {}
|
||||
export class EditBranchDto extends CommandBranchDto {}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { omit } from 'lodash';
|
||||
import { BranchesSettingsService } from '../BranchesSettings';
|
||||
|
||||
@Injectable()
|
||||
export class BranchTransactionDTOTransformer {
|
||||
constructor(private readonly branchesSettings: BranchesSettingsService) {}
|
||||
|
||||
/**
|
||||
* Excludes DTO branch id when mutli-warehouses feature is inactive.
|
||||
* @returns {any}
|
||||
*/
|
||||
private excludeDTOBranchIdWhenInactive = async <
|
||||
T extends { branchId?: number },
|
||||
>(
|
||||
DTO: T,
|
||||
): Promise<Omit<T, 'branchId'> | T> => {
|
||||
const isActive = await this.branchesSettings.isMultiBranchesActive();
|
||||
|
||||
return !isActive ? omit(DTO, ['branchId']) : DTO;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the input DTO for branches feature.
|
||||
* @param {T} DTO -
|
||||
* @returns {Omit<T, 'branchId'> | T}
|
||||
*/
|
||||
public transformDTO = async <T extends { branchId?: number }>(
|
||||
DTO: T,
|
||||
): Promise<Omit<T, 'branchId'> | T> => {
|
||||
return this.excludeDTOBranchIdWhenInactive<T>(DTO);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { BankTransaction } from '@/modules/BankingTransactions/models/BankTransaction';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class CashflowTransactionsActivateBranches {
|
||||
constructor(
|
||||
@Inject(BankTransaction.name)
|
||||
private readonly bankTransaction: TenantModelProxy<typeof BankTransaction>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all cashflow transactions with the primary branch.
|
||||
* @param {number} primaryBranchId - The primary branch id.
|
||||
* @param {Knex.Transaction} trx - The database transaction.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateCashflowTransactionsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the cashflow transactions with primary branch.
|
||||
await this.bankTransaction()
|
||||
.query(trx)
|
||||
.update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Expense } from '@/modules/Expenses/models/Expense.model';
|
||||
|
||||
@Injectable()
|
||||
export class ExpensesActivateBranches {
|
||||
constructor(
|
||||
@Inject(Expense.name)
|
||||
private readonly expenseModel: TenantModelProxy<typeof Expense>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all expenses transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateExpensesWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the expenses with primary branch.
|
||||
await this.expenseModel().query(trx).update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ManualJournal } from '@/modules/ManualJournals/models/ManualJournal';
|
||||
|
||||
@Injectable()
|
||||
export class ManualJournalsActivateBranches {
|
||||
constructor(
|
||||
private readonly manualJournalModel: TenantModelProxy<typeof ManualJournal>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all manual journals transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateManualJournalsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the manual journal with primary branch.
|
||||
await this.manualJournalModel()
|
||||
.query(trx)
|
||||
.update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { omit } from 'lodash';
|
||||
import { BranchesSettingsService } from '../../BranchesSettings';
|
||||
import { IManualJournalDTO } from '@/modules/ManualJournals/types/ManualJournals.types';
|
||||
|
||||
@Injectable()
|
||||
export class ManualJournalBranchesDTOTransformer {
|
||||
constructor(
|
||||
@Inject()
|
||||
private readonly branchesSettings: BranchesSettingsService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param DTO
|
||||
* @returns
|
||||
*/
|
||||
private excludeDTOBranchIdWhenInactive = async (
|
||||
DTO: IManualJournalDTO,
|
||||
): Promise<IManualJournalDTO> => {
|
||||
const isActive = await this.branchesSettings.isMultiBranchesActive();
|
||||
|
||||
if (isActive) {
|
||||
return DTO;
|
||||
}
|
||||
return {
|
||||
...DTO,
|
||||
entries: DTO.entries.map((e) => omit(e, ['branchId'])),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public transformDTO = async (
|
||||
DTO: IManualJournalDTO,
|
||||
): Promise<IManualJournalDTO> => {
|
||||
return this.excludeDTOBranchIdWhenInactive(DTO);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { IManualJournalDTO } from '@/modules/ManualJournals/types/ManualJournals.types';
|
||||
import { IManualJournalEntryDTO } from '@/modules/ManualJournals/types/ManualJournals.types';
|
||||
import { ERRORS } from './constants';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
|
||||
@Injectable()
|
||||
export class ManualJournalBranchesValidator {
|
||||
/**
|
||||
* Validates the DTO entries should have branch id.
|
||||
* @param {IManualJournalDTO} manualJournalDTO
|
||||
*/
|
||||
public validateEntriesHasBranchId = async (
|
||||
manualJournalDTO: IManualJournalDTO,
|
||||
) => {
|
||||
const hasNoIdEntries = manualJournalDTO.entries.filter(
|
||||
(entry: IManualJournalEntryDTO) =>
|
||||
!entry.branchId && !manualJournalDTO.branchId,
|
||||
);
|
||||
if (hasNoIdEntries.length > 0) {
|
||||
throw new ServiceError(ERRORS.MANUAL_JOURNAL_ENTRIES_HAVE_NO_BRANCH_ID);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export const ERRORS = {
|
||||
MANUAL_JOURNAL_ENTRIES_HAVE_NO_BRANCH_ID:
|
||||
'MANUAL_JOURNAL_ENTRIES_HAVE_NO_BRANCH_ID',
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
|
||||
@Injectable()
|
||||
export class BillActivateBranches {
|
||||
constructor(private readonly billModel: TenantModelProxy<typeof Bill>) {}
|
||||
|
||||
/**
|
||||
* Updates all bills transactions with the primary branch.
|
||||
* @param {number} tenantId
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateBillsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the sale invoice with primary branch.
|
||||
await Bill.query(trx).update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Knex } from 'knex';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { BillPayment } from '@/modules/BillPayments/models/BillPayment';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class BillPaymentsActivateBranches {
|
||||
constructor(
|
||||
private readonly billPaymentModel: TenantModelProxy<typeof BillPayment>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all bills payments transcations with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateBillPaymentsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
// Updates the bill payments with primary branch.
|
||||
await this.billPaymentModel().query(trx).update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditActivateBranches {
|
||||
constructor(
|
||||
private readonly vendorCreditModel: TenantModelProxy<typeof VendorCredit>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all vendor credits transcations with the primary branch.
|
||||
* @param {number} tenantId
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateVendorCreditsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the vendors credits with primary branch.
|
||||
await this.vendorCreditModel()
|
||||
.query(trx)
|
||||
.update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Knex } from 'knex';
|
||||
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteActivateBranches {
|
||||
constructor(
|
||||
private readonly creditNoteModel: TenantModelProxy<typeof CreditNote>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all creidt notes transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateCreditsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
// Updates the sale invoice with primary branch.
|
||||
await this.creditNoteModel().query(trx).update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { PaymentReceived } from '@/modules/PaymentReceived/models/PaymentReceived';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentReceiveActivateBranches {
|
||||
constructor(
|
||||
private readonly paymentReceivedModel: TenantModelProxy<typeof PaymentReceived>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all creidt notes transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updatePaymentsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
// Updates the sale invoice with primary branch.
|
||||
await this.paymentReceivedModel().query(trx).update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Knex } from 'knex';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { PaymentReceived } from '@/modules/PaymentReceived/models/PaymentReceived';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class SaleEstimateActivateBranches {
|
||||
constructor(
|
||||
@Inject(PaymentReceived.name)
|
||||
private readonly paymentReceivedModel: TenantModelProxy<typeof PaymentReceived>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all sale estimates transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateEstimatesWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction
|
||||
) => {
|
||||
// Updates the sale invoice with primary branch.
|
||||
await this.paymentReceivedModel().query(trx).update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class SaleInvoiceActivateBranches {
|
||||
constructor(
|
||||
private readonly saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all sale invoices transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateInvoicesWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the sale invoice with primary branch.
|
||||
await this.saleInvoiceModel()
|
||||
.query(trx)
|
||||
.update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SaleReceipt } from '@/modules/SaleReceipts/models/SaleReceipt';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class SaleReceiptActivateBranches {
|
||||
constructor(
|
||||
private readonly saleReceiptModel: TenantModelProxy<typeof SaleReceipt>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all sale receipts transactions with the primary branch.
|
||||
* @param {number} primaryBranchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateReceiptsWithBranch = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Updates the sale receipt with primary branch.
|
||||
await this.saleReceiptModel()
|
||||
.query(trx)
|
||||
.update({ branchId: primaryBranchId });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { BranchesSettingsService } from '../BranchesSettings';
|
||||
import { ERRORS } from './constants';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class ValidateBranchExistance {
|
||||
constructor(
|
||||
private readonly branchesSettings: BranchesSettingsService,
|
||||
|
||||
@Inject(Branch.name)
|
||||
private readonly branchModel: TenantModelProxy<typeof Branch>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate transaction branch id when the feature is active.
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public validateTransactionBranchWhenActive = async (
|
||||
branchId: number | null,
|
||||
) => {
|
||||
const isActive = this.branchesSettings.isMultiBranchesActive();
|
||||
|
||||
// Can't continue if the multi-warehouses feature is inactive.
|
||||
if (!isActive) return;
|
||||
|
||||
return this.validateTransactionBranch(branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate transaction branch id existance.
|
||||
* @param {number} branchId
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public validateTransactionBranch = async (branchId: number | null) => {
|
||||
this.validateBranchIdExistance(branchId);
|
||||
|
||||
await this.validateBranchExistance(branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the branch id existance.
|
||||
* @param {number} branchId
|
||||
*/
|
||||
public validateBranchIdExistance = (branchId: number | null) => {
|
||||
if (!branchId) {
|
||||
throw new ServiceError(ERRORS.BRANCH_ID_REQUIRED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the branch id existance.
|
||||
* @param {number} branchId
|
||||
*/
|
||||
public validateBranchExistance = async (branchId: number) => {
|
||||
const branch = await this.branchModel().query().findById(branchId);
|
||||
|
||||
if (!branch) {
|
||||
throw new ServiceError(ERRORS.BRANCH_ID_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
export const ERRORS = {
|
||||
BRANCH_ID_REQUIRED: 'BRANCH_ID_REQUIRED',
|
||||
BRANCH_ID_NOT_FOUND: 'BRANCH_ID_NOT_FOUND'
|
||||
}
|
||||
192
packages/server/src/modules/Branches/models/Branch.model.ts
Normal file
192
packages/server/src/modules/Branches/models/Branch.model.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
// import { Model, mixin } from 'objection';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import BranchMetadata from './Branch.settings';
|
||||
// import ModelSetting from './ModelSetting';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
|
||||
export class Branch extends BaseModel{
|
||||
name!: string;
|
||||
code!: string;
|
||||
address!: string;
|
||||
city!: string;
|
||||
country!: string;
|
||||
phoneNumber!: string;
|
||||
email!: string;
|
||||
website!: string;
|
||||
primary!: boolean;
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'branches';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
/**
|
||||
* Filters accounts by the given ids.
|
||||
* @param {Query} query
|
||||
* @param {number[]} accountsIds
|
||||
*/
|
||||
isPrimary(query) {
|
||||
query.where('primary', true);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 PaymentReceive = require('models/PaymentReceive');
|
||||
// const PaymentMade = require('models/BillPayment');
|
||||
// const VendorCredit = require('models/VendorCredit');
|
||||
// const CreditNote = require('models/CreditNote');
|
||||
// const AccountTransaction = require('models/AccountTransaction');
|
||||
// const InventoryTransaction = require('models/InventoryTransaction');
|
||||
|
||||
// return {
|
||||
// /**
|
||||
// * Branch may belongs to associated sale invoices.
|
||||
// */
|
||||
// invoices: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: SaleInvoice.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'sales_invoices.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated sale estimates.
|
||||
// */
|
||||
// estimates: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: SaleEstimate.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'sales_estimates.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated sale receipts.
|
||||
// */
|
||||
// receipts: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: SaleReceipt.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'sales_receipts.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated payment receives.
|
||||
// */
|
||||
// paymentReceives: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: PaymentReceive.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'payment_receives.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated bills.
|
||||
// */
|
||||
// bills: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: Bill.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'bills.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated payment mades.
|
||||
// */
|
||||
// paymentMades: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: PaymentMade.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'bills_payments.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated credit notes.
|
||||
// */
|
||||
// creditNotes: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: CreditNote.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'credit_notes.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated to vendor credits.
|
||||
// */
|
||||
// vendorCredit: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: VendorCredit.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'vendor_credits.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated to accounts transactions.
|
||||
// */
|
||||
// accountsTransactions: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: AccountTransaction.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'accounts_transactions.branchId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Branch may belongs to associated to inventory transactions.
|
||||
// */
|
||||
// inventoryTransactions: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: InventoryTransaction.default,
|
||||
// join: {
|
||||
// from: 'branches.id',
|
||||
// to: 'inventory_transactions.branchId',
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
|
||||
/**
|
||||
* Model settings.
|
||||
*/
|
||||
// static get meta() {
|
||||
// return BranchMetadata;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class GetBranchService {
|
||||
constructor(
|
||||
@Inject(Branch.name)
|
||||
private readonly branch: TenantModelProxy<typeof Branch>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves the given branch details.
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public getBranch = async (branchId: number): Promise<Branch> => {
|
||||
const branch = await this.branch()
|
||||
.query()
|
||||
.findById(branchId)
|
||||
.throwIfNotFound();
|
||||
|
||||
return branch;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Branch } from '../models/Branch.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class GetBranchesService {
|
||||
constructor(
|
||||
@Inject(Branch.name)
|
||||
private readonly branch: TenantModelProxy<typeof Branch>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves branches list.
|
||||
* @returns
|
||||
*/
|
||||
public getBranches = async () => {
|
||||
const branches = await this.branch().query().orderBy('name', 'DESC');
|
||||
|
||||
return branches;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CashflowTransactionsActivateBranches } from '../../Integrations/Cashflow/CashflowActivateBranches';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly cashflowActivateBranches: CashflowTransactionsActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateCashflowWithBranchOnActivated({
|
||||
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.cashflowActivateBranches.updateCashflowTransactionsWithBranch(
|
||||
primaryBranch.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { events } from '@/common/events/events';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreditNoteActivateBranches } from '../../integrations/Sales/CreditNoteBranchesActivate';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly creditNotesActivateBranches: CreditNoteActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateCreditNoteWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.creditNotesActivateBranches.updateCreditsWithBranch(
|
||||
primaryBranch.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { events } from '@/common/events/events';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ExpensesActivateBranches } from '../../Integrations/Expense/ExpensesActivateBranches';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
|
||||
@Injectable()
|
||||
export class ExpenseActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly expensesActivateBranches: ExpensesActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateExpensesWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.expensesActivateBranches.updateExpensesWithBranch(
|
||||
primaryBranch.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { BillPaymentsActivateBranches } from '../../Integrations/Purchases/PaymentMadeBranchesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentMadeActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly paymentsActivateBranches: BillPaymentsActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updatePaymentsWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.paymentsActivateBranches.updateBillPaymentsWithBranch(
|
||||
primaryBranch.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { events } from '@/common/events/events';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { PaymentReceiveActivateBranches } from '../../integrations/Sales/PaymentReceiveBranchesActivate';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentReceiveActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly paymentsActivateBranches: PaymentReceiveActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateCreditNoteWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.paymentsActivateBranches.updatePaymentsWithBranch(
|
||||
primaryBranch.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { events } from '@/common/events/events';
|
||||
import { SaleEstimateActivateBranches } from '../../integrations/Sales/SaleEstimatesBranchesActivate';
|
||||
|
||||
@Injectable()
|
||||
export class SaleEstimatesActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly estimatesActivateBranches: SaleEstimateActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateEstimatesWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.estimatesActivateBranches.updateEstimatesWithBranch(
|
||||
primaryBranch.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { events } from '@/common/events/events';
|
||||
import { SaleInvoiceActivateBranches } from '../../Integrations/Sales/SaleInvoiceBranchesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class SaleInvoicesActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly invoicesActivateBranches: SaleInvoiceActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateInvoicesWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.invoicesActivateBranches.updateInvoicesWithBranch(
|
||||
primaryBranch.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IBranchesActivatedPayload } from '../../Branches.types';
|
||||
import { SaleReceiptActivateBranches } from '../../integrations/Sales/SaleReceiptBranchesActivate';
|
||||
|
||||
@Injectable()
|
||||
export class SaleReceiptsActivateBranchesSubscriber {
|
||||
constructor(
|
||||
private readonly receiptsActivateBranches: SaleReceiptActivateBranches,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates accounts transactions with the primary branch once
|
||||
* the multi-branches is activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateReceiptsWithBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.receiptsActivateBranches.updateReceiptsWithBranch(
|
||||
primaryBranch.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import {
|
||||
IBillCreatingPayload,
|
||||
IBillEditingPayload,
|
||||
} from '@/modules/Bills/Bills.types';
|
||||
|
||||
@Injectable()
|
||||
export class BillBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on bill creating.
|
||||
* @param {IBillCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.bill.onCreating)
|
||||
async validateBranchExistanceOnBillCreating({
|
||||
billDTO,
|
||||
}: IBillCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
billDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once bill editing.
|
||||
* @param {IBillEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.bill.onEditing)
|
||||
async validateBranchExistanceOnBillEditing({ billDTO }: IBillEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
billDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { ICommandCashflowCreatingPayload } from '@/modules/BankingTransactions/types/BankingTransactions.types';
|
||||
|
||||
@Injectable()
|
||||
export class CashflowBranchDTOValidatorSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance once cashflow transaction creating.
|
||||
* @param {ICommandCashflowCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.cashflow.onTransactionCreating)
|
||||
async validateBranchExistanceOnCashflowTransactionCreating({
|
||||
newTransactionDTO,
|
||||
}: ICommandCashflowCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
newTransactionDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import {
|
||||
ICustomerOpeningBalanceEditingPayload,
|
||||
ICustomerEventCreatingPayload,
|
||||
} from '@/modules/Customers/types/Customers.types';
|
||||
import {
|
||||
IVendorEventCreatingPayload,
|
||||
IVendorOpeningBalanceEditingPayload,
|
||||
} from '@/modules/Vendors/types/Vendors.types';
|
||||
|
||||
@Injectable()
|
||||
export class ContactBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on customer creating.
|
||||
* @param {ICustomerEventCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.customers.onCreating)
|
||||
async validateBranchExistanceOnCustomerCreating({
|
||||
customerDTO,
|
||||
}: ICustomerEventCreatingPayload) {
|
||||
// Can't continue if the customer opening balance is zero.
|
||||
if (!customerDTO.openingBalance) return;
|
||||
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
customerDTO.openingBalanceBranchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once customer opening balance editing.
|
||||
* @param {ICustomerOpeningBalanceEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.customers.onOpeningBalanceChanging)
|
||||
async validateBranchExistanceOnCustomerOpeningBalanceEditing({
|
||||
openingBalanceEditDTO,
|
||||
}: ICustomerOpeningBalanceEditingPayload) {
|
||||
if (!openingBalanceEditDTO.openingBalance) return;
|
||||
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
openingBalanceEditDTO.openingBalanceBranchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the branch existance on vendor creating.
|
||||
* @param {IVendorEventCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.vendors.onCreating)
|
||||
async validateBranchExistanceonVendorCreating({
|
||||
vendorDTO,
|
||||
}: IVendorEventCreatingPayload) {
|
||||
// Can't continue if the customer opening balance is zero.
|
||||
if (!vendorDTO.openingBalance) return;
|
||||
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
vendorDTO.openingBalanceBranchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once the vendor opening balance editing.
|
||||
* @param {IVendorOpeningBalanceEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.vendors.onOpeningBalanceChanging)
|
||||
async validateBranchExistanceOnVendorOpeningBalanceEditing({
|
||||
openingBalanceEditDTO,
|
||||
}: IVendorOpeningBalanceEditingPayload) {
|
||||
if (!openingBalanceEditDTO.openingBalance) return;
|
||||
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
openingBalanceEditDTO.openingBalanceBranchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { ICreditNoteEditingPayload } from '@/modules/CreditNotes/types/CreditNotes.types';
|
||||
import { ICreditNoteCreatingPayload } from '@/modules/CreditNotes/types/CreditNotes.types';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on credit note creating.
|
||||
* @param {ICreditNoteCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.creditNote.onCreating)
|
||||
async validateBranchExistanceOnCreditCreating({
|
||||
creditNoteDTO,
|
||||
}: ICreditNoteCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
creditNoteDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once credit note editing.
|
||||
* @param {ICreditNoteEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.creditNote.onEditing)
|
||||
async validateBranchExistanceOnCreditEditing({
|
||||
creditNoteEditDTO,
|
||||
}: ICreditNoteEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
creditNoteEditDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IRefundCreditNoteCreatingPayload } from '@/modules/CreditNoteRefunds/types/CreditNoteRefunds.types';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteRefundBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on refund credit note creating.
|
||||
* @param {IRefundCreditNoteCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.creditNote.onRefundCreating)
|
||||
async validateBranchExistanceOnCreditRefundCreating({
|
||||
newCreditNoteDTO,
|
||||
}: IRefundCreditNoteCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
newCreditNoteDTO.branchId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import {
|
||||
IExpenseCreatingPayload,
|
||||
IExpenseEventEditingPayload,
|
||||
} from '@/modules/Expenses/Expenses.types';
|
||||
@Injectable()
|
||||
export class ExpenseBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance once expense transaction creating.
|
||||
* @param {IExpenseCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.expenses.onCreating)
|
||||
async validateBranchExistanceOnExpenseCreating({
|
||||
expenseDTO,
|
||||
}: IExpenseCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
expenseDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once expense transaction editing.
|
||||
* @param {IExpenseEventEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.expenses.onEditing)
|
||||
async validateBranchExistanceOnExpenseEditing({
|
||||
expenseDTO,
|
||||
}: IExpenseEventEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
expenseDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { IInventoryAdjustmentCreatingPayload } from '@/modules/InventoryAdjutments/types/InventoryAdjustments.types';
|
||||
|
||||
@Injectable()
|
||||
export class InventoryAdjustmentBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on inventory adjustment creating.
|
||||
* @param {IInventoryAdjustmentCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.inventoryAdjustment.onQuickCreating)
|
||||
async validateBranchExistanceOnInventoryCreating({
|
||||
quickAdjustmentDTO,
|
||||
}: IInventoryAdjustmentCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
quickAdjustmentDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import {
|
||||
ISaleInvoiceCreatingPaylaod,
|
||||
ISaleInvoiceEditingPayload,
|
||||
} from '@/modules/SaleInvoices/SaleInvoice.types';
|
||||
|
||||
@Injectable()
|
||||
export class InvoiceBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on invoice creating.
|
||||
* @param {ISaleInvoiceCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.saleInvoice.onCreating)
|
||||
async validateBranchExistanceOnInvoiceCreating({
|
||||
saleInvoiceDTO,
|
||||
}: ISaleInvoiceCreatingPaylaod) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
saleInvoiceDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once invoice editing.
|
||||
* @param {ISaleInvoiceEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.saleInvoice.onEditing)
|
||||
async validateBranchExistanceOnInvoiceEditing({
|
||||
saleInvoiceDTO,
|
||||
}: ISaleInvoiceEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
saleInvoiceDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
import {
|
||||
IManualJournalCreatingPayload,
|
||||
IManualJournalEditingPayload,
|
||||
} from '@/modules/ManualJournals/types/ManualJournals.types';
|
||||
import { ManualJournalBranchesValidator } from '../../Integrations/ManualJournals/ManualJournalsBranchesValidator';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { Features } from '@/common/types/Features';
|
||||
import { FeaturesManager } from '../../../Features/FeaturesManager';
|
||||
|
||||
@Injectable()
|
||||
export class ManualJournalBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateManualJournalBranch: ManualJournalBranchesValidator,
|
||||
private readonly featuresManager: FeaturesManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on estimate creating.
|
||||
* @param {IManualJournalCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.manualJournals.onCreating)
|
||||
async validateBranchExistanceOnBillCreating({
|
||||
manualJournalDTO,
|
||||
}: IManualJournalCreatingPayload) {
|
||||
// Detarmines whether the multi-branches is accessible by tenant.
|
||||
const isAccessible = await this.featuresManager.accessible(
|
||||
Features.BRANCHES
|
||||
);
|
||||
// Can't continue if the multi-branches feature is inactive.
|
||||
if (!isAccessible) return;
|
||||
|
||||
// Validates the entries whether have branch id.
|
||||
await this.validateManualJournalBranch.validateEntriesHasBranchId(
|
||||
manualJournalDTO
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {ISaleEstimateEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.manualJournals.onEditing)
|
||||
async validateBranchExistanceOnBillEditing({
|
||||
manualJournalDTO,
|
||||
}: IManualJournalEditingPayload) {
|
||||
// Detarmines whether the multi-branches is accessible by tenant.
|
||||
const isAccessible = await this.featuresManager.accessible(
|
||||
Features.BRANCHES
|
||||
);
|
||||
// Can't continue if the multi-branches feature is inactive.
|
||||
if (!isAccessible) return;
|
||||
|
||||
await this.validateManualJournalBranch.validateEntriesHasBranchId(
|
||||
manualJournalDTO
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
IBillPaymentCreatingPayload,
|
||||
IBillPaymentEditingPayload,
|
||||
} from '@/modules/BillPayments/types/BillPayments.types';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentMadeBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on estimate creating.
|
||||
* @param {ISaleEstimateCreatedPayload} payload
|
||||
*/
|
||||
@OnEvent(events.billPayment.onCreating)
|
||||
async validateBranchExistanceOnPaymentCreating({
|
||||
billPaymentDTO,
|
||||
}: IBillPaymentCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
billPaymentDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {ISaleEstimateEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.billPayment.onEditing)
|
||||
async validateBranchExistanceOnPaymentEditing({
|
||||
billPaymentDTO,
|
||||
}: IBillPaymentEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
billPaymentDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
IPaymentReceivedCreatingPayload,
|
||||
IPaymentReceivedEditingPayload,
|
||||
} from '@/modules/PaymentReceived/types/PaymentReceived.types';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentReceiveBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on estimate creating.
|
||||
* @param {IPaymentReceivedCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.paymentReceive.onCreating)
|
||||
async validateBranchExistanceOnPaymentCreating({
|
||||
paymentReceiveDTO,
|
||||
}: IPaymentReceivedCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
paymentReceiveDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {IPaymentReceivedEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.paymentReceive.onEditing)
|
||||
async validateBranchExistanceOnPaymentEditing({
|
||||
paymentReceiveDTO,
|
||||
}: IPaymentReceivedEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
paymentReceiveDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import {
|
||||
ISaleEstimateCreatingPayload,
|
||||
ISaleEstimateEditingPayload,
|
||||
} from '@/modules/SaleEstimates/types/SaleEstimates.types';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
|
||||
@Injectable()
|
||||
export class SaleEstimateBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on estimate creating.
|
||||
* @param {ISaleEstimateCreatedPayload} payload
|
||||
*/
|
||||
@OnEvent(events.saleEstimate.onCreating)
|
||||
async validateBranchExistanceOnEstimateCreating({
|
||||
estimateDTO,
|
||||
}: ISaleEstimateCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
estimateDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {ISaleEstimateEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.saleEstimate.onEditing)
|
||||
async validateBranchExistanceOnEstimateEditing({
|
||||
estimateDTO,
|
||||
}: ISaleEstimateEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
estimateDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
ISaleReceiptCreatingPayload,
|
||||
ISaleReceiptEditingPayload,
|
||||
} from '@/modules/SaleReceipts/types/SaleReceipts.types';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class SaleReceiptBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on estimate creating.
|
||||
* @param {ISaleReceiptCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.saleReceipt.onCreating)
|
||||
async validateBranchExistanceOnInvoiceCreating({
|
||||
saleReceiptDTO,
|
||||
}: ISaleReceiptCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
saleReceiptDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {ISaleReceiptEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.saleReceipt.onEditing)
|
||||
async validateBranchExistanceOnInvoiceEditing({
|
||||
saleReceiptDTO,
|
||||
}: ISaleReceiptEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
saleReceiptDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
IVendorCreditCreatingPayload,
|
||||
IVendorCreditEditingPayload,
|
||||
} from '@/modules/VendorCredit/types/VendorCredit.types';
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on estimate creating.
|
||||
* @param {ISaleEstimateCreatedPayload} payload
|
||||
*/
|
||||
@OnEvent(events.vendorCredit.onCreating)
|
||||
async validateBranchExistanceOnCreditCreating({
|
||||
vendorCreditCreateDTO,
|
||||
}: IVendorCreditCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
vendorCreditCreateDTO.branchId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {ISaleEstimateEditingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.vendorCredit.onEditing)
|
||||
async validateBranchExistanceOnCreditEditing({
|
||||
vendorCreditDTO,
|
||||
}: IVendorCreditEditingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
vendorCreditDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IRefundVendorCreditCreatingPayload } from '@/modules/VendorCreditsRefund/types/VendorCreditRefund.types';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditRefundBranchValidateSubscriber {
|
||||
constructor(
|
||||
private readonly validateBranchExistance: ValidateBranchExistance,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate branch existance on refund credit note creating.
|
||||
* @param {IRefundVendorCreditCreatingPayload} payload
|
||||
*/
|
||||
@OnEvent(events.vendorCredit.onRefundCreating)
|
||||
async validateBranchExistanceOnCreditRefundCreating({
|
||||
refundVendorCreditDTO,
|
||||
}: IRefundVendorCreditCreatingPayload) {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
refundVendorCreditDTO.branchId,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user