refactor(nestjs): export module

This commit is contained in:
Ahmed Bouhuolia
2025-04-08 16:19:35 +02:00
parent 6287f8b6e3
commit 04c25bd31a
60 changed files with 748 additions and 504 deletions

View 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',
};

View File

@@ -17,6 +17,7 @@ import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
import { BankAccount } from '../BankingTransactions/models/BankAccount';
import { GetAccountsService } from './GetAccounts.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { AccountsExportable } from './AccountsExportable.service';
// import { GetAccountsService } from './GetAccounts.service';
const models = [RegisterTenancyModel(BankAccount)];
@@ -38,6 +39,7 @@ const models = [RegisterTenancyModel(BankAccount)];
GetAccountTypesService,
GetAccountTransactionsService,
GetAccountsService,
AccountsExportable
],
exports: [AccountRepository, CreateAccountService, ...models],
})

View File

@@ -2,8 +2,16 @@ import { AccountsApplication } from './AccountsApplication.service';
import { Exportable } from '../Export/Exportable';
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
import { IAccountsFilter, IAccountsStructureType } from './Accounts.types';
import { Injectable } from '@nestjs/common';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { Account } from './models/Account.model';
@Injectable()
@ExportableService({ name: Account.name })
export class AccountsExportable extends Exportable {
/**
* @param {AccountsApplication} accountsApplication
*/
constructor(private readonly accountsApplication: AccountsApplication) {
super();
}

View File

@@ -15,12 +15,13 @@ import { Model } from 'objection';
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
import { ExportableModel } from '../../Export/decorators/ExportableModel.decorator';
// import AccountSettings from './Account.Settings';
// import { DEFAULT_VIEWS } from '@/modules/Accounts/constants';
// import { buildFilterQuery, buildSortColumnQuery } from '@/lib/ViewRolesBuilder';
// import { flatToNestedArray } from 'utils';
@ExportableModel()
export class Account extends TenantBaseModel {
public name!: string;
public slug!: string;

View File

@@ -79,6 +79,7 @@ import { TenancyModule } from '../Tenancy/Tenancy.module';
import { LoopsModule } from '../Loops/Loops.module';
import { AttachmentsModule } from '../Attachments/Attachment.module';
import { S3Module } from '../S3/S3.module';
import { ExportModule } from '../Export/Export.module';
@Module({
imports: [
@@ -192,7 +193,8 @@ import { S3Module } from '../S3/S3.module';
PaymentServicesModule,
LoopsModule,
AttachmentsModule,
S3Module
S3Module,
ExportModule
],
controllers: [AppController],
providers: [

View File

@@ -16,6 +16,7 @@ import { BillPaymentGLEntries } from './commands/BillPaymentGLEntries';
import { BillPaymentGLEntriesSubscriber } from './subscribers/BillPaymentGLEntriesSubscriber';
import { LedgerModule } from '../Ledger/Ledger.module';
import { AccountsModule } from '../Accounts/Accounts.module';
import { BillPaymentsExportable } from './queries/BillPaymentsExportable';
@Module({
imports: [LedgerModule, AccountsModule],
@@ -34,6 +35,7 @@ import { AccountsModule } from '../Accounts/Accounts.module';
TenancyContext,
BillPaymentGLEntries,
BillPaymentGLEntriesSubscriber,
BillPaymentsExportable
],
exports: [BillPaymentValidators, CreateBillPaymentService],
controllers: [BillPaymentsController],

View File

@@ -20,12 +20,12 @@ export class BillPaymentsApplication {
private deleteBillPaymentService: DeleteBillPayment,
private getBillPaymentService: GetBillPayment,
private getPaymentBillsService: GetPaymentBills,
// private getBillPaymentsService: GetBillPayments,
private getBillPaymentsService: GetBillPayments,
) {}
/**
* Creates a bill payment with associated GL entries.
* @param {IBillPaymentDTO} billPaymentDTO
* @param {IBillPaymentDTO} billPaymentDTO - Create bill payment dto.
* @returns {Promise<IBillPayment>}
*/
public createBillPayment(billPaymentDTO: CreateBillPaymentDto) {
@@ -34,7 +34,7 @@ export class BillPaymentsApplication {
/**
* Delets the given bill payment with associated GL entries.
* @param {number} billPaymentId
* @param {number} billPaymentId - Bill payment id.
*/
public deleteBillPayment(billPaymentId: number) {
return this.deleteBillPaymentService.deleteBillPayment(billPaymentId);
@@ -58,13 +58,10 @@ export class BillPaymentsApplication {
/**
* Retrieves bill payments list.
* @param {number} tenantId
* @param filterDTO
* @returns
*/
// public getBillPayments(filterDTO: IBillPaymentsFilter) {
// return this.getBillPaymentsService.getBillPayments(filterDTO);
// }
public getBillPayments(filterDTO: IBillPaymentsFilter) {
return this.getBillPaymentsService.getBillPayments(filterDTO);
}
/**
* Retrieve specific bill payment.

View File

@@ -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);
// }
// }

View File

@@ -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 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);
}
}

View File

@@ -26,6 +26,7 @@ import { BillInventoryTransactions } from './commands/BillInventoryTransactions'
import { GetBillsService } from './queries/GetBills.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
import { BillsExportable } from './commands/BillsExportable';
@Module({
imports: [
@@ -57,6 +58,7 @@ import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
BillGLEntriesSubscriber,
BillInventoryTransactions,
BillWriteInventoryTransactionsSubscriber,
BillsExportable
],
controllers: [BillsController],
})

View File

@@ -1,37 +1,35 @@
// import { Inject, Service } from 'typedi';
// import { Knex } from 'knex';
// import { IBillsFilter } from '@/interfaces';
// import { Exportable } from '@/services/Export/Exportable';
// import { BillsApplication } from '../Bills.application';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
// import Objection from 'objection';
import { Knex } from 'knex';
import { BillsApplication } from '../Bills.application';
import { Injectable } from '@nestjs/common';
import { Exportable } from '@/modules/Export/Exportable';
import { IBillsFilter } from '../Bills.types';
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
// @Service()
// export class BillsExportable extends Exportable {
// @Inject()
// private billsApplication: BillsApplication;
@Injectable()
export class BillsExportable extends Exportable {
constructor(private readonly billsApplication: BillsApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: IBillsFilter) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// query.withGraphFetched('warehouse');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// filterQuery,
// } as IBillsFilter;
/**
* Retrieves the accounts data to exportable sheet.
*/
public exportable(query: IBillsFilter) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
query.withGraphFetched('warehouse');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
filterQuery,
} as IBillsFilter;
// return this.billsApplication
// .getBills(tenantId, parsedQuery)
// .then((output) => output.bills);
// }
// }
return this.billsApplication
.getBills(parsedQuery)
.then((output) => output.bills);
}
}

View File

@@ -14,7 +14,9 @@ import { BillLandedCost } from '@/modules/BillLandedCosts/models/BillLandedCost'
import { DiscountType } from '@/common/types/Discount';
import type { Knex, QueryBuilder } from 'knex';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class Bill extends TenantBaseModel {
public amount: number;
public paymentAmount: number;

View File

@@ -13,8 +13,7 @@ export class GetBillPayments {
/**
* Retrieve the specific bill associated payment transactions.
* @param {number} billId
* @returns {}
* @param {number} billId - Bill id.
*/
public getBillPayments = async (billId: number) => {
const billsEntries = await this.billPaymentEntryModel

View File

@@ -24,6 +24,7 @@ import { LedgerModule } from '../Ledger/Ledger.module';
import { AccountsModule } from '../Accounts/Accounts.module';
import { GetCreditNotesService } from './queries/GetCreditNotes.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { CreditNotesExportable } from './commands/CreditNotesExportable';
@Module({
imports: [
@@ -53,6 +54,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
CreditNoteBrandingTemplate,
CreditNoteGLEntries,
CreditNoteGLEntriesSubscriber,
CreditNotesExportable
],
exports: [
CreateCreditNoteService,

View File

@@ -1,35 +1,34 @@
// import { Inject, Service } from 'typedi';
// import { ICreditNotesQueryDTO } from '@/interfaces';
// import { Exportable } from '@/services/Export/Exportable';
// import ListCreditNotes from '../ListCreditNotes';
import { Exportable } from '@/modules/Export/Exportable';
import { CreditNoteApplication } from '../CreditNoteApplication.service';
import { Injectable } from '@nestjs/common';
import { ICreditNotesQueryDTO } from '../types/CreditNotes.types';
// @Service()
// export class CreditNotesExportable extends Exportable {
// @Inject()
// private getCreditNotes: ListCreditNotes;
@Injectable()
export class CreditNotesExportable extends Exportable {
constructor(private readonly creditNotesApp: CreditNoteApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId -
// * @param {IVendorCreditsQueryDTO} query -
// * @returns {}
// */
// public exportable(tenantId: number, query: ICreditNotesQueryDTO) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// query.withGraphFetched('warehouse');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: 12000,
// filterQuery,
// } as ICreditNotesQueryDTO;
/**
* Retrieves the accounts data to exportable sheet.
* @param {IVendorCreditsQueryDTO} query -
*/
public exportable(query: ICreditNotesQueryDTO) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
query.withGraphFetched('warehouse');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: 12000,
filterQuery,
} as ICreditNotesQueryDTO;
// return this.getCreditNotes
// .getCreditNotesList(tenantId, parsedQuery)
// .then((output) => output.creditNotes);
// }
// }
return this.creditNotesApp
.getCreditNotes(parsedQuery)
.then((output) => output.creditNotes);
}
}

View File

@@ -2,11 +2,13 @@ import { DiscountType } from '@/common/types/Discount';
import { BaseModel } from '@/models/Model';
import { Branch } from '@/modules/Branches/models/Branch.model';
import { Customer } from '@/modules/Customers/models/Customer';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
import { mixin, Model, raw } from 'objection';
@ExportableModel()
export class CreditNote extends TenantBaseModel {
public amount: number;
public exchangeRate: number;

View File

@@ -12,6 +12,7 @@ import { CreateEditCustomerDTO } from './commands/CreateEditCustomerDTO.service'
import { CustomersController } from './Customers.controller';
import { CustomersApplication } from './CustomersApplication.service';
import { DeleteCustomer } from './commands/DeleteCustomer.service';
import { CustomersExportable } from './CustomersExportable';
@Module({
imports: [TenancyDatabaseModule],
@@ -29,7 +30,8 @@ import { DeleteCustomer } from './commands/DeleteCustomer.service';
DeleteCustomer,
TenancyContext,
TransformerInjectable,
GetCustomerService
GetCustomerService,
CustomersExportable
],
})
export class CustomersModule {}

View File

@@ -4,9 +4,10 @@ import { CreateCustomer } from './commands/CreateCustomer.service';
import { EditCustomer } from './commands/EditCustomer.service';
import { DeleteCustomer } from './commands/DeleteCustomer.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 { EditCustomerDto } from './dtos/EditCustomer.dto';
import { GetCustomers } from './queries/GetCustomers.service';
@Injectable()
export class CustomersApplication {
@@ -16,13 +17,12 @@ export class CustomersApplication {
private editCustomerService: EditCustomer,
private deleteCustomerService: DeleteCustomer,
private editOpeningBalanceService: EditOpeningBalanceCustomer,
// private getCustomersService: GetCustomers,
private getCustomersService: GetCustomers,
) {}
/**
* Retrieves the given customer details.
* @param {number} tenantId
* @param {number} customerId
* @param {number} customerId - Customer id.
*/
public getCustomer = (customerId: number) => {
return this.getCustomerService.getCustomer(customerId);
@@ -30,7 +30,7 @@ export class CustomersApplication {
/**
* Creates a new customer.
* @param {ICustomerNewDTO} customerDTO
* @param {ICustomerNewDTO} customerDTO - Create customer dto.
* @returns {Promise<ICustomer>}
*/
public createCustomer = (customerDTO: CreateCustomerDto) => {
@@ -49,9 +49,7 @@ export class CustomersApplication {
/**
* Deletes the given customer and associated transactions.
* @param {number} tenantId
* @param {number} customerId
* @param {ISystemUser} authorizedUser
* @param {number} customerId - Customer id.
* @returns {Promise<void>}
*/
public deleteCustomer = (customerId: number) => {
@@ -60,9 +58,8 @@ export class CustomersApplication {
/**
* Changes the opening balance of the given customer.
* @param {number} tenantId
* @param {number} customerId
* @param {Date|string} openingBalanceEditDTO
* @param {number} customerId - Customer id.
* @param {Date|string} openingBalanceEditDTO - Opening balance edit dto.
* @returns {Promise<ICustomer>}
*/
public editOpeningBalance = (
@@ -77,10 +74,9 @@ export class CustomersApplication {
/**
* Retrieve customers paginated list.
* @param {number} tenantId - Tenant id.
* @param {ICustomersFilter} filter - Cusotmers filter.
*/
// public getCustomers = (filterDTO: ICustomersFilter) => {
// return this.getCustomersService.getCustomersList(filterDTO);
// };
public getCustomers = (filterDTO: ICustomersFilter) => {
return this.getCustomersService.getCustomersList(filterDTO);
};
}

View File

@@ -1,30 +1,34 @@
// import { Inject, Service } from 'typedi';
// import { IItemsFilter } from '@/interfaces';
// import { CustomersApplication } from './CustomersApplication';
// import { Exportable } from '@/services/Export/Exportable';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
import { Injectable } from '@nestjs/common';
import { CustomersApplication } from './CustomersApplication.service';
import { IItemsFilter } from '../Items/types/Items.types';
import { EXPORT_SIZE_LIMIT } from '../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()
// export class CustomersExportable extends Exportable {
// @Inject()
// private customersApplication: CustomersApplication;
@Injectable()
@ExportableService({ name: Customer.name })
export class CustomersExportable extends Exportable {
constructor(private readonly customersApplication: CustomersApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: IItemsFilter) {
// const parsedQuery = {
// sortOrder: 'DESC',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// } as IItemsFilter;
/**
* Retrieves the accounts data to exportable sheet.
* @param {ICustomersFilter} query - Customers query.
*/
public exportable(query: ICustomersFilter) {
const parsedQuery = {
sortOrder: 'DESC',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
} as IItemsFilter;
// return this.customersApplication
// .getCustomers(tenantId, parsedQuery)
// .then((output) => output.customers);
// }
// }
return this.customersApplication
.getCustomers(parsedQuery)
.then((output) => output.customers);
}
}

View File

@@ -17,6 +17,7 @@ import { LedgerModule } from '../Ledger/Ledger.module';
import { BranchesModule } from '../Branches/Branches.module';
import { GetExpensesService } from './queries/GetExpenses.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { ExpensesExportable } from './ExpensesExportable';
@Module({
imports: [LedgerModule, BranchesModule, DynamicListModule],
@@ -37,6 +38,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
ExpenseGLEntriesStorageService,
ExpenseGLEntriesService,
GetExpensesService,
ExpensesExportable
],
})
export class ExpensesModule {}

View File

@@ -1,34 +1,38 @@
// import { Inject, Service } from 'typedi';
// import { Exportable } from '../Export/Exportable';
// import { IExpensesFilter } from '@/interfaces';
// import { ExpensesApplication } from './ExpensesApplication.service';
// import { EXPORT_SIZE_LIMIT } from '../Export/constants';
import { Exportable } from '../Export/Exportable';
import { ExpensesApplication } from './ExpensesApplication.service';
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
import { Injectable } from '@nestjs/common';
import { IExpensesFilter } from './Expenses.types';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { Expense } from './models/Expense.model';
// @Service()
// export class ExpensesExportable extends Exportable {
// @Inject()
// private expensesApplication: ExpensesApplication;
@Injectable()
@ExportableService({ name: Expense.name })
export class ExpensesExportable extends Exportable {
constructor(
private readonly expensesApplication: ExpensesApplication,
) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: IExpensesFilter) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// filterQuery,
// } as IExpensesFilter;
/**
* Retrieves the accounts data to exportable sheet.
*/
public exportable(query: IExpensesFilter) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
filterQuery,
} as IExpensesFilter;
// return this.expensesApplication
// .getExpenses(tenantId, parsedQuery)
// .then((output) => output.expenses);
// }
// }
return this.expensesApplication
.getExpenses(parsedQuery)
.then((output) => output.expenses);
}
}

View File

@@ -3,7 +3,9 @@ import * as moment from 'moment';
import { ExpenseCategory } from './ExpenseCategory.model';
import { Account } from '@/modules/Accounts/models/Account.model';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class Expense extends TenantBaseModel {
totalAmount!: number;
currencyCode!: string;

View File

@@ -1,20 +1,24 @@
import { Response } from 'express';
import { convertAcceptFormatToFormat } from './_utils';
import { Controller, Headers, Query, Res } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
import { AcceptType } from '@/constants/accept-type';
import { ExportQuery } from './dtos/ExportQuery.dto';
import { ExportResourceService } from './ExportService';
import { AcceptType } from '@/constants/accept-type';
import { convertAcceptFormatToFormat } from './Export.utils';
@Controller('/export')
@ApiTags('export')
export class ExportController {
constructor(private readonly exportResourceApp: ExportResourceService) {}
@Get()
@ApiOperation({ summary: 'Retrieves exported the given resource.' })
async export(
@Query() query: ExportQuery,
@Res() res: Response,
@Headers('accept') acceptHeader: string,
) {
const applicationFormat = convertAcceptFormatToFormat(acceptType);
const applicationFormat = convertAcceptFormatToFormat(acceptHeader);
const data = await this.exportResourceApp.export(
query.resource,

View File

@@ -0,0 +1,13 @@
import { ACCEPT_TYPE } from '@/common/constants/http.constants';
import { ExportFormat } from './common';
export const convertAcceptFormatToFormat = (accept: string): ExportFormat => {
switch (accept) {
case ACCEPT_TYPE.APPLICATION_CSV:
return ExportFormat.Csv;
case ACCEPT_TYPE.APPLICATION_PDF:
return ExportFormat.Pdf;
case ACCEPT_TYPE.APPLICATION_XLSX:
return ExportFormat.Xlsx;
}
};

View File

@@ -1,22 +1,3 @@
// 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";
@@ -33,7 +14,7 @@ export class ExportableResources {
* Importable instances.
*/
private importables = [
{ resource: 'Account', exportable: AccountsExportable },
// { resource: 'Account', exportable: AccountsExportable },
// { resource: 'Item', exportable: ItemsExportable },
// { resource: 'ItemCategory', exportable: ItemCategoriesExportable },
// { resource: 'Customer', exportable: CustomersExportable },

View File

@@ -22,7 +22,6 @@ export class ExportResourceService {
) {}
/**
*
* @param {string} resourceName
* @param {ExportFormat} format
* @returns
@@ -46,15 +45,14 @@ export class ExportResourceService {
format: ExportFormat = ExportFormat.Csv
) {
const resource = sanitizeResourceName(resourceName);
const resourceMeta = this.getResourceMeta(tenantId, resource);
const resourceMeta = this.getResourceMeta(resource);
const resourceColumns = this.resourceService.getResourceColumns(
tenantId,
resource
);
this.validateResourceMeta(resourceMeta);
const data = await this.getExportableData(tenantId, resource);
const transformed = this.transformExportedData(tenantId, resource, data);
const data = await this.getExportableData(resource);
const transformed = this.transformExportedData(resource, data);
// Returns the csv, xlsx format.
if (format === ExportFormat.Csv || format === ExportFormat.Xlsx) {
@@ -67,7 +65,6 @@ export class ExportResourceService {
const printableColumns = this.getPrintableColumns(resourceMeta);
return this.exportPdf.pdf(
tenantId,
printableColumns,
transformed,
resourceMeta?.print?.pageTitle

View File

@@ -6,7 +6,7 @@ export class Exportable {
*/
public async exportable(
query: Record<string, any>,
): Promise<Array<Record<string, any>>> {
): Promise<any> {
return [];
}

View File

@@ -0,0 +1,32 @@
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);
};
}
/**
* 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);
}

View File

@@ -20,9 +20,9 @@ import {
} from 'lodash';
import pluralize from 'pluralize';
import { ResourceMetaFieldsMap } from './interfaces';
import { IModelMetaField, IModelMetaField2 } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import { multiNumberParse } from '@/utils/multi-number-parse';
import { ServiceError } from '../Items/ServiceError';
import { IModelMetaField, IModelMetaField2 } from '@/interfaces/Model';
export const ERRORS = {
RESOURCE_NOT_IMPORTABLE: 'RESOURCE_NOT_IMPORTABLE',
@@ -336,7 +336,7 @@ export const valueParser =
* @param {string} key - Mapped key path. formats: `group.key` or `key`.
* @returns {string}
*/
export const parseKey: R.Curry<string> = R.curry(
export const parseKey = R.curry(
(fields: { [key: string]: IModelMetaField2 }, key: string) => {
const fieldKey = getFieldKey(key);
const field = fields[fieldKey];

View File

@@ -8,6 +8,7 @@ export class Import extends BaseModel {
mapping!: string;
columns!: string;
params!: string;
importId!: string;
/**
* Table name.

View File

@@ -1,29 +1,29 @@
// import { Inject, Service } from 'typedi';
// import { Exportable } from '../Export/Exportable';
// import { IAccountsFilter, IAccountsStructureType } from '@/interfaces';
// import ItemCategoriesService from './ItemCategoriesService';
import { Injectable } from '@nestjs/common';
import { Exportable } from '../Export/Exportable';
import { ItemCategoryApplication } from './ItemCategory.application';
import { IItemCategoriesFilter } from './ItemCategory.interfaces';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { ItemCategory } from './models/ItemCategory.model';
// @Service()
// export class ItemCategoriesExportable extends Exportable {
// @Inject()
// private itemCategoriesApplication: ItemCategoriesService;
@Injectable()
@ExportableService({ name: ItemCategory.name })
export class ItemCategoriesExportable extends Exportable {
constructor(private readonly itemCategoryApp: ItemCategoryApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: IAccountsFilter) {
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// inactiveMode: false,
// ...query,
// structure: IAccountsStructureType.Flat,
// } as IAccountsFilter;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(query: Partial<IItemCategoriesFilter>) {
const parsedQuery = {
...query
} as IItemCategoriesFilter;
// return this.itemCategoriesApplication
// .getItemCategoriesList(tenantId, parsedQuery, {})
// .then((output) => output.itemCategories);
// }
// }
return this.itemCategoryApp
.getItemCategories(parsedQuery)
.then((output) => output.itemCategories);
}
}

View File

@@ -11,6 +11,7 @@ import { TransformerInjectable } from '../Transformer/TransformerInjectable.serv
import { TenancyContext } from '../Tenancy/TenancyContext.service';
import { GetItemCategoriesService } from './queries/GetItemCategories.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { ItemCategoriesExportable } from './ItemCategoriesExportable';
@Module({
imports: [TenancyDatabaseModule, DynamicListModule],
@@ -23,6 +24,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
DeleteItemCategoryService,
ItemCategoryApplication,
CommandItemCategoryValidatorService,
ItemCategoriesExportable,
TransformerInjectable,
TenancyContext,
],

View File

@@ -1,6 +1,8 @@
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { Model } from 'objection';
@ExportableModel()
export class ItemCategory extends TenantBaseModel {
name!: string;
description!: string;

View File

@@ -1,7 +1,9 @@
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { Model } from 'objection';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class Item extends TenantBaseModel {
public readonly quantityOnHand: number;
public readonly name: string;

View File

@@ -15,6 +15,7 @@ import { GetManualJournal } from './queries/GetManualJournal.service';
import { ManualJournalWriteGLSubscriber } from './commands/ManualJournalGLEntriesSubscriber';
import { ManualJournalGLEntries } from './commands/ManualJournalGLEntries';
import { LedgerModule } from '../Ledger/Ledger.module';
import { ManualJournalsExportable } from './commands/ManualJournalExportable';
@Module({
imports: [BranchesModule, LedgerModule],
@@ -33,7 +34,8 @@ import { LedgerModule } from '../Ledger/Ledger.module';
ManualJournalsApplication,
GetManualJournal,
ManualJournalGLEntries,
ManualJournalWriteGLSubscriber
ManualJournalWriteGLSubscriber,
ManualJournalsExportable
],
})
export class ManualJournalsModule {}

View File

@@ -4,8 +4,12 @@ import { EditManualJournal } from './commands/EditManualJournal.service';
import { PublishManualJournal } from './commands/PublishManualJournal.service';
import { GetManualJournal } from './queries/GetManualJournal.service';
import { DeleteManualJournalService } from './commands/DeleteManualJournal.service';
import { IManualJournalDTO, } from './types/ManualJournals.types';
import { CreateManualJournalDto, EditManualJournalDto } from './dtos/ManualJournal.dto';
import { IManualJournalsFilter } from './types/ManualJournals.types';
import {
CreateManualJournalDto,
EditManualJournalDto,
} from './dtos/ManualJournal.dto';
import { GetManualJournals } from './queries/GetManualJournals.service';
// import { GetManualJournals } from './queries/GetManualJournals';
@Injectable()
@@ -16,7 +20,7 @@ export class ManualJournalsApplication {
private deleteManualJournalService: DeleteManualJournalService,
private publishManualJournalService: PublishManualJournal,
private getManualJournalService: GetManualJournal,
// private getManualJournalsService: GetManualJournals,
private getManualJournalsService: GetManualJournals,
) {}
/**
@@ -50,9 +54,7 @@ export class ManualJournalsApplication {
* @return {Promise<void>}
*/
public deleteManualJournal = (manualJournalId: number) => {
return this.deleteManualJournalService.deleteManualJournal(
manualJournalId,
);
return this.deleteManualJournalService.deleteManualJournal(manualJournalId);
};
/**
@@ -68,23 +70,16 @@ export class ManualJournalsApplication {
/**
* Retrieves the specific manual journal.
* @param {number} manualJournalId
* @returns
*/
public getManualJournal = (manualJournalId: number) => {
return this.getManualJournalService.getManualJournal(
manualJournalId,
);
return this.getManualJournalService.getManualJournal(manualJournalId);
};
/**
* Retrieves the paginated manual journals.
* @param {number} tenantId
* @param {IManualJournalsFilter} filterDTO
* @returns
*/
// public getManualJournals = (
// filterDTO: IManualJournalsFilter,
// ) => {
// // return this.getManualJournalsService.getManualJournals(filterDTO);
// };
public getManualJournals = (filterDTO: IManualJournalsFilter) => {
return this.getManualJournalsService.getManualJournals(filterDTO);
};
}

View File

@@ -1,30 +1,31 @@
// import { Inject, Service } from 'typedi';
// import { IManualJournalsFilter } from '@/interfaces';
// import { Exportable } from '../../Export/Exportable';
// import { ManualJournalsApplication } from '../ManualJournalsApplication';
// import { EXPORT_SIZE_LIMIT } from '../../Export/constants';
import { Exportable } from '../../Export/Exportable';
import { EXPORT_SIZE_LIMIT } from '../../Export/constants';
import { Injectable } from '@nestjs/common';
import { IManualJournalsFilter } from '../types/ManualJournals.types';
import { ManualJournalsApplication } from '../ManualJournalsApplication.service';
// @Service()
// export class ManualJournalsExportable extends Exportable {
// @Inject()
// private manualJournalsApplication: ManualJournalsApplication;
@Injectable()
export class ManualJournalsExportable extends Exportable {
constructor(
private readonly manualJournalsApplication: ManualJournalsApplication,
) {
super();
}
// /**
// * Retrieves the manual journals data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: IManualJournalsFilter) {
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// } as IManualJournalsFilter;
/**
* Retrieves the manual journals data to exportable sheet.
*/
public exportable(query: IManualJournalsFilter) {
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
} as IManualJournalsFilter;
// return this.manualJournalsApplication
// .getManualJournals(tenantId, parsedQuery)
// .then((output) => output.manualJournals);
// }
// }
return this.manualJournalsApplication
.getManualJournals(parsedQuery)
.then((output) => output.manualJournals);
}
}

View File

@@ -9,7 +9,9 @@ import { Model, mixin } from 'objection';
import { ManualJournalEntry } from './ManualJournalEntry';
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class ManualJournal extends TenantBaseModel {
date: Date;
journalNumber: string;

View File

@@ -34,6 +34,7 @@ import { MailModule } from '../Mail/Mail.module';
import { SendPaymentReceivedMailProcessor } from './processors/PaymentReceivedMailNotification.processor';
import { BullModule } from '@nestjs/bull';
import { SEND_PAYMENT_RECEIVED_MAIL_QUEUE } from './constants';
import { PaymentsReceivedExportable } from './commands/PaymentsReceivedExportable';
@Module({
controllers: [PaymentReceivesController],
@@ -59,6 +60,7 @@ import { SEND_PAYMENT_RECEIVED_MAIL_QUEUE } from './constants';
GetPaymentsReceivedService,
SendPaymentReceiveMailNotification,
SendPaymentReceivedMailProcessor,
PaymentsReceivedExportable
],
exports: [
PaymentReceivesApplication,

View File

@@ -1,39 +1,34 @@
// import { Inject, Service } from 'typedi';
// import { IAccountsStructureType, IPaymentsReceivedFilter } from '@/interfaces';
// import { Exportable } from '@/services/Export/Exportable';
// import { PaymentReceivesApplication } from './PaymentReceived.application';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
import { Injectable } from '@nestjs/common';
import { PaymentReceivesApplication } from '../PaymentReceived.application';
import { IPaymentsReceivedFilter } from '../types/PaymentReceived.types';
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
import { Exportable } from '@/modules/Export/Exportable';
// @Service()
// export class PaymentsReceivedExportable extends Exportable {
// @Inject()
// private paymentReceivedApp: PaymentReceivesApplication;
@Injectable()
export class PaymentsReceivedExportable extends Exportable {
constructor(private readonly paymentReceivedApp: PaymentReceivesApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @param {IPaymentsReceivedFilter} query -
// * @returns
// */
// public exportable(tenantId: number, query: IPaymentsReceivedFilter) {
// const filterQuery = (builder) => {
// builder.withGraphFetched('entries.invoice');
// builder.withGraphFetched('branch');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// inactiveMode: false,
// ...query,
// structure: IAccountsStructureType.Flat,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// filterQuery,
// } as IPaymentsReceivedFilter;
// return this.paymentReceivedApp
// .getPaymentReceives(tenantId, parsedQuery)
// .then((output) => output.paymentReceives);
// }
// }
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @param {IPaymentsReceivedFilter} query -
* @returns
*/
public exportable(query: IPaymentsReceivedFilter) {
const filterQuery = (builder) => {
builder.withGraphFetched('entries.invoice');
builder.withGraphFetched('branch');
};
const parsedQuery = {
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
filterQuery,
...query
};
return this.paymentReceivedApp
.getPaymentsReceived(parsedQuery)
.then((output) => output.paymentReceives);
}
}

View File

@@ -1,7 +1,9 @@
import { Model } from 'objection';
import { PaymentReceivedEntry } from './PaymentReceivedEntry';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class PaymentReceived extends TenantBaseModel {
customerId: number;
paymentDate: string;

View File

@@ -35,6 +35,7 @@ import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectab
import { SaleEstimatePdfTemplate } from '../SaleInvoices/queries/SaleEstimatePdfTemplate.service';
import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
import { SendSaleEstimateMailQueue } from './types/SaleEstimates.types';
import { SaleEstimatesExportable } from './SaleEstimatesExportable';
@Module({
imports: [
@@ -74,7 +75,8 @@ import { SendSaleEstimateMailQueue } from './types/SaleEstimates.types';
SaleEstimatesApplication,
SendSaleEstimateMail,
GetSaleEstimatePdf,
SaleEstimatePdfTemplate
SaleEstimatePdfTemplate,
SaleEstimatesExportable
],
})
export class SaleEstimatesModule {}

View File

@@ -1,35 +1,38 @@
// import { Inject, Service } from 'typedi';
// import { ISalesInvoicesFilter } from '@/interfaces';
// import { Exportable } from '@/services/Export/Exportable';
// import { SaleEstimatesApplication } from './SaleEstimates.application';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
import { Injectable } from '@nestjs/common';
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
import { Exportable } from '../Export/Exportable';
import { ISalesInvoicesFilter } from '../SaleInvoices/SaleInvoice.types';
import { SaleEstimatesApplication } from './SaleEstimates.application';
import { ISalesEstimatesFilter } from './types/SaleEstimates.types';
// @Service()
// export class SaleEstimatesExportable extends Exportable {
// @Inject()
// private saleEstimatesApplication: SaleEstimatesApplication;
@Injectable()
export class SaleEstimatesExportable extends Exportable {
constructor(
private readonly saleEstimatesApplication: SaleEstimatesApplication,
) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: ISalesInvoicesFilter) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// query.withGraphFetched('warehouse');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// filterQuery,
// } as ISalesInvoicesFilter;
/**
* Retrieves the accounts data to exportable sheet.
* @param {ISalesEstimatesFilter} query -
*/
public exportable(query: ISalesEstimatesFilter) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
query.withGraphFetched('warehouse');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
filterQuery,
} as ISalesInvoicesFilter;
// return this.saleEstimatesApplication
// .getSaleEstimates(tenantId, parsedQuery)
// .then((output) => output.salesEstimates);
// }
// }
return this.saleEstimatesApplication
.getSaleEstimates(parsedQuery)
.then((output) => output.salesEstimates);
}
}

View File

@@ -2,8 +2,9 @@ import * as moment from 'moment';
import { Model } from 'objection';
import { Injectable } from '@nestjs/common';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@Injectable()
@ExportableModel()
export class SaleEstimate extends TenantBaseModel {
exchangeRate!: number;
amount!: number;

View File

@@ -56,6 +56,7 @@ import { SaleInvoiceCostGLEntries } from './SaleInvoiceCostGLEntries';
import { InvoicePaymentsGLEntriesRewrite } from './InvoicePaymentsGLRewrite';
import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.module';
import { SaleInvoicesCost } from './SalesInvoicesCost';
import { SaleInvoicesExportable } from './commands/SaleInvoicesExportable';
@Module({
imports: [
@@ -118,6 +119,7 @@ import { SaleInvoicesCost } from './SalesInvoicesCost';
SaleInvoiceWriteInventoryTransactionsSubscriber,
InvoicePaymentsGLEntriesRewrite,
SaleInvoicesCost,
SaleInvoicesExportable
],
exports: [GetSaleInvoice, SaleInvoicesCost, SaleInvoicePdf],
})

View File

@@ -1,35 +1,39 @@
// import { Inject, Service } from 'typedi';
// import { ISalesInvoicesFilter } from '@/interfaces';
// import { SaleInvoiceApplication } from './SaleInvoices.application';
// import { Exportable } from '@/services/Export/Exportable';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
import { Exportable } from '@/modules/Export/Exportable';
import { Injectable } from '@nestjs/common';
import { SaleInvoiceApplication } from '../SaleInvoices.application';
import { ISalesInvoicesFilter } from '../SaleInvoice.types';
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
import { SaleInvoice } from '../models/SaleInvoice';
// @Service()
// export class SaleInvoicesExportable extends Exportable {
// @Inject()
// private saleInvoicesApplication: SaleInvoiceApplication;
@Injectable()
@ExportableService({ name: SaleInvoice.name })
export class SaleInvoicesExportable extends Exportable{
constructor(
private readonly saleInvoicesApplication: SaleInvoiceApplication,
) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: ISalesInvoicesFilter) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// query.withGraphFetched('warehouse');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// filterQuery,
// } as ISalesInvoicesFilter;
/**
* Retrieves the accounts data to exportable sheet.
*/
public exportable(query: ISalesInvoicesFilter) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
query.withGraphFetched('warehouse');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
filterQuery,
} as ISalesInvoicesFilter;
// return this.saleInvoicesApplication
// .getSaleInvoices(tenantId, parsedQuery)
// .then((output) => output.salesInvoices);
// }
// }
return this.saleInvoicesApplication
.getSaleInvoices(parsedQuery)
.then((output) => output.salesInvoices);
}
}

View File

@@ -14,8 +14,10 @@ import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { PaymentIntegrationTransactionLink } from '../SaleInvoice.types';
import { TransactionPaymentServiceEntry } from '@/modules/PaymentServices/models/TransactionPaymentServiceEntry.model';
import { InjectAttachable } from '@/modules/Attachments/decorators/InjectAttachable.decorator';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@InjectAttachable()
@ExportableModel()
export class SaleInvoice extends TenantBaseModel{
public taxAmountWithheld: number;
public balance: number;

View File

@@ -35,6 +35,7 @@ import { MailNotificationModule } from '../MailNotification/MailNotification.mod
import { SendSaleReceiptMailProcess } from './processes/SendSaleReceiptMail.process';
import { MailModule } from '../Mail/Mail.module';
import { SendSaleReceiptMailQueue } from './constants';
import { SaleReceiptsExportable } from './commands/SaleReceiptsExportable';
@Module({
controllers: [SaleReceiptsController],
@@ -75,6 +76,7 @@ import { SendSaleReceiptMailQueue } from './constants';
SaleReceiptInventoryTransactions,
SaleReceiptInventoryTransactionsSubscriber,
SendSaleReceiptMailProcess,
SaleReceiptsExportable
],
})
export class SaleReceiptsModule {}

View File

@@ -1,35 +1,35 @@
// import { Inject, Service } from 'typedi';
// import { ISalesReceiptsFilter } from '@/interfaces';
// import { Exportable } from '@/services/Export/Exportable';
// import { SaleReceiptApplication } from './SaleReceiptApplication';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
import { Exportable } from '@/modules/Export/Exportable';
import { Injectable } from '@nestjs/common';
import { SaleReceiptApplication } from '../SaleReceiptApplication.service';
import { ISalesReceiptsFilter } from '../types/SaleReceipts.types';
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
// @Service()
// export class SaleReceiptsExportable extends Exportable {
// @Inject()
// private saleReceiptsApp: SaleReceiptApplication;
@Injectable()
export class SaleReceiptsExportable extends Exportable {
constructor(private readonly saleReceiptsApp: SaleReceiptApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: ISalesReceiptsFilter) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// query.withGraphFetched('warehouse');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// filterQuery,
// } as ISalesReceiptsFilter;
/**
* Retrieves the accounts data to exportable sheet.
* @param {ISalesReceiptsFilter} query -
*/
public exportable(query: ISalesReceiptsFilter) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
query.withGraphFetched('warehouse');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
filterQuery,
} as ISalesReceiptsFilter;
// return this.saleReceiptsApp
// .getSaleReceipts(tenantId, parsedQuery)
// .then((output) => output.data);
// }
// }
return this.saleReceiptsApp
.getSaleReceipts(parsedQuery)
.then((output) => output.data);
}
}

View File

@@ -12,6 +12,7 @@ import { MetadataModelMixin } from '@/modules/DynamicListing/models/MetadataMode
import { ResourceableModelMixin } from '@/modules/Resource/models/ResourcableModel';
import { CustomViewBaseModelMixin } from '@/modules/CustomViews/CustomViewBaseModel';
import { SearchableBaseModelMixin } from '@/modules/DynamicListing/models/SearchableBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
const ExtendedModel = R.pipe(
CustomViewBaseModelMixin,
@@ -20,6 +21,7 @@ const ExtendedModel = R.pipe(
MetadataModelMixin,
)(BaseModel);
@ExportableModel()
export class SaleReceipt extends ExtendedModel {
public amount!: number;
public exchangeRate!: number;

View File

@@ -21,6 +21,7 @@ import { WriteTaxTransactionsItemEntries } from './WriteTaxTransactionsItemEntri
import { SyncItemTaxRateOnEditTaxRate } from './SyncItemTaxRateOnEditTaxRate';
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
import { TaxRateTransaction } from './models/TaxRateTransaction.model';
import { TaxRatesExportable } from './TaxRatesExportable';
const models = [RegisterTenancyModel(TaxRateTransaction)];
@@ -47,6 +48,7 @@ const models = [RegisterTenancyModel(TaxRateTransaction)];
SyncItemTaxRateOnEditTaxSubscriber,
WriteTaxTransactionsItemEntries,
SyncItemTaxRateOnEditTaxRate,
TaxRatesExportable
],
exports: [ItemEntriesTaxTransactions, ...models],
})

View File

@@ -1,18 +1,20 @@
// import { Inject, Service } from 'typedi';
// import { Exportable } from '../Export/Exportable';
// import { TaxRatesApplication } from './TaxRate.application';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { Exportable } from '../Export/Exportable';
import { TaxRateModel } from './models/TaxRate.model';
import { TaxRatesApplication } from './TaxRate.application';
import { Injectable } from '@nestjs/common';
// @Service()
// export class TaxRatesExportable extends Exportable {
// @Inject()
// private taxRatesApplication: TaxRatesApplication;
@Injectable()
@ExportableService({ name: TaxRateModel.name })
export class TaxRatesExportable extends Exportable {
constructor(private readonly taxRatesApplication: TaxRatesApplication) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number) {
// return this.taxRatesApplication.getTaxRates(tenantId);
// }
// }
/**
* Retrieves the accounts data to exportable sheet.
*/
public exportable() {
return this.taxRatesApplication.getTaxRates();
}
}

View File

@@ -5,7 +5,9 @@ import { mixin, Model, raw } from 'objection';
// import TaxRateMeta from './TaxRate.settings';
// import ModelSetting from './ModelSetting';
import { BaseModel } from '@/models/Model';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class TaxRateModel extends BaseModel {
active!: boolean;
code!: string;

View File

@@ -25,6 +25,7 @@ import { VendorCreditInventoryTransactions } from './commands/VendorCreditInvent
import { GetVendorCreditsService } from './queries/GetVendorCredits.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
import { VendorCreditsExportable } from './commands/VendorCreditsExportable';
@Module({
imports: [
@@ -54,7 +55,8 @@ import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
VendorCreditGLEntries,
VendorCreditGlEntriesSubscriber,
VendorCreditInventoryTransactions,
VendorCreditInventoryTransactionsSubscriber
VendorCreditInventoryTransactionsSubscriber,
VendorCreditsExportable
],
exports: [
CreateVendorCreditService,

View File

@@ -1,36 +1,38 @@
// import { Inject, Service } from 'typedi';
// import { IVendorCreditsQueryDTO } from '@/interfaces';
// import ListVendorCredits from '../queries/ListVendorCredits';
// import { Exportable } from '@/services/Export/Exportable';
// import { QueryBuilder } from 'knex';
import { Injectable } from '@nestjs/common';
import { VendorCreditsApplicationService } from '../VendorCreditsApplication.service';
import { Exportable } from '@/modules/Export/Exportable';
import { IVendorCreditsQueryDTO } from '../types/VendorCredit.types';
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
import { VendorCredit } from '../models/VendorCredit';
// @Service()
// export class VendorCreditsExportable extends Exportable {
// @Inject()
// private getVendorCredits: ListVendorCredits;
@Injectable()
@ExportableService({ name: VendorCredit.name })
export class VendorCreditsExportable extends Exportable {
constructor(
private readonly vendorCreditsApp: VendorCreditsApplicationService,
) {
super();
}
// /**
// * Retrieves the vendor credits data to exportable sheet.
// * @param {number} tenantId -
// * @param {IVendorCreditsQueryDTO} query -
// * @returns {}
// */
// public exportable(tenantId: number, query: IVendorCreditsQueryDTO) {
// const filterQuery = (query) => {
// query.withGraphFetched('branch');
// query.withGraphFetched('warehouse');
// };
// const parsedQuery = {
// sortOrder: 'desc',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: 12000,
// filterQuery,
// } as IVendorCreditsQueryDTO;
/**
* Retrieves the vendor credits data to exportable sheet.
*/
public exportable(query: IVendorCreditsQueryDTO) {
const filterQuery = (query) => {
query.withGraphFetched('branch');
query.withGraphFetched('warehouse');
};
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: 12000,
filterQuery,
} as IVendorCreditsQueryDTO;
// return this.getVendorCredits
// .getVendorCredits(tenantId, parsedQuery)
// .then((output) => output.vendorCredits);
// }
// }
return this.vendorCreditsApp
.getVendorCredits(parsedQuery)
.then((output) => output.vendorCredits);
}
}

View File

@@ -5,7 +5,9 @@ import { Branch } from '@/modules/Branches/models/Branch.model';
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
import { DiscountType } from '@/common/types/Discount';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
@ExportableModel()
export class VendorCredit extends TenantBaseModel {
vendorId: number;
amount: number;

View File

@@ -14,6 +14,7 @@ import { TenancyContext } from '../Tenancy/TenancyContext.service';
import { VendorsController } from './Vendors.controller';
import { GetVendorsService } from './queries/GetVendors.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { VendorsExportable } from './VendorsExportable';
@Module({
imports: [TenancyDatabaseModule, DynamicListModule],
@@ -31,6 +32,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
VendorsApplication,
TransformerInjectable,
TenancyContext,
VendorsExportable
],
})
export class VendorsModule {}

View File

@@ -1,30 +1,34 @@
// import { Inject, Service } from 'typedi';
// import { IItemsFilter } from '@/interfaces';
// import { Exportable } from '@/services/Export/Exportable';
// import { VendorsApplication } from './VendorsApplication';
// import { EXPORT_SIZE_LIMIT } from '@/services/Export/constants';
import { Injectable } from '@nestjs/common';
import { VendorsApplication } from './VendorsApplication.service';
import { Exportable } from '../Export/Exportable';
import { IVendorsFilter } from './types/Vendors.types';
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { Vendor } from './models/Vendor';
// @Service()
// export class VendorsExportable extends Exportable {
// @Inject()
// private vendorsApplication: VendorsApplication;
@Injectable()
@ExportableService({ name: Vendor.name })
export class VendorsExportable extends Exportable {
constructor(
private readonly vendorsApplication: VendorsApplication,
) {
super();
}
// /**
// * Retrieves the accounts data to exportable sheet.
// * @param {number} tenantId
// * @returns
// */
// public exportable(tenantId: number, query: IItemsFilter) {
// const parsedQuery = {
// sortOrder: 'DESC',
// columnSortBy: 'created_at',
// ...query,
// page: 1,
// pageSize: EXPORT_SIZE_LIMIT,
// } as IItemsFilter;
/**
* Retrieves the vendors data to exportable sheet.
*/
public exportable(query: IVendorsFilter) {
const parsedQuery = {
sortOrder: 'DESC',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: EXPORT_SIZE_LIMIT,
} as IVendorsFilter;
// return this.vendorsApplication
// .getVendors(tenantId, parsedQuery)
// .then((output) => output.vendors);
// }
// }
return this.vendorsApplication
.getVendors(parsedQuery)
.then((output) => output.vendors);
}
}

View File

@@ -8,6 +8,7 @@ import { Model, mixin } from 'objection';
// import ModelSearchable from './ModelSearchable';
import { BaseModel } from '@/models/Model';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
// class VendorQueryBuilder extends PaginationQueryBuilder {
// constructor(...args) {
@@ -21,6 +22,7 @@ import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
// }
// }
@ExportableModel()
export class Vendor extends TenantBaseModel {
contactService: string;
contactType: string;

View File

@@ -0,0 +1,131 @@
// @ts-nocheck
const validGrouping = (integerPart, sep) =>
integerPart.split(sep).reduce((acc, group, idx) => {
if (idx > 0) {
return acc && group.length === 3;
}
return acc && group.length;
}, true);
export const multiNumberParse = (number: number | string, standardDecSep = '.') => {
// if it's a number already, this is going to be easy...
if (typeof number === 'number') {
return number;
}
// check validity of parameters
if (!number || typeof number !== 'string') {
throw new TypeError('number must be a string');
}
if (typeof standardDecSep !== 'string' || standardDecSep.length !== 1) {
throw new TypeError('standardDecSep must be a single character string');
}
// check if negative
const negative = number[0] === '-';
// strip unnecessary chars
const stripped = number
// get rid of trailing non-numbers
.replace(/[^\d]+$/, '')
// get rid of the signal
.slice(negative ? 1 : 0);
// analyze separators
const separators = (stripped.match(/[^\d]/g) || []).reduce(
(acc, sep, idx) => {
const sepChr = `str_${sep.codePointAt(0)}`;
const cnt = ((acc[sepChr] || {}).cnt || 0) + 1;
return {
...acc,
[sepChr]: {
sep,
cnt,
lastIdx: idx,
},
};
},
{}
);
// check correctness of separators
const sepKeys = Object.keys(separators);
if (!sepKeys.length) {
// no separator, that's easy-peasy
return parseInt(stripped, 10) * (negative ? -1 : 1);
}
if (sepKeys.length > 2) {
// there's more than 2 separators, that's wrong
return Number.NaN;
}
if (sepKeys.length > 1) {
// there's two separators, that's ok by now
let sep1 = separators[sepKeys[0]];
let sep2 = separators[sepKeys[1]];
if (sep1.lastIdx > sep2.lastIdx) {
// swap
[sep1, sep2] = [sep2, sep1];
}
// if more than one separator appears more than once, that's wrong
if (sep1.cnt > 1 && sep2.cnt > 1) {
return Number.NaN;
}
// check if the last separator is the single one
if (sep2.cnt > 1) {
return Number.NaN;
}
// check the groupings
const [integerPart] = stripped.split(sep2.sep);
if (!validGrouping(integerPart, sep1.sep)) {
return Number.NaN;
}
// ok, we got here! let's handle it
return (
parseFloat(stripped.split(sep1.sep).join('').replace(sep2.sep, '.')) *
(negative ? -1 : 1)
);
}
// ok, only one separator, which is nice
const sep = separators[sepKeys[0]];
if (sep.cnt > 1) {
// there's more than one separator, which means it's integer
// let's check the groupings
if (!validGrouping(stripped, sep.sep)) {
return Number.NaN;
}
// it's valid, let's return an integer
return parseInt(stripped.split(sep.sep).join(''), 10) * (negative ? -1 : 1);
}
// just one separator, let's check last group
const groups = stripped.split(sep.sep);
if (groups[groups.length - 1].length === 3) {
// ok, we're in ambiguous territory here
if (sep.sep !== standardDecSep) {
// it's an integer
return (
parseInt(stripped.split(sep.sep).join(''), 10) * (negative ? -1 : 1)
);
}
}
// well, it looks like it's a simple float
return parseFloat(stripped.replace(sep.sep, '.')) * (negative ? -1 : 1);
};