Created
March 27, 2014 20:34
-
-
Save SysPete/9817984 to your computer and use it in GitHub Desktop.
old TaxZone.pm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use utf8; | |
package Interchange6::Schema::Result::TaxRule; | |
=head1 NAME | |
Interchange6::Schema::Result::TaxRule | |
=cut | |
use strict; | |
use warnings; | |
use DateTime; | |
use base 'DBIx::Class::Core'; | |
# to enable code references to be serialized | |
$Storable::Deparse = 1; | |
$Storable::Eval = 1; | |
# component load order is important so be careful here: | |
__PACKAGE__->load_components( | |
qw(InflateColumn::Serializer InflateColumn::DateTime TimeStamp)); | |
=head1 TABLE: C<tax_rules> | |
=cut | |
__PACKAGE__->table("tax_rules"); | |
=head1 DESCRIPTION | |
=head1 ACCESSORS | |
=head2 tax_rules_id | |
data_type: 'integer' | |
is_auto_increment: 1 | |
is_nullable: 0 | |
sequence: 'tax_rules_id_seq' | |
=head2 name | |
data_type: 'varchar' | |
is_nullable: 0 | |
size: 64 | |
=head2 priority | |
data_type: integer | |
is_nullable: 0 | |
default: 0 | |
=head2 last_rule | |
data_type: boolean | |
is_nullable: 0 | |
default: 1 | |
=head2 supplier_zone | |
data_type: integer | |
is_nullable: 0 | |
=head2 customer_zone | |
data_type: integer | |
is_nullable: 0 | |
=head2 business_customer | |
data_type: boolean | |
is_nullable: 1 | |
default: undef | |
=head2 product_type | |
data_type: varchar | |
is_nullable: 1 | |
size: 64 | |
=head2 tax_code | |
data_type: 'varchar' | |
is_nullable: 0 | |
size: 64 | |
=head2 valid_from | |
data_type: 'date' | |
set_on_create: 1 | |
is_nullable: 0 | |
=head2 valid_to | |
data_type: 'date' | |
is_nullable: 1 | |
=head2 coderef_rule | |
data_type: 'varchar' | |
size: 1024 | |
serializer_class: 'Storable' | |
is_nullable: 1 | |
WARNING: Here be dragons. If you think you need to use coderef_rule then make sure you have tested it thoroughly. This method might eat your cat and burn down your house. Do not run as root! See t/taxes.t in the distribution source for examples. | |
=cut | |
__PACKAGE__->add_columns( | |
"tax_rules_id", | |
{ | |
data_type => "integer", | |
is_auto_increment => 1, | |
is_nullable => 0, | |
sequence => "taxes_id_seq" | |
}, | |
"name", | |
{ data_type => "varchar", is_nullable => 0, size => 64 }, | |
"priority", | |
{ data_type => "integer", is_nullable => 0, default => 0 }, | |
"last_rule", | |
{ data_type => "boolean", is_nullable => 0, default => 1 }, | |
"supplier_zone", | |
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, | |
"customer_zone", | |
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, | |
"business_customer", | |
{ data_type => "boolean", is_nullable => 1, default => undef }, | |
"product_type", | |
{ data_type => "varchar", is_nullable => 1, size => 64 }, | |
"tax_code", | |
{ data_type => "varchar", is_nullable => 0, size => 64 }, | |
"valid_from", | |
{ data_type => "date", set_on_create => 1, is_nullable => 0 }, | |
"valid_to", | |
{ data_type => "date", is_nullable => 1 }, | |
"coderef_rule", | |
{ | |
data_type => "varchar", | |
size => 1024, | |
serializer_class => "Storable", | |
is_nullable => 1 | |
}, | |
); | |
=head1 METHODS | |
=head1 PRIMARY KEY | |
=over 4 | |
=item * L</tax_rules_id> | |
=back | |
=cut | |
__PACKAGE__->set_primary_key("tax_rules_id"); | |
=head1 RELATIONS | |
=head2 supplier_zone | |
Type: belongs_to | |
=cut | |
__PACKAGE__->belongs_to( | |
"supplier_zone", | |
"Interchange6::Schema::Result::TaxZone", | |
{ "foreign.tax_zones_id" => "self.supplier_zone" } | |
); | |
=head2 customer_zone | |
Type: belongs_to | |
=cut | |
__PACKAGE__->belongs_to( | |
"customer_zone", | |
"Interchange6::Schema::Result::TaxZone", | |
{ "foreign.tax_zones_id" => "self.customer_zone" } | |
); | |
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use utf8; | |
package Interchange6::Schema::ResultSet::TaxRule; | |
=head1 NAME | |
Interchange6::Schema::ResultSet::TaxRule | |
=cut | |
=head1 SYNOPSIS | |
Provides extra accessor methods for L<Interchange6::Schema::Result::TaxRule> | |
=cut | |
use strict; | |
use warnings; | |
use Moo; | |
extends 'DBIx::Class::ResultSet'; | |
with('Interchange6::Schema::Role::Errors'); | |
use DateTime; | |
use MooX::Types::MooseLike; | |
use MooX::Types::MooseLike::Base qw/ArrayRef HashRef/; | |
use MooX::HandlesVia; | |
use namespace::clean; | |
=head1 METHODS | |
=head2 taxes | |
Should not be called directly - use get_taxes method. | |
=cut | |
has taxes => ( | |
is => 'ro', | |
isa => ArrayRef [HashRef], | |
default => sub { [] }, | |
handles_via => 'Array', | |
handles => { | |
clear_taxes => 'clear', | |
_add_tax => 'push', | |
is_empty => 'is_empty', | |
} | |
); | |
=head2 get_taxes | |
When passed a hashref of args it returns an arrayref of taxes. | |
Arguments: | |
=over 4 | |
item * supplier_zone name - required | |
item * customer_zone name - required | |
item * price - required | |
item * product_type - optional | |
item * business_customer (boolean) - optional | |
item * tax_included (boolean) - optional with default 0 | |
item * business_customer (boolean) - optional with default 0 | |
=back | |
=cut | |
sub get_taxes { | |
my ( $self, $args ) = @_; | |
$self->clear_errors; | |
$self->clear_taxes; | |
my @return; | |
my $schema = $self->result_source->schema; | |
my $dtf = $schema->storage->datetime_parser; | |
my $dt = DateTime->today; | |
# set tax_included to 0 if not defined | |
$args->{'tax_included'} = 0 unless defined $args->{'tax_included'}; | |
# check for required args | |
unless ( defined $args->{'supplier_country'} ) { | |
# supplier country must be defined | |
$self->add_error( "missing arg supplier_country" ); | |
return; | |
} | |
unless ( defined $args->{'customer_country'} ) { | |
# customer country must be defined | |
$self->add_error( "missing arg customer_country" ); | |
return; | |
} | |
unless ( defined $args->{'price'} ) { | |
# price country must be defined | |
$self->add_error( "missing arg price" ); | |
return; | |
} | |
my $rules = $self->search( | |
{ | |
valid_from => { '<=', $dtf->format_datetime($dt) }, | |
valid_to => [ undef, { '>=', $dtf->format_datetime($dt) } ], | |
}, | |
{ order_by => 'priority' } | |
); | |
RULES: while ( my $rule = $rules->next ) { | |
# start with checks that don't hit the DB | |
# check product_type | |
if ( defined $rule->product_type ) { | |
next RULES | |
unless ( defined $args->{'product_type'} | |
&& $args->{'product_type'} eq $rule->product_type ); | |
} | |
# check business_customer | |
if ( defined $rule->business_customer ) { | |
# defined so does rule match arg? | |
$args->{'business_customer'} = 0 | |
unless $args->{'business_customer'}; | |
next RULES | |
unless $args->{'business_customer'} == $rule->business_customer; | |
} | |
# checks that might hit the DB from here on | |
# check supplier_country and supplier_state | |
if ( defined $rule->supplier_zone ) { | |
# rule has supplier_zone | |
# supplier_country must be in zone | |
next RULES | |
unless $rule->supplier_zone->has_country( | |
$args->{'supplier_country'} ); | |
if ( $rule->supplier_zone->state_count ) { | |
# supplier_zone has states in it | |
# supplier_state must be defined and in zone | |
next RULES | |
unless ( | |
defined $args->{'supplier_state'} | |
&& $rule->supplier_zone->has_state( | |
$args->{'supplier_state'} | |
) | |
); | |
} | |
} | |
# check customer_country and customer_state | |
if ( defined $rule->customer_zone ) { | |
# rule has customer_zone | |
# customer_country must be in zone | |
next RULES | |
unless $rule->customer_zone->has_country( | |
$args->{'customer_country'} ); | |
if ( $rule->customer_zone->state_count ) { | |
# customer_zone has states in it | |
# customer_state must be defined and in zone | |
next RULES | |
unless ( | |
defined $args->{'customer_state'} | |
&& $rule->customer_zone->has_state( | |
$args->{'customer_state'} | |
) | |
); | |
} | |
} | |
# coderef_rule - last thing before we work out the taxes | |
if ( defined $rule->coderef_rule ) { | |
my $coderef = $rule->coderef_rule; | |
next RULES unless &$coderef( $self, $args, $rule ); | |
} | |
# if we got this far then this rule is applicable so work out the taxes | |
my $tax = $schema->resultset('Tax')->current_tax( $rule->tax_code ); | |
unless ( defined $tax ) { | |
$self->add_error( "tax_code not found: " . $rule->tax_code ); | |
return; | |
} | |
my $tax_amount = $tax->calculate( | |
{ | |
price => $args->{'price'}, | |
tax_included => $args->{'tax_included'} | |
} | |
); | |
$self->_add_tax( | |
{ | |
tax_amount => $tax_amount, | |
tax_rule => $rule->name, | |
tax_code => $rule->tax_code, | |
tax_percent => $tax->tax_percent, | |
} | |
); | |
last RULES if $rule->last_rule; | |
} | |
return $self->taxes; | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hexfusion was here