340 lines
8.1 KiB
Perl
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;
|