webgui/lib/WebGUI/Shop/TaxDriver.pm
2011-04-05 08:42:15 -05:00

340 lines
8.1 KiB
Perl

package WebGUI::Shop::TaxDriver;
=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
=head1 NAME
Package WebGUI::Shop::TaxDriver
=head1 DESCRIPTION
This package is the base class for all modules which implement a tax driver.
=head1 SYNOPSIS
use WebGUI::Shop::TaxDriver;
my $taxDriver = WebGUI::Shop::TaxDriver->new($session);
=head1 METHODS
These subroutines are available from this package:
=cut
use strict;
use Class::InsideOut qw{ :std };
use JSON qw{ from_json to_json };
=head1 NAME
Package WebGUI::Shop::TaxDriver
=head1 DESCRIPTION
Base class for all modules which do tax calculations in the Shop.
=head1 SYNOPSIS
use base 'WebGUI::Shop::TaxDriver';
my $driver = WebGUI::Shop::TaxDriver->new($session);
=head1 METHODS
These subroutines are available from this package:
=cut
readonly session => my %session;
readonly messages => my %messages;
private options => my %options;
=head2 appendCartItemVars ( var, cartItem )
Adds tax driver specific template variables for the given cart item to the supplied hashref.
=head3 var
The template variable hash ref to add the tax vars to.
=head3 cartItem
The instanstance of WebGUI::Shop::CartItem to add the vars for.
=cut
sub appendCartItemVars {
my $self = shift;
my $var = shift;
my $item = shift;
WebGUI::Error::InvalidParam->throw( 'Must supply a hash ref' )
unless $var && ref $var eq 'HASH';
WebGUI::Error::InvalidObject->throw( expected => 'WebGUI::Shop::CartItem', got => ref $item, error => 'Must pass a cart item' )
unless $item && $item->isa( 'WebGUI::Shop::CartItem' );
my $sku = $item->getSku;
my $address = eval { $item->getShippingAddress };
my $taxRate = $self->getTaxRate( $sku, $address );
my $quantity = $item->get( 'quantity' );
my $price = $sku->getPrice;
my $tax = $price * $taxRate / 100;
$var->{ taxRate } = $taxRate;
$var->{ taxAmount } = $item->cart->formatCurrency( $tax );
$var->{ pricePlusTax } = $item->cart->formatCurrency( $price + $tax );
$var->{ extendedPricePlusTax } = $item->cart->formatCurrency( $quantity * ( $price + $tax ) );
}
#-----------------------------------------------------------
=head2 canManage ( )
Returns true if the current user can manage taxes.
=cut
sub canManage {
my $self = shift;
my $admin = WebGUI::Shop::Admin->new( $self->session );
return $admin->canManage;
}
#-----------------------------------------------------------
=head2 className {
Returns the class name of your plugin. You must overload this method in you own plugin.
=cut
sub className {
my $self = shift;
$self->session->log->fatal( "Tax plugin (".$self->className.") is required to overload the className method" );
return 'WebGUI::Shop::TaxDriver';
}
#-----------------------------------------------------------
=head2 get ( [ property ] )
Returns the value of the requested configuration property. Returns a hash ref of all property/value pairs when no
specific property is passed.
=head3 property
The property whose value should be returned.
=cut
sub get {
my $self = shift;
my $key = shift;
my $options = $options{ id $self };
# Return safe copy of options hash if no key is passed.
return { %{ $options } } unless $key;
# Return option if key is passed.
return $options->{ $key } if exists $options->{ $key };
# Key does not exist.
$self->session->log->warn( "Non-existant option [$key] was queried by tax plugin $self" );
return undef;
}
#-----------------------------------------------------------
=head2 getConfigurationScreen ( )
Returns the configuration screen that contains the configuration options for this plugin in the admin console.
=cut
sub getConfigurationScreen {
return 'This plugin has no configuration options';
}
#-----------------------------------------------------------
=head2 getTaxRate ( sku, [ address ] )
Returns the tax rate in percents (eg. 19 for a rate of 19%) for the given sku and shipping address. Your tax driver
must overload this method.
Note that address is optional and that it's up to your plugin to handle that case.
=head3 sku
The sku for which the tax rate must be determined. Should be a WebGUI::Asset::Sku::* instance.
=head3 address
Optional, the shipping address for which to calculate the tax. Must be an instance of WebGUI::Shop::Address.
=cut
sub getTaxRate {
my $self = shift;
$self->session->log->fatal("Tax plugin ". $self->className ." is required to overload getTaxRate");
}
#-----------------------------------------------------------
=head2 getTransactionTaxData ( sku, address )
Returns a hashref containing tax information that should be stored along with transaction items.
=head3 sku
The sku belonging to the transaction item.
=head3 address
The address belonging to the transaction item.
=cut
sub getTransactionTaxData {
my $self = shift;
my $config = {
className => $self->className,
};
return $config;
}
#-----------------------------------------------------------
=head2 getUserScreen ( )
Returns the screen for entering per user configuration for this tax driver.
=cut
sub getUserScreen {
return 'There are no tax options to configure.';
}
#-----------------------------------------------------------
=head2 skuFormDefinition ( )
Returns a hash ref containing the form definition for the per sku options for this tax driver.
=cut
sub skuFormDefinition {
return {};
}
#-------------------------------------------------------------------
=head2 new ( $session )
Constructor
=head3 session
Instanciated WebGUI::Session object.
=cut
sub new {
my $class = shift;
my $session = shift;
WebGUI::Error::InvalidObject->throw( expected => "WebGUI::Session", got => (ref $session), error => "Need a session." )
unless $session && $session->isa( 'WebGUI::Session' );
my $self = {};
bless $self, $class;
register $self;
my $id = id $self;
$session{ $id } = $session;
$messages{ $id } = [];
# Load plugin configuration
my $optionsJSON = $session->db->quickScalar( 'select options from taxDriver where className=?', [
$self->className,
] );
$options{ $id } = $optionsJSON ? from_json( $optionsJSON ) : {};
return $self;
}
#-------------------------------------------------------------------
=head2 processSkuFormPost ( )
Processes the form parameters defined in the skuFormDefinition method and returns a hash ref containing the result.
=cut
sub processSkuFormPost {
my $self = shift;
my $form = $self->session->form;
my $configuration = {};
my $definition = $self->skuFormDefinition;
foreach my $fieldName ( keys %{ $definition } ) {
my ($fieldType, $defaultValue) = @{ $definition->{ $fieldName } }{ qw{ fieldType defaultValue } };
$configuration->{ $fieldName } = $form->process( $fieldName, $fieldType, $defaultValue );
}
return $configuration;
}
#-----------------------------------------------------------
=head2 update ( properties )
Updates the properties of the tax driver according to those passed.
=head3 properties
Hash ref containing the properties to set.
=cut
sub update {
my $self = shift;
my $update = shift;
my $db = $self->session->db;
# update local options hash
$options{ id $self } = { %{ $options{ id $self } }, %{ $update } };
# Persist to db
$db->write( 'replace into taxDriver (className, options) values (?,?)', [
$self->className,
to_json( $options{ id $self } ),
] );
}
1;