mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +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 { BankingMatchingModule } from '../BankingMatching/BankingMatching.module';
|
||||
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
||||
import { TransactionsLockingModule } from '../TransactionsLocking/TransactionsLocking.module';
|
||||
import { SettingsModule } from '../Settings/Settings.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -141,9 +143,11 @@ import { BankingTransactionsModule } from '../BankingTransactions/BankingTransac
|
||||
BankAccountsModule,
|
||||
BankRulesModule,
|
||||
BankingTransactionsModule,
|
||||
// BankingTransactionsExcludeModule,
|
||||
// BankingTransactionsRegonizeModule,
|
||||
// BankingMatchingModule,
|
||||
BankingTransactionsExcludeModule,
|
||||
BankingTransactionsRegonizeModule,
|
||||
BankingMatchingModule,
|
||||
TransactionsLockingModule,
|
||||
SettingsModule
|
||||
],
|
||||
controllers: [AppController],
|
||||
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