@aglyn/plugins-commerce 1.0.0-beta.284 → 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
@@ -0,0 +1,285 @@
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
+ */ import { resolveSiteTimeZone } from "@aglyn/aglyn/app-utils/collection-entry-date";
18
+ import { isHostPluginEnabled } from "@aglyn/aglyn/server";
19
+ import { zonedDayKey } from "@aglyn/shared-util-timestamp/zoned-time";
20
+ import { logHostActivity } from "@aglyn/tenant-data-admin";
21
+ import { BUNDLE_ID } from "../constants/bundle-common.js";
22
+ import { changedCheckInCustomerFields, checkInDayLabel, dueCheckInsForReservation, newCheckInDocument, reservationCheckInId, STAY_CHECK_IN_SETTINGS_DOC, stayCheckInPlan, storedStayCheckIns } from "../model/commerce-check-in.js";
23
+ import { readStayCheckInMode, reservationGuests, reservationGuestsProblem, stayChecksInPerGuest } from "../model/commerce-reservations.js";
24
+ import { reservationsOnPlan } from "./reservation-availability-query.js";
25
+ import { bodyOf, gate, resolved, validId } from "./products-write.js";
26
+ import { WALK_IN_PERMISSION, WALK_IN_PLAN_REFUSAL, WALK_IN_PLUGIN_OFF } from "./reservation-walk-in.js";
27
+ /*
28
+ * `POST /api/commerce/reservations/guests` (AGL-4043): staff change how many
29
+ * guests a stay is for after it is booked — a family arrives with one more,
30
+ * or one fewer.
31
+ *
32
+ * Body: { hostId, reservationId, guests }
33
+ *
34
+ * `guests` is a whole number from 1 up to what the resource sleeps
35
+ * (`resourceGuestCeiling`). Who may ask is who may book a walk-in: the same
36
+ * gate (`products-write.ts`'s), asking "Book walk-ins and change guests"
37
+ * (`commerce.walkIns`, AGL-4047) on the site, or staff, while nothing is
38
+ * frozen; the commerce plugin on for the site; and the store's plan taking
39
+ * reservations. A stay that is pending, confirmed or
40
+ * checked in can change; one cancelled, a no-show or checked out cannot.
41
+ *
42
+ * WHEN THE STAY IS CHECKED IN ONE GUEST AT A TIME, its check-ins follow in
43
+ * the same transaction, on today and every later day that already has them
44
+ * (`stayCheckInPlan`): added guests get new waiting check-ins; removed guests
45
+ * take away only waiting ones, never one already checked in. A count below
46
+ * how many are checked in on one of those days is refused, and nothing is
47
+ * written. A day with no check-ins yet is left to its own reconcile, which
48
+ * reads the new count.
49
+ *
50
+ * Every change stamps who made it and when on the stay, and writes a line to
51
+ * the site's activity log. Asking for the count the stay already has answers
52
+ * `unchanged` and writes nothing, so a retried tap is harmless.
53
+ */ export const RESERVATION_GUESTS_GONE = 'That stay is gone.';
54
+ export const RESERVATION_GUESTS_CLOSED = 'Guests can change only on a stay that is booked or checked in';
55
+ /** A member who does not hold the key a guests change asks: the walk-in's refusal, naming it. */ export const RESERVATION_GUESTS_PERMISSION_REFUSAL = WALK_IN_PERMISSION.refusal;
56
+ /** The most check-ins of one stay, from today on, the route reads in its transaction. */ export const RESERVATION_GUESTS_CHECK_IN_ROWS = 500;
57
+ /** The statuses whose guests can change. */ const OPEN_STATUSES = [
58
+ 'pending',
59
+ 'confirmed',
60
+ 'checked_in'
61
+ ];
62
+ /** The refusal for a count below how many are already checked in on a day. */ export function guestsBelowCheckedInMessage(checkedIn, dayKey, todayKey) {
63
+ const when = dayKey === todayKey ? 'today' : `on ${checkInDayLabel(dayKey)}`;
64
+ return `${checkedIn} of this stay’s guests are already checked in ${when}. Undo a check-in first, or keep ${checkedIn} or more.`;
65
+ }
66
+ export function createReservationGuestsHandler(options = {}) {
67
+ return async (req, res)=>{
68
+ var _options_logActivity;
69
+ if (req.method !== 'POST') {
70
+ return res.status(405).json({
71
+ error: 'Method not allowed'
72
+ });
73
+ }
74
+ const deps = resolved(options);
75
+ const logActivity = (_options_logActivity = options.logActivity) != null ? _options_logActivity : logHostActivity;
76
+ const body = bodyOf(req);
77
+ const hostId = body['hostId'];
78
+ const reservationId = body['reservationId'];
79
+ const rawGuests = body['guests'];
80
+ const guests = typeof rawGuests === 'number' || typeof rawGuests === 'string' ? Number(rawGuests) : NaN;
81
+ if (!validId(hostId) || !validId(reservationId) || rawGuests === undefined || rawGuests === null || rawGuests === '') {
82
+ return res.status(400).json({
83
+ error: 'Missing guest details'
84
+ });
85
+ }
86
+ try {
87
+ var _door_host_data;
88
+ const door = await gate(req, res, hostId, deps, {
89
+ permission: WALK_IN_PERMISSION
90
+ });
91
+ if (!door) return;
92
+ if (!isHostPluginEnabled(door.org, door.host.data(), BUNDLE_ID)) {
93
+ return res.status(403).json({
94
+ error: WALK_IN_PLUGIN_OFF
95
+ });
96
+ }
97
+ if (!reservationsOnPlan(door.org)) {
98
+ return res.status(403).json({
99
+ error: WALK_IN_PLAN_REFUSAL
100
+ });
101
+ }
102
+ const db = deps.firestore();
103
+ const hostRef = db.collection('hosts').doc(hostId);
104
+ const reservationRef = hostRef.collection('reservations').doc(reservationId);
105
+ const checkIns = hostRef.collection('checkIns');
106
+ // Today on the store's calendar: earlier days are history, and stay
107
+ // as they were checked in.
108
+ const timeZone = resolveSiteTimeZone(door.org, (_door_host_data = door.host.data()) != null ? _door_host_data : null);
109
+ const todayKey = zonedDayKey(deps.now(), timeZone);
110
+ const outcome = await db.runTransaction(async (transaction)=>{
111
+ var _reservation_resourceId, _ref;
112
+ const stay = await transaction.get(reservationRef);
113
+ if (!stay.exists) return {
114
+ status: 404,
115
+ body: {
116
+ error: RESERVATION_GUESTS_GONE
117
+ }
118
+ };
119
+ const reservation = stay.data();
120
+ if (!OPEN_STATUSES.includes(reservation.status)) {
121
+ return {
122
+ status: 409,
123
+ body: {
124
+ error: RESERVATION_GUESTS_CLOSED
125
+ }
126
+ };
127
+ }
128
+ const resourceId = String((_reservation_resourceId = reservation.resourceId) != null ? _reservation_resourceId : '');
129
+ const [resourceSnapshot, settings, stored] = await Promise.all([
130
+ validId(resourceId) ? transaction.get(hostRef.collection('resources').doc(resourceId)) : null,
131
+ transaction.get(hostRef.collection('settings').doc(STAY_CHECK_IN_SETTINGS_DOC)),
132
+ transaction.get(checkIns.where('reservationId', '==', reservationId).where('dayKey', '>=', todayKey).limit(RESERVATION_GUESTS_CHECK_IN_ROWS))
133
+ ]);
134
+ const resource = (resourceSnapshot == null ? void 0 : resourceSnapshot.exists) ? resourceSnapshot.data() : null;
135
+ const problem = reservationGuestsProblem(guests, resource);
136
+ if (problem) return {
137
+ status: 400,
138
+ body: {
139
+ error: problem
140
+ }
141
+ };
142
+ const previousGuests = reservationGuests(reservation);
143
+ if (previousGuests === guests) {
144
+ return {
145
+ status: 200,
146
+ body: {
147
+ reservationId,
148
+ guests,
149
+ previousGuests,
150
+ unchanged: true
151
+ }
152
+ };
153
+ }
154
+ // How the stay is checked in: the store's control, else the
155
+ // resource's own setting; a resource gone since, once per stay.
156
+ const mode = readStayCheckInMode(settings.exists ? settings.get('stays') : undefined);
157
+ const perGuest = resource ? stayChecksInPerGuest(resource, mode) : mode === 'guest';
158
+ const changed = _extends({}, reservation, {
159
+ guests
160
+ });
161
+ const nowMs = deps.now();
162
+ const byDay = new Map();
163
+ for (const doc of stored.docs){
164
+ var _doc_get, _byDay_get;
165
+ const dayKey = String((_doc_get = doc.get('dayKey')) != null ? _doc_get : '');
166
+ if (dayKey < todayKey) continue;
167
+ byDay.set(dayKey, [
168
+ ...(_byDay_get = byDay.get(dayKey)) != null ? _byDay_get : [],
169
+ doc
170
+ ]);
171
+ }
172
+ const creates = [];
173
+ const drops = [];
174
+ const patches = [];
175
+ for (const dayKey of [
176
+ ...byDay.keys()
177
+ ].sort()){
178
+ var _storedStayCheckIns_get, _ref1;
179
+ const docs = byDay.get(dayKey);
180
+ const existing = (_storedStayCheckIns_get = storedStayCheckIns(docs).get(reservationId)) != null ? _storedStayCheckIns_get : [];
181
+ const due = dueCheckInsForReservation({
182
+ reservationId,
183
+ reservation: changed,
184
+ resourceName: (_ref1 = resource == null ? void 0 : resource.name) != null ? _ref1 : null,
185
+ dayKey,
186
+ perGuest,
187
+ existing
188
+ });
189
+ // A day the stay no longer covers is its own reconcile's to settle.
190
+ if (!due.size) continue;
191
+ const plan = stayCheckInPlan({
192
+ unitCount: perGuest ? guests : 1,
193
+ existing
194
+ });
195
+ if (perGuest && plan.checkedIn > guests) {
196
+ return {
197
+ status: 409,
198
+ body: {
199
+ error: guestsBelowCheckedInMessage(plan.checkedIn, dayKey, todayKey)
200
+ }
201
+ };
202
+ }
203
+ for (const place of plan.create){
204
+ const id = reservationCheckInId(reservationId, dayKey, place);
205
+ const entry = due.get(id);
206
+ if (entry) creates.push({
207
+ ref: checkIns.doc(id),
208
+ data: newCheckInDocument(entry, nowMs)
209
+ });
210
+ }
211
+ const dropped = new Set(plan.drop);
212
+ for (const doc of docs){
213
+ if (dropped.has(doc.id)) {
214
+ drops.push(doc.ref);
215
+ continue;
216
+ }
217
+ const entry = due.get(doc.id);
218
+ if (!entry) continue;
219
+ const storedRow = doc.data();
220
+ // A guest already checked in keeps everything but the count of
221
+ // the stay's check-ins, which the list reads as "2 of 3".
222
+ const patch = storedRow.status === 'checked_in' ? storedRow.unitCount !== entry.unitCount ? {
223
+ unitCount: entry.unitCount
224
+ } : null : changedCheckInCustomerFields(storedRow, entry);
225
+ if (patch) patches.push({
226
+ ref: doc.ref,
227
+ patch: _extends({}, patch, {
228
+ updatedAtMs: nowMs
229
+ })
230
+ });
231
+ }
232
+ }
233
+ transaction.update(reservationRef, {
234
+ guests,
235
+ guestsChangedAtMs: nowMs,
236
+ guestsChangedBy: door.uid
237
+ });
238
+ for (const write of creates)transaction.create(write.ref, write.data);
239
+ for (const ref of drops)transaction.delete(ref);
240
+ for (const write of patches)transaction.update(write.ref, write.patch);
241
+ return {
242
+ status: 200,
243
+ body: {
244
+ reservationId,
245
+ guests,
246
+ previousGuests,
247
+ checkIns: {
248
+ added: creates.length,
249
+ removed: drops.length
250
+ }
251
+ },
252
+ activity: {
253
+ previous: previousGuests,
254
+ resourceName: (_ref = resource == null ? void 0 : resource.name) != null ? _ref : '',
255
+ arrivalDayMs: Number(reservation.checkInDayMs) || 0
256
+ }
257
+ };
258
+ });
259
+ if (outcome.status === 200 && 'activity' in outcome && outcome.activity) {
260
+ const { previous, resourceName, arrivalDayMs } = outcome.activity;
261
+ const arrival = arrivalDayMs ? new Date(arrivalDayMs).toISOString().slice(0, 10) : '';
262
+ await logActivity(hostId, {
263
+ uid: door.uid,
264
+ email: door.email
265
+ }, `Changed a stay’s guests from ${previous} to ${guests}`, {
266
+ type: 'commerce:reservation',
267
+ id: reservationId,
268
+ name: [
269
+ resourceName || 'Stay',
270
+ arrival
271
+ ].filter(Boolean).join(' · ')
272
+ });
273
+ }
274
+ return res.status(outcome.status).json(outcome.body);
275
+ } catch (error) {
276
+ console.error('Changing a stay’s guests failed', error);
277
+ return res.status(500).json({
278
+ error: 'The guests could not be changed. Try again.'
279
+ });
280
+ }
281
+ };
282
+ }
283
+ export const reservationGuestsHandler = createReservationGuestsHandler();
284
+
285
+ //# sourceMappingURL=reservation-guests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/reservation-guests.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 { resolveSiteTimeZone } from '@aglyn/aglyn/app-utils/collection-entry-date'\nimport { isHostPluginEnabled, type PluginApiHandler } from '@aglyn/aglyn/server'\nimport { zonedDayKey } from '@aglyn/shared-util-timestamp/zoned-time'\nimport { logHostActivity } from '@aglyn/tenant-data-admin'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n changedCheckInCustomerFields,\n checkInDayLabel,\n dueCheckInsForReservation,\n newCheckInDocument,\n reservationCheckInId,\n STAY_CHECK_IN_SETTINGS_DOC,\n stayCheckInPlan,\n storedStayCheckIns,\n type HostCheckIn,\n} from '../model/commerce-check-in'\nimport {\n readStayCheckInMode,\n reservationGuests,\n reservationGuestsProblem,\n stayChecksInPerGuest,\n type HostReservation,\n type HostResource,\n} from '../model/commerce-reservations'\nimport { reservationsOnPlan } from './reservation-availability-query'\nimport { bodyOf, gate, resolved, validId, type ProductsWriteDeps } from './products-write'\nimport { WALK_IN_PERMISSION, WALK_IN_PLAN_REFUSAL, WALK_IN_PLUGIN_OFF } from './reservation-walk-in'\n\n/*\n * `POST /api/commerce/reservations/guests` (AGL-4043): staff change how many\n * guests a stay is for after it is booked — a family arrives with one more,\n * or one fewer.\n *\n * Body: { hostId, reservationId, guests }\n *\n * `guests` is a whole number from 1 up to what the resource sleeps\n * (`resourceGuestCeiling`). Who may ask is who may book a walk-in: the same\n * gate (`products-write.ts`'s), asking \"Book walk-ins and change guests\"\n * (`commerce.walkIns`, AGL-4047) on the site, or staff, while nothing is\n * frozen; the commerce plugin on for the site; and the store's plan taking\n * reservations. A stay that is pending, confirmed or\n * checked in can change; one cancelled, a no-show or checked out cannot.\n *\n * WHEN THE STAY IS CHECKED IN ONE GUEST AT A TIME, its check-ins follow in\n * the same transaction, on today and every later day that already has them\n * (`stayCheckInPlan`): added guests get new waiting check-ins; removed guests\n * take away only waiting ones, never one already checked in. A count below\n * how many are checked in on one of those days is refused, and nothing is\n * written. A day with no check-ins yet is left to its own reconcile, which\n * reads the new count.\n *\n * Every change stamps who made it and when on the stay, and writes a line to\n * the site's activity log. Asking for the count the stay already has answers\n * `unchanged` and writes nothing, so a retried tap is harmless.\n */\n\nexport const RESERVATION_GUESTS_GONE = 'That stay is gone.'\nexport const RESERVATION_GUESTS_CLOSED =\n 'Guests can change only on a stay that is booked or checked in'\n/** A member who does not hold the key a guests change asks: the walk-in's refusal, naming it. */\nexport const RESERVATION_GUESTS_PERMISSION_REFUSAL = WALK_IN_PERMISSION.refusal\n\n/** The most check-ins of one stay, from today on, the route reads in its transaction. */\nexport const RESERVATION_GUESTS_CHECK_IN_ROWS = 500\n\n/** The statuses whose guests can change. */\nconst OPEN_STATUSES: ReadonlyArray<HostReservation['status']> = ['pending', 'confirmed', 'checked_in']\n\n/** The refusal for a count below how many are already checked in on a day. */\nexport function guestsBelowCheckedInMessage(checkedIn: number, dayKey: string, todayKey: string): string {\n const when = dayKey === todayKey ? 'today' : `on ${checkInDayLabel(dayKey)}`\n return `${checkedIn} of this stay’s guests are already checked in ${when}. Undo a check-in first, or keep ${checkedIn} or more.`\n}\n\nexport interface ReservationGuestsDeps extends ProductsWriteDeps {\n logActivity?: typeof logHostActivity\n}\n\ntype Outcome =\n | {\n status: 200\n body: {\n reservationId: string\n guests: number\n previousGuests: number\n unchanged?: true\n checkIns?: { added: number; removed: number }\n }\n activity?: { previous: number; resourceName: string; arrivalDayMs: number }\n }\n | { status: 400 | 404 | 409; body: { error: string } }\n\nexport function createReservationGuestsHandler(options: ReservationGuestsDeps = {}): PluginApiHandler {\n return async (req, res) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const deps = resolved(options)\n const logActivity = options.logActivity ?? logHostActivity\n const body = bodyOf(req)\n const hostId = body['hostId']\n const reservationId = body['reservationId']\n const rawGuests = body['guests']\n const guests = typeof rawGuests === 'number' || typeof rawGuests === 'string' ? Number(rawGuests) : NaN\n if (!validId(hostId) || !validId(reservationId) || rawGuests === undefined || rawGuests === null || rawGuests === '') {\n return res.status(400).json({ error: 'Missing guest details' })\n }\n try {\n const door = await gate(req, res, hostId, deps, { permission: WALK_IN_PERMISSION })\n if (!door) return\n if (!isHostPluginEnabled(door.org as never, door.host.data() as never, BUNDLE_ID)) {\n return res.status(403).json({ error: WALK_IN_PLUGIN_OFF })\n }\n if (!reservationsOnPlan(door.org)) {\n return res.status(403).json({ error: WALK_IN_PLAN_REFUSAL })\n }\n const db = deps.firestore()\n const hostRef = db.collection('hosts').doc(hostId)\n const reservationRef = hostRef.collection('reservations').doc(reservationId)\n const checkIns = hostRef.collection('checkIns')\n // Today on the store's calendar: earlier days are history, and stay\n // as they were checked in.\n const timeZone = resolveSiteTimeZone(\n door.org as { timeZone?: string },\n (door.host.data() ?? null) as { timeZone?: string } | null,\n )\n const todayKey = zonedDayKey(deps.now(), timeZone)\n\n const outcome: Outcome = await db.runTransaction(async (transaction) => {\n const stay = await transaction.get(reservationRef)\n if (!stay.exists) return { status: 404, body: { error: RESERVATION_GUESTS_GONE } }\n const reservation = stay.data() as HostReservation\n if (!OPEN_STATUSES.includes(reservation.status)) {\n return { status: 409, body: { error: RESERVATION_GUESTS_CLOSED } }\n }\n const resourceId = String(reservation.resourceId ?? '')\n const [resourceSnapshot, settings, stored] = await Promise.all([\n validId(resourceId) ? transaction.get(hostRef.collection('resources').doc(resourceId)) : null,\n transaction.get(hostRef.collection('settings').doc(STAY_CHECK_IN_SETTINGS_DOC)),\n transaction.get(\n checkIns\n .where('reservationId', '==', reservationId)\n .where('dayKey', '>=', todayKey)\n .limit(RESERVATION_GUESTS_CHECK_IN_ROWS),\n ),\n ])\n const resource = resourceSnapshot?.exists ? (resourceSnapshot.data() as HostResource) : null\n const problem = reservationGuestsProblem(guests, resource)\n if (problem) return { status: 400, body: { error: problem } }\n const previousGuests = reservationGuests(reservation)\n if (previousGuests === guests) {\n return { status: 200, body: { reservationId, guests, previousGuests, unchanged: true } }\n }\n\n // How the stay is checked in: the store's control, else the\n // resource's own setting; a resource gone since, once per stay.\n const mode = readStayCheckInMode(settings.exists ? settings.get('stays') : undefined)\n const perGuest = resource ? stayChecksInPerGuest(resource, mode) : mode === 'guest'\n const changed: HostReservation = { ...reservation, guests }\n const nowMs = deps.now()\n const byDay = new Map<string, FirebaseFirestore.QueryDocumentSnapshot[]>()\n for (const doc of stored.docs) {\n const dayKey = String(doc.get('dayKey') ?? '')\n if (dayKey < todayKey) continue\n byDay.set(dayKey, [...(byDay.get(dayKey) ?? []), doc])\n }\n const creates: Array<{ ref: FirebaseFirestore.DocumentReference; data: HostCheckIn }> = []\n const drops: FirebaseFirestore.DocumentReference[] = []\n const patches: Array<{ ref: FirebaseFirestore.DocumentReference; patch: Record<string, unknown> }> = []\n for (const dayKey of [...byDay.keys()].sort()) {\n const docs = byDay.get(dayKey)!\n const existing = storedStayCheckIns(docs).get(reservationId) ?? []\n const due = dueCheckInsForReservation({\n reservationId,\n reservation: changed,\n resourceName: resource?.name ?? null,\n dayKey,\n perGuest,\n existing,\n })\n // A day the stay no longer covers is its own reconcile's to settle.\n if (!due.size) continue\n const plan = stayCheckInPlan({ unitCount: perGuest ? guests : 1, existing })\n if (perGuest && plan.checkedIn > guests) {\n return { status: 409, body: { error: guestsBelowCheckedInMessage(plan.checkedIn, dayKey, todayKey) } }\n }\n for (const place of plan.create) {\n const id = reservationCheckInId(reservationId, dayKey, place)\n const entry = due.get(id)\n if (entry) creates.push({ ref: checkIns.doc(id), data: newCheckInDocument(entry, nowMs) })\n }\n const dropped = new Set(plan.drop)\n for (const doc of docs) {\n if (dropped.has(doc.id)) {\n drops.push(doc.ref)\n continue\n }\n const entry = due.get(doc.id)\n if (!entry) continue\n const storedRow = doc.data() as Partial<HostCheckIn>\n // A guest already checked in keeps everything but the count of\n // the stay's check-ins, which the list reads as \"2 of 3\".\n const patch =\n storedRow.status === 'checked_in'\n ? storedRow.unitCount !== entry.unitCount\n ? { unitCount: entry.unitCount }\n : null\n : changedCheckInCustomerFields(storedRow, entry)\n if (patch) patches.push({ ref: doc.ref, patch: { ...patch, updatedAtMs: nowMs } })\n }\n }\n transaction.update(reservationRef, {\n guests,\n guestsChangedAtMs: nowMs,\n guestsChangedBy: door.uid,\n })\n for (const write of creates) transaction.create(write.ref, write.data)\n for (const ref of drops) transaction.delete(ref)\n for (const write of patches) transaction.update(write.ref, write.patch)\n return {\n status: 200,\n body: {\n reservationId,\n guests,\n previousGuests,\n checkIns: { added: creates.length, removed: drops.length },\n },\n activity: {\n previous: previousGuests,\n resourceName: resource?.name ?? '',\n arrivalDayMs: Number(reservation.checkInDayMs) || 0,\n },\n }\n })\n\n if (outcome.status === 200 && 'activity' in outcome && outcome.activity) {\n const { previous, resourceName, arrivalDayMs } = outcome.activity\n const arrival = arrivalDayMs ? new Date(arrivalDayMs).toISOString().slice(0, 10) : ''\n await logActivity(\n hostId,\n { uid: door.uid, email: door.email },\n `Changed a stay’s guests from ${previous} to ${guests}`,\n {\n type: 'commerce:reservation',\n id: reservationId,\n name: [resourceName || 'Stay', arrival].filter(Boolean).join(' · '),\n },\n )\n }\n return res.status(outcome.status).json(outcome.body)\n } catch (error) {\n console.error('Changing a stay’s guests failed', error)\n return res.status(500).json({ error: 'The guests could not be changed. Try again.' })\n }\n }\n}\n\nexport const reservationGuestsHandler = createReservationGuestsHandler()\n"],"names":["resolveSiteTimeZone","isHostPluginEnabled","zonedDayKey","logHostActivity","BUNDLE_ID","changedCheckInCustomerFields","checkInDayLabel","dueCheckInsForReservation","newCheckInDocument","reservationCheckInId","STAY_CHECK_IN_SETTINGS_DOC","stayCheckInPlan","storedStayCheckIns","readStayCheckInMode","reservationGuests","reservationGuestsProblem","stayChecksInPerGuest","reservationsOnPlan","bodyOf","gate","resolved","validId","WALK_IN_PERMISSION","WALK_IN_PLAN_REFUSAL","WALK_IN_PLUGIN_OFF","RESERVATION_GUESTS_GONE","RESERVATION_GUESTS_CLOSED","RESERVATION_GUESTS_PERMISSION_REFUSAL","refusal","RESERVATION_GUESTS_CHECK_IN_ROWS","OPEN_STATUSES","guestsBelowCheckedInMessage","checkedIn","dayKey","todayKey","when","createReservationGuestsHandler","options","req","res","method","status","json","error","deps","logActivity","body","hostId","reservationId","rawGuests","guests","Number","NaN","undefined","door","permission","org","host","data","db","firestore","hostRef","collection","doc","reservationRef","checkIns","timeZone","now","outcome","runTransaction","transaction","reservation","stay","get","exists","includes","resourceId","String","resourceSnapshot","settings","stored","Promise","all","where","limit","resource","problem","previousGuests","unchanged","mode","perGuest","changed","nowMs","byDay","Map","docs","set","creates","drops","patches","keys","sort","existing","due","resourceName","name","size","plan","unitCount","place","create","id","entry","push","ref","dropped","Set","drop","has","storedRow","patch","updatedAtMs","update","guestsChangedAtMs","guestsChangedBy","uid","write","delete","added","length","removed","activity","previous","arrivalDayMs","checkInDayMs","arrival","Date","toISOString","slice","email","type","filter","Boolean","join","console","reservationGuestsHandler"],"mappings":"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"}
@@ -16,12 +16,22 @@
16
16
  */
17
17
  import { type PluginApiHandler } from '@aglyn/aglyn/server';
18
18
  import * as CommerceModel from '../model';
19
- import { type ProductsWriteDeps } from './products-write';
19
+ import { type GatePermission, type ProductsWriteDeps } from './products-write';
20
20
  export declare const WALK_IN_GONE = "That resource is gone.";
21
21
  export declare const WALK_IN_TAKEN_ONE_UNIT = "Those dates are taken";
22
22
  export declare const WALK_IN_TAKEN_EVERY_UNIT = "Every unit is taken on at least one of those nights";
23
23
  export declare const WALK_IN_PLUGIN_OFF = "Reservations are not turned on for this site";
24
24
  export declare const WALK_IN_ID_CONFLICT = "That walk-in id belongs to another stay";
25
+ /**
26
+ * A member who does not hold "Book walk-ins and change guests" on the site
27
+ * (AGL-4047): the refusal names the permission and who can change it, never
28
+ * a role.
29
+ */
30
+ export declare const WALK_IN_PERMISSION_REFUSAL: string;
31
+ /** The key a walk-in and a guests change check, read as the rules read it. */
32
+ export declare const WALK_IN_PERMISSION: GatePermission;
33
+ /** A store whose plan does not take reservations, worded as the plan refusals are. */
34
+ export declare const WALK_IN_PLAN_REFUSAL = "Reservations are not included in your plan \u2014 see Billing";
25
35
  /** The refusal for dates with no free unit, worded for the resource. */
26
36
  export declare function walkInTakenMessage(resource: CommerceModel.HostResource): string;
27
37
  export declare function createReservationWalkInHandler(options?: ProductsWriteDeps): PluginApiHandler;
@@ -1,3 +1,4 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
1
2
  /**
2
3
  * @license
3
4
  * Copyright 2026 Aglyn LLC
@@ -17,7 +18,8 @@
17
18
  import { isHostPluginEnabled } from "@aglyn/aglyn/server";
18
19
  import { BUNDLE_ID } from "../constants/bundle-common.js";
19
20
  import * as CommerceModel from "../model/index.js";
20
- import { readLiveReservations, reservationAvailabilityQuery } from "./reservation-availability-query.js";
21
+ import { readLiveReservations, reservationAvailabilityQuery, reservationsOnPlan } from "./reservation-availability-query.js";
22
+ import { RESERVATION_SITE_ROLE_PRESET, reservationPermissionRefusal } from "../model/plugin-permissions.js";
21
23
  import { bodyOf, gate, resolved, validId } from "./products-write.js";
22
24
  /*
23
25
  * `POST /api/commerce/reservations/walk-in` (AGL-4046): a staff walk-in,
@@ -31,12 +33,17 @@ import { bodyOf, gate, resolved, validId } from "./products-write.js";
31
33
  * storefront's `/api/commerce/reserve` uses, so the loser's transaction re-runs
32
34
  * on the winner's write and is refused.
33
35
  *
34
- * Who may call it is who the Firestore rules let write a reservation from the
35
- * console: a verified member with a content-write role on the site
36
- * (`canWriteHostContent`: admin, editor, author), or staff, while the site,
37
- * its org and the platform are not frozen. That is `products-write.ts`'s
38
- * `gate`, reused rather than restated. The commerce plugin must also be on for
39
- * the site.
36
+ * Who may call it: a verified member who holds "Book walk-ins and change
37
+ * guests" (`commerce.walkIns`, AGL-4047) on the site, or staff, while the
38
+ * site, its org and the platform are not frozen. The key's preset is the
39
+ * site role that wrote a reservation before it was a key (Admin, Editor,
40
+ * Author), and it follows "Manage reservations" unless a role or member sets
41
+ * it, so nobody's access moved; a custom role can now grant it to the
42
+ * window's staff. That is `products-write.ts`'s `gate`, reused rather than
43
+ * restated, reading the key as the rules do. The commerce plugin must
44
+ * also be on for the site, and the store's plan must take reservations: the
45
+ * same `commerce` entitlement `/api/commerce/reserve` asks
46
+ * (`reservationsOnPlan`), so a lapsed plan books through neither door.
40
47
  *
41
48
  * The stay is written with exactly the fields the card wrote: confirmed, no
42
49
  * email, no deposit, nothing paid. Payment is collected at the register.
@@ -45,6 +52,17 @@ export const WALK_IN_TAKEN_ONE_UNIT = 'Those dates are taken';
45
52
  export const WALK_IN_TAKEN_EVERY_UNIT = 'Every unit is taken on at least one of those nights';
46
53
  export const WALK_IN_PLUGIN_OFF = 'Reservations are not turned on for this site';
47
54
  export const WALK_IN_ID_CONFLICT = 'That walk-in id belongs to another stay';
55
+ /**
56
+ * A member who does not hold "Book walk-ins and change guests" on the site
57
+ * (AGL-4047): the refusal names the permission and who can change it, never
58
+ * a role.
59
+ */ export const WALK_IN_PERMISSION_REFUSAL = reservationPermissionRefusal('commerce.walkIns');
60
+ /** The key a walk-in and a guests change check, read as the rules read it. */ export const WALK_IN_PERMISSION = {
61
+ key: 'commerce.walkIns',
62
+ presetFor: RESERVATION_SITE_ROLE_PRESET,
63
+ refusal: WALK_IN_PERMISSION_REFUSAL
64
+ };
65
+ /** A store whose plan does not take reservations, worded as the plan refusals are. */ export const WALK_IN_PLAN_REFUSAL = 'Reservations are not included in your plan — see Billing';
48
66
  /** The refusal for dates with no free unit, worded for the resource. */ export function walkInTakenMessage(resource) {
49
67
  return CommerceModel.resourceUnits(resource) > 1 ? WALK_IN_TAKEN_EVERY_UNIT : WALK_IN_TAKEN_ONE_UNIT;
50
68
  }
@@ -52,7 +70,12 @@ const dayOf = (value)=>{
52
70
  const ms = Number(value);
53
71
  return Number.isFinite(ms) && ms > 0 ? CommerceModel.toDayMs(ms) : 0;
54
72
  };
55
- export function createReservationWalkInHandler(options = {}) {
73
+ /*
74
+ * Body: `{ hostId, resourceId, checkInDayMs, checkOutDayMs, guestName?,
75
+ * guests?, reservationId? }`. `guests` (AGL-4043) is how many the stay is
76
+ * for, 1 up to what the resource sleeps; a stay checked in per guest makes a
77
+ * check-in for each.
78
+ */ export function createReservationWalkInHandler(options = {}) {
56
79
  return async (req, res)=>{
57
80
  if (req.method !== 'POST') {
58
81
  return res.status(405).json({
@@ -66,6 +89,10 @@ export function createReservationWalkInHandler(options = {}) {
66
89
  const checkInDayMs = dayOf(body['checkInDayMs']);
67
90
  const checkOutDayMs = dayOf(body['checkOutDayMs']);
68
91
  const guestName = typeof body['guestName'] === 'string' ? body['guestName'].trim().slice(0, 120) : '';
92
+ // How many guests (AGL-4043): optional, checked against what the
93
+ // resource sleeps once it is read.
94
+ const rawGuests = body['guests'];
95
+ const guestsAsked = rawGuests === undefined || rawGuests === null || rawGuests === '' ? undefined : Number(rawGuests);
69
96
  // Optional, client-minted: a retry of the same walk-in (a dropped
70
97
  // response on a weak signal) finds its own stay instead of booking a
71
98
  // second unit.
@@ -76,13 +103,23 @@ export function createReservationWalkInHandler(options = {}) {
76
103
  });
77
104
  }
78
105
  try {
79
- const door = await gate(req, res, hostId, deps);
106
+ const door = await gate(req, res, hostId, deps, {
107
+ permission: WALK_IN_PERMISSION
108
+ });
80
109
  if (!door) return;
81
110
  if (!isHostPluginEnabled(door.org, door.host.data(), BUNDLE_ID)) {
82
111
  return res.status(403).json({
83
112
  error: WALK_IN_PLUGIN_OFF
84
113
  });
85
114
  }
115
+ // The plan question every reservation door asks (AGL-1873), before
116
+ // anything is read or written. Staff impersonating a store still meet
117
+ // it: the walk-in books for the store, on the store's plan.
118
+ if (!reservationsOnPlan(door.org)) {
119
+ return res.status(403).json({
120
+ error: WALK_IN_PLAN_REFUSAL
121
+ });
122
+ }
86
123
  const db = deps.firestore();
87
124
  const hostRef = db.collection('hosts').doc(hostId);
88
125
  const resourceSnapshot = await hostRef.collection('resources').doc(resourceId).get();
@@ -98,6 +135,10 @@ export function createReservationWalkInHandler(options = {}) {
98
135
  if (quote.problem) return res.status(400).json({
99
136
  error: quote.problem
100
137
  });
138
+ const guestsProblem = CommerceModel.reservationGuestsProblem(guestsAsked, resource);
139
+ if (guestsProblem) return res.status(400).json({
140
+ error: guestsProblem
141
+ });
101
142
  const reservations = hostRef.collection('reservations');
102
143
  const availability = reservationAvailabilityQuery(reservations, resourceId, checkInDayMs);
103
144
  const reservationRef = reservations.doc(typeof requestedId === 'string' ? requestedId : createResourceUid());
@@ -132,19 +173,22 @@ export function createReservationWalkInHandler(options = {}) {
132
173
  }
133
174
  };
134
175
  }
135
- transaction.set(reservationRef, {
176
+ transaction.set(reservationRef, _extends({
136
177
  resourceId,
137
178
  status: 'confirmed',
138
179
  checkInDayMs,
139
180
  checkOutDayMs,
140
181
  guestName: guestName || null,
141
- guestEmail: null,
182
+ guestEmail: null
183
+ }, guestsAsked !== undefined ? {
184
+ guests: guestsAsked
185
+ } : {}, {
142
186
  nights: quote.nights,
143
187
  totalCents: quote.totalCents,
144
188
  depositCents: 0,
145
189
  paidCents: 0,
146
190
  createdAtMs: nowMs
147
- });
191
+ }));
148
192
  return {
149
193
  status: 200,
150
194
  body: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/reservation-walk-in.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 { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport { isHostPluginEnabled, type PluginApiHandler } from '@aglyn/aglyn/server'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport * as CommerceModel from '../model'\nimport {\n readLiveReservations,\n reservationAvailabilityQuery,\n} from './reservation-availability-query'\nimport { bodyOf, gate, resolved, validId, type ProductsWriteDeps } from './products-write'\n\n/*\n * `POST /api/commerce/reservations/walk-in` (AGL-4046): a staff walk-in,\n * race-safe.\n *\n * The console Reservations card and the native apps used to write a walk-in\n * straight from the client after their own availability read. Two staff on two\n * devices could both read the last free unit (the last RV hookup) and both\n * write a stay into it. This route re-asks availability INSIDE the transaction\n * that writes, on the same query and the same `isRangeAvailable` rule the\n * storefront's `/api/commerce/reserve` uses, so the loser's transaction re-runs\n * on the winner's write and is refused.\n *\n * Who may call it is who the Firestore rules let write a reservation from the\n * console: a verified member with a content-write role on the site\n * (`canWriteHostContent`: admin, editor, author), or staff, while the site,\n * its org and the platform are not frozen. That is `products-write.ts`'s\n * `gate`, reused rather than restated. The commerce plugin must also be on for\n * the site.\n *\n * The stay is written with exactly the fields the card wrote: confirmed, no\n * email, no deposit, nothing paid. Payment is collected at the register.\n */\n\nexport const WALK_IN_GONE = 'That resource is gone.'\nexport const WALK_IN_TAKEN_ONE_UNIT = 'Those dates are taken'\nexport const WALK_IN_TAKEN_EVERY_UNIT =\n 'Every unit is taken on at least one of those nights'\nexport const WALK_IN_PLUGIN_OFF = 'Reservations are not turned on for this site'\nexport const WALK_IN_ID_CONFLICT = 'That walk-in id belongs to another stay'\n\n/** The refusal for dates with no free unit, worded for the resource. */\nexport function walkInTakenMessage(resource: CommerceModel.HostResource): string {\n return CommerceModel.resourceUnits(resource) > 1\n ? WALK_IN_TAKEN_EVERY_UNIT\n : WALK_IN_TAKEN_ONE_UNIT\n}\n\nconst dayOf = (value: unknown): number => {\n const ms = Number(value)\n return Number.isFinite(ms) && ms > 0 ? CommerceModel.toDayMs(ms) : 0\n}\n\ntype Outcome =\n | { status: 200; body: { reservationId: string; replayed?: true } }\n | { status: 409; body: { error: string } }\n\nexport function createReservationWalkInHandler(\n options: ProductsWriteDeps = {},\n): PluginApiHandler {\n return async (req, res) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const deps = resolved(options)\n const body = bodyOf(req)\n const hostId = body['hostId']\n const resourceId = body['resourceId']\n const checkInDayMs = dayOf(body['checkInDayMs'])\n const checkOutDayMs = dayOf(body['checkOutDayMs'])\n const guestName =\n typeof body['guestName'] === 'string'\n ? body['guestName'].trim().slice(0, 120)\n : ''\n // Optional, client-minted: a retry of the same walk-in (a dropped\n // response on a weak signal) finds its own stay instead of booking a\n // second unit.\n const requestedId = body['reservationId']\n if (\n !validId(hostId) ||\n !validId(resourceId) ||\n !checkInDayMs ||\n !checkOutDayMs ||\n (requestedId !== undefined && requestedId !== null && !validId(requestedId))\n ) {\n return res.status(400).json({ error: 'Missing walk-in details' })\n }\n try {\n const door = await gate(req, res, hostId, deps)\n if (!door) return\n if (!isHostPluginEnabled(door.org as never, door.host.data() as never, BUNDLE_ID)) {\n return res.status(403).json({ error: WALK_IN_PLUGIN_OFF })\n }\n const db = deps.firestore()\n const hostRef = db.collection('hosts').doc(hostId)\n const resourceSnapshot = await hostRef.collection('resources').doc(resourceId).get()\n const resource = resourceSnapshot.data() as CommerceModel.HostResource | undefined\n if (!resourceSnapshot.exists || !resource) {\n return res.status(404).json({ error: WALK_IN_GONE })\n }\n // The one rule for what can be booked (no nights, under the minimum\n // stay), shared with the card, the widget and both native apps.\n const quote = CommerceModel.computeReservationQuote(resource, checkInDayMs, checkOutDayMs)\n if (quote.problem) return res.status(400).json({ error: quote.problem })\n\n const reservations = hostRef.collection('reservations')\n const availability = reservationAvailabilityQuery(reservations, resourceId, checkInDayMs)\n const reservationRef = reservations.doc(\n typeof requestedId === 'string' ? requestedId : createResourceUid(),\n )\n const outcome: Outcome = await db.runTransaction(async (transaction) => {\n const [existing, fresh] = await Promise.all([\n transaction.get(reservationRef),\n transaction.get(availability),\n ])\n if (existing.exists) {\n const same =\n existing.get('resourceId') === resourceId &&\n Number(existing.get('checkInDayMs')) === checkInDayMs &&\n Number(existing.get('checkOutDayMs')) === checkOutDayMs\n return same\n ? { status: 200, body: { reservationId: reservationRef.id, replayed: true } }\n : { status: 409, body: { error: WALK_IN_ID_CONFLICT } }\n }\n // Re-timed inside the transaction: a retry under contention runs\n // later, and a pending hold's 30-minute lapse is measured from now.\n const nowMs = deps.now()\n if (\n !CommerceModel.isRangeAvailable(\n resource,\n readLiveReservations(fresh),\n checkInDayMs,\n checkOutDayMs,\n nowMs,\n )\n ) {\n return { status: 409, body: { error: walkInTakenMessage(resource) } }\n }\n transaction.set(reservationRef, {\n resourceId,\n status: 'confirmed',\n checkInDayMs,\n checkOutDayMs,\n guestName: guestName || null,\n guestEmail: null,\n nights: quote.nights,\n totalCents: quote.totalCents,\n depositCents: 0,\n paidCents: 0,\n createdAtMs: nowMs,\n } satisfies CommerceModel.HostReservation)\n return { status: 200, body: { reservationId: reservationRef.id } }\n })\n return res.status(outcome.status).json(outcome.body)\n } catch (error) {\n console.error('Walk-in reservation failed', error)\n return res.status(500).json({ error: 'Walk-in failed' })\n }\n }\n}\n\nexport const reservationWalkInHandler = createReservationWalkInHandler()\n"],"names":["createResourceUid","isHostPluginEnabled","BUNDLE_ID","CommerceModel","readLiveReservations","reservationAvailabilityQuery","bodyOf","gate","resolved","validId","WALK_IN_GONE","WALK_IN_TAKEN_ONE_UNIT","WALK_IN_TAKEN_EVERY_UNIT","WALK_IN_PLUGIN_OFF","WALK_IN_ID_CONFLICT","walkInTakenMessage","resource","resourceUnits","dayOf","value","ms","Number","isFinite","toDayMs","createReservationWalkInHandler","options","req","res","method","status","json","error","deps","body","hostId","resourceId","checkInDayMs","checkOutDayMs","guestName","trim","slice","requestedId","undefined","door","org","host","data","db","firestore","hostRef","collection","doc","resourceSnapshot","get","exists","quote","computeReservationQuote","problem","reservations","availability","reservationRef","outcome","runTransaction","transaction","existing","fresh","Promise","all","same","reservationId","id","replayed","nowMs","now","isRangeAvailable","set","guestEmail","nights","totalCents","depositCents","paidCents","createdAtMs","console","reservationWalkInHandler"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/reservation-walk-in.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 { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport { isHostPluginEnabled, type PluginApiHandler } from '@aglyn/aglyn/server'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport * as CommerceModel from '../model'\nimport {\n readLiveReservations,\n reservationAvailabilityQuery,\n reservationsOnPlan,\n} from './reservation-availability-query'\nimport {\n RESERVATION_SITE_ROLE_PRESET,\n reservationPermissionRefusal,\n} from '../model/plugin-permissions'\nimport { bodyOf, gate, resolved, validId, type GatePermission, type ProductsWriteDeps } from './products-write'\n\n/*\n * `POST /api/commerce/reservations/walk-in` (AGL-4046): a staff walk-in,\n * race-safe.\n *\n * The console Reservations card and the native apps used to write a walk-in\n * straight from the client after their own availability read. Two staff on two\n * devices could both read the last free unit (the last RV hookup) and both\n * write a stay into it. This route re-asks availability INSIDE the transaction\n * that writes, on the same query and the same `isRangeAvailable` rule the\n * storefront's `/api/commerce/reserve` uses, so the loser's transaction re-runs\n * on the winner's write and is refused.\n *\n * Who may call it: a verified member who holds \"Book walk-ins and change\n * guests\" (`commerce.walkIns`, AGL-4047) on the site, or staff, while the\n * site, its org and the platform are not frozen. The key's preset is the\n * site role that wrote a reservation before it was a key (Admin, Editor,\n * Author), and it follows \"Manage reservations\" unless a role or member sets\n * it, so nobody's access moved; a custom role can now grant it to the\n * window's staff. That is `products-write.ts`'s `gate`, reused rather than\n * restated, reading the key as the rules do. The commerce plugin must\n * also be on for the site, and the store's plan must take reservations: the\n * same `commerce` entitlement `/api/commerce/reserve` asks\n * (`reservationsOnPlan`), so a lapsed plan books through neither door.\n *\n * The stay is written with exactly the fields the card wrote: confirmed, no\n * email, no deposit, nothing paid. Payment is collected at the register.\n */\n\nexport const WALK_IN_GONE = 'That resource is gone.'\nexport const WALK_IN_TAKEN_ONE_UNIT = 'Those dates are taken'\nexport const WALK_IN_TAKEN_EVERY_UNIT =\n 'Every unit is taken on at least one of those nights'\nexport const WALK_IN_PLUGIN_OFF = 'Reservations are not turned on for this site'\nexport const WALK_IN_ID_CONFLICT = 'That walk-in id belongs to another stay'\n/**\n * A member who does not hold \"Book walk-ins and change guests\" on the site\n * (AGL-4047): the refusal names the permission and who can change it, never\n * a role.\n */\nexport const WALK_IN_PERMISSION_REFUSAL = reservationPermissionRefusal('commerce.walkIns')\n\n/** The key a walk-in and a guests change check, read as the rules read it. */\nexport const WALK_IN_PERMISSION: GatePermission = {\n key: 'commerce.walkIns',\n presetFor: RESERVATION_SITE_ROLE_PRESET,\n refusal: WALK_IN_PERMISSION_REFUSAL,\n}\n/** A store whose plan does not take reservations, worded as the plan refusals are. */\nexport const WALK_IN_PLAN_REFUSAL = 'Reservations are not included in your plan — see Billing'\n\n/** The refusal for dates with no free unit, worded for the resource. */\nexport function walkInTakenMessage(resource: CommerceModel.HostResource): string {\n return CommerceModel.resourceUnits(resource) > 1\n ? WALK_IN_TAKEN_EVERY_UNIT\n : WALK_IN_TAKEN_ONE_UNIT\n}\n\nconst dayOf = (value: unknown): number => {\n const ms = Number(value)\n return Number.isFinite(ms) && ms > 0 ? CommerceModel.toDayMs(ms) : 0\n}\n\ntype Outcome =\n | { status: 200; body: { reservationId: string; replayed?: true } }\n | { status: 409; body: { error: string } }\n\n/*\n * Body: `{ hostId, resourceId, checkInDayMs, checkOutDayMs, guestName?,\n * guests?, reservationId? }`. `guests` (AGL-4043) is how many the stay is\n * for, 1 up to what the resource sleeps; a stay checked in per guest makes a\n * check-in for each.\n */\nexport function createReservationWalkInHandler(\n options: ProductsWriteDeps = {},\n): PluginApiHandler {\n return async (req, res) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const deps = resolved(options)\n const body = bodyOf(req)\n const hostId = body['hostId']\n const resourceId = body['resourceId']\n const checkInDayMs = dayOf(body['checkInDayMs'])\n const checkOutDayMs = dayOf(body['checkOutDayMs'])\n const guestName =\n typeof body['guestName'] === 'string'\n ? body['guestName'].trim().slice(0, 120)\n : ''\n // How many guests (AGL-4043): optional, checked against what the\n // resource sleeps once it is read.\n const rawGuests = body['guests']\n const guestsAsked =\n rawGuests === undefined || rawGuests === null || rawGuests === '' ? undefined : Number(rawGuests)\n // Optional, client-minted: a retry of the same walk-in (a dropped\n // response on a weak signal) finds its own stay instead of booking a\n // second unit.\n const requestedId = body['reservationId']\n if (\n !validId(hostId) ||\n !validId(resourceId) ||\n !checkInDayMs ||\n !checkOutDayMs ||\n (requestedId !== undefined && requestedId !== null && !validId(requestedId))\n ) {\n return res.status(400).json({ error: 'Missing walk-in details' })\n }\n try {\n const door = await gate(req, res, hostId, deps, { permission: WALK_IN_PERMISSION })\n if (!door) return\n if (!isHostPluginEnabled(door.org as never, door.host.data() as never, BUNDLE_ID)) {\n return res.status(403).json({ error: WALK_IN_PLUGIN_OFF })\n }\n // The plan question every reservation door asks (AGL-1873), before\n // anything is read or written. Staff impersonating a store still meet\n // it: the walk-in books for the store, on the store's plan.\n if (!reservationsOnPlan(door.org)) {\n return res.status(403).json({ error: WALK_IN_PLAN_REFUSAL })\n }\n const db = deps.firestore()\n const hostRef = db.collection('hosts').doc(hostId)\n const resourceSnapshot = await hostRef.collection('resources').doc(resourceId).get()\n const resource = resourceSnapshot.data() as CommerceModel.HostResource | undefined\n if (!resourceSnapshot.exists || !resource) {\n return res.status(404).json({ error: WALK_IN_GONE })\n }\n // The one rule for what can be booked (no nights, under the minimum\n // stay), shared with the card, the widget and both native apps.\n const quote = CommerceModel.computeReservationQuote(resource, checkInDayMs, checkOutDayMs)\n if (quote.problem) return res.status(400).json({ error: quote.problem })\n const guestsProblem = CommerceModel.reservationGuestsProblem(guestsAsked, resource)\n if (guestsProblem) return res.status(400).json({ error: guestsProblem })\n\n const reservations = hostRef.collection('reservations')\n const availability = reservationAvailabilityQuery(reservations, resourceId, checkInDayMs)\n const reservationRef = reservations.doc(\n typeof requestedId === 'string' ? requestedId : createResourceUid(),\n )\n const outcome: Outcome = await db.runTransaction(async (transaction) => {\n const [existing, fresh] = await Promise.all([\n transaction.get(reservationRef),\n transaction.get(availability),\n ])\n if (existing.exists) {\n const same =\n existing.get('resourceId') === resourceId &&\n Number(existing.get('checkInDayMs')) === checkInDayMs &&\n Number(existing.get('checkOutDayMs')) === checkOutDayMs\n return same\n ? { status: 200, body: { reservationId: reservationRef.id, replayed: true } }\n : { status: 409, body: { error: WALK_IN_ID_CONFLICT } }\n }\n // Re-timed inside the transaction: a retry under contention runs\n // later, and a pending hold's 30-minute lapse is measured from now.\n const nowMs = deps.now()\n if (\n !CommerceModel.isRangeAvailable(\n resource,\n readLiveReservations(fresh),\n checkInDayMs,\n checkOutDayMs,\n nowMs,\n )\n ) {\n return { status: 409, body: { error: walkInTakenMessage(resource) } }\n }\n transaction.set(reservationRef, {\n resourceId,\n status: 'confirmed',\n checkInDayMs,\n checkOutDayMs,\n guestName: guestName || null,\n guestEmail: null,\n ...(guestsAsked !== undefined ? { guests: guestsAsked } : {}),\n nights: quote.nights,\n totalCents: quote.totalCents,\n depositCents: 0,\n paidCents: 0,\n createdAtMs: nowMs,\n } satisfies CommerceModel.HostReservation)\n return { status: 200, body: { reservationId: reservationRef.id } }\n })\n return res.status(outcome.status).json(outcome.body)\n } catch (error) {\n console.error('Walk-in reservation failed', error)\n return res.status(500).json({ error: 'Walk-in failed' })\n }\n }\n}\n\nexport const reservationWalkInHandler = createReservationWalkInHandler()\n"],"names":["createResourceUid","isHostPluginEnabled","BUNDLE_ID","CommerceModel","readLiveReservations","reservationAvailabilityQuery","reservationsOnPlan","RESERVATION_SITE_ROLE_PRESET","reservationPermissionRefusal","bodyOf","gate","resolved","validId","WALK_IN_GONE","WALK_IN_TAKEN_ONE_UNIT","WALK_IN_TAKEN_EVERY_UNIT","WALK_IN_PLUGIN_OFF","WALK_IN_ID_CONFLICT","WALK_IN_PERMISSION_REFUSAL","WALK_IN_PERMISSION","key","presetFor","refusal","WALK_IN_PLAN_REFUSAL","walkInTakenMessage","resource","resourceUnits","dayOf","value","ms","Number","isFinite","toDayMs","createReservationWalkInHandler","options","req","res","method","status","json","error","deps","body","hostId","resourceId","checkInDayMs","checkOutDayMs","guestName","trim","slice","rawGuests","guestsAsked","undefined","requestedId","door","permission","org","host","data","db","firestore","hostRef","collection","doc","resourceSnapshot","get","exists","quote","computeReservationQuote","problem","guestsProblem","reservationGuestsProblem","reservations","availability","reservationRef","outcome","runTransaction","transaction","existing","fresh","Promise","all","same","reservationId","id","replayed","nowMs","now","isRangeAvailable","set","guestEmail","guests","nights","totalCents","depositCents","paidCents","createdAtMs","console","reservationWalkInHandler"],"mappings":"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"}