Merge branch 'f-phone-number-lookup'
authorMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 22 Mar 2019 11:56:12 +0000 (12:56 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 22 Mar 2019 11:56:12 +0000 (12:56 +0100)
SL/Controller/BankTransaction.pm
SL/Controller/Order.pm
bin/mozilla/ct.pl
bin/mozilla/ic.pl
js/kivi.BankTransaction.js
locale/de/all
sql/Pg-upgrade2/bank_transactions_check_constraint_invoice_amount.sql [new file with mode: 0644]
t/bank/bank_transactions.t
t/db_helper/payment.t
templates/webpages/bank_transactions/_payment_suggestion.html

index 638da64..a937451 100644 (file)
@@ -570,7 +570,6 @@ sub save_single_bank_transaction {
   my $worker = sub {
     my $bt_id                 = $data{bank_transaction_id};
     my $sign                  = $bank_transaction->amount < 0 ? -1 : 1;
-    my $not_assigned_amount   = $bank_transaction->not_assigned_amount;
     my $payment_received      = $bank_transaction->amount > 0;
     my $payment_sent          = $bank_transaction->amount < 0;
 
@@ -617,9 +616,8 @@ sub save_single_bank_transaction {
       my $memo   = ($data{memos}   // [])->[$n_invoices];
 
       $n_invoices++ ;
-
-
-      if (!$not_assigned_amount && $invoice->open_amount) {
+      if (   ($payment_sent     && $bank_transaction->not_assigned_amount >= 0)
+          || ($payment_received && $bank_transaction->not_assigned_amount <= 0)) {
         return {
           %data,
           result  => 'error',
@@ -654,10 +652,11 @@ sub save_single_bank_transaction {
     # should be better done elsewhere - changing not_assigned_amount to abs feels seriously bogus
 
     my $open_amount = $payment_type eq 'with_skonto_pt' ? $invoice->amount_less_skonto : $invoice->open_amount;
-    $open_amount         = abs($open_amount);
-    $not_assigned_amount = abs($not_assigned_amount);
-    my $amount_for_booking = ($open_amount < $not_assigned_amount) ? $open_amount : $not_assigned_amount;
-    my $amount_for_payment = $amount_for_booking;
+    $open_amount            = abs($open_amount);
+    $open_amount           -= $free_skonto_amount if ($payment_type eq 'free_skonto');
+    my $not_assigned_amount = abs($bank_transaction->not_assigned_amount);
+    my $amount_for_booking  = ($open_amount < $not_assigned_amount) ? $open_amount : $not_assigned_amount;
+    my $amount_for_payment  = $amount_for_booking;
 
     # get the right direction for the payment bookings (all amounts < 0 are stornos, credit notes or negative ap)
     $amount_for_payment *= -1 if $invoice->amount < 0;
index 52577bd..f6afed9 100644 (file)
@@ -1383,7 +1383,7 @@ sub recalc {
                                 tax       => $tax });
   }
 
-  pairwise { $a->{linetotal} = $b->{linetotal} } @{$self->order->items}, @{$pat{items}};
+  pairwise { $a->{linetotal} = $b->{linetotal} } @{$self->order->items_sorted}, @{$pat{items}};
 }
 
 # get data for saving, printing, ..., that is not changed in the form
index 11c81ee..77770d8 100644 (file)
@@ -229,6 +229,8 @@ sub list_names {
       addr_city addr_country addr_gln business_id salesman_id insertdateto insertdatefrom all
     ), "$form->{db}number",
     map({ "cvar_$_->{name}" } @searchable_custom_variables),
+    map({'cvar_'. $_->{name} .'_from'} grep({$_->{type} eq 'date'} @searchable_custom_variables)),
+    map({'cvar_'. $_->{name} .'_to'}   grep({$_->{type} eq 'date'} @searchable_custom_variables)),
     map({'cvar_'. $_->{name} .'_qtyop'} grep({$_->{type} eq 'number'} @searchable_custom_variables)),
     map({ "l_$_" } @columns),
   );
index 9e3da51..9803f0c 100644 (file)
@@ -420,6 +420,8 @@ sub generate_report {
     @itemstatus_keys,
     @callback_keys,
     map({ "cvar_$_->{name}" } @searchable_custom_variables),
+    map({'cvar_'. $_->{name} .'_from'} grep({$_->{type} eq 'date'} @searchable_custom_variables)),
+    map({'cvar_'. $_->{name} .'_to'}   grep({$_->{type} eq 'date'} @searchable_custom_variables)),
     map({'cvar_'. $_->{name} .'_qtyop'} grep({$_->{type} eq 'number'} @searchable_custom_variables)),
     map({ "l_$_" } @columns),
   );
index a0a0f0f..b756217 100644 (file)
@@ -82,7 +82,17 @@ namespace('kivi.BankTransaction', function(ns) {
     var amount     = $container.data('invoice-amount') * 1;
 
     $('[id^="' + bank_transaction_id + '."]').each(function(idx, elt) {
-      amount += $(elt).data('invoice-amount');
+      if ($("input[name='skonto_pt." + elt.id + "']").val() == 1) {
+        // skonto payment term
+        amount += $(elt).data('invoice-amount-less-skonto');
+      } else {
+        // normal amount
+        amount += $(elt).data('invoice-amount');
+        //subtract free skonto if checked (no check for number!)
+        if ($("input[name='skonto_pt." + elt.id + "']").val() == 'free_skonto') {
+          amount -= $("input[name='free_skonto_amount." + elt.id + "']").val();
+        }
+      }
     });
 
     $container.html(kivi.format_amount(amount, 2));
@@ -141,19 +151,25 @@ namespace('kivi.BankTransaction', function(ns) {
     });
   };
   ns.update_skonto = function(caller, bt_id, prop_id, formatted_amount_with_skonto_pt) {
+
     if (caller.value === 'free_skonto') {
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).val("");
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).prop('disabled', false);
+      $("input[name='skonto_pt." + bt_id + '.' + prop_id + "']").val('free_skonto');
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).focus();
     }
     if (caller.value === 'without_skonto') {
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).val(kivi.format_amount(0,2));
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).prop('disabled', true);
+      $("input[name='skonto_pt." + bt_id + '.' + prop_id + "']").val(0);
     }
     if (caller.value === 'with_skonto_pt') {
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).val(formatted_amount_with_skonto_pt);
       $('#free_skonto_amount_' + bt_id + '_' + prop_id).prop('disabled', true);
+      $("input[name='skonto_pt." + bt_id + '.' + prop_id + "']").val(1);
     }
+    // recalc assigned amount
+    ns.update_invoice_amount(bt_id);
   };
 
 });
index 8836f03..f1dd92b 100755 (executable)
@@ -398,6 +398,7 @@ $self->{texts} = {
   'Bank Connections'            => 'Bankverbindungen',
   'Bank Import'                 => 'Kontoauszug importieren',
   'Bank Transaction'            => 'Bankkonto',
+  'Bank Transaction is in a closed period.' => 'Die Bankbewegung befindet sich innerhalb eines geschlossenen Zeitraums.',
   'Bank account'                => 'Bankkonto',
   'Bank accounts'               => 'Bankkonten',
   'Bank code'                   => 'Bankleitzahl',
@@ -1456,6 +1457,7 @@ $self->{texts} = {
   'Formula'                     => 'Formel',
   'France'                      => 'Frankreich',
   'Free report period'          => 'Freier Zeitraum',
+  'Free skonto amount has to be a positive number.' => 'Der freie Skontobetrag muss positiv (absolut) sein.',
   'Free-form text'              => 'Textzeile',
   'Fristsetzung'                => 'Fristsetzung',
   'From'                        => 'Von',
@@ -3934,6 +3936,7 @@ $self->{texts} = {
   'You have to specify an execution date for each antry.' => 'Sie müssen für jeden zu buchenden Eintrag ein Ausführungsdatum angeben.',
   'You must chose a user.'      => 'Sie müssen einen Benutzer auswählen.',
   'You must enter a name for your new print templates.' => 'Sie müssen einen Namen für die neuen Druckvorlagen angeben.',
+  'You must not change this AP transaction.' => 'Sie dürfen diese Kreditorenbuchung nicht verändern.',
   'You must not change this AR transaction.' => 'Sie dürfen diese Debitorenbuchung nicht verändern.',
   'You must not change this invoice.' => 'Sie dürfen diese Rechnung nicht verändern.',
   'You must not print this invoice.' => 'Sie dürfen diese Rechnung nicht drucken.',
@@ -4047,6 +4050,7 @@ $self->{texts} = {
   'for date'                    => 'zum Stichtag',
   'found'                       => 'Gefunden',
   'found_br'                    => 'Gef.',
+  'free skonto'                 => 'Freier Skontobetrag',
   'from'                        => 'von',
   'from \'#1\' imported Files'  => 'Von \'#1\' importierte Dateien',
   'from (time)'                 => 'von',
diff --git a/sql/Pg-upgrade2/bank_transactions_check_constraint_invoice_amount.sql b/sql/Pg-upgrade2/bank_transactions_check_constraint_invoice_amount.sql
new file mode 100644 (file)
index 0000000..cb81293
--- /dev/null
@@ -0,0 +1,5 @@
+-- @tag: bank_transactions_check_constraint_invoice_amount
+-- @description: Bank-Transaktionen dürfen mehrfach verbucht werden - Sicherheitscheck auf DB-Ebene, Überbuchen der Bankbewegung verbieten
+-- @depends: bank_transactions_type2 release_3_5_3
+
+ALTER TABLE bank_transactions ADD CHECK (abs(invoice_amount) <= abs(amount));
index aaff649..8b38424 100644 (file)
@@ -1,4 +1,4 @@
-use Test::More tests => 290;
+use Test::More tests => 289;
 
 use strict;
 
@@ -51,6 +51,7 @@ sub clear_up {
   SL::DB::Manager::BankAccount->delete_all(all => 1);
   SL::DB::Manager::PaymentTerm->delete_all(all => 1);
   SL::DB::Manager::Currency->delete_all(where => [ name => 'CUR' ]);
+  # SL::DB::Manager::Default->delete_all(all => 1);
 };
 
 my $bt_controller;
@@ -1189,18 +1190,19 @@ sub test_closedto {
   is($bt1->closed_period, 0, "$testname undefined closedto");
 
   my $defaults = SL::DB::Manager::Default->get_all(limit => 1)->[0];
-  $defaults->closedto(DateTime->new(year => 2019, month => 12, day => 30));
+  $defaults->closedto(DateTime->new(year => 2019, month => 12, day => 31));
   $defaults->save();
   $::instance_conf->reload->data;
   $bt1->load();
+  is($bt1->closed_period, 1, "$testname defined and next date closedto");
 
-  is($bt1->closed_period, 1, "$testname defined and same date closedto");
-
-  $bt1->valutadate(DateTime->new(year => 2019, month => 12, day => 31));
+  $bt1->valutadate(DateTime->new(year => 2020, month => 1, day => 1));
   $bt1->save();
   $bt1->load();
 
   is($bt1->closed_period, 0, "$testname defined closedto and next date valuta");
+  $defaults->closedto(undef);
+  $defaults->save();
 
 }
 
index 508bfc9..b23958e 100644 (file)
@@ -347,7 +347,7 @@ sub total_amount {
 
 
 # test 1
-sub test_default_invoice_one_item_19_without_skonto() {
+sub test_default_invoice_one_item_19_without_skonto {
   my $title = 'default invoice, one item, 19% tax, without_skonto';
   my $item    = create_invoice_item(part => $parts[0], qty => 2.5);
   my $invoice = create_sales_invoice(
@@ -380,7 +380,7 @@ sub test_default_invoice_one_item_19_without_skonto() {
 
 }
 
-sub test_default_invoice_one_item_19_without_skonto_overpaid() {
+sub test_default_invoice_one_item_19_without_skonto_overpaid {
   my $title = 'default invoice, one item, 19% tax, without_skonto';
 
   my $item    = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -419,7 +419,7 @@ sub test_default_invoice_one_item_19_without_skonto_overpaid() {
 
 
 # test 2
-sub test_default_invoice_two_items_19_7_tax_with_skonto() {
+sub test_default_invoice_two_items_19_7_tax_with_skonto {
   my $title = 'default invoice, two items, 19/7% tax with_skonto_pt';
 
   my $item1   = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -451,7 +451,7 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto() {
   is($total,                          0,   "${title}: even balance");
 }
 
-sub test_default_invoice_two_items_19_7_tax_with_skonto_tax_included() {
+sub test_default_invoice_two_items_19_7_tax_with_skonto_tax_included {
   my $title = 'default invoice, two items, 19/7% tax with_skonto_pt';
 
   my $item1   = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -488,7 +488,7 @@ TODO: {
 }
 
 # test 3 : two items, without skonto
-sub test_default_invoice_two_items_19_7_without_skonto() {
+sub test_default_invoice_two_items_19_7_without_skonto {
   my $title = 'default invoice, two items, 19/7% tax without skonto';
 
   my $item1   = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -521,7 +521,7 @@ sub test_default_invoice_two_items_19_7_without_skonto() {
 }
 
 # test 4
-sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment() {
+sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment {
   my $title = 'default invoice, two items, 19/7% tax without skonto incomplete payment';
 
   my $item1   = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -550,7 +550,7 @@ sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment() {
 }
 
 # test 5
-sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments() {
+sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments {
   my $title = 'default invoice, two items, 19/7% tax not included';
 
   my $item1   = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -584,7 +584,7 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments() {
 }
 
 # test 6
-sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto() {
+sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto {
   my $title = 'default invoice, two items, 19/7% tax not included';
 
   my $item1   = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -623,7 +623,7 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fin
 
 }
 
-sub  test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent() {
+sub  test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent {
   my $title = 'default invoice, two items, 19/7% tax not included';
 
   # if there is only one cent left there can only be one skonto booking, the
@@ -662,7 +662,7 @@ sub  test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fi
 
 }
 
-sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent() {
+sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent {
   my $title = 'default invoice, two items, 19/7% tax not included';
 
   # if there are two cents left there will be two skonto bookings, 1 cent each
@@ -697,7 +697,7 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fin
 
 }
 
-sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto() {
+sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto {
   my $title = 'default invoice, one item, 19% tax, without_skonto';
 
   my $item    = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -736,7 +736,7 @@ sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto
 
 }
 
-sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent() {
+sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent {
   my $title = 'default invoice, one item, 19% tax, without_skonto';
 
   my $item    = create_invoice_item(part => $parts[0], qty => 2.5);
@@ -772,7 +772,7 @@ sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto
 }
 
 # test 3 : two items, without skonto
-sub test_default_purchase_invoice_two_charts_19_7_without_skonto() {
+sub test_default_purchase_invoice_two_charts_19_7_without_skonto {
   my $title = 'default invoice, two items, 19/7% tax without skonto';
 
   my $purchase_invoice = new_purchase_invoice();
@@ -795,7 +795,7 @@ sub test_default_purchase_invoice_two_charts_19_7_without_skonto() {
 
 }
 
-sub test_default_purchase_invoice_two_charts_19_7_with_skonto() {
+sub test_default_purchase_invoice_two_charts_19_7_with_skonto {
   my $title = 'default invoice, two items, 19/7% tax without skonto';
 
   my $purchase_invoice = new_purchase_invoice();
@@ -818,7 +818,7 @@ sub test_default_purchase_invoice_two_charts_19_7_with_skonto() {
 
 }
 
-sub test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto() {
+sub test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto {
   my $title = 'default purchase_invoice, two charts, 19/7% tax multiple payments with final difference as skonto';
 
   # check whether unrounded amounts passed via $params{amount} are rounded for without_skonto case
@@ -838,7 +838,7 @@ sub test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_
 };
 
 
-sub test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto() {
+sub test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto {
   my $title = 'default purchase_invoice, two charts, 19/7% tax multiple payments with final difference as skonto';
 
   my $purchase_invoice = new_purchase_invoice();
@@ -872,7 +872,7 @@ sub test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_pa
 }
 
 # test
-sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50() {
+sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50 {
   my $title = 'default invoice, two items, 19/7% tax with_skonto_pt 50/50';
 
   my $item1   = create_invoice_item(part => $parts[2], qty => 1);
@@ -905,7 +905,7 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50() {
 }
 
 # test
-sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25() {
+sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25 {
   my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25';
 
   my $item1   = create_invoice_item(part => $parts[2], qty => 0.5);
@@ -939,7 +939,7 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25() {
   is($total              , 0    , "${title}: even balance");
 }
 
-sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included() {
+sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included {
   my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25';
 
   my $item1   = create_invoice_item(part => $parts[2], qty => 0.5);
@@ -976,7 +976,7 @@ TODO: {
   }
 }
 
-sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple() {
+sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple {
   my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25';
 
   my $item1   = create_invoice_item(part => $parts[2], qty => 0.5);
index 8f2e736..d481621 100644 (file)
@@ -1,12 +1,16 @@
 [%- USE P -%][%- USE HTML -%][%- USE LxERP -%]
-<span id="[% HTML.escape(bt_id) %].[% HTML.escape(invoice.id) %]" data-invoice-amount="[% HTML.escape(invoice.open_amount * 1) %]">
+[% SELECT_OPTIONS = invoice.get_payment_select_options_for_bank_transaction(bt_id) %]
+[% is_skonto_pt   = SELECT_OPTIONS.1.selected %]
+[% formatted_skonto_amount          = LxERP.format_amount(invoice.skonto_amount, 2) %]
+[% formatted_skonto_amount_selected = is_skonto_pt ? $formatted_skonto_amount : LxERP.format_amount(0, 2) %]
+<span id="[% HTML.escape(bt_id) %].[% HTML.escape(invoice.id) %]"
+  data-invoice-amount="[% HTML.escape(invoice.open_amount * 1) %]"
+  data-invoice-amount-less-skonto="[% HTML.escape(invoice.amount_less_skonto * 1) %]">
  [% P.hidden_tag("invoice_ids." _ bt_id _ "[]", invoice.id) %]
- [% SELECT_OPTIONS = invoice.get_payment_select_options_for_bank_transaction(bt_id) %]
- [% formatted_skonto_amount_selected = SELECT_OPTIONS.1.selected ? LxERP.format_amount(invoice.skonto_amount, 2) : LxERP.format_amount(0, 2) %]
- [% formatted_skonto_amount          = LxERP.format_amount(invoice.skonto_amount, 2) %]
+ [% P.hidden_tag("skonto_pt." _ bt_id _ "." _ invoice.id _ "", is_skonto_pt) %]
  [% LxERP.t8("Invno.") %]: [% HTML.escape(invoice.invnumber) %]</br>
  [% LxERP.t8("Open amount") %]: [% LxERP.format_amount(invoice.open_amount, 2) %]</br>
  [% P.select_tag("invoice_skontos." _ bt_id _ "[]", SELECT_OPTIONS, value_key="payment_type", title_key="display", onChange="kivi.BankTransaction.update_skonto(this, " _ bt_id _ ", " _ invoice.id _ ", '$formatted_skonto_amount')"  ) %]</br>
- [% LxERP.t8("Skonto amount") %]: [% P.input_tag("free_skonto_amount." _ bt_id _ "." _ invoice.id _ "", "$formatted_skonto_amount_selected", default=0, style=style, disabled=1, size=4, class='numeric') %]
+ [% LxERP.t8("Skonto amount") %]: [% P.input_tag("free_skonto_amount." _ bt_id _ "." _ invoice.id _ "", "$formatted_skonto_amount_selected", default=0, style=style, disabled=1, size=4, class='numeric', onblur="kivi.BankTransaction.update_invoice_amount(" _ bt_id _ ", 0, this)") %]
  [% P.link_tag("#", "x", onclick="kivi.BankTransaction.delete_invoice(" _ bt_id _ "," _ invoice.id _ ")") %]
 </span>