From 82254cc7c2fab1a48c291f75a0a04f2fdaaa6b11 Mon Sep 17 00:00:00 2001 From: einhverfr Date: Tue, 4 Mar 2008 19:47:19 +0000 Subject: Adding David Mora's single-payment interface patches git-svn-id: https://ledger-smb.svn.sourceforge.net/svnroot/ledger-smb/trunk@2098 4979c152-3d1c-0410-bac9-87ea11338e46 --- LedgerSMB/AM.pm | 4 +- LedgerSMB/DBObject/Payment.pm | 18 ++++- UI/am-account-form.html | 73 ++++++++++++-------- UI/payments/payment1.html | 70 +++++++------------ UI/payments/payment2.html | 157 +++++++++++++++++++++++++++++++++++------- bin/am.pl | 4 +- scripts/payment.pl | 106 ++++++++++++++++------------ sql/modules/Payment.sql | 111 ++++++++++++++++++----------- sql/modules/chart.sql | 28 +++++++- 9 files changed, 377 insertions(+), 194 deletions(-) diff --git a/LedgerSMB/AM.pm b/LedgerSMB/AM.pm index 803a9f32..e1ff4043 100644 --- a/LedgerSMB/AM.pm +++ b/LedgerSMB/AM.pm @@ -158,8 +158,8 @@ sub save_account { $form->{link} = ""; foreach my $item ( - $form->{AR}, $form->{AR_amount}, $form->{AR_tax}, - $form->{AR_paid}, $form->{AP}, $form->{AP_amount}, + $form->{AR}, $form->{AR_amount}, $form->{AR_tax}, $form->{AR_overpayment}, + $form->{AR_paid}, $form->{AP}, $form->{AP_amount}, $form->{AP_overpayment}, $form->{AP_tax}, $form->{AP_paid}, $form->{IC}, $form->{IC_income}, $form->{IC_sale}, $form->{IC_expense}, $form->{IC_cogs}, $form->{IC_taxpart}, $form->{IC_taxservice} diff --git a/LedgerSMB/DBObject/Payment.pm b/LedgerSMB/DBObject/Payment.pm index bf507190..7e85e049 100644 --- a/LedgerSMB/DBObject/Payment.pm +++ b/LedgerSMB/DBObject/Payment.pm @@ -314,6 +314,20 @@ sub list_accounting { return @{$self->{pay_accounts}}; } +=item list_overpayment_accounting + +This method lists all accounts that match the role specified in account_class property and +are availible to store an overpayment / advanced payment / pre-payment. +=back +=cut + +sub list_overpayment_accounting { + my ($self) = @_; + @{$self->{overpayment_accounts}} = $self->exec_method( funcname => 'chart_list_overpayment'); + return @{$self->{overpayment_accounts}}; +} + + =item get_sources This method builds all the possible sources of money, @@ -378,8 +392,8 @@ $self->{account_class} sub get_vc_info { my ($self) = @_; - #@{$self->{vendor_customer_info}} = $self->call_procedure(procname => 'vendor_customer_info'); - #return @{$self->{vendor_customer_info}}; + @{$self->{vendor_customer_info}} = $self->exec_method(funcname => 'payment_get_vc_info'); + return @{$self->{vendor_customer_info}}; } =item get_payment_detail_data diff --git a/UI/am-account-form.html b/UI/am-account-form.html index 34482b51..64bffb8b 100644 --- a/UI/am-account-form.html +++ b/UI/am-account-form.html @@ -10,14 +10,14 @@ - - @@ -28,32 +28,32 @@
'accno', size => '20', value => form.accno} ?>
'description', size => '40', value => form.description} ?>
- @@ -228,12 +241,12 @@
- 'category', type => 'radio', label => text('Asset'), value => 'A', ${checked.A_} => checked.A_, } ?>
- 'category', type => 'radio', label => text('Liability'), ${checked.L_} => checked.L_, value => 'L'} ?>
- 'category', type => 'radio', label => text('Equity'), ${checked.Q_} => checked.Q_, value => 'Q'} ?>
- 'category', type => 'radio', label => text('Income'), ${checked.I_} => checked.I_, value => 'I'} ?>
- 'category', type => 'radio', label => text('Expense'), @@ -61,7 +61,7 @@ value => 'E'} ?>
- 'contra', type => 'checkbox', label => text('Contra'), @@ -69,13 +69,13 @@ value => '1'} ?> - 'charttype', type => 'radio', label => text('Heading'), ${checked.H} => checked.H, value => 'H'} ?>
- 'charttype', type => 'radio', label => text('Account'), @@ -93,19 +93,19 @@
- 'AR', type => 'checkbox', label => text('AR'), ${form.AR} => form.AR, value => 'AR'} ?> - 'AP', type => 'checkbox', label => text('AP'), ${form.AP} => form.AP, value => 'AP'} ?> - 'IC', type => 'checkbox', label => text('Inventory'), @@ -130,59 +130,72 @@
- 'AR_amount', type => 'checkbox', label => text('Income'), ${form.AR_amount} => form.AR_amount, value => 'AR_amount'} ?>
- 'AR_paid', type => 'checkbox', label => text('Payment'), ${form.AR_paid} => form.AR_paid, value => 'AR_paid'} ?>
- 'AR_tax', type => 'checkbox', label => text('Tax'), ${form.AR_tax} => form.AR_tax, - value => 'AR_tax'} ?> + value => 'AR_tax'} ?>
+ 'AR_overpayment', + type => 'checkbox', + label => text('Overpayment'), + ${form.AR_overpayment} => form.AR_overpayment, + value => 'AR_overpayment'} ?> +
- 'AP_amount', type => 'checkbox', label => text('Expense/Asset'), ${form.AP_amount} => form.AP_amount, value => 'AP_amount'} ?>
- 'AP_paid', type => 'checkbox', label => text('Payment'), ${form.AP_paid} => form.AP_paid, value => 'AP_paid'} ?>
- 'AP_tax', type => 'checkbox', label => text('Tax'), ${form.AP_tax} => form.AP_tax, - value => 'AP_tax'} ?> + value => 'AP_tax'} ?>
+ 'AP_overpayment', + type => 'checkbox', + label => text('Overpayment'), + ${form.AP_overpayment} => form.AP_overpayment, + value => 'AP_overpayment'} ?>
- 'IC_sale', type => 'checkbox', label => text('Income'), ${form.IC_sale} => form.IC_sale, value => 'IC_sale'} ?>
- 'IC_cogs', type => 'checkbox', label => text('COGS'), ${form.IC_cogs} => form.IC_cogs, value => 'IC_cogs'} ?>
- 'IC_taxpart', type => 'checkbox', label => text('Tax'), @@ -190,19 +203,19 @@ value => 'IC_taxpart'} ?>
- 'IC_income', type => 'checkbox', label => text('Income'), ${form.IC_income} => form.IC_income, value => 'IC_income'} ?>
- 'IC_expense', type => 'checkbox', label => text('Expense'), ${form.IC_expense} => form.IC_expense, value => 'IC_expense'} ?>
- 'IC_taxservice', type => 'checkbox', label => text('Tax'), @@ -217,7 +230,7 @@
'gifi_accno', size => '9', value => form.gifi_accno} ?>

'hidden', name => hidden, value => hiddens.item(hidden) }; END ?> - + diff --git a/UI/payments/payment1.html b/UI/payments/payment1.html index d064ad0e..6d2d2216 100644 --- a/UI/payments/payment1.html +++ b/UI/payments/payment1.html @@ -2,7 +2,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <?lsmb titlebar ?> + <?lsmb titlebar -?> @@ -16,46 +16,19 @@
- - - - - - - - - - - - - - - - - - + + + - - - - - - - + -?> +
- - - - - - - + + + + diff --git a/UI/payments/payment2.html b/UI/payments/payment2.html index e1a5964e..335fc778 100644 --- a/UI/payments/payment2.html +++ b/UI/payments/payment2.html @@ -7,11 +7,12 @@ - + - + @@ -19,14 +20,14 @@ INCLUDE input element_data=accountclass ?> -
- -
@@ -78,19 +51,26 @@
- - - +
>= + datefrom.type = "text"; + datefrom.size = "10" ; + datefrom.maxlenght = "10" ; + datefrom.name = "datefrom"; + INCLUDE input element_data=datefrom; + -?> + <= +
+
- - -
+ + +
@@ -35,7 +36,7 @@ - + + + + +
@@ -116,15 +117,14 @@ - @@ -140,7 +140,7 @@ - + @@ -157,9 +157,15 @@ - - + -
: - - - + + + - +
">
-
"> -
+
+ + " + onClick="maximize_minimize('div_topay_', + 'topaystate_' ,this, + 'UI/payments/img/down.gif', 'UI/payments/img/up.gif')"> +
"> @@ -193,25 +199,124 @@
-
- - - + + + + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
X
+ -- + + + + + + + + + +
+ + + + + +
 
 
+ +
+ + + - +
+ + + +
\ No newline at end of file diff --git a/bin/am.pl b/bin/am.pl index a81d2166..b30b4fe2 100644 --- a/bin/am.pl +++ b/bin/am.pl @@ -195,7 +195,7 @@ sub save_account { ) if length $a > 2; for ( - qw(AR_amount AR_tax AR_paid AP_amount AP_tax AP_paid IC_taxpart IC_taxservice IC_sale IC_cogs IC_income IC_expense) + qw(AR_amount AR_tax AR_paid AR_overpayment AP_amount AP_tax AP_paid AP_overpayment IC_taxpart IC_taxservice IC_sale IC_cogs IC_income IC_expense) ) { $form->error( @@ -208,7 +208,7 @@ sub save_account { foreach $item ( "AR", "AP" ) { $i = 0; - for ( "${item}_amount", "${item}_paid", "${item}_tax" ) { + for ( "${item}_amount", "${item}_paid", "${item}_tax", "${item}_overpayment" ) { $i++ if $form->{$_}; } $form->error( diff --git a/scripts/payment.pl b/scripts/payment.pl index af67868f..5b56e1f3 100644 --- a/scripts/payment.pl +++ b/scripts/payment.pl @@ -62,7 +62,7 @@ use strict; =item payment This method is used to set the filter screen and prints it, using the -TT2 system. (hopefully it will... ) +TT2 system. =back @@ -415,11 +415,14 @@ 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'}; +# TODO TODO TODO TODO TODO TODO TODO +($Payment->{entity_id}, $Payment->{company_name}) = split /--/ , $request->{'vendor-customer'}; +# WE NEED TO RETRIEVE A BILLING LOCATION, THIS IS HARDCODED FOR NOW... Should we change it? +$Payment->{location_class_id} = '1'; +#$request->error($Payment->{entity_id}); my @vc_options; - -#@array_options = $Payment->get_vc_info(); -#$request->error($array_options[0]->{name}); +@vc_options = $Payment->get_vc_info(); +# TODO TODO TODO TODO TODO TODO TODO # 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}) { @@ -427,8 +430,10 @@ if ($request->{projects}) { @project = { name => 'projects', text => $project_number.' '.$project_name, value => $request->{projects}}; } # LETS GET THE DEPARTMENT INFO +# WE HAVE TO SET $dbPayment->{department_id} NOW, THIS DATA WILL BE USED LATER WHEN WE +# CALL FOR payment_get_open_invoices. :) if ($request->{department}) { - ($department_id, $department_name) = split /--/, $request->{department}; + ($Payment->{department_id}, $department_name) = split /--/, $request->{department}; @department = { name => 'department', text => $department_name, value => $request->{department}}; } # LETS GET ALL THE ACCOUNTS @@ -491,20 +496,17 @@ my @column_headers = ({text => $locale->text('Invoice')}, text => 1 }; } - - # FINALLY WE ADD TO THE COLUMN HEADERS A LAST FIELD TO PRINT THE CLOSE INVOICE CHECKBOX TRICK :) +# 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. +# WE WONT DO ANYTHING IF WE DONT FIND ANY INVOICES, THE USER CAN STILL POST A PREPAYMENT my @invoice_data; +my @topay_state; # WE WILL USE THIS TO HELP UI TO DETERMINE WHAT IS VISIBLE @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 ... +# LETS SET THE EXCHANGERATE VALUES my $due_fx; my $topay_fx_value; if ("$exchangerate") { $topay_fx_value = $due_fx = "$array_options[$ref]->{due}"/"$exchangerate"; @@ -532,20 +534,47 @@ for my $ref (0 .. $#array_options) { $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. - } - + # Ugly hack, but works ;) ... + }#END HASH };# END PUSH + + push @topay_state, { + id => "topaystate_$array_options[$ref]->{invoice_id}", + value => $request->{"topaystate_$array_options[$ref]->{invoice_id}"} + }; #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").'!'); -} +# And finally, we are going to store the information for the overpayment / prepayment / advanced payment +# and all the stuff, this is only needed for the update function. +my @overpayment; +my @overpayment_account; +# Got to build the account selection box first. +my @overpayment_account = $Payment->list_overpayment_accounting(); +# Now we build the structure for the UI +for (my $i=1 ; $i <= $request->{overpayment_qty}; $i++) { + if (!$request->{"overpayment_checkbox_$i"}) { + if ( $request->{"overpayment_topay_$i"} ) { + # Now we split the account selected options + my ($id, $accno, $description) = split(/--/, $request->{"overpayment_account_$i"}); + + push @overpayment, {amount => $request->{"overpayment_topay_$i"}, + source1 => $request->{"overpayment_source1_$i"}, + source2 => $request->{"overpayment_source2_$i"}, + account => { id => $id, + accno => $accno, + description => $description + } + }; + } else { + $i = $request->{overpayment_qty} + 1; + } + } +} # LETS BUILD THE SELECTION FOR THE UI my $select = { stylesheet => $request->{_user}->{stylesheet}, @@ -577,34 +606,19 @@ my $select = { }, column_headers => \@column_headers, rows => \@invoice_data, + topay_state => \@topay_state, 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'}] + vc => { name => $Payment->{company_name}, # We will assume that the first Billing Information as default + address => [ {text => $vc_options[0]->{'line_one'}}, + {text => $vc_options[0]->{'line_two'}}, + {text => $vc_options[0]->{'line_three'}}, + {text => $vc_options[0]->{city}}, + {text => $vc_options[0]->{state}}, + {text => $vc_options[0]->{country}}] }, - 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 => [ @@ -623,7 +637,9 @@ my $select = { }, exrate => @currency_options, selectedcheckboxes => @selected_checkboxes ? \@selected_checkboxes : '', - notes => $request->{notes} + notes => $request->{notes}, + overpayment => \@overpayment, + overpayment_account => \@overpayment_account }; my $template = LedgerSMB::Template->new( user => $request->{_user}, diff --git a/sql/modules/Payment.sql b/sql/modules/Payment.sql index e5b02f3c..a0a36b3c 100644 --- a/sql/modules/Payment.sql +++ b/sql/modules/Payment.sql @@ -6,16 +6,17 @@ $$ DECLARE out_entity entity%ROWTYPE; BEGIN FOR out_entity IN - SELECT ec.id, e.name, e.entity_class, e.created + SELECT ec.id, cp.legal_name as name, e.entity_class, e.created FROM entity e JOIN entity_credit_account ec ON (ec.entity_id = e.id) + JOIN company cp ON (cp.entity_id = e.id) WHERE ec.entity_class = in_account_class AND CASE WHEN in_account_class = 1 THEN - id IN (SELECT entity_id FROM ap + e.id IN (SELECT entity_id FROM ap WHERE amount <> paid GROUP BY entity_id) WHEN in_account_class = 2 THEN - id IN (SELECT entity_id FROM ar + e.id IN (SELECT entity_id FROM ar WHERE amount <> paid GROUP BY entity_id) END @@ -61,12 +62,19 @@ CREATE TYPE payment_invoice AS ( ); CREATE OR REPLACE FUNCTION payment_get_open_invoices -(in_account_class int, in_entity_credit_id int, in_curr char(3)) +(in_account_class int, + in_entity_credit_id int, + in_curr char(3), + in_datefrom date, + in_dateto date, + in_amountfrom numeric, + in_amountto numeric, + in_department_id int) RETURNS SETOF payment_invoice AS $$ DECLARE payment_inv payment_invoice; BEGIN - FOR payment_inv IN + FOR payment_inv IN SELECT a.id AS invoice_id, a.invnumber, a.transdate AS invoice_date, a.amount, CASE WHEN discount_terms @@ -79,15 +87,16 @@ BEGIN > extract('days' FROM age(a.transdate)) THEN 0 ELSE (a.amount - a.paid) * c.discount / 100 - END AS due + END + AS due FROM (SELECT id, invnumber, transdate, amount, entity_id, 1 as invoice_class, paid, curr, - entity_credit_account + entity_credit_account, department_id FROM ap UNION SELECT id, invnumber, transdate, amount, entity_id, 2 AS invoice_class, paid, curr, - entity_credit_account + entity_credit_account, department_id FROM ar ) a JOIN entity_credit_account c ON (c.id = a.entity_credit_account @@ -97,13 +106,24 @@ BEGIN AND c.entity_class = in_account_class AND a.amount - a.paid <> 0 AND a.curr = in_curr + AND (a.transdate >= in_datefrom + OR in_datefrom IS NULL) + AND (a.transdate <= in_dateto + OR in_dateto IS NULL) + AND (a.amount >= in_amountfrom + OR in_amountfrom IS NULL) + AND (a.amount <= in_amountto + OR in_amountto IS NULL) + AND (a.department_id = in_department_id + OR in_department_id IS NULL) + LOOP RETURN NEXT payment_inv; END LOOP; END; $$ LANGUAGE PLPGSQL; -COMMENT ON FUNCTION payment_get_open_invoices(int, int, char(3)) IS +COMMENT ON FUNCTION payment_get_open_invoices(int, int, char(3), date, date, numeric, numeric) IS $$ This function takes three arguments: Type: 1 for vendor, 2 for customer Entity_id: The entity_id of the customer or vendor @@ -479,8 +499,6 @@ BEGIN END; $$ LANGUAGE PLPGSQL; -- I HAVE TO MAKE A COMMENT ON THIS FUNCTION - - -- Move this to the projects module when we start on that. CT CREATE OR REPLACE FUNCTION project_list_open(in_date date) RETURNS SETOF project AS @@ -566,37 +584,50 @@ $$ language plpgsql; COMMENT ON FUNCTION currency_get_exchangerate(in_currency char(3), in_date date, in_account_class int) IS $$ This function return the exchange rate of a given currency, date and exchange rate class (buy or sell). $$; +-- +-- payment_location_result has the same arch as location_result, except for one field +-- This should be unified on the API when we get things working - David Mora +-- +CREATE TYPE payment_location_result AS ( + id int, + line_one text, + line_two text, + line_three text, + city text, + state text, + country text, + class text +); + -CREATE OR REPLACE FUNCTION payment_get_vc_info(in_entity_id int) -RETURNS SETOF entity AS +-- +-- payment_get_vc_info has the same arch as company__list_locations, except for the filtering capabilities +-- This should be unified on the API when we get things working - David Mora +-- +CREATE OR REPLACE FUNCTION payment_get_vc_info(in_entity_id int, in_location_class_id int) +RETURNS SETOF payment_location_result AS $$ -DECLARE - out_info entity%ROWTYPE; - - BEGIN - FOR out_info IN - - SELECT e.id, e.name FROM entity e - JOIN company c ON (e.id = c.entity_id) - WHERE e.id = in_entity_id - - --SELECT e.id, c.legal_name, l.line_one, l.city_province, cy.name FROM entity e - --JOIN company c ON (e.id = c.entity_id) - --JOIN company_to_location cl ON (c.id = cl.company_id) - --JOIN location l ON (l.id = cl.location_id) - --JOIN country cy ON (cy.id = l.country_id) - LOOP - return next out_info; - END LOOP; - - IF NOT FOUND THEN - RAISE EXCEPTION 'ID % not found', in_entity_id; - END IF; - - END; -$$ language plpgsql; -COMMENT ON FUNCTION payment_get_vc_info(in_entity_id int) IS -$$ This function return vendor or customer info, its under construction $$; +DECLARE out_row RECORD; + BEGIN + FOR out_row IN + SELECT l.id, l.line_one, l.line_two, l.line_three, l.city, + l.state, c.name, lc.class + FROM location l + JOIN company_to_location ctl ON (ctl.location_id = l.id) + JOIN company cp ON (ctl.company_id = cp.id) + JOIN location_class lc ON (ctl.location_class = lc.id) + JOIN country c ON (c.id = l.country_id) + WHERE cp.entity_id = in_entity_id AND + lc.id = in_location_class_id + ORDER BY lc.id, l.id, c.name + LOOP + RETURN NEXT out_row; + END LOOP; + END; +$$ LANGUAGE PLPGSQL; + +COMMENT ON FUNCTION payment_get_vc_info(in_entity_id int, in_location_class_id int) IS +$$ This function returns vendor or customer info $$; CREATE TYPE payment_record AS ( amount numeric, diff --git a/sql/modules/chart.sql b/sql/modules/chart.sql index 53460766..2e136371 100644 --- a/sql/modules/chart.sql +++ b/sql/modules/chart.sql @@ -20,9 +20,9 @@ DECLARE resultrow record; link_string text; BEGIN IF in_account_class = 1 THEN - link_string := '%AR_paid%'; - ELSE link_string := '%AP_paid%'; + ELSE + link_string := '%AR_paid%'; END IF; FOR resultrow IN @@ -58,3 +58,27 @@ $$ LANGUAGE PLPGSQL; COMMENT ON FUNCTION chart_get_ar_ap(in_account_class int) IS $$ This function returns the cash account acording with in_account_class which must be 1 or 2 $$; + +CREATE OR REPLACE FUNCTION chart_list_overpayment(in_account_class int) +RETURNS SETOF chart AS +$$ +DECLARE resultrow record; + link_string text; +BEGIN + IF in_account_class = 1 THEN + link_string := '%AP_overpayment%'; + ELSE + link_string := '%AR_overpayment%'; + END IF; + + FOR resultrow IN + SELECT * FROM chart + WHERE link LIKE link_string + ORDER BY accno + LOOP + return next resultrow; + END LOOP; +END; +$$ language plpgsql; +COMMENT ON FUNCTION chart_list_cash(in_account_class int) IS +$$ This function returns the overpayment accounts acording with in_account_class which must be 1 or 2 $$; -- cgit v1.2.3