Committer: vtroitsky
LJSUP-12356: Remove not working subs from SelfPromo.pm [final refactoring stage cleaning old stuff]U trunk/cgi-bin/LJ/Pay/SelfPromo.pm
Modified: trunk/cgi-bin/LJ/Pay/SelfPromo.pm =================================================================== --- trunk/cgi-bin/LJ/Pay/SelfPromo.pm 2012-05-28 08:44:30 UTC (rev 12017) +++ trunk/cgi-bin/LJ/Pay/SelfPromo.pm 2012-05-28 10:21:00 UTC (rev 12018) @@ -12,13 +12,6 @@ #use LJ::Pay::SelfPromo::Lock; #use LJ::Pay::SelfPromo::Error; -#use LJ::Pay::SelfPromo::EntryPromo; -#use LJ::Pay::SelfPromo::JournalPromo; -#use LJ::Pay::SelfPromo::CommunityPromo; -#use LJ::Pay::SelfPromo::EntryPromoUA; -#use LJ::Pay::SelfPromo::JournalPromoUA; -#use LJ::Pay::SelfPromo::CommunityPromoUA; - use Sys::Hostname qw(); use Exporter; @@ -43,42 +36,14 @@ use constant $errors; -my %classes_map = ( -'cyr' => { - 'entry' => 'LJ::Pay::SelfPromo::EntryPromo', - 'community' => 'LJ::Pay::SelfPromo::CommunityPromo', - 'journal' => 'LJ::Pay::SelfPromo::JournalPromo', -}, -'ua' => { - 'entry' => 'LJ::Pay::SelfPromo::EntryPromoUA', - 'community' => 'LJ::Pay::SelfPromo::CommunityPromoUA', - 'journal' => 'LJ::Pay::SelfPromo::JournalPromoUA', -}, -); - my %objects_map = ( 'entry' => 'entry', 'community' => 'community', 'journal' => 'journal', ); -sub old_type { 'entry' } -sub old_class { 'entry' }; # TODO: remove that function from base SelfPromo class -sub old_country {''} - sub class { PROMO_SELF() } -sub old_get_class_by_type { - my ($class, $type, $country) = @_; - $country ||= 'cyr'; - return $classes_map{$country}{$type}; -} - -sub old_get_object_by_type { - my ($class, $type) = @_; - return $objects_map{$type}; -} - ### HIGH LEVEL INTERFACE ### # NOTE: ALL FUNCTIONS HERE HAVE TO PERFORM EXCLUSIVE MODE OPERATIONS !# sub buyout_cost { @@ -88,22 +53,7 @@ } return $slot->config->{'min_cost'}; # return minimal price } - -sub old_buyout_cost { - my ($class) = @_; - if ( my $promo = $class->current_promo_info( undef, 'require_db' => 1 ) ) { # changed to current_promo_info - - # there actually is a promoted entry right now, so let's - # return however much its author paid for it plus the bidding step - - return $promo->cost + $LJ::SELF_PROMO_CONF->{$class->class}{'step'}; - } - - return $LJ::SELF_PROMO_CONF->{$class->class}{'min_cost'}; -} - - =item is_object_eligible Check that specified object is eligible to promote: As object may be considered: entries and users (entries and communities) @@ -135,29 +85,6 @@ return 1; } -sub old_is_object_eligible { - my ($class, $object, $promoter, $reason_ref) = @_; - my $type = ref $object; - - unless ($type) { - $$reason_ref = 'unknown_object'; - } - - if ($type eq 'LJ::Entry') { - # LJ::Entry promo - return $class->is_entry_eligible($object, $promoter, $reason_ref); - } elsif ($type eq 'LJ::User') { - # LJ::User promo - if ($object->is_community) { - return $class->is_community_eligible($object, $promoter, $reason_ref); - } else { - return $class->is_journal_eligible($object, $promoter, $reason_ref); - } - } else { - $$reason_ref = 'unknown_object'; - } -} - =item buyout Function to make a bid: core logic is implemented here TODO: remove specific logic to subfunctions @@ -172,7 +99,6 @@ 8. Update history =cut - sub buyout { my ( $class, $slot, $promoted_object, $promoter, $price ) = @_; @@ -333,160 +259,6 @@ return $cart; } -sub old_buyout { - my ( $class, $object, $promoter, $price ) = @_; - - # Acquire the lock to process buyout exclusive! - # If lock is not acquired during TIMEOUT period, system wide default value 10s, then exception raised. - - # TODO: Translate exception to SelfPromo Error! - my $lock = $class->lock; # actually use the lock specific for that class, lock() - - $class->raise_error( ERROR_BIDS_HAVE_CHANGED ) unless $lock; - - ## check object that we are going to promote - do { - my $reason; - unless ( $class->is_object_eligible( $object, $promoter, \$reason ) ) { - $class->raise_error( ERROR_OBJECT_INELIGIBLE, $reason ); # TODO: fix error messages, make it class specific - } - }; - - ## check price - do { - my $price_additional = $price - $LJ::SELF_PROMO_CONF->{$class->class()}{'min_cost'}; - if ( $price_additional % $LJ::SELF_PROMO_CONF->{$class->class()}{'step'} ) { - $class->raise_error(ERROR_INVALID_PRICE); - } - - my $min_price = $class->buyout_cost( 'require_db' => 1 ); - unless ( $price >= $min_price ) { - LJ::Pay::SelfPromo->debug_msg( - "not enough money offered, need at least $min_price"); - - $class->raise_error( ERROR_PRICE_INSUFFICIENT, $min_price ); - } - - my $wallet_balance = int LJ::Pay::Wallet->get_user_balance($promoter); - unless ( $wallet_balance >= $price ) { - LJ::Pay::SelfPromo->debug_msg( - "promoter doesn't actually have that much " . - "(has $wallet_balance, tried to buy out for $price)" - ); - - $class->raise_error( ERROR_WALLET_INSUFFICIENT_FUNDS, - $wallet_balance ); - } - }; - - # create a cart and pay for it from the user's balance; - # this may throw a wallet exception - my $cart; - do { - - LJ::Pay::SelfPromo->debug_msg("creating the cart"); - - # calculate how much money goes where for this item: - # a part of it goes to the system, a part of it goes to the - # user who purchased the selfpromo that was running before the - # buyout, and a part of it is a rounding error that - # goes to a special account made for these purposes - my ( $refund, $refund_promoid, $refund_userid ) = ( 0, 0, 0 ); - if ( my $promo = $class->current_promo_info( undef, 'require_db' => 1 ) ) { - $refund = $class->calculate_refund($promo); - $refund_promoid = $promo->promoid; - $refund_userid = $promo->promoterid || $promo->posterid; # TODO: Have to remove posterid, implement it inside $promo object - } - - my $refund_remainder = - $refund % $LJ::SELF_PROMO_CONF->{$class->class()}{'refund_step'}; - my $refund_rounded = $refund - $refund_remainder; - my $profit = $price - $refund; - - my $remainder_to = - LJ::load_user( $LJ::SELF_PROMO_CONF->{$class->class()}{'remainder_receiver'} ); - my $remainder_userid = $remainder_to ? $remainder_to->userid : 0; - - $cart = $class->create_shop_cart( - { - 'cart_owner' => $promoter, - 'object' => $object, - 'price' => $price, - 'profit' => $profit, - 'rcptid' => $promoter->userid, - 'refund' => $refund_rounded, - 'refund_userid' => $refund_userid, - 'refund_promoid' => $refund_promoid, - 'remainder' => $refund_remainder, - 'remainder_userid' => $remainder_userid, - 'type' => 'buyout', - } - ); - - LJ::Pay::SelfPromo->debug_msg("cart created, setting the method"); - - # Take the money from the promoter - $cart->set_method( LJ::Pay::Method::Wallet->code ); - - LJ::Pay::SelfPromo->debug_msg("paying for the cart"); - LJ::Pay::Wallet->pay_for_cart( $cart->get_payid ); - LJ::Pay::SelfPromo->debug_msg("paid successfully"); - # TODO: Catch exceptions from wallet operations!!! - - }; - - # deliver the cart synchronously, so that changes are applied - # immediately; we can do that because you can't schedule - # a selfpromo - # - # this part isn't supposed to throw any exceptions because - # all the checks have been done before - - # NOTES: - # 1. There might not be enought LJ tokens in the user's wallet, at the moment when transaction begins. - # 2. - - do { - $class->debug_msg("delivering the cart/items"); - $class->debug_msg( "payid=" . $cart->get_payid ); - - my ($item) = $cart->get_items; - - LJ::Pay::SelfPromo->debug_msg( "piid=" . $item->get_piid ); - - $cart->update( 'used' => 'Y' ); - $item->update( 'status' => 'pend' ); - - # 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"); - - local $SIG{'__WARN__'} = sub { - my @messages = @_; - $class->debug_msg( "delivery warning: ", @messages ); - warn @messages; - }; - - my $deliver_res = $item->deliver( $cart, time, sub { } ); - unless ($deliver_res) { - $class->debug_msg("delivery failed"); - die "delivering item failed, see error log for details"; - } - $cart->mark_complete; - }; - - LJ::Pay::SelfPromo->debug_msg("all done"); - - # Update history ??? - LJ::Pay::SelfPromo::History->update(); - - return $cart; -} - - =item _deliver_item Actually perform all specific actions to cancel/refuns previous promo Parameters: @@ -511,8 +283,6 @@ my $type = $item->get_prop('selfpromo_type'); # action type - LJ::Pay::SelfPromo->debug_msg( "TEST" ); - 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 @@ -690,208 +460,6 @@ LJ::Pay::SelfPromo->debug_msg("delivery successful"); } -sub _old_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 - - # 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 $object_type = $class->type; - - 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 @@ -986,97 +554,6 @@ return 1; } -sub old_admin_cancel_promo { - my ( $class, %args ) = @_; - - my $object = $args{'object'}; - my $admin = $args{'admin'}; - - # TODO: Acquire lock to perform cancel action! - my $lock = $class->lock; - # TODO: Perform lock timeout processing - - my $promo = $class->current_promo_info( undef, 'require_db' => 1 ); - unless ( $promo && $promo->is_promoting($object)) # TODO: Implement function to compare specified object with current promoted one -# && $promo->journalid == $entry->journalid -# && $promo->jitemid == $entry->jitemid ) - { - # your princess is in another castle, sorry - # TODO: return an error - return; - } - - # create a cart and set it as free, and then mark it as pending - # delivery - my $cart; - do { - - # calculate how much money goes where for this item: - # none it goes to the system, a part of it goes to the - # user who purchased the selfpromo being cancelled, - # and a part of it is a rounding error that goes to a - # special account made for these purposes - my $refund = 0; - if ( $args{'refund'} ) { - $refund = $class->calculate_refund($promo); - } - - my $refund_promoid = $promo->promoid; - my $refund_userid = $promo->promoterid || $promo->posterid; # TODO: remote posterid inside $promo object - - my $refund_remainder = - $refund % $LJ::SELF_PROMO_CONF->{$class->class()}{'refund_step'}; - my $refund_rounded = $refund - $refund_remainder; - - my $remainder_to = - LJ::load_user( $LJ::SELF_PROMO_CONF->{$class->class()}{'remainder_receiver'} ); - my $remainder_userid = $remainder_to ? $remainder_to->userid : 0; - - $cart = $class->create_shop_cart( - { - 'cart_owner' => $admin, - 'object' => undef, - 'price' => 0, - 'profit' => 0, - 'rcptid' => $admin->userid, - 'refund' => $refund_rounded, - 'refund_userid' => $refund_userid, - 'refund_promoid' => $refund_promoid, - 'remainder' => $refund_remainder, - 'remainder_userid' => $remainder_userid, - 'type' => 'admin_cancel', - } - ); - - # mark this cart as paid for - $cart->set_method( LJ::Pay::Method::Free->code ); - $cart->update( 'used' => 'N', 'mailed' => 'N' ); - $cart->set_daterecv_epoch(time); - }; - - # deliver the cart synchronously, so that changes are applied - # immediately; we can do that because you can't schedule - # a selfpromo - # - # this part isn't supposed to throw any exceptions because - # all the checks have been done before - - do { - my ($item) = $cart->get_items; - - $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; -} - # owner of the promoted object cancel promotion with refunding to the promotera # obsolete sub owner_cancel_promo { # the name of the function has been changed from poster_cancel_promo @@ -1089,10 +566,7 @@ # TODO: Perform error processing when lock couldn't be acquired during default timeout, 10s my $promotion = $class->current_promotion( $slot, 'require_db' => 1 ); - use Data::Dumper; - # warn "CP:".Dumper($promotion); - unless ( $promotion && $promotion->is_promoting($promoted_object) ) { # your princess is in another castle, sorry @@ -1220,10 +694,8 @@ return 1; } + # Remote / promoter itself cancel promotion without refunding -# REFACTORING: -# 1. Pass slot -# 2. sub withdraw_object { my ( $class, $slot, $promoted_object ) = @_; @@ -1303,103 +775,7 @@ return 1; } -sub old_withdraw_object { - my ( $class, $object ) = @_; - - # TODO? : Acquire lock to perform cancelling operation on selfpromo - # TODO: Add errors processing in case of not acquiring lock during default timeout. - my $lock = $class->lock; - # So we are actually here in case we've got lock successfully!!! - - my $promo = $class->current_promo_info( undef, 'require_db' => 1 ); - return unless $promo; # do nothing & return undef in case of - - my $owner = $promo->owner; # get the owner if the cucrrently promoted object - my $promoter = $promo->promoter; # get the promoter object - my $object_url = $promo->object_url; - - # TODO??? : return undef is better? - # TODO: Here better raise common error - die 'promoted object mismatch' - unless $promo && $promo->is_promoting($object); -# $promo->journalid == $entry->journalid -# && $promo->jitemid == $entry->jitemid; - - unless ( LJ::u_equals($owner, $promoter) ) { - - my $remote = LJ::get_remote(); # TODO: To remove dependency from remote user !!! - - # Owner cancels promo, need to pay refund to promoter - unless ( LJ::u_equals($remote, $promoter) ) { - # Req: $owner == $remote - # Notifications will be sent via shop - # TODO: ensure $owner == $remote , it's not obvious from conditions, it has to be concluded! - -# return $class->owner_cancel_promo($object); - - # send notifications to the promoter (owner cancelled) - $class->send_notification( - $promoter, 'deactivate', - 'reason' => 'owner', - 'object_url' => $object_url, - 'object' => $object, - 'owner' => $owner, - 'duration' => time - $promo->started, - ); - - # send notification to the owner itself (owner cancelled) - $class->send_notification( - $promo->owner, 'deactivate', - 'reason' => 'owner', - 'object_url' => $object_url, - 'object' => $object, - 'duration' => time - $promo->started, - 'notify_owner' => 1, - ); - - $class->deactivate_promo( - $promo->promoid, $promoter, - 'reason' => 'withdraw', - 'object' => $object, - 'object_url' => $object_url, - ); - return 1; - - } else { - $class->send_notification( # send notification to the owner of the promoted object - $owner, 'deactivate', - 'reason' => 'withdraw', -# 'entry_url' => $entry->url, # It's object name actually - 'object_url' => $object_url, - 'duration' => $promo->exptime - $promo->started, -# 'notify_poster' => 1, - 'notify_owner' => 1, - ); - } - } - - # Send notification to promoter - $class->send_notification( - $promoter, 'deactivate', - 'reason' => 'withdraw', - 'object_url' => $object_url, -# 'entry_url' => $entry->url, - 'duration' => $promo->exptime - $promo->started, - ); - - $class->deactivate_promo( - $promo->promoid, $promoter, - 'reason' => 'withdraw', -# 'entry' => $entry, -# 'entry_url' => $entry->url, - 'object' => $object, - 'object_url' => $object_url, - ); - - return 1; - } - # return current promoted object: # So it might be: entry / journal / community sub current_promoted_object { @@ -1409,18 +785,9 @@ return $promotion->promoted_object; } -sub old_current_promoted_object { - my ($class, %opts) = @_; - my $promo = $class->current_promo_info(undef, %opts); - return unless $promo; - return $promo->object; -} - # Check that current promo can still be active # deactivate it: depending on cases -#sub check_current_entry { # Called from worker - sub check_current_promotion { my ($class, $slot) = @_; @@ -1511,121 +878,6 @@ } } -sub old_check_current_promo { - my ($class) = @_; - - # Acquire lock to exclusive change promotion status - # TODO: Perform error processing in case we can't acquire the lock during default timeout. - my $lock = $class->lock; - # return unless $lock; - - my $promo = $class->current_promo_info( undef, 'require_db' => 1 ); - return unless $promo; # everything's fine if nothing's promoted - - my $object = $promo->object; # promoted object: entry / user(community/journal) - my $owner = $promo->owner; # owner of the promoted object: user - my $promoter = $promo->promoter; # promoter: user - my $object_url = $promo->object_url; - - if ($promo->is_object_deleted) { - - # we no longer have an entry because it's been deleted, - # so let's reconstruct the URL => get it from promo object - - $class->deactivate_promo( - $promo->promoid, $promoter, - 'reason' => 'deleted', - # 'entry_url' => $entry_url, - 'object_url' => $object_url, - 'promo' => $promo, - 'promoinfo' => $promo, - ); - - $class->send_notification( - $promoter, 'deactivate', - 'reason' => 'deleted', - # 'entry_url' => $entry->url, - 'object_url' => $object_url, - 'duration' => time - $promo->started, - ); - - unless ( LJ::u_equals($owner, $promoter) ) { - $class->send_notification( - $owner, 'deactivate', - 'reason' => 'deleted', - # 'entry_url' => $entry->url, - 'object_url' => $object_url, - 'duration' => time - $promo->started, - # 'notify_poster' => 1, - 'notify_owner' => 1, - ); - } - } - - my $reason; - - unless ( $class->is_object_eligible( $object, $promoter, \$reason ) ) { - $class->deactivate_object( - # 'entry' => $entry, - 'object' => $object, - 'object_url' => $object_url, - 'reason' => 'ineligible', - 'details' => $reason, - ); - - $class->send_notification( - $promoter, 'deactivate', - 'reason' => 'ineligible', - 'details' => $reason, - # 'entry' => $entry, - # 'entry_url' => $entry->url, - 'object_url' => $object_url, - 'duration' => time - $promo->started, - ); - - unless ( LJ::u_equals($owner, $promoter) ) { - $class->send_notification( - $owner, 'deactivate', - 'reason' => 'ineligible', - 'details' => $reason, - # 'entry' => $entry, - # 'entry_url' => $entry->url, - 'object_url' => $object_url, - 'duration' => time - $promo->started, - 'notify_owner' => 1, - ); - } - } - - unless ( $promo->exptime > time ) { - $class->deactivate_object( #'entry' => $entry, - 'object' => $object, - 'object_url' => $object_url, - 'reason' => 'expired' ); - - $class->send_notification( - $promoter, 'deactivate', - 'reason' => 'expired', - # 'entry' => $entry, - # 'entry_url' => $entry->url, - 'object_url' => $object_url, - 'duration' => time - $promo->started, - ); - - unless ( LJ::u_equals($owner, $promoter) ) { - $class->send_notification( - $owner, 'deactivate', - 'reason' => 'expired', - # 'entry' => $entry, - # 'entry_url' => $entry->url, - 'object_url' => $object_url, - 'duration' => time - $promo->started, - 'notify_owner' => 1, - ); - } - } -} - ### LOW LEVEL INTERFACE ### # BEWARE NOTE: All functions here don't perform exclusive operations, no locks and mutexes! @@ -1681,178 +933,6 @@ } -# return object LJ::Pay::SelfPromo::Promo, make subclasses? -sub old_current_promo_info { - my ($class, $promoid, %opts) = @_; - - unless ($promoid) { - my $from_memcache; - - unless ( $opts{'require_db'} ) { - $from_memcache = LJ::MemCache::get( $class->memcache_key ); - } - - # from_memcache = undef means there's nothing in memcache - # (or it's disabled in the options), so we need to hit DB; - # from_memcache = 0 means 'no current entry'; - # from_memcache = HASH(0xDEADBEEF) means bless it and return - if ( defined $from_memcache ) { - return unless $from_memcache; - return LJ::Pay::SelfPromo::Promo->new($from_memcache); - } - - - my $rows = $class->find_promos( # perform select for class specific rows - { 'require_active' => 1, 'return_rows' => 1 } ); - - unless ($rows && @$rows) { - LJ::MemCache::set( $class->memcache_key, 0, 1800 ); - return; - } - - unless ( @$rows == 1 ) { - warn 'more than 1 entry in selfpromo, data corrupt?'; - } - - my $row = $rows->[0]; - LJ::MemCache::set( $class->memcache_key, $row, 1800 ); - return LJ::Pay::SelfPromo::Promo->new($row); - } - - return do { - my $promos = $class->find_promos( { 'promoid' => $promoid } ); - - return unless @$promos; - return $promos->[0]; - }; - -} - -# this one pretty much tries to satisfy the PayItem's needs: -# -# * it dies if we're trying to replace an active entry in promo -# * it doesn't send any notifications -# -# called from LJ::Pay::Payment::PayItem::SelfPromo - -# Actually creates new selfpromo object / active row in DBa -sub old_activate_object { - my ( $class, $object, $cost, $promoter ) = @_; - - # ????: Before activate the new object, check current promo???? gain lock ??? - $class->check_current_promo; - - if ( my $object_promoted = $class->current_promoted_object( 'require_db' => 1 )) { - # this is an abnormal case, that's why the exception is stringly-typed - - # my $entry_url = $entry->url; - # my $promoted_url = $entry_promoted->url; - # die - # "cannot promote $entry_url because $promoted_url is already there"; - } - -# Possible remove all operations with DB into SelfPromo::Promo object ? -# my $promo = LJ::Pay::SelfPromo::Promo->create( -# 'object' => $object, -# 'started' => time, -# 'exptime' => time + $LJ::SELF_PROMO_CONF->{$class->class()}{'duration'}, -# 'cost' => $cost, -# 'promoterid' => $promoter->userid, # promoter have to be defined! -# 'type' => $class->type, -# ); - -# or (better) -# $promo_object->activate(); - -# TODO: Move that to SelfPromo::Promo class, make it constructor - - $class->db_insert_promo( - - # TODO: Entry specific code (move into Promo object creation) - $class->class eq 'entry' ? ( - 'journalid' => $object->journalid, # common - 'posterid' => $object->posterid, # entry specific - - 'jitemid' => $object->jitemid, # entry specific - 'ditemid' => $object->ditemid, # entry specific - ) : ( - 'journalid' => $object->{userid}, # journal / community - 'posterid' => $object->{userid}, # journal / - 'jitemid' => 0, - 'ditemid' => 0, - ), - 'started' => time, - 'exptime' => time + $LJ::SELF_PROMO_CONF->{$class->class()}{'duration'}, - 'cost' => $cost, - 'promoterid' => $promoter->userid, # promoter have to be defined! - ); - -# $class->clear_memcache($object->posterid, $object->ditemid); - - $class->clear_memcache($object); # First read op go to DB - - $class->log( - $promoter, - # 'entry_url' => $entry->url, - 'object_url' => ($class->class eq 'entry' ? $object->url : $object->journal_base), #$promo->object_url, TODO: Entry specific!!!!! - 'object' => $object, - 'event' => 'activate', - ); -} - -# supported opts: reason, details, object, refund -# -# called from LJ::Pay::Payment::PayItem::SelfPromo -sub old_deactivate_object { - my ( $class, %opts ) = @_; - - my $promo = $class->current_promo_info(undef, 'require_db' => 1); - my $object = $opts{'object'}; - - # Ensure we deactivate active object only! - # Just take the active object and do that!!!! - -# ???? - unless ( $promo && $promo->is_promoting($object) ) -# && $promo->journalid == $entry->journalid -# && $promo->jitemid == $entry->jitemid ) - { - # your princess is in another castle, sorry - return; - } - - $class->deactivate_promo( - $promo->promoid, $promo->promoter, - 'reason' => $opts{'reason'}, - 'details' => $opts{'details'}, - 'object' => $opts{'object'}, - # 'entry' => $opts{'entry'}, - # 'entry_url' => $entry->url, - 'object_url' => $opts{'object_url'}, - 'refund' => $opts{'refund'}, - ); -} - - -# supported opts: reason, details, object, refund -# TODO: we have no specify promoid -sub old_deactivate_promo { - my ( $class, $promoid, $promoter, %opts ) = @_; - - $class->db_update_promo( $promoid, 'active' => 0, 'finished' => time ); - $class->clear_memcache; - - $class->log( - $promoter, - # 'entry_url' => $opts{'entry_url'}, - 'object_url' => $opts{'object_url'}, - 'object' => $opts{'object'}, - 'event' => 'deactivate', - 'reason' => $opts{'reason'}, - 'details' => $opts{'details'}, - ); -} - # supported opts: # # * cart_owner @@ -1921,60 +1001,6 @@ return $cart; } -sub old_create_shop_cart { - my ( $class, $opts ) = @_; - - LJ::Pay::SelfPromo->debug_msg( - "create_shop_cart called: " . LJ::compact_dumper($opts) ); - - 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' => '', - 'amt' => $opts->{'price'} / LJ::Pay::Wallet::EXCHANGE_RATE, - 'qty' => 1, - 'anon' => 0, - 'rcptid' => $opts->{'rcptid'}, - ); - - $cart->add_item(%$it); - - ($it) = $cart->get_items; - - # set payitem props as appropriate - $it->set_prop( 'selfpromo' => $class->class ); - $it->set_prop( 'selfpromo_type' => $opts->{'type'} ); - $it->set_prop( 'selfpromo_profit' => $opts->{'profit'} ); - $it->set_prop( 'selfpromo_refund' => $opts->{'refund'} ); - $it->set_prop( 'selfpromo_refund_userid' => $opts->{'refund_userid'} ); - $it->set_prop( 'selfpromo_refund_promoid' => $opts->{'refund_promoid'} ); - $it->set_prop( 'selfpromo_remainder' => $opts->{'remainder'} ); - $it->set_prop( - 'selfpromo_remainder_userid' => $opts->{'remainder_userid'} ); - - # Add object specific properties, if object exists (in case of non refunding cart) - if ( my $object = $opts->{'object'} ) { - - my $ownerid = ($class->type eq 'entry' ? $object->journal->userid : $object->userid); # TODO: Refactor that - $it->set_prop( 'selfpromo_journalid' => $ownerid ); - - if ( $class->type eq 'entry' ) { - $it->set_prop( 'selfpromo_ditemid' => $object->ditemid ); - } - } - - LJ::Pay::SelfPromo->debug_msg( - "create_shop_cart successful, " . - "payid=" . $cart->get_payid . ", " . - "piid=" . $it->get_piid - ); - - return $cart; -} - # supported opts: reason, details, object, refund_amount, exptimea # Send notification to the specified user about action performed with promo related to him @@ -2070,97 +1096,7 @@ ); } -sub old_send_notification { - my ( $class, $user, $action, %opts ) = @_; - - my ( $ml_var, %ml_params ); - - my $sp_class = $class->class(); - - if ( $action eq 'deactivate' ) { - my $reason = $opts{'reason'}; - # my $entry = $opts{'entry'}; # note that it may be undefined - my $object = $opts{'object'}; # note that it may be undefined, especially for entries!!!! - - %ml_params = ( - 'refund_amount' => $opts{'refund_amount'}, -# 'entry_url' => $opts{'entry_url'}, - 'object_url' => $opts{'object_url'}, - 'duration_hours' => int( $opts{'duration'} / 3600 ), - 'duration_min' => int( ( $opts{'duration'} % 3600 ) / 60 ), - # 'poster' => $user->display_name, # TODO: Update ml names for semantic consistency! - 'user' => $user->display_name, - ); - - if ( $reason eq 'admin' ) { - if ( $opts{'notify_owner'} ) { - $ml_var = "selfpromo.$sp_class.notification.deactivate.admin3"; - } else { - $ml_var = "selfpromo.$sp_class.notification.deactivate.admin2"; - unless ( $opts{'refund_amount'} > 0 ) { - $ml_var .= '.norefund'; - } - $ml_params{'owner'} = $opts{'owner'} ? $opts{'owner'}->display_name : ''; - } - } - if ( $reason eq 'buyout' ) { - if ( $opts{'notify_owner'} ) { - $ml_var = "selfpromo.$sp_class.notification.deactivate.buyout3"; - } else { - $ml_var = "selfpromo.$sp_class.notification.deactivate.buyout2"; - $ml_params{'owner'} = $opts{'owner'} ? $opts{'owner'}->display_name : ''; - } - } - - if ( $reason eq 'deleted' ) { - $ml_var = "selfpromo.$sp_class.notification.deactivate.deleted"; - } - - if ( $reason eq 'expired' ) { - $ml_var = "selfpromo.$sp_class.notification.deactivate.expired"; - } - - if ( $reason eq 'ineligible' ) { - my $details = $opts{'details'}; - $ml_var = "selfpromo.$sp_class.notification.deactivate.ineligible.$details"; - # $ml_params{'object_subject'} = $object->subject_text; # TODO: Make it more coommon for journals/communitites: make it PromoObject method - } - - if ( $reason eq 'withdraw' ) { - $ml_var = "selfpromo.$sp_class.notification.deactivate.withdraw"; - } - - if ( $reason eq 'owner' ) { - if ( $opts{'notify_owner'} ) { - $ml_var = "selfpromo.$sp_class.notification.deactivate.withdraw"; - } else { - $ml_var = "selfpromo.$sp_class.notification.deactivate.owner"; - $ml_params{'promoter'} = $ml_params{'user'}; - $ml_params{'owner'} = $opts{'owner'} ? $opts{'owner'}->display_name : ''; - # $ml_params{'poster'} = $object ? $object->poster->display_name : ''; # TODO: Use jfd - } - } - } - - my $lang = $user->prop('browselang') || $LJ::DEFAULT_LANG; - my $subject = - LJ::Lang::get_text( $lang, "$ml_var.subject", undef, - \%ml_params, ); - - my $body = LJ::Lang::get_text( $lang, "$ml_var.body", undef, - \%ml_params, ); - - LJ::send_mail( - { 'to' => $user->email_raw, - 'from' => $LJ::DONOTREPLY_EMAIL, - 'fromname' => $LJ::SITENAME, - 'subject' => $subject, - 'body' => $body, - } - ); -} - # TODO: Candidate to move it to PromotionSlot sub was_promoted { my ($class, $slot, $object) = @_; @@ -2173,73 +1109,6 @@ ); } -# Moved to LJ::Pay::Promotion::Auction -sub old_calculate_refund { - my ( $class, $promo ) = @_; - - my $unit = $LJ::SELF_PROMO_CONF->{$class->class}{'refund_time_unit'}; - my $duration = $promo->exptime - $promo->started; - my $refund_step = $LJ::SELF_PROMO_CONF->{$class->class}{'refund_step'}; - - my $remaining_time = $promo->exptime - time; - $remaining_time = 0 if $remaining_time < 0; - - my $remaining_time_units = int( $remaining_time / $unit ); - - my $unit_cost = $promo->cost * $unit / $duration; - my $refund_amount = int( $remaining_time_units * $unit_cost ); - - return $refund_amount; -} - -# Moved to LJ::Pay::Promotion::Auction -sub old_db_insert_promo { - my ( $class, %args ) = @_; - - my $dbh = LJ::get_db_writer(); - - $args{'type'} = $class->type; - $args{'country'} = $class->country; - - my ( @sets, @binds ); - while ( my ( $k, $v ) = each %args ) { - push @sets, "$k=?"; - push @binds, $v; - } - my $sets = join( ',', @sets ); - - $dbh->do( "INSERT INTO selfpromo SET $sets", undef, @binds ); -} -# Moved to LJ::Pay::Promotion::Auction -sub old_db_update_promo { - my ( $class, $promoid, %args ) = @_; - - my $dbh = LJ::get_db_writer(); - - my ( @sets, @binds ); - while ( my ( $k, $v ) = each %args ) { - push @sets, "$k=?"; - push @binds, $v; - } - my $sets = join( ',', @sets ); - - $dbh->do( "UPDATE selfpromo SET $sets WHERE promoid=? AND type=? AND country=?", - undef, @binds, $promoid, $class->type, $class->country); -} - -sub old_clear_memcache { - my ($class, $ownerid, $objectid) = @_; - LJ::MemCache::delete( $class->memcache_key ); - LJ::MemCache::delete( $class->was_promoted_key($ownerid, $objectid) ) if $ownerid and $objectid; -} - -sub old_memcache_key { - my $self = shift; - return 'self_promo_'.$self->class().$self->country().'_active'; -} - -sub old_was_promoted_key { 'self_promo_'.$_[0]->class().$_[0]->country().'_ids_promoted:'. join ':', $_[1], $_[2] } - sub raise_error { my ( $class, @args ) = @_; LJ::Pay::SelfPromo::Error->raise(@args); @@ -2250,48 +1119,16 @@ return LJ::Pay::SelfPromo::Lock->new($slot ? $slot->slot_id : $class->class()); } -sub old_lock { - return LJ::Pay::SelfPromo::Lock->new(shift->class()); -} - sub lock_taken { my ($class, $slot) = @_; return LJ::Pay::SelfPromo::Lock->taken($slot ? $slot->slot_id : $class->class()); } -sub old_lock_taken { - return LJ::Pay::SelfPromo::Lock->taken(shift->class()); -} - sub lock_taken_elsewhere { my ($class, $slot) = @_; return LJ::Pay::SelfPromo::Lock->taken_elsewhere($slot ? $slot->slot_id : $class->class()); } -sub old_lock_taken_elsewhere { - return LJ::Pay::SelfPromo::Lock->taken_elsewhere(shift->class()); -} - -# supported opts: object_url, event, reason, detailsh# TODO: Add specific common messages for all types of selfpromo -sub old_log { - my ( $class, $promoter, %opts ) = @_; - - my $message = ''; - - $message .= 'type: '.$class->class.'; object: ' . $opts{'object_url'} . '; event: ' . $opts{'event'}; - - if ( my $reason = $opts{'reason'} ) { - if ( my $details = $opts{'details'} ) { - $reason .= '/' . $details; - } - - $message .= ' (' . $reason . ')'; - } - - my $systemu = LJ::load_user('system'); - return LJ::statushistory_add( $promoter, $systemu, 'selfpromo', $message ); -} - sub debug_msg { my ( $class, @args ) = @_;