@porulle/core 0.10.8 → 0.13.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.
- package/dist/auth/auth-schema-guard.d.ts +2444 -0
- package/dist/auth/auth-schema-guard.d.ts.map +1 -0
- package/dist/auth/auth-schema-guard.js +113 -0
- package/dist/auth/auth-schema.d.ts +228 -0
- package/dist/auth/auth-schema.d.ts.map +1 -1
- package/dist/auth/auth-schema.js +24 -2
- package/dist/auth/middleware.d.ts +1 -0
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +13 -5
- package/dist/auth/org.d.ts +8 -2
- package/dist/auth/org.d.ts.map +1 -1
- package/dist/auth/org.js +12 -4
- package/dist/auth/organization-guard.d.ts +5 -0
- package/dist/auth/organization-guard.d.ts.map +1 -0
- package/dist/auth/organization-guard.js +124 -0
- package/dist/auth/permissions.d.ts +10 -0
- package/dist/auth/permissions.d.ts.map +1 -1
- package/dist/auth/permissions.js +31 -7
- package/dist/auth/role-authority.d.ts +44 -0
- package/dist/auth/role-authority.d.ts.map +1 -0
- package/dist/auth/role-authority.js +85 -0
- package/dist/auth/setup.d.ts.map +1 -1
- package/dist/auth/setup.js +17 -0
- package/dist/auth/strict-org-resolution.d.ts.map +1 -1
- package/dist/auth/strict-org-resolution.js +9 -1
- package/dist/auth/types.d.ts +1 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -0
- package/dist/config/types.d.ts +33 -4
- package/dist/config/types.d.ts.map +1 -1
- package/dist/hooks/checkout.d.ts.map +1 -1
- package/dist/hooks/checkout.js +10 -9
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/interfaces/rest/audit-middleware.d.ts.map +1 -1
- package/dist/interfaces/rest/audit-middleware.js +2 -0
- package/dist/interfaces/rest/customer-portal.d.ts.map +1 -1
- package/dist/interfaces/rest/customer-portal.js +9 -8
- package/dist/interfaces/rest/index.d.ts.map +1 -1
- package/dist/interfaces/rest/index.js +4 -0
- package/dist/interfaces/rest/route-coverage.d.ts +14 -0
- package/dist/interfaces/rest/route-coverage.d.ts.map +1 -0
- package/dist/interfaces/rest/route-coverage.js +81 -0
- package/dist/interfaces/rest/router.d.ts +7 -2
- package/dist/interfaces/rest/router.d.ts.map +1 -1
- package/dist/interfaces/rest/router.js +8 -4
- package/dist/interfaces/rest/routes/admin/compensation-failures.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/compensation-failures.js +7 -5
- package/dist/interfaces/rest/routes/admin/custom-field-proposals.d.ts +5 -0
- package/dist/interfaces/rest/routes/admin/custom-field-proposals.d.ts.map +1 -0
- package/dist/interfaces/rest/routes/admin/custom-field-proposals.js +22 -0
- package/dist/interfaces/rest/routes/admin/entity-field-definitions.d.ts +5 -0
- package/dist/interfaces/rest/routes/admin/entity-field-definitions.d.ts.map +1 -0
- package/dist/interfaces/rest/routes/admin/entity-field-definitions.js +39 -0
- package/dist/interfaces/rest/routes/admin/permissions.d.ts +1 -1
- package/dist/interfaces/rest/routes/admin/permissions.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/permissions.js +2 -0
- package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/staff.js +126 -66
- package/dist/interfaces/rest/routes/admin-jobs.js +3 -3
- package/dist/interfaces/rest/routes/audit.js +3 -3
- package/dist/interfaces/rest/routes/carts.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/carts.js +13 -10
- package/dist/interfaces/rest/routes/catalog.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/catalog.js +47 -4
- package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/checkout.js +30 -35
- package/dist/interfaces/rest/routes/documents.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/documents.js +10 -5
- package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/inventory.js +2 -0
- package/dist/interfaces/rest/routes/media.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/media.js +7 -3
- package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/orders.js +26 -8
- package/dist/interfaces/rest/routes/pricing.js +2 -2
- package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/promotions.js +13 -10
- package/dist/interfaces/rest/routes/search.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/search.js +14 -1
- package/dist/interfaces/rest/schemas/admin-custom-field-proposals.d.ts +134 -0
- package/dist/interfaces/rest/schemas/admin-custom-field-proposals.d.ts.map +1 -0
- package/dist/interfaces/rest/schemas/admin-custom-field-proposals.js +26 -0
- package/dist/interfaces/rest/schemas/admin-entity-field-definitions.d.ts +592 -0
- package/dist/interfaces/rest/schemas/admin-entity-field-definitions.d.ts.map +1 -0
- package/dist/interfaces/rest/schemas/admin-entity-field-definitions.js +109 -0
- package/dist/interfaces/rest/schemas/carts.d.ts +7 -0
- package/dist/interfaces/rest/schemas/carts.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/catalog.d.ts +1364 -401
- package/dist/interfaces/rest/schemas/catalog.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/catalog.js +86 -0
- package/dist/interfaces/rest/schemas/customer-portal.d.ts +35 -0
- package/dist/interfaces/rest/schemas/customer-portal.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/orders.d.ts +204 -0
- package/dist/interfaces/rest/schemas/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/pricing.d.ts +1 -0
- package/dist/interfaces/rest/schemas/pricing.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/responses.d.ts +71 -0
- package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/search.d.ts +1 -0
- package/dist/interfaces/rest/schemas/search.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/search.js +1 -0
- package/dist/interfaces/rest/utils.d.ts +15 -0
- package/dist/interfaces/rest/utils.d.ts.map +1 -1
- package/dist/interfaces/rest/utils.js +45 -2
- package/dist/kernel/compensation/executor.js +2 -2
- package/dist/kernel/database/tx-context.d.ts +8 -0
- package/dist/kernel/database/tx-context.d.ts.map +1 -1
- package/dist/kernel/database/tx-context.js +13 -0
- package/dist/kernel/hooks/create-context.d.ts +2 -0
- package/dist/kernel/hooks/create-context.d.ts.map +1 -1
- package/dist/kernel/hooks/create-context.js +1 -0
- package/dist/kernel/hooks/types.d.ts +2 -0
- package/dist/kernel/hooks/types.d.ts.map +1 -1
- package/dist/kernel/plugin/manifest.d.ts.map +1 -1
- package/dist/kernel/plugin/manifest.js +9 -5
- package/dist/modules/analytics/service.js +2 -2
- package/dist/modules/audit/service.js +3 -3
- package/dist/modules/cart/repository/index.d.ts +13 -7
- package/dist/modules/cart/repository/index.d.ts.map +1 -1
- package/dist/modules/cart/repository/index.js +16 -10
- package/dist/modules/cart/schema.d.ts +17 -0
- package/dist/modules/cart/schema.d.ts.map +1 -1
- package/dist/modules/cart/schema.js +4 -0
- package/dist/modules/cart/service.d.ts +22 -9
- package/dist/modules/cart/service.d.ts.map +1 -1
- package/dist/modules/cart/service.js +57 -33
- package/dist/modules/catalog/brand-service.js +7 -7
- package/dist/modules/catalog/category-service.js +7 -7
- package/dist/modules/catalog/entity-service.d.ts +19 -10
- package/dist/modules/catalog/entity-service.d.ts.map +1 -1
- package/dist/modules/catalog/entity-service.js +180 -51
- package/dist/modules/catalog/module.d.ts +6 -1
- package/dist/modules/catalog/module.d.ts.map +1 -1
- package/dist/modules/catalog/module.js +6 -1
- package/dist/modules/catalog/ownership.d.ts +5 -0
- package/dist/modules/catalog/ownership.d.ts.map +1 -0
- package/dist/modules/catalog/ownership.js +11 -0
- package/dist/modules/catalog/read-policy.d.ts +9 -0
- package/dist/modules/catalog/read-policy.d.ts.map +1 -0
- package/dist/modules/catalog/read-policy.js +8 -0
- package/dist/modules/catalog/repository/index.d.ts +55 -3
- package/dist/modules/catalog/repository/index.d.ts.map +1 -1
- package/dist/modules/catalog/repository/index.js +335 -6
- package/dist/modules/catalog/revision.d.ts +4 -0
- package/dist/modules/catalog/revision.d.ts.map +1 -0
- package/dist/modules/catalog/revision.js +33 -0
- package/dist/modules/catalog/schema.d.ts +979 -110
- package/dist/modules/catalog/schema.d.ts.map +1 -1
- package/dist/modules/catalog/schema.js +112 -2
- package/dist/modules/catalog/schemas.d.ts +2 -0
- package/dist/modules/catalog/schemas.d.ts.map +1 -1
- package/dist/modules/catalog/schemas.js +2 -0
- package/dist/modules/catalog/service.d.ts +80 -15
- package/dist/modules/catalog/service.d.ts.map +1 -1
- package/dist/modules/catalog/service.js +522 -14
- package/dist/modules/channels/adapter.d.ts +85 -0
- package/dist/modules/channels/adapter.d.ts.map +1 -1
- package/dist/modules/channels/adapter.js +9 -1
- package/dist/modules/customers/module.d.ts.map +1 -1
- package/dist/modules/customers/module.js +1 -0
- package/dist/modules/customers/service.d.ts +2 -0
- package/dist/modules/customers/service.d.ts.map +1 -1
- package/dist/modules/customers/service.js +21 -20
- package/dist/modules/documents/module.d.ts.map +1 -1
- package/dist/modules/documents/module.js +1 -0
- package/dist/modules/documents/service.d.ts +18 -4
- package/dist/modules/documents/service.d.ts.map +1 -1
- package/dist/modules/documents/service.js +54 -16
- package/dist/modules/fulfillment/module.d.ts.map +1 -1
- package/dist/modules/fulfillment/module.js +1 -0
- package/dist/modules/fulfillment/service.d.ts +2 -0
- package/dist/modules/fulfillment/service.d.ts.map +1 -1
- package/dist/modules/fulfillment/service.js +15 -6
- package/dist/modules/inventory/service.d.ts.map +1 -1
- package/dist/modules/inventory/service.js +15 -14
- package/dist/modules/media/module.d.ts +68 -0
- package/dist/modules/media/module.d.ts.map +1 -1
- package/dist/modules/media/module.js +2 -0
- package/dist/modules/media/schema.d.ts +70 -0
- package/dist/modules/media/schema.d.ts.map +1 -1
- package/dist/modules/media/schema.js +20 -2
- package/dist/modules/media/service.d.ts +8 -1
- package/dist/modules/media/service.d.ts.map +1 -1
- package/dist/modules/media/service.js +71 -23
- package/dist/modules/orders/guest-access.d.ts +27 -0
- package/dist/modules/orders/guest-access.d.ts.map +1 -0
- package/dist/modules/orders/guest-access.js +46 -0
- package/dist/modules/orders/module.d.ts.map +1 -1
- package/dist/modules/orders/module.js +1 -0
- package/dist/modules/orders/quote.d.ts.map +1 -1
- package/dist/modules/orders/quote.js +1 -0
- package/dist/modules/orders/repository/index.d.ts +1 -1
- package/dist/modules/orders/repository/index.d.ts.map +1 -1
- package/dist/modules/orders/repository/index.js +2 -2
- package/dist/modules/orders/schema.d.ts +17 -0
- package/dist/modules/orders/schema.d.ts.map +1 -1
- package/dist/modules/orders/schema.js +5 -3
- package/dist/modules/orders/service.d.ts +16 -7
- package/dist/modules/orders/service.d.ts.map +1 -1
- package/dist/modules/orders/service.js +184 -55
- package/dist/modules/pricing/module.d.ts.map +1 -1
- package/dist/modules/pricing/module.js +1 -0
- package/dist/modules/pricing/schema.d.ts +17 -0
- package/dist/modules/pricing/schema.d.ts.map +1 -1
- package/dist/modules/pricing/schema.js +1 -0
- package/dist/modules/pricing/schemas.d.ts +1 -0
- package/dist/modules/pricing/schemas.d.ts.map +1 -1
- package/dist/modules/pricing/schemas.js +1 -0
- package/dist/modules/pricing/service.d.ts +2 -0
- package/dist/modules/pricing/service.d.ts.map +1 -1
- package/dist/modules/pricing/service.js +18 -12
- package/dist/modules/promotions/module.d.ts.map +1 -1
- package/dist/modules/promotions/module.js +1 -0
- package/dist/modules/promotions/service.d.ts +3 -0
- package/dist/modules/promotions/service.d.ts.map +1 -1
- package/dist/modules/promotions/service.js +19 -11
- package/dist/modules/search/adapter.d.ts +8 -0
- package/dist/modules/search/adapter.d.ts.map +1 -1
- package/dist/modules/search/module.d.ts.map +1 -1
- package/dist/modules/search/module.js +3 -0
- package/dist/modules/search/service.d.ts +5 -0
- package/dist/modules/search/service.d.ts.map +1 -1
- package/dist/modules/search/service.js +131 -11
- package/dist/modules/settings/module.d.ts.map +1 -1
- package/dist/modules/settings/module.js +1 -0
- package/dist/modules/settings/service.d.ts +3 -0
- package/dist/modules/settings/service.d.ts.map +1 -1
- package/dist/modules/settings/service.js +6 -4
- package/dist/modules/shipping/service.js +9 -9
- package/dist/modules/tax/module.d.ts.map +1 -1
- package/dist/modules/tax/module.js +1 -0
- package/dist/modules/tax/service.d.ts +3 -0
- package/dist/modules/tax/service.d.ts.map +1 -1
- package/dist/modules/tax/service.js +11 -9
- package/dist/modules/webhooks/hook.js +2 -2
- package/dist/modules/webhooks/module.d.ts.map +1 -1
- package/dist/modules/webhooks/module.js +1 -0
- package/dist/modules/webhooks/service.d.ts +2 -0
- package/dist/modules/webhooks/service.d.ts.map +1 -1
- package/dist/modules/webhooks/service.js +4 -4
- package/dist/runtime/kernel-modules.d.ts +73 -0
- package/dist/runtime/kernel-modules.d.ts.map +1 -1
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +10 -2
- package/dist/test-utils/create-pglite-adapter.d.ts.map +1 -1
- package/dist/test-utils/create-pglite-adapter.js +35 -13
- package/dist/test-utils/create-test-config.d.ts.map +1 -1
- package/dist/test-utils/create-test-config.js +4 -0
- package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
- package/dist/test-utils/rest-api-test-utils.js +2 -0
- package/dist/test-utils/test-actors.js +2 -2
- package/dist/utils/id.d.ts +2 -0
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +11 -0
- package/package.json +6 -5
- package/src/auth/auth-schema-guard.ts +143 -0
- package/src/auth/auth-schema.ts +50 -19
- package/src/auth/middleware.ts +17 -5
- package/src/auth/org.ts +15 -3
- package/src/auth/organization-guard.ts +158 -0
- package/src/auth/permissions.ts +31 -8
- package/src/auth/role-authority.ts +107 -0
- package/src/auth/setup.ts +17 -0
- package/src/auth/strict-org-resolution.ts +7 -1
- package/src/auth/types.ts +1 -1
- package/src/config/defaults.ts +2 -0
- package/src/config/types.ts +32 -4
- package/src/hooks/checkout.ts +19 -12
- package/src/index.ts +30 -6
- package/src/interfaces/rest/audit-middleware.ts +2 -0
- package/src/interfaces/rest/customer-portal.ts +31 -24
- package/src/interfaces/rest/index.ts +4 -0
- package/src/interfaces/rest/route-coverage.ts +103 -0
- package/src/interfaces/rest/router.ts +16 -10
- package/src/interfaces/rest/routes/admin/compensation-failures.ts +8 -5
- package/src/interfaces/rest/routes/admin/custom-field-proposals.ts +37 -0
- package/src/interfaces/rest/routes/admin/entity-field-definitions.ts +89 -0
- package/src/interfaces/rest/routes/admin/permissions.ts +3 -1
- package/src/interfaces/rest/routes/admin/staff.ts +161 -72
- package/src/interfaces/rest/routes/admin-jobs.ts +3 -3
- package/src/interfaces/rest/routes/audit.ts +3 -3
- package/src/interfaces/rest/routes/carts.ts +17 -7
- package/src/interfaces/rest/routes/catalog.ts +96 -0
- package/src/interfaces/rest/routes/checkout.ts +41 -38
- package/src/interfaces/rest/routes/documents.ts +15 -1
- package/src/interfaces/rest/routes/inventory.ts +2 -0
- package/src/interfaces/rest/routes/media.ts +8 -3
- package/src/interfaces/rest/routes/orders.ts +27 -8
- package/src/interfaces/rest/routes/pricing.ts +2 -2
- package/src/interfaces/rest/routes/promotions.ts +12 -9
- package/src/interfaces/rest/routes/search.ts +19 -1
- package/src/interfaces/rest/schemas/admin-custom-field-proposals.ts +29 -0
- package/src/interfaces/rest/schemas/admin-entity-field-definitions.ts +120 -0
- package/src/interfaces/rest/schemas/catalog.ts +92 -0
- package/src/interfaces/rest/schemas/search.ts +2 -0
- package/src/interfaces/rest/utils.ts +61 -2
- package/src/kernel/compensation/executor.ts +2 -2
- package/src/kernel/database/tx-context.ts +25 -0
- package/src/kernel/hooks/create-context.ts +3 -0
- package/src/kernel/hooks/types.ts +2 -0
- package/src/kernel/plugin/manifest.ts +9 -5
- package/src/modules/analytics/service.ts +2 -2
- package/src/modules/audit/service.ts +3 -3
- package/src/modules/cart/repository/index.ts +22 -8
- package/src/modules/cart/schema.ts +4 -0
- package/src/modules/cart/service.ts +62 -27
- package/src/modules/catalog/brand-service.ts +7 -7
- package/src/modules/catalog/category-service.ts +7 -7
- package/src/modules/catalog/entity-service.ts +188 -53
- package/src/modules/catalog/module.ts +15 -0
- package/src/modules/catalog/ownership.ts +17 -0
- package/src/modules/catalog/read-policy.ts +16 -0
- package/src/modules/catalog/repository/index.ts +566 -4
- package/src/modules/catalog/revision.ts +35 -0
- package/src/modules/catalog/schema.ts +169 -1
- package/src/modules/catalog/schemas.ts +2 -0
- package/src/modules/catalog/service.ts +766 -26
- package/src/modules/channels/adapter.ts +107 -1
- package/src/modules/customers/module.ts +2 -0
- package/src/modules/customers/service.ts +23 -22
- package/src/modules/documents/module.ts +2 -0
- package/src/modules/documents/service.ts +74 -11
- package/src/modules/fulfillment/module.ts +2 -0
- package/src/modules/fulfillment/service.ts +17 -6
- package/src/modules/inventory/service.ts +15 -24
- package/src/modules/media/module.ts +2 -0
- package/src/modules/media/schema.ts +23 -2
- package/src/modules/media/service.ts +89 -28
- package/src/modules/orders/guest-access.ts +55 -0
- package/src/modules/orders/module.ts +1 -0
- package/src/modules/orders/quote.ts +1 -0
- package/src/modules/orders/repository/index.ts +2 -0
- package/src/modules/orders/schema.ts +5 -3
- package/src/modules/orders/service.ts +302 -52
- package/src/modules/pricing/module.ts +2 -0
- package/src/modules/pricing/schema.ts +1 -0
- package/src/modules/pricing/schemas.ts +1 -0
- package/src/modules/pricing/service.ts +21 -18
- package/src/modules/promotions/module.ts +2 -0
- package/src/modules/promotions/service.ts +25 -16
- package/src/modules/search/adapter.ts +8 -0
- package/src/modules/search/module.ts +3 -0
- package/src/modules/search/service.ts +142 -12
- package/src/modules/settings/module.ts +2 -0
- package/src/modules/settings/service.ts +8 -4
- package/src/modules/shipping/service.ts +9 -9
- package/src/modules/tax/module.ts +1 -0
- package/src/modules/tax/service.ts +13 -9
- package/src/modules/webhooks/hook.ts +2 -2
- package/src/modules/webhooks/module.ts +2 -0
- package/src/modules/webhooks/service.ts +6 -4
- package/src/runtime/server.ts +16 -2
- package/src/test-utils/create-pglite-adapter.ts +34 -12
- package/src/test-utils/create-test-config.ts +10 -6
- package/src/test-utils/rest-api-test-utils.ts +2 -0
- package/src/test-utils/test-actors.ts +2 -2
- package/src/utils/id.ts +20 -0
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { assertOwnership, assertPermission } from "../../auth/permissions.js";
|
|
3
|
-
import {
|
|
1
|
+
import { resolveOrgIdForCommerce } from "../../auth/org.js";
|
|
2
|
+
import { assertOwnership, assertPermission, hasPermission } from "../../auth/permissions.js";
|
|
3
|
+
import { defaultGuestOrderAccess } from "./guest-access.js";
|
|
4
|
+
import { isCatalogEntityVisible } from "../catalog/read-policy.js";
|
|
5
|
+
import { CommerceConflictError, CommerceForbiddenError, CommerceInvalidTransitionError, CommerceNotFoundError, CommerceValidationError, toCommerceError, } from "../../kernel/errors.js";
|
|
4
6
|
import { runAfterHooks, runBeforeHooks } from "../../kernel/hooks/executor.js";
|
|
5
7
|
import { createHookContext } from "../../kernel/hooks/create-context.js";
|
|
6
8
|
import { canTransition, orderStateMachine, } from "../../kernel/state-machine/machine.js";
|
|
7
9
|
import { Err, Ok } from "../../kernel/result.js";
|
|
8
10
|
import { createLogger } from "../../utils/logger.js";
|
|
11
|
+
import { makeIdempotencyScope } from "../../utils/id.js";
|
|
9
12
|
import { paginate } from "../../utils/pagination.js";
|
|
10
13
|
import { withTransaction, } from "../../kernel/database/tx-context.js";
|
|
11
|
-
function context(actor, services, database, tx = null) {
|
|
14
|
+
function context(actor, services, database, config, tx = null) {
|
|
12
15
|
return createHookContext({
|
|
13
16
|
actor,
|
|
14
17
|
tx,
|
|
@@ -17,6 +20,7 @@ function context(actor, services, database, tx = null) {
|
|
|
17
20
|
...(services.jobs ? { jobs: services.jobs } : {}),
|
|
18
21
|
context: { moduleName: "orders" },
|
|
19
22
|
database: { db: database.db },
|
|
23
|
+
commerceConfig: config,
|
|
20
24
|
});
|
|
21
25
|
}
|
|
22
26
|
export class OrderService {
|
|
@@ -58,8 +62,15 @@ export class OrderService {
|
|
|
58
62
|
const resolved = [];
|
|
59
63
|
for (const item of input.lineItems) {
|
|
60
64
|
// Org-integrity — the referenced entity must belong to this order's org.
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
// This is an internal invariant check, so it reads past the storefront
|
|
66
|
+
// visibility policy; unprivileged buyers are gated in the same branch.
|
|
67
|
+
const owned = await catalog.getByIdForInternalUse(item.entityId, resolveOrgIdForCommerce(actor, this.deps.config), { includeVariants: item.variantId !== undefined }, ctx);
|
|
68
|
+
if (!owned.ok ||
|
|
69
|
+
!owned.value ||
|
|
70
|
+
!isCatalogEntityVisible({
|
|
71
|
+
status: owned.value?.status ?? "draft",
|
|
72
|
+
isVisible: owned.value?.isVisible ?? false,
|
|
73
|
+
}, actor)) {
|
|
63
74
|
return Err(new CommerceValidationError(`Line item entity ${item.entityId} does not belong to this organization.`));
|
|
64
75
|
}
|
|
65
76
|
if (item.variantId !== undefined &&
|
|
@@ -92,6 +103,112 @@ export class OrderService {
|
|
|
92
103
|
}
|
|
93
104
|
return Ok(resolved);
|
|
94
105
|
}
|
|
106
|
+
async resolveCreateCustomerId(requestedCustomerId, actor, ctx) {
|
|
107
|
+
// API keys are the documented POS operator actor. Keep this as an actor
|
|
108
|
+
// type predicate so self-service user actors remain unable to choose a
|
|
109
|
+
// foreign customerId even when they are authenticated.
|
|
110
|
+
const isOperator = actor?.type === "api_key";
|
|
111
|
+
if (isOperator) {
|
|
112
|
+
if (requestedCustomerId === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
return this.resolveRequestedCustomerId(requestedCustomerId, actor, ctx);
|
|
115
|
+
}
|
|
116
|
+
if (hasPermission(actor, "orders:create:on-behalf")) {
|
|
117
|
+
if (requestedCustomerId === undefined)
|
|
118
|
+
return undefined;
|
|
119
|
+
return this.resolveRequestedCustomerId(requestedCustomerId, actor, ctx);
|
|
120
|
+
}
|
|
121
|
+
// `orders:read:own` is the system's existing "this actor is a shopper"
|
|
122
|
+
// marker -- it is in DEFAULT_CUSTOMER_PERMISSIONS and guards the read-own
|
|
123
|
+
// order routes. Using it here decides *attribution*, which is a proxy and is
|
|
124
|
+
// deliberately a stopgap: the honest discriminator is caller intent, which a
|
|
125
|
+
// storefront route knows and this service cannot see.
|
|
126
|
+
//
|
|
127
|
+
// Known misclassification: a dual-hatted role holding `orders:read:own` for
|
|
128
|
+
// its own personal orders, plus `orders:create`, self-attributes a walk-in
|
|
129
|
+
// sale. The proxy is tolerable only because it fails narrow -- it can attach
|
|
130
|
+
// the actor's own profile or fall through to a guest order, never expose
|
|
131
|
+
// another principal's data.
|
|
132
|
+
if (!hasPermission(actor, "orders:read:own"))
|
|
133
|
+
return undefined;
|
|
134
|
+
if (!actor?.userId)
|
|
135
|
+
return undefined;
|
|
136
|
+
const customers = this.deps.services.customers;
|
|
137
|
+
if (!customers?.getByUserId)
|
|
138
|
+
return undefined;
|
|
139
|
+
const own = await customers.getByUserId(actor.userId, actor, ctx);
|
|
140
|
+
return own.ok ? own.value?.id : undefined;
|
|
141
|
+
}
|
|
142
|
+
async resolveRequestedCustomerId(requestedCustomerId, actor, ctx) {
|
|
143
|
+
const customers = this.deps.services.customers;
|
|
144
|
+
const customer = await customers?.getById(requestedCustomerId, actor, ctx);
|
|
145
|
+
if (!customer?.ok || !customer.value) {
|
|
146
|
+
throw new CommerceValidationError("customerId must reference a customer in this organization.");
|
|
147
|
+
}
|
|
148
|
+
return customer.value.id;
|
|
149
|
+
}
|
|
150
|
+
async authorizeOrderRead(order, actor, ctx, guestCredential) {
|
|
151
|
+
try {
|
|
152
|
+
if (actor?.permissions.includes("orders:read") ||
|
|
153
|
+
actor?.permissions.includes("*:*")) {
|
|
154
|
+
// no-op
|
|
155
|
+
}
|
|
156
|
+
else if (actor?.permissions.includes("orders:read:own")) {
|
|
157
|
+
if (order.customerId == null) {
|
|
158
|
+
const cartId = typeof order.metadata?.cartId === "string"
|
|
159
|
+
? order.metadata.cartId
|
|
160
|
+
: undefined;
|
|
161
|
+
const cart = this.deps.services.cart;
|
|
162
|
+
if (!cartId || !guestCredential || !cart?.getById) {
|
|
163
|
+
throw new CommerceForbiddenError("You do not have access to this resource.");
|
|
164
|
+
}
|
|
165
|
+
const guestCart = await cart.getById(cartId, actor, ctx, guestCredential);
|
|
166
|
+
if (!guestCart.ok) {
|
|
167
|
+
throw new CommerceForbiddenError("You do not have access to this resource.");
|
|
168
|
+
}
|
|
169
|
+
// The secret is genuine, but a bearer credential with no lifetime
|
|
170
|
+
// reads this order forever — and a secret leaks far more easily than
|
|
171
|
+
// it is guessed. Bound it to a window after placement, and fail with
|
|
172
|
+
// the identical error so a stale window is not an oracle telling the
|
|
173
|
+
// caller their secret is valid.
|
|
174
|
+
const guestAccess = this.deps.config.orders?.guestAccessStrategy ?? defaultGuestOrderAccess;
|
|
175
|
+
if (!guestAccess.canAccessOrder(order, new Date())) {
|
|
176
|
+
throw new CommerceForbiddenError("You do not have access to this resource.");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
// Older integrations may have stored the auth user ID directly as
|
|
181
|
+
// customerId. Keep that valid ownership shape while resolving the
|
|
182
|
+
// normal auth-user -> customer-profile relationship below.
|
|
183
|
+
let ownerActor = actor;
|
|
184
|
+
if (actor.userId !== order.customerId) {
|
|
185
|
+
const customers = this.deps.services.customers;
|
|
186
|
+
const profile = actor.userId && customers?.getByUserId
|
|
187
|
+
? await customers.getByUserId(actor.userId, actor, ctx)
|
|
188
|
+
: { ok: false };
|
|
189
|
+
ownerActor = profile.ok
|
|
190
|
+
? { ...actor, userId: profile.value.id }
|
|
191
|
+
: actor;
|
|
192
|
+
}
|
|
193
|
+
assertOwnership(ownerActor, order.customerId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
assertPermission(actor, "orders:read");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
return Err(toCommerceError(error));
|
|
202
|
+
}
|
|
203
|
+
return Ok(undefined);
|
|
204
|
+
}
|
|
205
|
+
async authorizedReplay(order, actor, ctx, guestCredential) {
|
|
206
|
+
const access = await this.authorizeOrderRead(order, actor, ctx, guestCredential);
|
|
207
|
+
if (!access.ok) {
|
|
208
|
+
return Err(new CommerceConflictError("Idempotency key does not belong to this account."));
|
|
209
|
+
}
|
|
210
|
+
return Ok(await this.hydrateOrder(order, ctx));
|
|
211
|
+
}
|
|
95
212
|
async create(input, actor, ctx, opts) {
|
|
96
213
|
if (opts?.stockPolicy === "reserve" && !ctx) {
|
|
97
214
|
return withTransaction(this.deps.database, { actor }, (txCtx) => this.create(input, actor, txCtx, opts));
|
|
@@ -105,17 +222,37 @@ export class OrderService {
|
|
|
105
222
|
if (input.lineItems.length === 0) {
|
|
106
223
|
return Err(new CommerceValidationError("Order requires at least one line item."));
|
|
107
224
|
}
|
|
225
|
+
let resolvedCustomerId;
|
|
226
|
+
try {
|
|
227
|
+
resolvedCustomerId = await this.resolveCreateCustomerId(input.customerId, actor, ctx);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
return Err(toCommerceError(error));
|
|
231
|
+
}
|
|
232
|
+
const serviceInput = {
|
|
233
|
+
...input,
|
|
234
|
+
...(resolvedCustomerId !== undefined
|
|
235
|
+
? { customerId: resolvedCustomerId }
|
|
236
|
+
: {}),
|
|
237
|
+
};
|
|
238
|
+
if (resolvedCustomerId === undefined)
|
|
239
|
+
delete serviceInput.customerId;
|
|
108
240
|
const beforeHooks = this.deps.hooks.resolve("orders.beforeCreate");
|
|
109
241
|
const afterHooks = this.deps.hooks.resolve("orders.afterCreate");
|
|
110
|
-
const hookCtx = context(actor, this.deps.services, this.deps.database, ctx?.tx);
|
|
111
|
-
const processed = await runBeforeHooks(beforeHooks,
|
|
112
|
-
const orgId =
|
|
242
|
+
const hookCtx = context(actor, this.deps.services, this.deps.database, this.deps.config, ctx?.tx);
|
|
243
|
+
const processed = await runBeforeHooks(beforeHooks, serviceInput, "create", hookCtx);
|
|
244
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
245
|
+
const idempotencyScope = processed.idempotencyKey
|
|
246
|
+
? await makeIdempotencyScope(actor, opts?.guestCredential, typeof processed.metadata?.cartId === "string"
|
|
247
|
+
? processed.metadata.cartId
|
|
248
|
+
: undefined)
|
|
249
|
+
: undefined;
|
|
113
250
|
// Idempotent replay: offline POS queues and network retries re-submit the
|
|
114
251
|
// same create — return the original order instead of double-creating.
|
|
115
252
|
if (processed.idempotencyKey) {
|
|
116
|
-
const existing = await this.repo.findByIdempotencyKey(orgId, processed.idempotencyKey, ctx);
|
|
253
|
+
const existing = await this.repo.findByIdempotencyKey(orgId, processed.idempotencyKey, idempotencyScope, ctx);
|
|
117
254
|
if (existing) {
|
|
118
|
-
return
|
|
255
|
+
return this.authorizedReplay(existing, actor, ctx, opts?.guestCredential);
|
|
119
256
|
}
|
|
120
257
|
}
|
|
121
258
|
// Resolve line prices with org-integrity + provenance (see resolveLines).
|
|
@@ -167,6 +304,7 @@ export class OrderService {
|
|
|
167
304
|
...(processed.paymentIntentId != null ? { paymentIntentId: processed.paymentIntentId } : {}),
|
|
168
305
|
...(processed.paymentMethodId != null ? { paymentMethodId: processed.paymentMethodId } : {}),
|
|
169
306
|
...(processed.idempotencyKey != null ? { idempotencyKey: processed.idempotencyKey } : {}),
|
|
307
|
+
...(idempotencyScope !== undefined ? { idempotencyScope } : {}),
|
|
170
308
|
metadata: processed.metadata ?? {},
|
|
171
309
|
placedAt: new Date(),
|
|
172
310
|
...(processed.customerId !== undefined
|
|
@@ -177,9 +315,10 @@ export class OrderService {
|
|
|
177
315
|
catch (error) {
|
|
178
316
|
// Concurrent replay lost the unique-index race — return the winner.
|
|
179
317
|
if (processed.idempotencyKey) {
|
|
180
|
-
const winner = await this.repo.findByIdempotencyKey(orgId, processed.idempotencyKey, ctx);
|
|
181
|
-
if (winner)
|
|
182
|
-
return
|
|
318
|
+
const winner = await this.repo.findByIdempotencyKey(orgId, processed.idempotencyKey, idempotencyScope, ctx);
|
|
319
|
+
if (winner) {
|
|
320
|
+
return this.authorizedReplay(winner, actor, ctx, opts?.guestCredential);
|
|
321
|
+
}
|
|
183
322
|
}
|
|
184
323
|
throw error;
|
|
185
324
|
}
|
|
@@ -228,49 +367,39 @@ export class OrderService {
|
|
|
228
367
|
const report = await runAfterHooks(afterHooks, null, hydrated, "create", hookCtx);
|
|
229
368
|
return Ok(hydrated, report.hasErrors ? { hookErrors: report.errors } : undefined);
|
|
230
369
|
}
|
|
231
|
-
async getById(id, actor, ctx) {
|
|
232
|
-
const orgId =
|
|
370
|
+
async getById(id, actor, ctx, guestCredential) {
|
|
371
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
233
372
|
const order = await this.repo.findById(orgId, id, ctx);
|
|
234
373
|
if (!order)
|
|
235
374
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// no-op
|
|
240
|
-
}
|
|
241
|
-
else if (actor?.permissions.includes("orders:read:own")) {
|
|
242
|
-
assertOwnership(actor, order.customerId ?? null);
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
assertPermission(actor, "orders:read");
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
return Err(toCommerceError(error));
|
|
250
|
-
}
|
|
375
|
+
const access = await this.authorizeOrderRead(order, actor, ctx, guestCredential);
|
|
376
|
+
if (!access.ok)
|
|
377
|
+
return access;
|
|
251
378
|
const hydrated = await this.hydrateOrder(order, ctx);
|
|
252
379
|
// Run afterGet hooks — allows plugins to enrich the order (e.g., vendor fulfillment)
|
|
253
380
|
const afterGetHooks = this.deps.hooks.resolve("orders.afterGet");
|
|
254
381
|
if (afterGetHooks.length > 0) {
|
|
255
|
-
const hookCtx = context(actor, this.deps.services, this.deps.database, ctx?.tx);
|
|
382
|
+
const hookCtx = context(actor, this.deps.services, this.deps.database, this.deps.config, ctx?.tx);
|
|
256
383
|
await runAfterHooks(afterGetHooks, null, hydrated, "read", hookCtx);
|
|
257
384
|
}
|
|
258
385
|
return Ok(hydrated);
|
|
259
386
|
}
|
|
260
|
-
async getByNumber(orderNumber, actor, ctx) {
|
|
261
|
-
const orgId =
|
|
387
|
+
async getByNumber(orderNumber, actor, ctx, guestCredential) {
|
|
388
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
262
389
|
const order = await this.repo.findByOrderNumber(orgId, orderNumber, ctx);
|
|
263
390
|
if (!order)
|
|
264
391
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
265
|
-
return this.getById(order.id, actor, ctx);
|
|
392
|
+
return this.getById(order.id, actor, ctx, guestCredential);
|
|
266
393
|
}
|
|
267
394
|
/** Returns the order previously created with this idempotency key, or null. */
|
|
268
|
-
async getByIdempotencyKey(idempotencyKey, actor, ctx) {
|
|
269
|
-
const orgId =
|
|
270
|
-
const
|
|
395
|
+
async getByIdempotencyKey(idempotencyKey, actor, ctx, guestCredential) {
|
|
396
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
397
|
+
const resolvedActor = actor ?? ctx?.actor ?? null;
|
|
398
|
+
const idempotencyScope = await makeIdempotencyScope(resolvedActor, guestCredential);
|
|
399
|
+
const order = await this.repo.findByIdempotencyKey(orgId, idempotencyKey, idempotencyScope, ctx);
|
|
271
400
|
if (!order)
|
|
272
401
|
return Ok(null);
|
|
273
|
-
return
|
|
402
|
+
return this.authorizedReplay(order, actor ?? ctx?.actor ?? null, ctx, guestCredential);
|
|
274
403
|
}
|
|
275
404
|
async list(params, actor, ctx) {
|
|
276
405
|
try {
|
|
@@ -279,7 +408,7 @@ export class OrderService {
|
|
|
279
408
|
catch (error) {
|
|
280
409
|
return Err(toCommerceError(error));
|
|
281
410
|
}
|
|
282
|
-
const orgId =
|
|
411
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
283
412
|
let items;
|
|
284
413
|
if (params.status) {
|
|
285
414
|
items = await this.repo.findByStatus(orgId, params.status, ctx);
|
|
@@ -297,7 +426,7 @@ export class OrderService {
|
|
|
297
426
|
});
|
|
298
427
|
}
|
|
299
428
|
async listByCustomer(customerId, params, actor, ctx) {
|
|
300
|
-
const orgId =
|
|
429
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
301
430
|
let items = await this.repo.findByCustomerId(orgId, customerId, ctx);
|
|
302
431
|
if (params.status) {
|
|
303
432
|
items = items.filter((order) => order.status === params.status);
|
|
@@ -342,7 +471,7 @@ export class OrderService {
|
|
|
342
471
|
if (term.length < 3) {
|
|
343
472
|
return Ok({ items: [], hint: "Enter at least 3 characters to search." });
|
|
344
473
|
}
|
|
345
|
-
const orgId =
|
|
474
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
346
475
|
const rows = await this.repo.lookup(orgId, term, opts, ctx);
|
|
347
476
|
const items = rows.map((r) => ({
|
|
348
477
|
id: r.id,
|
|
@@ -361,7 +490,7 @@ export class OrderService {
|
|
|
361
490
|
return Ok({ items });
|
|
362
491
|
}
|
|
363
492
|
async changeStatus(input, actor, ctx) {
|
|
364
|
-
const orgId =
|
|
493
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
365
494
|
const order = await this.repo.findById(orgId, input.orderId, ctx);
|
|
366
495
|
if (!order)
|
|
367
496
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -376,7 +505,7 @@ export class OrderService {
|
|
|
376
505
|
}
|
|
377
506
|
const beforeHooks = this.deps.hooks.resolve("orders.beforeStatusChange");
|
|
378
507
|
const afterHooks = this.deps.hooks.resolve("orders.afterStatusChange");
|
|
379
|
-
const hookCtx = context(actor, this.deps.services, this.deps.database, ctx?.tx);
|
|
508
|
+
const hookCtx = context(actor, this.deps.services, this.deps.database, this.deps.config, ctx?.tx);
|
|
380
509
|
const statusHookInput = {
|
|
381
510
|
orderId: order.id,
|
|
382
511
|
fromStatus: order.status,
|
|
@@ -562,7 +691,7 @@ export class OrderService {
|
|
|
562
691
|
catch (error) {
|
|
563
692
|
return Err(toCommerceError(error));
|
|
564
693
|
}
|
|
565
|
-
const orgId =
|
|
694
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
566
695
|
const found = await this.repo.findWithLineItems(orgId, orderId, ctx);
|
|
567
696
|
if (!found)
|
|
568
697
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -662,7 +791,7 @@ export class OrderService {
|
|
|
662
791
|
catch (error) {
|
|
663
792
|
return Err(toCommerceError(error));
|
|
664
793
|
}
|
|
665
|
-
const orgId =
|
|
794
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
666
795
|
const refund = await this.repo.findRefundById(orgId, refundId, ctx);
|
|
667
796
|
if (!refund || refund.orderId !== orderId) {
|
|
668
797
|
return Err(new CommerceNotFoundError("Refund not found."));
|
|
@@ -704,7 +833,7 @@ export class OrderService {
|
|
|
704
833
|
catch (error) {
|
|
705
834
|
return Err(toCommerceError(error));
|
|
706
835
|
}
|
|
707
|
-
const orgId =
|
|
836
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
708
837
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
709
838
|
if (!order)
|
|
710
839
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -718,7 +847,7 @@ export class OrderService {
|
|
|
718
847
|
catch (error) {
|
|
719
848
|
return Err(toCommerceError(error));
|
|
720
849
|
}
|
|
721
|
-
const orgId =
|
|
850
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
722
851
|
const policies = await this.refundPolicies(orgId, ctx);
|
|
723
852
|
const usedToday = await this.repo.sumRefundsByOperatorToday(orgId, actor?.userId ?? "system", policies.timezone, ctx);
|
|
724
853
|
return Ok({
|
|
@@ -735,7 +864,7 @@ export class OrderService {
|
|
|
735
864
|
catch (error) {
|
|
736
865
|
return Err(toCommerceError(error));
|
|
737
866
|
}
|
|
738
|
-
const orgId =
|
|
867
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
739
868
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
740
869
|
if (!order)
|
|
741
870
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -831,7 +960,7 @@ export class OrderService {
|
|
|
831
960
|
* payment operation, not a fulfillment one.
|
|
832
961
|
*/
|
|
833
962
|
async capture(orderId, actor, opts, ctx) {
|
|
834
|
-
const orgId =
|
|
963
|
+
const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
|
|
835
964
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
836
965
|
if (!order)
|
|
837
966
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -870,7 +999,7 @@ export class OrderService {
|
|
|
870
999
|
return Ok(hydrated);
|
|
871
1000
|
}
|
|
872
1001
|
async getStatusHistory(orderId, actor, ctx) {
|
|
873
|
-
const orgId =
|
|
1002
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
874
1003
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
875
1004
|
if (!order) {
|
|
876
1005
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -924,7 +1053,7 @@ export class OrderService {
|
|
|
924
1053
|
catch (error) {
|
|
925
1054
|
return Err(toCommerceError(error));
|
|
926
1055
|
}
|
|
927
|
-
const orgId =
|
|
1056
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
928
1057
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
929
1058
|
if (!order)
|
|
930
1059
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -989,7 +1118,7 @@ export class OrderService {
|
|
|
989
1118
|
catch (error) {
|
|
990
1119
|
return Err(toCommerceError(error));
|
|
991
1120
|
}
|
|
992
|
-
const orgId =
|
|
1121
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
993
1122
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
994
1123
|
if (!order)
|
|
995
1124
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -1022,7 +1151,7 @@ export class OrderService {
|
|
|
1022
1151
|
catch (error) {
|
|
1023
1152
|
return Err(toCommerceError(error));
|
|
1024
1153
|
}
|
|
1025
|
-
const orgId =
|
|
1154
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
1026
1155
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
1027
1156
|
if (!order)
|
|
1028
1157
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -1044,7 +1173,7 @@ export class OrderService {
|
|
|
1044
1173
|
return Ok(await this.recalcOrderTotals(order, actor, "line_item_removed", ctx));
|
|
1045
1174
|
}
|
|
1046
1175
|
async updateOrder(orderId, data, actor, ctx) {
|
|
1047
|
-
const orgId =
|
|
1176
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
1048
1177
|
const order = await this.repo.findById(orgId, orderId, ctx);
|
|
1049
1178
|
if (!order) {
|
|
1050
1179
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/module.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErD,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE;QACP,UAAU,EAAE,iBAAiB,CAAC;KAC/B,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,aAAa;YACd,OAAO,MAAM;oBAAkB,OAAO,cAAc;qCAgB9D,CAAC"}
|
|
@@ -104,6 +104,23 @@ export declare const prices: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
|
104
104
|
identity: undefined;
|
|
105
105
|
generated: undefined;
|
|
106
106
|
}, {}, {}>;
|
|
107
|
+
compareAtAmount: import("drizzle-orm/pg-core").PgColumn<{
|
|
108
|
+
name: "compare_at_amount";
|
|
109
|
+
tableName: "prices";
|
|
110
|
+
dataType: "number";
|
|
111
|
+
columnType: "PgInteger";
|
|
112
|
+
data: number;
|
|
113
|
+
driverParam: string | number;
|
|
114
|
+
notNull: false;
|
|
115
|
+
hasDefault: false;
|
|
116
|
+
isPrimaryKey: false;
|
|
117
|
+
isAutoincrement: false;
|
|
118
|
+
hasRuntimeDefault: false;
|
|
119
|
+
enumValues: undefined;
|
|
120
|
+
baseColumn: never;
|
|
121
|
+
identity: undefined;
|
|
122
|
+
generated: undefined;
|
|
123
|
+
}, {}, {}>;
|
|
107
124
|
customerGroupId: import("drizzle-orm/pg-core").PgColumn<{
|
|
108
125
|
name: "customer_group_id";
|
|
109
126
|
tableName: "prices";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkClB,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B1B,CAAC"}
|
|
@@ -12,6 +12,7 @@ export const prices = pgTable("prices", {
|
|
|
12
12
|
variantId: uuid("variant_id").references(() => variants.id, { onDelete: "cascade" }),
|
|
13
13
|
currency: text("currency").notNull(),
|
|
14
14
|
amount: integer("amount").notNull(),
|
|
15
|
+
compareAtAmount: integer("compare_at_amount"),
|
|
15
16
|
customerGroupId: text("customer_group_id"),
|
|
16
17
|
minQuantity: integer("min_quantity"),
|
|
17
18
|
maxQuantity: integer("max_quantity"),
|
|
@@ -4,6 +4,7 @@ export declare const SetBasePriceBodySchema: z.ZodObject<{
|
|
|
4
4
|
variantId: z.ZodOptional<z.ZodString>;
|
|
5
5
|
currency: z.ZodString;
|
|
6
6
|
amount: z.ZodNumber;
|
|
7
|
+
compareAtAmount: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
7
8
|
customerGroupId: z.ZodOptional<z.ZodString>;
|
|
8
9
|
minQuantity: z.ZodOptional<z.ZodNumber>;
|
|
9
10
|
maxQuantity: z.ZodOptional<z.ZodNumber>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAItC,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AAItC,eAAO,MAAM,sBAAsB;;;;;;;;;;;;iBAYF,CAAC;AAElC,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;iBAeF,CAAC;AAIpC,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACvE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -5,6 +5,7 @@ export const SetBasePriceBodySchema = z.object({
|
|
|
5
5
|
variantId: z.string().optional().openapi({ example: "variant-uuid" }),
|
|
6
6
|
currency: z.string().length(3).openapi({ example: "USD" }),
|
|
7
7
|
amount: z.number().openapi({ example: 29.99 }),
|
|
8
|
+
compareAtAmount: z.number().nullable().optional(),
|
|
8
9
|
customerGroupId: z.string().optional(),
|
|
9
10
|
minQuantity: z.number().int().optional(),
|
|
10
11
|
maxQuantity: z.number().int().optional(),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Actor } from "../../auth/types.js";
|
|
2
|
+
import type { CommerceConfig } from "../../config/types.js";
|
|
2
3
|
import type { DatabaseAdapter } from "../../kernel/database/adapter.js";
|
|
3
4
|
import type { TxContext } from "../../kernel/database/tx-context.js";
|
|
4
5
|
import type { HookRegistry } from "../../kernel/hooks/registry.js";
|
|
@@ -10,6 +11,7 @@ interface PricingServiceDeps {
|
|
|
10
11
|
repository: PricingRepository;
|
|
11
12
|
catalogRepository: CatalogRepository;
|
|
12
13
|
hooks: HookRegistry;
|
|
14
|
+
config: CommerceConfig;
|
|
13
15
|
services: Record<string, unknown>;
|
|
14
16
|
database: DatabaseAdapter;
|
|
15
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAOrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EACV,iBAAiB,EACjB,KAAK,EACL,aAAa,EAGd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxE,MAAM,MAAM,iBAAiB,GACzB,qBAAqB,GACrB,gBAAgB,GAChB,QAAQ,GACR,UAAU,CAAC;AAEf,UAAU,kBAAkB;IAC1B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,eAAe,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/pricing/service.ts"],"names":[],"mappings":"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"}
|