mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
refactor(nestjs): export and import module
This commit is contained in:
@@ -4,9 +4,34 @@ import { ExportResourceService } from './ExportService';
|
||||
import { ExportPdf } from './ExportPdf';
|
||||
import { ExportAls } from './ExportAls';
|
||||
import { ExportApplication } from './ExportApplication';
|
||||
import { ResourceModule } from '../Resource/Resource.module';
|
||||
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
||||
import { ImportModel } from '../Import/models/Import';
|
||||
import { ExportableResources } from './ExportResources';
|
||||
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({
|
||||
providers: [ExportResourceService, ExportPdf, ExportAls, ExportApplication],
|
||||
imports: [
|
||||
...models,
|
||||
ResourceModule,
|
||||
TemplateInjectableModule,
|
||||
ChromiumlyTenancyModule,
|
||||
AccountsModule
|
||||
],
|
||||
providers: [
|
||||
ExportResourceService,
|
||||
ExportPdf,
|
||||
ExportAls,
|
||||
ExportApplication,
|
||||
ExportableResources,
|
||||
ExportableRegistry
|
||||
],
|
||||
exports: [...models],
|
||||
controllers: [ExportController],
|
||||
})
|
||||
export class ExportModule {}
|
||||
|
||||
@@ -3,6 +3,7 @@ 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:
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
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,5 +1,5 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import xlsx from 'xlsx';
|
||||
import * as xlsx from 'xlsx';
|
||||
import * as R from 'ramda';
|
||||
import { get } from 'lodash';
|
||||
import { sanitizeResourceName } from '../Import/_utils';
|
||||
@@ -10,6 +10,9 @@ import { ExportPdf } from './ExportPdf';
|
||||
import { ExportAls } from './ExportAls';
|
||||
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()
|
||||
export class ExportResourceService {
|
||||
@@ -18,6 +21,7 @@ export class ExportResourceService {
|
||||
private readonly exportPdf: ExportPdf,
|
||||
private readonly exportableResources: ExportableResources,
|
||||
private readonly resourceService: ResourceService,
|
||||
private readonly moduleRef: ModuleRef,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -27,11 +31,9 @@ export class ExportResourceService {
|
||||
*/
|
||||
public async export(
|
||||
resourceName: string,
|
||||
format: ExportFormat = ExportFormat.Csv
|
||||
format: ExportFormat = ExportFormat.Csv,
|
||||
) {
|
||||
return this.exportAls.run(() =>
|
||||
this.exportAlsRun(resourceName, format)
|
||||
);
|
||||
return this.exportAls.run(() => this.exportAlsRun(resourceName, format));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,18 +43,19 @@ export class ExportResourceService {
|
||||
*/
|
||||
public async exportAlsRun(
|
||||
resourceName: string,
|
||||
format: ExportFormat = ExportFormat.Csv
|
||||
format: ExportFormat = ExportFormat.Csv,
|
||||
) {
|
||||
const resource = sanitizeResourceName(resourceName);
|
||||
const resourceMeta = this.getResourceMeta(resource);
|
||||
const resourceColumns = this.resourceService.getResourceColumns(
|
||||
resource
|
||||
);
|
||||
|
||||
const resourceColumns = this.resourceService.getResourceColumns(resource);
|
||||
this.validateResourceMeta(resourceMeta);
|
||||
|
||||
const data = await this.getExportableData(resource);
|
||||
const transformed = this.transformExportedData(resource, data);
|
||||
|
||||
console.log(format);
|
||||
|
||||
// Returns the csv, xlsx format.
|
||||
if (format === ExportFormat.Csv || format === ExportFormat.Xlsx) {
|
||||
const exportableColumns = this.getExportableColumns(resourceColumns);
|
||||
@@ -66,7 +69,7 @@ export class ExportResourceService {
|
||||
return this.exportPdf.pdf(
|
||||
printableColumns,
|
||||
transformed,
|
||||
resourceMeta?.print?.pageTitle
|
||||
resourceMeta?.print?.pageTitle,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -102,14 +105,14 @@ export class ExportResourceService {
|
||||
*/
|
||||
private transformExportedData(
|
||||
resource: string,
|
||||
data: Array<Record<string, any>>
|
||||
data: Array<Record<string, any>>,
|
||||
): Array<Record<string, any>> {
|
||||
const resourceMeta = this.getResourceMeta(resource);
|
||||
|
||||
return R.when<Array<Record<string, any>>, Array<Record<string, any>>>(
|
||||
R.always(Boolean(resourceMeta.exportFlattenOn)),
|
||||
(data) => flatDataCollections(data, resourceMeta.exportFlattenOn),
|
||||
data
|
||||
data,
|
||||
);
|
||||
}
|
||||
/**
|
||||
@@ -119,10 +122,14 @@ export class ExportResourceService {
|
||||
* @returns A promise that resolves to the exportable data.
|
||||
*/
|
||||
private async getExportableData(resource: string) {
|
||||
const exportable =
|
||||
this.exportableResources.registry.getExportable(resource);
|
||||
|
||||
return exportable.exportable({});
|
||||
const exportable = getExportableService(resource);
|
||||
const contextId = ContextIdFactory.create();
|
||||
const exportableInstance = await this.moduleRef.resolve(
|
||||
exportable,
|
||||
contextId,
|
||||
{ strict: false },
|
||||
);
|
||||
return exportableInstance.exportable({});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +140,7 @@ export class ExportResourceService {
|
||||
private getExportableColumns(resourceColumns: any) {
|
||||
const processColumns = (
|
||||
columns: { [key: string]: IModelMetaColumn },
|
||||
parent = ''
|
||||
parent = '',
|
||||
) => {
|
||||
return Object.entries(columns)
|
||||
.filter(([_, value]) => value.exportable !== false)
|
||||
@@ -159,9 +166,10 @@ export class ExportResourceService {
|
||||
private getPrintableColumns(resourceMeta: IModelMeta) {
|
||||
const processColumns = (
|
||||
columns: { [key: string]: IModelMetaColumn },
|
||||
parent = ''
|
||||
parent = '',
|
||||
) => {
|
||||
return Object.entries(columns)
|
||||
// @ts-expect-error
|
||||
.filter(([_, value]) => value.printable !== false)
|
||||
.flatMap(([key, value]) => {
|
||||
if (value.type === 'collection' && value.collectionOf === 'object') {
|
||||
@@ -191,7 +199,7 @@ export class ExportResourceService {
|
||||
private createWorkbook(data: any[], exportableColumns: any[]) {
|
||||
const workbook = xlsx.utils.book_new();
|
||||
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));
|
||||
|
||||
|
||||
@@ -4,8 +4,4 @@ export class ExportQuery {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
resource: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
format: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user