added scheduled vendor payouts workflow activity

This commit is contained in:
JT Smith 2009-10-20 11:04:03 -05:00
parent b8b7dc2875
commit d87d766856
5 changed files with 357 additions and 7 deletions

View file

@ -7,6 +7,11 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief. save you many hours of grief.
7.8.2
--------------------------------------------------------------------
* WebGUI now requires Business::PayPal::API 0.62 or higher.
7.8.1 7.8.1
-------------------------------------------------------------------- --------------------------------------------------------------------
@ -32,6 +37,7 @@ save you many hours of grief.
prefix from the filename. prefix from the filename.
7.8.0 7.8.0
-------------------------------------------------------------------- --------------------------------------------------------------------

View file

@ -35,18 +35,36 @@ fixTableDefaultCharsets($session);
correctWikiAttachmentPermissions( $session ); correctWikiAttachmentPermissions( $session );
transactionsNotifications( $session ); transactionsNotifications( $session );
fixBadVarCharColumns ( $session ); fixBadVarCharColumns ( $session );
addVendorPayouts($session);
finish($session); # this line required finish($session); # this line required
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Describe what our function does sub addVendorPayouts {
#sub exampleFunction { my $session = shift;
# my $session = shift; print "\tAdding vendor payouts... " unless $quiet;
# print "\tWe're doing some stuff here that you should know about... " unless $quiet; my $db = $session->db;
# # and here's our code $db->write(" create table if not exists vendorPayoutLog (
# print "DONE!\n" unless $quiet; payoutId char(22) binary not null primary key,
#} isSuccessful tinyint(1) not null,
errorCode char(10),
errorMessage char(255),
paypalTimestamp char(20) not null,
amount decimal(7,2) not null,
currency char(3) not null,
correlationId char(13) not null,
paymentInformation char(255) not null
)");
$db->write(" create table if not exists vendorPayoutLog_items (
payoutId char(22) binary not null,
transactionItemId char(22) binary not null,
amount decimal(7,2) not null,
primary key( payoutId, transactionItemId )
)");
print "DONE!\n" unless $quiet;
}
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
sub fixTableDefaultCharsets { sub fixTableDefaultCharsets {

View file

@ -0,0 +1,262 @@
package WebGUI::Workflow::Activity::PayoutVendors;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2009 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use Business::PayPal::API qw{ MassPay };
use Data::Dumper;
use WebGUI::Mail::Send;
use base 'WebGUI::Workflow::Activity';
=head1 NAME
Package WebGUI::Workflow::Activity::PayoutVendors
=head1 DESCRIPTION
Pays profits to vendors, currently via paypal, but others may be added in the future.
=head1 SYNOPSIS
See WebGUI::Workflow::Activity for details on how to use any activity.
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 definition ()
See WebGUI::Workflow::Activity for details.
=cut
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session, "Workflow_Activity_PayoutVendors");
tie my %properties, 'Tie::IxHash', (
paypalUsername => {
fieldType => 'text',
label => $i18n->get('PayPal username'),
},
paypalPassword => {
fieldType => 'password',
label => $i18n->get('PayPal password'),
},
paypalSignature => {
fieldType => 'text',
label => $i18n->get('PayPal signature'),
},
useSandbox => {
fieldType => 'yesNo',
label => $i18n->get('Use in Sandbox (test-mode)'),
defaultValue => 0,
},
currencyCode => {
fieldType => 'text',
label => $i18n->get('Currency code'),
maxlength => 3,
size => 3,
defaultValue => 'USD',
},
paypalSubject => {
fieldType => 'text',
label => $i18n->get('Subject for vendor notication email'),
defaultValue => $i18n->get('Vendor payout from').' ' . $session->setting->get('companyUrl'),
},
notificationGroupId => {
fieldType => 'group',
label => $i18n->get('Notify on error'),
},
);
push @{ $definition }, {
name => $i18n->get('Vendor Payout'),
properties => \%properties,
};
return $class->SUPER::definition( $session, $definition );
}
#-------------------------------------------------------------------
=head2 payoutVendor (vendorId)
Sends unsent vendor payouts to paypal.
=head3 vendorId
The vendor to be sent his payouts.
=cut
sub payoutVendor {
my $self = shift;
my $vendorId = shift;
my $db = $self->session->db;
my $payoutId = $self->session->id->generate;
# Instanciate vendor and check if he exists.
my $vendor = WebGUI::Shop::Vendor->new( $self->session, $vendorId );
unless ( $vendor ) {
$self->session->log->error( "Could not instanciate vendor with id [$vendorId] for payout" );
return undef;
}
# check to see that the vendor has a payout address
if ($vendor->get('paymentInformation') eq '') {
$self->session->log->warn("Vendor ".$vendor->getId." hasn't specified a payout address.");
return undef;
}
# Fetch all transactionItems that are scheduled for payout to the vendor.
my $sth = $db->read(
'select itemId, vendorPayoutAmount from transactionItem '
. ' where vendorId=? and vendorPayoutStatus=? and vendorPayoutAmount > 0',
[
$vendorId,
'Scheduled',
]
);
# Process all transaction items and log them in the db.
my $totalAmount = 0;
while ( my $item = $sth->hashRef ) {
$totalAmount += $item->{ vendorPayoutAmount };
$db->write( 'insert into vendorPayoutLog_items (payoutId, transactionItemId, amount) values (?,?,?)', [
$payoutId,
$item->{ itemId },
$item->{ vendorPayoutAmount },
] );
}
my $itemCount = $sth->rows;
$sth->finish;
# Do PayPal MassPay request
my $pp = new Business::PayPal::API(
Username => $self->get('paypalUsername'),
Password => $self->get('paypalPassword'),
Signature => $self->get('paypalSignature'),
sandbox => $self->get('useSandbox'),
);
my %response = $pp->MassPay(
EmailSubject => $self->get('paypalSubject'),
currencyID => $self->get('currencyCode'),
MassPayItems => [ {
ReceiverEmail => $vendor->get('paymentInformation'),
Amount => $totalAmount,
UniqueID => $payoutId,
Note => "Payout for $itemCount sold items",
} ],
);
# Process paypal response
my $payoutDetails = {
payoutId => $payoutId,
isSuccessful => $response{ Ack } eq 'Success' ? 1 : 0,
paypalTimestamp => $response{ Timestamp },
correlationId => $response{ CorrelationID },
amount => $totalAmount,
currency => $self->get('currencyCode'),
paymentInformation => $vendor->get('paymentInformation'),
};
if ( $response{ Ack } ne 'Success' ) {
# An error occurred, keep the error codes
my $errorCode = $response{ Error }->[ 0 ]->{ ErrorCode };
my $errorMessage = $response{ Error }->[ 0 ]->{ LongMessage };
# TODO: Send out email.
my $mail = WebGUI::Mail::Send->create($self->session, {
toGroup => $self->get('notificationGroupId'),
subject => 'Vendor payout error',
});
$mail->addText(
"An error occurred during an automated vendor payout attempt. Response details:\n"
. Dumper( \%response )
. "\n\nVendor information:\n"
. Dumper( $vendor->get )
);
$mail->send;
$payoutDetails->{ errorCode } = $errorCode;
$payoutDetails->{ errorMessage } = $errorMessage;
}
else {
# The transaction was successful, so change the state of the transactionItems to Paid.
$db->write(
'update transactionItem set vendorPayoutStatus=? where itemId in ( '
.' select transactionItemId from vendorPayoutLog_items where payoutId=? '
.')',
[
'Paid',
$payoutId,
]
);
}
# Persist response data to db
$db->setRow( 'vendorPayoutLog', 'payoutId', $payoutDetails, $payoutId );
};
#-------------------------------------------------------------------
=head2 execute ()
See WebGUI::Workflow::Activity for details.
=cut
sub execute {
my $self = shift;
my $object = shift;
my $instance = shift;
my $start = time;
my $ttl = $self->getTTL;
# Fetch vendors eligible for payout.
my $sth = $self->session->db->read(
"select distinct vendorId from transactionItem where vendorPayoutStatus='Scheduled' and vendorPayoutAmount > 0"
);
# Pay on a vendor by vendor basis.
while ( (my $vendorId) = $sth->array ) {
$self->payoutVendor( $vendorId );
# Make sure we won't run longer than allowed.
if ( ( time - $start + 1 ) >= $ttl ) {
$sth->finish;
return $self->WAITING( 1 );
}
}
$sth->finish;
return $self->COMPLETE;
}
1;

View file

@ -0,0 +1,63 @@
package WebGUI::i18n::English::Workflow_Activity_PayoutVendors;
use strict;
our $I18N = {
'PayPal username' => {
message => q|PayPal username|,
lastUpdated => 0,
context => q|field label|
},
'PayPal password' => {
message => q|PayPal password|,
lastUpdated => 0,
context => q|field label|
},
'PayPal signature' => {
message => q|PayPal signature|,
lastUpdated => 0,
context => q|field label|
},
'Use in Sandbox (test-mode)' => {
message => q|Use in Sandbox (test-mode)|,
lastUpdated => 0,
context => q|field label|
},
'Currency code' => {
message => q|Currency code|,
lastUpdated => 0,
context => q|field label|
},
'Subject for vendor notification email' => {
message => q|Subject for vendor notification email|,
lastUpdated => 0,
context => q|field label|
},
'Vendor payout from' => {
message => q|Vendor payout from|,
lastUpdated => 0,
context => q|Prefix that goes before company URL to create the default value from Subject for vendor notification email.|
},
'Notify on error' => {
message => q|Notify on error|,
lastUpdated => 0,
context => q|field label|
},
'Vendor Payout' => {
message => q|Vendor Payout|,
lastUpdated => 0,
context => q|field label|
},
};
1;
#vim:ft=perl

View file

@ -133,6 +133,7 @@ checkModule('Digest::SHA', '5.47' );
checkModule("CSS::Minifier::XS", "0.03" ); checkModule("CSS::Minifier::XS", "0.03" );
checkModule("JavaScript::Minifier::XS", "0.05" ); checkModule("JavaScript::Minifier::XS", "0.05" );
checkModule("Readonly", "1.03" ); checkModule("Readonly", "1.03" );
checkModule("Business::PayPal::API", "0.62" );
failAndExit("Required modules are missing, running no more checks.") if $missingModule; failAndExit("Required modules are missing, running no more checks.") if $missingModule;