feat(backend): remove auto loyalty redemption from booking progress
Remove auto-apply of pending loyalty redemption during ProgressBookingHandler. Now only checks if loyalty was applied on this booking (via booking_discounts) to skip stamp award. Redemption is purely manual via ApplyLoyaltyRedemption. Use LoyaltyStampCost constant instead of hardcoded 10. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -2553,51 +2553,13 @@ func ProgressBookingHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Printf("Failed to calculate booking total for %s: %v", bookingID, err)
|
log.Printf("Failed to calculate booking total for %s: %v", bookingID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply existing pending loyalty redemption (earned from previous 10 bookings)
|
// Don't award a stamp if this booking already used a loyalty redemption
|
||||||
// Skip if already applied at payment time (or by admin)
|
// (take or receive, never both).
|
||||||
var loyaltyAlreadyApplied bool
|
var loyaltyAppliedOnThisBooking bool
|
||||||
tx.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND discount_source = 'loyalty')`, bookingID).Scan(&loyaltyAlreadyApplied)
|
tx.QueryRow(r.Context(), `SELECT EXISTS(SELECT 1 FROM booking_discounts WHERE booking_id = $1 AND discount_source = 'loyalty')`, bookingID).Scan(&loyaltyAppliedOnThisBooking)
|
||||||
if bookingTotal > 0 && !loyaltyAlreadyApplied {
|
|
||||||
var redemptionID string
|
|
||||||
if err := tx.QueryRow(r.Context(), `
|
|
||||||
SELECT id FROM loyalty_redemptions
|
|
||||||
WHERE user_id = $1 AND status = 'pending' AND expires_at > NOW()
|
|
||||||
ORDER BY redeemed_at ASC LIMIT 1
|
|
||||||
`, booking.User.ID).Scan(&redemptionID); err == nil && redemptionID != "" {
|
|
||||||
discountAmount := roundTo2(bookingTotal * 0.10)
|
|
||||||
|
|
||||||
if _, err := tx.Exec(r.Context(), `
|
|
||||||
INSERT INTO booking_discounts (booking_id, user_id, discount_source, source_id, campaign_type, milestone_type, discount_percent, original_total, discount_amount)
|
|
||||||
VALUES ($1, $2, 'loyalty', $3, NULL, NULL, 10.00, $4, $5)
|
|
||||||
`, bookingID, booking.User.ID, redemptionID, bookingTotal, discountAmount); err != nil {
|
|
||||||
log.Printf("ALERT: failed to insert booking discount: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := tx.Exec(r.Context(), `
|
|
||||||
INSERT INTO payments (booking_id, payment_type, payment_method, amount, status, created_by)
|
|
||||||
VALUES ($1, 'partial', 'discount', $2, 'completed', $3)
|
|
||||||
`, bookingID, discountAmount, booking.User.ID); err != nil {
|
|
||||||
log.Printf("ALERT: failed to insert payment record: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := tx.Exec(r.Context(), `
|
|
||||||
UPDATE loyalty_redemptions SET status = 'applied', applied_to_booking_id = $1, applied_at = NOW()
|
|
||||||
WHERE id = $2
|
|
||||||
`, bookingID, redemptionID); err != nil {
|
|
||||||
log.Printf("ALERT: failed to update loyalty redemption: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := tx.Exec(r.Context(), `
|
|
||||||
UPDATE users SET loyalty_stamps = GREATEST(0, loyalty_stamps - 10) WHERE id = $1
|
|
||||||
`, booking.User.ID); err != nil {
|
|
||||||
log.Printf("ALERT: failed to update loyalty stamps: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment stamps (max 1 per day, only for paid bookings)
|
|
||||||
var newStampCount int
|
var newStampCount int
|
||||||
if bookingTotal > 0 {
|
if bookingTotal > 0 && !loyaltyAppliedOnThisBooking {
|
||||||
if err := tx.QueryRow(r.Context(), `
|
if err := tx.QueryRow(r.Context(), `
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET loyalty_stamps = loyalty_stamps + 1
|
SET loyalty_stamps = loyalty_stamps + 1
|
||||||
@@ -2617,12 +2579,12 @@ func ProgressBookingHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create pending redemption when stamps reach 10
|
// Create pending redemption when stamps reach LoyaltyStampCost
|
||||||
if newStampCount == 10 {
|
if newStampCount == payments.LoyaltyStampCost {
|
||||||
_, err = tx.Exec(r.Context(), `
|
_, err = tx.Exec(r.Context(), `
|
||||||
INSERT INTO loyalty_redemptions (user_id, stamps_redeemed, status, redeemed_at)
|
INSERT INTO loyalty_redemptions (user_id, stamps_redeemed, status, redeemed_at)
|
||||||
VALUES ($1, 10, 'pending', NOW())
|
VALUES ($1, $2, 'pending', NOW())
|
||||||
`, booking.User.ID)
|
`, booking.User.ID, payments.LoyaltyStampCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to create loyalty redemption for user %s: %v", booking.User.ID, err)
|
log.Printf("Failed to create loyalty redemption for user %s: %v", booking.User.ID, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user