Files
trackgo-be/src/modules/reports/shared/helpers/report-cell.formatter.ts
T
shancheas 2955b974d2 Add reporting features with new report engine and bookmark management
- Introduced a comprehensive report engine for generating and managing reports, including sales and logistics reports.
- Added new API endpoints for retrieving report configurations, data, and metadata, ensuring secure access with privilege checks.
- Implemented a report bookmarks system to allow users to save and manage report filters and configurations.
- Created database migrations for the `report_bookmarks` table and updated the schema to support new report functionalities.
- Developed services and controllers for handling report queries and bookmarks, including CRUD operations for bookmarks.
- Enhanced API documentation to reflect the new reporting features and endpoints.
- Added unit and integration tests to validate the new functionalities and ensure data integrity across report operations.
2026-09-01 08:45:52 +07:00

108 lines
2.9 KiB
TypeScript

import { DateTime } from '../../../../common/value-objects/date-time/date-time';
import { Decimal } from '../../../../common/value-objects/decimal/decimal';
import { DATA_FORMAT } from '../constants/data-format';
import type { DataFormat } from '../constants/data-format';
import type { ReportColumnConfigEntity } from '../entities/report-config.entity';
export function formatReportCell(raw: unknown, format: DataFormat): unknown {
if (raw === null || raw === undefined) {
switch (format) {
case DATA_FORMAT.NUMBER:
case DATA_FORMAT.CURRENCY:
case DATA_FORMAT.MINUS_CURRENCY:
return Decimal.zero().toString();
default:
return raw;
}
}
switch (format) {
case DATA_FORMAT.TEXT:
return String(raw);
case DATA_FORMAT.TEXT_UPPERCASE:
return String(raw).toUpperCase();
case DATA_FORMAT.TEXT_LOWERCASE:
return String(raw).toLowerCase();
case DATA_FORMAT.NUMBER:
return formatDecimalOrZero(raw);
case DATA_FORMAT.CURRENCY:
return formatDecimalOrZero(raw);
case DATA_FORMAT.MINUS_CURRENCY:
return negateDecimalString(formatDecimalOrZero(raw));
case DATA_FORMAT.PERCENTAGE:
return `${raw}%`;
case DATA_FORMAT.BOOLEAN:
return raw === true || raw === 1 || raw === '1' ? 'Yes' : 'No';
case DATA_FORMAT.STATUS:
return String(raw);
case DATA_FORMAT.DATE_EPOCH:
return formatEpoch(raw);
case DATA_FORMAT.DATE_TIMESTAMP:
return formatTimestamp(raw);
default:
return raw;
}
}
export function formatReportRow(
row: Record<string, unknown>,
columnConfigs: ReportColumnConfigEntity[],
): Record<string, unknown> {
const formatted: Record<string, unknown> = { ...row };
for (const col of columnConfigs) {
if (col.column in formatted) {
formatted[col.column] = formatReportCell(
formatted[col.column],
col.format,
);
}
}
return formatted;
}
function formatDecimalOrZero(raw: unknown): string {
try {
if (raw === null || raw === undefined || raw === '') {
return Decimal.zero().toString();
}
return Decimal.create(String(raw)).toString();
} catch {
return Decimal.zero().toString();
}
}
function negateDecimalString(value: string): string {
try {
const decimal = Decimal.create(value);
if (decimal.isZero()) {
return decimal.toString();
}
return Decimal.create(`-${value.replace(/^-/, '')}`).toString();
} catch {
return Decimal.zero().toString();
}
}
function formatEpoch(raw: unknown): string {
const ms = Number(raw);
if (!Number.isFinite(ms)) {
return String(raw);
}
return DateTime.fromUnixMs(ms).format();
}
function formatTimestamp(raw: unknown): string {
if (typeof raw === 'string') {
try {
return DateTime.create(raw).format();
} catch {
return raw;
}
}
const ms = Number(raw);
if (Number.isFinite(ms)) {
return DateTime.fromUnixMs(ms).format();
}
return String(raw);
}