diff options
author | einhverfr <einhverfr@4979c152-3d1c-0410-bac9-87ea11338e46> | 2007-12-20 00:07:59 +0000 |
---|---|---|
committer | einhverfr <einhverfr@4979c152-3d1c-0410-bac9-87ea11338e46> | 2007-12-20 00:07:59 +0000 |
commit | 0f9d68697da12477342cc41825737b282a215f32 (patch) | |
tree | 4c2eea402e7e3a0800c5fc29a0ed1a65800ac14c | |
parent | de4c93c23b93218ec5feaec2ebb01189f73428a2 (diff) |
More contact, payment, voucher fixes/enhancements
git-svn-id: https://ledger-smb.svn.sourceforge.net/svnroot/ledger-smb/trunk@1984 4979c152-3d1c-0410-bac9-87ea11338e46
-rwxr-xr-x | LedgerSMB.pm | 16 | ||||
-rw-r--r-- | LedgerSMB/Batch.pm | 8 | ||||
-rw-r--r-- | LedgerSMB/DBObject/Company.pm | 3 | ||||
-rw-r--r-- | README.sql-ledger | 3 | ||||
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | UI/Contact/contact.html | 13 | ||||
-rw-r--r-- | UI/batch/filter.html | 2 | ||||
-rw-r--r-- | UI/lib/elements.html | 2 | ||||
-rw-r--r-- | UI/payments/check_job.html | 2 | ||||
-rw-r--r-- | UI/payments/payments_detail.html | 19 | ||||
-rw-r--r-- | scripts/vouchers.pl | 251 | ||||
-rw-r--r-- | sql/modules/Company.sql | 33 | ||||
-rw-r--r-- | utils/process_queue/process_queue.pl | 8 |
13 files changed, 325 insertions, 43 deletions
diff --git a/LedgerSMB.pm b/LedgerSMB.pm index 30c3b2b8..9a38149d 100755 --- a/LedgerSMB.pm +++ b/LedgerSMB.pm @@ -276,7 +276,7 @@ sub escape { my $regex = qr/([^a-zA-Z0-9_.-])/; $str =~ s/$regex/sprintf("%%%02x", ord($1))/ge; - $str; + return $str; } sub is_blank { @@ -471,7 +471,7 @@ sub format_amount { sub parse_amount { my $self = shift @_; my %args = @_; - my $myconfig = $args{user}; + my $myconfig = $args{user} || $self->{_user}; my $amount = $args{amount}; if ( $amount eq '' or ! defined $amount) { @@ -809,6 +809,18 @@ sub remove_cgi_globals { } } } + +sub take_top_level { + my ($self) = @_; + my $return_hash = {}; + for my $key (keys %$self){ + if (!ref($self->{$key}) && $key !~ /^\./){ + $return_hash->{$key} = $self->{$key} + } + } + return $return_hash; +} + 1; diff --git a/LedgerSMB/Batch.pm b/LedgerSMB/Batch.pm index 67bc0ad9..a09031cd 100644 --- a/LedgerSMB/Batch.pm +++ b/LedgerSMB/Batch.pm @@ -31,13 +31,21 @@ sub get_search_results { sub post { my ($self) = @_; ($self->{post_return_ref}) = $self->exec_method(funcname => 'batch_post'); + $self->{dbh}->commit; return $self->{post_return_ref}; } sub delete { my ($self) = @_; ($self->{delete_ref}) = $self->exec_method(funcname => 'batch_delete'); + $self->{dbh}->commit; return $self->{delete_ref}; } +sub list_vouchers { + my ($self) = @_; + @{$self->{vouchers}} = $self->exec_method(funcname => 'voucher_list'); + return @{$self->{vouchers}}; +} + 1; diff --git a/LedgerSMB/DBObject/Company.pm b/LedgerSMB/DBObject/Company.pm index 13b9ff65..0e56567b 100644 --- a/LedgerSMB/DBObject/Company.pm +++ b/LedgerSMB/DBObject/Company.pm @@ -14,8 +14,10 @@ sub set_entity_class { sub save { my $self = shift @_; $self->set_entity_class(); + $self->{threshold} = $self->parse_amount(amount => $self->{threshold}); my ($ref) = $self->exec_method(funcname => 'entity_credit_save'); $self->{entity_id} = $ref->{entity_credit_save}; + $self->{threshold} = $self->format_amount(amount => $self->{threshold}); $self->{dbh}->commit; } @@ -88,6 +90,7 @@ sub get { $self->set_entity_class(); my ($ref) = $self->exec_method(funcname => 'entity__retrieve_credit'); $self->merge($ref); + $self->{threshold} = $self->format_amount(amount => $self->{threshold}); $self->{name} = $self->{legal_name}; diff --git a/README.sql-ledger b/README.sql-ledger index c29d8410..1c68f0ca 100644 --- a/README.sql-ledger +++ b/README.sql-ledger @@ -12,4 +12,5 @@ a working LedgerSMB installation. The database will be updated on first login. -You will also want to migrate your configuration by running the SL2LS.pl script included in this directory. +You will also want to migrate your configuration by running the SL2LS.pl script +included in this directory. @@ -3,12 +3,6 @@ For 1.3: 1) Refactor admin.pl. Merge user management with main UI and create separate dataset management interface. (in progress, Chris) -2) Add real security enforcement (in progress, Chris, part of admin reworking) +2) Setup wizard. -3) Refactor contact management code - -4) Setup wizard. - -Additional prerequisites include: -1) Refactoring HR code. (In progress, Chris) diff --git a/UI/Contact/contact.html b/UI/Contact/contact.html index 3a8d27b3..311660b8 100644 --- a/UI/Contact/contact.html +++ b/UI/Contact/contact.html @@ -152,6 +152,11 @@ problems with multi-word single-quoted constructs in PI tags. -CT --> value = entity_id } ?> <?lsmb PROCESS input element_data = { + type = "hidden" + name = "account_class" + value = account_class + } ?> + <?lsmb PROCESS input element_data = { label = text('Name:'), type= "text", name = "name", @@ -289,6 +294,14 @@ problems with multi-word single-quoted constructs in PI tags. -CT --> label = text('Business Type:') #' } ?> </td> + <td> <?lsmb INCLUDE input element_data = { + name = "threshold" + value = threshold + type = "text" + size = "20" + label = text('Threshold') + class = "numeric" + } ?> </tr> </table> diff --git a/UI/batch/filter.html b/UI/batch/filter.html index 3cb69089..87c1d847 100644 --- a/UI/batch/filter.html +++ b/UI/batch/filter.html @@ -30,7 +30,7 @@ options = batch_users value_attr = "entity_id" text_attr = "username" - name = "created_by" + name = "created_by_eid" default_values = [created_by] } ?></div> <div class="input" id="description_div"> diff --git a/UI/lib/elements.html b/UI/lib/elements.html index 4345e7ee..e22bd026 100644 --- a/UI/lib/elements.html +++ b/UI/lib/elements.html @@ -156,7 +156,7 @@ <?lsmb IF element_data.defined('text_attr'); option_data.text = option_data.$text_attr; END ?> - <?lsmb # Selected is a special case -- no attribute key, so it is handled here by looking for the option value in the default_values key. + <?lsmb # Selected is a special case -- no attribute key, so it is handled here by looking for the option value in the default_values list. IF element_data.defined('default_values') AND element_data.default_values.grep("^${option_data.value}$").size; option_data.selected = ' selected="selected"'; ELSE; diff --git a/UI/payments/check_job.html b/UI/payments/check_job.html index b59caeab..455a9934 100644 --- a/UI/payments/check_job.html +++ b/UI/payments/check_job.html @@ -25,10 +25,12 @@ ELSE; text('Job Failed'); END ?></div> + <?lsmb IF ! job.success ?> <div class="info"> <?lsmb text('Error:') ?><br /> <?lsmb job.error_condition ?> </div> + <?lsmb END # if ! job.success ?> <?lsmb END # if job.completed ?> </body> </html> diff --git a/UI/payments/payments_detail.html b/UI/payments/payments_detail.html index bd41fcd2..1e75c603 100644 --- a/UI/payments/payments_detail.html +++ b/UI/payments/payments_detail.html @@ -13,6 +13,11 @@ <?lsmb payment_type = (account_class == 1) ? text('Payments') : text('Receipts') ?> <body id="payment_2_body"> +<!-- CT: This template produces invalid XHTML due to the use of nested tables. + Because nested tables are widely used (perhaps improperly) for layout, + most browsers should have no issues with them. Furthermore, I cannot find + any cleaner solution to embedding tabular data within tabular data than + this --> <div class="listtop"><?lsmb payment_type ?></div> <form name="pay_dues" method="post" action="payment.pl"> <!-- Moving all hidden variables to the top. -CT --> @@ -177,7 +182,11 @@ } ?> <?lsmb r.account_number ?> </td> - <td class="entity_name"><?lsmb r.contact_name ?></td> + <td class="entity_name"><span class="<?lsmb + IF r.has_vouchers; 'name_has_vouchers' ; + ELSE ; 'name_has_no_vouchers' ; + END + ?>"><?lsmb r.contact_name ?></span></td> <td class="invoice"><?lsmb r.total_due ?> <?lsmb currency ?></td> <td class="payment"> <?lsmb INCLUDE input element_data = { @@ -223,8 +232,10 @@ <tr> <td class="invoice_date_list"> <?lsmb i.2 ?></td> <td class="invoice_list"> <?lsmb i.1 ?></td> - <td class="total_due_list"> <?lsmb i.3 ?></td> - <td class="paid_list"> <?lsmb i.4 ?></td> + <td class="total_due_list"> + <?lsmb INCLUDE format_money number=i.3 ?></td> + <td class="paid_list"> + <?lsmb INCLUDE format_money number=i.4 ?></td> <td class="net_due_list"> <?lsmb INCLUDE format_money number= i.6 ?> <?lsmb currency ?></td> @@ -249,7 +260,7 @@ <?lsmb INCLUDE input element_data = { type = "hidden" name = "net_$i.0" - value = i.6 + value = ${"payment_$r.contact_id_$i.0"} } ?> </td> </tr> diff --git a/scripts/vouchers.pl b/scripts/vouchers.pl index f8474556..4a3c1129 100644 --- a/scripts/vouchers.pl +++ b/scripts/vouchers.pl @@ -29,6 +29,15 @@ sub create_batch { } sub create_vouchers { + my ($request) = shift @_; + my $batch = LedgerSMB::Batch->new({base => $request}); + $batch->{batch_class} = $request->{batch_type}; + $batch->create; + add_vouchers($batch); +} + + +sub add_vouchers { # This function is not safe for caching as long as the scripts are in bin. # This is because these scripts import all functions into the *current* # namespace. People using fastcgi and modperl should *not* cache this @@ -36,11 +45,7 @@ sub create_vouchers { # Also-- request is in 'our' scope here due to the redirect logic. our ($request) = shift @_; use LedgerSMB::Form; - my $batch = LedgerSMB::Batch->new({base => $request}); - $batch->{batch_class} = $request->{batch_type}; - $batch->create; - our $vouchers_dispatch = { payable => {script => 'bin/ap.pl', function => sub {add()}}, @@ -61,8 +66,6 @@ sub create_vouchers { }; - # Note that the line below is generally considered incredibly bad form. - # However, the code we are including is going to require it for now. -- CT our $form = new Form; our $locale = $request->{_locale}; @@ -84,10 +87,13 @@ sub create_vouchers { $form->{script} =~ s|.*/||; if ($script =~ /^bin/){ + # Note that the line below is generally considered incredibly bad form. + # However, the code we are including is going to require it for now. + # -- CT { no strict; no warnings 'redefine'; do $script; } } elsif ($script =~ /scripts/) { - + # Maybe we should move this to a require statement? --CT { do $script } } @@ -95,19 +101,242 @@ sub create_vouchers { $vouchers_dispatch->{$request->{batch_type}}{function}($request); } +sub search_batch { + my ($request) = @_; + my $batch_request = LedgerSMB::Batch->new(base => $request); + $batch_request->get_search_criteria(); + my $template = LedgerSMB::Template->new( + user => $request->{_user}, + locale => $request->{_locale}, + path => 'UI/batch', + template => 'filter', + format => 'HTML', + ); + $template->render($batch_request); +} + +sub list_batches { + my ($request) = @_; + my $batch = LedgerSMB::Batch->new(base => $request); + my @search_results = $batch->get_search_results; + $batch->{script} = "vouchers.pl"; + + my @columns = + qw(select id control_code description transaction_total payment_total); + + my $base_href = "vouchers.pl"; + my $search_href = "$base_href?action=list_batches"; + my $batch_href = "$base_href?action=get_batch"; + + for my $key ( + qw(class_id approved created_by description amount_gt amount_lt) + ){ + $search_href .= "&$key=$batch->{key}"; + } + + my %column_heading = ( + 'select' => $batch->{_locale}->text('Select'), + transaction_total => { + text => $batch->{_locale}->text('AR/AP/GL Total'), + href => "$search_href&order_by=transaction_total" + }, + payment_total => { + text => $batch->{_locale}->text('Paid/Received Total'), + href => "$search_href&order_by=payment_total" + }, + description => { + text => $batch->{_locale}->text('Description'), + href => "$search_href&order_by=description" + }, + control_code => { + text => $batch->{_locale}->text('Batch Number'), + href => "$search_href&order_by=control_code" + }, + id => { + text => $batch->{_locale}->text('ID'), + href => "$search_href&order_by=control_code" + }, + ); + my $count = 0; + my @rows; + for my $result (@search_results){ + ++$count; + $batch->{"row_$count"} = $result->{id}; + push @rows, { + 'select' => { + input => { + type => 'checkbox', + value => 1, + name => "batch_$result->{id}" + } + }, + transaction_total => $batch->format_amount( + amount => $result->{transaction_total} + ), + payment_total => $batch->format_amount ( + amount => $result->{payment_total} + ), + description => $result->{description}, + control_code => { + text => $result->{control_code}, + href => "$batch_href&batch_id=$result->{id}", + + }, + id => $result->{id}, + }; + } + $batch->{rowcount} = $count; + my $template = LedgerSMB::Template->new( + user => $request->{_user}, + locale => $request->{_locale}, + path => 'UI', + template => 'form-dynatable', + format => ($batch->{format}) ? $batch->{format} : 'HTML', + ); + + my $hiddens = $batch->take_top_level(); + $batch->{rowcount} = "$count"; + delete $batch->{search_results}; + + $template->render({ + form => $batch, + columns => \@columns, + heading => \%column_heading, + rows => \@rows, + hiddens => $hiddens, + buttons => [{ + name => 'action', + type => 'submit', + text => $request->{_locale}->text('Post'), + value => 'batch_approve', + class => 'submit', + },{ + name => 'action', + type => 'submit', + text => $request->{_locale}->text('Delete'), + value => 'batch_delete', + class => 'submit', + }] + }); + +} + sub get_batch { + my ($request) = @_; + my $batch = LedgerSMB::Batch->new(base => $request); + my $rows = []; + + $batch->{id} ||= $batch->{batch_id}; + # $batch->get; + my @vouchers = $batch->list_vouchers; + + my $base_href = "vouchers.pl?action=get_batch&batch_id=$batch->{batch_id}"; + + my @columns = qw(id description batch_class reference amount date); + my $heading = { + id => { + text => $request->{_locale}->text('ID'), + href => "$base_href&order_by=id" + }, + description => { + href => "$base_href&order_by=description", + text => $request->{_locale}->text('Description'), + }, + batch_class => { + text => $request->{_locale}->text('Class'), + href => "$base_href&order_by=class" + }, + amount => { + text => $request->{_locale}->text('Amount'), + href => "$base_href&order_by=amount" + }, + reference => { + text => $request->{_locale}->text('Source/Reference'), + href => "$base_href&order_by=reference" + }, + date => { + text => $request->{_locale}->text('Date'), + href => "$base_href&order_by=date" + } + }; + + my $classcount; + + for my $row (@vouchers) { + $classcount = ($classcount + 1) % 2; + $classcount ||= 0; + push @$rows, { + description => $row->{description}, + id => $row->{id}, + batch_class => $row->{batch_class}, + amount => $batch->format_amount(amount => $row->{amount}), + date => $row->{transaction_date}, + reference => $row->{reference}, + class => "listrow$classcount" + + }; + } + $batch->{title} = "Batch ID: $batch->{batch_id}"; + my $template = LedgerSMB::Template->new( + user => $request->{_user}, + locale => $request->{_locale}, + path => 'UI', + template => 'form-dynatable', + format => ($batch->{format}) ? $batch->{format} : 'HTML', + ); + my $hiddens = $batch->take_top_level(); + $template->render({ + form => $batch, + columns => \@columns, + heading => $heading, + rows => $rows, + hiddens => $hiddens, + buttons => [{ + name => 'action', + type => 'submit', + text => $request->{_locale}->text('Post'), + value => 'batch_approve', + class => 'submit', + },{ + name => 'action', + type => 'submit', + text => $request->{_locale}->text('Delete'), + value => 'batch_delete', + class => 'submit', + }] + }); + + } -sub list_vouchers { +sub list_batches_batch_delete { + batch_delete(@_); } -sub add_vouchers { +sub list_batches_batch_approve { + batch_approve(@_); } -sub approve_batch { +sub batch_approve { + my ($request) = @_; + my $batch = LedgerSMB::Batch->new(base => $request); + for my $count (1 .. $batch->{rowcount}){ + next unless $batch->{"batch_" . $batch->{"row_$count"}}; + $batch->{batch_id} = $batch->{"row_$count"}; + $batch->post; + } + search_batch($request); } -sub delete_batch { +sub batch_delete { + my ($request) = @_; + my $batch = LedgerSMB::Batch->new(base => $request); + for my $count (1 .. $batch->{rowcount}){ + next unless $batch->{"batch_" . $batch->{"row_$count"}}; + $batch->{batch_id} = $batch->{"row_$count"}; + $batch->delete; + } + search_batch($request); } eval { do "scripts/custom/Voucher.pl"}; diff --git a/sql/modules/Company.sql b/sql/modules/Company.sql index cac1a5ac..ff2795af 100644 --- a/sql/modules/Company.sql +++ b/sql/modules/Company.sql @@ -126,7 +126,10 @@ CREATE TYPE entity_credit_search_return AS ( pricegroup_id int, curr char(3), startdate date, - enddate date + enddate date, + ar_ap_account_id int, + cash_account_id int, + threshold numeric ); COMMENT ON TYPE entity_credit_search_return IS @@ -142,7 +145,8 @@ BEGIN SELECT c.legal_name, c.id, e.id, ec.entity_class, ec.discount, ec.taxincluded, ec.creditlimit, ec.terms, ec.meta_number, ec.business_id, ec.language_code, ec.pricegroup_id, - ec.curr::char(3), ec.startdate, ec.enddate + ec.curr::char(3), ec.startdate, ec.enddate, ec.ar_ap_account_id, + ec.cash_account_id, ec.threshold INTO out_row FROM company c JOIN entity e ON (c.entity_id = e.id) @@ -166,7 +170,9 @@ CREATE OR REPLACE FUNCTION entity_credit_save ( in_curr char, in_startdate date, in_enddate date, in_notes text, in_name text, in_tax_id TEXT, - in_threshold NUMERIC + in_threshold NUMERIC, + in_ar_ap_account_id int, + in_cash_account_id int ) returns INT as $$ @@ -178,7 +184,7 @@ CREATE OR REPLACE FUNCTION entity_credit_save ( BEGIN -- TODO: Move every table to an upsert mode independantly. - SELECT INTO v_row * FROM company WHERE id = in_id; + SELECT INTO v_row * FROM company WHERE legal_name = in_name; IF NOT FOUND THEN -- do some inserts @@ -209,7 +215,9 @@ CREATE OR REPLACE FUNCTION entity_credit_save ( startdate, enddate, discount_terms, - threshold + threshold, + ar_ap_account_id, + cash_account_id ) VALUES ( new_entity_id, @@ -226,7 +234,9 @@ CREATE OR REPLACE FUNCTION entity_credit_save ( in_startdate, in_enddate, in_discount_terms, - in_threshold + in_threshold, + in_ar_ap_account_id, + in_cash_account_id ); -- entity note class insert into entity_note (note_class, note, ref_key, vector) VALUES ( @@ -236,12 +246,14 @@ CREATE OR REPLACE FUNCTION entity_credit_save ( ELSIF FOUND THEN - update company set tax_id = in_tax_id where id = in_id; + update company set tax_id = in_tax_id where id = v_row.id; update entity_credit_account SET discount = in_discount, taxincluded = in_taxincluded, creditlimit = in_creditlimit, terms = in_terms, + ar_ap_account_id = in_ar_ap_account_id, + cash_account_id = in_cash_account_id, meta_number = in_meta_number, business_id = in_business_id, language_code = in_language, @@ -253,12 +265,7 @@ CREATE OR REPLACE FUNCTION entity_credit_save ( discount_terms = in_discount_terms where entity_id = v_row.entity_id; - - UPDATE entity_note SET - note = in_note - WHERE ref_key = v_row.entity_id; - return in_id; - + return v_row.entity_id; END IF; END; diff --git a/utils/process_queue/process_queue.pl b/utils/process_queue/process_queue.pl index 28401eb6..5bcc24ca 100644 --- a/utils/process_queue/process_queue.pl +++ b/utils/process_queue/process_queue.pl @@ -28,19 +28,20 @@ sub on_notify { my $job_id = 1; while ($job_id){ ($job_id) = $dbh->selectrow_array( - "SELECT min(id) from pending_job + "SELECT id from pending_job WHERE completed_at IS NULL + ORDER BY id LIMIT 1 FOR UPDATE" ); if ($job_id){ $job_id = $dbh->quote($job_id); my ($job_class) = $dbh->selectrow_array( "select class from batch_class where id = - (select batch_class from pending_job where id = $job_id" + (select batch_class from pending_job where id = $job_id)" ); # Right now, we assume that every pending job has a batch id. # Longer-run we may need to use a template handle as well. -CT - $dbh->execute('SELECT ' . + $dbh->do('SELECT ' . $dbh->quote_identifier("job__process_$job_class") . "($job_id)" ); my $errstr = $dbh->errstr; @@ -60,6 +61,7 @@ sub on_notify { # The line below is necessary because the job process functions # use set session authorization so one must reconnect to reset # administrative permissions. -CT + $dbh->disconnect; $dbh = db_init(); } } |