Merged PR 1989: fix(checkout): resolve currency constraint violations in price handling

fix(checkout): resolve currency constraint violations in price handling

- Add ensureCurrencyDefaults() helper to normalize price objects with EUR defaults
- Fix currency constraint violation in shopping cart item additions (bug #5405)
- Apply price normalization across availability, checkout, and shopping cart services
- Update 8 locations: availability.adapter, checkout.service, shopping-cart.service,
  get-availability-params.adapter, availability-transformers, reward quantity control
- Refactor OrderType to @isa/common/data-access for cross-domain reusability
- Remove duplicate availability service from catalogue library
- Enhance PriceValue and VatValue schemas with proper currency defaults
- Add availability-transformers.spec.ts test coverage
- Fix QuantityControl fallback from 0 to 1 to prevent invalid state warnings

Resolves issue where POST requests to /checkout/v6/store/shoppingcart/{id}/item
were sending price objects without required currency/currencySymbol fields,
causing 400 Bad Request with 'Currency: Constraint violation: NotNull' error.

Related work items: #5405
This commit is contained in:
Lorenz Hilpert
2025-10-28 10:34:39 +00:00
committed by Nino Righi
parent 2d654aa63a
commit bfd151dd84
24 changed files with 1185 additions and 1170 deletions

View File

@@ -3899,6 +3899,90 @@
"implicitDependencies": []
}
},
"format-name": {
"name": "format-name",
"type": "lib",
"data": {
"root": "libs/utils/format-name",
"targets": {
"eslint:lint": {
"cache": true,
"options": {
"cwd": "libs/utils/format-name",
"command": "eslint ."
},
"inputs": [
"default",
"^default",
"{workspaceRoot}/eslint.config.js",
"{workspaceRoot}/libs/utils/format-name/eslint.config.cjs",
"{workspaceRoot}/tools/eslint-rules/**/*",
{
"externalDependencies": [
"eslint"
]
}
],
"outputs": [
"{options.outputFile}"
],
"metadata": {
"technologies": [
"eslint"
],
"description": "Runs ESLint on project",
"help": {
"command": "npx eslint --help",
"example": {
"options": {
"max-warnings": 0
}
}
}
},
"executor": "nx:run-commands",
"configurations": {},
"parallelism": true
},
"test": {
"executor": "@nx/vite:test",
"outputs": [
"{options.reportsDirectory}"
],
"options": {
"reportsDirectory": "../../../coverage/libs/utils/format-name"
},
"configurations": {},
"parallelism": true,
"cache": true,
"inputs": [
"default",
"^production"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"configurations": {},
"options": {},
"parallelism": true,
"cache": true,
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.json",
"{workspaceRoot}/.eslintignore",
"{workspaceRoot}/eslint.config.js"
]
}
},
"name": "format-name",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/utils/format-name/src",
"prefix": "lib",
"projectType": "library",
"tags": [],
"implicitDependencies": []
}
},
"ui-input-controls": {
"name": "ui-input-controls",
"type": "lib",
@@ -5530,6 +5614,90 @@
"implicitDependencies": []
}
},
"ui-carousel": {
"name": "ui-carousel",
"type": "lib",
"data": {
"root": "libs/ui/carousel",
"targets": {
"eslint:lint": {
"cache": true,
"options": {
"cwd": "libs/ui/carousel",
"command": "eslint ."
},
"inputs": [
"default",
"^default",
"{workspaceRoot}/eslint.config.js",
"{workspaceRoot}/libs/ui/carousel/eslint.config.cjs",
"{workspaceRoot}/tools/eslint-rules/**/*",
{
"externalDependencies": [
"eslint"
]
}
],
"outputs": [
"{options.outputFile}"
],
"metadata": {
"technologies": [
"eslint"
],
"description": "Runs ESLint on project",
"help": {
"command": "npx eslint --help",
"example": {
"options": {
"max-warnings": 0
}
}
}
},
"executor": "nx:run-commands",
"configurations": {},
"parallelism": true
},
"test": {
"executor": "@nx/vite:test",
"outputs": [
"{options.reportsDirectory}"
],
"options": {
"reportsDirectory": "../../../coverage/libs/ui/carousel"
},
"configurations": {},
"parallelism": true,
"cache": true,
"inputs": [
"default",
"^production"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"configurations": {},
"options": {},
"parallelism": true,
"cache": true,
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.json",
"{workspaceRoot}/.eslintignore",
"{workspaceRoot}/eslint.config.js"
]
}
},
"name": "ui-carousel",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/ui/carousel/src",
"prefix": "ui",
"projectType": "library",
"tags": [],
"implicitDependencies": []
}
},
"ui-buttons": {
"name": "ui-buttons",
"type": "lib",
@@ -6753,6 +6921,11 @@
"target": "ui-empty-state",
"type": "static"
},
{
"source": "remission-shared-search-item-to-remit-dialog",
"target": "utils-scroll-position",
"type": "static"
},
{
"source": "remission-shared-search-item-to-remit-dialog",
"target": "remission-shared-product",
@@ -6764,7 +6937,63 @@
"type": "static"
}
],
"checkout-feature-reward-order-confirmation": [],
"checkout-feature-reward-order-confirmation": [
{
"source": "checkout-feature-reward-order-confirmation",
"target": "shared-address",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "crm-data-access",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "oms-data-access",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "icons",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "ui-buttons",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "ui-input-controls",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "checkout-data-access",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "shared-product-image",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "shared-product-router-link",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "checkout-shared-product-info",
"type": "static"
},
{
"source": "checkout-feature-reward-order-confirmation",
"target": "core-tabs",
"type": "static"
}
],
"remission-return-receipt-actions": [
{
"source": "remission-return-receipt-actions",
@@ -6840,16 +7069,6 @@
}
],
"reward-selection-dialog": [
{
"source": "reward-selection-dialog",
"target": "shared-address",
"type": "static"
},
{
"source": "reward-selection-dialog",
"target": "checkout-data-access",
"type": "static"
},
{
"source": "reward-selection-dialog",
"target": "availability-data-access",
@@ -6860,6 +7079,11 @@
"target": "catalogue-data-access",
"type": "static"
},
{
"source": "reward-selection-dialog",
"target": "checkout-data-access",
"type": "static"
},
{
"source": "reward-selection-dialog",
"target": "core-logging",
@@ -6986,6 +7210,16 @@
"source": "checkout-feature-reward-shopping-cart",
"target": "reward-selection-dialog",
"type": "static"
},
{
"source": "checkout-feature-reward-shopping-cart",
"target": "oms-data-access",
"type": "static"
},
{
"source": "checkout-feature-reward-shopping-cart",
"target": "common-data-access",
"type": "static"
}
],
"remi-remission-list": [
@@ -7136,6 +7370,11 @@
"target": "crm-data-access",
"type": "static"
},
{
"source": "reward-catalog",
"target": "core-navigation",
"type": "static"
},
{
"source": "reward-catalog",
"target": "utils-scroll-position",
@@ -7146,6 +7385,11 @@
"target": "ui-skeleton-loader",
"type": "static"
},
{
"source": "reward-catalog",
"target": "format-name",
"type": "static"
},
{
"source": "reward-catalog",
"target": "ui-input-controls",
@@ -7199,6 +7443,11 @@
"target": "catalogue-data-access",
"type": "static"
},
{
"source": "checkout-shared-product-info",
"target": "shared-product-format",
"type": "static"
},
{
"source": "checkout-shared-product-info",
"target": "shared-product-image",
@@ -7209,11 +7458,6 @@
"target": "shared-product-router-link",
"type": "static"
},
{
"source": "checkout-shared-product-info",
"target": "shared-product-format",
"type": "static"
},
{
"source": "checkout-shared-product-info",
"target": "remission-data-access",
@@ -7253,6 +7497,11 @@
"target": "ui-buttons",
"type": "static"
},
{
"source": "oms-feature-return-details",
"target": "format-name",
"type": "static"
},
{
"source": "oms-feature-return-details",
"target": "ui-menu",
@@ -7456,6 +7705,11 @@
"target": "ui-tooltip",
"type": "static"
},
{
"source": "oms-feature-return-search",
"target": "format-name",
"type": "static"
},
{
"source": "oms-feature-return-search",
"target": "ui-item-rows",
@@ -7711,6 +7965,16 @@
"source": "utils-scroll-position",
"target": "core-storage",
"type": "static"
},
{
"source": "utils-scroll-position",
"target": "icons",
"type": "static"
},
{
"source": "utils-scroll-position",
"target": "ui-buttons",
"type": "static"
}
],
"checkout-data-access": [
@@ -7754,6 +8018,16 @@
"target": "common-data-access",
"type": "static"
},
{
"source": "checkout-data-access",
"target": "shared-address",
"type": "static"
},
{
"source": "checkout-data-access",
"target": "oms-data-access",
"type": "static"
},
{
"source": "checkout-data-access",
"target": "catalogue-data-access",
@@ -7774,11 +8048,6 @@
"target": "common-decorators",
"type": "static"
},
{
"source": "checkout-data-access",
"target": "oms-data-access",
"type": "static"
},
{
"source": "checkout-data-access",
"target": "remission-data-access",
@@ -7839,6 +8108,7 @@
"ui-skeleton-loader": [],
"utils-z-safe-parse": [],
"common-decorators": [],
"format-name": [],
"ui-input-controls": [
{
"source": "ui-input-controls",
@@ -7864,6 +8134,11 @@
}
],
"crm-data-access": [
{
"source": "crm-data-access",
"target": "generated-swagger-oms-api",
"type": "static"
},
{
"source": "crm-data-access",
"target": "generated-swagger-crm-api",
@@ -8094,6 +8369,18 @@
],
"ui-item-rows": [],
"core-config": [],
"ui-carousel": [
{
"source": "ui-carousel",
"target": "ui-buttons",
"type": "static"
},
{
"source": "ui-carousel",
"target": "icons",
"type": "static"
}
],
"ui-buttons": [
{
"source": "ui-buttons",
@@ -8336,6 +8623,11 @@
"target": "ui-buttons",
"type": "static"
},
{
"source": "isa-app",
"target": "ui-carousel",
"type": "static"
},
{
"source": "isa-app",
"target": "ui-datepicker",