transaction backend and tests complete
This commit is contained in:
parent
c2c258400d
commit
02199ff58c
5 changed files with 862 additions and 1 deletions
|
|
@ -35,9 +35,82 @@ addShoppingHandler($session);
|
||||||
addAddressBook($session);
|
addAddressBook($session);
|
||||||
insertCommercePayDriverTable($session);
|
insertCommercePayDriverTable($session);
|
||||||
addPaymentDrivers($session);
|
addPaymentDrivers($session);
|
||||||
|
convertTransactionLog($session);
|
||||||
|
|
||||||
finish($session); # this line required
|
finish($session); # this line required
|
||||||
|
|
||||||
|
#-------------------------------------------------
|
||||||
|
sub convertTransactionLog {
|
||||||
|
my $session = shift;
|
||||||
|
print "\tInstalling transaction log.\n" unless ($quiet);
|
||||||
|
$session->db->write("alter table transaction rename oldtransaction");
|
||||||
|
$session->db->write("alter table transactionItem rename oldtransactionitem");
|
||||||
|
$session->db->write("create table transaction (
|
||||||
|
transactionId varchar(22) binary not null primary key,
|
||||||
|
isSuccessful bool not null default 0,
|
||||||
|
transactionCode varchar(100),
|
||||||
|
statusCode varchar(35),
|
||||||
|
statusMessage varchar(100),
|
||||||
|
userId varchar(22) binary not null,
|
||||||
|
username varchar(35) not null,
|
||||||
|
amount float,
|
||||||
|
shippingAddressId varchar(22) binary,
|
||||||
|
shippingAddressName varchar(35),
|
||||||
|
shippingAddress1 varchar(35),
|
||||||
|
shippingAddress2 varchar(35),
|
||||||
|
shippingAddress3 varchar(35),
|
||||||
|
shippingCity varchar(35),
|
||||||
|
shippingState varchar(35),
|
||||||
|
shippingCountry varchar(35),
|
||||||
|
shippingCode varchar(35),
|
||||||
|
shippingPhoneNumber varchar(35),
|
||||||
|
shippingDriverId varchar(22) binary,
|
||||||
|
shippingDriverLabel varchar(35),
|
||||||
|
shippingPrice float,
|
||||||
|
paymentAddressId varchar(22) binary,
|
||||||
|
paymentAddressName varchar(35),
|
||||||
|
paymentAddress1 varchar(35),
|
||||||
|
paymentAddress2 varchar(35),
|
||||||
|
paymentAddress3 varchar(35),
|
||||||
|
paymentCity varchar(35),
|
||||||
|
paymentState varchar(35),
|
||||||
|
paymentCountry varchar(35),
|
||||||
|
paymentCode varchar(35),
|
||||||
|
paymentPhoneNumber varchar(35),
|
||||||
|
paymentDriverId varchar(22) binary,
|
||||||
|
paymentDriverLabel varchar(35),
|
||||||
|
couponId varchar(22),
|
||||||
|
couponTitle varchar(35),
|
||||||
|
couponDiscount float,
|
||||||
|
taxes float,
|
||||||
|
dateOfPurchase datetime
|
||||||
|
)");
|
||||||
|
$session->db->write("create table transactionItem (
|
||||||
|
itemId varchar(22) binary not null primary key,
|
||||||
|
transactionId varchar(22) binary not null,
|
||||||
|
assetId varchar(22),
|
||||||
|
configuredTitle varchar(255),
|
||||||
|
options mediumText,
|
||||||
|
shippingAddressId varchar(22) binary,
|
||||||
|
shippingName varchar(35),
|
||||||
|
shippingAddress1 varchar(35),
|
||||||
|
shippingAddress2 varchar(35),
|
||||||
|
shippingAddress3 varchar(35),
|
||||||
|
shippingCity varchar(35),
|
||||||
|
shippingState varchar(35),
|
||||||
|
shippingCountry varchar(35),
|
||||||
|
shippingCode varchar(35),
|
||||||
|
shippingPhoneNumber varchar(35),
|
||||||
|
shippingTrackingNumber varchar(255),
|
||||||
|
shippingStatus varchar(35) not null default 'NotShipped',
|
||||||
|
shippingDate datetime,
|
||||||
|
quantity int not null default 1,
|
||||||
|
price float,
|
||||||
|
index transactionId (transactionId)
|
||||||
|
)");
|
||||||
|
$session->setting->add('shopMyPurchasesTemplateId','');
|
||||||
|
$session->setting->add('shopMyPurchaseDetailTemplateId','');
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
sub addAddressBook {
|
sub addAddressBook {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ A cart item is a manager of a WebGUI::Asset::Sku class that is put into a user's
|
||||||
|
|
||||||
use WebGUI::Shop::CartItem;
|
use WebGUI::Shop::CartItem;
|
||||||
|
|
||||||
my $item = WebGUI::Shop::CartItem->new($session, $cartId, $assetId);
|
my $item = WebGUI::Shop::CartItem->new($cart);
|
||||||
|
|
||||||
=head1 METHODS
|
=head1 METHODS
|
||||||
|
|
||||||
|
|
|
||||||
334
lib/WebGUI/Shop/Transaction.pm
Normal file
334
lib/WebGUI/Shop/Transaction.pm
Normal file
|
|
@ -0,0 +1,334 @@
|
||||||
|
package WebGUI::Shop::Transaction;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Class::InsideOut qw{ :std };
|
||||||
|
use WebGUI::Asset::Template;
|
||||||
|
use WebGUI::Exception::Shop;
|
||||||
|
use WebGUI::Form;
|
||||||
|
use WebGUI::International;
|
||||||
|
use WebGUI::Shop::AddressBook;
|
||||||
|
use WebGUI::Shop::TransactionItem;
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Package WebGUI::Shop::Transaction
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This package keeps records of every puchase made.
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use WebGUI::Shop::Transaction;
|
||||||
|
|
||||||
|
my $transaction = WebGUI::Shop::Transaction->new($session, $id);
|
||||||
|
|
||||||
|
=head1 METHODS
|
||||||
|
|
||||||
|
These subroutines are available from this package:
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
readonly session => my %session;
|
||||||
|
private properties => my %properties;
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 addItem ( cartitem )
|
||||||
|
|
||||||
|
Adds an item to the transaction. Returns a reference to the newly added item.
|
||||||
|
|
||||||
|
=head3 cartitem
|
||||||
|
|
||||||
|
A reference to a subclass of WebGUI::Shop::CartItem.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub addItem {
|
||||||
|
my ($self, $cartItem) = @_;
|
||||||
|
my $item = WebGUI::Shop::TransactionItem->create( $self, $cartItem);
|
||||||
|
return $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 create ( session, properties )
|
||||||
|
|
||||||
|
Constructor. Creates a new transaction object. Returns a reference to the object.
|
||||||
|
|
||||||
|
=head3 session
|
||||||
|
|
||||||
|
A reference to the current session.
|
||||||
|
|
||||||
|
=head3 properties
|
||||||
|
|
||||||
|
See update().
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub create {
|
||||||
|
my ($class, $session, $properties) = @_;
|
||||||
|
unless (defined $session && $session->isa("WebGUI::Session")) {
|
||||||
|
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
|
||||||
|
}
|
||||||
|
my $transactionId = $session->id->generate;
|
||||||
|
$session->db->write('insert into transaction (transactionId, userId, username, dateOfPurchase) values (?,?,?,now())',
|
||||||
|
[$transactionId, $session->user->userId, $session->user->username]);
|
||||||
|
my $self = $class->new($session, $transactionId);
|
||||||
|
$self->update($properties);
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 delete ()
|
||||||
|
|
||||||
|
Deletes this transaction and all transactionItems contained in it.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete {
|
||||||
|
my ($self) = @_;
|
||||||
|
foreach my $item (@{$self->getItems}) {
|
||||||
|
$item->delete;
|
||||||
|
}
|
||||||
|
$self->session->db->write("delete from transaction where transactionId=?",[$self->getId]);
|
||||||
|
undef $self;
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 formatCurrency ( amount )
|
||||||
|
|
||||||
|
Formats a number as a float with two digits after the decimal like 0.00.
|
||||||
|
|
||||||
|
=head3 amount
|
||||||
|
|
||||||
|
The number to format.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub formatCurrency {
|
||||||
|
my ($self, $amount) = @_;
|
||||||
|
return sprintf("%.2f", $amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 get ( [ property ] )
|
||||||
|
|
||||||
|
Returns a duplicated hash reference of this objectÕs data.
|
||||||
|
|
||||||
|
=head3 property
|
||||||
|
|
||||||
|
Any field ? returns the value of a field rather than the hash reference.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub get {
|
||||||
|
my ($self, $name) = @_;
|
||||||
|
if (defined $name) {
|
||||||
|
return $properties{id $self}{$name};
|
||||||
|
}
|
||||||
|
my %copyOfHashRef = %{$properties{id $self}};
|
||||||
|
return \%copyOfHashRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getId ()
|
||||||
|
|
||||||
|
Returns the unique id for this transaction.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getId {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->get("transactionId");
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getItem ( itemId )
|
||||||
|
|
||||||
|
Returns a reference to a WebGUI::Shop::TransactionItem object.
|
||||||
|
|
||||||
|
=head3 itemId
|
||||||
|
|
||||||
|
The id of the item to retrieve.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getItem {
|
||||||
|
my ($self, $itemId) = @_;
|
||||||
|
return WebGUI::Shop::TransactionItem->new($self, $itemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getItems ( )
|
||||||
|
|
||||||
|
Returns an array reference of WebGUI::Shop::TransactionItem objects that are in the transaction.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getItems {
|
||||||
|
my ($self) = @_;
|
||||||
|
my @itemsObjects = ();
|
||||||
|
my $items = $self->session->db->read("select itemId from transactionItem where transactionId=?",[$self->getId]);
|
||||||
|
while (my ($itemId) = $items->array) {
|
||||||
|
push(@itemsObjects, $self->getItem($itemId));
|
||||||
|
}
|
||||||
|
return \@itemsObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 new ( session, transactionId )
|
||||||
|
|
||||||
|
Constructor. Instanciates a transaction based upon a transactionId.
|
||||||
|
|
||||||
|
=head3 session
|
||||||
|
|
||||||
|
A reference to the current session.
|
||||||
|
|
||||||
|
=head3 transactionId
|
||||||
|
|
||||||
|
The unique id of a transaction to instanciate.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my ($class, $session, $transactionId) = @_;
|
||||||
|
unless (defined $session && $session->isa("WebGUI::Session")) {
|
||||||
|
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
|
||||||
|
}
|
||||||
|
unless (defined $transactionId) {
|
||||||
|
WebGUI::Error::InvalidParam->throw(error=>"Need a transactionId.");
|
||||||
|
}
|
||||||
|
my $transaction = $session->db->quickHashRef('select * from transaction where transactionId=?', [$transactionId]);
|
||||||
|
if ($transaction->{transactionId} eq "") {
|
||||||
|
WebGUI::Error::ObjectNotFound->throw(error=>"No such transaction.", id=>$transactionId);
|
||||||
|
}
|
||||||
|
my $self = register $class;
|
||||||
|
my $id = id $self;
|
||||||
|
$session{ $id } = $session;
|
||||||
|
$properties{ $id } = $transaction;
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 update ( properties )
|
||||||
|
|
||||||
|
Sets properties in the transaction.
|
||||||
|
|
||||||
|
=head3 properties
|
||||||
|
|
||||||
|
A hash reference that contains one of the following:
|
||||||
|
|
||||||
|
=head4 cart
|
||||||
|
|
||||||
|
A reference to a cart object. Will pull shipping method, shipping address, tax, items, total, and coupon from
|
||||||
|
it. Alternatively you can set manually any of the following properties that are set by cart automatically:
|
||||||
|
amount shippingAddressId shippingAddressName shippingAddress1 shippingAddress2 shippingAddress3 shippingCity
|
||||||
|
shippingState shippingCountry shippingCode shippingPhoneNumber shippingDriverId shippingDriverLabel shippingPrice
|
||||||
|
couponId couponTitle couponDiscount taxes
|
||||||
|
|
||||||
|
You can also use the addItem() method to manually add items to the transaction rather than passing a cart full of items.
|
||||||
|
|
||||||
|
=head4 paymentAddress
|
||||||
|
|
||||||
|
A reference to a WebGUI::Shop::Address that contains the payment address. Alternatively you can set manually
|
||||||
|
any of the properties that are set by payment address automatically: paymentAddressId paymentAddressName
|
||||||
|
paymentAddress1 paymentAddress2 paymentAddress3 paymentCity paymentState paymentCountry paymentCode
|
||||||
|
paymentPhoneNumber
|
||||||
|
|
||||||
|
=head4 paymentMethod
|
||||||
|
|
||||||
|
A reference to a WebGUI::Shop::PayDriver subclass that is used to make payment. Alternatively you can set
|
||||||
|
manually any of the properties that are set by payment method automatically: paymentDriverId paymentDriverLabel
|
||||||
|
|
||||||
|
=head4 isSuccessful
|
||||||
|
|
||||||
|
A boolean indicating whether the transaction was completed successfully.
|
||||||
|
|
||||||
|
=head4 transactionCode
|
||||||
|
|
||||||
|
The transaction id or code given by the payment gateway.
|
||||||
|
|
||||||
|
=head4 statusCode
|
||||||
|
|
||||||
|
The status code that came back from the payment gateway when trying to process the payment.
|
||||||
|
|
||||||
|
=head4 statusMessage
|
||||||
|
|
||||||
|
The extended status message that came back from the payment gateway when trying to process the payment.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub update {
|
||||||
|
my ($self, $newProperties) = @_;
|
||||||
|
my $id = id $self;
|
||||||
|
if (exists $newProperties->{cart}) {
|
||||||
|
my $cart = $newProperties->{cart};
|
||||||
|
$newProperties->{taxes} = $cart->getTaxes;
|
||||||
|
my $address = $cart->getShippingAddress;
|
||||||
|
$newProperties->{shippingAddressId} = $address->getId;
|
||||||
|
$newProperties->{shippingAddressName} = $address->get('name');
|
||||||
|
$newProperties->{shippingAddress1} = $address->get('address1');
|
||||||
|
$newProperties->{shippingAddress2} = $address->get('address2');
|
||||||
|
$newProperties->{shippingAddress3} = $address->get('address3');
|
||||||
|
$newProperties->{shippingCity} = $address->get('city');
|
||||||
|
$newProperties->{shippingState} = $address->get('state');
|
||||||
|
$newProperties->{shippingCountry} = $address->get('country');
|
||||||
|
$newProperties->{shippingCode} = $address->get('code');
|
||||||
|
$newProperties->{shippingPhoneNumber} = $address->get('phoneNumber');
|
||||||
|
my $shipper = $cart->getShipper;
|
||||||
|
$newProperties->{shippingDriverId} = $shipper->getId;
|
||||||
|
$newProperties->{shippingDriverLabel} = $shipper->get('label');
|
||||||
|
$newProperties->{shippingPrice} = $shipper->calculate($cart);
|
||||||
|
$newProperties->{couponId} = $cart->get('couponId');
|
||||||
|
$newProperties->{couponTitle} = '';
|
||||||
|
$newProperties->{couponDiscount} = '';
|
||||||
|
$newProperties->{amount} = $cart->getSubtotal + $newProperties->{couponDiscount} + $newProperties->{shippingPrice} + $newProperties->{taxes};
|
||||||
|
foreach my $item (@{$cart->getItems}) {
|
||||||
|
$self->addItem({item=>$item});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exists $newProperties->{paymentAddress}) {
|
||||||
|
my $address = $newProperties->{paymentAddress};
|
||||||
|
$newProperties->{paymentAddressId} = $address->getId;
|
||||||
|
$newProperties->{paymentAddressName} = $address->get('name');
|
||||||
|
$newProperties->{paymentAddress1} = $address->get('address1');
|
||||||
|
$newProperties->{paymentAddress2} = $address->get('address2');
|
||||||
|
$newProperties->{paymentAddress3} = $address->get('address3');
|
||||||
|
$newProperties->{paymentCity} = $address->get('city');
|
||||||
|
$newProperties->{paymentState} = $address->get('state');
|
||||||
|
$newProperties->{paymentCountry} = $address->get('country');
|
||||||
|
$newProperties->{paymentCode} = $address->get('code');
|
||||||
|
$newProperties->{paymentPhoneNumber} = $address->get('phoneNumber');
|
||||||
|
}
|
||||||
|
if (exists $newProperties->{paymentMethod}) {
|
||||||
|
my $pay = $newProperties->{paymentMethod};
|
||||||
|
$newProperties->{paymentDriverId} = $pay->getId;
|
||||||
|
$newProperties->{paymentDriverLabel} = $pay->get('label');
|
||||||
|
}
|
||||||
|
my @fields = (qw( isSuccessful transactionCode statusCode statusMessage amount shippingAddressId
|
||||||
|
shippingAddressName shippingAddress1 shippingAddress2 shippingAddress3 shippingCity shippingState
|
||||||
|
shippingCountry shippingCode shippingPhoneNumber shippingDriverId shippingDriverLabel
|
||||||
|
shippingPrice paymentAddressId paymentAddressName
|
||||||
|
paymentAddress1 paymentAddress2 paymentAddress3 paymentCity paymentState paymentCountry paymentCode
|
||||||
|
paymentPhoneNumber paymentDriverId paymentDriverLabel couponId couponTitle couponDiscount taxes ));
|
||||||
|
foreach my $field (@fields) {
|
||||||
|
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
|
||||||
|
}
|
||||||
|
$self->session->db->setRow("transaction","transactionId",$properties{$id});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1;
|
||||||
252
lib/WebGUI/Shop/TransactionItem.pm
Normal file
252
lib/WebGUI/Shop/TransactionItem.pm
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
package WebGUI::Shop::TransactionItem;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Class::InsideOut qw{ :std };
|
||||||
|
use JSON;
|
||||||
|
use WebGUI::DateTime;
|
||||||
|
use WebGUI::Exception::Shop;
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Package WebGUI::Shop::TransactionItem
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Each transaction item represents a sku that was purchased or attempted to be purchased.
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use WebGUI::Shop::TransactionItem;
|
||||||
|
|
||||||
|
my $item = WebGUI::Shop::TransactionItem->new($transaction);
|
||||||
|
|
||||||
|
=head1 METHODS
|
||||||
|
|
||||||
|
These subroutines are available from this package:
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
readonly transaction => my %transaction;
|
||||||
|
private properties => my %properties;
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 create ( transaction, properties)
|
||||||
|
|
||||||
|
Constructor. Adds an item to the transaction. Returns a reference to the item.
|
||||||
|
|
||||||
|
=head3 transaction
|
||||||
|
|
||||||
|
A reference to WebGUI::Shop::Transaction object.
|
||||||
|
|
||||||
|
=head3 properties
|
||||||
|
|
||||||
|
See update() for details.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub create {
|
||||||
|
my ($class, $transaction, $properties) = @_;
|
||||||
|
unless (defined $transaction && $transaction->isa("WebGUI::Shop::Transaction")) {
|
||||||
|
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Shop::Transaction", got=>(ref $transaction), error=>"Need a transaction.");
|
||||||
|
}
|
||||||
|
unless (defined $properties && ref $properties eq "HASH") {
|
||||||
|
WebGUI::Error::InvalidParam->throw(param=>$properties, error=>"Need a properties hash reference.");
|
||||||
|
}
|
||||||
|
my $itemId = $transaction->session->id->generate;
|
||||||
|
$transaction->session->db->write('insert into transactionItem (itemId, transactionId) values (?,?)', [$itemId, $transaction->getId]);
|
||||||
|
my $self = $class->new($transaction, $itemId);
|
||||||
|
$self->update($properties);
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 delete ( )
|
||||||
|
|
||||||
|
Removes this item from the transaction.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub delete {
|
||||||
|
my $self = shift;
|
||||||
|
$self->transaction->session->db->deleteRow("transactionItem","itemId",$self->getId);
|
||||||
|
undef $self;
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 get ( [ property ] )
|
||||||
|
|
||||||
|
Returns a duplicated hash reference of this object’s data.
|
||||||
|
|
||||||
|
=head3 property
|
||||||
|
|
||||||
|
Any field − returns the value of a field rather than the hash reference.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub get {
|
||||||
|
my ($self, $name) = @_;
|
||||||
|
if (defined $name) {
|
||||||
|
if ($name eq "options") {
|
||||||
|
my $options = $properties{id $self}{$name};
|
||||||
|
if ($options eq "") {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return JSON::from_json($properties{id $self}{$name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $properties{id $self}{$name};
|
||||||
|
}
|
||||||
|
my %copyOfHashRef = %{$properties{id $self}};
|
||||||
|
return \%copyOfHashRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getId ()
|
||||||
|
|
||||||
|
Returns the unique id of this item.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getId {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->get("itemId");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getSku ( )
|
||||||
|
|
||||||
|
Returns an instanciated WebGUI::Asset::Sku object for this item.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getSku {
|
||||||
|
my ($self) = @_;
|
||||||
|
my $asset = WebGUI::Asset->newByDynamicClass($self->transaction->session, $self->get("assetId"));
|
||||||
|
$asset->applyOptions($self->get("options"));
|
||||||
|
return $asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 new ( transaction, itemId )
|
||||||
|
|
||||||
|
Constructor. Instanciates a transaction item based upon itemId.
|
||||||
|
|
||||||
|
=head3 transaction
|
||||||
|
|
||||||
|
A reference to the current transaction
|
||||||
|
|
||||||
|
=head3 itemId
|
||||||
|
|
||||||
|
The unique id of the item to instanciate.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my ($class, $transaction, $itemId) = @_;
|
||||||
|
unless (defined $transaction && $transaction->isa("WebGUI::Shop::Transaction")) {
|
||||||
|
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Shop::Transaction", got=>(ref $transaction), error=>"Need a transaction.");
|
||||||
|
}
|
||||||
|
unless (defined $itemId) {
|
||||||
|
WebGUI::Error::InvalidParam->throw(error=>"Need an itemId.");
|
||||||
|
}
|
||||||
|
my $item = $transaction->session->db->quickHashRef('select * from transactionItem where itemId=?', [$itemId]);
|
||||||
|
if ($item->{itemId} eq "") {
|
||||||
|
WebGUI::Error::ObjectNotFound->throw(error=>"Item not found.", id=>$itemId);
|
||||||
|
}
|
||||||
|
if ($item->{transactionId} ne $transaction->getId) {
|
||||||
|
WebGUI::Error::ObjectNotFound->throw(error=>"Item not in this transaction.", id=>$itemId);
|
||||||
|
}
|
||||||
|
my $self = register $class;
|
||||||
|
my $id = id $self;
|
||||||
|
$transaction{ $id } = $transaction;
|
||||||
|
$properties{ $id } = $item;
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 transaction ( )
|
||||||
|
|
||||||
|
Returns a reference to the transaction object.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 update ( properties )
|
||||||
|
|
||||||
|
Sets properties of the transaction item.
|
||||||
|
|
||||||
|
=head3 properties
|
||||||
|
|
||||||
|
A hash reference that contains one of the following:
|
||||||
|
|
||||||
|
=head4 item
|
||||||
|
|
||||||
|
A reference to a WebGUI::Shop::CartItem. Alternatively you can manually pass in any of the following
|
||||||
|
fields that would be created automatically by this object: assetId configuredTitle options shippingAddressId
|
||||||
|
shippingName shippingAddress1 shippingAddress2 shippingAddress3 shippingCity shippingState shippingCountry
|
||||||
|
shippingCode shippingPhoneNumber quantity price
|
||||||
|
|
||||||
|
=head4 shippingTrackingNumber
|
||||||
|
|
||||||
|
A tracking number that is used by the shipping method for this transaction.
|
||||||
|
|
||||||
|
=head4 shippingStatus
|
||||||
|
|
||||||
|
The status of this item. The default is 'NotShipped'. Other statuses include: Cancelled, BackOrdered, Shipped
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub update {
|
||||||
|
my ($self, $newProperties) = @_;
|
||||||
|
my $id = id $self;
|
||||||
|
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} = $sku->getConfiguredTitle;
|
||||||
|
my $address = $item->getShippingAddress;
|
||||||
|
$newProperties->{shippingAddressId} = $address->getId;
|
||||||
|
$newProperties->{shippingAddressName} = $address->get('name');
|
||||||
|
$newProperties->{shippingAddress1} = $address->get('address1');
|
||||||
|
$newProperties->{shippingAddress2} = $address->get('address2');
|
||||||
|
$newProperties->{shippingAddress3} = $address->get('address3');
|
||||||
|
$newProperties->{shippingCity} = $address->get('city');
|
||||||
|
$newProperties->{shippingState} = $address->get('state');
|
||||||
|
$newProperties->{shippingCountry} = $address->get('country');
|
||||||
|
$newProperties->{shippingCode} = $address->get('code');
|
||||||
|
$newProperties->{shippingPhoneNumber} = $address->get('phoneNumber');
|
||||||
|
$newProperties->{quantity} = $item->get('quantity');
|
||||||
|
}
|
||||||
|
my @fields = (qw(assetId configuredTitle options shippingAddressId shippingTrackingNumber shippingStatus
|
||||||
|
shippingName shippingAddress1 shippingAddress2 shippingAddress3 shippingCity shippingState
|
||||||
|
shippingCountry shippingCode shippingPhoneNumber quantity price));
|
||||||
|
foreach my $field (@fields) {
|
||||||
|
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
|
||||||
|
}
|
||||||
|
if (exists $newProperties->{options} && ref($newProperties->{options}) eq "HASH") {
|
||||||
|
$properties{$id}{options} = JSON::to_json($newProperties->{options});
|
||||||
|
}
|
||||||
|
if (exists $newProperties->{shippingStatus}) {
|
||||||
|
$properties{$id}{shippingDate} = WebGUI::DateTime->new($self->transaction->session,time())->toDatabase;
|
||||||
|
}
|
||||||
|
$self->transaction->session->db->setRow("transactionItem","itemId",$properties{$id});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1;
|
||||||
202
t/Shop/Transaction.t
Normal file
202
t/Shop/Transaction.t
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
# vim:syntax=perl
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
# WebGUI is Copyright 2001-2008 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
|
||||||
|
#------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Tests the transaction backend for the shop.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
use FindBin;
|
||||||
|
use strict;
|
||||||
|
use lib "$FindBin::Bin/../lib";
|
||||||
|
use Test::More;
|
||||||
|
use Test::Deep;
|
||||||
|
use WebGUI::Test; # Must use this before any other WebGUI modules
|
||||||
|
use WebGUI::Session;
|
||||||
|
use WebGUI::Shop::Transaction;
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# Init
|
||||||
|
my $session = WebGUI::Test->session;
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
plan tests => 64; # Increment this number for each test you create
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# put your tests here
|
||||||
|
|
||||||
|
my $transaction = WebGUI::Shop::Transaction->create($session,{
|
||||||
|
amount => 40,
|
||||||
|
shippingAddressId => 'xxx1',
|
||||||
|
shippingAddressName => 'abc',
|
||||||
|
shippingAddress1 => 'def',
|
||||||
|
shippingAddress2 => 'hij',
|
||||||
|
shippingAddress3 => 'lmn',
|
||||||
|
shippingCity => 'opq',
|
||||||
|
shippingState => 'wxy',
|
||||||
|
shippingCountry => 'z',
|
||||||
|
shippingCode => '53333',
|
||||||
|
shippingPhoneNumber => '123456',
|
||||||
|
shippingDriverId => 'xxx2',
|
||||||
|
shippingDriverLabel => 'foo',
|
||||||
|
shippingPrice => 5,
|
||||||
|
paymentAddressId => 'xxx3',
|
||||||
|
paymentAddressName => 'abc1',
|
||||||
|
paymentAddress1 => 'def1',
|
||||||
|
paymentAddress2 => 'hij1',
|
||||||
|
paymentAddress3 => 'lmn1',
|
||||||
|
paymentCity => 'opq1',
|
||||||
|
paymentState => 'wxy1',
|
||||||
|
paymentCountry => 'z1',
|
||||||
|
paymentCode => '66666',
|
||||||
|
paymentPhoneNumber => '908765',
|
||||||
|
paymentDriverId => 'xxx4',
|
||||||
|
paymentDriverLabel => 'kkk',
|
||||||
|
couponId => 'xxx5',
|
||||||
|
couponTitle => 'title1',
|
||||||
|
couponDiscount => -5,
|
||||||
|
taxes => 7,
|
||||||
|
});
|
||||||
|
|
||||||
|
# objects work
|
||||||
|
isa_ok($transaction, "WebGUI::Shop::Transaction");
|
||||||
|
isa_ok($transaction->session, "WebGUI::Session");
|
||||||
|
|
||||||
|
|
||||||
|
# basic transaction properties
|
||||||
|
is($transaction->get("amount"), 40, "set and get amount");
|
||||||
|
is($transaction->get("shippingAddressId"), 'xxx1', "set and get shipping address id");
|
||||||
|
is($transaction->get("shippingAddressName"), 'abc', "set and get shipping address name");
|
||||||
|
is($transaction->get("shippingAddress1"), 'def', "set and get shipping address 1");
|
||||||
|
is($transaction->get("shippingAddress2"), 'hij', "set and get shipping address 2");
|
||||||
|
is($transaction->get("shippingAddress3"), 'lmn', "set and get shipping address 3");
|
||||||
|
is($transaction->get("shippingCity"), 'opq', "set and get shipping city");
|
||||||
|
is($transaction->get("shippingState"), 'wxy', "set and get shipping state");
|
||||||
|
is($transaction->get("shippingCountry"), 'z', "set and get shipping country");
|
||||||
|
is($transaction->get("shippingCode"), '53333', "set and get shipping code");
|
||||||
|
is($transaction->get("shippingPhoneNumber"), '123456', "set and get shipping phone number");
|
||||||
|
is($transaction->get("shippingDriverId"), 'xxx2', "set and get shipping driver id");
|
||||||
|
is($transaction->get("shippingDriverLabel"), 'foo', "set and get shipping driver label");
|
||||||
|
is($transaction->get("shippingPrice"), 5, "set and get shipping price");
|
||||||
|
is($transaction->get("paymentAddressId"), 'xxx3', "set and get payment address id");
|
||||||
|
is($transaction->get("paymentAddressName"), 'abc1', "set and get payment address name");
|
||||||
|
is($transaction->get("paymentAddress1"), 'def1', "set and get payment address 1");
|
||||||
|
is($transaction->get("paymentAddress2"), 'hij1', "set and get payment address 2");
|
||||||
|
is($transaction->get("paymentAddress3"), 'lmn1', "set and get payment address 3");
|
||||||
|
is($transaction->get("paymentCity"), 'opq1', "set and get payment city");
|
||||||
|
is($transaction->get("paymentState"), 'wxy1', "set and get payment state");
|
||||||
|
is($transaction->get("paymentCountry"), 'z1', "set and get payment country");
|
||||||
|
is($transaction->get("paymentCode"), '66666', "set and get payment code");
|
||||||
|
is($transaction->get("paymentPhoneNumber"), '908765', "set and get payment phone number");
|
||||||
|
is($transaction->get("paymentDriverId"), 'xxx4', "set and get payment driver id");
|
||||||
|
is($transaction->get("paymentDriverLabel"), 'kkk', "set and get payment driver label");
|
||||||
|
is($transaction->get("couponId"), 'xxx5', "set and get coupon id");
|
||||||
|
is($transaction->get("couponTitle"), 'title1', "set and get coupon title");
|
||||||
|
is($transaction->get("couponDiscount"), -5, "set and get coupon discount");
|
||||||
|
is($transaction->get("taxes"), 7, "set and get taxes");
|
||||||
|
|
||||||
|
|
||||||
|
$transaction->update({
|
||||||
|
isSuccessful => 1,
|
||||||
|
transactionCode => 'yyy',
|
||||||
|
statusCode => 'jd31',
|
||||||
|
statusMessage => 'was a success',
|
||||||
|
});
|
||||||
|
|
||||||
|
is($transaction->get("isSuccessful"), 1,"update and get isSuccessful");
|
||||||
|
is($transaction->get("transactionCode"), 'yyy',"update and get transaction code");
|
||||||
|
is($transaction->get("statusCode"), 'jd31',"update and get status code");
|
||||||
|
is($transaction->get("statusMessage"), 'was a success',"update and get status message");
|
||||||
|
|
||||||
|
# make sure new() works
|
||||||
|
my $tcopy = WebGUI::Shop::Transaction->new($session, $transaction->getId);
|
||||||
|
|
||||||
|
isa_ok($tcopy, "WebGUI::Shop::Transaction");
|
||||||
|
is($tcopy->getId, $transaction->getId, "is it the same object");
|
||||||
|
|
||||||
|
|
||||||
|
# basic item properties
|
||||||
|
my $item = $transaction->addItem({
|
||||||
|
assetId => 'a',
|
||||||
|
configuredTitle => 'b',
|
||||||
|
options => {color=>'blue'},
|
||||||
|
shippingAddressId => 'c',
|
||||||
|
shippingName => 'd',
|
||||||
|
shippingAddress1 => 'e',
|
||||||
|
shippingAddress2 => 'f',
|
||||||
|
shippingAddress3 => 'g',
|
||||||
|
shippingCity => 'h',
|
||||||
|
shippingState => 'i',
|
||||||
|
shippingCountry => 'j',
|
||||||
|
shippingCode => 'k',
|
||||||
|
shippingPhoneNumber => 'l',
|
||||||
|
quantity => 5,
|
||||||
|
price => 33,
|
||||||
|
});
|
||||||
|
|
||||||
|
isa_ok($item, "WebGUI::Shop::TransactionItem");
|
||||||
|
isa_ok($item->transaction, "WebGUI::Shop::Transaction");
|
||||||
|
|
||||||
|
is($item->get("assetId"), 'a', "set and get asset id");
|
||||||
|
is($item->get("configuredTitle"), 'b', "set and get configured title");
|
||||||
|
cmp_deeply($item->get("options"), {color=>'blue'}, "set and get options");
|
||||||
|
is($item->get("shippingAddressId"), 'c', "set and get shipping address id");
|
||||||
|
is($item->get("shippingName"), 'd', "set and get shipping name");
|
||||||
|
is($item->get("shippingAddress1"), 'e', "set and get shipping address 1");
|
||||||
|
is($item->get("shippingAddress2"), 'f', "set and get shipping address 2");
|
||||||
|
is($item->get("shippingAddress3"), 'g', "set and get shipping address 3");
|
||||||
|
is($item->get("shippingCity"), 'h', "set and get shipping city");
|
||||||
|
is($item->get("shippingState"), 'i', "set and get shipping state");
|
||||||
|
is($item->get("shippingCountry"), 'j', "set and get shipping country");
|
||||||
|
is($item->get("shippingCode"), 'k', "set and get shipping code");
|
||||||
|
is($item->get("shippingPhoneNumber"), 'l', "set and get shipping phone number");
|
||||||
|
is($item->get("quantity"), 5, "set and get quantity");
|
||||||
|
is($item->get("price"), 33, "set and get price");
|
||||||
|
|
||||||
|
$item->update({
|
||||||
|
shippingTrackingNumber => 'adfs',
|
||||||
|
shippingStatus => 'BackOrdered',
|
||||||
|
});
|
||||||
|
|
||||||
|
is($item->get("shippingTrackingNumber"), 'adfs', "update and get shipping tracking number");
|
||||||
|
is($item->get("shippingStatus"), 'BackOrdered', "update and get shipping status");
|
||||||
|
|
||||||
|
# make sure shipping date is updated when shipping status is changed
|
||||||
|
like($item->get("shippingDate"), qr/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/, "shipping date is set");
|
||||||
|
my $dateNow = $item->get('shippingDate');
|
||||||
|
sleep(1);
|
||||||
|
$item->update({shippingStatus=>'Cancelled'});
|
||||||
|
isnt($item->get('shippingDate'), $dateNow, 'shipping date is updated');
|
||||||
|
|
||||||
|
# make sure new() works
|
||||||
|
my $icopy = $transaction->getItem($item->getId);
|
||||||
|
isa_ok($icopy, "WebGUI::Shop::TransactionItem");
|
||||||
|
is($icopy->getId, $item->getId, "items are the same");
|
||||||
|
|
||||||
|
# get itmes
|
||||||
|
is(scalar @{$transaction->getItems}, 1, "can retrieve items");
|
||||||
|
|
||||||
|
# delete
|
||||||
|
$item->delete;
|
||||||
|
is(scalar @{$transaction->getItems}, 0, "can delete items");
|
||||||
|
|
||||||
|
$transaction->delete;
|
||||||
|
is($session->db->quickScalar("select transactionId from transaction where transactionId=?",[$transaction->getId]), undef, "can delete transactions");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# Cleanup
|
||||||
|
END {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue