Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 662df9d7

Von Bernd Bleßmann vor mehr als 3 Jahren hinzugefügt

  • ID 662df9d7fdc9c953d324a975a5bf554e6534c42e
  • Vorgänger 459b3c8d
  • Nachfolger c7b167f5

Zeiterfassung: Konvertierung: Artikel/Projekt: override- und default-Parameter

Unterschiede anzeigen:

SL/BackgroundJob/ConvertTimeRecordings.pm
85 85

  
86 86
  # valid parameters with default values
87 87
  my %valid_params = (
88
    from_date       => DateTime->new( day => 1,    month => DateTime->today_local->month, year => DateTime->today_local->year)->subtract(months => 1)->to_kivitendo,
89
    to_date         => DateTime->last_day_of_month(month => DateTime->today_local->month, year => DateTime->today_local->year)->subtract(months => 1)->to_kivitendo,
90
    customernumbers => [],
91
    part_id         => undef,
92
    project_id      => undef,
93
    rounding        => 1,
94
    link_order      => 0,
88
    from_date           => DateTime->new( day => 1,    month => DateTime->today_local->month, year => DateTime->today_local->year)->subtract(months => 1)->to_kivitendo,
89
    to_date             => DateTime->last_day_of_month(month => DateTime->today_local->month, year => DateTime->today_local->year)->subtract(months => 1)->to_kivitendo,
90
    customernumbers     => [],
91
    override_part_id    => undef,
92
    default_part_id     => undef,
93
    override_project_id => undef,
94
    default_project_id  => undef,
95
    rounding            => 1,
96
    link_order          => 0,
95 97
  );
96 98

  
97 99

  
......
136 138

  
137 139

  
138 140
  # check part
139
  if ($self->params->{part_id} && !SL::DB::Manager::Part->find_by(id => $self->params->{part_id},
140
                                                                  or => [obsolete => undef, obsolete => 0])) {
141
    die 'No valid part found by given part id';
141
  if ($self->params->{override_part_id} && !SL::DB::Manager::Part->find_by(id => $self->params->{override_part_id},
142
                                                                           or => [obsolete => undef, obsolete => 0])) {
143
    die 'No valid part found by given override part id';
144
  }
145
  if ($self->params->{default_part_id} && !SL::DB::Manager::Part->find_by(id => $self->params->{default_part_id},
146
                                                                           or => [obsolete => undef, obsolete => 0])) {
147
    die 'No valid part found by given default part id';
142 148
  }
143 149

  
144 150

  
145 151
  # check project
146
  if ($self->params->{project_id} && !SL::DB::Manager::Project->find_by(id => $self->params->{project_id},
147
                                                                        active => 1, valid => 1)) {
148
    die 'No valid project found by given project id';
152
  if ($self->params->{override_project_id} && !SL::DB::Manager::Project->find_by(id => $self->params->{override_project_id},
153
                                                                                 active => 1, valid => 1)) {
154
    die 'No valid project found by given override project id';
155
  }
156
  if ($self->params->{default_project_id} && !SL::DB::Manager::Project->find_by(id => $self->params->{default_project_id},
157
                                                                                active => 1, valid => 1)) {
158
    die 'No valid project found by given default project id';
149 159
  }
150 160

  
151 161
  return $self->params;
......
158 168
  push @{ $time_recordings_by_customer_id{$_->customer_id} }, $_ for @$time_recordings;
159 169

  
160 170
  my %convert_params = (
161
    rounding        => $self->params->{rounding},
162
    default_part_id => $self->params->{part_id},
171
    rounding         => $self->params->{rounding},
172
    override_part_id => $self->params->{override_part_id},
173
    default_part_id  => $self->params->{default_part_id},
163 174
  );
164 175

  
165 176
  my @donumbers;
......
193 204

  
194 205
  my %convert_params = (
195 206
    rounding        => $self->params->{rounding},
196
    default_part_id => $self->params->{part_id},
207
    override_part_id => $self->params->{override_part_id},
208
    default_part_id  => $self->params->{default_part_id},
197 209
  );
198 210

  
199 211
  my @donumbers;
......
257 269
  if (!$tr->order_id) {
258 270
    # check project
259 271
    my $project_id;
260
    #$project_id   = $self->override_project_id;
261
    $project_id   = $self->params->{project_id};
272
    $project_id   = $self->params->{override_project_id};
262 273
    $project_id ||= $tr->project_id;
263
    #$project_id ||= $self->default_project_id;
274
    $project_id ||= $self->params->{default_project_id};
264 275

  
265 276
    if (!$project_id) {
266 277
      $self->log_error('searching related order failed for time recording id ' . $tr->id . ' : no project id');
......
300 311

  
301 312
  # check part
302 313
  my $part_id;
303
  #$part_id   = $self->override_part_id;
314
  $part_id   = $self->params->{override_part_id};
304 315
  $part_id ||= $tr->part_id;
305
  #$part_id ||= $self->default_part_id;
306
  $part_id ||= $self->params->{part_id};
316
  $part_id ||= $self->params->{default_part_id};
307 317

  
308 318
  if (!$part_id) {
309 319
    $self->log_error('searching related order failed for time recording id ' . $tr->id . ' : no part id');
......
339 349
    return;
340 350
  }
341 351

  
342
  if ($tr->project_id && $tr->project_id != ($matching_order->globalproject_id || 0)) {
352
  if ($tr->project_id && !$self->params->{override_project_id} && $tr->project_id != ($matching_order->globalproject_id || 0)) {
343 353
    $self->log_error('searching related order failed for time recording id ' . $tr->id . ' : project of order does not match project of time recording');
344 354
    return;
345 355
  }
......
415 425

  
416 426
customernumbers: [c1,22332,334343]
417 427

  
418
=item C<part_id>
428
=item C<override_part_id>
429

  
430
The part id of a time based service which should be used to
431
book the times instead of the parts which are set in the time
432
recordings.
433

  
434
=item C<default_part_id>
419 435

  
420 436
The part id of a time based service which should be used to
421 437
book the times if no part is set in the time recording entry.
......
452 468
Hint: take a look or extend the job CloseProjectsBelongingToClosedSalesOrder for
453 469
further automatisation of your organisational needs.
454 470

  
455
=item C<project_id>
471
=item C<override_project_id>
456 472

  
457
Use this project_id instead of the project_id in the time recordings.
473
Use this project id instead of the project id in the time recordings to find
474
a related order. This is only used if C<link_order> is true.
475

  
476
=item C<default_project_id>
477

  
478
Use this project id if no project id is set in the time recording
479
entry. This is only used if C<link_order> is true.
458 480

  
459 481
=back
460 482

  
......
468 490
numbers. E.g. (default_/override_)part_number,
469 491
(default_/override_)project_number.
470 492

  
471
=item * part and project parameters override and default
472

  
473
In the moment, the part id given as parameter is used as the default value.
474
This means, it will be used if there is no part in the time recvording entry.
475

  
476
The project id given is used as override parameter. It overrides the project
477
given in the time recording entry.
478

  
479
To solve this, there should be parameters named override_part_id,
480
default_part_id, override_project_id and default_project_id.
481

  
482 493

  
483 494
=back
484 495

  
SL/DB/DeliveryOrder.pm
194 194
  #  - merge same descriptions
195 195
  #
196 196

  
197
  my $default_part_id = $params{default_part_id}    ? $params{default_part_id}
198
                      : $params{default_partnumber} ? SL::DB::Manager::Part->find_by(partnumber => $params{default_partnumber})->id
199
                      : undef;
197
  my $default_part_id  = $params{default_part_id}     ? $params{default_part_id}
198
                       : $params{default_partnumber}  ? SL::DB::Manager::Part->find_by(partnumber => $params{default_partnumber})->id
199
                       : undef;
200
  my $override_part_id = $params{override_part_id}    ? $params{override_part_id}
201
                       : $params{override_partnumber} ? SL::DB::Manager::Part->find_by(partnumber => $params{override_partnumber})->id
202
                       : undef;
200 203

  
201 204
  # check parts and collect entries
202 205
  my %part_by_part_id;
......
204 207
  foreach my $source (@$sources) {
205 208
    next if !$source->duration;
206 209

  
207
    my $part_id  = $source->part_id ? $source->part_id
208
                 : $default_part_id ? $default_part_id
209
                 : undef;
210
    my $part_id   = $override_part_id;
211
    $part_id    ||= $source->part_id;
212
    $part_id    ||= $default_part_id;
210 213

  
211 214
    die 'article not found for entry "' . $source->displayable_times . '"' if !$part_id;
212 215

  
......
434 437
given as C<$sources>. All time recording entries must belong to the same
435 438
customer. Time recordings are sorted by article and date. For each article
436 439
a new delivery order item is created. If no article is associated with an
437
entry, a default article will be used.
440
entry, a default article will be used. The article given in the time
441
recording entry can be overriden.
438 442
Entries of the same date (for each article) are summed together and form a
439 443
list entry in the long description of the item.
440 444

  
......
451 455
An optional hash reference. If it exists then it is used to set
452 456
attributes of the newly created delivery order object.
453 457

  
458
=item C<default_part_id>
459

  
460
An optional part id which is used as default value if no part is set
461
in the time recording entry.
462

  
463
=item C<default_partnumber>
464

  
465
Like C<default_part_id> but given as partnumber, not as id.
466

  
467
=item C<override_part_id>
468

  
469
An optional part id which is used instead of a value set in the time
470
recording entry.
471

  
472
=item C<override_partnumber>
473

  
474
Like C<overrride_part_id> but given as partnumber, not as id.
475

  
454 476
=item C<related_order>
455 477

  
456 478
An optional C<SL::DB::Order> object. If it exists then it is used to
t/background_job/convert_time_recordings.t
1
use Test::More tests => 40;
1
use Test::More tests => 52;
2 2

  
3 3
use strict;
4 4

  
......
37 37
clear_up();
38 38

  
39 39
########################################
40
# two time recordings, one order linked with project_id
40
# two time recordings, one order linked with project_id in time recording entry
41 41
########################################
42 42
my $part     = new_service(partnumber => 'Serv1', unit => 'Std')->save;
43 43
my $project  = create_project(projectnumber => 'p1', description => 'Project 1');
......
70 70

  
71 71
my %data   = (
72 72
  link_order => 1,
73
  project_id => $project->id,
74 73
  from_date  => '01.01.2021',
75 74
  to_date    => '30.04.2021',
76 75
);
......
102 101

  
103 102

  
104 103
########################################
105
# two time recordings, one order linked with project_id
104
# two time recordings, one order linked with project_id in time recording entry
106 105
# unit in order is 'min', but part is 'Std'
107 106
########################################
108 107
$part     = new_service(partnumber => 'Serv1', unit => 'Std')->save;
......
133 132
  part       => $part,
134 133
)->save;
135 134

  
136
# two time recordings, one order linked with project_id
137 135
%data = (
138 136
  link_order => 1,
139
  project_id => $project->id,
140 137
  from_date  => '01.04.2021',
141 138
  to_date    => '30.04.2021',
142 139
);
......
161 158

  
162 159

  
163 160
########################################
164
# two time recordings, one order linked with project_id
161
# two time recordings, one order linked with project_id in time recording entry
165 162
# unit in order is 'Std', but part is 'min'
166 163
########################################
167 164
$part     = new_service(partnumber => 'Serv1', unit => 'min')->save;
......
192 189
  part       => $part,
193 190
)->save;
194 191

  
195
# two time recordings, one order linked with project_id
196 192
%data = (
197 193
  link_order => 1,
198
  project_id => $project->id,
199 194
  from_date  => '01.04.2021',
200 195
  to_date    => '30.04.2021',
201 196
);
......
313 308
clear_up();
314 309

  
315 310

  
311
########################################
312
# override project and part
313
########################################
314
$part     = new_service(partnumber => 'Serv1', unit => 'Std')->save;
315
my $part2    = new_service(partnumber => 'Serv2', unit => 'min')->save;
316
$project  = create_project(projectnumber => 'p1', description => 'Project 1');
317
my $project2 = create_project(projectnumber => 'p2', description => 'Project 2');
318
$customer = new_customer()->save;
319

  
320
$sales_order = create_sales_order(
321
  save             => 1,
322
  customer         => $customer,
323
  globalproject    => $project,
324
  taxincluded      => 0,
325
  orderitems       => [ create_order_item(part => $part, qty => 180, unit => 'min', sellprice => 70), ]
326
);
327
my $sales_order2 = create_sales_order(
328
  save             => 1,
329
  customer         => $customer,
330
  globalproject    => $project,
331
  taxincluded      => 0,
332
  orderitems       => [ create_order_item(part => $part2, qty => 180, unit => 'min', sellprice => 70), ]
333
);
334

  
335
new_time_recording(
336
  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 10, minute => 10),
337
  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute => 10),
338
  customer   => $customer,
339
  project    => $project,
340
  part       => $part,
341
)->save;
342
new_time_recording(
343
  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute => 10),
344
  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 12, minute => 10),
345
  customer   => $customer,
346
  project    => $project2,
347
  part       => $part2,
348
)->save;
349
new_time_recording(
350
  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 12, minute => 10),
351
  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 13, minute => 10),
352
  customer   => $customer,
353
)->save;
354

  
355
%data = (
356
  link_order          => 1,
357
  from_date           => '01.04.2021',
358
  to_date             => '30.04.2021',
359
  override_part_id    => $part->id,
360
  override_project_id => $project->id,
361
);
362
$db_obj = SL::DB::BackgroundJob->new();
363
$db_obj->set_data(%data);
364
$job    = SL::BackgroundJob::ConvertTimeRecordings->new;
365
$ret    = $job->run($db_obj);
366

  
367
$linked_dos = $sales_order->linked_records(to => 'DeliveryOrder');
368
is($linked_dos->[0]->globalproject_id, $project->id, 'overriden part and project: project in delivery order');
369

  
370
$linked_items = $sales_order->items->[0]->linked_records(to => 'DeliveryOrderItem');
371
is($linked_items->[0]->qty*1, 3, 'overriden part and project: qty in delivery order');
372
is($linked_items->[0]->base_qty*1, 3, 'overriden part and project: base_qty in delivery order');
373
is($linked_items->[0]->parts_id, $part->id, 'overriden part and project: part id');
374

  
375
my $linked_dos2 = $sales_order2->linked_records(to => 'DeliveryOrder');
376
is(scalar @$linked_dos2, 0, 'overriden part and project: no delivery order for unused order');
377

  
378
# reload order and orderitems to get changes to deliverd and ship
379
Rose::DB::Object::Helpers::forget_related($sales_order, 'orderitems');
380
$sales_order->load;
381
Rose::DB::Object::Helpers::forget_related($sales_order2, 'orderitems');
382
$sales_order2->load;
383

  
384
is($sales_order ->items->[0]->ship||0, 180, 'overriden part and project: ship in related order');
385
is($sales_order2->items->[0]->ship||0,   0, 'overriden part and project: ship in not related order');
386

  
387
clear_up();
388

  
389

  
390
########################################
391
# default project and part
392
########################################
393
$part     = new_service(partnumber => 'Serv1', unit => 'Std')->save;
394
$project  = create_project(projectnumber => 'p1', description => 'Project 1');
395
$customer = new_customer()->save;
396

  
397
$sales_order = create_sales_order(
398
  save             => 1,
399
  customer         => $customer,
400
  globalproject    => $project,
401
  taxincluded      => 0,
402
  orderitems       => [ create_order_item(part => $part, qty => 180, unit => 'min', sellprice => 70), ]
403
);
404

  
405
new_time_recording(
406
  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 10, minute => 10),
407
  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute => 40),
408
  customer   => $customer,
409
)->save;
410

  
411
%data = (
412
  link_order         => 1,
413
  from_date          => '01.04.2021',
414
  to_date            => '30.04.2021',
415
  default_part_id    => $part->id,
416
  default_project_id => $project->id,
417
);
418
$db_obj = SL::DB::BackgroundJob->new();
419
$db_obj->set_data(%data);
420
$job    = SL::BackgroundJob::ConvertTimeRecordings->new;
421
$ret    = $job->run($db_obj);
422

  
423
$linked_dos = $sales_order->linked_records(to => 'DeliveryOrder');
424
is($linked_dos->[0]->globalproject_id, $project->id, 'default and project: project in delivery order');
425

  
426
$linked_items = $sales_order->items->[0]->linked_records(to => 'DeliveryOrderItem');
427
is($linked_items->[0]->qty*1, 1.5, 'default part and project: qty in delivery order');
428
is($linked_items->[0]->base_qty*1, 1.5, 'default part and project: base_qty in delivery order');
429
is($linked_items->[0]->parts_id, $part->id, 'default part and project: part id');
430

  
431
# reload order and orderitems to get changes to deliverd and ship
432
Rose::DB::Object::Helpers::forget_related($sales_order, 'orderitems');
433
$sales_order->load;
434

  
435
is($sales_order->items->[0]->ship*1, 90, 'default part and project: ship in related order');
436

  
437
clear_up();
438

  
439

  
316 440
########################################
317 441
# check rounding
318 442
########################################
......
453 577
#####
454 578

  
455 579
%data = (
456
  part_id => '123',
580
  override_part_id => '123',
457 581
);
458 582

  
459 583
$db_obj = SL::DB::BackgroundJob->new();
......
462 586

  
463 587
$err_msg = '';
464 588
eval { $ret = $job->run($db_obj);  1; } or do {$err_msg = $@};
465
ok($err_msg =~ '^No valid part found by given part id', 'invalid part id detected');
589
ok($err_msg =~ '^No valid part found by given override part id', 'invalid part id detected');
466 590

  
467 591
#####
468 592

  
469 593
$part = new_service(partnumber => 'Serv1', unit => 'Std', obsolete => 1)->save;
470 594
%data = (
471
  part_id => $part->id,
595
  override_part_id => $part->id,
472 596
);
473 597

  
474 598
$db_obj = SL::DB::BackgroundJob->new();
......
477 601

  
478 602
$err_msg = '';
479 603
eval { $ret = $job->run($db_obj);  1; } or do {$err_msg = $@};
480
ok($err_msg =~ '^No valid part found by given part id', 'obsolete part detected');
604
ok($err_msg =~ '^No valid part found by given override part id', 'obsolete part detected');
481 605

  
482 606
#####
483 607

  
484 608
%data = (
485
  project_id => 123,
609
  override_project_id => 123,
486 610
);
487 611

  
488 612
$db_obj = SL::DB::BackgroundJob->new();
......
491 615

  
492 616
$err_msg = '';
493 617
eval { $ret = $job->run($db_obj);  1; } or do {$err_msg = $@};
494
ok($err_msg =~ '^No valid project found by given project id', 'invalid project id detected');
618
ok($err_msg =~ '^No valid project found by given override project id', 'invalid project id detected');
495 619

  
496 620
#####
497 621

  
498 622
$project = create_project(projectnumber => 'p1', description => 'Project 1', valid => 0)->save;
499 623
%data = (
500
  project_id => $project->id,
624
  override_project_id => $project->id,
501 625
);
502 626

  
503 627
$db_obj = SL::DB::BackgroundJob->new();
......
506 630

  
507 631
$err_msg = '';
508 632
eval { $ret = $job->run($db_obj);  1; } or do {$err_msg = $@};
509
ok($err_msg =~ '^No valid project found by given project id', 'invalid project detected');
633
ok($err_msg =~ '^No valid project found by given override project id', 'invalid project detected');
510 634

  
511 635
#####
512 636

  

Auch abrufbar als: Unified diff