Diff -- /var/www/vhosts/3dshawn.com/repricer.3dshawn.com/_attic/cart_promo.cgi
Diff

/var/www/vhosts/3dshawn.com/repricer.3dshawn.com/_attic/cart_promo.cgi

added on local at 2026-07-01 21:47:31

Added
+102
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 7f871778ddf4
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2#======================================================================
3# RePricer -- apply or remove a promo code on a buyer cart.
4#
5# POST /cart_promo.cgi
6# action=apply storefront_id=N code=...
7# action=remove storefront_id=N
8#
9# Validates the code via MODS::RePricer::Promotions::load_by_code +
10# validate against the current cart subtotal. On success, writes to
11# cart_promotions; the cart page re-reads that table to display the
12# discount. The actual redemption row is written later, by
13# stripe_webhook.cgi on payment_intent.succeeded, so a failed payment
14# doesn't burn the buyer's max_per_user slot.
15#======================================================================
16use strict;
17use warnings;
18
19use lib '/var/www/vhosts/3dshawn.com/repricer.3dshawn.com';
20use CGI;
21use MODS::DBConnect;
22use MODS::RePricer::Config;
23use MODS::RePricer::Cart;
24use MODS::RePricer::Promotions;
25
26$| = 1;
27
28my $q = CGI->new;
29my $form = $q->Vars;
30my $db = MODS::DBConnect->new;
31my $cfg = MODS::RePricer::Config->new;
32my $cart = MODS::RePricer::Cart->new;
33my $promo = MODS::RePricer::Promotions->new;
34my $DB = $cfg->settings('database_name');
35
36my $sid = $form->{storefront_id} || $form->{id} || 0;
37$sid =~ s/[^0-9]//g;
38my $action = $form->{action} || '';
39$action =~ s/[^a-z_]//g;
40
41# Always redirect back to the cart so the buyer sees the result in
42# context. URL-encode the flash so a code like 'X & Y' survives.
43sub _back {
44 my ($sid, $kind, $msg) = @_;
45 my $u = '/cart.cgi?id=' . $sid;
46 if ($kind && defined $msg) {
47 my $e = $msg;
48 $e =~ s/([^A-Za-z0-9\-_.~])/sprintf('%%%02X', ord($1))/eg;
49 $u .= '&' . $kind . '=' . $e;
50 }
51 print "Status: 302 Found\nLocation: $u\n\n";
52 exit;
53}
54
55_back($sid, 'promo_err', 'Cart not found.') unless $sid;
56my $token = $cart->read_token($q);
57_back($sid, 'promo_err', 'Your cart session expired -- add something and try again.') unless $token;
58
59my $dbh = $db->db_connect();
60
61if ($action eq 'remove') {
62 $promo->cart_clear($db, $dbh, $DB, $token, $sid);
63 $db->db_disconnect($dbh);
64 _back($sid, 'promo_ok', 'Promo code removed.');
65}
66
67if ($action eq 'apply') {
68 my $code = $form->{code} || '';
69 my $row = $promo->load_by_code($db, $dbh, $DB, $code,
70 kind => 'model', storefront_id => $sid);
71 unless ($row && $row->{id}) {
72 $db->db_disconnect($dbh);
73 _back($sid, 'promo_err', "That code isn't valid for this store.");
74 }
75
76 my $subtotal = $cart->total_cents($db, $dbh, $DB, $token, $sid);
77 if ($subtotal <= 0) {
78 $db->db_disconnect($dbh);
79 _back($sid, 'promo_err', 'Add something to your cart first.');
80 }
81
82 # new_customer is the simplest signal we have without joining
83 # buyer_accounts -- treat anonymous buyers as new. The webhook does
84 # the final new_customer check against orders on payment success.
85 my %v = $promo->validate($db, $dbh, $DB, $row,
86 kind => 'model',
87 subtotal_cents => $subtotal,
88 buyer_email => '',
89 new_customer => 1,
90 );
91 unless ($v{ok}) {
92 $db->db_disconnect($dbh);
93 _back($sid, 'promo_err', $v{reason} || 'That code is not valid right now.');
94 }
95
96 $promo->cart_apply($db, $dbh, $DB, $token, $sid, $row->{id});
97 $db->db_disconnect($dbh);
98 _back($sid, 'promo_ok', 'Code applied -- discount shows below.');
99}
100
101$db->db_disconnect($dbh);
102_back($sid, 'promo_err', 'Unknown action.');
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help