10 use Support::TestSetup;
13 use SL::Controller::CustomVariableConfig;
15 use SL::Dev::ALL qw(:ALL);
16 use SL::DB::PriceRule;
18 use SL::DB::CustomVariableConfig;
20 Support::TestSetup::login();
23 SL::DB::Manager::PriceRule->delete_all(all => 1);
24 SL::DB::Manager::CustomVariable->delete_all(all => 1);
25 SL::DB::Manager::CustomVariableConfig->delete_all(all => 1);
26 SL::DB::Manager::Order->delete_all(all => 1);
27 SL::DB::Manager::Shipto->delete_all(all => 1);
29 $::request->{_cache} = {};
36 # a select cvar price rule for one specific value A
37 # and an order where the part has exactly that cvar set to first A and then B
39 my $cvar_config = SL::DB::CustomVariableConfig->new(
42 description => "test",
44 options => "A##B##C##D",
46 flags => "editable=0",
49 included_by_default => 0,
52 my $name = "price for test A";
54 my $price_rule = SL::DB::PriceRule->new(
59 SL::DB::PriceRuleItem->new(
60 custom_variable_configs => $cvar_config,
67 my $order = create_sales_order()->save->load;
69 $order->items_sorted->[0]->part->cvar_by_name('test')->value("A");
70 $order->items_sorted->[0]->part->cvar_by_name('test')->save;
72 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");
74 $order->items_sorted->[0]->part->cvar_by_name('test')->value("B");
75 $order->items_sorted->[0]->part->cvar_by_name('test')->save;
77 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");
83 # now try the same, but with an editable cvar config
85 my $cvar_config = SL::DB::CustomVariableConfig->new(
88 description => "test2",
90 options => "A##B##C##D",
92 flags => "editable=1",
95 included_by_default => 0,
98 my $name = "price for test A";
100 my $price_rule = SL::DB::PriceRule->new(
105 SL::DB::PriceRuleItem->new(
106 custom_variable_configs => $cvar_config,
113 my $order = create_sales_order()->save->load;
114 my $item = $order->items_sorted->[0];
116 $item->cvar_by_name('test')->value("A");
117 $item->cvar_by_name('test')->save;
119 ok(1 == grep({ $_->{name} eq $name } @{ SL::DB::Manager::PriceRule->get_all_matching(record => $order, record_item => $item) }), "editable=1 price rule matches");
121 $item->cvar_by_name('test')->value("B");
122 $item->cvar_by_name('test')->save;
124 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");
128 # structural test: check whether the registered CVar types in SL::DB::Manager::PriceRuleItem have all the possible types of SL::Controller::CustomVariableConfigs
129 for (@SL::Controller::CustomVariableConfig::types) {
130 ok(exists $SL::DB::Manager::PriceRuleItem::price_rule_type_by_cvar_type{$_}, "PriceRuleItem has cvar config type $_ registered");
133 # k, now for a more broad test:
135 # we can have these modules in cvars:
142 # and the cvars themselves can have these types:
152 # ...with the numeric and date ones also having comparison ops
155 # to be matched against all different record/record items
158 # testing all of that is too much, so this will do some combinations:
160 # 2. a price_rule that uses both
161 # 3. record + record item that either uses that or not
162 # 4. expected behaviour
165 my ($price_rule, $record, $record_item, $comment, $expected_match) = @_;
167 # needed to clear cvar caches in price rule implementation
168 $::request->{_cache} = {};
170 my $matching_rules = SL::DB::Manager::PriceRule->get_all_matching(record => $record, record_item => $record_item);
171 my @does_match = grep { $_->{name} eq $price_rule->name } @$matching_rules;
173 if ($expected_match) {
174 ok(@does_match && $price_rule->name eq $does_match[0]->name, "$comment - expected match, got @does_match");
176 ok(!@does_match, "$comment - expected no match, got @does_match");
183 my $name = "before critical customer date";
185 my $config = SL::DB::CustomVariableConfig->new(
189 description => $name,
192 included_by_default => 0,
195 my $price_rule = SL::DB::PriceRule->new(
200 SL::DB::PriceRuleItem->new(
201 custom_variable_configs => $config,
202 value_date => DateTime->new(year => 2022, month => 12, day => 9),
209 my $order = create_sales_order()->save->load;
210 my $item = $order->items_sorted->[0];
212 test($price_rule, $order, $item, $name, 0);
214 $order->customer->cvar_by_name($name)->value(DateTime->new(year => 2022, month => 12, day => 12));
215 $order->customer->cvar_by_name($name)->save;
216 test($price_rule, $order, $item, "$name -- too late", 0);
218 $order->customer->cvar_by_name($name)->value(DateTime->new(year => 2022, month => 12, day => 5));
219 $order->customer->cvar_by_name($name)->save;
220 test($price_rule, $order, $item, "$name -- early", 1);
226 my $name = "contact number equals 1234";
228 my $config = SL::DB::CustomVariableConfig->new(
229 module => 'Contacts',
232 description => $name,
235 included_by_default => 0,
238 my $price_rule = SL::DB::PriceRule->new(
243 SL::DB::PriceRuleItem->new(
244 custom_variable_configs => $config,
252 my $order = create_sales_order()->save->load;
253 my $item = $order->items_sorted->[0];
255 test($price_rule, $order, $item, "$name -- no contact", 0);
257 $order->contact(SL::DB::Contact->new)->save;
259 test($price_rule, $order, $item, "$name -- null", 0);
261 $order->contact->cvar_by_name($name)->value(45);
262 $order->contact->cvar_by_name($name)->save;
263 test($price_rule, $order, $item, "$name -- not matching", 0);
265 $order->contact->cvar_by_name($name)->value(1234);
266 $order->contact->cvar_by_name($name)->save;
267 test($price_rule, $order, $item, "$name -- matching", 1);
273 my $name = "project part matches";
275 my $config = SL::DB::CustomVariableConfig->new(
276 module => 'Projects',
279 description => $name,
282 included_by_default => 0,
285 my $part = new_part()->save;
287 my $price_rule = SL::DB::PriceRule->new(
292 SL::DB::PriceRuleItem->new(
293 custom_variable_configs => $config,
294 value_int => $part->id,
300 my $project1 = SL::DB::Project->new(
301 project_type => SL::DB::Manager::ProjectType->find_by(description => 'Standard'),
302 project_status => SL::DB::Manager::ProjectStatus->find_by(name => 'running'),
305 my $order = create_sales_order()->save->load;
306 my $item = $order->items_sorted->[0];
308 test($price_rule, $order, $item, "$name -- no project", 0);
310 $order->globalproject($project1)->save;
312 test($price_rule, $order, $item, "$name -- global project, but no value", 0);
314 $order->globalproject->cvar_by_name($name)->value($item->part);
315 $order->globalproject->cvar_by_name($name)->save;
316 test($price_rule, $order, $item, "$name -- global project, not matching", 0);
318 $order->globalproject->cvar_by_name($name)->value($part);
319 $order->globalproject->cvar_by_name($name)->save;
320 test($price_rule, $order, $item, "$name -- global project, matching", 1);
322 my $project2 = SL::DB::Project->new(
323 project_type => SL::DB::Manager::ProjectType->find_by(description => 'Standard'),
324 project_status => SL::DB::Manager::ProjectStatus->find_by(name => 'running'),
327 $item->project($project2)->save;
329 test($price_rule, $order, $item, "$name -- item project, but no value", 0);
331 $item->project->cvar_by_name($name)->value($item->part);
332 $item->project->cvar_by_name($name)->save;
333 test($price_rule, $order, $item, "$name -- item project, not matching", 0);
335 $item->project->cvar_by_name($name)->value($part);
336 $item->project->cvar_by_name($name)->save;
337 test($price_rule, $order, $item, "$name -- item project, matching", 1);
343 my $name = "part customer matches";
345 my $config = SL::DB::CustomVariableConfig->new(
349 description => $name,
352 included_by_default => 0,
356 my $customer = new_customer()->save->load;
358 my $price_rule = SL::DB::PriceRule->new(
363 SL::DB::PriceRuleItem->new(
364 custom_variable_configs => $config,
365 value_int => $customer->id,
371 my $order = create_purchase_order()->save->load;
372 my $item = $order->items_sorted->[0];
374 test($price_rule, $order, $item, "$name -- no value", 0);
376 $item->part->cvar_by_name($name)->value(new_customer());
377 $item->part->cvar_by_name($name)->save;
378 test($price_rule, $order, $item, "$name -- not matching", 0);
380 $item->part->cvar_by_name($name)->value($customer);
381 $item->part->cvar_by_name($name)->save;
382 test($price_rule, $order, $item, "$name -- matching", 1);
388 my $name = "part number with default value 15 matches 15";
390 my $config = SL::DB::CustomVariableConfig->new(
394 description => $name,
398 included_by_default => 0,
402 my $price_rule = SL::DB::PriceRule->new(
407 SL::DB::PriceRuleItem->new(
408 custom_variable_configs => $config,
416 my $order = create_sales_order()->save->load;
417 my $item = $order->items_sorted->[0];
419 test($price_rule, $order, $item, "$name -- default value", 1);
421 $item->part->cvar_by_name($name)->value(20);
422 $item->part->cvar_by_name($name)->save;
423 test($price_rule, $order, $item, "$name -- not matching", 0);
425 $item->part->cvar_by_name($name)->value(15);
426 $item->part->cvar_by_name($name)->save;
427 test($price_rule, $order, $item, "$name -- matching", 1);
433 my $name = "shipto cvar and price rule matching that";
435 my $config = SL::DB::CustomVariableConfig->new(
439 description => $name,
442 included_by_default => 0,
446 my $price_rule = SL::DB::PriceRule->new(
451 SL::DB::PriceRuleItem->new(
452 custom_variable_configs => $config,
460 my $order = create_sales_order()->save->load;
461 my $item = $order->items_sorted->[0];
462 my $shipto = SL::DB::Shipto->new;
463 $order->shipto($shipto);
466 test($price_rule, $order, $item, "$name -- default value", 0);
468 $order->shipto->cvar_by_name($name)->value(20);
469 $order->shipto->cvar_by_name($name)->save;
470 test($price_rule, $order, $item, "$name -- not matching", 0);
472 $order->shipto->cvar_by_name($name)->value(15);
473 $order->shipto->cvar_by_name($name)->save;
474 test($price_rule, $order, $item, "$name -- matching", 1);
480 my $name = "custom shipto cvar and price rule matching that";
482 my $config = SL::DB::CustomVariableConfig->new(
486 description => $name,
489 included_by_default => 0,
493 my $price_rule = SL::DB::PriceRule->new(
498 SL::DB::PriceRuleItem->new(
499 custom_variable_configs => $config,
507 my $order = create_sales_order()->save->load;
508 my $item = $order->items_sorted->[0];
509 my $shipto = SL::DB::Shipto->new(trans_id => $order->id, module => 'OE')->save;
511 ok(ref $order->custom_shipto eq 'SL::DB::Shipto', 'custom shipto is readable from order');
513 test($price_rule, $order, $item, "$name -- default value", 0);
515 $order->custom_shipto->cvar_by_name($name)->value(20);
516 $order->custom_shipto->cvar_by_name($name)->save;
517 test($price_rule, $order, $item, "$name -- not matching", 0);
519 $order->custom_shipto->cvar_by_name($name)->value(15);
520 $order->custom_shipto->cvar_by_name($name)->save;
521 test($price_rule, $order, $item, "$name -- matching", 1);
527 my $name = "custom shipto cvar and price rule matching that";
529 my $config = SL::DB::CustomVariableConfig->new(
533 description => $name,
536 included_by_default => 0,
540 my $price_rule = SL::DB::PriceRule->new(
545 SL::DB::PriceRuleItem->new(
546 custom_variable_configs => $config,
554 my $order = create_sales_order()->save->load;
555 my $item = $order->items_sorted->[0];
556 my $shipto1 = SL::DB::Shipto->new;
557 $order->shipto($shipto1);
558 my $shipto2 = SL::DB::Shipto->new(trans_id => $order->id, module => 'OE')->save;
561 test($price_rule, $order, $item, "$name -- default value", 0);
563 $order->custom_shipto->cvar_by_name($name)->value(20);
564 $order->custom_shipto->cvar_by_name($name)->save;
565 test($price_rule, $order, $item, "$name -- not matching custom", 0);
567 $order->shipto->cvar_by_name($name)->value(15);
568 $order->shipto->cvar_by_name($name)->save;
569 test($price_rule, $order, $item, "$name -- not matching custom, matching shipto", 0);
571 $order->custom_shipto->cvar_by_name($name)->value(15);
572 $order->custom_shipto->cvar_by_name($name)->save;
573 test($price_rule, $order, $item, "$name -- matching both", 1);
575 $order->shipto->cvar_by_name($name)->value(20);
576 $order->shipto->cvar_by_name($name)->save;
577 test($price_rule, $order, $item, "$name -- matching custom, not matching shipto", 1);
583 my $name = "no price rule, but cvars exist with module requirementsspecs or type text";
585 my $config1 = SL::DB::CustomVariableConfig->new(
586 module => 'RequirementSpecs',
589 description => $name,
592 included_by_default => 0,
596 my $config2 = SL::DB::CustomVariableConfig->new(
597 module => 'Customer',
600 description => $name,
603 included_by_default => 0,
607 my $order = create_sales_order()->save->load;
608 my $item = $order->items_sorted->[0];
611 test(undef, $order, $item, "$name -- nothing to match", 0);