|
use Test::More;
|
|
|
|
use strict;
|
|
|
|
use lib 't';
|
|
use utf8;
|
|
|
|
use Carp;
|
|
use Data::Dumper;
|
|
use Support::TestSetup;
|
|
use Test::Exception;
|
|
|
|
use SL::Controller::CustomVariableConfig;
|
|
|
|
use SL::Dev::ALL qw(:ALL);
|
|
use SL::DB::PriceRule;
|
|
use SL::DB::Project;
|
|
use SL::DB::CustomVariableConfig;
|
|
|
|
Support::TestSetup::login();
|
|
|
|
sub reset_db {
|
|
SL::DB::Manager::PriceRule->delete_all(all => 1);
|
|
SL::DB::Manager::CustomVariable->delete_all(all => 1);
|
|
SL::DB::Manager::CustomVariableConfig->delete_all(all => 1);
|
|
SL::DB::Manager::Order->delete_all(all => 1);
|
|
SL::DB::Manager::Shipto->delete_all(all => 1);
|
|
|
|
$::request->{_cache} = {};
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
# cvar price rules.
|
|
# a select cvar price rule for one specific value A
|
|
# and an order where the part has exactly that cvar set to first A and then B
|
|
|
|
my $cvar_config = SL::DB::CustomVariableConfig->new(
|
|
module => 'IC',
|
|
name => "test",
|
|
description => "test",
|
|
type => "select",
|
|
options => "A##B##C##D",
|
|
default_value => "D",
|
|
flags => "editable=0",
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
)->save->load;
|
|
|
|
my $name = "price for test A";
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $cvar_config,
|
|
value_text => "A",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
|
|
$order->items_sorted->[0]->part->cvar_by_name('test')->value("A");
|
|
$order->items_sorted->[0]->part->cvar_by_name('test')->save;
|
|
|
|
ok(1 == grep({ $_->{name} eq $name } @{ SL::DB::Manager::PriceRule->get_all_matching(record => $order, record_item => $order->items_sorted->[0]) }), "editable=0 price rule matches");
|
|
|
|
$order->items_sorted->[0]->part->cvar_by_name('test')->value("B");
|
|
$order->items_sorted->[0]->part->cvar_by_name('test')->save;
|
|
|
|
ok(0 == grep({ $_->{name} eq $name } @{ SL::DB::Manager::PriceRule->get_all_matching(record => $order, record_item => $order->items_sorted->[0]) }), "editable=0 price rule does not match");
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
# now try the same, but with an editable cvar config
|
|
|
|
my $cvar_config = SL::DB::CustomVariableConfig->new(
|
|
module => 'IC',
|
|
name => "test",
|
|
description => "test2",
|
|
type => "select",
|
|
options => "A##B##C##D",
|
|
default_value => "D",
|
|
flags => "editable=1",
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
)->save->load;
|
|
|
|
my $name = "price for test A";
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $cvar_config,
|
|
value_text => "A",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
|
|
$item->cvar_by_name('test')->value("A");
|
|
$item->cvar_by_name('test')->save;
|
|
|
|
ok(1 == grep({ $_->{name} eq $name } @{ SL::DB::Manager::PriceRule->get_all_matching(record => $order, record_item => $item) }), "editable=1 price rule matches");
|
|
|
|
$item->cvar_by_name('test')->value("B");
|
|
$item->cvar_by_name('test')->save;
|
|
|
|
ok(0 == grep({ $_->{name} eq $name } @{ SL::DB::Manager::PriceRule->get_all_matching(record => $order, record_item => $item) }), "editable=1 price rule does not match");
|
|
|
|
}
|
|
|
|
# structural test: check whether the registered CVar types in SL::DB::Manager::PriceRuleItem have all the possible types of SL::Controller::CustomVariableConfigs
|
|
for (@SL::Controller::CustomVariableConfig::types) {
|
|
ok(exists $SL::DB::Manager::PriceRuleItem::price_rule_type_by_cvar_type{$_}, "PriceRuleItem has cvar config type $_ registered");
|
|
}
|
|
|
|
# k, now for a more broad test:
|
|
#
|
|
# we can have these modules in cvars:
|
|
# - CT
|
|
# - Contact
|
|
# - IC
|
|
# - Project
|
|
# - ShipTo
|
|
#
|
|
# and the cvars themselves can have these types:
|
|
# - select
|
|
# - customer
|
|
# - vendor
|
|
# - part
|
|
# - integer
|
|
# - number
|
|
# - date
|
|
# - timestamp
|
|
#
|
|
# ...with the numeric and date ones also having comparison ops
|
|
#
|
|
#
|
|
# to be matched against all different record/record items
|
|
#
|
|
#
|
|
# testing all of that is too much, so this will do some combinations:
|
|
# 1. a cvar config
|
|
# 2. a price_rule that uses both
|
|
# 3. record + record item that either uses that or not
|
|
# 4. expected behaviour
|
|
{
|
|
sub test {
|
|
my ($price_rule, $record, $record_item, $comment, $expected_match) = @_;
|
|
|
|
# needed to clear cvar caches in price rule implementation
|
|
$::request->{_cache} = {};
|
|
|
|
my $matching_rules = SL::DB::Manager::PriceRule->get_all_matching(record => $record, record_item => $record_item);
|
|
my @does_match = grep { $_->{name} eq $price_rule->name } @$matching_rules;
|
|
|
|
if ($expected_match) {
|
|
ok(@does_match && $price_rule->name eq $does_match[0]->name, "$comment - expected match, got @does_match");
|
|
} else {
|
|
ok(!@does_match, "$comment - expected no match, got @does_match");
|
|
}
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "before critical customer date";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'CT',
|
|
type => 'date',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
)->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_date => DateTime->new(year => 2022, month => 12, day => 9),
|
|
op => "lt",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
|
|
test($price_rule, $order, $item, $name, 0);
|
|
|
|
$order->customer->cvar_by_name($name)->value(DateTime->new(year => 2022, month => 12, day => 12));
|
|
$order->customer->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- too late", 0);
|
|
|
|
$order->customer->cvar_by_name($name)->value(DateTime->new(year => 2022, month => 12, day => 5));
|
|
$order->customer->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- early", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "contact number equals 1234";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'Contacts',
|
|
type => 'number',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
)->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_num => 1234,
|
|
op => "eq",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
|
|
test($price_rule, $order, $item, "$name -- no contact", 0);
|
|
|
|
$order->contact(SL::DB::Contact->new)->save;
|
|
|
|
test($price_rule, $order, $item, "$name -- null", 0);
|
|
|
|
$order->contact->cvar_by_name($name)->value(45);
|
|
$order->contact->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching", 0);
|
|
|
|
$order->contact->cvar_by_name($name)->value(1234);
|
|
$order->contact->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "project part matches";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'Projects',
|
|
type => 'part',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
)->save->load;
|
|
|
|
my $part = new_part()->save;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_int => $part->id,
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $project1 = SL::DB::Project->new(
|
|
project_type => SL::DB::Manager::ProjectType->find_by(description => 'Standard'),
|
|
project_status => SL::DB::Manager::ProjectStatus->find_by(name => 'running'),
|
|
)->save->load;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
|
|
test($price_rule, $order, $item, "$name -- no project", 0);
|
|
|
|
$order->globalproject($project1)->save;
|
|
|
|
test($price_rule, $order, $item, "$name -- global project, but no value", 0);
|
|
|
|
$order->globalproject->cvar_by_name($name)->value($item->part);
|
|
$order->globalproject->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- global project, not matching", 0);
|
|
|
|
$order->globalproject->cvar_by_name($name)->value($part);
|
|
$order->globalproject->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- global project, matching", 1);
|
|
|
|
my $project2 = SL::DB::Project->new(
|
|
project_type => SL::DB::Manager::ProjectType->find_by(description => 'Standard'),
|
|
project_status => SL::DB::Manager::ProjectStatus->find_by(name => 'running'),
|
|
)->save->load;
|
|
|
|
$item->project($project2)->save;
|
|
|
|
test($price_rule, $order, $item, "$name -- item project, but no value", 0);
|
|
|
|
$item->project->cvar_by_name($name)->value($item->part);
|
|
$item->project->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- item project, not matching", 0);
|
|
|
|
$item->project->cvar_by_name($name)->value($part);
|
|
$item->project->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- item project, matching", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "part customer matches";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'IC',
|
|
type => 'customer',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $customer = new_customer()->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "vendor",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_int => $customer->id,
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_purchase_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
|
|
test($price_rule, $order, $item, "$name -- no value", 0);
|
|
|
|
$item->part->cvar_by_name($name)->value(new_customer());
|
|
$item->part->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching", 0);
|
|
|
|
$item->part->cvar_by_name($name)->value($customer);
|
|
$item->part->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "part number with default value 15 matches 15";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'IC',
|
|
type => 'number',
|
|
name => $name,
|
|
description => $name,
|
|
default_value => 15,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_num => 15,
|
|
op => "eq",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
|
|
test($price_rule, $order, $item, "$name -- default value", 1);
|
|
|
|
$item->part->cvar_by_name($name)->value(20);
|
|
$item->part->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching", 0);
|
|
|
|
$item->part->cvar_by_name($name)->value(15);
|
|
$item->part->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "shipto cvar and price rule matching that";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'ShipTo',
|
|
type => 'number',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_num => 15,
|
|
op => "eq",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
my $shipto = SL::DB::Shipto->new;
|
|
$order->shipto($shipto);
|
|
$order->save->load;
|
|
|
|
test($price_rule, $order, $item, "$name -- default value", 0);
|
|
|
|
$order->shipto->cvar_by_name($name)->value(20);
|
|
$order->shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching", 0);
|
|
|
|
$order->shipto->cvar_by_name($name)->value(15);
|
|
$order->shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "custom shipto cvar and price rule matching that";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'ShipTo',
|
|
type => 'number',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_num => 15,
|
|
op => "eq",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
my $shipto = SL::DB::Shipto->new(trans_id => $order->id, module => 'OE')->save;
|
|
|
|
ok(ref $order->custom_shipto eq 'SL::DB::Shipto', 'custom shipto is readable from order');
|
|
|
|
test($price_rule, $order, $item, "$name -- default value", 0);
|
|
|
|
$order->custom_shipto->cvar_by_name($name)->value(20);
|
|
$order->custom_shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching", 0);
|
|
|
|
$order->custom_shipto->cvar_by_name($name)->value(15);
|
|
$order->custom_shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "custom shipto cvar and price rule matching that";
|
|
|
|
my $config = SL::DB::CustomVariableConfig->new(
|
|
module => 'ShipTo',
|
|
type => 'number',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $price_rule = SL::DB::PriceRule->new(
|
|
name => $name,
|
|
price => 1,
|
|
type => "customer",
|
|
items => [
|
|
SL::DB::PriceRuleItem->new(
|
|
custom_variable_configs => $config,
|
|
value_num => 15,
|
|
op => "eq",
|
|
type => "cvar",
|
|
),
|
|
],
|
|
)->save;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
my $shipto1 = SL::DB::Shipto->new;
|
|
$order->shipto($shipto1);
|
|
my $shipto2 = SL::DB::Shipto->new(trans_id => $order->id, module => 'OE')->save;
|
|
$order->save->load;
|
|
|
|
test($price_rule, $order, $item, "$name -- default value", 0);
|
|
|
|
$order->custom_shipto->cvar_by_name($name)->value(20);
|
|
$order->custom_shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching custom", 0);
|
|
|
|
$order->shipto->cvar_by_name($name)->value(15);
|
|
$order->shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- not matching custom, matching shipto", 0);
|
|
|
|
$order->custom_shipto->cvar_by_name($name)->value(15);
|
|
$order->custom_shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching both", 1);
|
|
|
|
$order->shipto->cvar_by_name($name)->value(20);
|
|
$order->shipto->cvar_by_name($name)->save;
|
|
test($price_rule, $order, $item, "$name -- matching custom, not matching shipto", 1);
|
|
}
|
|
|
|
{
|
|
reset_db();
|
|
|
|
my $name = "no price rule, but cvars exist with module requirementsspecs or type text";
|
|
|
|
my $config1 = SL::DB::CustomVariableConfig->new(
|
|
module => 'RequirementSpecs',
|
|
type => 'number',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $config2 = SL::DB::CustomVariableConfig->new(
|
|
module => 'Customer',
|
|
type => 'text',
|
|
name => $name,
|
|
description => $name,
|
|
searchable => 0,
|
|
includeable => 0,
|
|
included_by_default => 0,
|
|
flags => '',
|
|
)->save->load;
|
|
|
|
my $order = create_sales_order()->save->load;
|
|
my $item = $order->items_sorted->[0];
|
|
$order->save->load;
|
|
|
|
test(undef, $order, $item, "$name -- nothing to match", 0);
|
|
}
|
|
}
|
|
|
|
reset_db();
|
|
|
|
done_testing();
|