Revision 810
Date:
2021/02/05 22:07:54
Author:
ahitrov
Revision Log:
2-by-1
Files:
Legend:
Added
Removed
Modified
utf8/plugins/webshop/lib/webshop/Discount.pm
20
20
[1, 'Скидка активна'],
21
21
],
22
22
},
23
{ 'attr' => 'mechanic', 'type' => 'status', 'rusname' => 'Механика',
24
'cases' => [
25
['simple', 'Простая скидка'],
26
['two_as_one', 'Скидка на каждую вторую покупку'],
27
],
28
},
23
29
{ 'attr' => 'uid', 'type' => 'status', 'rusname' => 'Доступность для пользователей',
24
30
'cases' => [
25
31
[0, 'Скидка доступна всем пользователям'],
…
…
127
133
@basket = grep { exists $items{$_->item_id} } @basket;
128
134
return 0 unless @basket;
129
135
}
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
}
136
if ( $self->mechanic eq 'two_as_one' ) {
137
$discount_counted = $self->mechanic_two_as_one( \@basket );
135
138
} else {
136
my $found_sum = 0;
137
foreach my $bi ( @$basket ) {
138
$found_sum += $bi->number * $bi->{item}->price;
139
}
140
warn "Sum found: [$found_sum]\n" if $DEBUG;
141
$discount_counted = $self->count_sum_discount( $found_sum );
139
$discount_counted = $self->mechanic_simple( \@basket );
142
140
}
143
return $discount_counted;
141
142
return wantarray ? ($discount_counted, \@basket) : $discount_counted;
144
143
}
145
144
146
145
147
sub count_item_discount {
146
sub mechanic_simple {
148
147
my $self = shift;
149
my $item = shift;
150
return 0 unless $item;
151
return 0 if exists $item->{special_price} && $item->special_price;
148
my $basket = shift;
149
return 0 unless ref $basket eq 'ARRAY' && @$basket;
152
150
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;
151
my $discount = 0;
152
my $price_field = $self->field;
153
$price_field =~ s/\s//sg;
154
$price_field ||= 'price';
155
my $value = $self->discount;
156
$value =~ s/\s//sg;
157
return 0 unless $value;
158
my ($proc, $fixed);
159
if ( $value =~ /([\d\.]+)\s*%/ ) {
160
$proc = $1;
161
} elsif ( $value =~ /^\s*([\d\.]+)\s*$/ ) {
162
$fixed = $1;
163
} else {
164
return 0;
165
}
166
167
foreach my $bi ( @$basket ) {
168
my $item_discount = 0;
169
if ( $proc ) {
170
$item_discount += $bi->{item}->$price_field / 100 * $proc;
171
} else {
172
$item_discount += $bi->{item}->$price_field > $fixed ? $fixed : 0;
164
173
}
174
my $sum = ($bi->{item}->$price_field - $item_discount) * $bi->number;
175
$bi->{sum_discounted}{$self->id}{sum_show} = $sum;
176
$bi->{sum_discounted}{$self->id}{sum_bill} = $sum;
177
$bi->{sum_discounted}{$self->id}{discount} = $item_discount * $bi->number;
178
$discount += $bi->{sum_discounted}{$self->id}{discount};
165
179
}
166
return $count;
180
181
return $discount;
167
182
}
168
183
184
sub mechanic_two_as_one {
185
my $self = shift;
186
my $basket = shift;
187
return 0 unless ref $basket eq 'ARRAY';
188
189
my @new_basket;
190
foreach my $bi ( @$basket ) {
191
$bi->{sum_discounted} = {};
192
for ( my $i = 0; $i < $bi->number; $i++ ) {
193
push @new_basket, $bi;
194
}
195
}
196
return 0 if scalar @new_basket <= 1;
197
198
my $price_field = $self->field;
199
$price_field =~ s/\s//sg;
200
$price_field ||= 'price';
201
202
my $value = $self->discount;
203
$value =~ s/\s//sg;
204
$value ||= '100%';
205
my ($proc, $fixed);
206
if ( $value =~ /([\d\.]+)\s*%/ ) {
207
$proc = $1;
208
} elsif ( $value =~ /^\s*([\d\.]+)\s*$/ ) {
209
$fixed = $1;
210
} else {
211
return 0;
212
}
213
214
my $discount = 0;
215
my @sorted = sort { $b->{item}->$price_field <=> $a->{item}->$price_field } @new_basket;
216
my $border = int(scalar(@sorted) / 2) + scalar(@sorted) % 2;
217
218
my $sum = 0;
219
for( my $i = 0; $i < scalar(@sorted); $i++ ) {
220
my $bi = $sorted[$i];
221
$sum += $bi->{item}->$price_field;
222
if ( $i >= $border ) {
223
my $item_discount = 0;
224
if ( $proc ) {
225
$item_discount = $bi->{item}->$price_field * ($proc / 100);
226
} else {
227
$item_discount = $bi->{item}->$price_field > $fixed ? $fixed : 0;
228
}
229
$bi->{sum_discounted}{$self->id}{sum_show} += $bi->{item}->$price_field - $item_discount;
230
$bi->{sum_discounted}{$self->id}{discount} += $item_discount;
231
$discount += $item_discount;
232
} else {
233
$bi->{sum_discounted}{$self->id}{sum_show} += $bi->{item}->$price_field;
234
}
235
}
236
my $avg_discount = ($sum - $discount) / $sum;
237
foreach my $bi ( @sorted ) {
238
my $bill_price = $bi->{item}->$price_field * $avg_discount;
239
$bi->{sum_discounted}{$self->id}{sum_bill} += $bill_price;
240
}
241
242
return $discount;
243
}
244
169
245
sub count_sum_discount
170
246
{
171
247
my $self = shift;
…
…
197
273
}
198
274
199
275
if ( $self->discount ) {
200
$self->{discount} =~ s/\D//sg;
276
$self->{discount} =~ s/[^\d\.%]//sg;
201
277
}
202
278
203
279
return 1;
utf8/plugins/webshop/lib/webshop/Keeper.pm
508
508
}
509
509
}
510
510
511
my ($discount_sum, $discount_payment) = (0, 0);
512
511
513
my $now = Contenido::DateTime->new;
512
514
my @discounts = $keeper->get_documents(
513
515
class => 'webshop::Discount',
…
…
515
517
interval=> [$now, $now],
516
518
%dopts,
517
519
);
518
my @summoned = sort { $b->min_sum <=> $a->min_sum } grep { $_->min_sum && $_->discount && $_->min_sum =~ /^\d+$/ } @discounts;
520
my @summoned = sort { $b->min_sum <=> $a->min_sum } grep { $_->discount && $_->min_sum =~ /^\d+$/ } @discounts;
521
warn "Summoned: ".scalar(@summoned)." discounts\n" if $DEBUG;
519
522
my ($total, $sum) = $self->basket_count( \@basket );
523
warn "Sum: $sum\n" if $DEBUG;
520
524
return 0 unless $sum;
521
my $result = 0;
525
526
my $discount_used;
522
527
foreach my $discount ( @summoned ) {
528
warn "Check discount: ".$discount->name."\n" if $DEBUG;
523
529
if ( $sum > $discount->min_sum ) {
524
530
my $res = $discount->get_discount( basket => \@basket );
525
$result = $res if $res > $result;
531
warn "Discount result: $res\n" if $DEBUG;
532
if ( $res > $discount_sum && $res < $sum ) {
533
$discount_sum = $res;
534
$discount_used = $discount;
535
}
526
536
}
527
537
}
538
if ( ref $discount_used ) {
539
foreach my $bi ( @basket ) {
540
if ( exists $bi->{sum_discounted} && exists $bi->{sum_discounted}{$discount_used->id} ) {
541
$bi->{sum_discounted} = $bi->{sum_discounted}{$discount_used->id};
542
} else {
543
$bi->{sum_discounted} = {};
544
}
545
}
546
}
528
547
529
548
my $summarize = 0;
530
549
if ( ref $payment && $payment->discount && $payment->discount > 0 ) {
…
…
541
560
}
542
561
if ( $payment->summarize ) {
543
562
$summarize = 1;
544
$result += $payment_discount_sum if $payment_discount_sum + $result < $sum;
545
} else {
546
$result = $payment_discount_sum if $payment_discount_sum > $result;
547
563
}
564
$discount_payment = $payment_discount_sum if $payment_discount_sum < $sum;
548
565
}
549
566
550
$result = 0 if $result >= $sum;
551
return ($result, $summarize);
567
return ($discount_sum, $discount_payment, $summarize);
552
568
}
553
569
554
555
570
sub check_coupons {
556
571
my $self = shift;
557
572
my (%opts) = @_;
Небольшая справка по веткам
cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.
koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.
utf8 – актуальная ветка, заточенная под UTF-8.
Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.