@softwear/latestcollectioncore 1.0.191 → 1.0.192
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -1
- package/dist/layoutFieldFormat.d.ts +16 -0
- package/dist/layoutFieldFormat.js +60 -0
- package/dist/pdf.d.ts +2 -1
- package/dist/reports.js +14 -30
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/layoutFieldFormat.ts +60 -0
- package/src/pdf.ts +3 -1
- package/src/reports.ts +10 -21
- package/test/layoutFieldFormat.spec.ts +69 -0
- package/test/reports.spec.ts +54 -0
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export { default as reports, genPDF } from './reports';
|
|
|
19
19
|
export { default as round2 } from './round2';
|
|
20
20
|
export { default as sizeToMap } from './sizeToMap';
|
|
21
21
|
export { default as transaction } from './transaction';
|
|
22
|
+
export type { LayoutFieldFormat } from './layoutFieldFormat';
|
|
23
|
+
export { isCurrencyFieldFormat, isZeroFieldValue, resolveLayoutFieldText, shouldSuppressZeroField } from './layoutFieldFormat';
|
|
22
24
|
export * from './pdf';
|
|
23
25
|
export type { GenPdfAlert, GenPdfOptions, PdfFontDefinition, PdfFontVariant, PdfImageAsset } from './reports';
|
|
24
26
|
export * from './types';
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.isAxiosError = exports.exponentialDelay = exports.axiosRetry = exports.createAxiosInstance = exports.lcAxios = exports.transaction = exports.sizeToMap = exports.round2 = exports.genPDF = exports.reports = exports.projectObject = exports.pivotTable = exports.isean13 = exports.imageBinder = exports.hasOnlyDigits = exports.hashBrand = exports.getPreferedPropertyMappings = exports.getBrandName = exports.findMetaBrandSetting = exports.findSkuByBarcode = exports.ensureImpliedProperties = exports.ensureArray = exports.edifact = exports.ean13 = exports.deepCopy = exports.buildPropertyMappingFn = exports.articleStatus = void 0;
|
|
20
|
+
exports.isAxiosError = exports.exponentialDelay = exports.axiosRetry = exports.createAxiosInstance = exports.lcAxios = exports.shouldSuppressZeroField = exports.resolveLayoutFieldText = exports.isZeroFieldValue = exports.isCurrencyFieldFormat = exports.transaction = exports.sizeToMap = exports.round2 = exports.genPDF = exports.reports = exports.projectObject = exports.pivotTable = exports.isean13 = exports.imageBinder = exports.hasOnlyDigits = exports.hashBrand = exports.getPreferedPropertyMappings = exports.getBrandName = exports.findMetaBrandSetting = exports.findSkuByBarcode = exports.ensureImpliedProperties = exports.ensureArray = exports.edifact = exports.ean13 = exports.deepCopy = exports.buildPropertyMappingFn = exports.articleStatus = void 0;
|
|
21
21
|
var articleStatus_1 = require("./articleStatus");
|
|
22
22
|
Object.defineProperty(exports, "articleStatus", { enumerable: true, get: function () { return __importDefault(articleStatus_1).default; } });
|
|
23
23
|
var buildPropertyMappingFn_1 = require("./buildPropertyMappingFn");
|
|
@@ -61,6 +61,11 @@ var sizeToMap_1 = require("./sizeToMap");
|
|
|
61
61
|
Object.defineProperty(exports, "sizeToMap", { enumerable: true, get: function () { return __importDefault(sizeToMap_1).default; } });
|
|
62
62
|
var transaction_1 = require("./transaction");
|
|
63
63
|
Object.defineProperty(exports, "transaction", { enumerable: true, get: function () { return __importDefault(transaction_1).default; } });
|
|
64
|
+
var layoutFieldFormat_1 = require("./layoutFieldFormat");
|
|
65
|
+
Object.defineProperty(exports, "isCurrencyFieldFormat", { enumerable: true, get: function () { return layoutFieldFormat_1.isCurrencyFieldFormat; } });
|
|
66
|
+
Object.defineProperty(exports, "isZeroFieldValue", { enumerable: true, get: function () { return layoutFieldFormat_1.isZeroFieldValue; } });
|
|
67
|
+
Object.defineProperty(exports, "resolveLayoutFieldText", { enumerable: true, get: function () { return layoutFieldFormat_1.resolveLayoutFieldText; } });
|
|
68
|
+
Object.defineProperty(exports, "shouldSuppressZeroField", { enumerable: true, get: function () { return layoutFieldFormat_1.shouldSuppressZeroField; } });
|
|
64
69
|
__exportStar(require("./pdf"), exports);
|
|
65
70
|
__exportStar(require("./types"), exports);
|
|
66
71
|
__exportStar(require("./consts"), exports);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type LayoutFieldFormat = 'text' | 'number' | 'date' | 'currency' | 'number-nonzero' | 'currency-nonzero';
|
|
2
|
+
export interface ResolveLayoutFieldTextOptions {
|
|
3
|
+
pageNumber?: number;
|
|
4
|
+
pageCount?: number;
|
|
5
|
+
formatDate: (raw: number | string) => string;
|
|
6
|
+
formatCurrency?: (raw: string) => string;
|
|
7
|
+
onFieldNotFound?: (source: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function isZeroFieldValue(value: unknown): boolean;
|
|
10
|
+
export declare function isCurrencyFieldFormat(format: string | undefined): boolean;
|
|
11
|
+
export declare function shouldSuppressZeroField(format: string | undefined): boolean;
|
|
12
|
+
export declare function resolveLayoutFieldText(object: {
|
|
13
|
+
format?: string;
|
|
14
|
+
source?: string;
|
|
15
|
+
type?: string;
|
|
16
|
+
}, printBuffer: any, getProperty: (propertyName: string, object: any) => any, options: ResolveLayoutFieldTextOptions): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveLayoutFieldText = exports.shouldSuppressZeroField = exports.isCurrencyFieldFormat = exports.isZeroFieldValue = void 0;
|
|
4
|
+
function isZeroFieldValue(value) {
|
|
5
|
+
if (value === 0 || value === '0')
|
|
6
|
+
return true;
|
|
7
|
+
if (typeof value === 'number')
|
|
8
|
+
return value === 0;
|
|
9
|
+
if (typeof value !== 'string')
|
|
10
|
+
return false;
|
|
11
|
+
const trimmed = value.trim();
|
|
12
|
+
if (trimmed === '0')
|
|
13
|
+
return true;
|
|
14
|
+
const normalized = trimmed.replace(',', '.');
|
|
15
|
+
const parsed = parseFloat(normalized);
|
|
16
|
+
return trimmed !== '' && !Number.isNaN(parsed) && parsed === 0;
|
|
17
|
+
}
|
|
18
|
+
exports.isZeroFieldValue = isZeroFieldValue;
|
|
19
|
+
function isCurrencyFieldFormat(format) {
|
|
20
|
+
return format === 'currency' || format === 'currency-nonzero';
|
|
21
|
+
}
|
|
22
|
+
exports.isCurrencyFieldFormat = isCurrencyFieldFormat;
|
|
23
|
+
function shouldSuppressZeroField(format) {
|
|
24
|
+
return format === 'currency-nonzero' || format === 'number-nonzero';
|
|
25
|
+
}
|
|
26
|
+
exports.shouldSuppressZeroField = shouldSuppressZeroField;
|
|
27
|
+
function resolveLayoutFieldText(object, printBuffer, getProperty, options) {
|
|
28
|
+
var _a, _b, _c, _d, _e;
|
|
29
|
+
if (object.type !== 'field')
|
|
30
|
+
return '';
|
|
31
|
+
let raw;
|
|
32
|
+
if (object.source === 'pageNumber')
|
|
33
|
+
raw = String((_a = options.pageNumber) !== null && _a !== void 0 ? _a : '');
|
|
34
|
+
else if (object.source === 'pageCount')
|
|
35
|
+
raw = String((_b = options.pageCount) !== null && _b !== void 0 ? _b : 0);
|
|
36
|
+
else if (object.source === 'page')
|
|
37
|
+
raw = `${(_c = options.pageNumber) !== null && _c !== void 0 ? _c : ''} / ${(_d = options.pageCount) !== null && _d !== void 0 ? _d : 0}`;
|
|
38
|
+
else if (object.source && printBuffer !== undefined && printBuffer !== null)
|
|
39
|
+
raw = getProperty(object.source, printBuffer);
|
|
40
|
+
else
|
|
41
|
+
raw = printBuffer;
|
|
42
|
+
if (shouldSuppressZeroField(object.format) && isZeroFieldValue(raw))
|
|
43
|
+
return '';
|
|
44
|
+
let text;
|
|
45
|
+
if (typeof raw === 'number')
|
|
46
|
+
text = String(raw);
|
|
47
|
+
else if (raw === undefined || raw === null) {
|
|
48
|
+
(_e = options.onFieldNotFound) === null || _e === void 0 ? void 0 : _e.call(options, object.source || '');
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
text = String(raw);
|
|
53
|
+
if (object.format === 'date')
|
|
54
|
+
text = options.formatDate(parseInt(text));
|
|
55
|
+
if (isCurrencyFieldFormat(object.format)) {
|
|
56
|
+
text = options.formatCurrency ? options.formatCurrency(text) : '€ ' + parseFloat(text).toFixed(2);
|
|
57
|
+
}
|
|
58
|
+
return text;
|
|
59
|
+
}
|
|
60
|
+
exports.resolveLayoutFieldText = resolveLayoutFieldText;
|
package/dist/pdf.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LayoutFieldFormat } from './layoutFieldFormat';
|
|
1
2
|
export interface PaperSize {
|
|
2
3
|
width: number;
|
|
3
4
|
height: number;
|
|
@@ -28,7 +29,7 @@ export interface TextLayoutObject extends BaseLayoutObject {
|
|
|
28
29
|
export interface FieldLayoutObject extends BaseLayoutObject {
|
|
29
30
|
type: 'field';
|
|
30
31
|
source?: string;
|
|
31
|
-
format?:
|
|
32
|
+
format?: LayoutFieldFormat;
|
|
32
33
|
textAlign?: TextAlign;
|
|
33
34
|
fontFamily: string;
|
|
34
35
|
fontSize: number;
|
package/dist/reports.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.genPDF = void 0;
|
|
|
16
16
|
const jspdf_1 = require("jspdf");
|
|
17
17
|
const date_fns_1 = require("date-fns");
|
|
18
18
|
const deepCopy_1 = __importDefault(require("./deepCopy"));
|
|
19
|
+
const layoutFieldFormat_1 = require("./layoutFieldFormat");
|
|
19
20
|
/** Measurement uses context `currentPageNumber` (1-based). Rendering uses jsPDF’s `getCurrentPageInfo().pageNumber`, which is already 1-based (first page is 1). */
|
|
20
21
|
function getCurrentPageNumber(doc, context) {
|
|
21
22
|
var _a;
|
|
@@ -268,7 +269,7 @@ function truncateTextToFitWidth(doc, text, maxWidth) {
|
|
|
268
269
|
return truncatedText + ELLIPSIS;
|
|
269
270
|
}
|
|
270
271
|
function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options, context) {
|
|
271
|
-
var _a, _b
|
|
272
|
+
var _a, _b;
|
|
272
273
|
let text = ''; // Will hold text to display for either 'text' or 'field'
|
|
273
274
|
// Get text from object for text objects
|
|
274
275
|
if (object.type == 'text') {
|
|
@@ -276,33 +277,16 @@ function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options
|
|
|
276
277
|
}
|
|
277
278
|
// Get text from printBuffer for field objects
|
|
278
279
|
if (object.type == 'field') {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
text = getProperty(object.source, printBuffer);
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
292
|
-
text = printBuffer;
|
|
293
|
-
}
|
|
294
|
-
if (typeof text == 'number')
|
|
295
|
-
text = '' + text;
|
|
296
|
-
if (object.format == 'date')
|
|
297
|
-
text = formatDate(parseInt(text));
|
|
298
|
-
if (text === undefined || typeof text != 'string') {
|
|
299
|
-
(_a = options.onAlert) === null || _a === void 0 ? void 0 : _a.call(options, { header: 'fieldnotfound', body: object.source, type: 'warning', timeout: 10000 });
|
|
300
|
-
text = '';
|
|
301
|
-
}
|
|
302
|
-
if (object.format == 'currency') {
|
|
303
|
-
const raw = text;
|
|
304
|
-
text = options.formatCurrency ? options.formatCurrency(raw) : '€ ' + parseFloat(raw).toFixed(2);
|
|
305
|
-
}
|
|
280
|
+
text = (0, layoutFieldFormat_1.resolveLayoutFieldText)(object, printBuffer, getProperty, {
|
|
281
|
+
pageNumber: doc.getNumberOfPages(),
|
|
282
|
+
pageCount: context.pageCount || 0,
|
|
283
|
+
formatDate,
|
|
284
|
+
formatCurrency: options.formatCurrency,
|
|
285
|
+
onFieldNotFound: (source) => {
|
|
286
|
+
var _a;
|
|
287
|
+
(_a = options.onAlert) === null || _a === void 0 ? void 0 : _a.call(options, { header: 'fieldnotfound', body: source, type: 'warning', timeout: 10000 });
|
|
288
|
+
},
|
|
289
|
+
});
|
|
306
290
|
}
|
|
307
291
|
// Manipulate case as specified in object
|
|
308
292
|
if ((object.type === 'text' || object.type === 'field') && object.case === 1)
|
|
@@ -364,7 +348,7 @@ function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options
|
|
|
364
348
|
const imgUrl = resolveImageUrl(object, printBuffer);
|
|
365
349
|
if (imgUrl) {
|
|
366
350
|
const urlLower = String(imgUrl).toLowerCase();
|
|
367
|
-
const imageAsset = (
|
|
351
|
+
const imageAsset = (_a = context.imageAssets) === null || _a === void 0 ? void 0 : _a.get(String(imgUrl));
|
|
368
352
|
const format = (imageAsset === null || imageAsset === void 0 ? void 0 : imageAsset.format) || (urlLower.endsWith('.png') ? 'PNG' : urlLower.endsWith('.jpg') || urlLower.endsWith('.jpeg') ? 'JPEG' : 'JPEG');
|
|
369
353
|
let drawX = x;
|
|
370
354
|
let drawY = y;
|
|
@@ -403,7 +387,7 @@ function drawSimpleObject(x, y, doc, object, printBuffer, width, height, options
|
|
|
403
387
|
return;
|
|
404
388
|
const fontStyleStr = FONT_STYLES[object.fontStyle & 3] || 'normal';
|
|
405
389
|
// Use object font if it's a custom font; otherwise layout default overrides standard fonts (Helvetica etc.)
|
|
406
|
-
const fontFamily = object.fontFamily && ((
|
|
390
|
+
const fontFamily = object.fontFamily && ((_b = options.isCustomPdfFont) === null || _b === void 0 ? void 0 : _b.call(options, object.fontFamily)) ? object.fontFamily : context.defaultFontFamily || object.fontFamily || 'Helvetica';
|
|
407
391
|
doc.setFont(fontFamily, fontStyleStr);
|
|
408
392
|
doc.setFontSize(object.fontSize / 4);
|
|
409
393
|
doc.text(truncateTextToFitWidth(doc, text, width), x, y, { align: textAlign, baseline: 'hanging' });
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -19,6 +19,8 @@ export { default as reports, genPDF } from './reports'
|
|
|
19
19
|
export { default as round2 } from './round2'
|
|
20
20
|
export { default as sizeToMap } from './sizeToMap'
|
|
21
21
|
export { default as transaction } from './transaction'
|
|
22
|
+
export type { LayoutFieldFormat } from './layoutFieldFormat'
|
|
23
|
+
export { isCurrencyFieldFormat, isZeroFieldValue, resolveLayoutFieldText, shouldSuppressZeroField } from './layoutFieldFormat'
|
|
22
24
|
export * from './pdf'
|
|
23
25
|
export type { GenPdfAlert, GenPdfOptions, PdfFontDefinition, PdfFontVariant, PdfImageAsset } from './reports'
|
|
24
26
|
export * from './types'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type LayoutFieldFormat = 'text' | 'number' | 'date' | 'currency' | 'number-nonzero' | 'currency-nonzero'
|
|
2
|
+
|
|
3
|
+
export interface ResolveLayoutFieldTextOptions {
|
|
4
|
+
pageNumber?: number
|
|
5
|
+
pageCount?: number
|
|
6
|
+
formatDate: (raw: number | string) => string
|
|
7
|
+
formatCurrency?: (raw: string) => string
|
|
8
|
+
onFieldNotFound?: (source: string) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isZeroFieldValue(value: unknown): boolean {
|
|
12
|
+
if (value === 0 || value === '0') return true
|
|
13
|
+
if (typeof value === 'number') return value === 0
|
|
14
|
+
if (typeof value !== 'string') return false
|
|
15
|
+
const trimmed = value.trim()
|
|
16
|
+
if (trimmed === '0') return true
|
|
17
|
+
const normalized = trimmed.replace(',', '.')
|
|
18
|
+
const parsed = parseFloat(normalized)
|
|
19
|
+
return trimmed !== '' && !Number.isNaN(parsed) && parsed === 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isCurrencyFieldFormat(format: string | undefined): boolean {
|
|
23
|
+
return format === 'currency' || format === 'currency-nonzero'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function shouldSuppressZeroField(format: string | undefined): boolean {
|
|
27
|
+
return format === 'currency-nonzero' || format === 'number-nonzero'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function resolveLayoutFieldText(
|
|
31
|
+
object: { format?: string; source?: string; type?: string },
|
|
32
|
+
printBuffer: any,
|
|
33
|
+
getProperty: (propertyName: string, object: any) => any,
|
|
34
|
+
options: ResolveLayoutFieldTextOptions,
|
|
35
|
+
): string {
|
|
36
|
+
if (object.type !== 'field') return ''
|
|
37
|
+
|
|
38
|
+
let raw: unknown
|
|
39
|
+
if (object.source === 'pageNumber') raw = String(options.pageNumber ?? '')
|
|
40
|
+
else if (object.source === 'pageCount') raw = String(options.pageCount ?? 0)
|
|
41
|
+
else if (object.source === 'page') raw = `${options.pageNumber ?? ''} / ${options.pageCount ?? 0}`
|
|
42
|
+
else if (object.source && printBuffer !== undefined && printBuffer !== null) raw = getProperty(object.source, printBuffer)
|
|
43
|
+
else raw = printBuffer
|
|
44
|
+
|
|
45
|
+
if (shouldSuppressZeroField(object.format) && isZeroFieldValue(raw)) return ''
|
|
46
|
+
|
|
47
|
+
let text: string
|
|
48
|
+
if (typeof raw === 'number') text = String(raw)
|
|
49
|
+
else if (raw === undefined || raw === null) {
|
|
50
|
+
options.onFieldNotFound?.(object.source || '')
|
|
51
|
+
return ''
|
|
52
|
+
} else text = String(raw)
|
|
53
|
+
|
|
54
|
+
if (object.format === 'date') text = options.formatDate(parseInt(text))
|
|
55
|
+
if (isCurrencyFieldFormat(object.format)) {
|
|
56
|
+
text = options.formatCurrency ? options.formatCurrency(text) : '€ ' + parseFloat(text).toFixed(2)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return text
|
|
60
|
+
}
|
package/src/pdf.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { LayoutFieldFormat } from './layoutFieldFormat'
|
|
2
|
+
|
|
1
3
|
export interface PaperSize {
|
|
2
4
|
width: number
|
|
3
5
|
height: number
|
|
@@ -32,7 +34,7 @@ export interface TextLayoutObject extends BaseLayoutObject {
|
|
|
32
34
|
export interface FieldLayoutObject extends BaseLayoutObject {
|
|
33
35
|
type: 'field'
|
|
34
36
|
source?: string
|
|
35
|
-
format?:
|
|
37
|
+
format?: LayoutFieldFormat
|
|
36
38
|
textAlign?: TextAlign
|
|
37
39
|
fontFamily: string
|
|
38
40
|
fontSize: number
|
package/src/reports.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsPDF } from 'jspdf'
|
|
2
2
|
import { format } from 'date-fns'
|
|
3
3
|
import deepCopy from './deepCopy'
|
|
4
|
+
import { resolveLayoutFieldText } from './layoutFieldFormat'
|
|
4
5
|
import { PaperSize, Layout, LayoutObject, ContainerLayoutObject } from './pdf'
|
|
5
6
|
|
|
6
7
|
type RenderMode = 'measurement' | 'rendering'
|
|
@@ -342,27 +343,15 @@ function drawSimpleObject(x: number, y: number, doc: jsPDF, object: LayoutObject
|
|
|
342
343
|
}
|
|
343
344
|
// Get text from printBuffer for field objects
|
|
344
345
|
if (object.type == 'field') {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
text = printBuffer
|
|
355
|
-
}
|
|
356
|
-
if (typeof text == 'number') text = '' + text
|
|
357
|
-
if (object.format == 'date') text = formatDate(parseInt(text))
|
|
358
|
-
if (text === undefined || typeof text != 'string') {
|
|
359
|
-
options.onAlert?.({ header: 'fieldnotfound', body: object.source, type: 'warning', timeout: 10000 })
|
|
360
|
-
text = ''
|
|
361
|
-
}
|
|
362
|
-
if (object.format == 'currency') {
|
|
363
|
-
const raw = text
|
|
364
|
-
text = options.formatCurrency ? options.formatCurrency(raw) : '€ ' + parseFloat(raw).toFixed(2)
|
|
365
|
-
}
|
|
346
|
+
text = resolveLayoutFieldText(object, printBuffer, getProperty, {
|
|
347
|
+
pageNumber: doc.getNumberOfPages(),
|
|
348
|
+
pageCount: context.pageCount || 0,
|
|
349
|
+
formatDate,
|
|
350
|
+
formatCurrency: options.formatCurrency,
|
|
351
|
+
onFieldNotFound: (source) => {
|
|
352
|
+
options.onAlert?.({ header: 'fieldnotfound', body: source, type: 'warning', timeout: 10000 })
|
|
353
|
+
},
|
|
354
|
+
})
|
|
366
355
|
}
|
|
367
356
|
// Manipulate case as specified in object
|
|
368
357
|
if ((object.type === 'text' || object.type === 'field') && object.case === 1) text = text.toUpperCase()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { isZeroFieldValue, resolveLayoutFieldText } from '../src/layoutFieldFormat'
|
|
3
|
+
|
|
4
|
+
const getProperty = (propertyName: string, object: any) => object[propertyName]
|
|
5
|
+
|
|
6
|
+
describe('isZeroFieldValue', () => {
|
|
7
|
+
it('detects numeric and string zero values', () => {
|
|
8
|
+
expect(isZeroFieldValue(0)).toBe(true)
|
|
9
|
+
expect(isZeroFieldValue('0')).toBe(true)
|
|
10
|
+
expect(isZeroFieldValue('0.00')).toBe(true)
|
|
11
|
+
expect(isZeroFieldValue('0,00')).toBe(true)
|
|
12
|
+
expect(isZeroFieldValue(' 0.0 ')).toBe(true)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('does not treat empty or non-zero values as zero', () => {
|
|
16
|
+
expect(isZeroFieldValue('')).toBe(false)
|
|
17
|
+
expect(isZeroFieldValue(null)).toBe(false)
|
|
18
|
+
expect(isZeroFieldValue(undefined)).toBe(false)
|
|
19
|
+
expect(isZeroFieldValue('10')).toBe(false)
|
|
20
|
+
expect(isZeroFieldValue(0.01)).toBe(false)
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
describe('resolveLayoutFieldText', () => {
|
|
25
|
+
const baseOptions = {
|
|
26
|
+
formatDate: (raw: number | string) => `DATE:${raw}`,
|
|
27
|
+
formatCurrency: (raw: string) => `CUR:${raw}`,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
it('suppresses currency-nonzero fields with zero values', () => {
|
|
31
|
+
const text = resolveLayoutFieldText(
|
|
32
|
+
{ type: 'field', source: 'amount', format: 'currency-nonzero' },
|
|
33
|
+
{ amount: '0.00' },
|
|
34
|
+
getProperty,
|
|
35
|
+
baseOptions,
|
|
36
|
+
)
|
|
37
|
+
expect(text).toBe('')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('formats non-zero currency-nonzero fields as currency', () => {
|
|
41
|
+
const text = resolveLayoutFieldText(
|
|
42
|
+
{ type: 'field', source: 'amount', format: 'currency-nonzero' },
|
|
43
|
+
{ amount: '12.5' },
|
|
44
|
+
getProperty,
|
|
45
|
+
baseOptions,
|
|
46
|
+
)
|
|
47
|
+
expect(text).toBe('CUR:12.5')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('suppresses number-nonzero fields with zero values', () => {
|
|
51
|
+
const text = resolveLayoutFieldText(
|
|
52
|
+
{ type: 'field', source: 'qty', format: 'number-nonzero' },
|
|
53
|
+
{ qty: 0 },
|
|
54
|
+
getProperty,
|
|
55
|
+
baseOptions,
|
|
56
|
+
)
|
|
57
|
+
expect(text).toBe('')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('keeps regular number fields at zero', () => {
|
|
61
|
+
const text = resolveLayoutFieldText(
|
|
62
|
+
{ type: 'field', source: 'qty', format: 'number' },
|
|
63
|
+
{ qty: 0 },
|
|
64
|
+
getProperty,
|
|
65
|
+
baseOptions,
|
|
66
|
+
)
|
|
67
|
+
expect(text).toBe('0')
|
|
68
|
+
})
|
|
69
|
+
})
|
package/test/reports.spec.ts
CHANGED
|
@@ -389,4 +389,58 @@ describe('genPDF', () => {
|
|
|
389
389
|
// jsPDF encodes U+20AC as WinAnsi 0x80 in the text operator; still one glyph before digits.
|
|
390
390
|
expect(pdfText).toMatch(/\(\s*.\s*10\.00\) Tj/)
|
|
391
391
|
})
|
|
392
|
+
|
|
393
|
+
it('suppresses currency-nonzero fields when the value is zero', async () => {
|
|
394
|
+
const layout: Layout = {
|
|
395
|
+
name: 'currency-nonzero',
|
|
396
|
+
paperSize: { width: 210, height: 297, footerHeight: 20 },
|
|
397
|
+
objects: [
|
|
398
|
+
{
|
|
399
|
+
type: 'field' as const,
|
|
400
|
+
name: 'discount',
|
|
401
|
+
x: 20,
|
|
402
|
+
y: 20,
|
|
403
|
+
width: 500,
|
|
404
|
+
height: 50,
|
|
405
|
+
active: true,
|
|
406
|
+
source: 'discount',
|
|
407
|
+
format: 'currency-nonzero' as const,
|
|
408
|
+
textAlign: 1 as const,
|
|
409
|
+
fontFamily: 'Helvetica',
|
|
410
|
+
fontSize: 32,
|
|
411
|
+
fontStyle: 0,
|
|
412
|
+
},
|
|
413
|
+
],
|
|
414
|
+
}
|
|
415
|
+
const doc = await genPDF(layout, { discount: '0.00' })
|
|
416
|
+
const pdfText = Buffer.from(doc.output('arraybuffer')).toString('latin1')
|
|
417
|
+
expect(pdfText).not.toMatch(/0\.00/)
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
it('renders currency-nonzero fields when the value is non-zero', async () => {
|
|
421
|
+
const layout: Layout = {
|
|
422
|
+
name: 'currency-nonzero-value',
|
|
423
|
+
paperSize: { width: 210, height: 297, footerHeight: 20 },
|
|
424
|
+
objects: [
|
|
425
|
+
{
|
|
426
|
+
type: 'field' as const,
|
|
427
|
+
name: 'discount',
|
|
428
|
+
x: 20,
|
|
429
|
+
y: 20,
|
|
430
|
+
width: 500,
|
|
431
|
+
height: 50,
|
|
432
|
+
active: true,
|
|
433
|
+
source: 'discount',
|
|
434
|
+
format: 'currency-nonzero' as const,
|
|
435
|
+
textAlign: 1 as const,
|
|
436
|
+
fontFamily: 'Helvetica',
|
|
437
|
+
fontSize: 32,
|
|
438
|
+
fontStyle: 0,
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
}
|
|
442
|
+
const doc = await genPDF(layout, { discount: '5' })
|
|
443
|
+
const pdfText = Buffer.from(doc.output('arraybuffer')).toString('latin1')
|
|
444
|
+
expect(pdfText).toMatch(/\(\s*.\s*5\.00\) Tj/)
|
|
445
|
+
})
|
|
392
446
|
})
|