format_amount - negative 0 vermeiden
[kivitendo-erp.git] / SL / Form.pm
index 9209f3a..35b21d5 100644 (file)
@@ -66,6 +66,7 @@ use SL::IC;
 use SL::IS;
 use SL::Layout::Dispatcher;
 use SL::Locale;
+use SL::Locale::String;
 use SL::Mailer;
 use SL::Menu;
 use SL::MoreCommon qw(uri_encode uri_decode);
@@ -472,11 +473,13 @@ sub header {
     jquery.multiselect2side
     ui-lightness/jquery-ui
     jquery-ui.custom
+    tooltipster themes/tooltipster-light
   );
 
   $layout->use_javascript("$_.js") for (qw(
     jquery jquery-ui jquery.cookie jquery.checkall jquery.download
     jquery/jquery.form jquery/fixes client_js
+    jquery/jquery.tooltipster.min
     common part_selection switchmenuframe
   ), "jquery/ui/i18n/jquery.ui.datepicker-$::myconfig{countrycode}");
 
@@ -537,7 +540,7 @@ sub footer {
   print $::request->{layout}->post_content;
 
   if (my @inline_scripts = $::request->{layout}->javascripts_inline) {
-    print "<script type='text/javascript'>@inline_scripts</script>\n";
+    print "<script type='text/javascript'>" . join("; ", @inline_scripts) . "</script>\n";
   }
 
   print <<EOL
@@ -582,6 +585,17 @@ sub set_standard_title {
   $::lxdebug->leave_sub;
 }
 
+sub prepare_global_vars {
+  my ($self) = @_;
+
+  $self->{AUTH}            = $::auth;
+  $self->{INSTANCE_CONF}   = $::instance_conf;
+  $self->{LOCALE}          = $::locale;
+  $self->{LXCONFIG}        = $::lx_office_conf;
+  $self->{LXDEBUG}         = $::lxdebug;
+  $self->{MYCONFIG}        = \%::myconfig;
+}
+
 sub _prepare_html_template {
   $main::lxdebug->enter_sub();
 
@@ -808,6 +822,7 @@ sub format_amount {
   my $force_places = defined $places && $places >= 0;
 
   $amount = $self->round_amount($amount, abs $places) if $force_places;
+  $neg    = 0 if $amount == 0; # don't show negative zero
   $amount = sprintf "%.*f", ($force_places ? $places : 10), abs $amount; # 6 is default for %fa
 
   # before the sprintf amount was a number, afterwards it's a string. because of the dynamic nature of perl
@@ -1299,6 +1314,9 @@ sub generate_attachment_filename {
   } elsif ($attachment_filename && $self->{"${prefix}number"}) {
     $attachment_filename .=  "_" . $self->{"${prefix}number"} . $self->get_extension_for_format();
 
+  } elsif ($attachment_filename) {
+    $attachment_filename .=  $self->get_extension_for_format();
+
   } else {
     $attachment_filename = "";
   }
@@ -1703,36 +1721,19 @@ sub get_default_currency {
 }
 
 sub set_payment_options {
-  $main::lxdebug->enter_sub();
-
   my ($self, $myconfig, $transdate) = @_;
 
-  return $main::lxdebug->leave_sub() unless ($self->{payment_id});
-
-  my $dbh = $self->get_standard_dbh($myconfig);
+  my $terms = $self->{payment_id} ? SL::DB::PaymentTerm->new(id => $self->{payment_id})->load : undef;
+  return if !$terms;
 
-  my $query =
-    qq|SELECT p.terms_netto, p.terms_skonto, p.percent_skonto, p.description_long , p.description | .
-    qq|FROM payment_terms p | .
-    qq|WHERE p.id = ?|;
+  $transdate                  ||= $self->{invdate} || $self->{transdate};
+  my $due_date                  = $self->{duedate} || $self->{reqdate};
 
-  ($self->{terms_netto}, $self->{terms_skonto}, $self->{percent_skonto},
-   $self->{payment_terms}, $self->{payment_description}) =
-     selectrow_query($self, $dbh, $query, $self->{payment_id});
-
-  if ($transdate eq "") {
-    if ($self->{invdate}) {
-      $transdate = $self->{invdate};
-    } else {
-      $transdate = $self->{transdate};
-    }
-  }
-
-  $query =
-    qq|SELECT ?::date + ?::integer AS netto_date, ?::date + ?::integer AS skonto_date | .
-    qq|FROM payment_terms|;
-  ($self->{netto_date}, $self->{skonto_date}) =
-    selectrow_query($self, $dbh, $query, $transdate, $self->{terms_netto}, $transdate, $self->{terms_skonto});
+  $self->{$_}                   = $terms->$_ for qw(terms_netto terms_skonto percent_skonto);
+  $self->{payment_terms}        = $terms->description_long;
+  $self->{payment_description}  = $terms->description;
+  $self->{netto_date}           = $terms->calc_date(reference_date => $transdate, due_date => $due_date, terms => 'net')->to_kivitendo;
+  $self->{skonto_date}          = $terms->calc_date(reference_date => $transdate, due_date => $due_date, terms => 'discount')->to_kivitendo;
 
   my ($invtotal, $total);
   my (%amounts, %formatted_amounts);
@@ -1762,7 +1763,8 @@ sub set_payment_options {
   }
 
   if ($self->{"language_id"}) {
-    $query =
+    my $dbh   = $self->get_standard_dbh($myconfig);
+    my $query =
       qq|SELECT t.translation, l.output_numberformat, l.output_dateformat, l.output_longdates | .
       qq|FROM generic_translations t | .
       qq|LEFT JOIN language l ON t.language_id = l.id | .
@@ -1801,13 +1803,15 @@ sub set_payment_options {
   $self->{payment_terms} =~ s/<%account_number%>/$self->{account_number}/g;
   $self->{payment_terms} =~ s/<%bank%>/$self->{bank}/g;
   $self->{payment_terms} =~ s/<%bank_code%>/$self->{bank_code}/g;
+  $self->{payment_terms} =~ s/<\%bic\%>/$self->{bic}/g;
+  $self->{payment_terms} =~ s/<\%iban\%>/$self->{iban}/g;
+  $self->{payment_terms} =~ s/<\%mandate_date_of_signature\%>/$self->{mandate_date_of_signature}/g;
+  $self->{payment_terms} =~ s/<\%mandator_id\%>/$self->{mandator_id}/g;
 
   map { $self->{payment_terms} =~ s/<%${_}%>/$formatted_amounts{$_}/g; } keys %formatted_amounts;
 
   $self->{skonto_in_percent} = $formatted_amounts{skonto_in_percent};
 
-  $main::lxdebug->leave_sub();
-
 }
 
 sub get_template_language {
@@ -1980,23 +1984,6 @@ sub get_employee_data {
   $main::lxdebug->leave_sub();
 }
 
-sub get_duedate {
-  $main::lxdebug->enter_sub();
-
-  my ($self, $myconfig, $reference_date) = @_;
-
-  my $terms   = $self->{payment_id}  ? SL::DB::PaymentTerm->new(id => $self->{payment_id}) ->load
-              : $self->{customer_id} ? SL::DB::Customer   ->new(id => $self->{customer_id})->load->payment
-              : $self->{vendor_id}   ? SL::DB::Vendor     ->new(id => $self->{vendor_id})  ->load->payment
-              : $self->{invdate}     ? undef # no payment terms, therefore invdate == duedate
-              :                        croak("Missing field in \$::form: payment_id, customer_id, vendor_id or invdate");
-  my $duedate = $terms ? $terms->calc_date(reference_date => $reference_date)->to_kivitendo : undef;
-
-  $main::lxdebug->leave_sub();
-
-  return $duedate;
-}
-
 sub _get_contacts {
   $main::lxdebug->enter_sub();
 
@@ -2618,6 +2605,25 @@ sub all_vc {
   $main::lxdebug->leave_sub();
 }
 
+sub mtime_ischanged {
+  my ($self, $table, $option) = @_;
+
+  return                                       unless $self->{id};
+  croak ("wrong call, no valid table defined") unless $table =~ /^(oe|ar|ap|delivery_orders|parts)$/;
+
+  my $query       = "SELECT mtime, itime FROM " . $table . " WHERE id = ?";
+  my $ref         = selectfirst_hashref_query($self, $self->get_standard_dbh, $query, $self->{id});
+  $ref->{mtime} ||= $ref->{itime};
+
+  if ($self->{lastmtime} && $self->{lastmtime} ne $ref->{mtime} ) {
+      $self->error(($option eq 'mail') ?
+        t8("The document has been changed by another user. No mail was sent. Please reopen it in another window and copy the changes to the new window") :
+        t8("The document has been changed by another user. Please reopen it in another window and copy the changes to the new window")
+      );
+    ::end_of_request();
+  }
+}
+
 sub language_payment {
   $main::lxdebug->enter_sub();
 
@@ -2769,6 +2775,7 @@ sub create_links {
       qq|SELECT
            a.cp_id, a.invnumber, a.transdate, a.${table}_id, a.datepaid,
            a.duedate, a.ordnumber, a.taxincluded, (SELECT cu.name FROM currencies cu WHERE cu.id=a.currency_id) AS currency, a.notes,
+           a.mtime, a.itime,
            a.intnotes, a.department_id, a.amount AS oldinvtotal,
            a.paid AS oldtotalpaid, a.employee_id, a.gldate, a.type,
            a.globalproject_id, ${extra_columns}
@@ -2785,7 +2792,8 @@ sub create_links {
     foreach my $key (keys %$ref) {
       $self->{$key} = $ref->{$key};
     }
-
+    $self->{mtime}   ||= $self->{itime};
+    $self->{lastmtime} = $self->{mtime};
     my $transdate = "current_date";
     if ($self->{transdate}) {
       $transdate = $dbh->quote($self->{transdate});
@@ -3507,9 +3515,9 @@ sub calculate_arap {
     if ( $selected_tax ) {
 
       if ( $buysell eq 'sell' ) {
-        $self->{AR_amounts}{"tax_$i"} = $selected_tax->chart->accno unless $selected_tax->taxkey == 0;
+        $self->{AR_amounts}{"tax_$i"} = $selected_tax->chart->accno if defined $selected_tax->chart;
       } else {
-        $self->{AP_amounts}{"tax_$i"} = $selected_tax->chart->accno unless $selected_tax->taxkey == 0;
+        $self->{AP_amounts}{"tax_$i"} = $selected_tax->chart->accno if defined $selected_tax->chart;
       };
 
       $self->{"taxkey_$i"} = $selected_tax->taxkey;
@@ -3751,6 +3759,17 @@ Used to override the default favicon.
 
 A html page title will be generated from this
 
+=item mtime_ischanged
+
+Tries to avoid concurrent write operations to records by checking the database mtime with a fetched one.
+
+Can be used / called with any table, that has itime and mtime attributes.
+Valid C<table> names are: oe, ar, ap, delivery_orders, parts.
+Can be called wit C<option> mail to generate a different error message.
+
+Returns undef if no save operation has been done yet ($self->{id} not present).
+Returns undef if no concurrent write process is detected otherwise a error message.
+
 =back
 
 =cut