Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision dee8b29f

Von Kivitendo Admin vor mehr als 8 Jahren hinzugefügt

  • ID dee8b29f4976d834517d1fced4eacba17dcc315d
  • Vorgänger 4291cf9e
  • Nachfolger 2d8e82ac

Payment Helper kann nun auch Kursverluste/Gewinne

+ neue Helper-Methode exchange_rate für Rechnungen

Unterschiede anzeigen:

SL/DB/Helper/Payment.pm
4 4

  
5 5
use parent qw(Exporter);
6 6
our @EXPORT = qw(pay_invoice);
7
our @EXPORT_OK = qw(skonto_date skonto_charts amount_less_skonto within_skonto_period percent_skonto reference_account reference_amount open_amount open_percent remaining_skonto_days skonto_amount check_skonto_configuration valid_skonto_amount get_payment_suggestions validate_payment_type open_sepa_transfer_amount get_payment_select_options_for_bank_transaction create_bank_transaction);
7
our @EXPORT_OK = qw(skonto_date skonto_charts amount_less_skonto within_skonto_period percent_skonto reference_account reference_amount open_amount open_percent remaining_skonto_days skonto_amount check_skonto_configuration valid_skonto_amount get_payment_suggestions validate_payment_type open_sepa_transfer_amount get_payment_select_options_for_bank_transaction create_bank_transaction exchangerate);
8 8
our %EXPORT_TAGS = (
9 9
  "ALL" => [@EXPORT, @EXPORT_OK],
10 10
);
......
15 15
use SL::DATEV qw(:CONSTANTS);
16 16
use SL::Locale::String qw(t8);
17 17
use List::Util qw(sum);
18
use SL::DB::Exchangerate;
19
use SL::DB::Currency;
18 20
use Carp;
19 21

  
20 22
#
......
40 42

  
41 43
  my $transdate_obj;
42 44
  if (ref($params{transdate} eq 'DateTime')) {
43
    print "found transdate ref\n"; sleep 2;
44 45
    $transdate_obj = $params{transdate};
45 46
  } else {
46 47
   $transdate_obj = $::locale->parse_date_to_object($params{transdate});
......
115 116
  my $source = $params{'source'} || '';
116 117

  
117 118
  my $rounded_params_amount = _round( $params{amount} ); # / $exchangerate);
119
  my $fx_gain_loss_amount = 0; # for fx_gain and fx_loss
118 120

  
119 121
  my $db = $self->db;
120 122
  $db->do_transaction(sub {
......
158 160
      # deal with fxtransaction
159 161
      if ( $self->currency_id != $::instance_conf->get_currency_id ) {
160 162
        my $fxamount = _round($amount - ($amount * $exchangerate));
161
        # print "amount: $amount, fxamount = $fxamount\n";
162
        # print "amount - (amount * exchangerate) = " . $amount . " - (" . $amount . " - " . $exchangerate . ")\n";
163 163
        $new_acc_trans = SL::DB::AccTransaction->new(trans_id       => $self->id,
164 164
                                                     chart_id       => $account_bank->id,
165 165
                                                     chart_link     => $account_bank->link,
......
171 171
                                                     fx_transaction => 1,
172 172
                                                     tax_id         => SL::DB::Manager::Tax->find_by(taxkey => 0)->id);
173 173
        $new_acc_trans->save;
174
        # if invoice exchangerate differs from exchangerate of payment
175
        # deal with fxloss and fxamount
176
        if ($self->exchangerate and $self->exchangerate != 1 and $self->exchangerate != $exchangerate) {
177
          my $fxgain_chart = SL::DB::Manager::Chart->find_by(id => $::instance_conf->get_fxgain_accno_id) || die "Can't determine fxgain chart";
178
          my $fxloss_chart = SL::DB::Manager::Chart->find_by(id => $::instance_conf->get_fxloss_accno_id) || die "Can't determine fxloss chart";
179
          my $gain_loss_amount = _round($amount * ($exchangerate - $self->exchangerate ) * -1,2);
180
          my $gain_loss_chart = $gain_loss_amount > 0 ? $fxgain_chart : $fxloss_chart;
181
          $fx_gain_loss_amount = $gain_loss_amount;
182

  
183
          $new_acc_trans = SL::DB::AccTransaction->new(trans_id       => $self->id,
184
                                                       chart_id       => $gain_loss_chart->id,
185
                                                       chart_link     => $gain_loss_chart->link,
186
                                                       amount         => $gain_loss_amount,
187
                                                       transdate      => $transdate_obj,
188
                                                       source         => $source,
189
                                                       memo           => $memo,
190
                                                       taxkey         => 0,
191
                                                       fx_transaction => 0,
192
                                                       tax_id         => SL::DB::Manager::Tax->find_by(taxkey => 0)->id);
193
          $new_acc_trans->save;
194

  
195
        };
174 196
      };
175 197
    };
176 198

  
......
238 260
    my $arap_booking= SL::DB::AccTransaction->new(trans_id   => $self->id,
239 261
                                                  chart_id   => $reference_account->id,
240 262
                                                  chart_link => $reference_account->link,
241
                                                  amount     => _round($arap_amount * $mult * $exchangerate),
263
                                                  amount     => _round($arap_amount * $mult * $exchangerate - $fx_gain_loss_amount),
242 264
                                                  transdate  => $transdate_obj,
243 265
                                                  source     => '', #$params{source},
244 266
                                                  taxkey     => 0,
245 267
                                                  tax_id     => SL::DB::Manager::Tax->find_by(taxkey => 0)->id);
246 268
    $arap_booking->save;
247 269

  
248
    $self->paid($self->paid + _round($paid_amount)) if $paid_amount;
270
    $fx_gain_loss_amount *= -1 if $self->is_sales;
271
    $self->paid($self->paid + _round($paid_amount) + $fx_gain_loss_amount) if $paid_amount;
249 272
    $self->datepaid($transdate_obj);
250 273
    $self->save;
251 274

  
......
628 651

  
629 652
};
630 653

  
654
sub exchangerate {
655
  my ($self) = @_;
656

  
657
  return 1 if $self->currency_id == $::instance_conf->get_currency_id;
658

  
659
  my $rate = SL::DB::Manager::Exchangerate->find_by(currency_id => $self->currency_id,
660
                                                    transdate   => $self->transdate,
661
                                                   );
662
  return undef unless $rate;
663
  $self->is_sales ? return $rate->sell : return $rate->buy;
664
};
631 665

  
632 666
sub get_payment_suggestions {
633 667

  
......
1068 1102
Amount is always relative to the absolute amount of the invoice, use positive
1069 1103
values for sales and purchases.
1070 1104

  
1105
=item C<exchangerate>
1106

  
1107
Returns the exchangerate in database format for the invoice according to that invoice's transdate.
1108
Returns 'sell' for sales, 'buy' for purchases.
1109

  
1071 1110
=back
1072 1111

  
1073 1112
=head1 TODO AND CAVEATS
......
1079 1118
when looking at open amount, maybe consider that there may already be queued
1080 1119
amounts in SEPA Export
1081 1120

  
1082
=item *
1083

  
1084
Can only handle default currency.
1085

  
1086 1121
=back
1087 1122

  
1088 1123
=head1 AUTHOR
t/db_helper/payment.t
22 22
use SL::DB::TaxZone;
23 23
use SL::DB::BankAccount;
24 24
use SL::DB::PaymentTerm;
25
use SL::DBUtils qw(selectfirst_array_query);
25 26
use Data::Dumper;
26 27

  
27 28
my ($customer, $vendor, $currency_id, @parts, $buchungsgruppe, $buchungsgruppe7, $unit, $employee, $tax, $tax7, $tax_9, $taxzone, $payment_terms, $bank_account);
28
my ($transdate, $transdate2, $currency, $exchangerate, $exchangerate2);
29
my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart);
29
my ($transdate1, $transdate2, $transdate3, $transdate4, $currency, $exchangerate, $exchangerate2, $exchangerate3, $exchangerate4);
30
my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart, $fxloss_chart, $fxgain_chart);
30 31

  
31 32
my $ALWAYS_RESET = 1;
32 33

  
......
56 57

  
57 58
  clear_up();
58 59

  
59
  $transdate  = DateTime->today;
60
  $transdate1 = DateTime->today;
60 61
  $transdate2 = DateTime->today->add(days => 1);
62
  $transdate3 = DateTime->today->add(days => 2);
63
  $transdate4 = DateTime->today->add(days => 3);
61 64

  
62 65
  $buchungsgruppe  = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 19%', %{ $params{buchungsgruppe} }) || croak "No accounting group";
63 66
  $buchungsgruppe7 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%')                                || croak "No accounting group for 7\%";
......
72 75
  $currency_id     = $::instance_conf->get_currency_id;
73 76

  
74 77
  $currency = SL::DB::Currency->new(name => 'CUR')->save;
75
  $exchangerate  = SL::DB::Exchangerate->new(transdate   => $transdate,
78

  
79
  $fxgain_chart = SL::DB::Manager::Chart->find_by(accno => '2660') or die "Can't find fxgain_chart in test";
80
  $fxloss_chart = SL::DB::Manager::Chart->find_by(accno => '2150') or die "Can't find fxloss_chart in test";
81

  
82
  $currency->db->dbh->do('UPDATE defaults SET fxgain_accno_id = ' . $fxgain_chart->id);
83
  $currency->db->dbh->do('UPDATE defaults SET fxloss_accno_id = ' . $fxloss_chart->id);
84
  $::instance_conf->reload->data;
85
  is($fxgain_chart->id,  $::instance_conf->get_fxgain_accno_id, "fxgain_chart was updated in defaults");
86
  is($fxloss_chart->id,  $::instance_conf->get_fxloss_accno_id, "fxloss_chart was updated in defaults");
87

  
88
  $exchangerate  = SL::DB::Exchangerate->new(transdate   => $transdate1,
76 89
                                             buy         => '1.33333',
77 90
                                             sell        => '1.33333',
78 91
                                             currency_id => $currency->id,
79 92
                                            )->save;
80 93
  $exchangerate2 = SL::DB::Exchangerate->new(transdate   => $transdate2,
81
                                             buy         => '1.55555',
82
                                             sell        => '1.55555',
94
                                             buy         => '0.8',
95
                                             sell        => '0.8',
96
                                             currency_id => $currency->id,
97
                                            )->save;
98
  $exchangerate3 = SL::DB::Exchangerate->new(transdate   => $transdate3,
99
                                             buy         => '1.55557',
100
                                             sell        => '1.55557',
101
                                             currency_id => $currency->id,
102
                                            )->save;
103
  $exchangerate4 = SL::DB::Exchangerate->new(transdate   => $transdate4,
104
                                             buy         => '0.77777',
105
                                             sell        => '0.77777',
83 106
                                             currency_id => $currency->id,
84 107
                                            )->save;
85 108

  
......
174 197
    currency_id => $currency_id,
175 198
    employee_id => $employee->id,
176 199
    salesman_id => $employee->id,
177
    gldate      => DateTime->today_local->to_kivitendo,
200
    gldate      => $transdate1,
178 201
    taxzone_id  => $taxzone->id,
179
    transdate   => DateTime->today_local->to_kivitendo,
202
    transdate   => $transdate1,
180 203
    invoice     => 1,
181 204
    type        => 'invoice',
182 205
    %params,
......
195 218
    invnumber   => 'newap ' . $purchase_invoice_counter ,
196 219
    currency_id => $currency_id,
197 220
    employee_id => $employee->id,
198
    gldate      => DateTime->today_local->to_kivitendo,
221
    gldate      => $transdate1,
199 222
    taxzone_id  => $taxzone->id,
200
    transdate   => DateTime->today_local->to_kivitendo,
223
    transdate   => $transdate1,
201 224
    invoice     => 0,
202 225
    type        => 'invoice',
203 226
    taxincluded => 0,
......
213 236
                                        chart_id   => $expense_chart->id,
214 237
                                        chart_link => $expense_chart->link,
215 238
                                        amount     => '-100',
216
                                        transdate  => $transdate,
239
                                        transdate  => $transdate1,
217 240
                                        source     => '',
218 241
                                        taxkey     => 9,
219 242
                                        tax_id     => SL::DB::Manager::Tax->find_by(taxkey => 9)->id);
......
225 248
                                        chart_id   => $tax_chart->id,
226 249
                                        chart_link => $tax_chart->link,
227 250
                                        amount     => '-19',
228
                                        transdate  => $transdate,
251
                                        transdate  => $transdate1,
229 252
                                        source     => '',
230 253
                                        taxkey     => 0,
231 254
                                        tax_id     => SL::DB::Manager::Tax->find_by(taxkey => 9)->id);
......
236 259
                                        chart_id   => $expense_chart->id,
237 260
                                        chart_link => $expense_chart->link,
238 261
                                        amount     => '-100',
239
                                        transdate  => $transdate,
262
                                        transdate  => $transdate1,
240 263
                                        source     => '',
241 264
                                        taxkey     => 8,
242 265
                                        tax_id     => SL::DB::Manager::Tax->find_by(taxkey => 8)->id);
......
249 272
                                         chart_id   => $tax_chart->id,
250 273
                                         chart_link => $tax_chart->link,
251 274
                                         amount     => '-7',
252
                                         transdate  => $transdate,
275
                                         transdate  => $transdate1,
253 276
                                         source     => '',
254 277
                                         taxkey     => 0,
255 278
                                         tax_id     => SL::DB::Manager::Tax->find_by(taxkey => 8)->id);
......
259 282
                                                chart_id   => $arap_chart->id,
260 283
                                                chart_link => $arap_chart->link,
261 284
                                                amount     => '226',
262
                                                transdate  => $transdate,
285
                                                transdate  => $transdate1,
263 286
                                                source     => '',
264 287
                                                taxkey     => 0,
265 288
                                                tax_id     => SL::DB::Manager::Tax->find_by(taxkey => 0)->id);
......
1032 1055
      invoice      => 0,
1033 1056
      amount       => $amount,
1034 1057
      netamount    => $netamount,
1035
      transdate    => $transdate,
1058
      transdate    => $transdate1,
1036 1059
      taxincluded  => 0,
1037 1060
      customer_id  => $customer->id,
1038 1061
      taxzone_id   => $customer->taxzone_id,
......
1060 1083
  $invoice->pay_invoice(chart_id   => $bank->id,
1061 1084
                        amount     => 50,
1062 1085
                        currency   => 'CUR',
1063
                        transdate  => $transdate->to_kivitendo,
1086
                        transdate  => $transdate1->to_kivitendo,
1064 1087
                       );
1065 1088
  $invoice->pay_invoice(chart_id   => $bank->id,
1066 1089
                        amount     => 39.25,
1067 1090
                        currency   => 'CUR',
1068
                        transdate  => $transdate->to_kivitendo,
1091
                        transdate  => $transdate1->to_kivitendo,
1069 1092
                       );
1070 1093
  # $invoice->pay_invoice(chart_id   => $bank->id,
1071 1094
  #                       amount     => 30,
......
1081 1104
  my $netamount = $::form->round_amount($amount / 1.19,2);
1082 1105
  my $invoice = SL::DB::Invoice->new(
1083 1106
      invoice      => 0,
1084
      amount       => 119, #$amount,
1085
      netamount    => 100, #$netamount,
1086
      transdate    => $transdate,
1107
      amount       => 119,
1108
      netamount    => 100,
1109
      transdate    => $transdate1,
1087 1110
      taxincluded  => 1,
1088 1111
      customer_id  => $customer->id,
1089 1112
      taxzone_id   => $customer->taxzone_id,
......
1109 1132
  $invoice->pay_invoice(chart_id   => $bank->id,
1110 1133
                        amount     => 89.25,
1111 1134
                        currency   => 'CUR',
1112
                        transdate  => $transdate->to_kivitendo,
1135
                        transdate  => $transdate1->to_kivitendo,
1113 1136
                       );
1114 1137

  
1115 1138
};
1116 1139

  
1117 1140
sub test_ap_currency_tax_not_included_and_payment {
1118
  my $netamount = $::form->round_amount(75 * $exchangerate->sell,2); #  75 in CUR, 100.00 in EUR
1141
  my $netamount = $::form->round_amount(75 * $exchangerate->buy,2); #  75 in CUR, 100.00 in EUR
1119 1142
  my $amount    = $::form->round_amount($netamount * 1.19,2);        # 100 in CUR, 119.00 in EUR
1120 1143
  my $invoice   = SL::DB::PurchaseInvoice->new(
1121 1144
      invoice      => 0,
1122 1145
      invnumber    => 'test_ap_currency_tax_not_included_and_payment',
1123 1146
      amount       => $amount,
1124 1147
      netamount    => $netamount,
1125
      transdate    => $transdate,
1148
      transdate    => $transdate1,
1126 1149
      taxincluded  => 0,
1127 1150
      vendor_id    => $vendor->id,
1128 1151
      taxzone_id   => $vendor->taxzone_id,
......
1149 1172
  $invoice->pay_invoice(chart_id   => $bank->id,
1150 1173
                        amount     => 50,
1151 1174
                        currency   => 'CUR',
1152
                        transdate  => $transdate->to_kivitendo,
1175
                        transdate  => $transdate1->to_kivitendo,
1153 1176
                       );
1154 1177
  $invoice->pay_invoice(chart_id   => $bank->id,
1155 1178
                        amount     => 39.25,
1156 1179
                        currency   => 'CUR',
1157
                        transdate  => $transdate->to_kivitendo,
1180
                        transdate  => $transdate1->to_kivitendo,
1158 1181
                       );
1159
  # $invoice->pay_invoice(chart_id   => $bank->id,
1160
  #                       amount     => 30,
1161
  #                       transdate  => $transdate2->to_kivitendo,
1162
  #                      );
1163 1182
  is(scalar @{$invoice->transactions}, 9, 'ap transaction has 9 transactions (incl. fxtransactions)');
1164 1183
  is($invoice->paid, $invoice->amount, 'ap transaction paid = amount in default currency');
1165 1184
};
1166 1185

  
1167 1186
sub test_ap_currency_tax_included {
1168 1187
  # we want the acc_trans amount to be 100
1169
  my $amount    = $::form->round_amount(75 * $exchangerate->sell * 1.19);
1188
  my $amount    = $::form->round_amount(75 * $exchangerate->buy * 1.19);
1170 1189
  my $netamount = $::form->round_amount($amount / 1.19,2);
1171 1190
  my $invoice = SL::DB::PurchaseInvoice->new(
1172 1191
      invoice      => 0,
1173 1192
      amount       => 119, #$amount,
1174 1193
      netamount    => 100, #$netamount,
1175
      transdate    => $transdate,
1194
      transdate    => $transdate1,
1176 1195
      taxincluded  => 1,
1177 1196
      vendor_id    => $vendor->id,
1178 1197
      taxzone_id   => $vendor->taxzone_id,
......
1199 1218
  $invoice->pay_invoice(chart_id   => $bank->id,
1200 1219
                        amount     => 89.25,
1201 1220
                        currency   => 'CUR',
1202
                        transdate  => $transdate->to_kivitendo,
1221
                        transdate  => $transdate1->to_kivitendo,
1222
                       );
1223

  
1224
};
1225

  
1226
sub test_ar_currency_tax_not_included_and_payment_2 {
1227
  my $title = 'test_ar_currency_tax_not_included_and_payment_2';
1228
  my $netamount = $::form->round_amount(125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1229
  my $amount    = $::form->round_amount($netamount * 1.19,2);          # 148.75 in CUR, 119.00 in EUR
1230
  my $invoice   = SL::DB::Invoice->new(
1231
      invoice      => 0,
1232
      amount       => $amount,
1233
      netamount    => $netamount,
1234
      transdate    => $transdate2,
1235
      taxincluded  => 0,
1236
      customer_id  => $customer->id,
1237
      taxzone_id   => $customer->taxzone_id,
1238
      currency_id  => $currency->id,
1239
      transactions => [],
1240
      notes        => 'test_ar_currency_tax_not_included_and_payment 0.8',
1241
      invnumber    => 'test_ar_currency_tax_not_included_and_payment 0.8',
1242
  );
1243
  $invoice->add_ar_amount_row(
1244
    amount     => $invoice->netamount,
1245
    chart      => $ar_amount_chart,
1246
    tax_id     => $tax->id,
1247
  );
1248

  
1249
  $invoice->create_ar_row(chart => $ar_chart);
1250
  $invoice->save;
1251

  
1252
  is($invoice->currency_id , $currency->id , "$title: currency_id has been saved");
1253
  is($invoice->netamount   , 100           , "$title: ar amount has been converted");
1254
  is($invoice->amount      , 119           , "$title: ar amount has been converted");
1255
  is($invoice->taxincluded ,   0           , "$title: ar transaction doesn\"t have taxincluded");
1256
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $title . " " . $ar_amount_chart->accno . ": has been converted for currency");
1257
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $title  . " " . $ar_chart->accno . ': has been converted for currency');
1258

  
1259
  $invoice->pay_invoice(chart_id   => $bank->id,
1260
                        amount     => 123.45,
1261
                        currency   => 'CUR',
1262
                        transdate  => $transdate2->to_kivitendo,
1263
                       );
1264
  $invoice->pay_invoice(chart_id   => $bank->id,
1265
                        amount     => 15.30,
1266
                        currency   => 'CUR',
1267
                        transdate  => $transdate3->to_kivitendo,
1268
                       );
1269
  $invoice->pay_invoice(chart_id   => $bank->id,
1270
                        amount     => 10.00,
1271
                        currency   => 'CUR',
1272
                        transdate  => $transdate4->to_kivitendo,
1273
                       );
1274
  # $invoice->pay_invoice(chart_id   => $bank->id,
1275
  #                       amount     => 30,
1276
  #                       transdate  => $transdate2->to_kivitendo,
1277
  #                      );
1278
  my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1279
  is(scalar @{$fx_transactions}, 3, "$title: ar transaction has 3 fx transactions");
1280
  is($fx_transactions->[0]->amount, '24.69000', "$title fx transactions 1: 123.45-(123.45*0.8) = 24.69");
1281

  
1282
  is(scalar @{$invoice->transactions}, 14, "$title ar transaction has 14 transactions (incl. fxtransactions and fx_gain)");
1283
  is($invoice->paid, $invoice->amount, "$title ar transaction paid = amount in default currency");
1284
};
1285

  
1286
sub test_ar_currency_tax_not_included_and_payment_2_credit_note {
1287
  my $netamount = $::form->round_amount(-125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1288
  my $amount    = $::form->round_amount($netamount * 1.19,2);          # 148.75 in CUR, 119.00 in EUR
1289
  my $invoice   = SL::DB::Invoice->new(
1290
      invoice      => 0,
1291
      amount       => $amount,
1292
      netamount    => $netamount,
1293
      transdate    => $transdate2,
1294
      taxincluded  => 0,
1295
      customer_id  => $customer->id,
1296
      taxzone_id   => $customer->taxzone_id,
1297
      currency_id  => $currency->id,
1298
      transactions => [],
1299
      notes        => 'test_ar_currency_tax_not_included_and_payment credit note 0.8',
1300
      invnumber    => 'test_ar_currency_tax_not_included_and_payment credit note 0.8',
1301
  );
1302
  $invoice->add_ar_amount_row(
1303
    amount     => $invoice->netamount,
1304
    chart      => $ar_amount_chart,
1305
    tax_id     => $tax->id,
1306
  );
1307

  
1308
  $invoice->create_ar_row(chart => $ar_chart);
1309
  $invoice->save;
1310

  
1311
  is($invoice->currency_id , $currency->id , 'currency_id has been saved');
1312
  is($invoice->netamount   , -100          , 'ar amount has been converted');
1313
  is($invoice->amount      , -119          , 'ar amount has been converted');
1314
  is($invoice->taxincluded ,   0           , 'ar transaction doesn\'t have taxincluded');
1315
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ar_amount_chart->accno . ': has been converted for currency');
1316
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ar_chart->accno . ': has been converted for currency');
1317

  
1318
  $invoice->pay_invoice(chart_id   => $bank->id,
1319
                        amount     => -123.45,
1320
                        currency   => 'CUR',
1321
                        transdate  => $transdate2->to_kivitendo,
1322
                       );
1323
  $invoice->pay_invoice(chart_id   => $bank->id,
1324
                        amount     => -25.30,
1325
                        currency   => 'CUR',
1326
                        transdate  => $transdate2->to_kivitendo,
1327
                       );
1328
  my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1329
  is(scalar @{$fx_transactions}, 2, 'ar transaction has 2 fx transactions');
1330
  is($fx_transactions->[0]->amount, '-24.69000', 'fx transactions 1: 123.45-(123.45*0.8) = 24.69');
1331

  
1332
  is(scalar @{$invoice->transactions}, 9, 'ar transaction has 9 transactions (incl. fxtransactions)');
1333
  is($invoice->paid, $invoice->amount, 'ar transaction paid = amount in default currency');
1334
};
1335

  
1336
sub test_ap_currency_tax_not_included_and_payment_2 {
1337
  my $title = 'test_ap_currency_tax_not_included_and_payment_2';
1338
  my $netamount = $::form->round_amount(125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1339
  my $amount    = $::form->round_amount($netamount * 1.19,2);          # 148.75 in CUR, 119.00 in EUR
1340
  my $invoice   = SL::DB::PurchaseInvoice->new(
1341
      invoice      => 0,
1342
      amount       => $amount,
1343
      netamount    => $netamount,
1344
      transdate    => $transdate2,
1345
      taxincluded  => 0,
1346
      vendor_id    => $vendor->id,
1347
      taxzone_id   => $vendor->taxzone_id,
1348
      currency_id  => $currency->id,
1349
      transactions => [],
1350
      notes        => 'test_ap_currency_tax_not_included_and_payment_2 0.8 + 1.33333',
1351
      invnumber    => 'test_ap_currency_tax_not_included_and_payment_2 0.8 + 1.33333',
1352
  );
1353
  $invoice->add_ap_amount_row(
1354
    amount     => $invoice->netamount,
1355
    chart      => $ap_amount_chart,
1356
    tax_id     => $tax_9->id,
1357
  );
1358

  
1359
  $invoice->create_ap_row(chart => $ap_chart);
1360
  $invoice->save;
1361

  
1362
  is($invoice->currency_id , $currency->id , "$title: currency_id has been saved");
1363
  is($invoice->netamount   ,  100          , "$title: ap amount has been converted");
1364
  is($invoice->amount      ,  119          , "$title: ap amount has been converted");
1365
  is($invoice->taxincluded ,    0          , "$title: ap transaction doesn\'t have taxincluded");
1366
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency');
1367
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency');
1368

  
1369
  $invoice->pay_invoice(chart_id   => $bank->id,
1370
                        amount     => 10,
1371
                        currency   => 'CUR',
1372
                        transdate  => $transdate2->to_kivitendo,
1373
                       );
1374
  $invoice->pay_invoice(chart_id   => $bank->id,
1375
                        amount     => 123.45,
1376
                        currency   => 'CUR',
1377
                        transdate  => $transdate3->to_kivitendo,
1203 1378
                       );
1379
  $invoice->pay_invoice(chart_id   => $bank->id,
1380
                        amount     => 15.30,
1381
                        currency   => 'CUR',
1382
                        transdate  => $transdate4->to_kivitendo,
1383
                       );
1384
  my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1385
  is(scalar @{$fx_transactions}, 3, "$title: ap transaction has 3 fx transactions");
1386
  is($fx_transactions->[0]->amount,  '-2.00000', "$title: fx transaction 1:  10.00-( 10.00*0.80000) =   2.00000");
1387
  is($fx_transactions->[1]->amount,  '68.59000', "$title: fx transaction 2: 123.45-(123.45*1.55557) = -68.58511");
1388
  is($fx_transactions->[2]->amount,  '-3.40000', "$title: fx transaction 3:  15.30-(15.30 *0.77777) =   3.40012");
1389

  
1390
  my $fx_loss_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxloss_chart->id ], sort_by => ('acc_trans_id'));
1391
  my $fx_gain_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxgain_chart->id ], sort_by => ('acc_trans_id'));
1392
  is($fx_gain_transactions->[0]->amount,   '0.34000', "$title: fx gain amount ok");
1393
  is($fx_loss_transactions->[0]->amount, '-93.28000', "$title: fx loss amount ok");
1394

  
1395
  is(scalar @{$invoice->transactions}, 14, "$title: ap transaction has 14 transactions (incl. fxtransactions and gain_loss)");
1396
  is($invoice->paid, $invoice->amount, "$title: ap transaction paid = amount in default currency");
1397
  is(total_amount($invoice), 0,   "$title: even balance");
1398
};
1399

  
1400
sub test_ap_currency_tax_not_included_and_payment_2_credit_note {
1401
  my $title = 'test_ap_currency_tax_not_included_and_payment_2_credit_note';
1402
  my $netamount = $::form->round_amount(-125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1403
  my $amount    = $::form->round_amount($netamount * 1.19,2);          # 148.75 in CUR, 119.00 in EUR
1404
  my $invoice   = SL::DB::PurchaseInvoice->new(
1405
      invoice      => 0,
1406
      amount       => $amount,
1407
      netamount    => $netamount,
1408
      transdate    => $transdate2,
1409
      taxincluded  => 0,
1410
      vendor_id    => $vendor->id,
1411
      taxzone_id   => $vendor->taxzone_id,
1412
      currency_id  => $currency->id,
1413
      transactions => [],
1414
      notes        => 'test_ap_currency_tax_not_included_and_payment credit note 0.8 + 1.33333',
1415
      invnumber    => 'test_ap_currency_tax_not_included_and_payment credit note 0.8 + 1.33333',
1416
  );
1417
  $invoice->add_ap_amount_row(
1418
    amount     => $invoice->netamount,
1419
    chart      => $ap_amount_chart,
1420
    tax_id     => $tax_9->id,
1421
  );
1422

  
1423
  $invoice->create_ap_row(chart => $ap_chart);
1424
  $invoice->save;
1204 1425

  
1426
  is($invoice->currency_id , $currency->id , "$title: currency_id has been saved");
1427
  is($invoice->netamount   , -100          , "$title: ap amount has been converted");
1428
  is($invoice->amount      , -119          , "$title: ap amount has been converted");
1429
  is($invoice->taxincluded ,   0           , "$title: ap transaction doesn\'t have taxincluded");
1430
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ap_amount_chart->accno . ': has been converted for currency');
1431
  is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ap_chart->accno . ': has been converted for currency');
1432

  
1433
  $invoice->pay_invoice(chart_id   => $bank->id,
1434
                        amount     => -10,
1435
                        currency   => 'CUR',
1436
                        transdate  => $transdate2->to_kivitendo,
1437
                       );
1438
  $invoice->pay_invoice(chart_id   => $bank->id,
1439
                        amount     => -123.45,
1440
                        currency   => 'CUR',
1441
                        transdate  => $transdate3->to_kivitendo,
1442
                       );
1443
  $invoice->pay_invoice(chart_id   => $bank->id,
1444
                        amount     => -15.30,
1445
                        currency   => 'CUR',
1446
                        transdate  => $transdate4->to_kivitendo,
1447
                       );
1448
  my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1449
  is(scalar @{$fx_transactions}, 3, "$title: ap transaction has 3 fx transactions");
1450
  is($fx_transactions->[0]->amount,   '2.00000', "$title: fx transaction 1:  10.00-( 10.00*0.80000) =   2.00000");
1451
  is($fx_transactions->[1]->amount, '-68.59000', "$title: fx transaction 2: 123.45-(123.45*1.55557) = -68.58511");
1452
  is($fx_transactions->[2]->amount,   '3.40000', "$title: fx transaction 3:  15.30-(15.30 *0.77777) =   3.40012");
1453

  
1454
  my $fx_gain_loss_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxgain_chart->id ], sort_by => ('acc_trans_id'));
1455
  is($fx_gain_loss_transactions->[0]->amount, '93.28000', "$title: fx gain loss amount ok");
1456

  
1457
  is(scalar @{$invoice->transactions}, 14, "$title: ap transaction has 14 transactions (incl. fxtransactions and gain_loss)");
1458
  is($invoice->paid, $invoice->amount, "$title: ap transaction paid = amount in default currency");
1459
  is(total_amount($invoice), 0,   "$title: even balance");
1205 1460
};
1206 1461

  
1207 1462
Support::TestSetup::login();
1208
 # die;
1209 1463

  
1210 1464
# test cases: without_skonto
1211
 test_default_invoice_one_item_19_without_skonto();
1212
 test_default_invoice_two_items_19_7_tax_with_skonto();
1213
 test_default_invoice_two_items_19_7_without_skonto();
1214
 test_default_invoice_two_items_19_7_without_skonto_incomplete_payment();
1215
 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments();
1216
 test_default_purchase_invoice_two_charts_19_7_without_skonto();
1217
 test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto();
1218
 test_default_invoice_one_item_19_without_skonto_overpaid();
1465
test_default_invoice_one_item_19_without_skonto();
1466
test_default_invoice_two_items_19_7_tax_with_skonto();
1467
test_default_invoice_two_items_19_7_without_skonto();
1468
test_default_invoice_two_items_19_7_without_skonto_incomplete_payment();
1469
test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments();
1470
test_default_purchase_invoice_two_charts_19_7_without_skonto();
1471
test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto();
1472
test_default_invoice_one_item_19_without_skonto_overpaid();
1219 1473

  
1220 1474
# test cases: difference_as_skonto
1221
 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto();
1222
 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent();
1223
 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent();
1224
 test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto();
1225
 test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent();
1226
 test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto();
1475
test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto();
1476
test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent();
1477
test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent();
1478
test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto();
1479
test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent();
1480
test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto();
1227 1481

  
1228 1482
# test cases: with_skonto_pt
1229
 test_default_invoice_two_items_19_7_tax_with_skonto_50_50();
1230
 test_default_invoice_four_items_19_7_tax_with_skonto_4x_25();
1231
 test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple();
1232
 test_default_purchase_invoice_two_charts_19_7_with_skonto();
1233
 test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included();
1234
 test_default_invoice_two_items_19_7_tax_with_skonto_tax_included();
1483
test_default_invoice_two_items_19_7_tax_with_skonto_50_50();
1484
test_default_invoice_four_items_19_7_tax_with_skonto_4x_25();
1485
test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple();
1486
test_default_purchase_invoice_two_charts_19_7_with_skonto();
1487
test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included();
1488
test_default_invoice_two_items_19_7_tax_with_skonto_tax_included();
1235 1489

  
1236 1490
# test payment of ar and ap transactions with currency and tax included/not included
1237
 test_ar_currency_tax_not_included_and_payment();
1238
 test_ar_currency_tax_included();
1239
 test_ap_currency_tax_not_included_and_payment();
1240
 test_ap_currency_tax_included();
1491
# exchangerate = 1.33333
1492
test_ar_currency_tax_not_included_and_payment();
1493
test_ar_currency_tax_included();
1494
test_ap_currency_tax_not_included_and_payment();
1495
test_ap_currency_tax_included();
1496

  
1497
test_ar_currency_tax_not_included_and_payment_2();              # exchangerate 0.8
1498
test_ar_currency_tax_not_included_and_payment_2_credit_note();  # exchangerate 0.8
1499

  
1500
test_ap_currency_tax_not_included_and_payment_2();             # two exchangerates, with fx_gain_loss
1501
test_ap_currency_tax_not_included_and_payment_2_credit_note(); # two exchangerates, with fx_gain_loss
1502

  
1503
{ local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct";
1504
  my ($acc_trans_sum)  = selectfirst_array_query($::form, $currency->db->dbh, 'SELECT SUM(amount) FROM acc_trans'); is($acc_trans_sum, '0.00000', "sum of all acc_trans is 0");
1505
}
1241 1506

  
1242 1507
# remove all created data at end of test
1243 1508
clear_up();

Auch abrufbar als: Unified diff