mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
refactor: branches and warehouses to nestjs
This commit is contained in:
@@ -36,6 +36,7 @@ import { ExpensesModule } from '../Expenses/Expenses.module';
|
|||||||
import { ItemCategoryModule } from '../ItemCategories/ItemCategory.module';
|
import { ItemCategoryModule } from '../ItemCategories/ItemCategory.module';
|
||||||
import { TaxRatesModule } from '../TaxRates/TaxRate.module';
|
import { TaxRatesModule } from '../TaxRates/TaxRate.module';
|
||||||
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
||||||
|
import { BranchesModule } from '../Branches/Branches.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -95,6 +96,7 @@ import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
|||||||
ExpensesModule,
|
ExpensesModule,
|
||||||
TaxRatesModule,
|
TaxRatesModule,
|
||||||
PdfTemplatesModule,
|
PdfTemplatesModule,
|
||||||
|
BranchesModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -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);
|
||||||
|
// }
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
Delete,
|
||||||
|
Body,
|
||||||
|
Param,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { BranchesApplication } from './BranchesApplication.service';
|
||||||
|
import { ICreateBranchDTO, IEditBranchDTO } from './Branches.types';
|
||||||
|
|
||||||
|
@Controller('branches')
|
||||||
|
export class BranchesController {
|
||||||
|
constructor(private readonly branchesApplication: BranchesApplication) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
getBranches() {
|
||||||
|
// return this.branchesApplication.getBranches();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
getBranch(@Param('id') id: string) {
|
||||||
|
return this.branchesApplication.getBranch(Number(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
createBranch(@Body() createBranchDTO: ICreateBranchDTO) {
|
||||||
|
return this.branchesApplication.createBranch(createBranchDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id')
|
||||||
|
editBranch(@Param('id') id: string, @Body() editBranchDTO: IEditBranchDTO) {
|
||||||
|
return this.branchesApplication.editBranch(Number(id), editBranchDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
deleteBranch(@Param('id') id: string) {
|
||||||
|
return this.branchesApplication.deleteBranch(Number(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('activate')
|
||||||
|
activateBranches() {
|
||||||
|
return this.branchesApplication.activateBranches();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id/mark-as-primary')
|
||||||
|
markBranchAsPrimary(@Param('id') id: string) {
|
||||||
|
return this.branchesApplication.markBranchAsPrimary(Number(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
31
packages/server-nest/src/modules/Branches/Branches.module.ts
Normal file
31
packages/server-nest/src/modules/Branches/Branches.module.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TenancyDatabaseModule],
|
||||||
|
controllers: [BranchesController],
|
||||||
|
providers: [
|
||||||
|
CreateBranchService,
|
||||||
|
EditBranchService,
|
||||||
|
DeleteBranchService,
|
||||||
|
GetBranchService,
|
||||||
|
GetBranchesService,
|
||||||
|
MarkBranchAsPrimaryService,
|
||||||
|
ActivateBranches,
|
||||||
|
BranchesApplication,
|
||||||
|
TenancyContext,
|
||||||
|
TransformerInjectable,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class BranchesModule {}
|
||||||
50
packages/server-nest/src/modules/Branches/Branches.types.ts
Normal file
50
packages/server-nest/src/modules/Branches/Branches.types.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
|
||||||
|
export interface IBranch {
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
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: IBranch;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBranchMarkAsPrimaryPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldBranch: IBranch;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
export interface IBranchMarkedAsPrimaryPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldBranch: IBranch;
|
||||||
|
markedBranch: IBranch;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import { IBranch, 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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BranchesApplication {
|
||||||
|
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.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @returns {IBranch}
|
||||||
|
*/
|
||||||
|
// public getBranches = (): Promise<Branch[]> => {
|
||||||
|
// // return this.getBranchesService.getBranches(tenantId);
|
||||||
|
// };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given branch details.
|
||||||
|
* @param {number} branchId - Branch id.
|
||||||
|
* @returns {Promise<IBranch>}
|
||||||
|
*/
|
||||||
|
public getBranch = (branchId: number): Promise<IBranch> => {
|
||||||
|
return this.getBranchService.getBranch(branchId);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new branch.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
* @param {ICreateBranchDTO} createBranchDTO
|
||||||
|
* @returns {Promise<IBranch>}
|
||||||
|
*/
|
||||||
|
public createBranch = (
|
||||||
|
createBranchDTO: ICreateBranchDTO,
|
||||||
|
): 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: IEditBranchDTO,
|
||||||
|
): 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);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Service, Inject } from 'typedi';
|
||||||
|
import { Features } from '@/interfaces';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class BranchesSettings {
|
||||||
|
@Inject()
|
||||||
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks multi-branches as activated.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
*/
|
||||||
|
public markMultiBranchesAsActivated = (tenantId: number) => {
|
||||||
|
const settings = this.tenancy.settings(tenantId);
|
||||||
|
|
||||||
|
settings.set({ group: 'features', key: Features.BRANCHES, value: 1 });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves whether multi-branches is active.
|
||||||
|
* @param {number} tenantId
|
||||||
|
*/
|
||||||
|
public isMultiBranchesActive = (tenantId: number) => {
|
||||||
|
const settings = this.tenancy.settings(tenantId);
|
||||||
|
|
||||||
|
return settings.get({ group: 'features', key: Features.BRANCHES });
|
||||||
|
};
|
||||||
|
}
|
||||||
30
packages/server-nest/src/modules/Branches/CRUDBranch.ts
Normal file
30
packages/server-nest/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-nest/src/modules/Branches/EventsProvider.ts
Normal file
50
packages/server-nest/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,80 @@
|
|||||||
|
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 { BranchesSettings } 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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ActivateBranches {
|
||||||
|
constructor(
|
||||||
|
private readonly uow: UnitOfWork,
|
||||||
|
private readonly eventPublisher: EventEmitter2,
|
||||||
|
private readonly createBranch: CreateBranchService,
|
||||||
|
private readonly branchesSettings: BranchesSettings,
|
||||||
|
private readonly i18n: I18nService,
|
||||||
|
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branchModel: typeof Branch,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = (): Promise<void> => {
|
||||||
|
const isActivated = 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,50 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ERRORS } from '../constants';
|
||||||
|
import { Branch } from '../models/Branch.model';
|
||||||
|
|
||||||
|
import { ServiceError } from '../../Items/ServiceError';
|
||||||
|
@Injectable()
|
||||||
|
export class BranchCommandValidator {
|
||||||
|
constructor(
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branchModel: 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,55 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import {
|
||||||
|
IBranchCreatedPayload,
|
||||||
|
IBranchCreatePayload,
|
||||||
|
ICreateBranchDTO,
|
||||||
|
} from '../Branches.types';
|
||||||
|
import { BranchCommandValidator } from './BranchCommandValidator.service';
|
||||||
|
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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CreateBranchService {
|
||||||
|
constructor(
|
||||||
|
private readonly uow: UnitOfWork,
|
||||||
|
private readonly eventPublisher: EventEmitter2,
|
||||||
|
private readonly validator: BranchCommandValidator,
|
||||||
|
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branchModel: typeof Branch,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new branch.
|
||||||
|
* @param {ICreateBranchDTO} createBranchDTO
|
||||||
|
* @returns {Promise<IBranch>}
|
||||||
|
*/
|
||||||
|
public createBranch = async (
|
||||||
|
createBranchDTO: ICreateBranchDTO,
|
||||||
|
): 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,65 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { IBranchDeletedPayload, IBranchDeletePayload } from './Branch.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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DeleteBranchService {
|
||||||
|
constructor(
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branchModel: 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,61 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import {
|
||||||
|
IBranchEditedPayload,
|
||||||
|
IBranchEditPayload,
|
||||||
|
IEditBranchDTO,
|
||||||
|
} 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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EditBranchService {
|
||||||
|
constructor(
|
||||||
|
private readonly branchModel: 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: IEditBranchDTO,
|
||||||
|
) => {
|
||||||
|
// 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,62 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MarkBranchAsPrimaryService {
|
||||||
|
constructor(
|
||||||
|
private readonly uow: UnitOfWork,
|
||||||
|
private readonly eventPublisher: EventEmitter2,
|
||||||
|
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branchModel: 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-nest/src/modules/Branches/constants.ts
Normal file
7
packages/server-nest/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'
|
||||||
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { omit } from 'lodash';
|
||||||
|
// import { BranchesSettings } from '../BranchesSettings';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class BranchTransactionDTOTransform {
|
||||||
|
// @Inject()
|
||||||
|
// branchesSettings: BranchesSettings;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Excludes DTO branch id when mutli-warehouses feature is inactive.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @returns {any}
|
||||||
|
// */
|
||||||
|
// private excludeDTOBranchIdWhenInactive = <T extends { branchId?: number }>(
|
||||||
|
// tenantId: number,
|
||||||
|
// DTO: T
|
||||||
|
// ): Omit<T, 'branchId'> | T => {
|
||||||
|
// const isActive = this.branchesSettings.isMultiBranchesActive(tenantId);
|
||||||
|
|
||||||
|
// return !isActive ? omit(DTO, ['branchId']) : DTO;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Transformes the input DTO for branches feature.
|
||||||
|
// * @param {number} tenantId -
|
||||||
|
// * @param {T} DTO -
|
||||||
|
// * @returns {Omit<T, 'branchId'> | T}
|
||||||
|
// */
|
||||||
|
// public transformDTO =
|
||||||
|
// <T extends { branchId?: number }>(tenantId: number) =>
|
||||||
|
// (DTO: T): Omit<T, 'branchId'> | T => {
|
||||||
|
// return this.excludeDTOBranchIdWhenInactive<T>(tenantId, DTO);
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CashflowTransactionsActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all cashflow transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateCashflowTransactionsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { CashflowTransaction } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the cashflow transactions with primary branch.
|
||||||
|
// await CashflowTransaction.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ExpensesActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all expenses transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateExpensesWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { Expense } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the expenses with primary branch.
|
||||||
|
// await Expense.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ManualJournalsActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all manual journals transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateManualJournalsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { ManualJournal } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the manual journal with primary branch.
|
||||||
|
// await ManualJournal.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// import { omit } from 'lodash';
|
||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import { IManualJournal } from '@/interfaces';
|
||||||
|
// import { BranchesSettings } from '../../BranchesSettings';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ManualJournalBranchesDTOTransformer {
|
||||||
|
// @Inject()
|
||||||
|
// branchesSettings: BranchesSettings;
|
||||||
|
|
||||||
|
// private excludeDTOBranchIdWhenInactive = (
|
||||||
|
// tenantId: number,
|
||||||
|
// DTO: IManualJournal
|
||||||
|
// ): IManualJournal => {
|
||||||
|
// const isActive = this.branchesSettings.isMultiBranchesActive(tenantId);
|
||||||
|
|
||||||
|
// if (isActive) return DTO;
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// ...DTO,
|
||||||
|
// entries: DTO.entries.map((e) => omit(e, ['branchId'])),
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// */
|
||||||
|
// public transformDTO =
|
||||||
|
// (tenantId: number) =>
|
||||||
|
// (DTO: IManualJournal): IManualJournal => {
|
||||||
|
// return this.excludeDTOBranchIdWhenInactive(tenantId, DTO);
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { ServiceError } from '@/exceptions';
|
||||||
|
// import { IManualJournalDTO, IManualJournalEntryDTO } from '@/interfaces';
|
||||||
|
// import { ERRORS } from './constants';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// 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,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class BillActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all bills transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateBillsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { Bill } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale invoice with primary branch.
|
||||||
|
// await Bill.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class BillPaymentsActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all bills payments transcations with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateBillPaymentsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { BillPayment } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the bill payments with primary branch.
|
||||||
|
// await BillPayment.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class VendorCreditActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all vendor credits transcations with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateVendorCreditsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { VendorCredit } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the vendors credits with primary branch.
|
||||||
|
// await VendorCredit.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreditNoteActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all creidt notes transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateCreditsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { CreditNote } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale invoice with primary branch.
|
||||||
|
// await CreditNote.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class PaymentReceiveActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all creidt notes transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updatePaymentsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { PaymentReceive } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale invoice with primary branch.
|
||||||
|
// await PaymentReceive.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleEstimateActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all sale estimates transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateEstimatesWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { PaymentReceive } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale invoice with primary branch.
|
||||||
|
// await PaymentReceive.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleInvoiceActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all sale invoices transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateInvoicesWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale invoice with primary branch.
|
||||||
|
// await SaleInvoice.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleReceiptActivateBranches {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all sale receipts transactions with the primary branch.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryBranchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateReceiptsWithBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryBranchId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const { SaleReceipt } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale receipt with primary branch.
|
||||||
|
// await SaleReceipt.query(trx).update({ branchId: primaryBranchId });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// import { ServiceError } from '@/exceptions';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { BranchesSettings } from '../BranchesSettings';
|
||||||
|
// import { ERRORS } from './constants';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ValidateBranchExistance {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// @Inject()
|
||||||
|
// branchesSettings: BranchesSettings;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate transaction branch id when the feature is active.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} branchId
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public validateTransactionBranchWhenActive = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// branchId: number | null
|
||||||
|
// ) => {
|
||||||
|
// const isActive = this.branchesSettings.isMultiBranchesActive(tenantId);
|
||||||
|
|
||||||
|
// // Can't continue if the multi-warehouses feature is inactive.
|
||||||
|
// if (!isActive) return;
|
||||||
|
|
||||||
|
// return this.validateTransactionBranch(tenantId, branchId);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate transaction branch id existance.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} branchId
|
||||||
|
// * @return {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public validateTransactionBranch = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// branchId: number | null
|
||||||
|
// ) => {
|
||||||
|
// this.validateBranchIdExistance(branchId);
|
||||||
|
|
||||||
|
// await this.validateBranchExistance(tenantId, branchId);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param branchId
|
||||||
|
// */
|
||||||
|
// public validateBranchIdExistance = (branchId: number | null) => {
|
||||||
|
// if (!branchId) {
|
||||||
|
// throw new ServiceError(ERRORS.BRANCH_ID_REQUIRED);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param tenantId
|
||||||
|
// * @param branchId
|
||||||
|
// */
|
||||||
|
// public validateBranchExistance = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// branchId: number
|
||||||
|
// ) => {
|
||||||
|
// const { Branch } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// const branch = await Branch.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-nest/src/modules/Branches/models/Branch.model.ts
Normal file
192
packages/server-nest/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,25 @@
|
|||||||
|
import { Inject } from '@nestjs/common';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Branch } from '../models/Branch.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GetBranchService {
|
||||||
|
constructor(
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branch: 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,20 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { Branch } from '../models/Branch.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GetBranchesService {
|
||||||
|
constructor(
|
||||||
|
@Inject(Branch.name)
|
||||||
|
private readonly branch: typeof Branch,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves branches list.
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getBranches = async () => {
|
||||||
|
const branches = await this.branch.query().orderBy('name', 'DESC');
|
||||||
|
|
||||||
|
return branches;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { CashflowTransactionsActivateBranches } from '../../Integrations/Cashflow/CashflowActivateBranches';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreditNoteActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private cashflowActivateBranches: CashflowTransactionsActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateCashflowWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateCashflowWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.cashflowActivateBranches.updateCashflowTransactionsWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { CreditNoteActivateBranches } from '../../Integrations/Sales/CreditNoteBranchesActivate';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreditNoteActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private creditNotesActivateBranches: CreditNoteActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateCreditNoteWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateCreditNoteWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.creditNotesActivateBranches.updateCreditsWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { ExpensesActivateBranches } from '../../Integrations/Expense/ExpensesActivateBranches';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ExpenseActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private expensesActivateBranches: ExpensesActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateExpensesWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateExpensesWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.expensesActivateBranches.updateExpensesWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { BillPaymentsActivateBranches } from '../../Integrations/Purchases/PaymentMadeBranchesActivate';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class PaymentMadeActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private paymentsActivateBranches: BillPaymentsActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updatePaymentsWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updatePaymentsWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.paymentsActivateBranches.updateBillPaymentsWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { PaymentReceiveActivateBranches } from '../../Integrations/Sales/PaymentReceiveBranchesActivate';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class PaymentReceiveActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private paymentsActivateBranches: PaymentReceiveActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateCreditNoteWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateCreditNoteWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.paymentsActivateBranches.updatePaymentsWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { SaleEstimateActivateBranches } from '../../Integrations/Sales/SaleEstimatesBranchesActivate';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleEstimatesActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private estimatesActivateBranches: SaleEstimateActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateEstimatesWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateEstimatesWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.estimatesActivateBranches.updateEstimatesWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { SaleInvoiceActivateBranches } from '../../Integrations/Sales/SaleInvoiceBranchesActivate';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleInvoicesActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private invoicesActivateBranches: SaleInvoiceActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateInvoicesWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateInvoicesWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.invoicesActivateBranches.updateInvoicesWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { IBranchesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { SaleReceiptActivateBranches } from '../../Integrations/Sales/SaleReceiptBranchesActivate';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleReceiptsActivateBranchesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private receiptsActivateBranches: SaleReceiptActivateBranches;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.branch.onActivated,
|
||||||
|
// this.updateReceiptsWithBranchOnActivated
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates accounts transactions with the primary branch once
|
||||||
|
// * the multi-branches is activated.
|
||||||
|
// * @param {IBranchesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateReceiptsWithBranchOnActivated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch,
|
||||||
|
// trx,
|
||||||
|
// }: IBranchesActivatedPayload) => {
|
||||||
|
// await this.receiptsActivateBranches.updateReceiptsWithBranch(
|
||||||
|
// tenantId,
|
||||||
|
// primaryBranch.id,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// export * from './CashflowBranchesActivateSubscriber';
|
||||||
|
// export * from './CreditNoteBranchesActivateSubscriber';
|
||||||
|
// export * from './PaymentMadeBranchesActivateSubscriber';
|
||||||
|
// export * from './PaymentReceiveBranchesActivateSubscriber';
|
||||||
|
// export * from './SaleReceiptsBranchesActivateSubscriber';
|
||||||
|
// export * from './SaleEstiamtesBranchesActivateSubscriber';
|
||||||
|
// export * from './SaleInvoiceBranchesActivateSubscriber';
|
||||||
|
// export * from './ExpenseBranchesActivateSubscriber';
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { IBillCreatingPayload, IBillEditingPayload } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class BillBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.bill.onCreating,
|
||||||
|
// this.validateBranchExistanceOnBillCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.bill.onEditing,
|
||||||
|
// this.validateBranchExistanceOnBillEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {ISaleEstimateCreatedPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnBillCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// billDTO,
|
||||||
|
// }: IBillCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// billDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {ISaleEstimateEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnBillEditing = async ({
|
||||||
|
// billDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IBillEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// billDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { ICommandCashflowCreatingPayload } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CashflowBranchDTOValidatorSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.cashflow.onTransactionCreating,
|
||||||
|
// this.validateBranchExistanceOnCashflowTransactionCreating
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once cashflow transaction creating.
|
||||||
|
// * @param {ICommandCashflowCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCashflowTransactionCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// newTransactionDTO,
|
||||||
|
// }: ICommandCashflowCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// newTransactionDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// ICustomerEventCreatingPayload,
|
||||||
|
// ICustomerOpeningBalanceEditingPayload,
|
||||||
|
// IVendorEventCreatingPayload,
|
||||||
|
// IVendorOpeningBalanceEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ContactBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.customers.onCreating,
|
||||||
|
// this.validateBranchExistanceOnCustomerCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.customers.onOpeningBalanceChanging,
|
||||||
|
// this.validateBranchExistanceOnCustomerOpeningBalanceEditing
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.vendors.onCreating,
|
||||||
|
// this.validateBranchExistanceonVendorCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.vendors.onOpeningBalanceChanging,
|
||||||
|
// this.validateBranchExistanceOnVendorOpeningBalanceEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on customer creating.
|
||||||
|
// * @param {ICustomerEventCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCustomerCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// customerDTO,
|
||||||
|
// }: ICustomerEventCreatingPayload) => {
|
||||||
|
// // Can't continue if the customer opening balance is zero.
|
||||||
|
// if (!customerDTO.openingBalance) return;
|
||||||
|
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// customerDTO.openingBalanceBranchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once customer opening balance editing.
|
||||||
|
// * @param {ICustomerOpeningBalanceEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCustomerOpeningBalanceEditing = async ({
|
||||||
|
// openingBalanceEditDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: ICustomerOpeningBalanceEditingPayload) => {
|
||||||
|
// if (!openingBalanceEditDTO.openingBalance) return;
|
||||||
|
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// openingBalanceEditDTO.openingBalanceBranchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validates the branch existance on vendor creating.
|
||||||
|
// * @param {IVendorEventCreatingPayload} payload -
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceonVendorCreating = async ({
|
||||||
|
// vendorDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IVendorEventCreatingPayload) => {
|
||||||
|
// // Can't continue if the customer opening balance is zero.
|
||||||
|
// if (!vendorDTO.openingBalance) return;
|
||||||
|
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// vendorDTO.openingBalanceBranchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once the vendor opening balance editing.
|
||||||
|
// * @param {IVendorOpeningBalanceEditingPayload}
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnVendorOpeningBalanceEditing = async ({
|
||||||
|
// tenantId,
|
||||||
|
// openingBalanceEditDTO,
|
||||||
|
// }: IVendorOpeningBalanceEditingPayload) => {
|
||||||
|
// if (!openingBalanceEditDTO.openingBalance) return;
|
||||||
|
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// openingBalanceEditDTO.openingBalanceBranchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// ICreditNoteCreatingPayload,
|
||||||
|
// ICreditNoteEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreditNoteBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.creditNote.onCreating,
|
||||||
|
// this.validateBranchExistanceOnCreditCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.creditNote.onEditing,
|
||||||
|
// this.validateBranchExistanceOnCreditEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {ICreditNoteCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCreditCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// creditNoteDTO,
|
||||||
|
// }: ICreditNoteCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// creditNoteDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {ISaleEstimateEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCreditEditing = async ({
|
||||||
|
// creditNoteEditDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: ICreditNoteEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// creditNoteEditDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { IRefundCreditNoteCreatingPayload } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreditNoteRefundBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.creditNote.onRefundCreating,
|
||||||
|
// this.validateBranchExistanceOnCreditRefundCreating
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on refund credit note creating.
|
||||||
|
// * @param {ICreditNoteCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCreditRefundCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// newCreditNoteDTO,
|
||||||
|
// }: IRefundCreditNoteCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// newCreditNoteDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// IExpenseCreatingPayload,
|
||||||
|
// IExpenseEventEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ExpenseBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.expenses.onCreating,
|
||||||
|
// this.validateBranchExistanceOnExpenseCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.expenses.onEditing,
|
||||||
|
// this.validateBranchExistanceOnExpenseEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once expense transaction creating.
|
||||||
|
// * @param {ISaleEstimateCreatedPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnExpenseCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// expenseDTO,
|
||||||
|
// }: IExpenseCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// expenseDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once expense transaction editing.
|
||||||
|
// * @param {ISaleEstimateEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnExpenseEditing = async ({
|
||||||
|
// expenseDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IExpenseEventEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// expenseDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { IInventoryAdjustmentCreatingPayload } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class InventoryAdjustmentBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.inventoryAdjustment.onQuickCreating,
|
||||||
|
// this.validateBranchExistanceOnInventoryCreating
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on invoice creating.
|
||||||
|
// * @param {ISaleInvoiceCreatingPaylaod} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnInventoryCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// quickAdjustmentDTO,
|
||||||
|
// }: IInventoryAdjustmentCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// quickAdjustmentDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// ISaleInvoiceCreatingPaylaod,
|
||||||
|
// ISaleInvoiceEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class InvoiceBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.saleInvoice.onCreating,
|
||||||
|
// this.validateBranchExistanceOnInvoiceCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.saleInvoice.onEditing,
|
||||||
|
// this.validateBranchExistanceOnInvoiceEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on invoice creating.
|
||||||
|
// * @param {ISaleInvoiceCreatingPaylaod} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnInvoiceCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// saleInvoiceDTO,
|
||||||
|
// }: ISaleInvoiceCreatingPaylaod) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// saleInvoiceDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once invoice editing.
|
||||||
|
// * @param {ISaleInvoiceEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnInvoiceEditing = async ({
|
||||||
|
// saleInvoiceDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: ISaleInvoiceEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// saleInvoiceDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// Features,
|
||||||
|
// IManualJournalCreatingPayload,
|
||||||
|
// IManualJournalEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ManualJournalBranchesValidator } from '../../Integrations/ManualJournals/ManualJournalsBranchesValidator';
|
||||||
|
// import { FeaturesManager } from '@/services/Features/FeaturesManager';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ManualJournalBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateManualJournalBranch: ManualJournalBranchesValidator;
|
||||||
|
|
||||||
|
// @Inject()
|
||||||
|
// private featuresManager: FeaturesManager;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.manualJournals.onCreating,
|
||||||
|
// this.validateBranchExistanceOnBillCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.manualJournals.onEditing,
|
||||||
|
// this.validateBranchExistanceOnBillEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {IManualJournalCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnBillCreating = async ({
|
||||||
|
// manualJournalDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IManualJournalCreatingPayload) => {
|
||||||
|
// // Detarmines whether the multi-branches is accessible by tenant.
|
||||||
|
// const isAccessible = await this.featuresManager.accessible(
|
||||||
|
// tenantId,
|
||||||
|
// 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
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnBillEditing = async ({
|
||||||
|
// tenantId,
|
||||||
|
// manualJournalDTO,
|
||||||
|
// }: IManualJournalEditingPayload) => {
|
||||||
|
// // Detarmines whether the multi-branches is accessible by tenant.
|
||||||
|
// const isAccessible = await this.featuresManager.accessible(
|
||||||
|
// tenantId,
|
||||||
|
// Features.BRANCHES
|
||||||
|
// );
|
||||||
|
// // Can't continue if the multi-branches feature is inactive.
|
||||||
|
// if (!isAccessible) return;
|
||||||
|
|
||||||
|
// await this.validateManualJournalBranch.validateEntriesHasBranchId(
|
||||||
|
// manualJournalDTO
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// IBillPaymentCreatingPayload,
|
||||||
|
// IBillPaymentEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class PaymentMadeBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.billPayment.onCreating,
|
||||||
|
// this.validateBranchExistanceOnPaymentCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.billPayment.onEditing,
|
||||||
|
// this.validateBranchExistanceOnPaymentEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {ISaleEstimateCreatedPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnPaymentCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// billPaymentDTO,
|
||||||
|
// }: IBillPaymentCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// billPaymentDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {ISaleEstimateEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnPaymentEditing = async ({
|
||||||
|
// billPaymentDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IBillPaymentEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// billPaymentDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// IPaymentReceivedCreatingPayload,
|
||||||
|
// IPaymentReceivedEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class PaymentReceiveBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.paymentReceive.onCreating,
|
||||||
|
// this.validateBranchExistanceOnPaymentCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.paymentReceive.onEditing,
|
||||||
|
// this.validateBranchExistanceOnPaymentEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {IPaymentReceivedCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnPaymentCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// paymentReceiveDTO,
|
||||||
|
// }: IPaymentReceivedCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// paymentReceiveDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {IPaymentReceivedEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnPaymentEditing = async ({
|
||||||
|
// paymentReceiveDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IPaymentReceivedEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// paymentReceiveDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// ISaleEstimateCreatingPayload,
|
||||||
|
// ISaleEstimateEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleEstimateBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.saleEstimate.onCreating,
|
||||||
|
// this.validateBranchExistanceOnEstimateCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.saleEstimate.onEditing,
|
||||||
|
// this.validateBranchExistanceOnEstimateEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {ISaleEstimateCreatedPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnEstimateCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// estimateDTO,
|
||||||
|
// }: ISaleEstimateCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// estimateDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {ISaleEstimateEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnEstimateEditing = async ({
|
||||||
|
// estimateDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: ISaleEstimateEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// estimateDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// ISaleReceiptCreatingPayload,
|
||||||
|
// ISaleReceiptEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class SaleReceiptBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.saleReceipt.onCreating,
|
||||||
|
// this.validateBranchExistanceOnInvoiceCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.saleReceipt.onEditing,
|
||||||
|
// this.validateBranchExistanceOnInvoiceEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {ISaleReceiptCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnInvoiceCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// saleReceiptDTO,
|
||||||
|
// }: ISaleReceiptCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// saleReceiptDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {ISaleReceiptEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnInvoiceEditing = async ({
|
||||||
|
// saleReceiptDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: ISaleReceiptEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// saleReceiptDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import {
|
||||||
|
// IVendorCreditCreatingPayload,
|
||||||
|
// IVendorCreditEditingPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class VendorCreditBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.vendorCredit.onCreating,
|
||||||
|
// this.validateBranchExistanceOnCreditCreating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.vendorCredit.onEditing,
|
||||||
|
// this.validateBranchExistanceOnCreditEditing
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on estimate creating.
|
||||||
|
// * @param {ISaleEstimateCreatedPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCreditCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// vendorCreditCreateDTO,
|
||||||
|
// }: IVendorCreditCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// vendorCreditCreateDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance once estimate editing.
|
||||||
|
// * @param {ISaleEstimateEditingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCreditEditing = async ({
|
||||||
|
// vendorCreditDTO,
|
||||||
|
// tenantId,
|
||||||
|
// }: IVendorCreditEditingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// vendorCreditDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { IRefundVendorCreditCreatingPayload } from '@/interfaces';
|
||||||
|
// import { ValidateBranchExistance } from '../../Integrations/ValidateBranchExistance';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class VendorCreditRefundBranchValidateSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private validateBranchExistance: ValidateBranchExistance;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach = (bus) => {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.vendorCredit.onRefundCreating,
|
||||||
|
// this.validateBranchExistanceOnCreditRefundCreating
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate branch existance on refund credit note creating.
|
||||||
|
// * @param {IRefundVendorCreditCreatingPayload} payload
|
||||||
|
// */
|
||||||
|
// private validateBranchExistanceOnCreditRefundCreating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// refundVendorCreditDTO,
|
||||||
|
// }: IRefundVendorCreditCreatingPayload) => {
|
||||||
|
// await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||||
|
// tenantId,
|
||||||
|
// refundVendorCreditDTO.branchId
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export * from './BillBranchSubscriber';
|
||||||
|
export * from './CashflowBranchDTOValidatorSubscriber';
|
||||||
|
export * from './CreditNoteBranchesSubscriber';
|
||||||
|
export * from './CreditNoteRefundBranchSubscriber';
|
||||||
|
export * from './ExpenseBranchSubscriber';
|
||||||
|
export * from './ManualJournalBranchSubscriber';
|
||||||
|
export * from './PaymentMadeBranchSubscriber';
|
||||||
|
export * from './PaymentReceiveBranchSubscriber';
|
||||||
|
export * from './SaleEstimateMultiBranchesSubscriber';
|
||||||
|
export * from './SaleReceiptBranchesSubscriber';
|
||||||
|
export * from './VendorCreditBranchSubscriber';
|
||||||
|
export * from './VendorCreditRefundBranchSubscriber';
|
||||||
|
export * from './InvoiceBranchValidatorSubscriber';
|
||||||
|
export * from './ContactOpeningBalanceBranchSubscriber';
|
||||||
|
export * from './InventoryAdjustmentBranchValidatorSubscriber';
|
||||||
@@ -15,6 +15,14 @@ import { events } from '@/common/events/events';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateExpense {
|
export class CreateExpense {
|
||||||
|
/**
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandExpenseValidator} validator - Command expense validator.
|
||||||
|
* @param {ExpenseDTOTransformer} transformDTO - Expense DTO transformer.
|
||||||
|
* @param {typeof Account} accountModel - Account model.
|
||||||
|
* @param {typeof Expense} expenseModel - Expense model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly eventEmitter: EventEmitter2,
|
private readonly eventEmitter: EventEmitter2,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ import {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeleteExpense {
|
export class DeleteExpense {
|
||||||
|
/**
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandExpenseValidator} validator - Command expense validator.
|
||||||
|
* @param {typeof Expense} expenseModel - Expense model.
|
||||||
|
* @param {typeof ExpenseCategory} expenseCategoryModel - Expense category model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly eventEmitter: EventEmitter2,
|
private readonly eventEmitter: EventEmitter2,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ import { events } from '@/common/events/events';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EditExpense {
|
export class EditExpense {
|
||||||
|
/**
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandExpenseValidator} validator - Command expense validator.
|
||||||
|
* @param {ExpenseDTOTransformer} transformDTO - Expense DTO transformer.
|
||||||
|
* @param {typeof Expense} expenseModel - Expense model.
|
||||||
|
* @param {typeof Account} accountModel - Account model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private eventEmitter: EventEmitter2,
|
private eventEmitter: EventEmitter2,
|
||||||
private uow: UnitOfWork,
|
private uow: UnitOfWork,
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PublishExpense {
|
export class PublishExpense {
|
||||||
|
/**
|
||||||
|
* @param {EventEmitter2} eventPublisher - Event emitter.
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandExpenseValidator} validator - Command expense validator.
|
||||||
|
* @param {typeof Expense} expenseModel - Expense model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly eventPublisher: EventEmitter2,
|
private readonly eventPublisher: EventEmitter2,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ import { GetItemCategoryService } from './queries/GetItemCategory.service';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ItemCategoryApplication {
|
export class ItemCategoryApplication {
|
||||||
|
/**
|
||||||
|
* @param {CreateItemCategoryService} createItemCategoryService - Create item category service.
|
||||||
|
* @param {EditItemCategoryService} editItemCategoryService - Edit item category service.
|
||||||
|
* @param {GetItemCategoryService} getItemCategoryService - Get item category service.
|
||||||
|
* @param {DeleteItemCategoryService} deleteItemCategoryService - Delete item category service.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly createItemCategoryService: CreateItemCategoryService,
|
private readonly createItemCategoryService: CreateItemCategoryService,
|
||||||
private readonly editItemCategoryService: EditItemCategoryService,
|
private readonly editItemCategoryService: EditItemCategoryService,
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import { ACCOUNT_ROOT_TYPE, ACCOUNT_TYPE } from '@/constants/accounts';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommandItemCategoryValidatorService {
|
export class CommandItemCategoryValidatorService {
|
||||||
|
/**
|
||||||
|
* @param {typeof ItemCategory} itemCategoryModel - Item category model.
|
||||||
|
* @param {typeof Account} accountModel - Account model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(ItemCategory.name)
|
@Inject(ItemCategory.name)
|
||||||
private readonly itemCategoryModel: typeof ItemCategory,
|
private readonly itemCategoryModel: typeof ItemCategory,
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ import { SystemUser } from '@/modules/System/models/SystemUser';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateItemCategoryService {
|
export class CreateItemCategoryService {
|
||||||
|
/**
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandItemCategoryValidatorService} validator - Command item category validator service.
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {typeof ItemCategory} itemCategoryModel - Item category model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
private readonly validator: CommandItemCategoryValidatorService,
|
private readonly validator: CommandItemCategoryValidatorService,
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ import { Item } from '@/modules/Items/models/Item';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeleteItemCategoryService {
|
export class DeleteItemCategoryService {
|
||||||
|
/**
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandItemCategoryValidatorService} validator - Command item category validator service.
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {typeof ItemCategory} itemCategoryModel - Item category model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
private readonly validator: CommandItemCategoryValidatorService,
|
private readonly validator: CommandItemCategoryValidatorService,
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ import { Inject } from '@nestjs/common';
|
|||||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||||
|
|
||||||
export class EditItemCategoryService {
|
export class EditItemCategoryService {
|
||||||
|
/**
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {CommandItemCategoryValidatorService} validator - Command item category validator service.
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {TenancyContext} tenancyContext - Tenancy context.
|
||||||
|
* @param {typeof ItemCategory} itemCategoryModel - Item category model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
private readonly validator: CommandItemCategoryValidatorService,
|
private readonly validator: CommandItemCategoryValidatorService,
|
||||||
@@ -21,6 +28,7 @@ export class EditItemCategoryService {
|
|||||||
@Inject(ItemCategory.name)
|
@Inject(ItemCategory.name)
|
||||||
private readonly itemCategoryModel: typeof ItemCategory,
|
private readonly itemCategoryModel: typeof ItemCategory,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edits item category.
|
* Edits item category.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import { ItemCategory } from '../models/ItemCategory.model';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetItemCategoryService {
|
export class GetItemCategoryService {
|
||||||
|
/**
|
||||||
|
* @param {typeof ItemCategory} itemCategoryModel - Item category model.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(ItemCategory.name)
|
@Inject(ItemCategory.name)
|
||||||
private readonly itemCategoryModel: typeof ItemCategory,
|
private readonly itemCategoryModel: typeof ItemCategory,
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import { TransformerContext } from './Transformer.types';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TransformerInjectable {
|
export class TransformerInjectable {
|
||||||
|
/**
|
||||||
|
* @param {TenancyContext} tenancyContext - Tenancy context.
|
||||||
|
* @param {I18nService} i18n - I18n service.
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private readonly tenancyContext: TenancyContext,
|
private readonly tenancyContext: TenancyContext,
|
||||||
private readonly i18n: I18nService,
|
private readonly i18n: I18nService,
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class BillActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all credit note transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateBillsWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { Bill, ItemEntry } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale estimates with primary warehouse.
|
||||||
|
// await Bill.query().update({ warehouseId: primaryWarehouse.id });
|
||||||
|
|
||||||
|
// // Update the sale estimates entries with primary warehouse.
|
||||||
|
// await ItemEntry.query().where('referenceType', 'Bill').update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreditNotesActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all credit note transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateCreditsWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { CreditNote, ItemEntry } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale estimates with primary warehouse.
|
||||||
|
// await CreditNote.query().update({ warehouseId: primaryWarehouse.id });
|
||||||
|
|
||||||
|
// // Update the sale estimates entries with primary warehouse.
|
||||||
|
// await ItemEntry.query().where('referenceType', 'CreditNote').update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class EstimatesActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all inventory transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateEstimatesWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { SaleEstimate, ItemEntry } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale estimates with primary warehouse.
|
||||||
|
// await SaleEstimate.query().update({ warehouseId: primaryWarehouse.id });
|
||||||
|
|
||||||
|
// // Update the sale estimates entries with primary warehouse.
|
||||||
|
// await ItemEntry.query().where('referenceType', 'SaleEstimate').update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class InventoryActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all inventory transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateInventoryTransactionsWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { InventoryTransaction, InventoryCostLotTracker } =
|
||||||
|
// this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the inventory transactions with primary warehouse.
|
||||||
|
// await InventoryTransaction.query().update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// await InventoryCostLotTracker.query().update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class InvoicesActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all inventory transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateInvoicesWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { SaleInvoice, ItemEntry } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the sale invoices with primary warehouse.
|
||||||
|
// await SaleInvoice.query().update({ warehouseId: primaryWarehouse.id });
|
||||||
|
|
||||||
|
// // Update the sale invoices entries with primary warehouse.
|
||||||
|
// await ItemEntry.query().where('referenceType', 'SaleInvoice').update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ReceiptActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all sale receipts transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateReceiptsWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { SaleReceipt, ItemEntry } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the vendor credits transactions with primary warehouse.
|
||||||
|
// await SaleReceipt.query().update({ warehouseId: primaryWarehouse.id });
|
||||||
|
|
||||||
|
// // Update the sale invoices entries with primary warehouse.
|
||||||
|
// await ItemEntry.query().where('referenceType', 'SaleReceipt').update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { IWarehouse } from '@/interfaces';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class VendorCreditActivateWarehouses {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all vendor credits transactions with the primary warehouse.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} primaryWarehouse
|
||||||
|
// * @returns {Promise<void>}
|
||||||
|
// */
|
||||||
|
// public updateCreditsWithWarehouse = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouse: IWarehouse
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { VendorCredit, ItemEntry } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// // Updates the vendor credits transactions with primary warehouse.
|
||||||
|
// await VendorCredit.query().update({ warehouseId: primaryWarehouse.id });
|
||||||
|
|
||||||
|
// // Update the sale invoices entries with primary warehouse.
|
||||||
|
// await ItemEntry.query().where('referenceType', 'VendorCredit').update({
|
||||||
|
// warehouseId: primaryWarehouse.id,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { IWarehousesActivatedPayload } from '@/interfaces';
|
||||||
|
// import { UpdateInventoryTransactionsWithWarehouse } from './UpdateInventoryTransactionsWithWarehouse';
|
||||||
|
// import { CreateInitialWarehousesItemsQuantity } from './CreateInitialWarehousesitemsQuantity';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ActivateWarehousesSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private updateInventoryTransactionsWithWarehouse: UpdateInventoryTransactionsWithWarehouse;
|
||||||
|
|
||||||
|
// @Inject()
|
||||||
|
// private createInitialWarehousesItemsQuantity: CreateInitialWarehousesItemsQuantity;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.warehouse.onActivated,
|
||||||
|
// this.updateInventoryTransactionsWithWarehouseOnActivating
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.warehouse.onActivated,
|
||||||
|
// this.createInitialWarehousesItemsQuantityOnActivating
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates inventory transactiont to primary warehouse once
|
||||||
|
// * multi-warehouses activated.
|
||||||
|
// * @param {IWarehousesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private updateInventoryTransactionsWithWarehouseOnActivating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryWarehouse,
|
||||||
|
// }: IWarehousesActivatedPayload) => {
|
||||||
|
// await this.updateInventoryTransactionsWithWarehouse.run(
|
||||||
|
// tenantId,
|
||||||
|
// primaryWarehouse.id
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Creates initial warehouses items quantity once the multi-warehouses activated.
|
||||||
|
// * @param {IWarehousesActivatedPayload}
|
||||||
|
// */
|
||||||
|
// private createInitialWarehousesItemsQuantityOnActivating = async ({
|
||||||
|
// tenantId,
|
||||||
|
// primaryWarehouse,
|
||||||
|
// }: IWarehousesActivatedPayload) => {
|
||||||
|
// await this.createInitialWarehousesItemsQuantity.run(
|
||||||
|
// tenantId,
|
||||||
|
// primaryWarehouse.id
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
26
packages/server-nest/src/modules/Warehouses/CRUDWarehouse.ts
Normal file
26
packages/server-nest/src/modules/Warehouses/CRUDWarehouse.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import { ServiceError } from '@/exceptions';
|
||||||
|
// import { ERRORS } from './contants';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// export class CRUDWarehouse {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// getWarehouseOrThrowNotFound = async (tenantId: number, warehouseId: number) => {
|
||||||
|
// const { Warehouse } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// const foundWarehouse = await Warehouse.query().findById(warehouseId);
|
||||||
|
|
||||||
|
// if (!foundWarehouse) {
|
||||||
|
// throw new ServiceError(ERRORS.WAREHOUSE_NOT_FOUND);
|
||||||
|
// }
|
||||||
|
// return foundWarehouse;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// throwIfWarehouseNotFound = (warehouse) => {
|
||||||
|
// if (!warehouse) {
|
||||||
|
// throw new ServiceError(ERRORS.WAREHOUSE_NOT_FOUND);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { Knex } from 'knex';
|
||||||
|
// import { IItem, IItemWarehouseQuantityChange } from '@/interfaces';
|
||||||
|
// import { WarehousesItemsQuantitySync } from './Integrations/WarehousesItemsQuantitySync';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class CreateInitialWarehousesItemsQuantity {
|
||||||
|
// @Inject()
|
||||||
|
// private warehousesItemsQuantitySync: WarehousesItemsQuantitySync;
|
||||||
|
|
||||||
|
// @Inject()
|
||||||
|
// private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Retrieves items warehouses quantity changes of the given inventory items.
|
||||||
|
// * @param {IItem[]} items
|
||||||
|
// * @param {IWarehouse} primaryWarehouse
|
||||||
|
// * @returns {IItemWarehouseQuantityChange[]}
|
||||||
|
// */
|
||||||
|
// private getWarehousesItemsChanges = (
|
||||||
|
// items: IItem[],
|
||||||
|
// primaryWarehouseId: number
|
||||||
|
// ): IItemWarehouseQuantityChange[] => {
|
||||||
|
// return items
|
||||||
|
// .filter((item: IItem) => item.quantityOnHand)
|
||||||
|
// .map((item: IItem) => ({
|
||||||
|
// itemId: item.id,
|
||||||
|
// warehouseId: primaryWarehouseId,
|
||||||
|
// amount: item.quantityOnHand,
|
||||||
|
// }));
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Creates initial warehouses items quantity.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// */
|
||||||
|
// public run = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// primaryWarehouseId: number,
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { Item } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// const items = await Item.query(trx).where('type', 'Inventory');
|
||||||
|
|
||||||
|
// const warehousesChanges = this.getWarehousesItemsChanges(
|
||||||
|
// items,
|
||||||
|
// primaryWarehouseId
|
||||||
|
// );
|
||||||
|
// await this.warehousesItemsQuantitySync.mutateWarehousesItemsQuantity(
|
||||||
|
// tenantId,
|
||||||
|
// warehousesChanges,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// import {
|
||||||
|
// BillsActivateWarehousesSubscriber,
|
||||||
|
// CreditsActivateWarehousesSubscriber,
|
||||||
|
// InvoicesActivateWarehousesSubscriber,
|
||||||
|
// ReceiptsActivateWarehousesSubscriber,
|
||||||
|
// EstimatesActivateWarehousesSubscriber,
|
||||||
|
// InventoryActivateWarehousesSubscriber,
|
||||||
|
// VendorCreditsActivateWarehousesSubscriber,
|
||||||
|
// } from './Subscribers/Activate';
|
||||||
|
// import {
|
||||||
|
// BillWarehousesValidateSubscriber,
|
||||||
|
// CreditNoteWarehousesValidateSubscriber,
|
||||||
|
// SaleReceiptWarehousesValidateSubscriber,
|
||||||
|
// SaleEstimateWarehousesValidateSubscriber,
|
||||||
|
// SaleInvoicesWarehousesValidateSubscriber,
|
||||||
|
// VendorCreditWarehousesValidateSubscriber,
|
||||||
|
// InventoryAdjustmentWarehouseValidatorSubscriber,
|
||||||
|
// } from './Subscribers/Validators';
|
||||||
|
// import { DeleteItemWarehousesQuantitySubscriber } from './Subscribers/DeleteItemWarehousesQuantitySubscriber';
|
||||||
|
|
||||||
|
// export default () => [
|
||||||
|
// BillsActivateWarehousesSubscriber,
|
||||||
|
// CreditsActivateWarehousesSubscriber,
|
||||||
|
// InvoicesActivateWarehousesSubscriber,
|
||||||
|
// ReceiptsActivateWarehousesSubscriber,,
|
||||||
|
// EstimatesActivateWarehousesSubscriber,
|
||||||
|
// InventoryActivateWarehousesSubscriber,
|
||||||
|
// VendorCreditsActivateWarehousesSubscriber,
|
||||||
|
|
||||||
|
// BillWarehousesValidateSubscriber,
|
||||||
|
// CreditNoteWarehousesValidateSubscriber,
|
||||||
|
// SaleReceiptWarehousesValidateSubscriber,
|
||||||
|
// SaleEstimateWarehousesValidateSubscriber,
|
||||||
|
// SaleInvoicesWarehousesValidateSubscriber,
|
||||||
|
// VendorCreditWarehousesValidateSubscriber,
|
||||||
|
// InventoryAdjustmentWarehouseValidatorSubscriber,
|
||||||
|
|
||||||
|
// DeleteItemWarehousesQuantitySubscriber,
|
||||||
|
// ];
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// import { Inject, Service } from 'typedi';
|
||||||
|
// import { chain, difference } from 'lodash';
|
||||||
|
// import { ServiceError } from '@/exceptions';
|
||||||
|
// import { ERRORS } from './constants';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class ValidateWarehouseExistance {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate transaction warehouse id existance.
|
||||||
|
// * @param transDTO
|
||||||
|
// * @param entries
|
||||||
|
// */
|
||||||
|
// public validateWarehouseIdExistance = (
|
||||||
|
// transDTO: { warehouseId?: number },
|
||||||
|
// entries: { warehouseId?: number }[] = []
|
||||||
|
// ) => {
|
||||||
|
// const notAssignedWarehouseEntries = entries.filter((e) => !e.warehouseId);
|
||||||
|
|
||||||
|
// if (notAssignedWarehouseEntries.length > 0 && !transDTO.warehouseId) {
|
||||||
|
// throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||||
|
// }
|
||||||
|
// if (entries.length === 0 && !transDTO.warehouseId) {
|
||||||
|
// throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate warehouse existance.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} warehouseId
|
||||||
|
// */
|
||||||
|
// public validateWarehouseExistance = (
|
||||||
|
// tenantId: number,
|
||||||
|
// warehouseId: number
|
||||||
|
// ) => {
|
||||||
|
// const { Warehouse } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// const warehouse = Warehouse.query().findById(warehouseId);
|
||||||
|
|
||||||
|
// if (!warehouse) {
|
||||||
|
// throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {{ warehouseId?: number }[]} entries
|
||||||
|
// */
|
||||||
|
// public validateItemEntriesWarehousesExistance = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// entries: { warehouseId?: number }[]
|
||||||
|
// ) => {
|
||||||
|
// const { Warehouse } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// const entriesWarehousesIds = chain(entries)
|
||||||
|
// .filter((e) => !!e.warehouseId)
|
||||||
|
// .map((e) => e.warehouseId)
|
||||||
|
// .uniq()
|
||||||
|
// .value();
|
||||||
|
|
||||||
|
// const warehouses = await Warehouse.query().whereIn(
|
||||||
|
// 'id',
|
||||||
|
// entriesWarehousesIds
|
||||||
|
// );
|
||||||
|
// const warehousesIds = warehouses.map((e) => e.id);
|
||||||
|
// const notFoundWarehousesIds = difference(
|
||||||
|
// entriesWarehousesIds,
|
||||||
|
// warehousesIds
|
||||||
|
// );
|
||||||
|
// if (notFoundWarehousesIds.length > 0) {
|
||||||
|
// throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { omit } from 'lodash';
|
||||||
|
// import * as R from 'ramda';
|
||||||
|
// import { WarehousesSettings } from '../WarehousesSettings';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class WarehouseTransactionDTOTransform {
|
||||||
|
// @Inject()
|
||||||
|
// private warehousesSettings: WarehousesSettings;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Excludes DTO warehouse id when mutli-warehouses feature is inactive.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @returns {Promise<Omit<T, 'warehouseId'> | T>}
|
||||||
|
// */
|
||||||
|
// private excludeDTOWarehouseIdWhenInactive = <
|
||||||
|
// T extends { warehouseId?: number }
|
||||||
|
// >(
|
||||||
|
// tenantId: number,
|
||||||
|
// DTO: T
|
||||||
|
// ): Omit<T, 'warehouseId'> | T => {
|
||||||
|
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
|
||||||
|
|
||||||
|
// return !isActive ? omit(DTO, ['warehouseId']) : DTO;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {T} DTO -
|
||||||
|
// * @returns {Omit<T, 'warehouseId'> | T}
|
||||||
|
// */
|
||||||
|
// public transformDTO =
|
||||||
|
// <T extends { warehouseId?: number }>(tenantId: number) =>
|
||||||
|
// (DTO: T): Omit<T, 'warehouseId'> | T => {
|
||||||
|
// return this.excludeDTOWarehouseIdWhenInactive<T>(tenantId, DTO);
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { isEmpty } from 'lodash';
|
||||||
|
// import { ValidateWarehouseExistance } from './ValidateWarehouseExistance';
|
||||||
|
// import { WarehousesSettings } from '../WarehousesSettings';
|
||||||
|
|
||||||
|
// interface IWarehouseTransactionDTO {
|
||||||
|
// warehouseId?: number|null;
|
||||||
|
// entries?: { warehouseId?: number|null }[];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class WarehousesDTOValidators {
|
||||||
|
// @Inject()
|
||||||
|
// private validateWarehouseExistanceService: ValidateWarehouseExistance;
|
||||||
|
|
||||||
|
// @Inject()
|
||||||
|
// private warehousesSettings: WarehousesSettings;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validates the warehouse existance of sale invoice transaction.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {ISaleInvoiceCreateDTO | ISaleInvoiceEditDTO} saleInvoiceDTO
|
||||||
|
// */
|
||||||
|
// public validateDTOWarehouseExistance = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// DTO: IWarehouseTransactionDTO
|
||||||
|
// ) => {
|
||||||
|
// // Validates the sale invoice warehouse id existance.
|
||||||
|
// this.validateWarehouseExistanceService.validateWarehouseIdExistance(
|
||||||
|
// DTO,
|
||||||
|
// DTO.entries
|
||||||
|
// );
|
||||||
|
// // Validate the sale invoice warehouse existance on the storage.
|
||||||
|
// if (DTO.warehouseId) {
|
||||||
|
// this.validateWarehouseExistanceService.validateWarehouseExistance(
|
||||||
|
// tenantId,
|
||||||
|
// DTO.warehouseId
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// // Validate the sale invoice entries warehouses existance on the storage.
|
||||||
|
// if (!isEmpty(DTO.entries)) {
|
||||||
|
// await this.validateWarehouseExistanceService.validateItemEntriesWarehousesExistance(
|
||||||
|
// tenantId,
|
||||||
|
// DTO.entries
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Validate the warehouse existance of
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {IWarehouseTransactionDTO} saleInvoiceDTO
|
||||||
|
// * @returns
|
||||||
|
// */
|
||||||
|
// public validateDTOWarehouseWhenActive = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// DTO: IWarehouseTransactionDTO
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
|
||||||
|
|
||||||
|
// // Can't continue if the multi-warehouses feature is inactive.
|
||||||
|
// if (!isActive) return;
|
||||||
|
|
||||||
|
// return this.validateDTOWarehouseExistance(tenantId, DTO);
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
// import {
|
||||||
|
// IInventoryTransaction,
|
||||||
|
// IItemWarehouseQuantityChange,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { set, get, chain, toPairs } from 'lodash';
|
||||||
|
|
||||||
|
// export class WarehousesItemsQuantity {
|
||||||
|
// balanceMap: { [warehouseId: number]: { [itemId: number]: number } } = {};
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {number} warehouseId
|
||||||
|
// * @param {number} itemId
|
||||||
|
// * @returns {number}
|
||||||
|
// */
|
||||||
|
// public get = (warehouseId: number, itemId: number): number => {
|
||||||
|
// return get(this.balanceMap, `${warehouseId}.${itemId}`, 0);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {number} warehouseId
|
||||||
|
// * @param {number} itemId
|
||||||
|
// * @param {number} amount
|
||||||
|
// * @returns {WarehousesItemsQuantity}
|
||||||
|
// */
|
||||||
|
// public set = (warehouseId: number, itemId: number, amount: number) => {
|
||||||
|
// if (!get(this.balanceMap, warehouseId)) {
|
||||||
|
// set(this.balanceMap, warehouseId, {});
|
||||||
|
// }
|
||||||
|
// set(this.balanceMap, `${warehouseId}.${itemId}`, amount);
|
||||||
|
|
||||||
|
// return this;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {number} warehouseId
|
||||||
|
// * @param {number} itemId
|
||||||
|
// * @param {number} amount
|
||||||
|
// * @returns {WarehousesItemsQuantity}
|
||||||
|
// */
|
||||||
|
// public increment = (warehouseId: number, itemId: number, amount: number) => {
|
||||||
|
// const oldAmount = this.get(warehouseId, itemId);
|
||||||
|
|
||||||
|
// return this.set(warehouseId, itemId, oldAmount + amount);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {number} warehouseId
|
||||||
|
// * @param {number} itemId
|
||||||
|
// * @param {number} amount
|
||||||
|
// * @returns {WarehousesItemsQuantity}
|
||||||
|
// */
|
||||||
|
// public decrement = (warehouseId: number, itemId: number, amount: number) => {
|
||||||
|
// const oldAmount = this.get(warehouseId, itemId);
|
||||||
|
|
||||||
|
// return this.set(warehouseId, itemId, oldAmount - amount);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @returns {WarehousesItemsQuantity}
|
||||||
|
// */
|
||||||
|
// public reverse = () => {
|
||||||
|
// const collection = this.toArray();
|
||||||
|
|
||||||
|
// collection.forEach((change) => {
|
||||||
|
// this.set(change.warehouseId, change.itemId, change.amount * -1);
|
||||||
|
// });
|
||||||
|
// return this;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @returns {IItemWarehouseQuantityChange[]}
|
||||||
|
// */
|
||||||
|
// public toArray = (): IItemWarehouseQuantityChange[] => {
|
||||||
|
// return chain(this.balanceMap)
|
||||||
|
// .toPairs()
|
||||||
|
// .map(([warehouseId, item]) => {
|
||||||
|
// const pairs = toPairs(item);
|
||||||
|
|
||||||
|
// return pairs.map(([itemId, amount]) => ({
|
||||||
|
// itemId: parseInt(itemId),
|
||||||
|
// warehouseId: parseInt(warehouseId),
|
||||||
|
// amount,
|
||||||
|
// }));
|
||||||
|
// })
|
||||||
|
// .flatten()
|
||||||
|
// .value();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// *
|
||||||
|
// * @param {IInventoryTransaction[]} inventoryTransactions
|
||||||
|
// * @returns {WarehousesItemsQuantity}
|
||||||
|
// */
|
||||||
|
// static fromInventoryTransaction = (
|
||||||
|
// inventoryTransactions: IInventoryTransaction[]
|
||||||
|
// ): WarehousesItemsQuantity => {
|
||||||
|
// const warehouseTransactions = inventoryTransactions.filter(
|
||||||
|
// (transaction) => transaction.warehouseId
|
||||||
|
// );
|
||||||
|
// const warehouseItemsQuantity = new WarehousesItemsQuantity();
|
||||||
|
|
||||||
|
// warehouseTransactions.forEach((transaction: IInventoryTransaction) => {
|
||||||
|
// const change =
|
||||||
|
// transaction.direction === 'IN'
|
||||||
|
// ? warehouseItemsQuantity.increment
|
||||||
|
// : warehouseItemsQuantity.decrement;
|
||||||
|
|
||||||
|
// change(transaction.warehouseId, transaction.itemId, transaction.quantity);
|
||||||
|
// });
|
||||||
|
// return warehouseItemsQuantity;
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// import events from '@/subscribers/events';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { WarehousesItemsQuantitySync } from './WarehousesItemsQuantitySync';
|
||||||
|
// import {
|
||||||
|
// IInventoryTransactionsCreatedPayload,
|
||||||
|
// IInventoryTransactionsDeletedPayload,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { WarehousesSettings } from '../WarehousesSettings';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class WarehousesItemsQuantitySyncSubscriber {
|
||||||
|
// @Inject()
|
||||||
|
// private warehousesItemsQuantitySync: WarehousesItemsQuantitySync;
|
||||||
|
|
||||||
|
// @Inject()
|
||||||
|
// private warehousesSettings: WarehousesSettings;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Attaches events with handlers.
|
||||||
|
// */
|
||||||
|
// public attach(bus) {
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.inventory.onInventoryTransactionsCreated,
|
||||||
|
// this.syncWarehousesItemsQuantityOnInventoryTransCreated
|
||||||
|
// );
|
||||||
|
// bus.subscribe(
|
||||||
|
// events.inventory.onInventoryTransactionsDeleted,
|
||||||
|
// this.syncWarehousesItemsQuantityOnInventoryTransDeleted
|
||||||
|
// );
|
||||||
|
// return bus;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Syncs warehouses items quantity once inventory transactions created.
|
||||||
|
// * @param {IInventoryTransactionsCreatedPayload}
|
||||||
|
// */
|
||||||
|
// private syncWarehousesItemsQuantityOnInventoryTransCreated = async ({
|
||||||
|
// tenantId,
|
||||||
|
// inventoryTransactions,
|
||||||
|
// trx,
|
||||||
|
// }: IInventoryTransactionsCreatedPayload) => {
|
||||||
|
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
|
||||||
|
|
||||||
|
// // Can't continue if the warehouses features is not active.
|
||||||
|
// if (!isActive) return;
|
||||||
|
|
||||||
|
// await this.warehousesItemsQuantitySync.mutateWarehousesItemsQuantityFromTransactions(
|
||||||
|
// tenantId,
|
||||||
|
// inventoryTransactions,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Syncs warehouses items quantity once inventory transactions deleted.
|
||||||
|
// * @param {IInventoryTransactionsDeletedPayload}
|
||||||
|
// */
|
||||||
|
// private syncWarehousesItemsQuantityOnInventoryTransDeleted = async ({
|
||||||
|
// tenantId,
|
||||||
|
// oldInventoryTransactions,
|
||||||
|
// trx,
|
||||||
|
// }: IInventoryTransactionsDeletedPayload) => {
|
||||||
|
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
|
||||||
|
|
||||||
|
// // Can't continue if the warehouses feature is not active yet.
|
||||||
|
// if (!isActive) return;
|
||||||
|
|
||||||
|
// await this.warehousesItemsQuantitySync.reverseWarehousesItemsQuantityFromTransactions(
|
||||||
|
// tenantId,
|
||||||
|
// oldInventoryTransactions,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
// import { Knex } from 'knex';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
// import { omit } from 'lodash';
|
||||||
|
// import {
|
||||||
|
// IInventoryTransaction,
|
||||||
|
// IItemWarehouseQuantityChange,
|
||||||
|
// } from '@/interfaces';
|
||||||
|
// import { WarehousesItemsQuantity } from './WarehousesItemsQuantity';
|
||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class WarehousesItemsQuantitySync {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Retrieves the reversed warehouses items quantity changes.
|
||||||
|
// * @param {IInventoryTransaction[]} inventoryTransactions
|
||||||
|
// * @returns {IItemWarehouseQuantityChange[]}
|
||||||
|
// */
|
||||||
|
// public getReverseWarehousesItemsQuantityChanges = (
|
||||||
|
// inventoryTransactions: IInventoryTransaction[]
|
||||||
|
// ): IItemWarehouseQuantityChange[] => {
|
||||||
|
// const warehouseItemsQuantity =
|
||||||
|
// WarehousesItemsQuantity.fromInventoryTransaction(inventoryTransactions);
|
||||||
|
|
||||||
|
// return warehouseItemsQuantity.reverse().toArray();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Retrieves the warehouses items changes from the given inventory tranasctions.
|
||||||
|
// * @param {IInventoryTransaction[]} inventoryTransactions
|
||||||
|
// * @returns {IItemWarehouseQuantityChange[]}
|
||||||
|
// */
|
||||||
|
// public getWarehousesItemsQuantityChange = (
|
||||||
|
// inventoryTransactions: IInventoryTransaction[]
|
||||||
|
// ): IItemWarehouseQuantityChange[] => {
|
||||||
|
// const warehouseItemsQuantity =
|
||||||
|
// WarehousesItemsQuantity.fromInventoryTransaction(inventoryTransactions);
|
||||||
|
|
||||||
|
// return warehouseItemsQuantity.toArray();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Mutates warehouses items quantity on hand on the storage.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {IItemWarehouseQuantityChange[]} warehousesItemsQuantity
|
||||||
|
// * @param {Knex.Transaction} trx
|
||||||
|
// */
|
||||||
|
// public mutateWarehousesItemsQuantity = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// warehousesItemsQuantity: IItemWarehouseQuantityChange[],
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const mutationsOpers = warehousesItemsQuantity.map(
|
||||||
|
// (change: IItemWarehouseQuantityChange) =>
|
||||||
|
// this.mutateWarehouseItemQuantity(tenantId, change, trx)
|
||||||
|
// );
|
||||||
|
// await Promise.all(mutationsOpers);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Mutates the warehouse item quantity.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {number} warehouseItemQuantity
|
||||||
|
// * @param {Knex.Transaction} trx
|
||||||
|
// */
|
||||||
|
// public mutateWarehouseItemQuantity = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// warehouseItemQuantity: IItemWarehouseQuantityChange,
|
||||||
|
// trx: Knex.Transaction
|
||||||
|
// ): Promise<void> => {
|
||||||
|
// const { ItemWarehouseQuantity } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// const itemWarehouseQuantity = await ItemWarehouseQuantity.query(trx)
|
||||||
|
// .where('itemId', warehouseItemQuantity.itemId)
|
||||||
|
// .where('warehouseId', warehouseItemQuantity.warehouseId)
|
||||||
|
// .first();
|
||||||
|
|
||||||
|
// if (itemWarehouseQuantity) {
|
||||||
|
// await ItemWarehouseQuantity.changeAmount(
|
||||||
|
// {
|
||||||
|
// itemId: warehouseItemQuantity.itemId,
|
||||||
|
// warehouseId: warehouseItemQuantity.warehouseId,
|
||||||
|
// },
|
||||||
|
// 'quantityOnHand',
|
||||||
|
// warehouseItemQuantity.amount,
|
||||||
|
// trx
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// await ItemWarehouseQuantity.query(trx).insert({
|
||||||
|
// ...omit(warehouseItemQuantity, ['amount']),
|
||||||
|
// quantityOnHand: warehouseItemQuantity.amount,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Mutates warehouses items quantity from inventory transactions.
|
||||||
|
// * @param {number} tenantId -
|
||||||
|
// * @param {IInventoryTransaction[]} inventoryTransactions -
|
||||||
|
// * @param {Knex.Transaction}
|
||||||
|
// */
|
||||||
|
// public mutateWarehousesItemsQuantityFromTransactions = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// inventoryTransactions: IInventoryTransaction[],
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const changes = this.getWarehousesItemsQuantityChange(
|
||||||
|
// inventoryTransactions
|
||||||
|
// );
|
||||||
|
// await this.mutateWarehousesItemsQuantity(tenantId, changes, trx);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Reverses warehouses items quantity from inventory transactions.
|
||||||
|
// * @param {number} tenantId
|
||||||
|
// * @param {IInventoryTransaction[]} inventoryTransactions
|
||||||
|
// * @param {Knex.Transaction} trx
|
||||||
|
// */
|
||||||
|
// public reverseWarehousesItemsQuantityFromTransactions = async (
|
||||||
|
// tenantId: number,
|
||||||
|
// inventoryTransactions: IInventoryTransaction[],
|
||||||
|
// trx?: Knex.Transaction
|
||||||
|
// ) => {
|
||||||
|
// const changes = this.getReverseWarehousesItemsQuantityChanges(
|
||||||
|
// inventoryTransactions
|
||||||
|
// );
|
||||||
|
// await this.mutateWarehousesItemsQuantity(tenantId, changes, trx);
|
||||||
|
// };
|
||||||
|
// }
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export const ERRORS = {
|
||||||
|
WAREHOUSE_ID_NOT_FOUND: 'WAREHOUSE_ID_NOT_FOUND',
|
||||||
|
ITEM_ENTRY_WAREHOUSE_ID_NOT_FOUND: 'ITEM_ENTRY_WAREHOUSE_ID_NOT_FOUND',
|
||||||
|
};
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { GetItemWarehouseTransformer } from './GettItemWarehouseTransformer';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ItemWarehouseQuantity } from '../models/ItemWarehouseQuantity';
|
||||||
|
import { Item } from '@/modules/Items/models/Item';
|
||||||
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GetItemWarehouses {
|
||||||
|
constructor(
|
||||||
|
@Inject(ItemWarehouseQuantity.name)
|
||||||
|
private readonly itemWarehouseQuantityModel: typeof ItemWarehouseQuantity,
|
||||||
|
|
||||||
|
@Inject(Item.name)
|
||||||
|
private readonly itemModel: typeof Item,
|
||||||
|
private readonly transformer: TransformerInjectable,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the item warehouses.
|
||||||
|
* @param {number} itemId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getItemWarehouses = async (itemId: number) => {
|
||||||
|
// Retrieves specific item or throw not found service error.
|
||||||
|
const item = await this.itemModel
|
||||||
|
.query()
|
||||||
|
.findById(itemId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
const itemWarehouses = await this.itemWarehouseQuantityModel
|
||||||
|
.query()
|
||||||
|
.where('itemId', itemId)
|
||||||
|
.withGraphFetched('warehouse');
|
||||||
|
|
||||||
|
// Retrieves the transformed items warehouses.
|
||||||
|
return this.transformer.transform(
|
||||||
|
itemWarehouses,
|
||||||
|
new GetItemWarehouseTransformer(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||||
|
import { Item } from '@/modules/Items/models/Item';
|
||||||
|
|
||||||
|
export class GetItemWarehouseTransformer extends Transformer {
|
||||||
|
/**
|
||||||
|
* Include these attributes to sale invoice object.
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
public includeAttributes = (): string[] => {
|
||||||
|
return [
|
||||||
|
'warehouseId',
|
||||||
|
'warehouseName',
|
||||||
|
'warehouseCode',
|
||||||
|
'quantityOnHandFormatted',
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude the warehouse attribute.
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
public excludeAttributes = (): string[] => {
|
||||||
|
return ['warehouse'];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formatted sell price.
|
||||||
|
* @param item
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
public quantityOnHandFormatted(item: Item): string {
|
||||||
|
return this.formatNumber(item.quantityOnHand, { money: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
public warehouseCode(item: Item): string {
|
||||||
|
return item.warehouse.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public warehouseName(item: Item): string {
|
||||||
|
return item.warehouse.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public warehouseId(item: Item): number {
|
||||||
|
return item.warehouse.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
// import { Service, Inject } from 'typedi';
|
||||||
|
|
||||||
|
// @Service()
|
||||||
|
// export class UpdateInventoryTransactionsWithWarehouse {
|
||||||
|
// @Inject()
|
||||||
|
// tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Updates all inventory transactions with primary warehouse.
|
||||||
|
// * @param {number} tenantId -
|
||||||
|
// * @param {number} warehouseId -
|
||||||
|
// */
|
||||||
|
// public run = async (tenantId: number, primaryWarehouseId: number) => {
|
||||||
|
// const { InventoryTransaction } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
// await InventoryTransaction.query().update({
|
||||||
|
// warehouseId: primaryWarehouseId,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// }
|
||||||
212
packages/server-nest/src/modules/Warehouses/Warehouse.types.ts
Normal file
212
packages/server-nest/src/modules/Warehouses/Warehouse.types.ts
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
|
||||||
|
export interface IWarehouse {
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
export interface IWarehouseTransfer {
|
||||||
|
id?: number;
|
||||||
|
date: Date;
|
||||||
|
fromWarehouseId: number;
|
||||||
|
toWarehouseId: number;
|
||||||
|
reason?: string;
|
||||||
|
transactionNumber: string;
|
||||||
|
entries: IWarehouseTransferEntry[];
|
||||||
|
transferInitiatedAt?: Date;
|
||||||
|
transferDeliveredAt?: Date;
|
||||||
|
|
||||||
|
isInitiated?: boolean;
|
||||||
|
isTransferred?: boolean;
|
||||||
|
}
|
||||||
|
export interface IWarehouseTransferEntry {
|
||||||
|
id?: number;
|
||||||
|
index?: number;
|
||||||
|
itemId: number;
|
||||||
|
description: string;
|
||||||
|
quantity: number;
|
||||||
|
cost: number;
|
||||||
|
}
|
||||||
|
export interface ICreateWarehouseDTO {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
city?: string;
|
||||||
|
country?: string;
|
||||||
|
address?: string;
|
||||||
|
|
||||||
|
primary?: boolean;
|
||||||
|
}
|
||||||
|
export interface IEditWarehouseDTO {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
city: string;
|
||||||
|
country: string;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferEntryDTO {
|
||||||
|
index?: number;
|
||||||
|
itemId: number;
|
||||||
|
description: string;
|
||||||
|
quantity: number;
|
||||||
|
cost?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICreateWarehouseTransferDTO {
|
||||||
|
fromWarehouseId: number;
|
||||||
|
toWarehouseId: number;
|
||||||
|
transactionNumber: string;
|
||||||
|
date: Date;
|
||||||
|
transferInitiated: boolean;
|
||||||
|
transferDelivered: boolean;
|
||||||
|
entries: IWarehouseTransferEntryDTO[];
|
||||||
|
}
|
||||||
|
export interface IEditWarehouseTransferDTO {
|
||||||
|
fromWarehouseId: number;
|
||||||
|
toWarehouseId: number;
|
||||||
|
transactionNumber: string;
|
||||||
|
date: Date;
|
||||||
|
entries: {
|
||||||
|
id?: number;
|
||||||
|
itemId: number;
|
||||||
|
description: string;
|
||||||
|
quantity: number;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseEditPayload {
|
||||||
|
tenantId: number;
|
||||||
|
warehouseId: number;
|
||||||
|
warehouseDTO: IEditWarehouseDTO;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseEditedPayload {
|
||||||
|
tenantId: number;
|
||||||
|
warehouse: IWarehouse;
|
||||||
|
warehouseDTO: IEditWarehouseDTO;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseDeletePayload {
|
||||||
|
// tenantId: number;
|
||||||
|
warehouseId: number;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
export interface IWarehouseDeletedPayload {
|
||||||
|
tenantId: number;
|
||||||
|
warehouseId: number;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
export interface IWarehouseCreatePayload {
|
||||||
|
// tenantId: number;
|
||||||
|
warehouseDTO: ICreateWarehouseDTO;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseCreatedPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
warehouse: IWarehouse;
|
||||||
|
warehouseDTO: ICreateWarehouseDTO;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferCreate {
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
warehouseTransferDTO: ICreateWarehouseTransferDTO;
|
||||||
|
tenantId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferCreated {
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
warehouseTransfer: IWarehouseTransfer;
|
||||||
|
warehouseTransferDTO: ICreateWarehouseTransferDTO;
|
||||||
|
// tenantId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferEditPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
editWarehouseDTO: IEditWarehouseTransferDTO;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferEditedPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
editWarehouseDTO: IEditWarehouseTransferDTO;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
warehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferDeletePayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferDeletedPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
warehouseTransfer: IWarehouseTransfer;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetWarehousesTransfersFilterDTO {
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
searchKeyword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IItemWarehouseQuantityChange {
|
||||||
|
itemId: number;
|
||||||
|
warehouseId: number;
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehousesActivatePayload {
|
||||||
|
// tenantId: number;
|
||||||
|
}
|
||||||
|
export interface IWarehousesActivatedPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
primaryWarehouse: IWarehouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseMarkAsPrimaryPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldWarehouse: IWarehouse;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
export interface IWarehouseMarkedAsPrimaryPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldWarehouse: IWarehouse;
|
||||||
|
markedWarehouse: IWarehouse;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferInitiatePayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface IWarehouseTransferInitiatedPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
warehouseTransfer: IWarehouseTransfer;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferTransferingPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWarehouseTransferTransferredPayload {
|
||||||
|
// tenantId: number;
|
||||||
|
warehouseTransfer: IWarehouseTransfer;
|
||||||
|
oldWarehouseTransfer: IWarehouseTransfer;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import {
|
||||||
|
ICreateWarehouseDTO,
|
||||||
|
IEditWarehouseDTO,
|
||||||
|
IWarehouse,
|
||||||
|
} from './Warehouse.types';
|
||||||
|
import { ActivateWarehousesService } from './commands/ActivateWarehouses';
|
||||||
|
import { CreateWarehouse } from './commands/CreateWarehouse.service';
|
||||||
|
import { DeleteWarehouseService } from './commands/DeleteWarehouse.service';
|
||||||
|
import { EditWarehouse } from './commands/EditWarehouse.service';
|
||||||
|
import { GetWarehouse } from './queries/GetWarehouse';
|
||||||
|
import { GetWarehouses } from './queries/GetWarehouses';
|
||||||
|
import { GetItemWarehouses } from './Items/GetItemWarehouses';
|
||||||
|
import { WarehouseMarkPrimary } from './commands/WarehouseMarkPrimary.service';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WarehousesApplication {
|
||||||
|
constructor(
|
||||||
|
private createWarehouseService: CreateWarehouse,
|
||||||
|
private editWarehouseService: EditWarehouse,
|
||||||
|
private deleteWarehouseService: DeleteWarehouseService,
|
||||||
|
private getWarehouseService: GetWarehouse,
|
||||||
|
private getWarehousesService: GetWarehouses,
|
||||||
|
private activateWarehousesService: ActivateWarehousesService,
|
||||||
|
private markWarehousePrimaryService: WarehouseMarkPrimary,
|
||||||
|
private getItemWarehousesService: GetItemWarehouses,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new warehouse.
|
||||||
|
* @param {ICreateWarehouseDTO} createWarehouseDTO
|
||||||
|
* @returns {Promise<IWarehouse>}
|
||||||
|
*/
|
||||||
|
public createWarehouse = (createWarehouseDTO: ICreateWarehouseDTO) => {
|
||||||
|
return this.createWarehouseService.createWarehouse(createWarehouseDTO);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the given warehouse.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} warehouseId
|
||||||
|
* @param {IEditWarehouseDTO} editWarehouseDTO
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
public editWarehouse = (
|
||||||
|
warehouseId: number,
|
||||||
|
editWarehouseDTO: IEditWarehouseDTO,
|
||||||
|
) => {
|
||||||
|
return this.editWarehouseService.editWarehouse(
|
||||||
|
warehouseId,
|
||||||
|
editWarehouseDTO,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the given warehouse.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} warehouseId
|
||||||
|
*/
|
||||||
|
public deleteWarehouse = (warehouseId: number) => {
|
||||||
|
return this.deleteWarehouseService.deleteWarehouse(warehouseId);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the specific warehouse.
|
||||||
|
* @param {number} warehouseId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getWarehouse = (warehouseId: number) => {
|
||||||
|
return this.getWarehouseService.getWarehouse(warehouseId);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getWarehouses = () => {
|
||||||
|
return this.getWarehousesService.getWarehouses();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the warehouses feature.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
public activateWarehouses = () => {
|
||||||
|
return this.activateWarehousesService.activateWarehouses();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the given warehouse as primary.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
* @returns {Promise<IWarehouse>}
|
||||||
|
*/
|
||||||
|
public markWarehousePrimary = (
|
||||||
|
tenantId: number,
|
||||||
|
warehouseId: number,
|
||||||
|
): Promise<IWarehouse> => {
|
||||||
|
return this.markWarehousePrimaryService.markAsPrimary(warehouseId);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the specific item warehouses quantity.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} itemId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getItemWarehouses = (itemId: number): Promise<any> => {
|
||||||
|
return this.getItemWarehousesService.getItemWarehouses(itemId);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WarehousesSettings {
|
||||||
|
/**
|
||||||
|
* Marks multi-warehouses as activated.
|
||||||
|
*/
|
||||||
|
public markMutliwarehoussAsActivated = () => {
|
||||||
|
// const settings = this.tenancy.settings(tenantId);
|
||||||
|
|
||||||
|
// settings.set({ group: 'features', key: Features.WAREHOUSES, value: 1 });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines multi-warehouses is active.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public isMultiWarehousesActive = () => {
|
||||||
|
// const settings = this.tenancy.settings(tenantId);
|
||||||
|
|
||||||
|
// return settings.get({ group: 'features', key: Features.WAREHOUSES });
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { CreateInitialWarehouse } from './CreateInitialWarehouse.service';
|
||||||
|
import { WarehousesSettings } from '../WarehousesSettings';
|
||||||
|
import { ERRORS } from '../contants';
|
||||||
|
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
import { events } from '@/common/events/events';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ActivateWarehousesService {
|
||||||
|
/**
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {CreateInitialWarehouse} createInitialWarehouse - Create initial warehouse service.
|
||||||
|
* @param {WarehousesSettings} settings - Warehouses settings.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private readonly uow: UnitOfWork,
|
||||||
|
private readonly eventEmitter: EventEmitter2,
|
||||||
|
private readonly createInitialWarehouse: CreateInitialWarehouse,
|
||||||
|
private readonly settings: WarehousesSettings,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws error if the multi-warehouses is already activated.
|
||||||
|
*/
|
||||||
|
private throwIfWarehousesActivated(isActivated: boolean): void {
|
||||||
|
if (isActivated) {
|
||||||
|
throw new ServiceError(ERRORS.MUTLI_WAREHOUSES_ALREADY_ACTIVATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the multi-warehouses.
|
||||||
|
*
|
||||||
|
* - Creates a new warehouses and mark it as primary.
|
||||||
|
* - Seed warehouses items quantity.
|
||||||
|
* - Mutate inventory transactions with the primary warehouse.
|
||||||
|
*/
|
||||||
|
public async activateWarehouses(): Promise<void> {
|
||||||
|
const isActivated = this.settings.isMultiWarehousesActive();
|
||||||
|
this.throwIfWarehousesActivated(isActivated);
|
||||||
|
|
||||||
|
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
|
await this.eventEmitter.emitAsync(events.warehouse.onActivate, { trx });
|
||||||
|
|
||||||
|
const primaryWarehouse =
|
||||||
|
await this.createInitialWarehouse.createInitialWarehouse();
|
||||||
|
|
||||||
|
this.settings.markMutliwarehoussAsActivated();
|
||||||
|
|
||||||
|
await this.eventEmitter.emitAsync(events.warehouse.onActivated, {
|
||||||
|
primaryWarehouse,
|
||||||
|
trx,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { CreateWarehouse } from './CreateWarehouse.service';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { I18nContext } from 'nestjs-i18n';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CreateInitialWarehouse {
|
||||||
|
/**
|
||||||
|
* @param {CreateWarehouse} createWarehouse - Create warehouse service.
|
||||||
|
* @param {I18nContext} i18n - I18n context.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private readonly createWarehouse: CreateWarehouse,
|
||||||
|
private readonly i18n: I18nContext,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a initial warehouse.
|
||||||
|
* @param {number} tenantId
|
||||||
|
*/
|
||||||
|
public createInitialWarehouse = async () => {
|
||||||
|
return this.createWarehouse.createWarehouse({
|
||||||
|
name: this.i18n.t('warehouses.primary_warehouse'),
|
||||||
|
code: '10001',
|
||||||
|
primary: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import {
|
||||||
|
ICreateWarehouseDTO,
|
||||||
|
IWarehouseCreatedPayload,
|
||||||
|
IWarehouseCreatePayload,
|
||||||
|
} from '../Warehouse.types';
|
||||||
|
import { WarehouseValidator } from './WarehouseValidator.service';
|
||||||
|
import { Warehouse } from '../models/Warehouse.model';
|
||||||
|
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
|
import { events } from '@/common/events/events';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CreateWarehouse {
|
||||||
|
/**
|
||||||
|
* @param {UnitOfWork} uow - Unit of work.
|
||||||
|
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||||
|
* @param {WarehouseValidator} validator - Warehouse command validator.
|
||||||
|
* @param {typeof Warehouse} warehouseModel - Warehouse model.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private readonly uow: UnitOfWork,
|
||||||
|
private readonly eventEmitter: EventEmitter2,
|
||||||
|
private readonly validator: WarehouseValidator,
|
||||||
|
|
||||||
|
@Inject(Warehouse.name)
|
||||||
|
private readonly warehouseModel: typeof Warehouse,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorize the warehouse before creating.
|
||||||
|
* @param {ICreateWarehouseDTO} warehouseDTO -
|
||||||
|
*/
|
||||||
|
public authorize = async (warehouseDTO: ICreateWarehouseDTO) => {
|
||||||
|
if (warehouseDTO.code) {
|
||||||
|
await this.validator.validateWarehouseCodeUnique(warehouseDTO.code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new warehouse on the system.
|
||||||
|
* @param {ICreateWarehouseDTO} warehouseDTO
|
||||||
|
*/
|
||||||
|
public createWarehouse = async (
|
||||||
|
warehouseDTO: ICreateWarehouseDTO
|
||||||
|
): Promise<Warehouse> => {
|
||||||
|
// Authorize warehouse before creating.
|
||||||
|
await this.authorize(warehouseDTO);
|
||||||
|
|
||||||
|
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
|
// Triggers `onWarehouseCreate` event.
|
||||||
|
await this.eventEmitter.emitAsync(events.warehouse.onEdit, {
|
||||||
|
warehouseDTO,
|
||||||
|
trx,
|
||||||
|
} as IWarehouseCreatePayload);
|
||||||
|
|
||||||
|
// Creates a new warehouse on the storage.
|
||||||
|
const warehouse = await this.warehouseModel.query(trx).insertAndFetch({
|
||||||
|
...warehouseDTO,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Triggers `onWarehouseCreated` event.
|
||||||
|
await this.eventEmitter.emitAsync(events.warehouse.onCreated, {
|
||||||
|
warehouseDTO,
|
||||||
|
warehouse,
|
||||||
|
trx,
|
||||||
|
} as IWarehouseCreatedPayload);
|
||||||
|
|
||||||
|
return warehouse;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ItemWarehouseQuantity } from '../models/ItemWarehouseQuantity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DeleteItemWarehousesQuantity {
|
||||||
|
/**
|
||||||
|
* @param {typeof ItemWarehouseQuantity} itemWarehouseQuantityModel - Item warehouse quantity model.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
@Inject(ItemWarehouseQuantity.name)
|
||||||
|
private readonly itemWarehouseQuantityModel: typeof ItemWarehouseQuantity,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the given item warehouses quantities.
|
||||||
|
* @param {number} itemId
|
||||||
|
* @param {Knex.Transaction} trx -
|
||||||
|
*/
|
||||||
|
public deleteItemWarehousesQuantity = async (
|
||||||
|
itemId: number,
|
||||||
|
trx?: Knex.Transaction,
|
||||||
|
): Promise<void> => {
|
||||||
|
await this.itemWarehouseQuantityModel
|
||||||
|
.query(trx)
|
||||||
|
.where('itemId', itemId)
|
||||||
|
.delete();
|
||||||
|
};
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user