mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
Merge pull request #806 from bigcapitalhq/refactor-export-module
refactor(nestjs): export module
This commit is contained in:
8
packages/server/src/common/constants/http.constants.ts
Normal file
8
packages/server/src/common/constants/http.constants.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const ACCEPT_TYPE = {
|
||||||
|
APPLICATION_PDF: 'application/pdf',
|
||||||
|
APPLICATION_JSON: 'application/json',
|
||||||
|
APPLICATION_JSON_TABLE: 'application/json+table',
|
||||||
|
APPLICATION_XLSX: 'application/xlsx',
|
||||||
|
APPLICATION_CSV: 'application/csv',
|
||||||
|
APPLICATION_TEXT_HTML: 'application/json+html',
|
||||||
|
};
|
||||||
@@ -164,6 +164,7 @@ export interface IModelMetaRelationField2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IModelMetaField2 = IModelMetaFieldCommon2 &
|
export type IModelMetaField2 = IModelMetaFieldCommon2 &
|
||||||
|
IModelMetaFieldWithFields &
|
||||||
(
|
(
|
||||||
| IModelMetaFieldText
|
| IModelMetaFieldText
|
||||||
| IModelMetaFieldNumber
|
| IModelMetaFieldNumber
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
|||||||
import { BankAccount } from '../BankingTransactions/models/BankAccount';
|
import { BankAccount } from '../BankingTransactions/models/BankAccount';
|
||||||
import { GetAccountsService } from './GetAccounts.service';
|
import { GetAccountsService } from './GetAccounts.service';
|
||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
// import { GetAccountsService } from './GetAccounts.service';
|
import { AccountsExportable } from './AccountsExportable.service';
|
||||||
|
|
||||||
const models = [RegisterTenancyModel(BankAccount)];
|
const models = [RegisterTenancyModel(BankAccount)];
|
||||||
|
|
||||||
@@ -38,7 +38,13 @@ const models = [RegisterTenancyModel(BankAccount)];
|
|||||||
GetAccountTypesService,
|
GetAccountTypesService,
|
||||||
GetAccountTransactionsService,
|
GetAccountTransactionsService,
|
||||||
GetAccountsService,
|
GetAccountsService,
|
||||||
|
AccountsExportable,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
AccountRepository,
|
||||||
|
CreateAccountService,
|
||||||
|
...models,
|
||||||
|
AccountsExportable,
|
||||||
],
|
],
|
||||||
exports: [AccountRepository, CreateAccountService, ...models],
|
|
||||||
})
|
})
|
||||||
export class AccountsModule {}
|
export class AccountsModule {}
|
||||||
|
|||||||
@@ -2,8 +2,17 @@ import { AccountsApplication } from './AccountsApplication.service';
|
|||||||
import { Exportable } from '../Export/Exportable';
|
import { Exportable } from '../Export/Exportable';
|
||||||
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
||||||
import { IAccountsFilter, IAccountsStructureType } from './Accounts.types';
|
import { IAccountsFilter, IAccountsStructureType } from './Accounts.types';
|
||||||
|
import { Global, Injectable } from '@nestjs/common';
|
||||||
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
|
import { Account } from './models/Account.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@ExportableService({ name: Account.name })
|
||||||
|
@Global()
|
||||||
export class AccountsExportable extends Exportable {
|
export class AccountsExportable extends Exportable {
|
||||||
|
/**
|
||||||
|
* @param {AccountsApplication} accountsApplication
|
||||||
|
*/
|
||||||
constructor(private readonly accountsApplication: AccountsApplication) {
|
constructor(private readonly accountsApplication: AccountsApplication) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,43 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { IAccountCreateDTO } from '@/interfaces';
|
import { Importable } from '../Import/Importable';
|
||||||
// import { CreateAccount } from './CreateAccount.service';
|
import { AccountsSampleData } from './AccountsImportable.SampleData';
|
||||||
// import { Importable } from '../Import/Importable';
|
import { CreateAccountDTO } from './CreateAccount.dto';
|
||||||
// import { AccountsSampleData } from './AccountsImportable.SampleData';
|
import { CreateAccountService } from './CreateAccount.service';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class AccountsImportable extends Importable {
|
export class AccountsImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly createAccountService: CreateAccountService) {
|
||||||
// private createAccountService: CreateAccount;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {CreateAccountDTO} createAccountDTO - Create account dto.
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
* @returns
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public importable(
|
||||||
// public importable(
|
createAccountDTO: CreateAccountDTO,
|
||||||
// tenantId: number,
|
trx?: Knex.Transaction,
|
||||||
// createAccountDTO: IAccountCreateDTO,
|
) {
|
||||||
// trx?: Knex.Transaction
|
return this.createAccountService.createAccount(
|
||||||
// ) {
|
createAccountDTO,
|
||||||
// return this.createAccountService.createAccount(
|
trx,
|
||||||
// tenantId,
|
);
|
||||||
// createAccountDTO,
|
}
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return AccountsSampleData;
|
return AccountsSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
199
packages/server/src/modules/Accounts/models/Account.meta.ts
Normal file
199
packages/server/src/modules/Accounts/models/Account.meta.ts
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import { ACCOUNT_TYPES } from "../Accounts.constants";
|
||||||
|
|
||||||
|
export const AccountMeta = {
|
||||||
|
defaultFilterField: 'name',
|
||||||
|
defaultSort: {
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
sortField: 'name',
|
||||||
|
},
|
||||||
|
importable: true,
|
||||||
|
exportable: true,
|
||||||
|
print: {
|
||||||
|
pageTitle: 'Chart of Accounts',
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
name: 'account.field.name',
|
||||||
|
column: 'name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'account.field.description',
|
||||||
|
column: 'description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
slug: {
|
||||||
|
name: 'account.field.slug',
|
||||||
|
column: 'slug',
|
||||||
|
fieldType: 'text',
|
||||||
|
columnable: false,
|
||||||
|
filterable: false,
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
name: 'account.field.code',
|
||||||
|
column: 'code',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
root_type: {
|
||||||
|
name: 'account.field.root_type',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'asset', label: 'Asset' },
|
||||||
|
{ key: 'liability', label: 'Liability' },
|
||||||
|
{ key: 'equity', label: 'Equity' },
|
||||||
|
{ key: 'Income', label: 'Income' },
|
||||||
|
{ key: 'expense', label: 'Expense' },
|
||||||
|
],
|
||||||
|
filterCustomQuery: RootTypeFieldFilterQuery,
|
||||||
|
sortable: false,
|
||||||
|
},
|
||||||
|
normal: {
|
||||||
|
name: 'account.field.normal',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'debit', label: 'account.field.normal.debit' },
|
||||||
|
{ key: 'credit', label: 'account.field.normal.credit' },
|
||||||
|
],
|
||||||
|
filterCustomQuery: NormalTypeFieldFilterQuery,
|
||||||
|
sortable: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
name: 'account.field.type',
|
||||||
|
column: 'account_type',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: ACCOUNT_TYPES.map((accountType) => ({
|
||||||
|
label: accountType.label,
|
||||||
|
key: accountType.key,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'account.field.active',
|
||||||
|
column: 'active',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
filterable: false,
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
name: 'account.field.balance',
|
||||||
|
column: 'amount',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
currency: {
|
||||||
|
name: 'account.field.currency',
|
||||||
|
column: 'currency_code',
|
||||||
|
fieldType: 'text',
|
||||||
|
filterable: false,
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'account.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
name: {
|
||||||
|
name: 'account.field.name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
name: 'account.field.code',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
rootType: {
|
||||||
|
name: 'account.field.root_type',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'accountRootType',
|
||||||
|
},
|
||||||
|
accountType: {
|
||||||
|
name: 'account.field.type',
|
||||||
|
accessor: 'accountTypeLabel',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
accountNormal: {
|
||||||
|
name: 'account.field.normal',
|
||||||
|
accessor: 'accountNormalFormatted',
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'account.field.currency',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
bankBalance: {
|
||||||
|
name: 'account.field.bank_balance',
|
||||||
|
accessor: 'bankBalanceFormatted',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
name: 'account.field.balance',
|
||||||
|
accessor: 'formattedAmount',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'account.field.description',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'account.field.active',
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
name: 'account.field.created_at',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
name: {
|
||||||
|
name: 'account.field.name',
|
||||||
|
fieldType: 'text',
|
||||||
|
unique: true,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'account.field.description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
name: 'account.field.code',
|
||||||
|
fieldType: 'text',
|
||||||
|
minLength: 3,
|
||||||
|
maxLength: 6,
|
||||||
|
unique: true,
|
||||||
|
importHint: 'Unique number to identify the account.',
|
||||||
|
},
|
||||||
|
accountType: {
|
||||||
|
name: 'account.field.type',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: ACCOUNT_TYPES.map((accountType) => ({
|
||||||
|
label: accountType.label,
|
||||||
|
key: accountType.key,
|
||||||
|
})),
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'account.field.active',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'account.field.currency',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
parentAccountId: {
|
||||||
|
name: 'account.field.parent_account',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Account',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter query of root type field .
|
||||||
|
*/
|
||||||
|
function RootTypeFieldFilterQuery(query, role) {
|
||||||
|
query.modify('filterByRootType', role.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter query of normal field .
|
||||||
|
*/
|
||||||
|
function NormalTypeFieldFilterQuery(query, role) {
|
||||||
|
query.modify('filterByAccountNormal', role.value);
|
||||||
|
}
|
||||||
@@ -1,26 +1,21 @@
|
|||||||
/* eslint-disable global-require */
|
/* eslint-disable global-require */
|
||||||
// import { mixin, Model } from 'objection';
|
|
||||||
import { castArray } from 'lodash';
|
import { castArray } from 'lodash';
|
||||||
|
import { Model } from 'objection';
|
||||||
import DependencyGraph from '@/libs/dependency-graph';
|
import DependencyGraph from '@/libs/dependency-graph';
|
||||||
import {
|
import {
|
||||||
ACCOUNT_TYPES,
|
ACCOUNT_TYPES,
|
||||||
getAccountsSupportsMultiCurrency,
|
getAccountsSupportsMultiCurrency,
|
||||||
} from '@/constants/accounts';
|
} from '@/constants/accounts';
|
||||||
import { TenantModel } from '@/modules/System/models/TenantModel';
|
|
||||||
// import { SearchableModel } from '@/modules/Search/SearchableMdel';
|
|
||||||
// import { CustomViewBaseModel } from '@/modules/CustomViews/CustomViewBaseModel';
|
|
||||||
// import { ModelSettings } from '@/modules/Settings/ModelSettings';
|
|
||||||
import { AccountTypesUtils } from '@/libs/accounts-utils/AccountTypesUtils';
|
import { AccountTypesUtils } from '@/libs/accounts-utils/AccountTypesUtils';
|
||||||
import { Model } from 'objection';
|
|
||||||
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
|
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
||||||
// import AccountSettings from './Account.Settings';
|
import { ExportableModel } from '../../Export/decorators/ExportableModel.decorator';
|
||||||
// import { DEFAULT_VIEWS } from '@/modules/Accounts/constants';
|
import { AccountMeta } from './Account.meta';
|
||||||
// import { buildFilterQuery, buildSortColumnQuery } from '@/lib/ViewRolesBuilder';
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
// import { flatToNestedArray } from 'utils';
|
|
||||||
|
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
|
@InjectModelMeta(AccountMeta)
|
||||||
export class Account extends TenantBaseModel {
|
export class Account extends TenantBaseModel {
|
||||||
public name!: string;
|
public name!: string;
|
||||||
public slug!: string;
|
public slug!: string;
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ import { TenancyModule } from '../Tenancy/Tenancy.module';
|
|||||||
import { LoopsModule } from '../Loops/Loops.module';
|
import { LoopsModule } from '../Loops/Loops.module';
|
||||||
import { AttachmentsModule } from '../Attachments/Attachment.module';
|
import { AttachmentsModule } from '../Attachments/Attachment.module';
|
||||||
import { S3Module } from '../S3/S3.module';
|
import { S3Module } from '../S3/S3.module';
|
||||||
|
import { ExportModule } from '../Export/Export.module';
|
||||||
|
import { ImportModule } from '../Import/Import.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -192,7 +194,9 @@ import { S3Module } from '../S3/S3.module';
|
|||||||
PaymentServicesModule,
|
PaymentServicesModule,
|
||||||
LoopsModule,
|
LoopsModule,
|
||||||
AttachmentsModule,
|
AttachmentsModule,
|
||||||
S3Module
|
S3Module,
|
||||||
|
ExportModule,
|
||||||
|
ImportModule
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ import { CreateUncategorizedTransactionService } from './commands/CreateUncatego
|
|||||||
import { CategorizeTransactionAsExpense } from './commands/CategorizeTransactionAsExpense';
|
import { CategorizeTransactionAsExpense } from './commands/CategorizeTransactionAsExpense';
|
||||||
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
import { BankingTransactionsModule } from '../BankingTransactions/BankingTransactions.module';
|
||||||
import { ExpensesModule } from '../Expenses/Expenses.module';
|
import { ExpensesModule } from '../Expenses/Expenses.module';
|
||||||
|
import { UncategorizedTransactionsImportable } from './commands/UncategorizedTransactionsImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [BankingTransactionsModule, ExpensesModule],
|
imports: [BankingTransactionsModule, ExpensesModule],
|
||||||
providers: [
|
providers: [
|
||||||
CreateUncategorizedTransactionService,
|
CreateUncategorizedTransactionService,
|
||||||
CategorizeTransactionAsExpense,
|
CategorizeTransactionAsExpense,
|
||||||
|
UncategorizedTransactionsImportable
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CreateUncategorizedTransactionService,
|
CreateUncategorizedTransactionService,
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import { BillPaymentGLEntries } from './commands/BillPaymentGLEntries';
|
|||||||
import { BillPaymentGLEntriesSubscriber } from './subscribers/BillPaymentGLEntriesSubscriber';
|
import { BillPaymentGLEntriesSubscriber } from './subscribers/BillPaymentGLEntriesSubscriber';
|
||||||
import { LedgerModule } from '../Ledger/Ledger.module';
|
import { LedgerModule } from '../Ledger/Ledger.module';
|
||||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||||
|
import { BillPaymentsExportable } from './queries/BillPaymentsExportable';
|
||||||
|
import { GetBillPayments } from '../Bills/queries/GetBillPayments';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [LedgerModule, AccountsModule],
|
imports: [LedgerModule, AccountsModule],
|
||||||
@@ -34,6 +36,8 @@ import { AccountsModule } from '../Accounts/Accounts.module';
|
|||||||
TenancyContext,
|
TenancyContext,
|
||||||
BillPaymentGLEntries,
|
BillPaymentGLEntries,
|
||||||
BillPaymentGLEntriesSubscriber,
|
BillPaymentGLEntriesSubscriber,
|
||||||
|
GetBillPayments,
|
||||||
|
BillPaymentsExportable
|
||||||
],
|
],
|
||||||
exports: [BillPaymentValidators, CreateBillPaymentService],
|
exports: [BillPaymentValidators, CreateBillPaymentService],
|
||||||
controllers: [BillPaymentsController],
|
controllers: [BillPaymentsController],
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ export class BillPaymentsApplication {
|
|||||||
private deleteBillPaymentService: DeleteBillPayment,
|
private deleteBillPaymentService: DeleteBillPayment,
|
||||||
private getBillPaymentService: GetBillPayment,
|
private getBillPaymentService: GetBillPayment,
|
||||||
private getPaymentBillsService: GetPaymentBills,
|
private getPaymentBillsService: GetPaymentBills,
|
||||||
// private getBillPaymentsService: GetBillPayments,
|
private getBillPaymentsService: GetBillPayments,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a bill payment with associated GL entries.
|
* Creates a bill payment with associated GL entries.
|
||||||
* @param {IBillPaymentDTO} billPaymentDTO
|
* @param {IBillPaymentDTO} billPaymentDTO - Create bill payment dto.
|
||||||
* @returns {Promise<IBillPayment>}
|
* @returns {Promise<IBillPayment>}
|
||||||
*/
|
*/
|
||||||
public createBillPayment(billPaymentDTO: CreateBillPaymentDto) {
|
public createBillPayment(billPaymentDTO: CreateBillPaymentDto) {
|
||||||
@@ -34,7 +34,7 @@ export class BillPaymentsApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Delets the given bill payment with associated GL entries.
|
* Delets the given bill payment with associated GL entries.
|
||||||
* @param {number} billPaymentId
|
* @param {number} billPaymentId - Bill payment id.
|
||||||
*/
|
*/
|
||||||
public deleteBillPayment(billPaymentId: number) {
|
public deleteBillPayment(billPaymentId: number) {
|
||||||
return this.deleteBillPaymentService.deleteBillPayment(billPaymentId);
|
return this.deleteBillPaymentService.deleteBillPayment(billPaymentId);
|
||||||
@@ -58,13 +58,10 @@ export class BillPaymentsApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves bill payments list.
|
* Retrieves bill payments list.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param filterDTO
|
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
// public getBillPayments(filterDTO: IBillPaymentsFilter) {
|
public getBillPayments() {
|
||||||
// return this.getBillPaymentsService.getBillPayments(filterDTO);
|
// return this.getBillPaymentsService.getBillPayments(filterDTO);
|
||||||
// }
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve specific bill payment.
|
* Retrieve specific bill payment.
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
|
||||||
// import { BillPaymentsApplication } from './BillPaymentsApplication';
|
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
|
||||||
|
|
||||||
// @Service()
|
|
||||||
// export class BillPaymentExportable extends Exportable {
|
|
||||||
// @Inject()
|
|
||||||
// private billPaymentsApplication: BillPaymentsApplication;
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
|
||||||
// * @param {number} tenantId
|
|
||||||
// * @returns
|
|
||||||
// */
|
|
||||||
// public exportable(tenantId: number, query: any) {
|
|
||||||
// const filterQuery = (builder) => {
|
|
||||||
// builder.withGraphFetched('entries.bill');
|
|
||||||
// builder.withGraphFetched('branch');
|
|
||||||
// };
|
|
||||||
// const parsedQuery = {
|
|
||||||
// sortOrder: 'desc',
|
|
||||||
// columnSortBy: 'created_at',
|
|
||||||
// ...query,
|
|
||||||
// page: 1,
|
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
|
||||||
// filterQuery
|
|
||||||
// } as any;
|
|
||||||
|
|
||||||
// return this.billPaymentsApplication
|
|
||||||
// .getBillPayments(tenantId, parsedQuery)
|
|
||||||
// .then((output) => output.billPayments);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { BillPaymentsApplication } from "../BillPaymentsApplication.service";
|
||||||
|
import { Exportable } from "@/modules/Export/Exportable";
|
||||||
|
import { EXPORT_SIZE_LIMIT } from "@/modules/Export/constants";
|
||||||
|
import { ExportableService } from "@/modules/Export/decorators/ExportableModel.decorator";
|
||||||
|
import { BillPayment } from "../models/BillPayment";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@ExportableService({ name: BillPayment.name })
|
||||||
|
export class BillPaymentsExportable extends Exportable {
|
||||||
|
constructor(
|
||||||
|
private readonly billPaymentsApplication: BillPaymentsApplication
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the accounts data to exportable sheet.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async exportable(query: any) {
|
||||||
|
const filterQuery = (builder) => {
|
||||||
|
builder.withGraphFetched('entries.bill');
|
||||||
|
builder.withGraphFetched('branch');
|
||||||
|
};
|
||||||
|
const parsedQuery = {
|
||||||
|
sortOrder: 'desc',
|
||||||
|
columnSortBy: 'created_at',
|
||||||
|
...query,
|
||||||
|
page: 1,
|
||||||
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
|
filterQuery
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
return [];
|
||||||
|
|
||||||
|
// return this.billPaymentsApplication
|
||||||
|
// .billPayments(tenantId, parsedQuery)
|
||||||
|
// .then((output) => output.billPayments);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,8 @@ import { BillInventoryTransactions } from './commands/BillInventoryTransactions'
|
|||||||
import { GetBillsService } from './queries/GetBills.service';
|
import { GetBillsService } from './queries/GetBills.service';
|
||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
||||||
|
import { BillsExportable } from './commands/BillsExportable';
|
||||||
|
import { BillsImportable } from './commands/BillsImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -57,7 +59,10 @@ import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
|||||||
BillGLEntriesSubscriber,
|
BillGLEntriesSubscriber,
|
||||||
BillInventoryTransactions,
|
BillInventoryTransactions,
|
||||||
BillWriteInventoryTransactionsSubscriber,
|
BillWriteInventoryTransactionsSubscriber,
|
||||||
|
BillsExportable,
|
||||||
|
BillsImportable
|
||||||
],
|
],
|
||||||
controllers: [BillsController],
|
controllers: [BillsController],
|
||||||
|
exports: [BillsExportable, BillsImportable],
|
||||||
})
|
})
|
||||||
export class BillsModule {}
|
export class BillsModule {}
|
||||||
|
|||||||
@@ -1,37 +1,38 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { BillsApplication } from '../Bills.application';
|
||||||
// import { IBillsFilter } from '@/interfaces';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { Exportable } from '@/modules/Export/Exportable';
|
||||||
// import { BillsApplication } from '../Bills.application';
|
import { IBillsFilter } from '../Bills.types';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
|
||||||
// import Objection from 'objection';
|
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { Bill } from '../models/Bill';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class BillsExportable extends Exportable {
|
@ExportableService({ name: Bill.name })
|
||||||
// @Inject()
|
export class BillsExportable extends Exportable {
|
||||||
// private billsApplication: BillsApplication;
|
constructor(private readonly billsApplication: BillsApplication) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
*/
|
||||||
// * @returns
|
public exportable(query: IBillsFilter) {
|
||||||
// */
|
const filterQuery = (query) => {
|
||||||
// public exportable(tenantId: number, query: IBillsFilter) {
|
query.withGraphFetched('branch');
|
||||||
// const filterQuery = (query) => {
|
query.withGraphFetched('warehouse');
|
||||||
// query.withGraphFetched('branch');
|
};
|
||||||
// query.withGraphFetched('warehouse');
|
const parsedQuery = {
|
||||||
// };
|
sortOrder: 'desc',
|
||||||
// const parsedQuery = {
|
columnSortBy: 'created_at',
|
||||||
// sortOrder: 'desc',
|
...query,
|
||||||
// columnSortBy: 'created_at',
|
page: 1,
|
||||||
// ...query,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// page: 1,
|
filterQuery,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
} as IBillsFilter;
|
||||||
// filterQuery,
|
|
||||||
// } as IBillsFilter;
|
|
||||||
|
|
||||||
// return this.billsApplication
|
return this.billsApplication
|
||||||
// .getBills(tenantId, parsedQuery)
|
.getBills(parsedQuery)
|
||||||
// .then((output) => output.bills);
|
.then((output) => output.bills);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,46 +1,46 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { CreateBill } from './CreateBill.service';
|
||||||
// import { Importable } from '@/services/Import/Importable';
|
import { BillsSampleData } from '../Bills.constants';
|
||||||
// import { CreateBill } from './CreateBill.service';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { IBillDTO } from '@/interfaces';
|
import { Importable } from '@/modules/Import/Importable';
|
||||||
// import { BillsSampleData } from '../Bills.constants';
|
import { CreateBillDto } from '../dtos/Bill.dto';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class BillsImportable extends Importable {
|
export class BillsImportable extends Importable {
|
||||||
// @Inject()
|
constructor(
|
||||||
// private createBillService: CreateBill;
|
private readonly createBillService: CreateBill,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {number} tenantId
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
* @param {IAccountCreateDTO} createAccountDTO
|
||||||
// * @returns
|
* @returns
|
||||||
// */
|
*/
|
||||||
// public importable(
|
public importable(
|
||||||
// tenantId: number,
|
createBillDto: CreateBillDto,
|
||||||
// createAccountDTO: IBillDTO,
|
trx?: Knex.Transaction
|
||||||
// trx?: Knex.Transaction
|
) {
|
||||||
// ) {
|
return this.createBillService.createBill(
|
||||||
// return this.createBillService.createBill(
|
createBillDto,
|
||||||
// tenantId,
|
trx
|
||||||
// createAccountDTO,
|
);
|
||||||
// {},
|
}
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return BillsSampleData;
|
return BillsSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
286
packages/server/src/modules/Bills/models/Bill.meta.ts
Normal file
286
packages/server/src/modules/Bills/models/Bill.meta.ts
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
import { Features } from "@/common/types/Features";
|
||||||
|
|
||||||
|
export const BillMeta = {
|
||||||
|
defaultFilterField: 'vendor',
|
||||||
|
defaultSort: {
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
sortField: 'bill_date',
|
||||||
|
},
|
||||||
|
importable: true,
|
||||||
|
exportFlattenOn: 'entries',
|
||||||
|
exportable: true,
|
||||||
|
importAggregator: 'group',
|
||||||
|
importAggregateOn: 'entries',
|
||||||
|
importAggregateBy: 'billNumber',
|
||||||
|
print: {
|
||||||
|
pageTitle: 'Bills',
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
vendor: {
|
||||||
|
name: 'bill.field.vendor',
|
||||||
|
column: 'vendor_id',
|
||||||
|
fieldType: 'relation',
|
||||||
|
|
||||||
|
relationType: 'enumeration',
|
||||||
|
relationKey: 'vendor',
|
||||||
|
|
||||||
|
relationEntityLabel: 'display_name',
|
||||||
|
relationEntityKey: 'id',
|
||||||
|
},
|
||||||
|
bill_number: {
|
||||||
|
name: 'bill.field.bill_number',
|
||||||
|
column: 'bill_number',
|
||||||
|
columnable: true,
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
bill_date: {
|
||||||
|
name: 'bill.field.bill_date',
|
||||||
|
column: 'bill_date',
|
||||||
|
columnable: true,
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
due_date: {
|
||||||
|
name: 'bill.field.due_date',
|
||||||
|
column: 'due_date',
|
||||||
|
columnable: true,
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
reference_no: {
|
||||||
|
name: 'bill.field.reference_no',
|
||||||
|
column: 'reference_no',
|
||||||
|
columnable: true,
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
name: 'bill.field.status',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
columnable: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'bill.field.status.paid', key: 'paid' },
|
||||||
|
{ label: 'bill.field.status.partially-paid', key: 'partially-paid' },
|
||||||
|
{ label: 'bill.field.status.overdue', key: 'overdue' },
|
||||||
|
{ label: 'bill.field.status.unpaid', key: 'unpaid' },
|
||||||
|
{ label: 'bill.field.status.opened', key: 'opened' },
|
||||||
|
{ label: 'bill.field.status.draft', key: 'draft' },
|
||||||
|
],
|
||||||
|
filterCustomQuery: StatusFieldFilterQuery,
|
||||||
|
sortCustomQuery: StatusFieldSortQuery,
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'bill.field.amount',
|
||||||
|
column: 'amount',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
payment_amount: {
|
||||||
|
name: 'bill.field.payment_amount',
|
||||||
|
column: 'payment_amount',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'bill.field.note',
|
||||||
|
column: 'note',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'bill.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
billDate: {
|
||||||
|
name: 'Date',
|
||||||
|
accessor: 'formattedBillDate',
|
||||||
|
},
|
||||||
|
billNumber: {
|
||||||
|
name: 'Bill No.',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
referenceNo: {
|
||||||
|
name: 'Reference No.',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
dueDate: {
|
||||||
|
name: 'Due Date',
|
||||||
|
type: 'date',
|
||||||
|
accessor: 'formattedDueDate',
|
||||||
|
},
|
||||||
|
vendorId: {
|
||||||
|
name: 'Vendor',
|
||||||
|
accessor: 'vendor.displayName',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'Amount',
|
||||||
|
accessor: 'formattedAmount',
|
||||||
|
},
|
||||||
|
exchangeRate: {
|
||||||
|
name: 'Exchange Rate',
|
||||||
|
type: 'number',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'Currency Code',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
dueAmount: {
|
||||||
|
name: 'Due Amount',
|
||||||
|
accessor: 'formattedDueAmount',
|
||||||
|
},
|
||||||
|
paidAmount: {
|
||||||
|
name: 'Paid Amount',
|
||||||
|
accessor: 'formattedPaymentAmount',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'Note',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
open: {
|
||||||
|
name: 'Open',
|
||||||
|
type: 'boolean',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
name: 'Entries',
|
||||||
|
accessor: 'entries',
|
||||||
|
type: 'collection',
|
||||||
|
collectionOf: 'object',
|
||||||
|
columns: {
|
||||||
|
itemName: {
|
||||||
|
name: 'Item Name',
|
||||||
|
accessor: 'item.name',
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
name: 'Item Rate',
|
||||||
|
accessor: 'rateFormatted',
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
name: 'Item Quantity',
|
||||||
|
accessor: 'quantityFormatted',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'Item Description',
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'Item Amount',
|
||||||
|
accessor: 'totalFormatted',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
branch: {
|
||||||
|
name: 'Branch',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'branch.name',
|
||||||
|
features: [Features.BRANCHES],
|
||||||
|
},
|
||||||
|
warehouse: {
|
||||||
|
name: 'Warehouse',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'warehouse.name',
|
||||||
|
features: [Features.BRANCHES],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
billNumber: {
|
||||||
|
name: 'Bill No.',
|
||||||
|
fieldType: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
referenceNo: {
|
||||||
|
name: 'Reference No.',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billDate: {
|
||||||
|
name: 'Date',
|
||||||
|
fieldType: 'date',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
dueDate: {
|
||||||
|
name: 'Due Date',
|
||||||
|
fieldType: 'date',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
vendorId: {
|
||||||
|
name: 'Vendor',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Contact',
|
||||||
|
relationImportMatch: 'displayName',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
exchangeRate: {
|
||||||
|
name: 'Exchange Rate',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'Note',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
open: {
|
||||||
|
name: 'Open',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
name: 'Entries',
|
||||||
|
fieldType: 'collection',
|
||||||
|
collectionOf: 'object',
|
||||||
|
collectionMinLength: 1,
|
||||||
|
required: true,
|
||||||
|
fields: {
|
||||||
|
itemId: {
|
||||||
|
name: 'Item',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Item',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
required: true,
|
||||||
|
importHint: 'Matches the item name or code.',
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
name: 'Rate',
|
||||||
|
fieldType: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
name: 'Quantity',
|
||||||
|
fieldType: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'Line Description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
branchId: {
|
||||||
|
name: 'Branch',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Branch',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
features: [Features.BRANCHES],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
warehouseId: {
|
||||||
|
name: 'Warehouse',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Warehouse',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
features: [Features.WAREHOUSES],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status field filter custom query.
|
||||||
|
*/
|
||||||
|
function StatusFieldFilterQuery(query, role) {
|
||||||
|
query.modify('statusFilter', role.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status field sort custom query.
|
||||||
|
*/
|
||||||
|
function StatusFieldSortQuery(query, role) {
|
||||||
|
query.modify('sortByStatus', role.order);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Model, raw, mixin } from 'objection';
|
import type { Knex } from 'knex';
|
||||||
|
import { Model, raw } from 'objection';
|
||||||
import { castArray, difference, defaultTo } from 'lodash';
|
import { castArray, difference, defaultTo } from 'lodash';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
@@ -12,9 +13,13 @@ import { BaseModel, PaginationQueryBuilderType } from '@/models/Model';
|
|||||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||||
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost';
|
||||||
import { DiscountType } from '@/common/types/Discount';
|
import { DiscountType } from '@/common/types/Discount';
|
||||||
import type { Knex, QueryBuilder } from 'knex';
|
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { BillMeta } from './Bill.meta';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
|
@InjectModelMeta(BillMeta)
|
||||||
export class Bill extends TenantBaseModel {
|
export class Bill extends TenantBaseModel {
|
||||||
public amount: number;
|
public amount: number;
|
||||||
public paymentAmount: number;
|
public paymentAmount: number;
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ export class GetBillPayments {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the specific bill associated payment transactions.
|
* Retrieve the specific bill associated payment transactions.
|
||||||
* @param {number} billId
|
* @param {number} billId - Bill id.
|
||||||
* @returns {}
|
|
||||||
*/
|
*/
|
||||||
public getBillPayments = async (billId: number) => {
|
public getBillPayments = async (billId: number) => {
|
||||||
const billsEntries = await this.billPaymentEntryModel
|
const billsEntries = await this.billPaymentEntryModel
|
||||||
|
|||||||
11
packages/server/src/modules/Branches/models/Branch.meta.ts
Normal file
11
packages/server/src/modules/Branches/models/Branch.meta.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export const BranchMeta = {
|
||||||
|
fields2: {
|
||||||
|
name: {
|
||||||
|
name: 'Name',
|
||||||
|
fieldType: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {},
|
||||||
|
fields: {}
|
||||||
|
};
|
||||||
@@ -3,7 +3,10 @@
|
|||||||
// import BranchMetadata from './Branch.settings';
|
// import BranchMetadata from './Branch.settings';
|
||||||
// import ModelSetting from './ModelSetting';
|
// import ModelSetting from './ModelSetting';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { BranchMeta } from './Branch.meta';
|
||||||
|
|
||||||
|
@InjectModelMeta(BranchMeta)
|
||||||
export class Branch extends BaseModel{
|
export class Branch extends BaseModel{
|
||||||
name!: string;
|
name!: string;
|
||||||
code!: string;
|
code!: string;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { LedgerModule } from '../Ledger/Ledger.module';
|
|||||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||||
import { GetCreditNotesService } from './queries/GetCreditNotes.service';
|
import { GetCreditNotesService } from './queries/GetCreditNotes.service';
|
||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
|
import { CreditNotesExportable } from './commands/CreditNotesExportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -36,7 +37,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
AutoIncrementOrdersModule,
|
AutoIncrementOrdersModule,
|
||||||
LedgerModule,
|
LedgerModule,
|
||||||
AccountsModule,
|
AccountsModule,
|
||||||
DynamicListModule
|
DynamicListModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
CreateCreditNoteService,
|
CreateCreditNoteService,
|
||||||
@@ -53,6 +54,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
CreditNoteBrandingTemplate,
|
CreditNoteBrandingTemplate,
|
||||||
CreditNoteGLEntries,
|
CreditNoteGLEntries,
|
||||||
CreditNoteGLEntriesSubscriber,
|
CreditNoteGLEntriesSubscriber,
|
||||||
|
CreditNotesExportable,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CreateCreditNoteService,
|
CreateCreditNoteService,
|
||||||
@@ -66,6 +68,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
GetCreditNoteState,
|
GetCreditNoteState,
|
||||||
CreditNoteApplication,
|
CreditNoteApplication,
|
||||||
CreditNoteBrandingTemplate,
|
CreditNoteBrandingTemplate,
|
||||||
|
CreditNotesExportable,
|
||||||
],
|
],
|
||||||
controllers: [CreditNotesController],
|
controllers: [CreditNotesController],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,35 +1,37 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Exportable } from '@/modules/Export/Exportable';
|
||||||
// import { ICreditNotesQueryDTO } from '@/interfaces';
|
import { CreditNoteApplication } from '../CreditNoteApplication.service';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import ListCreditNotes from '../ListCreditNotes';
|
import { ICreditNotesQueryDTO } from '../types/CreditNotes.types';
|
||||||
|
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { CreditNote } from '../models/CreditNote';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class CreditNotesExportable extends Exportable {
|
@ExportableService({ name: CreditNote.name })
|
||||||
// @Inject()
|
export class CreditNotesExportable extends Exportable {
|
||||||
// private getCreditNotes: ListCreditNotes;
|
constructor(private readonly creditNotesApp: CreditNoteApplication) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId -
|
* @param {IVendorCreditsQueryDTO} query -
|
||||||
// * @param {IVendorCreditsQueryDTO} query -
|
*/
|
||||||
// * @returns {}
|
public exportable(query: ICreditNotesQueryDTO) {
|
||||||
// */
|
const filterQuery = (query) => {
|
||||||
// public exportable(tenantId: number, query: ICreditNotesQueryDTO) {
|
query.withGraphFetched('branch');
|
||||||
// const filterQuery = (query) => {
|
query.withGraphFetched('warehouse');
|
||||||
// query.withGraphFetched('branch');
|
};
|
||||||
// query.withGraphFetched('warehouse');
|
const parsedQuery = {
|
||||||
// };
|
sortOrder: 'desc',
|
||||||
// const parsedQuery = {
|
columnSortBy: 'created_at',
|
||||||
// sortOrder: 'desc',
|
...query,
|
||||||
// columnSortBy: 'created_at',
|
page: 1,
|
||||||
// ...query,
|
pageSize: 12000,
|
||||||
// page: 1,
|
filterQuery,
|
||||||
// pageSize: 12000,
|
} as ICreditNotesQueryDTO;
|
||||||
// filterQuery,
|
|
||||||
// } as ICreditNotesQueryDTO;
|
|
||||||
|
|
||||||
// return this.getCreditNotes
|
return this.creditNotesApp
|
||||||
// .getCreditNotesList(tenantId, parsedQuery)
|
.getCreditNotes(parsedQuery)
|
||||||
// .then((output) => output.creditNotes);
|
.then((output) => output.creditNotes);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import { DiscountType } from '@/common/types/Discount';
|
|||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
import { Branch } from '@/modules/Branches/models/Branch.model';
|
import { Branch } from '@/modules/Branches/models/Branch.model';
|
||||||
import { Customer } from '@/modules/Customers/models/Customer';
|
import { Customer } from '@/modules/Customers/models/Customer';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||||
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
|
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
|
||||||
import { mixin, Model, raw } from 'objection';
|
import { mixin, Model, raw } from 'objection';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
export class CreditNote extends TenantBaseModel {
|
export class CreditNote extends TenantBaseModel {
|
||||||
public amount: number;
|
public amount: number;
|
||||||
public exchangeRate: number;
|
public exchangeRate: number;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||||
@@ -7,8 +8,6 @@ import {
|
|||||||
} from '../types/CreditNotes.types';
|
} from '../types/CreditNotes.types';
|
||||||
import { CreditNote } from '../models/CreditNote';
|
import { CreditNote } from '../models/CreditNote';
|
||||||
import { CreditNoteTransformer } from './CreditNoteTransformer';
|
import { CreditNoteTransformer } from './CreditNoteTransformer';
|
||||||
import { Inject } from '@nestjs/common';
|
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@@ -12,9 +12,13 @@ import { CreateEditCustomerDTO } from './commands/CreateEditCustomerDTO.service'
|
|||||||
import { CustomersController } from './Customers.controller';
|
import { CustomersController } from './Customers.controller';
|
||||||
import { CustomersApplication } from './CustomersApplication.service';
|
import { CustomersApplication } from './CustomersApplication.service';
|
||||||
import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
||||||
|
import { CustomersExportable } from './CustomersExportable';
|
||||||
|
import { CustomersImportable } from './CustomersImportable';
|
||||||
|
import { GetCustomers } from './queries/GetCustomers.service';
|
||||||
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule, DynamicListModule],
|
||||||
controllers: [CustomersController],
|
controllers: [CustomersController],
|
||||||
providers: [
|
providers: [
|
||||||
ActivateCustomer,
|
ActivateCustomer,
|
||||||
@@ -29,7 +33,10 @@ import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
|||||||
DeleteCustomer,
|
DeleteCustomer,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
GetCustomerService
|
GetCustomerService,
|
||||||
|
CustomersExportable,
|
||||||
|
CustomersImportable,
|
||||||
|
GetCustomers
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CustomersModule {}
|
export class CustomersModule {}
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import { CreateCustomer } from './commands/CreateCustomer.service';
|
|||||||
import { EditCustomer } from './commands/EditCustomer.service';
|
import { EditCustomer } from './commands/EditCustomer.service';
|
||||||
import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
||||||
import { EditOpeningBalanceCustomer } from './commands/EditOpeningBalanceCustomer.service';
|
import { EditOpeningBalanceCustomer } from './commands/EditOpeningBalanceCustomer.service';
|
||||||
import { ICustomerOpeningBalanceEditDTO } from './types/Customers.types';
|
import { ICustomerOpeningBalanceEditDTO, ICustomersFilter } from './types/Customers.types';
|
||||||
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||||
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
||||||
|
import { GetCustomers } from './queries/GetCustomers.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CustomersApplication {
|
export class CustomersApplication {
|
||||||
@@ -16,13 +17,12 @@ export class CustomersApplication {
|
|||||||
private editCustomerService: EditCustomer,
|
private editCustomerService: EditCustomer,
|
||||||
private deleteCustomerService: DeleteCustomer,
|
private deleteCustomerService: DeleteCustomer,
|
||||||
private editOpeningBalanceService: EditOpeningBalanceCustomer,
|
private editOpeningBalanceService: EditOpeningBalanceCustomer,
|
||||||
// private getCustomersService: GetCustomers,
|
private getCustomersService: GetCustomers,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the given customer details.
|
* Retrieves the given customer details.
|
||||||
* @param {number} tenantId
|
* @param {number} customerId - Customer id.
|
||||||
* @param {number} customerId
|
|
||||||
*/
|
*/
|
||||||
public getCustomer = (customerId: number) => {
|
public getCustomer = (customerId: number) => {
|
||||||
return this.getCustomerService.getCustomer(customerId);
|
return this.getCustomerService.getCustomer(customerId);
|
||||||
@@ -30,7 +30,7 @@ export class CustomersApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new customer.
|
* Creates a new customer.
|
||||||
* @param {ICustomerNewDTO} customerDTO
|
* @param {ICustomerNewDTO} customerDTO - Create customer dto.
|
||||||
* @returns {Promise<ICustomer>}
|
* @returns {Promise<ICustomer>}
|
||||||
*/
|
*/
|
||||||
public createCustomer = (customerDTO: CreateCustomerDto) => {
|
public createCustomer = (customerDTO: CreateCustomerDto) => {
|
||||||
@@ -49,9 +49,7 @@ export class CustomersApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the given customer and associated transactions.
|
* Deletes the given customer and associated transactions.
|
||||||
* @param {number} tenantId
|
* @param {number} customerId - Customer id.
|
||||||
* @param {number} customerId
|
|
||||||
* @param {ISystemUser} authorizedUser
|
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public deleteCustomer = (customerId: number) => {
|
public deleteCustomer = (customerId: number) => {
|
||||||
@@ -60,9 +58,8 @@ export class CustomersApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the opening balance of the given customer.
|
* Changes the opening balance of the given customer.
|
||||||
* @param {number} tenantId
|
* @param {number} customerId - Customer id.
|
||||||
* @param {number} customerId
|
* @param {Date|string} openingBalanceEditDTO - Opening balance edit dto.
|
||||||
* @param {Date|string} openingBalanceEditDTO
|
|
||||||
* @returns {Promise<ICustomer>}
|
* @returns {Promise<ICustomer>}
|
||||||
*/
|
*/
|
||||||
public editOpeningBalance = (
|
public editOpeningBalance = (
|
||||||
@@ -77,10 +74,9 @@ export class CustomersApplication {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve customers paginated list.
|
* Retrieve customers paginated list.
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {ICustomersFilter} filter - Cusotmers filter.
|
* @param {ICustomersFilter} filter - Cusotmers filter.
|
||||||
*/
|
*/
|
||||||
// public getCustomers = (filterDTO: ICustomersFilter) => {
|
public getCustomers = (filterDTO: ICustomersFilter) => {
|
||||||
// return this.getCustomersService.getCustomersList(filterDTO);
|
return this.getCustomersService.getCustomersList(filterDTO);
|
||||||
// };
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,34 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { IItemsFilter } from '@/interfaces';
|
import { CustomersApplication } from './CustomersApplication.service';
|
||||||
// import { CustomersApplication } from './CustomersApplication';
|
import { IItemsFilter } from '../Items/types/Items.types';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
import { Exportable } from '../Export/Exportable';
|
||||||
|
import { ICustomersFilter } from './types/Customers.types';
|
||||||
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
|
import { Customer } from './models/Customer';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class CustomersExportable extends Exportable {
|
@ExportableService({ name: Customer.name })
|
||||||
// @Inject()
|
export class CustomersExportable extends Exportable {
|
||||||
// private customersApplication: CustomersApplication;
|
constructor(private readonly customersApplication: CustomersApplication) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {ICustomersFilter} query - Customers query.
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public exportable(query: ICustomersFilter) {
|
||||||
// public exportable(tenantId: number, query: IItemsFilter) {
|
const parsedQuery = {
|
||||||
// const parsedQuery = {
|
sortOrder: 'DESC',
|
||||||
// sortOrder: 'DESC',
|
columnSortBy: 'created_at',
|
||||||
// columnSortBy: 'created_at',
|
...query,
|
||||||
// ...query,
|
page: 1,
|
||||||
// page: 1,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
} as IItemsFilter;
|
||||||
// } as IItemsFilter;
|
|
||||||
|
|
||||||
// return this.customersApplication
|
return this.customersApplication
|
||||||
// .getCustomers(tenantId, parsedQuery)
|
.getCustomers(parsedQuery)
|
||||||
// .then((output) => output.customers);
|
.then((output) => output.customers);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Importable } from '@/services/Import/Importable';
|
import { CustomersSampleData } from './_SampleData';
|
||||||
// import { CreateCustomer } from './CRUD/CreateCustomer';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Knex } from 'knex';
|
import { Importable } from '../Import/Importable';
|
||||||
// import { ICustomer, ICustomerNewDTO } from '@/interfaces';
|
import { CreateCustomer } from './commands/CreateCustomer.service';
|
||||||
// import { CustomersSampleData } from './_SampleData';
|
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class CustomersImportable extends Importable {
|
export class CustomersImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly createCustomerService: CreateCustomer) {
|
||||||
// private createCustomerService: CreateCustomer;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Mapps the imported data to create a new customer service.
|
* Mapps the imported data to create a new customer service.
|
||||||
// * @param {number} tenantId
|
* @param {number} tenantId
|
||||||
// * @param {ICustomerNewDTO} createDTO
|
* @param {ICustomerNewDTO} createDTO
|
||||||
// * @param {Knex.Transaction} trx
|
* @param {Knex.Transaction} trx
|
||||||
// * @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
// */
|
*/
|
||||||
// public async importable(
|
public async importable(
|
||||||
// tenantId: number,
|
createDTO: CreateCustomerDto,
|
||||||
// createDTO: ICustomerNewDTO,
|
trx?: Knex.Transaction<any, any[]>,
|
||||||
// trx?: Knex.Transaction<any, any[]>
|
): Promise<void> {
|
||||||
// ): Promise<void> {
|
await this.createCustomerService.createCustomer(createDTO, trx);
|
||||||
// await this.createCustomerService.createCustomer(tenantId, createDTO, trx);
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data of customers used to download sample sheet.
|
* Retrieves the sample data of customers used to download sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return CustomersSampleData;
|
return CustomersSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
422
packages/server/src/modules/Customers/models/Customer.meta.ts
Normal file
422
packages/server/src/modules/Customers/models/Customer.meta.ts
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
export const CustomerMeta = {
|
||||||
|
importable: true,
|
||||||
|
exportable: true,
|
||||||
|
defaultFilterField: 'displayName',
|
||||||
|
defaultSort: {
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
sortField: 'created_at',
|
||||||
|
},
|
||||||
|
print: {
|
||||||
|
pageTitle: 'Customers',
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
first_name: {
|
||||||
|
name: 'vendor.field.first_name',
|
||||||
|
column: 'first_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
last_name: {
|
||||||
|
name: 'vendor.field.last_name',
|
||||||
|
column: 'last_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
display_name: {
|
||||||
|
name: 'vendor.field.display_name',
|
||||||
|
column: 'display_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
name: 'vendor.field.email',
|
||||||
|
column: 'email',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
work_phone: {
|
||||||
|
name: 'vendor.field.work_phone',
|
||||||
|
column: 'work_phone',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
personal_phone: {
|
||||||
|
name: 'vendor.field.personal_pone',
|
||||||
|
column: 'personal_phone',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
company_name: {
|
||||||
|
name: 'vendor.field.company_name',
|
||||||
|
column: 'company_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
website: {
|
||||||
|
name: 'vendor.field.website',
|
||||||
|
column: 'website',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'vendor.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
name: 'vendor.field.balance',
|
||||||
|
column: 'balance',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
opening_balance: {
|
||||||
|
name: 'vendor.field.opening_balance',
|
||||||
|
column: 'opening_balance',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
opening_balance_at: {
|
||||||
|
name: 'vendor.field.opening_balance_at',
|
||||||
|
column: 'opening_balance_at',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
currency_code: {
|
||||||
|
name: 'vendor.field.currency',
|
||||||
|
column: 'currency_code',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
name: 'vendor.field.status',
|
||||||
|
type: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'overdue', label: 'vendor.field.status.overdue' },
|
||||||
|
{ key: 'unpaid', label: 'vendor.field.status.unpaid' },
|
||||||
|
],
|
||||||
|
filterCustomQuery: (query, role) => {
|
||||||
|
switch (role.value) {
|
||||||
|
case 'overdue':
|
||||||
|
query.modify('overdue');
|
||||||
|
break;
|
||||||
|
case 'unpaid':
|
||||||
|
query.modify('unpaid');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
customerType: {
|
||||||
|
name: 'Customer Type',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'formattedCustomerType',
|
||||||
|
},
|
||||||
|
firstName: {
|
||||||
|
name: 'vendor.field.first_name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
name: 'vendor.field.last_name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
displayName: {
|
||||||
|
name: 'vendor.field.display_name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
name: 'vendor.field.email',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
workPhone: {
|
||||||
|
name: 'vendor.field.work_phone',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
personalPhone: {
|
||||||
|
name: 'vendor.field.personal_phone',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
companyName: {
|
||||||
|
name: 'vendor.field.company_name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
website: {
|
||||||
|
name: 'vendor.field.website',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
name: 'vendor.field.balance',
|
||||||
|
type: 'number',
|
||||||
|
accessor: 'formattedBalance',
|
||||||
|
},
|
||||||
|
openingBalance: {
|
||||||
|
name: 'vendor.field.opening_balance',
|
||||||
|
type: 'number',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
openingBalanceAt: {
|
||||||
|
name: 'vendor.field.opening_balance_at',
|
||||||
|
type: 'date',
|
||||||
|
printable: false,
|
||||||
|
accessor: 'formattedOpeningBalanceAt'
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'vendor.field.currency',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
name: 'vendor.field.status',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'vendor.field.note',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
// Billing Address
|
||||||
|
billingAddress1: {
|
||||||
|
name: 'Billing Address 1',
|
||||||
|
column: 'billing_address1',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
billingAddress2: {
|
||||||
|
name: 'Billing Address 2',
|
||||||
|
column: 'billing_address2',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
billingAddressCity: {
|
||||||
|
name: 'Billing Address City',
|
||||||
|
column: 'billing_address_city',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
billingAddressCountry: {
|
||||||
|
name: 'Billing Address Country',
|
||||||
|
column: 'billing_address_country',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
billingAddressPostcode: {
|
||||||
|
name: 'Billing Address Postcode',
|
||||||
|
column: 'billing_address_postcode',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
billingAddressState: {
|
||||||
|
name: 'Billing Address State',
|
||||||
|
column: 'billing_address_state',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
billingAddressPhone: {
|
||||||
|
name: 'Billing Address Phone',
|
||||||
|
column: 'billing_address_phone',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
// Shipping Address
|
||||||
|
shippingAddress1: {
|
||||||
|
name: 'Shipping Address 1',
|
||||||
|
column: 'shipping_address1',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
shippingAddress2: {
|
||||||
|
name: 'Shipping Address 2',
|
||||||
|
column: 'shipping_address2',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
shippingAddressCity: {
|
||||||
|
name: 'Shipping Address City',
|
||||||
|
column: 'shipping_address_city',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
shippingAddressCountry: {
|
||||||
|
name: 'Shipping Address Country',
|
||||||
|
column: 'shipping_address_country',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
shippingAddressPostcode: {
|
||||||
|
name: 'Shipping Address Postcode',
|
||||||
|
column: 'shipping_address_postcode',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
shippingAddressPhone: {
|
||||||
|
name: 'Shipping Address Phone',
|
||||||
|
column: 'shipping_address_phone',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
shippingAddressState: {
|
||||||
|
name: 'Shipping Address State',
|
||||||
|
column: 'shipping_address_state',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
name: 'vendor.field.created_at',
|
||||||
|
type: 'date',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
customerType: {
|
||||||
|
name: 'Customer Type',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'business', label: 'Business' },
|
||||||
|
{ key: 'individual', label: 'Individual' },
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
firstName: {
|
||||||
|
name: 'customer.field.first_name',
|
||||||
|
column: 'first_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
name: 'customer.field.last_name',
|
||||||
|
column: 'last_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
displayName: {
|
||||||
|
name: 'customer.field.display_name',
|
||||||
|
column: 'display_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
name: 'customer.field.email',
|
||||||
|
column: 'email',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
workPhone: {
|
||||||
|
name: 'customer.field.work_phone',
|
||||||
|
column: 'work_phone',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
personalPhone: {
|
||||||
|
name: 'customer.field.personal_phone',
|
||||||
|
column: 'personal_phone',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
companyName: {
|
||||||
|
name: 'customer.field.company_name',
|
||||||
|
column: 'company_name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
website: {
|
||||||
|
name: 'customer.field.website',
|
||||||
|
column: 'website',
|
||||||
|
fieldType: 'url',
|
||||||
|
},
|
||||||
|
openingBalance: {
|
||||||
|
name: 'customer.field.opening_balance',
|
||||||
|
column: 'opening_balance',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
openingBalanceAt: {
|
||||||
|
name: 'customer.field.opening_balance_at',
|
||||||
|
column: 'opening_balance_at',
|
||||||
|
filterable: false,
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
openingBalanceExchangeRate: {
|
||||||
|
name: 'Opening Balance Ex. Rate',
|
||||||
|
column: 'opening_balance_exchange_rate',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'customer.field.currency',
|
||||||
|
column: 'currency_code',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'Note',
|
||||||
|
column: 'note',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'Active',
|
||||||
|
column: 'active',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
// Billing Address
|
||||||
|
billingAddress1: {
|
||||||
|
name: 'Billing Address 1',
|
||||||
|
column: 'billing_address1',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billingAddress2: {
|
||||||
|
name: 'Billing Address 2',
|
||||||
|
column: 'billing_address2',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billingAddressCity: {
|
||||||
|
name: 'Billing Address City',
|
||||||
|
column: 'billing_address_city',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billingAddressCountry: {
|
||||||
|
name: 'Billing Address Country',
|
||||||
|
column: 'billing_address_country',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billingAddressPostcode: {
|
||||||
|
name: 'Billing Address Postcode',
|
||||||
|
column: 'billing_address_postcode',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billingAddressState: {
|
||||||
|
name: 'Billing Address State',
|
||||||
|
column: 'billing_address_state',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
billingAddressPhone: {
|
||||||
|
name: 'Billing Address Phone',
|
||||||
|
column: 'billing_address_phone',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
// Shipping Address
|
||||||
|
shippingAddress1: {
|
||||||
|
name: 'Shipping Address 1',
|
||||||
|
column: 'shipping_address1',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
shippingAddress2: {
|
||||||
|
name: 'Shipping Address 2',
|
||||||
|
column: 'shipping_address2',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
shippingAddressCity: {
|
||||||
|
name: 'Shipping Address City',
|
||||||
|
column: 'shipping_address_city',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
shippingAddressCountry: {
|
||||||
|
name: 'Shipping Address Country',
|
||||||
|
column: 'shipping_address_country',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
shippingAddressPostcode: {
|
||||||
|
name: 'Shipping Address Postcode',
|
||||||
|
column: 'shipping_address_postcode',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
shippingAddressPhone: {
|
||||||
|
name: 'Shipping Address Phone',
|
||||||
|
column: 'shipping_address_phone',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
shippingAddressState: {
|
||||||
|
name: 'Shipping Address State',
|
||||||
|
column: 'shipping_address_state',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function statusFieldFilterQuery(query, role) {
|
||||||
|
switch (role.value) {
|
||||||
|
case 'overdue':
|
||||||
|
query.modify('overdue');
|
||||||
|
break;
|
||||||
|
case 'unpaid':
|
||||||
|
query.modify('unpaid');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { CustomerMeta } from './Customer.meta';
|
||||||
|
|
||||||
|
|
||||||
|
@InjectModelMeta(CustomerMeta)
|
||||||
export class Customer extends TenantBaseModel{
|
export class Customer extends TenantBaseModel{
|
||||||
contactService: string;
|
contactService: string;
|
||||||
contactType: string;
|
contactType: string;
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ import { LedgerModule } from '../Ledger/Ledger.module';
|
|||||||
import { BranchesModule } from '../Branches/Branches.module';
|
import { BranchesModule } from '../Branches/Branches.module';
|
||||||
import { GetExpensesService } from './queries/GetExpenses.service';
|
import { GetExpensesService } from './queries/GetExpenses.service';
|
||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
|
import { ExpensesExportable } from './ExpensesExportable';
|
||||||
|
import { ExpensesImportable } from './ExpensesImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [LedgerModule, BranchesModule, DynamicListModule],
|
imports: [LedgerModule, BranchesModule, DynamicListModule],
|
||||||
controllers: [ExpensesController],
|
controllers: [ExpensesController],
|
||||||
exports: [CreateExpense],
|
exports: [CreateExpense, ExpensesExportable, ExpensesImportable],
|
||||||
providers: [
|
providers: [
|
||||||
CreateExpense,
|
CreateExpense,
|
||||||
ExpenseDTOTransformer,
|
ExpenseDTOTransformer,
|
||||||
@@ -37,6 +39,8 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
ExpenseGLEntriesStorageService,
|
ExpenseGLEntriesStorageService,
|
||||||
ExpenseGLEntriesService,
|
ExpenseGLEntriesService,
|
||||||
GetExpensesService,
|
GetExpensesService,
|
||||||
|
ExpensesExportable,
|
||||||
|
ExpensesImportable,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ExpensesModule {}
|
export class ExpensesModule {}
|
||||||
|
|||||||
@@ -1,34 +1,39 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Exportable } from '../Export/Exportable';
|
||||||
// import { Exportable } from '../Export/Exportable';
|
import { ExpensesApplication } from './ExpensesApplication.service';
|
||||||
// import { IExpensesFilter } from '@/interfaces';
|
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
||||||
// import { ExpensesApplication } from './ExpensesApplication.service';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
import { IExpensesFilter } from './Expenses.types';
|
||||||
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
|
import { Expense } from './models/Expense.model';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class ExpensesExportable extends Exportable {
|
@ExportableService({ name: Expense.name })
|
||||||
// @Inject()
|
export class ExpensesExportable extends Exportable {
|
||||||
// private expensesApplication: ExpensesApplication;
|
constructor(
|
||||||
|
private readonly expensesApplication: ExpensesApplication,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {IExpensesFilter}
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public exportable(query: IExpensesFilter) {
|
||||||
// public exportable(tenantId: number, query: IExpensesFilter) {
|
const filterQuery = (query) => {
|
||||||
// const filterQuery = (query) => {
|
query.withGraphFetched('branch');
|
||||||
// query.withGraphFetched('branch');
|
};
|
||||||
// };
|
const parsedQuery = {
|
||||||
// const parsedQuery = {
|
sortOrder: 'desc',
|
||||||
// sortOrder: 'desc',
|
columnSortBy: 'created_at',
|
||||||
// columnSortBy: 'created_at',
|
...query,
|
||||||
// ...query,
|
page: 1,
|
||||||
// page: 1,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
filterQuery,
|
||||||
// filterQuery,
|
} as IExpensesFilter;
|
||||||
// } as IExpensesFilter;
|
|
||||||
|
|
||||||
// return this.expensesApplication
|
return this.expensesApplication
|
||||||
// .getExpenses(tenantId, parsedQuery)
|
.getExpenses(parsedQuery)
|
||||||
// .then((output) => output.expenses);
|
.then((output) => output.expenses);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,46 +1,41 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { Importable } from '../Import/Importable';
|
||||||
// import { IExpenseCreateDTO } from '@/interfaces';
|
import { ExpensesSampleData } from './constants';
|
||||||
// import { Importable } from '../Import/Importable';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { CreateExpense } from './CRUD/CreateExpense.service';
|
import { CreateExpense } from './commands/CreateExpense.service';
|
||||||
// import { ExpensesSampleData } from './constants';
|
import { CreateExpenseDto } from './dtos/Expense.dto';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class ExpensesImportable extends Importable {
|
export class ExpensesImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly createExpenseService: CreateExpense) {
|
||||||
// private createExpenseService: CreateExpense;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {number} tenantId
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
* @param {IAccountCreateDTO} createAccountDTO
|
||||||
// * @returns
|
* @returns
|
||||||
// */
|
*/
|
||||||
// public importable(
|
public importable(
|
||||||
// tenantId: number,
|
createAccountDTO: CreateExpenseDto,
|
||||||
// createAccountDTO: IExpenseCreateDTO,
|
trx?: Knex.Transaction,
|
||||||
// trx?: Knex.Transaction
|
) {
|
||||||
// ) {
|
return this.createExpenseService.newExpense(createAccountDTO, trx);
|
||||||
// return this.createExpenseService.newExpense(
|
}
|
||||||
// tenantId,
|
|
||||||
// createAccountDTO,
|
|
||||||
// {},
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return ExpensesSampleData;
|
return ExpensesSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import * as moment from 'moment';
|
|||||||
import { ExpenseCategory } from './ExpenseCategory.model';
|
import { ExpenseCategory } from './ExpenseCategory.model';
|
||||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
export class Expense extends TenantBaseModel {
|
export class Expense extends TenantBaseModel {
|
||||||
totalAmount!: number;
|
totalAmount!: number;
|
||||||
currencyCode!: string;
|
currencyCode!: string;
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { convertAcceptFormatToFormat } from './_utils';
|
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
import { Controller, Headers, Query, Res } from '@nestjs/common';
|
import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
|
||||||
|
import { AcceptType } from '@/constants/accept-type';
|
||||||
import { ExportQuery } from './dtos/ExportQuery.dto';
|
import { ExportQuery } from './dtos/ExportQuery.dto';
|
||||||
import { ExportResourceService } from './ExportService';
|
import { ExportResourceService } from './ExportService';
|
||||||
import { AcceptType } from '@/constants/accept-type';
|
import { convertAcceptFormatToFormat } from './Export.utils';
|
||||||
|
|
||||||
@Controller('/export')
|
@Controller('/export')
|
||||||
|
@ApiTags('export')
|
||||||
export class ExportController {
|
export class ExportController {
|
||||||
constructor(private readonly exportResourceApp: ExportResourceService) {}
|
constructor(private readonly exportResourceApp: ExportResourceService) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@ApiOperation({ summary: 'Retrieves exported the given resource.' })
|
||||||
async export(
|
async export(
|
||||||
@Query() query: ExportQuery,
|
@Query() query: ExportQuery,
|
||||||
@Res() res: Response,
|
@Res() res: Response,
|
||||||
@Headers('accept') acceptHeader: string,
|
@Headers('accept') acceptHeader: string,
|
||||||
) {
|
) {
|
||||||
const applicationFormat = convertAcceptFormatToFormat(acceptType);
|
const applicationFormat = convertAcceptFormatToFormat(acceptHeader);
|
||||||
|
|
||||||
const data = await this.exportResourceApp.export(
|
const data = await this.exportResourceApp.export(
|
||||||
query.resource,
|
query.resource,
|
||||||
|
|||||||
@@ -4,9 +4,32 @@ import { ExportResourceService } from './ExportService';
|
|||||||
import { ExportPdf } from './ExportPdf';
|
import { ExportPdf } from './ExportPdf';
|
||||||
import { ExportAls } from './ExportAls';
|
import { ExportAls } from './ExportAls';
|
||||||
import { ExportApplication } from './ExportApplication';
|
import { ExportApplication } from './ExportApplication';
|
||||||
|
import { ResourceModule } from '../Resource/Resource.module';
|
||||||
|
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
||||||
|
import { ImportModel } from '../Import/models/Import';
|
||||||
|
import { ExportableRegistry } from './ExportRegistery';
|
||||||
|
import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectable.module';
|
||||||
|
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
|
||||||
|
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||||
|
|
||||||
|
const models = [RegisterTenancyModel(ImportModel)];
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [ExportResourceService, ExportPdf, ExportAls, ExportApplication],
|
imports: [
|
||||||
|
...models,
|
||||||
|
ResourceModule,
|
||||||
|
TemplateInjectableModule,
|
||||||
|
ChromiumlyTenancyModule,
|
||||||
|
AccountsModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
ExportResourceService,
|
||||||
|
ExportPdf,
|
||||||
|
ExportAls,
|
||||||
|
ExportApplication,
|
||||||
|
ExportableRegistry
|
||||||
|
],
|
||||||
|
exports: [...models],
|
||||||
controllers: [ExportController],
|
controllers: [ExportController],
|
||||||
})
|
})
|
||||||
export class ExportModule {}
|
export class ExportModule {}
|
||||||
|
|||||||
14
packages/server/src/modules/Export/Export.utils.ts
Normal file
14
packages/server/src/modules/Export/Export.utils.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { ACCEPT_TYPE } from '@/common/constants/http.constants';
|
||||||
|
import { ExportFormat } from './common';
|
||||||
|
|
||||||
|
export const convertAcceptFormatToFormat = (accept: string): ExportFormat => {
|
||||||
|
switch (accept) {
|
||||||
|
default:
|
||||||
|
case ACCEPT_TYPE.APPLICATION_CSV:
|
||||||
|
return ExportFormat.Csv;
|
||||||
|
case ACCEPT_TYPE.APPLICATION_PDF:
|
||||||
|
return ExportFormat.Pdf;
|
||||||
|
case ACCEPT_TYPE.APPLICATION_XLSX:
|
||||||
|
return ExportFormat.Xlsx;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -15,7 +15,7 @@ export class ExportAls {
|
|||||||
* @returns The result of the callback function.
|
* @returns The result of the callback function.
|
||||||
*/
|
*/
|
||||||
public run<T>(callback: () => T): T {
|
public run<T>(callback: () => T): T {
|
||||||
return this.als.run<T>(new Map(), () => {
|
return this.als.run<T, []>(new Map(), () => {
|
||||||
this.markAsExport();
|
this.markAsExport();
|
||||||
|
|
||||||
return callback();
|
return callback();
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
// import Container, { Service } from 'typedi';
|
|
||||||
// import { AccountsExportable } from '../Accounts/AccountsExportable';
|
|
||||||
// import { ExportableRegistry } from './ExportRegistery';
|
|
||||||
// import { ItemsExportable } from '../Items/ItemsExportable';
|
|
||||||
// import { CustomersExportable } from '../Contacts/Customers/CustomersExportable';
|
|
||||||
// import { VendorsExportable } from '../Contacts/Vendors/VendorsExportable';
|
|
||||||
// import { ExpensesExportable } from '../Expenses/ExpensesExportable';
|
|
||||||
// import { SaleInvoicesExportable } from '../Sales/Invoices/SaleInvoicesExportable';
|
|
||||||
// import { SaleEstimatesExportable } from '../Sales/Estimates/SaleEstimatesExportable';
|
|
||||||
// import { SaleReceiptsExportable } from '../Sales/Receipts/SaleReceiptsExportable';
|
|
||||||
// import { BillsExportable } from '../Purchases/Bills/BillsExportable';
|
|
||||||
// import { PaymentsReceivedExportable } from '../Sales/PaymentReceived/PaymentsReceivedExportable';
|
|
||||||
// import { BillPaymentExportable } from '../Purchases/BillPayments/BillPaymentExportable';
|
|
||||||
// import { ManualJournalsExportable } from '../ManualJournals/ManualJournalExportable';
|
|
||||||
// import { CreditNotesExportable } from '../CreditNotes/CreditNotesExportable';
|
|
||||||
// import { VendorCreditsExportable } from '../Purchases/VendorCredits/VendorCreditsExportable';
|
|
||||||
// import { ItemCategoriesExportable } from '../ItemCategories/ItemCategoriesExportable';
|
|
||||||
// import { TaxRatesExportable } from '../TaxRates/TaxRatesExportable';
|
|
||||||
|
|
||||||
import { Injectable } from "@nestjs/common";
|
|
||||||
import { ExportableRegistry } from "./ExportRegistery";
|
|
||||||
import { AccountsExportable } from "../Accounts/AccountsExportable.service";
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class ExportableResources {
|
|
||||||
constructor(
|
|
||||||
private readonly exportRegistry: ExportableRegistry,
|
|
||||||
) {
|
|
||||||
this.boot();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Importable instances.
|
|
||||||
*/
|
|
||||||
private importables = [
|
|
||||||
{ resource: 'Account', exportable: AccountsExportable },
|
|
||||||
// { resource: 'Item', exportable: ItemsExportable },
|
|
||||||
// { resource: 'ItemCategory', exportable: ItemCategoriesExportable },
|
|
||||||
// { resource: 'Customer', exportable: CustomersExportable },
|
|
||||||
// { resource: 'Vendor', exportable: VendorsExportable },
|
|
||||||
// { resource: 'Expense', exportable: ExpensesExportable },
|
|
||||||
// { resource: 'SaleInvoice', exportable: SaleInvoicesExportable },
|
|
||||||
// { resource: 'SaleEstimate', exportable: SaleEstimatesExportable },
|
|
||||||
// { resource: 'SaleReceipt', exportable: SaleReceiptsExportable },
|
|
||||||
// { resource: 'Bill', exportable: BillsExportable },
|
|
||||||
// { resource: 'PaymentReceive', exportable: PaymentsReceivedExportable },
|
|
||||||
// { resource: 'BillPayment', exportable: BillPaymentExportable },
|
|
||||||
// { resource: 'ManualJournal', exportable: ManualJournalsExportable },
|
|
||||||
// { resource: 'CreditNote', exportable: CreditNotesExportable },
|
|
||||||
// { resource: 'VendorCredit', exportable: VendorCreditsExportable },
|
|
||||||
// { resource: 'TaxRate', exportable: TaxRatesExportable },
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public get registry() {
|
|
||||||
return ExportableResources.registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Boots all the registered importables.
|
|
||||||
*/
|
|
||||||
public boot() {
|
|
||||||
if (!ExportableResources.registry) {
|
|
||||||
const instance = ExportableRegistry.getInstance();
|
|
||||||
|
|
||||||
this.importables.forEach((importable) => {
|
|
||||||
const importableInstance = Container.get(importable.exportable);
|
|
||||||
instance.registerExportable(importable.resource, importableInstance);
|
|
||||||
});
|
|
||||||
ExportableResources.registry = instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +1,37 @@
|
|||||||
// @ts-nocheck
|
import { Injectable } from '@nestjs/common';
|
||||||
import xlsx from 'xlsx';
|
import * as xlsx from 'xlsx';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { sanitizeResourceName } from '../Import/_utils';
|
import { sanitizeResourceName } from '../Import/_utils';
|
||||||
import { ExportableResources } from './ExportResources';
|
|
||||||
import { ServiceError } from '@/exceptions';
|
|
||||||
import { Errors, ExportFormat } from './common';
|
import { Errors, ExportFormat } from './common';
|
||||||
import { IModelMeta, IModelMetaColumn } from '@/interfaces';
|
|
||||||
import { flatDataCollections, getDataAccessor } from './utils';
|
import { flatDataCollections, getDataAccessor } from './utils';
|
||||||
import { ExportPdf } from './ExportPdf';
|
import { ExportPdf } from './ExportPdf';
|
||||||
import { ExportAls } from './ExportAls';
|
import { ExportAls } from './ExportAls';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { IModelMeta, IModelMetaColumn } from '@/interfaces/Model';
|
||||||
|
import { ServiceError } from '../Items/ServiceError';
|
||||||
|
import { ResourceService } from '../Resource/ResourceService';
|
||||||
|
import { getExportableService } from './decorators/ExportableModel.decorator';
|
||||||
|
import { ContextIdFactory, ModuleRef } from '@nestjs/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ExportResourceService {
|
export class ExportResourceService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly exportAls: ExportAls,
|
private readonly exportAls: ExportAls,
|
||||||
private readonly exportPdf: ExportPdf,
|
private readonly exportPdf: ExportPdf,
|
||||||
private readonly exportableResources: ExportableResources,
|
|
||||||
private readonly resourceService: ResourceService,
|
private readonly resourceService: ResourceService,
|
||||||
|
private readonly moduleRef: ModuleRef,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {string} resourceName
|
* @param {string} resourceName
|
||||||
* @param {ExportFormat} format
|
* @param {ExportFormat} format
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public async export(
|
public async export(
|
||||||
resourceName: string,
|
resourceName: string,
|
||||||
format: ExportFormat = ExportFormat.Csv
|
format: ExportFormat = ExportFormat.Csv,
|
||||||
) {
|
) {
|
||||||
return this.exportAls.run(() =>
|
return this.exportAls.run(() => this.exportAlsRun(resourceName, format));
|
||||||
this.exportAlsRun(resourceName, format)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,18 +41,18 @@ export class ExportResourceService {
|
|||||||
*/
|
*/
|
||||||
public async exportAlsRun(
|
public async exportAlsRun(
|
||||||
resourceName: string,
|
resourceName: string,
|
||||||
format: ExportFormat = ExportFormat.Csv
|
format: ExportFormat = ExportFormat.Csv,
|
||||||
) {
|
) {
|
||||||
const resource = sanitizeResourceName(resourceName);
|
const resource = sanitizeResourceName(resourceName);
|
||||||
const resourceMeta = this.getResourceMeta(tenantId, resource);
|
const resourceMeta = this.getResourceMeta(resource);
|
||||||
const resourceColumns = this.resourceService.getResourceColumns(
|
|
||||||
tenantId,
|
const resourceColumns = this.resourceService.getResourceColumns(resource);
|
||||||
resource
|
|
||||||
);
|
|
||||||
this.validateResourceMeta(resourceMeta);
|
this.validateResourceMeta(resourceMeta);
|
||||||
|
|
||||||
const data = await this.getExportableData(tenantId, resource);
|
const data = await this.getExportableData(resource);
|
||||||
const transformed = this.transformExportedData(tenantId, resource, data);
|
const transformed = this.transformExportedData(resource, data);
|
||||||
|
|
||||||
|
console.log(format);
|
||||||
|
|
||||||
// Returns the csv, xlsx format.
|
// Returns the csv, xlsx format.
|
||||||
if (format === ExportFormat.Csv || format === ExportFormat.Xlsx) {
|
if (format === ExportFormat.Csv || format === ExportFormat.Xlsx) {
|
||||||
@@ -67,10 +65,9 @@ export class ExportResourceService {
|
|||||||
const printableColumns = this.getPrintableColumns(resourceMeta);
|
const printableColumns = this.getPrintableColumns(resourceMeta);
|
||||||
|
|
||||||
return this.exportPdf.pdf(
|
return this.exportPdf.pdf(
|
||||||
tenantId,
|
|
||||||
printableColumns,
|
printableColumns,
|
||||||
transformed,
|
transformed,
|
||||||
resourceMeta?.print?.pageTitle
|
resourceMeta?.print?.pageTitle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,14 +103,14 @@ export class ExportResourceService {
|
|||||||
*/
|
*/
|
||||||
private transformExportedData(
|
private transformExportedData(
|
||||||
resource: string,
|
resource: string,
|
||||||
data: Array<Record<string, any>>
|
data: Array<Record<string, any>>,
|
||||||
): Array<Record<string, any>> {
|
): Array<Record<string, any>> {
|
||||||
const resourceMeta = this.getResourceMeta(resource);
|
const resourceMeta = this.getResourceMeta(resource);
|
||||||
|
|
||||||
return R.when<Array<Record<string, any>>, Array<Record<string, any>>>(
|
return R.when<Array<Record<string, any>>, Array<Record<string, any>>>(
|
||||||
R.always(Boolean(resourceMeta.exportFlattenOn)),
|
R.always(Boolean(resourceMeta.exportFlattenOn)),
|
||||||
(data) => flatDataCollections(data, resourceMeta.exportFlattenOn),
|
(data) => flatDataCollections(data, resourceMeta.exportFlattenOn),
|
||||||
data
|
data,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -123,10 +120,14 @@ export class ExportResourceService {
|
|||||||
* @returns A promise that resolves to the exportable data.
|
* @returns A promise that resolves to the exportable data.
|
||||||
*/
|
*/
|
||||||
private async getExportableData(resource: string) {
|
private async getExportableData(resource: string) {
|
||||||
const exportable =
|
const exportable = getExportableService(resource);
|
||||||
this.exportableResources.registry.getExportable(resource);
|
const contextId = ContextIdFactory.create();
|
||||||
|
const exportableInstance = await this.moduleRef.resolve(
|
||||||
return exportable.exportable({});
|
exportable,
|
||||||
|
contextId,
|
||||||
|
{ strict: false },
|
||||||
|
);
|
||||||
|
return exportableInstance.exportable({});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,7 +138,7 @@ export class ExportResourceService {
|
|||||||
private getExportableColumns(resourceColumns: any) {
|
private getExportableColumns(resourceColumns: any) {
|
||||||
const processColumns = (
|
const processColumns = (
|
||||||
columns: { [key: string]: IModelMetaColumn },
|
columns: { [key: string]: IModelMetaColumn },
|
||||||
parent = ''
|
parent = '',
|
||||||
) => {
|
) => {
|
||||||
return Object.entries(columns)
|
return Object.entries(columns)
|
||||||
.filter(([_, value]) => value.exportable !== false)
|
.filter(([_, value]) => value.exportable !== false)
|
||||||
@@ -163,9 +164,10 @@ export class ExportResourceService {
|
|||||||
private getPrintableColumns(resourceMeta: IModelMeta) {
|
private getPrintableColumns(resourceMeta: IModelMeta) {
|
||||||
const processColumns = (
|
const processColumns = (
|
||||||
columns: { [key: string]: IModelMetaColumn },
|
columns: { [key: string]: IModelMetaColumn },
|
||||||
parent = ''
|
parent = '',
|
||||||
) => {
|
) => {
|
||||||
return Object.entries(columns)
|
return Object.entries(columns)
|
||||||
|
// @ts-expect-error
|
||||||
.filter(([_, value]) => value.printable !== false)
|
.filter(([_, value]) => value.printable !== false)
|
||||||
.flatMap(([key, value]) => {
|
.flatMap(([key, value]) => {
|
||||||
if (value.type === 'collection' && value.collectionOf === 'object') {
|
if (value.type === 'collection' && value.collectionOf === 'object') {
|
||||||
@@ -195,7 +197,7 @@ export class ExportResourceService {
|
|||||||
private createWorkbook(data: any[], exportableColumns: any[]) {
|
private createWorkbook(data: any[], exportableColumns: any[]) {
|
||||||
const workbook = xlsx.utils.book_new();
|
const workbook = xlsx.utils.book_new();
|
||||||
const worksheetData = data.map((item) =>
|
const worksheetData = data.map((item) =>
|
||||||
exportableColumns.map((col) => get(item, getDataAccessor(col)))
|
exportableColumns.map((col) => get(item, getDataAccessor(col))),
|
||||||
);
|
);
|
||||||
worksheetData.unshift(exportableColumns.map((col) => col.name));
|
worksheetData.unshift(exportableColumns.map((col) => col.name));
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export class Exportable {
|
|||||||
*/
|
*/
|
||||||
public async exportable(
|
public async exportable(
|
||||||
query: Record<string, any>,
|
query: Record<string, any>,
|
||||||
): Promise<Array<Record<string, any>>> {
|
): Promise<any> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Global } from "@nestjs/common";
|
||||||
|
|
||||||
|
const exportableModels = new Map<string, boolean>();
|
||||||
|
const exportableService = new Map<string, any>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator that marks a model as exportable and registers its metadata.
|
||||||
|
* @param metadata Model metadata configuration for export
|
||||||
|
*/
|
||||||
|
export function ExportableModel() {
|
||||||
|
return function (target: any) {
|
||||||
|
const modelName = target.name;
|
||||||
|
exportableModels.set(modelName, true);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ExportableService({ name }: { name: string }) {
|
||||||
|
return function (target: any) {
|
||||||
|
exportableService.set(name, target);
|
||||||
|
|
||||||
|
// Apply the @Global() decorator to make the service globally available
|
||||||
|
Global()(target);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the registered exportable model metadata
|
||||||
|
* @param modelName Name of the model class
|
||||||
|
*/
|
||||||
|
export function getExportableModelMeta(modelName: string): boolean | undefined {
|
||||||
|
return exportableModels.get(modelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getExportableService(modelName: string) {
|
||||||
|
return exportableService.get(modelName);
|
||||||
|
}
|
||||||
@@ -4,8 +4,4 @@ export class ExportQuery {
|
|||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
resource: string;
|
resource: string;
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
format: string;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,40 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ImportAls } from './ImportALS';
|
import { ImportAls } from './ImportALS';
|
||||||
|
import { ImportSampleService } from './ImportSample';
|
||||||
|
import { ImportResourceApplication } from './ImportResourceApplication';
|
||||||
|
import { ImportDeleteExpiredFiles } from './ImportRemoveExpiredFiles';
|
||||||
|
import { ImportFileUploadService } from './ImportFileUpload';
|
||||||
|
import { ImportFileProcessCommit } from './ImportFileProcessCommit';
|
||||||
|
import { ImportFileProcess } from './ImportFileProcess';
|
||||||
|
import { ImportFilePreview } from './ImportFilePreview';
|
||||||
|
import { ImportFileMeta } from './ImportFileMeta';
|
||||||
|
import { ImportFileMapping } from './ImportFileMapping';
|
||||||
|
import { ImportFileDataValidator } from './ImportFileDataValidator';
|
||||||
|
import { ImportFileDataTransformer } from './ImportFileDataTransformer';
|
||||||
|
import { ImportFileCommon } from './ImportFileCommon';
|
||||||
|
import { ImportableResources } from './ImportableResources';
|
||||||
|
import { ResourceModule } from '../Resource/Resource.module';
|
||||||
|
import { TenancyModule } from '../Tenancy/Tenancy.module';
|
||||||
|
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [ImportAls],
|
imports: [ResourceModule, TenancyModule, AccountsModule],
|
||||||
|
providers: [
|
||||||
|
ImportAls,
|
||||||
|
ImportSampleService,
|
||||||
|
ImportableResources,
|
||||||
|
ImportResourceApplication,
|
||||||
|
ImportDeleteExpiredFiles,
|
||||||
|
ImportFileUploadService,
|
||||||
|
ImportFileProcessCommit,
|
||||||
|
ImportFileProcess,
|
||||||
|
ImportFilePreview,
|
||||||
|
ImportFileMeta,
|
||||||
|
ImportFileMapping,
|
||||||
|
ImportFileDataValidator,
|
||||||
|
ImportFileDataTransformer,
|
||||||
|
ImportFileCommon,
|
||||||
|
],
|
||||||
exports: [ImportAls],
|
exports: [ImportAls],
|
||||||
})
|
})
|
||||||
export class ImportModule {}
|
export class ImportModule {}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import {
|
|||||||
import { getUniqueImportableValue, trimObject } from './_utils';
|
import { getUniqueImportableValue, trimObject } from './_utils';
|
||||||
import { ImportableResources } from './ImportableResources';
|
import { ImportableResources } from './ImportableResources';
|
||||||
import { ResourceService } from '../Resource/ResourceService';
|
import { ResourceService } from '../Resource/ResourceService';
|
||||||
import { Import } from '@/system/models';
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ServiceError } from '../Items/ServiceError';
|
import { ServiceError } from '../Items/ServiceError';
|
||||||
|
import { ImportModelShape } from './models/Import';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFileCommon {
|
export class ImportFileCommon {
|
||||||
@@ -32,7 +32,7 @@ export class ImportFileCommon {
|
|||||||
* @returns {Promise<[ImportOperSuccess[], ImportOperError[]]>}
|
* @returns {Promise<[ImportOperSuccess[], ImportOperError[]]>}
|
||||||
*/
|
*/
|
||||||
public async import(
|
public async import(
|
||||||
importFile: Import,
|
importFile: ImportModelShape,
|
||||||
parsedData: Record<string, any>[],
|
parsedData: Record<string, any>[],
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<[ImportOperSuccess[], ImportOperError[]]> {
|
): Promise<[ImportOperSuccess[], ImportOperError[]]> {
|
||||||
@@ -68,7 +68,6 @@ export class ImportFileCommon {
|
|||||||
try {
|
try {
|
||||||
// Run the importable function and listen to the errors.
|
// Run the importable function and listen to the errors.
|
||||||
const data = await importable.importable(
|
const data = await importable.importable(
|
||||||
tenantId,
|
|
||||||
transformedDTO,
|
transformedDTO,
|
||||||
trx,
|
trx,
|
||||||
);
|
);
|
||||||
@@ -135,14 +134,13 @@ export class ImportFileCommon {
|
|||||||
* @param {Record<string, any>} params
|
* @param {Record<string, any>} params
|
||||||
*/
|
*/
|
||||||
public async validateParams(
|
public async validateParams(
|
||||||
tenantId: number,
|
|
||||||
resourceName: string,
|
resourceName: string,
|
||||||
params: Record<string, any>,
|
params: Record<string, any>,
|
||||||
) {
|
) {
|
||||||
const ImportableRegistry = this.importable.registry;
|
const ImportableRegistry = this.importable.registry;
|
||||||
const importable = ImportableRegistry.getImportable(resourceName);
|
const importable = ImportableRegistry.getImportable(resourceName);
|
||||||
|
|
||||||
await importable.validateParams(tenantId, params);
|
await importable.validateParams(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { fromPairs, isUndefined } from 'lodash';
|
import { fromPairs, isUndefined } from 'lodash';
|
||||||
import {
|
import {
|
||||||
ImportDateFormats,
|
ImportDateFormats,
|
||||||
@@ -8,15 +8,19 @@ import {
|
|||||||
import { ResourceService } from '../Resource/ResourceService';
|
import { ResourceService } from '../Resource/ResourceService';
|
||||||
import { ServiceError } from '../Items/ServiceError';
|
import { ServiceError } from '../Items/ServiceError';
|
||||||
import { ERRORS } from './_utils';
|
import { ERRORS } from './_utils';
|
||||||
import { Import } from './models/Import';
|
import { ImportModel } from './models/Import';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFileMapping {
|
export class ImportFileMapping {
|
||||||
constructor(private readonly resource: ResourceService) {}
|
constructor(
|
||||||
|
private readonly resource: ResourceService,
|
||||||
|
|
||||||
|
@Inject(ImportModel.name)
|
||||||
|
private readonly importModel: () => typeof ImportModel,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping the excel sheet columns with resource columns.
|
* Mapping the excel sheet columns with resource columns.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} importId
|
* @param {number} importId
|
||||||
* @param {ImportMappingAttr} maps
|
* @param {ImportMappingAttr} maps
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +28,8 @@ export class ImportFileMapping {
|
|||||||
importId: string,
|
importId: string,
|
||||||
maps: ImportMappingAttr[],
|
maps: ImportMappingAttr[],
|
||||||
): Promise<ImportFileMapPOJO> {
|
): Promise<ImportFileMapPOJO> {
|
||||||
const importFile = await Import.query()
|
const importFile = await this.importModel()
|
||||||
|
.query()
|
||||||
.findOne('filename', importId)
|
.findOne('filename', importId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
@@ -41,7 +46,7 @@ export class ImportFileMapping {
|
|||||||
|
|
||||||
const mappingStringified = JSON.stringify(maps);
|
const mappingStringified = JSON.stringify(maps);
|
||||||
|
|
||||||
await Import.query().findById(importFile.id).patch({
|
await this.importModel().query().findById(importFile.id).patch({
|
||||||
mapping: mappingStringified,
|
mapping: mappingStringified,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
@@ -54,7 +59,6 @@ export class ImportFileMapping {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the mapping attributes.
|
* Validate the mapping attributes.
|
||||||
* @param {number} tenantId -
|
|
||||||
* @param {} importFile -
|
* @param {} importFile -
|
||||||
* @param {ImportMappingAttr[]} maps
|
* @param {ImportMappingAttr[]} maps
|
||||||
* @throws {ServiceError(ERRORS.INVALID_MAP_ATTRS)}
|
* @throws {ServiceError(ERRORS.INVALID_MAP_ATTRS)}
|
||||||
@@ -116,7 +120,6 @@ export class ImportFileMapping {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the date format mapping.
|
* Validates the date format mapping.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {string} resource
|
* @param {string} resource
|
||||||
* @param {ImportMappingAttr[]} maps
|
* @param {ImportMappingAttr[]} maps
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
import { Import } from './models/Import';
|
import { ImportModel } from './models/Import';
|
||||||
import { ImportFileMetaTransformer } from './ImportFileMetaTransformer';
|
import { ImportFileMetaTransformer } from './ImportFileMetaTransformer';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFileMeta {
|
export class ImportFileMeta {
|
||||||
constructor(private readonly transformer: TransformerInjectable) {}
|
constructor(
|
||||||
|
private readonly transformer: TransformerInjectable,
|
||||||
|
private readonly tenancyContext: TenancyContext,
|
||||||
|
|
||||||
|
@Inject(ImportModel.name)
|
||||||
|
private readonly importModel: () => typeof ImportModel,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the import meta of the given import model id.
|
* Retrieves the import meta of the given import model id.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {number} importId
|
* @param {number} importId
|
||||||
* @returns {}
|
|
||||||
*/
|
*/
|
||||||
async getImportMeta(importId: string) {
|
async getImportMeta(importId: string) {
|
||||||
const importFile = await Import.query()
|
const tenant = await this.tenancyContext.getTenant();
|
||||||
|
const tenantId = tenant.id;
|
||||||
|
|
||||||
|
const importFile = await this.importModel()
|
||||||
|
.query()
|
||||||
.where('tenantId', tenantId)
|
.where('tenantId', tenantId)
|
||||||
.findOne('importId', importId);
|
.findOne('importId', importId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { ImportFilePreviewPOJO } from './interfaces';
|
import { ImportFilePreviewPOJO } from './interfaces';
|
||||||
import { ImportFileProcess } from './ImportFileProcess';
|
import { ImportFileProcess } from './ImportFileProcess';
|
||||||
import { ImportAls } from './ImportALS';
|
import { ImportAls } from './ImportALS';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { TENANCY_DB_CONNECTION } from '../Tenancy/TenancyDB/TenancyDB.constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFilePreview {
|
export class ImportFilePreview {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly importFile: ImportFileProcess,
|
private readonly importFile: ImportFileProcess,
|
||||||
private readonly importAls: ImportAls,
|
private readonly importAls: ImportAls,
|
||||||
|
|
||||||
|
@Inject(TENANCY_DB_CONNECTION)
|
||||||
|
private readonly tenantKnex: () => Knex
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,8 +32,7 @@ export class ImportFilePreview {
|
|||||||
* @returns {Promise<ImportFilePreviewPOJO>}
|
* @returns {Promise<ImportFilePreviewPOJO>}
|
||||||
*/
|
*/
|
||||||
public async previewAlsRun(importId: string): Promise<ImportFilePreviewPOJO> {
|
public async previewAlsRun(importId: string): Promise<ImportFilePreviewPOJO> {
|
||||||
const knex = this.tenancy.knex(tenantId);
|
const trx = await this.tenantKnex().transaction({ isolationLevel: 'read uncommitted' });
|
||||||
const trx = await knex.transaction({ isolationLevel: 'read uncommitted' });
|
|
||||||
|
|
||||||
const meta = await this.importFile.import(importId, trx);
|
const meta = await this.importFile.import(importId, trx);
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { chain } from 'lodash';
|
import { chain } from 'lodash';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { ERRORS, getUnmappedSheetColumns, readImportFile } from './_utils';
|
import { ERRORS, getUnmappedSheetColumns, readImportFile } from './_utils';
|
||||||
import { ImportFileCommon } from './ImportFileCommon';
|
import { ImportFileCommon } from './ImportFileCommon';
|
||||||
import { ImportFileDataTransformer } from './ImportFileDataTransformer';
|
import { ImportFileDataTransformer } from './ImportFileDataTransformer';
|
||||||
import { ImportFilePreviewPOJO } from './interfaces';
|
import { ImportFilePreviewPOJO } from './interfaces';
|
||||||
import { parseSheetData } from './sheet_utils';
|
import { parseSheetData } from './sheet_utils';
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { ResourceService } from '../Resource/ResourceService';
|
import { ResourceService } from '../Resource/ResourceService';
|
||||||
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
|
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
|
||||||
import { ServiceError } from '../Items/ServiceError';
|
import { ServiceError } from '../Items/ServiceError';
|
||||||
|
import { ImportModel } from './models/Import';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFileProcess {
|
export class ImportFileProcess {
|
||||||
@@ -17,6 +19,10 @@ export class ImportFileProcess {
|
|||||||
private readonly importCommon: ImportFileCommon,
|
private readonly importCommon: ImportFileCommon,
|
||||||
private readonly importParser: ImportFileDataTransformer,
|
private readonly importParser: ImportFileDataTransformer,
|
||||||
private readonly uow: UnitOfWork,
|
private readonly uow: UnitOfWork,
|
||||||
|
private readonly tenancyContext: TenancyContext,
|
||||||
|
|
||||||
|
@Inject(ImportModel.name)
|
||||||
|
private readonly importModel: typeof ImportModel,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +35,11 @@ export class ImportFileProcess {
|
|||||||
importId: string,
|
importId: string,
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<ImportFilePreviewPOJO> {
|
): Promise<ImportFilePreviewPOJO> {
|
||||||
const importFile = await Import.query()
|
const tenant = await this.tenancyContext.getTenant();
|
||||||
|
const tenantId = tenant.id;
|
||||||
|
|
||||||
|
const importFile = await this.importModel
|
||||||
|
.query()
|
||||||
.findOne('importId', importId)
|
.findOne('importId', importId)
|
||||||
.where('tenantId', tenantId)
|
.where('tenantId', tenantId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
@@ -48,28 +58,21 @@ export class ImportFileProcess {
|
|||||||
|
|
||||||
// Runs the importing operation with ability to return errors that will happen.
|
// Runs the importing operation with ability to return errors that will happen.
|
||||||
const [successedImport, failedImport, allData] =
|
const [successedImport, failedImport, allData] =
|
||||||
await this.uow.withTransaction(
|
await this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||||
tenantId,
|
// Prases the sheet json data.
|
||||||
async (trx: Knex.Transaction) => {
|
const parsedData = await this.importParser.parseSheetData(
|
||||||
// Prases the sheet json data.
|
importFile,
|
||||||
const parsedData = await this.importParser.parseSheetData(
|
resourceFields,
|
||||||
tenantId,
|
sheetData,
|
||||||
importFile,
|
trx,
|
||||||
resourceFields,
|
);
|
||||||
sheetData,
|
const [successedImport, failedImport] = await this.importCommon.import(
|
||||||
trx,
|
importFile,
|
||||||
);
|
parsedData,
|
||||||
const [successedImport, failedImport] =
|
trx,
|
||||||
await this.importCommon.import(
|
);
|
||||||
tenantId,
|
return [successedImport, failedImport, parsedData];
|
||||||
importFile,
|
}, trx);
|
||||||
parsedData,
|
|
||||||
trx,
|
|
||||||
);
|
|
||||||
return [successedImport, failedImport, parsedData];
|
|
||||||
},
|
|
||||||
trx,
|
|
||||||
);
|
|
||||||
const mapping = importFile.mappingParsed;
|
const mapping = importFile.mappingParsed;
|
||||||
const errors = chain(failedImport)
|
const errors = chain(failedImport)
|
||||||
.map((oper) => oper.error)
|
.map((oper) => oper.error)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { ImportFilePreviewPOJO } from './interfaces';
|
import { Knex } from 'knex';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
|
import { IImportFileCommitedEventPayload, ImportFilePreviewPOJO } from './interfaces';
|
||||||
import { ImportFileProcess } from './ImportFileProcess';
|
import { ImportFileProcess } from './ImportFileProcess';
|
||||||
import { ImportAls } from './ImportALS';
|
import { ImportAls } from './ImportALS';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
||||||
import { events } from '@/common/events/events';
|
import { events } from '@/common/events/events';
|
||||||
|
import { TENANCY_DB_CONNECTION } from '../Tenancy/TenancyDB/TenancyDB.constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFileProcessCommit {
|
export class ImportFileProcessCommit {
|
||||||
@@ -11,6 +13,9 @@ export class ImportFileProcessCommit {
|
|||||||
private readonly importFile: ImportFileProcess,
|
private readonly importFile: ImportFileProcess,
|
||||||
private readonly importAls: ImportAls,
|
private readonly importAls: ImportAls,
|
||||||
private readonly eventEmitter: EventEmitter2,
|
private readonly eventEmitter: EventEmitter2,
|
||||||
|
|
||||||
|
@Inject(TENANCY_DB_CONNECTION)
|
||||||
|
private readonly tenantKnex: () => Knex,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,8 +35,9 @@ export class ImportFileProcessCommit {
|
|||||||
* @returns {Promise<ImportFilePreviewPOJO>}
|
* @returns {Promise<ImportFilePreviewPOJO>}
|
||||||
*/
|
*/
|
||||||
public async commitAlsRun(importId: string): Promise<ImportFilePreviewPOJO> {
|
public async commitAlsRun(importId: string): Promise<ImportFilePreviewPOJO> {
|
||||||
const trx = await knex.transaction({ isolationLevel: 'read uncommitted' });
|
const trx = await this.tenantKnex().transaction({
|
||||||
|
isolationLevel: 'read uncommitted',
|
||||||
|
});
|
||||||
const meta = await this.importFile.import(importId, trx);
|
const meta = await this.importFile.import(importId, trx);
|
||||||
|
|
||||||
// Commit the successed transaction.
|
// Commit the successed transaction.
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import { ResourceService } from '../Resource/ResourceService';
|
|||||||
import { ImportFileCommon } from './ImportFileCommon';
|
import { ImportFileCommon } from './ImportFileCommon';
|
||||||
import { ImportFileDataValidator } from './ImportFileDataValidator';
|
import { ImportFileDataValidator } from './ImportFileDataValidator';
|
||||||
import { ImportFileUploadPOJO } from './interfaces';
|
import { ImportFileUploadPOJO } from './interfaces';
|
||||||
import { Import } from '@/system/models';
|
|
||||||
import { parseSheetData } from './sheet_utils';
|
import { parseSheetData } from './sheet_utils';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ImportModel } from './models/Import';
|
||||||
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportFileUploadService {
|
export class ImportFileUploadService {
|
||||||
@@ -19,6 +20,10 @@ export class ImportFileUploadService {
|
|||||||
private resourceService: ResourceService,
|
private resourceService: ResourceService,
|
||||||
private importFileCommon: ImportFileCommon,
|
private importFileCommon: ImportFileCommon,
|
||||||
private importValidator: ImportFileDataValidator,
|
private importValidator: ImportFileDataValidator,
|
||||||
|
private tenancyContext: TenancyContext,
|
||||||
|
|
||||||
|
@Inject(ImportModel.name)
|
||||||
|
private readonly importModel: typeof ImportModel,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,12 +41,7 @@ export class ImportFileUploadService {
|
|||||||
params: Record<string, number | string>,
|
params: Record<string, number | string>,
|
||||||
): Promise<ImportFileUploadPOJO> {
|
): Promise<ImportFileUploadPOJO> {
|
||||||
try {
|
try {
|
||||||
return await this.importUnhandled(
|
return await this.importUnhandled(resourceName, filename, params);
|
||||||
tenantId,
|
|
||||||
resourceName,
|
|
||||||
filename,
|
|
||||||
params,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
deleteImportFile(filename);
|
deleteImportFile(filename);
|
||||||
throw err;
|
throw err;
|
||||||
@@ -81,15 +81,18 @@ export class ImportFileUploadService {
|
|||||||
await this.importFileCommon.validateParamsSchema(resource, params);
|
await this.importFileCommon.validateParamsSchema(resource, params);
|
||||||
|
|
||||||
// Validates importable params asyncly.
|
// Validates importable params asyncly.
|
||||||
await this.importFileCommon.validateParams(tenantId, resource, params);
|
await this.importFileCommon.validateParams(resource, params);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const _params = this.importFileCommon.transformParams(resource, params);
|
const _params = this.importFileCommon.transformParams(resource, params);
|
||||||
const paramsStringified = JSON.stringify(_params);
|
const paramsStringified = JSON.stringify(_params);
|
||||||
|
|
||||||
|
const tenant = await this.tenancyContext.getTenant();
|
||||||
|
const tenantId = tenant.id;
|
||||||
|
|
||||||
// Store the import model with related metadata.
|
// Store the import model with related metadata.
|
||||||
const importFile = await Import.query().insert({
|
const importFile = await this.importModel.query().insert({
|
||||||
filename,
|
filename,
|
||||||
resource,
|
resource,
|
||||||
tenantId,
|
tenantId,
|
||||||
@@ -97,10 +100,8 @@ export class ImportFileUploadService {
|
|||||||
columns: coumnsStringified,
|
columns: coumnsStringified,
|
||||||
params: paramsStringified,
|
params: paramsStringified,
|
||||||
});
|
});
|
||||||
const resourceColumnsMap = this.resourceService.getResourceFields2(
|
const resourceColumnsMap =
|
||||||
tenantId,
|
this.resourceService.getResourceFields2(resource);
|
||||||
resource,
|
|
||||||
);
|
|
||||||
const resourceColumns = getResourceColumns(resourceColumnsMap);
|
const resourceColumns = getResourceColumns(resourceColumnsMap);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,34 +1,36 @@
|
|||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import bluebird from 'bluebird';
|
import bluebird from 'bluebird';
|
||||||
import { deleteImportFile } from './_utils';
|
import { deleteImportFile } from './_utils';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Import } from './models/Import';
|
import { ImportModel } from './models/Import';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportDeleteExpiredFiles {
|
export class ImportDeleteExpiredFiles {
|
||||||
|
constructor(
|
||||||
|
@Inject(ImportModel.name)
|
||||||
|
private readonly importModel: typeof ImportModel,
|
||||||
|
) {}
|
||||||
/**
|
/**
|
||||||
* Delete expired files.
|
* Delete expired files.
|
||||||
*/
|
*/
|
||||||
async deleteExpiredFiles() {
|
async deleteExpiredFiles() {
|
||||||
const yesterday = moment().subtract(1, 'hour').format('YYYY-MM-DD HH:mm');
|
const yesterday = moment().subtract(1, 'hour').format('YYYY-MM-DD HH:mm');
|
||||||
|
|
||||||
const expiredImports = await Import.query().where(
|
const expiredImports = await this.importModel
|
||||||
'createdAt',
|
.query()
|
||||||
'<',
|
.where('createdAt', '<', yesterday);
|
||||||
yesterday
|
|
||||||
);
|
|
||||||
await bluebird.map(
|
await bluebird.map(
|
||||||
expiredImports,
|
expiredImports,
|
||||||
async (expiredImport) => {
|
async (expiredImport) => {
|
||||||
await deleteImportFile(expiredImport.filename);
|
await deleteImportFile(expiredImport.filename);
|
||||||
},
|
},
|
||||||
{ concurrency: 10 }
|
{ concurrency: 10 },
|
||||||
);
|
);
|
||||||
const expiredImportsIds = expiredImports.map(
|
const expiredImportsIds = expiredImports.map(
|
||||||
(expiredImport) => expiredImport.id
|
(expiredImport) => expiredImport.id,
|
||||||
);
|
);
|
||||||
if (expiredImportsIds.length > 0) {
|
if (expiredImportsIds.length > 0) {
|
||||||
await Import.query().whereIn('id', expiredImportsIds).delete();
|
await this.importModel.query().whereIn('id', expiredImportsIds).delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class ImportableResources {
|
|||||||
// resource: 'UncategorizedCashflowTransaction',
|
// resource: 'UncategorizedCashflowTransaction',
|
||||||
// importable: UncategorizedTransactionsImportable,
|
// importable: UncategorizedTransactionsImportable,
|
||||||
// },
|
// },
|
||||||
// { resource: 'Customer', importable: CustomersImportable },
|
// { resource: 'Customer', importable: CustomersImportable },
|
||||||
// { resource: 'Vendor', importable: VendorsImportable },
|
// { resource: 'Vendor', importable: VendorsImportable },
|
||||||
// { resource: 'Item', importable: ItemsImportable },
|
// { resource: 'Item', importable: ItemsImportable },
|
||||||
// { resource: 'ItemCategory', importable: ItemCategoriesImportable },
|
// { resource: 'ItemCategory', importable: ItemCategoriesImportable },
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import * as Yup from 'yup';
|
|||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import fs from 'fs/promises';
|
import * as fs from 'fs/promises';
|
||||||
import path from 'path';
|
import * as path from 'path';
|
||||||
import {
|
import {
|
||||||
defaultTo,
|
defaultTo,
|
||||||
upperFirst,
|
upperFirst,
|
||||||
@@ -18,11 +18,11 @@ import {
|
|||||||
split,
|
split,
|
||||||
last,
|
last,
|
||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
import pluralize from 'pluralize';
|
import * as pluralize from 'pluralize';
|
||||||
import { ResourceMetaFieldsMap } from './interfaces';
|
import { ResourceMetaFieldsMap } from './interfaces';
|
||||||
import { IModelMetaField, IModelMetaField2 } from '@/interfaces';
|
|
||||||
import { ServiceError } from '@/exceptions';
|
|
||||||
import { multiNumberParse } from '@/utils/multi-number-parse';
|
import { multiNumberParse } from '@/utils/multi-number-parse';
|
||||||
|
import { ServiceError } from '../Items/ServiceError';
|
||||||
|
import { IModelMetaField, IModelMetaField2 } from '@/interfaces/Model';
|
||||||
|
|
||||||
export const ERRORS = {
|
export const ERRORS = {
|
||||||
RESOURCE_NOT_IMPORTABLE: 'RESOURCE_NOT_IMPORTABLE',
|
RESOURCE_NOT_IMPORTABLE: 'RESOURCE_NOT_IMPORTABLE',
|
||||||
@@ -70,13 +70,13 @@ export const convertFieldsToYupValidation = (fields: ResourceMetaFieldsMap) => {
|
|||||||
if (!isUndefined(field.minLength)) {
|
if (!isUndefined(field.minLength)) {
|
||||||
fieldSchema = fieldSchema.min(
|
fieldSchema = fieldSchema.min(
|
||||||
field.minLength,
|
field.minLength,
|
||||||
`Minimum length is ${field.minLength} characters`
|
`Minimum length is ${field.minLength} characters`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!isUndefined(field.maxLength)) {
|
if (!isUndefined(field.maxLength)) {
|
||||||
fieldSchema = fieldSchema.max(
|
fieldSchema = fieldSchema.max(
|
||||||
field.maxLength,
|
field.maxLength,
|
||||||
`Maximum length is ${field.maxLength} characters`
|
`Maximum length is ${field.maxLength} characters`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (field.fieldType === 'number') {
|
} else if (field.fieldType === 'number') {
|
||||||
@@ -106,11 +106,12 @@ export const convertFieldsToYupValidation = (fields: ResourceMetaFieldsMap) => {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return moment(val, 'YYYY-MM-DD', true).isValid();
|
return moment(val, 'YYYY-MM-DD', true).isValid();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
} else if (field.fieldType === 'url') {
|
} else if (field.fieldType === 'url') {
|
||||||
fieldSchema = fieldSchema.url();
|
fieldSchema = fieldSchema.url();
|
||||||
} else if (field.fieldType === 'collection') {
|
} else if (field.fieldType === 'collection') {
|
||||||
|
// @ts-expect-error
|
||||||
const nestedFieldShema = convertFieldsToYupValidation(field.fields);
|
const nestedFieldShema = convertFieldsToYupValidation(field.fields);
|
||||||
fieldSchema = Yup.array().label(field.name);
|
fieldSchema = Yup.array().label(field.name);
|
||||||
|
|
||||||
@@ -149,12 +150,12 @@ const parseFieldName = (fieldName: string, field: IModelMetaField) => {
|
|||||||
*/
|
*/
|
||||||
export const getUnmappedSheetColumns = (columns, mapping) => {
|
export const getUnmappedSheetColumns = (columns, mapping) => {
|
||||||
return columns.filter(
|
return columns.filter(
|
||||||
(column) => !mapping.some((map) => map.from === column)
|
(column) => !mapping.some((map) => map.from === column),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sanitizeResourceName = (resourceName: string) => {
|
export const sanitizeResourceName = (resourceName: string) => {
|
||||||
return upperFirst(camelCase(pluralize.singular(resourceName)));
|
return upperFirst(camelCase(pluralize(resourceName, 1)));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSheetColumns = (sheetData: unknown[]) => {
|
export const getSheetColumns = (sheetData: unknown[]) => {
|
||||||
@@ -170,11 +171,11 @@ export const getSheetColumns = (sheetData: unknown[]) => {
|
|||||||
*/
|
*/
|
||||||
export const getUniqueImportableValue = (
|
export const getUniqueImportableValue = (
|
||||||
importableFields: { [key: string]: IModelMetaField2 },
|
importableFields: { [key: string]: IModelMetaField2 },
|
||||||
objectDTO: Record<string, any>
|
objectDTO: Record<string, any>,
|
||||||
) => {
|
) => {
|
||||||
const uniqueImportableValue = pickBy(
|
const uniqueImportableValue = pickBy(
|
||||||
importableFields,
|
importableFields,
|
||||||
(field) => field.unique
|
(field) => field.unique,
|
||||||
);
|
);
|
||||||
const uniqueImportableKeys = Object.keys(uniqueImportableValue);
|
const uniqueImportableKeys = Object.keys(uniqueImportableValue);
|
||||||
const uniqueImportableKey = first(uniqueImportableKeys);
|
const uniqueImportableKey = first(uniqueImportableKeys);
|
||||||
@@ -254,7 +255,7 @@ export const getResourceColumns = (resourceColumns: {
|
|||||||
(group: string) =>
|
(group: string) =>
|
||||||
([fieldKey, { name, importHint, required, order, ...field }]: [
|
([fieldKey, { name, importHint, required, order, ...field }]: [
|
||||||
string,
|
string,
|
||||||
IModelMetaField2
|
IModelMetaField2,
|
||||||
]) => {
|
]) => {
|
||||||
const extra: Record<string, any> = {};
|
const extra: Record<string, any> = {};
|
||||||
const key = fieldKey;
|
const key = fieldKey;
|
||||||
@@ -299,7 +300,7 @@ export const valueParser =
|
|||||||
// Parses the enumeration value.
|
// Parses the enumeration value.
|
||||||
} else if (field.fieldType === 'enumeration') {
|
} else if (field.fieldType === 'enumeration') {
|
||||||
const option = get(field, 'options', []).find(
|
const option = get(field, 'options', []).find(
|
||||||
(option) => option.label?.toLowerCase() === value?.toLowerCase()
|
(option) => option.label?.toLowerCase() === value?.toLowerCase(),
|
||||||
);
|
);
|
||||||
_value = get(option, 'key');
|
_value = get(option, 'key');
|
||||||
// Parses the numeric value.
|
// Parses the numeric value.
|
||||||
@@ -336,7 +337,7 @@ export const valueParser =
|
|||||||
* @param {string} key - Mapped key path. formats: `group.key` or `key`.
|
* @param {string} key - Mapped key path. formats: `group.key` or `key`.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export const parseKey: R.Curry<string> = R.curry(
|
export const parseKey = R.curry(
|
||||||
(fields: { [key: string]: IModelMetaField2 }, key: string) => {
|
(fields: { [key: string]: IModelMetaField2 }, key: string) => {
|
||||||
const fieldKey = getFieldKey(key);
|
const fieldKey = getFieldKey(key);
|
||||||
const field = fields[fieldKey];
|
const field = fields[fieldKey];
|
||||||
@@ -355,7 +356,7 @@ export const parseKey: R.Curry<string> = R.curry(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _key;
|
return _key;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -398,11 +399,11 @@ export const getFieldKey = (input: string) => {
|
|||||||
export function aggregate(
|
export function aggregate(
|
||||||
input: Array<any>,
|
input: Array<any>,
|
||||||
comparatorAttr: string,
|
comparatorAttr: string,
|
||||||
groupOn: string
|
groupOn: string,
|
||||||
): Array<Record<string, any>> {
|
): Array<Record<string, any>> {
|
||||||
return input.reduce((acc, curr) => {
|
return input.reduce((acc, curr) => {
|
||||||
const existingEntry = acc.find(
|
const existingEntry = acc.find(
|
||||||
(entry) => entry[comparatorAttr] === curr[comparatorAttr]
|
(entry) => entry[comparatorAttr] === curr[comparatorAttr],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existingEntry) {
|
if (existingEntry) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IModelMetaField2 } from "@/interfaces/Model";
|
import { IModelMetaField2 } from "@/interfaces/Model";
|
||||||
import { Import } from "./models/Import";
|
import { ImportModelShape } from "./models/Import";
|
||||||
|
|
||||||
export interface ImportMappingAttr {
|
export interface ImportMappingAttr {
|
||||||
from: string;
|
from: string;
|
||||||
@@ -65,7 +65,7 @@ export interface ImportOperError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ImportableContext {
|
export interface ImportableContext {
|
||||||
import: Import;
|
import: ImportModelShape;
|
||||||
rowIndex: number;
|
rowIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,3 +75,9 @@ export const ImportDateFormats = [
|
|||||||
'MM/dd/yy',
|
'MM/dd/yy',
|
||||||
'dd/MMM/yyyy',
|
'dd/MMM/yyyy',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export interface IImportFileCommitedEventPayload {
|
||||||
|
importId: string;
|
||||||
|
meta: ImportFilePreviewPOJO;
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Model, ModelObject } from 'objection';
|
import { Model, ModelObject } from 'objection';
|
||||||
// import SystemModel from './SystemModel';
|
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
|
||||||
export class Import extends BaseModel {
|
export class ImportModel extends BaseModel {
|
||||||
resource: string;
|
resource!: string;
|
||||||
tenantId: number;
|
tenantId!: number;
|
||||||
|
filename!: string;
|
||||||
mapping!: string;
|
mapping!: string;
|
||||||
columns!: string;
|
columns!: string;
|
||||||
params!: string;
|
params!: string;
|
||||||
|
importId!: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
@@ -84,4 +85,4 @@ export class Import extends BaseModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ImportShape = ModelObject<Import>;
|
export type ImportModelShape = ModelObject<ImportModel>;
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Exportable } from '../Export/Exportable';
|
import { Exportable } from '../Export/Exportable';
|
||||||
// import { IAccountsFilter, IAccountsStructureType } from '@/interfaces';
|
import { ItemCategoryApplication } from './ItemCategory.application';
|
||||||
// import ItemCategoriesService from './ItemCategoriesService';
|
import { IItemCategoriesFilter } from './ItemCategory.interfaces';
|
||||||
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
|
import { ItemCategory } from './models/ItemCategory.model';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class ItemCategoriesExportable extends Exportable {
|
@ExportableService({ name: ItemCategory.name })
|
||||||
// @Inject()
|
export class ItemCategoriesExportable extends Exportable {
|
||||||
// private itemCategoriesApplication: ItemCategoriesService;
|
constructor(private readonly itemCategoryApp: ItemCategoryApplication) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {number} tenantId
|
||||||
// * @returns
|
* @returns
|
||||||
// */
|
*/
|
||||||
// public exportable(tenantId: number, query: IAccountsFilter) {
|
public exportable(query: Partial<IItemCategoriesFilter>) {
|
||||||
// const parsedQuery = {
|
const parsedQuery = {
|
||||||
// sortOrder: 'desc',
|
...query
|
||||||
// columnSortBy: 'created_at',
|
} as IItemCategoriesFilter;
|
||||||
// inactiveMode: false,
|
|
||||||
// ...query,
|
|
||||||
// structure: IAccountsStructureType.Flat,
|
|
||||||
// } as IAccountsFilter;
|
|
||||||
|
|
||||||
// return this.itemCategoriesApplication
|
return this.itemCategoryApp
|
||||||
// .getItemCategoriesList(tenantId, parsedQuery, {})
|
.getItemCategories(parsedQuery)
|
||||||
// .then((output) => output.itemCategories);
|
.then((output) => output.itemCategories);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,38 +1,32 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Importable } from '../Import/Importable';
|
||||||
// import ItemCategoriesService from './ItemCategoriesService';
|
import { Knex } from 'knex';
|
||||||
// import { Importable } from '../Import/Importable';
|
import { ItemCategoriesSampleData } from './constants';
|
||||||
// import { Knex } from 'knex';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { IItemCategoryOTD } from '@/interfaces';
|
import { CreateItemCategoryDto } from './dtos/ItemCategory.dto';
|
||||||
// import { ItemCategoriesSampleData } from './constants';
|
import { ItemCategoryApplication } from './ItemCategory.application';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class ItemCategoriesImportable extends Importable {
|
export class ItemCategoriesImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly itemCategoriesApp: ItemCategoryApplication) {
|
||||||
// private itemCategoriesService: ItemCategoriesService;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to create new item category service.
|
* Importing to create new item category service.
|
||||||
// * @param {number} tenantId
|
* @param {CreateItemCategoryDto} createDTO
|
||||||
// * @param {any} createDTO
|
* @param {Knex.Transaction} trx
|
||||||
// * @param {Knex.Transaction} trx
|
*/
|
||||||
// */
|
public async importable(
|
||||||
// public async importable(
|
createDTO: CreateItemCategoryDto,
|
||||||
// tenantId: number,
|
trx?: Knex.Transaction,
|
||||||
// createDTO: IItemCategoryOTD,
|
) {
|
||||||
// trx?: Knex.Transaction
|
await this.itemCategoriesApp.createItemCategory(createDTO, trx);
|
||||||
// ) {
|
}
|
||||||
// await this.itemCategoriesService.newItemCategory(
|
|
||||||
// tenantId,
|
|
||||||
// createDTO,
|
|
||||||
// {},
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Item categories sample data used to download sample sheet file.
|
* Item categories sample data used to download sample sheet file.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return ItemCategoriesSampleData;
|
return ItemCategoriesSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { EditItemCategoryService } from './commands/EditItemCategory.service';
|
|||||||
import { GetItemCategoryService } from './queries/GetItemCategory.service';
|
import { GetItemCategoryService } from './queries/GetItemCategory.service';
|
||||||
import { GetItemCategoriesService } from './queries/GetItemCategories.service';
|
import { GetItemCategoriesService } from './queries/GetItemCategories.service';
|
||||||
import { CreateItemCategoryDto, EditItemCategoryDto } from './dtos/ItemCategory.dto';
|
import { CreateItemCategoryDto, EditItemCategoryDto } from './dtos/ItemCategory.dto';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ItemCategoryApplication {
|
export class ItemCategoryApplication {
|
||||||
@@ -33,8 +34,9 @@ export class ItemCategoryApplication {
|
|||||||
*/
|
*/
|
||||||
public createItemCategory(
|
public createItemCategory(
|
||||||
itemCategoryDTO: CreateItemCategoryDto,
|
itemCategoryDTO: CreateItemCategoryDto,
|
||||||
|
trx?: Knex.Transaction,
|
||||||
) {
|
) {
|
||||||
return this.createItemCategoryService.newItemCategory(itemCategoryDTO);
|
return this.createItemCategoryService.newItemCategory(itemCategoryDTO, trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { TransformerInjectable } from '../Transformer/TransformerInjectable.serv
|
|||||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
import { GetItemCategoriesService } from './queries/GetItemCategories.service';
|
import { GetItemCategoriesService } from './queries/GetItemCategories.service';
|
||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
|
import { ItemCategoriesExportable } from './ItemCategoriesExportable';
|
||||||
|
import { ItemCategoriesImportable } from './ItemCategoriesImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule, DynamicListModule],
|
imports: [TenancyDatabaseModule, DynamicListModule],
|
||||||
@@ -25,6 +27,12 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
CommandItemCategoryValidatorService,
|
CommandItemCategoryValidatorService,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
|
ItemCategoriesExportable,
|
||||||
|
ItemCategoriesImportable,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
ItemCategoriesExportable,
|
||||||
|
ItemCategoriesImportable,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ItemCategoryModule {}
|
export class ItemCategoryModule {}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export const ItemCategoryMeta = {
|
||||||
|
defaultFilterField: 'name',
|
||||||
|
defaultSort: {
|
||||||
|
sortField: 'name',
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
},
|
||||||
|
importable: true,
|
||||||
|
exportable: true,
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
name: 'item_category.field.name',
|
||||||
|
column: 'name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'item_category.field.description',
|
||||||
|
column: 'description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
name: 'item_category.field.count',
|
||||||
|
column: 'count',
|
||||||
|
fieldType: 'number',
|
||||||
|
virtualColumn: true,
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'item_category.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
columnType: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
name: {
|
||||||
|
name: 'item_category.field.name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'item_category.field.description',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
name: 'item_category.field.count',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
name: 'item_category.field.created_at',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
name: {
|
||||||
|
name: 'item_category.field.name',
|
||||||
|
column: 'name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'item_category.field.description',
|
||||||
|
column: 'description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
|
||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { ItemCategoryMeta } from './ItemCategory.meta';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
|
@InjectModelMeta(ItemCategoryMeta)
|
||||||
export class ItemCategory extends TenantBaseModel {
|
export class ItemCategory extends TenantBaseModel {
|
||||||
name!: string;
|
name!: string;
|
||||||
description!: string;
|
description!: string;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { ItemsEntriesService } from './ItemsEntries.service';
|
|||||||
import { GetItemsService } from './GetItems.service';
|
import { GetItemsService } from './GetItems.service';
|
||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdjustments.module';
|
import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdjustments.module';
|
||||||
|
import { ItemsExportable } from './ItemsExportable.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -38,7 +39,8 @@ import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdju
|
|||||||
TenancyContext,
|
TenancyContext,
|
||||||
TransformerInjectable,
|
TransformerInjectable,
|
||||||
ItemsEntriesService,
|
ItemsEntriesService,
|
||||||
|
ItemsExportable,
|
||||||
],
|
],
|
||||||
exports: [ItemsEntriesService],
|
exports: [ItemsEntriesService, ItemsExportable],
|
||||||
})
|
})
|
||||||
export class ItemsModule {}
|
export class ItemsModule {}
|
||||||
|
|||||||
36
packages/server/src/modules/Items/ItemsExportable.service.ts
Normal file
36
packages/server/src/modules/Items/ItemsExportable.service.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Global, Injectable } from '@nestjs/common';
|
||||||
|
import { Exportable } from '../Export/Exportable';
|
||||||
|
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
||||||
|
import { ItemsApplicationService } from './ItemsApplication.service';
|
||||||
|
import { IItemsFilter } from './types/Items.types';
|
||||||
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
|
import { Item } from './models/Item';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@ExportableService({ name: Item.name })
|
||||||
|
@Global()
|
||||||
|
export class ItemsExportable extends Exportable {
|
||||||
|
constructor(
|
||||||
|
private readonly itemsApplication: ItemsApplicationService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the accounts data to exportable sheet.
|
||||||
|
* @param {IItemsFilter} query - Items export query.
|
||||||
|
*/
|
||||||
|
public exportable(query: IItemsFilter) {
|
||||||
|
const parsedQuery = {
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
columnSortBy: 'created_at',
|
||||||
|
page: 1,
|
||||||
|
...query,
|
||||||
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
|
} as IItemsFilter;
|
||||||
|
|
||||||
|
return this.itemsApplication
|
||||||
|
.getItems(parsedQuery)
|
||||||
|
.then((output) => output.items);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
packages/server/src/modules/Items/ItemsImportable.service.ts
Normal file
36
packages/server/src/modules/Items/ItemsImportable.service.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Importable } from '../Import/Importable';
|
||||||
|
import { CreateItemService } from './CreateItem.service';
|
||||||
|
import { CreateItemDto } from './dtos/Item.dto';
|
||||||
|
import { ItemsSampleData } from './Items.constants';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ItemsImportable extends Importable {
|
||||||
|
constructor(
|
||||||
|
private readonly createItemService: CreateItemService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapps the imported data to create a new item service.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {ICustomerNewDTO} createDTO
|
||||||
|
* @param {Knex.Transaction} trx
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
public async importable(
|
||||||
|
createDTO: CreateItemDto,
|
||||||
|
trx?: Knex.Transaction<any, any[]>
|
||||||
|
): Promise<void> {
|
||||||
|
await this.createItemService.createItem(createDTO, trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the sample data of customers used to download sample sheet.
|
||||||
|
*/
|
||||||
|
public sampleData(): any[] {
|
||||||
|
return ItemsSampleData;
|
||||||
|
}
|
||||||
|
}
|
||||||
309
packages/server/src/modules/Items/models/Item.meta.ts
Normal file
309
packages/server/src/modules/Items/models/Item.meta.ts
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
export const ItemMeta = {
|
||||||
|
importable: true,
|
||||||
|
exportable: true,
|
||||||
|
defaultFilterField: 'name',
|
||||||
|
defaultSort: {
|
||||||
|
sortField: 'name',
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
},
|
||||||
|
print: {
|
||||||
|
pageTitle: 'Items',
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
type: {
|
||||||
|
name: 'item.field.type',
|
||||||
|
column: 'type',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'inventory', label: 'item.field.type.inventory' },
|
||||||
|
{ key: 'service', label: 'item.field.type.service' },
|
||||||
|
{ key: 'non-inventory', label: 'item.field.type.non-inventory' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
name: 'item.field.name',
|
||||||
|
column: 'name',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
name: 'item.field.code',
|
||||||
|
column: 'code',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
sellable: {
|
||||||
|
name: 'item.field.sellable',
|
||||||
|
column: 'sellable',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
purchasable: {
|
||||||
|
name: 'item.field.purchasable',
|
||||||
|
column: 'purchasable',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
sell_price: {
|
||||||
|
name: 'item.field.sell_price',
|
||||||
|
column: 'sell_price',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
cost_price: {
|
||||||
|
name: 'item.field.cost_price',
|
||||||
|
column: 'cost_price',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
cost_account: {
|
||||||
|
name: 'item.field.cost_account',
|
||||||
|
column: 'cost_account_id',
|
||||||
|
fieldType: 'relation',
|
||||||
|
|
||||||
|
relationType: 'enumeration',
|
||||||
|
relationKey: 'costAccount',
|
||||||
|
|
||||||
|
relationEntityLabel: 'name',
|
||||||
|
relationEntityKey: 'slug',
|
||||||
|
},
|
||||||
|
sell_account: {
|
||||||
|
name: 'item.field.sell_account',
|
||||||
|
column: 'sell_account_id',
|
||||||
|
fieldType: 'relation',
|
||||||
|
|
||||||
|
relationType: 'enumeration',
|
||||||
|
relationKey: 'sellAccount',
|
||||||
|
|
||||||
|
relationEntityLabel: 'name',
|
||||||
|
relationEntityKey: 'slug',
|
||||||
|
},
|
||||||
|
inventory_account: {
|
||||||
|
name: 'item.field.inventory_account',
|
||||||
|
column: 'inventory_account_id',
|
||||||
|
|
||||||
|
relationType: 'enumeration',
|
||||||
|
relationKey: 'inventoryAccount',
|
||||||
|
|
||||||
|
relationEntityLabel: 'name',
|
||||||
|
relationEntityKey: 'slug',
|
||||||
|
},
|
||||||
|
sell_description: {
|
||||||
|
name: 'Sell description',
|
||||||
|
column: 'sell_description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
purchase_description: {
|
||||||
|
name: 'Purchase description',
|
||||||
|
column: 'purchase_description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
quantity_on_hand: {
|
||||||
|
name: 'item.field.quantity_on_hand',
|
||||||
|
column: 'quantity_on_hand',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'item.field.note',
|
||||||
|
column: 'note',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
name: 'item.field.category',
|
||||||
|
column: 'category_id',
|
||||||
|
|
||||||
|
relationType: 'enumeration',
|
||||||
|
relationKey: 'category',
|
||||||
|
|
||||||
|
relationEntityLabel: 'name',
|
||||||
|
relationEntityKey: 'id',
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'item.field.active',
|
||||||
|
column: 'active',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
filterable: false,
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'item.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
columnType: 'date',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
type: {
|
||||||
|
name: 'item.field.type',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
accessor: 'typeFormatted',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
name: 'item.field.name',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
name: 'item.field.code',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
sellable: {
|
||||||
|
name: 'item.field.sellable',
|
||||||
|
type: 'boolean',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
purchasable: {
|
||||||
|
name: 'item.field.purchasable',
|
||||||
|
type: 'boolean',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
sellPrice: {
|
||||||
|
name: 'item.field.sell_price',
|
||||||
|
type: 'number',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
costPrice: {
|
||||||
|
name: 'item.field.cost_price',
|
||||||
|
type: 'number',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
costAccount: {
|
||||||
|
name: 'item.field.cost_account',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'costAccount.name',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
sellAccount: {
|
||||||
|
name: 'item.field.sell_account',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'sellAccount.name',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
inventoryAccount: {
|
||||||
|
name: 'item.field.inventory_account',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'inventoryAccount.name',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
sellDescription: {
|
||||||
|
name: 'Sell description',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
purchaseDescription: {
|
||||||
|
name: 'Purchase description',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
quantityOnHand: {
|
||||||
|
name: 'item.field.quantity_on_hand',
|
||||||
|
type: 'number',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'item.field.note',
|
||||||
|
type: 'text',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
name: 'item.field.category',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'category.name',
|
||||||
|
exportable: true,
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'item.field.active',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
name: 'item.field.created_at',
|
||||||
|
type: 'date',
|
||||||
|
exportable: true,
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
type: {
|
||||||
|
name: 'item.field.type',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'inventory', label: 'item.field.type.inventory' },
|
||||||
|
{ key: 'service', label: 'item.field.type.service' },
|
||||||
|
{ key: 'non-inventory', label: 'item.field.type.non-inventory' },
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
name: 'item.field.name',
|
||||||
|
fieldType: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
name: 'item.field.code',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
sellable: {
|
||||||
|
name: 'item.field.sellable',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
purchasable: {
|
||||||
|
name: 'item.field.purchasable',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
sellPrice: {
|
||||||
|
name: 'item.field.sell_price',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
costPrice: {
|
||||||
|
name: 'item.field.cost_price',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
costAccountId: {
|
||||||
|
name: 'item.field.cost_account',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Account',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
importHint: 'Matches the account name or code.',
|
||||||
|
},
|
||||||
|
sellAccountId: {
|
||||||
|
name: 'item.field.sell_account',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Account',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
importHint: 'Matches the account name or code.',
|
||||||
|
},
|
||||||
|
inventoryAccountId: {
|
||||||
|
name: 'item.field.inventory_account',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Account',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
importHint: 'Matches the account name or code.',
|
||||||
|
},
|
||||||
|
sellDescription: {
|
||||||
|
name: 'Sell Description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
purchaseDescription: {
|
||||||
|
name: 'Purchase Description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'item.field.note',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
categoryId: {
|
||||||
|
name: 'item.field.category',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'ItemCategory',
|
||||||
|
relationImportMatch: ['name'],
|
||||||
|
importHint: 'Matches the category name.',
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
name: 'item.field.active',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
|
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { ItemMeta } from './Item.meta';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
|
@InjectModelMeta(ItemMeta)
|
||||||
export class Item extends TenantBaseModel {
|
export class Item extends TenantBaseModel {
|
||||||
public readonly quantityOnHand: number;
|
public readonly quantityOnHand: number;
|
||||||
public readonly name: string;
|
public readonly name: string;
|
||||||
@@ -48,6 +53,13 @@ export class Item extends TenantBaseModel {
|
|||||||
}
|
}
|
||||||
return q;
|
return q;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inactive/Active mode.
|
||||||
|
*/
|
||||||
|
inactiveMode(query, active = false) {
|
||||||
|
query.where('items.active', !active);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,13 @@ import { GetManualJournal } from './queries/GetManualJournal.service';
|
|||||||
import { ManualJournalWriteGLSubscriber } from './commands/ManualJournalGLEntriesSubscriber';
|
import { ManualJournalWriteGLSubscriber } from './commands/ManualJournalGLEntriesSubscriber';
|
||||||
import { ManualJournalGLEntries } from './commands/ManualJournalGLEntries';
|
import { ManualJournalGLEntries } from './commands/ManualJournalGLEntries';
|
||||||
import { LedgerModule } from '../Ledger/Ledger.module';
|
import { LedgerModule } from '../Ledger/Ledger.module';
|
||||||
|
import { ManualJournalsExportable } from './commands/ManualJournalExportable';
|
||||||
|
import { ManualJournalImportable } from './commands/ManualJournalsImport';
|
||||||
|
import { GetManualJournals } from './queries/GetManualJournals.service';
|
||||||
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [BranchesModule, LedgerModule],
|
imports: [BranchesModule, LedgerModule, DynamicListModule],
|
||||||
controllers: [ManualJournalsController],
|
controllers: [ManualJournalsController],
|
||||||
providers: [
|
providers: [
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
@@ -32,8 +36,12 @@ import { LedgerModule } from '../Ledger/Ledger.module';
|
|||||||
AutoIncrementOrdersService,
|
AutoIncrementOrdersService,
|
||||||
ManualJournalsApplication,
|
ManualJournalsApplication,
|
||||||
GetManualJournal,
|
GetManualJournal,
|
||||||
|
GetManualJournals,
|
||||||
ManualJournalGLEntries,
|
ManualJournalGLEntries,
|
||||||
ManualJournalWriteGLSubscriber
|
ManualJournalWriteGLSubscriber,
|
||||||
|
ManualJournalsExportable,
|
||||||
|
ManualJournalImportable,
|
||||||
],
|
],
|
||||||
|
exports: [ManualJournalsExportable, ManualJournalImportable],
|
||||||
})
|
})
|
||||||
export class ManualJournalsModule {}
|
export class ManualJournalsModule {}
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import { EditManualJournal } from './commands/EditManualJournal.service';
|
|||||||
import { PublishManualJournal } from './commands/PublishManualJournal.service';
|
import { PublishManualJournal } from './commands/PublishManualJournal.service';
|
||||||
import { GetManualJournal } from './queries/GetManualJournal.service';
|
import { GetManualJournal } from './queries/GetManualJournal.service';
|
||||||
import { DeleteManualJournalService } from './commands/DeleteManualJournal.service';
|
import { DeleteManualJournalService } from './commands/DeleteManualJournal.service';
|
||||||
import { IManualJournalDTO, } from './types/ManualJournals.types';
|
import { IManualJournalsFilter } from './types/ManualJournals.types';
|
||||||
import { CreateManualJournalDto, EditManualJournalDto } from './dtos/ManualJournal.dto';
|
import {
|
||||||
|
CreateManualJournalDto,
|
||||||
|
EditManualJournalDto,
|
||||||
|
} from './dtos/ManualJournal.dto';
|
||||||
|
import { GetManualJournals } from './queries/GetManualJournals.service';
|
||||||
// import { GetManualJournals } from './queries/GetManualJournals';
|
// import { GetManualJournals } from './queries/GetManualJournals';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -16,7 +20,7 @@ export class ManualJournalsApplication {
|
|||||||
private deleteManualJournalService: DeleteManualJournalService,
|
private deleteManualJournalService: DeleteManualJournalService,
|
||||||
private publishManualJournalService: PublishManualJournal,
|
private publishManualJournalService: PublishManualJournal,
|
||||||
private getManualJournalService: GetManualJournal,
|
private getManualJournalService: GetManualJournal,
|
||||||
// private getManualJournalsService: GetManualJournals,
|
private getManualJournalsService: GetManualJournals,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,9 +54,7 @@ export class ManualJournalsApplication {
|
|||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public deleteManualJournal = (manualJournalId: number) => {
|
public deleteManualJournal = (manualJournalId: number) => {
|
||||||
return this.deleteManualJournalService.deleteManualJournal(
|
return this.deleteManualJournalService.deleteManualJournal(manualJournalId);
|
||||||
manualJournalId,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,23 +70,16 @@ export class ManualJournalsApplication {
|
|||||||
/**
|
/**
|
||||||
* Retrieves the specific manual journal.
|
* Retrieves the specific manual journal.
|
||||||
* @param {number} manualJournalId
|
* @param {number} manualJournalId
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
public getManualJournal = (manualJournalId: number) => {
|
public getManualJournal = (manualJournalId: number) => {
|
||||||
return this.getManualJournalService.getManualJournal(
|
return this.getManualJournalService.getManualJournal(manualJournalId);
|
||||||
manualJournalId,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the paginated manual journals.
|
* Retrieves the paginated manual journals.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {IManualJournalsFilter} filterDTO
|
* @param {IManualJournalsFilter} filterDTO
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
// public getManualJournals = (
|
public getManualJournals = (filterDTO: IManualJournalsFilter) => {
|
||||||
// filterDTO: IManualJournalsFilter,
|
return this.getManualJournalsService.getManualJournals(filterDTO);
|
||||||
// ) => {
|
};
|
||||||
// // return this.getManualJournalsService.getManualJournals(filterDTO);
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Exportable } from '../../Export/Exportable';
|
||||||
// import { IManualJournalsFilter } from '@/interfaces';
|
import { EXPORT_SIZE_LIMIT } from '../../Export/constants';
|
||||||
// import { Exportable } from '../../Export/Exportable';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { ManualJournalsApplication } from '../ManualJournalsApplication';
|
import { IManualJournalsFilter } from '../types/ManualJournals.types';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '../../Export/constants';
|
import { ManualJournalsApplication } from '../ManualJournalsApplication.service';
|
||||||
|
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { ManualJournal } from '../models/ManualJournal';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class ManualJournalsExportable extends Exportable {
|
@ExportableService({ name: ManualJournal.name })
|
||||||
// @Inject()
|
export class ManualJournalsExportable extends Exportable {
|
||||||
// private manualJournalsApplication: ManualJournalsApplication;
|
constructor(
|
||||||
|
private readonly manualJournalsApplication: ManualJournalsApplication,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the manual journals data to exportable sheet.
|
* Retrieves the manual journals data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {IManualJournalsFilter} query -
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public exportable(query: IManualJournalsFilter) {
|
||||||
// public exportable(tenantId: number, query: IManualJournalsFilter) {
|
const parsedQuery = {
|
||||||
// const parsedQuery = {
|
sortOrder: 'desc',
|
||||||
// sortOrder: 'desc',
|
columnSortBy: 'created_at',
|
||||||
// columnSortBy: 'created_at',
|
...query,
|
||||||
// ...query,
|
page: 1,
|
||||||
// page: 1,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
} as IManualJournalsFilter;
|
||||||
// } as IManualJournalsFilter;
|
|
||||||
|
|
||||||
// return this.manualJournalsApplication
|
return this.manualJournalsApplication
|
||||||
// .getManualJournals(tenantId, parsedQuery)
|
.getManualJournals(parsedQuery)
|
||||||
// .then((output) => output.manualJournals);
|
.then((output) => output.manualJournals);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,60 +1,57 @@
|
|||||||
// import { Inject } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import * as Yup from 'yup';
|
||||||
// import * as Yup from 'yup';
|
import { Importable } from '../../Import/Importable';
|
||||||
// import { Importable } from '../../Import/Importable';
|
import { CreateManualJournalService } from './CreateManualJournal.service';
|
||||||
// import { CreateManualJournalService } from './CreateManualJournal.service';
|
import { ImportableContext } from '../../Import/interfaces';
|
||||||
// import { IManualJournalDTO } from '@/interfaces';
|
import { ManualJournalsSampleData } from '../constants';
|
||||||
// import { ImportableContext } from '../../Import/interfaces';
|
import { CreateManualJournalDto } from '../dtos/ManualJournal.dto';
|
||||||
// import { ManualJournalsSampleData } from '../constants';
|
|
||||||
|
|
||||||
// export class ManualJournalImportable extends Importable {
|
export class ManualJournalImportable extends Importable {
|
||||||
// @Inject()
|
constructor(
|
||||||
// private createManualJournalService: CreateManualJournalService;
|
private readonly createManualJournalService: CreateManualJournalService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {CreateManualJournalDto} createAccountDTO
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
*/
|
||||||
// * @returns
|
public importable(
|
||||||
// */
|
createJournalDTO: CreateManualJournalDto,
|
||||||
// public importable(
|
trx?: Knex.Transaction,
|
||||||
// tenantId: number,
|
) {
|
||||||
// createJournalDTO: IManualJournalDTO,
|
return this.createManualJournalService.makeJournalEntries(
|
||||||
// trx?: Knex.Transaction
|
createJournalDTO,
|
||||||
// ) {
|
trx,
|
||||||
// return this.createManualJournalService.makeJournalEntries(
|
);
|
||||||
// tenantId,
|
}
|
||||||
// createJournalDTO,
|
|
||||||
// {},
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Transformes the DTO before passing it to importable and validation.
|
* Transformes the DTO before passing it to importable and validation.
|
||||||
// * @param {Record<string, any>} createDTO
|
* @param {Record<string, any>} createDTO
|
||||||
// * @param {ImportableContext} context
|
* @param {ImportableContext} context
|
||||||
// * @returns {Record<string, any>}
|
* @returns {Record<string, any>}
|
||||||
// */
|
*/
|
||||||
// public transform(createDTO: Record<string, any>, context: ImportableContext) {
|
public transform(createDTO: Record<string, any>, context: ImportableContext) {
|
||||||
// return createDTO;
|
return createDTO;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Params validation schema.
|
* Params validation schema.
|
||||||
// * @returns {ValidationSchema[]}
|
* @returns {ValidationSchema[]}
|
||||||
// */
|
*/
|
||||||
// public paramsValidationSchema() {
|
public paramsValidationSchema() {
|
||||||
// return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
// autoIncrement: Yup.boolean(),
|
autoIncrement: Yup.boolean(),
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data of manual journals that used to download sample sheet.
|
* Retrieves the sample data of manual journals that used to download sample sheet.
|
||||||
// * @returns {Record<string, any>}
|
* @returns {Record<string, any>}
|
||||||
// */
|
*/
|
||||||
// public sampleData(): Record<string, any>[] {
|
public sampleData(): Record<string, any>[] {
|
||||||
// return ManualJournalsSampleData;
|
return ManualJournalsSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
export const ManualJournalMeta = {
|
||||||
|
defaultFilterField: 'date',
|
||||||
|
defaultSort: {
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
sortField: 'name',
|
||||||
|
},
|
||||||
|
importable: true,
|
||||||
|
exportFlattenOn: 'entries',
|
||||||
|
|
||||||
|
exportable: true,
|
||||||
|
importAggregator: 'group',
|
||||||
|
importAggregateOn: 'entries',
|
||||||
|
importAggregateBy: 'journalNumber',
|
||||||
|
|
||||||
|
print: {
|
||||||
|
pageTitle: 'Manual Journals',
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
date: {
|
||||||
|
name: 'manual_journal.field.date',
|
||||||
|
column: 'date',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
journal_number: {
|
||||||
|
name: 'manual_journal.field.journal_number',
|
||||||
|
column: 'journal_number',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
reference: {
|
||||||
|
name: 'manual_journal.field.reference',
|
||||||
|
column: 'reference',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
journal_type: {
|
||||||
|
name: 'manual_journal.field.journal_type',
|
||||||
|
column: 'journal_type',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'manual_journal.field.amount',
|
||||||
|
column: 'amount',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'manual_journal.field.description',
|
||||||
|
column: 'description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
name: 'manual_journal.field.status',
|
||||||
|
column: 'status',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'draft', label: 'Draft' },
|
||||||
|
{ key: 'published', label: 'published' },
|
||||||
|
],
|
||||||
|
filterCustomQuery: StatusFieldFilterQuery,
|
||||||
|
sortCustomQuery: StatusFieldSortQuery,
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'manual_journal.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
date: {
|
||||||
|
name: 'manual_journal.field.date',
|
||||||
|
type: 'date',
|
||||||
|
accessor: 'formattedDate',
|
||||||
|
},
|
||||||
|
journalNumber: {
|
||||||
|
name: 'manual_journal.field.journal_number',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
reference: {
|
||||||
|
name: 'manual_journal.field.reference',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
journalType: {
|
||||||
|
name: 'manual_journal.field.journal_type',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'Amount',
|
||||||
|
accessor: 'formattedAmount',
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'manual_journal.field.currency',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
exchangeRate: {
|
||||||
|
name: 'manual_journal.field.exchange_rate',
|
||||||
|
type: 'number',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'manual_journal.field.description',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
name: 'Entries',
|
||||||
|
type: 'collection',
|
||||||
|
collectionOf: 'object',
|
||||||
|
columns: {
|
||||||
|
credit: {
|
||||||
|
name: 'Credit',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
debit: {
|
||||||
|
name: 'Debit',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
name: 'Account',
|
||||||
|
accessor: 'account.name',
|
||||||
|
},
|
||||||
|
contact: {
|
||||||
|
name: 'Contact',
|
||||||
|
accessor: 'contact.displayName',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'Note',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
publish: {
|
||||||
|
name: 'Publish',
|
||||||
|
type: 'boolean',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
publishedAt: {
|
||||||
|
name: 'Published At',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
name: 'Created At',
|
||||||
|
accessor: 'formattedCreatedAt',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
date: {
|
||||||
|
name: 'manual_journal.field.date',
|
||||||
|
fieldType: 'date',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
journalNumber: {
|
||||||
|
name: 'manual_journal.field.journal_number',
|
||||||
|
fieldType: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
reference: {
|
||||||
|
name: 'manual_journal.field.reference',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
journalType: {
|
||||||
|
name: 'manual_journal.field.journal_type',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'manual_journal.field.currency',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
exchange_rate: {
|
||||||
|
name: 'manual_journal.field.exchange_rate',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'manual_journal.field.description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
name: 'Entries',
|
||||||
|
fieldType: 'collection',
|
||||||
|
collectionOf: 'object',
|
||||||
|
collectionMinLength: 2,
|
||||||
|
required: true,
|
||||||
|
fields: {
|
||||||
|
credit: {
|
||||||
|
name: 'Credit',
|
||||||
|
fieldType: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
debit: {
|
||||||
|
name: 'Debit',
|
||||||
|
fieldType: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
accountId: {
|
||||||
|
name: 'Account',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Account',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
contact: {
|
||||||
|
name: 'Contact',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Contact',
|
||||||
|
relationImportMatch: 'displayName',
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
name: 'Note',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
publish: {
|
||||||
|
name: 'Publish',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status field sorting custom query.
|
||||||
|
*/
|
||||||
|
function StatusFieldSortQuery(query, role) {
|
||||||
|
return query.modify('sortByStatus', role.order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status field filter custom query.
|
||||||
|
*/
|
||||||
|
function StatusFieldFilterQuery(query, role) {
|
||||||
|
query.modify('filterByStatus', role.value);
|
||||||
|
}
|
||||||
@@ -9,7 +9,12 @@ import { Model, mixin } from 'objection';
|
|||||||
import { ManualJournalEntry } from './ManualJournalEntry';
|
import { ManualJournalEntry } from './ManualJournalEntry';
|
||||||
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
|
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { ManualJournalMeta } from './ManualJournal.meta';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
|
@InjectModelMeta(ManualJournalMeta)
|
||||||
export class ManualJournal extends TenantBaseModel {
|
export class ManualJournal extends TenantBaseModel {
|
||||||
date: Date;
|
date: Date;
|
||||||
journalNumber: string;
|
journalNumber: string;
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import { MailModule } from '../Mail/Mail.module';
|
|||||||
import { SendPaymentReceivedMailProcessor } from './processors/PaymentReceivedMailNotification.processor';
|
import { SendPaymentReceivedMailProcessor } from './processors/PaymentReceivedMailNotification.processor';
|
||||||
import { BullModule } from '@nestjs/bull';
|
import { BullModule } from '@nestjs/bull';
|
||||||
import { SEND_PAYMENT_RECEIVED_MAIL_QUEUE } from './constants';
|
import { SEND_PAYMENT_RECEIVED_MAIL_QUEUE } from './constants';
|
||||||
|
import { PaymentsReceivedExportable } from './commands/PaymentsReceivedExportable';
|
||||||
|
import { PaymentsReceivedImportable } from './commands/PaymentsReceivedImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [PaymentReceivesController],
|
controllers: [PaymentReceivesController],
|
||||||
@@ -59,6 +61,8 @@ import { SEND_PAYMENT_RECEIVED_MAIL_QUEUE } from './constants';
|
|||||||
GetPaymentsReceivedService,
|
GetPaymentsReceivedService,
|
||||||
SendPaymentReceiveMailNotification,
|
SendPaymentReceiveMailNotification,
|
||||||
SendPaymentReceivedMailProcessor,
|
SendPaymentReceivedMailProcessor,
|
||||||
|
PaymentsReceivedExportable,
|
||||||
|
PaymentsReceivedImportable
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
PaymentReceivesApplication,
|
PaymentReceivesApplication,
|
||||||
|
|||||||
@@ -1,39 +1,34 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { IAccountsStructureType, IPaymentsReceivedFilter } from '@/interfaces';
|
import { PaymentReceivesApplication } from '../PaymentReceived.application';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { IPaymentsReceivedFilter } from '../types/PaymentReceived.types';
|
||||||
// import { PaymentReceivesApplication } from './PaymentReceived.application';
|
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
import { Exportable } from '@/modules/Export/Exportable';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class PaymentsReceivedExportable extends Exportable {
|
export class PaymentsReceivedExportable extends Exportable {
|
||||||
// @Inject()
|
constructor(private readonly paymentReceivedApp: PaymentReceivesApplication) {
|
||||||
// private paymentReceivedApp: PaymentReceivesApplication;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {number} tenantId
|
||||||
// * @param {IPaymentsReceivedFilter} query -
|
* @param {IPaymentsReceivedFilter} query -
|
||||||
// * @returns
|
* @returns
|
||||||
// */
|
*/
|
||||||
// public exportable(tenantId: number, query: IPaymentsReceivedFilter) {
|
public exportable(query: IPaymentsReceivedFilter) {
|
||||||
// const filterQuery = (builder) => {
|
const filterQuery = (builder) => {
|
||||||
// builder.withGraphFetched('entries.invoice');
|
builder.withGraphFetched('entries.invoice');
|
||||||
// builder.withGraphFetched('branch');
|
builder.withGraphFetched('branch');
|
||||||
// };
|
};
|
||||||
|
const parsedQuery = {
|
||||||
// const parsedQuery = {
|
page: 1,
|
||||||
// sortOrder: 'desc',
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// columnSortBy: 'created_at',
|
filterQuery,
|
||||||
// inactiveMode: false,
|
...query
|
||||||
// ...query,
|
};
|
||||||
// structure: IAccountsStructureType.Flat,
|
return this.paymentReceivedApp
|
||||||
// page: 1,
|
.getPaymentsReceived(parsedQuery)
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
.then((output) => output.paymentReceives);
|
||||||
// filterQuery,
|
}
|
||||||
// } as IPaymentsReceivedFilter;
|
}
|
||||||
|
|
||||||
// return this.paymentReceivedApp
|
|
||||||
// .getPaymentReceives(tenantId, parsedQuery)
|
|
||||||
// .then((output) => output.paymentReceives);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,46 +1,45 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { CreatePaymentReceivedDto } from '../dtos/PaymentReceived.dto';
|
||||||
// import { IPaymentReceivedCreateDTO } from '@/interfaces';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Importable } from '@/services/Import/Importable';
|
import { PaymentsReceiveSampleData } from '../constants';
|
||||||
// import { CreatePaymentReceived } from './commands/CreatePaymentReceived.serivce';
|
import { CreatePaymentReceivedService } from './CreatePaymentReceived.serivce';
|
||||||
// import { PaymentsReceiveSampleData } from './constants';
|
import { Importable } from '@/modules/Import/Importable';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class PaymentsReceivedImportable extends Importable {
|
export class PaymentsReceivedImportable extends Importable {
|
||||||
// @Inject()
|
constructor(
|
||||||
// private createPaymentReceiveService: CreatePaymentReceived;
|
private readonly createPaymentReceiveService: CreatePaymentReceivedService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {CreatePaymentReceivedDto} createAccountDTO
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
* @returns
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public importable(
|
||||||
// public importable(
|
createPaymentDTO: CreatePaymentReceivedDto,
|
||||||
// tenantId: number,
|
trx?: Knex.Transaction,
|
||||||
// createPaymentDTO: IPaymentReceivedCreateDTO,
|
) {
|
||||||
// trx?: Knex.Transaction
|
return this.createPaymentReceiveService.createPaymentReceived(
|
||||||
// ) {
|
createPaymentDTO,
|
||||||
// return this.createPaymentReceiveService.createPaymentReceived(
|
trx,
|
||||||
// tenantId,
|
);
|
||||||
// createPaymentDTO,
|
}
|
||||||
// {},
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return PaymentsReceiveSampleData;
|
return PaymentsReceiveSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
import { PaymentReceivedEntry } from './PaymentReceivedEntry';
|
import { PaymentReceivedEntry } from './PaymentReceivedEntry';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
export class PaymentReceived extends TenantBaseModel {
|
export class PaymentReceived extends TenantBaseModel {
|
||||||
customerId: number;
|
customerId: number;
|
||||||
paymentDate: string;
|
paymentDate: string;
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ResourceService } from './ResourceService';
|
import { ResourceService } from './ResourceService';
|
||||||
|
import { BranchesModule } from '../Branches/Branches.module';
|
||||||
|
import { WarehousesModule } from '../Warehouses/Warehouses.module';
|
||||||
|
import { AccountsExportable } from '../Accounts/AccountsExportable.service';
|
||||||
|
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [BranchesModule, WarehousesModule, AccountsModule],
|
||||||
providers: [ResourceService],
|
providers: [ResourceService],
|
||||||
exports: [ResourceService],
|
exports: [ResourceService],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export class ResourceService {
|
|||||||
*/
|
*/
|
||||||
public getResourceModel(inputModelName: string) {
|
public getResourceModel(inputModelName: string) {
|
||||||
const modelName = resourceToModelName(inputModelName);
|
const modelName = resourceToModelName(inputModelName);
|
||||||
const resourceModel = this.moduleRef.get(modelName);
|
const resourceModel = this.moduleRef.get(modelName, { strict: false });
|
||||||
|
|
||||||
if (!resourceModel) {
|
if (!resourceModel) {
|
||||||
throw new ServiceError(ERRORS.RESOURCE_MODEL_NOT_FOUND);
|
throw new ServiceError(ERRORS.RESOURCE_MODEL_NOT_FOUND);
|
||||||
@@ -46,7 +46,7 @@ export class ResourceService {
|
|||||||
const resourceModel = this.getResourceModel(modelName);
|
const resourceModel = this.getResourceModel(modelName);
|
||||||
|
|
||||||
// Retrieve the resource meta.
|
// Retrieve the resource meta.
|
||||||
const resourceMeta = resourceModel.getMeta(metakey);
|
const resourceMeta = resourceModel().getMeta(metakey);
|
||||||
|
|
||||||
// Localization the fields names.
|
// Localization the fields names.
|
||||||
return resourceMeta;
|
return resourceMeta;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { camelCase, upperFirst } from 'lodash';
|
import { camelCase, upperFirst } from 'lodash';
|
||||||
import pluralize from 'pluralize';
|
import * as pluralize from 'pluralize';
|
||||||
|
|
||||||
export const resourceToModelName = (resourceName: string): string => {
|
export const resourceToModelName = (resourceName: string): string => {
|
||||||
return upperFirst(camelCase(pluralize.singular(resourceName)));
|
return upperFirst(camelCase(pluralize.singular(resourceName)));
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectab
|
|||||||
import { SaleEstimatePdfTemplate } from '../SaleInvoices/queries/SaleEstimatePdfTemplate.service';
|
import { SaleEstimatePdfTemplate } from '../SaleInvoices/queries/SaleEstimatePdfTemplate.service';
|
||||||
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
|
||||||
import { SendSaleEstimateMailQueue } from './types/SaleEstimates.types';
|
import { SendSaleEstimateMailQueue } from './types/SaleEstimates.types';
|
||||||
|
import { SaleEstimatesExportable } from './SaleEstimatesExportable';
|
||||||
|
import { SaleEstimatesImportable } from './SaleEstimatesImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -74,7 +76,13 @@ import { SendSaleEstimateMailQueue } from './types/SaleEstimates.types';
|
|||||||
SaleEstimatesApplication,
|
SaleEstimatesApplication,
|
||||||
SendSaleEstimateMail,
|
SendSaleEstimateMail,
|
||||||
GetSaleEstimatePdf,
|
GetSaleEstimatePdf,
|
||||||
SaleEstimatePdfTemplate
|
SaleEstimatePdfTemplate,
|
||||||
|
SaleEstimatesExportable,
|
||||||
|
SaleEstimatesImportable
|
||||||
],
|
],
|
||||||
|
exports: [
|
||||||
|
SaleEstimatesExportable,
|
||||||
|
SaleEstimatesImportable
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class SaleEstimatesModule {}
|
export class SaleEstimatesModule {}
|
||||||
|
|||||||
@@ -1,35 +1,41 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { ISalesInvoicesFilter } from '@/interfaces';
|
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { Exportable } from '../Export/Exportable';
|
||||||
// import { SaleEstimatesApplication } from './SaleEstimates.application';
|
import { ISalesInvoicesFilter } from '../SaleInvoices/SaleInvoice.types';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
import { SaleEstimatesApplication } from './SaleEstimates.application';
|
||||||
|
import { ISalesEstimatesFilter } from './types/SaleEstimates.types';
|
||||||
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
|
import { SaleEstimate } from './models/SaleEstimate';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleEstimatesExportable extends Exportable {
|
@ExportableService({ name: SaleEstimate.name })
|
||||||
// @Inject()
|
export class SaleEstimatesExportable extends Exportable {
|
||||||
// private saleEstimatesApplication: SaleEstimatesApplication;
|
constructor(
|
||||||
|
private readonly saleEstimatesApplication: SaleEstimatesApplication,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {ISalesEstimatesFilter} query -
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public exportable(query: ISalesEstimatesFilter) {
|
||||||
// public exportable(tenantId: number, query: ISalesInvoicesFilter) {
|
const filterQuery = (query) => {
|
||||||
// const filterQuery = (query) => {
|
query.withGraphFetched('branch');
|
||||||
// query.withGraphFetched('branch');
|
query.withGraphFetched('warehouse');
|
||||||
// query.withGraphFetched('warehouse');
|
};
|
||||||
// };
|
const parsedQuery = {
|
||||||
// const parsedQuery = {
|
sortOrder: 'desc',
|
||||||
// sortOrder: 'desc',
|
columnSortBy: 'created_at',
|
||||||
// columnSortBy: 'created_at',
|
...query,
|
||||||
// ...query,
|
page: 1,
|
||||||
// page: 1,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
filterQuery,
|
||||||
// filterQuery,
|
} as ISalesInvoicesFilter;
|
||||||
// } as ISalesInvoicesFilter;
|
|
||||||
|
|
||||||
// return this.saleEstimatesApplication
|
return this.saleEstimatesApplication
|
||||||
// .getSaleEstimates(tenantId, parsedQuery)
|
.getSaleEstimates(parsedQuery)
|
||||||
// .then((output) => output.salesEstimates);
|
.then((output) => output.salesEstimates);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,45 +1,45 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { CreateSaleEstimate } from './commands/CreateSaleEstimate.service';
|
||||||
// import { ISaleEstimateDTO } from '@/interfaces';
|
import { SaleEstimatesSampleData } from './constants';
|
||||||
// import { CreateSaleEstimate } from './commands/CreateSaleEstimate.service';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Importable } from '@/services/Import/Importable';
|
import { CreateSaleEstimateDto } from './dtos/SaleEstimate.dto';
|
||||||
// import { SaleEstimatesSampleData } from './constants';
|
import { Importable } from '../Import/Importable';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleEstimatesImportable extends Importable {
|
export class SaleEstimatesImportable extends Importable{
|
||||||
// @Inject()
|
constructor(
|
||||||
// private createEstimateService: CreateSaleEstimate;
|
private readonly createEstimateService: CreateSaleEstimate
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {CreateSaleEstimateDto} createAccountDTO
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
* @returns
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public importable(
|
||||||
// public importable(
|
createEstimateDTO: CreateSaleEstimateDto,
|
||||||
// tenantId: number,
|
trx?: Knex.Transaction
|
||||||
// createEstimateDTO: ISaleEstimateDTO,
|
) {
|
||||||
// trx?: Knex.Transaction
|
return this.createEstimateService.createEstimate(
|
||||||
// ) {
|
createEstimateDTO,
|
||||||
// return this.createEstimateService.createEstimate(
|
trx
|
||||||
// tenantId,
|
);
|
||||||
// createEstimateDTO,
|
}
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return SaleEstimatesSampleData;
|
return SaleEstimatesSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import * as moment from 'moment';
|
|||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
|
||||||
@Injectable()
|
@ExportableModel()
|
||||||
export class SaleEstimate extends TenantBaseModel {
|
export class SaleEstimate extends TenantBaseModel {
|
||||||
exchangeRate!: number;
|
exchangeRate!: number;
|
||||||
amount!: number;
|
amount!: number;
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ import { SaleInvoiceCostGLEntries } from './SaleInvoiceCostGLEntries';
|
|||||||
import { InvoicePaymentsGLEntriesRewrite } from './InvoicePaymentsGLRewrite';
|
import { InvoicePaymentsGLEntriesRewrite } from './InvoicePaymentsGLRewrite';
|
||||||
import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.module';
|
import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.module';
|
||||||
import { SaleInvoicesCost } from './SalesInvoicesCost';
|
import { SaleInvoicesCost } from './SalesInvoicesCost';
|
||||||
|
import { SaleInvoicesExportable } from './commands/SaleInvoicesExportable';
|
||||||
|
import { SaleInvoicesImportable } from './commands/SaleInvoicesImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -118,7 +120,15 @@ import { SaleInvoicesCost } from './SalesInvoicesCost';
|
|||||||
SaleInvoiceWriteInventoryTransactionsSubscriber,
|
SaleInvoiceWriteInventoryTransactionsSubscriber,
|
||||||
InvoicePaymentsGLEntriesRewrite,
|
InvoicePaymentsGLEntriesRewrite,
|
||||||
SaleInvoicesCost,
|
SaleInvoicesCost,
|
||||||
|
SaleInvoicesExportable,
|
||||||
|
SaleInvoicesImportable,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
GetSaleInvoice,
|
||||||
|
SaleInvoicesCost,
|
||||||
|
SaleInvoicePdf,
|
||||||
|
SaleInvoicesExportable,
|
||||||
|
SaleInvoicesImportable,
|
||||||
],
|
],
|
||||||
exports: [GetSaleInvoice, SaleInvoicesCost, SaleInvoicePdf],
|
|
||||||
})
|
})
|
||||||
export class SaleInvoicesModule {}
|
export class SaleInvoicesModule {}
|
||||||
|
|||||||
@@ -1,35 +1,39 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Exportable } from '@/modules/Export/Exportable';
|
||||||
// import { ISalesInvoicesFilter } from '@/interfaces';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { SaleInvoiceApplication } from './SaleInvoices.application';
|
import { SaleInvoiceApplication } from '../SaleInvoices.application';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { ISalesInvoicesFilter } from '../SaleInvoice.types';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
|
||||||
|
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { SaleInvoice } from '../models/SaleInvoice';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleInvoicesExportable extends Exportable {
|
@ExportableService({ name: SaleInvoice.name })
|
||||||
// @Inject()
|
export class SaleInvoicesExportable extends Exportable{
|
||||||
// private saleInvoicesApplication: SaleInvoiceApplication;
|
constructor(
|
||||||
|
private readonly saleInvoicesApplication: SaleInvoiceApplication,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
*/
|
||||||
// * @returns
|
public exportable(query: ISalesInvoicesFilter) {
|
||||||
// */
|
const filterQuery = (query) => {
|
||||||
// public exportable(tenantId: number, query: ISalesInvoicesFilter) {
|
query.withGraphFetched('branch');
|
||||||
// const filterQuery = (query) => {
|
query.withGraphFetched('warehouse');
|
||||||
// query.withGraphFetched('branch');
|
};
|
||||||
// query.withGraphFetched('warehouse');
|
const parsedQuery = {
|
||||||
// };
|
sortOrder: 'desc',
|
||||||
// const parsedQuery = {
|
columnSortBy: 'created_at',
|
||||||
// sortOrder: 'desc',
|
...query,
|
||||||
// columnSortBy: 'created_at',
|
page: 1,
|
||||||
// ...query,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// page: 1,
|
filterQuery,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
} as ISalesInvoicesFilter;
|
||||||
// filterQuery,
|
|
||||||
// } as ISalesInvoicesFilter;
|
|
||||||
|
|
||||||
// return this.saleInvoicesApplication
|
return this.saleInvoicesApplication
|
||||||
// .getSaleInvoices(tenantId, parsedQuery)
|
.getSaleInvoices(parsedQuery)
|
||||||
// .then((output) => output.salesInvoices);
|
.then((output) => output.salesInvoices);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,46 +1,39 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
// import { ISaleInvoiceCreateDTO } from '@/interfaces';
|
import { CreateSaleInvoice } from './CreateSaleInvoice.service';
|
||||||
// import { CreateSaleInvoice } from './commands/CreateSaleInvoice.service';
|
import { Importable } from '@/modules/Import/Importable';
|
||||||
// import { Importable } from '@/services/Import/Importable';
|
import { CreateSaleInvoiceDto } from '../dtos/SaleInvoice.dto';
|
||||||
// import { SaleInvoicesSampleData } from './constants';
|
import { SaleInvoicesSampleData } from '../constants';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleInvoicesImportable extends Importable {
|
export class SaleInvoicesImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly createInvoiceService: CreateSaleInvoice) {
|
||||||
// private createInvoiceService: CreateSaleInvoice;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to account service.
|
* Importing to account service.
|
||||||
// * @param {number} tenantId
|
* @param {CreateSaleInvoiceDto} createAccountDTO
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
*/
|
||||||
// * @returns
|
public importable(
|
||||||
// */
|
createAccountDTO: CreateSaleInvoiceDto,
|
||||||
// public importable(
|
trx?: Knex.Transaction,
|
||||||
// tenantId: number,
|
) {
|
||||||
// createAccountDTO: ISaleInvoiceCreateDTO,
|
return this.createInvoiceService.createSaleInvoice(createAccountDTO, trx);
|
||||||
// trx?: Knex.Transaction
|
}
|
||||||
// ) {
|
|
||||||
// return this.createInvoiceService.createSaleInvoice(
|
|
||||||
// tenantId,
|
|
||||||
// createAccountDTO,
|
|
||||||
// {},
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return SaleInvoicesSampleData;
|
return SaleInvoicesSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -0,0 +1,316 @@
|
|||||||
|
import { Features } from "@/common/types/Features";
|
||||||
|
|
||||||
|
export const SaleInvoiceMeta = {
|
||||||
|
defaultFilterField: 'customer',
|
||||||
|
defaultSort: {
|
||||||
|
sortOrder: 'DESC',
|
||||||
|
sortField: 'created_at',
|
||||||
|
},
|
||||||
|
exportable: true,
|
||||||
|
exportFlattenOn: 'entries',
|
||||||
|
|
||||||
|
importable: true,
|
||||||
|
importAggregator: 'group',
|
||||||
|
importAggregateOn: 'entries',
|
||||||
|
importAggregateBy: 'invoiceNo',
|
||||||
|
|
||||||
|
print: {
|
||||||
|
pageTitle: 'Sale invoices',
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
customer: {
|
||||||
|
name: 'invoice.field.customer',
|
||||||
|
column: 'customer_id',
|
||||||
|
fieldType: 'relation',
|
||||||
|
|
||||||
|
relationType: 'enumeration',
|
||||||
|
relationKey: 'customer',
|
||||||
|
|
||||||
|
relationEntityLabel: 'display_name',
|
||||||
|
relationEntityKey: 'id',
|
||||||
|
},
|
||||||
|
invoice_date: {
|
||||||
|
name: 'invoice.field.invoice_date',
|
||||||
|
column: 'invoice_date',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
due_date: {
|
||||||
|
name: 'invoice.field.due_date',
|
||||||
|
column: 'due_date',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
invoice_no: {
|
||||||
|
name: 'invoice.field.invoice_no',
|
||||||
|
column: 'invoice_no',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
reference_no: {
|
||||||
|
name: 'invoice.field.reference_no',
|
||||||
|
column: 'reference_no',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
invoice_message: {
|
||||||
|
name: 'invoice.field.invoice_message',
|
||||||
|
column: 'invoice_message',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
terms_conditions: {
|
||||||
|
name: 'invoice.field.terms_conditions',
|
||||||
|
column: 'terms_conditions',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'invoice.field.amount',
|
||||||
|
column: 'balance',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
payment_amount: {
|
||||||
|
name: 'invoice.field.payment_amount',
|
||||||
|
column: 'payment_amount',
|
||||||
|
fieldType: 'number',
|
||||||
|
},
|
||||||
|
due_amount: {
|
||||||
|
// calculated.
|
||||||
|
name: 'invoice.field.due_amount',
|
||||||
|
column: 'due_amount',
|
||||||
|
fieldType: 'number',
|
||||||
|
virtualColumn: true,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
name: 'invoice.field.status',
|
||||||
|
fieldType: 'enumeration',
|
||||||
|
options: [
|
||||||
|
{ key: 'draft', label: 'invoice.field.status.draft' },
|
||||||
|
{ key: 'delivered', label: 'invoice.field.status.delivered' },
|
||||||
|
{ key: 'unpaid', label: 'invoice.field.status.unpaid' },
|
||||||
|
{ key: 'overdue', label: 'invoice.field.status.overdue' },
|
||||||
|
{ key: 'partially-paid', label: 'invoice.field.status.partially-paid' },
|
||||||
|
{ key: 'paid', label: 'invoice.field.status.paid' },
|
||||||
|
],
|
||||||
|
filterCustomQuery: StatusFieldFilterQuery,
|
||||||
|
sortCustomQuery: StatusFieldSortQuery,
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
name: 'invoice.field.created_at',
|
||||||
|
column: 'created_at',
|
||||||
|
fieldType: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
invoiceDate: {
|
||||||
|
name: 'invoice.field.invoice_date',
|
||||||
|
type: 'date',
|
||||||
|
accessor: 'invoiceDateFormatted',
|
||||||
|
},
|
||||||
|
dueDate: {
|
||||||
|
name: 'invoice.field.due_date',
|
||||||
|
type: 'date',
|
||||||
|
accessor: 'dueDateFormatted',
|
||||||
|
},
|
||||||
|
referenceNo: {
|
||||||
|
name: 'invoice.field.reference_no',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
invoiceNo: {
|
||||||
|
name: 'invoice.field.invoice_no',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
name: 'invoice.field.customer',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'customer.displayName',
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'invoice.field.amount',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'balanceAmountFormatted',
|
||||||
|
},
|
||||||
|
exchangeRate: {
|
||||||
|
name: 'invoice.field.exchange_rate',
|
||||||
|
type: 'number',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'invoice.field.currency',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
paidAmount: {
|
||||||
|
name: 'Paid Amount',
|
||||||
|
accessor: 'paymentAmountFormatted',
|
||||||
|
},
|
||||||
|
dueAmount: {
|
||||||
|
name: 'Due Amount',
|
||||||
|
accessor: 'dueAmountFormatted',
|
||||||
|
},
|
||||||
|
invoiceMessage: {
|
||||||
|
name: 'invoice.field.invoice_message',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
termsConditions: {
|
||||||
|
name: 'invoice.field.terms_conditions',
|
||||||
|
type: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
delivered: {
|
||||||
|
name: 'invoice.field.delivered',
|
||||||
|
type: 'boolean',
|
||||||
|
printable: false,
|
||||||
|
accessor: 'isDelivered',
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
name: 'Entries',
|
||||||
|
accessor: 'entries',
|
||||||
|
type: 'collection',
|
||||||
|
collectionOf: 'object',
|
||||||
|
columns: {
|
||||||
|
itemName: {
|
||||||
|
name: 'Item Name',
|
||||||
|
accessor: 'item.name',
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
name: 'Item Rate',
|
||||||
|
accessor: 'rateFormatted',
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
name: 'Item Quantity',
|
||||||
|
accessor: 'quantityFormatted',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'Item Description',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
amount: {
|
||||||
|
name: 'Item Amount',
|
||||||
|
accessor: 'totalFormatted',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
branch: {
|
||||||
|
name: 'Branch',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'branch.name',
|
||||||
|
features: [Features.BRANCHES],
|
||||||
|
},
|
||||||
|
warehouse: {
|
||||||
|
name: 'Warehouse',
|
||||||
|
type: 'text',
|
||||||
|
accessor: 'warehouse.name',
|
||||||
|
features: [Features.BRANCHES],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields2: {
|
||||||
|
invoiceDate: {
|
||||||
|
name: 'invoice.field.invoice_date',
|
||||||
|
fieldType: 'date',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
dueDate: {
|
||||||
|
name: 'invoice.field.due_date',
|
||||||
|
fieldType: 'date',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
referenceNo: {
|
||||||
|
name: 'invoice.field.reference_no',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
invoiceNo: {
|
||||||
|
name: 'invoice.field.invoice_no',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
customerId: {
|
||||||
|
name: 'invoice.field.customer',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Contact',
|
||||||
|
relationImportMatch: 'displayName',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
exchangeRate: {
|
||||||
|
name: 'invoice.field.exchange_rate',
|
||||||
|
fieldType: 'number',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
currencyCode: {
|
||||||
|
name: 'invoice.field.currency',
|
||||||
|
fieldType: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
invoiceMessage: {
|
||||||
|
name: 'invoice.field.invoice_message',
|
||||||
|
fieldType: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
termsConditions: {
|
||||||
|
name: 'invoice.field.terms_conditions',
|
||||||
|
fieldType: 'text',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
name: 'invoice.field.entries',
|
||||||
|
fieldType: 'collection',
|
||||||
|
collectionOf: 'object',
|
||||||
|
collectionMinLength: 1,
|
||||||
|
required: true,
|
||||||
|
fields: {
|
||||||
|
itemId: {
|
||||||
|
name: 'invoice.field.item_name',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Item',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
required: true,
|
||||||
|
importHint: 'Matches the item name or code.',
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
name: 'invoice.field.rate',
|
||||||
|
fieldType: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
name: 'invoice.field.quantity',
|
||||||
|
fieldType: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
name: 'invoice.field.description',
|
||||||
|
fieldType: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
delivered: {
|
||||||
|
name: 'invoice.field.delivered',
|
||||||
|
fieldType: 'boolean',
|
||||||
|
printable: false,
|
||||||
|
},
|
||||||
|
branchId: {
|
||||||
|
name: 'Branch',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Branch',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
features: [Features.BRANCHES],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
warehouseId: {
|
||||||
|
name: 'Warehouse',
|
||||||
|
fieldType: 'relation',
|
||||||
|
relationModel: 'Warehouse',
|
||||||
|
relationImportMatch: ['name', 'code'],
|
||||||
|
features: [Features.WAREHOUSES],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status field filter custom query.
|
||||||
|
*/
|
||||||
|
function StatusFieldFilterQuery(query, role) {
|
||||||
|
query.modify('statusFilter', role.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status field sort custom query.
|
||||||
|
*/
|
||||||
|
function StatusFieldSortQuery(query, role) {
|
||||||
|
query.modify('sortByStatus', role.order);
|
||||||
|
}
|
||||||
@@ -11,11 +11,15 @@ import { DiscountType } from '@/common/types/Discount';
|
|||||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
import { ISearchRole } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
import { ISearchRole } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { PaymentIntegrationTransactionLink } from '../SaleInvoice.types';
|
|
||||||
import { TransactionPaymentServiceEntry } from '@/modules/PaymentServices/models/TransactionPaymentServiceEntry.model';
|
import { TransactionPaymentServiceEntry } from '@/modules/PaymentServices/models/TransactionPaymentServiceEntry.model';
|
||||||
import { InjectAttachable } from '@/modules/Attachments/decorators/InjectAttachable.decorator';
|
import { InjectAttachable } from '@/modules/Attachments/decorators/InjectAttachable.decorator';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||||
|
import { SaleInvoiceMeta } from './SaleInvoice.meta';
|
||||||
|
|
||||||
@InjectAttachable()
|
@InjectAttachable()
|
||||||
|
@ExportableModel()
|
||||||
|
@InjectModelMeta(SaleInvoiceMeta)
|
||||||
export class SaleInvoice extends TenantBaseModel{
|
export class SaleInvoice extends TenantBaseModel{
|
||||||
public taxAmountWithheld: number;
|
public taxAmountWithheld: number;
|
||||||
public balance: number;
|
public balance: number;
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { SaleInvoiceTransformer } from './SaleInvoice.transformer';
|
import { SaleInvoiceTransformer } from './SaleInvoice.transformer';
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||||
import { SaleInvoice } from '../models/SaleInvoice';
|
import { SaleInvoice } from '../models/SaleInvoice';
|
||||||
import { ISalesInvoicesFilter } from '../SaleInvoice.types';
|
import { ISalesInvoicesFilter } from '../SaleInvoice.types';
|
||||||
import { Knex } from 'knex';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetSaleInvoicesService {
|
export class GetSaleInvoicesService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly dynamicListService: DynamicListService,
|
private readonly dynamicListService: DynamicListService,
|
||||||
private readonly transformer: TransformerInjectable,
|
private readonly transformer: TransformerInjectable,
|
||||||
|
|
||||||
|
@Inject(SaleInvoice.name)
|
||||||
|
private readonly saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +37,8 @@ export class GetSaleInvoicesService {
|
|||||||
SaleInvoice,
|
SaleInvoice,
|
||||||
filter,
|
filter,
|
||||||
);
|
);
|
||||||
const { results, pagination } = await SaleInvoice.query()
|
const { results, pagination } = await this.saleInvoiceModel()
|
||||||
|
.query()
|
||||||
.onBuild((builder) => {
|
.onBuild((builder) => {
|
||||||
builder.withGraphFetched('entries.item');
|
builder.withGraphFetched('entries.item');
|
||||||
builder.withGraphFetched('customer');
|
builder.withGraphFetched('customer');
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import { MailNotificationModule } from '../MailNotification/MailNotification.mod
|
|||||||
import { SendSaleReceiptMailProcess } from './processes/SendSaleReceiptMail.process';
|
import { SendSaleReceiptMailProcess } from './processes/SendSaleReceiptMail.process';
|
||||||
import { MailModule } from '../Mail/Mail.module';
|
import { MailModule } from '../Mail/Mail.module';
|
||||||
import { SendSaleReceiptMailQueue } from './constants';
|
import { SendSaleReceiptMailQueue } from './constants';
|
||||||
|
import { SaleReceiptsExportable } from './commands/SaleReceiptsExportable';
|
||||||
|
import { SaleReceiptsImportable } from './commands/SaleReceiptsImportable';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [SaleReceiptsController],
|
controllers: [SaleReceiptsController],
|
||||||
@@ -75,6 +77,8 @@ import { SendSaleReceiptMailQueue } from './constants';
|
|||||||
SaleReceiptInventoryTransactions,
|
SaleReceiptInventoryTransactions,
|
||||||
SaleReceiptInventoryTransactionsSubscriber,
|
SaleReceiptInventoryTransactionsSubscriber,
|
||||||
SendSaleReceiptMailProcess,
|
SendSaleReceiptMailProcess,
|
||||||
|
SaleReceiptsExportable,
|
||||||
|
SaleReceiptsImportable,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SaleReceiptsModule {}
|
export class SaleReceiptsModule {}
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Exportable } from '@/modules/Export/Exportable';
|
||||||
// import { ISalesReceiptsFilter } from '@/interfaces';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Exportable } from '@/services/Export/Exportable';
|
import { SaleReceiptApplication } from '../SaleReceiptApplication.service';
|
||||||
// import { SaleReceiptApplication } from './SaleReceiptApplication';
|
import { ISalesReceiptsFilter } from '../types/SaleReceipts.types';
|
||||||
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
|
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleReceiptsExportable extends Exportable {
|
export class SaleReceiptsExportable extends Exportable {
|
||||||
// @Inject()
|
constructor(private readonly saleReceiptsApp: SaleReceiptApplication) {
|
||||||
// private saleReceiptsApp: SaleReceiptApplication;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
* @param {ISalesReceiptsFilter} query -
|
||||||
// * @returns
|
*/
|
||||||
// */
|
public exportable(query: ISalesReceiptsFilter) {
|
||||||
// public exportable(tenantId: number, query: ISalesReceiptsFilter) {
|
const filterQuery = (query) => {
|
||||||
// const filterQuery = (query) => {
|
query.withGraphFetched('branch');
|
||||||
// query.withGraphFetched('branch');
|
query.withGraphFetched('warehouse');
|
||||||
// query.withGraphFetched('warehouse');
|
};
|
||||||
// };
|
const parsedQuery = {
|
||||||
// const parsedQuery = {
|
sortOrder: 'desc',
|
||||||
// sortOrder: 'desc',
|
columnSortBy: 'created_at',
|
||||||
// columnSortBy: 'created_at',
|
...query,
|
||||||
// ...query,
|
page: 1,
|
||||||
// page: 1,
|
pageSize: EXPORT_SIZE_LIMIT,
|
||||||
// pageSize: EXPORT_SIZE_LIMIT,
|
filterQuery,
|
||||||
// filterQuery,
|
} as ISalesReceiptsFilter;
|
||||||
// } as ISalesReceiptsFilter;
|
|
||||||
|
|
||||||
// return this.saleReceiptsApp
|
return this.saleReceiptsApp
|
||||||
// .getSaleReceipts(tenantId, parsedQuery)
|
.getSaleReceipts(parsedQuery)
|
||||||
// .then((output) => output.data);
|
.then((output) => output.data);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -1,45 +1,44 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
// import { IAccountCreateDTO, ISaleReceiptDTO } from '@/interfaces';
|
import { CreateSaleReceipt } from './CreateSaleReceipt.service';
|
||||||
// import { CreateSaleReceipt } from './commands/CreateSaleReceipt.service';
|
import { Importable } from '@/modules/Import/Importable';
|
||||||
// import { Importable } from '@/services/Import/Importable';
|
import { CreateSaleReceiptDto } from '../dtos/SaleReceipt.dto';
|
||||||
// import { SaleReceiptsSampleData } from './constants';
|
import { SaleReceiptsSampleData } from '../constants';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleReceiptsImportable extends Importable {
|
export class SaleReceiptsImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly createReceiptService: CreateSaleReceipt) {
|
||||||
// private createReceiptService: CreateSaleReceipt;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to sale receipts service.
|
* Importing to sale receipts service.
|
||||||
// * @param {number} tenantId
|
* @param {number} tenantId
|
||||||
// * @param {IAccountCreateDTO} createAccountDTO
|
* @param {IAccountCreateDTO} createAccountDTO
|
||||||
// * @returns
|
* @returns
|
||||||
// */
|
*/
|
||||||
// public importable(
|
public importable(
|
||||||
// tenantId: number,
|
createAccountDTO: CreateSaleReceiptDto,
|
||||||
// createAccountDTO: ISaleReceiptDTO,
|
trx?: Knex.Transaction,
|
||||||
// trx?: Knex.Transaction
|
) {
|
||||||
// ) {
|
return this.createReceiptService.createSaleReceipt(
|
||||||
// return this.createReceiptService.createSaleReceipt(
|
createAccountDTO,
|
||||||
// tenantId,
|
trx,
|
||||||
// createAccountDTO,
|
);
|
||||||
// trx
|
}
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return SaleReceiptsSampleData;
|
return SaleReceiptsSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { MetadataModelMixin } from '@/modules/DynamicListing/models/MetadataMode
|
|||||||
import { ResourceableModelMixin } from '@/modules/Resource/models/ResourcableModel';
|
import { ResourceableModelMixin } from '@/modules/Resource/models/ResourcableModel';
|
||||||
import { CustomViewBaseModelMixin } from '@/modules/CustomViews/CustomViewBaseModel';
|
import { CustomViewBaseModelMixin } from '@/modules/CustomViews/CustomViewBaseModel';
|
||||||
import { SearchableBaseModelMixin } from '@/modules/DynamicListing/models/SearchableBaseModel';
|
import { SearchableBaseModelMixin } from '@/modules/DynamicListing/models/SearchableBaseModel';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
|
||||||
const ExtendedModel = R.pipe(
|
const ExtendedModel = R.pipe(
|
||||||
CustomViewBaseModelMixin,
|
CustomViewBaseModelMixin,
|
||||||
@@ -20,6 +21,7 @@ const ExtendedModel = R.pipe(
|
|||||||
MetadataModelMixin,
|
MetadataModelMixin,
|
||||||
)(BaseModel);
|
)(BaseModel);
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
export class SaleReceipt extends ExtendedModel {
|
export class SaleReceipt extends ExtendedModel {
|
||||||
public amount!: number;
|
public amount!: number;
|
||||||
public exchangeRate!: number;
|
public exchangeRate!: number;
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import { WriteTaxTransactionsItemEntries } from './WriteTaxTransactionsItemEntri
|
|||||||
import { SyncItemTaxRateOnEditTaxRate } from './SyncItemTaxRateOnEditTaxRate';
|
import { SyncItemTaxRateOnEditTaxRate } from './SyncItemTaxRateOnEditTaxRate';
|
||||||
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
||||||
import { TaxRateTransaction } from './models/TaxRateTransaction.model';
|
import { TaxRateTransaction } from './models/TaxRateTransaction.model';
|
||||||
|
import { TaxRatesExportable } from './TaxRatesExportable';
|
||||||
|
import { TaxRatesImportable } from './TaxRatesImportable';
|
||||||
|
|
||||||
const models = [RegisterTenancyModel(TaxRateTransaction)];
|
const models = [RegisterTenancyModel(TaxRateTransaction)];
|
||||||
|
|
||||||
@@ -47,6 +49,8 @@ const models = [RegisterTenancyModel(TaxRateTransaction)];
|
|||||||
SyncItemTaxRateOnEditTaxSubscriber,
|
SyncItemTaxRateOnEditTaxSubscriber,
|
||||||
WriteTaxTransactionsItemEntries,
|
WriteTaxTransactionsItemEntries,
|
||||||
SyncItemTaxRateOnEditTaxRate,
|
SyncItemTaxRateOnEditTaxRate,
|
||||||
|
TaxRatesExportable,
|
||||||
|
TaxRatesImportable
|
||||||
],
|
],
|
||||||
exports: [ItemEntriesTaxTransactions, ...models],
|
exports: [ItemEntriesTaxTransactions, ...models],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
|
||||||
// import { Exportable } from '../Export/Exportable';
|
import { Exportable } from '../Export/Exportable';
|
||||||
// import { TaxRatesApplication } from './TaxRate.application';
|
import { TaxRateModel } from './models/TaxRate.model';
|
||||||
|
import { TaxRatesApplication } from './TaxRate.application';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class TaxRatesExportable extends Exportable {
|
@ExportableService({ name: TaxRateModel.name })
|
||||||
// @Inject()
|
export class TaxRatesExportable extends Exportable {
|
||||||
// private taxRatesApplication: TaxRatesApplication;
|
constructor(private readonly taxRatesApplication: TaxRatesApplication) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the accounts data to exportable sheet.
|
* Retrieves the accounts data to exportable sheet.
|
||||||
// * @param {number} tenantId
|
*/
|
||||||
// * @returns
|
public exportable() {
|
||||||
// */
|
return this.taxRatesApplication.getTaxRates();
|
||||||
// public exportable(tenantId: number) {
|
}
|
||||||
// return this.taxRatesApplication.getTaxRates(tenantId);
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,46 +1,40 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Knex } from 'knex';
|
||||||
// import { Knex } from 'knex';
|
import { CreateTaxRate } from './commands/CreateTaxRate.service';
|
||||||
// import { ICreateTaxRateDTO } from '@/interfaces';
|
import { Importable } from '../Import/Importable';
|
||||||
// import { CreateTaxRate } from './commands/CreateTaxRate.service';
|
import { TaxRatesSampleData } from './TaxRatesImportable.SampleData';
|
||||||
// import { Importable } from '../Import/Importable';
|
import { CreateTaxRateDto } from './dtos/TaxRate.dto';
|
||||||
// import { TaxRatesSampleData } from './TaxRatesImportable.SampleData';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class TaxRatesImportable extends Importable {
|
export class TaxRatesImportable extends Importable {
|
||||||
// @Inject()
|
constructor(private readonly createTaxRateService: CreateTaxRate) {
|
||||||
// private createTaxRateService: CreateTaxRate;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Importing to tax rate creating service.
|
* Importing to tax rate creating service.
|
||||||
// * @param {number} tenantId -
|
* @param {CreateTaxRateDto} ICreateTaxRateDTO -
|
||||||
// * @param {ICreateTaxRateDTO} ICreateTaxRateDTO -
|
* @param {Knex.Transaction} trx -
|
||||||
// * @param {Knex.Transaction} trx -
|
*/
|
||||||
// * @returns
|
public importable(
|
||||||
// */
|
createAccountDTO: CreateTaxRateDto,
|
||||||
// public importable(
|
trx?: Knex.Transaction,
|
||||||
// tenantId: number,
|
) {
|
||||||
// createAccountDTO: ICreateTaxRateDTO,
|
return this.createTaxRateService.createTaxRate(createAccountDTO, trx);
|
||||||
// trx?: Knex.Transaction
|
}
|
||||||
// ) {
|
|
||||||
// return this.createTaxRateService.createTaxRate(
|
|
||||||
// tenantId,
|
|
||||||
// createAccountDTO,
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Concurrrency controlling of the importing process.
|
* Concurrrency controlling of the importing process.
|
||||||
// * @returns {number}
|
* @returns {number}
|
||||||
// */
|
*/
|
||||||
// public get concurrency() {
|
public get concurrency() {
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Retrieves the sample data that used to download accounts sample sheet.
|
* Retrieves the sample data that used to download accounts sample sheet.
|
||||||
// */
|
*/
|
||||||
// public sampleData(): any[] {
|
public sampleData(): any[] {
|
||||||
// return TaxRatesSampleData;
|
return TaxRatesSampleData;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { mixin, Model, raw } from 'objection';
|
|||||||
// import TaxRateMeta from './TaxRate.settings';
|
// import TaxRateMeta from './TaxRate.settings';
|
||||||
// import ModelSetting from './ModelSetting';
|
// import ModelSetting from './ModelSetting';
|
||||||
import { BaseModel } from '@/models/Model';
|
import { BaseModel } from '@/models/Model';
|
||||||
|
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||||
|
|
||||||
|
@ExportableModel()
|
||||||
export class TaxRateModel extends BaseModel {
|
export class TaxRateModel extends BaseModel {
|
||||||
active!: boolean;
|
active!: boolean;
|
||||||
code!: string;
|
code!: string;
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ const models = [
|
|||||||
TenantUser,
|
TenantUser,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorator factory that registers a model with the tenancy system.
|
* Decorator factory that registers a model with the tenancy system.
|
||||||
* @param model The model class to register
|
* @param model The model class to register
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user