OrderController: nach Speichern hiddens der ids wieder setzen, …
[kivitendo-erp.git] / SL / DN.pm
index 46749ab..5d0ee14 100644 (file)
--- a/SL/DN.pm
+++ b/SL/DN.pm
@@ -25,7 +25,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.
 #======================================================================
 #
 # Dunning process module
@@ -36,6 +37,9 @@ package DN;
 
 use SL::Common;
 use SL::DBUtils;
+use SL::DB::AuthUser;
+use SL::DB::Default;
+use SL::DB::Employee;
 use SL::GenericTranslations;
 use SL::IS;
 use SL::Mailer;
@@ -43,6 +47,9 @@ use SL::MoreCommon;
 use SL::Template;
 use SL::DB::Printer;
 use SL::DB::Language;
+use SL::TransNumber;
+use SL::Util qw(trim);
+use SL::DB;
 
 use strict;
 
@@ -52,7 +59,7 @@ sub get_config {
   my ($self, $myconfig, $form) = @_;
 
   # connect to database
-  my $dbh = $form->dbconnect($myconfig);
+  my $dbh = SL::DB->client->dbh;
 
   my $query =
     qq|SELECT * | .
@@ -66,22 +73,28 @@ sub get_config {
   }
 
   $query =
-    qq|SELECT dunning_ar_amount_fee, dunning_ar_amount_interest, dunning_ar
+    qq|SELECT dunning_ar_amount_fee, dunning_ar_amount_interest, dunning_ar, dunning_creator
        FROM defaults|;
-  ($form->{AR_amount_fee}, $form->{AR_amount_interest}, $form->{AR}) = selectrow_query($form, $dbh, $query);
-
-  $dbh->disconnect();
+  ($form->{AR_amount_fee}, $form->{AR_amount_interest}, $form->{AR}, $form->{dunning_creator})
+    = selectrow_query($form, $dbh, $query);
 
   $main::lxdebug->leave_sub();
 }
 
 sub save_config {
+  my ($self, $myconfig, $form) = @_;
   $main::lxdebug->enter_sub();
 
+  my $rc = SL::DB->client->with_transaction(\&_save_config, $self, $myconfig, $form);
+
+  $::lxdebug->leave_sub;
+  return $rc;
+}
+
+sub _save_config {
   my ($self, $myconfig, $form) = @_;
 
-  # connect to database
-  my $dbh = $form->dbconnect_noauto($myconfig);
+  my $dbh = SL::DB->client->dbh;
 
   my ($query, @values);
 
@@ -125,14 +138,13 @@ sub save_config {
     }
   }
 
-  $query  = qq|UPDATE defaults SET dunning_ar_amount_fee = ?, dunning_ar_amount_interest = ?, dunning_ar = ?|;
-  @values = (conv_i($form->{AR_amount_fee}), conv_i($form->{AR_amount_interest}), conv_i($form->{AR}));
+  $query  = qq|UPDATE defaults SET dunning_ar_amount_fee = ?, dunning_ar_amount_interest = ?, dunning_ar = ?,
+               dunning_creator = ?|;
+  @values = (conv_i($form->{AR_amount_fee}), conv_i($form->{AR_amount_interest}), conv_i($form->{AR}),
+             $form->{dunning_creator});
   do_query($form, $dbh, $query, @values);
 
-  $dbh->commit();
-  $dbh->disconnect();
-
-  $main::lxdebug->leave_sub();
+  return 1;
 }
 
 sub create_invoice_for_fees {
@@ -204,11 +216,12 @@ sub create_invoice_for_fees {
 
   my ($ar_id) = selectrow_query($form, $dbh, qq|SELECT nextval('glid')|);
   my $curr = $form->get_default_currency($myconfig);
+  my $trans_number = SL::TransNumber->new(type => 'invoice', dbh => $dbh);
 
   $query =
     qq|INSERT INTO ar (id,          invnumber, transdate, gldate, customer_id,
                        taxincluded, amount,    netamount, paid,   duedate,
-                       invoice,     curr,      notes,
+                       invoice,     currency_id, taxzone_id,      notes,
                        employee_id)
        VALUES (
          ?,                     -- id
@@ -228,36 +241,47 @@ sub create_invoice_for_fees {
          -- duedate:
          (SELECT duedate FROM dunning WHERE dunning_id = ? LIMIT 1),
          'f',                   -- invoice
-         ?,                     -- curr
+         (SELECT id FROM currencies WHERE name = ?), -- curr
+         --taxzone_id:
+         (SELECT taxzone_id FROM customer WHERE id =
+          (SELECT ar.customer_id
+           FROM dunning dn
+           LEFT JOIN ar ON (dn.trans_id = ar.id)
+           WHERE dn.dunning_id = ?
+           LIMIT 1)
+         ),
          ?,                     -- notes
          -- employee_id:
          (SELECT id FROM employee WHERE login = ?)
        )|;
   @values = ($ar_id,            # id
-             $form->update_defaults($myconfig, 'invnumber', $dbh), # invnumber
+             $trans_number->create_unique, # invnumber
              $dunning_id,       # customer_id
              $amount,
              $amount,
              $dunning_id,       # duedate
              $curr,             # default currency
+             $dunning_id,       # taxzone_id
              sprintf($main::locale->text('Automatically created invoice for fee and interest for dunning %s'), $dunning_id), # notes
-             $form->{login});   # employee_id
+             $::myconfig{login});   # employee_id
   do_query($form, $dbh, $query, @values);
 
   $query =
-    qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, gldate, taxkey)
-       VALUES (?, ?, ?, current_date, current_date, 0)|;
+    qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, gldate, taxkey, tax_id, chart_link)
+       VALUES (?, ?, ?, current_date, current_date, 0,
+               (SELECT id   FROM tax   WHERE (taxkey = 0) AND (rate = 0)),
+               (SELECT link FROM chart WHERE id = ?))|;
   $sth = prepare_query($form, $dbh, $query);
 
-  @values = ($ar_id, conv_i($form->{AR_amount_fee}), $fee_remaining);
+  @values = ($ar_id, conv_i($form->{AR_amount_fee}), $fee_remaining, conv_i($form->{AR_amount_fee}));
   do_statement($form, $sth, $query, @values);
 
   if ($interest_remaining) {
-    @values = ($ar_id, conv_i($form->{AR_amount_interest}), $interest_remaining);
+    @values = ($ar_id, conv_i($form->{AR_amount_interest}), $interest_remaining, conv_i($form->{AR_amount_interest}));
     do_statement($form, $sth, $query, @values);
   }
 
-  @values = ($ar_id, conv_i($form->{AR}), -1 * $amount);
+  @values = ($ar_id, conv_i($form->{AR}), -1 * $amount, conv_i($form->{AR}));
   do_statement($form, $sth, $query, @values);
 
   $sth->finish();
@@ -268,12 +292,26 @@ sub create_invoice_for_fees {
   $main::lxdebug->leave_sub();
 }
 
+
 sub save_dunning {
+  my ($self, $myconfig, $form, $rows) = @_;
   $main::lxdebug->enter_sub();
 
+  my $rc = SL::DB->client->with_transaction(\&_save_dunning, $self, $myconfig, $form, $rows);
+
+  if (!$rc) {
+    die SL::DB->client->error
+  }
+  $::lxdebug->leave_sub;
+
+  return $rc;
+}
+
+
+sub _save_dunning {
   my ($self, $myconfig, $form, $rows) = @_;
-  # connect to database
-  my $dbh = $form->dbconnect_noauto($myconfig);
+
+  my $dbh = SL::DB->client->dbh;
 
   my ($query, @values);
 
@@ -326,21 +364,19 @@ sub save_dunning {
 
   $form->{DUNNING_PDFS_EMAIL} = [];
 
+  $form->{dunning_id} = $dunning_id;
+
   $self->create_invoice_for_fees($myconfig, $form, $dbh, $dunning_id);
 
   $self->print_invoice_for_fees($myconfig, $form, $dunning_id, $dbh);
   $self->print_dunning($myconfig, $form, $dunning_id, $dbh);
 
-  $form->{dunning_id} = $dunning_id;
 
   if ($send_email) {
     $self->send_email($myconfig, $form, $dunning_id, $dbh);
   }
 
-  $dbh->commit();
-  $dbh->disconnect();
-
-  $main::lxdebug->leave_sub();
+  return 1;
 }
 
 sub send_email {
@@ -351,8 +387,8 @@ sub send_email {
   my $query =
     qq|SELECT
          dcfg.email_body,     dcfg.email_subject, dcfg.email_attachment,
-         c.email AS recipient
-
+         COALESCE (NULLIF(c.invoice_mail, ''), c.email) AS recipient, c.name,
+         (SELECT login from employee where id = ar.employee_id) as invoice_employee_login
        FROM dunning d
        LEFT JOIN dunning_config dcfg ON (d.dunning_config_id = dcfg.id)
        LEFT JOIN ar                  ON (d.trans_id          = ar.id)
@@ -361,22 +397,38 @@ sub send_email {
        LIMIT 1|;
   my $ref = selectfirst_hashref_query($form, $dbh, $query, $dunning_id);
 
-  if (!$ref || !$ref->{recipient} || !$myconfig->{email}) {
+  # without a recipient, we cannot send a mail
+  if (!$ref || !$ref->{recipient}) {
     $main::lxdebug->leave_sub();
-    return;
+    die $main::locale->text("No email recipient for customer #1 defined.", $ref->{name});
+  }
+
+  # without a sender we cannot send a mail
+  # two cases: check mail from 1. current user OR  2. employee who created the invoice
+  my ($from, $sign);
+  if ($::instance_conf->get_dunning_creator eq 'current_employee') {
+    $from = $myconfig->{email};
+    die $main::locale->text('No email for current user #1 defined.', $myconfig->{name}) unless $from;
+  } else {
+    eval {
+      $from = SL::DB::Manager::AuthUser->find_by(login =>  $ref->{invoice_employee_login})->get_config_value("email");
+      $sign = SL::DB::Manager::AuthUser->find_by(login =>  $ref->{invoice_employee_login})->get_config_value("signature");
+      die unless ($from);
+      1;
+    } or die $main::locale->text('No email for user with login #1 defined.', $ref->{invoice_employee_login});
   }
 
   my $template     = SL::Template::create(type => 'PlainText', form => $form, myconfig => $myconfig);
   my $mail         = Mailer->new();
-  $mail->{charset} = $::lx_office_conf{system}->{dbcharset} || Common::DEFAULT_CHARSET;
-  $mail->{from}    = $myconfig->{email};
+  $mail->{bcc}     = $form->get_bcc_defaults($myconfig, $form->{bcc});
+  $mail->{from}    = $from;
   $mail->{to}      = $ref->{recipient};
   $mail->{subject} = $template->parse_block($ref->{email_subject});
   $mail->{message} = $template->parse_block($ref->{email_body});
-
-  if ($myconfig->{signature}) {
-    $mail->{message} .= "\n-- \n$myconfig->{signature}";
-  }
+  my $sign_backup  = $::myconfig{signature};
+  $::myconfig{signature} = $sign if $sign;
+  $mail->{message} .= $form->create_email_signature();
+  $::myconfig{signature} = $sign_backup if $sign;
 
   $mail->{message} =~ s/\r\n/\n/g;
 
@@ -394,7 +446,9 @@ sub set_template_options {
 
   my ($self, $myconfig, $form) = @_;
 
-  $form->{templates}    = "$myconfig->{templates}";
+  my $defaults = SL::DB::Default->get;
+  $form->error($::locale->text('No print templates have been created for this client yet. Please do so in the client configuration.')) if !$defaults->templates;
+  $form->{templates}    = $defaults->templates;
   $form->{language}     = $form->get_template_language($myconfig);
   $form->{printer_code} = $form->get_printer_code($myconfig);
 
@@ -433,7 +487,7 @@ sub set_template_options {
 
   $form->{IN} = undef;
   for my $filename (@template_files) {
-    if (-f "$form->{templates}/$filename") {
+    if (-f ($defaults->templates . "/$filename")) {
       $form->{IN} = $filename;
       last;
     }
@@ -446,11 +500,11 @@ sub set_template_options {
   # prepare meta information for template introspection
   $form->{template_meta} = {
     formname  => $form->{formname},
-    language  => SL::DB::Manager::Language->find_by_or_create(id => $form->{language_id}),
+    language  => SL::DB::Manager::Language->find_by_or_create(id => $form->{language_id} || undef),
     format    => $form->{format},
     media     => $form->{media},
     extension => $extension,
-    printer   => SL::DB::Manager::Printer->find_by_or_create(id => $form->{printer_id}),
+    printer   => SL::DB::Manager::Printer->find_by_or_create(id => $form->{printer_id} || undef),
     today     => DateTime->today,
   };
 
@@ -464,7 +518,7 @@ sub get_invoices {
   my ($self, $myconfig, $form) = @_;
 
   # connect to database
-  my $dbh = $form->dbconnect($myconfig);
+  my $dbh = SL::DB->client->dbh;
 
   my $where;
   my @values;
@@ -477,7 +531,7 @@ sub get_invoices {
 
   } elsif ($form->{customer}) {
     $where .= qq| AND (ct.name ILIKE ?)|;
-    push(@values, '%' . $form->{customer} . '%');
+    push(@values, like($form->{customer}));
   }
 
   my %columns = (
@@ -489,7 +543,7 @@ sub get_invoices {
   foreach my $key (keys(%columns)) {
     next unless ($form->{$key});
     $where .= qq| AND $columns{$key} ILIKE ?|;
-    push(@values, '%' . $form->{$key} . '%');
+    push(@values, like($form->{$key}));
   }
 
   if ($form->{dunning_level}) {
@@ -500,7 +554,7 @@ sub get_invoices {
   $form->{minamount} = $form->parse_amount($myconfig,$form->{minamount});
   if ($form->{minamount}) {
     $where .= qq| AND ((a.amount - a.paid) > ?) |;
-    push(@values, $form->{minamount});
+    push(@values, trim($form->{minamount}));
   }
 
   my $query =
@@ -509,11 +563,16 @@ sub get_invoices {
        WHERE dunning_level = (SELECT MAX(dunning_level) FROM dunning_config)|;
   my ($id_for_max_dunning_level) = selectrow_query($form, $dbh, $query);
 
+  if (!$form->{l_include_direct_debit}) {
+    $where .= qq| AND NOT COALESCE(a.direct_debit, FALSE) |;
+  }
+
   $query =
     qq|SELECT
-         a.id, a.ordnumber, a.transdate, a.invnumber, a.amount, a.language_id,
+         a.id, a.invoice, a.ordnumber, a.transdate, a.invnumber, a.amount, a.language_id,
          ct.name AS customername, a.customer_id, a.duedate,
          a.amount - a.paid AS open_amount,
+         a.direct_debit,
 
          cfg.dunning_description, cfg.dunning_level,
 
@@ -576,7 +635,6 @@ sub get_invoices {
   $query = qq|SELECT id, dunning_description FROM dunning_config ORDER BY dunning_level|;
   $form->{DUNNING_CONFIG} = selectall_hashref_query($form, $dbh, $query);
 
-  $dbh->disconnect;
   $main::lxdebug->leave_sub();
 }
 
@@ -587,7 +645,7 @@ sub get_dunning {
   my ($self, $myconfig, $form) = @_;
 
   # connect to database
-  my $dbh = $form->dbconnect($myconfig);
+  my $dbh = SL::DB->client->dbh;
 
   my $where = qq| WHERE (da.trans_id = a.id)|;
 
@@ -599,7 +657,7 @@ sub get_dunning {
 
   } elsif ($form->{customer}) {
     $where .= qq| AND (ct.name ILIKE ?)|;
-    push(@values, '%' . $form->{customer} . '%');
+    push(@values, like($form->{customer}));
   }
 
   my %columns = (
@@ -610,7 +668,7 @@ sub get_dunning {
   foreach my $key (keys(%columns)) {
     next unless ($form->{$key});
     $where .= qq| AND $columns{$key} ILIKE ?|;
-    push(@values, '%' . $form->{$key} . '%');
+    push(@values, like($form->{$key}));
   }
 
   if ($form->{dunning_level}) {
@@ -689,7 +747,6 @@ sub get_dunning {
     map { $ref->{$_} = $form->format_amount($myconfig, $ref->{$_}, 2)} qw(amount fee interest);
   }
 
-  $dbh->disconnect;
   $main::lxdebug->leave_sub();
 }
 
@@ -745,10 +802,20 @@ sub print_dunning {
   my ($self, $myconfig, $form, $dunning_id, $provided_dbh) = @_;
 
   # connect to database
-  my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect_noauto($myconfig);
+  my $dbh = $provided_dbh || SL::DB->client->dbh;
 
   $dunning_id =~ s|[^\d]||g;
 
+  my ($language_tc, $output_numberformat, $output_dateformat, $output_longdates);
+  if ($form->{"language_id"}) {
+    ($language_tc, $output_numberformat, $output_dateformat, $output_longdates) =
+      AM->get_language_details($myconfig, $form, $form->{language_id});
+  } else {
+    $output_dateformat = $myconfig->{dateformat};
+    $output_numberformat = $myconfig->{numberformat};
+    $output_longdates = 1;
+  }
+
   my $query =
     qq|SELECT
          da.fee, da.interest,
@@ -761,7 +828,9 @@ sub print_dunning {
          ar.transdate,       ar.duedate,      ar.customer_id,
          ar.invnumber,       ar.ordnumber,    ar.cp_id,
          ar.amount,          ar.netamount,    ar.paid,
-         ar.curr,
+         ar.employee_id,     ar.salesman_id,
+         (SELECT cu.name FROM currencies cu WHERE cu.id = ar.currency_id) AS curr,
+         (SELECT description from department WHERE id = ar.department_id) AS department,
          ar.amount - ar.paid AS open_amount,
          ar.amount - ar.paid + da.fee + da.interest AS linetotal
 
@@ -790,7 +859,8 @@ sub print_dunning {
          c.country,           c.department_1, c.department_2, c.email,     c.customernumber,
          c.greeting,          c.contact,      c.phone,        c.fax,       c.homepage,
          c.email,             c.taxincluded,  c.business_id,  c.taxnumber, c.iban,
-         c,ustid,             e.name as salesman_name,
+         c.ustid,
+         ar.id AS invoice_id,
          co.*
        FROM dunning d
        LEFT JOIN ar          ON (d.trans_id = ar.id)
@@ -804,7 +874,7 @@ sub print_dunning {
 
   $query =
     qq|SELECT
-         cfg.interest_rate, cfg.template AS formname,
+         cfg.interest_rate, cfg.template AS formname, cfg.dunning_level,
          cfg.email_subject, cfg.email_body, cfg.email_attachment,
          d.transdate AS dunning_date,
          (SELECT SUM(fee)
@@ -835,6 +905,17 @@ sub print_dunning {
   $form->{total_open_amount} = $form->format_amount($myconfig, $form->round_amount($ref->{total_open_amount}, 2), 2);
   $form->{total_amount}      = $form->format_amount($myconfig, $form->round_amount($ref->{fee} + $ref->{total_interest} + $ref->{total_open_amount}, 2), 2);
 
+  $::form->format_dates($output_dateformat, $output_longdates,
+    qw(dn_dunning_date dn_dunning_duedate dn_transdate dn_duedate
+          dunning_date    dunning_duedate    transdate    duedate)
+  );
+  $::form->reformat_numbers($output_numberformat, 2, qw(
+    dn_amount dn_netamount dn_paid dn_open_amount dn_fee dn_interest dn_linetotal
+       amount    netamount    paid    open_amount    fee    interest    linetotal
+    total_interest total_open_interest total_amount total_open_amount
+  ));
+  $::form->reformat_numbers($output_numberformat, undef, qw(interest_rate));
+
   $self->set_customer_cvars($myconfig, $form);
   $self->set_template_options($myconfig, $form);
 
@@ -846,12 +927,23 @@ sub print_dunning {
   delete $form->{tmpfile};
 
   push @{ $form->{DUNNING_PDFS} }, $filename;
-  push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'filename' => "${spool}/$filename",
-                                           'name'     => "dunning_${dunning_id}.pdf" };
+  push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'path' => "${spool}/$filename",
+                                           'name'     => $form->get_formname_translation('dunning') . "_${dunning_id}.pdf" };
 
-  $form->parse_template($myconfig);
+  my $employee_id = ($::instance_conf->get_dunning_creator eq 'invoice_employee') ?
+                      $form->{employee_id}                                        :
+                      SL::DB::Manager::Employee->current->id;
 
-  $dbh->disconnect() unless $provided_dbh;
+  $form->get_employee_data('prefix' => 'employee', 'id' => $employee_id);
+  $form->get_employee_data('prefix' => 'salesman', 'id' => $form->{salesman_id});
+
+  $form->{attachment_type}    = "dunning";
+  if ( $form->{dunning_level} ) {
+    $form->{attachment_type} .= $form->{dunning_level} if $form->{dunning_level} < 4;
+  }
+  $form->{attachment_filename} = $form->get_formname_translation($form->{attachment_type}) . "_${dunning_id}.pdf";
+  $form->{attachment_id} = $form->{invoice_id};
+  $form->parse_template($myconfig);
 
   $main::lxdebug->leave_sub();
 }
@@ -861,18 +953,20 @@ sub print_invoice_for_fees {
 
   my ($self, $myconfig, $form, $dunning_id, $provided_dbh) = @_;
 
-  my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect($myconfig);
+  my $dbh = $provided_dbh || SL::DB->client->dbh;
 
   my ($query, @values, $sth);
 
   $query =
     qq|SELECT
          d.fee_interest_ar_id,
-         dcfg.template
+         d.trans_id AS invoice_id,
+         dcfg.template,
+         dcfg.dunning_level
        FROM dunning d
        LEFT JOIN dunning_config dcfg ON (d.dunning_config_id = dcfg.id)
        WHERE d.dunning_id = ?|;
-  my ($ar_id, $template) = selectrow_query($form, $dbh, $query, $dunning_id);
+  my ($ar_id, $invoice_id, $template, $dunning_level) = selectrow_query($form, $dbh, $query, $dunning_id);
 
   if (!$ar_id) {
     $main::lxdebug->leave_sub();
@@ -900,7 +994,7 @@ sub print_invoice_for_fees {
   map { $form->{$_} = $ref->{$_} } keys %{ $ref };
 
   $query = qq|SELECT * FROM employee WHERE login = ?|;
-  $ref = selectfirst_hashref_query($form, $dbh, $query, $form->{login});
+  $ref = selectfirst_hashref_query($form, $dbh, $query, $::myconfig{login});
   map { $form->{"employee_${_}"} = $ref->{$_} } keys %{ $ref };
 
   $query = qq|SELECT * FROM acc_trans WHERE trans_id = ? ORDER BY acc_trans_id ASC|;
@@ -940,6 +1034,9 @@ sub print_invoice_for_fees {
 
   map { delete $form->{$_} } grep /^[a-z_]+_\d+$/, keys %{ $form };
 
+  $form->{attachment_filename} = $form->get_formname_translation('dunning_invoice') . "_${dunning_id}.pdf";
+  $form->{attachment_type}     = "dunning";
+  $form->{attachment_id}       = $form->{invoice_id};
   $form->parse_template($myconfig);
 
   restore_form($saved_form);
@@ -948,8 +1045,6 @@ sub print_invoice_for_fees {
   push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'filename' => "${spool}/$filename",
                                            'name'     => "dunning_invoice_${dunning_id}.pdf" };
 
-  $dbh->disconnect() unless $provided_dbh;
-
   $main::lxdebug->leave_sub();
 }
 
@@ -965,6 +1060,13 @@ sub set_customer_cvars {
                                                   translation_type => 'greetings::' . ($form->{cp_gender} eq 'f' ? 'female' : 'male'),
                                                   language_id      => $form->{language_id},
                                                   allow_fallback   => 1);
+  if ($form->{cp_id}) {
+    $custom_variables = CVar->get_custom_variables(dbh      => $form->get_standard_dbh,
+                                                   module   => 'Contacts',
+                                                   trans_id => $form->{cp_id});
+    $form->{"cp_cvar_$_->{name}"} = $_->{value} for @{ $custom_variables };
+  }
+
 }
 
 1;