Committer: vtroitsky
LJSUP-11372: [Refactoring] Selfpromo cart item synchronously delivery logic localized in SelfPromo.pm U trunk/cgi-bin/LJ/Pay/Payment/PayItem/SelfPromo.pm U trunk/cgi-bin/LJ/Pay/SelfPromo.pm
Modified: trunk/cgi-bin/LJ/Pay/Payment/PayItem/SelfPromo.pm =================================================================== --- trunk/cgi-bin/LJ/Pay/Payment/PayItem/SelfPromo.pm 2012-03-30 13:19:59 UTC (rev 11660) +++ trunk/cgi-bin/LJ/Pay/Payment/PayItem/SelfPromo.pm 2012-03-30 14:29:54 UTC (rev 11661) @@ -38,7 +38,6 @@ return $view_ua_ratings; } - sub get_object { #return LJ::Pay::SelfPromo::Promo->create_from_item($self); my ($self) = @_; @@ -61,7 +60,7 @@ sub get_object_url { my ($self) = @_; - #my $promo_object = LJ::Pay::SelfPromo::Promo->create_from_item($self); + #my $promotion_object = LJ::Pay::SelfPromo::Promo->create_from_item($self); # return $promo_object->url; my $object = $self->get_object; @@ -93,19 +92,6 @@ return; } -#sub get_entry_url { -# my ($self) = @_; -# -# my $journalid = $self->get_prop('selfpromo_journalid'); -# my $ditemid = $self->get_prop('selfpromo_ditemid'); -# -# return unless $journalid && $ditemid; -# -# my $journal = LJ::load_userid($journalid); -# -# return $journal->journal_base . "/$ditemid.html"; -#} - sub get_product_name { my ($self) = @_; my $sp_type = $self->get_prop('selfpromo'); @@ -142,211 +128,8 @@ } sub _deliver_item { - my ( $self, $payment, $buyer_u, $rcpt_u, $note_rec_change ) = @_; - - LJ::Pay::SelfPromo->debug_msg("delivery of a selfpromo item requested"); - LJ::Pay::SelfPromo->debug_msg( "piid=" . $self->get_piid ); - -# TODO: Refactoring: Move most of that code have to be refactored more and to be moved into the LJ/Pay/SelfPromo* modules!, just put here necesasary functions calls - - # if we cannot get a lock straight away, let this be delivered later; - # resolves race condition with ljmaint.pl and webs trying to deliver - # the same item simultaneously - if ( LJ::Pay::SelfPromo->lock_taken_elsewhere ) { - LJ::Pay::SelfPromo->debug_msg( - "actually, another process got the lock, quitting"); - return; - } - - # this should be temporary until we l10n the shop - my $lang = ($rcpt_u && $rcpt_u->prop('browselang')) ? $rcpt_u->prop('browselang') : $LJ::DEFAULT_LANG; - my $ml = sub { - my ( $code, $params ) = @_; - return LJ::Lang::get_text( $lang, $code, undef, $params ); - }; - - - my $class_type = $self->get_prop('selfpromo'); - my $class = LJ::Pay::SelfPromo->get_class_by_type($class_type , (view_ua_ratings($buyer_u) ? 'ua' : 'cyr')); - - LJ::Pay::SelfPromo->debug_msg("acquiring the lock"); - my $lock = $class->lock; - LJ::Pay::SelfPromo->debug_msg("got the lock"); - - LJ::Pay::SelfPromo->debug_msg("checking the current entry"); - $class->check_current_promo; - LJ::Pay::SelfPromo->debug_msg("current entry checked"); - - my $type = $self->get_prop('selfpromo_type'); - - # if there's an entry being promoted, deactivate it, and - # then handle any refund if need be - # - # note that it also stays valid for admin or poster cancellations because they - # also only cancel the current promotion - my $promo; - my $object_url; - if ($promo = $class->current_promo_info(undef, 'require_db' => 1)) { - $object_url = $promo->object_url; - my $object = $promo->object; - - $class->deactivate_object( - 'object' => $object, - 'object_url' => $object_url, - 'reason' => 'buyout', - 'details' => $self->get_piid, - ); - - # Refund some tokens to previous promoter + send notifications - if ( my $refund_userid = $self->get_prop('selfpromo_refund_userid') ) { - - # my $promoid = $self->get_prop('selfpromo_refund_promoid'); - - my $refund_to = LJ::load_userid($refund_userid); - - # my $promo = LJ::Pay::SelfPromo->current_entry_info($promoid); - - my $refund = $self->get_prop('selfpromo_refund'); - if ($refund) { - LJ::Pay::SelfPromo->debug_msg("crediting them"); - - # credit them: - LJ::Pay::Wallet->try_add( $refund_to, $refund ); - LJ::Pay::Wallet::Log->log( - 'userid' => $refund_userid, - 'action' => LJ::Pay::Wallet::Log::ACTION_ADD, - 'qty' => $refund, - 'payid' => $self->get_payid, - 'piid' => $self->get_piid, - 'status' => LJ::Pay::Wallet::Log::STATUS_FINISHED, - 'time_end' => time, - ); - - LJ::Pay::SelfPromo->debug_msg("successfully credited"); - } - - # $object_url = $promo->entry_url; - - my $reason_map = { - 'buyout' => 'buyout', - 'admin_cancel' => 'admin', - 'owner_cancel' => 'owner', - }; - - # email them: - $class->send_notification( - $refund_to, 'deactivate', - 'reason' => $reason_map->{$type}, - 'object_url' => $object_url, - 'object' => $object, - 'owner' => $promo->owner, - 'refund_amount' => $refund, - 'duration' => time - $promo->started, - ); - - unless ( LJ::u_equals($promo->owner, $refund_to) ) { - $class->send_notification( - $promo->owner, 'deactivate', - 'reason' => $reason_map->{$type}, - 'object_url' => $object_url, - 'object' => $object, - 'refund_amount' => $refund, - 'duration' => time - $promo->started, - 'notify_owner' => 1, - ); - } - - LJ::Pay::SelfPromo->debug_msg("refund successful"); - } - } - - # if there's any 'remainder' tokens we need to send, go send them: - if ( my $remainder = $self->get_prop('selfpromo_remainder') ) { - my $remainder_to_userid = - $self->get_prop('selfpromo_remainder_userid'); - my $remainder_to = LJ::load_userid($remainder_to_userid); - - if ($remainder_to) { - LJ::Pay::SelfPromo->debug_msg( - "sending the remainder of tokens to " . - $remainder_to->username ); - - LJ::Pay::Wallet->try_add( $remainder_to, $remainder ); - LJ::Pay::Wallet::Log->log( - 'userid' => $remainder_to_userid, - 'action' => LJ::Pay::Wallet::Log::ACTION_ADD, - 'qty' => $remainder, - 'payid' => $self->get_payid, - 'piid' => $self->get_piid, - 'status' => LJ::Pay::Wallet::Log::STATUS_FINISHED, - 'time_end' => time, - ); - } - - } - - # now that we've handled all the deactivations, refunds, and remainders, - # we will need to determine if we need to activate anything, - # and what to email, which really depends on the item type - my ( $email_subject, $email_body ); - - if ( $type eq 'buyout' ) { - # my $entry = $self->get_entry; - my $object = $self->get_object; - my $owner = $self->get_object_owner; - my $object_url = $self->get_object_url; # New promo object URL - - my $cost = $self->get_amt * LJ::Pay::Wallet::EXCHANGE_RATE(); - $class->activate_object( $object, $cost, $rcpt_u ); - - $email_subject = $ml->("selfpromo.$class_type.notification.activate.subject"); - - LJ::Pay::SelfPromo->debug_msg("generating the emails"); - # Need to send second email if object owner and recipient are different - unless ( LJ::u_equals($owner, $rcpt_u) ) { - $email_body = $ml->( - "selfpromo.$class_type.notification.activate.body", - { 'user' => $owner->display_name, - 'object_url' => $object_url, - }, - ); - - LJ::send_mail( - { 'to' => $owner->email_raw, - 'from' => $LJ::DONOTREPLY_EMAIL, - 'fromname' => $LJ::SITENAME, - 'subject' => $email_subject, - 'body' => $email_body, - } - ); - } - - $email_body = $ml->( - "selfpromo.$class_type.notification.activate.body", - { 'user' => $rcpt_u->display_name, - 'object_url' => $object_url, - }, - ); - } - elsif ( $type eq 'admin_cancel' ) { - - # we don't need to activate anything, but the admin - # gets notified that everything was cancelled - # successfully - - $email_subject = $ml->("selfpromo.$class_type.notification.admin_cancel.subject"); - - $email_body = $ml->( - "selfpromo.$class_type.notification.admin_cancel.body", - { 'user' => $rcpt_u->display_name, - 'object_url' => $promo ? $object_url : '', - }, - ); - } - - LJ::Pay::SelfPromo->debug_msg("delivery successful"); - - return ( 1, $email_subject, $email_body ); + # We've already delivered that item in LJ/Pay/* packages + return (1, undef, undef); } 1; Modified: trunk/cgi-bin/LJ/Pay/SelfPromo.pm =================================================================== --- trunk/cgi-bin/LJ/Pay/SelfPromo.pm 2012-03-30 13:19:59 UTC (rev 11660) +++ trunk/cgi-bin/LJ/Pay/SelfPromo.pm 2012-03-30 14:29:54 UTC (rev 11661) @@ -73,7 +73,7 @@ ### HIGH LEVEL INTERFACE ### # NOTE: ALL FUNCTIONS HERE HAVE TO PERFORM EXCLUSIVE MODE OPERATIONS !# -# TODO: specify promo_type +# TODO: specify promo_type : pass slot object sub buyout_cost { my ($class) = @_; @@ -93,6 +93,12 @@ Check that specified object is eligible to promote: As object may be considered: entries and users (entries and communities) Have to be overriden in childs + + REFACTOR: + 1. create PromotedObject object from passed object (or use them if it's already passed) + 2. call $promoted->is_eligible($promoter) + 3. Ensure that object isn't currently promoted in all promos!!! + =cut sub is_object_eligible { my ($class, $object, $promoter, $reason_ref) = @_; @@ -120,6 +126,16 @@ =item buyout Function to make a bid: core logic is implemented here TODO: remove specific logic to subfunctions + REFACTOR: (pass slot) + 1. Slot and PromotedObject passed + 2. Gain lock + 3. call is_object_eligible(slot,object,promoter) + 4. check price + 5. check promoter balance + 6. create cart and pay for them + 7. deliver cart (send notifications & refund) + 8. Update history + =cut sub buyout { my ( $class, $object, $promoter, $price ) = @_; @@ -247,6 +263,8 @@ # Perform deliver: deactivate previous selfpromo object / return money to the previous promoter / create new promotion object + $class->_deliver_item($item, $promoter); + LJ::Pay::SelfPromo->debug_msg( "cart and item updated to be ready for delivery"); @@ -261,6 +279,7 @@ $class->debug_msg("delivery failed"); die "delivering item failed, see error log for details"; } + $cart->mark_complete; }; LJ::Pay::SelfPromo->debug_msg("all done"); @@ -272,7 +291,230 @@ } +=item _deliver_item + Deliver cart item +=cut +sub _deliver_item { + my ($class, $item, $rcpt_u) = @_; + + LJ::Pay::SelfPromo->debug_msg("delivery of a selfpromo item requested"); + LJ::Pay::SelfPromo->debug_msg( "piid=" . $item->get_piid ); + +# TODO: Refactoring: Move most of that code have to be refactored more and to be moved into the LJ/Pay/SelfPromo* modules!, just put here necesasary functions calls + + # if we cannot get a lock straight away, let this be delivered later; + # resolves race condition with ljmaint.pl and webs trying to deliver + # the same item simultaneously + #if ( LJ::Pay::SelfPromo->lock_taken_elsewhere ) { + # LJ::Pay::SelfPromo->debug_msg( + # "actually, another process got the lock, quitting"); + # return; + #} + + # this should be temporary until we l10n the shop + my $lang = ($rcpt_u && $rcpt_u->prop('browselang')) ? $rcpt_u->prop('browselang') : $LJ::DEFAULT_LANG; + my $ml = sub { + my ( $code, $params ) = @_; + return LJ::Lang::get_text( $lang, $code, undef, $params ); + }; + + # my $class = LJ::Pay::SelfPromo->get_class_by_type($class_type , (view_ua_ratings($promoter) ? 'ua' : 'cyr')); + my $object_type = $class->type; + + #LJ::Pay::SelfPromo->debug_msg("acquiring the lock"); + #my $lock = $class->lock; + # LJ::Pay::SelfPromo->debug_msg("got the lock"); + + #LJ::Pay::SelfPromo->debug_msg("checking the current entry"); + #$class->check_current_promo; + #LJ::Pay::SelfPromo->debug_msg("current entry checked"); + + my $type = $item->get_prop('selfpromo_type'); # action type + + LJ::Pay::SelfPromo->debug_msg("type = $type, object_type = $object_type, class = $class"); + # if there's an entry being promoted, deactivate it, and + # then handle any refund if need be + # + # note that it also stays valid for admin or poster cancellations because they + # also only cancel the current promotion + my $promo; + my $object_url; + if ($promo = $class->current_promo_info(undef, 'require_db' => 1)) { + + LJ::Pay::SelfPromo->debug_msg("current PROMO received"); + $object_url = $promo->object_url; + my $object = $promo->object; + + $class->deactivate_object( + 'object' => $object, + 'object_url' => $object_url, + 'reason' => 'buyout', + 'details' => $item->get_piid, + ); + + # Refund some tokens to previous promoter + send notifications + if ( my $refund_userid = $item->get_prop('selfpromo_refund_userid') ) { + + # my $promoid = $item->get_prop('selfpromo_refund_promoid'); + + my $refund_to = LJ::load_userid($refund_userid); + + # my $promo = LJ::Pay::SelfPromo->current_entry_info($promoid); + + my $refund = $item->get_prop('selfpromo_refund'); + if ($refund) { + LJ::Pay::SelfPromo->debug_msg("crediting them"); + + # credit them: + LJ::Pay::Wallet->try_add( $refund_to, $refund ); + LJ::Pay::Wallet::Log->log( + 'userid' => $refund_userid, + 'action' => LJ::Pay::Wallet::Log::ACTION_ADD, + 'qty' => $refund, + 'payid' => $item->get_payid, + 'piid' => $item->get_piid, + 'status' => LJ::Pay::Wallet::Log::STATUS_FINISHED, + 'time_end' => time, + ); + + LJ::Pay::SelfPromo->debug_msg("successfully credited"); + } + + # $object_url = $promo->entry_url; + + my $reason_map = { + 'buyout' => 'buyout', + 'admin_cancel' => 'admin', + 'owner_cancel' => 'owner', + }; + + # email them: + $class->send_notification( + $refund_to, 'deactivate', + 'reason' => $reason_map->{$type}, + 'object_url' => $object_url, + 'object' => $object, + 'owner' => $promo->owner, + 'refund_amount' => $refund, + 'duration' => time - $promo->started, + ); + + unless ( LJ::u_equals($promo->owner, $refund_to) ) { + $class->send_notification( + $promo->owner, 'deactivate', + 'reason' => $reason_map->{$type}, + 'object_url' => $object_url, + 'object' => $object, + 'refund_amount' => $refund, + 'duration' => time - $promo->started, + 'notify_owner' => 1, + ); + } + + LJ::Pay::SelfPromo->debug_msg("refund successful"); + } + } + + # if there's any 'remainder' tokens we need to send, go send them: + if ( my $remainder = $item->get_prop('selfpromo_remainder') ) { + my $remainder_to_userid = + $item->get_prop('selfpromo_remainder_userid'); + my $remainder_to = LJ::load_userid($remainder_to_userid); + + if ($remainder_to) { + LJ::Pay::SelfPromo->debug_msg( + "sending the remainder of tokens to " . + $remainder_to->username ); + + LJ::Pay::Wallet->try_add( $remainder_to, $remainder ); + LJ::Pay::Wallet::Log->log( + 'userid' => $remainder_to_userid, + 'action' => LJ::Pay::Wallet::Log::ACTION_ADD, + 'qty' => $remainder, + 'payid' => $item->get_payid, + 'piid' => $item->get_piid, + 'status' => LJ::Pay::Wallet::Log::STATUS_FINISHED, + 'time_end' => time, + ); + } + + } + + # now that we've handled all the deactivations, refunds, and remainders, + # we will need to determine if we need to activate anything, + # and what to email, which really depends on the item type + my ( $email_subject, $email_body ); + + if ( $type eq 'buyout' ) { + my $object = $item->get_object; + my $owner = $item->get_object_owner; + my $object_url = $item->get_object_url; # New promo object URL + my $cost = $item->get_amt * LJ::Pay::Wallet::EXCHANGE_RATE(); + $class->activate_object( $object, $cost, $rcpt_u ); + + $email_subject = $ml->("selfpromo.$object_type.notification.activate.subject"); + + LJ::Pay::SelfPromo->debug_msg("generating the emails"); + # Need to send second email if object owner and recipient are different + unless ( LJ::u_equals($owner, $rcpt_u) ) { + $email_body = $ml->( + "selfpromo.$object_type.notification.activate.body", + { 'user' => $owner->display_name, + 'object_url' => $object_url, + }, + ); + + LJ::send_mail( + { 'to' => $owner->email_raw, + 'from' => $LJ::DONOTREPLY_EMAIL, + 'fromname' => $LJ::SITENAME, + 'subject' => $email_subject, + 'body' => $email_body, + } + ); + } + + $email_body = $ml->( + "selfpromo.$object_type.notification.activate.body", + { 'user' => $rcpt_u->display_name, + 'object_url' => $object_url, + }, + ); + } + elsif ( $type eq 'admin_cancel' ) { + + # we don't need to activate anything, but the admin + # gets notified that everything was cancelled + # successfully + + $email_subject = $ml->("selfpromo.$object_type.notification.admin_cancel.subject"); + + $email_body = $ml->( + "selfpromo.$object_type.notification.admin_cancel.body", + { 'user' => $rcpt_u->display_name, + 'object_url' => $promo ? $object_url : '', + }, + ); + } + + + if ($email_subject && $email_body) { + LJ::send_mail( + { 'to' => $rcpt_u->email_raw, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'subject' => $email_subject, + 'body' => $email_body, + 'wrap' => 1, + 'charset' => 'utf-8', + } + ); + } + + LJ::Pay::SelfPromo->debug_msg("delivery successful"); +} + =item admin_cancel_promo Admin function to cancel current promo =cut @@ -291,7 +533,6 @@ # && $promo->journalid == $entry->journalid # && $promo->jitemid == $entry->jitemid ) { - # your princess is in another castle, sorry # TODO: return an error return; @@ -357,7 +598,12 @@ $cart->update( 'used' => 'Y' ); $item->update( 'status' => 'pend' ); + + $class->_deliver_item($item, $admin); + $item->deliver( $item->get_cart, time, sub { } ); + + $cart->mark_complete(); }; return 1; @@ -371,7 +617,7 @@ return unless $object; # TODO: Acquire lock to perform cancelling! - # my $lock = $class->lock; + my $lock = $class->lock; # TODO: Perform error processing when lock couldn't be acquired during default timeout, 10s my $promo = $class->current_promo_info( undef, 'require_db' => 1 ); @@ -425,12 +671,20 @@ $cart->update( 'used' => 'Y' ); $item->update( 'status' => 'pend' ); + + $class->_deliver_item($item, $owner); + $item->deliver( $item->get_cart, time, sub { } ); + $cart->mark_complete; + return 1; } # Remote / promoter itself cancel promotion without refunding -#sub withdraw_entry { +# REFACTORING: +# 1. Pass slot +# 2. + sub withdraw_object { my ( $class, $object ) = @_; @@ -937,6 +1191,8 @@ my $cart = LJ::Pay::Payment::new_cart( $opts->{'cart_owner'} ); + $cart->payvar_append('do_not_notify_recepient',1); + my $it = LJ::Pay::Payment::PayItem->new_memonly( 'item' => 'selfpromo', 'subitem' => '',