kivitendo/SL/DB/Manager/PriceRuleItem.pm @ a140dece
9589ecd7 | Sven Schöling | # This file has been auto-generated only because it didn't exist.
|
||
# Feel free to modify it at will; it will not be overwritten automatically.
|
||||
package SL::DB::Manager::PriceRuleItem;
|
||||
use strict;
|
||||
use SL::DB::Helper::Manager;
|
||||
use base qw(SL::DB::Helper::Manager);
|
||||
sub object_class { 'SL::DB::PriceRuleItem' }
|
||||
__PACKAGE__->make_manager_methods;
|
||||
use SL::Locale::String qw(t8);
|
||||
cdb719c4 | Sven Schöling | use List::Util qw(first);
|
||
use SL::DB::CustomVariableConfig;
|
||||
9589ecd7 | Sven Schöling | |||
my %ops = (
|
||||
49eebab7 | Sven Schöling | 'num' => { eq => '=', le => '<=', ge => '>=' },
|
||
9589ecd7 | Sven Schöling | 'date' => { eq => '=', lt => '<', gt => '>' },
|
||
);
|
||||
f7e3b59b | Sven Schöling | my @types = (
|
||
{ type => 'customer', description => t8('Customer'), customer => 1, vendor => 0, data_type => 'int', data => sub { $_[0]->customer->id }, },
|
||||
{ type => 'vendor', description => t8('Vendor'), customer => 0, vendor => 1, data_type => 'int', data => sub { $_[0]->vendor->id }, },
|
||||
{ type => 'business', description => t8('Type of Business'), customer => 1, vendor => 1, data_type => 'int', data => sub { $_[0]->customervendor->business_id }, exclude_nulls => 1 },
|
||||
{ type => 'reqdate', description => t8('Reqdate'), customer => 1, vendor => 1, data_type => 'date', data => sub { $_[0]->reqdate }, ops => 'date' },
|
||||
{ type => 'transdate', description => t8('Transdate'), customer => 1, vendor => 1, data_type => 'date', data => sub { $_[0]->transdate }, ops => 'date' },
|
||||
{ type => 'part', description => t8('Part'), customer => 1, vendor => 1, data_type => 'int', data => sub { $_[1]->part->id }, },
|
||||
{ type => 'pricegroup', description => t8('Pricegroup'), customer => 1, vendor => 1, data_type => 'int', data => sub { $_[1]->pricegroup_id }, exclude_nulls => 1 },
|
||||
{ type => 'partsgroup', description => t8('Partsgroup'), customer => 1, vendor => 1, data_type => 'int', data => sub { $_[1]->part->partsgroup_id }, exclude_nulls => 1 },
|
||||
{ type => 'qty', description => t8('Qty'), customer => 1, vendor => 1, data_type => 'num', data => sub { $_[1]->qty }, ops => 'num' },
|
||||
9589ecd7 | Sven Schöling | );
|
||
c51a1ebc | Sven Schöling | # text, textfield, htmlfield, bool are not supported
|
||
our %price_rule_type_by_cvar_type = (
|
||||
select => 'text',
|
||||
customer => 'int',
|
||||
vendor => 'int',
|
||||
part => 'int',
|
||||
number => 'num',
|
||||
date => 'date',
|
||||
text => undef,
|
||||
textfield => undef,
|
||||
htmlfield => undef,
|
||||
bool => undef,
|
||||
);
|
||||
3b2ffa1f | Jan Büren | # ITEM.part.cvar_by_name(var.config.name)
|
||
9589ecd7 | Sven Schöling | sub not_matching_sql_and_values {
|
||
my ($class, %params) = @_;
|
||||
die 'must be called with a customer/vendor type' unless $params{type};
|
||||
0fe023a4 | Sven Schöling | my @args = @params{'record', 'record_item'};
|
||
9589ecd7 | Sven Schöling | |||
my (@tokens, @values);
|
||||
f7e3b59b | Sven Schöling | for my $def (@types, cached_cvar_types()) {
|
||
my $type = $def->{type};
|
||||
9589ecd7 | Sven Schöling | next unless $def->{$params{type}};
|
||
0fe023a4 | Sven Schöling | my $value = $def->{data}->(@args);
|
||
9589ecd7 | Sven Schöling | |||
f7e3b59b | Sven Schöling | my $type_token = $def->{cvar_config} ? "custom_variable_configs_id = '$def->{cvar_config}'" : "type = '$type'";
|
||
0fe023a4 | Sven Schöling | if ($def->{exclude_nulls} && !defined $value) {
|
||
f7e3b59b | Sven Schöling | push @tokens, $type_token;
|
||
0fe023a4 | Sven Schöling | } else {
|
||
9589ecd7 | Sven Schöling | my @sub_tokens;
|
||
0fe023a4 | Sven Schöling | if ($def->{ops}) {
|
||
my $ops = $ops{$def->{ops}};
|
||||
for (keys %$ops) {
|
||||
19586862 | Sven Schöling | push @sub_tokens, "op = '$_' AND NOT ? $ops->{$_} value_$def->{data_type}";
|
||
0fe023a4 | Sven Schöling | push @values, $value;
|
||
}
|
||||
} else {
|
||||
push @sub_tokens, "NOT value_$def->{data_type} = ?";
|
||||
push @values, $value;
|
||||
9589ecd7 | Sven Schöling | }
|
||
f7e3b59b | Sven Schöling | push @tokens, "$type_token AND (@{[ join(' OR ', map qq|($_)|, @sub_tokens) ]})";
|
||
9589ecd7 | Sven Schöling | }
|
||
}
|
||||
return join(' OR ', map "($_)", @tokens), @values;
|
||||
}
|
||||
f7e3b59b | Sven Schöling | sub cached_cvar_types {
|
||
my $cache = $::request->cache("SL::DB::PriceRuleItem::cvar_types", []);
|
||||
@$cache = generate_cvar_types() if !@$cache;
|
||||
@$cache
|
||||
}
|
||||
# we only generate cvar types for cvar price_rules that are actually used to keep the query smaller
|
||||
# these are cached per request
|
||||
sub generate_cvar_types {
|
||||
de558fa6 | Sven Schöling | my @supported_cvar_modules = qw(CT Contacts IC Projects ShipTo);
|
||
my $cvar_configs = SL::DB::Manager::CustomVariableConfig->get_all(query => [ module => \@supported_cvar_modules ]);
|
||||
f7e3b59b | Sven Schöling | |||
my @types;
|
||||
697fe153 | Sven Schöling | my %ops_by_cvar_type = (
|
||
number => 'num',
|
||||
date => 'date',
|
||||
);
|
||||
f7e3b59b | Sven Schöling | for my $config (@$cvar_configs) {
|
||
697fe153 | Sven Schöling | # cvars can be pretty complicated, but most of that luckily doesn't affect price rule filtering:
|
||
# - editable flags are copied to submodule entries - so those need to be preferred
|
||||
# - cvars may be invalid - but in that case they just won't get crated so we won't find any
|
||||
# - cvars may be restricted to partgroups, but again, in that case we simply won't find any
|
||||
# - cvars may have different types of values () just like price_rule_items, but the ->value
|
||||
# accessor already handles that, so we only need to set the price_rule type accordingly
|
||||
my %data_by_module = (
|
||||
IC => sub {
|
||||
raw_value(
|
||||
$config->processed_flags->{editable}
|
||||
? $_[1]->cvar_by_name($config->name)->value
|
||||
: $_[1]->part->cvar_by_name($config->name)->value
|
||||
);
|
||||
},
|
||||
CT => sub {
|
||||
raw_value(
|
||||
$_[0]->customervendor->cvar_by_name($config->name)->value
|
||||
);
|
||||
},
|
||||
Projects => sub {
|
||||
raw_value(
|
||||
$_[1]->project ? $_[1]->project->cvar_by_name($config->name)->value :
|
||||
$_[0]->globalproject ? $_[0]->globalproject->cvar_by_name($config->name)->value : undef
|
||||
);
|
||||
},
|
||||
Contacts => sub {
|
||||
raw_value(
|
||||
$_[0]->contact ? $_[0]->contact->cvar_by_name($config->name)->value : undef
|
||||
);
|
||||
},
|
||||
de558fa6 | Sven Schöling | ShipTo => sub {
|
||
raw_value(
|
||||
$_[0]->custom_shipto ? $_[0]->custom_shipto->cvar_by_name($config->name)->value :
|
||||
$_[0]->shipto ? $_[0]->shipto->cvar_by_name($config->name)->value : undef
|
||||
);
|
||||
},
|
||||
697fe153 | Sven Schöling | );
|
||
2191ef7f | Sven Schöling | my $data_type;
|
||
if (exists $price_rule_type_by_cvar_type{$config->type}) {
|
||||
# known but undef typedefs are ignored.
|
||||
# those cvar configs are not supported and can not be used in price rules
|
||||
$data_type = $price_rule_type_by_cvar_type{$config->type} or next;
|
||||
} else {
|
||||
b41d5e72 | Jan Büren | die "cvar type @{[$config->type]} " . $config->description . " is not supported in price rules";
|
||
2191ef7f | Sven Schöling | }
|
||
697fe153 | Sven Schöling | |||
my $ops = $ops_by_cvar_type{$config->type};
|
||||
f7e3b59b | Sven Schöling | |||
push @types, {
|
||||
type => "cvar_" . $config->id,
|
||||
description => $config->description,
|
||||
customer => 1,
|
||||
vendor => 1,
|
||||
697fe153 | Sven Schöling | data_type => $data_type,
|
||
data => $data_by_module{$config->module},
|
||||
f7e3b59b | Sven Schöling | exclude_nulls => 1,
|
||
cvar_config => $config->id,
|
||||
697fe153 | Sven Schöling | ops => $ops,
|
||
};
|
||||
f7e3b59b | Sven Schöling | }
|
||
@types;
|
||||
}
|
||||
697fe153 | Sven Schöling | sub raw_value {
|
||
my ($value) = @_;
|
||||
return if !defined $value;
|
||||
return $value->id if (ref $value) =~ /Part|Customer|Contact|Vendor|Project/;
|
||||
return $value if (ref $value) =~ /DateTime/;
|
||||
die "reference value unsupported for binding to price_rules, got ref " . ref $value if ref $value;
|
||||
$value;
|
||||
}
|
||||
9589ecd7 | Sven Schöling | sub get_all_types {
|
||
my ($class, $vc) = @_;
|
||||
c383fc0b | Sven Schöling | $vc
|
||
f7e3b59b | Sven Schöling | ? [ map { [ $_->{type}, $_->{description} ] } grep { $_->{$vc} } @types ]
|
||
: [ map { [ $_->{type}, $_->{description} ] } @types ]
|
||||
9589ecd7 | Sven Schöling | }
|
||
986282c1 | Sven Schöling | sub get_type {
|
||
f7e3b59b | Sven Schöling | grep { $_->{type} eq $_[1] } @types
|
||
986282c1 | Sven Schöling | }
|
||
sub filter_match {
|
||||
my ($self, $type, $value) = @_;
|
||||
f7e3b59b | Sven Schöling | my $type_def = first { $_->{type} eq $type } @types;
|
||
986282c1 | Sven Schöling | |||
if (!$type_def->{ops}) {
|
||||
my $evalue = $::form->get_standard_dbh->quote($value);
|
||||
return "value_$type_def->{data_type} = $evalue";
|
||||
} elsif ($type_def->{ops} eq 'date') {
|
||||
my $date_value = $::form->get_standard_dbh->quote(DateTime->from_kivitendo($value));
|
||||
return "
|
||||
(value_$type_def->{data_type} > $date_value AND op = 'lt') OR
|
||||
(value_$type_def->{data_type} < $date_value AND op = 'gt') OR
|
||||
(value_$type_def->{data_type} = $date_value AND op = 'eq')
|
||||
";
|
||||
} elsif ($type_def->{ops} eq 'num') {
|
||||
my $num_value = $::form->get_standard_dbh->quote($::form->parse_amount(\%::myconfig, $value));
|
||||
return "
|
||||
(value_$type_def->{data_type} >= $num_value AND op = 'le') OR
|
||||
(value_$type_def->{data_type} <= $num_value AND op = 'ge') OR
|
||||
(value_$type_def->{data_type} = $num_value AND op = 'eq')
|
||||
";
|
||||
}
|
||||
}
|
||||
9589ecd7 | Sven Schöling | 1;
|