From: Alex Brelsfoard Date: Thu, 29 Jan 2015 17:40:45 +0000 (-0500) Subject: Merge branch 'master' of git.freeside.biz:/home/git/freeside X-Git-Url: http://git.freeside.biz/gitweb/?a=commitdiff_plain;h=9832a60d3fc60a1c8d7315f0404c4dadd3bd3794;hp=ecc98ec286adeba1290fc6898b39626046ea5eaa;p=freeside.git Merge branch 'master' of git.freeside.biz:/home/git/freeside --- diff --git a/FS/FS/API.pm b/FS/FS/API.pm index 62a97d8f0..629463c37 100644 --- a/FS/FS/API.pm +++ b/FS/FS/API.pm @@ -427,6 +427,119 @@ sub new_customer { =back +=item update_customer + +Updates an existing customer. Takes a hash reference as parameter with the foll$ + +=over 4 + +=item secret + +API Secret + +=item first + +first name (required) + +=item last + +last name (required) + +=item company + +Company name + +=item address1 (required) + +Address line one + +=item city (required) + +City + +=item county + +County + +=item state (required) + +State + +=item zip (required) + +Zip or postal code + +=item country + +2 Digit Country Code + +=item daytime + +Daytime phone number + +=item night + +Evening phone number + +=item fax + +Fax number + +=item mobile + +Mobile number + +=item invoicing_list + +comma-separated list of email addresses for email invoices. The special value '$ +postal_invoicing +Set to 1 to enable postal invoicing + +=item payby + +CARD, DCRD, CHEK, DCHK, LECB, BILL, COMP or PREPAY + +=item payinfo + +Card number for CARD/DCRD, account_number@aba_number for CHEK/DCHK, prepaid "pi$ + +=item paycvv + +Credit card CVV2 number (1.5+ or 1.4.2 with CVV schema patch) + +=item paydate + +Expiration date for CARD/DCRD + +=item payname + +Exact name on credit card for CARD/DCRD, bank name for CHEK/DCHK + +=item referral_custnum + +Referring customer number + +=item salesnum +Sales person number + +=item agentnum + +Agent number + +=cut +sub update_customer { + my( $class, %opt ) = @_; + + my $conf = new FS::Conf; + return { 'error' => 'Incorrect shared secret' } + unless $opt{secret} eq $conf->config('api_shared_secret'); + + FS::cust_main->API_update( %opt ); +} + +=back + + =item customer_info Returns general customer information. Takes a hash reference as parameter with the following keys: custnum and API secret diff --git a/FS/FS/Report/Tax.pm b/FS/FS/Report/Tax.pm index f3f441d21..23c16452e 100644 --- a/FS/FS/Report/Tax.pm +++ b/FS/FS/Report/Tax.pm @@ -41,13 +41,9 @@ sub report_internal { my ($taxname, $country, %breakdown); - # purify taxname properly here, as we're going to include it in lots of - # SQL statements using single quotes only - if ( $opt{taxname} =~ /^([\w\s]+)$/ ) { - $taxname = $1; - } else { - die "taxname required"; # UI prevents this - } + # taxname can contain arbitrary punctuation; escape it properly and + # include $taxname unquoted elsewhere + $taxname = dbh->quote($opt{'taxname'}); if ( $opt{country} =~ /^(\w\w)$/ ) { $country = $1; @@ -103,7 +99,7 @@ sub report_internal { GROUP BY billpkgnum, taxnum"; my $where = "WHERE cust_bill._date >= $beginning AND cust_bill._date <= $ending ". - "AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' ". + "AND COALESCE(cust_main_county.taxname,'Tax') = $taxname ". "AND cust_main_county.country = '$country'"; # SELECT/GROUP clauses for first-level queries my $select = "SELECT "; @@ -370,14 +366,14 @@ sub report_internal { SELECT 1 FROM cust_tax_exempt_pkg JOIN cust_main_county USING (taxnum) WHERE cust_tax_exempt_pkg.billpkgnum = cust_bill_pkg.billpkgnum - AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' + AND COALESCE(cust_main_county.taxname,'Tax') = $taxname AND cust_tax_exempt_pkg.creditbillpkgnum IS NULL ) AND NOT EXISTS( SELECT 1 FROM cust_bill_pkg_tax_location JOIN cust_main_county USING (taxnum) WHERE cust_bill_pkg_tax_location.taxable_billpkgnum = cust_bill_pkg.billpkgnum - AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' + AND COALESCE(cust_main_county.taxname,'Tax') = $taxname ) "; warn "\nOUTSIDE:\n$sql_outside\n" if $DEBUG; diff --git a/FS/FS/cust_main/API.pm b/FS/FS/cust_main/API.pm index 283683b8a..4a09b936a 100644 --- a/FS/FS/cust_main/API.pm +++ b/FS/FS/cust_main/API.pm @@ -3,6 +3,7 @@ package FS::cust_main::API; use strict; use FS::Conf; use FS::part_tag; +use FS::Record qw( qsearchs ); =item API_getinfo FIELD => VALUE, ... @@ -156,4 +157,66 @@ sub API_insert { } +sub API_update { + + my( $class, %opt ) = @_; + + my $conf = new FS::Conf; + + + my $custnum = $opt{'custnum'} + or return { 'error' => "no customer record" }; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + my $new = new FS::cust_main { $cust_main->hash }; + + $new->set( $_ => $opt{$_} ) + foreach grep { exists $opt{$_} } qw( + agentnum salesnum refnum agent_custid referral_custnum + last first company + daytime night fax mobile + payby payinfo paydate paycvv payname + ), + + + my @invoicing_list = $opt{'invoicing_list'} + ? split( /\s*\,\s*/, $opt{'invoicing_list'} ) + : (); + push @invoicing_list, 'POST' if $opt{'postal_invoicing'}; + + my ($bill_hash, $ship_hash); + foreach my $f (FS::cust_main->location_fields) { + # avoid having to change this in front-end code + $bill_hash->{$f} = $opt{"bill_$f"} || $opt{$f}; + $ship_hash->{$f} = $opt{"ship_$f"}; + } + + my $bill_location = FS::cust_location->new($bill_hash); + my $ship_location; + # we don't have an equivalent of the "same" checkbox in selfservice^Wthis API + # so is there a ship address, and if so, is it different from the billing + # address? + if ( length($ship_hash->{address1}) > 0 and + grep { $bill_hash->{$_} ne $ship_hash->{$_} } keys(%$ship_hash) + ) { + + $ship_location = FS::cust_location->new( $ship_hash ); + + } else { + $ship_location = $bill_location; + } + + $new->set('bill_location' => $bill_location); + $new->set('ship_location' => $ship_location); + + my $error = $new->replace( $cust_main, \@invoicing_list ); + return { 'error' => $error } if $error; + + return { 'error' => '', + }; + +} + 1; diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi index 83f2fc5d3..491cd42c5 100644 --- a/httemplate/search/report_tax.cgi +++ b/httemplate/search/report_tax.cgi @@ -151,7 +151,7 @@ TD.rowhead { font-weight: bold; text-align: left; padding: 0px 3px } <% emt('Out of taxable region') %> - + <% $money_sprintf->( $report->{outside } ) %> @@ -188,8 +188,9 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { $agentname = $agent->agentname; } -if ( $cgi->param('taxname') =~ /^([\w ]+)$/ ) { - $params{taxname} = $1; +# allow anything in here; FS::Report::Tax will treat it as unsafe +if ( length($cgi->param('taxname')) ) { + $params{taxname} = $cgi->param('taxname'); } else { die "taxname required"; } diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html index fa193d636..d7644b7de 100644 --- a/httemplate/view/cust_main/packages/services.html +++ b/httemplate/view/cust_main/packages/services.html @@ -97,20 +97,7 @@ function clearhint_search_cust_svc(obj, str) { % local $opt{'num_avail'} = $part_svc->num_avail;
<% svc_provision_link($cust_pkg, $part_svc, \%opt, $curuser) %> % } -% if ( -% qsearch({ -% 'table' => 'did_order', -% 'hashref' => { 'custnum' => $cust_pkg->custnum }, -% 'extra_sql' => ' LIMIT 1' -% }) -% || -% qsearch({ -% 'table' => 'did_order_item', -% 'hashref' => { 'custnum' => $cust_pkg->custnum }, -% 'addl_from' => ' INNER JOIN did_order ON did_order_item.ordernum = did_order.ordernum', -% 'extra_sql' => ' LIMIT 1' -% }) -% ) { +% if (browse_received_did_inventory($cust_pkg->custnum)) {
<% mt('Browse Received DID Inventory') |h %> % } % } @@ -183,6 +170,21 @@ sub svc_provision_link { $link; } +sub browse_received_did_inventory { + local($FS::Record::qsearch_qualify_columns) = 1; + qsearch({ + 'table' => 'did_order', + 'hashref' => { 'custnum' => $_[0] }, + 'extra_sql' => ' LIMIT 1' + }) || + qsearch({ + 'table' => 'did_order_item', + 'hashref' => { 'custnum' => $_[0] }, + 'addl_from' => ' INNER JOIN did_order ON did_order_item.ordernum = did_order.ordernum', + 'extra_sql' => ' LIMIT 1' + }); +} + my %hints = ( svc_acct => emt('(user or email)'), svc_domain => emt('(domain)'),