Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 1x 1x 5x 5x 5x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 12x 12x 1x 12x 1x 12x 10x 12x 12x | import { isNil, last, round } from 'lodash-es';
import { FormatsEnum } from '@amalia/data-capture/fields/types';
import { dayjs } from '@amalia/ext/dayjs';
import { isCurrencyValue, type CurrencyValue } from '@amalia/kernel/monetary/types';
import {
CustomReportSourceIdentifier,
type CustomReport,
type CustomReportColumn,
type CustomReportConfigurationField,
type CustomReportDataSourceManifest,
type CustomReportManifestsMap,
type CustomReportRow,
type CustomReportValue,
} from '../types/customReport';
export const getCustomReportFieldDefinition = (
customReport: Pick<CustomReport, 'configuration' | 'source'>,
manifestsMap: CustomReportManifestsMap,
field: { identifier: string; joins?: string[] },
): CustomReportDataSourceManifest['fields'][0] | null => {
const source = (field.joins?.length ? last(field.joins) : customReport.source) as string;
const manifest = manifestsMap[source];
// Manifest may not be loaded yet.
if (!manifest) {
return null;
}
return manifest.fields.find((fd) => fd.identifier === field.identifier) ?? null;
};
export const makeUniqueCustomReportFieldIdentifier = (
source: CustomReportSourceIdentifier,
fieldConfiguration: Pick<CustomReportConfigurationField, 'identifier' | 'joins'>,
) => {
const tableAlias = fieldConfiguration.joins?.length ? last(fieldConfiguration.joins) : source;
return `${tableAlias}__${fieldConfiguration.identifier}`;
};
export const getCustomReportColumnsDefinitions = (
customReport: Pick<CustomReport, 'configuration' | 'source'>,
manifestsMap: CustomReportManifestsMap,
) =>
customReport.configuration.fields
.map((fieldConfiguration) => {
const fieldDefinition = getCustomReportFieldDefinition(customReport, manifestsMap, fieldConfiguration);
// Some fields may have disappeared from the manifest. Remove them to avoid crashes.
if (!fieldDefinition) {
return null;
}
return {
fieldDefinition,
field: fieldConfiguration,
identifier: makeUniqueCustomReportFieldIdentifier(customReport.source, fieldConfiguration),
};
})
.filter(Boolean);
export function buildCustomReportColumns(
customReport: Pick<CustomReport, 'configuration' | 'source'>,
manifestsMap: CustomReportManifestsMap,
): CustomReportColumn[] {
return getCustomReportColumnsDefinitions(customReport, manifestsMap).map(
({ fieldDefinition, field, identifier }) => ({
identifier,
label: field.alias ?? fieldDefinition.label,
format: fieldDefinition.format,
}),
);
}
export function transformReportDataToTable(
columns: CustomReportColumn[],
items: CustomReportRow[],
precision: number = 2,
addCurrencySymbol: boolean = true,
) {
return [
columns.map((column) => column.label),
...items.map((row) =>
columns.map((field) => {
// for each field, take the value from the row
const rowValue = row[field.identifier];
switch (field.format) {
case FormatsEnum.currency:
return isNil(rowValue) || !isCurrencyValue(rowValue) || isNil(rowValue.value)
? ''
: addCurrencySymbol
? round(rowValue.value, precision) + rowValue.symbol
: round(rowValue.value, precision);
case FormatsEnum.number:
case FormatsEnum.percent:
return isNil(rowValue) ? 0 : round(+rowValue, precision);
case FormatsEnum.date:
// If the value is a timestamp, format it as a date.
// Otherwise just return the value as is.
return !isNil(rowValue) &&
dayjs(`${rowValue as Exclude<CustomReportValue, CurrencyValue>}`, 'X', true).isValid()
? dayjs.utc(`${rowValue as Exclude<CustomReportValue, CurrencyValue>}`, 'X').format('YYYY-MM-DD')
: `${(rowValue as Exclude<CustomReportValue, CurrencyValue>) ?? ''}`;
default:
return `${(rowValue as Exclude<CustomReportValue, CurrencyValue>) ?? ''}`;
}
}),
),
];
}
// PSQL max identifier length is 63 characters.
// We need to truncate the identifier to 63 characters to avoid errors.
export const formatMaxLengthIdentifierPsql = (identifier: string): string => identifier.substring(0, 63);
export const stringifyCustomReportFieldPosition = ({ identifier, joins }: CustomReportConfigurationField): string =>
JSON.stringify({ identifier, joins });
export const parseCustomReportFieldPosition = (value: string): CustomReportConfigurationField => ({
joins: undefined,
...(JSON.parse(value) as CustomReportConfigurationField),
});
export const getCustomReportJoinForUser = (source: CustomReportSourceIdentifier) => {
switch (source) {
case CustomReportSourceIdentifier.RULE_METRIC:
return 'ruleMetricUser';
case CustomReportSourceIdentifier.STATEMENT:
return 'statementUser';
default:
throw new Error('This custom report source is not supported');
}
};
|