Conversation
…paign is active With a kit campaign applied (e.g. buy 4 pay 3) the response always carries a `discount_rule`, and the storefront DiscountApplier handles any discount plus a typed coupon as an applied coupon unless `invalid_coupon_message` is set. Unknown, expired and below-minimum coupons showed "Cupom de desconto aplicado com sucesso." and were kept in the cart and the order. Now `invalid_coupon_message` is returned when the typed coupon matches no valid discount rule nor freebie coupon, and tells the missing amount when the coupon minimum is not reached. Campaign discounts are still applied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vitorrgg
left a comment
There was a problem hiding this comment.
Revisão adversarial
Veredito: aprovar com ressalvas. A correção principal funciona e não muda o cálculo do pedido (functions-checkout só lê discount_rule), mas deixa aberta uma variante do mesmo bug e o teste novo não roda no CI.
Validado: os 6 testes da PR passam. Rodei mais 15 cenários (domínio diferente, outro cliente, case mismatch, UTM + cupom errado, promoção aberta, sem lang/currency_id, amount ausente, cupom via chave direta do hidden_data, amount_field: freight) e todos se comportam como descrito, exceto os abaixo.
Required
- Cupom de brinde existente mas não aplicável ainda passa como "aplicado" (comentário inline em
apply-discount.mjs). A checagemisFreebieCouponignoradomain,check_product_idsemin_subtotal. Kit ativo + regrafreebie_coupon: BRINDEcommin_subtotal: 1000+ carrinho de R$ 280 → resposta comdiscount_ruledo kit, semfreebie_product_idse sem mensagem → oDiscountAppliermostra "Cupom aplicado com sucesso" e grava o cupom. É o mesmo relato da Tia Sônia. Reproduzi também comdomaindivergente echeck_product_idsfora do carrinho. - Teste não roda no CI. O pacote não tem script
test, entãopnpm test:appse otest-apps.ymlpulaminvalid-coupon.test.mjs. Falta"test": "node --test tests/"nopackage.json, como emcustom-shippingeloyalty-points.
Optional
- Mudança visível fora do caso "campanha ativa" (inline). Sem kit, o checkout já mostrava "Adicione mais R$ X ao carrinho para ganhar o desconto." em variante
infoa partir deavailable_extra_discount.min_amount. Agora a mensagem do app sobrescreve essa, com texto diferente e variantewarning. Vale alinhar o texto com o i18n existente. amount_field: 'freight': regra commin_amount: 50e frete R$ 20 devolve "Adicione mais R$ 30,00 ao carrinho", mas o que falta é frete. Caso raro; omitir a mensagem nesse campo ou cobrir com teste.- Fora deste repo: em
storefront-components/DiscountApplier.js(linhas ~196-204), kit ativo + regra de brinde aberta + cupom inválido ainda emiteupdate:coupon-codeporque veiofreebie_product_ids. O aviso aparece, mas o cupom vai pro carrinho e sai no pedido emextra_discount.discount_coupon. Follow-up.
Nit
discounts-v2continua com o bug nas lojas v2, como a descrição admite.
Sem achado
Regressão dos caminhos antigos (cupom válido, sem cupom, kit puro, brinde válido, mensagens de não cumulativo / limite de uso / produto excluído), auth, concorrência e integrações externas: função pura, nenhuma chamada nova à API.
Não verificado
Navegador e checkout real com discount_rule + invalid_coupon_message na mesma resposta (li o DiscountApplier, não executei); combinação com outro app de desconto instalado; Node 20 (rodei com 18).
| return rule.freebie_coupon?.toUpperCase() === couponCode | ||
| && validateDateRange(rule) | ||
| && validateCustomerId(rule, params); | ||
| }); |
There was a problem hiding this comment.
Required. Essa checagem só cobre data e cliente. Uma regra de brinde com freebie_coupon igual ao digitado mas com domain diferente, check_product_ids fora do carrinho ou min_subtotal acima do carrinho não gera freebie_product_ids e também não gera mensagem. Com kit ativo o checkout mostra "Cupom aplicado com sucesso" e grava o cupom, o mesmo sintoma que a PR corrige.
Sugestão: só considerar o cupom encontrado se a regra passou pelo mesmo filtro de getFreebiesPreview e de fato entrou em response.freebie_product_ids. Testei esta variante e ela fecha os três casos mantendo os 6 testes da PR verdes:
return rule.freebie_coupon?.toUpperCase() === couponCode
&& validateDateRange(rule)
&& validateCustomerId(rule, params)
&& mapCampaignProducts({ product_ids: rule.check_product_ids }, params).valid
&& Array.isArray(rule.product_ids) && rule.product_ids.length
&& matchFreebieRule(rule, params)
&& Array.isArray(response.freebie_product_ids)
&& rule.product_ids.every((id) => response.freebie_product_ids.includes(id));Para min_subtotal vale devolver "Adicione mais R$ X" como no caso de min_amount.
Testes de regressão: os três cenários acima esperando invalid_coupon_message definido.
| ); | ||
| response.invalid_coupon_message = params.lang === 'pt_br' | ||
| ? `Adicione mais ${missingAmount} ao carrinho para usar este cupom.` | ||
| : `Add ${missingAmount} more to the cart to use this coupon.`; |
There was a problem hiding this comment.
Optional. Dois pontos aqui:
- Isso muda comportamento também sem campanha ativa. O
DiscountApplierjá tratavaavailable_extra_discount.min_amountsemdiscount_rulecom "Adicione mais $1 ao carrinho para ganhar o desconto." em varianteinfo;invalid_coupon_messagesobrescreve isso e virawarningcom outro texto. O valor daqui é até mais correto (desconta brindes), mas vale usar o mesmo texto do i18n. - Com
amount_field: 'freight'a mensagem diz "ao carrinho" quando o que falta é frete (regramin_amount: 50, frete R$ 20 → "Adicione mais R$ 30,00 ao carrinho"). Sugiro pular a mensagem nesse campo, com teste cobrindo.
Problema
Com uma campanha de kit ativa (leve 4 pague 3), o
apply_discountsempre devolvediscount_rule. Quando o cliente digita um cupom que não bate com nenhuma regra, o app não sinaliza nada, e oDiscountApplierdo checkout trata "desconto + cupom digitado + seminvalid_coupon_message" como cupom aceito: mostra "Cupom de desconto aplicado com sucesso.", exibe o check verde e grava o cupom no carrinho, que segue no pedido. Relato da Tia Sônia: cliente finalizou a compra achando que o cupom de aniversário tinha sido aplicado.Acontece com cupom inexistente, vencido ou abaixo do valor mínimo. Sem campanha ativa o checkout já mostrava "O cupom de desconto inserido é inválido.", porque aí não vem
discount_rule.Mudança
Em
packages/apps/discounts/lib-mjs/apply-discount.mjs:freebie_couponde uma regra de brinde válida →invalid_coupon_message"O cupom de desconto inserido é inválido." (mesmo texto do i18n do checkout).min_amount→ "Adicione mais R$ X ao carrinho para usar este cupom." (formatMoneycomcurrency_idelangdos params).functions-checkoutignorainvalid_coupon_message, então o cálculo do pedido não muda.O
ecomplus/discounts-v2(lojas v2) tem o mesmo comportamento e não foi alterado aqui.Teste
packages/apps/discounts/tests/invalid-coupon.test.mjs(node:test, 6 casos): cupom inexistente, vencido e abaixo do mínimo falham sem a correção. Cupom válido, cupom de brinde e sem cupom continuam iguais. Roda comnode --test tests/na pasta do pacote; ainda fora dotest:appsporque o pacote não tem scripttest.@cloudcommerce/modules:currency_idrecebe o defaultBRLe a resposta ficavalidated: true.parseDiscountOptionsdoDiscountApplierem 12 cenários: os 3 casos acima mostravam "Cupom de desconto aplicado com sucesso." e agora mostram o aviso; os demais não mudam.🤖 Generated with Claude Code