@harbortouch/skytab-analytics-report-utils 0.26.0 → 0.28.0

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.
@@ -684,7 +684,12 @@ var employeeTipConfig = {
684
684
  // src/reports/dailySales/dailySales.ts
685
685
  var FIELDS10 = {
686
686
  groupById: { type: "string" },
687
- groupByName: { type: "string", size: FIRST_COLUMN_WIDTH, footerCalculation: { type: "label", label: "table.total" } },
687
+ groupByName: {
688
+ type: "string",
689
+ size: FIRST_COLUMN_WIDTH,
690
+ columnKey: "revenueClass",
691
+ footerCalculation: { type: "label", label: "table.total" }
692
+ },
688
693
  itemsQuantity: { type: "number", columnKey: "quantity" },
689
694
  salesAmountGross: { type: "money", columnKey: "grossSales" },
690
695
  discountsAmount: { type: "money", columnKey: "discountAmount" },
@@ -765,10 +770,10 @@ var FIELDS13 = {
765
770
  columnKey: "paymentType",
766
771
  footerCalculation: { type: "label", label: "table.total" }
767
772
  },
768
- paymentsCount: { type: "number", columnKey: "paymentsCount", footerCalculation: { type: "sum" } },
769
- paymentsAmount: { type: "money", columnKey: "paymentsAmount", footerCalculation: { type: "sum" } },
770
- tipsAmount: { type: "money", columnKey: "tips", footerCalculation: { type: "sum" } },
771
- totalSales: { type: "money", columnKey: "paymentsTotal", footerCalculation: { type: "sum" } }
773
+ paymentsCount: { type: "number-empty", columnKey: "paymentsCount", footerCalculation: { type: "sum" } },
774
+ paymentsAmount: { type: "money-empty", columnKey: "paymentsAmount", footerCalculation: { type: "sum" } },
775
+ tipsAmount: { type: "money-empty", columnKey: "tips", footerCalculation: { type: "sum" } },
776
+ totalSales: { type: "money-empty", columnKey: "paymentsTotal", footerCalculation: { type: "sum" } }
772
777
  };
773
778
  var DAILY_SALES_PAYMENTS_AVAILABLE_COLUMNS = [
774
779
  "paymentTypeName",
@@ -840,11 +845,12 @@ var dailySalesTaxesConfig = {
840
845
  sectionName: "common.report-section.taxes"
841
846
  };
842
847
 
843
- // src/reports/dailySales/dailySalesTrends.ts
848
+ // src/reports/dailySales/dailySalesTrendsDayPart.ts
844
849
  var FIELDS16 = {
845
850
  groupById: { type: "string" },
846
851
  groupByName: {
847
852
  type: "string",
853
+ columnKey: "daypart",
848
854
  size: FIRST_COLUMN_WIDTH,
849
855
  footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
850
856
  },
@@ -878,7 +884,7 @@ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS = [
878
884
  "guestAvg",
879
885
  "salesAmountNet"
880
886
  ];
881
- var dailySalesTrendsConfig = {
887
+ var dailySalesTrendsDayPartConfig = {
882
888
  fields: FIELDS16,
883
889
  availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
884
890
  defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
@@ -887,10 +893,50 @@ var dailySalesTrendsConfig = {
887
893
  sectionName: "common.report-section.sales-by-day-part",
888
894
  extraFooterFields: ["salesAmountNet"]
889
895
  };
896
+
897
+ // src/reports/dailySales/dailySalesTrendsOrderType.ts
898
+ var FIELDS17 = {
899
+ groupById: { type: "string" },
900
+ groupByName: {
901
+ columnKey: "orderType",
902
+ type: "string",
903
+ size: FIRST_COLUMN_WIDTH,
904
+ footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
905
+ },
906
+ salesAmountNet: { type: "money", columnKey: "netSales" },
907
+ ticketsCount: { type: "number", columnKey: "tickets" },
908
+ guestsCount: { type: "number", columnKey: "guests" },
909
+ ticketAvg: {
910
+ type: "money",
911
+ columnKey: "ticketAverage",
912
+ footerCalculation: {
913
+ type: "average",
914
+ numeratorField: "salesAmountNet",
915
+ denominatorField: "ticketsCount"
916
+ }
917
+ },
918
+ guestAvg: {
919
+ type: "money",
920
+ columnKey: "guestAverage",
921
+ footerCalculation: {
922
+ type: "average",
923
+ numeratorField: "salesAmountNet",
924
+ denominatorField: "guestsCount"
925
+ }
926
+ }
927
+ };
928
+ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2 = [
929
+ "groupByName",
930
+ "ticketsCount",
931
+ "guestsCount",
932
+ "ticketAvg",
933
+ "guestAvg",
934
+ "salesAmountNet"
935
+ ];
890
936
  var dailySalesTrendsOrderTypeConfig = {
891
- fields: FIELDS16,
892
- availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
893
- defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
937
+ fields: FIELDS17,
938
+ availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
939
+ defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
894
940
  hasFooter: true,
895
941
  dataAccessKey: "trendsByOrderType",
896
942
  sectionName: "common.report-section.sales-by-order-type",
@@ -918,7 +964,7 @@ var DAILY_SALES_SECTION_CONFIGS = [
918
964
  dailySalesTaxesConfig,
919
965
  dailySalesRefundsVoidsConfig,
920
966
  dailySalesDiscountsConfig,
921
- dailySalesTrendsConfig,
967
+ dailySalesTrendsDayPartConfig,
922
968
  dailySalesTrendsOrderTypeConfig
923
969
  ];
924
970
  var REPORT_CONFIG_MAP = {
@@ -3171,11 +3217,11 @@ var enUS3 = {
3171
3217
  "common.report-col.type": "Type",
3172
3218
  "common.report-col.type.short": "Type",
3173
3219
  "common.report-col.type.info": " ",
3174
- "common.report-section.revenue-class": "Revenue Class",
3220
+ "common.report-section.revenue-class": "Sales by Revenue Class",
3175
3221
  "common.report-section.payments": "Payments",
3176
3222
  "common.report-section.cash": "Expected Closeout Cash",
3177
3223
  "common.report-section.taxes": "Taxes",
3178
- "common.report-section.refunds-voids": "Refunds & Voids",
3224
+ "common.report-section.refunds-voids": "Refunds/Voids",
3179
3225
  "common.report-section.discounts": "Discounts",
3180
3226
  "common.report-section.sales-by-day-part": "Sales by Day Part",
3181
3227
  "common.report-section.sales-by-order-type": "Sales by Order Type",
@@ -3365,6 +3411,8 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
3365
3411
  return formatString(value, localeOptions);
3366
3412
  case "money":
3367
3413
  return formatMoney(getNumberToFormat(value), { currency, locale });
3414
+ case "money-empty":
3415
+ return value != null ? formatMoney(getNumberToFormat(value), { currency, locale }) : "";
3368
3416
  case "percent":
3369
3417
  return formatPercent(getNumberToFormat(value) * 100);
3370
3418
  case "fixedNumber":
@@ -3377,6 +3425,8 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
3377
3425
  const d = getDateToFormat(value);
3378
3426
  return d ? formatTime(d, { locale, format: "00:00:00" }) : "";
3379
3427
  }
3428
+ case "number-empty":
3429
+ return value != null ? String(getNumberToFormat(value)) : "";
3380
3430
  case "number":
3381
3431
  default:
3382
3432
  return String(getNumberToFormat(value));
@@ -3399,7 +3449,7 @@ export {
3399
3449
  dailySalesPaymentsConfig,
3400
3450
  dailySalesRefundsVoidsConfig,
3401
3451
  dailySalesTaxesConfig,
3402
- dailySalesTrendsConfig,
3452
+ dailySalesTrendsDayPartConfig,
3403
3453
  dailySalesTrendsOrderTypeConfig,
3404
3454
  Report,
3405
3455
  getReportConfig,
@@ -52,8 +52,8 @@ var ExcelExporter = class {
52
52
  async generate(content) {
53
53
  const workbook = new import_exceljs.default.Workbook();
54
54
  const usedNames = /* @__PURE__ */ new Set();
55
- for (const section of content.sections) {
56
- let sheetName = section.sheetName.slice(0, 31);
55
+ for (const [sectionIndex, section] of content.sections.entries()) {
56
+ let sheetName = (section.title || `Sheet${sectionIndex + 1}`).slice(0, 31);
57
57
  if (usedNames.has(sheetName.toLowerCase())) {
58
58
  let suffix = 2;
59
59
  let candidate = `${sheetName.slice(0, 28)}_${suffix}`;
@@ -1,15 +1,10 @@
1
- import { E as ExportTable, a as ExportFilter } from '../../types-BzLsgnfc.cjs';
2
- export { b as XlsxTableColumn } from '../../types-BzLsgnfc.cjs';
1
+ import { E as ExportSection } from '../../types-BPT5hjCR.cjs';
2
+ export { a as XlsxFilter, b as XlsxTable, c as XlsxTableColumn } from '../../types-BPT5hjCR.cjs';
3
3
 
4
- interface XlsxDocumentSection {
5
- sheetName: string;
6
- table?: ExportTable;
7
- filters?: ExportFilter[];
8
- }
9
4
  declare class ExcelExporter {
10
5
  generate(content: {
11
- sections: XlsxDocumentSection[];
6
+ sections: ExportSection[];
12
7
  }): Promise<Buffer>;
13
8
  }
14
9
 
15
- export { ExcelExporter, type XlsxDocumentSection, ExportFilter as XlsxFilter, ExportTable as XlsxTable };
10
+ export { ExcelExporter, ExportSection as XlsxSection };
@@ -1,15 +1,10 @@
1
- import { E as ExportTable, a as ExportFilter } from '../../types-BzLsgnfc.js';
2
- export { b as XlsxTableColumn } from '../../types-BzLsgnfc.js';
1
+ import { E as ExportSection } from '../../types-BPT5hjCR.js';
2
+ export { a as XlsxFilter, b as XlsxTable, c as XlsxTableColumn } from '../../types-BPT5hjCR.js';
3
3
 
4
- interface XlsxDocumentSection {
5
- sheetName: string;
6
- table?: ExportTable;
7
- filters?: ExportFilter[];
8
- }
9
4
  declare class ExcelExporter {
10
5
  generate(content: {
11
- sections: XlsxDocumentSection[];
6
+ sections: ExportSection[];
12
7
  }): Promise<Buffer>;
13
8
  }
14
9
 
15
- export { ExcelExporter, type XlsxDocumentSection, ExportFilter as XlsxFilter, ExportTable as XlsxTable };
10
+ export { ExcelExporter, ExportSection as XlsxSection };
@@ -18,8 +18,8 @@ var ExcelExporter = class {
18
18
  async generate(content) {
19
19
  const workbook = new ExcelJS.Workbook();
20
20
  const usedNames = /* @__PURE__ */ new Set();
21
- for (const section of content.sections) {
22
- let sheetName = section.sheetName.slice(0, 31);
21
+ for (const [sectionIndex, section] of content.sections.entries()) {
22
+ let sheetName = (section.title || `Sheet${sectionIndex + 1}`).slice(0, 31);
23
23
  if (usedNames.has(sheetName.toLowerCase())) {
24
24
  let suffix = 2;
25
25
  let candidate = `${sheetName.slice(0, 28)}_${suffix}`;
@@ -461,11 +461,11 @@ var enUS = {
461
461
  "common.report-col.type": "Type",
462
462
  "common.report-col.type.short": "Type",
463
463
  "common.report-col.type.info": " ",
464
- "common.report-section.revenue-class": "Revenue Class",
464
+ "common.report-section.revenue-class": "Sales by Revenue Class",
465
465
  "common.report-section.payments": "Payments",
466
466
  "common.report-section.cash": "Expected Closeout Cash",
467
467
  "common.report-section.taxes": "Taxes",
468
- "common.report-section.refunds-voids": "Refunds & Voids",
468
+ "common.report-section.refunds-voids": "Refunds/Voids",
469
469
  "common.report-section.discounts": "Discounts",
470
470
  "common.report-section.sales-by-day-part": "Sales by Day Part",
471
471
  "common.report-section.sales-by-order-type": "Sales by Order Type",
@@ -1614,6 +1614,8 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
1614
1614
  return formatString(value, localeOptions);
1615
1615
  case "money":
1616
1616
  return formatMoney(getNumberToFormat(value), { currency, locale });
1617
+ case "money-empty":
1618
+ return value != null ? formatMoney(getNumberToFormat(value), { currency, locale }) : "";
1617
1619
  case "percent":
1618
1620
  return formatPercent(getNumberToFormat(value) * 100);
1619
1621
  case "fixedNumber":
@@ -1626,6 +1628,8 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
1626
1628
  const d = getDateToFormat(value);
1627
1629
  return d ? formatTime(d, { locale, format: "00:00:00" }) : "";
1628
1630
  }
1631
+ case "number-empty":
1632
+ return value != null ? String(getNumberToFormat(value)) : "";
1629
1633
  case "number":
1630
1634
  default:
1631
1635
  return String(getNumberToFormat(value));
@@ -2318,7 +2322,12 @@ var employeeTipConfig = {
2318
2322
  // src/reports/dailySales/dailySales.ts
2319
2323
  var FIELDS10 = {
2320
2324
  groupById: { type: "string" },
2321
- groupByName: { type: "string", size: FIRST_COLUMN_WIDTH, footerCalculation: { type: "label", label: "table.total" } },
2325
+ groupByName: {
2326
+ type: "string",
2327
+ size: FIRST_COLUMN_WIDTH,
2328
+ columnKey: "revenueClass",
2329
+ footerCalculation: { type: "label", label: "table.total" }
2330
+ },
2322
2331
  itemsQuantity: { type: "number", columnKey: "quantity" },
2323
2332
  salesAmountGross: { type: "money", columnKey: "grossSales" },
2324
2333
  discountsAmount: { type: "money", columnKey: "discountAmount" },
@@ -2399,10 +2408,10 @@ var FIELDS13 = {
2399
2408
  columnKey: "paymentType",
2400
2409
  footerCalculation: { type: "label", label: "table.total" }
2401
2410
  },
2402
- paymentsCount: { type: "number", columnKey: "paymentsCount", footerCalculation: { type: "sum" } },
2403
- paymentsAmount: { type: "money", columnKey: "paymentsAmount", footerCalculation: { type: "sum" } },
2404
- tipsAmount: { type: "money", columnKey: "tips", footerCalculation: { type: "sum" } },
2405
- totalSales: { type: "money", columnKey: "paymentsTotal", footerCalculation: { type: "sum" } }
2411
+ paymentsCount: { type: "number-empty", columnKey: "paymentsCount", footerCalculation: { type: "sum" } },
2412
+ paymentsAmount: { type: "money-empty", columnKey: "paymentsAmount", footerCalculation: { type: "sum" } },
2413
+ tipsAmount: { type: "money-empty", columnKey: "tips", footerCalculation: { type: "sum" } },
2414
+ totalSales: { type: "money-empty", columnKey: "paymentsTotal", footerCalculation: { type: "sum" } }
2406
2415
  };
2407
2416
  var DAILY_SALES_PAYMENTS_AVAILABLE_COLUMNS = [
2408
2417
  "paymentTypeName",
@@ -2474,11 +2483,12 @@ var dailySalesTaxesConfig = {
2474
2483
  sectionName: "common.report-section.taxes"
2475
2484
  };
2476
2485
 
2477
- // src/reports/dailySales/dailySalesTrends.ts
2486
+ // src/reports/dailySales/dailySalesTrendsDayPart.ts
2478
2487
  var FIELDS16 = {
2479
2488
  groupById: { type: "string" },
2480
2489
  groupByName: {
2481
2490
  type: "string",
2491
+ columnKey: "daypart",
2482
2492
  size: FIRST_COLUMN_WIDTH,
2483
2493
  footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
2484
2494
  },
@@ -2512,7 +2522,7 @@ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS = [
2512
2522
  "guestAvg",
2513
2523
  "salesAmountNet"
2514
2524
  ];
2515
- var dailySalesTrendsConfig = {
2525
+ var dailySalesTrendsDayPartConfig = {
2516
2526
  fields: FIELDS16,
2517
2527
  availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
2518
2528
  defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
@@ -2521,10 +2531,50 @@ var dailySalesTrendsConfig = {
2521
2531
  sectionName: "common.report-section.sales-by-day-part",
2522
2532
  extraFooterFields: ["salesAmountNet"]
2523
2533
  };
2534
+
2535
+ // src/reports/dailySales/dailySalesTrendsOrderType.ts
2536
+ var FIELDS17 = {
2537
+ groupById: { type: "string" },
2538
+ groupByName: {
2539
+ columnKey: "orderType",
2540
+ type: "string",
2541
+ size: FIRST_COLUMN_WIDTH,
2542
+ footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
2543
+ },
2544
+ salesAmountNet: { type: "money", columnKey: "netSales" },
2545
+ ticketsCount: { type: "number", columnKey: "tickets" },
2546
+ guestsCount: { type: "number", columnKey: "guests" },
2547
+ ticketAvg: {
2548
+ type: "money",
2549
+ columnKey: "ticketAverage",
2550
+ footerCalculation: {
2551
+ type: "average",
2552
+ numeratorField: "salesAmountNet",
2553
+ denominatorField: "ticketsCount"
2554
+ }
2555
+ },
2556
+ guestAvg: {
2557
+ type: "money",
2558
+ columnKey: "guestAverage",
2559
+ footerCalculation: {
2560
+ type: "average",
2561
+ numeratorField: "salesAmountNet",
2562
+ denominatorField: "guestsCount"
2563
+ }
2564
+ }
2565
+ };
2566
+ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2 = [
2567
+ "groupByName",
2568
+ "ticketsCount",
2569
+ "guestsCount",
2570
+ "ticketAvg",
2571
+ "guestAvg",
2572
+ "salesAmountNet"
2573
+ ];
2524
2574
  var dailySalesTrendsOrderTypeConfig = {
2525
- fields: FIELDS16,
2526
- availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
2527
- defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
2575
+ fields: FIELDS17,
2576
+ availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
2577
+ defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
2528
2578
  hasFooter: true,
2529
2579
  dataAccessKey: "trendsByOrderType",
2530
2580
  sectionName: "common.report-section.sales-by-order-type",
@@ -2539,7 +2589,7 @@ var DAILY_SALES_SECTION_CONFIGS = [
2539
2589
  dailySalesTaxesConfig,
2540
2590
  dailySalesRefundsVoidsConfig,
2541
2591
  dailySalesDiscountsConfig,
2542
- dailySalesTrendsConfig,
2592
+ dailySalesTrendsDayPartConfig,
2543
2593
  dailySalesTrendsOrderTypeConfig
2544
2594
  ];
2545
2595
  var REPORT_CONFIG_MAP = {
@@ -3540,7 +3590,7 @@ var ExportBuilder = class {
3540
3590
  const sectionParameters = { ...parameters, cols: void 0 };
3541
3591
  sections = rawConfig.map((config) => {
3542
3592
  return {
3543
- sheetName: this.getConfigSectionName(config),
3593
+ title: this.getConfigSectionName(config),
3544
3594
  ...this.renderTableContent(config, reportData, sectionParameters)
3545
3595
  };
3546
3596
  });
@@ -3548,7 +3598,7 @@ var ExportBuilder = class {
3548
3598
  const metadata = this.buildMetadata(parameters);
3549
3599
  sections = [
3550
3600
  {
3551
- sheetName: name,
3601
+ title: name,
3552
3602
  filters: metadata.map(([label, value]) => ({ label, value })),
3553
3603
  ...this.renderTableContent(rawConfig, reportData, parameters)
3554
3604
  }
@@ -1,11 +1,7 @@
1
- import { R as ReportType, A as AnalyticsField } from '../report-Bx5XpFQ0.cjs';
2
- import { E as ExportTable, a as ExportFilter } from '../types-BzLsgnfc.cjs';
1
+ import { R as ReportType, A as AnalyticsField } from '../report-DmjPDGba.cjs';
2
+ import { E as ExportSection } from '../types-BPT5hjCR.cjs';
3
3
 
4
- interface ReportDocumentSection {
5
- sheetName: string;
6
- table?: ExportTable;
7
- filters?: ExportFilter[];
8
- }
4
+ type ReportDocumentSection = ExportSection;
9
5
  interface ReportLocation {
10
6
  id: number;
11
7
  name: string;
@@ -49,7 +45,7 @@ declare class ExportBuilder {
49
45
  private getDataForConfig;
50
46
  private formatMaybeDate;
51
47
  private buildMetadata;
52
- getContent(reportData: ReportData, parameters: ReportParameters, name: string): ReportDocumentSection[];
48
+ getContent(reportData: ReportData, parameters: ReportParameters, name: string): ExportSection[];
53
49
  }
54
50
 
55
51
  export { ExportBuilder, type ReportData, type ReportDocumentSection, type ReportLocation, type ReportParameters, type SingleReportData };
@@ -1,11 +1,7 @@
1
- import { R as ReportType, A as AnalyticsField } from '../report-Bx5XpFQ0.js';
2
- import { E as ExportTable, a as ExportFilter } from '../types-BzLsgnfc.js';
1
+ import { R as ReportType, A as AnalyticsField } from '../report-DmjPDGba.js';
2
+ import { E as ExportSection } from '../types-BPT5hjCR.js';
3
3
 
4
- interface ReportDocumentSection {
5
- sheetName: string;
6
- table?: ExportTable;
7
- filters?: ExportFilter[];
8
- }
4
+ type ReportDocumentSection = ExportSection;
9
5
  interface ReportLocation {
10
6
  id: number;
11
7
  name: string;
@@ -49,7 +45,7 @@ declare class ExportBuilder {
49
45
  private getDataForConfig;
50
46
  private formatMaybeDate;
51
47
  private buildMetadata;
52
- getContent(reportData: ReportData, parameters: ReportParameters, name: string): ReportDocumentSection[];
48
+ getContent(reportData: ReportData, parameters: ReportParameters, name: string): ExportSection[];
53
49
  }
54
50
 
55
51
  export { ExportBuilder, type ReportData, type ReportDocumentSection, type ReportLocation, type ReportParameters, type SingleReportData };
@@ -6,7 +6,7 @@ import {
6
6
  getReportConfig,
7
7
  getReportFormattingLocaleOptions,
8
8
  resolveTranslate
9
- } from "../chunk-SUWIUPHT.js";
9
+ } from "../chunk-FUBK4VLH.js";
10
10
 
11
11
  // src/exporters/exportBuilder.ts
12
12
  import { format, isValid, parseISO } from "date-fns";
@@ -196,7 +196,7 @@ var ExportBuilder = class {
196
196
  const sectionParameters = { ...parameters, cols: void 0 };
197
197
  sections = rawConfig.map((config) => {
198
198
  return {
199
- sheetName: this.getConfigSectionName(config),
199
+ title: this.getConfigSectionName(config),
200
200
  ...this.renderTableContent(config, reportData, sectionParameters)
201
201
  };
202
202
  });
@@ -204,7 +204,7 @@ var ExportBuilder = class {
204
204
  const metadata = this.buildMetadata(parameters);
205
205
  sections = [
206
206
  {
207
- sheetName: name,
207
+ title: name,
208
208
  filters: metadata.map(([label, value]) => ({ label, value })),
209
209
  ...this.renderTableContent(rawConfig, reportData, parameters)
210
210
  }
@@ -36,14 +36,15 @@ module.exports = __toCommonJS(pdf_exports);
36
36
  var import_pdfkit = __toESM(require("pdfkit"), 1);
37
37
 
38
38
  // src/exporters/pdf/pdf.utils.ts
39
- var stripEmojis = (text) => {
40
- if (!text) {
41
- return text;
39
+ var sanitizePdfText = (text) => {
40
+ if (!text?.trim()) {
41
+ return "";
42
42
  }
43
- return text.replace(
43
+ const leadingSpaces = /^ */.exec(text)?.[0] ?? "";
44
+ return leadingSpaces + text.trimStart().replace(/€/g, "EUR ").replace(
44
45
  /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA00}-\u{1FA6F}]|[\u{1FA70}-\u{1FAFF}]|[\u{FE00}-\u{FE0F}]|[\u{1F004}]|[\u{1F0CF}]|[\u{1F18E}]|[\u{1F191}-\u{1F19A}]|[\u{1F1E6}-\u{1F1FF}]|[\u{1F201}-\u{1F251}]/gu,
45
46
  ""
46
- ).replace(/\s+/g, " ").trim();
47
+ ).replace(/[\x00-\x1F\x7F]/g, " ").replace(/[^ -ÿ]/g, "").replace(/\s+/g, " ").trim();
47
48
  };
48
49
 
49
50
  // src/exporters/pdf/index.ts
@@ -67,6 +68,9 @@ var PdfExporter = class {
67
68
  doc.addPage();
68
69
  }
69
70
  let currentY = doc.y;
71
+ if (sanitizedSections.title) {
72
+ currentY = this.drawSectionTitle(doc, sanitizedSections.title);
73
+ }
70
74
  if (sanitizedSections.filters && sanitizedSections.filters.length > 0) {
71
75
  currentY = this.drawFilters(doc, sanitizedSections.filters);
72
76
  }
@@ -81,23 +85,23 @@ var PdfExporter = class {
81
85
  });
82
86
  }
83
87
  sanitizeSections(sections) {
84
- const sanitized = {};
88
+ const sanitized = { title: sanitizePdfText(sections.title) };
85
89
  if (sections.filters) {
86
90
  sanitized.filters = sections.filters.map((filter) => ({
87
- label: stripEmojis(filter.label),
88
- value: stripEmojis(filter.value)
91
+ label: sanitizePdfText(filter.label),
92
+ value: sanitizePdfText(filter.value)
89
93
  }));
90
94
  }
91
95
  if (sections.table) {
92
96
  sanitized.table = {
93
97
  columns: sections.table.columns.map((col) => ({
94
98
  ...col,
95
- header: stripEmojis(col.header)
99
+ header: sanitizePdfText(col.header)
96
100
  })),
97
101
  rows: sections.table.rows.map((row) => {
98
102
  const sanitizedRow = {};
99
103
  for (const [key, value] of Object.entries(row)) {
100
- sanitizedRow[key] = typeof value === "string" ? stripEmojis(value) : value;
104
+ sanitizedRow[key] = typeof value === "string" ? sanitizePdfText(value) : value;
101
105
  }
102
106
  return sanitizedRow;
103
107
  })
@@ -105,6 +109,11 @@ var PdfExporter = class {
105
109
  }
106
110
  return sanitized;
107
111
  }
112
+ drawSectionTitle(doc, title) {
113
+ doc.fillColor(COLOR_BLACK).font(FONT_BOLD).fontSize(13).text(title, { align: "left" });
114
+ doc.moveDown(0.5);
115
+ return doc.y;
116
+ }
108
117
  drawFilters(doc, filters) {
109
118
  doc.fillColor(COLOR_BLACK).font(FONT_BOLD).fontSize(11).text("Applied Filters", { align: "left" });
110
119
  doc.moveDown(0.5);
@@ -123,26 +132,33 @@ var PdfExporter = class {
123
132
  const columnCount = columns.length;
124
133
  const headerFontSize = columnCount > 13 ? 8 : columnCount > 10 ? 9 : columnCount > 7 ? 10 : 11;
125
134
  const dataFontSize = columnCount > 13 ? 7 : columnCount > 10 ? 8 : columnCount > 7 ? 9 : 10;
135
+ const headerWidthSlack = 2;
136
+ const headerMinWidths = /* @__PURE__ */ new Map();
126
137
  columns.forEach((col) => {
127
138
  doc.font(FONT_BOLD).fontSize(headerFontSize);
128
- let maxWidth = doc.widthOfString(col.header);
139
+ const headerTextWidth = doc.widthOfString(col.header);
140
+ const headerMinWidth = Math.max(...col.header.split(" ").map((w) => doc.widthOfString(w)));
129
141
  doc.font(FONT_REGULAR).fontSize(dataFontSize);
142
+ let maxDataWidth = 0;
130
143
  rows.forEach((row) => {
131
144
  const rv = row[col.key];
132
145
  const cellValue = typeof rv === "string" || typeof rv === "number" || typeof rv === "boolean" ? String(rv) : "";
133
146
  const textWidth = doc.widthOfString(cellValue);
134
- if (textWidth > maxWidth) {
135
- maxWidth = textWidth;
147
+ if (textWidth > maxDataWidth) {
148
+ maxDataWidth = textWidth;
136
149
  }
137
150
  });
138
- col.width = Math.max(maxWidth + baseCellPadding * 2, minColumnWidth);
151
+ const contentWidth = Math.max(headerTextWidth, maxDataWidth);
152
+ col.width = Math.max(contentWidth + baseCellPadding * 2 + headerWidthSlack, minColumnWidth);
153
+ headerMinWidths.set(col, headerMinWidth + baseCellPadding * 2 + headerWidthSlack);
139
154
  });
140
155
  const usableWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
141
156
  const totalColumnWidth = columns.reduce((sum, c) => sum + (c.width ?? minColumnWidth), 0);
142
157
  if (totalColumnWidth > usableWidth) {
143
158
  const scale = usableWidth / totalColumnWidth;
144
159
  columns.forEach((c) => {
145
- c.width = Math.max(Math.floor((c.width ?? minColumnWidth) * scale), minColumnWidth);
160
+ const headerMin = headerMinWidths.get(c) ?? minColumnWidth;
161
+ c.width = Math.max(Math.floor((c.width ?? minColumnWidth) * scale), headerMin, minColumnWidth);
146
162
  });
147
163
  }
148
164
  const tableWidth = columns.reduce((sum, c) => sum + (c.width ?? minColumnWidth), 0);
@@ -1,18 +1,15 @@
1
- import { E as ExportTable, a as ExportFilter, b as ExportTableColumn } from '../../types-BzLsgnfc.cjs';
1
+ import { E as ExportSection, a as ExportFilter, b as ExportTable, c as ExportTableColumn } from '../../types-BPT5hjCR.cjs';
2
2
 
3
- interface PdfSection {
4
- table?: ExportTable;
5
- filters?: ExportFilter[];
6
- }
7
3
  declare class PdfExporter {
8
4
  generate(content: {
9
- sections: PdfSection[];
5
+ sections: ExportSection[];
10
6
  }): Promise<Buffer>;
11
7
  private sanitizeSections;
8
+ drawSectionTitle(doc: PDFKit.PDFDocument, title: string): number;
12
9
  drawFilters(doc: PDFKit.PDFDocument, filters: ExportFilter[]): number;
13
10
  drawTable(doc: PDFKit.PDFDocument, table: ExportTable, startY?: number): void;
14
11
  drawHeader(doc: PDFKit.PDFDocument, columns: ExportTableColumn[], startY: number, tableWidth: number, headerHeight: number, cellPadding: number, headerFontSize: number, minColumnWidth: number): number;
15
12
  drawRow(doc: PDFKit.PDFDocument, row: Record<string, unknown>, rowIndex: number, columns: ExportTableColumn[], currentY: number, tableWidth: number, rowHeight: number, cellPadding: number, dataFontSize: number, minColumnWidth: number): number;
16
13
  }
17
14
 
18
- export { PdfExporter, ExportFilter as PdfFilter, type PdfSection, ExportTable as PdfTable, ExportTableColumn as PdfTableColumn };
15
+ export { PdfExporter, ExportFilter as PdfFilter, ExportSection as PdfSection, ExportTable as PdfTable, ExportTableColumn as PdfTableColumn };
@@ -1,18 +1,15 @@
1
- import { E as ExportTable, a as ExportFilter, b as ExportTableColumn } from '../../types-BzLsgnfc.js';
1
+ import { E as ExportSection, a as ExportFilter, b as ExportTable, c as ExportTableColumn } from '../../types-BPT5hjCR.js';
2
2
 
3
- interface PdfSection {
4
- table?: ExportTable;
5
- filters?: ExportFilter[];
6
- }
7
3
  declare class PdfExporter {
8
4
  generate(content: {
9
- sections: PdfSection[];
5
+ sections: ExportSection[];
10
6
  }): Promise<Buffer>;
11
7
  private sanitizeSections;
8
+ drawSectionTitle(doc: PDFKit.PDFDocument, title: string): number;
12
9
  drawFilters(doc: PDFKit.PDFDocument, filters: ExportFilter[]): number;
13
10
  drawTable(doc: PDFKit.PDFDocument, table: ExportTable, startY?: number): void;
14
11
  drawHeader(doc: PDFKit.PDFDocument, columns: ExportTableColumn[], startY: number, tableWidth: number, headerHeight: number, cellPadding: number, headerFontSize: number, minColumnWidth: number): number;
15
12
  drawRow(doc: PDFKit.PDFDocument, row: Record<string, unknown>, rowIndex: number, columns: ExportTableColumn[], currentY: number, tableWidth: number, rowHeight: number, cellPadding: number, dataFontSize: number, minColumnWidth: number): number;
16
13
  }
17
14
 
18
- export { PdfExporter, ExportFilter as PdfFilter, type PdfSection, ExportTable as PdfTable, ExportTableColumn as PdfTableColumn };
15
+ export { PdfExporter, ExportFilter as PdfFilter, ExportSection as PdfSection, ExportTable as PdfTable, ExportTableColumn as PdfTableColumn };
@@ -2,14 +2,15 @@
2
2
  import PDFDocument from "pdfkit";
3
3
 
4
4
  // src/exporters/pdf/pdf.utils.ts
5
- var stripEmojis = (text) => {
6
- if (!text) {
7
- return text;
5
+ var sanitizePdfText = (text) => {
6
+ if (!text?.trim()) {
7
+ return "";
8
8
  }
9
- return text.replace(
9
+ const leadingSpaces = /^ */.exec(text)?.[0] ?? "";
10
+ return leadingSpaces + text.trimStart().replace(/€/g, "EUR ").replace(
10
11
  /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA00}-\u{1FA6F}]|[\u{1FA70}-\u{1FAFF}]|[\u{FE00}-\u{FE0F}]|[\u{1F004}]|[\u{1F0CF}]|[\u{1F18E}]|[\u{1F191}-\u{1F19A}]|[\u{1F1E6}-\u{1F1FF}]|[\u{1F201}-\u{1F251}]/gu,
11
12
  ""
12
- ).replace(/\s+/g, " ").trim();
13
+ ).replace(/[\x00-\x1F\x7F]/g, " ").replace(/[^ -ÿ]/g, "").replace(/\s+/g, " ").trim();
13
14
  };
14
15
 
15
16
  // src/exporters/pdf/index.ts
@@ -33,6 +34,9 @@ var PdfExporter = class {
33
34
  doc.addPage();
34
35
  }
35
36
  let currentY = doc.y;
37
+ if (sanitizedSections.title) {
38
+ currentY = this.drawSectionTitle(doc, sanitizedSections.title);
39
+ }
36
40
  if (sanitizedSections.filters && sanitizedSections.filters.length > 0) {
37
41
  currentY = this.drawFilters(doc, sanitizedSections.filters);
38
42
  }
@@ -47,23 +51,23 @@ var PdfExporter = class {
47
51
  });
48
52
  }
49
53
  sanitizeSections(sections) {
50
- const sanitized = {};
54
+ const sanitized = { title: sanitizePdfText(sections.title) };
51
55
  if (sections.filters) {
52
56
  sanitized.filters = sections.filters.map((filter) => ({
53
- label: stripEmojis(filter.label),
54
- value: stripEmojis(filter.value)
57
+ label: sanitizePdfText(filter.label),
58
+ value: sanitizePdfText(filter.value)
55
59
  }));
56
60
  }
57
61
  if (sections.table) {
58
62
  sanitized.table = {
59
63
  columns: sections.table.columns.map((col) => ({
60
64
  ...col,
61
- header: stripEmojis(col.header)
65
+ header: sanitizePdfText(col.header)
62
66
  })),
63
67
  rows: sections.table.rows.map((row) => {
64
68
  const sanitizedRow = {};
65
69
  for (const [key, value] of Object.entries(row)) {
66
- sanitizedRow[key] = typeof value === "string" ? stripEmojis(value) : value;
70
+ sanitizedRow[key] = typeof value === "string" ? sanitizePdfText(value) : value;
67
71
  }
68
72
  return sanitizedRow;
69
73
  })
@@ -71,6 +75,11 @@ var PdfExporter = class {
71
75
  }
72
76
  return sanitized;
73
77
  }
78
+ drawSectionTitle(doc, title) {
79
+ doc.fillColor(COLOR_BLACK).font(FONT_BOLD).fontSize(13).text(title, { align: "left" });
80
+ doc.moveDown(0.5);
81
+ return doc.y;
82
+ }
74
83
  drawFilters(doc, filters) {
75
84
  doc.fillColor(COLOR_BLACK).font(FONT_BOLD).fontSize(11).text("Applied Filters", { align: "left" });
76
85
  doc.moveDown(0.5);
@@ -89,26 +98,33 @@ var PdfExporter = class {
89
98
  const columnCount = columns.length;
90
99
  const headerFontSize = columnCount > 13 ? 8 : columnCount > 10 ? 9 : columnCount > 7 ? 10 : 11;
91
100
  const dataFontSize = columnCount > 13 ? 7 : columnCount > 10 ? 8 : columnCount > 7 ? 9 : 10;
101
+ const headerWidthSlack = 2;
102
+ const headerMinWidths = /* @__PURE__ */ new Map();
92
103
  columns.forEach((col) => {
93
104
  doc.font(FONT_BOLD).fontSize(headerFontSize);
94
- let maxWidth = doc.widthOfString(col.header);
105
+ const headerTextWidth = doc.widthOfString(col.header);
106
+ const headerMinWidth = Math.max(...col.header.split(" ").map((w) => doc.widthOfString(w)));
95
107
  doc.font(FONT_REGULAR).fontSize(dataFontSize);
108
+ let maxDataWidth = 0;
96
109
  rows.forEach((row) => {
97
110
  const rv = row[col.key];
98
111
  const cellValue = typeof rv === "string" || typeof rv === "number" || typeof rv === "boolean" ? String(rv) : "";
99
112
  const textWidth = doc.widthOfString(cellValue);
100
- if (textWidth > maxWidth) {
101
- maxWidth = textWidth;
113
+ if (textWidth > maxDataWidth) {
114
+ maxDataWidth = textWidth;
102
115
  }
103
116
  });
104
- col.width = Math.max(maxWidth + baseCellPadding * 2, minColumnWidth);
117
+ const contentWidth = Math.max(headerTextWidth, maxDataWidth);
118
+ col.width = Math.max(contentWidth + baseCellPadding * 2 + headerWidthSlack, minColumnWidth);
119
+ headerMinWidths.set(col, headerMinWidth + baseCellPadding * 2 + headerWidthSlack);
105
120
  });
106
121
  const usableWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
107
122
  const totalColumnWidth = columns.reduce((sum, c) => sum + (c.width ?? minColumnWidth), 0);
108
123
  if (totalColumnWidth > usableWidth) {
109
124
  const scale = usableWidth / totalColumnWidth;
110
125
  columns.forEach((c) => {
111
- c.width = Math.max(Math.floor((c.width ?? minColumnWidth) * scale), minColumnWidth);
126
+ const headerMin = headerMinWidths.get(c) ?? minColumnWidth;
127
+ c.width = Math.max(Math.floor((c.width ?? minColumnWidth) * scale), headerMin, minColumnWidth);
112
128
  });
113
129
  }
114
130
  const tableWidth = columns.reduce((sum, c) => sum + (c.width ?? minColumnWidth), 0);
package/dist/index.cjs CHANGED
@@ -36,7 +36,7 @@ __export(index_exports, {
36
36
  dailySalesPaymentsConfig: () => dailySalesPaymentsConfig,
37
37
  dailySalesRefundsVoidsConfig: () => dailySalesRefundsVoidsConfig,
38
38
  dailySalesTaxesConfig: () => dailySalesTaxesConfig,
39
- dailySalesTrendsConfig: () => dailySalesTrendsConfig,
39
+ dailySalesTrendsDayPartConfig: () => dailySalesTrendsDayPartConfig,
40
40
  dailySalesTrendsOrderTypeConfig: () => dailySalesTrendsOrderTypeConfig,
41
41
  employeeTimecardConfig: () => employeeTimecardConfig,
42
42
  employeeTipConfig: () => employeeTipConfig,
@@ -756,7 +756,12 @@ var employeeTipConfig = {
756
756
  // src/reports/dailySales/dailySales.ts
757
757
  var FIELDS10 = {
758
758
  groupById: { type: "string" },
759
- groupByName: { type: "string", size: FIRST_COLUMN_WIDTH, footerCalculation: { type: "label", label: "table.total" } },
759
+ groupByName: {
760
+ type: "string",
761
+ size: FIRST_COLUMN_WIDTH,
762
+ columnKey: "revenueClass",
763
+ footerCalculation: { type: "label", label: "table.total" }
764
+ },
760
765
  itemsQuantity: { type: "number", columnKey: "quantity" },
761
766
  salesAmountGross: { type: "money", columnKey: "grossSales" },
762
767
  discountsAmount: { type: "money", columnKey: "discountAmount" },
@@ -837,10 +842,10 @@ var FIELDS13 = {
837
842
  columnKey: "paymentType",
838
843
  footerCalculation: { type: "label", label: "table.total" }
839
844
  },
840
- paymentsCount: { type: "number", columnKey: "paymentsCount", footerCalculation: { type: "sum" } },
841
- paymentsAmount: { type: "money", columnKey: "paymentsAmount", footerCalculation: { type: "sum" } },
842
- tipsAmount: { type: "money", columnKey: "tips", footerCalculation: { type: "sum" } },
843
- totalSales: { type: "money", columnKey: "paymentsTotal", footerCalculation: { type: "sum" } }
845
+ paymentsCount: { type: "number-empty", columnKey: "paymentsCount", footerCalculation: { type: "sum" } },
846
+ paymentsAmount: { type: "money-empty", columnKey: "paymentsAmount", footerCalculation: { type: "sum" } },
847
+ tipsAmount: { type: "money-empty", columnKey: "tips", footerCalculation: { type: "sum" } },
848
+ totalSales: { type: "money-empty", columnKey: "paymentsTotal", footerCalculation: { type: "sum" } }
844
849
  };
845
850
  var DAILY_SALES_PAYMENTS_AVAILABLE_COLUMNS = [
846
851
  "paymentTypeName",
@@ -912,11 +917,12 @@ var dailySalesTaxesConfig = {
912
917
  sectionName: "common.report-section.taxes"
913
918
  };
914
919
 
915
- // src/reports/dailySales/dailySalesTrends.ts
920
+ // src/reports/dailySales/dailySalesTrendsDayPart.ts
916
921
  var FIELDS16 = {
917
922
  groupById: { type: "string" },
918
923
  groupByName: {
919
924
  type: "string",
925
+ columnKey: "daypart",
920
926
  size: FIRST_COLUMN_WIDTH,
921
927
  footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
922
928
  },
@@ -950,7 +956,7 @@ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS = [
950
956
  "guestAvg",
951
957
  "salesAmountNet"
952
958
  ];
953
- var dailySalesTrendsConfig = {
959
+ var dailySalesTrendsDayPartConfig = {
954
960
  fields: FIELDS16,
955
961
  availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
956
962
  defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
@@ -959,10 +965,50 @@ var dailySalesTrendsConfig = {
959
965
  sectionName: "common.report-section.sales-by-day-part",
960
966
  extraFooterFields: ["salesAmountNet"]
961
967
  };
968
+
969
+ // src/reports/dailySales/dailySalesTrendsOrderType.ts
970
+ var FIELDS17 = {
971
+ groupById: { type: "string" },
972
+ groupByName: {
973
+ columnKey: "orderType",
974
+ type: "string",
975
+ size: FIRST_COLUMN_WIDTH,
976
+ footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
977
+ },
978
+ salesAmountNet: { type: "money", columnKey: "netSales" },
979
+ ticketsCount: { type: "number", columnKey: "tickets" },
980
+ guestsCount: { type: "number", columnKey: "guests" },
981
+ ticketAvg: {
982
+ type: "money",
983
+ columnKey: "ticketAverage",
984
+ footerCalculation: {
985
+ type: "average",
986
+ numeratorField: "salesAmountNet",
987
+ denominatorField: "ticketsCount"
988
+ }
989
+ },
990
+ guestAvg: {
991
+ type: "money",
992
+ columnKey: "guestAverage",
993
+ footerCalculation: {
994
+ type: "average",
995
+ numeratorField: "salesAmountNet",
996
+ denominatorField: "guestsCount"
997
+ }
998
+ }
999
+ };
1000
+ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2 = [
1001
+ "groupByName",
1002
+ "ticketsCount",
1003
+ "guestsCount",
1004
+ "ticketAvg",
1005
+ "guestAvg",
1006
+ "salesAmountNet"
1007
+ ];
962
1008
  var dailySalesTrendsOrderTypeConfig = {
963
- fields: FIELDS16,
964
- availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
965
- defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
1009
+ fields: FIELDS17,
1010
+ availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
1011
+ defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
966
1012
  hasFooter: true,
967
1013
  dataAccessKey: "trendsByOrderType",
968
1014
  sectionName: "common.report-section.sales-by-order-type",
@@ -990,7 +1036,7 @@ var DAILY_SALES_SECTION_CONFIGS = [
990
1036
  dailySalesTaxesConfig,
991
1037
  dailySalesRefundsVoidsConfig,
992
1038
  dailySalesDiscountsConfig,
993
- dailySalesTrendsConfig,
1039
+ dailySalesTrendsDayPartConfig,
994
1040
  dailySalesTrendsOrderTypeConfig
995
1041
  ];
996
1042
  var REPORT_CONFIG_MAP = {
@@ -1783,7 +1829,7 @@ function getColumnAlignment(type) {
1783
1829
  return "right";
1784
1830
  }
1785
1831
  function isNumericType(type) {
1786
- return type === "money" || type === "number" || type === "percent" || type === "fixedNumber";
1832
+ return type === "money" || type === "money-empty" || type === "number" || type === "number-empty" || type === "percent" || type === "fixedNumber";
1787
1833
  }
1788
1834
 
1789
1835
  // src/totals.ts
@@ -1924,7 +1970,7 @@ var DAILY_SALES_SECTIONS = [
1924
1970
  },
1925
1971
  {
1926
1972
  sectionLabel: "common.report-section.sales-by-day-part",
1927
- config: dailySalesTrendsConfig,
1973
+ config: dailySalesTrendsDayPartConfig,
1928
1974
  columns: [
1929
1975
  { fieldKey: "groupByName", columnKey: "daypart" },
1930
1976
  { fieldKey: "ticketsCount", columnKey: "tickets" },
@@ -1997,7 +2043,27 @@ var buildDailySalesRevClassFooter = (inputs) => {
1997
2043
  ];
1998
2044
  };
1999
2045
  var buildPaymentsSectionData = (payments) => {
2000
- return payments.filter((payment) => payment.paymentTypeName !== TENDER_TYPE.HOUSE_ACCOUNT);
2046
+ const filtered = payments.filter((payment) => payment.paymentTypeName !== TENDER_TYPE.HOUSE_ACCOUNT);
2047
+ const seenParentCategories = /* @__PURE__ */ new Set();
2048
+ const result = [];
2049
+ for (const payment of filtered) {
2050
+ if (payment.parentCategory !== null && !seenParentCategories.has(payment.parentCategory)) {
2051
+ seenParentCategories.add(payment.parentCategory);
2052
+ const headerRow = {
2053
+ ...payment,
2054
+ paymentTypeName: payment.parentCategory,
2055
+ parentCategory: "",
2056
+ paymentsCount: null,
2057
+ paymentsAmount: null,
2058
+ tipsAmount: null,
2059
+ totalSales: null
2060
+ };
2061
+ result.push(headerRow);
2062
+ }
2063
+ const child = payment.parentCategory !== null ? { ...payment, paymentTypeName: ` ${payment.paymentTypeName}` } : payment;
2064
+ result.push(child);
2065
+ }
2066
+ return result;
2001
2067
  };
2002
2068
 
2003
2069
  // src/translations/crowdin/skytab-analytics-report-utils/en-GB.ts
@@ -3411,11 +3477,11 @@ var enUS3 = {
3411
3477
  "common.report-col.type": "Type",
3412
3478
  "common.report-col.type.short": "Type",
3413
3479
  "common.report-col.type.info": " ",
3414
- "common.report-section.revenue-class": "Revenue Class",
3480
+ "common.report-section.revenue-class": "Sales by Revenue Class",
3415
3481
  "common.report-section.payments": "Payments",
3416
3482
  "common.report-section.cash": "Expected Closeout Cash",
3417
3483
  "common.report-section.taxes": "Taxes",
3418
- "common.report-section.refunds-voids": "Refunds & Voids",
3484
+ "common.report-section.refunds-voids": "Refunds/Voids",
3419
3485
  "common.report-section.discounts": "Discounts",
3420
3486
  "common.report-section.sales-by-day-part": "Sales by Day Part",
3421
3487
  "common.report-section.sales-by-order-type": "Sales by Order Type",
@@ -3605,6 +3671,8 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
3605
3671
  return formatString(value, localeOptions);
3606
3672
  case "money":
3607
3673
  return formatMoney(getNumberToFormat(value), { currency, locale });
3674
+ case "money-empty":
3675
+ return value != null ? formatMoney(getNumberToFormat(value), { currency, locale }) : "";
3608
3676
  case "percent":
3609
3677
  return formatPercent(getNumberToFormat(value) * 100);
3610
3678
  case "fixedNumber":
@@ -3617,6 +3685,8 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
3617
3685
  const d = getDateToFormat(value);
3618
3686
  return d ? formatTime(d, { locale, format: "00:00:00" }) : "";
3619
3687
  }
3688
+ case "number-empty":
3689
+ return value != null ? String(getNumberToFormat(value)) : "";
3620
3690
  case "number":
3621
3691
  default:
3622
3692
  return String(getNumberToFormat(value));
@@ -3640,7 +3710,7 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
3640
3710
  dailySalesPaymentsConfig,
3641
3711
  dailySalesRefundsVoidsConfig,
3642
3712
  dailySalesTaxesConfig,
3643
- dailySalesTrendsConfig,
3713
+ dailySalesTrendsDayPartConfig,
3644
3714
  dailySalesTrendsOrderTypeConfig,
3645
3715
  employeeTimecardConfig,
3646
3716
  employeeTipConfig,
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-Bx5XpFQ0.cjs';
2
- export { e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getReportConfig, n as getReportExportFileName } from './report-Bx5XpFQ0.cjs';
1
+ import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-DmjPDGba.cjs';
2
+ export { e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getReportConfig, n as getReportExportFileName } from './report-DmjPDGba.cjs';
3
3
  import { LocaleCode } from '@harbortouch/locale-registry';
4
4
  export { R as RenderedReport, a as ReportDocument, b as ReportFormat, c as ReportSection, d as ResolvedColumn, S as SummaryRow } from './ir-CUi0Z9hv.cjs';
5
5
 
@@ -143,6 +143,11 @@ declare const buildDailySalesRevClassFooter: (inputs: {
143
143
  })[];
144
144
  declare const buildPaymentsSectionData: <T extends {
145
145
  paymentTypeName: string;
146
+ paymentsCount: number | null;
147
+ paymentsAmount: number | null;
148
+ tipsAmount: number | null;
149
+ totalSales: number | null;
150
+ parentCategory: null | string;
146
151
  }>(payments: T[]) => T[];
147
152
 
148
153
  type DailySalesRefundsVoidsField = 'description' | 'count' | 'amount' | 'pctSales';
@@ -200,7 +205,7 @@ declare const salesByItemDetailConfig: {
200
205
  };
201
206
 
202
207
  type DailySalesTrendsField = 'groupById' | 'groupByName' | 'salesAmountNet' | 'ticketsCount' | 'guestsCount' | 'ticketAvg' | 'guestAvg';
203
- declare const dailySalesTrendsConfig: {
208
+ declare const dailySalesTrendsDayPartConfig: {
204
209
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
205
210
  readonly availableColumns: DailySalesTrendsField[];
206
211
  readonly defaultVisibleColumns: DailySalesTrendsField[];
@@ -209,6 +214,7 @@ declare const dailySalesTrendsConfig: {
209
214
  readonly sectionName: "common.report-section.sales-by-day-part";
210
215
  readonly extraFooterFields: ["salesAmountNet"];
211
216
  };
217
+
212
218
  declare const dailySalesTrendsOrderTypeConfig: {
213
219
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
214
220
  readonly availableColumns: DailySalesTrendsField[];
@@ -305,4 +311,4 @@ declare const getReportFormattingLocaleOptions: (locations: {
305
311
  }[]) => LocaleOption[];
306
312
  declare const formatFieldValue: (value: unknown, type: FieldType, localeOptions: LocaleOption, fullRecord: Record<string, unknown> | null | undefined, fieldConfig?: ColumnPresentationConfig) => string;
307
313
 
308
- export { ColumnAlignment, ColumnGroupConfig, ColumnPresentationConfig, DAILY_SALES_CASH_ROW_LABELS, DAILY_SALES_REV_CLASS_FOOTER_LABELS, type DailySalesCacheField, type DailySalesDiscountsField, type DailySalesField, type DailySalesPaymentsField, type DailySalesRefundsVoidsField, type DailySalesTaxesField, type DailySalesTrendsField, type EmployeeTimecardField, type EmployeeTipField, FieldType, type FormatDateOptions, type FormatMoneyOptions, type FormatNumberOptions, type FormatTimeOptions, type ItemTaxField, type LocaleOption, type ModifierMixField, type ProductMixField, REPORT_SECTION_CONFIGS, ReportColumnKey, ReportConfig, type ReportSectionColumnDef, type ReportSectionDefinition, ReportType, type SalesByItemDetailField, type SalesSummaryField, type SupportedLocale, TENDER_TYPE, type TicketLiveField, type TicketSummaryField, type TimeFormat, buildDailySalesCashPayments, buildDailySalesRevClassFooter, buildPaymentsSectionData, calculateReportTotals, dailySalesCacheConfig, dailySalesConfig, dailySalesDiscountsConfig, dailySalesPaymentsConfig, dailySalesRefundsVoidsConfig, dailySalesTaxesConfig, dailySalesTrendsConfig, dailySalesTrendsOrderTypeConfig, employeeTimecardConfig, employeeTipConfig, formatDate, formatFieldValue, formatFixedNumber, formatInteger, formatMoney, formatMoneyWithoutSymbol, formatPercent, formatString, formatTime, getColumnAlignment, getDateToFormat, getFooterValue, getNumberToFormat, getReportFormattingLocaleOptions, isNumericType, itemTaxConfig, modifierMixConfig, productMixConfig, resolveTranslate, salesByItemDetailConfig, salesSummaryConfig, ticketLiveConfig, ticketSummaryConfig };
314
+ export { ColumnAlignment, ColumnGroupConfig, ColumnPresentationConfig, DAILY_SALES_CASH_ROW_LABELS, DAILY_SALES_REV_CLASS_FOOTER_LABELS, type DailySalesCacheField, type DailySalesDiscountsField, type DailySalesField, type DailySalesPaymentsField, type DailySalesRefundsVoidsField, type DailySalesTaxesField, type DailySalesTrendsField, type EmployeeTimecardField, type EmployeeTipField, FieldType, type FormatDateOptions, type FormatMoneyOptions, type FormatNumberOptions, type FormatTimeOptions, type ItemTaxField, type LocaleOption, MessageKey, type ModifierMixField, type ProductMixField, REPORT_SECTION_CONFIGS, ReportColumnKey, ReportConfig, type ReportSectionColumnDef, type ReportSectionDefinition, ReportType, type SalesByItemDetailField, type SalesSummaryField, type SupportedLocale, TENDER_TYPE, type TicketLiveField, type TicketSummaryField, type TimeFormat, buildDailySalesCashPayments, buildDailySalesRevClassFooter, buildPaymentsSectionData, calculateReportTotals, dailySalesCacheConfig, dailySalesConfig, dailySalesDiscountsConfig, dailySalesPaymentsConfig, dailySalesRefundsVoidsConfig, dailySalesTaxesConfig, dailySalesTrendsDayPartConfig, dailySalesTrendsOrderTypeConfig, employeeTimecardConfig, employeeTipConfig, formatDate, formatFieldValue, formatFixedNumber, formatInteger, formatMoney, formatMoneyWithoutSymbol, formatPercent, formatString, formatTime, getColumnAlignment, getDateToFormat, getFooterValue, getNumberToFormat, getReportFormattingLocaleOptions, isNumericType, itemTaxConfig, modifierMixConfig, productMixConfig, resolveTranslate, salesByItemDetailConfig, salesSummaryConfig, ticketLiveConfig, ticketSummaryConfig };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-Bx5XpFQ0.js';
2
- export { e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getReportConfig, n as getReportExportFileName } from './report-Bx5XpFQ0.js';
1
+ import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-DmjPDGba.js';
2
+ export { e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getReportConfig, n as getReportExportFileName } from './report-DmjPDGba.js';
3
3
  import { LocaleCode } from '@harbortouch/locale-registry';
4
4
  export { R as RenderedReport, a as ReportDocument, b as ReportFormat, c as ReportSection, d as ResolvedColumn, S as SummaryRow } from './ir-CUi0Z9hv.js';
5
5
 
@@ -143,6 +143,11 @@ declare const buildDailySalesRevClassFooter: (inputs: {
143
143
  })[];
144
144
  declare const buildPaymentsSectionData: <T extends {
145
145
  paymentTypeName: string;
146
+ paymentsCount: number | null;
147
+ paymentsAmount: number | null;
148
+ tipsAmount: number | null;
149
+ totalSales: number | null;
150
+ parentCategory: null | string;
146
151
  }>(payments: T[]) => T[];
147
152
 
148
153
  type DailySalesRefundsVoidsField = 'description' | 'count' | 'amount' | 'pctSales';
@@ -200,7 +205,7 @@ declare const salesByItemDetailConfig: {
200
205
  };
201
206
 
202
207
  type DailySalesTrendsField = 'groupById' | 'groupByName' | 'salesAmountNet' | 'ticketsCount' | 'guestsCount' | 'ticketAvg' | 'guestAvg';
203
- declare const dailySalesTrendsConfig: {
208
+ declare const dailySalesTrendsDayPartConfig: {
204
209
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
205
210
  readonly availableColumns: DailySalesTrendsField[];
206
211
  readonly defaultVisibleColumns: DailySalesTrendsField[];
@@ -209,6 +214,7 @@ declare const dailySalesTrendsConfig: {
209
214
  readonly sectionName: "common.report-section.sales-by-day-part";
210
215
  readonly extraFooterFields: ["salesAmountNet"];
211
216
  };
217
+
212
218
  declare const dailySalesTrendsOrderTypeConfig: {
213
219
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
214
220
  readonly availableColumns: DailySalesTrendsField[];
@@ -305,4 +311,4 @@ declare const getReportFormattingLocaleOptions: (locations: {
305
311
  }[]) => LocaleOption[];
306
312
  declare const formatFieldValue: (value: unknown, type: FieldType, localeOptions: LocaleOption, fullRecord: Record<string, unknown> | null | undefined, fieldConfig?: ColumnPresentationConfig) => string;
307
313
 
308
- export { ColumnAlignment, ColumnGroupConfig, ColumnPresentationConfig, DAILY_SALES_CASH_ROW_LABELS, DAILY_SALES_REV_CLASS_FOOTER_LABELS, type DailySalesCacheField, type DailySalesDiscountsField, type DailySalesField, type DailySalesPaymentsField, type DailySalesRefundsVoidsField, type DailySalesTaxesField, type DailySalesTrendsField, type EmployeeTimecardField, type EmployeeTipField, FieldType, type FormatDateOptions, type FormatMoneyOptions, type FormatNumberOptions, type FormatTimeOptions, type ItemTaxField, type LocaleOption, type ModifierMixField, type ProductMixField, REPORT_SECTION_CONFIGS, ReportColumnKey, ReportConfig, type ReportSectionColumnDef, type ReportSectionDefinition, ReportType, type SalesByItemDetailField, type SalesSummaryField, type SupportedLocale, TENDER_TYPE, type TicketLiveField, type TicketSummaryField, type TimeFormat, buildDailySalesCashPayments, buildDailySalesRevClassFooter, buildPaymentsSectionData, calculateReportTotals, dailySalesCacheConfig, dailySalesConfig, dailySalesDiscountsConfig, dailySalesPaymentsConfig, dailySalesRefundsVoidsConfig, dailySalesTaxesConfig, dailySalesTrendsConfig, dailySalesTrendsOrderTypeConfig, employeeTimecardConfig, employeeTipConfig, formatDate, formatFieldValue, formatFixedNumber, formatInteger, formatMoney, formatMoneyWithoutSymbol, formatPercent, formatString, formatTime, getColumnAlignment, getDateToFormat, getFooterValue, getNumberToFormat, getReportFormattingLocaleOptions, isNumericType, itemTaxConfig, modifierMixConfig, productMixConfig, resolveTranslate, salesByItemDetailConfig, salesSummaryConfig, ticketLiveConfig, ticketSummaryConfig };
314
+ export { ColumnAlignment, ColumnGroupConfig, ColumnPresentationConfig, DAILY_SALES_CASH_ROW_LABELS, DAILY_SALES_REV_CLASS_FOOTER_LABELS, type DailySalesCacheField, type DailySalesDiscountsField, type DailySalesField, type DailySalesPaymentsField, type DailySalesRefundsVoidsField, type DailySalesTaxesField, type DailySalesTrendsField, type EmployeeTimecardField, type EmployeeTipField, FieldType, type FormatDateOptions, type FormatMoneyOptions, type FormatNumberOptions, type FormatTimeOptions, type ItemTaxField, type LocaleOption, MessageKey, type ModifierMixField, type ProductMixField, REPORT_SECTION_CONFIGS, ReportColumnKey, ReportConfig, type ReportSectionColumnDef, type ReportSectionDefinition, ReportType, type SalesByItemDetailField, type SalesSummaryField, type SupportedLocale, TENDER_TYPE, type TicketLiveField, type TicketSummaryField, type TimeFormat, buildDailySalesCashPayments, buildDailySalesRevClassFooter, buildPaymentsSectionData, calculateReportTotals, dailySalesCacheConfig, dailySalesConfig, dailySalesDiscountsConfig, dailySalesPaymentsConfig, dailySalesRefundsVoidsConfig, dailySalesTaxesConfig, dailySalesTrendsDayPartConfig, dailySalesTrendsOrderTypeConfig, employeeTimecardConfig, employeeTipConfig, formatDate, formatFieldValue, formatFixedNumber, formatInteger, formatMoney, formatMoneyWithoutSymbol, formatPercent, formatString, formatTime, getColumnAlignment, getDateToFormat, getFooterValue, getNumberToFormat, getReportFormattingLocaleOptions, isNumericType, itemTaxConfig, modifierMixConfig, productMixConfig, resolveTranslate, salesByItemDetailConfig, salesSummaryConfig, ticketLiveConfig, ticketSummaryConfig };
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  dailySalesPaymentsConfig,
9
9
  dailySalesRefundsVoidsConfig,
10
10
  dailySalesTaxesConfig,
11
- dailySalesTrendsConfig,
11
+ dailySalesTrendsDayPartConfig,
12
12
  dailySalesTrendsOrderTypeConfig,
13
13
  employeeTimecardConfig,
14
14
  employeeTipConfig,
@@ -37,7 +37,7 @@ import {
37
37
  salesSummaryConfig,
38
38
  ticketLiveConfig,
39
39
  ticketSummaryConfig
40
- } from "./chunk-SUWIUPHT.js";
40
+ } from "./chunk-FUBK4VLH.js";
41
41
 
42
42
  // src/utils/alignment.ts
43
43
  function getColumnAlignment(type) {
@@ -47,7 +47,7 @@ function getColumnAlignment(type) {
47
47
  return "right";
48
48
  }
49
49
  function isNumericType(type) {
50
- return type === "money" || type === "number" || type === "percent" || type === "fixedNumber";
50
+ return type === "money" || type === "money-empty" || type === "number" || type === "number-empty" || type === "percent" || type === "fixedNumber";
51
51
  }
52
52
 
53
53
  // src/reports/reportSection.ts
@@ -131,7 +131,7 @@ var DAILY_SALES_SECTIONS = [
131
131
  },
132
132
  {
133
133
  sectionLabel: "common.report-section.sales-by-day-part",
134
- config: dailySalesTrendsConfig,
134
+ config: dailySalesTrendsDayPartConfig,
135
135
  columns: [
136
136
  { fieldKey: "groupByName", columnKey: "daypart" },
137
137
  { fieldKey: "ticketsCount", columnKey: "tickets" },
@@ -204,7 +204,27 @@ var buildDailySalesRevClassFooter = (inputs) => {
204
204
  ];
205
205
  };
206
206
  var buildPaymentsSectionData = (payments) => {
207
- return payments.filter((payment) => payment.paymentTypeName !== TENDER_TYPE.HOUSE_ACCOUNT);
207
+ const filtered = payments.filter((payment) => payment.paymentTypeName !== TENDER_TYPE.HOUSE_ACCOUNT);
208
+ const seenParentCategories = /* @__PURE__ */ new Set();
209
+ const result = [];
210
+ for (const payment of filtered) {
211
+ if (payment.parentCategory !== null && !seenParentCategories.has(payment.parentCategory)) {
212
+ seenParentCategories.add(payment.parentCategory);
213
+ const headerRow = {
214
+ ...payment,
215
+ paymentTypeName: payment.parentCategory,
216
+ parentCategory: "",
217
+ paymentsCount: null,
218
+ paymentsAmount: null,
219
+ tipsAmount: null,
220
+ totalSales: null
221
+ };
222
+ result.push(headerRow);
223
+ }
224
+ const child = payment.parentCategory !== null ? { ...payment, paymentTypeName: ` ${payment.paymentTypeName}` } : payment;
225
+ result.push(child);
226
+ }
227
+ return result;
208
228
  };
209
229
  export {
210
230
  COLUMN_REGISTRY,
@@ -223,7 +243,7 @@ export {
223
243
  dailySalesPaymentsConfig,
224
244
  dailySalesRefundsVoidsConfig,
225
245
  dailySalesTaxesConfig,
226
- dailySalesTrendsConfig,
246
+ dailySalesTrendsDayPartConfig,
227
247
  dailySalesTrendsOrderTypeConfig,
228
248
  employeeTimecardConfig,
229
249
  employeeTipConfig,
@@ -1169,11 +1169,11 @@ declare const enUS: {
1169
1169
  readonly 'common.report-col.type': "Type";
1170
1170
  readonly 'common.report-col.type.short': "Type";
1171
1171
  readonly 'common.report-col.type.info': " ";
1172
- readonly 'common.report-section.revenue-class': "Revenue Class";
1172
+ readonly 'common.report-section.revenue-class': "Sales by Revenue Class";
1173
1173
  readonly 'common.report-section.payments': "Payments";
1174
1174
  readonly 'common.report-section.cash': "Expected Closeout Cash";
1175
1175
  readonly 'common.report-section.taxes': "Taxes";
1176
- readonly 'common.report-section.refunds-voids': "Refunds & Voids";
1176
+ readonly 'common.report-section.refunds-voids': "Refunds/Voids";
1177
1177
  readonly 'common.report-section.discounts': "Discounts";
1178
1178
  readonly 'common.report-section.sales-by-day-part': "Sales by Day Part";
1179
1179
  readonly 'common.report-section.sales-by-order-type': "Sales by Order Type";
@@ -1217,7 +1217,7 @@ declare const enUS: {
1217
1217
  };
1218
1218
  type MessageKey = keyof typeof enUS;
1219
1219
 
1220
- type FieldType = 'string' | 'money' | 'percent' | 'number' | 'fixedNumber' | 'date' | 'time' | 'boolean' | 'conditional';
1220
+ type FieldType = 'string' | 'money' | 'percent' | 'number' | 'fixedNumber' | 'date' | 'time' | 'boolean' | 'number-empty' | 'money-empty' | 'conditional';
1221
1221
  type ColumnAlignment = 'left' | 'right';
1222
1222
  type FooterCalculationType = 'sum' | 'percentChange' | 'variancePercent' | 'average' | 'quotientOfDifferences' | 'count' | 'label' | 'none';
1223
1223
  type FooterCalculation<TField = string> = {
@@ -1169,11 +1169,11 @@ declare const enUS: {
1169
1169
  readonly 'common.report-col.type': "Type";
1170
1170
  readonly 'common.report-col.type.short': "Type";
1171
1171
  readonly 'common.report-col.type.info': " ";
1172
- readonly 'common.report-section.revenue-class': "Revenue Class";
1172
+ readonly 'common.report-section.revenue-class': "Sales by Revenue Class";
1173
1173
  readonly 'common.report-section.payments': "Payments";
1174
1174
  readonly 'common.report-section.cash': "Expected Closeout Cash";
1175
1175
  readonly 'common.report-section.taxes': "Taxes";
1176
- readonly 'common.report-section.refunds-voids': "Refunds & Voids";
1176
+ readonly 'common.report-section.refunds-voids': "Refunds/Voids";
1177
1177
  readonly 'common.report-section.discounts': "Discounts";
1178
1178
  readonly 'common.report-section.sales-by-day-part': "Sales by Day Part";
1179
1179
  readonly 'common.report-section.sales-by-order-type': "Sales by Order Type";
@@ -1217,7 +1217,7 @@ declare const enUS: {
1217
1217
  };
1218
1218
  type MessageKey = keyof typeof enUS;
1219
1219
 
1220
- type FieldType = 'string' | 'money' | 'percent' | 'number' | 'fixedNumber' | 'date' | 'time' | 'boolean' | 'conditional';
1220
+ type FieldType = 'string' | 'money' | 'percent' | 'number' | 'fixedNumber' | 'date' | 'time' | 'boolean' | 'number-empty' | 'money-empty' | 'conditional';
1221
1221
  type ColumnAlignment = 'left' | 'right';
1222
1222
  type FooterCalculationType = 'sum' | 'percentChange' | 'variancePercent' | 'average' | 'quotientOfDifferences' | 'count' | 'label' | 'none';
1223
1223
  type FooterCalculation<TField = string> = {
@@ -11,5 +11,10 @@ interface ExportFilter {
11
11
  label: string;
12
12
  value: string;
13
13
  }
14
+ interface ExportSection {
15
+ title: string;
16
+ table?: ExportTable;
17
+ filters?: ExportFilter[];
18
+ }
14
19
 
15
- export type { ExportTable as E, ExportFilter as a, ExportTableColumn as b };
20
+ export type { ExportSection as E, ExportFilter as a, ExportTable as b, ExportTableColumn as c };
@@ -11,5 +11,10 @@ interface ExportFilter {
11
11
  label: string;
12
12
  value: string;
13
13
  }
14
+ interface ExportSection {
15
+ title: string;
16
+ table?: ExportTable;
17
+ filters?: ExportFilter[];
18
+ }
14
19
 
15
- export type { ExportTable as E, ExportFilter as a, ExportTableColumn as b };
20
+ export type { ExportSection as E, ExportFilter as a, ExportTable as b, ExportTableColumn as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harbortouch/skytab-analytics-report-utils",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Centralized report column presentation configuration for SkyTab Analytics",
5
5
  "engines": {
6
6
  "node": ">=22.6.0",