2 use Test::More tests => 7;
 
   5 use Support::TestSetup;
 
  11 use SL::DATEV qw(:CONSTANTS);
 
  12 use SL::Dev::CustomerVendor qw(new_customer);
 
  15 my ($customer, $employee, $ar_tax_19, $ar_tax_7, $ar_tax_0);
 
  16 my ($ar_chart, $bank, $ar_amount_chart);
 
  18 $config->{numberformat} = '1.000,00';
 
  23   $params{$_} ||= {} for qw(buchungsgruppe customer);
 
  27   $employee        = SL::DB::Manager::Employee->current                       || croak "No employee";
 
  28   $ar_tax_19       = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19) || croak "No 19% tax";
 
  29   $ar_tax_7        = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No 7% tax";
 
  30   $ar_tax_0        = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.00) || croak "No 0% tax";
 
  32   $customer = new_customer()->save; # new customer with default name "Testkunde"
 
  34   $ar_chart        = SL::DB::Manager::Chart->find_by(accno => '1400') || croak "Can't find Forderungen";
 
  35   $bank            = SL::DB::Manager::Chart->find_by(accno => '1200') || croak "Can't find Bank";
 
  36   $ar_amount_chart = SL::DB::Manager::Chart->find_by(accno => '8590') || croak "Can't find verrechn., eigentlich Anzahlungen";
 
  40 Support::TestSetup::login();
 
  44 # check ar without tax
 
  45 my $invoice = _ar(customer     => $customer,
 
  48                   notes        => 'ar without tax',
 
  51 # for testing load a fresh instance of the invoice from the database
 
  52 my $inv = SL::DB::Invoice->new(id => $invoice->id)->load;
 
  54   my $number_of_acc_trans = scalar @{ $inv->transactions };
 
  55   is($::form->round_amount($inv->amount) , 100                           , "invoice_amount = 100");
 
  56   is($number_of_acc_trans                , 5                             , "number of transactions");
 
  57   is($inv->datepaid->to_kivitendo        , DateTime->today->to_kivitendo , "datepaid");
 
  58   is($inv->amount - $inv->paid           , 0                             , "paid = amount ");
 
  59   is($inv->gldate->to_kivitendo, $inv->transactions->[0]->gldate->to_kivitendo, "gldate matches in ar and acc_trans");
 
  61   ok 0, "couldn't find first invoice";
 
  65 my $invoice2 = _ar_with_tax(customer     => $customer,
 
  68                             notes        => 'ar with taxincluded',
 
  70 my $inv_with_tax = SL::DB::Invoice->new(id => $invoice2->id)->load;
 
  71 if ( $inv_with_tax ) {
 
  72   is(scalar @{ $inv_with_tax->transactions }, 7,  "number of transactions for inv_with_tax");
 
  74   ok 0, "couldn't find second invoice";
 
  78 is(SL::DB::Manager::Invoice->get_all_count(), 2,  "total number of invoices created is 2");
 
  86   SL::DB::Manager::AccTransaction->delete_all(all => 1);
 
  87   SL::DB::Manager::Invoice->delete_all(       all => 1);
 
  88   SL::DB::Manager::Customer->delete_all(      all => 1);
 
  94   my $amount       = $params{amount}       || croak "ar needs param amount";
 
  95   my $customer     = $params{customer}     || croak "ar needs param customer";
 
  96   my $transdate    = $params{transdate}    || DateTime->today;
 
  97   my $gldate       = $params{gldate}       || DateTime->today->add(days => 1);
 
  98   my $with_payment = $params{with_payment} || 0;
 
 100   # SL::DB::Invoice has a _before_save_set_invnumber hook, so we don't need to pass invnumber
 
 101   my $invoice = SL::DB::Invoice->new(
 
 104       netamount        => $amount,
 
 105       transdate        => $transdate,
 
 108       customer_id      => $customer->id,
 
 109       taxzone_id       => $customer->taxzone_id,
 
 110       currency_id      => $customer->currency_id,
 
 111       globalproject_id => $params{project},
 
 112       notes            => $params{notes},
 
 116   my $db = $invoice->db;
 
 118   $db->with_transaction( sub {
 
 120     $invoice->add_ar_amount_row(
 
 121       amount     => $amount / 2,
 
 122       chart      => $ar_amount_chart,
 
 123       tax_id     => $ar_tax_0->id,
 
 125     $invoice->add_ar_amount_row(
 
 126       amount     => $amount / 2,
 
 127       chart      => $ar_amount_chart,
 
 128       tax_id     => $ar_tax_0->id,
 
 131     $invoice->create_ar_row( chart => $ar_chart );
 
 133     _save_and_pay_and_check(invoice     => $invoice,
 
 135                             pay         => $with_payment,
 
 141   }) || die "something went wrong: " . $db->error;
 
 148   my $amount       = $params{amount}       || croak "ar needs param amount";
 
 149   my $customer     = $params{customer}     || croak "ar needs param customer";
 
 150   my $transdate    = $params{transdate}    || DateTime->today;
 
 151   my $gldate       = $params{gldate}       || DateTime->today->add(days => 1);
 
 152   my $with_payment = $params{with_payment} || 0;
 
 154   my $invoice = SL::DB::Invoice->new(
 
 157     netamount        => $amount,
 
 158     transdate        => $transdate,
 
 161     customer_id      => $customer->id,
 
 162     taxzone_id       => $customer->taxzone_id,
 
 163     currency_id      => $customer->currency_id,
 
 164     globalproject_id => $params{project},
 
 165     notes            => $params{notes},
 
 169   my $db = $invoice->db;
 
 171   $db->with_transaction( sub {
 
 173     # TODO: check for currency and exchange rate
 
 175     $invoice->add_ar_amount_row(
 
 176       amount     => $amount / 2,
 
 177       chart      => $ar_amount_chart,
 
 178       tax_id     => $ar_tax_19->id,
 
 180     $invoice->add_ar_amount_row(
 
 181       amount     => $amount / 2,
 
 182       chart      => $ar_amount_chart,
 
 183       tax_id     => $ar_tax_19->id,
 
 186     $invoice->create_ar_row( chart => $ar_chart );
 
 187     _save_and_pay_and_check(invoice     => $invoice,
 
 189                             pay         => $with_payment,
 
 194   }) || die "something went wrong: " . $db->error;
 
 198 sub _save_and_pay_and_check {
 
 200   my $invoice     = $params{invoice} // croak "invoice missing";
 
 201   my $datev_check = $params{datev_check} // 1; # do datev check by default
 
 202   croak "no bank" unless ref $params{bank} eq 'SL::DB::Chart';
 
 204   # make sure invoice is saved before making payments
 
 205   my $return = $invoice->save;
 
 207   $invoice->pay_invoice(chart_id     => $params{bank}->id,
 
 208                         amount       => $invoice->amount,
 
 209                         transdate    => $invoice->transdate->to_kivitendo,
 
 210                         payment_type => 'without_skonto',  # default if not specified
 
 214     my $datev = SL::DATEV->new(
 
 215       dbh        => $invoice->db->dbh,
 
 216       trans_id   => $invoice->id,
 
 219     $datev->generate_datev_data;
 
 221     # _save_and_pay_and_check should always be called inside a with_transaction block
 
 222     if ($datev->errors) {
 
 223       $invoice->db->dbh->rollback;
 
 224       die join "\n", $::locale->text('DATEV check returned errors:'), $datev->errors;