Line # Revision Author
1 424 ahitrov package webshop::Discount;
2
3 use strict;
4 use warnings 'all';
5
6 use Contenido::Globals;
7 use base "Contenido::Document";
8 use Data::Dumper;
9
10 sub extra_properties
11 {
12 return (
13 425 ahitrov { 'attr' => 'code', 'hidden' => 1, 'column' => undef },
14 424 ahitrov { 'attr' => 'class', 'column' => undef },
15 425 ahitrov { 'attr' => 'dtime', 'rusname' => 'Начало действия скидки' },
16 { 'attr' => 'etime', 'rusname' => 'Окончание действия скидки' },
17 424 ahitrov { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
18 'cases' => [
19 [0, 'Скидка не активна'],
20 [1, 'Скидка активна'],
21 ],
22 },
23 { 'attr' => 'uid', 'type' => 'status', 'rusname' => 'Доступность для пользователей',
24 'cases' => [
25 [0, 'Скидка доступна всем пользователям'],
26 [1, 'Скидка доступна только зарегистрированным пользователям'],
27 ],
28 },
29 { 'attr' => 'groups', 'rusname' => 'Группы товаров',
30 lookup_opts => { class => $state->{webshop}->{item_section_class}, },
31 allow_null => 1,
32 rem => 'Список разделов, на содержимое которых распространяется скидка по купону',
33 },
34 425 ahitrov { 'attr' => 'min_sum', 'type' => 'string', 'rusname' => 'Порог суммы, с которого действует скидка',
35 429 ahitrov default => 0, column => 6, shortname => 'Сумма заказа' },
36 { 'attr' => 'field', 'type' => 'string', 'rusname' => 'Название ценовой колонки', shortname => 'Колонка',
37 column => 7,
38 rem => 'Используется название, отмеченное серым цветом в "name=priceNN"' },
39 425 ahitrov { 'attr' => 'discount', 'type' => 'string', 'rusname' => 'Размер скидки (число или процент)', shortname => 'Скидка',
40 429 ahitrov default => 0, column => 8,
41 rem => 'Данное поле будет задействовано, если не указана ценовая колонка', },
42 424 ahitrov )
43 }
44
45 sub class_name
46 {
47 return 'Webshop: скидка';
48 }
49
50 sub class_description
51 {
52 return 'Webshop: скидка';
53 }
54
55 sub class_table
56 {
57 return 'webshop::SQL::CouponsTable';
58 }
59
60 sub contenido_status_style
61 {
62 my $self = shift;
63 if ( $self->status == 3 ) {
64 return 'color:black;';
65 } elsif ( $self->status == 2 ) {
66 return 'color:red;';
67 } elsif ( $self->status == 4 ) {
68 return 'color:olive;';
69 }
70 }
71
72 sub table_links
73 {
74 return [
75 # { name => 'Купоны', class => 'webshop::Coupon', filter => 'pid', field => 'pid' },
76 ];
77 }
78
79
80 sub get_discount
81 {
82 my $self = shift;
83
84 my (%opts) = @_;
85 429 ahitrov return 0 unless exists $opts{basket} || exists $opts{uid} && $opts{uid} || exists $opts{session} && $opts{session};
86 424 ahitrov return 0 unless $self->discount;
87
88 429 ahitrov my $basket = delete $opts{basket};
89 $basket = $keeper->{webshop}->get_basket ( %opts ) unless $basket;
90 424 ahitrov return 0 unless ref $basket eq 'ARRAY' && @$basket;
91
92 429 ahitrov my @basket = grep { exists $_->{item} && $_->{item} } @$basket;
93 return 0 unless @basket;
94
95 424 ahitrov my ($number, $sum_total) = (0, 0);
96 429 ahitrov map { $number += $_->number; $sum_total += $_->number * $_->{item}->price } @basket;
97 432 ahitrov warn "BASKET: $number Items of $sum_total Value\n" if $DEBUG;
98 424 ahitrov
99 429 ahitrov my %item_props = map { $_->{attr} => $_ } $basket[0]->{item}->structure;
100 if ( exists $item_props{special_price} ) {
101 @basket = grep { !$_->{item}->special_price } @basket;
102 return 0 unless @basket;
103 }
104
105 424 ahitrov my $discount_counted = 0;
106 my $items;
107 if ( $self->groups ) {
108 $items = $self->keeper->get_documents (
109 s => [$self->groups],
110 class => $state->{webshop}->{item_document_class},
111 429 ahitrov ids => 1,
112 424 ahitrov return_mode => 'array_ref',
113 );
114 429 ahitrov return 0 unless ref $items eq 'ARRAY' && @$items;
115 424 ahitrov } else {
116 $items = $self->keeper->get_documents (
117 class => $state->{webshop}->{item_document_class},
118 lclass => 'webshop::DiscountItemLink',
119 lsource => $self->id,
120 429 ahitrov ids => 1,
121 424 ahitrov return_mode => 'array_ref',
122 );
123 }
124
125 if ( ref $items eq 'ARRAY' && @$items ) {
126 429 ahitrov my %items = map { $_ => 1 } @$items;
127 @basket = grep { exists $items{$_->item_id} } @basket;
128 return 0 unless @basket;
129 }
130 if ( $self->field ) {
131 foreach my $bi ( @basket ) {
132 next if exists $bi->{item}{special_price} && $bi->{item}->special_price;
133 $discount_counted += $self->count_item_discount( $bi->{item} ) * $bi->number;
134 424 ahitrov }
135 } else {
136 my $found_sum = 0;
137 foreach my $bi ( @$basket ) {
138 429 ahitrov $found_sum += $bi->number * $bi->{item}->price;
139 424 ahitrov }
140 warn "Sum found: [$found_sum]\n" if $DEBUG;
141 429 ahitrov $discount_counted = $self->count_sum_discount( $found_sum );
142 424 ahitrov }
143 429 ahitrov return $discount_counted;
144 424 ahitrov }
145
146
147 429 ahitrov sub count_item_discount {
148 my $self = shift;
149 my $item = shift;
150 return 0 unless $item;
151 return 0 if exists $item->{special_price} && $item->special_price;
152
153 my $count = 0;
154 my $item_field = $self->field;
155 $item_field =~ s/\s//sg;
156 if ( $item_field && $item->$item_field && $item->price > $item->$item_field ) {
157 $count = $item->price - $item->$item_field;
158 } elsif ( $self->discount ) {
159 my $value = $self->discount;
160 $value =~ s/\s//sg;
161 if ( $value =~ /([\d\.]+)%/ ) {
162 my $proc = $1;
163 $count = $item->price / 100 * $proc;
164 }
165 }
166 return $count;
167 }
168
169 sub count_sum_discount
170 424 ahitrov {
171 my $self = shift;
172 my $sum = shift;
173 return 0 unless $sum;
174
175 my $discount = $self->discount;
176 my $count = 0;
177 if ( $discount =~ /([\d\.]+)%/ ) {
178 my $proc = $1;
179 return 0 unless $proc;
180 $count = $sum / 100 * $proc;
181 } else {
182 $count = $discount;
183 }
184 429 ahitrov $count = 0 if $sum <= $count;
185 424 ahitrov return $count;
186 }
187
188
189
190 sub pre_store
191 {
192 my $self = shift;
193
194 my $default_section = $project->s_alias->{webshop_discounts} if ref $project->s_alias eq 'HASH';
195 if ( $default_section && !$self->sections ) {
196 $self->sections($default_section);
197 }
198
199 786 ahitrov if ( $self->discount ) {
200 $self->{discount} =~ s/\D//sg;
201 }
202
203 424 ahitrov return 1;
204 }
205
206
207 sub post_delete
208 {
209 my $self = shift;
210
211 427 ahitrov my $sql = $self->keeper->SQL->prepare('DELETE FROM webshop_coupon_links where source_id = ?');
212 424 ahitrov $sql->execute( $self->id );
213
214 1;
215 }
216
217 1;