-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: ensures no duplicate tax lines when completing cart #1262
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with comments 👍
@@ -27,7 +27,7 @@ describe("Order Taxes", () => { | |||
const cwd = path.resolve(path.join(__dirname, "..", "..")) | |||
try { | |||
dbConnection = await initDb({ cwd }) | |||
medusaProcess = await setupServer({ cwd }) | |||
medusaProcess = await setupServer({ cwd, verbose: true }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove flag
medusaProcess = await setupServer({ cwd, verbose: true }) | |
medusaProcess = await setupServer({ cwd }) |
if (!cart.payment_session) { | ||
throw new MedusaError( | ||
MedusaError.Types.NOT_ALLOWED, | ||
"You cannot complete a cart without a payment session." | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: While we are at it, should we also enforce shipping methods for cart completion to go through?
@@ -197,6 +197,111 @@ describe("Order Taxes", () => { | |||
expect(response.data.order.total).toEqual(2300) | |||
}) | |||
|
|||
test.only("completing cart with failure doesn't duplicate", async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very, very nit:
test.only("completing cart with failure doesn't duplicate", async () => { | |
test.only("completing cart with failure doesn't duplicate tax lines", async () => { |
Found out that this approach of deleting everything first and then continuing is not appropriate - the issue is that if you are completing a Swap cart for example we need to move the original line items to "return lines" and these should include the original tax lines. Will try to come up with a different approach |
Alternative approach is being investigated
conflict_target: ["item_id", "code"], | ||
overwrite: ["rate", "name", "updated_at"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!
async upsertTaxLines_( | ||
taxLines: (ShippingMethodTaxLine | LineItemTaxLine)[] | ||
): Promise<UpdateResult[]> { | ||
const itemTaxLineRepo = this.manager_.getCustomRepository(this.taxLineRepo_) | ||
const shippingTaxLineRepo = this.manager_.getCustomRepository( | ||
this.smTaxLineRepo_ | ||
) | ||
|
||
return await Promise.all( | ||
taxLines.map(async (tl) => { | ||
if ("item_id" in tl) { | ||
return await itemTaxLineRepo.update( | ||
{ item_id: tl.item_id, code: tl.code }, | ||
{ | ||
rate: tl.rate, | ||
name: tl.name, | ||
} | ||
) | ||
} | ||
|
||
return await shippingTaxLineRepo.update( | ||
{ shipping_method_id: tl.shipping_method_id, code: tl.code }, | ||
{ | ||
rate: tl.rate, | ||
name: tl.name, | ||
} | ||
) | ||
}) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete since no longer used right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used @srindom? I can't seem to find any references to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
* fix: ensures that no duplicate tax lines are created when completing cart
While I was developing a custom tax provider, I ran into a pretty frustrating issue related to multiple tax lines and incorrect / unexpected tax total calculations. I outlined the issue in discord, before finding the solution: https://discord.com/channels/876835651130097704/1169705457804398662 After some digging, I found this issue from a while back: #1262, where it states there is now a unique constraint on `item_id, code` and `shipping_method_id, code`. But, in the current documentation for creating a custom tax provider, it states these fields as part of the tax line items returned are optional. If these `code` values are left out, it can cause tax lines to be applied multiple times (as seen here as well: #1901) I'm not entirely sure how this should be phrased in the documentation, so I just wanted to get this up and on your radar for resolution. If it ends up being that `code` truly should not be optional, I suspect some type definitions would need to change as well?
What
A small fix that ensures that when a cart is completed any existing tax lines will be deleted. Currently, if a complete cart request is performed with a failure you can risk creating an order with two tax lines.
This fix ensures that any existing tax lines on the cart line items are cleared before the new tax lines are created.Edit: New approach introduces a unique constraint on
item_id, code
andshipping_method_id, code
. Two new repository methods are introduced in ShippingMethodTaxLineRepository and LineItemTaxLineRepository calledupsertLines
which uses an insert/on conflict to ensure that duplicate lines are not created.