add server to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 11:57:50 +02:00
parent 28e309981b
commit 80b97b5fdc
1303 changed files with 137049 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
import { Service, Inject } from 'typedi';
import { omit } from 'lodash';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import {
ICancelTransactionsLockingDTO,
ITransactionLockingPartiallyDTO,
ITransactionMeta,
ITransactionsLockingAllDTO,
ITransactionsLockingCanceled,
ITransactionsLockingPartialUnlocked,
TransactionsLockingGroup,
TransactionsLockingType,
} from '@/interfaces';
import TransactionsLockingRepository from './TransactionsLockingRepository';
import { ServiceError } from '@/exceptions';
import { ERRORS } from './constants';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
const Modules = ['all', 'sales', 'purchases', 'financial'];
@Service()
export default class TransactionsLockingService {
@Inject()
tenancy: HasTenancyService;
@Inject()
transactionsLockingRepo: TransactionsLockingRepository;
@Inject()
eventPublisher: EventPublisher;
/**
* Enable/disable all transacations locking.
* @param {number} tenantId
* @param {TransactionsLockingGroup} moduleGroup -
* @param {Partial<ITransactionsLockingAllDTO>} allLockingDTO
* @returns {Promise<ITransactionMeta>}
*/
public commandTransactionsLocking = async (
tenantId: number,
module: TransactionsLockingGroup = TransactionsLockingGroup.All,
transactionLockingDTO: Partial<ITransactionsLockingAllDTO>
): Promise<ITransactionMeta> => {
// Validate the transaction locking module.
this.validateTransactionsLockingModule(module);
// Saves all transactions locking settings.
await this.transactionsLockingRepo.saveTransactionsLocking(
tenantId,
module,
{
active: true,
lockToDate: transactionLockingDTO.lockToDate,
lockReason: transactionLockingDTO.reason,
}
);
// Flag transactions locking type.
await this.transactionsLockingRepo.flagTransactionsLockingType(
tenantId,
module === TransactionsLockingGroup.All
? TransactionsLockingType.All
: TransactionsLockingType.Partial
);
// Triggers `onTransactionLockingPartialUnlocked` event.
await this.eventPublisher.emitAsync(
events.transactionsLocking.partialUnlocked,
{
tenantId,
module,
transactionLockingDTO,
} as ITransactionsLockingPartialUnlocked
);
// Retrieve the transaction locking meta of the given
return this.transactionsLockingRepo.getTransactionsLocking(
tenantId,
module
);
};
/**
* Cancels the full transactions locking.
* @param {number} tenantId
* @param {TransactionsLockingGroup} moduleGroup
* @param {ICancelTransactionsLockingDTO} cancelLockingDTO
* @returns {Promise<ITransactionMeta>}
*/
public cancelTransactionLocking = async (
tenantId: number,
module: TransactionsLockingGroup = TransactionsLockingGroup.All,
cancelLockingDTO: ICancelTransactionsLockingDTO
): Promise<ITransactionMeta> => {
// Validate the transaction locking module.
this.validateTransactionsLockingModule(module);
// Saves transactions locking.
await this.transactionsLockingRepo.saveTransactionsLocking(
tenantId,
module,
{
active: false,
unlockFromDate: '',
unlockToDate: '',
unlockReason: cancelLockingDTO.reason,
}
);
// Reset flag transactions locking type to partial.
await this.transactionsLockingRepo.flagTransactionsLockingType(
tenantId,
TransactionsLockingType.Partial
);
// Triggers `onTransactionLockingPartialUnlocked` event.
await this.eventPublisher.emitAsync(
events.transactionsLocking.partialUnlocked,
{
tenantId,
module,
cancelLockingDTO,
} as ITransactionsLockingCanceled
);
return this.transactionsLockingRepo.getTransactionsLocking(
tenantId,
module
);
};
/**
* Unlock tranactions locking partially.
* @param {number} tenantId
* @param {TransactionsLockingGroup} moduleGroup
* @param {ITransactionLockingPartiallyDTO} partialTransactionLockingDTO
* @returns {Promise<ITransactionMeta>}
*/
public unlockTransactionsLockingPartially = async (
tenantId: number,
moduleGroup: TransactionsLockingGroup = TransactionsLockingGroup.All,
partialTransactionLockingDTO: ITransactionLockingPartiallyDTO
): Promise<ITransactionMeta> => {
// Validate the transaction locking module.
this.validateTransactionsLockingModule(moduleGroup);
// Retrieve the current transactions locking type.
const lockingType =
this.transactionsLockingRepo.getTransactionsLockingType(tenantId);
if (moduleGroup !== TransactionsLockingGroup.All) {
this.validateLockingTypeNotAll(lockingType);
}
// Saves transactions locking settings.
await this.transactionsLockingRepo.saveTransactionsLocking(
tenantId,
moduleGroup,
{
...omit(partialTransactionLockingDTO, ['reason']),
partialUnlockReason: partialTransactionLockingDTO.reason,
}
);
// Retrieve transaction locking meta of the given module.
return this.transactionsLockingRepo.getTransactionsLocking(
tenantId,
moduleGroup
);
};
/**
* Cancel partial transactions unlocking.
* @param {number} tenantId
* @param {TransactionsLockingGroup} moduleGroup
*/
public cancelPartialTransactionsUnlock = async (
tenantId: number,
module: TransactionsLockingGroup = TransactionsLockingGroup.All
) => {
// Validate the transaction locking module.
this.validateTransactionsLockingModule(module);
// Saves transactions locking settings.
await this.transactionsLockingRepo.saveTransactionsLocking(
tenantId,
module,
{ unlockFromDate: '', unlockToDate: '', partialUnlockReason: '' }
);
};
/**
* Validates the transaction locking type not partial.
* @param {number} tenantId
*/
public validateLockingTypeNotPartial = (lockingType: string) => {
if (lockingType === TransactionsLockingType.Partial) {
throw new ServiceError(ERRORS.TRANSACTION_LOCKING_PARTIAL);
}
};
/**
* Validates the transaction locking type not all.
* @param {number} tenantId
*/
public validateLockingTypeNotAll = (lockingType: string) => {
if (lockingType === TransactionsLockingType.All) {
throw new ServiceError(ERRORS.TRANSACTION_LOCKING_ALL);
}
};
/**
* Validate transactions locking module.
* @param {string} module
*/
public validateTransactionsLockingModule = (module: string) => {
if (Modules.indexOf(module) === -1) {
throw new ServiceError(ERRORS.TRANSACTIONS_LOCKING_MODULE_NOT_FOUND);
}
};
}

View File

@@ -0,0 +1,26 @@
import { Service, Inject } from 'typedi';
import TransactionsLockingGuard from './TransactionsLockingGuard';
import { TransactionsLockingGroup } from '@/interfaces';
@Service()
export default class FinancialTransactionLocking {
@Inject()
transactionLockingGuardService: TransactionsLockingGuard;
/**
* Validates the transaction locking of cashflow command action.
* @param {number} tenantId
* @param {Date} transactionDate
* @throws {ServiceError(TRANSACTIONS_DATE_LOCKED)}
*/
public transactionLockingGuard = (
tenantId: number,
transactionDate: Date
) => {
this.transactionLockingGuardService.transactionsLockingGuard(
tenantId,
transactionDate,
TransactionsLockingGroup.Financial
);
};
}

View File

@@ -0,0 +1,335 @@
import { Inject, Service } from 'typedi';
import FinancialTransactionLocking from './FinancialTransactionLockingGuard';
import events from '@/subscribers/events';
import {
ICommandCashflowCreatingPayload,
ICommandCashflowDeletingPayload,
IExpenseCreatingPayload,
IExpenseDeletingPayload,
IExpenseEventEditingPayload,
IInventoryAdjustmentCreatingPayload,
IInventoryAdjustmentDeletingPayload,
IInventoryAdjustmentPublishingPayload,
IManualJournalCreatingPayload,
IExpensePublishingPayload,
IManualJournalEditingPayload,
IManualJournalPublishingPayload,
} from '@/interfaces';
@Service()
export default class FinancialTransactionLockingGuardSubscriber {
@Inject()
financialTransactionsLocking: FinancialTransactionLocking;
/**
* Attaches events with handlers.
* @param bus
*/
public attach = (bus) => {
// Manual journals.
bus.subscribe(
events.manualJournals.onCreating,
this.transactionsLockingGuardOnManualJournalCreating
);
bus.subscribe(
events.manualJournals.onEditing,
this.transactionsLockingGuardOnManualJournalEditing
);
bus.subscribe(
events.manualJournals.onDeleting,
this.transactionsLockingGuardOnManualJournalDeleting
);
bus.subscribe(
events.manualJournals.onPublishing,
this.transactionsLockingGuardOnManualJournalPublishing
);
// Expenses
bus.subscribe(
events.expenses.onCreating,
this.transactionsLockingGuardOnExpenseCreating
);
bus.subscribe(
events.expenses.onEditing,
this.transactionsLockingGuardOnExpenseEditing
);
bus.subscribe(
events.expenses.onDeleting,
this.transactionsLockingGuardOnExpenseDeleting
);
bus.subscribe(
events.expenses.onPublishing,
this.transactionsLockingGuardOnExpensePublishing
);
// Cashflow
bus.subscribe(
events.cashflow.onTransactionCreating,
this.transactionsLockingGuardOnCashflowTransactionCreating
);
bus.subscribe(
events.cashflow.onTransactionDeleting,
this.transactionsLockingGuardOnCashflowTransactionDeleting
);
// Inventory adjustment.
bus.subscribe(
events.inventoryAdjustment.onQuickCreating,
this.transactionsLockingGuardOnInventoryAdjCreating
);
bus.subscribe(
events.inventoryAdjustment.onDeleting,
this.transactionLockingGuardOnInventoryAdjDeleting
);
bus.subscribe(
events.inventoryAdjustment.onPublishing,
this.transactionLockingGuardOnInventoryAdjPublishing
);
};
/**
* ---------------------------------------------
* - MANUAL JOURNALS SERVICE.
* ---------------------------------------------
*/
/**
* Transaction locking guard on manual journal creating.
* @param {IManualJournalCreatingPayload} payload
*/
private transactionsLockingGuardOnManualJournalCreating = async ({
tenantId,
manualJournalDTO,
}: IManualJournalCreatingPayload) => {
// Can't continue if the new journal is not published yet.
if (!manualJournalDTO.publish) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
manualJournalDTO.date
);
};
/**
* Transactions locking guard on manual journal deleting.
* @param {IManualJournalEditingPayload} payload
*/
private transactionsLockingGuardOnManualJournalDeleting = async ({
tenantId,
oldManualJournal,
}: IManualJournalEditingPayload) => {
// Can't continue if the old journal is not published.
if (!oldManualJournal.isPublished) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldManualJournal.date
);
};
/**
* Transactions locking guard on manual journal editing.
* @param {IManualJournalDeletingPayload} payload
*/
private transactionsLockingGuardOnManualJournalEditing = async ({
tenantId,
oldManualJournal,
manualJournalDTO,
}: IManualJournalEditingPayload) => {
// Can't continue if the old and new journal are not published.
if (!oldManualJournal.isPublished && !manualJournalDTO.publish) return;
// Validate the old journal date.
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldManualJournal.date
);
// Validate the new journal date.
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
manualJournalDTO.date
);
};
/**
* Transactions locking guard on manual journal publishing.
* @param {IManualJournalPublishingPayload}
*/
private transactionsLockingGuardOnManualJournalPublishing = async ({
oldManualJournal,
tenantId,
}: IManualJournalPublishingPayload) => {
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldManualJournal.date
);
};
/**
* ---------------------------------------------
* - EXPENSES SERVICE.
* ---------------------------------------------
*/
/**
* Transactions locking guard on expense creating.
* @param {IExpenseCreatingPayload} payload
*/
private transactionsLockingGuardOnExpenseCreating = async ({
expenseDTO,
tenantId,
}: IExpenseCreatingPayload) => {
// Can't continue if the new expense is not published yet.
if (!expenseDTO.publish) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
expenseDTO.paymentDate
);
};
/**
* Transactions locking guard on expense deleting.
* @param {IExpenseDeletingPayload} payload
*/
private transactionsLockingGuardOnExpenseDeleting = async ({
tenantId,
oldExpense,
}: IExpenseDeletingPayload) => {
// Can't continue if expense transaction is not published.
if (!oldExpense.isPublished) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldExpense.paymentDate
);
};
/**
* Transactions locking guard on expense editing.
* @param {IExpenseEventEditingPayload}
*/
private transactionsLockingGuardOnExpenseEditing = async ({
tenantId,
oldExpense,
expenseDTO,
}: IExpenseEventEditingPayload) => {
// Can't continue if the old and new expense is not published.
if (!oldExpense.isPublished && !expenseDTO.publish) return;
// Validate the old expense date.
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldExpense.paymentDate
);
// Validate the new expense date.
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
expenseDTO.paymentDate
);
};
/**
* Transactions locking guard on expense publishing.
* @param {IExpensePublishingPayload} payload -
*/
private transactionsLockingGuardOnExpensePublishing = async ({
tenantId,
oldExpense,
}: IExpensePublishingPayload) => {
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldExpense.paymentDate
);
};
/**
* ---------------------------------------------
* - CASHFLOW SERVICE.
* ---------------------------------------------
*/
/**
* Transactions locking guard on cashflow transaction creating.
* @param {ICommandCashflowCreatingPayload}
*/
private transactionsLockingGuardOnCashflowTransactionCreating = async ({
tenantId,
newTransactionDTO,
}: ICommandCashflowCreatingPayload) => {
if (!newTransactionDTO.publish) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
newTransactionDTO.date
);
};
/**
* Transactions locking guard on cashflow transaction deleting.
* @param {ICommandCashflowDeletingPayload}
*/
private transactionsLockingGuardOnCashflowTransactionDeleting = async ({
tenantId,
oldCashflowTransaction,
}: ICommandCashflowDeletingPayload) => {
// Can't continue if the cashflow transaction is not published.
if (!oldCashflowTransaction.isPublished) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldCashflowTransaction.date
);
};
/**
* ---------------------------------------------
* - INVENTORY ADJUSTMENT SERVICE.
* ---------------------------------------------
*/
/**
* Transactions locking guard on inventory adjustment creating.
* @param {IInventoryAdjustmentCreatingPayload} payload -
*/
private transactionsLockingGuardOnInventoryAdjCreating = async ({
tenantId,
quickAdjustmentDTO,
}: IInventoryAdjustmentCreatingPayload) => {
// Can't locking if the new adjustment is not published yet.
if (!quickAdjustmentDTO.publish) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
quickAdjustmentDTO.date
);
};
/**
* Transaction locking guard on inventory adjustment deleting.
* @param {IInventoryAdjustmentDeletingPayload} payload
*/
private transactionLockingGuardOnInventoryAdjDeleting = async ({
tenantId,
oldInventoryAdjustment,
}: IInventoryAdjustmentDeletingPayload) => {
// Can't locking if the adjustment is published yet.
if (!oldInventoryAdjustment.isPublished) return;
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldInventoryAdjustment.date
);
};
/**
* Transaction locking guard on inventory adjustment publishing.
* @param {IInventoryAdjustmentPublishingPayload} payload
*/
private transactionLockingGuardOnInventoryAdjPublishing = async ({
tenantId,
oldInventoryAdjustment,
}: IInventoryAdjustmentPublishingPayload) => {
await this.financialTransactionsLocking.transactionLockingGuard(
tenantId,
oldInventoryAdjustment.date
);
};
}

View File

@@ -0,0 +1,25 @@
import { Service, Inject } from 'typedi';
import TransactionsLockingGuard from './TransactionsLockingGuard';
import { TransactionsLockingGroup } from '@/interfaces';
@Service()
export default class PurchasesTransactionLocking {
@Inject()
transactionLockingGuardService: TransactionsLockingGuard;
/**
* Validates the transaction locking of purchases services commands.
* @param {number} tenantId
* @param {Date} transactionDate
*/
public transactionLockingGuard = async (
tenantId: number,
transactionDate: Date
) => {
this.transactionLockingGuardService.transactionsLockingGuard(
tenantId,
transactionDate,
TransactionsLockingGroup.Purchases
);
};
}

View File

@@ -0,0 +1,286 @@
import { Inject } from 'typedi';
import events from '@/subscribers/events';
import {
IBillCreatingPayload,
IBillEditingPayload,
IBillEventDeletingPayload,
IBillPaymentCreatingPayload,
IBillPaymentDeletingPayload,
IBillPaymentEditingPayload,
IRefundVendorCreditCreatingPayload,
IRefundVendorCreditDeletingPayload,
IVendorCreditCreatingPayload,
IVendorCreditDeletingPayload,
IVendorCreditEditingPayload,
} from '@/interfaces';
import PurchasesTransactionsLocking from './PurchasesTransactionLockingGuard';
export default class PurchasesTransactionLockingGuardSubscriber {
@Inject()
purchasesTransactionsLocking: PurchasesTransactionsLocking;
/**
* Attaches events with handlers.
* @param bus
*/
public attach = (bus) => {
// Bills
bus.subscribe(
events.bill.onCreating,
this.transactionLockingGuardOnBillCreating
);
bus.subscribe(
events.bill.onEditing,
this.transactionLockingGuardOnBillEditing
);
bus.subscribe(
events.bill.onDeleting,
this.transactionLockingGuardOnBillDeleting
);
// Payment mades.
bus.subscribe(
events.billPayment.onCreating,
this.transactionLockingGuardOnPaymentCreating
);
bus.subscribe(
events.billPayment.onEditing,
this.transactionLockingGuardOnPaymentEditing
);
bus.subscribe(
events.billPayment.onDeleting,
this.transactionLockingGuardOnPaymentDeleting
);
// Vendor credits.
bus.subscribe(
events.vendorCredit.onCreating,
this.transactionLockingGuardOnVendorCreditCreating
);
bus.subscribe(
events.vendorCredit.onDeleting,
this.transactionLockingGuardOnVendorCreditDeleting
);
bus.subscribe(
events.vendorCredit.onEditing,
this.transactionLockingGuardOnVendorCreditEditing
);
bus.subscribe(
events.vendorCredit.onRefundCreating,
this.transactionLockingGuardOnRefundVendorCredit
);
bus.subscribe(
events.vendorCredit.onRefundDeleting,
this.transactionLockingGuardOnRefundCreditDeleting
);
};
/**
* ---------------------------------------------
* PAYMENT MADES.
* ---------------------------------------------
*/
/**
* Transaction locking guard on payment editing.
* @param {IBillPaymentEditingPayload}
*/
private transactionLockingGuardOnPaymentEditing = async ({
tenantId,
oldBillPayment,
billPaymentDTO,
}: IBillPaymentEditingPayload) => {
// Validate old payment date.
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldBillPayment.paymentDate
);
// Validate the new payment date.
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
billPaymentDTO.paymentDate
);
};
/**
* Transaction locking guard on payment creating.
* @param {IBillPaymentCreatingPayload}
*/
private transactionLockingGuardOnPaymentCreating = async ({
tenantId,
billPaymentDTO,
}: IBillPaymentCreatingPayload) => {
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
billPaymentDTO.paymentDate
);
};
/**
* Transaction locking guard on payment deleting.
* @param {IBillPaymentDeletingPayload} payload -
*/
private transactionLockingGuardOnPaymentDeleting = async ({
tenantId,
oldBillPayment,
}: IBillPaymentDeletingPayload) => {
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldBillPayment.paymentDate
);
};
/**
* ---------------------------------------------
* BILLS.
* ---------------------------------------------
*/
/**
* Transaction locking guard on bill creating.
* @param {IBillCreatingPayload} payload
*/
private transactionLockingGuardOnBillCreating = async ({
tenantId,
billDTO,
}: IBillCreatingPayload) => {
// Can't continue if the new bill is not published.
if (!billDTO.open) return;
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
billDTO.billDate
);
};
/**
* Transaction locking guard on bill editing.
* @param {IBillEditingPayload} payload
*/
private transactionLockingGuardOnBillEditing = async ({
oldBill,
tenantId,
billDTO,
}: IBillEditingPayload) => {
// Can't continue if the old and new bill are not published.
if (!oldBill.isOpen && !billDTO.open) return;
// Validate the old bill date.
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldBill.billDate
);
// Validate the new bill date.
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
billDTO.billDate
);
};
/**
* Transaction locking guard on bill deleting.
* @param {IBillEventDeletingPayload} payload
*/
private transactionLockingGuardOnBillDeleting = async ({
tenantId,
oldBill,
}: IBillEventDeletingPayload) => {
// Can't continue if the old bill is not published.
if (!oldBill.isOpen) return;
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldBill.billDate
);
};
/**
* ---------------------------------------------
* VENDOR CREDITS.
* ---------------------------------------------
*/
/**
* Transaction locking guard on vendor credit creating.
* @param {IVendorCreditCreatingPayload} payload
*/
private transactionLockingGuardOnVendorCreditCreating = async ({
tenantId,
vendorCreditCreateDTO,
}: IVendorCreditCreatingPayload) => {
// Can't continue if the new vendor credit is not published.
if (!vendorCreditCreateDTO.open) return;
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
vendorCreditCreateDTO.vendorCreditDate
);
};
/**
* Transaction locking guard on vendor credit deleting.
* @param {IVendorCreditDeletingPayload} payload
*/
private transactionLockingGuardOnVendorCreditDeleting = async ({
tenantId,
oldVendorCredit,
}: IVendorCreditDeletingPayload) => {
// Can't continue if the old vendor credit is not open.
if (!oldVendorCredit.isOpen) return;
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldVendorCredit.vendorCreditDate
);
};
/**
* Transaction locking guard on vendor credit editing.
* @param {IVendorCreditEditingPayload} payload
*/
private transactionLockingGuardOnVendorCreditEditing = async ({
tenantId,
oldVendorCredit,
vendorCreditDTO,
}: IVendorCreditEditingPayload) => {
// Can't continue if the old and new vendor credit are not published.
if (!oldVendorCredit.isPublished && !vendorCreditDTO.open) return;
// Validate the old credit date.
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldVendorCredit.vendorCreditDate
);
// Validate the new credit date.
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
vendorCreditDTO.vendorCreditDate
);
};
/**
* Transaction locking guard on refund vendor credit creating.
* @param {IRefundVendorCreditCreatingPayload} payload -
*/
private transactionLockingGuardOnRefundVendorCredit = async ({
tenantId,
refundVendorCreditDTO,
}: IRefundVendorCreditCreatingPayload) => {
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
refundVendorCreditDTO.date
);
};
/**
* Transaction locking guard on refund vendor credit deleting.
* @param {IRefundVendorCreditDeletingPayload} payload
*/
private transactionLockingGuardOnRefundCreditDeleting = async ({
tenantId,
oldRefundCredit,
}: IRefundVendorCreditDeletingPayload) => {
await this.purchasesTransactionsLocking.transactionLockingGuard(
tenantId,
oldRefundCredit.date
);
};
}

View File

@@ -0,0 +1,93 @@
import { Service, Inject } from 'typedi';
import {
ITransactionLockingMetaPOJO,
ITransactionsLockingListPOJO,
ITransactionsLockingSchema,
TransactionsLockingGroup,
} from '@/interfaces';
import { TRANSACTIONS_LOCKING_SCHEMA } from './constants';
import TransactionsLockingMetaTransformer from './TransactionsLockingMetaTransformer';
import TransactionsLockingRepository from './TransactionsLockingRepository';
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
@Service()
export default class QueryTransactionsLocking {
@Inject()
private transactionsLockingRepo: TransactionsLockingRepository;
@Inject()
private transformer: TransformerInjectable;
/**
* Retrieve transactions locking modules.
* @param {number} tenantId
* @returns {ITransactionLockingMetaPOJO[]}
*/
public getTransactionsLockingModules = (
tenantId: number
): Promise<ITransactionLockingMetaPOJO[]> => {
const modules = TRANSACTIONS_LOCKING_SCHEMA.map(
(schema: ITransactionsLockingSchema) =>
this.getTransactionsLockingModuleMeta(tenantId, schema.module)
);
return Promise.all(modules);
};
/**
* Retireve the transactions locking all module.
* @param {number} tenantId
* @returns {ITransactionLockingMetaPOJO}
*/
public getTransactionsLockingAll = (
tenantId: number
): Promise<ITransactionLockingMetaPOJO> => {
return this.getTransactionsLockingModuleMeta(
tenantId,
TransactionsLockingGroup.All
);
};
/**
* Retrieve the transactions locking module meta.
* @param {number} tenantId -
* @param {TransactionsLockingGroup} module -
* @returns {ITransactionLockingMetaPOJO}
*/
public getTransactionsLockingModuleMeta = (
tenantId: number,
module: TransactionsLockingGroup
): Promise<ITransactionLockingMetaPOJO> => {
const meta = this.transactionsLockingRepo.getTransactionsLocking(
tenantId,
module
);
return this.transformer.transform(
tenantId,
meta,
new TransactionsLockingMetaTransformer(),
{ module }
);
};
/**
* Retrieve transactions locking list.
* @param {number} tenantId
* @returns {Promise<ITransactionsLockingListPOJO>}
*/
public getTransactionsLockingList = async (
tenantId: number
): Promise<ITransactionsLockingListPOJO> => {
// Retrieve the current transactions locking type.
const lockingType =
this.transactionsLockingRepo.getTransactionsLockingType(tenantId);
const all = await this.getTransactionsLockingAll(tenantId);
const modules = await this.getTransactionsLockingModules(tenantId);
return {
lockingType,
all,
modules,
};
};
}

View File

@@ -0,0 +1,25 @@
import { Service, Inject } from 'typedi';
import TransactionsLockingGuard from './TransactionsLockingGuard';
import { TransactionsLockingGroup } from '@/interfaces';
@Service()
export default class SalesTransactionLocking {
@Inject()
transactionLockingGuardService: TransactionsLockingGuard;
/**
* Validates the transaction locking of sales services commands.
* @param {number} tenantId
* @param {Date} transactionDate
*/
public transactionLockingGuard = async (
tenantId: number,
transactionDate: Date
) => {
await this.transactionLockingGuardService.transactionsLockingGuard(
tenantId,
transactionDate,
TransactionsLockingGroup.Sales
);
};
}

View File

@@ -0,0 +1,503 @@
import { Service, Inject } from 'typedi';
import {
ISaleReceiptCreatingPayload,
IRefundCreditNoteCreatingPayload,
ISaleInvoiceCreatingPaylaod,
ISaleReceiptDeletingPayload,
ICreditNoteDeletingPayload,
IPaymentReceiveCreatingPayload,
IRefundCreditNoteDeletingPayload,
IPaymentReceiveDeletingPayload,
ISaleEstimateDeletingPayload,
ISaleEstimateCreatingPayload,
ISaleEstimateEditingPayload,
ISaleInvoiceWriteoffCreatePayload,
ISaleInvoiceEditingPayload,
ISaleInvoiceDeletePayload,
ISaleInvoiceWrittenOffCancelPayload,
ICreditNoteEditingPayload,
ISaleReceiptEditingPayload,
IPaymentReceiveEditingPayload,
ISaleReceiptEventClosingPayload,
ICreditNoteCreatingPayload,
} from '@/interfaces';
import events from '@/subscribers/events';
import SalesTransactionLockingGuard from './SalesTransactionLockingGuard';
@Service()
export default class SalesTransactionLockingGuardSubscriber {
@Inject()
salesLockingGuard: SalesTransactionLockingGuard;
/**
* Attaches events with handlers.
*/
public attach = (bus) => {
// Sale invoice.
bus.subscribe(
events.saleInvoice.onCreating,
this.transactionLockingGuardOnInvoiceCreating
);
bus.subscribe(
events.saleInvoice.onEditing,
this.transactionLockingGuardOnInvoiceEditing
);
bus.subscribe(
events.saleInvoice.onWriteoff,
this.transactionLockinGuardOnInvoiceWritingoff
);
bus.subscribe(
events.saleInvoice.onWrittenoffCancel,
this.transactionLockinGuardOnInvoiceWritingoffCanceling
);
bus.subscribe(
events.saleInvoice.onDeleting,
this.transactionLockingGuardOnInvoiceDeleting
);
// Sale receipt
bus.subscribe(
events.saleReceipt.onCreating,
this.transactionLockingGuardOnReceiptCreating
);
bus.subscribe(
events.saleReceipt.onDeleting,
this.transactionLockingGuardOnReceiptDeleting
);
bus.subscribe(
events.saleReceipt.onEditing,
this.transactionLockingGuardOnReceiptEditing
);
bus.subscribe(
events.saleReceipt.onClosing,
this.transactionLockingGuardOnReceiptClosing
);
// Payment receive
bus.subscribe(
events.paymentReceive.onCreating,
this.transactionLockingGuardOnPaymentCreating
);
bus.subscribe(
events.paymentReceive.onEditing,
this.transactionLockingGuardOnPaymentEditing
);
bus.subscribe(
events.paymentReceive.onDeleting,
this.transactionLockingGuardPaymentDeleting
);
// Credit note.
bus.subscribe(
events.creditNote.onCreating,
this.transactionLockingGuardOnCreditCreating
);
bus.subscribe(
events.creditNote.onEditing,
this.transactionLockingGuardOnCreditEditing
);
bus.subscribe(
events.creditNote.onDeleting,
this.transactionLockingGuardOnCreditDeleting
);
bus.subscribe(
events.creditNote.onRefundCreating,
this.transactionLockingGuardOnCreditRefundCreating
);
bus.subscribe(
events.creditNote.onRefundDeleting,
this.transactionLockingGuardOnCreditRefundDeleteing
);
// Sale Estimate
bus.subscribe(
events.saleEstimate.onCreating,
this.transactionLockingGuardOnEstimateCreating
);
bus.subscribe(
events.saleEstimate.onDeleting,
this.transactionLockingGuardOnEstimateDeleting
);
bus.subscribe(
events.saleEstimate.onEditing,
this.transactionLockingGuardOnEstimateEditing
);
};
/**
* ---------------------------------------------
* SALES INVOICES.
* ---------------------------------------------
*/
/**
* Transaction locking guard on invoice creating.
* @param {ISaleInvoiceCreatingPaylaod} payload
*/
private transactionLockingGuardOnInvoiceCreating = async ({
saleInvoiceDTO,
tenantId,
}: ISaleInvoiceCreatingPaylaod) => {
// Can't continue if the new invoice is not published yet.
if (!saleInvoiceDTO.delivered) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleInvoiceDTO.invoiceDate
);
};
/**
* Transaction locking guard on invoice editing.
* @param {ISaleInvoiceEditingPayload} payload
*/
private transactionLockingGuardOnInvoiceEditing = async ({
tenantId,
oldSaleInvoice,
saleInvoiceDTO,
}: ISaleInvoiceEditingPayload) => {
// Can't continue if the old and new invoice are not published yet.
if (!oldSaleInvoice.isDelivered && !saleInvoiceDTO.delivered) return;
// Validate the old invoice date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldSaleInvoice.invoiceDate
);
// Validate the new invoice date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleInvoiceDTO.invoiceDate
);
};
/**
* Transaction locking guard on invoice deleting.
* @param {ISaleInvoiceDeletePayload} payload
*/
private transactionLockingGuardOnInvoiceDeleting = async ({
saleInvoice,
tenantId,
}: ISaleInvoiceDeletePayload) => {
// Can't continue if the old invoice not published.
if (!saleInvoice.isDelivered) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleInvoice.invoiceDate
);
};
/**
* Transaction locking guard on invoice writingoff.
* @param {ISaleInvoiceWriteoffCreatePayload} payload
*/
private transactionLockinGuardOnInvoiceWritingoff = async ({
tenantId,
saleInvoice,
}: ISaleInvoiceWriteoffCreatePayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleInvoice.invoiceDate
);
};
/**
* Transaciton locking guard on canceling written-off invoice.
* @param {ISaleInvoiceWrittenOffCancelPayload} payload
*/
private transactionLockinGuardOnInvoiceWritingoffCanceling = async ({
tenantId,
saleInvoice,
}: ISaleInvoiceWrittenOffCancelPayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleInvoice.invoiceDate
);
};
/**
* ---------------------------------------------
* SALES RECEIPTS.
* ---------------------------------------------
*/
/**
* Transaction locking guard on receipt creating.
* @param {ISaleReceiptCreatingPayload}
*/
private transactionLockingGuardOnReceiptCreating = async ({
tenantId,
saleReceiptDTO,
}: ISaleReceiptCreatingPayload) => {
// Can't continue if the sale receipt is not published.
if (!saleReceiptDTO.closed) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleReceiptDTO.receiptDate
);
};
/**
* Transaction locking guard on receipt creating.
* @param {ISaleReceiptDeletingPayload}
*/
private transactionLockingGuardOnReceiptDeleting = async ({
tenantId,
oldSaleReceipt,
}: ISaleReceiptDeletingPayload) => {
if (!oldSaleReceipt.isClosed) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldSaleReceipt.receiptDate
);
};
/**
* Transaction locking guard on sale receipt editing.
* @param {ISaleReceiptEditingPayload} payload
*/
private transactionLockingGuardOnReceiptEditing = async ({
tenantId,
oldSaleReceipt,
saleReceiptDTO,
}: ISaleReceiptEditingPayload) => {
// Validate the old receipt date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldSaleReceipt.receiptDate
);
// Validate the new receipt date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
saleReceiptDTO.receiptDate
);
};
/**
* Transaction locking guard on sale receipt closing.
* @param {ISaleReceiptEventClosingPayload} payload
*/
private transactionLockingGuardOnReceiptClosing = async ({
tenantId,
oldSaleReceipt,
}: ISaleReceiptEventClosingPayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldSaleReceipt.receiptDate
);
};
/**
* ---------------------------------------------
* CREDIT NOTES.
* ---------------------------------------------
*/
/**
* Transaction locking guard on credit note deleting.
* @param {ICreditNoteDeletingPayload} payload -
*/
private transactionLockingGuardOnCreditDeleting = async ({
oldCreditNote,
tenantId,
}: ICreditNoteDeletingPayload) => {
// Can't continue if the old credit is not published.
if (!oldCreditNote.isPublished) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldCreditNote.creditNoteDate
);
};
/**
* Transaction locking guard on credit note creating.
* @param {ICreditNoteCreatingPayload} payload
*/
private transactionLockingGuardOnCreditCreating = async ({
tenantId,
creditNoteDTO,
}: ICreditNoteCreatingPayload) => {
// Can't continue if the new credit is still draft.
if (!creditNoteDTO.open) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
creditNoteDTO.creditNoteDate
);
};
/**
* Transaction locking guard on credit note editing.
* @param {ICreditNoteEditingPayload} payload -
*/
private transactionLockingGuardOnCreditEditing = async ({
creditNoteEditDTO,
oldCreditNote,
tenantId,
}: ICreditNoteEditingPayload) => {
// Can't continue if the new and old credit note are not published yet.
if (!creditNoteEditDTO.open && !oldCreditNote.isPublished) return;
// Validate the old credit date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldCreditNote.creditNoteDate
);
// Validate the new credit date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
creditNoteEditDTO.creditNoteDate
);
};
/**
* Transaction locking guard on payment deleting.
* @param {IRefundCreditNoteDeletingPayload} paylaod -
*/
private transactionLockingGuardOnCreditRefundDeleteing = async ({
tenantId,
oldRefundCredit,
}: IRefundCreditNoteDeletingPayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldRefundCredit.date
);
};
/**
* Transaction locking guard on refund credit note creating.
* @param {IRefundCreditNoteCreatingPayload} payload -
*/
private transactionLockingGuardOnCreditRefundCreating = async ({
tenantId,
newCreditNoteDTO,
}: IRefundCreditNoteCreatingPayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
newCreditNoteDTO.date
);
};
/**
* ---------------------------------------------
* SALES ESTIMATES.
* ---------------------------------------------
*/
/**
* Transaction locking guard on estimate creating.
* @param {ISaleEstimateCreatingPayload} payload -
*/
private transactionLockingGuardOnEstimateCreating = async ({
estimateDTO,
tenantId,
}: ISaleEstimateCreatingPayload) => {
// Can't continue if the new estimate is not published yet.
if (!estimateDTO.delivered) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
estimateDTO.estimateDate
);
};
/**
* Transaction locking guard on estimate deleting.
* @param {ISaleEstimateDeletingPayload} payload
*/
private transactionLockingGuardOnEstimateDeleting = async ({
oldSaleEstimate,
tenantId,
}: ISaleEstimateDeletingPayload) => {
// Can't continue if the old estimate is not published.
if (!oldSaleEstimate.isDelivered) return;
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldSaleEstimate.estimateDate
);
};
/**
* Transaction locking guard on estimate editing.
* @param {ISaleEstimateEditingPayload} payload
*/
private transactionLockingGuardOnEstimateEditing = async ({
tenantId,
oldSaleEstimate,
estimateDTO,
}: ISaleEstimateEditingPayload) => {
// Can't continue if the new and old estimate transactions are not published yet.
if (!estimateDTO.delivered && !oldSaleEstimate.isDelivered) return;
// Validate the old estimate date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldSaleEstimate.estimateDate
);
// Validate the new estimate date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
estimateDTO.estimateDate
);
};
/**
* ---------------------------------------------
* PAYMENT RECEIVES.
* ---------------------------------------------
*/
/**
* Transaction locking guard on payment receive editing.
* @param {IPaymentReceiveEditingPayload}
*/
private transactionLockingGuardOnPaymentEditing = async ({
tenantId,
oldPaymentReceive,
paymentReceiveDTO,
}: IPaymentReceiveEditingPayload) => {
// Validate the old payment date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldPaymentReceive.paymentDate
);
// Validate the new payment date.
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
paymentReceiveDTO.paymentDate
);
};
/**
* Transaction locking guard on payment creating.
* @param {IPaymentReceiveCreatingPayload}
*/
private transactionLockingGuardOnPaymentCreating = async ({
tenantId,
paymentReceiveDTO,
}: IPaymentReceiveCreatingPayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
paymentReceiveDTO.paymentDate
);
};
/**
* Transaction locking guard on payment deleting.
* @param {IPaymentReceiveDeletingPayload} payload -
*/
private transactionLockingGuardPaymentDeleting = async ({
oldPaymentReceive,
tenantId,
}: IPaymentReceiveDeletingPayload) => {
await this.salesLockingGuard.transactionLockingGuard(
tenantId,
oldPaymentReceive.paymentDate
);
};
}

View File

@@ -0,0 +1,121 @@
import { Service, Inject } from 'typedi';
import moment from 'moment';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import { ServiceError, ServiceErrors } from '@/exceptions';
import { TransactionsLockingGroup } from '@/interfaces';
import TransactionsLockingRepository from './TransactionsLockingRepository';
import { ERRORS } from './constants';
@Service()
export default class TransactionsLockingGuard {
@Inject()
tenancy: HasTenancyService;
@Inject()
transactionsLockingRepo: TransactionsLockingRepository;
/**
* Detarmines whether the transaction date between the locking date period.
* @param {number} tenantId
* @param {Date} transactionDate
* @param {TransactionsLockingGroup} lockingGroup
* @returns {boolean}
*/
public isTransactionsLocking = (
tenantId: number,
transactionDate: Date,
lockingGroup: string = TransactionsLockingGroup.All
): boolean => {
const { isEnabled, unlockFromDate, unlockToDate, lockToDate } =
this.transactionsLockingRepo.getTransactionsLocking(
tenantId,
lockingGroup
);
// Returns false anyway in case if the transaction locking is disabled.
if (!isEnabled) return false;
const inLockingDate = moment(transactionDate).isSameOrBefore(lockToDate);
const inUnlockDate =
unlockFromDate && unlockToDate
? moment(transactionDate).isSameOrAfter(unlockFromDate) &&
moment(transactionDate).isSameOrBefore(unlockFromDate)
: false;
// Retruns true in case the transaction date between locking date
// and not between unlocking date.
return !!(isEnabled && inLockingDate && !inUnlockDate);
};
/**
* Validates the transaction date between the locking date period
* or throw service error.
* @param {number} tenantId
* @param {Date} transactionDate
* @param {TransactionsLockingGroup} lockingGroup
*
* @throws {ServiceError}
*/
public validateTransactionsLocking = (
tenantId: number,
transactionDate: Date,
lockingGroup: TransactionsLockingGroup
) => {
const isLocked = this.isTransactionsLocking(
tenantId,
transactionDate,
lockingGroup
);
if (isLocked) {
this.throwTransactionsLockError(tenantId, lockingGroup);
}
};
/**
* Throws transactions locking error.
* @param {number} tenantId
* @param {TransactionsLockingGroup} lockingGroup
*/
public throwTransactionsLockError = (
tenantId: number,
lockingGroup: TransactionsLockingGroup
) => {
const { lockToDate } = this.transactionsLockingRepo.getTransactionsLocking(
tenantId,
lockingGroup
);
throw new ServiceError(ERRORS.TRANSACTIONS_DATE_LOCKED, null, {
lockedToDate: lockToDate,
formattedLockedToDate: moment(lockToDate).format('YYYY/MM/DD'),
});
};
/**
* Validate the transaction locking of the given locking group and transaction date.
* @param {number} tenantId -
* @param {TransactionsLockingGroup} lockingGroup - transaction group
* @param {Date} fromDate -
*/
public transactionsLockingGuard = (
tenantId: number,
transactionDate: Date,
moduleType: TransactionsLockingGroup
) => {
const lockingType =
this.transactionsLockingRepo.getTransactionsLockingType(tenantId);
//
if (lockingType === TransactionsLockingGroup.All) {
return this.validateTransactionsLocking(
tenantId,
transactionDate,
TransactionsLockingGroup.All
);
}
//
return this.validateTransactionsLocking(
tenantId,
transactionDate,
moduleType
);
};
}

View File

@@ -0,0 +1,83 @@
import { get } from 'lodash';
import { TransactionsLockingGroup } from '@/interfaces';
import { Transformer } from '@/lib/Transformer/Transformer';
import { getTransactionsLockingSchemaMeta } from './constants';
export default class TransactionsLockingMetaTransformer extends Transformer {
/**
* Include these attributes to sale credit note object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'module',
'formattedModule',
'description',
'formattedLockToDate',
'formattedUnlockFromDate',
'formattedUnlockToDate',
];
};
/**
* Module slug.
* @returns {string}
*/
protected module = () => {
return this.options.module;
};
/**
* Formatted module name.
* @returns {string}
*/
protected formattedModule = () => {
return this.options.module === TransactionsLockingGroup.All
? this.context.i18n.__('transactions_locking.module.all_transactions')
: this.context.i18n.__(
get(
getTransactionsLockingSchemaMeta(this.options.module),
'formattedModule'
)
);
};
/**
* Module description.
* @returns {string}
*/
protected description = () => {
return this.options.module === TransactionsLockingGroup.All
? ''
: this.context.i18n.__(
get(
getTransactionsLockingSchemaMeta(this.options.module),
'description'
)
);
};
/**
* Formatted unlock to date.
* @returns {string}
*/
protected formattedUnlockToDate = (item) => {
return item.unlockToDate ? this.formatDate(item.unlockToDate) : '';
};
/**
* Formatted unlock from date.
* @returns {string}
*/
protected formattedUnlockFromDate = (item) => {
return item.unlockFromDate ? this.formatDate(item.unlockFromDate) : '';
};
/**
* Formatted lock to date.
* @returns {string}
*/
protected formattedLockToDate = (item) => {
return item.lockToDate ? this.formatDate(item.lockToDate) : '';
};
}

View File

@@ -0,0 +1,151 @@
import { Service, Inject } from 'typedi';
import { isUndefined } from 'lodash';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import {
ITransactionMeta,
TransactionsLockingGroup,
TransactionsLockingType,
} from '@/interfaces';
import { parseDate } from 'utils';
@Service()
export default class TransactionsLockingRepository {
@Inject()
tenancy: HasTenancyService;
async saveTransactionsLocking(
tenantId: number,
lockingGroup: string = TransactionsLockingGroup.All,
transactionlocking
) {
const settings = this.tenancy.settings(tenantId);
const group = `transactions-locking`;
if (!isUndefined(transactionlocking.active)) {
settings.set({
group,
key: `${lockingGroup}.active`,
value: transactionlocking.active,
});
}
if (!isUndefined(transactionlocking.lockToDate)) {
settings.set({
group,
key: `${lockingGroup}.lock_to_date`,
value: parseDate(transactionlocking.lockToDate),
});
}
if (!isUndefined(transactionlocking.unlockFromDate)) {
settings.set({
group,
key: `${lockingGroup}.unlock_from_date`,
value: parseDate(transactionlocking.unlockFromDate),
});
}
if (!isUndefined(transactionlocking.unlockToDate)) {
settings.set({
group,
key: `${lockingGroup}.unlock_to_date`,
value: parseDate(transactionlocking.unlockToDate),
});
}
if (!isUndefined(transactionlocking.lockReason)) {
settings.set({
group,
key: `${lockingGroup}.lock_reason`,
value: transactionlocking.lockReason,
});
}
if (!isUndefined(transactionlocking.unlockReason)) {
settings.set({
group,
key: `${lockingGroup}.unlock_reason`,
value: transactionlocking.unlockReason,
});
}
if (!isUndefined(transactionlocking.partialUnlockReason)) {
settings.set({
group,
key: `${lockingGroup}.partial_unlock_reason`,
value: transactionlocking.partialUnlockReason,
});
}
await settings.save();
}
getTransactionsLocking(
tenantId: number,
lockingGroup: string = TransactionsLockingGroup.All
): ITransactionMeta {
const settings = this.tenancy.settings(tenantId);
const group = `transactions-locking`;
const isEnabled = settings.get({ group, key: `${lockingGroup}.active` });
const lockFromDate = settings.get({
group,
key: `${lockingGroup}.lock_from_date`,
});
const lockToDate = settings.get({
group,
key: `${lockingGroup}.lock_to_date`,
});
const unlockFromDate = settings.get({
group,
key: `${lockingGroup}.unlock_from_date`,
});
const unlockToDate = settings.get({
group,
key: `${lockingGroup}.unlock_to_date`,
});
const lockReason = settings.get({
group,
key: `${lockingGroup}.lock_reason`,
});
const unlockReason = settings.get({
group,
key: `${lockingGroup}.unlock_reason`,
});
const partialUnlockReason = settings.get({
group,
key: `${lockingGroup}.partial_unlock_reason`,
});
return {
isEnabled,
lockToDate: lockToDate || null,
unlockFromDate: unlockFromDate || null,
unlockToDate: unlockToDate || null,
isPartialUnlock: Boolean(unlockToDate && unlockFromDate),
lockReason: lockReason || '',
unlockReason: unlockReason || '',
partialUnlockReason: partialUnlockReason || '',
};
}
getTransactionsLockingType(tenantId: number) {
const settings = this.tenancy.settings(tenantId);
const lockingType = settings.get({
group: 'transactions-locking',
key: 'locking-type',
});
return lockingType || 'partial';
}
flagTransactionsLockingType(
tenantId: number,
transactionsType: TransactionsLockingType
) {
const settings = this.tenancy.settings(tenantId);
settings.set({
group: 'transactions-locking',
key: 'locking-type',
value: transactionsType,
});
}
}

View File

@@ -0,0 +1,36 @@
import {
ITransactionsLockingSchema,
TransactionsLockingGroup,
} from '@/interfaces';
export const ERRORS = {
TRANSACTIONS_DATE_LOCKED: 'TRANSACTIONS_DATE_LOCKED',
TRANSACTION_LOCKING_PARTIAL: 'TRANSACTION_LOCKING_PARTIAL',
TRANSACTION_LOCKING_ALL: 'TRANSACTION_LOCKING_ALL',
TRANSACTIONS_LOCKING_MODULE_NOT_FOUND:
'TRANSACTIONS_LOCKING_MODULE_NOT_FOUND',
};
export const TRANSACTIONS_LOCKING_SCHEMA = [
{
module: 'sales',
formattedModule: 'transactions_locking.module.sales.label',
description: 'transactions_locking.module.sales.desc',
},
{
module: 'purchases',
formattedModule: 'transactions_locking.module.purchases.label',
description: 'transactions_locking.module.purchases.desc',
},
{
module: 'financial',
formattedModule: 'transactions_locking.module.financial.label',
description: 'transactions_locking.module.financial.desc',
},
] as ITransactionsLockingSchema[];
export function getTransactionsLockingSchemaMeta(
module: TransactionsLockingGroup
): ITransactionsLockingSchema {
return TRANSACTIONS_LOCKING_SCHEMA.find((schema) => schema.module === module);
}