mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
add server to monorepo.
This commit is contained in:
90
packages/server/src/services/Branches/ActivateBranches.ts
Normal file
90
packages/server/src/services/Branches/ActivateBranches.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { ERRORS } from './constants';
|
||||
import { Knex } from 'knex';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IBranchesActivatedPayload,
|
||||
IBranchesActivatePayload,
|
||||
} from '@/interfaces';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import { CreateBranch } from './CreateBranch';
|
||||
import { BranchesSettings } from './BranchesSettings';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
|
||||
@Service()
|
||||
export class ActivateBranches {
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
@Inject()
|
||||
private createBranch: CreateBranch;
|
||||
|
||||
@Inject()
|
||||
private branchesSettings: BranchesSettings;
|
||||
|
||||
/**
|
||||
* Throws service error if multi-branches feature is already activated.
|
||||
* @param {boolean} isActivated
|
||||
*/
|
||||
private throwIfMultiBranchesActivated = (isActivated: boolean) => {
|
||||
if (isActivated) {
|
||||
throw new ServiceError(ERRORS.MUTLI_BRANCHES_ALREADY_ACTIVATED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new initial branch.
|
||||
* @param {number} tenantId
|
||||
*/
|
||||
private createInitialBranch = (tenantId: number) => {
|
||||
const { __ } = this.tenancy.i18n(tenantId);
|
||||
|
||||
return this.createBranch.createBranch(tenantId, {
|
||||
name: __('branches.head_branch'),
|
||||
code: '10001',
|
||||
primary: true,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate multi-branches feature.
|
||||
* @param {number} tenantId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public activateBranches = (tenantId: number): Promise<void> => {
|
||||
const isActivated = this.branchesSettings.isMultiBranchesActive(tenantId);
|
||||
|
||||
// Throw error if mutli-branches is already activated.
|
||||
this.throwIfMultiBranchesActivated(isActivated);
|
||||
|
||||
// Activate multi-branches under unit-of-work envirement.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchActivate` branch.
|
||||
await this.eventPublisher.emitAsync(events.branch.onActivate, {
|
||||
tenantId,
|
||||
trx,
|
||||
} as IBranchesActivatePayload);
|
||||
|
||||
// Create a new branch as primary branch.
|
||||
const primaryBranch = await this.createInitialBranch(tenantId);
|
||||
|
||||
// Mark the mutli-branches is activated.
|
||||
await this.branchesSettings.markMultiBranchesAsActivated(tenantId);
|
||||
|
||||
// Triggers `onBranchActivated` branch.
|
||||
await this.eventPublisher.emitAsync(events.branch.onActivated, {
|
||||
tenantId,
|
||||
primaryBranch,
|
||||
trx,
|
||||
} as IBranchesActivatedPayload);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
52
packages/server/src/services/Branches/BranchValidate.ts
Normal file
52
packages/server/src/services/Branches/BranchValidate.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
@Service()
|
||||
export class BranchValidator {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
public validateBranchNotOnlyWarehouse = async (
|
||||
tenantId: number,
|
||||
branchId: number
|
||||
) => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
const warehouses = await Branch.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 {number} tenantId
|
||||
* @param {string} code
|
||||
* @param {number} exceptBranchId
|
||||
*/
|
||||
public validateBranchCodeUnique = async (
|
||||
tenantId: number,
|
||||
code: string,
|
||||
exceptBranchId?: number
|
||||
): Promise<void> => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
const branch = await Branch.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);
|
||||
}
|
||||
};
|
||||
}
|
||||
112
packages/server/src/services/Branches/BranchesApplication.ts
Normal file
112
packages/server/src/services/Branches/BranchesApplication.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { IBranch, ICreateBranchDTO, IEditBranchDTO } from '@/interfaces';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { ActivateBranches } from './ActivateBranches';
|
||||
import { CreateBranch } from './CreateBranch';
|
||||
import { DeleteBranch } from './DeleteBranch';
|
||||
import { EditBranch } from './EditBranch';
|
||||
import { GetBranch } from './GetBranch';
|
||||
import { GetBranches } from './GetBranches';
|
||||
import { MarkBranchAsPrimary } from './MarkBranchAsPrimary';
|
||||
|
||||
@Service()
|
||||
export class BranchesApplication {
|
||||
@Inject()
|
||||
private deleteBranchService: DeleteBranch;
|
||||
|
||||
@Inject()
|
||||
private createBranchService: CreateBranch;
|
||||
|
||||
@Inject()
|
||||
private getBranchService: GetBranch;
|
||||
|
||||
@Inject()
|
||||
private editBranchService: EditBranch;
|
||||
|
||||
@Inject()
|
||||
private getBranchesService: GetBranches;
|
||||
|
||||
@Inject()
|
||||
private activateBranchesService: ActivateBranches;
|
||||
|
||||
@Inject()
|
||||
private markBranchAsPrimaryService: MarkBranchAsPrimary;
|
||||
|
||||
/**
|
||||
* Retrieves branches list.
|
||||
* @param {number} tenantId
|
||||
* @returns {IBranch}
|
||||
*/
|
||||
public getBranches = (tenantId: number): Promise<IBranch[]> => {
|
||||
return this.getBranchesService.getBranches(tenantId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the given branch details.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public getBranch = (tenantId: number, branchId: number): Promise<IBranch> => {
|
||||
return this.getBranchService.getBranch(tenantId, branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new branch.
|
||||
* @param {number} tenantId -
|
||||
* @param {ICreateBranchDTO} createBranchDTO
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public createBranch = (
|
||||
tenantId: number,
|
||||
createBranchDTO: ICreateBranchDTO
|
||||
): Promise<IBranch> => {
|
||||
return this.createBranchService.createBranch(tenantId, createBranchDTO);
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits the given branch.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @param {IEditBranchDTO} editBranchDTO - Edit branch DTO.
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public editBranch = (
|
||||
tenantId: number,
|
||||
branchId: number,
|
||||
editBranchDTO: IEditBranchDTO
|
||||
): Promise<IBranch> => {
|
||||
return this.editBranchService.editBranch(tenantId, branchId, editBranchDTO);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the given branch.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} branchId - Branch id.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteBranch = (tenantId: number, branchId: number): Promise<void> => {
|
||||
return this.deleteBranchService.deleteBranch(tenantId, branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Activates the given branches.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public activateBranches = (tenantId: number): Promise<void> => {
|
||||
return this.activateBranchesService.activateBranches(tenantId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Marks the given branch as primary.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public markBranchAsPrimary = async (
|
||||
tenantId: number,
|
||||
branchId: number
|
||||
): Promise<IBranch> => {
|
||||
return this.markBranchAsPrimaryService.markAsPrimary(tenantId, branchId);
|
||||
};
|
||||
}
|
||||
29
packages/server/src/services/Branches/BranchesSettings.ts
Normal file
29
packages/server/src/services/Branches/BranchesSettings.ts
Normal file
@@ -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/src/services/Branches/CRUDBranch.ts
Normal file
30
packages/server/src/services/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;
|
||||
}
|
||||
}
|
||||
64
packages/server/src/services/Branches/CreateBranch.ts
Normal file
64
packages/server/src/services/Branches/CreateBranch.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IBranch,
|
||||
IBranchCreatedPayload,
|
||||
IBranchCreatePayload,
|
||||
ICreateBranchDTO,
|
||||
} from '@/interfaces';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import { BranchValidator } from './BranchValidate';
|
||||
|
||||
@Service()
|
||||
export class CreateBranch {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
@Inject()
|
||||
private validator: BranchValidator;
|
||||
|
||||
/**
|
||||
* Creates a new branch.
|
||||
* @param {number} tenantId
|
||||
* @param {ICreateBranchDTO} createBranchDTO
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public createBranch = (
|
||||
tenantId: number,
|
||||
createBranchDTO: ICreateBranchDTO
|
||||
): Promise<IBranch> => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
// Creates a new branch under unit-of-work.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
tenantId,
|
||||
createBranchDTO,
|
||||
trx,
|
||||
} as IBranchCreatePayload);
|
||||
|
||||
const branch = await Branch.query().insertAndFetch({
|
||||
...createBranchDTO,
|
||||
});
|
||||
// Triggers `onBranchCreated` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
tenantId,
|
||||
createBranchDTO,
|
||||
branch,
|
||||
trx,
|
||||
} as IBranchCreatedPayload);
|
||||
|
||||
return branch;
|
||||
});
|
||||
};
|
||||
}
|
||||
76
packages/server/src/services/Branches/DeleteBranch.ts
Normal file
76
packages/server/src/services/Branches/DeleteBranch.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import { Knex } from 'knex';
|
||||
import events from '@/subscribers/events';
|
||||
import { IBranchDeletedPayload, IBranchDeletePayload } from '@/interfaces';
|
||||
import { CURDBranch } from './CRUDBranch';
|
||||
import { BranchValidator } from './BranchValidate';
|
||||
import { ERRORS } from './constants';
|
||||
@Service()
|
||||
export class DeleteBranch extends CURDBranch {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
@Inject()
|
||||
private validator: BranchValidator;
|
||||
|
||||
/**
|
||||
* Validates the branch deleteing.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
private authorize = async (tenantId: number, branchId: number) => {
|
||||
await this.validator.validateBranchNotOnlyWarehouse(tenantId, branchId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes branch.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteBranch = async (
|
||||
tenantId: number,
|
||||
branchId: number
|
||||
): Promise<void> => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old branch or throw not found service error.
|
||||
const oldBranch = await Branch.query()
|
||||
.findById(branchId)
|
||||
.throwIfNotFound()
|
||||
.queryAndThrowIfHasRelations({
|
||||
type: ERRORS.BRANCH_HAS_ASSOCIATED_TRANSACTIONS,
|
||||
});
|
||||
// Authorize the branch before deleting.
|
||||
await this.authorize(tenantId, branchId);
|
||||
|
||||
// Deletes branch under unit-of-work.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
tenantId,
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchDeletePayload);
|
||||
|
||||
await Branch.query().findById(branchId).delete();
|
||||
|
||||
// Triggers `onBranchCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
tenantId,
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchDeletedPayload);
|
||||
});
|
||||
};
|
||||
}
|
||||
65
packages/server/src/services/Branches/EditBranch.ts
Normal file
65
packages/server/src/services/Branches/EditBranch.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IBranchEditedPayload,
|
||||
IBranchEditPayload,
|
||||
IEditBranchDTO,
|
||||
} from '@/interfaces';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import { CURDBranch } from './CRUDBranch';
|
||||
import events from '@/subscribers/events';
|
||||
|
||||
@Service()
|
||||
export class EditBranch extends CURDBranch {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Edits branch.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @param editBranchDTO
|
||||
*/
|
||||
public editBranch = async (
|
||||
tenantId: number,
|
||||
branchId: number,
|
||||
editBranchDTO: IEditBranchDTO
|
||||
) => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old branch or throw not found service error.
|
||||
const oldBranch = await this.getBranchOrThrowNotFound(tenantId, branchId);
|
||||
|
||||
// Deletes branch under unit-of-work.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchEdit` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
tenantId,
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchEditPayload);
|
||||
|
||||
// Edits the branch on the storage.
|
||||
const branch = await Branch.query().patchAndFetchById(branchId, {
|
||||
...editBranchDTO,
|
||||
});
|
||||
// Triggers `onBranchEdited` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
tenantId,
|
||||
oldBranch,
|
||||
branch,
|
||||
trx,
|
||||
} as IBranchEditedPayload);
|
||||
|
||||
return branch;
|
||||
});
|
||||
};
|
||||
}
|
||||
50
packages/server/src/services/Branches/EventsProvider.ts
Normal file
50
packages/server/src/services/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
|
||||
];
|
||||
26
packages/server/src/services/Branches/GetBranch.ts
Normal file
26
packages/server/src/services/Branches/GetBranch.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { CURDBranch } from './CRUDBranch';
|
||||
|
||||
@Service()
|
||||
export class GetBranch extends CURDBranch{
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns
|
||||
*/
|
||||
public getBranch = async (tenantId: number, branchId: number) => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
const branch = await Branch.query().findById(branchId);
|
||||
|
||||
// Throw not found service error if the branch not found.
|
||||
this.throwIfBranchNotFound(branch);
|
||||
|
||||
return branch;
|
||||
};
|
||||
}
|
||||
22
packages/server/src/services/Branches/GetBranches.ts
Normal file
22
packages/server/src/services/Branches/GetBranches.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { Service, Inject } from 'typedi';
|
||||
|
||||
@Service()
|
||||
export class GetBranches {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
/**
|
||||
* Retrieves branches list.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns
|
||||
*/
|
||||
public getBranches = async (tenantId: number) => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
const branches = await Branch.query().orderBy('name', 'DESC');
|
||||
|
||||
return branches;
|
||||
};
|
||||
}
|
||||
@@ -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,74 @@
|
||||
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'
|
||||
}
|
||||
67
packages/server/src/services/Branches/MarkBranchAsPrimary.ts
Normal file
67
packages/server/src/services/Branches/MarkBranchAsPrimary.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Knex } from 'knex';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import { CURDBranch } from './CRUDBranch';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import {
|
||||
IBranch,
|
||||
IBranchMarkAsPrimaryPayload,
|
||||
IBranchMarkedAsPrimaryPayload,
|
||||
} from '@/interfaces';
|
||||
|
||||
@Service()
|
||||
export class MarkBranchAsPrimary extends CURDBranch {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Marks the given branch as primary.
|
||||
* @param {number} tenantId
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<IBranch>}
|
||||
*/
|
||||
public markAsPrimary = async (
|
||||
tenantId: number,
|
||||
branchId: number
|
||||
): Promise<IBranch> => {
|
||||
const { Branch } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old branch or throw not found service error.
|
||||
const oldBranch = await this.getBranchOrThrowNotFound(tenantId, branchId);
|
||||
|
||||
// Updates the branches under unit-of-work envirement.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBranchMarkPrimary` event.
|
||||
await this.eventPublisher.emitAsync(events.branch.onMarkPrimary, {
|
||||
tenantId,
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchMarkAsPrimaryPayload);
|
||||
|
||||
// Updates all branches as not primary.
|
||||
await Branch.query(trx).update({ primary: false });
|
||||
|
||||
// Updates the given branch as primary.
|
||||
const markedBranch = await Branch.query(trx).patchAndFetchById(branchId, {
|
||||
primary: true,
|
||||
});
|
||||
// Triggers `onBranchMarkedPrimary` event.
|
||||
await this.eventPublisher.emitAsync(events.branch.onMarkedPrimary, {
|
||||
tenantId,
|
||||
markedBranch,
|
||||
oldBranch,
|
||||
trx,
|
||||
} as IBranchMarkedAsPrimaryPayload);
|
||||
|
||||
return markedBranch;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -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 './CashflowBranchesActviateSubscriber';
|
||||
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 {
|
||||
IPaymentReceiveCreatingPayload,
|
||||
IPaymentReceiveEditingPayload,
|
||||
} 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 {IPaymentReceiveCreatingPayload} payload
|
||||
*/
|
||||
private validateBranchExistanceOnPaymentCreating = async ({
|
||||
tenantId,
|
||||
paymentReceiveDTO,
|
||||
}: IPaymentReceiveCreatingPayload) => {
|
||||
await this.validateBranchExistance.validateTransactionBranchWhenActive(
|
||||
tenantId,
|
||||
paymentReceiveDTO.branchId
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate branch existance once estimate editing.
|
||||
* @param {IPaymentReceiveEditingPayload} payload
|
||||
*/
|
||||
private validateBranchExistanceOnPaymentEditing = async ({
|
||||
paymentReceiveDTO,
|
||||
tenantId,
|
||||
}: IPaymentReceiveEditingPayload) => {
|
||||
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';
|
||||
7
packages/server/src/services/Branches/constants.ts
Normal file
7
packages/server/src/services/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'
|
||||
};
|
||||
Reference in New Issue
Block a user