This change makes DiscountCalculator value affected pouches per product variant
(size-exact) instead of collapsing them by flavour. Before, two sizes of the same
flavour in one box were merged and priced at a single per-flavour value; now each pouch
is valued from its own box content-product unit price plus the flavour's per-pouch recipe
surcharge.
You can verify this against real data from a Rails console. The script is read-only —
DiscountCalculator#calculate, PouchValueCalculator, and SurchargeType::Recipe are all
pure calculations with no writes, so it is safe to run in production.
If this branch isn't deployed to the console you're on, the loaded
DiscountCalculatoris still master's (old) code. The script computes the new size-exact value inline (a faithful stand-in for the committed code) and compares it to the old collapsed value, then also prints what the deployed class returns so you can tell which is live.
Set BOX_ID to a real box id (see step 2 for how to find one that exercises the fix):
# ============================================================================
# READ-ONLY pouch valuation check for one box. No writes.
# ============================================================================
BOX_ID = 123 # <- a real box id
box = Box.find(BOX_ID)
order = box.order
abort "box #{box.id} has no content" if box.content.nil?
pouch_slug = PouchSize::ADDITIONAL_POUCHES_GROUP_SLUG
pouch_cps = box.content.content_products
.includes(product_variant: [:flavours, { product_collection: :product_group }])
.select { |cp| cp.product_variant&.product_collection&.product_group&.slug == pouch_slug }
if pouch_cps.empty?
puts "Box #{box.id} has no pouch content products."
else
pvc = Helpers::PouchValueCalculator.new(box_id: box.id)
surcharge_for = lambda do |flavour|
next 0 unless flavour
SurchargeType::Recipe.calculate_cohorted_surcharge_amount_for(
shipping_country: box.shipping_country, flavour: flavour.slug,
plan: box.plan, date: box.shipping_date,
cohort_resource: box, calculation_type: 'per_pouch'
).to_i
end
# NEW: each pouch valued from its own content-product unit price + surcharge
puts "Box #{box.id} pouches:"
new_total = 0
pouch_cps.sort_by { |cp| [cp.product_variant.flavour&.slug.to_s, cp.product_variant.slug.to_s] }.each do |cp|
pv, qty = cp.product_variant, cp.quantity.to_i
sur = surcharge_for.call(pv.flavour)
line = (cp.unit_price + sur) * qty
new_total += line
puts format(" %-24s flavour=%-10s unit_price=%4d + surcharge=%3d x %d = %d",
pv.slug, pv.flavour&.slug || '-', cp.unit_price, sur, qty, line)
end
# OLD: collapse by flavour, price via the (single-size) manifest
by_flavour = Hash.new(0)
pouch_cps.each { |cp| f = cp.product_variant.flavour; by_flavour[f.slug] += cp.quantity.to_i if f }
old_total = pvc.calculate(pouches: by_flavour)
# What THIS console's deployed DiscountCalculator actually returns
vwq = pouch_cps.to_h { |cp| [cp.product_variant, cp.quantity] }
deployed_total = Admin::OrderIssuesV2::Resolution::DiscountCalculator
.new(order:, box:).calculate(variants_with_quantities: vwq)
puts
puts "NEW (size-exact per variant): #{new_total}"
puts "OLD (collapsed by flavour): #{old_total}"
puts "Deployed calculator returns: #{deployed_total} (== NEW if branch is live, == OLD if master)"
puts(new_total == old_total ?
"=> No difference for this box." :
"=> DIFFERENCE of #{new_total - old_total} — this box exercises the fix.")
endMost boxes have a single pouch size per flavour, so NEW == OLD for them. To see the fix
change a value you need a box containing the same flavour at two different pouch
variants. This scans content_products, so keep it tightly scoped:
# Find a recent collision box (same flavour at 2+ pouch variants)
ContentProduct
.joins("JOIN contents ON contents.id = content_products.content_id AND contents.contentable_type = 'Box'")
.joins("JOIN boxes ON boxes.id = contents.contentable_id")
.joins(product_variant: { product_collection: :product_group })
.joins("JOIN flavours_product_variants fpv ON fpv.product_variant_id = content_products.product_variant_id")
.where(product_groups: { slug: PouchSize::ADDITIONAL_POUCHES_GROUP_SLUG })
.where("boxes.shipping_date >= ?", 90.days.ago.to_date)
.group("boxes.id", "fpv.flavour_id")
.having("COUNT(DISTINCT content_products.product_variant_id) > 1")
.limit(1)
.count.keys.first&.first # => a box id, or nilThese boxes are rare (single figures over a 90-day window), so nil is a plausible result
on a small window — widen the date range if so.
NEW == OLD— this box has one size per flavour. The valuation is unchanged, which is the expected result for the vast majority of boxes and confirms the fix is a no-op in the common case.NEW != OLD— a collision box: the pouch rows will show the sameflavour=with two differentunit_pricevalues (the two sizes).NEWprices each size from its own unit price;OLDcollapsed them onto one. The printed difference is the correction the fix makes.Deployed calculator returnstells you whether the new code is live in that console (matchesNEW) or whether it's still master (matchesOLD).