summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreinhverfr <einhverfr@4979c152-3d1c-0410-bac9-87ea11338e46>2007-12-20 00:07:59 +0000
committereinhverfr <einhverfr@4979c152-3d1c-0410-bac9-87ea11338e46>2007-12-20 00:07:59 +0000
commit0f9d68697da12477342cc41825737b282a215f32 (patch)
tree4c2eea402e7e3a0800c5fc29a0ed1a65800ac14c
parentde4c93c23b93218ec5feaec2ebb01189f73428a2 (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-xLedgerSMB.pm16
-rw-r--r--LedgerSMB/Batch.pm8
-rw-r--r--LedgerSMB/DBObject/Company.pm3
-rw-r--r--README.sql-ledger3
-rw-r--r--TODO8
-rw-r--r--UI/Contact/contact.html13
-rw-r--r--UI/batch/filter.html2
-rw-r--r--UI/lib/elements.html2
-rw-r--r--UI/payments/check_job.html2
-rw-r--r--UI/payments/payments_detail.html19
-rw-r--r--scripts/vouchers.pl251
-rw-r--r--sql/modules/Company.sql33
-rw-r--r--utils/process_queue/process_queue.pl8
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.
diff --git a/TODO b/TODO
index f6c2e017..f5253e85 100644
--- a/TODO
+++ b/TODO
@@ -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">&nbsp;<?lsmb i.2 ?></td>
<td class="invoice_list">&nbsp;<?lsmb i.1 ?></td>
- <td class="total_due_list">&nbsp;<?lsmb i.3 ?></td>
- <td class="paid_list">&nbsp;<?lsmb i.4 ?></td>
+ <td class="total_due_list">&nbsp;
+ <?lsmb INCLUDE format_money number=i.3 ?></td>
+ <td class="paid_list">&nbsp;
+ <?lsmb INCLUDE format_money number=i.4 ?></td>
<td class="net_due_list">&nbsp;
<?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();
}
}