Auftrags-Controller: Einheiten per Select ändern können und sellprice anpassen.
[kivitendo-erp.git] / bin / mozilla / ir.pl
index b226bb0..6bcba9b 100644 (file)
@@ -36,7 +36,9 @@ use SL::IR;
 use SL::IS;
 use SL::PE;
 use SL::DB::Default;
+use SL::DB::PurchaseInvoice;
 use List::Util qw(max sum);
+use List::UtilsBy qw(sort_by);
 
 require "bin/mozilla/io.pl";
 require "bin/mozilla/invoice_io.pl";
@@ -58,6 +60,10 @@ sub add {
 
   $main::auth->assert('vendor_invoice_edit');
 
+  if (!$::instance_conf->get_allow_new_purchase_invoice) {
+    $::form->show_generic_error($::locale->text("You do not have the permissions to access this function."));
+  }
+
   return $main::lxdebug->leave_sub() if (load_draft_maybe());
 
   $form->{title} = $locale->text('Record Vendor Invoice');
@@ -101,8 +107,7 @@ sub invoice_links {
   $form->{vc} = 'vendor';
 
   # create links
-  $form->{webdav}   = $::lx_office_conf{features}->{webdav};
-  $form->{jsscript} = 1;
+  $form->{webdav}   = $::instance_conf->get_webdav;
 
   $form->create_links("AP", \%myconfig, "vendor");
 
@@ -117,37 +122,14 @@ sub invoice_links {
     }
   }
 
-  my ($payment_id, $language_id, $taxzone_id, $currency);
-  if ($form->{payment_id}) {
-    $payment_id = $form->{payment_id};
-  }
-  if ($form->{language_id}) {
-    $language_id = $form->{language_id};
-  }
-  if ($form->{taxzone_id}) {
-    $taxzone_id = $form->{taxzone_id};
-  }
-  if ($form->{currency}) {
-    $currency = $form->{currency};
-  }
+  $form->backup_vars(qw(payment_id language_id taxzone_id
+                        currency delivery_term_id intnotes cp_id));
 
-  my $cp_id = $form->{cp_id};
   IR->get_vendor(\%myconfig, \%$form);
   IR->retrieve_invoice(\%myconfig, \%$form);
-  $form->{cp_id} = $cp_id;
 
-  if ($payment_id) {
-    $form->{payment_id} = $payment_id;
-  }
-  if ($language_id) {
-    $form->{language_id} = $language_id;
-  }
-  if ($taxzone_id) {
-    $form->{taxzone_id} = $taxzone_id;
-  }
-  if ($currency) {
-    $form->{currency} = $currency;
-  }
+  $form->restore_vars(qw(payment_id language_id taxzone_id
+                         currency delivery_term_id intnotes cp_id));
 
   my @curr = $form->get_all_currencies();
   map { $form->{selectcurrency} .= "<option>$_\n" } @curr;
@@ -227,6 +209,8 @@ sub prepare_invoice {
 
   $main::auth->assert('vendor_invoice_edit');
 
+  $form->{type}     = "purchase_invoice";
+
   if ($form->{id}) {
 
     map { $form->{$_} =~ s/\"/&quot;/g } qw(invnumber ordnumber quonumber);
@@ -276,6 +260,7 @@ sub form_header {
   my %TMPL_VAR = ();
   my @custom_hiddens;
 
+  $TMPL_VAR{invoice_obj} = SL::DB::PurchaseInvoice->new(id => $form->{id})->load if $form->{id};
   $form->{employee_id} = $form->{old_employee_id} if $form->{old_employee_id};
   $form->{salesman_id} = $form->{old_salesman_id} if $form->{old_salesman_id};
 
@@ -293,8 +278,8 @@ sub form_header {
                    "departments"   => "all_departments",
                    "price_factors" => "ALL_PRICE_FACTORS");
 
-  $TMPL_VAR{ALL_EMPLOYEES}         = SL::DB::Manager::Employee->get_all(query => [ or => [ id => $::form->{employee_id},  deleted => 0 ] ]);
-  $TMPL_VAR{ALL_CONTACTS}          = SL::DB::Manager::Contact->get_all(query => [
+  $TMPL_VAR{ALL_EMPLOYEES}         = SL::DB::Manager::Employee->get_all_sorted(query => [ or => [ id => $::form->{employee_id},  deleted => 0 ] ]);
+  $TMPL_VAR{ALL_CONTACTS}          = SL::DB::Manager::Contact->get_all_sorted(query => [
     or => [
       cp_cv_id => $::form->{"$::form->{vc}_id"} * 1,
       and      => [
@@ -329,8 +314,6 @@ sub form_header {
   $TMPL_VAR{creditwarning} = ($form->{creditlimit} != 0) && ($form->{creditremaining} < 0) && !$form->{update};
   $TMPL_VAR{is_credit_remaining_negativ} = $form->{creditremaining} =~ /-/;
 
-  $::request->{layout}->focus('#vendor');
-
   my $follow_up_vc         =  $form->{vendor};
   $follow_up_vc            =~ s/--\d*\s*$//;
   $TMPL_VAR{vendor_name} = $follow_up_vc;
@@ -353,11 +336,15 @@ sub form_header {
     max_dunning_level dunning_amount
     shiptoname shiptostreet shiptozipcode shiptocity shiptocountry  shiptocontact shiptophone shiptofax
     shiptoemail shiptodepartment_1 shiptodepartment_2 message email subject cc bcc taxaccounts cursor_fokus
-    convert_from_do_ids convert_from_oe_ids
+    convert_from_do_ids convert_from_oe_ids show_details gldate useasnew
   ), @custom_hiddens,
   map { $_.'_rate', $_.'_description', $_.'_taxnumber' } split / /, $form->{taxaccounts}];
 
-  $form->{jsscript} = 1;
+  $TMPL_VAR{payment_terms_obj} = get_payment_terms_for_invoice();
+  $form->{duedate}             = $TMPL_VAR{payment_terms_obj}->calc_date(reference_date => $form->{invdate}, due_date => $form->{due_due})->to_kivitendo if $TMPL_VAR{payment_terms_obj};
+
+  $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io autocomplete_customer autocomplete_part client_js));
+
   $form->header();
 
   print $form->parse_html_template("ir/form_header", \%TMPL_VAR);
@@ -365,6 +352,25 @@ sub form_header {
   $main::lxdebug->leave_sub();
 }
 
+sub _sort_payments {
+  my @fields   = qw(acc_trans_id gldate datepaid source memo paid AR_paid);
+  my @payments =
+    grep { $_->{paid} != 0 }
+    map  {
+      my $idx = $_;
+      +{ map { ($_ => delete($::form->{"${_}_${idx}"})) } @fields }
+    } (1..$::form->{paidaccounts});
+
+  @payments = sort_by { DateTime->from_kivitendo($_->{datepaid}) } @payments;
+
+  $::form->{paidaccounts} = max scalar(@payments), 1;
+
+  foreach my $idx (1 .. scalar(@payments)) {
+    my $payment = $payments[$idx - 1];
+    $::form->{"${_}_${idx}"} = $payment->{$_} for @fields;
+  }
+}
+
 sub form_footer {
   $main::lxdebug->enter_sub();
 
@@ -407,6 +413,8 @@ sub form_footer {
   }
 
   # payments
+  _sort_payments();
+
   my $totalpaid = 0;
   $form->{paidaccounts}++ if ($form->{"paid_$form->{paidaccounts}"});
   $form->{paid_indices} = [ 1 .. $form->{paidaccounts} ];
@@ -435,6 +443,8 @@ sub form_footer {
     $totalpaid += $form->{"paid_$i"};
   }
 
+  $form->{ALL_DELIVERY_TERMS} = SL::DB::Manager::DeliveryTerm->get_all_sorted();
+
   print $form->parse_html_template('ir/form_footer', {
     is_type_credit_note => ($form->{type} eq "credit_note"),
     totalpaid           => $totalpaid,
@@ -443,6 +453,7 @@ sub form_footer {
     show_delete         => ($::instance_conf->get_ir_changeable == 2)
                              ? ($form->current_date(\%myconfig) eq $form->{gldate})
                              : ($::instance_conf->get_ir_changeable == 1),
+    today               => DateTime->today,
   });
 ##print $form->parse_html_template('ir/_payments'); # parser
 ##print $form->parse_html_template('webdav/_list'); # parser
@@ -501,12 +512,18 @@ sub update {
 
     my $rows = scalar @{ $form->{item_list} };
 
+    $form->{"discount_$i"}   = $form->parse_amount(\%myconfig, $form->{"discount_$i"}) / 100.0;
+    $form->{"discount_$i"} ||= $form->{vendor_discount};
+
     if ($rows) {
-      $form->{"qty_$i"} = 1 unless $form->parse_amount(\%myconfig, $form->{"qty_$i"});
+      $form->{"qty_$i"} = $form->parse_amount(\%myconfig, $form->{"qty_$i"});
+      if( !$form->{"qty_$i"} ) {
+        $form->{"qty_$i"} = 1;
+      }
 
       if ($rows > 1) {
 
-        select_item(mode => 'IR');
+        select_item(mode => 'IR', pre_entered_qty => $form->{"qty_$i"});
         ::end_of_request();
 
       } else {
@@ -514,8 +531,6 @@ sub update {
         # override sellprice if there is one entered
         my $sellprice = $form->parse_amount(\%myconfig, $form->{"sellprice_$i"});
 
-        # ergaenzung fuer bug 736 Lieferanten-Rabatt auch in Einkaufsrechnungen vorbelegen jb
-        $form->{"discount_$i"} = $form->format_amount(\%myconfig, $form->{vendor_discount} * 100 );
         map { $form->{item_list}[$i]{$_} =~ s/\"/&quot;/g } qw(partnumber description unit);
         map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} } keys %{ $form->{item_list}[0] };
 
@@ -528,14 +543,29 @@ sub update {
         if ($sellprice) {
           $form->{"sellprice_$i"} = $sellprice;
         } else {
+          my $record        = _make_record();
+          my $price_source  = SL::PriceSource->new(record_item => $record->items->[$i-1], record => $record);
+          my $best_price    = $price_source->best_price;
+          my $best_discount = $price_source->best_discount;
+
+          if ($best_price) {
+            $::form->{"sellprice_$i"}           = $best_price->price;
+            $::form->{"active_price_source_$i"} = $best_price->source;
+          }
+          if ($best_discount) {
+            $::form->{"discount_$i"}               = $best_discount->discount;
+            $::form->{"active_discount_source_$i"} = $best_discount->source;
+          }
+
           # if there is an exchange rate adjust sellprice
           $form->{"sellprice_$i"} /= $exchangerate;
         }
 
-        my $amount                   = $form->{"sellprice_$i"} * $form->{"qty_$i"} * (1 - $form->{"discount_$i"} / 100);
+        my $amount                = $form->{"sellprice_$i"} * $form->{"qty_$i"} * (1 - $form->{"discount_$i"});
         $form->{creditremaining} -= $amount;
         $form->{"sellprice_$i"}   = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
         $form->{"qty_$i"}         = $form->format_amount(\%myconfig, $form->{"qty_$i"},       $dec_qty);
+        $form->{"discount_$i"}    = $form->format_amount(\%myconfig, $form->{"discount_$i"} * 100.0);
       }
 
       &display_form;
@@ -589,11 +619,14 @@ sub storno {
   # Payments must not be recorded for the new storno invoice.
   $form->{paidaccounts} = 0;
   map { my $key = $_; delete $form->{$key} if grep { $key =~ /^$_/ } qw(datepaid_ gldate_ acc_trans_id_ source_ memo_ paid_ exchangerate_ AR_paid_) } keys %{ $form };
+  # set new ids for storno invoice
+  delete $form->{"invoice_id_$_"} for 1 .. $form->{"rowcount"};
 
   # saving the history
   if(!exists $form->{addition} && $form->{id} ne "") {
-    $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
-    $form->{addition} = "CANCELED";
+    $form->{snumbers}  = qq|invnumber_| . $form->{invnumber};
+    $form->{what_done} = "invoice";
+    $form->{addition}  = "CANCELED";
     $form->save_history;
   }
   # /saving the history
@@ -621,6 +654,10 @@ sub use_as_new {
   $form->{paidaccounts} = 1;
   $form->{rowcount}--;
   $form->{invdate} = $form->current_date(\%myconfig);
+
+  $form->{"converted_from_invoice_id_$_"} = delete $form->{"invoice_id_$_"} for 1 .. $form->{"rowcount"};
+
+  $form->{useasnew} = 1;
   &display_form;
 
   $main::lxdebug->leave_sub();
@@ -635,6 +672,7 @@ sub post_payment {
 
   $main::auth->assert('vendor_invoice_edit');
 
+  $form->mtime_ischanged('ap') ;
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
   for my $i (1 .. $form->{paidaccounts}) {
     if ($form->{"paid_$i"}) {
@@ -657,9 +695,9 @@ sub post_payment {
   if (IR->post_payment(\%myconfig, \%$form)){
     if (!exists $form->{addition} && $form->{id} ne "") {
       # saving the history
-      $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
-      $form->{addition} = "PAYMENT POSTED";
-      $form->{what_done} = $form->{currency} . qq| | . $form->{paid} . qq| | . $locale->text("POSTED");
+      $form->{snumbers}  = qq|invnumber_| . $form->{invnumber};
+      $form->{addition}  = "PAYMENT POSTED";
+      $form->{what_done} = "invoice";
       $form->save_history;
       # /saving the history
     }
@@ -694,6 +732,7 @@ sub post {
 
   $main::auth->assert('vendor_invoice_edit');
 
+  $form->mtime_ischanged('ap');
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
   $form->isblank("invdate",   $locale->text('Invoice Date missing!'));
@@ -724,7 +763,8 @@ sub post {
 
   $form->error($locale->text('Cannot post transaction above the maximum future booking date!'))
     if ($form->date_max_future($invdate, \%myconfig));
-  $form->error($locale->text('Cannot post invoice for a closed period!')) if $max_datepaid && $form->date_closed($max_datepaid, \%myconfig);
+  $form->error($locale->text('Cannot post invoice for a closed period!'))
+    if ($invdate <= $closedto);
 
   $form->isblank("exchangerate", $locale->text('Exchangerate missing!'))
     if ($form->{currency} ne $form->{defaultcurrency});
@@ -759,9 +799,9 @@ sub post {
   if (IR->post_invoice(\%myconfig, \%$form)){
     # saving the history
     if(!exists $form->{addition} && $form->{id} ne "") {
-      $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
-      $form->{addition} = "POSTED";
-      #$form->{what_done} = $locale->text("Rechnungsnummer") . qq| | . $form->{invnumber};
+      $form->{snumbers}  = qq|invnumber_| . $form->{invnumber};
+      $form->{addition}  = "POSTED";
+      $form->{what_done} = 'invoice';
       $form->save_history;
     }
     # /saving the history