=pod

=head1 NAME

LedgerSMB::Scripts::payment - LedgerSMB class defining the Controller functions for payment handling.

=head1 SYNOPSIS

Defines the controller functions and workflow logic for payment processing.

=head1 COPYRIGHT

Copyright (c) 2007, David Mora R and Christian Ceballos B.

Licensed to the public under the terms of the GNU GPL version 2 or later.

Original copyright notice below. 

#=====================================================================
# PLAXIS
# Copyright (c) 2007
#
#  Author: David Mora R
# 	   Christian Ceballos B	   
#
#
#
#  
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# 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.


=head1 METHODS

=cut


package LedgerSMB::Scripts::payment;
use LedgerSMB::Template;
use LedgerSMB::DBObject::Payment;
use LedgerSMB::DBObject::Date;
use strict; 

# CT:  A few notes for future refactoring of this code:
# 1:  I don't think it is a good idea to make the UI too dependant on internal
#     code structures but I don't see a good alternative at the moment.
# 2:  CamelCasing: -1

=pod

=item payment

This method is used to set the filter screen and prints it, using the 
TT2 system. (hopefully it will... )

=back

=cut

sub payments {
    my ($request) = @_;
    my $payment =  LedgerSMB::DBObject::Payment->new({'base' => $request});
    $payment->get_metadata();
    my $template = LedgerSMB::Template->new(
        user     => $request->{_user},
        locale   => $request->{_locale},
        path     => 'UI/payments',
        template => 'payments_filter',
        format   => 'HTML', 
    );
    $template->render($payment);
}

sub get_search_criteria {
    my ($request) = @_;
    my $payment =  LedgerSMB::DBObject::Payment->new({'base' => $request});
    $payment->get_metadata();
    if ($payment->{batch_id} && $payment->{batch_date}){
        $payment->{date_reversed} = $payment->{batch_date};
    }
    my $template = LedgerSMB::Template->new(
        user     => $request->{_user},
        locale   => $request->{_locale},
        path     => 'UI/payments',
        template => 'search',
        format   => 'HTML', 
    );
    $template->render($payment);
}

sub get_search_results {
    my ($request) = @_;
    my $rows = [];
    my $payment =  LedgerSMB::DBObject::Payment->new({'base' => $request});
    my @search_results = $payment->search;
    my $template = LedgerSMB::Template->new(
        user     => $request->{_user},
        locale   => $request->{_locale},
        path     => 'UI',
        template => 'form-dynatable',
        format   => ($payment->{format}) ? $payment->{format} : 'HTML',
    ); 

    my $base_url = "payment.pl?";
    my $search_url = "$base_url";
    for my $key (keys %{$request->take_top_level}){
        if ($base_url =~ /\?$/){
            $base_url .= "$key=$request->{key}";
        } else {
            $base_url .= "&$key=$request->{key}";
        }
    }

    my @columns = qw(selected meta_number date_paid amount source company_paid);
    my $contact_type = ($payment->{account_class} == 1) ? 'Vendor' : 'Customer';

    # CT:  Locale strings for gettext:
    #  $request->{_locale}->text("Vendor Number");
    #  $request->{_locale}->text("Customer Number");

    my $heading = {
         selected     => $request->{_locale}->text('Selected'),
         company_paid => {
                          text => $request->{_locale}->text('Company Name'),
                          href => "$search_url&orderby=company_paid",
                         },
         meta_number  => {
                          text => $request->{_locale}->text(
                                        "$contact_type Number"
                                  ),
                          href => "$search_url&orderby=meta_number",
                         },
         date_paid    => {
                          text => $request->{_locale}->text('Date Paid'),
                          href => "$search_url&orderby=date_paid",
                         },
         amount       => {
                          text => $request->{_locale}->text('Total Paid'),
                          href => "$search_url&orderby=amount",
                         },
         source       => {
                          text => $request->{_locale}->text('Source'),
                          href => "$search_url&orderby=source",
                         },
    };


    my $classcount;
    $classcount = 0;
    my $rowcount;
    $rowcount = 1;
    for my $line (@search_results){
        $classcount ||= 0;
        $rowcount += 1;
        push(@$rows, {
          company_paid => $line->{company_paid},
          amount       => $request->format_amount(amount => $line->{amount}),
          i            => "$classcount",
          date_paid    => $line->{date_paid},
          source       => $line->{source},
          meta_number  => $line->{meta_number},
          selected     => {
                          input => {
                                    type  => "checkbox",
                                    name  => "payment_$rowcount",
                                    value => "1",
                          },
           }
        });
        $payment->{"credit_id_$rowcount"} = $line->{credit_id};
        $payment->{"date_paid_$rowcount"} = $line->{date_paid};
        $payment->{"source_$rowcount"} = $line->{source};
        $classcount = ($classcount + 1) % 2;
        ++$rowcount;
    }
    $payment->{rowcount} = $rowcount;
    $payment->{script} = 'payment.pl';
    $payment->{title} = $request->{_locale}->text("Payment Results");
    my $hiddens = $payment->take_top_level;
    $template->render({
        form    => $payment,
        columns => \@columns,
        heading => $heading,
	hiddens => $payment->take_top_level,
        rows    => $rows,
        buttons => [{
                    value => 'reverse_payments',
                    name  => 'action',
                    class => 'submit',
                    type  => 'submit',
                    text  => $request->{_locale}->text('Reverse Payments'),
                   }]
    }); 
}

sub get_search_results_reverse_payments {
    my ($request) = @_;
    my $payment = LedgerSMB::DBObject::Payment->new({base => $request});
    for my $count (1 .. $payment->{rowcount}){
        if ($payment->{"payment_$count"}){
           $payment->{credit_id} = $payment->{"credit_id_$count"};
           $payment->{date_paid} = $payment->{"date_paid_$count"};
           $payment->{source} = $payment->{"source_$count"};
           $payment->reverse;
        }
    }
    get_search_criteria($payment);
}

sub check_job {
    my ($request) = @_;
    my $payment =  LedgerSMB::DBObject::Payment->new({'base' => $request});
    $payment->check_job;
    my $template = LedgerSMB::Template->new(
        user     => $request->{_user},
        locale   => $request->{_locale},
        path     => 'UI/payments',
        template => 'check_job',
        format   => 'HTML', 
    );
    $template->render($payment);
}

sub post_payments_bulk {
    my ($request) = @_;
    my $payment =  LedgerSMB::DBObject::Payment->new({'base' => $request});
    $payment->post_bulk();
    my $template;
    if ($payment->{queue_payments}){
        $payment->{job_label} = 'Payments';
        $template = LedgerSMB::Template->new(
            user     => $request->{_user},
            locale   => $request->{_locale},
            path     => 'UI/payments',
            template => 'check_job',
            format   => 'HTML', 
        );
    } else {
        $template = LedgerSMB::Template->new(
            user     => $request->{_user},
            locale   => $request->{_locale},
            path     => 'UI/payments',
            template => 'payments_filter',
            format   => 'HTML', 
        );
    }
    $template->render($payment);
}

sub display_payments {
    my ($request) = @_;
    my $payment =  LedgerSMB::DBObject::Payment->new({'base' => $request});
    $payment->get_payment_detail_data();
	$payment->debug({file => '/tmp/delme'});
    for (@{$payment->{contact_invoices}}){
        $_->{total_due} = $payment->format_amount(amount =>  $_->{total_due});
    }
    my $template = LedgerSMB::Template->new(
        user     => $request->{_user},
        locale   => $request->{_locale},
        path     => 'UI/payments',
        template => 'payments_detail',
        format   => 'HTML', 
    );
    $template->render($payment);
}
  

=item payment

This method is used to set the filter screen and prints it, using the 
TT2 system. (hopefully it will... )

=back

=cut

sub payment {
 my ($request)    = @_;  
 my $locale       = $request->{_locale};
 my  $dbPayment = LedgerSMB::DBObject::Payment->new({'base' => $request});
 
# Lets get the project data... 
 my  @projectOptions; 
 my  @arrayOptions  = $dbPayment->list_open_projects();
  push @projectOptions, {}; #A blank field on the select box 
 for my $ref (0 .. $#arrayOptions) {
       push @projectOptions, { value => $arrayOptions[$ref]->{id}."--".$arrayOptions[$ref]->{projectnumber}."--".$arrayOptions[$ref]->{description},
                                text => $arrayOptions[$ref]->{projectnumber}."--".$arrayOptions[$ref]->{description}};
 }

# Lets get the departments data...
  my @departmentOptions;
  my $role =  $request->{type} eq 'receipt' ? 'P' : 'C';
  @arrayOptions = $dbPayment->list_departments($role);
  push @departmentOptions, {}; # A blank field on the select box
  for my $ref (0 .. $#arrayOptions) {
      push @departmentOptions, {  value => $arrayOptions[$ref]->{id}."--".$arrayOptions[$ref]->{description},
                                  text => $arrayOptions[$ref]->{description}};
  }

# Lets get the customer or vendor :)
 my @vcOptions;
 @arrayOptions = $dbPayment->get_open_accounts();
 for my $ref (0 .. $#arrayOptions) {
    push @vcOptions, { value => $arrayOptions[$ref]->{id}.'--'.$arrayOptions[$ref]->{name},
                       text => $arrayOptions[$ref]->{name}};
 }
# Lets get the open currencies (this uses the $dbPayment->{account_class} property)
 my @currOptions;
 @arrayOptions = $dbPayment->get_open_currencies(); 
 for my $ref (0 .. $#arrayOptions) {
     push @currOptions, { value => $arrayOptions[$ref]->{payments_get_open_currencies},
                           text => $arrayOptions[$ref]->{payments_get_open_currencies} };
 }
# Lets build filter by period
my $date = LedgerSMB::DBObject::Date->new({base => $request});
   $date->build_filter_by_period($locale);
   
# Lets set the data in a hash for the template system. :)    
my $select = {
  stylesheet => $request->{_user}->{stylesheet},
  login    => { name  => 'login', 
                value => $request->{_user}->{login}   },
  projects => {
    name => 'projects',
    options => \@projectOptions
  },
  department => {
    name => 'department',
    options => \@departmentOptions
  },
  vendor_customer => {
    name => 'vendor-customer',
    options => \@vcOptions
  },
  curr => {
    name => 'curr',
    options => \@currOptions
  },
  month => {
    name => 'month',
    options => $date->{monthsOptions}
  },
  year => {
    name => 'year',
    options => $date->{yearsOptions}
  },
  interval_radios => $date->{radioOptions},	
  amountfrom => {
	name => 'amountfrom',
	},
  amountto => {
	name => 'amountto',
  },
  accountclass => {
   name  => 'account_class',
   value => $dbPayment->{account_class} 
  },
  type => {
    name  => 'type',
    value => $request->{type}
  },
  action => {
    name => 'action',
    value => 'payment2', 
    text => $locale->text("Continue"),
  },
};
# Lets call upon the template system
my $template;

  $template = LedgerSMB::Template->new(
  user     => $request->{_user},
  locale   => $request->{_locale},
  path     => 'UI/payments',
  template => 'payment1',
  format => 'HTML', );
$template->render($select);# And finally, Lets print the screen :)
}

=pod

=item payment2

This method is used  for the payment module, it is a consecuence of the payment sub,
and its used for all the mechanics of an invoices payment module.

=back

=cut

sub payment2 {
my ($request) = @_;
my $locale       = $request->{_locale};
my $Payment = LedgerSMB::DBObject::Payment->new({'base' => $request});
# VARIABLES
my ($project_id, $project_number, $project_name, $department_id, $department_name );
my @array_options;
my @project;
my @selected_checkboxes;
my @department;
my @array_options;
my @currency_options;
my $exchangerate;
# LETS GET THE CUSTOMER/VENDOR INFORMATION	
($Payment->{entity_id}, my $vendor_customer_name) = split /--/ , $request->{'vendor-customer'};
my @vc_options;

#@array_options = $Payment->get_vc_info();
#$request->error($array_options[0]->{name});
# LETS BUILD THE PROJECTS INFO
# I DONT KNOW IF I NEED ALL THIS, BUT AS IT IS AVAILABLE I'LL STORE IT FOR LATER USAGE.
if ($request->{projects}) {
  ($project_id, $project_number, $project_name)  = split /--/ ,  $request->{projects} ; 
  @project = { name => 'projects',  text => $project_number.' '.$project_name,  value => $request->{projects}};
}
# LETS GET THE DEPARTMENT INFO
if ($request->{department}) {
 ($department_id, $department_name)             = split /--/, $request->{department};
 @department = { name => 'department',  text => $department_name,  value => $request->{department}};
} 
# LETS GET ALL THE ACCOUNTS
my @account_options = $Payment->list_accounting();
# LETS GET THE POSSIBLE SOURCES
my @sources_options = $Payment->get_sources(\%$locale);
# WE MUST PREPARE THE ENTITY INFORMATION
@array_options = $Payment->get_vc_info();
# LETS BUILD THE CURRENCIES INFORMATION 
# FIRST, WE NEED TO KNOW THE DEFAULT CURRENCY
my $default_currency = $Payment->get_default_currency(); 
# LETS BUILD THE COLUMN HEADERS WE ALWAYS NEED 
# THE OTHER HEADERS WILL BE BUILT IF THE RIGHT CONDITIONS ARE MET.
# -----------------------------------------------
# SOME USERS WONT USE MULTIPLE CURRENCIES, AND WONT LIKE THE FACT CURRENCY BEING
# ON THE SCREEN ALL THE TIME, SO IF THEY ARE USING THE DEFAULT CURRENCY WE WONT PRINT IT
my $currency_text  =  $request->{curr} eq $default_currency ? '' : '('.$request->{curr}.')';
my $default_currency_text = $currency_text ? '('.$default_currency.')' : '';
my @column_headers =  ({text => $locale->text('Invoice')},
                       {text => $locale->text('Date')},
                       {text => $locale->text('Total').$default_currency_text},
                       {text => $locale->text('Paid').$default_currency_text},
                       {text => $locale->text('Amount Due').$default_currency_text},
                       {text => $locale->text('To pay').$default_currency_text}
                       );
 # WE NEED TO KNOW IF WE ARE USING A CURRENCY THAT NEEDS AN EXCHANGERATE
 
 if ($default_currency ne $request->{curr} ) {
 # FIRST WE PUSH THE OTHER COLUMN HEADERS WE NEED    
     push @column_headers, {text => $locale->text('Exchange Rate')},
                           {text => $locale->text('Amount Due').$currency_text},
                           {text => $locale->text('To pay').$currency_text};
 # WE SET THEM IN THE RIGHT ORDER FOR THE TABLE INSIDE THE UI   
     @column_headers[5,6,7] = @column_headers[6,7,5];
 # DOES THE CURRENCY IN USE HAS AN EXCHANGE RATE?, IF SO 
 # WE MUST SET THE VALUE, OTHERWISE THE UI WILL HANDLE IT
   $exchangerate = $request->{exrate} ? 
                   $request->{exrate} :
                   $Payment->get_exchange_rate($request->{curr}, 
                   $request->{datepaid} ? $request->{datepaid} : $Payment->{current_date});
   if ($exchangerate) {
     @currency_options = {
          name => 'exrate',
          value => "$exchangerate", #THERE IS A STRANGE BEHAVIOUR WITH THIS, 
          text =>  "$exchangerate"  #IF I DONT USE THE DOUBLE QUOTES, IT WILL PRINT THE ADDRESS
                                    #THERE MUST BE A REASON FOR THIS, I MUST RETURN TO IT LATER
	  };
   } else {
   @currency_options = {
        name => 'exrate'};
   }
 
 } else {
 # WE MUST SET EXCHANGERATE TO 1 FOR THE MATHS SINCE WE
 # ARE USING THE DEFAULT CURRENCY
   $exchangerate = 1;
   @currency_options = {
                          name => 'exrate',
                          value => 1, 
                          text =>  1 
                       };
  }

 # FINALLY WE ADD TO THE COLUMN HEADERS A LAST FIELD TO PRINT THE CLOSE INVOICE CHECKBOX TRICK :)
 push @column_headers, {text => 'X'};
# WE NEED TO QUERY THE DATABASE TO CHECK FOR OPEN INVOICES
# IF WE DONT HAVE ANY INVOICES MATCHING THE FILTER PARAMETERS, WE WILL WARN THE USER AND STOP
# THE PROCCESS. 
my @invoice_data;
@array_options  = $Payment->get_open_invoices(); 
if (!$array_options[0]->{invoice_id}) { 
  $request->error($locale->text("Nothing to do"));
}
for my $ref (0 .. $#array_options) {
 if (  !$request->{"checkbox_$array_options[$ref]->{invoice_id}"}) {
 #We have to set some things first ...
   my $due_fx; my $topay_fx_value;
   if ("$exchangerate") {
       $topay_fx_value =   $due_fx = "$array_options[$ref]->{due}"/"$exchangerate";
   } else {
       $topay_fx_value = $due_fx = "N/A";
   }
   push @invoice_data, {       invoice => { number => $array_options[$ref]->{invnumber},
                                            id     =>  $array_options[$ref]->{invoice_id},
                                            href   => 'ar.pl?id='."$array_options[$ref]->{invoice_id}"
                                           },  
                               invoice_date      => "$array_options[$ref]->{invoice_date}",
                               amount            => "$array_options[$ref]->{amount}",
                               due               => "$array_options[$ref]->{due}",
                               paid              => "$array_options[$ref]->{amount}" - "$array_options[$ref]->{due}",
                               exchange_rate     => "$exchangerate",
                               due_fx            =>  $due_fx, # This was set at the begining of the for statement
                               topay             => "$array_options[$ref]->{due}",
                               source_text       =>  $request->{"source_text_$array_options[$ref]->{invoice_id}"},
                               optional          =>  $request->{"optional_pay_$array_options[$ref]->{invoice_id}"},
                               selected_account  =>  $request->{"account_$array_options[$ref]->{invoice_id}"},
                               selected_source   =>  $request->{"source_$array_options[$ref]->{invoice_id}"},
                               topay_fx          =>  { name  => "topay_fx_$array_options[$ref]->{invoice_id}",
                                                       value => $request->{"topay_fx_$array_options[$ref]->{invoice_id}"} ? 
                                                           $request->{"topay_fx_$array_options[$ref]->{invoice_id}"} eq 'N/A' ?
                                                           $topay_fx_value :
                                                           $request->{"topay_fx_$array_options[$ref]->{invoice_id}"} :
                                                           $topay_fx_value
                                                           # Ugly hack, but works ;) ... not sure if i should
                                                           # change it.
                                                 }  
                                                     
                           };# END PUSH 
 }
 else {
  push @selected_checkboxes, {name => "checkbox_$array_options[$ref]->{invoice_id}", 
                              value => "checked"} ;   
 } #END IF                          
}# END FOR
if (!@invoice_data) { 
 $request->error($locale->text("Nothing to do").'!');
}
# LETS BUILD THE SELECTION FOR THE UI
my $select = {
  stylesheet => $request->{_user}->{stylesheet},
  header  =>  { text => $request->{type} eq 'receipt' ? $locale->text('Receipt') : $locale->text('Payment') },
  login    => { name  => 'login', 
                value => $request->{_user}->{login}   },
  accountclass => {
   name  => 'account_class',
   value => $Payment->{account_class} 
  },
  project =>  @project ? @project : '' ,        # WE NEED TO VERIFY THAT THE ARRAY EXISTS, IF IT DOESNT, 
  department => @department ? @department : '', # WE WILL PASS A NULL STRING, THIS FIXES THE ISSUES
                                                # I WAS HAVING WITH THE NULL ARRAYS, STILL UGLY :P
  account => \@account_options,
  selected_account => $request->{account},
  datepaid => {
	name => 'datepaid',
	value => $request->{datepaid} ? $request->{datepaid} : $Payment->{current_date}
  },
  source => \@sources_options,
  selected_source => $request->{source}, 
  source_value => $request->{source_value},
  defaultcurrency => {
        text => $default_currency
  },
  curr => {       name  => 'curr',
                  value => $request->{curr},
          
  },
  column_headers => \@column_headers,
  rows		=>  \@invoice_data,
  vendorcustomer => { name => 'vendor-customer',
                      value => $request->{'vendor-customer'}
                     },
    
  vc => { name => $vendor_customer_name,
          address =>  [ {text => 'Crra 83 #32 -1'},
          	  {text => '442 6464'},
		  {text => 'Medell�n'},
		  {text => 'Colombia'}]
        },
  update => {
    title  => 'UPDATE ALT+U',
    name =>   'action',
    value =>  'payment2', 
    text => $locale->text('UPDATE')
  },
  post => {
    title  =>  'POST ALT+O',
    name => 'action',
    value => 'post', 
    text => $locale->text('POST')
  },
  post_and_print => {
    title     =>  'POST AND PRINT ALT+R',
    name => 'action',
    value => 'post_and_print', 
    text => $locale->text("POST AND PRINT")
  },
   format => {
    name => 'FORMAT',
    options => [
      {value => 1, text => "HTML" },
      {value => 2, text => "PDF" },
      {value => 3, text => "POSTSCRIPT" }
    ],
  },
    media => {
    name => 'MEDIA',
    options => [
      {value => 1, text => "Screen" },
      {value => 2, text => "PRINTER" },
      {value => 3, text => "EMAIL" }
    ],
  },
 exrate => @currency_options,
 selectedcheckboxes => @selected_checkboxes  ? \@selected_checkboxes : '',
 notes => $request->{notes}
};
my $template = LedgerSMB::Template->new(
  user     => $request->{_user},
  locale   => $request->{_locale},
  path     => 'UI/payments',
  template => 'payment2',
  format => 'HTML' );
eval {$template->render($select) };
 if ($@) { $request->error("$@");  } # PRINT ERRORS ON THE UI
}


eval { do "scripts/custom/payment.pl"};
1;