Revision 853
- Date:
- 2026/08/20 23:19:58
- Files:
-
- /utf8/plugins/webshop/lib/webshop/Init.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Keeper.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/ProfileCouponLink.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/SQL/ProfileCouponLinkTable.pm (Diff) (Checkout)
- /utf8/plugins/webshop/sql/TOAST/user_coupons.sql (Diff) (Checkout)
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);