File Coverage

blib/lib/Dancer2/Plugin/Interchange6/Routes/Cart.pm
Criterion Covered Total %
statement 58 58 100.0
branch 22 24 91.6
condition 3 3 100.0
subroutine 3 3 100.0
pod 1 1 100.0
total 87 89 97.7


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::Interchange6::Routes::Cart;
2              
3 2     2   7 use Try::Tiny;
  2         3  
  2         1263  
4              
5             =head1 NAME
6              
7             Dancer2::Plugin::Interchange6::Routes::Cart - Cart routes for Interchange6 Shop Machine
8              
9             =cut
10              
11             =head1 FUNCTIONS
12              
13             =head2 cart_route
14              
15             Returns the cart route based on the plugin configuration.
16              
17             =cut
18              
19             sub cart_route {
20 1     1 1 1 my $plugin = shift;
21              
22             return sub {
23 35     35   5781 my $app = shift;
24 35         154 my $params = $app->request->parameters;
25              
26 35         2942 my ( $product, $cart_input, $cart_product, $roles, @errors );
27              
28 35         126 my $cart_name = $params->get('cart');
29              
30 35 100       810 my $cart =
31             $cart_name ? $plugin->shop_cart($cart_name) : $plugin->shop_cart;
32              
33 35         190 $app->log( "debug", "cart_route cart name: ", $cart->name );
34              
35 35 100 100     15040 if ( my @skus = $params->get_all('remove') ) {
    100          
36              
37             # remove items from cart
38              
39 3         48 foreach my $sku (@skus) {
40             try {
41 3         138 $cart->remove($sku);
42             }
43             catch {
44 1         15 $app->log( "warning", "Cart remove $sku error: $_" );
45 1         378 push @errors, "Failed to remove product $sku from cart: $_";
46 3         23 };
47             }
48              
49             # if GET then URL now contains ugly query params so redirect
50 3 50       121 return $app->redirect('/cart') if $app->request->is_get;
51              
52             }
53             elsif ( $params->get('update')
54             && defined $params->get('quantity') )
55             {
56              
57 3         89 my $sku = $params->get('update');
58 3         13 my $qty = $params->get('quantity');
59              
60             # update existing cart product
61              
62 3         20 $app->log( "debug", "Update $sku with quantity $qty" );
63              
64             try {
65 3         134 $cart->update( $sku => $qty );
66             }
67             catch {
68 1         406 $app->log( "warning", "Update cart product $sku error: $_" );
69 1         381 push @errors, "Failed to update product $sku in cart: $_";
70 3         1195 };
71             }
72              
73 35 100       1400 if ( my $sku = $params->get('sku') ) {
74              
75             # add new product
76              
77             # we currently only support one product at a time
78              
79 19         427 $product = $plugin->shop_product($sku);
80              
81 19 100       72256 unless ( defined $product ) {
82 1         20 $app->log( "warning",
83             "sku $sku not found in POST /cart: $input" );
84 1         407 $app->session->write( shop_cart_error =>
85             { message => "Product not found with sku: $sku" } );
86 1         70 return $app->redirect('/');
87             }
88              
89 18 100       619 if ( defined $product->canonical_sku ) {
90              
91             # this is a variant so we need to add in variant info
92             # into $params if missing
93              
94 2         42 my $rset = $product->product_attributes->search(
95             {
96             'attribute.type' => 'variant',
97             },
98             {
99             prefetch => [
100             'attribute',
101             {
102             product_attribute_values => 'attribute_value'
103             }
104             ],
105             }
106             );
107 2         3025 while ( my $result = $rset->next ) {
108 4         35417 my $name = $result->attribute->name;
109              
110             # WTF! why do we get a resultset of pavs? Surely there
111             # should be only one related pav for pa?
112 4         174 my $value =
113             $result->product_attribute_values->first->attribute_value
114             ->value;
115              
116 4 50       2402 $params->set( $name => $value )
117             unless defined $params->get($name);
118             }
119             }
120              
121             # retrieve product attributes for possible variants
122 18         747 my $attr_ref = $product->attribute_iterator( hashref => 1 );
123 18         308310 my %user_input;
124              
125 18 100       67 if ( keys %$attr_ref ) {
126              
127 11         28 for my $name ( keys %$attr_ref ) {
128 22         137 $user_input{$name} = $params->get($name);
129             }
130              
131             $app->log(
132 11         106 "debug", "Attributes for $input: ",
133             $attr_ref, ", user input: ",
134             \%user_input
135             );
136 11         7835 my %match_info;
137              
138 11 100       67 unless ( $cart_product =
139             $product->find_variant( \%user_input, \%match_info ) )
140             {
141 2         310749 $app->log( "warning", "Variant not found for ",
142             $product->sku );
143              
144 2         1057 $app->session->write(
145             shop_cart_error => {
146             message => 'Variant not found.',
147             info => \%match_info
148             }
149             );
150              
151 2         169 return $app->redirect( $product->uri );
152             }
153             }
154             else {
155             # product without variants
156 7         10 $cart_product = $product;
157             }
158              
159 16 100       534264 my $quantity =
160             $params->get('quantity') ? $params->get('quantity') : 1;
161              
162             try {
163 16         823 $cart->add(
164             {
165             dbic_product => $cart_product,
166             sku => $cart_product->sku,
167             quantity => $quantity
168             }
169             );
170             }
171             catch {
172 1         542 $app->log( "warning", "Cart add error: $_" );
173 1         587 push @errors, "Failed to add product to cart: $_";
174 16         225 };
175             }
176              
177             # add stuff useful for cart display
178 32         1113 my $values = {
179             cart_subtotal => $cart->subtotal,
180             cart_total => $cart->total,
181             cart => $cart->products,
182             };
183 32 100       43087 $values->{cart_error} = join( ". ", @errors )
184             if scalar @errors;
185              
186             # call before_cart_display route so template tokens
187             # can be injected
188 32         542 $app->execute_hook( 'plugin.interchange6.before_cart_display',
189             $values );
190              
191 32         20371 $app->template( $plugin->cart_template, $values );
192             }
193 1         8 }
194              
195             1;