@aglyn/plugins-commerce 1.0.0-beta.218 → 1.0.0-beta.220

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.
Files changed (148) hide show
  1. package/README.md +6 -0
  2. package/package.json +14 -14
  3. package/src/index.d.ts +1 -0
  4. package/src/index.js +1 -19
  5. package/src/index.js.map +1 -1
  6. package/src/lib/components/cart.js +2 -1
  7. package/src/lib/components/cart.js.map +1 -1
  8. package/src/lib/components/console/catalog-organization-card.component.js +665 -459
  9. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
  10. package/src/lib/components/console/host-orders-card.component.js +2 -1
  11. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  12. package/src/lib/components/console/member-posts-card.component.js +1 -1
  13. package/src/lib/components/console/member-posts-card.component.js.map +1 -1
  14. package/src/lib/components/console/order-detail-dialog.component.js +8 -7
  15. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  16. package/src/lib/components/console/payments-settings-card.component.js +2 -2
  17. package/src/lib/components/console/payments-settings-card.component.js.map +1 -1
  18. package/src/lib/components/console/product-editor-dialog.component.js +1221 -889
  19. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  20. package/src/lib/components/console/product-zones.d.ts +184 -0
  21. package/src/lib/components/console/product-zones.js +54 -0
  22. package/src/lib/components/console/product-zones.js.map +1 -0
  23. package/src/lib/components/console/products-hub-card.component.js +3 -2
  24. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  25. package/src/lib/components/console/products-hub-zone.component.d.ts +1 -1
  26. package/src/lib/components/console/products-hub-zone.component.js +2 -1
  27. package/src/lib/components/console/products-hub-zone.component.js.map +1 -1
  28. package/src/lib/components/console/site-member-purchases.component.d.ts +24 -0
  29. package/src/lib/components/console/site-member-purchases.component.js +339 -0
  30. package/src/lib/components/console/site-member-purchases.component.js.map +1 -0
  31. package/src/lib/components/console/store-settings-card.component.js +2 -2
  32. package/src/lib/components/console/store-settings-card.component.js.map +1 -1
  33. package/src/lib/components/console/storefront-tax-summary-card.component.js +1 -1
  34. package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -1
  35. package/src/lib/components/member-signup.js +2 -2
  36. package/src/lib/components/member-signup.js.map +1 -1
  37. package/src/lib/components/newsletter-signup.js +2 -2
  38. package/src/lib/components/newsletter-signup.js.map +1 -1
  39. package/src/lib/components/product-detail.js +2 -1
  40. package/src/lib/components/product-detail.js.map +1 -1
  41. package/src/lib/components/product-grid.js +1 -1
  42. package/src/lib/components/product-grid.js.map +1 -1
  43. package/src/lib/constants/operator-alerts.js +5 -3
  44. package/src/lib/constants/operator-alerts.js.map +1 -1
  45. package/src/lib/constants/storefront-payments.d.ts +33 -0
  46. package/src/lib/constants/storefront-payments.js +35 -0
  47. package/src/lib/constants/storefront-payments.js.map +1 -0
  48. package/src/lib/declarations.server.d.ts +3 -1
  49. package/src/lib/declarations.server.js +19 -1
  50. package/src/lib/declarations.server.js.map +1 -1
  51. package/src/lib/model/commerce-io.js +1 -1
  52. package/src/lib/model/commerce-io.js.map +1 -1
  53. package/src/lib/model/commerce-record-lists.d.ts +31 -0
  54. package/src/lib/model/commerce-record-lists.js +45 -0
  55. package/src/lib/model/commerce-record-lists.js.map +1 -0
  56. package/src/lib/model/commerce-record-routes.d.ts +45 -0
  57. package/src/lib/model/commerce-record-routes.js +72 -0
  58. package/src/lib/model/commerce-record-routes.js.map +1 -0
  59. package/src/lib/model/commerce-search-sources.d.ts +21 -0
  60. package/src/lib/model/commerce-search-sources.js +42 -0
  61. package/src/lib/model/commerce-search-sources.js.map +1 -0
  62. package/src/lib/model/commerce-topics.d.ts +20 -0
  63. package/src/lib/model/commerce-topics.js +33 -0
  64. package/src/lib/model/commerce-topics.js.map +1 -0
  65. package/src/lib/model/index.d.ts +1 -0
  66. package/src/lib/model/index.js +1 -0
  67. package/src/lib/model/index.js.map +1 -1
  68. package/src/lib/model/product-record.d.ts +32 -0
  69. package/src/lib/model/product-record.js +82 -0
  70. package/src/lib/model/product-record.js.map +1 -0
  71. package/src/lib/model/site-member-purchases.d.ts +48 -0
  72. package/src/lib/model/site-member-purchases.js +50 -0
  73. package/src/lib/model/site-member-purchases.js.map +1 -0
  74. package/src/lib/model/storefront-tax-summary.d.ts +121 -0
  75. package/src/lib/model/storefront-tax-summary.js +148 -0
  76. package/src/lib/model/storefront-tax-summary.js.map +1 -0
  77. package/src/lib/plan-entitlements.d.ts +35 -0
  78. package/src/lib/plan-entitlements.js +54 -0
  79. package/src/lib/plan-entitlements.js.map +1 -0
  80. package/src/lib/plugin.js +21 -0
  81. package/src/lib/plugin.js.map +1 -1
  82. package/src/lib/server/billing-webhook.js +387 -248
  83. package/src/lib/server/billing-webhook.js.map +1 -1
  84. package/src/lib/server/cart-checkout.js +3 -3
  85. package/src/lib/server/cart-checkout.js.map +1 -1
  86. package/src/lib/server/checkout.js +2 -2
  87. package/src/lib/server/checkout.js.map +1 -1
  88. package/src/lib/server/connect.js +5 -5
  89. package/src/lib/server/connect.js.map +1 -1
  90. package/src/lib/server/draft-order.js +2 -2
  91. package/src/lib/server/draft-order.js.map +1 -1
  92. package/src/lib/server/gift-cards.js +7 -3
  93. package/src/lib/server/gift-cards.js.map +1 -1
  94. package/src/lib/server/low-stock.js +3 -1
  95. package/src/lib/server/low-stock.js.map +1 -1
  96. package/src/lib/server/member-post.js +2 -2
  97. package/src/lib/server/member-post.js.map +1 -1
  98. package/src/lib/server/membership-admin-password.js +4 -1
  99. package/src/lib/server/membership-admin-password.js.map +1 -1
  100. package/src/lib/server/membership-content.js +1 -1
  101. package/src/lib/server/membership-content.js.map +1 -1
  102. package/src/lib/server/membership-register.js +13 -2
  103. package/src/lib/server/membership-register.js.map +1 -1
  104. package/src/lib/server/newsletter.js +32 -19
  105. package/src/lib/server/newsletter.js.map +1 -1
  106. package/src/lib/server/pos-order.js +3 -3
  107. package/src/lib/server/pos-order.js.map +1 -1
  108. package/src/lib/server/process-abandoned.js +4 -2
  109. package/src/lib/server/process-abandoned.js.map +1 -1
  110. package/src/lib/server/process-restock.js +7 -5
  111. package/src/lib/server/process-restock.js.map +1 -1
  112. package/src/lib/server/product-record-index.d.ts +19 -0
  113. package/src/lib/server/product-record-index.js +83 -0
  114. package/src/lib/server/product-record-index.js.map +1 -0
  115. package/src/lib/server/reconcile-stock.js +1 -1
  116. package/src/lib/server/reconcile-stock.js.map +1 -1
  117. package/src/lib/server/reserve-stock.js +6 -1
  118. package/src/lib/server/reserve-stock.js.map +1 -1
  119. package/src/lib/server/reserve.js +2 -2
  120. package/src/lib/server/reserve.js.map +1 -1
  121. package/src/lib/server/revenue-source.d.ts +130 -0
  122. package/src/lib/server/revenue-source.js +286 -0
  123. package/src/lib/server/revenue-source.js.map +1 -0
  124. package/src/lib/server/supplier-outbox.js +16 -1
  125. package/src/lib/server/supplier-outbox.js.map +1 -1
  126. package/src/lib/server/supplier-update.js +19 -9
  127. package/src/lib/server/supplier-update.js.map +1 -1
  128. package/src/lib/server/tax-profile.d.ts +8 -5
  129. package/src/lib/server/tax-profile.js +22 -5
  130. package/src/lib/server/tax-profile.js.map +1 -1
  131. package/src/lib/server/tax-return-source.d.ts +125 -0
  132. package/src/lib/server/tax-return-source.js +524 -0
  133. package/src/lib/server/tax-return-source.js.map +1 -0
  134. package/src/lib/server/tax-summary.d.ts +92 -0
  135. package/src/lib/server/tax-summary.js +258 -0
  136. package/src/lib/server/tax-summary.js.map +1 -0
  137. package/src/lib/server.d.ts +1 -0
  138. package/src/lib/server.js +23 -0
  139. package/src/lib/server.js.map +1 -1
  140. package/src/lib/starter-templates.d.ts +19 -0
  141. package/src/lib/starter-templates.js +157 -0
  142. package/src/lib/starter-templates.js.map +1 -0
  143. package/src/lib/tenant-emails.d.ts +33 -0
  144. package/src/lib/tenant-emails.js +551 -0
  145. package/src/lib/tenant-emails.js.map +1 -0
  146. package/src/lib/testing/stand-in-crm-record-routes.d.ts +25 -0
  147. package/src/lib/testing/stand-in-crm-record-routes.js +46 -0
  148. package/src/lib/testing/stand-in-crm-record-routes.js.map +1 -0
@@ -0,0 +1,524 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ /**
18
+ * Storefront sales on the operator's sales tax return (AGL-1904, AGL-3080).
19
+ *
20
+ * The operator's return sums its own invoices; this is the storefront's half
21
+ * of it, answered through the platform's tax return source contract
22
+ * (`@aglyn/aglyn/plugin-manager/plugin-tax-return-sources`). It reads
23
+ * `storefrontTaxCollected` — a SEPARATE collection from the operator's own
24
+ * invoices, queried and reported separately, because a storefront row's
25
+ * money is mostly the merchant's while an invoice row's is the operator's.
26
+ * Summing the two would put other companies' receipts into the return's
27
+ * total sales, which is why they never meet in one query and never share a
28
+ * figure.
29
+ *
30
+ * What it answers, all worded for the filing jurisdiction the platform
31
+ * resolved:
32
+ *
33
+ * - **The three liability buckets**, never summed — see
34
+ * `model/storefront-tax-summary.ts`.
35
+ * - **A blocking finding for the platform-liable tax** in the filing
36
+ * jurisdiction. Every storefront checkout is created on the platform's
37
+ * own account, so a `mode: 'stripe'` store's shopper is charged tax Stripe
38
+ * computes against the PLATFORM's registrations — measured, not inferred.
39
+ * That money is in the platform's balance and is NOT in the filing
40
+ * figures, which sum the operator's own sales only. Filing those without
41
+ * deciding what to do with this figure is exactly the shortfall an
42
+ * auditor finds. It states the mechanics and asks for a decision; it does
43
+ * NOT assert a marketplace-facilitator position — that attaches by
44
+ * operation of law and belongs to counsel, not to this report.
45
+ * - **Two lines beneath the filing figures** — the platform-liable tax and
46
+ * the merchant's own rate, stated side by side and never folded into a
47
+ * form item, because this report does not decide how storefront receipts
48
+ * are reported and adding them to one would be deciding it silently.
49
+ * - **Facilitated sales by buyer state** — the economic-nexus question
50
+ * (AGL-1956), with the three buckets SUMMED per jurisdiction on purpose:
51
+ * a threshold counts the sale whoever remits it. Who remits is still
52
+ * carried per row.
53
+ *
54
+ * Truncation and rows no period can reach are reported, and the platform
55
+ * raises each as a blocking finding of its own.
56
+ */ import { firebaseAdmin } from "@aglyn/tenant-data-admin";
57
+ import { PLATFORM_BRAND_NAME } from "@aglyn/aglyn/app-utils/platform-brand";
58
+ import { asRowDate, centsToDollars } from "@aglyn/aglyn/app-utils/tax-jurisdiction-figures";
59
+ import { storefrontTaxSummary } from "../model/storefront-tax-summary.js";
60
+ /**
61
+ * Storefront tax in the FILING jurisdiction that Stripe computed against the
62
+ * platform's own registrations.
63
+ *
64
+ * The one figure that decides whether a period can be filed from the filing
65
+ * lines alone. Deliberately excludes `merchantManual` — a merchant's own
66
+ * configured rate never touched those registrations. Read against the
67
+ * configured jurisdiction rather than Texas, because a hard-coded key answers
68
+ * `0.00` everywhere else — and a zero here reads as "nothing to decide" on
69
+ * the one finding that blocks filing.
70
+ */ export function storefrontPlatformLiableCents(summary, filing) {
71
+ var _ref;
72
+ var _summary_aglynLiable_byJurisdiction, _summary_aglynLiable;
73
+ const figures = summary == null ? void 0 : (_summary_aglynLiable = summary.aglynLiable) == null ? void 0 : (_summary_aglynLiable_byJurisdiction = _summary_aglynLiable.byJurisdiction) == null ? void 0 : _summary_aglynLiable_byJurisdiction[filing.code];
74
+ const cents = Number((_ref = figures == null ? void 0 : figures.taxCollectedCents) != null ? _ref : 0);
75
+ return Number.isFinite(cents) ? cents : 0;
76
+ }
77
+ /** The merchant's own configured tax in the filing jurisdiction. */ function merchantManualCents(summary, filing) {
78
+ var _ref;
79
+ var _summary_merchantManual_byJurisdiction_filing_code, _summary_merchantManual_byJurisdiction, _summary_merchantManual;
80
+ return Number((_ref = summary == null ? void 0 : (_summary_merchantManual = summary.merchantManual) == null ? void 0 : (_summary_merchantManual_byJurisdiction = _summary_merchantManual.byJurisdiction) == null ? void 0 : (_summary_merchantManual_byJurisdiction_filing_code = _summary_merchantManual_byJurisdiction[filing.code]) == null ? void 0 : _summary_merchantManual_byJurisdiction_filing_code.taxCollectedCents) != null ? _ref : 0);
81
+ }
82
+ /** The storefront's findings. The platform raises the non-zero ones. */ export function storefrontTaxFindings(summary, filing) {
83
+ var _ref, _ref1;
84
+ var _summary_attention, _summary_attention1;
85
+ const brand = PLATFORM_BRAND_NAME;
86
+ return [
87
+ {
88
+ // BLOCKING on purpose — see the module note.
89
+ id: 'storefrontAglynLiableTax',
90
+ severity: 'blocking',
91
+ count: storefrontPlatformLiableCents(summary, filing),
92
+ label: `${filing.label} storefront tax collected under ${brand}’s registration`,
93
+ detail: 'Cents. Charged to shoppers on merchants’ storefront sales, computed ' + 'by Stripe Tax against THE PLATFORM’s registrations (the session is ' + 'created on the platform account), and settled into the platform’s ' + `balance. It is NOT included in ${filing.figuresName} below. Decide ` + 'with counsel how it is reported before filing — do not file as if ' + 'it were zero.'
94
+ },
95
+ {
96
+ id: 'storefrontUnclassified',
97
+ severity: 'blocking',
98
+ count: Number((_ref = summary == null ? void 0 : (_summary_attention = summary.attention) == null ? void 0 : _summary_attention.rowsUnclassified) != null ? _ref : 0),
99
+ label: 'Storefront rows with an unrecognised tax mode',
100
+ detail: 'Not counted in any storefront bucket, so they are in no figure at ' + 'all. Classify them before filing.'
101
+ },
102
+ {
103
+ id: 'storefrontMissingTaxableBase',
104
+ severity: 'review',
105
+ count: Number((_ref1 = summary == null ? void 0 : (_summary_attention1 = summary.attention) == null ? void 0 : _summary_attention1.rowsMissingTaxableBase) != null ? _ref1 : 0),
106
+ label: 'Storefront rows with tax but no stated base',
107
+ detail: 'Tax was collected but Stripe’s taxable_amount could not be read, so ' + 'the storefront taxable-sales figure understates the base. Re-read ' + 'the session in Stripe with the tax breakdown expanded.'
108
+ }
109
+ ];
110
+ }
111
+ /**
112
+ * The two lines beneath the filing figures: the platform-liable tax and the
113
+ * merchant's own rate, separately, and outside every form item.
114
+ */ export function storefrontFilingLines(summary, filing) {
115
+ const brand = PLATFORM_BRAND_NAME;
116
+ const platformLiable = centsToDollars(storefrontPlatformLiableCents(summary, filing));
117
+ const merchant = centsToDollars(merchantManualCents(summary, filing));
118
+ if (filing.form === 'tx-webfile') {
119
+ return [
120
+ {
121
+ item: '—',
122
+ label: `${filing.label} storefront tax under ${brand}’s registration (NOT in ${filing.figuresName})`,
123
+ dollars: platformLiable,
124
+ note: `Collected from shoppers on merchants’ sales and held in ${brand}’s ` + 'balance. Excluded from every item above. Its treatment on the ' + 'return is a question for counsel — see AGL-1904.'
125
+ },
126
+ {
127
+ item: '—',
128
+ label: `${filing.label} storefront tax under the MERCHANT’s own rate (not ${brand}’s)`,
129
+ dollars: merchant,
130
+ note: `A manual-mode store’s own configured rate. ${brand}’s registrations ` + 'played no part in computing it. Shown so it is visibly NOT the line ' + 'above — the two must never be added together.'
131
+ }
132
+ ];
133
+ }
134
+ return [
135
+ {
136
+ item: '—',
137
+ label: `${filing.code} storefront tax under the platform’s registration (NOT in the figures above)`,
138
+ dollars: platformLiable,
139
+ note: 'Collected from shoppers on merchants’ sales and held in the ' + 'platform’s balance. Excluded from every figure above. Its treatment ' + 'on the return is a question for the operator’s own counsel.'
140
+ },
141
+ {
142
+ item: '—',
143
+ label: `${filing.code} storefront tax under the MERCHANT’s own rate`,
144
+ dollars: merchant,
145
+ note: 'A manual-mode store’s own configured rate. The platform’s ' + 'registrations played no part in computing it. Shown so it is ' + 'visibly NOT the line above — the two must never be added together.'
146
+ }
147
+ ];
148
+ }
149
+ /** The three liability buckets, in the order a reader decides them. */ export function storefrontBucketRows(summary) {
150
+ const brand = PLATFORM_BRAND_NAME;
151
+ const buckets = [
152
+ {
153
+ id: 'aglynLiable',
154
+ label: `Computed against ${brand}’s registrations`,
155
+ liability: `In ${brand}’s balance. Stripe Tax computed it on ${brand}’s platform account.`,
156
+ platformLiable: true
157
+ },
158
+ {
159
+ id: 'merchantManual',
160
+ label: 'Merchant’s own configured rate',
161
+ liability: `The merchant’s. It never touched an ${brand} registration and is not ${brand}’s to remit.`,
162
+ platformLiable: false
163
+ },
164
+ {
165
+ id: 'connectedAccountLiable',
166
+ label: 'Stripe Tax named the connected account liable',
167
+ liability: 'The connected account’s. Empty today.',
168
+ platformLiable: false
169
+ }
170
+ ];
171
+ return buckets.map((bucket)=>{
172
+ var _ref;
173
+ const figures = summary == null ? void 0 : summary[bucket.id];
174
+ return {
175
+ id: bucket.id,
176
+ label: bucket.label,
177
+ liability: bucket.liability,
178
+ transactionCount: Number((_ref = figures == null ? void 0 : figures.transactionCount) != null ? _ref : 0),
179
+ grossDollars: centsToDollars(figures == null ? void 0 : figures.grossCents),
180
+ taxableSalesDollars: centsToDollars(figures == null ? void 0 : figures.taxableSalesCents),
181
+ taxCollectedDollars: centsToDollars(figures == null ? void 0 : figures.taxCollectedCents),
182
+ platformLiable: bucket.platformLiable
183
+ };
184
+ });
185
+ }
186
+ /**
187
+ * FACILITATED SALES BY STATE — the economic-nexus question (AGL-1956).
188
+ *
189
+ * The question a state asks a marketplace facilitator is "how much did you
190
+ * facilitate INTO this state, and in how many transactions" — not "how much
191
+ * tax did you collect there". A state the operator is not registered in
192
+ * collects nothing by definition, which is exactly why collection cannot be
193
+ * the measure: the states worth watching are the ones showing $0 tax and a
194
+ * rising sales figure.
195
+ *
196
+ * So this SUMS the three liability buckets per jurisdiction. The rule that
197
+ * the operator's own invoices and storefront rows are never summed still
198
+ * holds — nothing here touches the operator's own sales; within the
199
+ * storefront collection the buckets differ only in WHO REMITS, and a nexus
200
+ * threshold counts the sale whoever remits it. Who remits is still carried
201
+ * per row, because "do we have nexus here" and "what do we owe here" are
202
+ * answered off the same rows and must not blur.
203
+ *
204
+ * ⚠️ A LOWER BOUND, deliberately rather than silently: `storefront-tax-record.ts`
205
+ * files no row at all for a sale whose `taxMode` resolves to `none`, so a
206
+ * wholly untaxed storefront sale is invisible here — the population nexus
207
+ * detection most needs. Closing it is a write-side change recorded on
208
+ * AGL-1956. The filing jurisdiction does not depend on any of this: a filer
209
+ * registered where it is established has no in-state threshold left to cross.
210
+ */ export function storefrontFacilitatedJurisdictionRows(summary, filing) {
211
+ if (!summary) return [];
212
+ const totals = new Map();
213
+ const buckets = [
214
+ [
215
+ 'aglynLiable',
216
+ true
217
+ ],
218
+ [
219
+ 'merchantManual',
220
+ false
221
+ ],
222
+ [
223
+ 'connectedAccountLiable',
224
+ false
225
+ ]
226
+ ];
227
+ for (const [id, platformLiable] of buckets){
228
+ var _ref;
229
+ var _summary_id;
230
+ const byJurisdiction = (_ref = (_summary_id = summary[id]) == null ? void 0 : _summary_id.byJurisdiction) != null ? _ref : {};
231
+ for (const [jurisdiction, figures] of Object.entries(byJurisdiction)){
232
+ var _totals_get, _ref1, _ref2, _ref3;
233
+ const entry = (_totals_get = totals.get(jurisdiction)) != null ? _totals_get : {
234
+ count: 0,
235
+ salesCents: 0,
236
+ taxCents: 0,
237
+ platformCents: 0
238
+ };
239
+ const taxCents = Number((_ref1 = figures == null ? void 0 : figures.taxCollectedCents) != null ? _ref1 : 0);
240
+ entry.count += Number((_ref2 = figures == null ? void 0 : figures.transactionCount) != null ? _ref2 : 0);
241
+ entry.salesCents += Number((_ref3 = figures == null ? void 0 : figures.totalSalesCents) != null ? _ref3 : 0);
242
+ entry.taxCents += taxCents;
243
+ if (platformLiable) entry.platformCents += taxCents;
244
+ totals.set(jurisdiction, entry);
245
+ }
246
+ }
247
+ return [
248
+ ...totals.entries()
249
+ ].map(([jurisdiction, entry])=>({
250
+ jurisdiction,
251
+ isFilingJurisdiction: jurisdiction === filing.code,
252
+ transactionCount: entry.count,
253
+ totalSalesDollars: centsToDollars(entry.salesCents),
254
+ taxCollectedDollars: centsToDollars(entry.taxCents),
255
+ platformLiableTaxDollars: centsToDollars(entry.platformCents),
256
+ untaxed: entry.taxCents === 0
257
+ })).sort((a, b)=>// The filing jurisdiction first — it is the one obligation that does
258
+ // not wait on a threshold — then by the figure a threshold is
259
+ // actually measured against.
260
+ Number(b.isFilingJurisdiction) - Number(a.isFilingJurisdiction) || Number(b.totalSalesDollars) - Number(a.totalSalesDollars) || a.jurisdiction.localeCompare(b.jurisdiction));
261
+ }
262
+ /** The storefront's two tables on the return's screen. */ function storefrontTables(summary, filing) {
263
+ const brand = PLATFORM_BRAND_NAME;
264
+ return [
265
+ {
266
+ // Split by who owes it, never summed — one "storefront tax" total would
267
+ // merge two facts into a number that is true of neither.
268
+ columns: [
269
+ {
270
+ label: 'Bucket'
271
+ },
272
+ {
273
+ label: 'Sales',
274
+ numeric: true
275
+ },
276
+ {
277
+ label: 'Gross',
278
+ numeric: true,
279
+ money: true
280
+ },
281
+ {
282
+ label: 'Taxable sales',
283
+ numeric: true,
284
+ money: true
285
+ },
286
+ {
287
+ label: 'Tax collected',
288
+ numeric: true,
289
+ money: true
290
+ }
291
+ ],
292
+ rows: storefrontBucketRows(summary).map((row)=>({
293
+ key: row.id,
294
+ cells: [
295
+ _extends({
296
+ text: row.label,
297
+ caption: row.liability
298
+ }, row.platformLiable ? {
299
+ tag: {
300
+ label: `${brand} holds this`,
301
+ tone: 'attention'
302
+ }
303
+ } : {}),
304
+ {
305
+ text: String(row.transactionCount)
306
+ },
307
+ {
308
+ text: `$${row.grossDollars}`
309
+ },
310
+ {
311
+ text: `$${row.taxableSalesDollars}`
312
+ },
313
+ {
314
+ text: `$${row.taxCollectedDollars}`,
315
+ strong: row.platformLiable
316
+ }
317
+ ]
318
+ })),
319
+ empty: 'This period’s response carries no storefront figures.'
320
+ },
321
+ {
322
+ heading: 'Facilitated sales by buyer state',
323
+ description: `What ${brand} facilitated into each state, whoever remits the ` + 'tax — the figure an economic-nexus threshold is measured ' + `against. ${filing.code} needs no threshold: the filer is ` + 'established there, so the obligation is unconditional. A ' + 'region showing sales and no tax is the one to watch.',
324
+ columns: [
325
+ {
326
+ label: 'Buyer state'
327
+ },
328
+ {
329
+ label: 'Sales',
330
+ numeric: true
331
+ },
332
+ {
333
+ label: 'Total sales',
334
+ numeric: true,
335
+ money: true
336
+ },
337
+ {
338
+ label: 'Tax collected',
339
+ numeric: true,
340
+ money: true
341
+ },
342
+ {
343
+ label: `Of which ${brand} owes`,
344
+ numeric: true,
345
+ money: true
346
+ }
347
+ ],
348
+ rows: storefrontFacilitatedJurisdictionRows(summary, filing).map((row)=>({
349
+ key: row.jurisdiction,
350
+ cells: [
351
+ _extends({
352
+ text: row.jurisdiction === 'unknown' ? 'Not stated' : row.jurisdiction
353
+ }, row.isFilingJurisdiction ? {
354
+ tag: {
355
+ label: 'Registered',
356
+ tone: 'attention'
357
+ }
358
+ } : row.untaxed ? {
359
+ tag: {
360
+ label: 'No tax collected',
361
+ tone: 'neutral'
362
+ }
363
+ } : {}),
364
+ {
365
+ text: String(row.transactionCount)
366
+ },
367
+ {
368
+ text: `$${row.totalSalesDollars}`
369
+ },
370
+ {
371
+ text: `$${row.taxCollectedDollars}`
372
+ },
373
+ {
374
+ text: `$${row.platformLiableTaxDollars}`,
375
+ strong: Number(row.platformLiableTaxDollars) > 0
376
+ }
377
+ ]
378
+ })),
379
+ empty: 'No storefront sales recorded in this period.',
380
+ footnote: 'A LOWER BOUND. A storefront sale that collected no tax at ' + 'all files no row, so it is missing here — which is exactly ' + 'the population a nexus check wants. Recorded on AGL-1956.'
381
+ }
382
+ ];
383
+ }
384
+ /**
385
+ * The storefront's blocks of the working-papers export: the nexus figures
386
+ * beside the operator's own sales by jurisdiction — a different taxpayer's
387
+ * money and never summed with them — and the liability buckets after the
388
+ * working papers.
389
+ */ function storefrontExports(summary, filing) {
390
+ const brand = PLATFORM_BRAND_NAME;
391
+ const facilitated = storefrontFacilitatedJurisdictionRows(summary, filing);
392
+ return [
393
+ {
394
+ placement: 'jurisdictions',
395
+ rows: [
396
+ [
397
+ 'Facilitated sales by buyer state (merchants’ storefronts)'
398
+ ],
399
+ [
400
+ 'Buyer state',
401
+ 'Sales',
402
+ 'Total sales (USD)',
403
+ 'Tax collected (USD)',
404
+ `Of which ${brand} owes (USD)`
405
+ ],
406
+ ...facilitated.length ? facilitated.map((row)=>[
407
+ row.jurisdiction,
408
+ String(row.transactionCount),
409
+ row.totalSalesDollars,
410
+ row.taxCollectedDollars,
411
+ row.platformLiableTaxDollars
412
+ ]) : [
413
+ [
414
+ '—',
415
+ '0',
416
+ '0.00',
417
+ '0.00',
418
+ '0.00'
419
+ ]
420
+ ],
421
+ [
422
+ 'LOWER BOUND — a storefront sale that collected no tax files no row, ' + `so it is absent here. ${filing.code} needs no threshold: the filer ` + 'is established there.'
423
+ ]
424
+ ]
425
+ },
426
+ {
427
+ placement: 'sections',
428
+ rows: [
429
+ [
430
+ 'Storefront commerce tax by liability (AGL-1904) — NOT in ' + (filing.form === 'tx-webfile' ? 'the Webfile figures' : 'the breakdown above')
431
+ ],
432
+ [
433
+ 'Bucket',
434
+ 'Who owes it',
435
+ 'Transactions',
436
+ 'Gross (USD)',
437
+ 'Taxable sales (USD)',
438
+ 'Tax collected (USD)'
439
+ ],
440
+ ...storefrontBucketRows(summary).map((row)=>[
441
+ row.label,
442
+ row.liability,
443
+ String(row.transactionCount),
444
+ row.grossDollars,
445
+ row.taxableSalesDollars,
446
+ row.taxCollectedDollars
447
+ ])
448
+ ]
449
+ }
450
+ ];
451
+ }
452
+ /** One storefront row as the working papers carry it. */ function projectRow(row) {
453
+ var _row_orgId, _ref, _row_grossCents, _row_taxCents;
454
+ var _asRowDate, _row_customerAddress, _row_customerAddress1;
455
+ return {
456
+ id: row.id,
457
+ hostId: typeof row.hostId === 'string' ? row.hostId : null,
458
+ orgId: (_row_orgId = row.orgId) != null ? _row_orgId : null,
459
+ paidAt: (_ref = (_asRowDate = asRowDate(row.paidAt)) == null ? void 0 : _asRowDate.toISOString()) != null ? _ref : null,
460
+ taxMode: typeof row.taxMode === 'string' ? row.taxMode : null,
461
+ taxLiability: typeof row.taxLiability === 'string' ? row.taxLiability : null,
462
+ grossCents: Number((_row_grossCents = row.grossCents) != null ? _row_grossCents : 0),
463
+ taxCents: Number((_row_taxCents = row.taxCents) != null ? _row_taxCents : 0),
464
+ taxableSalesCents: (Array.isArray(row.taxLines) ? row.taxLines : []).map((line)=>{
465
+ var _ref;
466
+ return Number((_ref = line == null ? void 0 : line.taxableAmountCents) != null ? _ref : 0);
467
+ }).reduce((sum, base)=>sum + (Number.isFinite(base) ? base : 0), 0),
468
+ state: typeof ((_row_customerAddress = row.customerAddress) == null ? void 0 : _row_customerAddress.state) === 'string' ? row.customerAddress.state : null,
469
+ country: typeof ((_row_customerAddress1 = row.customerAddress) == null ? void 0 : _row_customerAddress1.country) === 'string' ? row.customerAddress.country : null
470
+ };
471
+ }
472
+ /**
473
+ * The storefront's answer for one period, from rows already read. Pure, so
474
+ * the section a preparer reads can be proved from fixtures.
475
+ */ export function storefrontTaxReturnAnswer(read, request) {
476
+ const brand = PLATFORM_BRAND_NAME;
477
+ const { filing } = request;
478
+ const summary = storefrontTaxSummary(read.rows, request);
479
+ return {
480
+ id: 'storefront',
481
+ name: 'Storefront',
482
+ title: 'Storefront commerce tax — merchants’ sales',
483
+ help: 'Tax charged to shoppers on merchants’ storefronts, split by who owes it. None of it is in the filing figures above.',
484
+ intro: `None of this is in the ${filing.form === 'tx-webfile' ? 'Webfile' : 'breakdown'} figures above, which sum ` + `${brand}’s OWN sales only. The first row is the one that ` + `needs a decision: those sessions are created on ${brand}’s ` + `platform account, so Stripe computed that tax against ` + `${brand}’s registrations and it settled into ${brand}’s balance.`,
485
+ truncated: read.truncated,
486
+ undatedRows: read.undatedRows,
487
+ findings: storefrontTaxFindings(summary, filing),
488
+ filingLines: storefrontFilingLines(summary, filing),
489
+ tables: storefrontTables(summary, filing),
490
+ figures: [],
491
+ exports: storefrontExports(summary, filing),
492
+ summary,
493
+ rows: read.rows.map(projectRow)
494
+ };
495
+ }
496
+ /**
497
+ * The storefront's source, registered on the console's API surface: the
498
+ * staff return awaits that surface before it asks.
499
+ *
500
+ * Two queries, and the second is the honesty check: the period query ranges
501
+ * on `paidAt`, and a Firestore range query CANNOT match a document whose
502
+ * field is null — so a row that failed to date itself would be invisible to
503
+ * every period. The equality probe counts those rows, over all of them, and
504
+ * the platform blocks the return on any.
505
+ */ export const commerceTaxReturnSource = {
506
+ async read (request) {
507
+ var _undated_data_count;
508
+ const collection = firebaseAdmin.app().firestore().collection('storefrontTaxCollected');
509
+ const [inPeriod, undated] = await Promise.all([
510
+ collection.where('paidAt', '>=', request.start).where('paidAt', '<', request.end).limit(request.rowCap + 1).get(),
511
+ collection.where('paidAt', '==', null).count().get()
512
+ ]);
513
+ const rows = inPeriod.docs.slice(0, request.rowCap).map((doc)=>_extends({
514
+ id: doc.id
515
+ }, doc.data()));
516
+ return storefrontTaxReturnAnswer({
517
+ rows,
518
+ truncated: inPeriod.size > request.rowCap,
519
+ undatedRows: Number((_undated_data_count = undated.data().count) != null ? _undated_data_count : 0)
520
+ }, request);
521
+ }
522
+ };
523
+
524
+ //# sourceMappingURL=tax-return-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/tax-return-source.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Storefront sales on the operator's sales tax return (AGL-1904, AGL-3080).\n *\n * The operator's return sums its own invoices; this is the storefront's half\n * of it, answered through the platform's tax return source contract\n * (`@aglyn/aglyn/plugin-manager/plugin-tax-return-sources`). It reads\n * `storefrontTaxCollected` — a SEPARATE collection from the operator's own\n * invoices, queried and reported separately, because a storefront row's\n * money is mostly the merchant's while an invoice row's is the operator's.\n * Summing the two would put other companies' receipts into the return's\n * total sales, which is why they never meet in one query and never share a\n * figure.\n *\n * What it answers, all worded for the filing jurisdiction the platform\n * resolved:\n *\n * - **The three liability buckets**, never summed — see\n * `model/storefront-tax-summary.ts`.\n * - **A blocking finding for the platform-liable tax** in the filing\n * jurisdiction. Every storefront checkout is created on the platform's\n * own account, so a `mode: 'stripe'` store's shopper is charged tax Stripe\n * computes against the PLATFORM's registrations — measured, not inferred.\n * That money is in the platform's balance and is NOT in the filing\n * figures, which sum the operator's own sales only. Filing those without\n * deciding what to do with this figure is exactly the shortfall an\n * auditor finds. It states the mechanics and asks for a decision; it does\n * NOT assert a marketplace-facilitator position — that attaches by\n * operation of law and belongs to counsel, not to this report.\n * - **Two lines beneath the filing figures** — the platform-liable tax and\n * the merchant's own rate, stated side by side and never folded into a\n * form item, because this report does not decide how storefront receipts\n * are reported and adding them to one would be deciding it silently.\n * - **Facilitated sales by buyer state** — the economic-nexus question\n * (AGL-1956), with the three buckets SUMMED per jurisdiction on purpose:\n * a threshold counts the sale whoever remits it. Who remits is still\n * carried per row.\n *\n * Truncation and rows no period can reach are reported, and the platform\n * raises each as a blocking finding of its own.\n */\n\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport {\n asRowDate,\n centsToDollars,\n} from '@aglyn/aglyn/app-utils/tax-jurisdiction-figures'\nimport type {\n TaxReturnExportBlock,\n TaxReturnFiling,\n TaxReturnFilingLine,\n TaxReturnFinding,\n TaxReturnSectionTable,\n TaxReturnSource,\n TaxReturnSourceAnswer,\n TaxReturnSourceRequest,\n} from '@aglyn/aglyn/plugin-manager/plugin-tax-return-sources'\nimport {\n storefrontTaxSummary,\n type StorefrontTaxReturnRowInput,\n type StorefrontTaxSummary,\n} from '../model/storefront-tax-summary'\n\n/** One row of the storefront listing, as the working papers carry it. */\nexport interface StorefrontTaxRow {\n id: string\n hostId: string | null\n orgId: string | null\n paidAt: string | null\n taxMode: string | null\n taxLiability: string | null\n grossCents: number\n taxCents: number\n taxableSalesCents: number\n state: string | null\n country: string | null\n}\n\n/** A liability bucket, ready to print. */\nexport interface StorefrontTaxBucketRow {\n id: 'aglynLiable' | 'merchantManual' | 'connectedAccountLiable'\n label: string\n /** Who owes it — the sentence that decides whether it is on this return. */\n liability: string\n transactionCount: number\n grossDollars: string\n taxableSalesDollars: string\n taxCollectedDollars: string\n /** True when this row is money in the platform's balance under its registration. */\n platformLiable: boolean\n}\n\n/** One state's facilitated storefront sales, for the nexus question. */\nexport interface StorefrontFacilitatedJurisdictionRow {\n jurisdiction: string\n /** True for the one jurisdiction this deployment files a return in. */\n isFilingJurisdiction: boolean\n transactionCount: number\n totalSalesDollars: string\n taxCollectedDollars: string\n /** The part of `taxCollectedDollars` the platform holds and must remit. */\n platformLiableTaxDollars: string\n /** True when NO tax was collected on any sale into this state. */\n untaxed: boolean\n}\n\n/**\n * Storefront tax in the FILING jurisdiction that Stripe computed against the\n * platform's own registrations.\n *\n * The one figure that decides whether a period can be filed from the filing\n * lines alone. Deliberately excludes `merchantManual` — a merchant's own\n * configured rate never touched those registrations. Read against the\n * configured jurisdiction rather than Texas, because a hard-coded key answers\n * `0.00` everywhere else — and a zero here reads as \"nothing to decide\" on\n * the one finding that blocks filing.\n */\nexport function storefrontPlatformLiableCents(\n summary: StorefrontTaxSummary | null | undefined,\n filing: TaxReturnFiling,\n): number {\n const figures = summary?.aglynLiable?.byJurisdiction?.[filing.code]\n const cents = Number(figures?.taxCollectedCents ?? 0)\n return Number.isFinite(cents) ? cents : 0\n}\n\n/** The merchant's own configured tax in the filing jurisdiction. */\nfunction merchantManualCents(\n summary: StorefrontTaxSummary | null | undefined,\n filing: TaxReturnFiling,\n): number {\n return Number(\n summary?.merchantManual?.byJurisdiction?.[filing.code]?.taxCollectedCents ?? 0,\n )\n}\n\n/** The storefront's findings. The platform raises the non-zero ones. */\nexport function storefrontTaxFindings(\n summary: StorefrontTaxSummary,\n filing: TaxReturnFiling,\n): TaxReturnFinding[] {\n const brand = PLATFORM_BRAND_NAME\n return [\n {\n // BLOCKING on purpose — see the module note.\n id: 'storefrontAglynLiableTax',\n severity: 'blocking',\n count: storefrontPlatformLiableCents(summary, filing),\n label: `${filing.label} storefront tax collected under ${brand}’s registration`,\n detail:\n 'Cents. Charged to shoppers on merchants’ storefront sales, computed ' +\n 'by Stripe Tax against THE PLATFORM’s registrations (the session is ' +\n 'created on the platform account), and settled into the platform’s ' +\n `balance. It is NOT included in ${filing.figuresName} below. Decide ` +\n 'with counsel how it is reported before filing — do not file as if ' +\n 'it were zero.',\n },\n {\n id: 'storefrontUnclassified',\n severity: 'blocking',\n count: Number(summary?.attention?.rowsUnclassified ?? 0),\n label: 'Storefront rows with an unrecognised tax mode',\n detail:\n 'Not counted in any storefront bucket, so they are in no figure at ' +\n 'all. Classify them before filing.',\n },\n {\n id: 'storefrontMissingTaxableBase',\n severity: 'review',\n count: Number(summary?.attention?.rowsMissingTaxableBase ?? 0),\n label: 'Storefront rows with tax but no stated base',\n detail:\n 'Tax was collected but Stripe’s taxable_amount could not be read, so ' +\n 'the storefront taxable-sales figure understates the base. Re-read ' +\n 'the session in Stripe with the tax breakdown expanded.',\n },\n ]\n}\n\n/**\n * The two lines beneath the filing figures: the platform-liable tax and the\n * merchant's own rate, separately, and outside every form item.\n */\nexport function storefrontFilingLines(\n summary: StorefrontTaxSummary,\n filing: TaxReturnFiling,\n): TaxReturnFilingLine[] {\n const brand = PLATFORM_BRAND_NAME\n const platformLiable = centsToDollars(storefrontPlatformLiableCents(summary, filing))\n const merchant = centsToDollars(merchantManualCents(summary, filing))\n if (filing.form === 'tx-webfile') {\n return [\n {\n item: '—',\n label: `${filing.label} storefront tax under ${brand}’s registration (NOT in ${filing.figuresName})`,\n dollars: platformLiable,\n note:\n `Collected from shoppers on merchants’ sales and held in ${brand}’s ` +\n 'balance. Excluded from every item above. Its treatment on the ' +\n 'return is a question for counsel — see AGL-1904.',\n },\n {\n item: '—',\n label: `${filing.label} storefront tax under the MERCHANT’s own rate (not ${brand}’s)`,\n dollars: merchant,\n note:\n `A manual-mode store’s own configured rate. ${brand}’s registrations ` +\n 'played no part in computing it. Shown so it is visibly NOT the line ' +\n 'above — the two must never be added together.',\n },\n ]\n }\n return [\n {\n item: '—',\n label: `${filing.code} storefront tax under the platform’s registration (NOT in the figures above)`,\n dollars: platformLiable,\n note:\n 'Collected from shoppers on merchants’ sales and held in the ' +\n 'platform’s balance. Excluded from every figure above. Its treatment ' +\n 'on the return is a question for the operator’s own counsel.',\n },\n {\n item: '—',\n label: `${filing.code} storefront tax under the MERCHANT’s own rate`,\n dollars: merchant,\n note:\n 'A manual-mode store’s own configured rate. The platform’s ' +\n 'registrations played no part in computing it. Shown so it is ' +\n 'visibly NOT the line above — the two must never be added together.',\n },\n ]\n}\n\n/** The three liability buckets, in the order a reader decides them. */\nexport function storefrontBucketRows(\n summary: StorefrontTaxSummary,\n): StorefrontTaxBucketRow[] {\n const brand = PLATFORM_BRAND_NAME\n const buckets: Array<{\n id: StorefrontTaxBucketRow['id']\n label: string\n liability: string\n platformLiable: boolean\n }> = [\n {\n id: 'aglynLiable',\n label: `Computed against ${brand}’s registrations`,\n liability: `In ${brand}’s balance. Stripe Tax computed it on ${brand}’s platform account.`,\n platformLiable: true,\n },\n {\n id: 'merchantManual',\n label: 'Merchant’s own configured rate',\n liability: `The merchant’s. It never touched an ${brand} registration and is not ${brand}’s to remit.`,\n platformLiable: false,\n },\n {\n id: 'connectedAccountLiable',\n label: 'Stripe Tax named the connected account liable',\n liability: 'The connected account’s. Empty today.',\n platformLiable: false,\n },\n ]\n return buckets.map((bucket) => {\n const figures = summary?.[bucket.id]\n return {\n id: bucket.id,\n label: bucket.label,\n liability: bucket.liability,\n transactionCount: Number(figures?.transactionCount ?? 0),\n grossDollars: centsToDollars(figures?.grossCents),\n taxableSalesDollars: centsToDollars(figures?.taxableSalesCents),\n taxCollectedDollars: centsToDollars(figures?.taxCollectedCents),\n platformLiable: bucket.platformLiable,\n }\n })\n}\n\n/**\n * FACILITATED SALES BY STATE — the economic-nexus question (AGL-1956).\n *\n * The question a state asks a marketplace facilitator is \"how much did you\n * facilitate INTO this state, and in how many transactions\" — not \"how much\n * tax did you collect there\". A state the operator is not registered in\n * collects nothing by definition, which is exactly why collection cannot be\n * the measure: the states worth watching are the ones showing $0 tax and a\n * rising sales figure.\n *\n * So this SUMS the three liability buckets per jurisdiction. The rule that\n * the operator's own invoices and storefront rows are never summed still\n * holds — nothing here touches the operator's own sales; within the\n * storefront collection the buckets differ only in WHO REMITS, and a nexus\n * threshold counts the sale whoever remits it. Who remits is still carried\n * per row, because \"do we have nexus here\" and \"what do we owe here\" are\n * answered off the same rows and must not blur.\n *\n * ⚠️ A LOWER BOUND, deliberately rather than silently: `storefront-tax-record.ts`\n * files no row at all for a sale whose `taxMode` resolves to `none`, so a\n * wholly untaxed storefront sale is invisible here — the population nexus\n * detection most needs. Closing it is a write-side change recorded on\n * AGL-1956. The filing jurisdiction does not depend on any of this: a filer\n * registered where it is established has no in-state threshold left to cross.\n */\nexport function storefrontFacilitatedJurisdictionRows(\n summary: StorefrontTaxSummary | null | undefined,\n filing: TaxReturnFiling,\n): StorefrontFacilitatedJurisdictionRow[] {\n if (!summary) return []\n const totals = new Map<\n string,\n { count: number; salesCents: number; taxCents: number; platformCents: number }\n >()\n const buckets: Array<[StorefrontTaxBucketRow['id'], boolean]> = [\n ['aglynLiable', true],\n ['merchantManual', false],\n ['connectedAccountLiable', false],\n ]\n for (const [id, platformLiable] of buckets) {\n const byJurisdiction = summary[id]?.byJurisdiction ?? {}\n for (const [jurisdiction, figures] of Object.entries(byJurisdiction)) {\n const entry = totals.get(jurisdiction) ?? {\n count: 0,\n salesCents: 0,\n taxCents: 0,\n platformCents: 0,\n }\n const taxCents = Number(figures?.taxCollectedCents ?? 0)\n entry.count += Number(figures?.transactionCount ?? 0)\n entry.salesCents += Number(figures?.totalSalesCents ?? 0)\n entry.taxCents += taxCents\n if (platformLiable) entry.platformCents += taxCents\n totals.set(jurisdiction, entry)\n }\n }\n return [...totals.entries()]\n .map(([jurisdiction, entry]) => ({\n jurisdiction,\n isFilingJurisdiction: jurisdiction === filing.code,\n transactionCount: entry.count,\n totalSalesDollars: centsToDollars(entry.salesCents),\n taxCollectedDollars: centsToDollars(entry.taxCents),\n platformLiableTaxDollars: centsToDollars(entry.platformCents),\n untaxed: entry.taxCents === 0,\n }))\n .sort(\n (a, b) =>\n // The filing jurisdiction first — it is the one obligation that does\n // not wait on a threshold — then by the figure a threshold is\n // actually measured against.\n Number(b.isFilingJurisdiction) - Number(a.isFilingJurisdiction) ||\n Number(b.totalSalesDollars) - Number(a.totalSalesDollars) ||\n a.jurisdiction.localeCompare(b.jurisdiction),\n )\n}\n\n/** The storefront's two tables on the return's screen. */\nfunction storefrontTables(\n summary: StorefrontTaxSummary,\n filing: TaxReturnFiling,\n): TaxReturnSectionTable[] {\n const brand = PLATFORM_BRAND_NAME\n return [\n {\n // Split by who owes it, never summed — one \"storefront tax\" total would\n // merge two facts into a number that is true of neither.\n columns: [\n { label: 'Bucket' },\n { label: 'Sales', numeric: true },\n { label: 'Gross', numeric: true, money: true },\n { label: 'Taxable sales', numeric: true, money: true },\n { label: 'Tax collected', numeric: true, money: true },\n ],\n rows: storefrontBucketRows(summary).map((row) => ({\n key: row.id,\n cells: [\n {\n text: row.label,\n caption: row.liability,\n ...(row.platformLiable\n ? { tag: { label: `${brand} holds this`, tone: 'attention' as const } }\n : {}),\n },\n { text: String(row.transactionCount) },\n { text: `$${row.grossDollars}` },\n { text: `$${row.taxableSalesDollars}` },\n { text: `$${row.taxCollectedDollars}`, strong: row.platformLiable },\n ],\n })),\n empty: 'This period’s response carries no storefront figures.',\n },\n {\n heading: 'Facilitated sales by buyer state',\n description:\n `What ${brand} facilitated into each state, whoever remits the ` +\n 'tax — the figure an economic-nexus threshold is measured ' +\n `against. ${filing.code} needs no threshold: the filer is ` +\n 'established there, so the obligation is unconditional. A ' +\n 'region showing sales and no tax is the one to watch.',\n columns: [\n { label: 'Buyer state' },\n { label: 'Sales', numeric: true },\n { label: 'Total sales', numeric: true, money: true },\n { label: 'Tax collected', numeric: true, money: true },\n { label: `Of which ${brand} owes`, numeric: true, money: true },\n ],\n rows: storefrontFacilitatedJurisdictionRows(summary, filing).map((row) => ({\n key: row.jurisdiction,\n cells: [\n {\n text: row.jurisdiction === 'unknown' ? 'Not stated' : row.jurisdiction,\n ...(row.isFilingJurisdiction\n ? { tag: { label: 'Registered', tone: 'attention' as const } }\n : row.untaxed\n ? { tag: { label: 'No tax collected', tone: 'neutral' as const } }\n : {}),\n },\n { text: String(row.transactionCount) },\n { text: `$${row.totalSalesDollars}` },\n { text: `$${row.taxCollectedDollars}` },\n {\n text: `$${row.platformLiableTaxDollars}`,\n strong: Number(row.platformLiableTaxDollars) > 0,\n },\n ],\n })),\n empty: 'No storefront sales recorded in this period.',\n footnote:\n 'A LOWER BOUND. A storefront sale that collected no tax at ' +\n 'all files no row, so it is missing here — which is exactly ' +\n 'the population a nexus check wants. Recorded on AGL-1956.',\n },\n ]\n}\n\n/**\n * The storefront's blocks of the working-papers export: the nexus figures\n * beside the operator's own sales by jurisdiction — a different taxpayer's\n * money and never summed with them — and the liability buckets after the\n * working papers.\n */\nfunction storefrontExports(\n summary: StorefrontTaxSummary,\n filing: TaxReturnFiling,\n): TaxReturnExportBlock[] {\n const brand = PLATFORM_BRAND_NAME\n const facilitated = storefrontFacilitatedJurisdictionRows(summary, filing)\n return [\n {\n placement: 'jurisdictions',\n rows: [\n ['Facilitated sales by buyer state (merchants’ storefronts)'],\n [\n 'Buyer state',\n 'Sales',\n 'Total sales (USD)',\n 'Tax collected (USD)',\n `Of which ${brand} owes (USD)`,\n ],\n ...(facilitated.length\n ? facilitated.map((row) => [\n row.jurisdiction,\n String(row.transactionCount),\n row.totalSalesDollars,\n row.taxCollectedDollars,\n row.platformLiableTaxDollars,\n ])\n : [['—', '0', '0.00', '0.00', '0.00']]),\n [\n 'LOWER BOUND — a storefront sale that collected no tax files no row, ' +\n `so it is absent here. ${filing.code} needs no threshold: the filer ` +\n 'is established there.',\n ],\n ],\n },\n {\n placement: 'sections',\n rows: [\n [\n 'Storefront commerce tax by liability (AGL-1904) — NOT in ' +\n (filing.form === 'tx-webfile' ? 'the Webfile figures' : 'the breakdown above'),\n ],\n [\n 'Bucket',\n 'Who owes it',\n 'Transactions',\n 'Gross (USD)',\n 'Taxable sales (USD)',\n 'Tax collected (USD)',\n ],\n ...storefrontBucketRows(summary).map((row) => [\n row.label,\n row.liability,\n String(row.transactionCount),\n row.grossDollars,\n row.taxableSalesDollars,\n row.taxCollectedDollars,\n ]),\n ],\n },\n ]\n}\n\n/** One storefront row as the working papers carry it. */\nfunction projectRow(row: StorefrontTaxReturnRowInput): StorefrontTaxRow {\n return {\n id: row.id,\n hostId: typeof row.hostId === 'string' ? row.hostId : null,\n orgId: row.orgId ?? null,\n paidAt: asRowDate(row.paidAt)?.toISOString() ?? null,\n taxMode: typeof row.taxMode === 'string' ? row.taxMode : null,\n taxLiability: typeof row.taxLiability === 'string' ? row.taxLiability : null,\n grossCents: Number(row.grossCents ?? 0),\n taxCents: Number(row.taxCents ?? 0),\n taxableSalesCents: (Array.isArray(row.taxLines) ? row.taxLines : [])\n .map((line) => Number(line?.taxableAmountCents ?? 0))\n .reduce((sum, base) => sum + (Number.isFinite(base) ? base : 0), 0),\n state: typeof row.customerAddress?.state === 'string' ? row.customerAddress.state : null,\n country:\n typeof row.customerAddress?.country === 'string' ? row.customerAddress.country : null,\n }\n}\n\n/**\n * The storefront's answer for one period, from rows already read. Pure, so\n * the section a preparer reads can be proved from fixtures.\n */\nexport function storefrontTaxReturnAnswer(\n read: {\n rows: readonly StorefrontTaxReturnRowInput[]\n truncated: boolean\n undatedRows: number\n },\n request: TaxReturnSourceRequest,\n): TaxReturnSourceAnswer {\n const brand = PLATFORM_BRAND_NAME\n const { filing } = request\n const summary = storefrontTaxSummary(read.rows, request)\n return {\n id: 'storefront',\n name: 'Storefront',\n title: 'Storefront commerce tax — merchants’ sales',\n help:\n 'Tax charged to shoppers on merchants’ storefronts, split by who owes it. None of it is in the filing figures above.',\n intro:\n `None of this is in the ${\n filing.form === 'tx-webfile' ? 'Webfile' : 'breakdown'\n } figures above, which sum ` +\n `${brand}’s OWN sales only. The first row is the one that ` +\n `needs a decision: those sessions are created on ${brand}’s ` +\n `platform account, so Stripe computed that tax against ` +\n `${brand}’s registrations and it settled into ${brand}’s balance.`,\n truncated: read.truncated,\n undatedRows: read.undatedRows,\n findings: storefrontTaxFindings(summary, filing),\n filingLines: storefrontFilingLines(summary, filing),\n tables: storefrontTables(summary, filing),\n figures: [],\n exports: storefrontExports(summary, filing),\n summary,\n rows: read.rows.map(projectRow),\n }\n}\n\n/**\n * The storefront's source, registered on the console's API surface: the\n * staff return awaits that surface before it asks.\n *\n * Two queries, and the second is the honesty check: the period query ranges\n * on `paidAt`, and a Firestore range query CANNOT match a document whose\n * field is null — so a row that failed to date itself would be invisible to\n * every period. The equality probe counts those rows, over all of them, and\n * the platform blocks the return on any.\n */\nexport const commerceTaxReturnSource: TaxReturnSource = {\n async read(request) {\n const collection = firebaseAdmin.app().firestore().collection('storefrontTaxCollected')\n const [inPeriod, undated] = await Promise.all([\n collection\n .where('paidAt', '>=', request.start)\n .where('paidAt', '<', request.end)\n .limit(request.rowCap + 1)\n .get(),\n collection.where('paidAt', '==', null).count().get(),\n ])\n const rows: StorefrontTaxReturnRowInput[] = inPeriod.docs\n .slice(0, request.rowCap)\n .map((doc) => ({\n id: doc.id,\n ...(doc.data() as Omit<StorefrontTaxReturnRowInput, 'id'>),\n }))\n return storefrontTaxReturnAnswer(\n {\n rows,\n truncated: inPeriod.size > request.rowCap,\n undatedRows: Number(undated.data().count ?? 0),\n },\n request,\n )\n },\n}\n"],"names":["firebaseAdmin","PLATFORM_BRAND_NAME","asRowDate","centsToDollars","storefrontTaxSummary","storefrontPlatformLiableCents","summary","filing","figures","aglynLiable","byJurisdiction","code","cents","Number","taxCollectedCents","isFinite","merchantManualCents","merchantManual","storefrontTaxFindings","brand","id","severity","count","label","detail","figuresName","attention","rowsUnclassified","rowsMissingTaxableBase","storefrontFilingLines","platformLiable","merchant","form","item","dollars","note","storefrontBucketRows","buckets","liability","map","bucket","transactionCount","grossDollars","grossCents","taxableSalesDollars","taxableSalesCents","taxCollectedDollars","storefrontFacilitatedJurisdictionRows","totals","Map","jurisdiction","Object","entries","entry","get","salesCents","taxCents","platformCents","totalSalesCents","set","isFilingJurisdiction","totalSalesDollars","platformLiableTaxDollars","untaxed","sort","a","b","localeCompare","storefrontTables","columns","numeric","money","rows","row","key","cells","text","caption","tag","tone","String","strong","empty","heading","description","footnote","storefrontExports","facilitated","placement","length","projectRow","hostId","orgId","paidAt","toISOString","taxMode","taxLiability","Array","isArray","taxLines","line","taxableAmountCents","reduce","sum","base","state","customerAddress","country","storefrontTaxReturnAnswer","read","request","name","title","help","intro","truncated","undatedRows","findings","filingLines","tables","exports","commerceTaxReturnSource","undated","collection","app","firestore","inPeriod","Promise","all","where","start","end","limit","rowCap","docs","slice","doc","data","size"],"mappings":"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"}