Repository navigation
Conversation
OrderItemPriceCalculationStrategy.calculateUnitPrice() gets an optional last argument, options?: { buyer?: Buyer }. A strategy layer can pass its own Buyer to the inner chain. DefaultOrderItemPriceCalculationStrategy passes options.buyer to ProductVariantService.calculateBuyerPriceForOrder(). Without a buyer, the price is for the Customer of the Order, as before.
DefaultOrderItemPriceCalculationStrategy is now exported from @vendure/core.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
|
Dashboard Preview: https://admin-dashboard-c6j6j34xi-vendure.vercel.app |
The IdInterceptor does not run for field resolvers. Thus the buyerPrice field gave the encoded ID values of the customFields argument to the ProductVariantBuyerPriceStrategy, and addItemToOrder gave the decoded values. The resolver now decodes a copy of its ID arguments. A copy is necessary because the field of each variant can share the same variable object.
|
|
Vendure Framework — View preview Changed pages: |



Description
OrderItemPriceCalculationStrategy.calculateUnitPrice()had no buyer argument. The default strategy always priced a line for the customer of the order. A strategy layer that had to price a line for a different buyer, for example an anonymous buyer for a cart that several customers use, had to skip the inner chain and callProductVariantService.calculateBuyerPriceForOrder()itself. Then a custom base strategy and the inner layers did not run for that line.Changes:
calculateUnitPrice(ctx, productVariant, orderLineCustomFields, order, quantity, options?)gets an optional last argument,options?: { buyer?: Buyer }. Vendure does not pass it. A layer can pass it toinner.DefaultOrderItemPriceCalculationStrategypassesoptions?.buyertocalculateBuyerPriceForOrder(). Without a buyer, the price is for the customer of the order, as before.DefaultOrderItemPriceCalculationStrategyis now exported from@vendure/core. It follows the same import pattern asDefaultGuestCheckoutStrategy, which also imports a service, anddefault-config.tsalready imports it. So the export adds no new import cycle.StrategyLayer.passThrough<S>()takes its method types fromS, so a layer that uses...args: Parameters<...>forwards the new argument without casts.options, emptyoptions, and a layer that passes its buyer to the default strategy.BuyerIdentityService.forCustomer()and passes it toinner. The inner layer receives that buyer, and the cart line gets that buyer's price.DefaultOrderItemPriceCalculationStrategyfrom@vendure/coreand checks that it is the base of the configured chain.inner, and the Vendure 4 upgrade notes describe the new argument and the export.Also fixed in a separate commit: the Shop API field
ProductVariant.buyerPrice(quantity, customFields)did not decode the ID values incustomFields. Core enables only guards for field resolvers, so theIdInterceptordoes not run forbuyerPrice. With an encodingEntityIdStrategy, theProductVariantBuyerPriceStrategygot the encoded ID (for example of a relation custom field onOrderLine), andaddItemToOrdergave it the decoded ID. On Postgres the query then failed. The resolver now decodes a copy of its ID arguments with the same logic as theIdInterceptor. It decodes a copy becauseGraphqlValueTransformer.transformValues()changes the object in place, and thebuyerPricefield of each variant in a query can share the same$customFieldsvariable object. Without the copy, the second field would decode the ID again. A new e2e test with anOrderLinerelation custom field checks that the strategy gets the decoded ID. The test fails without the fix.Breaking changes
No. The new argument is optional, and existing strategies and layers work without changes. A layer that calls
innerwith its own argument list must passoptionson, so that the inner strategies get the buyer of an outer layer. The docs tell you this.Checklist
📌 Always:
👍 Most of the time: