@aglyn/plugins-commerce 1.0.0-beta.285 → 1.0.0-beta.287

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 (420) hide show
  1. package/README.md +1 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/cart.js +25 -12
  4. package/src/lib/components/cart.js.map +1 -1
  5. package/src/lib/components/commerce-console-page.js +70 -13
  6. package/src/lib/components/commerce-console-page.js.map +1 -1
  7. package/src/lib/components/console/order-detail-dialog.component.js +2 -1
  8. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  9. package/src/lib/components/console/payment-methods-card.component.js +1 -1
  10. package/src/lib/components/console/payment-methods-card.component.js.map +1 -1
  11. package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +5 -0
  12. package/src/lib/components/console/pos/pos-cart-panel.component.js +18 -12
  13. package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -1
  14. package/src/lib/components/console/pos/pos-hardware-api.d.ts +76 -5
  15. package/src/lib/components/console/pos/pos-hardware-api.js +53 -11
  16. package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -1
  17. package/src/lib/components/console/pos/pos-hardware-buyer.component.d.ts +18 -0
  18. package/src/lib/components/console/pos/pos-hardware-buyer.component.js +629 -0
  19. package/src/lib/components/console/pos/pos-hardware-buyer.component.js.map +1 -0
  20. package/src/lib/components/console/pos/pos-hardware-sale-api.d.ts +162 -0
  21. package/src/lib/components/console/pos/pos-hardware-sale-api.js +122 -0
  22. package/src/lib/components/console/pos/pos-hardware-sale-api.js.map +1 -0
  23. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.d.ts +39 -0
  24. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js +251 -0
  25. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js.map +1 -0
  26. package/src/lib/components/console/pos/use-pos-display.js +50 -0
  27. package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
  28. package/src/lib/components/console/pos-cellular-control.component.d.ts +41 -0
  29. package/src/lib/components/console/pos-cellular-control.component.js +211 -0
  30. package/src/lib/components/console/pos-cellular-control.component.js.map +1 -0
  31. package/src/lib/components/console/pos-devices-card.component.d.ts +9 -1
  32. package/src/lib/components/console/pos-devices-card.component.js +47 -15
  33. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  34. package/src/lib/components/console/pos-display/pos-display-api.d.ts +6 -0
  35. package/src/lib/components/console/pos-display/pos-display-api.js +8 -1
  36. package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
  37. package/src/lib/components/console/pos-display-page.component.d.ts +13 -0
  38. package/src/lib/components/console/pos-display-page.component.js +44 -2
  39. package/src/lib/components/console/pos-display-page.component.js.map +1 -1
  40. package/src/lib/components/console/pos-hardware-card.component.d.ts +12 -4
  41. package/src/lib/components/console/pos-hardware-card.component.js +157 -36
  42. package/src/lib/components/console/pos-hardware-card.component.js.map +1 -1
  43. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +360 -80
  44. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -1
  45. package/src/lib/components/console/pos-hardware-terms-page.component.d.ts +34 -0
  46. package/src/lib/components/console/pos-hardware-terms-page.component.js +257 -0
  47. package/src/lib/components/console/pos-hardware-terms-page.component.js.map +1 -0
  48. package/src/lib/components/console/pos-hardware-terms-sign-page.component.d.ts +27 -0
  49. package/src/lib/components/console/pos-hardware-terms-sign-page.component.js +104 -0
  50. package/src/lib/components/console/pos-hardware-terms-sign-page.component.js.map +1 -0
  51. package/src/lib/components/console/pos-hardware-waiting-card.component.d.ts +24 -0
  52. package/src/lib/components/console/pos-hardware-waiting-card.component.js +205 -0
  53. package/src/lib/components/console/pos-hardware-waiting-card.component.js.map +1 -0
  54. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +297 -201
  55. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -1
  56. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +3 -0
  57. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +260 -92
  58. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
  59. package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +9 -0
  60. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +15 -6
  61. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
  62. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.d.ts +25 -0
  63. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js +136 -0
  64. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js.map +1 -0
  65. package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +6 -0
  66. package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +48 -31
  67. package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -1
  68. package/src/lib/components/console/pos-page.component.d.ts +1 -1
  69. package/src/lib/components/console/pos-page.component.js +63 -12
  70. package/src/lib/components/console/pos-page.component.js.map +1 -1
  71. package/src/lib/components/console/pos-reader-splash-setting.component.js +1 -1
  72. package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -1
  73. package/src/lib/components/console/product-check-in-fields.component.d.ts +4 -2
  74. package/src/lib/components/console/product-check-in-fields.component.js +60 -14
  75. package/src/lib/components/console/product-check-in-fields.component.js.map +1 -1
  76. package/src/lib/components/console/product-editor-dialog.component.js +44 -1
  77. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  78. package/src/lib/components/console/product-hardware-sku-field.component.d.ts +19 -0
  79. package/src/lib/components/console/product-hardware-sku-field.component.js +92 -0
  80. package/src/lib/components/console/product-hardware-sku-field.component.js.map +1 -0
  81. package/src/lib/components/console/product-kiosk-offer-field.component.d.ts +22 -0
  82. package/src/lib/components/console/product-kiosk-offer-field.component.js +94 -0
  83. package/src/lib/components/console/product-kiosk-offer-field.component.js.map +1 -0
  84. package/src/lib/components/console/product-register-fields.component.d.ts +4 -0
  85. package/src/lib/components/console/product-register-fields.component.js +31 -2
  86. package/src/lib/components/console/product-register-fields.component.js.map +1 -1
  87. package/src/lib/components/console/products-hub-card.component.js +11 -2
  88. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  89. package/src/lib/components/console/register-hardware-card.component.d.ts +11 -0
  90. package/src/lib/components/console/register-hardware-card.component.js +56 -27
  91. package/src/lib/components/console/register-hardware-card.component.js.map +1 -1
  92. package/src/lib/components/console/reservation-guests-dialog.component.d.ts +28 -0
  93. package/src/lib/components/console/reservation-guests-dialog.component.js +189 -0
  94. package/src/lib/components/console/reservation-guests-dialog.component.js.map +1 -0
  95. package/src/lib/components/console/reservations-card.component.d.ts +9 -0
  96. package/src/lib/components/console/reservations-card.component.js +158 -23
  97. package/src/lib/components/console/reservations-card.component.js.map +1 -1
  98. package/src/lib/components/console/shippingeasy-card.component.js +1 -1
  99. package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
  100. package/src/lib/components/console/shipstation-card.component.d.ts +1 -1
  101. package/src/lib/components/console/shipstation-card.component.js +3 -3
  102. package/src/lib/components/console/shipstation-card.component.js.map +1 -1
  103. package/src/lib/components/product-detail.d.ts +4 -0
  104. package/src/lib/components/product-detail.js +40 -5
  105. package/src/lib/components/product-detail.js.map +1 -1
  106. package/src/lib/components/product-reviews.js +28 -11
  107. package/src/lib/components/product-reviews.js.map +1 -1
  108. package/src/lib/components/reservation-widget.js +28 -5
  109. package/src/lib/components/reservation-widget.js.map +1 -1
  110. package/src/lib/components/use-day-picker.d.ts +25 -0
  111. package/src/lib/components/use-day-picker.js +57 -0
  112. package/src/lib/components/use-day-picker.js.map +1 -0
  113. package/src/lib/constants/operator-alerts.d.ts +55 -0
  114. package/src/lib/constants/operator-alerts.js +156 -1
  115. package/src/lib/constants/operator-alerts.js.map +1 -1
  116. package/src/lib/declarations.console-server.js +54 -1
  117. package/src/lib/declarations.console-server.js.map +1 -1
  118. package/src/lib/declarations.d.ts +4 -2
  119. package/src/lib/declarations.js +11 -4
  120. package/src/lib/declarations.js.map +1 -1
  121. package/src/lib/declarations.server.js +9 -0
  122. package/src/lib/declarations.server.js.map +1 -1
  123. package/src/lib/model/commerce-cart.d.ts +9 -1
  124. package/src/lib/model/commerce-cart.js +4 -3
  125. package/src/lib/model/commerce-cart.js.map +1 -1
  126. package/src/lib/model/commerce-check-in-product.d.ts +26 -0
  127. package/src/lib/model/commerce-check-in-product.js +64 -2
  128. package/src/lib/model/commerce-check-in-product.js.map +1 -1
  129. package/src/lib/model/commerce-check-in-record.d.ts +127 -0
  130. package/src/lib/model/commerce-check-in-record.js +36 -0
  131. package/src/lib/model/commerce-check-in-record.js.map +1 -0
  132. package/src/lib/model/commerce-check-in.d.ts +91 -87
  133. package/src/lib/model/commerce-check-in.js +186 -62
  134. package/src/lib/model/commerce-check-in.js.map +1 -1
  135. package/src/lib/model/commerce-kiosk-offer.d.ts +31 -0
  136. package/src/lib/model/commerce-kiosk-offer.js +35 -0
  137. package/src/lib/model/commerce-kiosk-offer.js.map +1 -0
  138. package/src/lib/model/commerce-orders.d.ts +76 -0
  139. package/src/lib/model/commerce-orders.js +6 -0
  140. package/src/lib/model/commerce-orders.js.map +1 -1
  141. package/src/lib/model/commerce-pos-day-report.d.ts +54 -1
  142. package/src/lib/model/commerce-pos-day-report.js +39 -2
  143. package/src/lib/model/commerce-pos-day-report.js.map +1 -1
  144. package/src/lib/model/commerce-pos-offline.d.ts +1 -1
  145. package/src/lib/model/commerce-pos-offline.js +6 -1
  146. package/src/lib/model/commerce-pos-offline.js.map +1 -1
  147. package/src/lib/model/commerce-pos-ops.js +3 -2
  148. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  149. package/src/lib/model/commerce-pos.d.ts +36 -3
  150. package/src/lib/model/commerce-pos.js +14 -6
  151. package/src/lib/model/commerce-pos.js.map +1 -1
  152. package/src/lib/model/commerce-receipt.js +3 -2
  153. package/src/lib/model/commerce-receipt.js.map +1 -1
  154. package/src/lib/model/commerce-reservations.d.ts +69 -4
  155. package/src/lib/model/commerce-reservations.js +57 -5
  156. package/src/lib/model/commerce-reservations.js.map +1 -1
  157. package/src/lib/model/commerce.d.ts +66 -0
  158. package/src/lib/model/commerce.js +15 -0
  159. package/src/lib/model/commerce.js.map +1 -1
  160. package/src/lib/model/order-list-fields.d.ts +11 -0
  161. package/src/lib/model/order-list-fields.js +17 -1
  162. package/src/lib/model/order-list-fields.js.map +1 -1
  163. package/src/lib/model/own-store-tax-summary.d.ts +152 -0
  164. package/src/lib/model/own-store-tax-summary.js +288 -0
  165. package/src/lib/model/own-store-tax-summary.js.map +1 -0
  166. package/src/lib/model/plugin-permissions.d.ts +67 -0
  167. package/src/lib/model/plugin-permissions.js +224 -7
  168. package/src/lib/model/plugin-permissions.js.map +1 -1
  169. package/src/lib/model/pos-cellular.d.ts +223 -0
  170. package/src/lib/model/pos-cellular.js +293 -0
  171. package/src/lib/model/pos-cellular.js.map +1 -0
  172. package/src/lib/model/pos-hardware-in-person.d.ts +98 -0
  173. package/src/lib/model/pos-hardware-in-person.js +224 -0
  174. package/src/lib/model/pos-hardware-in-person.js.map +1 -0
  175. package/src/lib/model/pos-hardware-tax-summary.d.ts +166 -0
  176. package/src/lib/model/pos-hardware-tax-summary.js +225 -0
  177. package/src/lib/model/pos-hardware-tax-summary.js.map +1 -0
  178. package/src/lib/model/pos-hardware-terms.d.ts +74 -0
  179. package/src/lib/model/pos-hardware-terms.js +115 -0
  180. package/src/lib/model/pos-hardware-terms.js.map +1 -0
  181. package/src/lib/model/pos-hardware.d.ts +349 -7
  182. package/src/lib/model/pos-hardware.js +291 -20
  183. package/src/lib/model/pos-hardware.js.map +1 -1
  184. package/src/lib/model/product-write.d.ts +10 -0
  185. package/src/lib/model/product-write.js +4 -2
  186. package/src/lib/model/product-write.js.map +1 -1
  187. package/src/lib/plugin.js +16 -0
  188. package/src/lib/plugin.js.map +1 -1
  189. package/src/lib/server/billing-webhook.js +25 -1
  190. package/src/lib/server/billing-webhook.js.map +1 -1
  191. package/src/lib/server/cancel-order.js +7 -5
  192. package/src/lib/server/cancel-order.js.map +1 -1
  193. package/src/lib/server/cart-checkout.js +20 -8
  194. package/src/lib/server/cart-checkout.js.map +1 -1
  195. package/src/lib/server/cart.js +29 -0
  196. package/src/lib/server/cart.js.map +1 -1
  197. package/src/lib/server/checkout.js +42 -13
  198. package/src/lib/server/checkout.js.map +1 -1
  199. package/src/lib/server/collection-membership.d.ts +4 -0
  200. package/src/lib/server/collection-membership.js +5 -10
  201. package/src/lib/server/collection-membership.js.map +1 -1
  202. package/src/lib/server/commerce-site-keys.d.ts +29 -0
  203. package/src/lib/server/commerce-site-keys.js +40 -0
  204. package/src/lib/server/commerce-site-keys.js.map +1 -0
  205. package/src/lib/server/draft-order.js +8 -5
  206. package/src/lib/server/draft-order.js.map +1 -1
  207. package/src/lib/server/fulfill-order.js +7 -5
  208. package/src/lib/server/fulfill-order.js.map +1 -1
  209. package/src/lib/server/gift-cards.js +8 -5
  210. package/src/lib/server/gift-cards.js.map +1 -1
  211. package/src/lib/server/local-fulfillment-status.js +9 -6
  212. package/src/lib/server/local-fulfillment-status.js.map +1 -1
  213. package/src/lib/server/member-post.js +6 -5
  214. package/src/lib/server/member-post.js.map +1 -1
  215. package/src/lib/server/membership-admin-password.d.ts +4 -2
  216. package/src/lib/server/membership-admin-password.js +10 -8
  217. package/src/lib/server/membership-admin-password.js.map +1 -1
  218. package/src/lib/server/membership-admin-remove.d.ts +7 -5
  219. package/src/lib/server/membership-admin-remove.js +9 -9
  220. package/src/lib/server/membership-admin-remove.js.map +1 -1
  221. package/src/lib/server/order-notifications.js +5 -2
  222. package/src/lib/server/order-notifications.js.map +1 -1
  223. package/src/lib/server/order-print.js +7 -5
  224. package/src/lib/server/order-print.js.map +1 -1
  225. package/src/lib/server/order-receipt-send.js +8 -5
  226. package/src/lib/server/order-receipt-send.js.map +1 -1
  227. package/src/lib/server/orders-shipping-prepare.js +9 -6
  228. package/src/lib/server/orders-shipping-prepare.js.map +1 -1
  229. package/src/lib/server/own-store-tax-return-source.d.ts +47 -0
  230. package/src/lib/server/own-store-tax-return-source.js +312 -0
  231. package/src/lib/server/own-store-tax-return-source.js.map +1 -0
  232. package/src/lib/server/payment-methods.js +13 -9
  233. package/src/lib/server/payment-methods.js.map +1 -1
  234. package/src/lib/server/pos-auth.d.ts +37 -6
  235. package/src/lib/server/pos-auth.js +40 -15
  236. package/src/lib/server/pos-auth.js.map +1 -1
  237. package/src/lib/server/pos-cellular-billing.d.ts +81 -0
  238. package/src/lib/server/pos-cellular-billing.js +711 -0
  239. package/src/lib/server/pos-cellular-billing.js.map +1 -0
  240. package/src/lib/server/pos-cellular-notify.d.ts +47 -0
  241. package/src/lib/server/pos-cellular-notify.js +150 -0
  242. package/src/lib/server/pos-cellular-notify.js.map +1 -0
  243. package/src/lib/server/pos-cellular.d.ts +88 -0
  244. package/src/lib/server/pos-cellular.js +339 -0
  245. package/src/lib/server/pos-cellular.js.map +1 -0
  246. package/src/lib/server/pos-check-in.d.ts +5 -1
  247. package/src/lib/server/pos-check-in.js +296 -28
  248. package/src/lib/server/pos-check-in.js.map +1 -1
  249. package/src/lib/server/pos-day-report.js +29 -3
  250. package/src/lib/server/pos-day-report.js.map +1 -1
  251. package/src/lib/server/pos-display.d.ts +16 -0
  252. package/src/lib/server/pos-display.js +129 -2
  253. package/src/lib/server/pos-display.js.map +1 -1
  254. package/src/lib/server/pos-hardware-admin.d.ts +10 -1
  255. package/src/lib/server/pos-hardware-admin.js +250 -84
  256. package/src/lib/server/pos-hardware-admin.js.map +1 -1
  257. package/src/lib/server/pos-hardware-attach.d.ts +105 -0
  258. package/src/lib/server/pos-hardware-attach.js +443 -0
  259. package/src/lib/server/pos-hardware-attach.js.map +1 -0
  260. package/src/lib/server/pos-hardware-buyer-lookup.d.ts +58 -0
  261. package/src/lib/server/pos-hardware-buyer-lookup.js +180 -0
  262. package/src/lib/server/pos-hardware-buyer-lookup.js.map +1 -0
  263. package/src/lib/server/pos-hardware-buyer-record.d.ts +29 -0
  264. package/src/lib/server/pos-hardware-buyer-record.js +86 -0
  265. package/src/lib/server/pos-hardware-buyer-record.js.map +1 -0
  266. package/src/lib/server/pos-hardware-cancel.d.ts +58 -0
  267. package/src/lib/server/pos-hardware-cancel.js +147 -0
  268. package/src/lib/server/pos-hardware-cancel.js.map +1 -0
  269. package/src/lib/server/pos-hardware-closure-notices.d.ts +27 -0
  270. package/src/lib/server/pos-hardware-closure-notices.js +85 -0
  271. package/src/lib/server/pos-hardware-closure-notices.js.map +1 -0
  272. package/src/lib/server/pos-hardware-closure.d.ts +60 -0
  273. package/src/lib/server/pos-hardware-closure.js +153 -0
  274. package/src/lib/server/pos-hardware-closure.js.map +1 -0
  275. package/src/lib/server/pos-hardware-in-person.d.ts +61 -0
  276. package/src/lib/server/pos-hardware-in-person.js +236 -0
  277. package/src/lib/server/pos-hardware-in-person.js.map +1 -0
  278. package/src/lib/server/pos-hardware-notify.d.ts +40 -2
  279. package/src/lib/server/pos-hardware-notify.js +195 -14
  280. package/src/lib/server/pos-hardware-notify.js.map +1 -1
  281. package/src/lib/server/pos-hardware-readers.d.ts +115 -0
  282. package/src/lib/server/pos-hardware-readers.js +430 -0
  283. package/src/lib/server/pos-hardware-readers.js.map +1 -0
  284. package/src/lib/server/pos-hardware-returns.d.ts +116 -0
  285. package/src/lib/server/pos-hardware-returns.js +502 -0
  286. package/src/lib/server/pos-hardware-returns.js.map +1 -0
  287. package/src/lib/server/pos-hardware-sale-fields.d.ts +28 -0
  288. package/src/lib/server/pos-hardware-sale-fields.js +44 -0
  289. package/src/lib/server/pos-hardware-sale-fields.js.map +1 -0
  290. package/src/lib/server/pos-hardware-sale.d.ts +54 -0
  291. package/src/lib/server/pos-hardware-sale.js +369 -0
  292. package/src/lib/server/pos-hardware-sale.js.map +1 -0
  293. package/src/lib/server/pos-hardware-tax-return-source.d.ts +99 -0
  294. package/src/lib/server/pos-hardware-tax-return-source.js +462 -0
  295. package/src/lib/server/pos-hardware-tax-return-source.js.map +1 -0
  296. package/src/lib/server/pos-hardware-terms.d.ts +64 -0
  297. package/src/lib/server/pos-hardware-terms.js +154 -0
  298. package/src/lib/server/pos-hardware-terms.js.map +1 -0
  299. package/src/lib/server/pos-hardware-user-eraser.d.ts +3 -0
  300. package/src/lib/server/pos-hardware-user-eraser.js +31 -7
  301. package/src/lib/server/pos-hardware-user-eraser.js.map +1 -1
  302. package/src/lib/server/pos-hardware-webhook.d.ts +5 -0
  303. package/src/lib/server/pos-hardware-webhook.js +51 -6
  304. package/src/lib/server/pos-hardware-webhook.js.map +1 -1
  305. package/src/lib/server/pos-hardware.d.ts +74 -1
  306. package/src/lib/server/pos-hardware.js +175 -10
  307. package/src/lib/server/pos-hardware.js.map +1 -1
  308. package/src/lib/server/pos-kiosk.d.ts +2 -0
  309. package/src/lib/server/pos-kiosk.js +17 -12
  310. package/src/lib/server/pos-kiosk.js.map +1 -1
  311. package/src/lib/server/pos-offline-card-order.d.ts +64 -0
  312. package/src/lib/server/pos-offline-card-order.js +102 -0
  313. package/src/lib/server/pos-offline-card-order.js.map +1 -0
  314. package/src/lib/server/pos-offline-card-reconcile.d.ts +67 -1
  315. package/src/lib/server/pos-offline-card-reconcile.js +215 -18
  316. package/src/lib/server/pos-offline-card-reconcile.js.map +1 -1
  317. package/src/lib/server/pos-offline-sync.d.ts +39 -0
  318. package/src/lib/server/pos-offline-sync.js +190 -55
  319. package/src/lib/server/pos-offline-sync.js.map +1 -1
  320. package/src/lib/server/pos-ops-gate.d.ts +15 -4
  321. package/src/lib/server/pos-ops-gate.js +42 -9
  322. package/src/lib/server/pos-ops-gate.js.map +1 -1
  323. package/src/lib/server/pos-ops-routes.js +24 -0
  324. package/src/lib/server/pos-ops-routes.js.map +1 -1
  325. package/src/lib/server/pos-order-refund-ids.d.ts +28 -0
  326. package/src/lib/server/pos-order-refund-ids.js +31 -0
  327. package/src/lib/server/pos-order-refund-ids.js.map +1 -0
  328. package/src/lib/server/pos-order.js +52 -49
  329. package/src/lib/server/pos-order.js.map +1 -1
  330. package/src/lib/server/pos-payment.js +1 -1
  331. package/src/lib/server/pos-payment.js.map +1 -1
  332. package/src/lib/server/pos-reader-splash-admin.js +30 -32
  333. package/src/lib/server/pos-reader-splash-admin.js.map +1 -1
  334. package/src/lib/server/pos-reader-splash-images-route.d.ts +17 -0
  335. package/src/lib/server/pos-reader-splash-images-route.js +113 -0
  336. package/src/lib/server/pos-reader-splash-images-route.js.map +1 -0
  337. package/src/lib/server/pos-reader-splash-images.d.ts +51 -0
  338. package/src/lib/server/pos-reader-splash-images.js +123 -0
  339. package/src/lib/server/pos-reader-splash-images.js.map +1 -0
  340. package/src/lib/server/pos-reader-splash.d.ts +68 -1
  341. package/src/lib/server/pos-reader-splash.js +182 -11
  342. package/src/lib/server/pos-reader-splash.js.map +1 -1
  343. package/src/lib/server/pos-readers.d.ts +29 -0
  344. package/src/lib/server/pos-readers.js +134 -35
  345. package/src/lib/server/pos-readers.js.map +1 -1
  346. package/src/lib/server/pos-return.d.ts +10 -0
  347. package/src/lib/server/pos-return.js +26 -1
  348. package/src/lib/server/pos-return.js.map +1 -1
  349. package/src/lib/server/pos-sale.js +6 -1
  350. package/src/lib/server/pos-sale.js.map +1 -1
  351. package/src/lib/server/pos-shift.js +11 -0
  352. package/src/lib/server/pos-shift.js.map +1 -1
  353. package/src/lib/server/pos-staff-pin.js +25 -20
  354. package/src/lib/server/pos-staff-pin.js.map +1 -1
  355. package/src/lib/server/pos-terminal.d.ts +14 -4
  356. package/src/lib/server/pos-terminal.js +34 -38
  357. package/src/lib/server/pos-terminal.js.map +1 -1
  358. package/src/lib/server/printers.d.ts +7 -3
  359. package/src/lib/server/printers.js +18 -12
  360. package/src/lib/server/printers.js.map +1 -1
  361. package/src/lib/server/product-drafts.d.ts +11 -1
  362. package/src/lib/server/product-drafts.js +12 -8
  363. package/src/lib/server/product-drafts.js.map +1 -1
  364. package/src/lib/server/product.d.ts +15 -1
  365. package/src/lib/server/product.js +16 -3
  366. package/src/lib/server/product.js.map +1 -1
  367. package/src/lib/server/products-write.d.ts +26 -2
  368. package/src/lib/server/products-write.js +19 -7
  369. package/src/lib/server/products-write.js.map +1 -1
  370. package/src/lib/server/refund.js +34 -11
  371. package/src/lib/server/refund.js.map +1 -1
  372. package/src/lib/server/reservation-availability-query.d.ts +8 -0
  373. package/src/lib/server/reservation-availability-query.js +11 -1
  374. package/src/lib/server/reservation-availability-query.js.map +1 -1
  375. package/src/lib/server/reservation-availability.d.ts +1 -1
  376. package/src/lib/server/reservation-availability.js +7 -2
  377. package/src/lib/server/reservation-availability.js.map +1 -1
  378. package/src/lib/server/reservation-guests.d.ts +32 -0
  379. package/src/lib/server/reservation-guests.js +285 -0
  380. package/src/lib/server/reservation-guests.js.map +1 -0
  381. package/src/lib/server/reservation-walk-in.d.ts +11 -1
  382. package/src/lib/server/reservation-walk-in.js +56 -12
  383. package/src/lib/server/reservation-walk-in.js.map +1 -1
  384. package/src/lib/server/reserve.js +18 -5
  385. package/src/lib/server/reserve.js.map +1 -1
  386. package/src/lib/server/returns.js +9 -6
  387. package/src/lib/server/returns.js.map +1 -1
  388. package/src/lib/server/reviews.d.ts +22 -2
  389. package/src/lib/server/reviews.js +88 -20
  390. package/src/lib/server/reviews.js.map +1 -1
  391. package/src/lib/server/shipping-connectors.js +10 -11
  392. package/src/lib/server/shipping-connectors.js.map +1 -1
  393. package/src/lib/server/site-page-resolver.js +20 -3
  394. package/src/lib/server/site-page-resolver.js.map +1 -1
  395. package/src/lib/server/store-day.d.ts +33 -0
  396. package/src/lib/server/store-day.js +46 -0
  397. package/src/lib/server/store-day.js.map +1 -0
  398. package/src/lib/server/store-setup-ai-writer.d.ts +2 -1
  399. package/src/lib/server/store-setup-ai-writer.js +5 -6
  400. package/src/lib/server/store-setup-ai-writer.js.map +1 -1
  401. package/src/lib/server/storefront-tax.d.ts +13 -0
  402. package/src/lib/server/storefront-tax.js +8 -1
  403. package/src/lib/server/storefront-tax.js.map +1 -1
  404. package/src/lib/server/tax-return-source.d.ts +32 -3
  405. package/src/lib/server/tax-return-source.js +99 -20
  406. package/src/lib/server/tax-return-source.js.map +1 -1
  407. package/src/lib/server.js +100 -2
  408. package/src/lib/server.js.map +1 -1
  409. package/src/lib/testing/fake-firestore.js +58 -16
  410. package/src/lib/testing/fake-firestore.js.map +1 -1
  411. package/src/lib/testing/pos-ops-memory-firestore.js +18 -4
  412. package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -1
  413. package/src/lib/testing/site-register-permissions.d.ts +29 -0
  414. package/src/lib/testing/site-register-permissions.js +38 -0
  415. package/src/lib/testing/site-register-permissions.js.map +1 -0
  416. package/src/lib/transfer/tracking.server.js +8 -5
  417. package/src/lib/transfer/tracking.server.js.map +1 -1
  418. package/src/lib/utils/add-to-cart.d.ts +2 -0
  419. package/src/lib/utils/add-to-cart.js +6 -3
  420. package/src/lib/utils/add-to-cart.js.map +1 -1
@@ -15,9 +15,11 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
15
15
  * See the License for the specific language governing permissions and
16
16
  * limitations under the License.
17
17
  */ import { createHash } from "crypto";
18
+ import * as Aglyn from "@aglyn/aglyn/server";
18
19
  import { firebaseAdmin, readOrgBilling } from "@aglyn/tenant-data-admin";
19
20
  import { hostConsoleUrl } from "@aglyn/tenant-data-admin/server/host-console-link";
20
- import { encodePosHardwareLines, isPosHardwareShippingMethod, POS_HARDWARE_ANCHOR, parsePosHardwareConfig, POS_HARDWARE_CURRENCY, POS_HARDWARE_METADATA_TYPE, POS_HARDWARE_ORDERS_COLLECTION, POS_HARDWARE_SALES_COLLECTION, POS_HARDWARE_SHIP_COUNTRIES, POS_HARDWARE_SHIPPING_LABELS, posHardwareOffers, posHardwareSku, pricePosHardwareCart } from "../model/pos-hardware.js";
21
+ import { encodePosHardwareLines, isPosHardwareShippingMethod, POS_HARDWARE_ANCHOR, parsePosHardwareConfig, parsePosHardwareInPersonConfig, POS_HARDWARE_CURRENCY, POS_HARDWARE_METADATA_TYPE, POS_HARDWARE_ORDERS_COLLECTION, POS_HARDWARE_SALES_COLLECTION, POS_HARDWARE_SHIP_COUNTRIES, POS_HARDWARE_SHIPPING_LABELS, posHardwareOffers, posHardwareOrderSource, posHardwareSku, pricePosHardwareCart } from "../model/pos-hardware.js";
22
+ import { mayVisitPosHardwareShop } from "../model/plugin-permissions.js";
21
23
  import { authorizePosStaff, posIdempotencyKey, posRequestBody } from "./pos-auth.js";
22
24
  import { posStripe, posTerminalAvailable } from "./pos-stripe.js";
23
25
  /*==========================================
@@ -28,9 +30,12 @@ import { posStripe, posTerminalAvailable } from "./pos-stripe.js";
28
30
  * checkout a Stripe Checkout Session for the basket, on the PLATFORM
29
31
  * orders this site's hardware orders, newest first
30
32
  *
31
- * Gated like the register (`authorizePosStaff`: an admin or editor of the
32
- * site with `managePos`, on a plan with POS), because the readers it sells
33
- * are the register's.
33
+ * Gated like the register (`authorizePosStaff`, on a plan with POS), because
34
+ * the readers it sells are the register's, with one difference (AGL-4047):
35
+ * the shop admits whoever works the register (`managePos`) AND whoever may
36
+ * buy hardware (`posBuyHardware`), which stands on its own — a bookkeeper
37
+ * with no register orders the store's readers. A checkout needs
38
+ * `posBuyHardware`; seeing the catalog and the site's orders needs either.
34
39
  *
35
40
  * THE SALE IS THE PLATFORM'S. The session is created with the platform key
36
41
  * and NO connected account, `transfer_data` or application fee: the merchant
@@ -43,6 +48,23 @@ import { posStripe, posTerminalAvailable } from "./pos-stripe.js";
43
48
  if (!posTerminalAvailable()) return null;
44
49
  return parsePosHardwareConfig(env);
45
50
  }
51
+ /**
52
+ * The platform's own store that sells hardware in person (AGL-4038), or
53
+ * `null` while that is off. Read like the shop's other figures; a store is
54
+ * the seller only when BOTH its id and its workspace's match, so a site moved
55
+ * to another workspace stops selling hardware rather than selling it for them.
56
+ */ export function posHardwareInPersonConfig(env = process.env) {
57
+ return parsePosHardwareInPersonConfig(env);
58
+ }
59
+ /** Whether a store, owned by `orgId`, is the platform's own hardware seller. */ export function isPosHardwareSellerStore(config, hostId, orgId) {
60
+ return Boolean(config) && (config == null ? void 0 : config.sellerHostId) === hostId && (config == null ? void 0 : config.sellerOrgId) === orgId;
61
+ }
62
+ /**
63
+ * An in-person order's id, from the register sale it came from: one register
64
+ * sale is one hardware order however often its completion is told.
65
+ */ export function posHardwareInPersonOrderId(hostId, registerOrderId) {
66
+ return `hw_${createHash('sha256').update(`pos:${hostId}:${registerOrderId}`).digest('hex').slice(0, 20)}`;
67
+ }
46
68
  /** The order's id, derived from the attempt so a repeated press is one order. */ export function posHardwareOrderId(orgId, hostId, attemptKey) {
47
69
  return `hw_${createHash('sha256').update(`${orgId}:${hostId}:${attemptKey}`).digest('hex').slice(0, 20)}`;
48
70
  }
@@ -60,7 +82,7 @@ export function hardwareOrdersRef(orgId) {
60
82
  return firebaseAdmin.app().firestore().collection(POS_HARDWARE_SALES_COLLECTION).doc(orderId);
61
83
  }
62
84
  /** An order as the merchant's card shows it: no Stripe ids, no staff notes. */ export function merchantHardwareOrderView(id, order) {
63
- var _order_lines, _order_subtotalCents, _ref, _ref1, _order_taxCents, _order_totalCents, _order_tracking, _order_createdAtMs, _ref2, _order_updatedAtMs;
85
+ var _order_lines, _order_subtotalCents, _ref, _ref1, _order_taxCents, _order_totalCents, _order_tracking, _order_createdAtMs, _ref2, _order_updatedAtMs, _order_discountCents, _order_units, _order_refundedCents;
64
86
  var _order_shipping, _order_shipping1;
65
87
  return {
66
88
  id,
@@ -80,7 +102,17 @@ export function hardwareOrdersRef(orgId) {
80
102
  totalCents: (_order_totalCents = order.totalCents) != null ? _order_totalCents : 0,
81
103
  tracking: (_order_tracking = order.tracking) != null ? _order_tracking : null,
82
104
  createdAtMs: (_order_createdAtMs = order.createdAtMs) != null ? _order_createdAtMs : 0,
83
- updatedAtMs: (_ref2 = (_order_updatedAtMs = order.updatedAtMs) != null ? _order_updatedAtMs : order.createdAtMs) != null ? _ref2 : 0
105
+ updatedAtMs: (_ref2 = (_order_updatedAtMs = order.updatedAtMs) != null ? _order_updatedAtMs : order.createdAtMs) != null ? _ref2 : 0,
106
+ // Bought in person (AGL-4038): handed over at the sale, no parcel.
107
+ source: posHardwareOrderSource(order),
108
+ discountCents: (_order_discountCents = order.discountCents) != null ? _order_discountCents : 0,
109
+ /** Readers still to set up, for an in-person order that took serials. */ readersToSetUp: ((_order_units = order.units) != null ? _order_units : []).filter((unit)=>!unit.readerId).length,
110
+ refundedCents: (_order_refundedCents = order.refundedCents) != null ? _order_refundedCents : 0,
111
+ /** The buyer's return request and what was decided, without who asked. */ returnRequest: order.returnRequest ? {
112
+ state: order.returnRequest.state,
113
+ requestedAtMs: order.returnRequest.requestedAtMs,
114
+ note: order.returnRequest.note
115
+ } : null
84
116
  };
85
117
  }
86
118
  /** The POS settings page of a site, as an absolute console URL. */ export async function posSettingsUrl(hostId) {
@@ -91,6 +123,59 @@ export function hardwareOrdersRef(orgId) {
91
123
  const joiner = path.includes('?') ? '&' : '?';
92
124
  return `${path}${joiner}${query}#${hash}`;
93
125
  }
126
+ /**
127
+ * The readers this workspace bought in person that are not set up yet
128
+ * (AGL-4038): whether its plan includes the point of sale, its stores and
129
+ * whether each can take a reader, and each order with what it waits for.
130
+ * Nothing at all while the in-person sale is off.
131
+ */ export async function waitingInPersonReaders(orgId, hostId) {
132
+ if (!posHardwareInPersonConfig() || !orgId) return {
133
+ posPlan: false,
134
+ stores: [],
135
+ orders: []
136
+ };
137
+ const firestore = firebaseAdmin.app().firestore();
138
+ const [orders, org, hosts] = await Promise.all([
139
+ hardwareOrdersRef(orgId).where('attachment.state', '==', 'attached').where('status', '==', 'delivered').limit(20).get(),
140
+ firestore.collection('orgs').doc(orgId).get(),
141
+ firestore.collection('hosts').where('orgId', '==', orgId).limit(20).get()
142
+ ]);
143
+ if (!orders.docs.length) return {
144
+ posPlan: false,
145
+ stores: [],
146
+ orders: []
147
+ };
148
+ const stores = await Promise.all(hosts.docs.map(async (doc)=>{
149
+ var _ref, _doc_get;
150
+ const id = String(doc.id);
151
+ const [terminal, setupUrl] = await Promise.all([
152
+ firestore.collection('hosts').doc(id).collection('terminal').doc('config').get(),
153
+ posSettingsUrl(id)
154
+ ]);
155
+ return {
156
+ hostId: id,
157
+ name: String((_ref = (_doc_get = doc.get('name')) != null ? _doc_get : doc.get('title')) != null ? _ref : id),
158
+ hasLocation: Boolean(terminal.exists && terminal.get('stripeLocationId')),
159
+ setupUrl: `${setupUrl.split('#')[0]}#pos-devices`
160
+ };
161
+ }));
162
+ return {
163
+ posPlan: Aglyn.checkEntitlement(org.data(), 'pos'),
164
+ stores,
165
+ // Every store's, this store's first: a reader waits wherever the
166
+ // workspace's people look.
167
+ orders: orders.docs.map((doc)=>({
168
+ id: String(doc.id),
169
+ order: doc.data()
170
+ })).filter(({ order })=>order.source === 'in_person').sort((a, b)=>Number(b.order.hostId === hostId) - Number(a.order.hostId === hostId)).map(({ id, order })=>{
171
+ var _order_units;
172
+ return _extends({}, merchantHardwareOrderView(id, order), {
173
+ hostId: order.hostId,
174
+ serialsTaken: ((_order_units = order.units) != null ? _order_units : []).filter((unit)=>unit.serialNumber && !unit.readerId).length
175
+ });
176
+ })
177
+ };
178
+ }
94
179
  export const posHardwareHandler = async (req, res)=>{
95
180
  var _body_hostId, _body_action;
96
181
  if (req.method !== 'POST') return res.status(405).json({
@@ -98,15 +183,85 @@ export const posHardwareHandler = async (req, res)=>{
98
183
  });
99
184
  const body = posRequestBody(req);
100
185
  const hostId = String((_body_hostId = body['hostId']) != null ? _body_hostId : '');
101
- const gate = await authorizePosStaff(req, hostId);
186
+ const action = String((_body_action = body['action']) != null ? _body_action : '');
187
+ // BUYING IS ITS OWN KEY (AGL-4047): anyone who works the register or may
188
+ // buy hardware sees what the shop offers and what this site ordered, and
189
+ // only a member holding "Buy point of sale hardware" — which follows
190
+ // `managePos` until a role or the member sets it, and may be granted
191
+ // without it — starts a checkout that the workspace pays for.
192
+ //
193
+ // A READER BOUGHT IN PERSON (AGL-4038): `waiting` is read without the
194
+ // point of sale plan, because a workspace without it is exactly the one
195
+ // that must be told to add it first; choosing its store and marking it set
196
+ // up are setting up devices (`posDevices`) on the store named.
197
+ const settingUp = action === 'choose-store' || action === 'mark-set-up';
198
+ const gate = await authorizePosStaff(req, hostId, action === 'checkout' ? 'posBuyHardware' : settingUp ? 'posDevices' : undefined, mayVisitPosHardwareShop, // A workspace whose plan lost the point of sale still sees what it bought
199
+ // and may ask to return a reader bought in person.
200
+ action === 'waiting' || action === 'orders' || action === 'request-return' ? {
201
+ planRequired: false
202
+ } : {});
102
203
  if ('error' in gate) return res.status(gate.status).json({
103
204
  error: gate.error
104
205
  });
105
206
  const staff = gate.staff;
106
207
  const config = posHardwareConfig();
107
- const action = String((_body_action = body['action']) != null ? _body_action : '');
108
208
  try {
109
209
  switch(action){
210
+ case 'waiting':
211
+ return res.status(200).json(await waitingInPersonReaders(staff.orgId, staff.hostId));
212
+ case 'request-return':
213
+ {
214
+ var _body_orderId;
215
+ const returns = await import("./pos-hardware-returns.js");
216
+ const orderId = String((_body_orderId = body['orderId']) != null ? _body_orderId : '');
217
+ try {
218
+ const order = await returns.requestPosHardwareReturn({
219
+ orgId: staff.orgId,
220
+ orderId,
221
+ uid: staff.uid,
222
+ reason: body['reason']
223
+ });
224
+ return res.status(200).json({
225
+ ok: true,
226
+ order: merchantHardwareOrderView(orderId, order)
227
+ });
228
+ } catch (error) {
229
+ if (error instanceof returns.PosHardwareReturnRefusal) {
230
+ return res.status(error.status).json({
231
+ error: error.message
232
+ });
233
+ }
234
+ throw error;
235
+ }
236
+ }
237
+ case 'choose-store':
238
+ case 'mark-set-up':
239
+ {
240
+ var _body_orderId1;
241
+ const readers = await import("./pos-hardware-readers.js");
242
+ const orderId = String((_body_orderId1 = body['orderId']) != null ? _body_orderId1 : '');
243
+ try {
244
+ const order = action === 'choose-store' ? await readers.choosePosHardwareStore({
245
+ orgId: staff.orgId,
246
+ orderId,
247
+ hostId: staff.hostId
248
+ }) : await readers.markPosHardwareSetUp({
249
+ orgId: staff.orgId,
250
+ orderId
251
+ });
252
+ return res.status(200).json({
253
+ ok: true,
254
+ order: merchantHardwareOrderView(orderId, order)
255
+ });
256
+ } catch (error) {
257
+ if (error instanceof readers.PosHardwareReaderRefusal) {
258
+ return res.status(error.status).json({
259
+ error: error.message
260
+ });
261
+ }
262
+ throw error;
263
+ }
264
+ }
110
265
  case 'catalog':
111
266
  if (!config) return res.status(200).json({
112
267
  available: false
@@ -124,9 +279,19 @@ export const posHardwareHandler = async (req, res)=>{
124
279
  });
125
280
  case 'orders':
126
281
  {
127
- const snapshot = await hardwareOrdersRef(staff.orgId).where('hostId', '==', staff.hostId).orderBy('createdAtMs', 'desc').limit(50).get();
282
+ // This site's orders, and the readers bought in person for the
283
+ // workspace that wait for a store to be chosen at setup (AGL-4038).
284
+ // A sale on the selling workspace's own To attach list is never one.
285
+ const [site, workspace] = await Promise.all([
286
+ hardwareOrdersRef(staff.orgId).where('hostId', '==', staff.hostId).orderBy('createdAtMs', 'desc').limit(50).get(),
287
+ hardwareOrdersRef(staff.orgId).where('hostId', '==', '').where('attachment.state', '==', 'attached').orderBy('createdAtMs', 'desc').limit(50).get()
288
+ ]);
289
+ const orders = [
290
+ ...site.docs,
291
+ ...workspace.docs
292
+ ].map((doc)=>merchantHardwareOrderView(String(doc.id), doc.data())).sort((a, b)=>b.createdAtMs - a.createdAtMs).slice(0, 50);
128
293
  return res.status(200).json({
129
- orders: snapshot.docs.map((doc)=>merchantHardwareOrderView(String(doc.id), doc.data()))
294
+ orders
130
295
  });
131
296
  }
132
297
  case 'checkout':
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-hardware.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\nimport { createHash } from 'crypto'\nimport type { PluginApiHandler } from '@aglyn/aglyn/server'\nimport { firebaseAdmin, readOrgBilling } from '@aglyn/tenant-data-admin'\nimport { hostConsoleUrl } from '@aglyn/tenant-data-admin/server/host-console-link'\nimport {\n encodePosHardwareLines,\n isPosHardwareShippingMethod,\n POS_HARDWARE_ANCHOR,\n parsePosHardwareConfig,\n POS_HARDWARE_CURRENCY,\n POS_HARDWARE_METADATA_TYPE,\n POS_HARDWARE_ORDERS_COLLECTION,\n POS_HARDWARE_SALES_COLLECTION,\n POS_HARDWARE_SHIP_COUNTRIES,\n POS_HARDWARE_SHIPPING_LABELS,\n posHardwareOffers,\n posHardwareSku,\n pricePosHardwareCart,\n type PosHardwareConfig,\n type PosHardwareOrder,\n} from '../model/pos-hardware'\nimport { authorizePosStaff, posIdempotencyKey, posRequestBody } from './pos-auth'\nimport { posStripe, posTerminalAvailable } from './pos-stripe'\n\n/*==========================================\n * `POST /api/commerce/pos-hardware` (AGL-4038): the merchant's half of the\n * POS hardware shop, behind the Hardware card on Products → Point of sale.\n *\n * catalog what is on offer and at what price, or `available: false`\n * checkout a Stripe Checkout Session for the basket, on the PLATFORM\n * orders this site's hardware orders, newest first\n *\n * Gated like the register (`authorizePosStaff`: an admin or editor of the\n * site with `managePos`, on a plan with POS), because the readers it sells\n * are the register's.\n *\n * THE SALE IS THE PLATFORM'S. The session is created with the platform key\n * and NO connected account, `transfer_data` or application fee: the merchant\n * is the buyer here, and the platform is the seller of record that places\n * the order with Stripe. The order document is written by the webhook once\n * Stripe says the session is paid (`pos-hardware-webhook.ts`), never here.\n *=========================================*/\n\n/** The shop's config from this deployment, or `null` while it is hidden. */\nexport function posHardwareConfig(\n env: Record<string, string | undefined> = process.env,\n): PosHardwareConfig | null {\n // A reader the platform cannot yet take payments on is not for sale: the\n // shop opens only where the register offers card readers at all.\n if (!posTerminalAvailable()) return null\n return parsePosHardwareConfig(env)\n}\n\n/** The order's id, derived from the attempt so a repeated press is one order. */\nexport function posHardwareOrderId(orgId: string, hostId: string, attemptKey: string): string {\n return `hw_${createHash('sha256').update(`${orgId}:${hostId}:${attemptKey}`).digest('hex').slice(0, 20)}`\n}\n\n/** The number a person reads: `HW-` and six characters of the id. */\nexport function posHardwareOrderNumber(orderId: string): string {\n return `HW-${orderId.replace(/^hw_/, '').slice(0, 6).toUpperCase()}`\n}\n\nexport function hardwareOrdersRef(orgId: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection('orgs')\n .doc(orgId)\n .collection(POS_HARDWARE_ORDERS_COLLECTION)\n}\n\n/**\n * `posHardwareSales/{orderId}`, the retained sale record beside each order\n * (see `PosHardwareSaleRecord`). Top-level on purpose: the workspace erasure\n * cannot reach it.\n */\nexport function posHardwareSaleRef(orderId: string) {\n return firebaseAdmin.app().firestore().collection(POS_HARDWARE_SALES_COLLECTION).doc(orderId)\n}\n\n/** An order as the merchant's card shows it: no Stripe ids, no staff notes. */\nexport function merchantHardwareOrderView(id: string, order: PosHardwareOrder) {\n return {\n id,\n number: posHardwareOrderNumber(id),\n status: order.status,\n lines: (order.lines ?? []).map((line) => ({\n sku: line.sku,\n name: line.name,\n quantity: line.quantity,\n unitCents: line.unitCents,\n lineCents: line.lineCents,\n })),\n subtotalCents: order.subtotalCents ?? 0,\n shippingCents: order.shipping?.cents ?? 0,\n shippingLabel: order.shipping?.label ?? '',\n taxCents: order.taxCents ?? 0,\n totalCents: order.totalCents ?? 0,\n tracking: order.tracking ?? null,\n createdAtMs: order.createdAtMs ?? 0,\n updatedAtMs: order.updatedAtMs ?? order.createdAtMs ?? 0,\n }\n}\n\nexport type MerchantHardwareOrderView = ReturnType<typeof merchantHardwareOrderView>\n\n/** The POS settings page of a site, as an absolute console URL. */\nexport async function posSettingsUrl(hostId: string): Promise<string> {\n return hostConsoleUrl(hostId, `/${hostId}/products/pos`)\n}\n\n/** `base` with `query` added before any `#fragment`, then `#hash`. */\nexport function withQueryAndHash(base: string, query: string, hash: string): string {\n const [path] = base.split('#')\n const joiner = path.includes('?') ? '&' : '?'\n return `${path}${joiner}${query}#${hash}`\n}\n\n\nexport const posHardwareHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const body = posRequestBody(req)\n const hostId = String(body['hostId'] ?? '')\n const gate = await authorizePosStaff(req, hostId)\n if ('error' in gate) return res.status(gate.status).json({ error: gate.error })\n const staff = gate.staff\n const config = posHardwareConfig()\n const action = String(body['action'] ?? '')\n try {\n switch (action) {\n case 'catalog':\n if (!config) return res.status(200).json({ available: false })\n return res.status(200).json({\n available: true,\n offers: posHardwareOffers(config),\n shipping: config.shipping.map((option) => ({\n method: option.method,\n label: POS_HARDWARE_SHIPPING_LABELS[option.method],\n cents: option.cents,\n })),\n automaticTax: config.automaticTax,\n shipCountries: POS_HARDWARE_SHIP_COUNTRIES,\n })\n case 'orders': {\n const snapshot = await hardwareOrdersRef(staff.orgId)\n .where('hostId', '==', staff.hostId)\n .orderBy('createdAtMs', 'desc')\n .limit(50)\n .get()\n return res.status(200).json({\n orders: snapshot.docs.map((doc: any) =>\n merchantHardwareOrderView(String(doc.id), doc.data() as PosHardwareOrder),\n ),\n })\n }\n case 'checkout': {\n if (!config) return res.status(404).json({ error: 'The hardware shop is not available.' })\n const attemptKey = posIdempotencyKey(req)\n if (!attemptKey) return res.status(400).json({ error: 'Missing Idempotency-Key' })\n if (!staff.orgId) return res.status(409).json({ error: 'This site has no workspace.' })\n const priced = pricePosHardwareCart(config, body['lines'])\n if ('error' in priced) return res.status(400).json({ error: priced.error })\n const method = body['shippingMethod']\n const shipping = isPosHardwareShippingMethod(method)\n ? config.shipping.find((option) => option.method === method)\n : undefined\n if (!shipping) return res.status(400).json({ error: 'Choose a shipping speed.' })\n\n const orderId = posHardwareOrderId(staff.orgId, staff.hostId, attemptKey)\n const billing = await readOrgBilling(staff.orgId).catch(() => ({}))\n const customer = String((billing as { stripeCustomerId?: unknown }).stripeCustomerId ?? '').trim()\n const base = await posSettingsUrl(staff.hostId)\n const params: Record<string, string | number | boolean> = {\n mode: 'payment',\n client_reference_id: orderId,\n success_url: withQueryAndHash(base, 'hardwareOrder=placed', POS_HARDWARE_ANCHOR),\n cancel_url: withQueryAndHash(base, 'hardwareOrder=canceled', POS_HARDWARE_ANCHOR),\n 'payment_method_types[0]': 'card',\n 'shipping_address_collection[allowed_countries][0]': POS_HARDWARE_SHIP_COUNTRIES[0],\n 'phone_number_collection[enabled]': true,\n 'shipping_options[0][shipping_rate_data][type]': 'fixed_amount',\n 'shipping_options[0][shipping_rate_data][display_name]': POS_HARDWARE_SHIPPING_LABELS[shipping.method],\n 'shipping_options[0][shipping_rate_data][fixed_amount][amount]': shipping.cents,\n 'shipping_options[0][shipping_rate_data][fixed_amount][currency]': POS_HARDWARE_CURRENCY,\n 'metadata[type]': POS_HARDWARE_METADATA_TYPE,\n 'metadata[orderId]': orderId,\n 'metadata[orgId]': staff.orgId,\n 'metadata[hostId]': staff.hostId,\n 'metadata[uid]': staff.uid,\n 'metadata[lines]': encodePosHardwareLines(priced.lines),\n 'metadata[shippingMethod]': shipping.method,\n 'metadata[shippingCents]': shipping.cents,\n 'metadata[subtotalCents]': priced.subtotalCents,\n 'payment_intent_data[description]': `Card reader order ${posHardwareOrderNumber(orderId)}`,\n 'payment_intent_data[metadata][type]': POS_HARDWARE_METADATA_TYPE,\n 'payment_intent_data[metadata][orderId]': orderId,\n 'payment_intent_data[metadata][orgId]': staff.orgId,\n ...(customer ? { customer } : {}),\n ...(config.automaticTax\n ? {\n 'automatic_tax[enabled]': true,\n 'shipping_options[0][shipping_rate_data][tax_behavior]': 'exclusive',\n // A returning workspace's saved address is kept up to date\n // from what Checkout collects, which automatic tax requires.\n ...(customer ? { 'customer_update[shipping]': 'auto' } : {}),\n }\n : {}),\n }\n priced.lines.forEach((line, index) => {\n const sku = posHardwareSku(line.sku)\n params[`line_items[${index}][quantity]`] = line.quantity\n // A literal, not POS_HARDWARE_CURRENCY: check:facilitator-charge-shape\n // reads Stripe Tax beside a usd line item only when it says so (AGL-1956).\n params[`line_items[${index}][price_data][currency]`] = 'usd'\n params[`line_items[${index}][price_data][unit_amount]`] = line.unitCents\n params[`line_items[${index}][price_data][product_data][name]`] = line.name\n if (sku) params[`line_items[${index}][price_data][product_data][description]`] = sku.use\n params[`line_items[${index}][price_data][product_data][metadata][sku]`] = line.sku\n if (config.automaticTax) params[`line_items[${index}][price_data][tax_behavior]`] = 'exclusive'\n })\n const created = await posStripe('POST', 'checkout/sessions', {\n params,\n idempotencyKey: `pos-hw-checkout-${orderId}`,\n })\n const url = String(created.body?.url ?? '')\n if (!created.ok || !url) {\n console.error('[pos-hardware] checkout refused', created.status, created.body?.error?.code)\n return res.status(502).json({ error: 'Checkout could not be started. Try again in a moment.' })\n }\n return res.status(200).json({ url, orderId })\n }\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n } catch (error) {\n console.error('[pos-hardware]', action, error)\n return res.status(500).json({ error: 'The hardware shop could not answer' })\n }\n}\n"],"names":["createHash","firebaseAdmin","readOrgBilling","hostConsoleUrl","encodePosHardwareLines","isPosHardwareShippingMethod","POS_HARDWARE_ANCHOR","parsePosHardwareConfig","POS_HARDWARE_CURRENCY","POS_HARDWARE_METADATA_TYPE","POS_HARDWARE_ORDERS_COLLECTION","POS_HARDWARE_SALES_COLLECTION","POS_HARDWARE_SHIP_COUNTRIES","POS_HARDWARE_SHIPPING_LABELS","posHardwareOffers","posHardwareSku","pricePosHardwareCart","authorizePosStaff","posIdempotencyKey","posRequestBody","posStripe","posTerminalAvailable","posHardwareConfig","env","process","posHardwareOrderId","orgId","hostId","attemptKey","update","digest","slice","posHardwareOrderNumber","orderId","replace","toUpperCase","hardwareOrdersRef","app","firestore","collection","doc","posHardwareSaleRef","merchantHardwareOrderView","id","order","number","status","lines","map","line","sku","name","quantity","unitCents","lineCents","subtotalCents","shippingCents","shipping","cents","shippingLabel","label","taxCents","totalCents","tracking","createdAtMs","updatedAtMs","posSettingsUrl","withQueryAndHash","base","query","hash","path","split","joiner","includes","posHardwareHandler","req","res","body","method","json","error","String","gate","staff","config","action","available","offers","option","automaticTax","shipCountries","snapshot","where","orderBy","limit","get","orders","docs","data","created","priced","find","undefined","billing","catch","customer","stripeCustomerId","trim","params","mode","client_reference_id","success_url","cancel_url","uid","forEach","index","use","idempotencyKey","url","ok","console","code"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-hardware.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\nimport { createHash } from 'crypto'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport type { PluginApiHandler } from '@aglyn/aglyn/server'\nimport { firebaseAdmin, readOrgBilling } from '@aglyn/tenant-data-admin'\nimport { hostConsoleUrl } from '@aglyn/tenant-data-admin/server/host-console-link'\nimport {\n encodePosHardwareLines,\n isPosHardwareShippingMethod,\n POS_HARDWARE_ANCHOR,\n parsePosHardwareConfig,\n parsePosHardwareInPersonConfig,\n POS_HARDWARE_CURRENCY,\n POS_HARDWARE_METADATA_TYPE,\n POS_HARDWARE_ORDERS_COLLECTION,\n POS_HARDWARE_SALES_COLLECTION,\n POS_HARDWARE_SHIP_COUNTRIES,\n POS_HARDWARE_SHIPPING_LABELS,\n posHardwareOffers,\n posHardwareOrderSource,\n posHardwareSku,\n pricePosHardwareCart,\n type PosHardwareConfig,\n type PosHardwareInPersonConfig,\n type PosHardwareOrder,\n} from '../model/pos-hardware'\nimport { mayVisitPosHardwareShop } from '../model/plugin-permissions'\nimport { authorizePosStaff, posIdempotencyKey, posRequestBody } from './pos-auth'\nimport { posStripe, posTerminalAvailable } from './pos-stripe'\n\n/*==========================================\n * `POST /api/commerce/pos-hardware` (AGL-4038): the merchant's half of the\n * POS hardware shop, behind the Hardware card on Products → Point of sale.\n *\n * catalog what is on offer and at what price, or `available: false`\n * checkout a Stripe Checkout Session for the basket, on the PLATFORM\n * orders this site's hardware orders, newest first\n *\n * Gated like the register (`authorizePosStaff`, on a plan with POS), because\n * the readers it sells are the register's, with one difference (AGL-4047):\n * the shop admits whoever works the register (`managePos`) AND whoever may\n * buy hardware (`posBuyHardware`), which stands on its own — a bookkeeper\n * with no register orders the store's readers. A checkout needs\n * `posBuyHardware`; seeing the catalog and the site's orders needs either.\n *\n * THE SALE IS THE PLATFORM'S. The session is created with the platform key\n * and NO connected account, `transfer_data` or application fee: the merchant\n * is the buyer here, and the platform is the seller of record that places\n * the order with Stripe. The order document is written by the webhook once\n * Stripe says the session is paid (`pos-hardware-webhook.ts`), never here.\n *=========================================*/\n\n/** The shop's config from this deployment, or `null` while it is hidden. */\nexport function posHardwareConfig(\n env: Record<string, string | undefined> = process.env,\n): PosHardwareConfig | null {\n // A reader the platform cannot yet take payments on is not for sale: the\n // shop opens only where the register offers card readers at all.\n if (!posTerminalAvailable()) return null\n return parsePosHardwareConfig(env)\n}\n\n/**\n * The platform's own store that sells hardware in person (AGL-4038), or\n * `null` while that is off. Read like the shop's other figures; a store is\n * the seller only when BOTH its id and its workspace's match, so a site moved\n * to another workspace stops selling hardware rather than selling it for them.\n */\nexport function posHardwareInPersonConfig(\n env: Record<string, string | undefined> = process.env,\n): PosHardwareInPersonConfig | null {\n return parsePosHardwareInPersonConfig(env)\n}\n\n/** Whether a store, owned by `orgId`, is the platform's own hardware seller. */\nexport function isPosHardwareSellerStore(\n config: PosHardwareInPersonConfig | null,\n hostId: string,\n orgId: string,\n): config is PosHardwareInPersonConfig {\n return Boolean(config) && config?.sellerHostId === hostId && config?.sellerOrgId === orgId\n}\n\n/**\n * An in-person order's id, from the register sale it came from: one register\n * sale is one hardware order however often its completion is told.\n */\nexport function posHardwareInPersonOrderId(hostId: string, registerOrderId: string): string {\n return `hw_${createHash('sha256').update(`pos:${hostId}:${registerOrderId}`).digest('hex').slice(0, 20)}`\n}\n\n/** The order's id, derived from the attempt so a repeated press is one order. */\nexport function posHardwareOrderId(orgId: string, hostId: string, attemptKey: string): string {\n return `hw_${createHash('sha256').update(`${orgId}:${hostId}:${attemptKey}`).digest('hex').slice(0, 20)}`\n}\n\n/** The number a person reads: `HW-` and six characters of the id. */\nexport function posHardwareOrderNumber(orderId: string): string {\n return `HW-${orderId.replace(/^hw_/, '').slice(0, 6).toUpperCase()}`\n}\n\nexport function hardwareOrdersRef(orgId: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection('orgs')\n .doc(orgId)\n .collection(POS_HARDWARE_ORDERS_COLLECTION)\n}\n\n/**\n * `posHardwareSales/{orderId}`, the retained sale record beside each order\n * (see `PosHardwareSaleRecord`). Top-level on purpose: the workspace erasure\n * cannot reach it.\n */\nexport function posHardwareSaleRef(orderId: string) {\n return firebaseAdmin.app().firestore().collection(POS_HARDWARE_SALES_COLLECTION).doc(orderId)\n}\n\n/** An order as the merchant's card shows it: no Stripe ids, no staff notes. */\nexport function merchantHardwareOrderView(id: string, order: PosHardwareOrder) {\n return {\n id,\n number: posHardwareOrderNumber(id),\n status: order.status,\n lines: (order.lines ?? []).map((line) => ({\n sku: line.sku,\n name: line.name,\n quantity: line.quantity,\n unitCents: line.unitCents,\n lineCents: line.lineCents,\n })),\n subtotalCents: order.subtotalCents ?? 0,\n shippingCents: order.shipping?.cents ?? 0,\n shippingLabel: order.shipping?.label ?? '',\n taxCents: order.taxCents ?? 0,\n totalCents: order.totalCents ?? 0,\n tracking: order.tracking ?? null,\n createdAtMs: order.createdAtMs ?? 0,\n updatedAtMs: order.updatedAtMs ?? order.createdAtMs ?? 0,\n // Bought in person (AGL-4038): handed over at the sale, no parcel.\n source: posHardwareOrderSource(order),\n discountCents: order.discountCents ?? 0,\n /** Readers still to set up, for an in-person order that took serials. */\n readersToSetUp: (order.units ?? []).filter((unit) => !unit.readerId).length,\n refundedCents: order.refundedCents ?? 0,\n /** The buyer's return request and what was decided, without who asked. */\n returnRequest: order.returnRequest\n ? { state: order.returnRequest.state, requestedAtMs: order.returnRequest.requestedAtMs, note: order.returnRequest.note }\n : null,\n }\n}\n\nexport type MerchantHardwareOrderView = ReturnType<typeof merchantHardwareOrderView>\n\n/** The POS settings page of a site, as an absolute console URL. */\nexport async function posSettingsUrl(hostId: string): Promise<string> {\n return hostConsoleUrl(hostId, `/${hostId}/products/pos`)\n}\n\n/** `base` with `query` added before any `#fragment`, then `#hash`. */\nexport function withQueryAndHash(base: string, query: string, hash: string): string {\n const [path] = base.split('#')\n const joiner = path.includes('?') ? '&' : '?'\n return `${path}${joiner}${query}#${hash}`\n}\n\n\n/**\n * The readers this workspace bought in person that are not set up yet\n * (AGL-4038): whether its plan includes the point of sale, its stores and\n * whether each can take a reader, and each order with what it waits for.\n * Nothing at all while the in-person sale is off.\n */\nexport async function waitingInPersonReaders(orgId: string, hostId: string) {\n if (!posHardwareInPersonConfig() || !orgId) return { posPlan: false, stores: [], orders: [] }\n const firestore = firebaseAdmin.app().firestore()\n const [orders, org, hosts] = await Promise.all([\n hardwareOrdersRef(orgId)\n .where('attachment.state', '==', 'attached')\n .where('status', '==', 'delivered')\n .limit(20)\n .get(),\n firestore.collection('orgs').doc(orgId).get(),\n firestore.collection('hosts').where('orgId', '==', orgId).limit(20).get(),\n ])\n if (!orders.docs.length) return { posPlan: false, stores: [], orders: [] }\n const stores = await Promise.all(\n hosts.docs.map(async (doc: any) => {\n const id = String(doc.id)\n const [terminal, setupUrl] = await Promise.all([\n firestore.collection('hosts').doc(id).collection('terminal').doc('config').get(),\n posSettingsUrl(id),\n ])\n return {\n hostId: id,\n name: String(doc.get('name') ?? doc.get('title') ?? id),\n hasLocation: Boolean(terminal.exists && terminal.get('stripeLocationId')),\n setupUrl: `${setupUrl.split('#')[0]}#pos-devices`,\n }\n }),\n )\n return {\n posPlan: Aglyn.checkEntitlement(org.data() as never, 'pos'),\n stores,\n // Every store's, this store's first: a reader waits wherever the\n // workspace's people look.\n orders: orders.docs\n .map((doc: any) => ({ id: String(doc.id), order: doc.data() as PosHardwareOrder }))\n .filter(({ order }) => order.source === 'in_person')\n .sort((a, b) => Number(b.order.hostId === hostId) - Number(a.order.hostId === hostId))\n .map(({ id, order }) => ({\n ...merchantHardwareOrderView(id, order),\n hostId: order.hostId,\n serialsTaken: (order.units ?? []).filter((unit) => unit.serialNumber && !unit.readerId).length,\n })),\n }\n}\n\nexport const posHardwareHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const body = posRequestBody(req)\n const hostId = String(body['hostId'] ?? '')\n const action = String(body['action'] ?? '')\n // BUYING IS ITS OWN KEY (AGL-4047): anyone who works the register or may\n // buy hardware sees what the shop offers and what this site ordered, and\n // only a member holding \"Buy point of sale hardware\" — which follows\n // `managePos` until a role or the member sets it, and may be granted\n // without it — starts a checkout that the workspace pays for.\n //\n // A READER BOUGHT IN PERSON (AGL-4038): `waiting` is read without the\n // point of sale plan, because a workspace without it is exactly the one\n // that must be told to add it first; choosing its store and marking it set\n // up are setting up devices (`posDevices`) on the store named.\n const settingUp = action === 'choose-store' || action === 'mark-set-up'\n const gate = await authorizePosStaff(\n req,\n hostId,\n action === 'checkout' ? 'posBuyHardware' : settingUp ? 'posDevices' : undefined,\n mayVisitPosHardwareShop,\n // A workspace whose plan lost the point of sale still sees what it bought\n // and may ask to return a reader bought in person.\n action === 'waiting' || action === 'orders' || action === 'request-return' ? { planRequired: false } : {},\n )\n if ('error' in gate) return res.status(gate.status).json({ error: gate.error })\n const staff = gate.staff\n const config = posHardwareConfig()\n try {\n switch (action) {\n case 'waiting':\n return res.status(200).json(await waitingInPersonReaders(staff.orgId, staff.hostId))\n case 'request-return': {\n const returns = await import('./pos-hardware-returns')\n const orderId = String(body['orderId'] ?? '')\n try {\n const order = await returns.requestPosHardwareReturn({\n orgId: staff.orgId,\n orderId,\n uid: staff.uid,\n reason: body['reason'],\n })\n return res.status(200).json({ ok: true, order: merchantHardwareOrderView(orderId, order) })\n } catch (error) {\n if (error instanceof returns.PosHardwareReturnRefusal) {\n return res.status(error.status).json({ error: error.message })\n }\n throw error\n }\n }\n case 'choose-store':\n case 'mark-set-up': {\n const readers = await import('./pos-hardware-readers')\n const orderId = String(body['orderId'] ?? '')\n try {\n const order =\n action === 'choose-store'\n ? await readers.choosePosHardwareStore({ orgId: staff.orgId, orderId, hostId: staff.hostId })\n : await readers.markPosHardwareSetUp({ orgId: staff.orgId, orderId })\n return res.status(200).json({ ok: true, order: merchantHardwareOrderView(orderId, order) })\n } catch (error) {\n if (error instanceof readers.PosHardwareReaderRefusal) {\n return res.status(error.status).json({ error: error.message })\n }\n throw error\n }\n }\n case 'catalog':\n if (!config) return res.status(200).json({ available: false })\n return res.status(200).json({\n available: true,\n offers: posHardwareOffers(config),\n shipping: config.shipping.map((option) => ({\n method: option.method,\n label: POS_HARDWARE_SHIPPING_LABELS[option.method],\n cents: option.cents,\n })),\n automaticTax: config.automaticTax,\n shipCountries: POS_HARDWARE_SHIP_COUNTRIES,\n })\n case 'orders': {\n // This site's orders, and the readers bought in person for the\n // workspace that wait for a store to be chosen at setup (AGL-4038).\n // A sale on the selling workspace's own To attach list is never one.\n const [site, workspace] = await Promise.all([\n hardwareOrdersRef(staff.orgId).where('hostId', '==', staff.hostId).orderBy('createdAtMs', 'desc').limit(50).get(),\n hardwareOrdersRef(staff.orgId)\n .where('hostId', '==', '')\n .where('attachment.state', '==', 'attached')\n .orderBy('createdAtMs', 'desc')\n .limit(50)\n .get(),\n ])\n const orders = [...site.docs, ...workspace.docs]\n .map((doc: any) => merchantHardwareOrderView(String(doc.id), doc.data() as PosHardwareOrder))\n .sort((a, b) => b.createdAtMs - a.createdAtMs)\n .slice(0, 50)\n return res.status(200).json({ orders })\n }\n case 'checkout': {\n if (!config) return res.status(404).json({ error: 'The hardware shop is not available.' })\n const attemptKey = posIdempotencyKey(req)\n if (!attemptKey) return res.status(400).json({ error: 'Missing Idempotency-Key' })\n if (!staff.orgId) return res.status(409).json({ error: 'This site has no workspace.' })\n const priced = pricePosHardwareCart(config, body['lines'])\n if ('error' in priced) return res.status(400).json({ error: priced.error })\n const method = body['shippingMethod']\n const shipping = isPosHardwareShippingMethod(method)\n ? config.shipping.find((option) => option.method === method)\n : undefined\n if (!shipping) return res.status(400).json({ error: 'Choose a shipping speed.' })\n\n const orderId = posHardwareOrderId(staff.orgId, staff.hostId, attemptKey)\n const billing = await readOrgBilling(staff.orgId).catch(() => ({}))\n const customer = String((billing as { stripeCustomerId?: unknown }).stripeCustomerId ?? '').trim()\n const base = await posSettingsUrl(staff.hostId)\n const params: Record<string, string | number | boolean> = {\n mode: 'payment',\n client_reference_id: orderId,\n success_url: withQueryAndHash(base, 'hardwareOrder=placed', POS_HARDWARE_ANCHOR),\n cancel_url: withQueryAndHash(base, 'hardwareOrder=canceled', POS_HARDWARE_ANCHOR),\n 'payment_method_types[0]': 'card',\n 'shipping_address_collection[allowed_countries][0]': POS_HARDWARE_SHIP_COUNTRIES[0],\n 'phone_number_collection[enabled]': true,\n 'shipping_options[0][shipping_rate_data][type]': 'fixed_amount',\n 'shipping_options[0][shipping_rate_data][display_name]': POS_HARDWARE_SHIPPING_LABELS[shipping.method],\n 'shipping_options[0][shipping_rate_data][fixed_amount][amount]': shipping.cents,\n 'shipping_options[0][shipping_rate_data][fixed_amount][currency]': POS_HARDWARE_CURRENCY,\n 'metadata[type]': POS_HARDWARE_METADATA_TYPE,\n 'metadata[orderId]': orderId,\n 'metadata[orgId]': staff.orgId,\n 'metadata[hostId]': staff.hostId,\n 'metadata[uid]': staff.uid,\n 'metadata[lines]': encodePosHardwareLines(priced.lines),\n 'metadata[shippingMethod]': shipping.method,\n 'metadata[shippingCents]': shipping.cents,\n 'metadata[subtotalCents]': priced.subtotalCents,\n 'payment_intent_data[description]': `Card reader order ${posHardwareOrderNumber(orderId)}`,\n 'payment_intent_data[metadata][type]': POS_HARDWARE_METADATA_TYPE,\n 'payment_intent_data[metadata][orderId]': orderId,\n 'payment_intent_data[metadata][orgId]': staff.orgId,\n ...(customer ? { customer } : {}),\n ...(config.automaticTax\n ? {\n 'automatic_tax[enabled]': true,\n 'shipping_options[0][shipping_rate_data][tax_behavior]': 'exclusive',\n // A returning workspace's saved address is kept up to date\n // from what Checkout collects, which automatic tax requires.\n ...(customer ? { 'customer_update[shipping]': 'auto' } : {}),\n }\n : {}),\n }\n priced.lines.forEach((line, index) => {\n const sku = posHardwareSku(line.sku)\n params[`line_items[${index}][quantity]`] = line.quantity\n // A literal, not POS_HARDWARE_CURRENCY: check:facilitator-charge-shape\n // reads Stripe Tax beside a usd line item only when it says so (AGL-1956).\n params[`line_items[${index}][price_data][currency]`] = 'usd'\n params[`line_items[${index}][price_data][unit_amount]`] = line.unitCents\n params[`line_items[${index}][price_data][product_data][name]`] = line.name\n if (sku) params[`line_items[${index}][price_data][product_data][description]`] = sku.use\n params[`line_items[${index}][price_data][product_data][metadata][sku]`] = line.sku\n if (config.automaticTax) params[`line_items[${index}][price_data][tax_behavior]`] = 'exclusive'\n })\n const created = await posStripe('POST', 'checkout/sessions', {\n params,\n idempotencyKey: `pos-hw-checkout-${orderId}`,\n })\n const url = String(created.body?.url ?? '')\n if (!created.ok || !url) {\n console.error('[pos-hardware] checkout refused', created.status, created.body?.error?.code)\n return res.status(502).json({ error: 'Checkout could not be started. Try again in a moment.' })\n }\n return res.status(200).json({ url, orderId })\n }\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n } catch (error) {\n console.error('[pos-hardware]', action, error)\n return res.status(500).json({ error: 'The hardware shop could not answer' })\n }\n}\n"],"names":["createHash","Aglyn","firebaseAdmin","readOrgBilling","hostConsoleUrl","encodePosHardwareLines","isPosHardwareShippingMethod","POS_HARDWARE_ANCHOR","parsePosHardwareConfig","parsePosHardwareInPersonConfig","POS_HARDWARE_CURRENCY","POS_HARDWARE_METADATA_TYPE","POS_HARDWARE_ORDERS_COLLECTION","POS_HARDWARE_SALES_COLLECTION","POS_HARDWARE_SHIP_COUNTRIES","POS_HARDWARE_SHIPPING_LABELS","posHardwareOffers","posHardwareOrderSource","posHardwareSku","pricePosHardwareCart","mayVisitPosHardwareShop","authorizePosStaff","posIdempotencyKey","posRequestBody","posStripe","posTerminalAvailable","posHardwareConfig","env","process","posHardwareInPersonConfig","isPosHardwareSellerStore","config","hostId","orgId","Boolean","sellerHostId","sellerOrgId","posHardwareInPersonOrderId","registerOrderId","update","digest","slice","posHardwareOrderId","attemptKey","posHardwareOrderNumber","orderId","replace","toUpperCase","hardwareOrdersRef","app","firestore","collection","doc","posHardwareSaleRef","merchantHardwareOrderView","id","order","number","status","lines","map","line","sku","name","quantity","unitCents","lineCents","subtotalCents","shippingCents","shipping","cents","shippingLabel","label","taxCents","totalCents","tracking","createdAtMs","updatedAtMs","source","discountCents","readersToSetUp","units","filter","unit","readerId","length","refundedCents","returnRequest","state","requestedAtMs","note","posSettingsUrl","withQueryAndHash","base","query","hash","path","split","joiner","includes","waitingInPersonReaders","posPlan","stores","orders","org","hosts","Promise","all","where","limit","get","docs","String","terminal","setupUrl","hasLocation","exists","checkEntitlement","data","sort","a","b","Number","serialsTaken","serialNumber","posHardwareHandler","req","res","body","method","json","error","action","settingUp","gate","undefined","planRequired","staff","returns","requestPosHardwareReturn","uid","reason","ok","PosHardwareReturnRefusal","message","readers","choosePosHardwareStore","markPosHardwareSetUp","PosHardwareReaderRefusal","available","offers","option","automaticTax","shipCountries","site","workspace","orderBy","created","priced","find","billing","catch","customer","stripeCustomerId","trim","params","mode","client_reference_id","success_url","cancel_url","forEach","index","use","idempotencyKey","url","console","code"],"mappings":"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"}
@@ -30,6 +30,8 @@ export declare function posKioskDeviceId(device: PosDeviceToken): string;
30
30
  * product, a gift card whose code needs issuing, and a digital download.
31
31
  */
32
32
  export declare function posKioskSellable(product: CommerceModel.HostProduct): boolean;
33
+ /** A variant the kiosk may sell: priced, and offered by the merchant's choice (AGL-4038). */
34
+ export declare function posKioskVariantOffered(product: CommerceModel.HostProduct, variant: CommerceModel.ProductVariant): boolean;
33
35
  /** A product as the kiosk may show it: names, prices and choices, nothing else. */
34
36
  export declare function posKioskProduct(id: string, product: CommerceModel.HostProduct, hostId: string): CommerceModel.PosKioskProduct;
35
37
  /** An order as its kiosk reads it back; null for any order this kiosk did not open. */
@@ -21,6 +21,7 @@ import { pluginSmsAvailable } from "@aglyn/aglyn/plugin-manager/plugin-sms-messa
21
21
  import { consumeRateLimit, firebaseAdmin, getLockdownVerdict, getOrgForHost, getPluginConfig } from "@aglyn/tenant-data-admin";
22
22
  import { resolveOrgPermissions } from "@aglyn/tenant-runtime/org-permissions";
23
23
  import * as CommerceModel from "../model/index.js";
24
+ import { productOfferedOnKiosk } from "../model/commerce-kiosk-offer.js";
24
25
  import { posRegisterSettings } from "../plugin-config.js";
25
26
  import { posKioskSettings } from "../pos-kiosk-config.js";
26
27
  import { verifyMemberPassword } from "./membership.js";
@@ -54,7 +55,7 @@ function refuse(status, error) {
54
55
  };
55
56
  }
56
57
  /** The kiosk's gate, asked again on every call. */ async function authorizeKiosk(req, body, write) {
57
- var _host_get, _ref, _ref1, _ref2, _register_data;
58
+ var _ref, _ref1, _ref2, _register_data;
58
59
  var _membership_permissions, _owner_org;
59
60
  const device = await resolveDisplayToken(displayToken(req, body));
60
61
  if (!device) return refuse(401, 'This kiosk is not paired.');
@@ -66,11 +67,12 @@ function refuse(status, error) {
66
67
  hostRef.collection('registers').doc(device.registerId).get()
67
68
  ]);
68
69
  if (!host.exists || !register.exists) return refuse(401, 'This kiosk is not paired.');
69
- const role = ((_host_get = host.get('memberRoles')) != null ? _host_get : {})[device.createdBy];
70
+ // The member who paired it must still work the register here: the key
71
+ // decides, not the site role (AGL-4047).
70
72
  const membership = device.createdBy ? await resolveOrgPermissions(device.createdBy, {
71
73
  hostId: device.hostId
72
74
  }) : null;
73
- if (role !== 'admin' && role !== 'editor' || !(membership == null ? void 0 : (_membership_permissions = membership.permissions) == null ? void 0 : _membership_permissions.managePos)) {
75
+ if (!(membership == null ? void 0 : (_membership_permissions = membership.permissions) == null ? void 0 : _membership_permissions.managePos)) {
74
76
  return refuse(403, 'This kiosk needs a staff member to pair it again.');
75
77
  }
76
78
  const owner = await getOrgForHost(device.hostId);
@@ -183,10 +185,16 @@ async function context(gate) {
183
185
  */ export function posKioskSellable(product) {
184
186
  var _product_variants;
185
187
  if (product.status !== 'active') return false;
188
+ // The merchant's own choice of what the kiosk offers (AGL-4038), for any
189
+ // product: "Offer on the kiosk" in the product editor.
190
+ if (!productOfferedOnKiosk(product)) return false;
186
191
  if (product.subscription && !product.subscriptionOptional) return false;
187
192
  if (product.giftCard) return false;
188
193
  if (product.type === 'digital') return false;
189
- return ((_product_variants = product.variants) != null ? _product_variants : []).some((variant)=>CommerceModel.variantHasPrice(variant));
194
+ return ((_product_variants = product.variants) != null ? _product_variants : []).some((variant)=>posKioskVariantOffered(product, variant));
195
+ }
196
+ /** A variant the kiosk may sell: priced, and offered by the merchant's choice (AGL-4038). */ export function posKioskVariantOffered(product, variant) {
197
+ return CommerceModel.variantHasPrice(variant) && productOfferedOnKiosk(product, variant.id);
190
198
  }
191
199
  /** A product as the kiosk may show it: names, prices and choices, nothing else. */ export function posKioskProduct(id, product, hostId) {
192
200
  var _product_description, _product_name, _product_categoryIds, _product_options, _product_variants;
@@ -210,7 +218,7 @@ async function context(gate) {
210
218
  ...option.values
211
219
  ]
212
220
  })),
213
- variants: ((_product_variants = product.variants) != null ? _product_variants : []).filter((variant)=>CommerceModel.variantHasPrice(variant)).map((variant)=>{
221
+ variants: ((_product_variants = product.variants) != null ? _product_variants : []).filter((variant)=>posKioskVariantOffered(product, variant)).map((variant)=>{
214
222
  var _variant_options;
215
223
  return {
216
224
  id: variant.id,
@@ -349,7 +357,7 @@ async function checkout(gate, req, body) {
349
357
  return refuse(409, 'An item in your cart is no longer available. Remove it and try again.');
350
358
  }
351
359
  const variant = line.variantId ? product.variants.find((candidate)=>candidate.id === line.variantId) : product.variants[0];
352
- if (!variant || !CommerceModel.variantHasPrice(variant)) {
360
+ if (!variant || !posKioskVariantOffered(product, variant)) {
353
361
  return refuse(409, `${product.name} is no longer available. Remove it and try again.`);
354
362
  }
355
363
  const wanted = cart.lines.filter((other)=>{
@@ -662,12 +670,8 @@ function signUnlock(payload) {
662
670
  return null;
663
671
  }
664
672
  }
665
- /** Whether a member may still unlock: their role and `managePos` today. */ async function mayUnlock(gate, memberUid) {
666
- var _host_get;
673
+ /** Whether a member may still unlock: `managePos` here today, whatever their site role (AGL-4047). */ async function mayUnlock(gate, memberUid) {
667
674
  var _membership_permissions;
668
- const host = await gate.hostRef.get();
669
- const role = ((_host_get = host.get('memberRoles')) != null ? _host_get : {})[memberUid];
670
- if (role !== 'admin' && role !== 'editor') return false;
671
675
  const membership = await resolveOrgPermissions(memberUid, {
672
676
  hostId: gate.hostId
673
677
  });
@@ -733,6 +737,7 @@ async function unlock(gate, req, body) {
733
737
  }
734
738
  };
735
739
  }
740
+ // Members of this site only, any role: `mayUnlock` below asks the key.
736
741
  const host = await gate.hostRef.get();
737
742
  const roles = (_host_get = host.get('memberRoles')) != null ? _host_get : {};
738
743
  const pins = await gate.hostRef.collection('posStaffPins').limit(50).get();
@@ -740,7 +745,7 @@ async function unlock(gate, req, body) {
740
745
  for (const doc of pins.docs){
741
746
  var _doc_get, _doc_get1;
742
747
  const uid = String(doc.id);
743
- if (roles[uid] !== 'admin' && roles[uid] !== 'editor') continue;
748
+ if (!roles[uid]) continue;
744
749
  if (Number((_doc_get = doc.get('lockedUntilMs')) != null ? _doc_get : 0) > now) continue;
745
750
  const hash = String((_doc_get1 = doc.get('pinScrypt')) != null ? _doc_get1 : '');
746
751
  if (hash && verifyMemberPassword(pin, hash)) {