mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 23:00:34 +00:00
refactor: settings module to Nestjs
This commit is contained in:
241
packages/server-nest/src/constants/metable-options.ts
Normal file
241
packages/server-nest/src/constants/metable-options.ts
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
// import { getTransactionsLockingSettingsSchema } from '@/api/controllers/TransactionsLocking/utils';
|
||||||
|
|
||||||
|
export const SettingsOptions = {
|
||||||
|
organization: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
base_currency: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
industry: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
fiscal_year: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
financial_date_start: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
time_zone: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
date_format: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
accounting_basis: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
manual_journals: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bill_payments: {
|
||||||
|
withdrawal_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sales_estimates: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
customer_notes: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sales_receipts: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
preferred_deposit_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
receipt_message: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sales_invoices: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
customer_notes: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payment_receives: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
preferred_deposit_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
preferred_advance_deposit: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
preferred_sell_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
preferred_cost_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
preferred_inventory_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expenses: {
|
||||||
|
preferred_payment_account: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
cost_compute_running: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accounts: {
|
||||||
|
account_code_required: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
account_code_unique: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cashflow: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
credit_note: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
customer_notes: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
vendor_credit: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warehouse_transfers: {
|
||||||
|
next_number: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
number_prefix: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
auto_increment: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'sms-notification': {
|
||||||
|
'sms-notification-enable.sale-invoice-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.sale-invoice-reminder': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.sale-estimate-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.sale-receipt-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.payment-receive-details': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'sms-notification-enable.customer-balance': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'transactions-locking': {
|
||||||
|
'locking-type': {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
// ...getTransactionsLockingSettingsSchema([
|
||||||
|
// 'all',
|
||||||
|
// 'sales',
|
||||||
|
// 'purchases',
|
||||||
|
// 'financial',
|
||||||
|
// ]),
|
||||||
|
},
|
||||||
|
features: {
|
||||||
|
'multi-warehouses': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
'multi-branches': {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -60,6 +60,8 @@ import { BankingTransactionsExcludeModule } from '../BankingTransactionsExclude/
|
|||||||
import { BankingTransactionsRegonizeModule } from '../BankingTranasctionsRegonize/BankingTransactionsRegonize.module';
|
import { BankingTransactionsRegonizeModule } from '../BankingTranasctionsRegonize/BankingTransactionsRegonize.module';
|
||||||
import { BankingMatchingModule } from '../BankingMatching/BankingMatching.module';
|
import { BankingMatchingModule } from '../BankingMatching/BankingMatching.module';
|
||||||
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
||||||
|
import { TransactionsLockingModule } from '../TransactionsLocking/TransactionsLocking.module';
|
||||||
|
import { SettingsModule } from '../Settings/Settings.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -141,9 +143,11 @@ import { BankingTransactionsModule } from '../BankingTransactions/BankingTransac
|
|||||||
BankAccountsModule,
|
BankAccountsModule,
|
||||||
BankRulesModule,
|
BankRulesModule,
|
||||||
BankingTransactionsModule,
|
BankingTransactionsModule,
|
||||||
// BankingTransactionsExcludeModule,
|
BankingTransactionsExcludeModule,
|
||||||
// BankingTransactionsRegonizeModule,
|
BankingTransactionsRegonizeModule,
|
||||||
// BankingMatchingModule,
|
BankingMatchingModule,
|
||||||
|
TransactionsLockingModule,
|
||||||
|
SettingsModule
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
40
packages/server-nest/src/modules/Metable/MetableConfig.ts
Normal file
40
packages/server-nest/src/modules/Metable/MetableConfig.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { get } from 'lodash';
|
||||||
|
|
||||||
|
export class MetableConfig {
|
||||||
|
public config: any;
|
||||||
|
|
||||||
|
constructor(config: any) {
|
||||||
|
this.setConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the config.
|
||||||
|
*/
|
||||||
|
setConfig(config: any) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the meta config.
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} group
|
||||||
|
* @param {string} accessor
|
||||||
|
* @returns {object|string}
|
||||||
|
*/
|
||||||
|
getMetaConfig(key: string, group?: string, accessor?: string) {
|
||||||
|
const configGroup = get(this.config, group);
|
||||||
|
const config = get(configGroup, key);
|
||||||
|
|
||||||
|
return accessor ? get(config, accessor) : config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the meta type.
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} group
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getMetaType(key: string, group?: string) {
|
||||||
|
return this.getMetaConfig(key, group, 'type');
|
||||||
|
}
|
||||||
|
}
|
||||||
9
packages/server-nest/src/modules/Metable/MetableModel.ts
Normal file
9
packages/server-nest/src/modules/Metable/MetableModel.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export class Metable {
|
||||||
|
static get modifiers() {
|
||||||
|
return {
|
||||||
|
whereKey(builder, key) {
|
||||||
|
builder.where('key', key);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
214
packages/server-nest/src/modules/Metable/MetableStore.ts
Normal file
214
packages/server-nest/src/modules/Metable/MetableStore.ts
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
import { Model } from 'objection';
|
||||||
|
import { omit, isEmpty } from 'lodash';
|
||||||
|
import { IMetadata, IMetaQuery, IMetableStore } from './types';
|
||||||
|
import { itemsStartWith } from 'utils';
|
||||||
|
|
||||||
|
export class MetableStore implements IMetableStore {
|
||||||
|
metadata: IMetadata[];
|
||||||
|
model: Model;
|
||||||
|
extraColumns: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this.metadata = [];
|
||||||
|
this.model = null;
|
||||||
|
this.extraColumns = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a extra columns.
|
||||||
|
* @param {Array} columns -
|
||||||
|
*/
|
||||||
|
setExtraColumns(columns: string[]): void {
|
||||||
|
this.extraColumns = columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the given metadata key.
|
||||||
|
* @param {string|IMetaQuery} query -
|
||||||
|
* @returns {IMetadata} - Metadata object.
|
||||||
|
*/
|
||||||
|
find(query: string | IMetaQuery): IMetadata {
|
||||||
|
const { key, value, ...extraColumns } = this.parseQuery(query);
|
||||||
|
|
||||||
|
return this.metadata.find((meta: IMetadata) => {
|
||||||
|
const isSameKey = meta.key === key;
|
||||||
|
const sameExtraColumns = this.extraColumns.some(
|
||||||
|
(extraColumn: string) => extraColumns[extraColumn] === meta[extraColumn]
|
||||||
|
);
|
||||||
|
const isSameExtraColumns = sameExtraColumns || isEmpty(extraColumns);
|
||||||
|
|
||||||
|
return isSameKey && isSameExtraColumns;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all metadata.
|
||||||
|
* @returns {IMetadata[]}
|
||||||
|
*/
|
||||||
|
all(): IMetadata[] {
|
||||||
|
return this.metadata
|
||||||
|
.filter((meta: IMetadata) => !meta._markAsDeleted)
|
||||||
|
.map((meta: IMetadata) =>
|
||||||
|
omit(meta, itemsStartWith(Object.keys(meta), '_'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve metadata of the given key.
|
||||||
|
* @param {String} key -
|
||||||
|
* @param {Mixied} defaultValue -
|
||||||
|
*/
|
||||||
|
get(query: string | IMetaQuery, defaultValue?: any): any | null {
|
||||||
|
const metadata = this.find(query);
|
||||||
|
return metadata
|
||||||
|
? metadata.value
|
||||||
|
: typeof defaultValue !== 'undefined'
|
||||||
|
? defaultValue
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Markes the metadata to should be deleted.
|
||||||
|
* @param {String} key -
|
||||||
|
*/
|
||||||
|
remove(query: string | IMetaQuery): void {
|
||||||
|
const metadata: IMetadata = this.find(query);
|
||||||
|
|
||||||
|
if (metadata) {
|
||||||
|
metadata._markAsDeleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all meta data of the given group.
|
||||||
|
* @param {string} group
|
||||||
|
*/
|
||||||
|
removeAll(group: string = 'default'): void {
|
||||||
|
this.metadata = this.metadata.map((meta) => ({
|
||||||
|
...meta,
|
||||||
|
_markAsDeleted: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the meta data to the stack.
|
||||||
|
* @param {String} key -
|
||||||
|
* @param {String} value -
|
||||||
|
*/
|
||||||
|
set(query: IMetaQuery | IMetadata[] | string, metaValue?: any): void {
|
||||||
|
if (Array.isArray(query)) {
|
||||||
|
const metadata = query;
|
||||||
|
|
||||||
|
metadata.forEach((meta: IMetadata) => {
|
||||||
|
this.set(meta);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { key, value, ...extraColumns } = this.parseQuery(query);
|
||||||
|
const metadata = this.find(query);
|
||||||
|
const newValue = metaValue || value;
|
||||||
|
|
||||||
|
if (metadata) {
|
||||||
|
metadata.value = newValue;
|
||||||
|
metadata._markAsUpdated = true;
|
||||||
|
} else {
|
||||||
|
this.metadata.push({
|
||||||
|
value: newValue,
|
||||||
|
key,
|
||||||
|
...extraColumns,
|
||||||
|
_markAsInserted: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses query query.
|
||||||
|
* @param query
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
parseQuery(query: string | IMetaQuery): IMetaQuery {
|
||||||
|
return typeof query !== 'object' ? { key: query } : { ...query };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the metadata before saving to the database.
|
||||||
|
* @param {string|number|boolean} value -
|
||||||
|
* @param {string} valueType -
|
||||||
|
* @return {string|number|boolean} -
|
||||||
|
*/
|
||||||
|
static formatMetaValue(
|
||||||
|
value: string | boolean | number,
|
||||||
|
valueType: string
|
||||||
|
): string | number | boolean {
|
||||||
|
let parsedValue;
|
||||||
|
|
||||||
|
switch (valueType) {
|
||||||
|
case 'number':
|
||||||
|
parsedValue = `${value}`;
|
||||||
|
break;
|
||||||
|
case 'boolean':
|
||||||
|
parsedValue = value ? '1' : '0';
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
parsedValue = JSON.stringify(parsedValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
parsedValue = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return parsedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the metadata to the collection.
|
||||||
|
* @param {Array} collection -
|
||||||
|
*/
|
||||||
|
mapMetadataToCollection(metadata: IMetadata[], parseType: string = 'parse') {
|
||||||
|
return metadata.map((model) =>
|
||||||
|
this.mapMetadataToCollection(model, parseType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load metadata to the metable collection.
|
||||||
|
* @param {Array} meta -
|
||||||
|
*/
|
||||||
|
from(meta: []) {
|
||||||
|
if (Array.isArray(meta)) {
|
||||||
|
meta.forEach((m) => {
|
||||||
|
this.from(m);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.metadata.push(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {array}
|
||||||
|
*/
|
||||||
|
toArray(): IMetadata[] {
|
||||||
|
return this.metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static method to load metadata to the collection.
|
||||||
|
* @param {Array} meta
|
||||||
|
*/
|
||||||
|
static from(meta) {
|
||||||
|
const collection = new MetableCollection();
|
||||||
|
collection.from(meta);
|
||||||
|
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the momerized metadata.
|
||||||
|
*/
|
||||||
|
resetMetadata() {
|
||||||
|
this.metadata = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
246
packages/server-nest/src/modules/Metable/MetableStoreDB.ts
Normal file
246
packages/server-nest/src/modules/Metable/MetableStoreDB.ts
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import { IMetadata, IMetableStoreStorage } from './types';
|
||||||
|
import { MetableStore } from './MetableStore';
|
||||||
|
import { isBlank, parseBoolean } from 'utils';
|
||||||
|
import { MetableConfig } from './MetableConfig';
|
||||||
|
import { EntityRepository } from '@/common/repository/EntityRepository';
|
||||||
|
|
||||||
|
export class MetableDBStore
|
||||||
|
extends MetableStore
|
||||||
|
implements IMetableStoreStorage
|
||||||
|
{
|
||||||
|
repository: any;
|
||||||
|
KEY_COLUMN: string;
|
||||||
|
VALUE_COLUMN: string;
|
||||||
|
TYPE_COLUMN: string;
|
||||||
|
extraQuery: Function;
|
||||||
|
loaded: Boolean;
|
||||||
|
config: MetableConfig;
|
||||||
|
extraColumns: Array<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
constructor(config: any) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.loaded = false;
|
||||||
|
this.KEY_COLUMN = 'key';
|
||||||
|
this.VALUE_COLUMN = 'value';
|
||||||
|
this.TYPE_COLUMN = 'type';
|
||||||
|
this.repository = null;
|
||||||
|
|
||||||
|
this.extraQuery = (meta) => {
|
||||||
|
return {
|
||||||
|
key: meta[this.KEY_COLUMN],
|
||||||
|
...this.transfromMetaExtraColumns(meta),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.config = new MetableConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes meta query.
|
||||||
|
* @param {IMetadata} meta
|
||||||
|
*/
|
||||||
|
private transfromMetaExtraColumns(meta: IMetadata) {
|
||||||
|
return this.extraColumns.reduce((obj, column) => {
|
||||||
|
const metaValue = meta[column];
|
||||||
|
|
||||||
|
if (!isBlank(metaValue)) {
|
||||||
|
obj[column] = metaValue;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set repository entity of this metadata collection.
|
||||||
|
* @param {Object} repository -
|
||||||
|
*/
|
||||||
|
setRepository(repository: EntityRepository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a extra query callback.
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
setExtraQuery(callback) {
|
||||||
|
this.extraQuery = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the modified, deleted and insert metadata.
|
||||||
|
*/
|
||||||
|
save() {
|
||||||
|
this.validateStoreIsLoaded();
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
this.saveUpdated(this.metadata),
|
||||||
|
this.saveDeleted(this.metadata),
|
||||||
|
this.saveInserted(this.metadata),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the updated metadata.
|
||||||
|
* @param {IMetadata[]} metadata -
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
saveUpdated(metadata: IMetadata[]) {
|
||||||
|
const updated = metadata.filter((m) => m._markAsUpdated === true);
|
||||||
|
const opers = [];
|
||||||
|
|
||||||
|
updated.forEach((meta) => {
|
||||||
|
const updateOper = this.repository
|
||||||
|
.update(
|
||||||
|
{ [this.VALUE_COLUMN]: meta.value },
|
||||||
|
{ ...this.extraQuery(meta) },
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
meta._markAsUpdated = false;
|
||||||
|
});
|
||||||
|
opers.push(updateOper);
|
||||||
|
});
|
||||||
|
return Promise.all(opers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the deleted metadata.
|
||||||
|
* @param {IMetadata[]} metadata -
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
saveDeleted(metadata: IMetadata[]) {
|
||||||
|
const deleted = metadata.filter(
|
||||||
|
(m: IMetadata) => m._markAsDeleted === true,
|
||||||
|
);
|
||||||
|
const opers: Array<Promise<void>> = [];
|
||||||
|
|
||||||
|
if (deleted.length > 0) {
|
||||||
|
deleted.forEach((meta) => {
|
||||||
|
const deleteOper = this.repository
|
||||||
|
.deleteBy({
|
||||||
|
...this.extraQuery(meta),
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
meta._markAsDeleted = false;
|
||||||
|
});
|
||||||
|
opers.push(deleteOper);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.all(opers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the inserted metadata.
|
||||||
|
* @param {IMetadata[]} metadata -
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
saveInserted(metadata: IMetadata[]) {
|
||||||
|
const inserted = metadata.filter(
|
||||||
|
(m: IMetadata) => m._markAsInserted === true,
|
||||||
|
);
|
||||||
|
const opers: Array<Promise<void>> = [];
|
||||||
|
|
||||||
|
inserted.forEach((meta) => {
|
||||||
|
const insertData = {
|
||||||
|
[this.KEY_COLUMN]: meta.key,
|
||||||
|
[this.VALUE_COLUMN]: meta.value,
|
||||||
|
...this.transfromMetaExtraColumns(meta),
|
||||||
|
};
|
||||||
|
const insertOper = this.repository.create(insertData).then(() => {
|
||||||
|
meta._markAsInserted = false;
|
||||||
|
});
|
||||||
|
opers.push(insertOper);
|
||||||
|
});
|
||||||
|
return Promise.all(opers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the metadata from the storage.
|
||||||
|
* @param {String|Array} key -
|
||||||
|
* @param {Boolean} force -
|
||||||
|
*/
|
||||||
|
async load() {
|
||||||
|
const metadata = await this.repository.all();
|
||||||
|
const mappedMetadata = this.mapMetadataCollection(metadata);
|
||||||
|
|
||||||
|
this.resetMetadata();
|
||||||
|
|
||||||
|
mappedMetadata.forEach((meta: IMetadata) => {
|
||||||
|
this.metadata.push(meta);
|
||||||
|
});
|
||||||
|
this.loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the metadata values after fetching it from the storage.
|
||||||
|
* @param {String|Number|Boolean} value -
|
||||||
|
* @param {String} valueType -
|
||||||
|
* @return {String|Number|Boolean} -
|
||||||
|
*/
|
||||||
|
static parseMetaValue(
|
||||||
|
value: string,
|
||||||
|
valueType: string | false,
|
||||||
|
): string | boolean | number {
|
||||||
|
let parsedValue: string | number | boolean;
|
||||||
|
|
||||||
|
switch (valueType) {
|
||||||
|
case 'number':
|
||||||
|
parsedValue = parseFloat(value);
|
||||||
|
break;
|
||||||
|
case 'boolean':
|
||||||
|
parsedValue = parseBoolean(value, false);
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
parsedValue = JSON.stringify(parsedValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
parsedValue = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return parsedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping and parse metadata to collection entries.
|
||||||
|
* @param {Meta} attr -
|
||||||
|
* @param {String} parseType -
|
||||||
|
*/
|
||||||
|
mapMetadata(metadata: IMetadata) {
|
||||||
|
const metaType = this.config.getMetaType(
|
||||||
|
metadata[this.KEY_COLUMN],
|
||||||
|
metadata['group'],
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
key: metadata[this.KEY_COLUMN],
|
||||||
|
value: MetableDBStore.parseMetaValue(
|
||||||
|
metadata[this.VALUE_COLUMN],
|
||||||
|
metaType,
|
||||||
|
),
|
||||||
|
...this.extraColumns.reduce((obj, extraCol: string) => {
|
||||||
|
obj[extraCol] = metadata[extraCol] || null;
|
||||||
|
return obj;
|
||||||
|
}, {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the metadata to the collection.
|
||||||
|
* @param {Array} collection -
|
||||||
|
*/
|
||||||
|
mapMetadataCollection(metadata: IMetadata[]) {
|
||||||
|
return metadata.map((model) => this.mapMetadata(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw error in case the store is not loaded yet.
|
||||||
|
*/
|
||||||
|
private validateStoreIsLoaded() {
|
||||||
|
if (!this.loaded) {
|
||||||
|
throw new Error(
|
||||||
|
'You could not save the store before loaded from the storage.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
packages/server-nest/src/modules/Metable/types.ts
Normal file
27
packages/server-nest/src/modules/Metable/types.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export interface IMetadata {
|
||||||
|
key: string;
|
||||||
|
value: string | boolean | number;
|
||||||
|
group: string;
|
||||||
|
_markAsDeleted?: boolean;
|
||||||
|
_markAsInserted?: boolean;
|
||||||
|
_markAsUpdated?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMetaQuery {
|
||||||
|
key: string;
|
||||||
|
group?: string;
|
||||||
|
value?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMetableStore {
|
||||||
|
find(query: string | IMetaQuery): IMetadata;
|
||||||
|
all(): IMetadata[];
|
||||||
|
get(query: string | IMetaQuery, defaultValue: any): string | number | boolean;
|
||||||
|
remove(query: string | IMetaQuery): void;
|
||||||
|
removeAll(): void;
|
||||||
|
toArray(): IMetadata[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMetableStoreStorage {
|
||||||
|
save(): Promise<void>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { Controller, Get } from '@nestjs/common';
|
||||||
|
import { Inject } from '@nestjs/common';
|
||||||
|
import { SETTINGS } from './Settings.module';
|
||||||
|
import { SettingsStore } from './SettingsStore';
|
||||||
|
|
||||||
|
@Controller('settings')
|
||||||
|
export class SettingsController {
|
||||||
|
constructor(
|
||||||
|
@Inject(SETTINGS) private readonly settingsStore: SettingsStore,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Get('')
|
||||||
|
async getSettings() {
|
||||||
|
return this.settingsStore.all();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
packages/server-nest/src/modules/Settings/Settings.module.ts
Normal file
19
packages/server-nest/src/modules/Settings/Settings.module.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { SettingRepository } from './repositories/Setting.repository';
|
||||||
|
import { SettingsStore } from './SettingsStore';
|
||||||
|
|
||||||
|
export const SETTINGS = 'SETTINGS';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
SettingRepository,
|
||||||
|
{
|
||||||
|
provide: SETTINGS,
|
||||||
|
useFactory: (settingRepository: SettingRepository) => {
|
||||||
|
return new SettingsStore(settingRepository);
|
||||||
|
},
|
||||||
|
inject: [SettingRepository],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class SettingsModule {}
|
||||||
16
packages/server-nest/src/modules/Settings/SettingsStore.ts
Normal file
16
packages/server-nest/src/modules/Settings/SettingsStore.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { EntityRepository } from '@/common/repository/EntityRepository';
|
||||||
|
import { MetableDBStore } from '../Metable/MetableStoreDB';
|
||||||
|
import { SettingsOptions } from '@/constants/metable-options';
|
||||||
|
|
||||||
|
export class SettingsStore extends MetableDBStore {
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {number} tenantId
|
||||||
|
*/
|
||||||
|
constructor(repository: EntityRepository, config: any = SettingsOptions) {
|
||||||
|
super(config);
|
||||||
|
|
||||||
|
// this.setExtraColumns(['group']);
|
||||||
|
this.setRepository(repository);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
packages/server-nest/src/modules/Settings/models/Setting.ts
Normal file
22
packages/server-nest/src/modules/Settings/models/Setting.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { BaseModel } from '@/models/Model';
|
||||||
|
// import TenantModel from 'models/TenantModel';
|
||||||
|
// import Auth from './Auth';
|
||||||
|
|
||||||
|
export class Setting extends BaseModel {
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
static get tableName() {
|
||||||
|
return 'settings';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra metadata query to query with the current authenticate user.
|
||||||
|
* @param {Object} query
|
||||||
|
*/
|
||||||
|
// static extraMetadataQuery(query) {
|
||||||
|
// if (Auth.isLogged()) {
|
||||||
|
// query.where('user_id', Auth.userId());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject } from '@nestjs/common';
|
||||||
|
import { TenantRepository } from '@/common/repository/TenantRepository';
|
||||||
|
import { TENANCY_DB_CONNECTION } from '@/modules/Tenancy/TenancyDB/TenancyDB.constants';
|
||||||
|
import { Setting } from '../models/Setting';
|
||||||
|
|
||||||
|
export class SettingRepository extends TenantRepository {
|
||||||
|
constructor(
|
||||||
|
@Inject(TENANCY_DB_CONNECTION)
|
||||||
|
private readonly tenantKnex: Knex,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the repository's model.
|
||||||
|
*/
|
||||||
|
get model(): typeof Setting {
|
||||||
|
return Setting.bindKnex(this.tenantKnex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { Controller, Put, Get, Body, Param, UseGuards } from '@nestjs/common';
|
||||||
|
import { TransactionsLockingService } from './commands/CommandTransactionsLockingService';
|
||||||
|
import { TransactionsLockingGroup } from './types/TransactionsLocking.types';
|
||||||
|
import { ITransactionsLockingAllDTO } from './types/TransactionsLocking.types';
|
||||||
|
import { ICancelTransactionsLockingDTO } from './types/TransactionsLocking.types';
|
||||||
|
import { ITransactionLockingPartiallyDTO } from './types/TransactionsLocking.types';
|
||||||
|
import { QueryTransactionsLocking } from './queries/QueryTransactionsLocking';
|
||||||
|
|
||||||
|
@Controller('transactions-locking')
|
||||||
|
export class TransactionsLockingController {
|
||||||
|
constructor(
|
||||||
|
private readonly transactionsLockingService: TransactionsLockingService,
|
||||||
|
private readonly queryTransactionsLocking: QueryTransactionsLocking,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Put('lock')
|
||||||
|
async commandTransactionsLocking(
|
||||||
|
@Body('module') module: TransactionsLockingGroup,
|
||||||
|
@Body() transactionLockingDTO: ITransactionsLockingAllDTO,
|
||||||
|
) {
|
||||||
|
const transactionMeta =
|
||||||
|
await this.transactionsLockingService.commandTransactionsLocking(
|
||||||
|
module,
|
||||||
|
transactionLockingDTO,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
message: 'All transactions locking has been submit successfully.',
|
||||||
|
data: transactionMeta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put('cancel-lock')
|
||||||
|
async cancelTransactionLocking(
|
||||||
|
@Body('module') module: TransactionsLockingGroup,
|
||||||
|
@Body() cancelLockingDTO: ICancelTransactionsLockingDTO,
|
||||||
|
) {
|
||||||
|
const data = await this.transactionsLockingService.cancelTransactionLocking(
|
||||||
|
module,
|
||||||
|
cancelLockingDTO,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
message: 'Transactions locking has been canceled successfully.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put('unlock-partial')
|
||||||
|
async unlockTransactionsLockingBetweenPeriod(
|
||||||
|
@Body('module') module: TransactionsLockingGroup,
|
||||||
|
@Body() unlockDTO: ITransactionLockingPartiallyDTO,
|
||||||
|
) {
|
||||||
|
const transactionMeta =
|
||||||
|
await this.transactionsLockingService.unlockTransactionsLockingPartially(
|
||||||
|
module,
|
||||||
|
unlockDTO,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
message: 'Transactions locking has been unlocked partially successfully.',
|
||||||
|
data: transactionMeta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put('cancel-unlock-partial')
|
||||||
|
async cancelPartialUnlocking(
|
||||||
|
@Body('module') module: TransactionsLockingGroup,
|
||||||
|
) {
|
||||||
|
const transactionMeta =
|
||||||
|
await this.transactionsLockingService.cancelPartialTransactionsUnlock(
|
||||||
|
module,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
message: 'Partial transaction unlocking has been canceled successfully.',
|
||||||
|
data: transactionMeta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Get(':module')
|
||||||
|
// async getTransactionLockingMeta(@Param('module') module: string) {
|
||||||
|
// return await this.queryTransactionsLocking.getTransactionsLocking(module);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
async getTransactionLockingMetaList() {
|
||||||
|
return await this.queryTransactionsLocking.getTransactionsLockingAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TransactionsLockingService } from './commands/CommandTransactionsLockingService';
|
||||||
|
import { FinancialTransactionLocking } from './guards/FinancialTransactionLockingGuard';
|
||||||
|
import { PurchasesTransactionLockingGuard } from './guards/PurchasesTransactionLockingGuard';
|
||||||
|
import { SalesTransactionLockingGuard } from './guards/SalesTransactionLockingGuard';
|
||||||
|
import { TransactionsLockingGuard } from './guards/TransactionsLockingGuard';
|
||||||
|
import { TransactionsLockingRepository } from './TransactionsLockingRepository';
|
||||||
|
import { FinancialTransactionLockingGuardSubscriber } from './subscribers/FinancialsTransactionLockingGuardSubscriber';
|
||||||
|
import { PurchasesTransactionLockingGuardSubscriber } from './subscribers/PurchasesTransactionLockingGuardSubscriber';
|
||||||
|
import { SalesTransactionLockingGuardSubscriber } from './subscribers/SalesTransactionLockingGuardSubscriber';
|
||||||
|
import { QueryTransactionsLocking } from './queries/QueryTransactionsLocking';
|
||||||
|
import { TransactionsLockingController } from './TransactionsLocking.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
TransactionsLockingService,
|
||||||
|
FinancialTransactionLocking,
|
||||||
|
PurchasesTransactionLockingGuard,
|
||||||
|
SalesTransactionLockingGuard,
|
||||||
|
TransactionsLockingGuard,
|
||||||
|
TransactionsLockingRepository,
|
||||||
|
FinancialTransactionLockingGuardSubscriber,
|
||||||
|
PurchasesTransactionLockingGuardSubscriber,
|
||||||
|
SalesTransactionLockingGuardSubscriber,
|
||||||
|
QueryTransactionsLocking,
|
||||||
|
],
|
||||||
|
controllers: [TransactionsLockingController],
|
||||||
|
})
|
||||||
|
export class TransactionsLockingModule {}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
import { isUndefined } from 'lodash';
|
||||||
|
import {
|
||||||
|
ITransactionMeta,
|
||||||
|
TransactionsLockingGroup,
|
||||||
|
TransactionsLockingType,
|
||||||
|
} from './types/TransactionsLocking.types';
|
||||||
|
import { parseDate } from 'utils';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { SettingsStore } from '../Settings/SettingsStore';
|
||||||
|
import { SETTINGS } from '../Settings/Settings.module';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TransactionsLockingRepository {
|
||||||
|
constructor(
|
||||||
|
@Inject(SETTINGS) private readonly settingsStore: SettingsStore,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save transactions locking settings
|
||||||
|
* @param {string} lockingGroup - The group of the transactions locking
|
||||||
|
* @param {ITransactionMeta} transactionlocking - The transactions locking settings
|
||||||
|
*/
|
||||||
|
public async saveTransactionsLocking(
|
||||||
|
lockingGroup: string = TransactionsLockingGroup.All,
|
||||||
|
transactionlocking,
|
||||||
|
) {
|
||||||
|
const group = `transactions-locking`;
|
||||||
|
|
||||||
|
if (!isUndefined(transactionlocking.active)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.active`,
|
||||||
|
value: transactionlocking.active,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(transactionlocking.lockToDate)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.lock_to_date`,
|
||||||
|
value: parseDate(transactionlocking.lockToDate),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(transactionlocking.unlockFromDate)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.unlock_from_date`,
|
||||||
|
value: parseDate(transactionlocking.unlockFromDate),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(transactionlocking.unlockToDate)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.unlock_to_date`,
|
||||||
|
value: parseDate(transactionlocking.unlockToDate),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(transactionlocking.lockReason)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.lock_reason`,
|
||||||
|
value: transactionlocking.lockReason,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(transactionlocking.unlockReason)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.unlock_reason`,
|
||||||
|
value: transactionlocking.unlockReason,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(transactionlocking.partialUnlockReason)) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.partial_unlock_reason`,
|
||||||
|
value: transactionlocking.partialUnlockReason,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await this.settingsStore.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transactions locking settings
|
||||||
|
* @param {string} lockingGroup - The group of the transactions locking
|
||||||
|
* @returns {ITransactionMeta} - The transactions locking settings
|
||||||
|
*/
|
||||||
|
public getTransactionsLocking(
|
||||||
|
lockingGroup: string = TransactionsLockingGroup.All,
|
||||||
|
): ITransactionMeta {
|
||||||
|
const group = `transactions-locking`;
|
||||||
|
|
||||||
|
const isEnabled = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.active`,
|
||||||
|
});
|
||||||
|
const lockFromDate = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.lock_from_date`,
|
||||||
|
});
|
||||||
|
const lockToDate = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.lock_to_date`,
|
||||||
|
});
|
||||||
|
const unlockFromDate = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.unlock_from_date`,
|
||||||
|
});
|
||||||
|
const unlockToDate = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.unlock_to_date`,
|
||||||
|
});
|
||||||
|
const lockReason = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.lock_reason`,
|
||||||
|
});
|
||||||
|
const unlockReason = this.settingsStore.get({
|
||||||
|
group,
|
||||||
|
key: `${lockingGroup}.unlock_reason`,
|
||||||
|
});
|
||||||
|
const partialUnlockReason = this.settingsStore.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 || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transactions locking type
|
||||||
|
* @returns {string} - The transactions locking type
|
||||||
|
*/
|
||||||
|
public getTransactionsLockingType() {
|
||||||
|
const lockingType = this.settingsStore.get({
|
||||||
|
group: 'transactions-locking',
|
||||||
|
key: 'locking-type',
|
||||||
|
});
|
||||||
|
return lockingType || 'partial';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag transactions locking type
|
||||||
|
* @param {TransactionsLockingType} transactionsType - The transactions locking type
|
||||||
|
*/
|
||||||
|
public flagTransactionsLockingType(
|
||||||
|
transactionsType: TransactionsLockingType,
|
||||||
|
) {
|
||||||
|
this.settingsStore.set({
|
||||||
|
group: 'transactions-locking',
|
||||||
|
key: 'locking-type',
|
||||||
|
value: transactionsType,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
import { omit } from 'lodash';
|
||||||
|
import {
|
||||||
|
ICancelTransactionsLockingDTO,
|
||||||
|
ITransactionLockingPartiallyDTO,
|
||||||
|
ITransactionMeta,
|
||||||
|
ITransactionsLockingAllDTO,
|
||||||
|
ITransactionsLockingCanceled,
|
||||||
|
ITransactionsLockingPartialUnlocked,
|
||||||
|
TransactionsLockingGroup,
|
||||||
|
TransactionsLockingType,
|
||||||
|
} from '../types/TransactionsLocking.types';
|
||||||
|
import { TransactionsLockingRepository } from '../TransactionsLockingRepository';
|
||||||
|
import { ERRORS } from '../constants';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
|
import { events } from '@/common/events/events';
|
||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
|
||||||
|
const Modules = ['all', 'sales', 'purchases', 'financial'];
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TransactionsLockingService {
|
||||||
|
constructor(
|
||||||
|
private readonly transactionsLockingRepo: TransactionsLockingRepository,
|
||||||
|
private readonly eventPublisher: EventEmitter2,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable/disable all transacations locking.
|
||||||
|
* @param {TransactionsLockingGroup} module - The transaction locking module.
|
||||||
|
* @param {Partial<ITransactionsLockingAllDTO>} allLockingDTO
|
||||||
|
* @returns {Promise<ITransactionMeta>}
|
||||||
|
*/
|
||||||
|
public commandTransactionsLocking = async (
|
||||||
|
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(module, {
|
||||||
|
active: true,
|
||||||
|
lockToDate: transactionLockingDTO.lockToDate,
|
||||||
|
lockReason: transactionLockingDTO.reason,
|
||||||
|
});
|
||||||
|
// Flag transactions locking type.
|
||||||
|
await this.transactionsLockingRepo.flagTransactionsLockingType(
|
||||||
|
module === TransactionsLockingGroup.All
|
||||||
|
? TransactionsLockingType.All
|
||||||
|
: TransactionsLockingType.Partial,
|
||||||
|
);
|
||||||
|
// Triggers `onTransactionLockingPartialUnlocked` event.
|
||||||
|
await this.eventPublisher.emitAsync(
|
||||||
|
events.transactionsLocking.partialUnlocked,
|
||||||
|
{
|
||||||
|
module,
|
||||||
|
transactionLockingDTO,
|
||||||
|
} as ITransactionsLockingPartialUnlocked,
|
||||||
|
);
|
||||||
|
// Retrieve the transaction locking meta of the given
|
||||||
|
return this.transactionsLockingRepo.getTransactionsLocking(module);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the full transactions locking.
|
||||||
|
* @param {TransactionsLockingGroup} module - The transaction locking module.
|
||||||
|
* @param {ICancelTransactionsLockingDTO} cancelLockingDTO
|
||||||
|
* @returns {Promise<ITransactionMeta>}
|
||||||
|
*/
|
||||||
|
public cancelTransactionLocking = async (
|
||||||
|
module: TransactionsLockingGroup = TransactionsLockingGroup.All,
|
||||||
|
cancelLockingDTO: ICancelTransactionsLockingDTO,
|
||||||
|
): Promise<ITransactionMeta> => {
|
||||||
|
// Validate the transaction locking module.
|
||||||
|
this.validateTransactionsLockingModule(module);
|
||||||
|
|
||||||
|
// Saves transactions locking.
|
||||||
|
await this.transactionsLockingRepo.saveTransactionsLocking(module, {
|
||||||
|
active: false,
|
||||||
|
unlockFromDate: '',
|
||||||
|
unlockToDate: '',
|
||||||
|
unlockReason: cancelLockingDTO.reason,
|
||||||
|
});
|
||||||
|
// Reset flag transactions locking type to partial.
|
||||||
|
await this.transactionsLockingRepo.flagTransactionsLockingType(
|
||||||
|
TransactionsLockingType.Partial,
|
||||||
|
);
|
||||||
|
// Triggers `onTransactionLockingPartialUnlocked` event.
|
||||||
|
await this.eventPublisher.emitAsync(
|
||||||
|
events.transactionsLocking.partialUnlocked,
|
||||||
|
{
|
||||||
|
module,
|
||||||
|
cancelLockingDTO,
|
||||||
|
} as ITransactionsLockingCanceled,
|
||||||
|
);
|
||||||
|
return this.transactionsLockingRepo.getTransactionsLocking(module);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock tranactions locking partially.
|
||||||
|
* @param {TransactionsLockingGroup} module - The transaction locking module.
|
||||||
|
* @param {ITransactionLockingPartiallyDTO} partialTransactionLockingDTO
|
||||||
|
* @returns {Promise<ITransactionMeta>}
|
||||||
|
*/
|
||||||
|
public unlockTransactionsLockingPartially = async (
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (moduleGroup !== TransactionsLockingGroup.All) {
|
||||||
|
this.validateLockingTypeNotAll(lockingType);
|
||||||
|
}
|
||||||
|
// Saves transactions locking settings.
|
||||||
|
await this.transactionsLockingRepo.saveTransactionsLocking(moduleGroup, {
|
||||||
|
...omit(partialTransactionLockingDTO, ['reason']),
|
||||||
|
partialUnlockReason: partialTransactionLockingDTO.reason,
|
||||||
|
});
|
||||||
|
// Retrieve transaction locking meta of the given module.
|
||||||
|
return this.transactionsLockingRepo.getTransactionsLocking(moduleGroup);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel partial transactions unlocking.
|
||||||
|
* @param {TransactionsLockingGroup} module - The transaction locking module.
|
||||||
|
*/
|
||||||
|
public cancelPartialTransactionsUnlock = async (
|
||||||
|
module: TransactionsLockingGroup = TransactionsLockingGroup.All,
|
||||||
|
) => {
|
||||||
|
// Validate the transaction locking module.
|
||||||
|
this.validateTransactionsLockingModule(module);
|
||||||
|
|
||||||
|
// Saves transactions locking settings.
|
||||||
|
await this.transactionsLockingRepo.saveTransactionsLocking(
|
||||||
|
module,
|
||||||
|
{ unlockFromDate: '', unlockToDate: '', partialUnlockReason: '' },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the transaction locking type not partial.
|
||||||
|
* @param {string} lockingType - The transaction locking type.
|
||||||
|
*/
|
||||||
|
public validateLockingTypeNotPartial = (lockingType: string) => {
|
||||||
|
if (lockingType === TransactionsLockingType.Partial) {
|
||||||
|
throw new ServiceError(ERRORS.TRANSACTION_LOCKING_PARTIAL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the transaction locking type not all.
|
||||||
|
* @param {string} lockingType - The transaction locking type.
|
||||||
|
*/
|
||||||
|
public validateLockingTypeNotAll = (lockingType: string) => {
|
||||||
|
if (lockingType === TransactionsLockingType.All) {
|
||||||
|
throw new ServiceError(ERRORS.TRANSACTION_LOCKING_ALL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate transactions locking module.
|
||||||
|
* @param {string} module - The transaction locking module.
|
||||||
|
*/
|
||||||
|
public validateTransactionsLockingModule = (module: string) => {
|
||||||
|
if (Modules.indexOf(module) === -1) {
|
||||||
|
throw new ServiceError(ERRORS.TRANSACTIONS_LOCKING_MODULE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
|
||||||
|
import { TransactionsLockingGuard } from './TransactionsLockingGuard';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FinancialTransactionLocking {
|
||||||
|
constructor(
|
||||||
|
public readonly transactionLockingGuardService: TransactionsLockingGuard,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the transaction locking of cashflow command action.
|
||||||
|
* @param {Date} transactionDate - The transaction date.
|
||||||
|
* @throws {ServiceError(TRANSACTIONS_DATE_LOCKED)}
|
||||||
|
*/
|
||||||
|
public transactionLockingGuard = (transactionDate: Date) => {
|
||||||
|
this.transactionLockingGuardService.transactionsLockingGuard(
|
||||||
|
transactionDate,
|
||||||
|
TransactionsLockingGroup.Financial,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { TransactionsLockingGuard } from './TransactionsLockingGuard';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PurchasesTransactionLockingGuard {
|
||||||
|
constructor(
|
||||||
|
private readonly transactionLockingGuardService: TransactionsLockingGuard,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the transaction locking of purchases services commands.
|
||||||
|
* @param {Date} transactionDate - The transaction date.
|
||||||
|
*/
|
||||||
|
public transactionLockingGuard = async (
|
||||||
|
transactionDate: Date
|
||||||
|
) => {
|
||||||
|
this.transactionLockingGuardService.transactionsLockingGuard(
|
||||||
|
transactionDate,
|
||||||
|
TransactionsLockingGroup.Purchases
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { TransactionsLockingGuard } from './TransactionsLockingGuard';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SalesTransactionLockingGuard {
|
||||||
|
constructor(
|
||||||
|
private readonly transactionLockingGuardService: TransactionsLockingGuard,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the transaction locking of sales services commands.
|
||||||
|
* @param {Date} transactionDate - The transaction date.
|
||||||
|
*/
|
||||||
|
public transactionLockingGuard = async (
|
||||||
|
transactionDate: Date
|
||||||
|
) => {
|
||||||
|
await this.transactionLockingGuardService.transactionsLockingGuard(
|
||||||
|
transactionDate,
|
||||||
|
TransactionsLockingGroup.Sales
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
|
||||||
|
import { TransactionsLockingRepository } from '../TransactionsLockingRepository';
|
||||||
|
import { ERRORS } from '../constants';
|
||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TransactionsLockingGuard {
|
||||||
|
constructor(
|
||||||
|
private readonly transactionsLockingRepo: TransactionsLockingRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the transaction date between the locking date period.
|
||||||
|
* @param {Date} transactionDate - The transaction date.
|
||||||
|
* @param {TransactionsLockingGroup} lockingGroup - The transaction group.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public isTransactionsLocking = (
|
||||||
|
transactionDate: Date,
|
||||||
|
lockingGroup: string = TransactionsLockingGroup.All
|
||||||
|
): boolean => {
|
||||||
|
const { isEnabled, unlockFromDate, unlockToDate, lockToDate } =
|
||||||
|
this.transactionsLockingRepo.getTransactionsLocking(
|
||||||
|
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 {Date} transactionDate - The transaction date.
|
||||||
|
* @param {TransactionsLockingGroup} lockingGroup - The transaction group.
|
||||||
|
*
|
||||||
|
* @throws {ServiceError}
|
||||||
|
*/
|
||||||
|
public validateTransactionsLocking = (
|
||||||
|
transactionDate: Date,
|
||||||
|
lockingGroup: TransactionsLockingGroup
|
||||||
|
) => {
|
||||||
|
const isLocked = this.isTransactionsLocking(
|
||||||
|
transactionDate,
|
||||||
|
lockingGroup
|
||||||
|
);
|
||||||
|
if (isLocked) {
|
||||||
|
this.throwTransactionsLockError(lockingGroup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws transactions locking error.
|
||||||
|
* @param {TransactionsLockingGroup} lockingGroup - The transaction group.
|
||||||
|
*/
|
||||||
|
public throwTransactionsLockError = (
|
||||||
|
lockingGroup: TransactionsLockingGroup
|
||||||
|
) => {
|
||||||
|
const { lockToDate } = this.transactionsLockingRepo.getTransactionsLocking(
|
||||||
|
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 {TransactionsLockingGroup} lockingGroup - The transaction group.
|
||||||
|
* @param {Date} transactionDate - The transaction date.
|
||||||
|
*/
|
||||||
|
public transactionsLockingGuard = (
|
||||||
|
transactionDate: Date,
|
||||||
|
moduleType: TransactionsLockingGroup
|
||||||
|
) => {
|
||||||
|
const lockingType =
|
||||||
|
this.transactionsLockingRepo.getTransactionsLockingType();
|
||||||
|
|
||||||
|
//
|
||||||
|
if (lockingType === TransactionsLockingGroup.All) {
|
||||||
|
return this.validateTransactionsLocking(
|
||||||
|
transactionDate,
|
||||||
|
TransactionsLockingGroup.All
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return this.validateTransactionsLocking(
|
||||||
|
transactionDate,
|
||||||
|
moduleType
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
ITransactionLockingMetaPOJO,
|
||||||
|
ITransactionsLockingListPOJO,
|
||||||
|
ITransactionsLockingSchema,
|
||||||
|
TransactionsLockingGroup,
|
||||||
|
} from '../types/TransactionsLocking.types';
|
||||||
|
import { TRANSACTIONS_LOCKING_SCHEMA } from '../constants';
|
||||||
|
import { TransactionsLockingRepository } from '../TransactionsLockingRepository';
|
||||||
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
|
import { TransactionsLockingMetaTransformer } from './TransactionsLockingMetaTransformer';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class QueryTransactionsLocking {
|
||||||
|
constructor(
|
||||||
|
private readonly transactionsLockingRepo: TransactionsLockingRepository,
|
||||||
|
private readonly transformer: TransformerInjectable,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve transactions locking modules.
|
||||||
|
* @returns {ITransactionLockingMetaPOJO[]}
|
||||||
|
*/
|
||||||
|
public getTransactionsLockingModules = (): Promise<
|
||||||
|
ITransactionLockingMetaPOJO[]
|
||||||
|
> => {
|
||||||
|
const modules = TRANSACTIONS_LOCKING_SCHEMA.map(
|
||||||
|
(schema: ITransactionsLockingSchema) =>
|
||||||
|
this.getTransactionsLockingModuleMeta(schema.module),
|
||||||
|
);
|
||||||
|
return Promise.all(modules);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retireve the transactions locking all module.
|
||||||
|
* @returns {ITransactionLockingMetaPOJO}
|
||||||
|
*/
|
||||||
|
public getTransactionsLockingAll =
|
||||||
|
(): Promise<ITransactionLockingMetaPOJO> => {
|
||||||
|
return this.getTransactionsLockingModuleMeta(
|
||||||
|
TransactionsLockingGroup.All,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the transactions locking module meta.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
* @param {TransactionsLockingGroup} module -
|
||||||
|
* @returns {ITransactionLockingMetaPOJO}
|
||||||
|
*/
|
||||||
|
public getTransactionsLockingModuleMeta = (
|
||||||
|
module: TransactionsLockingGroup,
|
||||||
|
): Promise<ITransactionLockingMetaPOJO> => {
|
||||||
|
const meta = this.transactionsLockingRepo.getTransactionsLocking(module);
|
||||||
|
return this.transformer.transform(
|
||||||
|
meta,
|
||||||
|
new TransactionsLockingMetaTransformer(),
|
||||||
|
{ module },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve transactions locking list.
|
||||||
|
* @returns {Promise<ITransactionsLockingListPOJO>}
|
||||||
|
*/
|
||||||
|
public getTransactionsLockingList =
|
||||||
|
async (): Promise<ITransactionsLockingListPOJO> => {
|
||||||
|
// Retrieve the current transactions locking type.
|
||||||
|
const lockingType =
|
||||||
|
this.transactionsLockingRepo.getTransactionsLockingType();
|
||||||
|
|
||||||
|
const all = await this.getTransactionsLockingAll();
|
||||||
|
const modules = await this.getTransactionsLockingModules();
|
||||||
|
|
||||||
|
return {
|
||||||
|
lockingType,
|
||||||
|
all,
|
||||||
|
modules,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { get } from 'lodash';
|
||||||
|
import { getTransactionsLockingSchemaMeta } from '../constants';
|
||||||
|
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||||
|
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
|
||||||
|
|
||||||
|
export 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.t('transactions_locking.module.all_transactions')
|
||||||
|
: this.context.i18n.t(
|
||||||
|
get(
|
||||||
|
getTransactionsLockingSchemaMeta(this.options.module),
|
||||||
|
'formattedModule',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module description.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected description = () => {
|
||||||
|
return this.options.module === TransactionsLockingGroup.All
|
||||||
|
? ''
|
||||||
|
: this.context.i18n.t(
|
||||||
|
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) : '';
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,261 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
|
import { FinancialTransactionLocking } from '../guards/FinancialTransactionLockingGuard';
|
||||||
|
import {
|
||||||
|
IManualJournalCreatingPayload,
|
||||||
|
IManualJournalEditingPayload,
|
||||||
|
IManualJournalPublishingPayload,
|
||||||
|
} from '@/modules/ManualJournals/types/ManualJournals.types';
|
||||||
|
import {
|
||||||
|
IExpenseCreatingPayload,
|
||||||
|
IExpenseDeletingPayload,
|
||||||
|
IExpenseEventEditingPayload,
|
||||||
|
IExpensePublishingPayload,
|
||||||
|
} from '@/modules/Expenses/Expenses.types';
|
||||||
|
import {
|
||||||
|
ICommandCashflowCreatingPayload,
|
||||||
|
ICommandCashflowDeletingPayload,
|
||||||
|
} from '@/modules/BankingTransactions/types/BankingTransactions.types';
|
||||||
|
import { events } from '@/common/events/events';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FinancialTransactionLockingGuardSubscriber {
|
||||||
|
constructor(
|
||||||
|
public readonly financialTransactionsLocking: FinancialTransactionLocking,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* - MANUAL JOURNALS SERVICE.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on manual journal creating.
|
||||||
|
* @param {IManualJournalCreatingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.manualJournals.onCreating)
|
||||||
|
public async transactionsLockingGuardOnManualJournalCreating({
|
||||||
|
manualJournalDTO,
|
||||||
|
}: IManualJournalCreatingPayload) {
|
||||||
|
// Can't continue if the new journal is not published yet.
|
||||||
|
if (!manualJournalDTO.publish) return;
|
||||||
|
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
manualJournalDTO.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on manual journal deleting.
|
||||||
|
* @param {IManualJournalEditingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.manualJournals.onDeleting)
|
||||||
|
public async transactionsLockingGuardOnManualJournalDeleting({
|
||||||
|
oldManualJournal,
|
||||||
|
}: IManualJournalEditingPayload) {
|
||||||
|
// Can't continue if the old journal is not published.
|
||||||
|
if (!oldManualJournal.isPublished) return;
|
||||||
|
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldManualJournal.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on manual journal editing.
|
||||||
|
* @param {IManualJournalDeletingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.manualJournals.onEditing)
|
||||||
|
public async transactionsLockingGuardOnManualJournalEditing({
|
||||||
|
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(
|
||||||
|
oldManualJournal.date,
|
||||||
|
);
|
||||||
|
// Validate the new journal date.
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
manualJournalDTO.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on manual journal publishing.
|
||||||
|
* @param {IManualJournalPublishingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.manualJournals.onPublishing)
|
||||||
|
public async transactionsLockingGuardOnManualJournalPublishing({
|
||||||
|
oldManualJournal,
|
||||||
|
}: IManualJournalPublishingPayload) {
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldManualJournal.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* - EXPENSES SERVICE.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on expense creating.
|
||||||
|
* @param {IExpenseCreatingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.expenses.onCreating)
|
||||||
|
public async transactionsLockingGuardOnExpenseCreating({
|
||||||
|
expenseDTO,
|
||||||
|
}: IExpenseCreatingPayload) {
|
||||||
|
// Can't continue if the new expense is not published yet.
|
||||||
|
if (!expenseDTO.publish) return;
|
||||||
|
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
expenseDTO.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on expense deleting.
|
||||||
|
* @param {IExpenseDeletingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.expenses.onDeleting)
|
||||||
|
public async transactionsLockingGuardOnExpenseDeleting({
|
||||||
|
oldExpense,
|
||||||
|
}: IExpenseDeletingPayload) {
|
||||||
|
// Can't continue if expense transaction is not published.
|
||||||
|
if (!oldExpense.isPublished) return;
|
||||||
|
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldExpense.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on expense editing.
|
||||||
|
* @param {IExpenseEventEditingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.expenses.onEditing)
|
||||||
|
public async transactionsLockingGuardOnExpenseEditing({
|
||||||
|
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(
|
||||||
|
oldExpense.paymentDate,
|
||||||
|
);
|
||||||
|
// Validate the new expense date.
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
expenseDTO.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on expense publishing.
|
||||||
|
* @param {IExpensePublishingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.expenses.onPublishing)
|
||||||
|
public async transactionsLockingGuardOnExpensePublishing({
|
||||||
|
oldExpense,
|
||||||
|
}: IExpensePublishingPayload) {
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldExpense.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* - CASHFLOW SERVICE.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on cashflow transaction creating.
|
||||||
|
* @param {ICommandCashflowCreatingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.cashflow.onTransactionCreating)
|
||||||
|
public async transactionsLockingGuardOnCashflowTransactionCreating({
|
||||||
|
newTransactionDTO,
|
||||||
|
}: ICommandCashflowCreatingPayload) {
|
||||||
|
if (!newTransactionDTO.publish) return;
|
||||||
|
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
newTransactionDTO.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on cashflow transaction deleting.
|
||||||
|
* @param {ICommandCashflowDeletingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.cashflow.onTransactionDeleting)
|
||||||
|
public async transactionsLockingGuardOnCashflowTransactionDeleting({
|
||||||
|
oldCashflowTransaction,
|
||||||
|
}: ICommandCashflowDeletingPayload) {
|
||||||
|
// Can't continue if the cashflow transaction is not published.
|
||||||
|
if (!oldCashflowTransaction.isPublished) return;
|
||||||
|
|
||||||
|
await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldCashflowTransaction.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* - INVENTORY ADJUSTMENT SERVICE.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transactions locking guard on inventory adjustment creating.
|
||||||
|
* @param {IInventoryAdjustmentCreatingPayload} payload -
|
||||||
|
*/
|
||||||
|
// @OnEvent(events.inventoryAdjustment.onQuickCreating)
|
||||||
|
// public async transactionsLockingGuardOnInventoryAdjCreating({
|
||||||
|
// 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
|
||||||
|
// */
|
||||||
|
// @OnEvent(events.inventoryAdjustment.onDeleting)
|
||||||
|
// public async transactionsLockingGuardOnInventoryAdjDeleting({
|
||||||
|
// oldInventoryAdjustment,
|
||||||
|
// }: IInventoryAdjustmentDeletingPayload) {
|
||||||
|
// // Can't locking if the adjustment is published yet.
|
||||||
|
// if (!oldInventoryAdjustment.isPublished) return;
|
||||||
|
|
||||||
|
// await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
// oldInventoryAdjustment.date
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Transaction locking guard on inventory adjustment publishing.
|
||||||
|
// * @param {IInventoryAdjustmentPublishingPayload} payload
|
||||||
|
// */
|
||||||
|
// @OnEvent(events.inventoryAdjustment.onPublishing)
|
||||||
|
// public async transactionsLockingGuardOnInventoryAdjPublishing({
|
||||||
|
// oldInventoryAdjustment,
|
||||||
|
// }: IInventoryAdjustmentPublishingPayload) {
|
||||||
|
// await this.financialTransactionsLocking.transactionLockingGuard(
|
||||||
|
// oldInventoryAdjustment.date
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { events } from '@/common/events/events';
|
||||||
|
import {
|
||||||
|
IRefundVendorCreditCreatingPayload,
|
||||||
|
IRefundVendorCreditDeletingPayload,
|
||||||
|
} from '@/modules/VendorCreditsRefund/types/VendorCreditRefund.types';
|
||||||
|
import {
|
||||||
|
IVendorCreditCreatingPayload,
|
||||||
|
IVendorCreditDeletingPayload,
|
||||||
|
IVendorCreditEditingPayload,
|
||||||
|
} from '@/modules/VendorCredit/types/VendorCredit.types';
|
||||||
|
import {
|
||||||
|
IBillCreatingPayload,
|
||||||
|
IBillEditingPayload,
|
||||||
|
IBillEventDeletingPayload,
|
||||||
|
} from '@/modules/Bills/Bills.types';
|
||||||
|
import {
|
||||||
|
IBillPaymentCreatingPayload,
|
||||||
|
IBillPaymentEditingPayload,
|
||||||
|
} from '@/modules/BillPayments/types/BillPayments.types';
|
||||||
|
import { IBillPaymentDeletingPayload } from '@/modules/BillPayments/types/BillPayments.types';
|
||||||
|
import { PurchasesTransactionLockingGuard } from '../guards/PurchasesTransactionLockingGuard';
|
||||||
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PurchasesTransactionLockingGuardSubscriber {
|
||||||
|
constructor(
|
||||||
|
public readonly purchasesTransactionsLocking: PurchasesTransactionLockingGuard,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* PAYMENT MADES.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment editing.
|
||||||
|
* @param {IBillPaymentEditingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.billPayment.onEditing)
|
||||||
|
public async transactionLockingGuardOnPaymentEditing({
|
||||||
|
oldBillPayment,
|
||||||
|
billPaymentDTO,
|
||||||
|
}: IBillPaymentEditingPayload) {
|
||||||
|
// Validate old payment date.
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldBillPayment.paymentDate,
|
||||||
|
);
|
||||||
|
// Validate the new payment date.
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
billPaymentDTO.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment creating.
|
||||||
|
* @param {IBillPaymentCreatingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.billPayment.onCreating)
|
||||||
|
public async transactionLockingGuardOnPaymentCreating({
|
||||||
|
billPaymentDTO,
|
||||||
|
}: IBillPaymentCreatingPayload) {
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
billPaymentDTO.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment deleting.
|
||||||
|
* @param {IBillPaymentDeletingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.billPayment.onDeleting)
|
||||||
|
public async transactionLockingGuardOnPaymentDeleting({
|
||||||
|
oldBillPayment,
|
||||||
|
}: IBillPaymentDeletingPayload) {
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldBillPayment.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* BILLS.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on bill creating.
|
||||||
|
* @param {IBillCreatingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.bill.onCreating)
|
||||||
|
public async transactionLockingGuardOnBillCreating({
|
||||||
|
billDTO,
|
||||||
|
}: IBillCreatingPayload) {
|
||||||
|
// Can't continue if the new bill is not published.
|
||||||
|
if (!billDTO.open) return;
|
||||||
|
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
billDTO.billDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on bill editing.
|
||||||
|
* @param {IBillEditingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.bill.onEditing)
|
||||||
|
public async transactionLockingGuardOnBillEditing({
|
||||||
|
oldBill,
|
||||||
|
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(
|
||||||
|
oldBill.billDate,
|
||||||
|
);
|
||||||
|
// Validate the new bill date.
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
billDTO.billDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on bill deleting.
|
||||||
|
* @param {IBillEventDeletingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.bill.onDeleting)
|
||||||
|
public async transactionLockingGuardOnBillDeleting({
|
||||||
|
oldBill,
|
||||||
|
}: IBillEventDeletingPayload) {
|
||||||
|
// Can't continue if the old bill is not published.
|
||||||
|
if (!oldBill.isOpen) return;
|
||||||
|
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldBill.billDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* VENDOR CREDITS.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on vendor credit creating.
|
||||||
|
* @param {IVendorCreditCreatingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.vendorCredit.onCreating)
|
||||||
|
public async transactionLockingGuardOnVendorCreditCreating({
|
||||||
|
vendorCreditCreateDTO,
|
||||||
|
}: IVendorCreditCreatingPayload) {
|
||||||
|
// Can't continue if the new vendor credit is not published.
|
||||||
|
if (!vendorCreditCreateDTO.open) return;
|
||||||
|
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
vendorCreditCreateDTO.vendorCreditDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on vendor credit deleting.
|
||||||
|
* @param {IVendorCreditDeletingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.vendorCredit.onDeleting)
|
||||||
|
public async transactionLockingGuardOnVendorCreditDeleting({
|
||||||
|
oldVendorCredit,
|
||||||
|
}: IVendorCreditDeletingPayload) {
|
||||||
|
// Can't continue if the old vendor credit is not open.
|
||||||
|
if (!oldVendorCredit.isOpen) return;
|
||||||
|
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldVendorCredit.vendorCreditDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on vendor credit editing.
|
||||||
|
* @param {IVendorCreditEditingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.vendorCredit.onEditing)
|
||||||
|
public async transactionLockingGuardOnVendorCreditEditing({
|
||||||
|
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(
|
||||||
|
oldVendorCredit.vendorCreditDate,
|
||||||
|
);
|
||||||
|
// Validate the new credit date.
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
vendorCreditDTO.vendorCreditDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on refund vendor credit creating.
|
||||||
|
* @param {IRefundVendorCreditCreatingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.vendorCredit.onRefundCreating)
|
||||||
|
public async transactionLockingGuardOnRefundVendorCredit({
|
||||||
|
refundVendorCreditDTO,
|
||||||
|
}: IRefundVendorCreditCreatingPayload) {
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
refundVendorCreditDTO.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on refund vendor credit deleting.
|
||||||
|
* @param {IRefundVendorCreditDeletingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.vendorCredit.onRefundDeleting)
|
||||||
|
public async transactionLockingGuardOnRefundCreditDeleting({
|
||||||
|
oldRefundCredit,
|
||||||
|
}: IRefundVendorCreditDeletingPayload) {
|
||||||
|
await this.purchasesTransactionsLocking.transactionLockingGuard(
|
||||||
|
oldRefundCredit.date,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,387 @@
|
|||||||
|
import { events } from '@/common/events/events';
|
||||||
|
import { SalesTransactionLockingGuard } from '../guards/SalesTransactionLockingGuard';
|
||||||
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
ISaleInvoiceCreatingPaylaod,
|
||||||
|
ISaleInvoiceDeletePayload,
|
||||||
|
ISaleInvoiceEditingPayload,
|
||||||
|
ISaleInvoiceWriteoffCreatePayload,
|
||||||
|
ISaleInvoiceWrittenOffCancelPayload,
|
||||||
|
} from '@/modules/SaleInvoices/SaleInvoice.types';
|
||||||
|
import {
|
||||||
|
IPaymentReceivedCreatingPayload,
|
||||||
|
IPaymentReceivedEditingPayload,
|
||||||
|
IPaymentReceivedDeletingPayload,
|
||||||
|
} from '@/modules/PaymentReceived/types/PaymentReceived.types';
|
||||||
|
import {
|
||||||
|
ISaleEstimateCreatingPayload,
|
||||||
|
ISaleEstimateDeletingPayload,
|
||||||
|
} from '@/modules/SaleEstimates/types/SaleEstimates.types';
|
||||||
|
import { ISaleEstimateEditingPayload } from '@/modules/SaleEstimates/types/SaleEstimates.types';
|
||||||
|
import { IRefundCreditNoteDeletingPayload } from '@/modules/CreditNoteRefunds/types/CreditNoteRefunds.types';
|
||||||
|
import { IRefundCreditNoteCreatingPayload } from '@/modules/CreditNoteRefunds/types/CreditNoteRefunds.types';
|
||||||
|
import {
|
||||||
|
ICreditNoteCreatingPayload,
|
||||||
|
ICreditNoteDeletingPayload,
|
||||||
|
} from '@/modules/CreditNotes/types/CreditNotes.types';
|
||||||
|
import { ICreditNoteEditingPayload } from '@/modules/CreditNotes/types/CreditNotes.types';
|
||||||
|
import {
|
||||||
|
ISaleReceiptCreatingPayload,
|
||||||
|
ISaleReceiptDeletingPayload,
|
||||||
|
ISaleReceiptEditingPayload,
|
||||||
|
} from '@/modules/SaleReceipts/types/SaleReceipts.types';
|
||||||
|
import { ISaleReceiptEventClosingPayload } from '@/modules/SaleReceipts/types/SaleReceipts.types';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SalesTransactionLockingGuardSubscriber {
|
||||||
|
constructor(
|
||||||
|
public readonly salesLockingGuard: SalesTransactionLockingGuard,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* SALES INVOICES.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on invoice creating.
|
||||||
|
* @param {ISaleInvoiceCreatingPaylaod} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleInvoice.onCreating)
|
||||||
|
public async transactionLockingGuardOnInvoiceCreating({
|
||||||
|
saleInvoiceDTO,
|
||||||
|
}: ISaleInvoiceCreatingPaylaod) {
|
||||||
|
// Can't continue if the new invoice is not published yet.
|
||||||
|
if (!saleInvoiceDTO.delivered) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
saleInvoiceDTO.invoiceDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on invoice editing.
|
||||||
|
* @param {ISaleInvoiceEditingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleInvoice.onEditing)
|
||||||
|
public async transactionLockingGuardOnInvoiceEditing({
|
||||||
|
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(
|
||||||
|
oldSaleInvoice.invoiceDate,
|
||||||
|
);
|
||||||
|
// Validate the new invoice date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
saleInvoiceDTO.invoiceDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on invoice deleting.
|
||||||
|
* @param {ISaleInvoiceDeletePayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleInvoice.onDelete)
|
||||||
|
public async transactionLockingGuardOnInvoiceDeleting({
|
||||||
|
oldSaleInvoice,
|
||||||
|
}: ISaleInvoiceDeletePayload) {
|
||||||
|
// Can't continue if the old invoice not published.
|
||||||
|
if (!oldSaleInvoice.isDelivered) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldSaleInvoice.invoiceDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on invoice writingoff.
|
||||||
|
* @param {ISaleInvoiceWriteoffCreatePayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleInvoice.onWriteoff)
|
||||||
|
public async transactionLockinGuardOnInvoiceWritingoff({
|
||||||
|
saleInvoice,
|
||||||
|
}: ISaleInvoiceWriteoffCreatePayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
saleInvoice.invoiceDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaciton locking guard on canceling written-off invoice.
|
||||||
|
* @param {ISaleInvoiceWrittenOffCancelPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleInvoice.onWrittenoffCancel)
|
||||||
|
public async transactionLockinGuardOnInvoiceWritingoffCanceling({
|
||||||
|
saleInvoice,
|
||||||
|
}: ISaleInvoiceWrittenOffCancelPayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
saleInvoice.invoiceDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* SALES RECEIPTS.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on receipt creating.
|
||||||
|
* @param {ISaleReceiptCreatingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleReceipt.onCreating)
|
||||||
|
public async transactionLockingGuardOnReceiptCreating({
|
||||||
|
saleReceiptDTO,
|
||||||
|
}: ISaleReceiptCreatingPayload) {
|
||||||
|
// Can't continue if the sale receipt is not published.
|
||||||
|
if (!saleReceiptDTO.closed) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
saleReceiptDTO.receiptDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on receipt creating.
|
||||||
|
* @param {ISaleReceiptDeletingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleReceipt.onDeleting)
|
||||||
|
public async transactionLockingGuardOnReceiptDeleting({
|
||||||
|
oldSaleReceipt,
|
||||||
|
}: ISaleReceiptDeletingPayload) {
|
||||||
|
if (!oldSaleReceipt.isClosed) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldSaleReceipt.receiptDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on sale receipt editing.
|
||||||
|
* @param {ISaleReceiptEditingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleReceipt.onEditing)
|
||||||
|
public async transactionLockingGuardOnReceiptEditing({
|
||||||
|
oldSaleReceipt,
|
||||||
|
saleReceiptDTO,
|
||||||
|
}: ISaleReceiptEditingPayload) {
|
||||||
|
// Validate the old receipt date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldSaleReceipt.receiptDate,
|
||||||
|
);
|
||||||
|
// Validate the new receipt date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
saleReceiptDTO.receiptDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on sale receipt closing.
|
||||||
|
* @param {ISaleReceiptEventClosingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleReceipt.onClosing)
|
||||||
|
public async transactionLockingGuardOnReceiptClosing({
|
||||||
|
oldSaleReceipt,
|
||||||
|
}: ISaleReceiptEventClosingPayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldSaleReceipt.receiptDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* CREDIT NOTES.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on credit note deleting.
|
||||||
|
* @param {ICreditNoteDeletingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.creditNote.onDeleting)
|
||||||
|
public async transactionLockingGuardOnCreditDeleting({
|
||||||
|
oldCreditNote,
|
||||||
|
}: ICreditNoteDeletingPayload) {
|
||||||
|
// Can't continue if the old credit is not published.
|
||||||
|
if (!oldCreditNote.isPublished) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldCreditNote.creditNoteDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on credit note creating.
|
||||||
|
* @param {ICreditNoteCreatingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.creditNote.onCreating)
|
||||||
|
public async transactionLockingGuardOnCreditCreating({
|
||||||
|
creditNoteDTO,
|
||||||
|
}: ICreditNoteCreatingPayload) {
|
||||||
|
// Can't continue if the new credit is still draft.
|
||||||
|
if (!creditNoteDTO.open) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
creditNoteDTO.creditNoteDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on credit note editing.
|
||||||
|
* @param {ICreditNoteEditingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.creditNote.onEditing)
|
||||||
|
public async transactionLockingGuardOnCreditEditing({
|
||||||
|
creditNoteEditDTO,
|
||||||
|
oldCreditNote,
|
||||||
|
}: 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(
|
||||||
|
oldCreditNote.creditNoteDate,
|
||||||
|
);
|
||||||
|
// Validate the new credit date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
creditNoteEditDTO.creditNoteDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment deleting.
|
||||||
|
* @param {IRefundCreditNoteDeletingPayload} paylaod -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.creditNote.onRefundDeleting)
|
||||||
|
public async transactionLockingGuardOnCreditRefundDeleteing({
|
||||||
|
oldRefundCredit,
|
||||||
|
}: IRefundCreditNoteDeletingPayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(oldRefundCredit.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on refund credit note creating.
|
||||||
|
* @param {IRefundCreditNoteCreatingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.creditNote.onRefundCreating)
|
||||||
|
public async transactionLockingGuardOnCreditRefundCreating({
|
||||||
|
newCreditNoteDTO,
|
||||||
|
}: IRefundCreditNoteCreatingPayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(newCreditNoteDTO.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* SALES ESTIMATES.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on estimate creating.
|
||||||
|
* @param {ISaleEstimateCreatingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleEstimate.onCreating)
|
||||||
|
public async transactionLockingGuardOnEstimateCreating({
|
||||||
|
estimateDTO,
|
||||||
|
}: ISaleEstimateCreatingPayload) {
|
||||||
|
// Can't continue if the new estimate is not published yet.
|
||||||
|
if (!estimateDTO.delivered) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
estimateDTO.estimateDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on estimate deleting.
|
||||||
|
* @param {ISaleEstimateDeletingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleEstimate.onDeleting)
|
||||||
|
public async transactionLockingGuardOnEstimateDeleting({
|
||||||
|
oldSaleEstimate,
|
||||||
|
}: ISaleEstimateDeletingPayload) {
|
||||||
|
// Can't continue if the old estimate is not published.
|
||||||
|
if (!oldSaleEstimate.isDelivered) return;
|
||||||
|
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldSaleEstimate.estimateDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on estimate editing.
|
||||||
|
* @param {ISaleEstimateEditingPayload} payload
|
||||||
|
*/
|
||||||
|
@OnEvent(events.saleEstimate.onEditing)
|
||||||
|
public async transactionLockingGuardOnEstimateEditing({
|
||||||
|
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(
|
||||||
|
oldSaleEstimate.estimateDate,
|
||||||
|
);
|
||||||
|
// Validate the new estimate date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
estimateDTO.estimateDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ---------------------------------------------
|
||||||
|
* PAYMENT RECEIVES.
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment receive editing.
|
||||||
|
* @param {IPaymentReceivedEditingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.paymentReceive.onEditing)
|
||||||
|
public async transactionLockingGuardOnPaymentEditing({
|
||||||
|
oldPaymentReceive,
|
||||||
|
paymentReceiveDTO,
|
||||||
|
}: IPaymentReceivedEditingPayload) {
|
||||||
|
// Validate the old payment date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldPaymentReceive.paymentDate,
|
||||||
|
);
|
||||||
|
// Validate the new payment date.
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
paymentReceiveDTO.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment creating.
|
||||||
|
* @param {IPaymentReceivedCreatingPayload}
|
||||||
|
*/
|
||||||
|
@OnEvent(events.paymentReceive.onCreating)
|
||||||
|
public async transactionLockingGuardOnPaymentCreating({
|
||||||
|
paymentReceiveDTO,
|
||||||
|
}: IPaymentReceivedCreatingPayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
paymentReceiveDTO.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction locking guard on payment deleting.
|
||||||
|
* @param {IPaymentReceivedDeletingPayload} payload -
|
||||||
|
*/
|
||||||
|
@OnEvent(events.paymentReceive.onDeleting)
|
||||||
|
public async transactionLockingGuardPaymentDeleting({
|
||||||
|
oldPaymentReceive,
|
||||||
|
}: IPaymentReceivedDeletingPayload) {
|
||||||
|
await this.salesLockingGuard.transactionLockingGuard(
|
||||||
|
oldPaymentReceive.paymentDate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
export interface ITransactionsLockingAllDTO {
|
||||||
|
lockToDate: Date;
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
export interface ITransactionsLockingCashflowDTO {}
|
||||||
|
export interface ITransactionsLockingSalesDTO {}
|
||||||
|
export interface ITransactionsLockingPurchasesDTO {}
|
||||||
|
|
||||||
|
export enum TransactionsLockingGroup {
|
||||||
|
All = 'all',
|
||||||
|
Sales = 'sales',
|
||||||
|
Purchases = 'purchases',
|
||||||
|
Financial = 'financial',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TransactionsLockingType {
|
||||||
|
Partial = 'partial',
|
||||||
|
All = 'all',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITransactionsLockingPartialUnlocked {
|
||||||
|
tenantId: number;
|
||||||
|
module: TransactionsLockingGroup;
|
||||||
|
transactionLockingDTO: ITransactionsLockingAllDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITransactionsLockingCanceled {
|
||||||
|
tenantId: number;
|
||||||
|
module: TransactionsLockingGroup;
|
||||||
|
cancelLockingDTO: ICancelTransactionsLockingDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITransactionLockingPartiallyDTO {
|
||||||
|
unlockFromDate: Date;
|
||||||
|
unlockToDate: Date;
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
export interface ICancelTransactionsLockingDTO {
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
export interface ITransactionMeta {
|
||||||
|
isEnabled: boolean;
|
||||||
|
isPartialUnlock: boolean;
|
||||||
|
lockToDate: Date;
|
||||||
|
unlockFromDate: string;
|
||||||
|
unlockToDate: string;
|
||||||
|
lockReason: string;
|
||||||
|
unlockReason: string;
|
||||||
|
partialUnlockReason: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITransactionLockingMetaPOJO {
|
||||||
|
module: string;
|
||||||
|
formattedModule: string;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
formattedLockToDate: Date;
|
||||||
|
formattedUnlockFromDate: string;
|
||||||
|
formattedunlockToDate: string;
|
||||||
|
}
|
||||||
|
export interface ITransactionsLockingListPOJO {
|
||||||
|
lockingType: string;
|
||||||
|
all: ITransactionLockingMetaPOJO;
|
||||||
|
modules: ITransactionLockingMetaPOJO[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITransactionsLockingSchema {
|
||||||
|
module: TransactionsLockingGroup;
|
||||||
|
formattedModule: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user