@unchainedshop/plugins 4.0.0-rc.9 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/lib/accounts/google-oauth.d.ts +4 -0
  2. package/lib/accounts/google-oauth.d.ts.map +1 -0
  3. package/lib/accounts/google-oauth.js +145 -0
  4. package/lib/accounts/google-oauth.js.map +1 -0
  5. package/lib/accounts/linkedin-oauth.d.ts +4 -0
  6. package/lib/accounts/linkedin-oauth.d.ts.map +1 -0
  7. package/lib/accounts/linkedin-oauth.js +82 -0
  8. package/lib/accounts/linkedin-oauth.js.map +1 -0
  9. package/lib/delivery/send-message.js.map +1 -1
  10. package/lib/enrollments/licensed.js +15 -2
  11. package/lib/enrollments/licensed.js.map +1 -1
  12. package/lib/files/gridfs/adapter.d.ts.map +1 -1
  13. package/lib/files/gridfs/adapter.js +11 -8
  14. package/lib/files/gridfs/adapter.js.map +1 -1
  15. package/lib/files/gridfs/gridfs-adapter.d.ts +3 -0
  16. package/lib/files/gridfs/gridfs-adapter.d.ts.map +1 -0
  17. package/lib/files/gridfs/gridfs-adapter.js +97 -0
  18. package/lib/files/gridfs/gridfs-adapter.js.map +1 -0
  19. package/lib/files/gridfs/gridfs-webhook.d.ts +11 -0
  20. package/lib/files/gridfs/gridfs-webhook.d.ts.map +1 -0
  21. package/lib/files/gridfs/gridfs-webhook.js +84 -0
  22. package/lib/files/gridfs/gridfs-webhook.js.map +1 -0
  23. package/lib/files/gridfs/handler-express.d.ts.map +1 -1
  24. package/lib/files/gridfs/handler-express.js +21 -25
  25. package/lib/files/gridfs/handler-express.js.map +1 -1
  26. package/lib/files/gridfs/handler-fastify.d.ts.map +1 -1
  27. package/lib/files/gridfs/handler-fastify.js +50 -13
  28. package/lib/files/gridfs/handler-fastify.js.map +1 -1
  29. package/lib/files/gridfs/module.d.ts +2 -2
  30. package/lib/files/minio/handler-express.d.ts.map +1 -1
  31. package/lib/files/minio/handler-express.js +4 -7
  32. package/lib/files/minio/handler-express.js.map +1 -1
  33. package/lib/files/minio/handler-fastify.js +2 -2
  34. package/lib/files/minio/handler-fastify.js.map +1 -1
  35. package/lib/files/minio/index.d.ts +1 -1
  36. package/lib/files/minio/index.d.ts.map +1 -1
  37. package/lib/files/minio/index.js +7 -7
  38. package/lib/files/minio/index.js.map +1 -1
  39. package/lib/files/minio/minio-adapter.d.ts +6 -0
  40. package/lib/files/minio/minio-adapter.d.ts.map +1 -0
  41. package/lib/files/minio/minio-adapter.js +181 -0
  42. package/lib/files/minio/minio-adapter.js.map +1 -0
  43. package/lib/files/minio/minio-webhook.d.ts +2 -0
  44. package/lib/files/minio/minio-webhook.d.ts.map +1 -0
  45. package/lib/files/minio/minio-webhook.js +33 -0
  46. package/lib/files/minio/minio-webhook.js.map +1 -0
  47. package/lib/filters/local-search.js +1 -1
  48. package/lib/filters/local-search.js.map +1 -1
  49. package/lib/filters/strict-equal.js +0 -18
  50. package/lib/filters/strict-equal.js.map +1 -1
  51. package/lib/payment/apple-iap/adapter.js +12 -10
  52. package/lib/payment/apple-iap/adapter.js.map +1 -1
  53. package/lib/payment/apple-iap/db/AppleTransactionsCollection.d.ts +1 -1
  54. package/lib/payment/apple-iap/db/AppleTransactionsCollection.d.ts.map +1 -1
  55. package/lib/payment/apple-iap/handler-express.d.ts.map +1 -1
  56. package/lib/payment/apple-iap/handler-express.js +14 -10
  57. package/lib/payment/apple-iap/handler-express.js.map +1 -1
  58. package/lib/payment/apple-iap/handler-fastify.d.ts.map +1 -1
  59. package/lib/payment/apple-iap/handler-fastify.js +15 -8
  60. package/lib/payment/apple-iap/handler-fastify.js.map +1 -1
  61. package/lib/payment/apple-iap/module/configureAppleTransactionsModule.d.ts +9 -0
  62. package/lib/payment/apple-iap/module/configureAppleTransactionsModule.d.ts.map +1 -0
  63. package/lib/payment/apple-iap/module/configureAppleTransactionsModule.js +17 -0
  64. package/lib/payment/apple-iap/module/configureAppleTransactionsModule.js.map +1 -0
  65. package/lib/payment/apple-iap/module.d.ts +4 -4
  66. package/lib/payment/apple-iap/module.d.ts.map +1 -1
  67. package/lib/payment/apple-iap/module.js +4 -2
  68. package/lib/payment/apple-iap/module.js.map +1 -1
  69. package/lib/payment/braintree.js +3 -1
  70. package/lib/payment/braintree.js.map +1 -1
  71. package/lib/payment/cryptopay/db/CryptopayTransactions.d.ts +1 -1
  72. package/lib/payment/cryptopay/db/CryptopayTransactions.d.ts.map +1 -1
  73. package/lib/payment/cryptopay/derive-btc-address.d.ts.map +1 -1
  74. package/lib/payment/cryptopay/derive-btc-address.js +2 -3
  75. package/lib/payment/cryptopay/derive-btc-address.js.map +1 -1
  76. package/lib/payment/cryptopay/derive-eth-address.d.ts.map +1 -1
  77. package/lib/payment/cryptopay/derive-eth-address.js +5 -3
  78. package/lib/payment/cryptopay/derive-eth-address.js.map +1 -1
  79. package/lib/payment/cryptopay/handle-webhook.js +2 -2
  80. package/lib/payment/cryptopay/handle-webhook.js.map +1 -1
  81. package/lib/payment/cryptopay/handler-express.d.ts.map +1 -1
  82. package/lib/payment/cryptopay/handler-express.js +4 -7
  83. package/lib/payment/cryptopay/handler-express.js.map +1 -1
  84. package/lib/payment/cryptopay/handler-fastify.js +1 -1
  85. package/lib/payment/cryptopay/handler-fastify.js.map +1 -1
  86. package/lib/payment/cryptopay/middleware.d.ts +2 -0
  87. package/lib/payment/cryptopay/middleware.d.ts.map +1 -0
  88. package/lib/payment/cryptopay/middleware.js +75 -0
  89. package/lib/payment/cryptopay/middleware.js.map +1 -0
  90. package/lib/payment/cryptopay/module/configureCryptopayModule.d.ts +25 -0
  91. package/lib/payment/cryptopay/module/configureCryptopayModule.d.ts.map +1 -0
  92. package/lib/payment/cryptopay/module/configureCryptopayModule.js +75 -0
  93. package/lib/payment/cryptopay/module/configureCryptopayModule.js.map +1 -0
  94. package/lib/payment/cryptopay/module.d.ts +2 -2
  95. package/lib/payment/cryptopay/module.d.ts.map +1 -1
  96. package/lib/payment/cryptopay/module.js +4 -4
  97. package/lib/payment/cryptopay/module.js.map +1 -1
  98. package/lib/payment/cryptopay/plugin.d.ts.map +1 -1
  99. package/lib/payment/cryptopay/plugin.js +18 -4
  100. package/lib/payment/cryptopay/plugin.js.map +1 -1
  101. package/lib/payment/datatrans-v2/handler-express.d.ts.map +1 -1
  102. package/lib/payment/datatrans-v2/handler-express.js +13 -11
  103. package/lib/payment/datatrans-v2/handler-express.js.map +1 -1
  104. package/lib/payment/datatrans-v2/handler-fastify.d.ts.map +1 -1
  105. package/lib/payment/datatrans-v2/handler-fastify.js +11 -5
  106. package/lib/payment/datatrans-v2/handler-fastify.js.map +1 -1
  107. package/lib/payment/datatrans-v2/index.js +63 -37
  108. package/lib/payment/datatrans-v2/index.js.map +1 -1
  109. package/lib/payment/datatrans-v2/middleware.d.ts +2 -0
  110. package/lib/payment/datatrans-v2/middleware.d.ts.map +1 -0
  111. package/lib/payment/datatrans-v2/middleware.js +68 -0
  112. package/lib/payment/datatrans-v2/middleware.js.map +1 -0
  113. package/lib/payment/datatrans-v2/parseRegistrationData.d.ts +1 -1
  114. package/lib/payment/datatrans-v2/parseRegistrationData.d.ts.map +1 -1
  115. package/lib/payment/paypal-checkout.js +4 -2
  116. package/lib/payment/paypal-checkout.js.map +1 -1
  117. package/lib/payment/payrexx/api/index.d.ts +1 -1
  118. package/lib/payment/payrexx/api/index.d.ts.map +1 -1
  119. package/lib/payment/payrexx/api/makeFetcher.d.ts +1 -1
  120. package/lib/payment/payrexx/api/makeFetcher.d.ts.map +1 -1
  121. package/lib/payment/payrexx/api/makeFetcher.js +1 -1
  122. package/lib/payment/payrexx/api/makeFetcher.js.map +1 -1
  123. package/lib/payment/payrexx/handler-express.d.ts.map +1 -1
  124. package/lib/payment/payrexx/handler-express.js +15 -15
  125. package/lib/payment/payrexx/handler-express.js.map +1 -1
  126. package/lib/payment/payrexx/handler-fastify.js +23 -15
  127. package/lib/payment/payrexx/handler-fastify.js.map +1 -1
  128. package/lib/payment/payrexx/index.js +21 -15
  129. package/lib/payment/payrexx/index.js.map +1 -1
  130. package/lib/payment/payrexx/middleware.d.ts +2 -0
  131. package/lib/payment/payrexx/middleware.d.ts.map +1 -0
  132. package/lib/payment/payrexx/middleware.js +86 -0
  133. package/lib/payment/payrexx/middleware.js.map +1 -0
  134. package/lib/payment/postfinance-checkout/api-client.d.ts.map +1 -1
  135. package/lib/payment/postfinance-checkout/api-client.js +7 -7
  136. package/lib/payment/postfinance-checkout/api-client.js.map +1 -1
  137. package/lib/payment/postfinance-checkout/handler-express.js +7 -8
  138. package/lib/payment/postfinance-checkout/handler-express.js.map +1 -1
  139. package/lib/payment/postfinance-checkout/handler-fastify.d.ts.map +1 -1
  140. package/lib/payment/postfinance-checkout/handler-fastify.js +6 -4
  141. package/lib/payment/postfinance-checkout/handler-fastify.js.map +1 -1
  142. package/lib/payment/postfinance-checkout/index.d.ts.map +1 -1
  143. package/lib/payment/postfinance-checkout/index.js +20 -7
  144. package/lib/payment/postfinance-checkout/index.js.map +1 -1
  145. package/lib/payment/postfinance-checkout/middleware.d.ts +2 -0
  146. package/lib/payment/postfinance-checkout/middleware.d.ts.map +1 -0
  147. package/lib/payment/postfinance-checkout/middleware.js +38 -0
  148. package/lib/payment/postfinance-checkout/middleware.js.map +1 -0
  149. package/lib/payment/saferpay/adapter.d.ts.map +1 -1
  150. package/lib/payment/saferpay/adapter.js +9 -0
  151. package/lib/payment/saferpay/adapter.js.map +1 -1
  152. package/lib/payment/saferpay/handler-express.d.ts.map +1 -1
  153. package/lib/payment/saferpay/handler-express.js +10 -8
  154. package/lib/payment/saferpay/handler-express.js.map +1 -1
  155. package/lib/payment/saferpay/handler-fastify.d.ts.map +1 -1
  156. package/lib/payment/saferpay/handler-fastify.js +11 -5
  157. package/lib/payment/saferpay/handler-fastify.js.map +1 -1
  158. package/lib/payment/saferpay/middleware.d.ts +2 -0
  159. package/lib/payment/saferpay/middleware.d.ts.map +1 -0
  160. package/lib/payment/saferpay/middleware.js +57 -0
  161. package/lib/payment/saferpay/middleware.js.map +1 -0
  162. package/lib/payment/saferpay/module/configureSaferpayTransactionsModule.d.ts +10 -0
  163. package/lib/payment/saferpay/module/configureSaferpayTransactionsModule.d.ts.map +1 -0
  164. package/lib/payment/saferpay/module/configureSaferpayTransactionsModule.js +24 -0
  165. package/lib/payment/saferpay/module/configureSaferpayTransactionsModule.js.map +1 -0
  166. package/lib/payment/saferpay/module.d.ts +2 -2
  167. package/lib/payment/stripe/handler-express.js +25 -17
  168. package/lib/payment/stripe/handler-express.js.map +1 -1
  169. package/lib/payment/stripe/handler-fastify.d.ts.map +1 -1
  170. package/lib/payment/stripe/handler-fastify.js +33 -12
  171. package/lib/payment/stripe/handler-fastify.js.map +1 -1
  172. package/lib/payment/stripe/index.js +21 -15
  173. package/lib/payment/stripe/index.js.map +1 -1
  174. package/lib/payment/stripe/middleware.d.ts +6 -0
  175. package/lib/payment/stripe/middleware.d.ts.map +1 -0
  176. package/lib/payment/stripe/middleware.js +114 -0
  177. package/lib/payment/stripe/middleware.js.map +1 -0
  178. package/lib/payment/stripe/stripe.d.ts +2 -2
  179. package/lib/payment/stripe/stripe.d.ts.map +1 -1
  180. package/lib/payment/stripe/stripe.js +14 -11
  181. package/lib/payment/stripe/stripe.js.map +1 -1
  182. package/lib/plugins-index.d.ts +48 -0
  183. package/lib/plugins-index.d.ts.map +1 -0
  184. package/lib/plugins-index.js +107 -0
  185. package/lib/plugins-index.js.map +1 -0
  186. package/lib/presets/all.d.ts +5 -5
  187. package/lib/presets/all.d.ts.map +1 -1
  188. package/lib/pricing/delivery-swiss-tax.d.ts.map +1 -1
  189. package/lib/pricing/delivery-swiss-tax.js +13 -20
  190. package/lib/pricing/delivery-swiss-tax.js.map +1 -1
  191. package/lib/pricing/order-discount.d.ts.map +1 -1
  192. package/lib/pricing/order-discount.js +5 -3
  193. package/lib/pricing/order-discount.js.map +1 -1
  194. package/lib/pricing/order-round.d.ts.map +1 -1
  195. package/lib/pricing/order-round.js +4 -3
  196. package/lib/pricing/order-round.js.map +1 -1
  197. package/lib/pricing/product-catalog-price-options.d.ts +2 -0
  198. package/lib/pricing/product-catalog-price-options.d.ts.map +1 -0
  199. package/lib/pricing/product-catalog-price-options.js +52 -0
  200. package/lib/pricing/product-catalog-price-options.js.map +1 -0
  201. package/lib/pricing/product-catalog-price.d.ts.map +1 -1
  202. package/lib/pricing/product-catalog-price.js +26 -2
  203. package/lib/pricing/product-catalog-price.js.map +1 -1
  204. package/lib/pricing/product-price-rateconversion.js +3 -3
  205. package/lib/pricing/product-price-rateconversion.js.map +1 -1
  206. package/lib/pricing/product-swiss-tax.d.ts +1 -5
  207. package/lib/pricing/product-swiss-tax.d.ts.map +1 -1
  208. package/lib/pricing/product-swiss-tax.js +26 -22
  209. package/lib/pricing/product-swiss-tax.js.map +1 -1
  210. package/lib/pricing/tax/ch.d.ts +7 -2
  211. package/lib/pricing/tax/ch.d.ts.map +1 -1
  212. package/lib/pricing/tax/ch.js +16 -1
  213. package/lib/pricing/tax/ch.js.map +1 -1
  214. package/lib/pricing/utils/isDeliveryAddressInCountry.d.ts +7 -0
  215. package/lib/pricing/utils/isDeliveryAddressInCountry.d.ts.map +1 -0
  216. package/lib/pricing/utils/isDeliveryAddressInCountry.js +13 -0
  217. package/lib/pricing/utils/isDeliveryAddressInCountry.js.map +1 -0
  218. package/lib/warehousing/eth-minter.js +23 -11
  219. package/lib/warehousing/eth-minter.js.map +1 -1
  220. package/lib/worker/bulk-import.d.ts +1 -1
  221. package/lib/worker/bulk-import.d.ts.map +1 -1
  222. package/lib/worker/bulk-import.js +11 -33
  223. package/lib/worker/bulk-import.js.map +1 -1
  224. package/lib/worker/email.d.ts.map +1 -1
  225. package/lib/worker/email.js +25 -7
  226. package/lib/worker/email.js.map +1 -1
  227. package/lib/worker/enrollment-order-generator.d.ts.map +1 -1
  228. package/lib/worker/enrollment-order-generator.js +7 -49
  229. package/lib/worker/enrollment-order-generator.js.map +1 -1
  230. package/lib/worker/error-notifications.js +1 -1
  231. package/lib/worker/error-notifications.js.map +1 -1
  232. package/lib/worker/export-token.d.ts.map +1 -1
  233. package/lib/worker/export-token.js +0 -1
  234. package/lib/worker/export-token.js.map +1 -1
  235. package/lib/worker/message.d.ts +1 -1
  236. package/lib/worker/message.d.ts.map +1 -1
  237. package/lib/worker/message.js +4 -2
  238. package/lib/worker/message.js.map +1 -1
  239. package/lib/worker/sms.js +17 -17
  240. package/lib/worker/sms.js.map +1 -1
  241. package/lib/worker/twilio.js +4 -0
  242. package/lib/worker/twilio.js.map +1 -1
  243. package/package.json +22 -33
  244. package/src/delivery/send-message.ts +1 -1
  245. package/src/enrollments/licensed.ts +15 -2
  246. package/src/files/gridfs/adapter.ts +12 -7
  247. package/src/files/gridfs/handler-express.ts +23 -25
  248. package/src/files/gridfs/handler-fastify.ts +53 -14
  249. package/src/files/minio/handler-express.ts +4 -7
  250. package/src/files/minio/handler-fastify.ts +2 -2
  251. package/src/files/minio/index.ts +16 -16
  252. package/src/filters/local-search.ts +1 -1
  253. package/src/filters/strict-equal.ts +0 -21
  254. package/src/payment/apple-iap/adapter.ts +12 -14
  255. package/src/payment/apple-iap/db/AppleTransactionsCollection.ts +1 -1
  256. package/src/payment/apple-iap/handler-express.ts +17 -11
  257. package/src/payment/apple-iap/handler-fastify.ts +19 -9
  258. package/src/payment/apple-iap/module.ts +9 -4
  259. package/src/payment/braintree.ts +4 -1
  260. package/src/payment/cryptopay/db/CryptopayTransactions.ts +1 -1
  261. package/src/payment/cryptopay/derive-btc-address.ts +1 -3
  262. package/src/payment/cryptopay/derive-eth-address.ts +5 -3
  263. package/src/payment/cryptopay/handle-webhook.ts +6 -6
  264. package/src/payment/cryptopay/handler-express.ts +4 -7
  265. package/src/payment/cryptopay/handler-fastify.ts +1 -1
  266. package/src/payment/cryptopay/module.ts +8 -5
  267. package/src/payment/cryptopay/plugin.ts +21 -4
  268. package/src/payment/datatrans-v2/handler-express.ts +17 -12
  269. package/src/payment/datatrans-v2/handler-fastify.ts +15 -6
  270. package/src/payment/datatrans-v2/index.ts +82 -50
  271. package/src/payment/paypal-checkout.ts +4 -2
  272. package/src/payment/payrexx/api/index.ts +1 -1
  273. package/src/payment/payrexx/api/makeFetcher.ts +2 -2
  274. package/src/payment/payrexx/handler-express.ts +24 -32
  275. package/src/payment/payrexx/handler-fastify.ts +33 -33
  276. package/src/payment/payrexx/index.ts +26 -16
  277. package/src/payment/postfinance-checkout/api-client.ts +13 -8
  278. package/src/payment/postfinance-checkout/handler-express.ts +8 -8
  279. package/src/payment/postfinance-checkout/handler-fastify.ts +7 -4
  280. package/src/payment/postfinance-checkout/index.ts +20 -8
  281. package/src/payment/saferpay/adapter.ts +14 -2
  282. package/src/payment/saferpay/handler-express.ts +14 -13
  283. package/src/payment/saferpay/handler-fastify.ts +14 -9
  284. package/src/payment/stripe/handler-express.ts +33 -33
  285. package/src/payment/stripe/handler-fastify.ts +40 -27
  286. package/src/payment/stripe/index.ts +18 -16
  287. package/src/payment/stripe/stripe.ts +17 -12
  288. package/src/pricing/delivery-swiss-tax.ts +16 -31
  289. package/src/pricing/order-discount.ts +6 -4
  290. package/src/pricing/order-round.ts +5 -4
  291. package/src/pricing/product-catalog-price-options.ts +67 -0
  292. package/src/pricing/product-catalog-price.ts +25 -2
  293. package/src/pricing/product-price-rateconversion.ts +3 -3
  294. package/src/pricing/product-swiss-tax.ts +39 -40
  295. package/src/pricing/tax/ch.ts +33 -7
  296. package/src/pricing/utils/isDeliveryAddressInCountry.test.ts +106 -0
  297. package/src/pricing/utils/isDeliveryAddressInCountry.ts +26 -0
  298. package/src/warehousing/eth-minter.ts +30 -11
  299. package/src/worker/budgetsms.ts +1 -1
  300. package/src/worker/bulk-import.ts +12 -53
  301. package/src/worker/email.ts +30 -8
  302. package/src/worker/enrollment-order-generator.ts +14 -72
  303. package/src/worker/error-notifications.ts +2 -2
  304. package/src/worker/export-token.ts +0 -1
  305. package/src/worker/message.ts +5 -3
  306. package/src/worker/twilio.ts +10 -3
  307. package/src/pricing/product-swiss-tax.test.ts +0 -139
@@ -3,7 +3,7 @@ import { createLogger } from '@unchainedshop/logger';
3
3
  import stripeClient from './stripe.js';
4
4
  import { FastifyRequest, RouteHandlerMethod } from 'fastify';
5
5
 
6
- const logger = createLogger('unchained:core-payment:stripe:handler');
6
+ const logger = createLogger('unchained:stripe:handler');
7
7
 
8
8
  export const WebhookEventTypes = {
9
9
  PAYMENT_INTENT_SUCCEEDED: 'payment_intent.succeeded',
@@ -24,11 +24,21 @@ export const stripeHandler: RouteHandlerMethod = async (
24
24
  try {
25
25
  const stripe = stripeClient();
26
26
  const sig = req.headers['stripe-signature'];
27
+ if (!process.env.STRIPE_ENDPOINT_SECRET) {
28
+ throw new Error('env STRIPE_ENDPOINT_SECRET is required for webhook handling');
29
+ }
30
+ if (!sig) {
31
+ throw new Error('stripe-signature header was not provided for webhook');
32
+ }
27
33
  event = stripe.webhooks.constructEvent(req.body as string, sig, process.env.STRIPE_ENDPOINT_SECRET);
28
34
  } catch (err) {
29
35
  logger.error(`Error constructing event: ${err.message}`);
30
36
  reply.status(400);
31
- return reply.send(err.message);
37
+ return reply.send({
38
+ success: false,
39
+ message: err.message,
40
+ name: err.name,
41
+ });
32
42
  }
33
43
 
34
44
  if (!Object.values(WebhookEventTypes).includes(event.type)) {
@@ -36,12 +46,12 @@ export const stripeHandler: RouteHandlerMethod = async (
36
46
  type: event.type,
37
47
  });
38
48
  reply.status(200);
39
- return reply.send(
40
- JSON.stringify({
41
- ignored: true,
42
- message: `Unhandled event type: ${event.type}. Supported types: ${Object.values(WebhookEventTypes).join(', ')}`,
43
- }),
44
- );
49
+ return reply.send({
50
+ success: false,
51
+ ignored: true,
52
+ name: 'UNHANDLED_EVENT_TYPE',
53
+ message: `Unhandled event type: ${event.type}. Supported types: ${Object.values(WebhookEventTypes).join(', ')}`,
54
+ });
45
55
  }
46
56
 
47
57
  const environmentInMetadata = event.data?.object?.metadata?.environment || '';
@@ -52,12 +62,12 @@ export const stripeHandler: RouteHandlerMethod = async (
52
62
  environment: environmentInMetadata,
53
63
  });
54
64
  reply.status(200);
55
- return reply.send(
56
- JSON.stringify({
57
- ignored: true,
58
- message: `Unhandled event environment: ${environmentInMetadata}. Supported environment: ${environmentInEnv}`,
59
- }),
60
- );
65
+ return reply.send({
66
+ success: false,
67
+ ignored: true,
68
+ name: 'UNHANDLED_EVENT_ENVIRONMENT',
69
+ message: `Unhandled event environment: ${environmentInMetadata}. Supported environment: ${environmentInEnv}`,
70
+ });
61
71
  }
62
72
 
63
73
  logger.info(`Processing event`, {
@@ -87,18 +97,18 @@ export const stripeHandler: RouteHandlerMethod = async (
87
97
  },
88
98
  });
89
99
 
100
+ if (!order) throw new Error(`Order with id ${orderPayment.orderId} not found`);
101
+
90
102
  logger.info(`checkout successful`, {
91
103
  orderPaymentId,
92
104
  orderId: order._id,
93
105
  type: event.type,
94
106
  });
95
107
  reply.status(200);
96
- return reply.send(
97
- JSON.stringify({
98
- message: 'checkout successful',
99
- orderId: order._id,
100
- }),
101
- );
108
+ return reply.send({
109
+ success: true,
110
+ orderId: order._id,
111
+ });
102
112
  } else if (event.type === WebhookEventTypes.SETUP_INTENT_SUCCEEDED) {
103
113
  const setupIntent = event.data.object;
104
114
  const { paymentProviderId, userId } = setupIntent.metadata || {};
@@ -122,18 +132,21 @@ export const stripeHandler: RouteHandlerMethod = async (
122
132
  type: event.type,
123
133
  });
124
134
  reply.status(200);
125
- return reply.send(
126
- JSON.stringify({
127
- message: 'payment credentials registration successful',
128
- paymentCredentialsId: paymentCredentials?._id,
129
- }),
130
- );
135
+ return reply.send({
136
+ success: true,
137
+ message: 'payment credentials registration successful',
138
+ paymentCredentialsId: paymentCredentials?._id,
139
+ });
131
140
  }
132
141
  } catch (error) {
133
142
  logger.error(error, {
134
143
  type: event.type,
135
144
  });
136
145
  reply.status(500);
137
- return reply.send(error.message);
146
+ return reply.send({
147
+ success: false,
148
+ message: error.message,
149
+ name: error.name,
150
+ });
138
151
  }
139
152
  };
@@ -8,7 +8,7 @@ import {
8
8
  PaymentError,
9
9
  } from '@unchainedshop/core';
10
10
 
11
- const logger = createLogger('unchained:core-payment:stripe');
11
+ const logger = createLogger('unchained:stripe');
12
12
 
13
13
  const Stripe: IPaymentAdapter = {
14
14
  ...PaymentAdapter,
@@ -24,13 +24,14 @@ const Stripe: IPaymentAdapter = {
24
24
  actions: (config, context) => {
25
25
  const { modules } = context;
26
26
 
27
- const descriptorPrefix = config.find(({ key }) => key === 'descriptorPrefix')?.value;
27
+ const descriptorPrefix = config.find(({ key }) => key === 'descriptorPrefix')?.value || '';
28
28
 
29
- const getUserData = async (forcedUserId) => {
29
+ const assertUserData = async (forcedUserId) => {
30
30
  const userId = forcedUserId || context?.userId;
31
31
  const user = await modules.users.findUserById(userId);
32
+ if (!user) throw new Error('User not found');
32
33
  const email = modules.users.primaryEmail(user)?.address;
33
- const name = user.profile.displayName || user.username || email;
34
+ const name = user.profile?.displayName || user.username || email;
34
35
  return {
35
36
  email,
36
37
  name,
@@ -41,8 +42,9 @@ const Stripe: IPaymentAdapter = {
41
42
  ...PaymentAdapter.actions(config, context),
42
43
 
43
44
  configurationError() {
44
- const stripe = stripeClient();
45
- if (!stripe) {
45
+ try {
46
+ stripeClient();
47
+ } catch {
46
48
  return PaymentError.INCOMPLETE_CONFIGURATION;
47
49
  }
48
50
  return null;
@@ -86,13 +88,13 @@ const Stripe: IPaymentAdapter = {
86
88
 
87
89
  sign: async (transactionContext = {}) => {
88
90
  const { orderPayment, order, paymentProviderId } = context;
89
-
91
+ const { userId, name, email } = await assertUserData(order?.userId);
90
92
  if (orderPayment) {
93
+ if (!order) throw new Error('order not found in context');
91
94
  const pricing = OrderPricingSheet({
92
- calculation: order.calculation,
93
- currencyCode: order.currencyCode,
95
+ calculation: order?.calculation,
96
+ currencyCode: order?.currencyCode,
94
97
  });
95
- const { userId, name, email } = await getUserData(order?.userId);
96
98
  const paymentIntent = await createOrderPaymentIntent(
97
99
  { userId, name, email, order, orderPayment, pricing, descriptorPrefix },
98
100
  transactionContext,
@@ -100,7 +102,6 @@ const Stripe: IPaymentAdapter = {
100
102
  return paymentIntent.client_secret;
101
103
  }
102
104
 
103
- const { userId, name, email } = await getUserData(order?.userId);
104
105
  const paymentIntent = await createRegistrationIntent(
105
106
  { userId, name, email, paymentProviderId, descriptorPrefix },
106
107
  transactionContext,
@@ -114,11 +115,12 @@ const Stripe: IPaymentAdapter = {
114
115
  throw new Error('You have to provide paymentIntentId or paymentCredentials');
115
116
  }
116
117
 
117
- const { order } = context;
118
- const orderPayment = await modules.orders.payments.findOrderPayment({
119
- orderPaymentId: order.paymentId,
120
- });
121
- const { userId, name, email } = await getUserData(order?.userId);
118
+ const { order, orderPayment } = context;
119
+
120
+ if (!order) throw new Error('order not found in context');
121
+ if (!orderPayment) throw new Error('orderPayment not found in context');
122
+
123
+ const { userId, name, email } = await assertUserData(order?.userId);
122
124
  const pricing = OrderPricingSheet({
123
125
  calculation: order.calculation,
124
126
  currencyCode: order.currencyCode,
@@ -3,29 +3,32 @@ import { Order, OrderPayment } from '@unchainedshop/core-orders';
3
3
  import { createLogger } from '@unchainedshop/logger';
4
4
  import { Stripe as StripeType } from 'stripe';
5
5
 
6
- const logger = createLogger('unchained:plugins:payment:stripe');
6
+ const logger = createLogger('unchained:stripe');
7
7
 
8
8
  const { STRIPE_SECRET, STRIPE_WEBHOOK_ENVIRONMENT, EMAIL_WEBSITE_NAME } = process.env;
9
9
 
10
10
  let stripe: Awaited<ReturnType<typeof initStripeClient>> | null;
11
11
 
12
- export const initStripeClient = async (): Promise<StripeType> => {
12
+ export const initStripeClient = async (): Promise<StripeType | null> => {
13
13
  if (!STRIPE_SECRET) {
14
14
  logger.warn('STRIPE_SECRET is not set, skipping initialization');
15
- return null;
15
+ return Promise.resolve(null);
16
16
  }
17
17
  // eslint-disable-next-line
18
18
  // @ts-ignore
19
19
  const { default: Stripe } = await import('stripe');
20
20
  stripe = new Stripe(STRIPE_SECRET, {
21
- apiVersion: '2025-06-30.basil',
21
+ apiVersion: '2025-09-30.clover',
22
22
  });
23
23
  return stripe;
24
24
  };
25
25
 
26
26
  initStripeClient().catch(logger.warn);
27
27
 
28
- export default function () {
28
+ export default function getStripe() {
29
+ if (!stripe) {
30
+ throw new Error('Stripe client not initialized');
31
+ }
29
32
  return stripe;
30
33
  }
31
34
 
@@ -33,7 +36,7 @@ const environment = STRIPE_WEBHOOK_ENVIRONMENT ?? null;
33
36
 
34
37
  export const upsertCustomer = async ({ userId, name, email }): Promise<string> => {
35
38
  try {
36
- const { data } = await stripe.customers.search({ query: `metadata["userId"]:"${userId}"` });
39
+ const { data } = await getStripe().customers.search({ query: `metadata["userId"]:"${userId}"` });
37
40
  const existingCustomer = data[0];
38
41
 
39
42
  if (
@@ -41,7 +44,7 @@ export const upsertCustomer = async ({ userId, name, email }): Promise<string> =
41
44
  existingCustomer.email !== email ||
42
45
  existingCustomer.metadata.environment !== environment
43
46
  ) {
44
- const updatedCustomer = await stripe.customers.update(existingCustomer.id, {
47
+ const updatedCustomer = await getStripe().customers.update(existingCustomer.id, {
45
48
  metadata: {
46
49
  userId,
47
50
  environment,
@@ -54,7 +57,7 @@ export const upsertCustomer = async ({ userId, name, email }): Promise<string> =
54
57
 
55
58
  return existingCustomer.id;
56
59
  } catch {
57
- const customer = await stripe.customers.create({
60
+ const customer = await getStripe().customers.create({
58
61
  metadata: {
59
62
  userId,
60
63
  environment: STRIPE_WEBHOOK_ENVIRONMENT ?? null,
@@ -83,9 +86,10 @@ export const createRegistrationIntent = async (
83
86
  options: Record<string, any> = {},
84
87
  ) => {
85
88
  const customer = options?.customer || (await upsertCustomer({ userId, name, email }));
86
- const description = `${descriptorPrefix || EMAIL_WEBSITE_NAME || 'Unchained'}`.trim();
89
+ const description =
90
+ `${options?.description || descriptorPrefix || EMAIL_WEBSITE_NAME || 'Unchained'}`.trim();
87
91
 
88
- const setupIntent = await stripe.setupIntents.create({
92
+ const setupIntent = await getStripe().setupIntents.create({
89
93
  description,
90
94
  customer,
91
95
  metadata: {
@@ -119,12 +123,13 @@ export const createOrderPaymentIntent = async (
119
123
  },
120
124
  options: Record<string, any> = {},
121
125
  ) => {
122
- const description = `${descriptorPrefix || EMAIL_WEBSITE_NAME || 'Unchained'}`.trim();
126
+ const description =
127
+ `${options?.description || descriptorPrefix || EMAIL_WEBSITE_NAME || 'Unchained'}`.trim();
123
128
  const customer = options?.customer || (await upsertCustomer({ userId, name, email }));
124
129
 
125
130
  const { currencyCode, amount } = pricing.total({ useNetPrice: false });
126
131
 
127
- const paymentIntent = await stripe.paymentIntents.create({
132
+ const paymentIntent = await getStripe().paymentIntents.create({
128
133
  amount: Math.round(amount),
129
134
  currency: currencyCode.toLowerCase(),
130
135
  description,
@@ -5,35 +5,8 @@ import {
5
5
  DeliveryPricingDirector,
6
6
  } from '@unchainedshop/core';
7
7
 
8
- import { Order } from '@unchainedshop/core-orders';
9
- import { DeliveryProvider } from '@unchainedshop/core-delivery';
10
- import { SwissTaxCategories } from './tax/ch.js';
11
-
12
- const getTaxRate = ({ order, provider }: { order?: Order; provider?: DeliveryProvider }) => {
13
- const taxCategoryFromProvider = provider?.configuration?.find(({ key }) => {
14
- if (key === 'swiss-tax-category') return true;
15
- return null;
16
- })?.value;
17
-
18
- const taxCategory = SwissTaxCategories[taxCategoryFromProvider] || SwissTaxCategories.DEFAULT;
19
- return taxCategory.rate(order?.ordered);
20
- };
21
-
22
- const isDeliveryAddressInSwitzerland = ({
23
- orderDelivery,
24
- order,
25
- countryCode: forceCountryCode = null,
26
- }) => {
27
- let countryCode = forceCountryCode?.toUpperCase().trim() || order.countryCode;
28
-
29
- const address = orderDelivery?.context?.address || order?.billingAddress;
30
-
31
- if (address?.countryCode > '') {
32
- countryCode = address.countryCode?.toUpperCase().trim();
33
- }
34
-
35
- return countryCode === 'CH' || countryCode === 'LI';
36
- };
8
+ import { resolveTaxCategoryFromDeliveryProvider, SwissTaxCategories } from './tax/ch.js';
9
+ import isDeliveryAddressInCountry from './utils/isDeliveryAddressInCountry.js';
37
10
 
38
11
  export const DeliverySwissTax: IDeliveryPricingAdapter = {
39
12
  ...DeliveryPricingAdapter,
@@ -44,7 +17,16 @@ export const DeliverySwissTax: IDeliveryPricingAdapter = {
44
17
  orderIndex: 80,
45
18
 
46
19
  isActivatedFor: (context) => {
47
- return isDeliveryAddressInSwitzerland(context);
20
+ if (!context.order) return false;
21
+ if (!context.orderDelivery) return false;
22
+ return isDeliveryAddressInCountry(
23
+ {
24
+ order: context.order,
25
+ orderDelivery: context.orderDelivery,
26
+ countryCode: context.countryCode,
27
+ },
28
+ ['CH', 'LI'],
29
+ );
48
30
  },
49
31
 
50
32
  actions: (params) => {
@@ -55,7 +37,10 @@ export const DeliverySwissTax: IDeliveryPricingAdapter = {
55
37
  ...pricingAdapter,
56
38
 
57
39
  calculate: async () => {
58
- const taxRate = getTaxRate(context);
40
+ const taxCategory =
41
+ resolveTaxCategoryFromDeliveryProvider(context.provider) || SwissTaxCategories.DEFAULT;
42
+ const taxRate = taxCategory.rate(context.order?.ordered);
43
+
59
44
  DeliveryPricingAdapter.log(`DeliverySwissTax -> Tax Multiplicator: ${taxRate}`);
60
45
  params.calculationSheet.filterBy({ isTaxable: true }).forEach(({ isNetPrice, ...row }) => {
61
46
  if (!isNetPrice) {
@@ -31,6 +31,8 @@ export const OrderDiscount: IOrderPricingAdapter<OrderDiscountConfiguration> = {
31
31
  ...pricingAdapter,
32
32
 
33
33
  calculate: async () => {
34
+ if (!order) return pricingAdapter.calculate();
35
+
34
36
  const totalAmountOfItems = params.calculationSheet.total({
35
37
  category: OrderPricingRowCategory.Items,
36
38
  useNetPrice: false,
@@ -57,7 +59,7 @@ export const OrderDiscount: IOrderPricingAdapter<OrderDiscountConfiguration> = {
57
59
 
58
60
  const deliveryShare = resolveRatioAndTaxDivisorForPricingSheet(
59
61
  DeliveryPricingSheet({
60
- calculation: orderDelivery.calculation || [],
62
+ calculation: orderDelivery?.calculation || [],
61
63
  currencyCode: order.currencyCode,
62
64
  }),
63
65
  totalAmountOfPaymentAndDelivery,
@@ -65,7 +67,7 @@ export const OrderDiscount: IOrderPricingAdapter<OrderDiscountConfiguration> = {
65
67
 
66
68
  const paymentShare = resolveRatioAndTaxDivisorForPricingSheet(
67
69
  PaymentPricingSheet({
68
- calculation: orderPayment.calculation || [],
70
+ calculation: orderPayment?.calculation || [],
69
71
  currencyCode: order.currencyCode,
70
72
  }),
71
73
  totalAmountOfPaymentAndDelivery,
@@ -86,8 +88,8 @@ export const OrderDiscount: IOrderPricingAdapter<OrderDiscountConfiguration> = {
86
88
  // If it's a fixed rate we need to deduct the already deducted amount from the fixed rate
87
89
  // before we hand it over to the split calculation
88
90
  const fixedRate =
89
- configuration.fixedRate > 0
90
- ? Math.max(0, configuration.fixedRate - itemsDiscountAmount)
91
+ Number(configuration.fixedRate) > 0
92
+ ? Math.max(0, configuration.fixedRate! - itemsDiscountAmount)
91
93
  : undefined;
92
94
  const leftInFeesToSplit = calcUtils.calculateAmountToSplit(
93
95
  { ...configuration, fixedRate },
@@ -54,6 +54,8 @@ export const OrderPriceRound: IOrderPricingAdapter & {
54
54
  calculate: async () => {
55
55
  const { currencyCode } = params.context;
56
56
 
57
+ if (!currencyCode) return pricingAdapter.calculate();
58
+
57
59
  const { amount: deliveryAmount } = params.calculationSheet.total({
58
60
  category: OrderPricingRowCategory.Delivery,
59
61
  useNetPrice: true,
@@ -73,13 +75,12 @@ export const OrderPriceRound: IOrderPricingAdapter & {
73
75
  useNetPrice: true,
74
76
  });
75
77
  if (discountAmount) {
76
- pricingAdapter.resultSheet().addDiscount({
78
+ pricingAdapter.resultSheet().calculation.push({
79
+ category: OrderPricingRowCategory.Discounts,
77
80
  amount: calculateDifference(discountAmount, currencyCode),
78
- taxAmount: 0,
79
81
  meta: {
80
82
  adapter: OrderPriceRound.key,
81
83
  },
82
- discountId: null,
83
84
  });
84
85
  }
85
86
 
@@ -126,7 +127,7 @@ export const OrderPriceRound: IOrderPricingAdapter & {
126
127
  // WORKAROUND BECAUSE ORDER TOTAL GROSS PRICE IS CALCULATED WITH A SUM OF EVERYTHING EXCEPT TAXES
127
128
  // AS OF UNCHAINED <= 2.6
128
129
  pricingAdapter.resultSheet().calculation.push({
129
- category: null,
130
+ category: null as any as string,
130
131
  amount: taxDifference,
131
132
  meta: {
132
133
  adapter: OrderPriceRound.key,
@@ -0,0 +1,67 @@
1
+ import {
2
+ ProductPricingDirector,
3
+ ProductPricingAdapter,
4
+ type IProductPricingAdapter,
5
+ } from '@unchainedshop/core';
6
+
7
+ const ProductPrice: IProductPricingAdapter = {
8
+ ...ProductPricingAdapter,
9
+
10
+ key: 'shop.unchained.pricing.product-price-options',
11
+ version: '1.0',
12
+ label: 'Add Gross Price of Options',
13
+ orderIndex: 1,
14
+
15
+ isActivatedFor: () => {
16
+ return true;
17
+ },
18
+
19
+ actions: (params) => {
20
+ const pricingAdapter = ProductPricingAdapter.actions(params);
21
+ const { countryCode, currencyCode, quantity, modules } = params.context;
22
+
23
+ return {
24
+ ...pricingAdapter,
25
+
26
+ async calculatePriceForProduct(product) {
27
+ const price = await modules.products.prices.price(product, {
28
+ countryCode,
29
+ currencyCode,
30
+ quantity,
31
+ });
32
+ if (price) {
33
+ const itemTotal = price.amount * quantity;
34
+ pricingAdapter.resultSheet().addItem({
35
+ amount: itemTotal,
36
+ isTaxable: Boolean(price.isTaxable),
37
+ isNetPrice: Boolean(price.isNetPrice),
38
+ meta: { adapter: ProductPrice.key },
39
+ });
40
+ }
41
+ },
42
+
43
+ async calculate() {
44
+ const { configuration } = params.context;
45
+
46
+ const productIds = configuration?.flatMap(({ key, value }) => {
47
+ if (key === 'option') return [value];
48
+ return [];
49
+ });
50
+
51
+ if (!productIds?.length) {
52
+ return pricingAdapter.calculate();
53
+ }
54
+
55
+ const options = await modules.products.findProducts({
56
+ productIds,
57
+ });
58
+
59
+ await Promise.all(options.map(this.calculatePriceForProduct));
60
+
61
+ return pricingAdapter.calculate();
62
+ },
63
+ };
64
+ },
65
+ };
66
+
67
+ ProductPricingDirector.registerAdapter(ProductPrice);
@@ -3,6 +3,7 @@ import {
3
3
  ProductPricingAdapter,
4
4
  IProductPricingAdapter,
5
5
  } from '@unchainedshop/core';
6
+ import { ProductTypes } from '@unchainedshop/core-products';
6
7
 
7
8
  export const ProductPrice: IProductPricingAdapter = {
8
9
  ...ProductPricingAdapter,
@@ -33,10 +34,32 @@ export const ProductPrice: IProductPricingAdapter = {
33
34
  const itemTotal = price.amount * quantity;
34
35
  pricingAdapter.resultSheet().addItem({
35
36
  amount: itemTotal,
36
- isTaxable: price.isTaxable,
37
- isNetPrice: price.isNetPrice,
37
+ isTaxable: Boolean(price.isTaxable),
38
+ isNetPrice: Boolean(price.isNetPrice),
38
39
  meta: { adapter: ProductPrice.key },
39
40
  });
41
+ } else if (product.type === ProductTypes.BundleProduct) {
42
+ for (const bundleItem of product.bundleItems || []) {
43
+ const bundledProduct = await modules.products.findProduct({
44
+ productId: bundleItem.productId,
45
+ });
46
+ if (bundledProduct) {
47
+ const bundleItemPrice = await modules.products.prices.price(bundledProduct, {
48
+ countryCode,
49
+ currencyCode,
50
+ quantity: bundleItem.quantity * quantity,
51
+ });
52
+ if (bundleItemPrice) {
53
+ const bundleItemTotal = bundleItemPrice.amount * bundleItem.quantity * quantity;
54
+ pricingAdapter.resultSheet().addItem({
55
+ amount: bundleItemTotal,
56
+ isTaxable: Boolean(bundleItemPrice.isTaxable),
57
+ isNetPrice: Boolean(bundleItemPrice.isNetPrice),
58
+ meta: { adapter: ProductPrice.key },
59
+ });
60
+ }
61
+ }
62
+ }
40
63
  }
41
64
 
42
65
  return pricingAdapter.calculate();
@@ -54,13 +54,13 @@ export const ProductPriceRateConversion: IProductPricingAdapter = {
54
54
 
55
55
  const rateData = await modules.products.prices.rates.getRate(fromCurrencyObj, targetCurrencyObj);
56
56
 
57
- if (rateData?.rate > 0) {
57
+ if (rateData && rateData.rate > 0) {
58
58
  const convertedAmount = Math.round(productPrice.amount * rateData.rate);
59
59
  pricingAdapter.resultSheet().resetCalculation(params.calculationSheet);
60
60
  pricingAdapter.resultSheet().addItem({
61
61
  amount: convertedAmount * quantity,
62
- isTaxable: productPrice?.isTaxable,
63
- isNetPrice: productPrice?.isNetPrice,
62
+ isTaxable: Boolean(productPrice?.isTaxable),
63
+ isNetPrice: Boolean(productPrice?.isNetPrice),
64
64
  meta: { adapter: ProductPriceRateConversion.key, rate: rateData.rate },
65
65
  });
66
66
  }
@@ -1,47 +1,16 @@
1
1
  import {
2
2
  ProductPricingDirector,
3
3
  ProductPricingAdapter,
4
- ProductPricingAdapterContext,
5
4
  IProductPricingAdapter,
6
5
  ProductPricingRowCategory,
7
- UnchainedCore,
8
6
  } from '@unchainedshop/core';
9
- import { SwissTaxCategories } from './tax/ch.js';
10
-
11
- export const getTaxRate = (context: ProductPricingAdapterContext) => {
12
- const { product, order } = context;
13
-
14
- const productSpecialTaxTag = product.tags?.find((tag) =>
15
- tag?.trim().toLowerCase().startsWith('swiss-tax-category:'),
16
- );
17
- const taxCategory =
18
- Object.values(SwissTaxCategories).find(
19
- (t) => `swiss-tax-category:${t.value}` === productSpecialTaxTag?.trim().toLowerCase(),
20
- ) || SwissTaxCategories.DEFAULT;
21
-
22
- return taxCategory.rate(order?.ordered);
23
- };
24
-
25
- export const isDeliveryAddressInSwitzerland = async ({
26
- order,
27
- countryCode: forceCountryCode,
28
- modules,
29
- }: ProductPricingAdapterContext & { modules: UnchainedCore['modules'] }) => {
30
- let countryCode = forceCountryCode?.toUpperCase().trim() || order.countryCode;
31
-
32
- if (order) {
33
- const orderDelivery = await modules.orders.deliveries.findDelivery({
34
- orderDeliveryId: order.deliveryId,
35
- });
36
- const address = orderDelivery?.context?.address || order.billingAddress;
37
-
38
- if (address?.countryCode > '') {
39
- countryCode = address.countryCode?.toUpperCase().trim();
40
- }
41
- }
42
-
43
- return countryCode === 'CH' || countryCode === 'LI';
44
- };
7
+ import {
8
+ resolveTaxCategoryFromDeliveryProvider,
9
+ resolveTaxCategoryFromProduct,
10
+ SwissTaxCategories,
11
+ SwissTaxCategoryResolver,
12
+ } from './tax/ch.js';
13
+ import isDeliveryAddressInCountry from './utils/isDeliveryAddressInCountry.js';
45
14
 
46
15
  export const ProductSwissTax: IProductPricingAdapter = {
47
16
  ...ProductPricingAdapter,
@@ -63,10 +32,40 @@ export const ProductSwissTax: IProductPricingAdapter = {
63
32
  ...pricingAdapter,
64
33
 
65
34
  calculate: async () => {
66
- if (!(await isDeliveryAddressInSwitzerland(context))) {
35
+ const orderDelivery = context.order?.deliveryId
36
+ ? await context.modules.orders.deliveries.findDelivery({
37
+ orderDeliveryId: context.order?.deliveryId,
38
+ })
39
+ : null;
40
+ if (
41
+ !isDeliveryAddressInCountry(
42
+ {
43
+ ...context,
44
+ orderDelivery,
45
+ },
46
+ ['CH', 'LI'],
47
+ )
48
+ ) {
67
49
  return pricingAdapter.calculate();
68
50
  }
69
- const taxRate = getTaxRate(context);
51
+
52
+ let taxCategory: SwissTaxCategoryResolver | null = resolveTaxCategoryFromProduct(
53
+ context.product,
54
+ );
55
+ if (!taxCategory) {
56
+ // No special tax category found, use default from delivery provider
57
+ const provider = orderDelivery?.deliveryProviderId
58
+ ? await context.modules.delivery.findProvider({
59
+ deliveryProviderId: orderDelivery?.deliveryProviderId,
60
+ })
61
+ : null;
62
+ if (provider) taxCategory = resolveTaxCategoryFromDeliveryProvider(provider);
63
+ }
64
+ // If still no tax category found, use default
65
+ if (!taxCategory) taxCategory = SwissTaxCategories.DEFAULT;
66
+
67
+ const taxRate = taxCategory.rate(context.order?.ordered);
68
+
70
69
  ProductPricingAdapter.log(`ProductSwissTax -> Tax Multiplicator: ${taxRate}`);
71
70
  params.calculationSheet.filterBy({ isTaxable: true }).forEach(({ isNetPrice, ...row }) => {
72
71
  if (!isNetPrice) {