From 1847a18ec70fb4b90151248cc67a2f1217f5b3aa Mon Sep 17 00:00:00 2001 From: Martin Kamerbeek Date: Mon, 29 Nov 2004 15:29:26 +0000 Subject: [PATCH] Committing the new Ecommerce system --- lib/WebGUI/Commerce/Item.pm | 20 +++ lib/WebGUI/Commerce/Payment.pm | 72 +++++++++ lib/WebGUI/Commerce/ShoppingCart.pm | 79 ++++++++++ lib/WebGUI/Commerce/Transaction.pm | 224 ++++++++++++++++++++++++++++ 4 files changed, 395 insertions(+) create mode 100644 lib/WebGUI/Commerce/Item.pm create mode 100644 lib/WebGUI/Commerce/Payment.pm create mode 100644 lib/WebGUI/Commerce/ShoppingCart.pm create mode 100644 lib/WebGUI/Commerce/Transaction.pm diff --git a/lib/WebGUI/Commerce/Item.pm b/lib/WebGUI/Commerce/Item.pm new file mode 100644 index 000000000..febdfe0db --- /dev/null +++ b/lib/WebGUI/Commerce/Item.pm @@ -0,0 +1,20 @@ +package WebGUI::Commerce::Item; + +#------------------------------------------------------------------- +sub new { + my ($class, $namespace, $load, $cmd, $plugin); + $class = shift; + $id = shift; + $namespace = shift; + + $cmd = "WebGUI::Commerce::Item::$namespace"; + $load = "use $cmd"; + eval($load); + WebGUI::ErrorHandler::warn("Item plugin failed to compile: $cmd.".$@) if($@); + $plugin = eval($cmd."->new('$id', '$namespace')"); + WebGUI::ErrorHandler::warn("Couldn't instantiate Item plugin: $cmd.".$@) if($@); + return $plugin; +} + +1; + diff --git a/lib/WebGUI/Commerce/Payment.pm b/lib/WebGUI/Commerce/Payment.pm new file mode 100644 index 000000000..a733ed9f9 --- /dev/null +++ b/lib/WebGUI/Commerce/Payment.pm @@ -0,0 +1,72 @@ +package WebGUI::Commerce::Payment; + +use strict; +use WebGUI::SQL; +use WebGUI::International; +use Tie::IxHash; + +#------------------------------------------------------------------- +sub get { + return $_[0]->{_properties}{$_[1]}; +} + +#------------------------------------------------------------------- +sub init { + my ($class, $namespace, $properties); + $class = shift; + $namespace = shift; + + $properties = WebGUI::SQL->buildHashRef("select fieldName, fieldValue from commerceSettings where namespace=".quote($namespace)." and type='Payment'"); + + bless {_properties => $properties, _namespace=>$namespace}, $class; +} + +#------------------------------------------------------------------- +sub load { + my ($class, $namespace, $load, $cmd, $plugin); + $class = shift; + $namespace = shift; + + $cmd = "WebGUI::Commerce::Payment::$namespace"; + $load = "use $cmd"; + eval($load); + WebGUI::ErrorHandler::warn("Payment plugin failed to compile: $cmd.".$@) if($@); + $plugin = eval($cmd."->init"); + WebGUI::ErrorHandler::warn("Couldn't instantiate payment plugin: $cmd.".$@) if($@); + return $plugin; +} + +#------------------------------------------------------------------- +sub namespace { + return $_[0]->{_namespace}; +} + +#------------------------------------------------------------------- +sub prepend { + my ($self, $name); + $self = shift; + $name = shift; + + return "~Payment~".$self->namespace."~".$name; +} + +#------------------------------------------------------------------- +sub recurringPeriodValues { + my ($i18n, %periods); + $i18n = WebGUI::International->new('Commerce'); + tie %periods, "Tie::IxHash"; + %periods = ( + Weekly => $i18n->get('weekly'), + BiWeekly => $i18n->get('biweekly'), + FourWeekly => $i18n->get('fourweekly'), + Monthly => $i18n->get('monthly'), + Quarterly => $i18n->get('quarterly'), + HalfYearly => $i18n->get('halfyearly'), + Yearly => $i18n->get('yearly'), + ); + + return \%periods; +} + +1; + diff --git a/lib/WebGUI/Commerce/ShoppingCart.pm b/lib/WebGUI/Commerce/ShoppingCart.pm new file mode 100644 index 000000000..d9be31b03 --- /dev/null +++ b/lib/WebGUI/Commerce/ShoppingCart.pm @@ -0,0 +1,79 @@ +package WebGUI::Commerce::ShoppingCart; + +use strict; +use WebGUI::Session; +use WebGUI::SQL; +use WebGUI::Commerce::Item; +use WebGUI::Commerce::Payment; + +#------------------------------------------------------------------- +sub add { + my ($self, $itemId, $itemType, $quantity); + $self = shift; + $itemId = shift; + $itemType = shift; + $quantity = shift || 1; + + $self->{_items}{$itemId."_".$itemType} = { + itemId => $itemId, + itemType => $itemType, + quantity => $self->{_items}{$itemId."_".$itemType}{quantity} + $quantity + }; + + WebGUI::SQL->write("delete from shoppingCart where sessionId=".quote($self->{_sessionId})." and itemId=".quote($itemId)." and itemType=".quote($itemType)); + WebGUI::SQL->write("insert into shoppingCart ". + "(sessionId, itemId, itemType, quantity) values ". + "(".quote($self->{_sessionId}).",".quote($itemId).",".quote($itemType).",".$self->{_items}{$itemId."_".$itemType}{quantity}.")"); +} + +#------------------------------------------------------------------- +sub empty { + my ($self); + $self = shift; + + WebGUI::SQL->write("delete from shoppingCart where sessionId=".quote($self->{_sessionId})); +} + +#------------------------------------------------------------------- +sub getItems { + my ($self, $periodResolve, %cartContent, $item, $properties, @recurring, @normal); + $self = shift; + + $periodResolve = WebGUI::Commerce::Payment::recurringPeriodValues; + %cartContent = %{$self->{_items}}; + foreach (values(%cartContent)) { + $item = WebGUI::Commerce::Item->new($_->{itemId}, $_->{itemType}); + $properties = { + quantity => $_->{quantity}, + period => lc($periodResolve->{$item->duration}), + name => $item->name, + price => sprintf('%.2f', $item->price), + totalPrice => sprintf('%.2f', $item->price * $_->{quantity}), + item => $item, + }; + + if ($item->isRecurring) { + push(@recurring, $properties); + } else { + push(@normal, $properties); + } + } + + return (\@normal, \@recurring); +} + +#------------------------------------------------------------------- +sub new { + my ($class, $sessionId, $sth, $row, %items); + $class = shift; + $sessionId = shift || $session{var}{sessionId}; + + $sth = WebGUI::SQL->read("select * from shoppingCart where sessionId=".quote($sessionId)); + while ($row = $sth->hashRef) { + $items{$row->{itemId}."_".$row->{itemType}} = $row; + } + + bless {_sessionId => $sessionId, _items => \%items}, $class; +} + +1; diff --git a/lib/WebGUI/Commerce/Transaction.pm b/lib/WebGUI/Commerce/Transaction.pm new file mode 100644 index 000000000..24201d6d8 --- /dev/null +++ b/lib/WebGUI/Commerce/Transaction.pm @@ -0,0 +1,224 @@ +package WebGUI::Commerce::Transaction; + +use strict; +use WebGUI::Session; +use WebGUI::Id; +use WebGUI::SQL; +use WebGUI::Commerce::Payment; + +#------------------------------------------------------------------- +sub addItem { + my ($self, $item, $quantity); + $self = shift; + $item = shift; + $quantity = shift; + + WebGUI::SQL->write("insert into transactionItem ". + "(transactionId, itemName, amount, quantity, itemId, itemType) values ". + "(".quote($self->{_transactionId}).",".quote($item->name).",".quote($item->price).",".quote($quantity).",". + quote($item->id).",".quote($item->type).")"); + # Adjust total amount in the transaction table. + WebGUI::SQL->write("update transaction set amount=amount+".($item->price * $quantity)." where transactionId=".quote($self->{_transactionId})); + $self->{_properties}{amount} += ($item->price * $quantity); + push @{$self->{_items}}, { + transactionId => $self->{_transactionId}, + itemName => $item->name, + amount => $item->price, + quantity => $quantity, + itemId => $item->id, + itemType => $item->type, + } +} + +#------------------------------------------------------------------- +sub cancelTransaction { + my ($self, $item, $plugin); + $self = shift; + + return "Not a recurring transaction" unless ($self->isRecurring); + + # Recurring transactions can only have one item, so our items must be the first + $item = $self->getItems->[0]; + + $plugin = WebGUI::Commerce::Payment->load($self->gateway); + $plugin->cancelRecurringPayment({ + id => $self->gatewayId + }); + return $plugin->resultMessage.' (code: '.$plugin->errorCode.')' if ($plugin->errorCode); + + $self->status('Canceled'); + + return undef; +} + +#------------------------------------------------------------------- +sub completeTransaction { + my ($self, $item); + $self = shift; + + foreach (@{$self->getItems}) { + $item = WebGUI::Commerce::Item->new($_->{itemId}, $_->{itemType}); + $item->handler; + } + + $self->status('Completed'); +} + +#------------------------------------------------------------------- +sub delete { + my ($self) = shift; + + WebGUI::SQL->write("delete from transaction where transactionId=".quote($self->{_transactionId})); + WebGUI::SQL->write("delete from transactionItem where transactionId=".quote($self->{_transactionId})); + + undef $self; +} + +#------------------------------------------------------------------- +sub gateway { + my ($self, $gateway); + $self = shift; + $gateway = shift; + + if ($gateway) { + $self->{_properties}{gateway} = $gateway; + WebGUI::SQL->write("update transaction set gateway=".quote($gateway)." where transactionId=".quote($self->{_transactionId})); + } + + return $self->{_properties}{gateway}; +} + +#------------------------------------------------------------------- +sub gatewayId { + my ($self, $gatewayId); + $self = shift; + $gatewayId = shift; + + if ($gatewayId) { + $self->{_properties}{gatewayId} = $gatewayId; + WebGUI::SQL->write("update transaction set gatewayId=".quote($gatewayId)." where transactionId=".quote($self->{_transactionId})); + } + + return $self->{_properties}{gatewayId}; +} + +#------------------------------------------------------------------- +sub get { + my ($self, $key); + $self = shift; + $key = shift; + + return $self->{_properties}{$key} if ($key); + return $self->{_properties}; +} + +#------------------------------------------------------------------- +sub getItems { + my ($self); + $self = shift; + + return $self->{_items}; +} + +#------------------------------------------------------------------- +sub isRecurring { + my ($self, $recurring); + $self = shift; + $recurring = shift; + + if (defined $recurring) { + $self->{_properties}{recurring} = $recurring; + WebGUI::SQL->write("update transaction set recurring=".quote($recurring)." where transactionId=".quote($self->{_transactionId})); + } + + return $self->{_properties}{recurring}; +} + +#------------------------------------------------------------------- +sub lastPayedTerm { + my ($self, $lastPayedTerm); + $self = shift; + $lastPayedTerm = shift; + + if (defined $lastPayedTerm) { + $self->{_properties}{lastPayedTerm} = $lastPayedTerm; + WebGUI::SQL->write("update transaction set lastPayedTerm=".quote($lastPayedTerm)." where transactionId=".quote($self->{_transactionId})); + } + + return $self->{_properties}{lastPayedTerm}; +} + +#------------------------------------------------------------------- +sub new { + my ($class, $transactionId, $gatewayId, $userId, $properties, $sth, $row, @items); + + $class = shift; + $transactionId = shift; + $gatewayId = shift; + $userId = shift || $session{user}{userId}; + + if ($transactionId eq 'new') { + $transactionId = WebGUI::Id::generate; + + WebGUI::SQL->write("insert into transaction ". + "(transactionId, userId, amount, gatewayId, initDate, completionDate, status) values ". + "(".quote($transactionId).",".quote($userId).",0,".quote($gatewayId).",".quote(time).",NULL,'Pending')"); + } + + $properties = WebGUI::SQL->quickHashRef("select * from transaction where transactionId=".quote($transactionId)); + $sth = WebGUI::SQL->read("select * from transactionItem where transactionId=".quote($transactionId)); + while ($row = $sth->hashRef) { + push(@items, $row); + } + + bless {_transactionId => $transactionId, _properties => $properties, _items => \@items}, $class; +} + +#------------------------------------------------------------------- +sub pendingTransactions { + my (@transactionIds, @transactions); + @transactionIds = WebGUI::SQL->buildArray("select transactionId from transaction where status = 'Pending'"); + + foreach (@transactionIds) { + push(@transactions, WebGUI::Commerce::Transaction->new($_)); + } + + return \@transactions; +} + +#------------------------------------------------------------------- +sub status { + my ($self, $status); + $self = shift; + $status = shift; + + if ($status) { + $self->{_properties}{status} = $status; + WebGUI::SQL->write("update transaction set status=".quote($status)." where transactionId=".quote($self->{_transactionId})); + } + + return $self->{_properties}{status}; +} + +#------------------------------------------------------------------- +sub transactionId { + my $self = shift; + return $self->{_transactionId}; +} + +#------------------------------------------------------------------- +sub transactionsByUser { + my ($self, @transactionIds, @transactions, $userId); + my $self = shift; + my $userId = shift; + + @transactionIds = WebGUI::SQL->buildArray("select transactionId from transaction where userId =".quote($userId)); + foreach (@transactionIds) { + push (@transactions, WebGUI::Commerce::Transaction->new($_)); + } + + return \@transactions; +} + +1; +