Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use standard ISO 8601 format for exported data #638

Merged
merged 1 commit into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions packages/server/src/lib/Transformer/Transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import moment from 'moment';
import * as R from 'ramda';
import { includes, isFunction, isObject, isUndefined, omit } from 'lodash';
import { formatNumber, sortObjectKeysAlphabetically } from 'utils';
import { EXPORT_DTE_FORMAT } from '@/services/Export/constants';

export class Transformer {
public context: any;
Expand Down Expand Up @@ -156,22 +157,34 @@ export class Transformer {
}

/**
*
* @param date
* @returns
* Format date.
* @param {} date
* @param {string} format -
* @returns {}
*/
protected formatDate(date) {
return date ? moment(date).format(this.dateFormat) : '';
protected formatDate(date, format?: string) {
// Use the export date format if the async operation is in exporting,
// otherwise use the given or default format.
const _format = this.context.exportAls.isExport
? EXPORT_DTE_FORMAT
: format || this.dateFormat;

return date ? moment(date).format(_format) : '';
}

protected formatDateFromNow(date){
/**
*
* @param date
* @returns {}
*/
protected formatDateFromNow(date) {
return date ? moment(date).fromNow(true) : '';
}

/**
*
* @param number
* @returns
* @returns {}
*/
protected formatNumber(number, props?) {
return formatNumber(number, { money: false, ...props });
Expand All @@ -181,7 +194,7 @@ export class Transformer {
*
* @param money
* @param options
* @returns
* @returns {}
*/
protected formatMoney(money, options?) {
return formatNumber(money, {
Expand Down
7 changes: 7 additions & 0 deletions packages/server/src/lib/Transformer/TransformerInjectable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ import { isNull } from 'lodash';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import { TenantMetadata } from '@/system/models';
import { Transformer } from './Transformer';
import { ImportAls } from '@/services/Import/ImportALS';
import { ExportAls } from '@/services/Export/ExportAls';

@Service()
export class TransformerInjectable {
@Inject()
private tenancy: HasTenancyService;

@Inject()
private exportAls: ExportAls;

/**
* Retrieves the application context of all tenant transformers.
* @param {number} tenantId
Expand All @@ -17,10 +22,12 @@ export class TransformerInjectable {
async getApplicationContext(tenantId: number) {
const i18n = this.tenancy.i18n(tenantId);
const organization = await TenantMetadata.query().findOne({ tenantId });
const exportAls = this.exportAls;

return {
organization,
i18n,
exportAls,
};
}

Expand Down
48 changes: 48 additions & 0 deletions packages/server/src/services/Export/ExportAls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Service } from 'typedi';
import { AsyncLocalStorage } from 'async_hooks';

@Service()
export class ExportAls {
private als: AsyncLocalStorage<Map<string, any>>;

constructor() {
this.als = new AsyncLocalStorage();
}

/**
* Runs a callback function within the context of a new AsyncLocalStorage store.
* @param callback The function to be executed within the AsyncLocalStorage context.
* @returns The result of the callback function.
*/
public run<T>(callback: () => T): T {
return this.als.run<T>(new Map(), () => {
this.markAsExport();

return callback();
});
}

/**
* Retrieves the current AsyncLocalStorage store.
* @returns The current store or undefined if not in a valid context.
*/
public getStore(): Map<string, any> | undefined {
return this.als.getStore();
}

/**
* Marks the current context as an export operation.
* @param flag Boolean flag to set or unset the export status. Defaults to true.
*/
public markAsExport(flag: boolean = true): void {
const store = this.getStore();
store?.set('isExport', flag);
}
/**
* Checks if the current context is an export operation.
* @returns {boolean} True if the context is an export operation, false otherwise.
*/
public get isExport(): boolean {
return !!this.getStore()?.get('isExport');
}
}
23 changes: 22 additions & 1 deletion packages/server/src/services/Export/ExportService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Errors, ExportFormat } from './common';
import { IModelMeta, IModelMetaColumn } from '@/interfaces';
import { flatDataCollections, getDataAccessor } from './utils';
import { ExportPdf } from './ExportPdf';
import { ExportAls } from './ExportAls';

@Service()
export class ExportResourceService {
Expand All @@ -22,13 +23,33 @@ export class ExportResourceService {
@Inject()
private exportPdf: ExportPdf;

@Inject()
private exportAls: ExportAls;

/**
*
* @param {number} tenantId
* @param {string} resourceName
* @param {ExportFormat} format
* @returns
*/
public async export(
tenantId: number,
resourceName: string,
format: ExportFormat = ExportFormat.Csv
) {
return this.exportAls.run(() =>
this.exportAlsRun(tenantId, resourceName, format)
);
}

/**
* Exports the given resource data through csv, xlsx or pdf.
* @param {number} tenantId - Tenant id.
* @param {string} resourceName - Resource name.
* @param {ExportFormat} format - File format.
*/
public async export(
public async exportAlsRun(
tenantId: number,
resourceName: string,
format: ExportFormat = ExportFormat.Csv
Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/services/Export/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const EXPORT_SIZE_LIMIT = 9999999;
export const EXPORT_SIZE_LIMIT = 9999999;
export const EXPORT_DTE_FORMAT = 'YYYY-MM-DD';
7 changes: 4 additions & 3 deletions packages/server/src/services/Import/ImportALS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class ImportAls {
constructor() {
this.als = new AsyncLocalStorage();
}

/**
* Runs a callback function within the context of a new AsyncLocalStorage store.
* @param callback The function to be executed within the AsyncLocalStorage context.
Expand Down Expand Up @@ -82,23 +83,23 @@ export class ImportAls {
* Checks if the current context is an import operation.
* @returns {boolean} True if the context is an import operation, false otherwise.
*/
public isImport(): boolean {
public get isImport(): boolean {
return !!this.getStore()?.get('isImport');
}

/**
* Checks if the current context is an import commit operation.
* @returns {boolean} True if the context is an import commit operation, false otherwise.
*/
public isImportCommit(): boolean {
public get isImportCommit(): boolean {
return !!this.getStore()?.get('isImportCommit');
}

/**
* Checks if the current context is an import preview operation.
* @returns {boolean} True if the context is an import preview operation, false otherwise.
*/
public isImportPreview(): boolean {
public get isImportPreview(): boolean {
return !!this.getStore()?.get('isImportPreview');
}
}
2 changes: 1 addition & 1 deletion packages/server/src/subscribers/Inventory/Inventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default class InventorySubscriber {
inventoryTransactions,
trx,
}: IInventoryTransactionsCreatedPayload) => {
const inImportPreviewScope = this.importAls.isImportPreview();
const inImportPreviewScope = this.importAls.isImportPreview;

// Avoid running the cost items job if the async process is in import preview.
if (inImportPreviewScope) return;
Expand Down
Loading