Revision 853

Date:
2026/08/20 23:19:58
Author:
ahitrov
Revision Log:
Profile-coupon link and merge function
Files:

Legend:

 
Added
 
Removed
 
Modified
  • utf8/plugins/webshop/lib/webshop/Init.pm

     
    18 18 webshop::SQL::Order
    19 19 webshop::SQL::CouponsTable
    20 20 webshop::SQL::CouponLinkTable
    21 webshop::SQL::OrderCouponLinkTable
    22 webshop::SQL::ProfileCouponLinkTable
    21 23
    22 24 webshop::Profile
    23 25
    … …  
    37 39 webshop::PaymentSection
    38 40 webshop::RegionSection
    39 41
    42 webshop::ProfileCouponLink
    43 webshop::DiscountItemLink
    40 44 webshop::CouponItemLink
    41 webshop::DiscountItemLink
    42 45 webshop::OrderCouponLink
    46 webshop::ProfileCouponLink
    43 47
    44 48 webshop::Service::CDEK
    45 49 ));
    … …  
    47 51 sub init {
    48 52 push @{ $state->{'available_documents'} }, qw(webshop::Basket webshop::Order webshop::Delivery webshop::Payment webshop::Coupon webshop::Discount webshop::Country webshop::Area webshop::Town webshop::Profile);
    49 53 push @{ $state->{'available_sections'} }, qw(webshop::DeliverySection webshop::PaymentSection webshop::RegionSection);
    50 push @{ $state->{'available_links'} }, qw(webshop::CouponItemLink webshop::OrderCouponLink);
    54 push @{ $state->{'available_links'} }, qw(webshop::CouponItemLink webshop::OrderCouponLink webshop::ProfileCouponLink);
    51 55 0;
    52 56 }
    53 57
  • utf8/plugins/webshop/lib/webshop/Keeper.pm

     
    454 454 warn "Merge (coupons) begin: ".Dumper(\%opts)."\n" if $DEBUG;
    455 455 return unless $opts{uid} && $opts{session};
    456 456
    457 my @items = $keeper->get_links (
    457 my $merge_from = $keeper->get_links (
    458 458 class => 'webshop::OrderCouponLink',
    459 459 session => $opts{session},
    460 460 source_id => 0,
    461 return_mode => 'array_ref',
    461 462 );
    462 463 my $merge_to = $keeper->get_links (
    463 464 class => 'webshop::OrderCouponLink',
    464 465 uid => $opts{uid},
    465 466 source_id => 0,
    467 return_mode => 'hash_ref',
    468 hash_by => 'dest_id',
    469 );
    470 my $profile_coupons_session = $keeper->get_links (
    471 class => 'webshop::ProfileCouponLink',
    472 session => $opts{session},
    473 source_id => 0,
    466 474 return_mode => 'array_ref',
    467 475 );
    468 my %cids = map{ $_->dest_id => 1 } (@items, @$merge_to);
    469 my @cids = keys %cids;
    470 my $coupons = @cids ? $keeper->get_documents(
    471 class => 'webshop::Coupon',
    472 id => \@cids,
    476 my $profile_coupons_registered = $keeper->get_links (
    477 class => 'webshop::ProfileCouponLink',
    478 source_id => $opts{uid},
    473 479 return_mode => 'hash_ref',
    474 ) : {};
    475 my %merge_to;
    476 foreach my $link ( @$merge_to ) {
    477 my $coupon = $coupons->{$link->dest_id};
    478 if ( !ref $coupon || !$coupon->is_accessible($opts{session}) ) {
    479 $link->delete;
    480 } elsif ( exists $merge_to{$link->dest_id} ) {
    481 $link->delete;
    482 } else {
    483 $merge_to{$link->dest_id} = $link;
    480 hash_by => 'dest_id',
    481 );
    482
    483 ### Merge coupon-order links
    484 if ( ref $merge_from eq 'ARRAY' && @$merge_from ) {
    485 foreach my $link ( @$merge_from ) {
    486 if ( exists $merge_to->{$link->dest_id} ) {
    487 $link->delete;
    488 } else {
    489 $link->session( undef );
    490 $link->uid( $opts{uid} );
    491 $link->store;
    492 $merge_to->{$link->dest_id} = $link;
    493 }
    484 494 }
    485 495 }
    486 foreach my $item ( @items ) {
    487 my $coupon = $coupons->{$item->dest_id};
    488 if ( !ref $coupon || !$coupon->is_accessible($opts{session}) ) {
    489 $item->delete;
    490 } elsif ( exists $merge_to{$item->dest_id} ) {
    491 $item->delete;
    492 } else {
    493 $item->session( undef );
    494 $item->uid( $opts{uid} );
    495 $item->store;
    496
    497 ### Merge user-coupon links
    498 if ( ref $profile_coupons_session eq 'ARRAY' && @$profile_coupons_session ) {
    499 foreach my $link ( @$profile_coupons_session ) {
    500 if ( exists $profile_coupons_registered->{$link->dest_id} ) {
    501 $link->delete
    502 } else {
    503 $link->session( undef );
    504 $link->source_id( $opts{uid} );
    505 $link->store;
    506 $profile_coupons_registered->{$link->dest_id} = $link;
    507 }
    496 508 }
    497 509 }
    510
    511 my %cids = map { $_ => 1 } keys %$merge_to;
    512 foreach my $cid ( keys %$profile_coupons_registered ) {
    513 $cids{$cid} = 1;
    514 }
    515 my @cids = keys %cids;
    516
    517 if ( @cids ) {
    518 my $coupons = @cids ? $keeper->get_documents(
    519 class => 'webshop::Coupon',
    520 id => \@cids,
    521 return_mode => 'hash_ref',
    522 ) : {};
    523 foreach my $link ( values %$merge_to ) {
    524 unless ( exists $coupons->{$link->dest_id} ) {
    525 $link->delete;
    526 next;
    527 }
    528 my $coupon = $coupons->{$link->dest_id};
    529 if ( !ref $coupon || !$coupon->is_accessible($opts{session}) ) {
    530 $link->delete;
    531 }
    532 }
    533 foreach my $link ( values %$profile_coupons_registered ) {
    534 unless ( exists $coupons->{$link->dest_id} ) {
    535 $link->delete;
    536 next;
    537 }
    538 my $coupon = $coupons->{$link->dest_id};
    539 if ( !ref $coupon || !$coupon->is_accessible($opts{session}) ) {
    540 $link->delete;
    541 }
    542 }
    543 }
    544
    498 545 }
    499 546
    500 547
  • utf8/plugins/webshop/lib/webshop/ProfileCouponLink.pm

     
    1 package webshop::ProfileCouponLink;
    2
    3 use base 'Contenido::Link';
    4 use Contenido::Globals;
    5
    6 sub class_name
    7 {
    8 return 'Пользовательские купоны';
    9 }
    10
    11 sub class_description
    12 {
    13 return 'Купоны, принадлежащие пользователю';
    14 }
    15
    16 sub extra_properties
    17 {
    18 return (
    19 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус купона пользователя',
    20 'cases' => [
    21 [0, 'недействительный'],
    22 [1, 'действительный'],
    23 ],
    24 },
    25 );
    26 }
    27
    28 sub class_table
    29 {
    30 return 'webshop::SQL::ProfileCouponLinkTable';
    31 }
    32
    33 sub available_sources
    34 {
    35 return [ $state->{users}->profile_document_class ];
    36 }
    37
    38 sub available_destinations
    39 {
    40 return [ qw(webshop::Coupon) ];
    41 }
    42
    43 1;
  • utf8/plugins/webshop/lib/webshop/SQL/ProfileCouponLinkTable.pm

     
    1 package webshop::SQL::ProfileCouponLinkTable;
    2
    3 use base 'SQL::LinkTable';
    4 use Contenido::Globals;
    5
    6 sub db_table
    7 {
    8 return 'webshop_user_coupons';
    9 }
    10
    11 my $available_filters = [qw(
    12
    13 _class_filter
    14 _status_filter
    15 _in_id_filter
    16 _id_filter
    17 _name_filter
    18 _class_excludes_filter
    19 _excludes_filter
    20 _datetime_filter
    21 _date_equal_filter
    22 _date_filter
    23
    24 _dest_id_filter
    25 _source_id_filter
    26 _source_class_filter
    27 _dest_class_filter
    28
    29 _session_filter
    30 )];
    31
    32 sub available_filters {
    33 return $available_filters;
    34 }
    35
    36
    37 # ----------------------------------------------------------------------------
    38 # Свойства храним в массивах, потому что порядок важен!
    39 # Это общие свойства - одинаковые для всех документов.
    40 #
    41 # attr - обязательный параметр, название атрибута;
    42 # type - тип аттрибута, требуется для отображдения;
    43 # rusname - русское название, опять же требуется для отображения;
    44 # hidden - равен 1, когда
    45 # readonly - инициализации при записи только без изменения в дальнейшем
    46 # db_field - поле в таблице
    47 # default - значение по умолчанию (поле всегда имеет это значение)
    48 # ----------------------------------------------------------------------------
    49 sub required_properties
    50 {
    51 my $self = shift;
    52
    53 my @parent_properties = $self->SUPER::required_properties;
    54 return (
    55 @parent_properties,
    56 { # ID Сессии
    57 'attr' => 'session',
    58 'type' => 'string',
    59 'rusname' => 'ID Сессии пользователя',
    60 'db_field' => 'session',
    61 'db_type' => 'text',
    62 },
    63 );
    64 }
    65
    66 ########### FILTERS DESCRIPTION ###############################################################################
    67 sub _session_filter {
    68 my ($self,%opts)=@_;
    69 return undef unless ( exists $opts{session} );
    70 return &SQL::Common::_generic_text_filter('d.session', $opts{session});
    71 }
    72
    73 1;
  • utf8/plugins/webshop/sql/TOAST/user_coupons.sql

     
    1 CREATE TABLE webshop_user_coupons (
    2 id integer DEFAULT nextval(('public.documents_id_seq'::text)::regclass) NOT NULL,
    3 ctime timestamp without time zone DEFAULT now() NOT NULL,
    4 mtime timestamp without time zone DEFAULT now() NOT NULL,
    5 class text DEFAULT 'webshop::ProfileCouponLink'::text NOT NULL,
    6 status smallint default 0 NOT NULL,
    7 session text,
    8 source_id integer,
    9 source_class text,
    10 dest_id integer,
    11 dest_class text default 'webshop::Coupon'::text,
    12 data text
    13 );
    14
    15 CREATE INDEX webshop_user_coupons_session ON webshop_user_coupons USING btree (session) where session IS NOT NULL;
    16 CREATE UNIQUE INDEX webshop_user_coupons_in_order ON webshop_user_coupons USING btree (source_id, dest_id) where source_id > 0;
    17 create index webshop_user_coupons_source on webshop_user_coupons (source_id);
    18 create index webshop_user_coupons_dest on webshop_user_coupons (dest_id);