@endora-commerce/mod-payments 0.100.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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/admin/index.d.ts +32 -0
  4. package/dist/admin/index.d.ts.map +1 -0
  5. package/dist/admin/index.js +61 -0
  6. package/dist/admin/index.js.map +1 -0
  7. package/dist/admin/zones/OrderPaymentsTab.d.ts +42 -0
  8. package/dist/admin/zones/OrderPaymentsTab.d.ts.map +1 -0
  9. package/dist/admin/zones/OrderPaymentsTab.js +104 -0
  10. package/dist/admin/zones/OrderPaymentsTab.js.map +1 -0
  11. package/dist/backend/adapters/built-in-adapters.d.ts +58 -0
  12. package/dist/backend/adapters/built-in-adapters.d.ts.map +1 -0
  13. package/dist/backend/adapters/built-in-adapters.js +83 -0
  14. package/dist/backend/adapters/built-in-adapters.js.map +1 -0
  15. package/dist/backend/drivers/bank-transfer-driver.d.ts +28 -0
  16. package/dist/backend/drivers/bank-transfer-driver.d.ts.map +1 -0
  17. package/dist/backend/drivers/bank-transfer-driver.js +26 -0
  18. package/dist/backend/drivers/bank-transfer-driver.js.map +1 -0
  19. package/dist/backend/drivers/gateway-adapter-port.d.ts +71 -0
  20. package/dist/backend/drivers/gateway-adapter-port.d.ts.map +1 -0
  21. package/dist/backend/drivers/gateway-adapter-port.js +18 -0
  22. package/dist/backend/drivers/gateway-adapter-port.js.map +1 -0
  23. package/dist/backend/drivers/pickup-driver.d.ts +23 -0
  24. package/dist/backend/drivers/pickup-driver.d.ts.map +1 -0
  25. package/dist/backend/drivers/pickup-driver.js +19 -0
  26. package/dist/backend/drivers/pickup-driver.js.map +1 -0
  27. package/dist/backend/email-templates/transactional-defaults.d.ts +6 -0
  28. package/dist/backend/email-templates/transactional-defaults.d.ts.map +1 -0
  29. package/dist/backend/email-templates/transactional-defaults.js +27 -0
  30. package/dist/backend/email-templates/transactional-defaults.js.map +1 -0
  31. package/dist/backend/entities/payment.entity.d.ts +26 -0
  32. package/dist/backend/entities/payment.entity.d.ts.map +1 -0
  33. package/dist/backend/entities/payment.entity.js +100 -0
  34. package/dist/backend/entities/payment.entity.js.map +1 -0
  35. package/dist/backend/index.d.ts +88 -0
  36. package/dist/backend/index.d.ts.map +1 -0
  37. package/dist/backend/index.js +318 -0
  38. package/dist/backend/index.js.map +1 -0
  39. package/dist/backend/routes.customer.d.ts +20 -0
  40. package/dist/backend/routes.customer.d.ts.map +1 -0
  41. package/dist/backend/routes.customer.js +24 -0
  42. package/dist/backend/routes.customer.js.map +1 -0
  43. package/dist/backend/routes.d.ts +36 -0
  44. package/dist/backend/routes.d.ts.map +1 -0
  45. package/dist/backend/routes.js +44 -0
  46. package/dist/backend/routes.js.map +1 -0
  47. package/dist/backend/services/gateway-refund-registry.d.ts +122 -0
  48. package/dist/backend/services/gateway-refund-registry.d.ts.map +1 -0
  49. package/dist/backend/services/gateway-refund-registry.js +106 -0
  50. package/dist/backend/services/gateway-refund-registry.js.map +1 -0
  51. package/dist/backend/services/payment-email-notifier.d.ts +71 -0
  52. package/dist/backend/services/payment-email-notifier.d.ts.map +1 -0
  53. package/dist/backend/services/payment-email-notifier.js +73 -0
  54. package/dist/backend/services/payment-email-notifier.js.map +1 -0
  55. package/dist/backend/services/payment-email-renderer.d.ts +22 -0
  56. package/dist/backend/services/payment-email-renderer.d.ts.map +1 -0
  57. package/dist/backend/services/payment-email-renderer.js +17 -0
  58. package/dist/backend/services/payment-email-renderer.js.map +1 -0
  59. package/dist/backend/services/payment-placement-apply-port.d.ts +33 -0
  60. package/dist/backend/services/payment-placement-apply-port.d.ts.map +1 -0
  61. package/dist/backend/services/payment-placement-apply-port.js +68 -0
  62. package/dist/backend/services/payment-placement-apply-port.js.map +1 -0
  63. package/dist/backend/services/payment-read-port.d.ts +33 -0
  64. package/dist/backend/services/payment-read-port.d.ts.map +1 -0
  65. package/dist/backend/services/payment-read-port.js +64 -0
  66. package/dist/backend/services/payment-read-port.js.map +1 -0
  67. package/dist/backend/services/payment-reference-port.d.ts +29 -0
  68. package/dist/backend/services/payment-reference-port.d.ts.map +1 -0
  69. package/dist/backend/services/payment-reference-port.js +70 -0
  70. package/dist/backend/services/payment-reference-port.js.map +1 -0
  71. package/dist/backend/services/payment-refund.d.ts +55 -0
  72. package/dist/backend/services/payment-refund.d.ts.map +1 -0
  73. package/dist/backend/services/payment-refund.js +101 -0
  74. package/dist/backend/services/payment-refund.js.map +1 -0
  75. package/dist/backend/services/payment-retry-service.d.ts +45 -0
  76. package/dist/backend/services/payment-retry-service.d.ts.map +1 -0
  77. package/dist/backend/services/payment-retry-service.js +187 -0
  78. package/dist/backend/services/payment-retry-service.js.map +1 -0
  79. package/dist/backend/services/payment-service.d.ts +62 -0
  80. package/dist/backend/services/payment-service.d.ts.map +1 -0
  81. package/dist/backend/services/payment-service.js +134 -0
  82. package/dist/backend/services/payment-service.js.map +1 -0
  83. package/dist/backend/services/receive-payment-handler.d.ts +260 -0
  84. package/dist/backend/services/receive-payment-handler.d.ts.map +1 -0
  85. package/dist/backend/services/receive-payment-handler.js +356 -0
  86. package/dist/backend/services/receive-payment-handler.js.map +1 -0
  87. package/dist/backend/services/registry-singleton.d.ts +16 -0
  88. package/dist/backend/services/registry-singleton.d.ts.map +1 -0
  89. package/dist/backend/services/registry-singleton.js +17 -0
  90. package/dist/backend/services/registry-singleton.js.map +1 -0
  91. package/dist/manifest.d.ts +210 -0
  92. package/dist/manifest.d.ts.map +1 -0
  93. package/dist/manifest.js +182 -0
  94. package/dist/manifest.js.map +1 -0
  95. package/dist/migrations/20260925T115728_payments_refunded_amount.d.ts +28 -0
  96. package/dist/migrations/20260925T115728_payments_refunded_amount.d.ts.map +1 -0
  97. package/dist/migrations/20260925T115728_payments_refunded_amount.js +32 -0
  98. package/dist/migrations/20260925T115728_payments_refunded_amount.js.map +1 -0
  99. package/dist/migrations/index.d.ts +27 -0
  100. package/dist/migrations/index.d.ts.map +1 -0
  101. package/dist/migrations/index.js +29 -0
  102. package/dist/migrations/index.js.map +1 -0
  103. package/docs/payments.md +69 -0
  104. package/i18n/en.json +5 -0
  105. package/i18n/pl.json +5 -0
  106. package/package.json +96 -0
  107. package/tailwind.css +14 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ <!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
2
+
3
+ # @endora-commerce/mod-payments
4
+
5
+ The platform payment capability: the built-in payment adapters (bank transfer, in-person pickup, credit limit, gateway), the payment record every order carries, and the settlement lifecycle that PSP integrations plug into. Switched off, checkout offers no payment method and the shop takes no orders.
6
+
7
+ ## What this is
8
+
9
+ An **Endora Commerce module package**. Its module id is `payments` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
10
+
11
+ A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
12
+
13
+ ## Entry points
14
+
15
+ | Import | Contents |
16
+ | --- | --- |
17
+ | `@endora-commerce/mod-payments` | the module manifest — its id, version, dependencies, settings and activation |
18
+ | `@endora-commerce/mod-payments/admin` | the Admin UI contribution: the screens, navigation and palette actions it adds |
19
+ | `@endora-commerce/mod-payments/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
20
+ | `@endora-commerce/mod-payments/migrations` | the module’s own schema migrations, in the order the platform runs them |
21
+ | `@endora-commerce/mod-payments/tailwind.css` | the Tailwind source declaration for the admin code above |
22
+
23
+ ## Depends on
24
+
25
+ Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
26
+
27
+ **Endora packages**
28
+
29
+ - `@endora-commerce/admin-kit` — *optional*
30
+ - `@endora-commerce/contracts`
31
+ - `@endora-commerce/email-components`
32
+ - `@endora-commerce/mod-orders`
33
+ - `@endora-commerce/platform`
34
+
35
+ **Third-party**
36
+
37
+ - `@mikro-orm/core` ^6
38
+ - `@mikro-orm/migrations` ^6
39
+ - `@mikro-orm/postgresql` ^6
40
+ - `fastify` ^5
41
+ - `lucide-react` ^1 — *optional*
42
+ - `react` ^19 — *optional*
43
+
44
+ ## What the tarball carries
45
+
46
+ - `dist/` — the compiled JavaScript and its type declarations
47
+ - `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
48
+ - `docs/` — the package’s own pages in the Endora Commerce documentation site
49
+ - `tailwind.css` — the Tailwind source declaration
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ pnpm add @endora-commerce/mod-payments
55
+ ```
56
+
57
+ ## Licence
58
+
59
+ MIT — the text is in `LICENSE`, beside this file.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `payments`' admin surface — one zone contribution and nothing else (feature
3
+ * 091, P7d;
4
+ * `specs/091-module-owned-admin-surfaces/contracts/admin-component-contribution.md`
5
+ * §10).
6
+ *
7
+ * **This module contributes no route and no sidebar entry.** It has never had
8
+ * one: its operator surface is a tab on `orders`' order detail, which is
9
+ * exactly what made it an FR-007 case — there was no place for the owner to
10
+ * contribute to, so the host named the owner instead. `order.detail.payment`
11
+ * is that place.
12
+ *
13
+ * **What it retires**: the `visibility-gate` key
14
+ * `admin/src/modules/orders/OrderDetail.tsx:visibility-gate:payments` in
15
+ * `backend/scripts/ledgers/foreign-module-ids.ts`, whose recorded retiring
16
+ * condition is this contribution. `orders` computed
17
+ * `isVisible({ module: 'payments', requiredPermission: 'payments:read' })` for
18
+ * the tab button and passed the same answer down to the body; it counts the
19
+ * zone now (Z15) and knows only that it has a tab called Payment.
20
+ *
21
+ * **No `match`, and it is a decision rather than an omission.** `match`
22
+ * narrows the *mounts of one place* (Z13), and this place has one host and one
23
+ * mount, so there is nothing to narrow.
24
+ * `admin/test/modules/payments/order-payments-zone.test.tsx` asserts it absent
25
+ * so a later author cannot add one quietly.
26
+ *
27
+ * **This entry exports data and nothing else** (R2); every component is a
28
+ * dynamic-import factory (R6).
29
+ */
30
+ import { type AdminContributions } from '@endora-commerce/admin-kit/contributions';
31
+ export declare const contributions: AdminContributions;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,0CAA0C,CAAC;AAsBlD,eAAO,MAAM,aAAa,EAAE,kBAU3B,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `payments`' admin surface — one zone contribution and nothing else (feature
3
+ * 091, P7d;
4
+ * `specs/091-module-owned-admin-surfaces/contracts/admin-component-contribution.md`
5
+ * §10).
6
+ *
7
+ * **This module contributes no route and no sidebar entry.** It has never had
8
+ * one: its operator surface is a tab on `orders`' order detail, which is
9
+ * exactly what made it an FR-007 case — there was no place for the owner to
10
+ * contribute to, so the host named the owner instead. `order.detail.payment`
11
+ * is that place.
12
+ *
13
+ * **What it retires**: the `visibility-gate` key
14
+ * `admin/src/modules/orders/OrderDetail.tsx:visibility-gate:payments` in
15
+ * `backend/scripts/ledgers/foreign-module-ids.ts`, whose recorded retiring
16
+ * condition is this contribution. `orders` computed
17
+ * `isVisible({ module: 'payments', requiredPermission: 'payments:read' })` for
18
+ * the tab button and passed the same answer down to the body; it counts the
19
+ * zone now (Z15) and knows only that it has a tab called Payment.
20
+ *
21
+ * **No `match`, and it is a decision rather than an omission.** `match`
22
+ * narrows the *mounts of one place* (Z13), and this place has one host and one
23
+ * mount, so there is nothing to narrow.
24
+ * `admin/test/modules/payments/order-payments-zone.test.tsx` asserts it absent
25
+ * so a later author cannot add one quietly.
26
+ *
27
+ * **This entry exports data and nothing else** (R2); every component is a
28
+ * dynamic-import factory (R6).
29
+ */
30
+ import { zoneComponent, } from '@endora-commerce/admin-kit/contributions';
31
+ /**
32
+ * The code that opens the contributed tab, read off the route in this merge
33
+ * request as §9.3 requires: `packages/modules/payments/src/backend/routes.ts`
34
+ * gates `GET /api/v1/admin/orders/:id/payments` with
35
+ * `requireAdmin('payments:read')`, which is also the code `orders`' own
36
+ * `useSurfaceVisibility` call named. §10.6's line agrees, measured rather than
37
+ * copied.
38
+ *
39
+ * **The panel calls a second route this code does not open**, and it is
40
+ * recorded rather than repaired: its invoice list is
41
+ * `GET /api/v1/admin/invoices?filter[orderId]=…`, gated `invoices:read` by
42
+ * `packages/modules/invoices/src/backend/routes.admin.ts`. A contribution
43
+ * declares one code, and an operator holding `payments:read` without
44
+ * `invoices:read` sees the tab and an error inside it — which is the behaviour
45
+ * the tab already had before the conversion, unchanged by it. Splitting the
46
+ * invoice half into an `invoices` contribution of its own is a product change
47
+ * and is outside P7d.
48
+ */
49
+ const PAYMENTS_READ = 'payments:read';
50
+ export const contributions = {
51
+ zones: [
52
+ // The only contribution to this member, so the weight orders nothing
53
+ // today. Declared rather than defaulted so a second contributor arrives
54
+ // beside it rather than ahead of it by accident.
55
+ zoneComponent('order.detail.payment', () => import('./zones/OrderPaymentsTab.js'), {
56
+ weight: 100,
57
+ requiredPermission: PAYMENTS_READ,
58
+ }),
59
+ ],
60
+ };
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EACL,aAAa,GAEd,MAAM,0CAA0C,CAAC;AAElD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,aAAa,GAAG,eAAe,CAAC;AAEtC,MAAM,CAAC,MAAM,aAAa,GAAuB;IAC/C,KAAK,EAAE;QACL,qEAAqE;QACrE,wEAAwE;QACxE,iDAAiD;QACjD,aAAa,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,6BAA6B,CAAC,EAAE;YACjF,MAAM,EAAE,GAAG;YACX,kBAAkB,EAAE,aAAa;SAClC,CAAC;KACH;CACF,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { AdminZoneProps } from '@endora-commerce/contracts';
3
+ /**
4
+ * Payment tab — the order's payment attempts
5
+ * (`GET /api/v1/admin/orders/:id/payments`) plus the invoices generated for it
6
+ * (`GET /api/v1/admin/invoices?filter[orderId]=…`). The PDF download reuses the
7
+ * order invoice endpoint already linked from the page header; it serves the
8
+ * most recent ready invoice, so the link is offered only for ready invoices.
9
+ *
10
+ * ## It is this module's surface on `orders`' screen now (feature 091, P7d)
11
+ *
12
+ * It stood at `admin/src/modules/orders/OrderPaymentsTab.tsx` and was rendered
13
+ * by `OrderDetail.tsx` behind
14
+ * `isVisible({ module: 'payments', requiredPermission: 'payments:read' })` —
15
+ * `orders` naming this module in its own file, which is the `visibility-gate`
16
+ * key of `backend/scripts/ledgers/foreign-module-ids.ts` that this
17
+ * contribution retires. The host renders `order.detail.payment` instead and
18
+ * shows the tab button by counting the zone (Z15); the presence axis, the
19
+ * permission and the ordering are the zone renderer's.
20
+ *
21
+ * **`useTranslation('core')` is kept, deliberately.** Twenty-three of the keys
22
+ * below are `orderDetail.*` in `_i18n`'s bundle and one family —
23
+ * `orderDetail.paymentStatus.*` — is read by `orders`' own list screen through
24
+ * `admin/src/modules/orders/paymentStatus.ts` as well. That is R-1 §9.2's
25
+ * *second* population, module code rendering out of `core`, which that ruling
26
+ * names and deliberately does **not** rule on; P7a and P7b left their moved
27
+ * panels on `core` for the same reason. Moving a family the host still reads
28
+ * would be the failure §9.2's own correction records: no throw, no 404, the
29
+ * raw key on the operator's screen.
30
+ *
31
+ * `apiBaseUrl` and not `import.meta.env`: this file compiles under `tsc` inside
32
+ * a module package, which carries no `vite/client` types, and the kit publishes
33
+ * the one place that expression is read.
34
+ */
35
+ export type OrderPaymentsTabProps = AdminZoneProps<'order.detail.payment'>;
36
+ export declare function OrderPaymentsTab(props: OrderPaymentsTabProps): ReactNode;
37
+ /**
38
+ * The zone renderer loads a contribution through a dynamic-import factory and
39
+ * reads its default export (feature 091, FR-013).
40
+ */
41
+ export default OrderPaymentsTab;
42
+ //# sourceMappingURL=OrderPaymentsTab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrderPaymentsTab.d.ts","sourceRoot":"","sources":["../../../src/admin/zones/OrderPaymentsTab.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAsHjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;AAE3E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CA+HxE;AAED;;;GAGG;AACH,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { FileDown } from 'lucide-react';
4
+ import { apiBaseUrl, apiClient, formatDateTime, formatMoney } from '@endora-commerce/admin-kit/lib';
5
+ import { Badge, Button, Section, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@endora-commerce/admin-kit/ui';
6
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
7
+ function toLedger(payments) {
8
+ const entries = [];
9
+ for (const p of payments) {
10
+ const wasPaid = p.paidAt != null || p.status === 'refunded' || p.status === 'partially_refunded';
11
+ entries.push({
12
+ key: `${p.id}-charge`,
13
+ attemptNo: p.attemptNo,
14
+ amount: p.amount,
15
+ currency: p.currency,
16
+ // Keep the charge shown as "paid" even after a later refund.
17
+ status: wasPaid ? 'paid' : p.status,
18
+ at: p.paidAt,
19
+ reference: p.externalReference,
20
+ failure: p.failureReason,
21
+ });
22
+ if (p.refundedAmount > 0) {
23
+ entries.push({
24
+ key: `${p.id}-refund`,
25
+ attemptNo: p.attemptNo,
26
+ amount: -p.refundedAmount,
27
+ currency: p.currency,
28
+ status: p.refundedAmount >= p.amount ? 'refunded' : 'partially_refunded',
29
+ // Exact refund time when recorded; else the payment's last-updated time
30
+ // (when the refund was reflected) so pre-existing refunds still show a date.
31
+ at: p.refundedAt ?? p.updatedAt,
32
+ reference: p.refundReference ?? p.externalReference,
33
+ failure: null,
34
+ });
35
+ }
36
+ }
37
+ return entries;
38
+ }
39
+ const PAYMENT_STATUS_VARIANT = {
40
+ awaiting_payment: 'warning',
41
+ paid: 'success',
42
+ failed: 'destructive',
43
+ deferred: 'secondary',
44
+ refunded: 'outline',
45
+ partially_refunded: 'outline',
46
+ };
47
+ const INVOICE_STATUS_VARIANT = {
48
+ pending: 'warning',
49
+ ready: 'success',
50
+ cancelled: 'outline',
51
+ };
52
+ function money(amount, currency) {
53
+ return formatMoney(amount, currency);
54
+ }
55
+ export function OrderPaymentsTab(props) {
56
+ const t = useTranslation('core');
57
+ const [payments, setPayments] = useState([]);
58
+ const [invoices, setInvoices] = useState([]);
59
+ const [loading, setLoading] = useState(true);
60
+ const [error, setError] = useState(false);
61
+ useEffect(() => {
62
+ let alive = true;
63
+ setLoading(true);
64
+ setError(false);
65
+ void Promise.all([
66
+ apiClient.get(`/api/v1/admin/orders/${props.orderId}/payments`),
67
+ apiClient.get(`/api/v1/admin/invoices?filter[orderId]=${props.orderId}`),
68
+ ])
69
+ .then(([p, inv]) => {
70
+ if (!alive)
71
+ return;
72
+ setPayments(p.data);
73
+ setInvoices(inv.data);
74
+ })
75
+ .catch(() => {
76
+ if (!alive)
77
+ return;
78
+ setError(true);
79
+ setPayments([]);
80
+ setInvoices([]);
81
+ })
82
+ .finally(() => {
83
+ if (alive)
84
+ setLoading(false);
85
+ });
86
+ return () => {
87
+ alive = false;
88
+ };
89
+ }, [props.orderId]);
90
+ const invoiceHref = `${apiBaseUrl}/api/v1/orders/${props.orderId}/invoice`;
91
+ if (loading) {
92
+ return _jsx("p", { className: "text-sm text-muted-foreground", children: t('common.state.loading') });
93
+ }
94
+ if (error) {
95
+ return _jsx("p", { className: "text-sm text-destructive", children: t('common.state.error') });
96
+ }
97
+ return (_jsxs(_Fragment, { children: [_jsx(Section, { title: t('orderDetail.payments.title'), children: payments.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('orderDetail.payments.empty') })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t('orderDetail.payments.columns.attempt') }), _jsx(TableHead, { children: t('orderDetail.payments.columns.amount') }), _jsx(TableHead, { children: t('orderDetail.payments.columns.status') }), _jsx(TableHead, { children: t('orderDetail.payments.columns.actionDate') }), _jsx(TableHead, { children: t('orderDetail.payments.columns.reference') }), _jsx(TableHead, { children: t('orderDetail.payments.columns.failure') })] }) }), _jsx(TableBody, { children: toLedger(payments).map((e) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: ["#", e.attemptNo] }), _jsx(TableCell, { className: "tabular-nums", children: money(e.amount, e.currency) }), _jsx(TableCell, { children: _jsx(Badge, { variant: PAYMENT_STATUS_VARIANT[e.status], children: t(`orderDetail.paymentStatus.${e.status}`) }) }), _jsx(TableCell, { children: e.at ? formatDateTime(e.at) : '—' }), _jsx(TableCell, { className: "font-mono text-xs", children: e.reference ?? '—' }), _jsx(TableCell, { className: "text-destructive", children: e.failure ?? '' })] }, e.key))) })] })) }), _jsx(Section, { title: t('orderDetail.invoices.title'), children: invoices.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('orderDetail.invoices.empty') })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t('orderDetail.invoices.columns.number') }), _jsx(TableHead, { children: t('orderDetail.invoices.columns.kind') }), _jsx(TableHead, { children: t('orderDetail.invoices.columns.issuedAt') }), _jsx(TableHead, { children: t('orderDetail.invoices.columns.total') }), _jsx(TableHead, { children: t('orderDetail.invoices.columns.status') }), _jsx(TableHead, {})] }) }), _jsx(TableBody, { children: invoices.map((inv) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-medium", children: inv.number }), _jsx(TableCell, { children: t(`orderDetail.invoices.kind.${inv.kind}`) }), _jsx(TableCell, { children: formatDateTime(inv.issuedAt) }), _jsx(TableCell, { className: "tabular-nums", children: money(inv.total, inv.currency) }), _jsx(TableCell, { children: _jsx(Badge, { variant: INVOICE_STATUS_VARIANT[inv.status], children: t(`orderDetail.invoices.status.${inv.status}`) }) }), _jsx(TableCell, { className: "text-right", children: inv.pdfReady ? (_jsx(Button, { asChild: true, variant: "outline", size: "sm", className: "bg-card", children: _jsxs("a", { href: invoiceHref, target: "_blank", rel: "noreferrer", children: [_jsx(FileDown, {}), t('orderDetail.invoices.download')] }) })) : null })] }, inv.id))) })] })) })] }));
98
+ }
99
+ /**
100
+ * The zone renderer loads a contribution through a dynamic-import factory and
101
+ * reads its default export (feature 091, FR-013).
102
+ */
103
+ export default OrderPaymentsTab;
104
+ //# sourceMappingURL=OrderPaymentsTab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrderPaymentsTab.js","sourceRoot":"","sources":["../../../src/admin/zones/OrderPaymentsTab.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { PaymentAdapter, PaymentEligibilityContext, ReceivePaymentContext, PaymentOutcome, StartPaymentResult } from '@endora-commerce/contracts';
2
+ declare abstract class BaseAdapter implements PaymentAdapter {
3
+ abstract readonly adapterKey: string;
4
+ abstract readonly type: PaymentAdapter['type'];
5
+ validateUseOnStorefront(_ctx: PaymentEligibilityContext): Promise<boolean>;
6
+ validateUseOnAdmin(_ctx: PaymentEligibilityContext): Promise<boolean>;
7
+ validateUseInApi(_ctx: PaymentEligibilityContext): Promise<boolean>;
8
+ abstract onStorefrontOrderCreated(ctx: {
9
+ orderId: string;
10
+ paymentId: string;
11
+ amount: number;
12
+ currency: string;
13
+ }): Promise<StartPaymentResult>;
14
+ /**
15
+ * Default: the ingress is the source of truth for the outcome (offline
16
+ * methods are settled by an admin / out-of-band). Provider details and the
17
+ * external reference flow straight through onto the Payment row.
18
+ */
19
+ onReceivePayment(ctx: ReceivePaymentContext): Promise<PaymentOutcome>;
20
+ }
21
+ /** Bank transfer (Przelew bankowy) — awaits an out-of-band transfer. */
22
+ export declare class BankTransferAdapter extends BaseAdapter {
23
+ readonly adapterKey = "bank_transfer";
24
+ readonly type: "bank_transfer";
25
+ onStorefrontOrderCreated(ctx: {
26
+ orderId: string;
27
+ paymentId: string;
28
+ amount: number;
29
+ currency: string;
30
+ }): Promise<StartPaymentResult>;
31
+ }
32
+ /** Cash on delivery / pickup (`Płatność przy odbiorze`) — settled on receipt. */
33
+ export declare class PickupAdapter extends BaseAdapter {
34
+ readonly adapterKey = "pickup";
35
+ readonly type: "pickup";
36
+ onStorefrontOrderCreated(): Promise<StartPaymentResult>;
37
+ }
38
+ /** Credit limit (`Limit kredytowy`) — reservation handled inline by OrderService. */
39
+ export declare class CreditLimitAdapter extends BaseAdapter {
40
+ readonly adapterKey = "credit_limit";
41
+ readonly type: "credit_limit";
42
+ onStorefrontOrderCreated(): Promise<StartPaymentResult>;
43
+ }
44
+ /**
45
+ * Payment gateway (`Bramka płatności`) — a vendor adapter ships separately and
46
+ * overrides `onStorefrontOrderCreated` to return a redirect. The bundled
47
+ * placeholder returns `none`; the real redirect comes from the wired
48
+ * GatewayAdapterPort.
49
+ */
50
+ export declare class GatewayAdapter extends BaseAdapter {
51
+ readonly adapterKey = "gateway";
52
+ readonly type: "gateway";
53
+ onStorefrontOrderCreated(): Promise<StartPaymentResult>;
54
+ }
55
+ /** The adapters registered for the platform's built-in payment kinds. */
56
+ export declare function builtInPaymentAdapters(): PaymentAdapter[];
57
+ export {};
58
+ //# sourceMappingURL=built-in-adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in-adapters.d.ts","sourceRoot":"","sources":["../../../src/backend/adapters/built-in-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EACnB,MAAM,4BAA4B,CAAC;AAiBpC,uBAAe,WAAY,YAAW,cAAc;IAClD,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAEzC,uBAAuB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAG1E,kBAAkB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAGrE,gBAAgB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzE,QAAQ,CAAC,wBAAwB,CAAC,GAAG,EAAE;QACrC,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAE/B;;;;OAIG;IACG,gBAAgB,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC;CAO5E;AAED,wEAAwE;AACxE,qBAAa,mBAAoB,SAAQ,WAAW;IAClD,QAAQ,CAAC,UAAU,mBAAmB;IACtC,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAU;IAEnC,wBAAwB,CAAC,GAAG,EAAE;QAClC,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAGhC;AAED,iFAAiF;AACjF,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,UAAU,YAAY;IAC/B,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAE5B,wBAAwB,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAG9D;AAED,qFAAqF;AACrF,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,UAAU,kBAAkB;IACrC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IAElC,wBAAwB,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAG9D;AAED;;;;;GAKG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC7C,QAAQ,CAAC,UAAU,aAAa;IAChC,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IAE7B,wBAAwB,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAG9D;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,IAAI,cAAc,EAAE,CAOzD"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Built-in payment adapters (feature 034). These formalise the pre-existing
3
+ * `payments/drivers/*` logic as `PaymentAdapter` implementations registered in
4
+ * the PaymentAdapterRegistry. All bundled adapters are offline (no external
5
+ * integration) except `gateway`, which delegates to the GatewayAdapterPort
6
+ * wired by the integrations module.
7
+ *
8
+ * Validators default to `() => true` (FR-011). `onReceivePayment` echoes the
9
+ * outcome the ingress already validated — the offline adapters do not
10
+ * independently verify a payment; the gateway adapter overrides this in a
11
+ * follow-up vendor module.
12
+ */
13
+ const orderReference = (orderId) => `ORDER-${orderId.slice(0, 8).toUpperCase()}`;
14
+ class BaseAdapter {
15
+ async validateUseOnStorefront(_ctx) {
16
+ return true;
17
+ }
18
+ async validateUseOnAdmin(_ctx) {
19
+ return true;
20
+ }
21
+ async validateUseInApi(_ctx) {
22
+ return true;
23
+ }
24
+ /**
25
+ * Default: the ingress is the source of truth for the outcome (offline
26
+ * methods are settled by an admin / out-of-band). Provider details and the
27
+ * external reference flow straight through onto the Payment row.
28
+ */
29
+ async onReceivePayment(ctx) {
30
+ return {
31
+ result: 'success',
32
+ externalReference: ctx.externalReference ?? null,
33
+ ...(ctx.providerDetails ? { providerDetails: ctx.providerDetails } : {}),
34
+ };
35
+ }
36
+ }
37
+ /** Bank transfer (Przelew bankowy) — awaits an out-of-band transfer. */
38
+ export class BankTransferAdapter extends BaseAdapter {
39
+ adapterKey = 'bank_transfer';
40
+ type = 'bank_transfer';
41
+ async onStorefrontOrderCreated(ctx) {
42
+ return { kind: 'awaiting_transfer', iban: null, reference: orderReference(ctx.orderId) };
43
+ }
44
+ }
45
+ /** Cash on delivery / pickup (`Płatność przy odbiorze`) — settled on receipt. */
46
+ export class PickupAdapter extends BaseAdapter {
47
+ adapterKey = 'pickup';
48
+ type = 'pickup';
49
+ async onStorefrontOrderCreated() {
50
+ return { kind: 'none' };
51
+ }
52
+ }
53
+ /** Credit limit (`Limit kredytowy`) — reservation handled inline by OrderService. */
54
+ export class CreditLimitAdapter extends BaseAdapter {
55
+ adapterKey = 'credit_limit';
56
+ type = 'credit_limit';
57
+ async onStorefrontOrderCreated() {
58
+ return { kind: 'none' };
59
+ }
60
+ }
61
+ /**
62
+ * Payment gateway (`Bramka płatności`) — a vendor adapter ships separately and
63
+ * overrides `onStorefrontOrderCreated` to return a redirect. The bundled
64
+ * placeholder returns `none`; the real redirect comes from the wired
65
+ * GatewayAdapterPort.
66
+ */
67
+ export class GatewayAdapter extends BaseAdapter {
68
+ adapterKey = 'gateway';
69
+ type = 'gateway';
70
+ async onStorefrontOrderCreated() {
71
+ return { kind: 'none' };
72
+ }
73
+ }
74
+ /** The adapters registered for the platform's built-in payment kinds. */
75
+ export function builtInPaymentAdapters() {
76
+ return [
77
+ new BankTransferAdapter(),
78
+ new PickupAdapter(),
79
+ new CreditLimitAdapter(),
80
+ new GatewayAdapter(),
81
+ ];
82
+ }
83
+ //# sourceMappingURL=built-in-adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in-adapters.js","sourceRoot":"","sources":["../../../src/backend/adapters/built-in-adapters.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;GAWG;AAEH,MAAM,cAAc,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,SAAS,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;AAEjG,MAAe,WAAW;IAIxB,KAAK,CAAC,uBAAuB,CAAC,IAA+B;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,CAAC,kBAAkB,CAAC,IAA+B;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,CAAC,gBAAgB,CAAC,IAA+B;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IASD;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CAAC,GAA0B;QAC/C,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,IAAI,IAAI;YAChD,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzE,CAAC;IACJ,CAAC;CACF;AAED,wEAAwE;AACxE,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IACzC,UAAU,GAAG,eAAe,CAAC;IAC7B,IAAI,GAAG,eAAwB,CAAC;IAEzC,KAAK,CAAC,wBAAwB,CAAC,GAK9B;QACC,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3F,CAAC;CACF;AAED,iFAAiF;AACjF,MAAM,OAAO,aAAc,SAAQ,WAAW;IACnC,UAAU,GAAG,QAAQ,CAAC;IACtB,IAAI,GAAG,QAAiB,CAAC;IAElC,KAAK,CAAC,wBAAwB;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,qFAAqF;AACrF,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACxC,UAAU,GAAG,cAAc,CAAC;IAC5B,IAAI,GAAG,cAAuB,CAAC;IAExC,KAAK,CAAC,wBAAwB;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,cAAe,SAAQ,WAAW;IACpC,UAAU,GAAG,SAAS,CAAC;IACvB,IAAI,GAAG,SAAkB,CAAC;IAEnC,KAAK,CAAC,wBAAwB;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,yEAAyE;AACzE,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,mBAAmB,EAAE;QACzB,IAAI,aAAa,EAAE;QACnB,IAAI,kBAAkB,EAAE;QACxB,IAAI,cAAc,EAAE;KACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Bank-transfer driver (T139 — already implicitly exercised by order-service).
3
+ *
4
+ * The driver is intentionally pure metadata: bank-transfer orders carry
5
+ * no external state beyond the proforma invoice generated at placement.
6
+ * The order is left in `paymentStatus='awaiting_payment'` until an admin
7
+ * marks it paid via `POST /api/v1/admin/orders/:id/payment-status`.
8
+ *
9
+ * Captured here so the file layout matches T141's "drivers/" directory
10
+ * convention; a future order-service refactor can dispatch through a
11
+ * registry that lives next to it.
12
+ */
13
+ export interface BankTransferReserveResult {
14
+ paymentRef: null;
15
+ nextAction: {
16
+ kind: 'awaiting_transfer';
17
+ iban: string | null;
18
+ reference: string;
19
+ };
20
+ }
21
+ export declare class BankTransferDriver {
22
+ readonly kind: "bank_transfer";
23
+ reserve(input: {
24
+ orderId: string;
25
+ iban?: string | null;
26
+ }): BankTransferReserveResult;
27
+ }
28
+ //# sourceMappingURL=bank-transfer-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bank-transfer-driver.d.ts","sourceRoot":"","sources":["../../../src/backend/drivers/bank-transfer-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE;QAAE,IAAI,EAAE,mBAAmB,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACnF;AAED,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAU;IAEzC,OAAO,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,yBAAyB;CAUrF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Bank-transfer driver (T139 — already implicitly exercised by order-service).
3
+ *
4
+ * The driver is intentionally pure metadata: bank-transfer orders carry
5
+ * no external state beyond the proforma invoice generated at placement.
6
+ * The order is left in `paymentStatus='awaiting_payment'` until an admin
7
+ * marks it paid via `POST /api/v1/admin/orders/:id/payment-status`.
8
+ *
9
+ * Captured here so the file layout matches T141's "drivers/" directory
10
+ * convention; a future order-service refactor can dispatch through a
11
+ * registry that lives next to it.
12
+ */
13
+ export class BankTransferDriver {
14
+ kind = 'bank_transfer';
15
+ reserve(input) {
16
+ return {
17
+ paymentRef: null,
18
+ nextAction: {
19
+ kind: 'awaiting_transfer',
20
+ iban: input.iban ?? null,
21
+ reference: `ORDER-${input.orderId.slice(0, 8).toUpperCase()}`,
22
+ },
23
+ };
24
+ }
25
+ }
26
+ //# sourceMappingURL=bank-transfer-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bank-transfer-driver.js","sourceRoot":"","sources":["../../../src/backend/drivers/bank-transfer-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,eAAwB,CAAC;IAEzC,OAAO,CAAC,KAAgD;QACtD,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE;gBACV,IAAI,EAAE,mBAAmB;gBACzB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;gBACxB,SAAS,EAAE,SAAS,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE;aAC9D;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,71 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ /**
3
+ * Gateway adapter port (T141 / FR-009).
4
+ *
5
+ * Per-vendor payment-gateway adapters implement this interface in
6
+ * follow-up specs (Stripe, Przelewy24, PayU, …). The port stays in the
7
+ * core so the order-placement transaction has a stable contract to
8
+ * dispatch through, and so a gateway adapter can be swapped without
9
+ * touching `order-service.ts`.
10
+ *
11
+ * Until a real adapter ships, `GatewayAdapterPortNotWired` returns
12
+ * `501 NOT_IMPLEMENTED` from any reserve/settle call. Order placement
13
+ * with a `gateway`-kind PaymentMethod therefore fails fast with a clear
14
+ * error rather than silently 500'ing.
15
+ */
16
+ export type Currency = string;
17
+ export interface GatewayReserveInput {
18
+ orderId: string;
19
+ organizationId: string;
20
+ amount: number;
21
+ currency: Currency;
22
+ /** Per-payment-method config; opaque to the port. */
23
+ vendorConfig: Record<string, unknown>;
24
+ tx: EntityManager;
25
+ }
26
+ export interface GatewaySettleInput {
27
+ orderId: string;
28
+ paymentRef: string;
29
+ vendorConfig: Record<string, unknown>;
30
+ tx: EntityManager;
31
+ }
32
+ export type GatewayReserveResult = {
33
+ ok: true;
34
+ paymentRef: string;
35
+ nextAction: {
36
+ kind: 'redirect';
37
+ url: string;
38
+ } | {
39
+ kind: 'none';
40
+ };
41
+ } | {
42
+ ok: false;
43
+ code: string;
44
+ message: string;
45
+ };
46
+ export interface GatewayAdapterPort {
47
+ /** Vendor identifier, e.g. `stripe`. Matches the adapter's own module. */
48
+ readonly vendor: string;
49
+ reserve(input: GatewayReserveInput): Promise<GatewayReserveResult>;
50
+ settle(input: GatewaySettleInput): Promise<{
51
+ ok: true;
52
+ } | {
53
+ ok: false;
54
+ code: string;
55
+ }>;
56
+ }
57
+ /**
58
+ * Default placeholder until a per-vendor adapter is wired by the
59
+ * integrations module's composition root. Implements the contract
60
+ * surface so type-checking passes everywhere; throws at runtime when
61
+ * the order-placement transaction tries to use it.
62
+ */
63
+ export declare class GatewayAdapterPortNotWired implements GatewayAdapterPort {
64
+ readonly vendor = "unwired";
65
+ reserve(_input: GatewayReserveInput): Promise<GatewayReserveResult>;
66
+ settle(_input: GatewaySettleInput): Promise<{
67
+ ok: false;
68
+ code: string;
69
+ }>;
70
+ }
71
+ //# sourceMappingURL=gateway-adapter-port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-adapter-port.d.ts","sourceRoot":"","sources":["../../../src/backend/drivers/gateway-adapter-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,EAAE,EAAE,aAAa,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,EAAE,EAAE,aAAa,CAAC;CACnB;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAClG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxF;AAED;;;;;GAKG;AACH,qBAAa,0BAA2B,YAAW,kBAAkB;IACnE,QAAQ,CAAC,MAAM,aAAa;IAEtB,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAQnE,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAO/E"}