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) = @_;