@harbortouch/skytab-analytics-report-utils 0.27.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" },
@@ -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",
@@ -3403,7 +3449,7 @@ export {
3403
3449
  dailySalesPaymentsConfig,
3404
3450
  dailySalesRefundsVoidsConfig,
3405
3451
  dailySalesTaxesConfig,
3406
- dailySalesTrendsConfig,
3452
+ dailySalesTrendsDayPartConfig,
3407
3453
  dailySalesTrendsOrderTypeConfig,
3408
3454
  Report,
3409
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",
@@ -2322,7 +2322,12 @@ var employeeTipConfig = {
2322
2322
  // src/reports/dailySales/dailySales.ts
2323
2323
  var FIELDS10 = {
2324
2324
  groupById: { type: "string" },
2325
- 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
+ },
2326
2331
  itemsQuantity: { type: "number", columnKey: "quantity" },
2327
2332
  salesAmountGross: { type: "money", columnKey: "grossSales" },
2328
2333
  discountsAmount: { type: "money", columnKey: "discountAmount" },
@@ -2478,11 +2483,12 @@ var dailySalesTaxesConfig = {
2478
2483
  sectionName: "common.report-section.taxes"
2479
2484
  };
2480
2485
 
2481
- // src/reports/dailySales/dailySalesTrends.ts
2486
+ // src/reports/dailySales/dailySalesTrendsDayPart.ts
2482
2487
  var FIELDS16 = {
2483
2488
  groupById: { type: "string" },
2484
2489
  groupByName: {
2485
2490
  type: "string",
2491
+ columnKey: "daypart",
2486
2492
  size: FIRST_COLUMN_WIDTH,
2487
2493
  footerCalculation: { type: "label", label: "common.report-section.trends-footer.total-sales" }
2488
2494
  },
@@ -2516,7 +2522,7 @@ var DAILY_SALES_TRENDS_AVAILABLE_COLUMNS = [
2516
2522
  "guestAvg",
2517
2523
  "salesAmountNet"
2518
2524
  ];
2519
- var dailySalesTrendsConfig = {
2525
+ var dailySalesTrendsDayPartConfig = {
2520
2526
  fields: FIELDS16,
2521
2527
  availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
2522
2528
  defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
@@ -2525,10 +2531,50 @@ var dailySalesTrendsConfig = {
2525
2531
  sectionName: "common.report-section.sales-by-day-part",
2526
2532
  extraFooterFields: ["salesAmountNet"]
2527
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
+ ];
2528
2574
  var dailySalesTrendsOrderTypeConfig = {
2529
- fields: FIELDS16,
2530
- availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
2531
- defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS,
2575
+ fields: FIELDS17,
2576
+ availableColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
2577
+ defaultVisibleColumns: DAILY_SALES_TRENDS_AVAILABLE_COLUMNS2,
2532
2578
  hasFooter: true,
2533
2579
  dataAccessKey: "trendsByOrderType",
2534
2580
  sectionName: "common.report-section.sales-by-order-type",
@@ -2543,7 +2589,7 @@ var DAILY_SALES_SECTION_CONFIGS = [
2543
2589
  dailySalesTaxesConfig,
2544
2590
  dailySalesRefundsVoidsConfig,
2545
2591
  dailySalesDiscountsConfig,
2546
- dailySalesTrendsConfig,
2592
+ dailySalesTrendsDayPartConfig,
2547
2593
  dailySalesTrendsOrderTypeConfig
2548
2594
  ];
2549
2595
  var REPORT_CONFIG_MAP = {
@@ -3544,7 +3590,7 @@ var ExportBuilder = class {
3544
3590
  const sectionParameters = { ...parameters, cols: void 0 };
3545
3591
  sections = rawConfig.map((config) => {
3546
3592
  return {
3547
- sheetName: this.getConfigSectionName(config),
3593
+ title: this.getConfigSectionName(config),
3548
3594
  ...this.renderTableContent(config, reportData, sectionParameters)
3549
3595
  };
3550
3596
  });
@@ -3552,7 +3598,7 @@ var ExportBuilder = class {
3552
3598
  const metadata = this.buildMetadata(parameters);
3553
3599
  sections = [
3554
3600
  {
3555
- sheetName: name,
3601
+ title: name,
3556
3602
  filters: metadata.map(([label, value]) => ({ label, value })),
3557
3603
  ...this.renderTableContent(rawConfig, reportData, parameters)
3558
3604
  }
@@ -1,11 +1,7 @@
1
- import { R as ReportType, A as AnalyticsField } from '../report-D_tOANVX.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-D_tOANVX.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-OJQZXKA5.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" },
@@ -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 = {
@@ -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" },
@@ -3431,11 +3477,11 @@ var enUS3 = {
3431
3477
  "common.report-col.type": "Type",
3432
3478
  "common.report-col.type.short": "Type",
3433
3479
  "common.report-col.type.info": " ",
3434
- "common.report-section.revenue-class": "Revenue Class",
3480
+ "common.report-section.revenue-class": "Sales by Revenue Class",
3435
3481
  "common.report-section.payments": "Payments",
3436
3482
  "common.report-section.cash": "Expected Closeout Cash",
3437
3483
  "common.report-section.taxes": "Taxes",
3438
- "common.report-section.refunds-voids": "Refunds & Voids",
3484
+ "common.report-section.refunds-voids": "Refunds/Voids",
3439
3485
  "common.report-section.discounts": "Discounts",
3440
3486
  "common.report-section.sales-by-day-part": "Sales by Day Part",
3441
3487
  "common.report-section.sales-by-order-type": "Sales by Order Type",
@@ -3664,7 +3710,7 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
3664
3710
  dailySalesPaymentsConfig,
3665
3711
  dailySalesRefundsVoidsConfig,
3666
3712
  dailySalesTaxesConfig,
3667
- dailySalesTrendsConfig,
3713
+ dailySalesTrendsDayPartConfig,
3668
3714
  dailySalesTrendsOrderTypeConfig,
3669
3715
  employeeTimecardConfig,
3670
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-D_tOANVX.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-D_tOANVX.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
 
@@ -205,7 +205,7 @@ declare const salesByItemDetailConfig: {
205
205
  };
206
206
 
207
207
  type DailySalesTrendsField = 'groupById' | 'groupByName' | 'salesAmountNet' | 'ticketsCount' | 'guestsCount' | 'ticketAvg' | 'guestAvg';
208
- declare const dailySalesTrendsConfig: {
208
+ declare const dailySalesTrendsDayPartConfig: {
209
209
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
210
210
  readonly availableColumns: DailySalesTrendsField[];
211
211
  readonly defaultVisibleColumns: DailySalesTrendsField[];
@@ -214,6 +214,7 @@ declare const dailySalesTrendsConfig: {
214
214
  readonly sectionName: "common.report-section.sales-by-day-part";
215
215
  readonly extraFooterFields: ["salesAmountNet"];
216
216
  };
217
+
217
218
  declare const dailySalesTrendsOrderTypeConfig: {
218
219
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
219
220
  readonly availableColumns: DailySalesTrendsField[];
@@ -310,4 +311,4 @@ declare const getReportFormattingLocaleOptions: (locations: {
310
311
  }[]) => LocaleOption[];
311
312
  declare const formatFieldValue: (value: unknown, type: FieldType, localeOptions: LocaleOption, fullRecord: Record<string, unknown> | null | undefined, fieldConfig?: ColumnPresentationConfig) => string;
312
313
 
313
- 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-D_tOANVX.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-D_tOANVX.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
 
@@ -205,7 +205,7 @@ declare const salesByItemDetailConfig: {
205
205
  };
206
206
 
207
207
  type DailySalesTrendsField = 'groupById' | 'groupByName' | 'salesAmountNet' | 'ticketsCount' | 'guestsCount' | 'ticketAvg' | 'guestAvg';
208
- declare const dailySalesTrendsConfig: {
208
+ declare const dailySalesTrendsDayPartConfig: {
209
209
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
210
210
  readonly availableColumns: DailySalesTrendsField[];
211
211
  readonly defaultVisibleColumns: DailySalesTrendsField[];
@@ -214,6 +214,7 @@ declare const dailySalesTrendsConfig: {
214
214
  readonly sectionName: "common.report-section.sales-by-day-part";
215
215
  readonly extraFooterFields: ["salesAmountNet"];
216
216
  };
217
+
217
218
  declare const dailySalesTrendsOrderTypeConfig: {
218
219
  readonly fields: Record<DailySalesTrendsField, ColumnPresentationConfig<DailySalesTrendsField>>;
219
220
  readonly availableColumns: DailySalesTrendsField[];
@@ -310,4 +311,4 @@ declare const getReportFormattingLocaleOptions: (locations: {
310
311
  }[]) => LocaleOption[];
311
312
  declare const formatFieldValue: (value: unknown, type: FieldType, localeOptions: LocaleOption, fullRecord: Record<string, unknown> | null | undefined, fieldConfig?: ColumnPresentationConfig) => string;
312
313
 
313
- 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-OJQZXKA5.js";
40
+ } from "./chunk-FUBK4VLH.js";
41
41
 
42
42
  // src/utils/alignment.ts
43
43
  function getColumnAlignment(type) {
@@ -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" },
@@ -243,7 +243,7 @@ export {
243
243
  dailySalesPaymentsConfig,
244
244
  dailySalesRefundsVoidsConfig,
245
245
  dailySalesTaxesConfig,
246
- dailySalesTrendsConfig,
246
+ dailySalesTrendsDayPartConfig,
247
247
  dailySalesTrendsOrderTypeConfig,
248
248
  employeeTimecardConfig,
249
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";
@@ -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";
@@ -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.27.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",