package webshop::Coupon;
use strict;
use warnings 'all';
use Contenido::Globals;
use base "Contenido::Document";
use Data::Dumper;
sub extra_properties
{
return (
{ 'attr' => 'class', 'column' => undef },
{ 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус',
'cases' => [
[0, 'Купон не активен'],
[1, 'Купон активен и разослан'],
[2, 'Прототип ждет обработки'],
[3, 'Купон использован'],
[4, 'Прототип обработан роботом'],
],
},
{ 'attr' => 'uid_proto','type' => 'status', 'rusname' => 'Прототип пользовательского доступа',
'cases' => [
[0, 'Купон доступен всем пользователям'],
[1, 'Персональный купон, создается для всех зарегистрированных пользователей'],
[2, 'Персональный купон, пользователи по выбору'],
[3, 'Персональный купон для одного пользователя'],
],
'rem' => 'Заполняется при создании прототипа купона',
},
{ 'attr' => 'uid_condition', 'type' => 'string', 'rusname' => 'Условие для прототипа' },
{ 'attr' => 'uid', 'type' => 'pickup', 'rusname' => 'Пользователь',
lookup_opts => { class => $state->{users}->profile_document_class, order_by => 'email', search_by => 'email' },
allow_null => 1, default => 0,
rem => '0 - действует для всех пользователей, многократно. id - для одного пользователя, однократно.'
},
{ 'attr' => 'groups', 'rusname' => 'Группы товаров',
lookup_opts => { class => $state->{webshop}->{item_section_class}, },
allow_null => 1,
rem => 'Список разделов, на содержимое которых распространяется скидка по купону',
},
{ 'attr' => 'discount', 'type' => 'string', 'rusname' => 'Скидка на сумму заказа (число или процент)', shortname => 'Скидка',
default => 0, column => 2 },
{ 'attr' => 'min_sum', 'type' => 'string', 'rusname' => 'Минимальная сумма, на которую действует скидка', default => 0 },
)
}
sub class_name
{
return 'Webshop: купон';
}
sub class_description
{
return 'Webshop: купон';
}
sub class_table
{
return 'webshop::SQL::CouponsTable';
}
sub contenido_status_style
{
my $self = shift;
if ( $self->status == 3 ) {
return 'color:black;';
} elsif ( $self->status == 2 ) {
return 'color:red;';
} elsif ( $self->status == 4 ) {
return 'color:olive;';
}
}
sub table_links
{
return [
{ name => 'Купоны', class => 'webshop::Coupon', filter => 'pid', field => 'pid' },
];
}
sub get_discount
{
my $self = shift;
my (%opts) = @_;
return 0 unless exists $opts{basket} || exists $opts{uid} && $opts{uid} || exists $opts{session} && $opts{session};
return 0 unless $self->discount;
my $basket = exists $opts{basket} ? delete $opts{basket} : $keeper->{webshop}->get_basket ( %opts );
return 0 unless ref $basket eq 'ARRAY' && @$basket;
my ($number, $sum_total) = (0, 0);
map { $number += $_->number; $sum_total += $_->number * $_->price } @$basket;
warn "BASKET: $number Items of $sum_total Value\n";
my $discount_counted = 0;
my $items;
if ( $self->groups ) {
$items = $self->keeper->get_documents (
s => [$self->groups],
class => $state->{webshop}->{item_document_class},
light => 1,
return_mode => 'array_ref',
);
} else {
$items = $self->keeper->get_documents (
class => $state->{webshop}->{item_document_class},
lclass => 'webshop::CouponItemLink',
lsource => $self->id,
light => 1,
return_mode => 'array_ref',
);
}
if ( ref $items eq 'ARRAY' && scalar @$items ) {
my $found_sum = 0;
foreach my $bi ( @$basket ) {
warn "BASKET: Basket item id [".$bi->item_id."]\n" if $DEBUG;
next if $bi->special_price;
foreach my $item ( @$items) {
if ( $bi->item_id == $item->id ) {
warn "BASKET: Product [".$item->name."] id [".$item->id."]\n" if $DEBUG;
$found_sum += $bi->number * $bi->price;
last;
}
}
}
warn "Sum found: [$found_sum]\n" if $DEBUG;
return $self->can_discount( $found_sum );
} elsif ( $self->groups ) {
return 0;
} else {
my $found_sum = 0;
foreach my $bi ( @$basket ) {
warn "BASKET: Basket item id [".$bi->item_id."]\n" if $DEBUG;
next if $bi->special_price;
$found_sum += $bi->number * $bi->price;
}
warn "Sum found: [$found_sum]\n" if $DEBUG;
return $self->can_discount( $found_sum );
}
return 0;
}
sub can_discount
{
my $self = shift;
my $sum = shift;
return 0 unless $sum;
my $discount = $self->discount;
my $min_sum = $self->min_sum || 0;
my $count = 0;
if ( $discount =~ /([\d\.]+)%/ ) {
my $proc = $1;
return 0 unless $proc;
$count = $sum / 100 * $proc;
} else {
$count = $discount;
}
my $rest = $sum - $count;
warn "Min Sum: $min_sum. Rest: $rest\n" if $DEBUG;
$count = 0 if ($min_sum && $sum < $min_sum) || $rest <= 0;
warn "Count: $count\n" if $DEBUG;
return $count;
}
#sub table_links
#{
# return [
# { name => 'Города', class => 'webshop::Town', filter => 'pid', field => 'pid' },
# ];
#}
sub pre_store
{
my $self = shift;
my $default_section = $project->s_alias->{webshop_coupons} if ref $project->s_alias eq 'HASH';
if ( $default_section && !$self->sections ) {
$self->sections($default_section);
}
return 1;
}
sub post_delete
{
my $self = shift;
my $sql = $self->keeper->SQL->prepare('DELETE FROM webshop_coupons where pid = ?');
$sql->execute( $self->id );
$sql = $self->keeper->SQL->prepare('DELETE FROM webshop_coupon_links where source_id = ?');
$sql->execute( $self->id );
$sql = $self->keeper->SQL->prepare('DELETE FROM webshop_order_coupons where dest_id = ?');
$sql->execute( $self->id );
1;
}
1;
Небольшая справка по веткам
cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.
koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.
utf8 – актуальная ветка, заточенная под UTF-8.
Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.