feature(payment-provider): Added payment provider for QR code. Remove… - #412
Conversation
…d QR SPAYD from product metadata
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Blacksmith Account SuspendedThis Blacksmith account requires additional verification. Jobs targeting Blacksmith runners will not be picked up and will remain queued until they timeout. Please contact Blacksmith Support for assistance. |
WalkthroughThis PR moves QR SPAYD handling from order metadata to payment-collection data, adds a manual QR payment provider that generates SPAYD and QR images, updates receipt quantity/subtotal logic and QR extraction, adds a region seeding script, and conditionally wires the provider via a feature flag. ChangesQR Payment Data Flow Migration
Sequence DiagramsequenceDiagram
participant Client
participant OrderReceiptService
participant QrManualPaymentProvider
participant QrPaymentModule
participant QRCode
Client->>OrderReceiptService: request/generate receipt for order
OrderReceiptService->>OrderReceiptService: getQrPaymentSpayd(order) scans payment_collections
OrderReceiptService->>QrManualPaymentProvider: (if initiating) initiatePayment(input)
QrManualPaymentProvider->>QrPaymentModule: getIban()
QrPaymentModule-->>QrManualPaymentProvider: iban
QrManualPaymentProvider->>QrManualPaymentProvider: buildPaymentQrSpayd(payment)
QrManualPaymentProvider->>QRCode: toDataURL(spayd)
QRCode-->>QrManualPaymentProvider: qr_data_url
QrManualPaymentProvider-->>OrderReceiptService: payment data with payment_qr_spayd and qr_data_url
OrderReceiptService-->>Client: attachment/pdf with QR commands
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR promotes QR/SPAYD payment from an order-metadata side-effect into a proper Medusa
Confidence Score: 4/5The core payment provider and receipt integration are sound, but the helpers.ts equality guard introduced in this PR can inflate line subtotals for certain promotion combinations — an issue already flagged in prior review rounds that remains open. The architecture is well-structured: SPAYD generation moved cleanly into the payment session, the subscriber is simplified, the feature flag correctly defaults to disabled, and the updatePayment reference-preservation bug from the previous review has been fixed. The open concern is the subtotal === unitPrice guard in getItemSubtotal which can misfire on valid line-level discounts (e.g., 2 items × 50% off), emitting inflated subtotals on every receipt and payment-reminder PDF. apps/medusa-be/src/modules/order-receipt/helpers.ts — the getItemSubtotal equality guard; apps/medusa-be/src/modules/payment-qr/tests/manual-provider.unit.spec.ts — test in the wrong directory Important Files Changed
Sequence DiagramsequenceDiagram
participant Customer
participant Medusa as Medusa Payment Module
participant QrProvider as QrManualPaymentProvider
participant QrModule as QrPaymentModuleService
participant Receipt as OrderReceiptModuleService
Customer->>Medusa: Initiate payment session
Medusa->>QrProvider: initiatePayment(amount, currency, context)
QrProvider->>QrModule: getIban()
QrModule-->>QrProvider: IBAN string
QrProvider->>QrProvider: buildPaymentQrSpayd(iban, amount, ref)
QrProvider->>QrProvider: QRCode.toDataURL(spayd)
QrProvider-->>Medusa: "{ id, status: pending, data: { payment_qr_spayd, payment_qr_data_url, qr_payment } }"
Customer->>Medusa: Authorize payment (checkout)
Medusa->>QrProvider: authorizePayment(data)
QrProvider-->>Medusa: "{ status: authorized, data }"
Note over Customer,Receipt: Order placed - order-placed subscriber fires
Medusa->>Receipt: generateOrderReceiptAttachment(order)
Receipt->>Receipt: getQrPaymentSpayd(order.payment_collections)
Note right of Receipt: Reads payment.data.payment_qr_spayd for matching provider_id
Receipt->>Receipt: buildPdfCommands(spayd)
Receipt-->>Medusa: PDF attachment with QR if applicable
Customer->>Medusa: Update cart (amount change)
Medusa->>QrProvider: updatePayment(data, newAmount)
QrProvider->>QrProvider: getPaymentReference(data.qr_payment.reference)
Note right of QrProvider: Preserves original reference from stored qr_payment object
QrProvider->>QrProvider: initiatePayment(newAmount, existingRef)
QrProvider-->>Medusa: Updated payment data with new QR
Reviews (8): Last reviewed commit: "fix(provider): simplify QR feature flag" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/medusa-be/src/subscribers/order-placed.ts (1)
24-33:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEarly return missing after order not found warning.
The code logs a warning when the order is not found but then proceeds to execute
sendOrderReceiptWorkflowanyway. This seems inconsistent—if the order wasn't found, the workflow will likely fail with aNOT_FOUNDerror or produce unexpected behaviour.Consider returning early after logging the warning:
🐛 Proposed fix to add early return
if (!order) { logger.warn(`Order ${data.id} was not found before receipt email.`) + return } await sendOrderReceiptWorkflow(container).run({🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/medusa-be/src/subscribers/order-placed.ts` around lines 24 - 33, The code logs when the order lookup returns no result but still proceeds to call sendOrderReceiptWorkflow; update the handler so that after logger.warn(`Order ${data.id} was not found before receipt email.`) you return early to avoid calling sendOrderReceiptWorkflow with a missing order. Locate the check that inspects order (the variable named order) and the subsequent await sendOrderReceiptWorkflow(container).run(...) call and add an early return immediately after the logger.warn to prevent executing the workflow when order is falsy.apps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts (1)
5-109: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winConsider adding tests for the new
buildPaymentSpaydmethod.The test suite properly removes tests for the deleted
buildMetadatamethod, but the newbuildPaymentSpaydmethod introduced inorder-payment-qr.tslacks corresponding unit tests. Given this method generates SPAYD strings used for payment QR codes (critical path for payment flows), adding test coverage would be beneficial.Would you like me to help generate unit tests for
buildPaymentSpaydcovering the key scenarios (valid payment data, missing IBAN, zero/invalid amount, currency fallback)?🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts` around lines 5 - 109, The test suite is missing unit tests for the new buildPaymentSpayd method; add tests exercising key scenarios (valid payment data -> exact SPAYD string or contains expected tokens, missing/invalid IBAN -> error or empty result depending on implementation, zero/negative/invalid amount -> formatted amount handling or rejection, and currency fallback to CZK when blank) by creating new it() cases in the existing order-payment-qr.unit.spec.ts that call OrderPaymentQr.buildPaymentSpayd with representative order/payment objects and assert the produced SPAYD strings contain ACC, AM (with correct formatting/rounding), CC (with fallback), and X-VS when applicable; reference the OrderPaymentQr class and buildPaymentSpayd method when adding these tests so they mirror the style and structure of the existing buildSpayd tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/medusa-be/medusa-config.ts`:
- Around line 386-389: Replace the hard-coded "qr_payment" dependency with the
exported QR module key constant: update the dependencies array to use the shared
module key constant (e.g., QR_PAYMENT_MODULE_KEY) instead of the string; import
that constant alongside QR_PAYMENT_PROVIDER/PAYKIT_PAYMENT_PROVIDERS and use it
in the dependencies list to avoid drift if the module key changes.
In `@apps/medusa-be/src/scripts/seed-qr-payment.ts`:
- Around line 104-107: The code throws a generic Error when the query row fails
the isRegionPaymentProviderLinks check; replace that throw with a MedusaError
using MedusaError.Types.INVALID_DATA and an explanatory message so the script
uses the backend's standardized error type—locate the conditional that calls
isRegionPaymentProviderLinks (the if block throwing Error) and change it to
throw new MedusaError(MedusaError.Types.INVALID_DATA, "...") with the same
descriptive text.
In `@apps/medusa-be/src/utils/order-payment-qr.ts`:
- Around line 162-164: Add unit tests for the exported buildPaymentQrSpayd
function to mirror the existing buildSpayd test coverage: create test cases that
call buildPaymentQrSpayd (and indirectly orderPaymentQr.buildPaymentSpayd) with
PaymentQrPaymentData variations to assert correct SPAYD output for valid input,
missing IBAN, null/invalid amount, absent currency (defaulting to expected
currency code), and correct variable symbol generation; use the same assertion
patterns as the buildSpayd tests and include edge cases (e.g., zero or negative
amounts, malformed IBAN) to ensure deterministic behavior.
---
Outside diff comments:
In `@apps/medusa-be/src/subscribers/order-placed.ts`:
- Around line 24-33: The code logs when the order lookup returns no result but
still proceeds to call sendOrderReceiptWorkflow; update the handler so that
after logger.warn(`Order ${data.id} was not found before receipt email.`) you
return early to avoid calling sendOrderReceiptWorkflow with a missing order.
Locate the check that inspects order (the variable named order) and the
subsequent await sendOrderReceiptWorkflow(container).run(...) call and add an
early return immediately after the logger.warn to prevent executing the workflow
when order is falsy.
In `@apps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts`:
- Around line 5-109: The test suite is missing unit tests for the new
buildPaymentSpayd method; add tests exercising key scenarios (valid payment data
-> exact SPAYD string or contains expected tokens, missing/invalid IBAN -> error
or empty result depending on implementation, zero/negative/invalid amount ->
formatted amount handling or rejection, and currency fallback to CZK when blank)
by creating new it() cases in the existing order-payment-qr.unit.spec.ts that
call OrderPaymentQr.buildPaymentSpayd with representative order/payment objects
and assert the produced SPAYD strings contain ACC, AM (with correct
formatting/rounding), CC (with fallback), and X-VS when applicable; reference
the OrderPaymentQr class and buildPaymentSpayd method when adding these tests so
they mirror the style and structure of the existing buildSpayd tests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d7b53d51-4d4b-4da2-8bc2-b50597d35409
📒 Files selected for processing (15)
apps/medusa-be/medusa-config.tsapps/medusa-be/package.jsonapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/subscribers/order-placed.tsapps/medusa-be/src/utils/order-payment-qr.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Greptile Review
- GitHub Check: main
- GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (18)
**/package.json
📄 CodeRabbit inference engine (CLAUDE.md)
Use pnpm CLI to add dependencies; never edit package.json directly
Files:
apps/medusa-be/package.json
apps/medusa-be/src/modules/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Place custom Medusa modules under apps/medusa-be/src/modules
Module directories use hyphens (
my-module/), but module keys in config use underscores (my_module)
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Import UI components using the pattern
import { ComponentName } from '@libs/ui/atoms/component-name'or'@libs/ui/molecules/component-name'
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/src/utils/order-payment-qr.tsapps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.tsapps/medusa-be/src/subscribers/order-placed.ts
apps/medusa-be/src/{api,modules,workflows,admin,subscribers,jobs}/**
📄 CodeRabbit inference engine (AGENTS.md)
In Medusa backend applications, organize custom code using the directory structure: api/, modules/, workflows/, admin/, subscribers/, jobs/
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/src/subscribers/order-placed.ts
apps/medusa-be/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx}: Runnpx tsc --noEmitfor typechecking before committing
Always use braces around conditional blocks, even for single statements; Biome will expand them
Declare one variable perconst/letstatement, not multiple on one line
Use nullish coalescing operator (??) instead of logical OR (||) for default values
Do not use non-null assertions (!); use type guards or validation instead
Annotate type asunknownwhen accessing dynamic object properties before applying type guards
Use comments only to explain 'why', never 'what'; self-document code with clear naming
Extract pure functions to separate files for testability without runtime dependencies
UseModules.*andContainerRegistrationKeys.*constants instead of hardcoding module/key strings
Do not use non-null assertions in TypeScript code; validate or use type guards instead
Validate data before type casting; never useas Typewithout prior validation
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/src/utils/order-payment-qr.tsapps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.tsapps/medusa-be/src/subscribers/order-placed.ts
apps/medusa-be/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Run
bunx biome check --write .to lint and auto-format code
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/src/utils/order-payment-qr.tsapps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.tsapps/medusa-be/src/subscribers/order-placed.ts
apps/medusa-be/src/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/**/*.ts: Useconstand explicit typing withdbService.sqlRaw<Type>()for SQL query results
Resolve logger usingcontainer.resolve<Logger>(ContainerRegistrationKeys.LOGGER)
Resolve Query usingcontainer.resolve<Query>(ContainerRegistrationKeys.QUERY)
UseModules.LOCKING(notModules.LOCK) to resolve locking services
UseModules.CACHING(notModules.CACHE) to resolve caching services
ThrowMedusaErrorwith appropriate type and message for error responses
UseMedusaError.Types.INVALID_DATAfor 400 validation errors
UseMedusaError.Types.NOT_FOUNDfor 404 errors
UseMedusaError.Types.UNAUTHORIZEDfor 401 authentication errors
UseMedusaError.Types.NOT_ALLOWEDfor 400 permission errors
UseMedusaError.Types.DUPLICATE_ERRORfor 422 duplicate entry errors
UseMedusaError.Types.CONFLICTfor 409 conflict errors
Use caching module'scomputeKey()to generate stable cache keys from filters and pagination
Use caching module'sget()with type assertion for cache retrieval
Use caching module'sset()with TTL and tags for cache storage and bulk invalidation
Use caching module'sclear()with tags to bulk-invalidate related cache entries
Always use Redis for caching in multi-container deployments instead of local variables
Batch operations usingCHUNK_SIZEconstant instead of unbounded loops
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/src/utils/order-payment-qr.tsapps/medusa-be/src/subscribers/order-placed.ts
apps/medusa-be/src/modules/*/index.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Export module key as a constant (e.g.,
MY_MODULE = "my_module") for reuse in imports
Files:
apps/medusa-be/src/modules/qr-payment/index.ts
apps/medusa-be/src/modules/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Modules use isolated containers; Query/Link unavailable during service initialization, defer to
onApplicationStart
Files:
apps/medusa-be/src/modules/qr-payment/index.tsapps/medusa-be/src/modules/qr-payment/constants.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/modules/qr-payment/services/manual.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.ts
apps/medusa-be/src/workflows/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Place business logic workflows under apps/medusa-be/src/workflows
Files:
apps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.ts
apps/medusa-be/src/workflows/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/workflows/**/*.ts: Use the second parameter{ container }object to access container in workflow steps
UsecreateStep()to define workflow steps with input validation and response wrapping
UsecreateWorkflow()to define multi-step business logic with rollback support
Returnnew StepResponse()from workflow steps to pass data to next steps
Returnnew WorkflowResponse()from workflows to pass final result to caller
Usetransform()in workflows for data manipulation only; cannot contain side effects
Usewhen().then()for conditional logic in workflows instead of if statements
Do not reassign or iterate workflow variables; variable definitions are static at definition time
UseuseQueryGraphStep()for Query operations within workflows
UseacquireLockStep(),releaseLockStep()for workflow-level locking instead of manual job locking
Files:
apps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Vitest for running tests in backend and UI library projects
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.tsapps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts
apps/medusa-be/tests/unit/**/*.unit.spec.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/tests/unit/**/*.unit.spec.ts: Focus unit tests on critical paths: validation, money calculations, and core business logic
Skip unit tests for: getters, static arrays, trivial transforms, constants, and pass-through methods
Do not test mocked methods; test real behavior instead
Do not testquery.graph()pass-through calls in unit tests
Do not test logging calls; they are implementation details
Use factory functions likecreateMockEntity(overrides)for test data generation
Useit.each()to test multiple error cases and boundary conditions
Usevi.useFakeTimers()for deterministic time-based testing; usevi.setSystemTime()for absolute time
Clear mocks withmockFn.mockReset()instead ofvi.clearAllMocks()formockResolvedValueOncechains
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts
apps/medusa-be/src/modules/*/service.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/modules/*/service.ts: ExtendMedusaServicein module services for automatic CRUD methods
Callsuper(container, options)in module service constructors; do not usesuper(...arguments)
Implement rate limiting and token management in service layer, not in HTTP client
Use workflows for cross-module orchestration; do not use Query/Link in module service constructors
Use Query and Link patterns to access other modules from services instead of direct imports
Files:
apps/medusa-be/src/modules/order-receipt/service.ts
apps/medusa-be/src/scripts/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/scripts/**/*.ts: Usemedusa exec ./path/to/script.ts [args]to run one-off scripts instead of creating HTTP endpoints
Use script patternnpx medusa exec ./src/scripts/startup.tsin startup hooks
Use destructive operations inmedusa execscripts, never in unprotected GET endpoints
Files:
apps/medusa-be/src/scripts/seed-qr-payment.ts
apps/medusa-be/**/medusa-config.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Use feature flag env vars in
medusa-config.tsevaluated at BUILD time, not runtime
Files:
apps/medusa-be/medusa-config.ts
apps/medusa-be/src/modules/*/__tests__/*.spec.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/modules/*/__tests__/*.spec.ts: UsemoduleIntegrationTestRunner()for module tests with real DB instead of mocking MedusaService methods
Mock loaders in tests usingvi.mock()to prevent actual initialization during testing
Wrap missing dependency resolution in try/catch in integration tests; Awilix throws even with nullish coalescing
Files:
apps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.ts
apps/medusa-be/src/subscribers/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Place event subscribers under apps/medusa-be/src/subscribers
Files:
apps/medusa-be/src/subscribers/order-placed.ts
🧠 Learnings (2)
📚 Learning: 2026-02-05T14:43:17.404Z
Learnt from: KaiUweCZE
Repo: NMIT-WR/new-engine PR: 324
File: apps/medusa-be/package.json:0-0
Timestamp: 2026-02-05T14:43:17.404Z
Learning: Validate and enforce React 19 compatibility across monorepo workspaces. Since Medusa UI supports React 19 via root package.json overrides and Medusa Cloud prerequisites show React 19 overrides for npm workspaces, ensure workspace root and all relevant package.json files align with React 19 (18+ requirement is satisfied). When reviewing, verify that overrides exist in the root package.json and that dependent packages in apps or packages directories declare React 19 (or compatible) in their peerDependencies or dependencies as appropriate for workspace usage.
Applied to files:
apps/medusa-be/package.json
📚 Learning: 2026-05-07T19:05:58.339Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 390
File: apps/medusa-be/package.json:78-81
Timestamp: 2026-05-07T19:05:58.339Z
Learning: When reviewing changes to `package.json`, do not automatically flag dependency additions/removals as "manually edited" or as "bypassing the pnpm lockfile" just because the `package.json` diff shows only that file changed. First verify whether `pnpm-lock.yaml` is missing the corresponding entries. Since `pnpm add` updates both `package.json` and `pnpm-lock.yaml` together, legitimate changes can appear in the `package.json` diff while still being properly tracked in the lockfile.
Applied to files:
apps/medusa-be/package.json
🔇 Additional comments (16)
apps/medusa-be/src/modules/order-receipt/helpers.ts (1)
37-40: LGTM!apps/medusa-be/src/utils/order-payment-qr.ts (2)
15-21: LGTM!
65-90: LGTM!apps/medusa-be/src/modules/order-receipt/service.ts (3)
1-2: LGTM!
42-42: LGTM!
279-303: LGTM!apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts (2)
1-38: LGTM!
40-107: LGTM!apps/medusa-be/src/workflows/send-order-payment-reminder.ts (1)
61-61: LGTM!apps/medusa-be/src/workflows/send-order-receipt.ts (1)
55-55: LGTM!apps/medusa-be/tests/unit/src/utils/order-payment-qr.unit.spec.ts (1)
1-3: LGTM!apps/medusa-be/src/modules/qr-payment/constants.ts (1)
1-5: LGTM!apps/medusa-be/src/modules/qr-payment/index.ts (1)
2-6: LGTM!apps/medusa-be/src/modules/qr-payment/services/manual.ts (1)
61-107: LGTM!Also applies to: 109-170, 172-217
apps/medusa-be/src/modules/qr-payment/__tests__/manual-provider.unit.spec.ts (1)
1-75: LGTM!apps/medusa-be/package.json (1)
41-41: LGTM!
Code Review SummaryStatus: No Issues Found | Recommendation: Merge OverviewAll previous CRITICAL and WARNING issues have been resolved in this incremental commit: Fixed Issues
Changes Summary
Files Reviewed (15 files)
Reviewed by laguna-m.1-20260312:free · 1,090,418 tokens |
|
@tomas-cm1 copy paste z discord konverzace: nitpick: v ramci konzistence, qr-payment prejmenovat na payment-qr at je to inline s fullfilment-XXX a payment-paykit |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts (1)
73-125: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winrefactor(test): table-drive the duplicate non-QR provider assertions with
it.each
Inapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts(lines 73-125), both tests verify the same behaviour for differentprovider_idvalues; merge them into a singleit.eachcase for"pp_paykit_comgate"and"pp_system_default"to reduce duplication.Proposed patch
- it("does not render payment QR commands for a non-QR payment", async () => { - const service = new OrderReceiptModuleService() - - const withoutQr = await service.generateOrderReceiptAttachment(baseOrder) - const withNonQrPayment = await service.generateOrderReceiptAttachment({ - ...baseOrder, - payment_collections: [ - { - payments: [ - { - data: { - payment_qr_spayd: - "SPD*1.0*ACC:CZ3301000000000002970297*AM:121.00*CC:CZK", - }, - provider_id: "pp_paykit_comgate", - }, - ], - }, - ], - }) - - expect(withNonQrPayment.content.length).toBe(withoutQr.content.length) - expect(withNonQrPayment.content.toString("utf8")).not.toContain( - "64.00 606.00" - ) - }) - - it("does not render payment QR commands for the system default payment", async () => { + it.each([ + ["pp_paykit_comgate"], + ["pp_system_default"], + ])( + "does not render payment QR commands for provider %s", + async (providerId) => { const service = new OrderReceiptModuleService() const withoutQr = await service.generateOrderReceiptAttachment(baseOrder) - const withSystemPayment = await service.generateOrderReceiptAttachment({ + const withNonQrPayment = await service.generateOrderReceiptAttachment({ ...baseOrder, payment_collections: [ { @@ data: { payment_qr_spayd: "SPD*1.0*ACC:CZ3301000000000002970297*AM:121.00*CC:CZK", }, - provider_id: "pp_system_default", + provider_id: providerId, }, ], }, ], }) - expect(withSystemPayment.content.length).toBe(withoutQr.content.length) - expect(withSystemPayment.content.toString("utf8")).not.toContain( + expect(withNonQrPayment.content.length).toBe(withoutQr.content.length) + expect(withNonQrPayment.content.toString("utf8")).not.toContain( "64.00 606.00" ) - }) + } + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts` around lines 73 - 125, Replace the two duplicated tests that call new OrderReceiptModuleService().generateOrderReceiptAttachment(...) for provider_id "pp_paykit_comgate" and "pp_system_default" with a single parameterized test using it.each (or test.each), iterating over the provider_id array; inside the test construct the order with payment_collections.payments[0].provider_id set to the iterated value and perform the same assertions against withoutQr (length equality and absence of "64.00 606.00"); keep references to OrderReceiptModuleService and generateOrderReceiptAttachment so the same setup/expectations are reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/medusa-be/src/modules/order-receipt/helpers.ts`:
- Around line 269-277: In getItemQuantity, currently the nullish coalescing
picks the first non-nullish raw value before calling toNumber; change it to
parse each source in order (item.quantity, item.detail?.quantity,
item.raw_quantity, item.detail?.raw_quantity) using toNumber and use the first
parsed value that is a finite number > 0, otherwise continue to the next source
and finally return 1 if none qualify; update the logic inside getItemQuantity to
iterate/check parsed values rather than the pre-parsed presence.
In `@docker-compose.yaml`:
- Line 66: The FEATURE_PAYMENT_QR_ENABLED environment default is currently set
to 0 which disables the QR payment provider in local setups; update the
docker-compose YAML so the variable FEATURE_PAYMENT_QR_ENABLED uses a default of
1 (i.e., change the parameter expansion from ${DC_FEATURE_PAYMENT_QR_ENABLED:-0}
to use :-1) so local/default runs enable the new QR payment provider by default;
find the line containing FEATURE_PAYMENT_QR_ENABLED in docker-compose.yaml and
make this single-value change.
---
Outside diff comments:
In `@apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts`:
- Around line 73-125: Replace the two duplicated tests that call new
OrderReceiptModuleService().generateOrderReceiptAttachment(...) for provider_id
"pp_paykit_comgate" and "pp_system_default" with a single parameterized test
using it.each (or test.each), iterating over the provider_id array; inside the
test construct the order with payment_collections.payments[0].provider_id set to
the iterated value and perform the same assertions against withoutQr (length
equality and absence of "64.00 606.00"); keep references to
OrderReceiptModuleService and generateOrderReceiptAttachment so the same
setup/expectations are reused.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a166182c-f53f-474e-887e-1f35784530a5
📒 Files selected for processing (11)
apps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/subscribers/order-placed.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsdocker-compose.yaml
💤 Files with no reviewable changes (1)
- apps/medusa-be/src/subscribers/order-placed.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Greptile Review
- GitHub Check: main
- GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (14)
apps/medusa-be/src/workflows/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Place business logic workflows under apps/medusa-be/src/workflows
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Import UI components using the pattern
import { ComponentName } from '@libs/ui/atoms/component-name'or'@libs/ui/molecules/component-name'
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/{api,modules,workflows,admin,subscribers,jobs}/**
📄 CodeRabbit inference engine (AGENTS.md)
In Medusa backend applications, organize custom code using the directory structure: api/, modules/, workflows/, admin/, subscribers/, jobs/
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx}: Runnpx tsc --noEmitfor typechecking before committing
Always use braces around conditional blocks, even for single statements; Biome will expand them
Declare one variable perconst/letstatement, not multiple on one line
Use nullish coalescing operator (??) instead of logical OR (||) for default values
Do not use non-null assertions (!); use type guards or validation instead
Annotate type asunknownwhen accessing dynamic object properties before applying type guards
Use comments only to explain 'why', never 'what'; self-document code with clear naming
Extract pure functions to separate files for testability without runtime dependencies
UseModules.*andContainerRegistrationKeys.*constants instead of hardcoding module/key strings
Do not use non-null assertions in TypeScript code; validate or use type guards instead
Validate data before type casting; never useas Typewithout prior validation
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Run
bunx biome check --write .to lint and auto-format code
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/**/*.ts: Useconstand explicit typing withdbService.sqlRaw<Type>()for SQL query results
Resolve logger usingcontainer.resolve<Logger>(ContainerRegistrationKeys.LOGGER)
Resolve Query usingcontainer.resolve<Query>(ContainerRegistrationKeys.QUERY)
UseModules.LOCKING(notModules.LOCK) to resolve locking services
UseModules.CACHING(notModules.CACHE) to resolve caching services
ThrowMedusaErrorwith appropriate type and message for error responses
UseMedusaError.Types.INVALID_DATAfor 400 validation errors
UseMedusaError.Types.NOT_FOUNDfor 404 errors
UseMedusaError.Types.UNAUTHORIZEDfor 401 authentication errors
UseMedusaError.Types.NOT_ALLOWEDfor 400 permission errors
UseMedusaError.Types.DUPLICATE_ERRORfor 422 duplicate entry errors
UseMedusaError.Types.CONFLICTfor 409 conflict errors
Use caching module'scomputeKey()to generate stable cache keys from filters and pagination
Use caching module'sget()with type assertion for cache retrieval
Use caching module'sset()with TTL and tags for cache storage and bulk invalidation
Use caching module'sclear()with tags to bulk-invalidate related cache entries
Always use Redis for caching in multi-container deployments instead of local variables
Batch operations usingCHUNK_SIZEconstant instead of unbounded loops
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/scripts/seed-qr-payment.tsapps/medusa-be/src/workflows/send-order-receipt.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/workflows/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/workflows/**/*.ts: Use the second parameter{ container }object to access container in workflow steps
UsecreateStep()to define workflow steps with input validation and response wrapping
UsecreateWorkflow()to define multi-step business logic with rollback support
Returnnew StepResponse()from workflow steps to pass data to next steps
Returnnew WorkflowResponse()from workflows to pass final result to caller
Usetransform()in workflows for data manipulation only; cannot contain side effects
Usewhen().then()for conditional logic in workflows instead of if statements
Do not reassign or iterate workflow variables; variable definitions are static at definition time
UseuseQueryGraphStep()for Query operations within workflows
UseacquireLockStep(),releaseLockStep()for workflow-level locking instead of manual job locking
Files:
apps/medusa-be/src/workflows/seed/paykit-payment-providers.tsapps/medusa-be/src/workflows/seed/constants.tsapps/medusa-be/src/workflows/send-order-payment-reminder.tsapps/medusa-be/src/workflows/send-order-receipt.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Vitest for running tests in backend and UI library projects
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts
apps/medusa-be/tests/unit/**/*.unit.spec.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/tests/unit/**/*.unit.spec.ts: Focus unit tests on critical paths: validation, money calculations, and core business logic
Skip unit tests for: getters, static arrays, trivial transforms, constants, and pass-through methods
Do not test mocked methods; test real behavior instead
Do not testquery.graph()pass-through calls in unit tests
Do not test logging calls; they are implementation details
Use factory functions likecreateMockEntity(overrides)for test data generation
Useit.each()to test multiple error cases and boundary conditions
Usevi.useFakeTimers()for deterministic time-based testing; usevi.setSystemTime()for absolute time
Clear mocks withmockFn.mockReset()instead ofvi.clearAllMocks()formockResolvedValueOncechains
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts
apps/medusa-be/src/modules/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Place custom Medusa modules under apps/medusa-be/src/modules
Module directories use hyphens (
my-module/), but module keys in config use underscores (my_module)
Files:
apps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/modules/*/service.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/modules/*/service.ts: ExtendMedusaServicein module services for automatic CRUD methods
Callsuper(container, options)in module service constructors; do not usesuper(...arguments)
Implement rate limiting and token management in service layer, not in HTTP client
Use workflows for cross-module orchestration; do not use Query/Link in module service constructors
Use Query and Link patterns to access other modules from services instead of direct imports
Files:
apps/medusa-be/src/modules/order-receipt/service.ts
apps/medusa-be/src/modules/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Modules use isolated containers; Query/Link unavailable during service initialization, defer to
onApplicationStart
Files:
apps/medusa-be/src/modules/order-receipt/service.tsapps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/scripts/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/scripts/**/*.ts: Usemedusa exec ./path/to/script.ts [args]to run one-off scripts instead of creating HTTP endpoints
Use script patternnpx medusa exec ./src/scripts/startup.tsin startup hooks
Use destructive operations inmedusa execscripts, never in unprotected GET endpoints
Files:
apps/medusa-be/src/scripts/seed-qr-payment.ts
apps/medusa-be/**/medusa-config.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Use feature flag env vars in
medusa-config.tsevaluated at BUILD time, not runtime
Files:
apps/medusa-be/medusa-config.ts
🧠 Learnings (1)
📚 Learning: 2026-02-25T14:46:02.729Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 335
File: apps/zane-operator/src/db.ts:205-207
Timestamp: 2026-02-25T14:46:02.729Z
Learning: Enforce PostgreSQL 18+ as the minimum version across docker-compose files. Since the repo uses postgres:18.1-alpine (evidence in docker-compose.yaml), ensure all docker-compose service images for PostgreSQL use 18.1-alpine or newer. When reviewing, look for postgres images with a tag below 18 (e.g., postgres:<older-version>) and update to 18.1-alpine or a newer compatible tag. This guideline applies to all docker-compose YAML files that define PostgreSQL services.
Applied to files:
docker-compose.yaml
🔇 Additional comments (9)
apps/medusa-be/src/workflows/seed/paykit-payment-providers.ts (1)
7-7: LGTM!Also applies to: 22-24
apps/medusa-be/src/workflows/seed/constants.ts (1)
1-1: LGTM!apps/medusa-be/src/workflows/send-order-payment-reminder.ts (1)
68-69: LGTM!Also applies to: 72-72
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts (1)
2-5: LGTM!Also applies to: 45-57
apps/medusa-be/src/modules/order-receipt/service.ts (1)
7-7: LGTM!Also applies to: 140-140
apps/medusa-be/src/scripts/seed-qr-payment.ts (1)
22-22: LGTM!Also applies to: 29-31, 139-154
apps/medusa-be/src/workflows/send-order-receipt.ts (1)
62-63: LGTM!Also applies to: 66-66
apps/medusa-be/medusa-config.ts (1)
9-12: LGTM!Also applies to: 31-42, 406-408
apps/medusa-be/src/modules/order-receipt/helpers.ts (1)
24-25: LGTM!Also applies to: 30-30, 281-286, 294-294
There was a problem hiding this comment.
♻️ Duplicate comments (1)
apps/medusa-be/src/modules/order-receipt/helpers.ts (1)
269-278:⚠️ Potential issue | 🟠 Major | ⚡ Quick winQuantity fallback evaluates presence before parsing, missing valid fallback candidates.
The current implementation uses nullish coalescing to select the first non-nullish field before calling
toNumber(). If that field contains"0","", or invalid data, subsequent valid fields are ignored and the function falls back to1, potentially misstating receipt quantities.For example, if
item.quantity = "0"butitem.detail.quantity = "5", the function will return1instead of5.♻️ Recommended fix: Parse each candidate in order
export function getItemQuantity(item: OrderReceiptLineItem) { - const quantity = toNumber( - item.quantity ?? - item.detail?.quantity ?? - item.raw_quantity ?? - item.detail?.raw_quantity - ) - - return quantity > 0 ? quantity : 1 + const candidates = [ + item.quantity, + item.detail?.quantity, + item.raw_quantity, + item.detail?.raw_quantity, + ] + + for (const candidate of candidates) { + const parsed = toNumber(candidate) + if (parsed > 0) { + return parsed + } + } + + return 1 }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/medusa-be/src/modules/order-receipt/helpers.ts` around lines 269 - 278, getItemQuantity currently picks the first non-nullish candidate with the nullish coalescing operator and only then calls toNumber, which causes values like "0", "" or invalid strings to block later valid fallbacks; change the logic to iterate through the candidates [item.quantity, item.detail?.quantity, item.raw_quantity, item.detail?.raw_quantity], call toNumber on each candidate in order, and return the first parsed numeric quantity > 0 (otherwise fall back to 1). Ensure you reference and update the getItemQuantity function and use toNumber for parsing each candidate rather than coalescing before parsing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@apps/medusa-be/src/modules/order-receipt/helpers.ts`:
- Around line 269-278: getItemQuantity currently picks the first non-nullish
candidate with the nullish coalescing operator and only then calls toNumber,
which causes values like "0", "" or invalid strings to block later valid
fallbacks; change the logic to iterate through the candidates [item.quantity,
item.detail?.quantity, item.raw_quantity, item.detail?.raw_quantity], call
toNumber on each candidate in order, and return the first parsed numeric
quantity > 0 (otherwise fall back to 1). Ensure you reference and update the
getItemQuantity function and use toNumber for parsing each candidate rather than
coalescing before parsing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d0147425-9fa8-4faf-8ee4-ab4c248a025b
📒 Files selected for processing (3)
apps/medusa-be/medusa-config.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Greptile Review
- GitHub Check: main
- GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Import UI components using the pattern
import { ComponentName } from '@libs/ui/atoms/component-name'or'@libs/ui/molecules/component-name'
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/medusa-config.ts
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Vitest for running tests in backend and UI library projects
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts
apps/medusa-be/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx}: Runnpx tsc --noEmitfor typechecking before committing
Always use braces around conditional blocks, even for single statements; Biome will expand them
Declare one variable perconst/letstatement, not multiple on one line
Use nullish coalescing operator (??) instead of logical OR (||) for default values
Do not use non-null assertions (!); use type guards or validation instead
Annotate type asunknownwhen accessing dynamic object properties before applying type guards
Use comments only to explain 'why', never 'what'; self-document code with clear naming
Extract pure functions to separate files for testability without runtime dependencies
UseModules.*andContainerRegistrationKeys.*constants instead of hardcoding module/key strings
Do not use non-null assertions in TypeScript code; validate or use type guards instead
Validate data before type casting; never useas Typewithout prior validation
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/medusa-config.ts
apps/medusa-be/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Run
bunx biome check --write .to lint and auto-format code
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.tsapps/medusa-be/src/modules/order-receipt/helpers.tsapps/medusa-be/medusa-config.ts
apps/medusa-be/tests/unit/**/*.unit.spec.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/tests/unit/**/*.unit.spec.ts: Focus unit tests on critical paths: validation, money calculations, and core business logic
Skip unit tests for: getters, static arrays, trivial transforms, constants, and pass-through methods
Do not test mocked methods; test real behavior instead
Do not testquery.graph()pass-through calls in unit tests
Do not test logging calls; they are implementation details
Use factory functions likecreateMockEntity(overrides)for test data generation
Useit.each()to test multiple error cases and boundary conditions
Usevi.useFakeTimers()for deterministic time-based testing; usevi.setSystemTime()for absolute time
Clear mocks withmockFn.mockReset()instead ofvi.clearAllMocks()formockResolvedValueOncechains
Files:
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts
apps/medusa-be/src/modules/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Place custom Medusa modules under apps/medusa-be/src/modules
Module directories use hyphens (
my-module/), but module keys in config use underscores (my_module)
Files:
apps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/{api,modules,workflows,admin,subscribers,jobs}/**
📄 CodeRabbit inference engine (AGENTS.md)
In Medusa backend applications, organize custom code using the directory structure: api/, modules/, workflows/, admin/, subscribers/, jobs/
Files:
apps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/**/*.ts: Useconstand explicit typing withdbService.sqlRaw<Type>()for SQL query results
Resolve logger usingcontainer.resolve<Logger>(ContainerRegistrationKeys.LOGGER)
Resolve Query usingcontainer.resolve<Query>(ContainerRegistrationKeys.QUERY)
UseModules.LOCKING(notModules.LOCK) to resolve locking services
UseModules.CACHING(notModules.CACHE) to resolve caching services
ThrowMedusaErrorwith appropriate type and message for error responses
UseMedusaError.Types.INVALID_DATAfor 400 validation errors
UseMedusaError.Types.NOT_FOUNDfor 404 errors
UseMedusaError.Types.UNAUTHORIZEDfor 401 authentication errors
UseMedusaError.Types.NOT_ALLOWEDfor 400 permission errors
UseMedusaError.Types.DUPLICATE_ERRORfor 422 duplicate entry errors
UseMedusaError.Types.CONFLICTfor 409 conflict errors
Use caching module'scomputeKey()to generate stable cache keys from filters and pagination
Use caching module'sget()with type assertion for cache retrieval
Use caching module'sset()with TTL and tags for cache storage and bulk invalidation
Use caching module'sclear()with tags to bulk-invalidate related cache entries
Always use Redis for caching in multi-container deployments instead of local variables
Batch operations usingCHUNK_SIZEconstant instead of unbounded loops
Files:
apps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/src/modules/**/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Modules use isolated containers; Query/Link unavailable during service initialization, defer to
onApplicationStart
Files:
apps/medusa-be/src/modules/order-receipt/helpers.ts
apps/medusa-be/**/medusa-config.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
Use feature flag env vars in
medusa-config.tsevaluated at BUILD time, not runtime
Files:
apps/medusa-be/medusa-config.ts
🔇 Additional comments (3)
apps/medusa-be/tests/unit/src/modules/order-receipt/service.unit.spec.ts (1)
59-67: LGTM!apps/medusa-be/src/modules/order-receipt/helpers.ts (1)
280-300: LGTM!apps/medusa-be/medusa-config.ts (1)
40-40: LGTM!
…d QR SPAYD from product metadata
Summary by CodeRabbit
New Features
Chores