Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 5a618706

Von Jan Büren vor mehr als 3 Jahren hinzugefügt

  • ID 5a618706a76c255d27288805c6fdd1f113f73183
  • Vorgänger c4a68243
  • Nachfolger 94a76a6d

orderitems um Attribut optional erweitert

Optionale orderitems werden nicht in den Belegsumme aufaddiert
Anpassung für Order-Controller und Druckvorlagen-System
Weitere Anwender-Details s.a. Changelog

Unterschiede anzeigen:

SL/ARAP.pm
67 67
  my $q_ordered = qq|SELECT oi.parts_id, oi.qty, oi.unit, p.unit AS partunit
68 68
                      FROM orderitems oi
69 69
                      LEFT JOIN parts p ON (oi.parts_id = p.id)
70
                      WHERE oi.trans_id = ?|;
70
                      WHERE oi.trans_id = ?
71
                      AND not oi.optional|;
71 72
  my $h_ordered = prepare_query($form, $dbh, $q_ordered);
72 73

  
73 74
  my @close_oe_ids;
SL/DB/Helper/FlattenToForm.pm
97 97
    _copy($item->part,    $form, '',               "_${idx}", 0,               qw(listprice));
98 98
    _copy($item,          $form, '',               "_${idx}", 0,               qw(description project_id ship serialnumber pricegroup_id ordnumber donumber cusordnumber unit
99 99
                                                                                  subtotal longdescription price_factor_id marge_price_factor reqdate transdate
100
                                                                                  active_price_source active_discount_source));
100
                                                                                  active_price_source active_discount_source optional));
101 101
    _copy($item,          $form, '',              "_${idx}", $format_noround, qw(qty sellprice fxsellprice));
102 102
    _copy($item,          $form, '',              "_${idx}", $format_amounts, qw(marge_total marge_percent lastcost));
103 103
    _copy($item,          $form, '',              "_${idx}", $format_percent, qw(discount));
SL/DB/Helper/PriceTaxCalculator.pm
44 44
  # set exchangerate in $data>{exchangerate}
45 45
  if ( ref($self) eq 'SL::DB::Order' ) {
46 46
    # orders store amount in the order currency
47
    $data{exchangerate} = 1;
47
    $data{exchangerate}         = 1;
48
    $data{allow_optional_items} = 1;
48 49
  } else {
49 50
    # invoices store amount in the default currency
50 51
    _get_exchangerate($self, \%data, %params);
......
121 122
  } else {
122 123
    $tax_amount = $linetotal * $tax_rate;
123 124
  }
124

  
125
  if ($taxkey->tax->chart_id) {
126
    $data->{taxes_by_chart_id}->{ $taxkey->tax->chart_id } ||= 0;
127
    $data->{taxes_by_chart_id}->{ $taxkey->tax->chart_id }  += $tax_amount;
128
    $data->{taxes_by_tax_id}->{ $taxkey->tax_id }          ||= 0;
129
    $data->{taxes_by_tax_id}->{ $taxkey->tax_id }           += $tax_amount;
130
  } elsif ($tax_amount) {
131
    die "tax_amount != 0 but no chart_id for taxkey " . $taxkey->id . " tax " . $taxkey->tax->id;
132
  }
133

  
134 125
  my $chart = $part->get_chart(type => $data->{is_sales} ? 'income' : 'expense', taxzone => $self->taxzone_id);
135
  $data->{amounts}->{ $chart->id }           ||= { taxkey => $taxkey->taxkey_id, tax_id => $taxkey->tax_id, amount => 0 };
136
  $data->{amounts}->{ $chart->id }->{amount}  += $linetotal;
137
  $data->{amounts}->{ $chart->id }->{amount}  -= $tax_amount if $self->taxincluded;
126
  unless ($data->{allow_optional_items} && $item->optional) {
127
    if ($taxkey->tax->chart_id) {
128
      $data->{taxes_by_chart_id}->{ $taxkey->tax->chart_id } ||= 0;
129
      $data->{taxes_by_chart_id}->{ $taxkey->tax->chart_id }  += $tax_amount;
130
      $data->{taxes_by_tax_id}->{ $taxkey->tax_id }          ||= 0;
131
      $data->{taxes_by_tax_id}->{ $taxkey->tax_id }           += $tax_amount;
132
    } elsif ($tax_amount) {
133
      die "tax_amount != 0 but no chart_id for taxkey " . $taxkey->id . " tax " . $taxkey->tax->id;
134
    }
138 135

  
136
    $data->{amounts}->{ $chart->id }           ||= { taxkey => $taxkey->taxkey_id, tax_id => $taxkey->tax_id, amount => 0 };
137
    $data->{amounts}->{ $chart->id }->{amount}  += $linetotal;
138
    $data->{amounts}->{ $chart->id }->{amount}  -= $tax_amount if $self->taxincluded;
139
  }
139 140
  my $linetotal_cost = 0;
140 141

  
141 142
  if (!$linetotal) {
......
150 151
    $item->marge_total(  $linetotal_net - $linetotal_cost);
151 152
    $item->marge_percent($item->marge_total * 100 / $linetotal_net);
152 153

  
153
    $self->marge_total(  $self->marge_total + $item->marge_total);
154
    $data->{lastcost_total} += $linetotal_cost;
154
    unless ($data->{allow_optional_items} && $item->optional) {
155
      $self->marge_total(  $self->marge_total + $item->marge_total);
156
      $data->{lastcost_total} += $linetotal_cost;
157
    }
155 158
  }
156 159

  
157 160
  push @{ $data->{assembly_items} }, [];
SL/DB/MetaSetup/OrderItem.pm
23 23
  marge_price_factor     => { type => 'numeric', default => 1, precision => 15, scale => 5 },
24 24
  marge_total            => { type => 'numeric', precision => 15, scale => 5 },
25 25
  mtime                  => { type => 'timestamp' },
26
  optional               => { type => 'boolean', default => 'false' },
26 27
  ordnumber              => { type => 'text' },
27 28
  parts_id               => { type => 'integer' },
28 29
  position               => { type => 'integer', not_null => 1 },
SL/DB/Order.pm
393 393
                                                        marge_percent marge_price_factor marge_total
394 394
                                                        ordnumber parts_id price_factor price_factor_id pricegroup_id
395 395
                                                        project_id qty reqdate sellprice serialnumber ship subtotal transdate unit
396
                                                        optional
396 397
                                                     )),
397 398
                                                 custom_variables => \@custom_variables,
398 399
    );
SL/OE.pm
1366 1366
       partnotes serialnumber reqdate sellprice sellprice_nofmt listprice listprice_nofmt netprice netprice_nofmt
1367 1367
       discount discount_nofmt p_discount discount_sub discount_sub_nofmt nodiscount_sub nodiscount_sub_nofmt
1368 1368
       linetotal linetotal_nofmt nodiscount_linetotal nodiscount_linetotal_nofmt tax_rate projectnumber projectdescription
1369
       price_factor price_factor_name partsgroup weight weight_nofmt lineweight lineweight_nofmt);
1369
       price_factor price_factor_name partsgroup weight weight_nofmt lineweight lineweight_nofmt optional);
1370 1370

  
1371 1371
  push @arrays, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
1372 1372
  push @arrays, map { "project_cvar_$_->{name}" } @{ $project_cvar_configs };
......
1433 1433
      push @{ $form->{TEMPLATE_ARRAYS}->{price_factor} },      $price_factor->{formatted_factor};
1434 1434
      push @{ $form->{TEMPLATE_ARRAYS}->{price_factor_name} }, $price_factor->{description};
1435 1435
      push @{ $form->{TEMPLATE_ARRAYS}->{partsgroup} },        $form->{"partsgroup_$i"};
1436
      push @{ $form->{TEMPLATE_ARRAYS}->{optional} },          $form->{"optional_$i"};
1436 1437

  
1437 1438
      my $sellprice     = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
1438 1439
      my ($dec)         = ($sellprice =~ /\.(\d+)/);
......
1472 1473
        $form->{non_separate_subtotal} += $linetotal;
1473 1474
      }
1474 1475

  
1475
      $form->{ordtotal}         += $linetotal;
1476
      $form->{ordtotal}         += $linetotal unless $form->{"optional_$i"};
1476 1477
      $form->{nodiscount_total} += $nodiscount_linetotal;
1477 1478
      $form->{discount_total}   += $discount;
1478 1479

  
......
1520 1521

  
1521 1522
      map { $taxrate += $form->{"${_}_rate"} } split(/ /, $form->{"taxaccounts_$i"});
1522 1523

  
1523
      if ($form->{taxincluded}) {
1524
      unless ($form->{"optional_$i"}) {
1525
        if ($form->{taxincluded}) {
1524 1526

  
1525
        # calculate tax
1526
        $taxamount = $linetotal * $taxrate / (1 + $taxrate);
1527
        $taxbase = $linetotal / (1 + $taxrate);
1528
      } else {
1529
        $taxamount = $linetotal * $taxrate;
1530
        $taxbase   = $linetotal;
1527
          # calculate tax
1528
          $taxamount = $linetotal * $taxrate / (1 + $taxrate);
1529
          $taxbase = $linetotal / (1 + $taxrate);
1530
        } else {
1531
          $taxamount = $linetotal * $taxrate;
1532
          $taxbase   = $linetotal;
1533
        }
1531 1534
      }
1532 1535

  
1533 1536
      if ($taxamount != 0) {
doc/changelog
37 37

  
38 38
Kleinere neue Features und Detailverbesserungen:
39 39

  
40
 - Angebote und Aufträge im Ein- und Verkauf können optionale Positionen enthalten.
41
   Optionale Positionen werden in der zweiten Zeile der Position aktiviert.
42
   Die einzelne Position wird dann berechnet und erscheint im Ausdruck mit dem
43
   berechnetem Preis, die Position wird aber nicht in der Gesamtsumme des Belegs
44
   aufgenommen. Dies gilt auch für die Gesamt-Marge und den Gesamt-Ertrag des Belegs.
45
   Innerhalb der Druckvorlagen steht das Attribut mit <%optional%> als Variable zu Verfügung.
46
   Beim Status setzen eines Auftrags (offen oder geschlossen) werden optionale Position
47
   ignoriert. D.h. ein Auftrag gilt als geschlossen, wenn alle nicht optionalen
48
   Positionen fakturiert worden sind. Das Attribut optional steht auch nur in
49
   den Angeboten/Aufträgen zu Verfügung. Sobald über den Workflow ein neuer Beleg
50
   erstellt wird, wird die vorher optionale Position zu einer normalen Position
51
   und wird dann auch entsprechend bei dem Rechnungsbeleg mit fakturiert und im
52
   Druckvorlagen-System entfällt das Attribut <%optional%>.
53
   Entsprechend exemplarisch im aktuellen Druckvorlagensatz RB ergänzt.
54

  
40 55
 - Lagerbestandsbericht: Die Resultate pro Seite können im Bericht eingestellt werden
41 56
 - Es gibt eine PDF-Druckvorschau für die Standard-Druckvorlage bei Angeboten und
42 57
   Aufträgen im Einkauf und Verkauf ohne ein vorheriges Dialogmenü (Druckvorlage
sql/Pg-upgrade2/orderitems_optional.sql
1
-- @tag: orderitems_optional
2
-- @description: Optionale Artikel im Angebot und Auftrag
3
-- @depends: release_3_5_6_1
4
ALTER TABLE orderitems ADD COLUMN optional BOOLEAN default FALSE;
5

  
t/db_helper/price_tax_calculator.t
98 98
    %params,
99 99
  );
100 100
}
101
sub new_order {
102
  my %params  = @_;
103

  
104
  return create_sales_order(
105
    transdate   => $transdate,
106
    taxzone_id  => $taxzone->id,
107
    %params,
108
  );
109
}
101 110

  
102 111
sub new_item {
103 112
  my (%params) = @_;
......
109 118
    %params,
110 119
  );
111 120
}
121
sub new_order_item {
122
  my (%params) = @_;
123

  
124
  my $part = delete($params{part}) || $parts[0];
125

  
126
  return create_order_item(
127
    part => $part,
128
    %params,
129
  );
130
}
112 131

  
113 132
sub test_default_invoice_one_item_19_tax_not_included() {
114 133
  reset_state();
......
553 572
    rounding                                    =>  0,
554 573
  }, "${title}: calculated data");
555 574
}
575
sub test_default_order_two_items_19_one_optional() {
576
  reset_state();
577

  
578
  my $item          = new_order_item(qty => 2.5);
579
  my $item_optional = new_order_item(qty => 2.5, optional => 1);
580

  
581
  my $order = new_order(
582
    taxincluded  => 0,
583
    orderitems => [ $item, $item_optional ],
584
  );
585

  
586
  my $taxkey = $item->part->get_taxkey(date => $transdate, is_sales => 1, taxzone => $order->taxzone_id);
587

  
588
  # sellprice 2.34 * qty 2.5 = 5.85
589
  # 19%(5.85) = 1.1115; rounded = 1.11
590
  # total rounded = 6.96
591

  
592
  # lastcost 1.93 * qty 2.5 = 4.825; rounded 4.83
593
  # line marge_total = 1.02
594
  # line marge_percent = 17.4358974358974
595

  
596
  my $title = 'default order, two item, one item optional, 19% tax not included';
597
  my %data  = $order->calculate_prices_and_taxes;
598

  
599
  is($item->marge_total,        1.02,             "${title}: item marge_total");
600
  is($item->marge_percent,      17.4358974358974, "${title}: item marge_percent");
601
  is($item->marge_price_factor, 1,                "${title}: item marge_price_factor");
602

  
603
  # optional items have a linetotal and marge, but ...
604
  is($item_optional->marge_total,        1.02,             "${title}: item optional marge_total");
605
  is($item_optional->marge_percent,      17.4358974358974, "${title}: item optional marge_percent");
606
  is($item_optional->marge_price_factor, 1,                "${title}: item optional marge_price_factor");
607

  
608
  # ... should not be calculated for the record sum
609
  is($order->netamount,       5.85,             "${title}: netamount");
610
  is($order->amount,          6.96,             "${title}: amount");
611
  is($order->marge_total,     1.02,             "${title}: marge_total");
612
  is($order->marge_percent,   17.4358974358974, "${title}: marge_percent");
613
  is($order->orderitems->[1]->optional, 1,      "${title}: second order item has attribute optional");
614
  # diag explain $order->orderitems->[1]->optional;
615
  # diag explain \%data;
616
  is_deeply(\%data, {
617
    allocated                                    => {},
618
    amounts                                      => {
619
      $buchungsgruppe->income_accno_id($taxzone) => {
620
        amount                                   => 5.85,
621
        tax_id                                   => $tax->id,
622
        taxkey                                   => 3,
623
      },
624
    },
625
    amounts_cogs                                 => {},
626
    assembly_items                               => [
627
      [],
628
      [],
629
    ],
630
    exchangerate                                 => 1,
631
    taxes_by_chart_id                            => {
632
      $tax->chart_id                             => 1.11,
633
    },
634
    taxes_by_tax_id                              => {
635
      $tax->id                                   => 1.1115,
636
    },
637
    items                                        => [
638
      { linetotal                                => 5.85,
639
        linetotal_cost                           => 4.83,
640
        sellprice                                => 2.34,
641
        tax_amount                               => 1.1115,
642
        taxkey_id                                => $taxkey->id,
643
      },
644
      { linetotal                                => 5.85,
645
        linetotal_cost                           => 4.83,
646
        sellprice                                => 2.34,
647
        tax_amount                               => 1.1115,
648
        taxkey_id                                => $taxkey->id,
649
      },
650
    ],
651
    rounding                                    =>  0,
652
  }, "${title}: calculated data");
653
}
556 654

  
557 655

  
558 656
Support::TestSetup::login();
......
566 664
test_default_invoice_one_item_19_tax_not_included_rounding_discount();
567 665
test_default_invoice_one_item_19_tax_not_included_rounding_discount_huge_qty();
568 666
test_default_invoice_one_item_19_tax_not_included_rounding_discount_big_qty_low_sellprice();
667
test_default_order_two_items_19_one_optional();
569 668

  
570 669
clear_up();
571 670
done_testing();
templates/print/RB/deutsch.tex
56 56
\newcommand{\auftragerteilt}{Auftrag erteilt:}
57 57
\newcommand{\angebotortdatum}{Wir nehmen das vorstehende Angebot an.}
58 58
\newcommand{\abweichendeLieferadresse}{abweichende Lieferadresse}
59
\newcommand{\optional}{Optionale Position nach Absprache}
59 60

  
60 61
% auftragbestätigung (sales_order)
61 62
\newcommand{\auftragsbestaetigung} {Auftragsbestätigung}
templates/print/RB/english.tex
68 68
\newcommand{\den} {Date}
69 69
\newcommand{\unterschrift} {Signature}
70 70
\newcommand{\stempel} {Company stamp}
71
\newcommand{\optional}{Optional position by arrangement}
71 72

  
72 73
% lieferschein (sales_delivery_order)
73 74
\newcommand{\lieferschein} {Delivery order}
templates/print/RB/sales_order.tex
151 151
          <%if serialnumber%> && \scriptsize \seriennummer: <%serialnumber%>\\<%end serialnumber%>
152 152
          <%if ean%> && \scriptsize \ean: <%ean%>\\<%end ean%>
153 153
          <%if projectnumber%> && \scriptsize \projektnummer: <%projectnumber%>\\<%end projectnumber%>
154
          <%if optional%> && \scriptsize \optional \\<%end%>
154 155
          <%if customer_make%>
155 156
            <%foreach customer_make%>
156 157
              \ifthenelse{\equal{<%customer_make%>}{<%name%>}}{&& \kundenartnr: <%customer_model%>\\}{}
templates/print/RB/sales_quotation.tex
147 147
          <%if serialnumber%> && \scriptsize \seriennummer: <%serialnumber%>\\<%end serialnumber%>
148 148
          <%if ean%> && \scriptsize \ean: <%ean%>\\<%end ean%>
149 149
          <%if projectnumber%> && \scriptsize \projektnummer: <%projectnumber%>\\<%end projectnumber%>
150
          <%if optional%> && \scriptsize \optional \\<%end%>
150 151
          <%if customer_make%>
151 152
            <%foreach customer_make%>
152 153
              \ifthenelse{\equal{<%customer_make%>}{<%name%>}}{&& \kundenartnr: <%customer_model%>\\}{}
templates/webpages/order/tabs/_second_row.html
38 38
      <span[%- IF ITEM.part.onhand < ITEM.part.rop -%] class="numeric plus0"[%- END -%]>
39 39
        [%- ITEM.part.onhand_as_number -%]&nbsp;[%- ITEM.part.unit -%]
40 40
      </span>&nbsp;
41
    <b>[%- 'Optional' | $T8 %]</b>&nbsp;
42
      [%- L.yes_no_tag("order.orderitems[].optional", ITEM.optional
43
                        class="recalc") %]&nbsp;
41 44
  </td></tr>
42 45

  
43 46
  <tr>

Auch abrufbar als: Unified diff