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

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

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

Added
+206
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 36f90d26dc5c
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 -- view cart for one storefront.
4#
5# GET /cart.cgi?id=<storefront_id>
6#
7# Renders the cart contents using the storefront's theme so it feels
8# like a continuation of the shopping experience. Each row has a
9# Remove (X) button. A Checkout button at the bottom kicks off the
10# Stripe Elements payment flow (see /checkout.cgi).
11#======================================================================
12use strict;
13use warnings;
14
15use lib '/var/www/vhosts/3dshawn.com/repricer.3dshawn.com';
16use CGI;
17use MODS::Template;
18use MODS::DBConnect;
19use MODS::RePricer::Config;
20use MODS::RePricer::Themes;
21use MODS::RePricer::Cart;
22use MODS::RePricer::Promotions;
23use MODS::RePricer::BuyerAuth;
24use MODS::RePricer::BuyerCredits;
25
26$| = 1;
27
28my $q = CGI->new;
29my $form = $q->Vars;
30my $tfile = MODS::Template->new;
31my $db = MODS::DBConnect->new;
32my $config = MODS::RePricer::Config->new;
33my $themes = MODS::RePricer::Themes->new;
34my $cart = MODS::RePricer::Cart->new;
35my $DB = $config->settings('database_name');
36
37my $sid = $form->{id} || $form->{storefront_id} || 0;
38$sid =~ s/[^0-9]//g;
39unless ($sid) {
40 print "Status: 302 Found\nLocation: /\n\n";
41 exit;
42}
43
44my $dbh = $db->db_connect();
45
46# Pull the storefront so the cart page can render in its theme.
47my $store = $db->db_readwrite($dbh,
48 qq~SELECT id, name, subdomain, theme_id FROM `${DB}`.storefronts WHERE id='$sid' AND status='live' LIMIT 1~,
49 $ENV{SCRIPT_NAME}, __LINE__);
50unless ($store && $store->{id}) {
51 $db->db_disconnect($dbh);
52 print "Status: 302 Found\nLocation: /\n\n";
53 exit;
54}
55
56my $theme = $themes->by_id($store->{theme_id});
57my $css_vars = $themes->css_vars($theme);
58
59my ($token, $cookie_line) = $cart->ensure_token($q);
60my @rows = $cart->items($db, $dbh, $DB, $token, $sid);
61my $subtotal = $cart->total_cents($db, $dbh, $DB, $token, $sid);
62
63# Promo state: an applied cart-promo lives in cart_promotions; we also
64# surface the platform's currently-marquee'd 'model' promo (if any) so
65# buyers see what's on offer before they even type a code.
66my $promo = MODS::RePricer::Promotions->new;
67my $applied = $promo->cart_applied($db, $dbh, $DB, $token, $sid);
68my $discount = $applied ? $promo->apply_to_total_cents($applied, $subtotal) : 0;
69my $total = $subtotal - $discount;
70$total = 0 if $total < 0;
71
72# Store credit available to this buyer (registered only -- guests can
73# see "Sign in to use your $X store credit" via a hint surfaced when
74# the email field is filled on the checkout page, not here).
75my $buyer_auth = MODS::RePricer::BuyerAuth->new;
76my $bc = MODS::RePricer::BuyerCredits->new;
77my $credit_cents = 0;
78my $credit_apply = 0; # how much of the current cart will be covered
79my $buyer_signed = 0;
80{
81 my $b = $buyer_auth->verify($q, $db, $dbh, $DB);
82 if ($b && $b->{id} && $b->{storefront_id} && $b->{storefront_id} eq $sid) {
83 $buyer_signed = 1;
84 $credit_cents = $bc->balance_cents($db, $dbh, $DB, $sid,
85 { buyer_account_id => $b->{id} });
86 if ($credit_cents > 0 && $total > 0) {
87 $credit_apply = $credit_cents > $total ? $total : $credit_cents;
88 }
89 }
90}
91my $total_after_credit = $total - $credit_apply;
92$total_after_credit = 0 if $total_after_credit < 0;
93
94$db->db_disconnect($dbh);
95
96my $applied_code = $applied ? ($applied->{code} || '') : '';
97my $applied_label = $applied ? $promo->marketing_label($applied) : '';
98
99# Flash from /cart_promo.cgi redirects (?promo_ok=... / ?promo_err=...).
100my $promo_flash_msg = '';
101my $promo_flash_kind = '';
102if (defined $form->{promo_ok}) {
103 $promo_flash_kind = 'ok';
104 $promo_flash_msg = $form->{promo_ok};
105} elsif (defined $form->{promo_err}) {
106 $promo_flash_kind = 'err';
107 $promo_flash_msg = $form->{promo_err};
108}
109$promo_flash_msg =~ s/[^\x20-\x7E]//g;
110$promo_flash_msg = substr($promo_flash_msg, 0, 200);
111
112my @items;
113my $needs_shipping = 0;
114foreach my $r (@rows) {
115 my $hero = $r->{hero_image_url} || '/assets/no-cover.svg';
116 my $price = '$' . sprintf('%.2f', ($r->{unit_price_cents} || 0) / 100);
117 my $line = '$' . sprintf('%.2f', (($r->{unit_price_cents} || 0) * ($r->{quantity} || 1)) / 100);
118 # Variant tag -- a tiny "3D PRINT \xb7 Red PLA" pill under the
119 # title so the buyer sees which kind/color/material they added.
120 my $kind = $r->{purchase_kind} || 'digital';
121 my $variant_pill = '';
122 if ($kind eq 'physical') {
123 $needs_shipping = 1;
124 my @bits = ('3D Print');
125 push @bits, _h($r->{selected_color}) if $r->{selected_color};
126 push @bits, _h($r->{selected_material}) if $r->{selected_material};
127 $variant_pill = join(' &middot; ', @bits);
128 } elsif ($kind eq 'digital') {
129 $variant_pill = 'Digital download';
130 }
131 if ($r->{is_bundle}) {
132 my $n = $r->{bundle_item_count} || 0;
133 $variant_pill = ($kind eq 'physical' ? 'Bundle &middot; 3D Print' : 'Bundle &middot; Digital')
134 . " &middot; $n item(s)";
135 }
136 push @items, {
137 cart_item_id => $r->{cart_item_id},
138 model_id => $r->{model_id} || 0,
139 bundle_id => $r->{bundle_id} || 0,
140 is_bundle => $r->{is_bundle} ? 1 : 0,
141 title => _h($r->{title}),
142 hero => $hero,
143 hero_pos => $r->{hero_image_pos} || '50% 50%',
144 price => $price,
145 line_total => $line,
146 quantity => $r->{quantity} || 1,
147 variant_pill => $variant_pill,
148 is_physical => ($kind eq 'physical') ? 1 : 0,
149 };
150}
151
152# Storefront header chrome (brand + search + sign in + cart) -- same
153# header every store.cgi layout renders. Pulled in via the shared
154# helper so cart, checkout, my_orders etc. all show identical chrome.
155require MODS::RePricer::StoreChrome;
156my $chrome_html = MODS::RePricer::StoreChrome->header_html({
157 store_id => $store->{id},
158 store_name => $store->{name} || $store->{subdomain},
159 is_buyer_in => $buyer_signed,
160 cart_count => scalar(@items),
161 db => $db,
162 dbh => $dbh,
163 DB => $DB,
164});
165
166my $tvars = {
167 theme_css_vars => $css_vars,
168 store_id => $store->{id},
169 store_name => $store->{name} || $store->{subdomain},
170 store_chrome_html => $chrome_html,
171 items => \@items,
172 has_items => scalar(@items) ? 1 : 0,
173 item_count => scalar(@items),
174 subtotal_display => '$' . sprintf('%.2f', $subtotal / 100),
175 discount_display => '$' . sprintf('%.2f', $discount / 100),
176 total_display => '$' . sprintf('%.2f', $total_after_credit / 100),
177 total_before_credit_display => '$' . sprintf('%.2f', $total / 100),
178 has_discount => $discount > 0 ? 1 : 0,
179 has_applied_promo => $applied ? 1 : 0,
180 applied_code => $applied_code,
181 applied_label => $applied_label,
182 credit_balance_display => '$' . sprintf('%.2f', $credit_cents / 100),
183 credit_applied_display => '$' . sprintf('%.2f', $credit_apply / 100),
184 has_credit => $credit_apply > 0 ? 1 : 0,
185 has_credit_balance => $credit_cents > 0 ? 1 : 0,
186 buyer_signed_in => $buyer_signed,
187 promo_flash_msg => $promo_flash_msg,
188 promo_flash_kind => $promo_flash_kind,
189 has_promo_flash => length $promo_flash_msg ? 1 : 0,
190 needs_shipping => $needs_shipping,
191 back_href => "/store.cgi?id=$sid",
192};
193
194print "Content-Type: text/html; charset=utf-8\nCache-Control: no-cache\n";
195print "Set-Cookie: $cookie_line\n" if $cookie_line;
196print "\n";
197
198print join('', $tfile->template('repricer_cart.html', $tvars, undef));
199
200sub _h {
201 my ($s) = @_;
202 $s = '' unless defined $s;
203 $s =~ s/&/&amp;/g; $s =~ s/</&lt;/g; $s =~ s/>/&gt;/g;
204 $s =~ s/"/&quot;/g; $s =~ s/'/&#39;/g;
205 return $s;
206}
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help