github medusajs/medusa v2.8.5
v2.8.5: Tax-inclusive Promotions, Improved Product Imports, and Faster Application Startup

latest releases: v2.10.1, @medusajs/workflows-sdk@2.10.1, @medusajs/workflow-engine-redis@2.10.1...
2 months ago

Highlights

Improved Product Imports

This release overhauls the bulk import process to make it more performant and include strict validations to catch formatting issues or typos during the pre-processing phase.

Import phases

A CSV file with products to import goes through the following two phases.

  • Pre-processing: In the pre-processing phase, we validate the contents of the entire file, check for typos, unknown columns, invalid data types, or missing values, and report errors as soon as you upload the file.
  • Importing: Products are imported in the background (as it could be time-consuming with large product catalogs). Since the validations have already been performed during the pre-processing phase, the chances of failure during the import phase are rare. However, certain database constraints around duplicate data might result in a failure.

Changes to import template

Earlier, the import template (downloaded from the admin dashboard) was out of sync with our documentation and supported many columns that were part of Medusa V1.

However, now the import template strictly allows the columns mentioned in the documentation, and an error will be raised if an unknown column is specified in the CSV file.

Performance improvements

The following changes have been made to the internals to improve the import performance and memory consumption.

  • Use S3 direct uploads instead of self-importing and storing huge CSV files on a Medusa server. For this, you must configure the S3 file provider in production.
  • Read the CSV contents as a stream of chunks and process/validate 1000 rows at a time. As a result, we never read or process the entire CSV file in memory. From our tests, this led to a memory drop from 4GB to 500MB when processing a file with 62000 rows.

Tax-inclusive Promotions

This release introduces an option to specify if fixed promotions take effect before or after taxes. Up until now, fixed promotions would always be applied before taxes, which could lead to unexpected total calculations in scenarios where pricing was otherwise tax-inclusive.

For example, consider a fixed promotion with a value of $10 applied to a tax-inclusive cart of $100 in a tax region with a 25% tax rate.

Before promotion is applied:

  • Cart total (tax-inclusive) -> $100 ($80 ex. 25% VAT)

After promotion is applied:

  • Cart total (tax-inclusive) -> $87.5 ($70 ex. 25% VAT)

As you can see, the cart is reduced by $12.5 even though the promotion value was $10. The calculation we used to perform to find the promotion adjustment was:

const adjustmentTotal = (cartWithoutTax - promotion.value) * (1 + tax_rate)

In our example, this would be:

const adjustmentTotal = (80 - 10) * (1.25) = 87.5

In this release, we updated this calculation to ensure the correct adjustment total. It looks as follows:

const adjustmentTotal = (cartWithoutTax - (promotion.value / 1 + tax_rate)) * (1 + tax_rate)

In our example, this would be:

const adjustmentTotal = (80 - 8) * (1.25) = 90

The tax-inclusivity option on a promotion is part of the promotion creation flow in the admin dashboard.

Improved application startup time

This release reduces application startup time by around ~75%. For example, on Medusa Cloud, the startup time for a relatively simple Medusa application has gone from 20 seconds to around 4 seconds. This improvement comes from parallelizing the bootstrapping of modules. Modules are strictly independent from each other, so this should have no side effects.

Querying deleted records

This release fixes issues with querying for deleted database records.

Up until now, filtering data by providing any value to the deleted_at filter would be treated as if you wanted to fetch deleted records.

For example:

const { data } = await query.graph({
  entity: "product",
  filters: { deleted_at: { $eq: null } }
}) 

In this query request, we are asking for all non-deleted records; however, we mistakenly assumed that any deleted_at filter would always be filtering for deleted records, so in this case, the result set would contain deleted records.

In this release, we remove the autodetection mechanism in favor of an explicit flag withDeleted.

To query deleted records, you now need to pass the flag to the request:

const { data } = await query.graph({
  entity: "product",
  filters: { deleted_at: { "<some timestamp>" } }
  withDeleted: true
}) 

Features

  • feat: wire up direct uploads with local file provider by @thetutlage in #12643
  • feat(promotion, dashboard, core-flows, cart, types, utils, medusa): tax inclusive promotions by @fPolic in #12412
  • feat(dashboard,types): add credit lines + loyalty changes by @riqwan in #11885
  • feat: Improve startup time by parallelizing module and link loading by @sradevski in #12731
  • feat: Normalize payment method data and options when passed to Stripe by @sradevski in #12757
  • fix(dashboard, types): loyalty UI changes by @fPolic in #12764
  • feat(): Add support for jwt asymetric keys by @adrien2p in #12813
  • feat: add cookie options by @riqwan in #12720

Bugs

  • fix(workflow-sdk): Async/nested runAsStep propagation by @adrien2p in #12675
  • fix: update product import template by @thetutlage in #12697
  • fix(create-medusa-app): remove "Created admin user" message by @shahednasser in #12707
  • fix(promotion, types): non discountable items check by @fPolic in #12644
  • fix: remote query types by @thetutlage in #12712
  • fix(core-flows): cart complete order address creation by @fPolic in #12493
  • fix(utils): medusa internal service returned data should match typings by @adrien2p in #12715
  • fix(utils): Typecasting non-text fields in FTS by @olivermrbl in #12729
  • fix: Disable ensure database checks when establishing DB connection by @sradevski in #12734
  • fix(create-medusa-app): ensure the same package manager is used consistently by @shahednasser in #12714
  • fix(payment): add account holder methods to the manual provider by @fPolic in #12751
  • fix(core, medusa-test-utils): Fix medusa test runner plugin modules loading by @adrien2p in #12753
  • fix: Add missing partially funded event handler for Stripe by @sradevski in #12763
  • fix: initiate request container before other express middleware by @thetutlage in #12761
  • fix(dashboard): fix subtitle for tax inclusive fields in promotions by @shahednasser in #12776
  • fix(workflow-engine-redis): Ensure PK is set without errors by @olivermrbl in #12775
  • fix: add operators to RemoteQueryFilters by @peterlgh7 in #12735
  • fix: Return and set the correct status when a session is created with… by @sradevski in #12769
  • fix: Allow setting the status of a payment session when updating by @sradevski in #12809
  • fix(workflow-engine-*): Cleanup expired executions and reduce redis storage usage by @adrien2p in #12795
  • fix(medusa): Query Config update Order By filter by @juanzgc in #12781
  • fix(payment): round currency precision by @carlos-r-l-rodrigues in #12803
  • fix(dashboard): fix currency input locale formatting by @fPolic in #12812
  • fix(utils): build query withDeleted remove auto detection by @adrien2p in #12788
  • fix: Add missing migration for payment statuses by @sradevski in #12821

Documentation

Chores

Other Changes

  • fix: keep enum values in types generation by @peterlgh7 in #12684
  • feat: Search by billing_address and shipping_address on Order model by @juanzgc in #12814
  • Enable filtering admin products by variant EAN, UPC, and barcode by @anteprimorac in #12815

New Contributors

Full Changelog: v2.8.4...v2.8.5

Don't miss a new medusa release

NewReleases is sending notifications on new releases.