From 7ce918852e95a4be61adcdd0b4684025f61ef0dd Mon Sep 17 00:00:00 2001 From: Martin Kamerbeek Date: Fri, 13 Mar 2009 12:39:29 +0000 Subject: [PATCH] Adding vendor payout manager --- docs/changelog/7.x.x.txt | 1 + docs/upgrades/upgrade_7.6.14-7.7.0.pl | 13 ++ lib/WebGUI/Asset/Sku.pm | 25 ++++ lib/WebGUI/Shop/TransactionItem.pm | 16 ++- lib/WebGUI/Shop/Vendor.pm | 174 +++++++++++++++++++++++++- 5 files changed, 222 insertions(+), 7 deletions(-) diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index e2ba38503..7d2a07253 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -11,6 +11,7 @@ resulting in permanently locked content (Martin Kamerbeek / Oqapi ) - fixed: Each textarea inserts identical JS that should be inserted only once ( Martin Kamerbeek / Oqapi ) + - added: Vendor payout system ( Martin Kamerbeek / Oqapi ) 7.6.14 - fixed: IE6 shows Admin Bar over Asset Manager diff --git a/docs/upgrades/upgrade_7.6.14-7.7.0.pl b/docs/upgrades/upgrade_7.6.14-7.7.0.pl index 1c0d5cc30..1ce34356e 100644 --- a/docs/upgrades/upgrade_7.6.14-7.7.0.pl +++ b/docs/upgrades/upgrade_7.6.14-7.7.0.pl @@ -47,6 +47,9 @@ pa_installWorkflow($session); pa_addPassiveAnalyticsSettings($session); pa_addPassiveAnalyticsStatus($session); +# vendor payouts +addTransactionItemFlags( $session ); + finish($session); # this line required #---------------------------------------------------------------------------- @@ -277,6 +280,16 @@ sub pa_installWorkflow { print "DONE!\n"; } +#---------------------------------------------------------------------------- +sub addTransactionItemFlags { + my $session = shift; + print "\tAdding columns for vendor payout tracking to transaction items..." unless $quiet; + + $session->db->write('alter table transactionItem add column vendorPayoutStatus char(10) default \'NotPaid\''); + $session->db->write('alter table transactionItem add column vendorPayoutAmount float (6,2) default 0.00'); + + print "Done.\n" unless $quiet; +} #---------------------------------------------------------------------------- # Describe what our function does diff --git a/lib/WebGUI/Asset/Sku.pm b/lib/WebGUI/Asset/Sku.pm index b2221d28e..675e41012 100644 --- a/lib/WebGUI/Asset/Sku.pm +++ b/lib/WebGUI/Asset/Sku.pm @@ -292,6 +292,31 @@ sub getThumbnailUrl { return undef; } +#------------------------------------------------------------------- +=head2 getVendorId ( ) + +Returns the vendorId of the vendor for this sku. Defaults to the default +vendor with id defaultvendor000000000. + +=cut + +sub getVendorId { + my $self = shift; + return 'defaultvendor000000000'; +} + +#------------------------------------------------------------------- + +=head2 getVendorPayout ( ) + +Returns the amount that should be payed to the vendor for this sku. + +=cut + +sub getVendorPayout { + return 0; +} + #------------------------------------------------------------------- =head2 getWeight ( ) diff --git a/lib/WebGUI/Shop/TransactionItem.pm b/lib/WebGUI/Shop/TransactionItem.pm index bef811aef..61287c932 100644 --- a/lib/WebGUI/Shop/TransactionItem.pm +++ b/lib/WebGUI/Shop/TransactionItem.pm @@ -267,11 +267,14 @@ sub update { if (exists $newProperties->{item}) { my $item = $newProperties->{ item }; my $sku = $item->getSku; - $newProperties->{ options } = $sku->getOptions; - $newProperties->{ assetId } = $sku->getId; - $newProperties->{ price } = $sku->getPrice; - $newProperties->{ configuredTitle } = $item->get('configuredTitle'); - $newProperties->{ quantity } = $item->get('quantity'); + $newProperties->{ options } = $sku->getOptions; + $newProperties->{ assetId } = $sku->getId; + $newProperties->{ price } = $sku->getPrice; + $newProperties->{ configuredTitle } = $item->get('configuredTitle'); + $newProperties->{ quantity } = $item->get('quantity'); + $newProperties->{ vendorId } = $sku->getVendorId; + $newProperties->{ vendorPayoutAmount } = sprintf '%.2f', $sku->getVendorPayout * $item->get('quantity'); + my $address = $item->getShippingAddress; $newProperties->{ shippingAddressId } = $address->getId; $newProperties->{ shippingAddressName } = $address->get('name'); @@ -289,7 +292,8 @@ sub update { } my @fields = (qw(assetId configuredTitle options shippingAddressId shippingTrackingNumber orderStatus shippingName shippingAddress1 shippingAddress2 shippingAddress3 shippingCity shippingState - shippingCountry shippingCode shippingPhoneNumber quantity price vendorId)); + shippingCountry shippingCode shippingPhoneNumber quantity price vendorId + vendorPayoutStatus vendorPayoutAmount)); foreach my $field (@fields) { $properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field}; } diff --git a/lib/WebGUI/Shop/Vendor.pm b/lib/WebGUI/Shop/Vendor.pm index ac6ba85df..6e08083f4 100644 --- a/lib/WebGUI/Shop/Vendor.pm +++ b/lib/WebGUI/Shop/Vendor.pm @@ -5,7 +5,9 @@ use Class::InsideOut qw{ :std }; use WebGUI::Shop::Admin; use WebGUI::Exception::Shop; use WebGUI::International; - +use WebGUI::Utility qw{ isIn }; +use List::Util qw{ sum }; +use JSON qw{ encode_json }; =head1 NAME @@ -406,4 +408,174 @@ sub www_manage { } +#------------------------------------------------------------------- +sub getPayoutTotals { + my $self = shift; + + my %totals = $self->session->db->buildHash( + 'select vendorPayoutStatus, sum(vendorPayoutAmount) as amount from transactionItem ' + .'where vendorId=? group by vendorPayoutStatus ', + [ $self->getId ] + ); + + # Format the payout categories and calc the total those. + %totals = + map { lcfirst $_ => sprintf '%.2f', $totals{ $_ } } + qw( Paid Scheduled NotPaid ); + $totals{ total } = sprintf '%.2f', sum values %totals; + + return \%totals; +} + +#------------------------------------------------------------------- +sub www_submitScheduledPayouts { + my $class = shift; + my $session = shift; + + my $admin = WebGUI::Shop::Admin->new($session); + return $session->privilege->adminOnly() unless ($admin->canManage); + + $session->db->write( + q{ update transactionItem set vendorPayoutStatus = 'Paid' where vendorPayoutStatus = 'Scheduled' } + ); + + return $class->www_managePayouts( $session ); +} + +#------------------------------------------------------------------- +sub www_setPayoutStatus { + my $class = shift; + my $session = shift; + + my $admin = WebGUI::Shop::Admin->new($session); + return $session->privilege->adminOnly() unless ($admin->canManage); + + my @itemIds = $session->form->process('itemId'); + my $status = $session->form->process('status'); + return "error: wrong status [$status]" unless isIn( $status, qw{ NotPaid Scheduled } ); + + foreach my $itemId (@itemIds) { + my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction( $session, $itemId ); + return "error: invalid transactionItemId [$itemId]" unless $item; + return "error: cannot change status of a Paid item" if $item->get('vendorPayoutStatus') eq 'Paid'; + + $item->update({ vendorPayoutStatus => $status }); + } + + return $status; +} + +#------------------------------------------------------------------- +sub www_vendorTotalsAsJSON { + my $class = shift; + my $session = shift; + + my $admin = WebGUI::Shop::Admin->new($session); + return $session->privilege->adminOnly() unless ($admin->canManage); + + my $vendorId = $session->form->process('vendorId'); + my ($vendorPayoutData, @placeholders); + + my @sql; + push @sql, + 'select vendorId, vendorPayoutStatus, sum(vendorPayoutAmount) as total from transactionItem'; + push @sql, ' where vendorId=? ' if $vendorId; + push @sql, ' group by vendorId, vendorPayoutStatus '; + + push @placeholders, $vendorId if $vendorId; + + my $sth = $session->db->read( join( ' ', @sql) , \@placeholders ); + while (my $row = $sth->hashRef) { + $vendorPayoutData->{ $row->{vendorId} }->{ $row->{vendorPayoutStatus} } = $row->{total}; + } + $sth->finish; + + my @dataset; + foreach my $vendorId (keys %{ $vendorPayoutData }) { + my $vendor = WebGUI::Shop::Vendor->new( $session, $vendorId ); + + push @dataset, { + %{ $vendor->get }, + %{ $vendorPayoutData->{ $vendorId } }, + } + } + + $session->http->setMimeType( 'application/json' ); + return JSON::to_json( { vendors => \@dataset } ); +} + +#------------------------------------------------------------------- +sub www_payoutDataAsJSON { + my $class = shift; + my $session = shift; + + my $admin = WebGUI::Shop::Admin->new($session); + return $session->privilege->adminOnly() unless ($admin->canManage); + + my $vendorId = $session->form->process('vendorId'); + my $startIndex = $session->form->process('startIndex'); + my $rowsPerPage = $session->form->process('results') || 100; + my $pageNumber = int( $startIndex / $rowsPerPage ) + 1; + + my $sql = + "select t1.* from transactionItem as t1 join transaction as t2 on t1.transactionId=t2.transactionId " + ." where vendorId=? and vendorPayoutAmount > 0 and vendorPayoutStatus <> 'Paid' order by t2.orderNumber"; + my $placeholders = [ $vendorId ]; + + my $paginator = WebGUI::Paginator->new( $session, '', $rowsPerPage, '', $pageNumber ); + $paginator->setDataByQuery( $sql, undef, 0, $placeholders ); + + my $data = { + totalRecords => $paginator->getRowCount, + results => $paginator->getPageData, + }; + + $session->http->setMimeType( 'application/json' ); + + return JSON::to_json( $data ); +} + +#------------------------------------------------------------------- +sub www_managePayouts { + my $class = shift; + my $session = shift; + + my $admin = WebGUI::Shop::Admin->new($session); + return $session->privilege->adminOnly() unless ($admin->canManage); + + # Load the required YUI stuff. + $session->style->setLink('/extras/yui/build/paginator/assets/skins/sam/paginator.css', {type=>'text/css', rel=>'stylesheet'}); + $session->style->setLink('/extras/yui/build/datatable/assets/skins/sam/datatable.css', {type=>'text/css', rel=>'stylesheet'}); + $session->style->setLink('/extras/yui/build/button/assets/skins/sam/button.css', {type=>'text/css', rel=>'stylesheet'}); + $session->style->setScript('/extras/yui/build/yahoo-dom-event/yahoo-dom-event.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/element/element-beta-min.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/connection/connection-min.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/json/json-min.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/paginator/paginator-min.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/datasource/datasource.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/datatable/datatable-min.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/yui/build/button/button-min.js', {type=>'text/javascript'}); + $session->style->setScript('/extras/VendorPayout/vendorPayout.js', {type=>'text/javascript'}); + + # Add css for scheduled payout highlighting + $session->style->setRawHeadTags(< + .yui-skin-sam .yui-dt tr.scheduled, + .yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc, + .yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc, + .yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc, + .yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc { + background-color : #080; + color : #fff; + } + +CSS + + my $output = q{
} + .q{}; + + my $console = WebGUI::Shop::Admin->new($session)->getAdminConsole; + return $console->render($output, 'Vendor payout'); #$i18n->get("vendors")); +} + 1;