# $Id: payment.pm,v 1.23 2004/07/26 05:25:12 mig Exp $
######################################
# Comas - Conference Management System
######################################
# Copyright 2003 CONSOL
# Congreso Nacional de Software Libre (http://www.consol.org.mx/)
#   Gunnar Wolf <gwolf@gwolf.cx>
#   Manuel Rabade <mig@mig-29.net>
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
######################################

######################################
# Module: Comas::HTML::committee::payment
# Front End for the payment tasks
######################################
# Depends on:

# Comas::Person - Handles the interaction with a person for Comas
# Comas::HTML::common - Common functions for the HTML FrontEnd
# Comas::Proposal - Handles the interaction with a person for Comas
# Comas::Admin - Manage administrative tasks for a Comas database 
# Data::FormValidator - Validates user input based on input profile

# This module is not meant to be called on its own, it should be called from
# Comas::HTML.

package Comas::HTML::committee::payment;

use strict;
use warnings;
use Carp;

use Comas::Admin;
use Comas::Conf qw(:read);
use Comas::Person;
use Comas::Proposal;
use Comas::HTML::common qw(:all);
use Comas::Payment;

use Data::FormValidator;
use PDF::API2;

use Exporter;

our @ISA = qw(Exporter);
our @EXPORT_OK = qw(payment_reg_select_person payment_reg_search_person
                    payment_reg_select payment_reg_confirm payment_reg_register

                    payment_mod_select_person_delete
                    payment_mod_search_person_delete payment_mod_select_delete
                    payment_mod_confirm_delete payment_mod_delete);

our %EXPORT_TAGS = (register => [qw(payment_reg_select_person
                                    payment_reg_search_person payment_reg_select
                                    payment_reg_confirm payment_reg_register)],

                    modify => [qw(payment_mod_select_person_delete
                                  payment_mod_search_person_delete
                                  payment_mod_select_delete
                                  payment_mod_confirm_delete
                                  payment_mod_delete )],

                    all => [@EXPORT_OK] );

=head1 NAME
    
Comas::HTML::committee::payment - Front End for the monetary admin tasks

=head1 SYNOPSIS

This module is not meant to be used by itself, but as an auxiliary to
L<Comas::HTML|Comas::HTML>. Please check L<Comas::HTML|Comas::HTML>'s
documentation, in the B<Front End Tasks> section, for further details on the
usage for this functions.

=head1 INTERNALS

This is a very complex part of Comas, have two main process: the registration
and modification (implies the lookup and currently is only implemented the
remove) of payments, both have the folowing secuence:

=over 2

=item - Select a person by his login or search by some parameters and select one
from a list.

=item - Show the person data (for verification) and the proposals list with its
amount in the case of register, or to remove a payment the list of proposals
already payed by the person.

=item - Confirm the action displaying the proposals that are going to be payed
or removed.

=item - Show a summary with the proposals payed or removed.

=back

=head2 METHODS

=head3 $res = $html->payment_reg_select_person;

Select a person (by his login, but also the tempalte should provide a form to
send some search parameters to another method that have to process them with
C<_search-person>) to start the payment registration process.

It's only a kind of wrapper to C<_select_person>.

=cut

sub payment_reg_select_person {
    my $h = shift;

    my ($template, $person) = $h->_select_person;
    $template->param(PAYMENT_REG => 1);
    if ($person) {
        return $h->payment_reg_select($person);
    } else {
        return $template->output;
    }
}

=pod

=head3 $res = $html->payment_reg_search_person;

Show a list of persons that match a given criteria so we can chosse one person
to start the payment registration process.

It's only a kind of wrapper to C<_serch_person>.

=cut

sub payment_reg_search_person {
    my $h = shift;
    my $template = $h->_search_person;
    $template->param(PAYMENT_REG => 1);
    return $template->output;
}

=pod

=head3 $res = $html->payment_reg_select($id);

Shows person details and the list of proposals with his amount, this is where we
chosse what proposals are going to pay the atteendee.

The list also includes the proposlas already payed by the attendee and the
proposals with no avalible places.

The argument C<$id> is the person id, if isn't defined the third element of the
path is used as person id (usefull when you display a list of persons).

The process of registering a payment starts here.

=cut

sub payment_reg_select {
    my (@proposal_ids, @proposals, $template, @proposals_sorted, $person,
        %person_data, %general_entry, %old_payments);
    my $h = shift;
    my $person_id = shift;

    unless($h->_ck_committee_task) {
        return $h->committee_menu('NOT_AUTHORIZED');
    }

    $template = $h->new_template('committee/payment/select_payment.tmpl');
    
    unless (defined $person_id) { $person_id = $h->{-path}->[3]; }
    
    $person = Comas::Person->new(-db => $h->{-db}, 
                                 -id => $person_id);
    
    %person_data = $person->get_data;
    $template->param(-id => $person->{-id},
                     -firstname => $person_data{-firstname},
                     -famname => $person_data{-famname},
                     -email => $person_data{-email},
                     -person_type => $h->{-db}->getCatDescr('person_type',
					       $person_data{-person_type_id}));
    
    foreach my $payment (Comas::Payment->get_payments(-db => $h->{-db},
                                                      -person =>
                                                      $person->{-id})) {
        my (undef, $prop_id) = Comas::Payment->get_payment_data(-db =>
                                                                $h->{-db},
                                                                -payment_id =>
                                                                $payment);
        if (defined($prop_id)) {
            $old_payments{$prop_id} = 1;
        } else {
            $old_payments{0} = 1;
        }            
    }

    @proposal_ids = Comas::Proposal->search(-db => $h->{-db},
                                            -prop_status_id =>
                                            get_conf($h->{-db},
                                                     'proposals_accepted_id'));
    foreach my $p_id (@proposal_ids) {
        my ($proposal_temp, %row, %prop_data);
        $proposal_temp = Comas::Proposal->new(-db => $h->{-db},
                                              -id => $p_id);
        %prop_data = $proposal_temp->get_data;
        $row{amount} = Comas::Payment->calculate_amount(-db => $h->{-db},
                                                        -person => 
                                                        $person->{-id},
                                                        -proposals =>
                                                        [$prop_data{-id}]);
        if ($row{amount} == 0) { next; }
        
        $row{id} = $prop_data{-id};
        $row{title} = $prop_data{-title};
        $row{prop_type_id} = $prop_data{-prop_type_id};
        $row{prop_type} = $proposal_temp->{-db}->getCatDescr('prop_type',
                                    $prop_data{-prop_type_id});
        ($row{people},
         $row{max_people}) = Comas::Payment->get_capacity(-db => $h->{-db},
                                                          -proposal =>
                                                          $prop_data{-id});
        if ($row{people} >= $row{max_people} and $row{max_people} != 0) {
            $row{full} = 1;
        }
        if ($old_payments{$row{id}}) {
            $row{payed} = 1;
        }
        push (@proposals, \%row);
    }
    
    @proposals_sorted = sort { $a->{title} cmp $b->{title} } @proposals;
    
    $general_entry{id} = 0;
    $general_entry{title} = $h->{-db}->getCatDescr('prop_type',0);
    $general_entry{amount} = Comas::Payment->calculate_amount(-db => $h->{-db},
                                                              -person => 
                                                              $person->{-id});

    ($general_entry{people}, $general_entry{max_people}) = (0,0);

    if ($old_payments{0}) {
        $general_entry{payed} = 1;
    }
    unless ($general_entry{amount} == 0) { push(@proposals_sorted,
                                           \%general_entry); }
    
    $template->param(PROPOSALS => \@proposals_sorted);
    return $template->output;
}

=pod

=head3 $res = $html->payment_reg_confirm;

Confirm the selected proposals in C<payment_reg_select> and show the total
amount.

The amount for each proposal can be changed here, and the total amount is
updated acording the modifications.

=cut

sub payment_reg_confirm {
    my ($person, $template, @proposals, @proposals_sorted, %person_data,
	%prop_types);
    my $h = shift;

    unless($h->_ck_committee_task) {
        return $h->committee_menu('NOT_AUTHORIZED');
    }

    %prop_types = $h->{-db}->getCatalog('prop_type');

    $template = $h->new_template('committee/payment/confirm_payment.tmpl');

    $template->param(-payment_type_list => 
                     _catalog2html_opts($h->{-db},"payment_type",
                                        $h->{-params}->{-payment_type_id},
                                        undef,1));

    $person = Comas::Person->new(-db => $h->{-db}, 
                                 -id => $h->{-path}->[3]);
    %person_data = $person->get_data;
    $template->param(-id => $person->{-id},
                     -firstname => $person_data{-firstname},
                     -famname => $person_data{-famname},
                     -email => $person_data{-email},
                     -person_type => $h->{-db}->getCatDescr('person_type',
					     $person_data{-person_type_id}));

    $template->param(general_amount =>
                     Comas::Payment->calculate_amount(-db => $h->{-db},
                                                      -person => 
                                                      $person->{-id}),
                     general_title => $prop_types{0});
    
    foreach my $param (keys %{$h->{-params}}) {
        if ($param =~ /^pay_prop_(.*)/) {
            my ($proposal_temp, %row, %prop_data);
            if ($1 == 0) {
                $row{id} = 0;
                $row{title} = $prop_types{0};
                $row{amount} = Comas::Payment->
                    calculate_amount(-db => $h->{-db},
                                     -person =>$person->{-id});     
                ($row{people}, $row{max_people}) = (0,0);
            } else {
                $proposal_temp = Comas::Proposal->new(-db => $h->{-db},
                                                      -id => $1);
                %prop_data = $proposal_temp->get_data;
                $row{amount} = Comas::Payment->calculate_amount(-db => $h->{-db},
                                                                -person => 
                                                                $person->{-id},
                                                                -proposals =>
                                                                [$prop_data{-id}]);
                ($row{people},
                 $row{max_people}) = Comas::Payment->get_capacity(-db => 
                                                                  $h->{-db},
                                                                  -proposal =>
                                                                  $prop_data{-id});
                
                $row{id} = $prop_data{-id};
                $row{title} = $prop_data{-title};
                $row{prop_type_id} = $prop_data{-prop_type_id};
                $row{prop_type} = $prop_types{$prop_data{-prop_type_id}};
            }
            push (@proposals, \%row);
        }
    }
    @proposals_sorted = sort { $a->{title} cmp $b->{title} } @proposals;
    $template->param(PROPOSALS => \@proposals_sorted);
    return $template->output;    
}

=pod

=head3 $res = $html->payment_reg_register;

If the payments are confirmed in C<payment_reg_confirm> let's register and show
them with the total amount.

The process of registering a payment ends here.

=cut

sub payment_reg_register {
    my ($person, $template, %person_data, @proposals, @proposals_sorted,
    $total_amount);
    my $h = shift;

    unless($h->_ck_committee_task) {
        return $h->committee_menu('NOT_AUTHORIZED');
    }

    $person = Comas::Person->new(-db => $h->{-db}, 
                                 -id => $h->{-path}->[3]);

    $template = $h->new_template('committee/payment/register_payment.tmpl');

    %person_data = $person->get_data;
    
    $template->param(-id => $person->{-id},
                     -firstname => $person_data{-firstname},
                     -famname => $person_data{-famname},
                     -email => $person_data{-email},
                     -person_type =>
                     $h->{-db}->getCatDescr('person_type',
				     $person_data{-person_type_id}));
    
    foreach my $param (keys %{$h->{-params}}) {
        my ($proposal_temp, %row, %prop_data);
        if ($param =~ /^amount_prop_(.*)/) {
            if ($1 == 0) {
                if (Comas::Payment->register(-db => $h->{-db_adm},
                                             -admin =>
                                             $h->{-session}->{-admin}->{-login},
                                             -admin_pwd =>
                                             $h->{-session}->{-admin}->{-passwd},
                                             -person => $person->{-id},
                                             -amount => $h->{-params}->{$param},
                                             -payment_type =>
                                             $h->{-params}->{-payment_type_id})) {
                    $row{id} = 0;
                    $row{title} = $h->{-db}->getCatDescr('prop_type',0);
                    $row{amount} = $h->{-params}->{$param};
                    $total_amount += $row{amount};
                    push (@proposals, \%row);
                }
              } else {
                  warn $h->{-params}->{$param};
                  if (Comas::Payment->register(-db => $h->{-db_adm},
                                               -admin =>
                                               $h->{-session}->{-admin}->{-login},
                                               -admin_pwd =>
                                               $h->{-session}->{-admin}->{-passwd},
                                               -person => $person->{-id},
                                               -amount => $h->{-params}->{$param},
                                               -payment_type =>
                                               $h->{-params}->{-payment_type_id},
                                               -proposal => $1 )) {
                      $proposal_temp = Comas::Proposal->new(-db => $h->{-db},
                                                            -id => $1);
                      %prop_data = $proposal_temp->get_data;
                      $row{id} = $prop_data{-id};
                      $row{title} = $prop_data{-title};
                      $row{prop_type_id} = $prop_data{-prop_type_id};
                      $row{prop_type} = $h->{-db}->getCatDescr('prop_type',
                                                  $prop_data{-prop_type_id});
                      $row{amount} = $h->{-params}->{$param};
                      $total_amount += $row{amount};
                      push (@proposals, \%row);
                  }
              }
        }
    }
    @proposals_sorted = sort { $a->{title} cmp $b->{title} } @proposals;
    $template->param(PROPOSALS => \@proposals_sorted,
                     -total_amount => $total_amount,
                     -payment_type => 
                     $h->{-db}->getCatDescr('payment_type',
                               $h->{-params}->{-payment_type_id}));
    return $template->output;
}

###############################################################################

=pod

=head3 $res = $html->payment_mod_select_person_delete;

Select a person (by his login, but also the tempalte should provide a form to
send some search parameters to another method that have to process them with
C<_search-person>) to remove payments.

It's only a kind of wrapper to C<_select_person>.

=cut

sub payment_mod_select_person_delete {
    my $h = shift;

    my ($template, $person) = $h->_select_person;
    $template->param(PAYMENT_MOD => 1);
    if ($person) {
        return $h->payment_mod_select_delete($person);
    } else {
        return $template->output;
    }
}

=pod

=head3 $res = $html->payment_mod_search_person_delete;

Show a list of persons that match a given criteria so we can chosse one person
to remove his payments.

It's only a kind of wrapper to C<_serch_person>.

=cut

sub payment_mod_search_person_delete {
    my ($template, $input_profile, $validator, $val_results, @person_ids,
        @persons);

    my $h = shift;
    $template = $h->_search_person;
    $template->param(PAYMENT_MOD => 1);
    return $template->output;
}

=pod

=head3 $res = $html->payment_mod_select_delete($id,$message);

Shows person details and the list of hist payments so we can select the ones
that are going to be removed.

The argument C<$id> is the person id, if isn't defined the third element of the
path is used as person id.

Can receive an optional explanatory message (C<$message>) that will be passed to
the template.

The process of removing a payment starts here.

=cut

sub payment_mod_select_delete {
    my $h = shift;
    my $person_id = shift;
    my $message = shift;

    my ($template, $person, %person_data, @payments, $total);

    unless($h->_ck_committee_task) {
        return $h->committee_menu('NOT_AUTHORIZED');
    }

    $template = $h->new_template('committee/payment/delete_payment.tmpl');

    if (defined $message) { $template->param($message => 1); }    

    unless (defined $person_id) { $person_id = $h->{-path}->[3]; }
    
    $person = Comas::Person->new(-db => $h->{-db}, 
                                 -id => $person_id);
    
    %person_data = $person->get_data;
    $template->param(-id => $person->{-id},
                     -firstname => $person_data{-firstname},
                     -famname => $person_data{-famname},
                     -email => $person_data{-email},
                     -person_type => $h->{-db}->getCatDescr('person_type',
                               $person_data{-person_type_id}));
    
    foreach my $payment (Comas::Payment->get_payments(-db => $h->{-db},
                                                      -person =>
                                                      $person->{-id})) {
        my ($proposal_temp, %row, %prop_data, $prop_id);

        (undef, $prop_id,
         $row{amount}) = Comas::Payment->get_payment_data(-db =>
                                                          $h->{-db},
                                                          -payment_id =>
                                                          $payment);

        $total += $row{amount};
        $row{id} = $payment;

        if ($prop_id == 0) {
            $row{title} = $h->{-db}->getCatDescr('prop_type',0);
            ($row{people}, $row{max_people}) = (0,0);
        } else {
            $proposal_temp = Comas::Proposal->new(-db => $h->{-db},
                                                  -id => $prop_id);
            %prop_data = $proposal_temp->get_data;
            
            $row{title} = $prop_data{-title};
            $row{prop_type_id} = $prop_data{-prop_type_id};
            $row{prop_type} = $h->{-db}->getCatDescr('prop_type',
                                        $prop_data{-prop_type_id});
            ($row{people},
             $row{max_people}) = Comas::Payment->get_capacity(-db => $h->{-db},
                                                              -proposal =>
                                                              $prop_data{-id});
        }
        push (@payments, \%row);
    }
    $template->param(PAYMENTS => \@payments,
                     -total => $total);
    return $template->output;
}

=pod

=head3 $res = $html->payment_reg_confirm;

Confirm that we want to remove the selected payments in
C<payment_mod_select_delete> with its total amount (of the selected payments).

=cut

sub payment_mod_confirm_delete {
    my $h = shift;

    unless($h->_ck_committee_task) {
        return $h->committee_menu('NOT_AUTHORIZED');
    }

    my ($template, $person, %person_data, @payments, $total);

    $template = $h->new_template('committee/payment/confirm_delete_payment.tmpl');

    $person = Comas::Person->new(-db => $h->{-db}, 
                                 -id => $h->{-path}->[3]);

    %person_data = $person->get_data;

    $template->param(-id => $person->{-id},
                     -firstname => $person_data{-firstname},
                     -famname => $person_data{-famname},
                     -email => $person_data{-email},
                     -person_type => $h->{-db}->getCatDescr('person_type',
                                              $person_data{-person_type_id}));

    foreach my $param (keys %{$h->{-params}}) {
        if ($param =~ /^del_pay_(.*)/) {
            my ($proposal_temp, %row, %prop_data, $prop_id);

            (undef, $prop_id,
             $row{amount}) = Comas::Payment->get_payment_data(-db =>
                                                              $h->{-db},
                                                              -payment_id =>
                                                              $1);
            
            $total += $row{amount};
            $row{id} = $1;

            if ($prop_id == 0) {
                $row{title} = $h->{-db}->getCatDescr('prop_type',0);
                ($row{people}, $row{max_people}) = (0,0);                
            } else {
                $proposal_temp = Comas::Proposal->new(-db => $h->{-db},
                                                      -id => $prop_id);
                %prop_data = $proposal_temp->get_data;
                
                $row{title} = $prop_data{-title};
                $row{prop_type_id} = $prop_data{-prop_type_id};
                $row{prop_type} = $h->{-db}->getCatDescr('prop_type',
					          $prop_data{-prop_type_id});
                ($row{people},
                 $row{max_people}) = Comas::Payment->get_capacity(-db => $h->{-db},
                                                                  -proposal =>
                                                                  $prop_data{-id});
            }
            push (@payments, \%row);
        }
    }
    
    $template->param(PAYMENTS => \@payments,
                     -total => $total);
    return $template->output;
}

=pod

=head3 $res = $html->payment_mod_delete;

Remove the selected payments in C<payment_mod_confirm_delete> and show
C<payment_mod_select_delete> updated.

The process of removing a payment ends here.

=cut

sub payment_mod_delete {
    my $h = shift;

    my ($template, $person, %person_data, @payments, $total);

    unless($h->_ck_committee_task) {
        return $h->committee_menu('NOT_AUTHORIZED');
    }

    foreach my $param (keys %{$h->{-params}}) {
        if ($param =~ /^del_pay_(.*)/) {
            Comas::Payment->delete(-db=> $h->{-db_adm}, -id => $1);
          }
    }

    return $h->payment_mod_select_delete($person,'DELETED');    
}

1;

=pod

=head1 SEE ALSO

L<Comas::HTML|Comas::HTML> module documentation

=head1 AUTHOR

Gunnar Wolf, gwolf@gwolf.cx

Manuel Rabade, mig@mig-29.net

Comas has been developed for CONSOL, Congreso Nacional de Software Libre,
http://www.consol.org.mx/

=head1 COPYRIGHT

Copyright 2003 Gunnar Wolf and Manuel Rabade

This library is free software, you can redistribute it and/or modify it
under the terms of the GPL version 2 or later.

=cut

# $Log: payment.pm,v $
# Revision 1.23  2004/07/26 05:25:12  mig
# Ups, i broke it while doing the POD, fixed.
#
# Revision 1.22  2004/07/26 05:20:29  mig
# POD is done.
#
# Revision 1.21  2004/07/08 00:15:40  gwolf
# Handling Comas' and the conference's base URL in the configuration,
# not hard-coded in the HTML templates themselves
#
# Revision 1.20  2004/07/02 06:02:07  mig
# Removed CONSOL specific functions (payment_print_sticker _print_sticker payment_print_diploma _print_diploma)
#
# Revision 1.19  2004/06/28 05:29:12  mig
# Partitial fix of spanish strings in the code
#
# Revision 1.18  2004/06/11 19:37:29  gigio
# Applied izone's patch that fixes calls to getCatalog and
# getCatDesc. There were 2 more calls left unfixed. This commits gets
# them, too.
#
# Revision 1.17  2004/04/07 21:32:40  gwolf
# Created Comas::DB methods getCatalog and getCatDescr, modified some of
# Comas::DB modules in order to use this interface instead of
# Comas::HTML::common::_id2descr (and removed that function, of course)
#
# Revision 1.16  2004/02/07 06:46:33  mig
# - Al pedo el centrado del nombre en las constancias :)
#
# Revision 1.15  2004/02/07 01:12:53  mig
# - Corrigo mega bug cuando se borraban pagos no se tomaba en cuenta cuando
#   este era la entrada general.
#
# Revision 1.14  2004/02/07 00:12:46  mig
# - Lista la consulta y modificacion de pagos
#
# Revision 1.13  2004/02/06 02:12:47  mig
# - Una ruta completa es mejor :)
#
# Revision 1.12  2004/02/06 02:02:51  mig
# - Lista la impresion de constancias :)
#
# Revision 1.11  2004/02/05 21:43:01  mig
# - Despues de imprimir te regresa a la pagina anterior
#
# Revision 1.10  2004/02/05 21:17:49  mig
# - A ver si esta es la buena del nick :-P
#
# Revision 1.9  2004/02/05 21:07:02  mig
# - Ya quedo el pedo de cuando no existe nick :)
#
# Revision 1.8  2004/02/05 20:51:47  mig
# - Error cuando no hay nick
#
# Revision 1.7  2004/02/05 20:16:16  mig
# - Al parecer listo los gafetes :)
#
# Revision 1.6  2004/02/03 03:22:00  mig
# - Mayor control en la creacion de pagos.
#
# Revision 1.5  2004/01/30 07:24:49  mig
# - Correcciones de identado
#
# Revision 1.4  2004/01/24 01:43:32  mig
# - Lista la busqueda de personas :)
#
# Revision 1.3  2004/01/23 07:48:39  mig
# - Ya hay registro de pagos !
#
