Dokumentation html und pdf Datei
[kivitendo-erp.git] / bin / mozilla / is.pl
index 5025257..26fb0ea 100644 (file)
@@ -24,7 +24,8 @@
 # GNU General Public License for more details.
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1335, USA.
 #======================================================================
 #
 # Inventory invoicing module
@@ -33,7 +34,6 @@
 
 use SL::FU;
 use SL::IS;
-use SL::PE;
 use SL::OE;
 use SL::MoreCommon qw(restore_form save_form);
 use Data::Dumper;
@@ -45,10 +45,12 @@ use English qw(-no_match_vars);
 
 use SL::DB::Default;
 use SL::DB::Customer;
+use SL::DB::Department;
+use SL::DB::Invoice;
 use SL::DB::PaymentTerm;
 
+require "bin/mozilla/common.pl";
 require "bin/mozilla/io.pl";
-require "bin/mozilla/arap.pl";
 
 use strict;
 
@@ -142,13 +144,6 @@ sub invoice_links {
   # create links
   $form->create_links("AR", \%myconfig, "customer");
 
-  if ($form->{all_customer}) {
-    unless ($form->{customer_id}) {
-      $form->{customer_id} = $form->{all_customer}->[0]->{id};
-      $form->{salesman_id} = $form->{all_customer}->[0]->{salesman_id};
-    }
-  }
-
   my $editing = $form->{id};
 
   $form->backup_vars(qw(payment_id language_id taxzone_id salesman_id
@@ -157,11 +152,6 @@ sub invoice_links {
 
   IS->get_customer(\%myconfig, \%$form);
 
-  #quote all_customer Bug 133
-  foreach my $ref (@{ $form->{all_customer} }) {
-    $ref->{name} = $form->quote($ref->{name});
-  }
-
   $form->restore_vars(qw(id));
 
   IS->retrieve_invoice(\%myconfig, \%$form);
@@ -170,23 +160,6 @@ sub invoice_links {
   $form->restore_vars(qw(taxincluded)) if $form->{id};
   $form->restore_vars(qw(salesman_id)) if $editing;
 
-
-  # build vendor/customer drop down compatibility... don't ask
-  if (@{ $form->{"all_customer"} }) {
-    $form->{"selectcustomer"} = 1;
-    $form->{customer}         = qq|$form->{customer}--$form->{"customer_id"}|;
-  }
-
-  $form->{"oldcustomer"}  = $form->{customer};
-
-  if ($form->{"oldcustomer"} !~ m/--\d+$/ && $form->{"customer_id"}) {
-    $form->{"oldcustomer"} .= qq|--$form->{"customer_id"}|
-  }
-
-
-#  $form->{oldcustomer} = "$form->{customer}--$form->{customer_id}";
-#  $form->{selectcustomer} = 1;
-
   $form->{employee} = "$form->{employee}--$form->{employee_id}";
 
   # forex
@@ -241,6 +214,8 @@ sub prepare_invoice {
   if ($form->{type} eq "credit_note") {
     $form->{type}     = "credit_note";
     $form->{formname} = "credit_note";
+  } elsif ($form->{formname} eq "proforma" ) {
+    $form->{type}     = "invoice";
   } else {
     $form->{type}     = "invoice";
     $form->{formname} = "invoice";
@@ -277,6 +252,142 @@ sub prepare_invoice {
   $main::lxdebug->leave_sub();
 }
 
+sub setup_is_action_bar {
+  my $form                    = $::form;
+  my $change_never            = $::instance_conf->get_is_changeable == 0;
+  my $change_on_same_day_only = $::instance_conf->get_is_changeable == 2 && ($form->current_date(\%::myconfig) ne $form->{gldate});
+  my $payments_balanced       = ($::form->{oldtotalpaid} == 0);
+  my $has_storno              = ($::form->{storno} && !$::form->{storno_id});
+
+  for my $bar ($::request->layout->get('actionbar')) {
+    $bar->add(
+      action => [
+        t8('Update'),
+        submit    => [ '#form', { action => "update" } ],
+        disabled  => $form->{locked} ? t8('The billing period has already been locked.') : undef,
+        id        => 'update_button',
+        checks    => [ 'kivi.validate_form' ],
+        accesskey => 'enter',
+      ],
+
+      combobox => [
+        action => [
+          t8('Post'),
+          submit   => [ '#form', { action => "post" } ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => $form->{locked}                           ? t8('The billing period has already been locked.')
+                    : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
+                    : ($form->{id} && $change_never)            ? t8('Changing invoices has been disabled in the configuration.')
+                    : ($form->{id} && $change_on_same_day_only) ? t8('Invoices can only be changed on the day they are posted.')
+                    :                                             undef,
+        ],
+        action => [
+          t8('Post Payment'),
+          submit   => [ '#form', { action => "post_payment" } ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+        ],
+        action => [ t8('Mark as paid'),
+          submit   => [ '#form', { action => "mark_as_paid" } ],
+          confirm  => t8('This will remove the invoice from showing as unpaid even if the unpaid amount does not match the amount. Proceed?'),
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+          only_if  => $::instance_conf->get_is_show_mark_as_paid,
+        ],
+      ], # end of combobox "Post"
+
+      combobox => [
+        action => [ t8('Storno'),
+          submit   => [ '#form', { action => "storno" } ],
+          confirm  => t8('Do you really want to cancel this invoice?'),
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id}        ? t8('This invoice has not been posted yet.')
+                    : !$payments_balanced ? t8('Cancelling is disallowed. Either undo or balance the current payments until the open amount matches the invoice amount')
+                    : undef,
+        ],
+        action => [ t8('Delete'),
+          submit   => [ '#form', { action => "delete" } ],
+          confirm  => t8('Do you really want to delete this object?'),
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id}             ? t8('This invoice has not been posted yet.')
+                    : $form->{locked}          ? t8('The billing period has already been locked.')
+                    : $change_never            ? t8('Changing invoices has been disabled in the configuration.')
+                    : $change_on_same_day_only ? t8('Invoices can only be changed on the day they are posted.')
+                    : $has_storno              ? t8('Can only delete the "Storno zu" part of the cancellation pair.')
+                    :                            undef,
+        ],
+      ], # end of combobox "Storno"
+
+      'separator',
+
+      combobox => [
+        action => [ t8('Workflow') ],
+        action => [
+          t8('Use As New'),
+          submit   => [ '#form', { action => "use_as_new" } ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+        ],
+        action => [
+          t8('Credit Note'),
+          submit   => [ '#form', { action => "credit_note" } ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => $form->{type} eq "credit_note" ? t8('Credit notes cannot be converted into other credit notes.')
+                    : !$form->{id}                   ? t8('This invoice has not been posted yet.')
+                    :                                  undef,
+        ],
+        action => [
+          t8('Sales Order'),
+          submit   => [ '#form', { action => "order" } ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+        ],
+      ], # end of combobox "Workflow"
+
+      combobox => [
+        action => [ t8('Export') ],
+        action => [
+          ($form->{id} ? t8('Print') : t8('Preview')),
+          call     => [ 'kivi.SalesPurchase.show_print_dialog', $form->{id} ? 'print' : 'preview' ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id} && $form->{locked} ? t8('The billing period has already been locked.') : undef,
+        ],
+        action => [ t8('Print and Post'),
+          call     => [ 'kivi.SalesPurchase.show_print_dialog', $form->{id} ? 'print' : 'print_and_post' ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => $form->{id} ? t8('This invoice has already been posted.') : undef,,
+        ],
+        action => [ t8('E Mail'),
+          call     => [ 'kivi.SalesPurchase.show_email_dialog' ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+        ],
+      ], # end of combobox "Export"
+
+      combobox => [
+        action => [ t8('more') ],
+        action => [
+          t8('History'),
+          call     => [ 'set_history_window', $form->{id} * 1, 'glid' ],
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+        ],
+        action => [
+          t8('Follow-Up'),
+          call     => [ 'follow_up_window' ],
+          disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef,
+        ],
+        action => [
+          t8('Drafts'),
+          call     => [ 'kivi.Draft.popup', 'is', 'invoice', $form->{draft_id}, $form->{draft_description} ],
+          disabled => $form->{id}     ? t8('This invoice has already been posted.')
+                    : $form->{locked} ? t8('The billing period has already been locked.')
+                    :                   undef,
+        ],
+      ], # end of combobox "more"
+    );
+  }
+  $::request->layout->add_javascripts('kivi.Validator.js');
+}
+
 sub form_header {
   $main::lxdebug->enter_sub();
 
@@ -290,21 +401,23 @@ sub form_header {
   my %TMPL_VAR = ();
   my @custom_hiddens;
 
-  if ($form->{id}) {
-    require SL::DB::Invoice;
-    $TMPL_VAR{invoice_obj} = SL::DB::Invoice->new(id => $form->{id})->load;
-  }
-  $form->{employee_id} = $form->{old_employee_id} if $form->{old_employee_id};
-  $form->{salesman_id} = $form->{old_salesman_id} if $form->{old_salesman_id};
+  $TMPL_VAR{customer_obj} = SL::DB::Customer->load_cached($form->{customer_id}) if $form->{customer_id};
+  $TMPL_VAR{invoice_obj}  = SL::DB::Invoice->load_cached($form->{id})           if $form->{id};
+
+  my $current_employee   = SL::DB::Manager::Employee->current;
+  $form->{employee_id}   = $form->{old_employee_id} if $form->{old_employee_id};
+  $form->{salesman_id}   = $form->{old_salesman_id} if $form->{old_salesman_id};
+  $form->{employee_id} ||= $current_employee->id;
+  $form->{salesman_id} ||= $current_employee->id;
 
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
   $form->get_lists("taxzones"      => ($form->{id} ? "ALL_TAXZONES" : "ALL_ACTIVE_TAXZONES"),
                    "currencies"    => "ALL_CURRENCIES",
-                   "customers"     => "ALL_CUSTOMERS",
-                   "departments"   => "all_departments",
                    "price_factors" => "ALL_PRICE_FACTORS");
 
+  $form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all_sorted;
+
   # Projects
   my @old_project_ids = uniq grep { $_ } map { $_ * 1 } ($form->{"globalproject_id"}, map { $form->{"project_id_$_"} } 1..$form->{"rowcount"});
   my @old_ids_cond    = @old_project_ids ? (id => \@old_project_ids) : ();
@@ -338,15 +451,6 @@ sub form_header {
       ]
     ]
   ]);
-  $TMPL_VAR{department_labels}     = sub { "$_[0]->{description}--$_[0]->{id}" };
-
-  # customer
-  $TMPL_VAR{vc_keys} = sub { "$_[0]->{name}--$_[0]->{id}" };
-  $TMPL_VAR{vclimit} = $myconfig{vclimit};
-  $TMPL_VAR{vc_select} = "customer_or_vendor_selection_window('customer', '', 0, 0)";
-  push @custom_hiddens, "customer_id";
-  push @custom_hiddens, "oldcustomer";
-  push @custom_hiddens, "selectcustomer";
 
   # currencies and exchangerate
   my @values = map { $_       } @{ $form->{ALL_CURRENCIES} };
@@ -363,10 +467,6 @@ sub form_header {
   $TMPL_VAR{creditwarning} = ($form->{creditlimit} != 0) && ($form->{creditremaining} < 0) && !$form->{update};
   $TMPL_VAR{is_credit_remaining_negativ} = $form->{creditremaining} =~ /-/;
 
-  my $follow_up_vc         =  $form->{customer};
-  $follow_up_vc            =~ s/--\d*\s*$//;
-  $TMPL_VAR{customer_name} = $follow_up_vc;
-
 # set option selected
   foreach my $item (qw(AR)) {
     $form->{"select$item"} =~ s/ selected//;
@@ -378,26 +478,25 @@ sub form_header {
   $TMPL_VAR{dateformat}          = $myconfig{dateformat};
   $TMPL_VAR{numberformat}        = $myconfig{numberformat};
 
-  push @custom_hiddens, map { "shiptocvar_" . $_->name } @{ SL::DB::Manager::CustomVariableConfig->get_all(where => [ module => 'ShipTo' ]) };
-
   # hiddens
   $TMPL_VAR{HIDDENS} = [qw(
-    id type media format queued printed emailed title vc discount
+    id type queued printed emailed vc discount
     title creditlimit creditremaining tradediscount business closedto locked shipped storno storno_id
     max_dunning_level dunning_amount dunning_description
-    shiptoname shiptostreet shiptozipcode shiptocity shiptocountry shiptogln shiptocontact shiptophone shiptofax
-    shiptoemail shiptodepartment_1 shiptodepartment_2  shiptocp_gender message email subject cc bcc taxaccounts cursor_fokus
+    taxaccounts cursor_fokus
     convert_from_do_ids convert_from_oe_ids convert_from_ar_ids useasnew
     invoice_id
     show_details
   ), @custom_hiddens,
   map { $_.'_rate', $_.'_description', $_.'_taxnumber' } split / /, $form->{taxaccounts}];
 
-  $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.Draft kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io autocomplete_customer autocomplete_part client_js));
+  $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.Draft kivi.File kivi.SalesPurchase kivi.Part kivi.CustomerVendor kivi.Validator ckeditor/ckeditor ckeditor/adapters/jquery kivi.io client_js));
 
   $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->{duedate})->to_kivitendo if $TMPL_VAR{payment_terms_obj};
 
+  setup_is_action_bar();
+
   $form->header();
 
   print $form->parse_html_template("is/form_header", \%TMPL_VAR);
@@ -446,7 +545,7 @@ sub form_footer {
   $form->{taxaccounts_array} = [ split(/ /, $form->{taxaccounts}) ];
 
   if( $form->{customer_id} && !$form->{taxincluded_changed_by_user} ) {
-    my $customer = SL::DB::Customer->new(id => $form->{customer_id})->load();
+    my $customer = SL::DB::Customer->load_cached($form->{customer_id});
     $form->{taxincluded} = defined($customer->taxincluded_checked) ? $customer->taxincluded_checked : $myconfig{taxincluded_checked};
   }
 
@@ -520,12 +619,13 @@ sub form_footer {
     is_type_credit_note => ($form->{type} eq "credit_note"),
     totalpaid           => $totalpaid,
     paid_missing        => $form->{invtotal} - $totalpaid,
-    print_options       => print_options(inline => 1),
+    print_options       => setup_sales_purchase_print_options(),
     show_storno         => $form->{id} && !$form->{storno} && !IS->has_storno(\%myconfig, $form, "ar") && !$totalpaid,
     show_delete         => ($::instance_conf->get_is_changeable == 2)
                              ? ($form->current_date(\%myconfig) eq $form->{gldate})
                              : ($::instance_conf->get_is_changeable == 1),
     today               => DateTime->today,
+    vc_obj              => $form->{customer_id} ? SL::DB::Customer->load_cached($form->{customer_id}) : undef,
   });
 ##print $form->parse_html_template('is/_payments'); # parser
 ##print $form->parse_html_template('webdav/_list'); # parser
@@ -534,16 +634,18 @@ sub form_footer {
 }
 
 sub mark_as_paid {
-  $main::lxdebug->enter_sub();
+  $::auth->assert('invoice_edit');
 
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
+  SL::DB::Invoice->new(id => $::form->{id})->load->mark_as_paid;
 
-  $main::auth->assert('invoice_edit');
-
-  &mark_as_paid_common(\%myconfig,"ar");
+  $::form->redirect($::locale->text("Marked as paid"));
+}
 
-  $main::lxdebug->leave_sub();
+sub show_draft {
+  # unless no lazy implementation of save draft without invdate
+  # set the current date like in version <= 3.4.1
+  $::form->{invdate}   = DateTime->today->to_lxoffice;
+  update();
 }
 
 sub update {
@@ -560,7 +662,11 @@ sub update {
   my $taxincluded         = $form->{taxincluded} ? "checked" : '';
   $form->{update} = 1;
 
-  &check_name("customer");
+  if (($form->{previous_customer_id} || $form->{customer_id}) != $form->{customer_id}) {
+    $::form->{salesman_id} = SL::DB::Manager::Employee->current->id if exists $::form->{salesman_id};
+
+    IS->get_customer(\%myconfig, $form);
+  }
 
   $form->{taxincluded} ||= $taxincluded;
 
@@ -749,7 +855,7 @@ sub post {
 
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
   $form->isblank("invdate",  $locale->text('Invoice Date missing!'));
-  $form->isblank("customer", $locale->text('Customer missing!'));
+  $form->isblank("customer_id", $locale->text('Customer missing!'));
   $form->error($locale->text('Cannot post invoice for a closed period!'))
         if ($form->date_closed($form->{"invdate"}, \%myconfig));
 
@@ -757,7 +863,7 @@ sub post {
   $form->{invnumber} =~ s/\s*$//g;
 
   # if oldcustomer ne customer redo form
-  if (&check_name('customer')) {
+  if (($form->{previous_customer_id} || $form->{customer_id}) != $form->{customer_id}) {
     &update;
     $::dispatcher->end_request;
   }
@@ -829,7 +935,7 @@ sub post {
   relink_accounts();
 
   my $terms        = get_payment_terms_for_invoice();
-  $form->{duedate} = $terms->calc_date(reference_date => $form->{invdate}, due_date => $form->{due_due})->to_kivitendo if $terms;
+  $form->{duedate} = $terms->calc_date(reference_date => $form->{invdate}, due_date => $form->{duedate})->to_kivitendo if $terms;
 
   # If transfer_out is requested, get rose db handle and do post and
   # transfer out in one transaction. Otherwise just post the invoice.
@@ -853,7 +959,7 @@ sub post {
         1;
       }) {
         push @errors, $EVAL_ERROR;
-        die 'transaction error';
+        $form->error($locale->text('Cannot post invoice and/or transfer out! Error message:') . "\n" . join("\n", @errors));
       }
 
       1;
@@ -879,9 +985,8 @@ sub post {
   if (!$form->{no_redirect_after_post}) {
     $form->{action} = 'edit';
     $form->{script} = 'is.pl';
-    $form->{saved_message} = $form->{label} . " $form->{invnumber} " . $locale->text('posted!');
     $form->{callback} = build_std_url(qw(action edit id callback saved_message));
-    $form->redirect;
+    $form->redirect($form->{label} . " $form->{invnumber} " . $locale->text('posted!'));
   }
 
   $main::lxdebug->leave_sub();
@@ -1103,35 +1208,9 @@ sub delete {
   $::form->error($::locale->text('Cannot delete invoice!'));
 }
 
-sub post_and_e_mail {
-  e_mail();
-};
-
-sub e_mail {
-  $main::lxdebug->enter_sub();
-
-  my $form     = $main::form;
-
-  $main::auth->assert('invoice_edit');
-
-  if (!$form->{id}) {
-    $form->{no_redirect_after_post} = 1;
-
-    my $saved_form = save_form();
-
-    post();
-
-    restore_form($saved_form, 0, qw(id invnumber));
-  }
-
-  edit_e_mail();
-
-  $main::lxdebug->leave_sub();
-}
-
 sub dispatcher {
   for my $action (qw(
-    print update ship_to e_mail storno post_payment use_as_new credit_note
+    print update ship_to storno post_payment use_as_new credit_note
     delete post order preview post_and_e_mail print_and_post
     mark_as_paid
   )) {