Remove an extra my from Shop::Cart.
Add the getTaxRates method to Tax, with tests. Add some calculate code to Tax, with tests, which don't pass yet.
This commit is contained in:
parent
52d2c63271
commit
2bc6cd49a7
4 changed files with 138 additions and 3 deletions
|
|
@ -72,7 +72,7 @@ sub create {
|
||||||
}
|
}
|
||||||
my $cartId = $session->db->quickScalar("select cartId from cart where sessionId=?",[$session->getId]);
|
my $cartId = $session->db->quickScalar("select cartId from cart where sessionId=?",[$session->getId]);
|
||||||
return $class->new($session, $cartId) if (defined $cartId);
|
return $class->new($session, $cartId) if (defined $cartId);
|
||||||
my $cartId = $session->id->generate;
|
$cartId = $session->id->generate;
|
||||||
$session->db->write('insert into cart (cartId, sessionId) values (?,?)', [$cartId, $session->getId]);
|
$session->db->write('insert into cart (cartId, sessionId) values (?,?)', [$cartId, $session->getId]);
|
||||||
return $class->new($session, $cartId);
|
return $class->new($session, $cartId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@ use Class::InsideOut qw{ :std };
|
||||||
use WebGUI::Text;
|
use WebGUI::Text;
|
||||||
use WebGUI::Storage;
|
use WebGUI::Storage;
|
||||||
use WebGUI::Exception::Shop;
|
use WebGUI::Exception::Shop;
|
||||||
|
use WebGUI::Shop::Cart;
|
||||||
|
use WebGUI::Shop::CartItem;
|
||||||
|
use WebGUI::Shop::AddressBook;
|
||||||
|
use WebGUI::Shop::Address;
|
||||||
|
use List::Util qw{sum};
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
|
|
@ -89,7 +94,23 @@ sub calculate {
|
||||||
my $cart = shift;
|
my $cart = shift;
|
||||||
WebGUI::Error::InvalidParam->throw(error => 'Must pass in a WebGUI::Shop::Cart object')
|
WebGUI::Error::InvalidParam->throw(error => 'Must pass in a WebGUI::Shop::Cart object')
|
||||||
unless ref($cart) eq 'WebGUI::Shop::Cart';
|
unless ref($cart) eq 'WebGUI::Shop::Cart';
|
||||||
return;
|
my $book = WebGUI::Shop::AddressBook->create($self->session);
|
||||||
|
my $address = WebGUI::Shop::Address->new($book, $cart->get('shippingAddressId'));
|
||||||
|
my $tax = 0;
|
||||||
|
foreach my $item (@{ $cart->getItems }) {
|
||||||
|
my $sku = $item->getSku;
|
||||||
|
my $unitPrice = $sku->getPrice;
|
||||||
|
my $quantity = $item->get('quantity');
|
||||||
|
my $taxables = $self->getTaxRates($address);
|
||||||
|
use Data::Dumper;
|
||||||
|
warn Dumper $taxables;
|
||||||
|
my $itemTax = sum(@{$taxables}) / 100; ##Form a percentage
|
||||||
|
warn "unitPrice: $unitPrice\n";
|
||||||
|
warn "quantity : $quantity\n";
|
||||||
|
warn "itemTax : $itemTax\n";
|
||||||
|
$tax += $unitPrice * $quantity * $itemTax;
|
||||||
|
}
|
||||||
|
return $tax;
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
@ -160,6 +181,30 @@ sub getItems {
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
=head2 getTaxRates ( $address )
|
||||||
|
|
||||||
|
Given a WebGUI::Shop::Address object, return all rates associated with the address as an arrayRef.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub getTaxRates {
|
||||||
|
my $self = shift;
|
||||||
|
my $address = shift;
|
||||||
|
WebGUI::Error::InvalidObject->throw(error => 'Need an address.', expected=>'WebGUI::Shop::Address', got=>(ref $address))
|
||||||
|
unless ref($address) eq 'WebGUI::Shop::Address';
|
||||||
|
my $result = $self->session->db->buildArrayRef(
|
||||||
|
q{
|
||||||
|
select taxRate from tax where
|
||||||
|
(field='state' and value=?)
|
||||||
|
OR (field='country' and value=?)
|
||||||
|
OR (field='code' and value=?)
|
||||||
|
},
|
||||||
|
[$address->get('state'), $address->get('country'), $address->get('code')]);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
=head2 importTaxData ( $filePath )
|
=head2 importTaxData ( $filePath )
|
||||||
|
|
||||||
Import tax information from the specified file in CSV format. The
|
Import tax information from the specified file in CSV format. The
|
||||||
|
|
|
||||||
84
t/Shop/Tax.t
84
t/Shop/Tax.t
|
|
@ -23,6 +23,8 @@ use Exception::Class;
|
||||||
use WebGUI::Test; # Must use this before any other WebGUI modules
|
use WebGUI::Test; # Must use this before any other WebGUI modules
|
||||||
use WebGUI::Session;
|
use WebGUI::Session;
|
||||||
use WebGUI::Text;
|
use WebGUI::Text;
|
||||||
|
use WebGUI::Shop::Cart;
|
||||||
|
use WebGUI::Shop::AddressBook;
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
# Init
|
# Init
|
||||||
|
|
@ -31,7 +33,7 @@ my $session = WebGUI::Test->session;
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
# Tests
|
# Tests
|
||||||
|
|
||||||
my $tests = 64;
|
my $tests = 68;
|
||||||
plan tests => 1 + $tests;
|
plan tests => 1 + $tests;
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
|
@ -366,6 +368,57 @@ cmp_deeply(
|
||||||
'importTaxData: error handling for file that that cannot be read',
|
'importTaxData: error handling for file that that cannot be read',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# getTaxRates
|
||||||
|
#
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
##Set up the tax information
|
||||||
|
$taxer->importTaxData(
|
||||||
|
WebGUI::Test->getTestCollateralPath('taxTables/largeTaxTable.csv')
|
||||||
|
),
|
||||||
|
my $book = WebGUI::Shop::AddressBook->create($session);
|
||||||
|
my $taxingAddress = $book->addAddress({
|
||||||
|
label => 'taxing',
|
||||||
|
city => 'Madison',
|
||||||
|
state => 'WI',
|
||||||
|
code => '53701',
|
||||||
|
country => 'USA',
|
||||||
|
});
|
||||||
|
my $taxFreeAddress = $book->addAddress({
|
||||||
|
label => 'no tax',
|
||||||
|
city => 'Portland',
|
||||||
|
state => 'OR',
|
||||||
|
code => '97123',
|
||||||
|
country => 'USA',
|
||||||
|
});
|
||||||
|
|
||||||
|
eval { $taxer->getTaxRates(); };
|
||||||
|
$e = Exception::Class->caught();
|
||||||
|
isa_ok($e, 'WebGUI::Error::InvalidObject', 'calculate: error handling for not sending a cart');
|
||||||
|
cmp_deeply(
|
||||||
|
$e,
|
||||||
|
methods(
|
||||||
|
error => 'Need an address.',
|
||||||
|
got => '',
|
||||||
|
expected => 'WebGUI::Shop::Address',
|
||||||
|
),
|
||||||
|
'importTaxData: error handling for file that does not exist in the filesystem',
|
||||||
|
);
|
||||||
|
|
||||||
|
cmp_deeply(
|
||||||
|
$taxer->getTaxRates($taxingAddress),
|
||||||
|
[5, 0.5],
|
||||||
|
'getTaxRates: return correct data for a state with tax data'
|
||||||
|
);
|
||||||
|
|
||||||
|
cmp_deeply(
|
||||||
|
$taxer->getTaxRates($taxFreeAddress),
|
||||||
|
[0.0],
|
||||||
|
'getTaxRates: return correct data for a state with no tax data'
|
||||||
|
);
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
#
|
#
|
||||||
# calculate
|
# calculate
|
||||||
|
|
@ -379,6 +432,32 @@ is($e->error, 'Must pass in a WebGUI::Shop::Cart object', 'calculate: error hand
|
||||||
|
|
||||||
##Build a cart, add some Donation SKUs to it. Set one to be taxable.
|
##Build a cart, add some Donation SKUs to it. Set one to be taxable.
|
||||||
|
|
||||||
|
my $cart = WebGUI::Shop::Cart->create($session);
|
||||||
|
$cart->update({ shippingAddressId => $taxingAddress->getId});
|
||||||
|
|
||||||
|
##Set up the tax information
|
||||||
|
$taxer->importTaxData(
|
||||||
|
WebGUI::Test->getTestCollateralPath('taxTables/goodTaxTable.csv')
|
||||||
|
),
|
||||||
|
|
||||||
|
my $taxableDonation = WebGUI::Asset->getRoot($session)->addChild({
|
||||||
|
className => 'WebGUI::Asset::Sku::Donation',
|
||||||
|
title => 'Taxable donation',
|
||||||
|
defaultPrice => 100.00,
|
||||||
|
});
|
||||||
|
|
||||||
|
$cart->addItem($taxableDonation);
|
||||||
|
|
||||||
|
foreach my $item (@{ $cart->getItems }) {
|
||||||
|
$item->setQuantity(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $tax = $taxer->calculate($cart);
|
||||||
|
is($tax, 5.5, 'calculate: simple tax calculation on 1 item in the cart');
|
||||||
|
|
||||||
|
$taxableDonation->purge;
|
||||||
|
$cart->delete;
|
||||||
|
$book->delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _grabTaxData {
|
sub _grabTaxData {
|
||||||
|
|
@ -395,5 +474,8 @@ sub _grabTaxData {
|
||||||
# Cleanup
|
# Cleanup
|
||||||
END {
|
END {
|
||||||
$session->db->write('delete from tax');
|
$session->db->write('delete from tax');
|
||||||
|
$session->db->write('delete from cart');
|
||||||
|
$session->db->write('delete from addressBook');
|
||||||
|
$session->db->write('delete from address');
|
||||||
$storage->delete;
|
$storage->delete;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
8
t/supporting_collateral/taxTables/largeTaxTable.csv
Normal file
8
t/supporting_collateral/taxTables/largeTaxTable.csv
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
field,value,taxRate
|
||||||
|
state,WI,5.0
|
||||||
|
code,53701,0.5
|
||||||
|
code,53702,0.5
|
||||||
|
code,53703,0.5
|
||||||
|
code,53704,0.5
|
||||||
|
state,CA,7.25
|
||||||
|
code,97123,0.0
|
||||||
|
Loading…
Add table
Add a link
Reference in a new issue