@harbortouch/skytab-analytics-report-utils 0.7.1 → 0.8.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.
@@ -19,6 +19,10 @@ export interface FormatMoneyOptions {
19
19
  currency?: string;
20
20
  decimals?: number;
21
21
  }
22
+ export interface FormatNumberOptions {
23
+ locale?: string;
24
+ decimals?: number;
25
+ }
22
26
  export declare const formatDate: (date: Date, options?: FormatDateOptions) => string;
23
27
  export declare const formatTime: (date: Date | string | number, options: FormatTimeOptions) => string;
24
28
  export declare const formatMoney: (amount: number, options?: FormatMoneyOptions) => string;
@@ -28,7 +32,7 @@ export declare const formatFixedNumber: (value: number, decimals?: number) => st
28
32
  export declare const formatString: (value: unknown) => string;
29
33
  export declare const getNumberToFormat: (value: unknown) => number;
30
34
  export declare const getDateToFormat: (value?: unknown) => Date | null;
31
- export declare const formatMoneyWithoutSymbol: (amount: number, options?: FormatMoneyOptions) => string;
35
+ export declare const formatMoneyWithoutSymbol: (amount: number, options?: FormatNumberOptions) => string;
32
36
  export declare const getReportFormattingLocaleOptions: (locations: {
33
37
  currency: string;
34
38
  countryCode: string;
package/dist/index.cjs CHANGED
@@ -819,7 +819,9 @@ var Report = {
819
819
  ITEM_TAX: "item-tax",
820
820
  EMPLOYEE_TIMECARD: "employee-timecard",
821
821
  EMPLOYEE_TIP: "employee-tip",
822
- SALES_BY_ITEM: "sales-by-item"
822
+ SALES_BY_ITEM: "sales-by-item",
823
+ DAILY_SALES: "daily-sales",
824
+ DAILY_SALES_LIVE: "daily-sales-live"
823
825
  };
824
826
  var REPORT_CONFIG_MAP = {
825
827
  "sales-summary": salesSummaryConfig,
@@ -830,7 +832,9 @@ var REPORT_CONFIG_MAP = {
830
832
  "item-tax": itemTaxConfig,
831
833
  "employee-timecard": employeeTimecardConfig,
832
834
  "employee-tip": null,
833
- "sales-by-item": salesByItemDetailConfig
835
+ "sales-by-item": salesByItemDetailConfig,
836
+ "daily-sales": dailySalesConfig,
837
+ "daily-sales-live": null
834
838
  };
835
839
  var getReportConfig = (reportType) => REPORT_CONFIG_MAP[reportType];
836
840
 
@@ -1521,8 +1525,12 @@ function calculateReportTotals(data, fieldConfig, opts) {
1521
1525
  }
1522
1526
  } else {
1523
1527
  derivedFields.push({ field, calc });
1524
- if (calc.numeratorField) fieldsToSum.add(calc.numeratorField);
1525
- if (calc.denominatorField) fieldsToSum.add(calc.denominatorField);
1528
+ if (calc.numeratorField) {
1529
+ fieldsToSum.add(calc.numeratorField);
1530
+ }
1531
+ if (calc.denominatorField) {
1532
+ fieldsToSum.add(calc.denominatorField);
1533
+ }
1526
1534
  }
1527
1535
  }
1528
1536
  const sums = {};
@@ -1601,48 +1609,75 @@ var dailySalesTaxesConfig = {
1601
1609
  };
1602
1610
 
1603
1611
  // src/formatting.ts
1612
+ var dateFormatterCache = /* @__PURE__ */ new Map();
1613
+ var timeFormatterCache = /* @__PURE__ */ new Map();
1614
+ var moneyFormatterCache = /* @__PURE__ */ new Map();
1615
+ var numberFormatterCache = /* @__PURE__ */ new Map();
1616
+ var getDateFormatter = (locale, timeZone) => {
1617
+ const key = `${locale}-${timeZone}`;
1618
+ let fmt = dateFormatterCache.get(key);
1619
+ if (!fmt) {
1620
+ fmt = new Intl.DateTimeFormat(locale, { dateStyle: "short", timeZone });
1621
+ dateFormatterCache.set(key, fmt);
1622
+ }
1623
+ return fmt;
1624
+ };
1625
+ var getTimeFormatter = (locale, timeZone, format) => {
1626
+ const key = `${locale}-${timeZone}-${format}`;
1627
+ let fmt = timeFormatterCache.get(key);
1628
+ if (!fmt) {
1629
+ if (format === "00:00") {
1630
+ fmt = new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", timeZone });
1631
+ } else if (format === "00:00-24H") {
1632
+ fmt = new Intl.DateTimeFormat(locale, {
1633
+ hour: "2-digit",
1634
+ minute: "2-digit",
1635
+ hour12: false,
1636
+ hourCycle: "h23",
1637
+ timeZone
1638
+ });
1639
+ } else {
1640
+ fmt = new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", second: "2-digit", timeZone });
1641
+ }
1642
+ timeFormatterCache.set(key, fmt);
1643
+ }
1644
+ return fmt;
1645
+ };
1646
+ var getMoneyFormatter = (locale, currency, decimals) => {
1647
+ const key = `${locale}-${currency}-${decimals}`;
1648
+ let fmt = moneyFormatterCache.get(key);
1649
+ if (!fmt) {
1650
+ fmt = new Intl.NumberFormat(locale, {
1651
+ style: "currency",
1652
+ currency,
1653
+ minimumFractionDigits: decimals,
1654
+ maximumFractionDigits: decimals
1655
+ });
1656
+ moneyFormatterCache.set(key, fmt);
1657
+ }
1658
+ return fmt;
1659
+ };
1660
+ var getNumberFormatter = (locale, decimals) => {
1661
+ const key = `${locale}-${decimals}`;
1662
+ let fmt = numberFormatterCache.get(key);
1663
+ if (!fmt) {
1664
+ fmt = new Intl.NumberFormat(locale, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
1665
+ numberFormatterCache.set(key, fmt);
1666
+ }
1667
+ return fmt;
1668
+ };
1604
1669
  var formatDate = (date, options = {}) => {
1605
1670
  const { locale = "en-US", timeZone = "UTC" } = options;
1606
- const d = new Date(date);
1607
- return new Intl.DateTimeFormat(locale, {
1608
- dateStyle: "short",
1609
- timeZone
1610
- }).format(d);
1671
+ return getDateFormatter(locale, timeZone).format(date);
1611
1672
  };
1612
1673
  var formatTime = (date, options) => {
1613
1674
  const { locale = "en-US", timeZone = "UTC", format } = options;
1614
1675
  const d = new Date(date);
1615
- if (format === "00:00") {
1616
- return new Intl.DateTimeFormat(locale, {
1617
- hour: "2-digit",
1618
- minute: "2-digit",
1619
- timeZone
1620
- }).format(d);
1621
- }
1622
- if (format === "00:00-24H") {
1623
- return new Intl.DateTimeFormat(locale, {
1624
- hour: "2-digit",
1625
- minute: "2-digit",
1626
- hour12: false,
1627
- hourCycle: "h23",
1628
- timeZone
1629
- }).format(d);
1630
- }
1631
- return new Intl.DateTimeFormat(locale, {
1632
- hour: "2-digit",
1633
- minute: "2-digit",
1634
- second: "2-digit",
1635
- timeZone
1636
- }).format(d);
1676
+ return getTimeFormatter(locale, timeZone, format).format(d);
1637
1677
  };
1638
1678
  var formatMoney = (amount, options = {}) => {
1639
1679
  const { locale = "en-US", currency = "USD", decimals = 2 } = options;
1640
- return new Intl.NumberFormat(locale, {
1641
- style: "currency",
1642
- currency,
1643
- minimumFractionDigits: decimals,
1644
- maximumFractionDigits: decimals
1645
- }).format(amount);
1680
+ return getMoneyFormatter(locale, currency, decimals).format(amount);
1646
1681
  };
1647
1682
  var formatPercent = (value, decimals = 2) => `${value.toFixed(decimals)}%`;
1648
1683
  var formatInteger = (value) => Math.round(value).toString();
@@ -1663,10 +1698,7 @@ var getDateToFormat = (value) => {
1663
1698
  };
1664
1699
  var formatMoneyWithoutSymbol = (amount, options = {}) => {
1665
1700
  const { locale = "en-US", decimals = 2 } = options;
1666
- return new Intl.NumberFormat(locale, {
1667
- minimumFractionDigits: decimals,
1668
- maximumFractionDigits: decimals
1669
- }).format(amount);
1701
+ return getNumberFormatter(locale, decimals).format(amount);
1670
1702
  };
1671
1703
  var getReportFormattingLocaleOptions = (locations) => {
1672
1704
  if (locations.length === 0) {
package/dist/index.d.ts CHANGED
@@ -17,5 +17,5 @@ export { dailySalesRefundsVoidsConfig, DAILY_SALES_REFUNDS_VOIDS_AVAILABLE_COLUM
17
17
  export { dailySalesTaxesConfig, DAILY_SALES_TAXES_AVAILABLE_COLUMNS, DAILY_SALES_TAXES_DEFAULT_VISIBLE_COLUMNS, } from './reports/dailySalesTaxes';
18
18
  export { employeeTimecardConfig, EMPLOYEE_TIMECARD_AVAILABLE_COLUMNS, EMPLOYEE_TIMECARD_DEFAULT_VISIBLE_COLUMNS, } from './reports/employeeTimecard';
19
19
  export { salesByItemDetailConfig, SALES_BY_ITEM_DETAIL_AVAILABLE_COLUMNS, SALES_BY_ITEM_DETAIL_DEFAULT_VISIBLE_COLUMNS, } from './reports/salesByItemDetail';
20
- export type { FormatDateOptions, FormatTimeOptions, FormatMoneyOptions, LocaleOption, TimeFormat } from './formatting';
20
+ export type { FormatNumberOptions, FormatDateOptions, FormatTimeOptions, FormatMoneyOptions, LocaleOption, TimeFormat, } from './formatting';
21
21
  export { formatDate, formatTime, formatMoney, formatPercent, formatInteger, formatFixedNumber, formatString, getNumberToFormat, getDateToFormat, getReportFormattingLocaleOptions, formatMoneyWithoutSymbol, formatFieldValue, } from './formatting';
package/dist/index.js CHANGED
@@ -731,7 +731,9 @@ var Report = {
731
731
  ITEM_TAX: "item-tax",
732
732
  EMPLOYEE_TIMECARD: "employee-timecard",
733
733
  EMPLOYEE_TIP: "employee-tip",
734
- SALES_BY_ITEM: "sales-by-item"
734
+ SALES_BY_ITEM: "sales-by-item",
735
+ DAILY_SALES: "daily-sales",
736
+ DAILY_SALES_LIVE: "daily-sales-live"
735
737
  };
736
738
  var REPORT_CONFIG_MAP = {
737
739
  "sales-summary": salesSummaryConfig,
@@ -742,7 +744,9 @@ var REPORT_CONFIG_MAP = {
742
744
  "item-tax": itemTaxConfig,
743
745
  "employee-timecard": employeeTimecardConfig,
744
746
  "employee-tip": null,
745
- "sales-by-item": salesByItemDetailConfig
747
+ "sales-by-item": salesByItemDetailConfig,
748
+ "daily-sales": dailySalesConfig,
749
+ "daily-sales-live": null
746
750
  };
747
751
  var getReportConfig = (reportType) => REPORT_CONFIG_MAP[reportType];
748
752
 
@@ -1433,8 +1437,12 @@ function calculateReportTotals(data, fieldConfig, opts) {
1433
1437
  }
1434
1438
  } else {
1435
1439
  derivedFields.push({ field, calc });
1436
- if (calc.numeratorField) fieldsToSum.add(calc.numeratorField);
1437
- if (calc.denominatorField) fieldsToSum.add(calc.denominatorField);
1440
+ if (calc.numeratorField) {
1441
+ fieldsToSum.add(calc.numeratorField);
1442
+ }
1443
+ if (calc.denominatorField) {
1444
+ fieldsToSum.add(calc.denominatorField);
1445
+ }
1438
1446
  }
1439
1447
  }
1440
1448
  const sums = {};
@@ -1513,48 +1521,75 @@ var dailySalesTaxesConfig = {
1513
1521
  };
1514
1522
 
1515
1523
  // src/formatting.ts
1524
+ var dateFormatterCache = /* @__PURE__ */ new Map();
1525
+ var timeFormatterCache = /* @__PURE__ */ new Map();
1526
+ var moneyFormatterCache = /* @__PURE__ */ new Map();
1527
+ var numberFormatterCache = /* @__PURE__ */ new Map();
1528
+ var getDateFormatter = (locale, timeZone) => {
1529
+ const key = `${locale}-${timeZone}`;
1530
+ let fmt = dateFormatterCache.get(key);
1531
+ if (!fmt) {
1532
+ fmt = new Intl.DateTimeFormat(locale, { dateStyle: "short", timeZone });
1533
+ dateFormatterCache.set(key, fmt);
1534
+ }
1535
+ return fmt;
1536
+ };
1537
+ var getTimeFormatter = (locale, timeZone, format) => {
1538
+ const key = `${locale}-${timeZone}-${format}`;
1539
+ let fmt = timeFormatterCache.get(key);
1540
+ if (!fmt) {
1541
+ if (format === "00:00") {
1542
+ fmt = new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", timeZone });
1543
+ } else if (format === "00:00-24H") {
1544
+ fmt = new Intl.DateTimeFormat(locale, {
1545
+ hour: "2-digit",
1546
+ minute: "2-digit",
1547
+ hour12: false,
1548
+ hourCycle: "h23",
1549
+ timeZone
1550
+ });
1551
+ } else {
1552
+ fmt = new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", second: "2-digit", timeZone });
1553
+ }
1554
+ timeFormatterCache.set(key, fmt);
1555
+ }
1556
+ return fmt;
1557
+ };
1558
+ var getMoneyFormatter = (locale, currency, decimals) => {
1559
+ const key = `${locale}-${currency}-${decimals}`;
1560
+ let fmt = moneyFormatterCache.get(key);
1561
+ if (!fmt) {
1562
+ fmt = new Intl.NumberFormat(locale, {
1563
+ style: "currency",
1564
+ currency,
1565
+ minimumFractionDigits: decimals,
1566
+ maximumFractionDigits: decimals
1567
+ });
1568
+ moneyFormatterCache.set(key, fmt);
1569
+ }
1570
+ return fmt;
1571
+ };
1572
+ var getNumberFormatter = (locale, decimals) => {
1573
+ const key = `${locale}-${decimals}`;
1574
+ let fmt = numberFormatterCache.get(key);
1575
+ if (!fmt) {
1576
+ fmt = new Intl.NumberFormat(locale, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
1577
+ numberFormatterCache.set(key, fmt);
1578
+ }
1579
+ return fmt;
1580
+ };
1516
1581
  var formatDate = (date, options = {}) => {
1517
1582
  const { locale = "en-US", timeZone = "UTC" } = options;
1518
- const d = new Date(date);
1519
- return new Intl.DateTimeFormat(locale, {
1520
- dateStyle: "short",
1521
- timeZone
1522
- }).format(d);
1583
+ return getDateFormatter(locale, timeZone).format(date);
1523
1584
  };
1524
1585
  var formatTime = (date, options) => {
1525
1586
  const { locale = "en-US", timeZone = "UTC", format } = options;
1526
1587
  const d = new Date(date);
1527
- if (format === "00:00") {
1528
- return new Intl.DateTimeFormat(locale, {
1529
- hour: "2-digit",
1530
- minute: "2-digit",
1531
- timeZone
1532
- }).format(d);
1533
- }
1534
- if (format === "00:00-24H") {
1535
- return new Intl.DateTimeFormat(locale, {
1536
- hour: "2-digit",
1537
- minute: "2-digit",
1538
- hour12: false,
1539
- hourCycle: "h23",
1540
- timeZone
1541
- }).format(d);
1542
- }
1543
- return new Intl.DateTimeFormat(locale, {
1544
- hour: "2-digit",
1545
- minute: "2-digit",
1546
- second: "2-digit",
1547
- timeZone
1548
- }).format(d);
1588
+ return getTimeFormatter(locale, timeZone, format).format(d);
1549
1589
  };
1550
1590
  var formatMoney = (amount, options = {}) => {
1551
1591
  const { locale = "en-US", currency = "USD", decimals = 2 } = options;
1552
- return new Intl.NumberFormat(locale, {
1553
- style: "currency",
1554
- currency,
1555
- minimumFractionDigits: decimals,
1556
- maximumFractionDigits: decimals
1557
- }).format(amount);
1592
+ return getMoneyFormatter(locale, currency, decimals).format(amount);
1558
1593
  };
1559
1594
  var formatPercent = (value, decimals = 2) => `${value.toFixed(decimals)}%`;
1560
1595
  var formatInteger = (value) => Math.round(value).toString();
@@ -1575,10 +1610,7 @@ var getDateToFormat = (value) => {
1575
1610
  };
1576
1611
  var formatMoneyWithoutSymbol = (amount, options = {}) => {
1577
1612
  const { locale = "en-US", decimals = 2 } = options;
1578
- return new Intl.NumberFormat(locale, {
1579
- minimumFractionDigits: decimals,
1580
- maximumFractionDigits: decimals
1581
- }).format(amount);
1613
+ return getNumberFormatter(locale, decimals).format(amount);
1582
1614
  };
1583
1615
  var getReportFormattingLocaleOptions = (locations) => {
1584
1616
  if (locations.length === 0) {
package/dist/report.d.ts CHANGED
@@ -9,6 +9,8 @@ export declare const Report: {
9
9
  readonly EMPLOYEE_TIMECARD: "employee-timecard";
10
10
  readonly EMPLOYEE_TIP: "employee-tip";
11
11
  readonly SALES_BY_ITEM: "sales-by-item";
12
+ readonly DAILY_SALES: "daily-sales";
13
+ readonly DAILY_SALES_LIVE: "daily-sales-live";
12
14
  };
13
15
  export type ReportType = (typeof Report)[keyof typeof Report];
14
16
  export declare const getReportConfig: (reportType: ReportType) => ReportConfig<string> | null;
@@ -1,4 +1,6 @@
1
1
  import { type ReportConfig } from '../types';
2
- export declare const EMPLOYEE_TIMECARD_AVAILABLE_COLUMNS: string[];
3
- export declare const EMPLOYEE_TIMECARD_DEFAULT_VISIBLE_COLUMNS: string[];
4
- export declare const employeeTimecardConfig: ReportConfig;
2
+ type EmployeeTimecardField = 'locationId' | 'locationName' | 'businessDate' | 'employeeName' | 'isActive' | 'lookup' | 'payrollCode' | 'jobName' | 'isBreak' | 'startTime' | 'endTime' | 'shiftHours';
3
+ export declare const EMPLOYEE_TIMECARD_AVAILABLE_COLUMNS: EmployeeTimecardField[];
4
+ export declare const EMPLOYEE_TIMECARD_DEFAULT_VISIBLE_COLUMNS: EmployeeTimecardField[];
5
+ export declare const employeeTimecardConfig: ReportConfig<EmployeeTimecardField>;
6
+ export {};
package/dist/types.d.ts CHANGED
@@ -2,18 +2,18 @@ import { type ReportColumnKey } from './columns';
2
2
  export type FieldType = 'string' | 'money' | 'percent' | 'number' | 'fixedNumber' | 'date' | 'time' | 'boolean';
3
3
  export type ColumnAlignment = 'left' | 'right';
4
4
  export type FooterCalculationType = 'sum' | 'percentChange' | 'average' | 'none';
5
- export interface FooterCalculation {
5
+ export interface FooterCalculation<TField = string> {
6
6
  type: FooterCalculationType;
7
- numeratorField?: string;
8
- denominatorField?: string;
7
+ numeratorField?: TField;
8
+ denominatorField?: TField;
9
9
  }
10
- export interface ColumnPresentationConfig {
10
+ export interface ColumnPresentationConfig<TField = string> {
11
11
  columnKey?: ReportColumnKey;
12
- type?: FieldType;
12
+ type: FieldType;
13
13
  size?: number;
14
14
  enableSorting?: boolean;
15
15
  filteringAvailable?: boolean;
16
- footerCalculation?: FooterCalculation;
16
+ footerCalculation?: FooterCalculation<TField>;
17
17
  }
18
18
  export interface ColumnGroupConfig {
19
19
  id: string;
@@ -23,7 +23,7 @@ export interface ColumnGroupConfig {
23
23
  lastYearFields?: string[];
24
24
  }
25
25
  export interface ReportConfig<TField extends string = string> {
26
- fields: Record<TField, ColumnPresentationConfig>;
26
+ fields: Record<TField, ColumnPresentationConfig<TField>>;
27
27
  availableColumns: TField[];
28
28
  defaultVisibleColumns: TField[];
29
29
  columnGroups?: ColumnGroupConfig[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harbortouch/skytab-analytics-report-utils",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Centralized report column presentation configuration for SkyTab Analytics",
5
5
  "engines": {
6
6
  "node": ">=22.6.0",