diff options
256 files changed, 1934 insertions, 10463 deletions
@@ -272,10 +272,6 @@ L<FS::cust_class> - Customer classification class L<FS::cust_category> - Customer category class -L<FS::cust_tag> - Customer tag class - -L<FS::part_tag> - Tag definition class - L<FS::cust_main_exemption> - Customer tax exemption class L<FS::cust_main_note> - Customer note class @@ -354,9 +350,7 @@ L<FS::queue_arg> - Job arguments L<FS::queue_depend> - Job dependencies -L<FS::msg_template> - Message templates (customer notices) - -L<FS::msgcat> - Message catalogs (error messages) +L<FS::msgcat> - Message catalogs L<FS::clientapi_session> diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm index 92c4d2299..08d31d263 100644 --- a/FS/FS/AccessRight.pm +++ b/FS/FS/AccessRight.pm @@ -108,7 +108,6 @@ tie my %rights, 'Tie::IxHash', 'View customer', #'View Customer | View tickets', 'Edit customer', - 'Edit customer tags', 'Edit referring customer', 'View customer history', 'Cancel customer', @@ -116,7 +115,6 @@ tie my %rights, 'Tie::IxHash', { rightname=>'Delete customer', desc=>"Enable customer deletions. Be very careful! Deleting a customer will remove all traces that this customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customer's packages if they cancel service." }, #aka. deletecustomers 'Bill customer now', #NEW 'Bulk send customer notices', #NEW - { rightname=>'View customers of all agents', global=>1 }, ], ### @@ -251,8 +249,6 @@ tie my %rights, 'Tie::IxHash', 'Billing event reports', 'Receivables report', 'Financial reports', - - #{ rightname => 'List customers of all agents', global=>1 }, ], ### @@ -289,9 +285,6 @@ tie my %rights, 'Tie::IxHash', 'Edit billing events', { rightname=>'Edit global billing events', global=>1 }, - 'Edit templates', - { rightname=>'Edit global templates', global=>1 }, - 'Edit inventory', { rightname=>'Edit global inventory', global=>1 }, @@ -301,9 +294,6 @@ tie my %rights, 'Tie::IxHash', { rightname=>'Broadband configuration' }, { rightname=>'Broadband global configuration', global=>1 }, - #{ rightname=>'Edit employees', global=>1, }, - #{ rightname=>'Edit employee groupss', global=>1, }, - { rightname=>'Configuration', global=>1 }, #most of the rest of the configuraiton is not agent-virtualized { rightname=>'Configuration download', }, #description of how it affects diff --git a/FS/FS/CGI.pm b/FS/FS/CGI.pm index 945478475..f33a718fa 100644 --- a/FS/FS/CGI.pm +++ b/FS/FS/CGI.pm @@ -227,15 +227,9 @@ sub popurl { =cut sub rooturl { - my $url_string; - if ( scalar(@_) ) { - $url_string = shift; - } else { - # better to start with the client-provided URL - my $cgi = &FS::UID::cgi; - $url_string = $cgi->isa('Apache') ? $cgi->uri : $cgi->url; - } - + # better to start with the client-provided URL + my $cgi = &FS::UID::cgi; + my $url_string = $cgi->isa('Apache') ? $cgi->uri : $cgi->url; $url_string =~ s/\?.*//; #even though this is kludgy diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 8003613e7..71fe75261 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -632,7 +632,7 @@ sub process_payment { validate($payinfo) or return { 'error' => gettext('invalid_card') }; # . ": ". $self->payinfo return { 'error' => gettext('unknown_card_type') } - if $payinfo !~ /^99\d{14}$/ && cardtype($payinfo) eq "Unknown"; + if cardtype($payinfo) eq "Unknown"; if ( length($p->{'paycvv'}) && $p->{'paycvv'} !~ /^\s*$/ ) { if ( cardtype($payinfo) eq 'American Express card' ) { @@ -683,7 +683,7 @@ sub process_payment { stateid stateid_state ); $new->set( 'payby' => $p->{'auto'} ? 'CHEK' : 'DCHK' ); } - $new->set( 'payinfo' => $cust_main->card_token || $payinfo ); + $new->set( 'payinfo' => $payinfo ); $new->set( 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01' ); my $error = $new->replace($cust_main); if ( $error ) { @@ -1344,7 +1344,7 @@ sub _do_bop_realtime { my $bill_error = $cust_main->bill || $cust_main->apply_payments_and_credits - || $cust_main->realtime_collect; + || $cust_main->collect('realtime' => 1); if ( $cust_main->balance > $old_balance && $cust_main->balance > 0 diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm index 5d70325d2..b9cd6c69f 100644 --- a/FS/FS/ClientAPI/Signup.pm +++ b/FS/FS/ClientAPI/Signup.pm @@ -649,10 +649,14 @@ sub new_customer { # " new customer: $bill_error" # if $bill_error; - $bill_error = $cust_main->realtime_collect( - method => FS::payby->payby2bop( $packet->{payby} ), - depend_jobnum => $placeholder->jobnum, - ); + if ($cust_main->_new_bop_required()) { + $bill_error = $cust_main->realtime_collect( + method => FS::payby->payby2bop( $packet->{payby} ), + depend_jobnum => $placeholder->jobnum, + ); + } else { + $bill_error = $cust_main->collect('realtime' => 1); + } #warn "[fs_signup_server] error collecting from new customer: $bill_error" # if $bill_error; diff --git a/FS/FS/ClientAPI_XMLRPC.pm b/FS/FS/ClientAPI_XMLRPC.pm deleted file mode 100644 index 138ad06a4..000000000 --- a/FS/FS/ClientAPI_XMLRPC.pm +++ /dev/null @@ -1,146 +0,0 @@ -package FS::ClientAPI_XMLRPC; - -=head1 NAME - -FS::ClientAPI_XMLRPC - Freeside XMLRPC accessible self-service API, on the backend - -=head1 SYNOPSIS - -This module implements the self-service API offered by xmlrpc.cgi and friends, -but on a backend machine. - -=head1 DESCRIPTION - -Use this API to implement your own client "self-service" module vi XMLRPC. - -Each routine described in L<FS::SelfService> is available vi XMLRPC as the -method FS.SelfService.XMLRPC.B<method>. All values are passed to the -selfservice-server in a struct of strings. The return values are in a -struct as strings, arrays, or structs as appropriate for the values -described in L<FS::SelfService>. - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::SelfService::XMLRPC>, L<FS::SelfService> - -=cut - -use strict; - -use vars qw($DEBUG $AUTOLOAD); -use FS::ClientAPI; - -$DEBUG = 0; -$FS::ClientAPI::DEBUG = $DEBUG; - -sub AUTOLOAD { - my $call = $AUTOLOAD; - $call =~ s/^FS::(SelfService::|ClientAPI_)XMLRPC:://; - - warn "FS::ClientAPI_XMLRPC::AUTOLOAD $call\n" if $DEBUG; - - my $autoload = &ss2clientapi; - - if (exists($autoload->{$call})) { - shift; #discard package name; - #$call = "FS::SelfService::$call"; - #no strict 'refs'; - #&{$call}(@_); - #FS::ClientAPI->dispatch($autoload->{$call}, @_); - FS::ClientAPI->dispatch($autoload->{$call}, { @_ } ); - }else{ - die "No such procedure: $call"; - } -} - -#terrible false laziness w/SelfService.pm -# - fix at build time, by including some file in both selfserv and backend libs? -# - or fix at runtime, by having selfservice client ask server for the list? -sub ss2clientapi { - { - 'passwd' => 'passwd/passwd', - 'chfn' => 'passwd/passwd', - 'chsh' => 'passwd/passwd', - 'login_info' => 'MyAccount/login_info', - 'login' => 'MyAccount/login', - 'logout' => 'MyAccount/logout', - 'customer_info' => 'MyAccount/customer_info', - 'edit_info' => 'MyAccount/edit_info', #add to ss cgi! - 'invoice' => 'MyAccount/invoice', - 'invoice_logo' => 'MyAccount/invoice_logo', - 'list_invoices' => 'MyAccount/list_invoices', #? - 'cancel' => 'MyAccount/cancel', #add to ss cgi! - 'payment_info' => 'MyAccount/payment_info', - 'payment_info_renew_info' => 'MyAccount/payment_info_renew_info', - 'process_payment' => 'MyAccount/process_payment', - 'process_payment_order_pkg' => 'MyAccount/process_payment_order_pkg', - 'process_payment_change_pkg' => 'MyAccount/process_payment_change_pkg', - 'process_payment_order_renew' => 'MyAccount/process_payment_order_renew', - 'process_prepay' => 'MyAccount/process_prepay', - 'realtime_collect' => 'MyAccount/realtime_collect', - 'list_pkgs' => 'MyAccount/list_pkgs', #add to ss (added?) - 'list_svcs' => 'MyAccount/list_svcs', #add to ss (added?) - 'list_svc_usage' => 'MyAccount/list_svc_usage', - 'list_cdr_usage' => 'MyAccount/list_cdr_usage', - 'list_support_usage' => 'MyAccount/list_support_usage', - 'order_pkg' => 'MyAccount/order_pkg', #add to ss cgi! - 'change_pkg' => 'MyAccount/change_pkg', - 'order_recharge' => 'MyAccount/order_recharge', - 'renew_info' => 'MyAccount/renew_info', - 'order_renew' => 'MyAccount/order_renew', - 'cancel_pkg' => 'MyAccount/cancel_pkg', #add to ss cgi! - 'charge' => 'MyAccount/charge', #? - 'part_svc_info' => 'MyAccount/part_svc_info', - 'provision_acct' => 'MyAccount/provision_acct', - 'provision_external' => 'MyAccount/provision_external', - 'unprovision_svc' => 'MyAccount/unprovision_svc', - 'myaccount_passwd' => 'MyAccount/myaccount_passwd', - 'create_ticket' => 'MyAccount/create_ticket', - 'signup_info' => 'Signup/signup_info', - 'skin_info' => 'MyAccount/skin_info', - 'access_info' => 'MyAccount/access_info', - 'domain_select_hash' => 'Signup/domain_select_hash', # expose? - 'new_customer' => 'Signup/new_customer', - 'capture_payment' => 'Signup/capture_payment', - 'agent_login' => 'Agent/agent_login', - 'agent_logout' => 'Agent/agent_logout', - 'agent_info' => 'Agent/agent_info', - 'agent_list_customers' => 'Agent/agent_list_customers', - 'mason_comp' => 'MasonComponent/mason_comp', - 'call_time' => 'PrepaidPhone/call_time', - 'call_time_nanpa' => 'PrepaidPhone/call_time_nanpa', - 'phonenum_balance' => 'PrepaidPhone/phonenum_balance', - 'bulk_processrow' => 'Bulk/processrow', - 'check_username' => 'Bulk/check_username', - #sg - 'ping' => 'SGNG/ping', - 'decompify_pkgs' => 'SGNG/decompify_pkgs', - 'previous_payment_info' => 'SGNG/previous_payment_info', - 'previous_payment_info_renew_info' - => 'SGNG/previous_payment_info_renew_info', - 'previous_process_payment' => 'SGNG/previous_process_payment', - 'previous_process_payment_order_pkg' - => 'SGNG/previous_process_payment_order_pkg', - 'previous_process_payment_change_pkg' - => 'SGNG/previous_process_payment_change_pkg', - 'previous_process_payment_order_renew' - => 'SGNG/previous_process_payment_order_renew', - }; -} - - -#XXX submit patch to SOAP::Lite - -use XMLRPC::Transport::HTTP; - -package XMLRPC::Transport::HTTP::Server; - -@XMLRPC::Transport::HTTP::Server::ISA = qw(SOAP::Transport::HTTP::Server); - -sub initialize; *initialize = \&XMLRPC::Server::initialize; -sub make_fault; *make_fault = \&XMLRPC::Transport::HTTP::CGI::make_fault; -sub make_response; *make_response = \&XMLRPC::Transport::HTTP::CGI::make_response; - -1; diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index ce8bd296e..a1ee23c19 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -549,36 +549,21 @@ worry that config_items is freeside-specific and icky. "Solo", ); -@base_items = qw( -invoice_template -invoice_latex -invoice_latexreturnaddress -invoice_latexfooter -invoice_latexsmallfooter -invoice_latexnotes -invoice_latexcoupon -invoice_html -invoice_htmlreturnaddress -invoice_htmlfooter -invoice_htmlnotes -logo.png -logo.eps -); - -my %msg_template_options = ( - 'type' => 'select-sub', - 'options_sub' => sub { require FS::Record; - require FS::agent; - require FS::msg_template; - map { $_->msgnum, $_->msgname } - qsearch('msg_template', { disabled => '' }); - }, - 'option_sub' => sub { require FS::msg_template; - my $msg_template = FS::msg_template->by_key(shift); - $msg_template ? $msg_template->msgname : '' - }, -); - +@base_items = qw ( + invoice_template + invoice_latex + invoice_latexreturnaddress + invoice_latexfooter + invoice_latexsmallfooter + invoice_latexnotes + invoice_latexcoupon + invoice_html + invoice_htmlreturnaddress + invoice_htmlfooter + invoice_htmlnotes + logo.png + logo.eps + ); #Billing (81 items) #Invoicing (50 items) @@ -587,6 +572,7 @@ my %msg_template_options = ( #... #Unclassified (77 items) + @config_items = map { new FS::ConfItem $_ } ( { @@ -598,7 +584,7 @@ my %msg_template_options = ( { 'key' => 'alert_expiration', - 'section' => 'notification', + 'section' => 'billing', 'description' => 'Enable alerts about billing method expiration (i.e. expiring credit cards).', 'type' => 'checkbox', 'per_agent' => 1, @@ -606,18 +592,11 @@ my %msg_template_options = ( { 'key' => 'alerter_template', - 'section' => 'deprecated', - 'description' => 'Template file for billing method expiration alerts (i.e. expiring credit cards).', + 'section' => 'billing', + 'description' => 'Template file for billing method expiration alerts (i.e. expiring credit cards). See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Credit_cards_and_Electronic_checks">billing documentation</a> for details.', 'type' => 'textarea', 'per_agent' => 1, }, - - { - 'key' => 'alerter_msgnum', - 'section' => 'notification', - 'description' => 'Template to use for credit card expiration alerts.', - %msg_template_options, - }, { 'key' => 'apacheip', @@ -738,13 +717,6 @@ my %msg_template_options = ( }, { - 'key' => 'business-onlinepayment-test_transaction', - 'section' => 'billing', - 'description' => 'Turns on the Business::OnlinePayment test_transaction flag. Note that not all gateway modules support this flag; if yours does not, transactions will still be sent live.', - 'type' => 'checkbox', - }, - - { 'key' => 'countrydefault', 'section' => 'UI', 'description' => 'Default two-letter country code (if not supplied, the default is `US\')', @@ -997,55 +969,6 @@ my %msg_template_options = ( }, { - 'key' => 'invoice_latextopmargin', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice topmargin setting. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { - 'key' => 'invoice_latexheadsep', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice headsep setting. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { - 'key' => 'invoice_latexaddresssep', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice separation between invoice header -and customer address. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { - 'key' => 'invoice_latextextheight', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice textheight setting. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { 'key' => 'invoice_latexnotes', 'section' => 'invoicing', 'description' => 'Notes section for LaTeX typeset PostScript invoices.', @@ -1078,53 +1001,6 @@ and customer address. Include units.', }, { - 'key' => 'invoice_latexextracouponspace', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice textheight space to reserve for a tear off coupon. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { - 'key' => 'invoice_latexcouponfootsep', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice separation between tear off coupon and footer. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { - 'key' => 'invoice_latexcouponamountenclosedsep', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice separation between total due and amount enclosed line. Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - { - 'key' => 'invoice_latexcoupontoaddresssep', - 'section' => 'invoicing', - 'description' => 'Optional LaTeX invoice separation between invoice data and the to address (usually invoice_latexreturnaddress). Include units.', - 'type' => 'text', - 'per_agent' => 1, - 'validate' => sub { shift =~ - /^-?\d*\.?\d+(in|mm|cm|pt|em|ex|pc|bp|dd|cc|sp)$/ - ? '' : 'Invalid LaTex length'; - }, - }, - - { 'key' => 'invoice_latexreturnaddress', 'section' => 'invoicing', 'description' => 'Return address for LaTeX typeset PostScript invoices.', @@ -1132,22 +1008,6 @@ and customer address. Include units.', }, { - 'key' => 'invoice_latexverticalreturnaddress', - 'section' => 'invoicing', - 'description' => 'Place the return address under the company logo rather than beside it.', - 'type' => 'checkbox', - 'per_agent' => 1, - }, - - { - 'key' => 'invoice_latexcouponaddcompanytoaddress', - 'section' => 'invoicing', - 'description' => 'Add the company name to the To address on the remittance coupon because the return address does not contain it.', - 'type' => 'checkbox', - 'per_agent' => 1, - }, - - { 'key' => 'invoice_latexsmallfooter', 'section' => 'invoicing', 'description' => 'Optional small footer for multi-page LaTeX typeset PostScript invoices.', @@ -1169,12 +1029,6 @@ and customer address. Include units.', 'type' => 'textarea' }, - { - 'key' => 'invoice_print_pdf', - 'section' => 'invoicing', - 'description' => 'Store postal invoices for download in PDF format rather than printing them directly.', - 'type' => 'checkbox', - }, { 'key' => 'invoice_default_terms', @@ -1241,22 +1095,15 @@ and customer address. Include units.', }, { - 'key' => 'payment_receipt_msgnum', - 'section' => 'notification', - 'description' => 'Template to use for payment receipts.', - %msg_template_options, - }, - - { 'key' => 'payment_receipt_email', - 'section' => 'deprecated', - 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received.', + 'section' => 'billing', + 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <ul><li><code>$date</code> <li><code>$name</code> <li><code>$paynum</code> - Freeside payment number <li><code>$paid</code> - Amount of payment <li><code>$payby</code> - Payment type (Card, Check, Electronic check, etc.) <li><code>$payinfo</code> - Masked credit card number or check number <li><code>$balance</code> - New balance<li><code>$pkg</code> - Package (requires payment_receipt-trigger set to "when payment is applied".)</ul>', 'type' => [qw( checkbox textarea )], }, { 'key' => 'payment_receipt-trigger', - 'section' => 'notification', + 'section' => 'billing', 'description' => 'When payment receipts are triggered. Defaults to when payment is made.', 'type' => 'select', 'select_hash' => [ @@ -1785,7 +1632,6 @@ and customer address. Include units.', 'description' => 'Run billing for signup server signups immediately, and do not provision accounts which subsequently have a balance.', 'type' => 'checkbox', }, - { 'key' => 'signup_server-classnum2', 'section' => 'self-service', @@ -1801,13 +1647,6 @@ and customer address. Include units.', }, { - 'key' => 'selfservice-xmlrpc', - 'section' => 'self-service', - 'description' => 'Run a standalone self-service XML-RPC server on the backend (on port 8080).', - 'type' => 'checkbox', - }, - - { 'key' => 'backend-realtime', 'section' => 'billing', 'description' => 'Run billing for backend signups immediately.', @@ -1815,58 +1654,44 @@ and customer address. Include units.', }, { - 'key' => 'decline_msgnum', - 'section' => 'notification', - 'description' => 'Template to use for credit card and electronic check decline messages.', - %msg_template_options, - }, - - { 'key' => 'declinetemplate', - 'section' => 'deprecated', + 'section' => 'billing', 'description' => 'Template file for credit card and electronic check decline emails.', 'type' => 'textarea', }, { 'key' => 'emaildecline', - 'section' => 'notification', + 'section' => 'billing', 'description' => 'Enable emailing of credit card and electronic check decline notices.', 'type' => 'checkbox', }, { 'key' => 'emaildecline-exclude', - 'section' => 'notification', + 'section' => 'billing', 'description' => 'List of error messages that should not trigger email decline notices, one per line.', 'type' => 'textarea', }, { - 'key' => 'cancel_msgnum', - 'section' => 'notification', - 'description' => 'Template to use for cancellation emails.', - %msg_template_options, - }, - - { 'key' => 'cancelmessage', - 'section' => 'deprecated', + 'section' => 'billing', 'description' => 'Template file for cancellation emails.', 'type' => 'textarea', }, { 'key' => 'cancelsubject', - 'section' => 'deprecated', + 'section' => 'billing', 'description' => 'Subject line for cancellation emails.', 'type' => 'text', }, { 'key' => 'emailcancel', - 'section' => 'notification', - 'description' => 'Enable emailing of cancellation notices. Make sure to select the template in the cancel_msgnum option.', + 'section' => 'billing', + 'description' => 'Enable emailing of cancellation notices. Make sure to fill in the cancelmessage and cancelsubject configuration values as well.', 'type' => 'checkbox', }, @@ -1920,23 +1745,16 @@ and customer address. Include units.', }, { - 'key' => 'welcome_msgnum', - 'section' => 'notification', - 'description' => 'Template to use for welcome messages when a svc_acct record is created.', - %msg_template_options, - }, - - { 'key' => 'welcome_email', - 'section' => 'deprecated', - 'description' => 'Template file for welcome email. Welcome emails are sent to the customer email invoice destination(s) each time a svc_acct record is created.', + 'section' => '', + 'description' => 'Template file for welcome email. Welcome emails are sent to the customer email invoice destination(s) each time a svc_acct record is created. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code></ul>', 'type' => 'textarea', 'per_agent' => 1, }, { 'key' => 'welcome_email-from', - 'section' => 'deprecated', + 'section' => '', 'description' => 'From: address header for welcome email', 'type' => 'text', 'per_agent' => 1, @@ -1944,7 +1762,7 @@ and customer address. Include units.', { 'key' => 'welcome_email-subject', - 'section' => 'deprecated', + 'section' => '', 'description' => 'Subject: header for welcome email', 'type' => 'text', 'per_agent' => 1, @@ -1952,7 +1770,7 @@ and customer address. Include units.', { 'key' => 'welcome_email-mimetype', - 'section' => 'deprecated', + 'section' => '', 'description' => 'MIME type for welcome email', 'type' => 'select', 'select_enum' => [ 'text/plain', 'text/html' ], @@ -1966,44 +1784,37 @@ and customer address. Include units.', 'type' => 'textarea', }, -# { -# 'key' => 'warning_msgnum', -# 'section' => 'notification', -# 'description' => 'Template to use for warning messages, sent to the customer email invoice destination(s) when a svc_acct record has its usage drop below a threshold.', -# %msg_template_options, -# }, - { 'key' => 'warning_email', - 'section' => 'notification', + 'section' => '', 'description' => 'Template file for warning email. Warning emails are sent to the customer email invoice destination(s) each time a svc_acct record has its usage drop below a threshold or 0. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code> <li><code>$column</code> <li><code>$amount</code> <li><code>$threshold</code></ul>', 'type' => 'textarea', }, { 'key' => 'warning_email-from', - 'section' => 'notification', + 'section' => '', 'description' => 'From: address header for warning email', 'type' => 'text', }, { 'key' => 'warning_email-cc', - 'section' => 'notification', + 'section' => '', 'description' => 'Additional recipient(s) (comma separated) for warning email when remaining usage reaches zero.', 'type' => 'text', }, { 'key' => 'warning_email-subject', - 'section' => 'notification', + 'section' => '', 'description' => 'Subject: header for warning email', 'type' => 'text', }, { 'key' => 'warning_email-mimetype', - 'section' => 'notification', + 'section' => '', 'description' => 'MIME type for warning email', 'type' => 'select', 'select_enum' => [ 'text/plain', 'text/html' ], @@ -2250,14 +2061,6 @@ and customer address. Include units.', }, { - 'key' => 'global_unique-pbx_title', - 'section' => '', - 'description' => 'Global phone number uniqueness control: enabled (usual setting - svc_pbx.title must be unique), or disabled turns off duplicate checking for this field.', - 'type' => 'select', - 'select_enum' => [ 'enabled', 'disabled' ], - }, - - { 'key' => 'svc_external-skip_manual', 'section' => 'UI', 'description' => 'When provisioning svc_external services, skip manual entry of id and title fields in the UI. Usually used in conjunction with an export that populates these fields (i.e. artera_turbo).', @@ -2307,12 +2110,7 @@ and customer address. Include units.', } }, }, - { - 'key' => 'ticket_system-force_default_queueid', - 'section' => '', - 'description' => 'Disallow queue selection when creating new tickets from customer view.', - 'type' => 'checkbox', - }, + { 'key' => 'ticket_system-selfservice_queueid', 'section' => '', @@ -2635,13 +2433,6 @@ and customer address. Include units.', }, { - 'key' => 'cgp_rule-domain_templates', - 'section' => '', - 'description' => 'Communigate Pro rule templates for domains, one per line, "svcnum Name"', - 'type' => 'textarea', - }, - - { 'key' => 'svc_forward-no_srcsvc', 'section' => '', 'description' => "Don't allow forwards from existing accounts, only arbitrary addresses. Useful when exporting to systems such as Communigate Pro which treat forwards in this fashion.", @@ -2936,15 +2727,8 @@ and customer address. Include units.', }, { - 'key' => 'impending_recur_msgnum', - 'section' => 'notification', - 'description' => 'Template to use for alerts about first-time recurring billing.', - %msg_template_options, - }, - - { 'key' => 'impending_recur_template', - 'section' => 'deprecated', + 'section' => 'billing', 'description' => 'Template file for alerts about looming first time recurrant billing. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitition language. Also see packages with a <a href="../browse/part_pkg.cgi">flat price plan</a> The following variables are available<ul><li><code>$packages</code> allowing <code>$packages->[0]</code> thru <code>$packages->[n]</code> <li><code>$package</code> the first package, same as <code>$packages->[0]</code> <li><code>$recurdates</code> allowing <code>$recurdates->[0]</code> thru <code>$recurdates->[n]</code> <li><code>$recurdate</code> the first recurdate, same as <code>$recurdate->[0]</code> <li><code>$first</code> <li><code>$last</code></ul>', # <li><code>$payby</code> <li><code>$expdate</code> most likely only confuse 'type' => 'textarea', @@ -3224,13 +3008,6 @@ and customer address. Include units.', }, { - 'key' => 'disable_settings_changes', - 'section' => '', - 'description' => 'Disable all settings changes, for demos, except for the usernames given in the comma-separated list.', - 'type' => [qw( checkbox text )], - }, - - { 'key' => 'cust_main-edit_agent_custid', 'section' => 'UI', 'description' => 'Enable editing of the agent_custid field.', @@ -3570,22 +3347,6 @@ and customer address. Include units.', }, { - 'key' => 'cdr-charged_party-field', - 'section' => '', - 'description' => 'Set the charged_party field of CDRs to this field.', - 'type' => 'select-sub', - 'options_sub' => sub { my $fields = FS::cdr->table_info->{'fields'}; - map { $_ => $fields->{$_}||$_ } - grep { $_ !~ /^(acctid|charged_party)$/ } - FS::Schema::dbdef->table('cdr')->columns; - }, - 'option_sub' => sub { my $f = shift; - FS::cdr->table_info->{'fields'}{$f} || $f; - }, - }, - - #probably deprecate in favor of cdr-charged_party-field above - { 'key' => 'cdr-charged_party-accountcode', 'section' => '', 'description' => 'Set the charged_party field of CDRs to the accountcode.', @@ -3670,14 +3431,6 @@ and customer address. Include units.', }, { - 'key' => 'mc-outbound_packages', - 'section' => '', - 'description' => "Don't use this.", - 'type' => 'select-part_pkg', - 'multiple' => 1, - }, - - { 'key' => 'disable-cust-pkg_class', 'section' => 'UI', 'description' => 'Disable the two-step dropdown for selecting package class and package, and return to the classic single dropdown.', @@ -3850,48 +3603,6 @@ and customer address. Include units.', 'type' => 'checkbox', }, - { - 'key' => 'cust_main-exports', - 'section' => '', - 'description' => 'Export(s) to call on cust_main insert, modification and deletion.', - 'type' => 'select-sub', - 'multiple' => 1, - 'options_sub' => sub { - require FS::Record; - require FS::part_export; - my @part_export = - map { qsearch( 'part_export', {exporttype => $_ } ) } - keys %{FS::part_export::export_info('cust_main')}; - map { $_->exportnum => $_->exporttype.' to '.$_->machine } @part_export; - }, - 'option_sub' => sub { - require FS::Record; - require FS::part_export; - my $part_export = FS::Record::qsearchs( - 'part_export', { 'exportnum' => shift } - ); - $part_export - ? $part_export->exporttype.' to '.$part_export->machine - : ''; - }, - }, - - { - 'key' => 'cust_tag-location', - 'section' => 'UI', - 'description' => 'Location where customer tags are displayed.', - 'type' => 'select', - 'select_enum' => [ 'misc_info', 'top' ], - }, - - { - 'key' => 'maestro-status_test', - 'section' => 'UI', - 'description' => 'Display a link to the maestro status test page on the customer view page', - 'type' => 'checkbox', - }, - - { key => "apacheroot", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" }, { key => "apachemachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" }, { key => "apachemachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" }, diff --git a/FS/FS/Cron/alert_expiration.pm b/FS/FS/Cron/alert_expiration.pm index 364fc60c7..a9b9da9e9 100644 --- a/FS/FS/Cron/alert_expiration.pm +++ b/FS/FS/Cron/alert_expiration.pm @@ -2,7 +2,7 @@ package FS::Cron::alert_expiration; use vars qw( @ISA @EXPORT_OK); use Exporter; -use FS::Record qw(qsearch qsearchs); +use FS::Record qw(qsearch); use FS::Conf; use FS::cust_main; use FS::Misc; @@ -58,7 +58,6 @@ sub alert_expiration { } return if(!@customers); foreach my $customer (@customers) { - next if !($customer->ncancelled_pkgs); # skip inactive customers my $paydate = $customer->paydate; next if $paydate =~ /^\s*$/; # skip empty expiration dates @@ -92,32 +91,25 @@ sub alert_expiration { if (grep { $expire_time < $_date + $_ && $expire_time > $_date + $_ - $window_time } ($warning_time, $urgent_time, $panic_time) ) { - # Send an expiration notice. my $agentnum = $customer->agentnum; - my $error = ''; - - my $msgnum = $conf->config('alerter_msgnum', $agentnum); - if ( $msgnum ) { # new hotness - my $msg_template = qsearchs('msg_template', { msgnum => $msgnum } ); - $error = $msg_template->send('cust_main' => $customer); - } - else { #!$msgnum, the hard way - $mail_sender = $conf->config('invoice_from', $agentnum); - $failure_recipient = $conf->config('invoice_from', $agentnum) - || 'postmaster'; - - my @alerter_template = $conf->config('alerter_template', $agentnum) - or die 'cannot load config file alerter_template'; - - my $alerter = new Text::Template(TYPE => 'ARRAY', - SOURCE => [ - map "$_\n", @alerter_template - ]) - or die "can't create Text::Template object: $Text::Template::ERROR"; - - $alerter->compile() - or die "can't compile template: $Text::Template::ERROR"; - + $mail_sender = $conf->config('invoice_from', $agentnum); + $failure_recipient = $conf->config('invoice_from', $agentnum) + || 'postmaster'; + + my @alerter_template = $conf->config('alerter_template', $agentnum) + or die 'cannot load config file alerter_template'; + + my $alerter = new Text::Template(TYPE => 'ARRAY', + SOURCE => [ + map "$_\n", @alerter_template + ]) + or die "can't create Text::Template object: $Text::Template::ERROR"; + + $alerter->compile() + or die "can't compile template: $Text::Template::ERROR"; + + my @packages = $customer->ncancelled_pkgs; + if(@packages) { my @invoicing_list = $customer->invoicing_list; my @to_addrs = grep { $_ ne 'POST' } @invoicing_list; if(@to_addrs) { @@ -141,29 +133,26 @@ sub alert_expiration { $fill_in{'payby'} = 'current method'; } # Send it already! - $error = FS::Misc::send_email ( + my $error = FS::Misc::send_email ( from => $mail_sender, to => [ @to_addrs ], subject => 'Billing Arrangement Expiration', body => [ $alerter->fill_in( HASH => \%fill_in ) ], ); - } - else { # if(@to_addrs) - push @{$agent_failure_body{$customer->agentnum}}, - sprintf(qq{%5d %-32.32s %4s %10s %12s %12s}, - $custnum, - $first . " " . $last . " " . $company, - $payby, - $paydate, - $daytime, - $night ); - } - } # if($msgnum) - -# should we die here rather than report failure as below? - die "can't send expiration alert: $error" - if $error; - + die "can't send expiration alert: $error" + if $error; + } + else { # if(@to_addrs) + push @{$agent_failure_body{$customer->agentnum}}, + sprintf(qq{%5d %-32.32s %4s %10s %12s %12s}, + $custnum, + $first . " " . $last . " " . $company, + $payby, + $paydate, + $daytime, + $night ); + } + } # if(@packages) } # if(expired) } # foreach(@customers) diff --git a/FS/FS/Cron/notify.pm b/FS/FS/Cron/notify.pm index ece96fcfd..5b0e186ad 100644 --- a/FS/FS/Cron/notify.pm +++ b/FS/FS/Cron/notify.pm @@ -21,8 +21,6 @@ sub notify_flat_delay { #we're at now now (and later). my($time) = $^T; - my $conf = new FS::Conf; - my $error = ''; my $integer = driver_name =~ /^mysql/ ? 'SIGNED' : 'INTEGER'; @@ -103,20 +101,14 @@ END push @cust_pkgs, $cust_pkg[0]; shift @cust_pkg; } - my $msgnum = $conf->config('impending_recur_msgnum',$cust_main->agentnum); - if ( $msgnum ) { - my $msg_template = qsearchs('msg_template', { msgnum => $msgnum }); - $error = $msg_template->send('cust_main' => $cust_main); - } - else { - $error = $cust_main->notify( 'impending_recur_template', + my $error = + $cust_main->notify( 'impending_recur_template', 'extra_fields' => { 'packages' => \@packages, 'recurdates' => \@recurdates, 'package' => $packages[0], 'recurdate' => $recurdates[0], }, ); - } #if $msgnum warn "Error notifying, custnum ". $cust_main->custnum. ": $error" if $error; unless ($error) { diff --git a/FS/FS/Daemon.pm b/FS/FS/Daemon.pm index b58cde49f..ca181345a 100644 --- a/FS/FS/Daemon.pm +++ b/FS/FS/Daemon.pm @@ -1,13 +1,11 @@ package FS::Daemon; use vars qw( @ISA @EXPORT_OK ); -use vars qw( $pid_dir $me $pid_file $sigint $sigterm $NOSIG $logfile ); +use vars qw( $pid_dir $me $pid_file $sigint $sigterm $logfile ); use Exporter; use Fcntl qw(:flock); use POSIX qw(setsid); use IO::File; -use File::Basename; -use File::Slurp qw(slurp); use Date::Format; #this is a simple refactoring of the stuff from freeside-queued, just to @@ -21,19 +19,10 @@ use Date::Format; $pid_dir = '/var/run'; -$NOSIG = 0; -$PID_NEWSTYLE = 0; - sub daemonize1 { $me = shift; - $pid_file = $pid_dir; - if ( $PID_NEWSTYLE ) { - $pid_file .= '/freeside'; - mkdir $pid_file unless -d $pid_file; - chown $FS::UID::freeside_uid, -1, $pid_file; - } - $pid_file .= "/$me"; + $pid_file = "$pid_dir/$me"; $pid_file .= '.'.shift if scalar(@_); $pid_file .= '.pid'; @@ -44,7 +33,6 @@ sub daemonize1 { print "$me started with pid $pid\n"; #logging to $log_file\n"; exit unless $pid_file; my $pidfh = new IO::File ">$pid_file" or exit; - chown $FS::UID::freeside_uid, -1, $pid_file; print $pidfh "$pid\n"; exit; } @@ -53,10 +41,8 @@ sub daemonize1 { #$SIG{CHLD} = \&REAPER; $sigterm = 0; $sigint = 0; - unless ( $NOSIG ) { - $SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; }; - $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; }; - } + $SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; }; + $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; }; } sub drop_root { @@ -92,18 +78,13 @@ sub sigterm { $sigterm; } sub logfile { $logfile = shift; } #_logmsg('test'); } sub myexit { - chomp( my $pid = slurp($pid_file) ); - unlink $pid_file if -e $pid_file && $$ == $pid; + unlink $pid_file if -e $pid_file; exit; } sub _die { - die @_ if $^S; # $^S = 1 during an eval(), don't break exception handling my $msg = shift; - - chomp( my $pid = slurp($pid_file) ); - unlink $pid_file if -e $pid_file && $$ == $pid; - + unlink $pid_file if -e $pid_file; _logmsg($msg); } @@ -117,4 +98,3 @@ sub _logmsg { close $log; } -1; diff --git a/FS/FS/Maestro.pm b/FS/FS/Maestro.pm deleted file mode 100644 index 05693681d..000000000 --- a/FS/FS/Maestro.pm +++ /dev/null @@ -1,139 +0,0 @@ -package FS::Maestro; - -use Date::Format; -use FS::Conf; -use FS::Record qw( qsearchs ); -use FS::cust_main; - -sub customer_status { - my( $custnum ) = shift; #@_; - my $svcnum = @_ ? shift : ''; - - my $curuser = $FS::CurrentUser::CurrentUser; - - my $cust_main = qsearchs({ - 'table' => 'cust_main', - 'hashref' => { 'custnum' => $custnum }, - 'extra_sql' => ' AND '. $curuser->agentnums_sql, - }) - or return { 'status' => 'E', - 'error' => "custnum $custnum not found" }; - - my( $svc_pbx, $good_till, $outbound_service ) = ( '', '', '' ); - my %result = (); - if ( $svcnum ) { - - ### - # reseller scenario to maestro (customer w/ multiple packages) - ### - - # find $svc_pbx - - $svc_pbx = qsearchs({ - 'table' => 'svc_pbx', - 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '. - ' LEFT JOIN cust_pkg USING ( pkgnum ) ', - 'hashref' => { 'svcnum' => $svcnum }, - 'extra_sql' => " AND custnum = $custnum", - }) - or return { 'status' => 'E', - 'error' => "svcnum $svcnum not found" }; - - #status in the reseller scenario - - my $cust_pkg = $svc_pbx->cust_svc->cust_pkg; - - $result{'status'} = substr($cust_pkg->ucfirst_status,0,1); - - # find "outbound service" y/n - - #XXX outbound service per-reseller ? - #my @cust_pkg = $cust_main->cust_pkg; - # - #my $conf = new FS::Conf; - #my %outbound_pkgs = map { $_=>1 } $conf->config('mc-outbound_packages'); - #my $outbound_service = - # scalar( grep { $outbound_pkgs{ $_->pkgpart } - # && !$_->get('cancel') - # } - # @cust_pkg - # ) - # ? 1 : 0; - - # find "good till" date/time stamp (this package) - - $good_till = time2str('%c', $cust_pkg->bill || time ); - - } else { - - ### - # regular customer to maestro (single package) - ### - - my @cust_pkg = $cust_main->cust_pkg; - - #things specific to the non-reseller scenario - - $result{'status'} = substr($cust_main->ucfirst_status,0,1); - - $result{'products'} = - [ map $_->pkgpart, grep !$_->get('cancel'), @cust_pkg ]; - - #find svc_pbx - - my @cust_svc = map $_->cust_svc, @cust_pkg; - - my @cust_svc_pbx = - grep { my($n,$l,$t) = $_->label; $t eq 'svc_pbx' } - @cust_svc; - - if ( ! @cust_svc_pbx ) { - return { 'status' => 'E', - 'error' => "customer $custnum has no conference service" }; - } elsif ( scalar(@cust_svc_pbx) > 1 ) { - return { 'status' => 'E', - 'error' => - "customer $custnum has more than one conference". - " service (reseller?); specify a svcnum as a second argument", - }; - } - - my $cust_svc_pbx = $cust_svc_pbx[0]; - - $svc_pbx = $cust_svc_pbx->svc_x; - - # find "outbound service" y/n - - my $conf = new FS::Conf; - my %outbound_pkgs = map { $_=>1 } $conf->config('mc-outbound_packages'); - $outbound_service = - scalar( grep { $outbound_pkgs{ $_->pkgpart } - && !$_->get('cancel') - } - @cust_pkg - ) - ? 1 : 0; - - # find "good till" date/time stamp - - my @active_cust_pkg = - sort { $a->bill <=> $b->bill } - grep { !$_->get('cancel') && $_->part_pkg->freq ne '0' } - @cust_pkg; - $good_till = time2str('%c', $active_cust_pkg[0]->bill || time ); - - } - - return { - 'name' => $cust_main->name, - 'email' => $cust_main->invoicing_list_emailonly_scalar, - 'max_lines' => $svc_pbx ? $svc_pbx->max_extensions : '', - 'max_simultaneous' => $svc_pbx ? $svc_pbx->max_simultaneous : '', - 'outbound_service' => $outbound_service, - 'good_till' => $good_till, - %result, - }; - -} - -1; diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 0f1415009..10edd6d0d 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -73,8 +73,6 @@ if ( -e $addl_handler_use_file ) { use HTML::FormatText; use HTML::Defang; use JSON; -# use XMLRPC::Transport::HTTP; -# use XMLRPC::Lite; # for XMLRPC::Serializer use MIME::Base64; use IO::Handle; use IO::File; @@ -219,7 +217,6 @@ if ( -e $addl_handler_use_file ) { use FS::part_pkg_report_option; use FS::cust_attachment; use FS::h_cust_pkg; - use FS::h_inventory_item; use FS::h_svc_acct; use FS::h_svc_broadband; use FS::h_svc_domain; @@ -242,12 +239,6 @@ if ( -e $addl_handler_use_file ) { use FS::cgp_rule; use FS::cgp_rule_condition; use FS::cgp_rule_action; - use FS::bill_batch; - use FS::cust_bill_batch; - use FS::rate_time; - use FS::rate_time_interval; - use FS::msg_template; - use FS::part_tag; # Sammath Naur if ( $FS::Mason::addl_handler_use ) { @@ -260,7 +251,6 @@ if ( -e $addl_handler_use_file ) { use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" ); use vars qw($Nobody $SystemUser); use RT; - use RT::Util; use RT::Tickets; use RT::Transactions; use RT::Users; @@ -291,9 +281,6 @@ if ( -e $addl_handler_use_file ) { use RT::Interface::Web::Request; - #nother undeclared web UI dep (for ticket links graph) - use IPC::Run::SafeHandles; - #slow, unreliable, segfaults and is optional #see rt/html/Ticket/Elements/ShowTransactionAttachments #use Text::Quoted; @@ -367,11 +354,6 @@ if ( -e $addl_handler_use_file ) { $m->comp('/elements/errorpage.html', @_); } - sub errorpage_popup { - use vars qw($m); - $m->comp('/elements/errorpage-popup.html', @_); - } - sub redirect { my( $location ) = @_; use vars qw($m); @@ -480,17 +462,14 @@ sub mason_interps { my $html_defang = new HTML::Defang (%defang_opts); - my $js_string_sub = sub { - #${$_[0]} =~ s/(['\\\n])/'\\'.($1 eq "\n" ? 'n' : $1)/ge; - ${$_[0]} =~ s/(['\\])/\\$1/g; - ${$_[0]} =~ s/\r/\\r/g; - ${$_[0]} =~ s/\n/\\n/g; - ${$_[0]} = "'". ${$_[0]}. "'"; - }; - my $fs_interp = new HTML::Mason::Interp ( %interp, - escape_flags => { 'js_string' => $js_string_sub, + escape_flags => { 'js_string' => sub { + #${$_[0]} =~ s/(['\\\n])/'\\'.($1 eq "\n" ? 'n' : $1)/ge; + ${$_[0]} =~ s/(['\\])/\\$1/g; + ${$_[0]} =~ s/\n/\\n/g; + ${$_[0]} = "'". ${$_[0]}. "'"; + }, 'defang' => sub { ${$_[0]} = $html_defang->defang(${$_[0]}); }, @@ -502,9 +481,7 @@ sub mason_interps { my $rt_interp = new HTML::Mason::Interp ( %interp, - escape_flags => { 'h' => \&RT::Interface::Web::EscapeUTF8, - 'js_string' => $js_string_sub, - }, + escape_flags => { 'h' => \&RT::Interface::Web::EscapeUTF8 }, compiler => HTML::Mason::Compiler::ToObject->new( default_escape_flags => 'h', allow_globals => [qw(%session)], diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm index 3b0616a91..b275c9dfc 100644 --- a/FS/FS/Misc.pm +++ b/FS/FS/Misc.pm @@ -8,16 +8,14 @@ use Data::Dumper; use IPC::Run qw( run timeout ); # for _pslatex use IPC::Run3; # for do_print... should just use IPC::Run i guess use File::Temp; -use Tie::IxHash; #do NOT depend on any FS:: modules here, causes weird (sometimes unreproducable #until on client machine) dependancy loops. put them in FS::Misc::Something #instead @ISA = qw( Exporter ); -@EXPORT_OK = qw( send_email generate_email send_fax +@EXPORT_OK = qw( generate_email send_email send_fax states_hash counties cities state_label card_types - pkg_freqs generate_ps generate_pdf do_print csv_from_fixed ); @@ -38,12 +36,136 @@ FS::Misc - Miscellaneous subroutines Miscellaneous subroutines. This module contains miscellaneous subroutines called from multiple other modules. These are not OO or necessarily related, -but are collected here to eliminate code duplication. +but are collected here to elimiate code duplication. =head1 SUBROUTINES =over 4 +=item generate_email OPTION => VALUE ... + +Options: + +=over 4 + +=item from + +Sender address, required + +=item to + +Recipient address, required + +=item subject + +email subject, required + +=item html_body + +Email body (HTML alternative). Arrayref of lines, or scalar. + +Will be placed inside an HTML <BODY> tag. + +=item text_body + +Email body (Text alternative). Arrayref of lines, or scalar. + +=back + +Returns an argument list to be passsed to L<send_email>. + +=cut + +#false laziness w/FS::cust_bill::generate_email + +use MIME::Entity; +use HTML::Entities; + +sub generate_email { + my %args = @_; + + my $me = '[FS::Misc::generate_email]'; + + my %return = ( + 'from' => $args{'from'}, + 'to' => $args{'to'}, + 'subject' => $args{'subject'}, + ); + + #if (ref($args{'to'}) eq 'ARRAY') { + # $return{'to'} = $args{'to'}; + #} else { + # $return{'to'} = [ grep { $_ !~ /^(POST|FAX)$/ } + # $self->cust_main->invoicing_list + # ]; + #} + + warn "$me creating HTML/text multipart message" + if $DEBUG; + + $return{'nobody'} = 1; + + my $alternative = build MIME::Entity + 'Type' => 'multipart/alternative', + 'Encoding' => '7bit', + 'Disposition' => 'inline' + ; + + my $data; + if ( ref($args{'text_body'}) eq 'ARRAY' ) { + $data = $args{'text_body'}; + } else { + $data = [ split(/\n/, $args{'text_body'}) ]; + } + + $alternative->attach( + 'Type' => 'text/plain', + #'Encoding' => 'quoted-printable', + 'Encoding' => '7bit', + 'Data' => $data, + 'Disposition' => 'inline', + ); + + my @html_data; + if ( ref($args{'html_body'}) eq 'ARRAY' ) { + @html_data = @{ $args{'html_body'} }; + } else { + @html_data = split(/\n/, $args{'html_body'}); + } + + $alternative->attach( + 'Type' => 'text/html', + 'Encoding' => 'quoted-printable', + 'Data' => [ '<html>', + ' <head>', + ' <title>', + ' '. encode_entities($return{'subject'}), + ' </title>', + ' </head>', + ' <body bgcolor="#e8e8e8">', + @html_data, + ' </body>', + '</html>', + ], + 'Disposition' => 'inline', + #'Filename' => 'invoice.pdf', + ); + + #no other attachment: + # multipart/related + # multipart/alternative + # text/plain + # text/html + + $return{'content-type'} = 'multipart/related'; + $return{'mimeparts'} = [ $alternative ]; + $return{'type'} = 'multipart/alternative'; #Content-Type of first part... + #$return{'disposition'} = 'inline'; + + %return; + +} + =item send_email OPTION => VALUE ... Options: @@ -231,154 +353,12 @@ sub send_email { $smtp_opt{'ssl'} = 1 if defined($enc) && $enc eq 'tls'; $transport = Email::Sender::Transport::SMTP->new( %smtp_opt ); } - - local $@; # just in case - eval { sendmail($message, { transport => $transport }) }; - - if(ref($@) and $@->isa('Email::Sender::Failure')) { - return ($@->code ? $@->code.' ' : '').$@->message - } - else { - return $@; - } -} - -=item generate_email OPTION => VALUE ... - -Options: - -=over 4 - -=item from - -Sender address, required - -=item to - -Recipient address, required - -=item subject - -email subject, required - -=item html_body - -Email body (HTML alternative). Arrayref of lines, or scalar. - -Will be placed inside an HTML <BODY> tag. - -=item text_body - -Email body (Text alternative). Arrayref of lines, or scalar. - -=back - -Constructs a multipart message from text_body and html_body. - -=cut - -#false laziness w/FS::cust_bill::generate_email - -use MIME::Entity; -use HTML::Entities; - -sub generate_email { - my %args = @_; - - my $me = '[FS::Misc::generate_email]'; - - my %return = ( - 'from' => $args{'from'}, - 'to' => $args{'to'}, - 'subject' => $args{'subject'}, - ); - - #if (ref($args{'to'}) eq 'ARRAY') { - # $return{'to'} = $args{'to'}; - #} else { - # $return{'to'} = [ grep { $_ !~ /^(POST|FAX)$/ } - # $self->cust_main->invoicing_list - # ]; - #} - - warn "$me creating HTML/text multipart message" - if $DEBUG; - - $return{'nobody'} = 1; - - my $alternative = build MIME::Entity - 'Type' => 'multipart/alternative', - 'Encoding' => '7bit', - 'Disposition' => 'inline' - ; - - my $data; - if ( ref($args{'text_body'}) eq 'ARRAY' ) { - $data = $args{'text_body'}; - } else { - $data = [ split(/\n/, $args{'text_body'}) ]; - } - $alternative->attach( - 'Type' => 'text/plain', - #'Encoding' => 'quoted-printable', - 'Encoding' => '7bit', - 'Data' => $data, - 'Disposition' => 'inline', - ); + eval { sendmail($message, { transport => $transport }); }; + ref($@) eq 'Email::Sender::Failure' + ? ( $@->code ? $@->code.' ' : '' ). $@->message + : $@; - my @html_data; - if ( ref($args{'html_body'}) eq 'ARRAY' ) { - @html_data = @{ $args{'html_body'} }; - } else { - @html_data = split(/\n/, $args{'html_body'}); - } - - $alternative->attach( - 'Type' => 'text/html', - 'Encoding' => 'quoted-printable', - 'Data' => [ '<html>', - ' <head>', - ' <title>', - ' '. encode_entities($return{'subject'}), - ' </title>', - ' </head>', - ' <body bgcolor="#e8e8e8">', - @html_data, - ' </body>', - '</html>', - ], - 'Disposition' => 'inline', - #'Filename' => 'invoice.pdf', - ); - - #no other attachment: - # multipart/related - # multipart/alternative - # text/plain - # text/html - - $return{'content-type'} = 'multipart/related'; - $return{'mimeparts'} = [ $alternative ]; - $return{'type'} = 'multipart/alternative'; #Content-Type of first part... - #$return{'disposition'} = 'inline'; - - %return; - -} - -=item process_send_email OPTION => VALUE ... - -Takes arguments as per generate_email() and sends the message. This -will die on any error and can be used in the job queue. - -=cut - -sub process_send_email { - my %message = @_; - my $error = send_email(generate_email(%message)); - die "$error\n" if $error; - ''; } =item send_fax OPTION => VALUE ... @@ -610,39 +590,6 @@ sub card_types { \%card_types; } -=item pkg_freqs - -Returns a hash reference of allowed package billing frequencies. - -=cut - -sub pkg_freqs { - tie my %freq, 'Tie::IxHash', ( - '0' => '(no recurring fee)', - '1h' => 'hourly', - '1d' => 'daily', - '2d' => 'every two days', - '3d' => 'every three days', - '1w' => 'weekly', - '2w' => 'biweekly (every 2 weeks)', - '1' => 'monthly', - '45d' => 'every 45 days', - '2' => 'bimonthly (every 2 months)', - '3' => 'quarterly (every 3 months)', - '4' => 'every 4 months', - '137d' => 'every 4 1/2 months (137 days)', - '6' => 'semiannually (every 6 months)', - '12' => 'annually', - '13' => 'every 13 months (annually +1 month)', - '24' => 'biannually (every 2 years)', - '36' => 'triannually (every 3 years)', - '48' => '(every 4 years)', - '60' => '(every 5 years)', - '120' => '(every 10 years)', - ) ; - \%freq; -} - =item generate_ps FILENAME Returns an postscript rendition of the LaTex file, as a scalar. diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index cd5e2d4ca..0845cc6f3 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -795,17 +795,6 @@ sub setfield { $self->set(@_); } -=item exists COLUMN - -Returns true if the column/field/key COLUMN exists. - -=cut - -sub exists { - my($self,$field) = @_; - exists($self->{Hash}->{$field}); -} - =item AUTLOADED METHODS $record->column is a synonym for $record->get('column'); @@ -1580,7 +1569,6 @@ sub process_batch_import { format_headers => $opt->{format_headers}, format_sep_chars => $opt->{format_sep_chars}, format_fixedlength_formats => $opt->{format_fixedlength_formats}, - format_row_callbacks => $opt->{format_row_callbacks}, #per-import job => $job, file => $file, @@ -1621,8 +1609,6 @@ Class method for batch imports. Available params: =item format_fixedlength_formats -=item format_row_callbacks - =item params =item job @@ -1647,7 +1633,7 @@ sub batch_import { my $param = shift; warn "$me batch_import call with params: \n". Dumper($param) - ;# if $DEBUG; + if $DEBUG; my $table = $param->{table}; my $formats = $param->{formats}; @@ -1688,11 +1674,6 @@ sub batch_import { ? $param->{'format_fixedlength_formats'}{ $param->{'format'} } : ''; - my $row_callback = - $param->{'format_row_callbacks'} - ? $param->{'format_row_callbacks'}{ $param->{'format'} } - : ''; - my @fields = @{ $formats->{ $format } }; my $row = 0; @@ -1788,8 +1769,6 @@ sub batch_import { next if $line =~ /^\s*$/; #skip empty lines - $line = &{$row_callback}($line) if $row_callback; - $parser->parse($line) or do { $dbh->rollback if $oldAutoCommit; return "can't parse: ". $parser->error_input(); diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 60d2bcef5..0b54282ef 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -960,30 +960,6 @@ sub tables_hashref { 'unique' => [], 'index' => [ ['disabled'] ], }, - - 'cust_tag' => { - 'columns' => [ - 'custtagnum', 'serial', '', '', '', '', - 'custnum', 'int', '', '', '', '', - 'tagnum', 'int', '', '', '', '', - ], - 'primary_key' => 'custtagnum', - 'unique' => [ [ 'custnum', 'tagnum' ] ], - 'index' => [ [ 'custnum' ] ], - }, - - 'part_tag' => { - 'columns' => [ - 'tagnum', 'serial', '', '', '', '', - 'tagname', 'varchar', '', $char_d, '', '', - 'tagdesc', 'varchar', 'NULL', $char_d, '', '', - 'tagcolor', 'varchar', 'NULL', 6, '', '', - 'disabled', 'char', 'NULL', 1, '', '', - ], - 'primary_key' => 'tagnum', - 'unique' => [], #[ [ 'tagname' ] ], #? - 'index' => [ [ 'disabled' ] ], - }, 'cust_main_exemption' => { 'columns' => [ @@ -1827,7 +1803,7 @@ sub tables_hashref { 'cgp_rule_condition' => { 'columns' => [ 'ruleconditionnum', 'serial', '', '', '', '', - 'conditionname', 'varchar', '', $char_d, '', '', + 'condition', 'varchar', '', $char_d, '', '', 'op', 'varchar', 'NULL', $char_d, '', '', 'params', 'varchar', 'NULL', 255, '', '', 'rulenum', 'int', '', '', '', '', @@ -2253,7 +2229,6 @@ sub tables_hashref { 'conn_sec', 'int', '', '', '0', '', 'min_charge', 'decimal', '', '10,5', '', '', #@money_type, '', '', 'sec_granularity', 'int', '', '', '', '', - 'ratetimenum', 'int', 'NULL', '', '', '', #time period (link to table of periods)? 'classnum', 'int', 'NULL', '', '', '', ], @@ -2285,28 +2260,6 @@ sub tables_hashref { 'index' => [ [ 'countrycode' ], [ 'npa' ], [ 'regionnum' ] ], }, - 'rate_time' => { - 'columns' => [ - 'ratetimenum', 'serial', '', '', '', '', - 'ratetimename', 'varchar', '', $char_d, '', '', - ], - 'primary_key' => 'ratetimenum', - 'unique' => [], - 'index' => [], - }, - - 'rate_time_interval' => { - 'columns' => [ - 'intervalnum', 'serial', '', '', '', '', - 'stime', 'int', '', '', '', '', - 'etime', 'int', '', '', '', '', - 'ratetimenum', 'int', '', '', '', '', - ], - 'primary_key' => 'intervalnum', - 'unique' => [], - 'index' => [], - }, - 'usage_class' => { 'columns' => [ 'classnum', 'serial', '', '', '', '', @@ -2846,11 +2799,10 @@ sub tables_hashref { 'svc_pbx' => { 'columns' => [ - 'svcnum', 'int', '', '', '', '', - 'id', 'int', 'NULL', '', '', '', - 'title', 'varchar', 'NULL', $char_d, '', '', - 'max_extensions', 'int', 'NULL', '', '', '', - 'max_simultaneous', 'int', 'NULL', '', '', '', + 'svcnum', 'int', '', '', '', '', + 'id', 'int', 'NULL', '', '', '', + 'title', 'varchar', 'NULL', $char_d, '', '', + 'max_extensions', 'int', 'NULL', '', '', '', ], 'primary_key' => 'svcnum', 'unique' => [], @@ -2896,57 +2848,6 @@ sub tables_hashref { 'index' => [['listnum'],['svcnum'],['contactemailnum'],['email']], }, - 'bill_batch' => { - 'columns' => [ - 'batchnum', 'serial', '', '', '', '', - 'status', 'char', 'NULL','1', '', '', - 'pdf', 'blob', 'NULL', '', '', '', - ], - 'primary_key' => 'batchnum', - 'unique' => [], - 'index' => [], - }, - - 'cust_bill_batch' => { - 'columns' => [ - 'billbatchnum', 'serial', '', '', '', '', - 'batchnum', 'int', '', '', '', '', - 'invnum', 'int', '', '', '', '', - ], - 'primary_key' => 'billbatchnum', - 'unique' => [], - 'index' => [ [ 'batchnum' ], [ 'invnum' ] ], - }, - - 'cust_bill_batch_option' => { - 'columns' => [ - 'optionnum', 'serial', '', '', '', '', - 'billbatchnum', 'int', '', '', '', '', - 'optionname', 'varchar', '', $char_d, '', '', - 'optionvalue', 'text', 'NULL', '', '', '', - ], - 'primary_key' => 'optionnum', - 'unique' => [], - 'index' => [ [ 'billbatchnum' ], [ 'optionname' ] ], - }, - - 'msg_template' => { - 'columns' => [ - 'msgnum', 'serial', '', '', '', '', - 'msgname', 'varchar', '', $char_d, '', '', - 'agentnum', 'int', 'NULL', '', '', '', - 'subject', 'varchar', 'NULL', 512, '', '', - 'mime_type', 'varchar', '', $char_d, '', '', - 'body', 'blob', 'NULL', '', '', '', - 'disabled', 'char', 'NULL', 1, '', '', - 'from_addr', 'varchar', 'NULL', 255, '', '', - ], - 'primary_key' => 'msgnum', - 'unique' => [ ['msgname', 'mime_type'] ], - 'index' => [ ['agentnum'], ] - }, - - # name type nullability length default local diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm index 2d00d2c14..821b1916a 100644 --- a/FS/FS/UI/Web.pm +++ b/FS/FS/UI/Web.pm @@ -494,7 +494,6 @@ use JSON; use FS::UID qw(getotaker); use FS::Record qw(qsearchs); use FS::queue; -use FS::CGI qw(rooturl); $DEBUG = 0; @@ -566,7 +565,6 @@ sub start_job { } } $param{CurrentUser} = getotaker(); - $param{RootURL} = rooturl($self->{cgi}->self_url); warn "FS::UI::Web::start_job\n". join('', map { if ( ref($param{$_}) ) { @@ -622,15 +620,13 @@ sub job_status { } my @return; - if ( $job && $job->status ne 'failed' && $job->status ne 'done' ) { + if ( $job && $job->status ne 'failed' ) { my ($progress, $action) = split ',', $job->statustext, 2; $action ||= 'Server processing job'; @return = ( 'progress', $progress, $action ); } elsif ( !$job ) { #handle job gone case : job successful # so close popup, redirect parent window... @return = ( 'complete' ); - } elsif ( $job->status eq 'done' ) { - @return = ( 'done', $job->statustext, '' ); } else { @return = ( 'error', $job ? $job->statustext : $jobnum ); } diff --git a/FS/FS/UI/Web/small_custview.pm b/FS/FS/UI/Web/small_custview.pm index 36dd30c6d..f8e202092 100644 --- a/FS/FS/UI/Web/small_custview.pm +++ b/FS/FS/UI/Web/small_custview.pm @@ -3,7 +3,6 @@ package FS::UI::Web::small_custview; use strict; use vars qw(@EXPORT_OK @ISA); use Exporter; -use HTML::Entities; use FS::Msgcat; use FS::Record qw(qsearchs); use FS::cust_main; @@ -36,26 +35,7 @@ sub small_custview { $html .= 'Customer #<B>'. $cust_main->display_custnum. '</B></A>'. ' - <B><FONT COLOR="#'. $cust_main->statuscolor. '">'. - ucfirst($cust_main->status). '</FONT></B>'; - - my @part_tag = $cust_main->part_tag; - if ( @part_tag ) { - $html .= '<TABLE>'; - foreach my $part_tag ( @part_tag ) { - $html .= '<TR><TD>'. - '<FONT '. ( length($part_tag->tagcolor) - ? 'STYLE="background-color:#'.$part_tag->tagcolor.'"' - : '' - ). - '>'. - encode_entities($part_tag->tagname.': '. $part_tag->tagdesc). - '</FONT>'. - '</TD></TR>'; - } - $html .= '</TABLE>'; - } - - $html .= + ucfirst($cust_main->status). '</FONT></B>'. ntable('#e8e8e8'). '<TR><TD VALIGN="top">'. ntable("#cccccc",2). '<TR><TD ALIGN="right" VALIGN="top">Billing<BR>Address</TD><TD BGCOLOR="#ffffff">'. $cust_main->getfield('last'). ', '. $cust_main->first. '<BR>'; diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm index b7a1c661a..576676f76 100644 --- a/FS/FS/Upgrade.pm +++ b/FS/FS/Upgrade.pm @@ -42,10 +42,6 @@ sub upgrade { my $data = upgrade_data(%opt); - my $oldAutoCommit = $FS::UID::AutoCommit; - local $FS::UID::AutoCommit = 0; - local $FS::UID::AutoCommit = 0; - foreach my $table ( keys %$data ) { my $class = "FS::$table"; @@ -57,10 +53,13 @@ sub upgrade { my $start = time; + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + $FS::UID::AutoCommit = 0; + $class->_upgrade_data(%opt); if ( $oldAutoCommit ) { - warn " committing\n"; dbh->commit or die dbh->errstr; } @@ -154,12 +153,6 @@ sub upgrade_data { 'cust_refund' => [], 'banned_pay' => [], - #default namespace - 'payment_gateway' => [], - - #migrate to templates - 'msg_template' => [], - ; \%hash; @@ -189,8 +182,7 @@ sub upgrade_sqlradius { my $str2time = str2time_sql( $dbh->{Driver}->{Name} ); my $group = "UserName"; $group .= ",Realm" - if ref($part_export) =~ /withdomain/ - || $dbh->{Driver}->{Name} =~ /^Pg/; #hmm + if ( ref($part_export) =~ /withdomain/ ); my $sth_alter = $dbh->prepare( "ALTER TABLE radacct ADD COLUMN FreesideStatus varchar(32) NULL" @@ -203,10 +195,7 @@ sub upgrade_sqlradius { $sth_update->execute or die $errmsg.$sth_update->errstr; } else { my $error = $sth_alter->errstr; - warn $errmsg.$error - unless $error =~ /Duplicate column name/i #mysql - || $error =~ /already exists/i; #Pg -; + warn $errmsg.$error unless $error =~ /Duplicate column name/i; } } else { my $error = $dbh->errstr; @@ -219,26 +208,21 @@ sub upgrade_sqlradius { if ( $sth_index ) { unless ( $sth_index->execute ) { my $error = $sth_index->errstr; - warn $errmsg.$error - unless $error =~ /Duplicate key name/i #mysql - || $error =~ /already exists/i; #Pg + warn $errmsg.$error unless $error =~ /Duplicate key name/i; } } else { my $error = $dbh->errstr; - warn $errmsg.$error. ' (preparing statement)';#unless $error =~ /exists/i; + warn $errmsg.$error; #unless $error =~ /exists/i; } - my $times = ($dbh->{Driver}->{Name} =~ /^mysql/) - ? ' AcctStartTime != 0 AND AcctStopTime != 0 ' - : ' AcctStartTime IS NOT NULL AND AcctStopTime IS NOT NULL '; - my $sth = $dbh->prepare("SELECT UserName, Realm, $str2time max(AcctStartTime)), $str2time max(AcctStopTime)) FROM radacct WHERE FreesideStatus = 'done' - AND $times + AND AcctStartTime != 0 + AND AcctStopTime != 0 GROUP BY $group ") or die $errmsg.$dbh->errstr; diff --git a/FS/FS/XMLRPC.pm b/FS/FS/XMLRPC.pm index 73ce13f7a..fb0e5ac74 100644 --- a/FS/FS/XMLRPC.pm +++ b/FS/FS/XMLRPC.pm @@ -1,7 +1,7 @@ - package FS::XMLRPC; +package FS::XMLRPC; use strict; -use vars qw( $DEBUG ); +use vars qw( @ISA $DEBUG ); use Frontier::RPC2; # Instead of 'use'ing freeside modules on the fly below, just preload them now. @@ -11,10 +11,10 @@ use FS::Conf; use FS::Record; use FS::cust_main; -use FS::Maestro; - use Data::Dumper; +@ISA = qw( ); + $DEBUG = 0; =head1 NAME @@ -131,9 +131,9 @@ sub _serve { #Subroutine, not method } - if ( scalar(@result) == 1 && ref($result[0]) eq 'HASH' ) { - return $result[0]; - } elsif (grep { UNIVERSAL::can($_, 'hashref') ? 0 : 1 } @result) { + warn Dumper(@result) if $DEBUG; + + if (grep { UNIVERSAL::can($_, 'hashref') ? 0 : 1 } @result) { #warn "FS::XMLRPC: One or more objects returned from '${fssub}' doesn't " . # "support the 'hashref' method."; @@ -147,8 +147,8 @@ sub _serve { #Subroutine, not method return [ $FS::VERSION ]; } # else... - warn "Unhandled XMLRPC request '${method_name}'"; - return {}; + warn "Unhandle XMLRPC request '${method_name}'"; + return []; } diff --git a/FS/FS/access_user.pm b/FS/FS/access_user.pm index 8c8ba8b9f..1bf6e9387 100644 --- a/FS/FS/access_user.pm +++ b/FS/FS/access_user.pm @@ -1,16 +1,20 @@ package FS::access_user; use strict; -use base qw( FS::m2m_Common FS::option_Common ); -use vars qw( $DEBUG $me $conf $htpasswd_file ); +use vars qw( @ISA $DEBUG $me $conf $htpasswd_file ); use FS::UID; use FS::Conf; use FS::Record qw( qsearch qsearchs dbh ); +use FS::m2m_Common; +use FS::option_Common; use FS::access_user_pref; use FS::access_usergroup; use FS::agent; use FS::cust_main; +@ISA = qw( FS::m2m_Common FS::option_Common FS::Record ); +#@ISA = qw( FS::m2m_Common FS::option_Common ); + $DEBUG = 0; $me = '[FS::access_user]'; @@ -363,11 +367,6 @@ user has the provided access right Optional table name in which agentnum is being checked. Sometimes required to resolve 'column reference "agentnum" is ambiguous' errors. -=item viewall_right - -All agents will be viewable if the current user has the provided access right. -Defaults to 'View customers of all agents'. - =back =cut @@ -378,21 +377,16 @@ sub agentnums_sql { my $agentnum = $opt{'table'} ? $opt{'table'}.'.agentnum' : 'agentnum'; - my @or = (); - - my $viewall_right = $opt{'viewall_right'} || 'View customers of all agents'; - if ( $self->access_right($viewall_right) ) { - push @or, "$agentnum IS NOT NULL"; - } else { - push @or, "$agentnum IN (". join(',', $self->agentnums). ')'; - } +# my @agentnums = map { "$agentnum = $_" } $self->agentnums; + my @agentnums = (); + push @agentnums, "$agentnum IN (". join(',', $self->agentnums). ')'; - push @or, "$agentnum IS NULL" + push @agentnums, "$agentnum IS NULL" if $opt{'null'} || ( $opt{'null_right'} && $self->access_right($opt{'null_right'}) ); - return ' 1 = 0 ' unless scalar(@or); - '( '. join( ' OR ', @or ). ' )'; + return ' 1 = 0 ' unless scalar(@agentnums); + '( '. join( ' OR ', @agentnums ). ' )'; } @@ -413,10 +407,10 @@ sub agentnum { $sth->fetchrow_arrayref->[0]; } -=item agents [ HASHREF | OPTION => VALUE ... ] +=item agents Returns the list of agents this user can view (via group membership), as -FS::agent objects. Accepts the same options as the agentnums_sql method. +FS::agent objects. =cut @@ -425,7 +419,7 @@ sub agents { qsearch({ 'table' => 'agent', 'hashref' => { disabled=>'' }, - 'extra_sql' => ' AND '. $self->agentnums_sql(@_), + 'extra_sql' => ' AND '. $self->agentnums_sql, }); } diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm index d291ca070..f17427517 100644 --- a/FS/FS/agent.pm +++ b/FS/FS/agent.pm @@ -269,20 +269,16 @@ sub payment_gateway { cardtype => '', taxclass => '', } ); - my $payment_gateway; - my $conf = new FS::Conf; + my $payment_gateway = new FS::payment_gateway; if ( $override ) { #use a payment gateway override $payment_gateway = $override->payment_gateway; - $payment_gateway->gateway_namespace('Business::OnlinePayment') - unless $payment_gateway->gateway_name; - } else { #use the standard settings from the config - # the standard settings from the config could be moved to a null agent # agent_payment_gateway referenced payment_gateway + my $conf = new FS::Conf; unless ( $conf->exists('business-onlinepayment') ) { if ( $options{'nofatal'} ) { return ''; @@ -306,8 +302,6 @@ sub payment_gateway { "did you set the business-onlinepayment configuration value?\n" unless $processor; - $payment_gateway = new FS::payment_gateway; - $payment_gateway->gateway_namespace( $conf->config('business-onlinepayment-namespace') || 'Business::OnlinePayment'); $payment_gateway->gateway_module($processor); @@ -318,13 +312,6 @@ sub payment_gateway { } - unless ( $payment_gateway->gateway_namespace ) { - $payment_gateway->gateway_namespace( - scalar($conf->config('business-onlinepayment-namespace')) - || 'Business::OnlinePayment' - ); - } - $payment_gateway; } diff --git a/FS/FS/bill_batch.pm b/FS/FS/bill_batch.pm deleted file mode 100644 index 136db0d9e..000000000 --- a/FS/FS/bill_batch.pm +++ /dev/null @@ -1,151 +0,0 @@ -package FS::bill_batch; - -use strict; -use vars qw( @ISA $me $DEBUG ); -use FS::Record qw( qsearch qsearchs dbh ); -use FS::cust_bill_batch; - -@ISA = qw( FS::Record ); -$me = '[ FS::bill_batch ]'; -$DEBUG=0; - -sub table { 'bill_batch' } - -sub nohistory_fields { 'pdf' } - -=head1 NAME - -FS::bill_batch - Object methods for bill_batch records - -=head1 SYNOPSIS - - use FS::bill_batch; - - $open_batch = FS::bill_batch->get_open_batch; - - my $pdf = $open_batch->print_pdf; - - $error = $open_batch->close; - -=head1 DESCRIPTION - -An FS::bill_batch object represents a batch of invoices. FS::bill_batch -inherits from FS::Record. The following fields are currently supported: - -=over 4 - -=item batchnum - primary key - -=item status - either 'O' (open) or 'R' (resolved/closed). - -=item pdf - blob field for temporarily storing the invoice as a PDF. - -=back - -=head1 METHODS - -=over 4 - -=item print_pdf - -Typeset the entire batch as a PDF file. Returns the PDF as a string. - -=cut - -sub print_pdf { - eval 'use CAM::PDF'; - warn "Failed to load CAM::PDF: '$@'\n" if $@; - - my $self = shift; - my $job = shift; - $job->update_statustext(0) if $job; - my @invoices = sort { $a->invnum <=> $b->invnum } - qsearch('cust_bill_batch', { batchnum => $self->batchnum }); - return "No invoices in batch ".$self->batchnum.'.' if !@invoices; - - my $pdf_out; - my $num = 0; - foreach my $invoice (@invoices) { - my $part = $invoice->cust_bill->print_pdf({$invoice->options}); - die 'Failed creating PDF from invoice '.$invoice->invnum.'\n' if !$part; - - if($pdf_out) { - $pdf_out->appendPDF(CAM::PDF->new($part)); - } - else { - $pdf_out = CAM::PDF->new($part); - } - if($job) { - # update progressbar - $num++; - my $error = $job->update_statustext(int(100 * $num/scalar(@invoices))); - die $error if $error; - } - } - - return $pdf_out->toPDF; -} - -=item close - -Set the status of the batch to 'R' (resolved). - -=cut - -sub close { - my $self = shift; - $self->status('R'); - return $self->replace; -} - -=back - -=head1 CLASS METHODS - -=item get_open_batch - -Returns the currently open batch. There should only be one at a time. - -=cut - -sub get_open_batch { - my $class = shift; - my $batch = qsearchs('bill_batch', { status => 'O' }); - return $batch if $batch; - $batch = FS::bill_batch->new({status => 'O'}); - my $error = $batch->insert; - die $error if $error; - return $batch; -} - -use Storable 'thaw'; -use Data::Dumper; -use MIME::Base64; - -sub process_print_pdf { - my $job = shift; - my $param = thaw(decode_base64(shift)); - warn Dumper($param) if $DEBUG; - die "no batchnum specified!\n" if ! exists($param->{batchnum}); - my $batch = FS::bill_batch->by_key($param->{batchnum}); - die "batch '$param->{batchnum}' not found!\n" if !$batch; - - my $pdf = $batch->print_pdf($job); - $batch->pdf($pdf); - my $error = $batch->replace; - die $error if $error; -} - - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm index e8be08056..2426f4191 100644 --- a/FS/FS/cdr.pm +++ b/FS/FS/cdr.pm @@ -285,10 +285,6 @@ sub check { # ; # return $error if $error; - for my $f ( grep { $self->$_ =~ /[a-z ]/i } qw( startdate enddate ) ) { - $self->$f( str2time($self->$f) ); - } - $self->calldate( $self->startdate_sql ) if !$self->calldate && $self->startdate; @@ -324,19 +320,15 @@ sub check { $self->SUPER::check; } -=item is_tollfree [ COLUMN ] - -Returns true when the cdr represents a toll free number and false otherwise. +=item is_tollfree -By default, inspects the dst field, but an optional column name can be passed -to inspect other field. + Returns true when the cdr represents a toll free number and false otherwise. =cut sub is_tollfree { my $self = shift; - my $field = scalar(@_) ? shift : 'dst'; - ( $self->$field() =~ /^(\+?1)?8(8|([02-7])\3)/ ) ? 1 : 0; + ( $self->dst =~ /^(\+?1)?8(8|([02-7])\3)/ ) ? 1 : 0; } =item set_charged_party @@ -365,11 +357,6 @@ sub set_charged_party { if $conf->exists('cdr-charged_party-accountcode-trim_leading_0s'); $self->charged_party( $charged_party ); - } elsif ( $conf->exists('cdr-charged_party-field') ) { - - my $field = $conf->config('cdr-charged_party-field'); - $self->charged_party( $self->$field() ); - } else { if ( $self->is_tollfree ) { @@ -539,86 +526,73 @@ my %export_names = ( }, ); -my %export_formats = (); -sub export_formats { - #my $self = shift; - - return %export_formats if keys %export_formats; - - my $conf = new FS::Conf; - my $date_format = $conf->config('date_format') || '%m/%d/%Y'; - - my $duration_sub = sub { - my($cdr, %opt) = @_; - if ( $opt{minutes} ) { - $opt{minutes}. ( $opt{granularity} ? 'm' : ' call' ); - } else { - #config if anyone really wants decimal minutes back - #sprintf('%.2fm', $cdr->billsec / 60 ); - int($cdr->billsec / 60).'m '. ($cdr->billsec % 60).'s'; - } - }; - - %export_formats = ( - 'simple' => [ - sub { time2str($date_format, shift->calldate_unix ) }, #DATE - sub { time2str('%r', shift->calldate_unix ) }, #TIME - 'userfield', #USER - 'dst', #NUMBER_DIALED - $duration_sub, #DURATION - #sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE - sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE - ], - 'simple2' => [ - sub { time2str($date_format, shift->calldate_unix ) }, #DATE - sub { time2str('%r', shift->calldate_unix ) }, #TIME - #'userfield', #USER - 'src', #called from - 'dst', #NUMBER_DIALED - $duration_sub, #DURATION - #sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE - sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE - ], - 'default' => [ - - #DATE - sub { time2str($date_format, shift->calldate_unix ) }, - # #time2str("%Y %b %d - %r", $cdr->calldate_unix ), - - #TIME - sub { time2str('%r', shift->calldate_unix ) }, - # time2str("%c", $cdr->calldate_unix), #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot - - #DEST ("Number") - sub { my($cdr, %opt) = @_; $opt{pretty_dst} || $cdr->dst; }, - - #REGIONNAME ("Destination") - sub { my($cdr, %opt) = @_; $opt{dst_regionname}; }, - - #DURATION - $duration_sub, - - #PRICE - sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, - - ], - ); - $export_formats{'source_default'} = [ 'src', @{ $export_formats{'default'} }, ]; - $export_formats{'accountcode_default'} = - [ @{ $export_formats{'default'} }[0,1], - 'accountcode', - @{ $export_formats{'default'} }[2..5], - ]; - - %export_formats -} +my $duration_sub = sub { + my($cdr, %opt) = @_; + if ( $opt{minutes} ) { + $opt{minutes}. ( $opt{granularity} ? 'm' : ' call' ); + } else { + #config if anyone really wants decimal minutes back + #sprintf('%.2fm', $cdr->billsec / 60 ); + int($cdr->billsec / 60).'m '. ($cdr->billsec % 60).'s'; + } +}; + +my %export_formats = ( + 'simple' => [ + sub { time2str('%D', shift->calldate_unix ) }, #DATE + sub { time2str('%r', shift->calldate_unix ) }, #TIME + 'userfield', #USER + 'dst', #NUMBER_DIALED + $duration_sub, #DURATION + #sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE + sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE + ], + 'simple2' => [ + sub { time2str('%D', shift->calldate_unix ) }, #DATE + sub { time2str('%r', shift->calldate_unix ) }, #TIME + #'userfield', #USER + 'src', #called from + 'dst', #NUMBER_DIALED + $duration_sub, #DURATION + #sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE + sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, #PRICE + ], + 'default' => [ + + #DATE + sub { time2str('%D', shift->calldate_unix ) }, + # #time2str("%Y %b %d - %r", $cdr->calldate_unix ), + + #TIME + sub { time2str('%r', shift->calldate_unix ) }, + # time2str("%c", $cdr->calldate_unix), #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot + + #DEST ("Number") + sub { my($cdr, %opt) = @_; $opt{pretty_dst} || $cdr->dst; }, + + #REGIONNAME ("Destination") + sub { my($cdr, %opt) = @_; $opt{dst_regionname}; }, + + #DURATION + $duration_sub, + + #PRICE + sub { my($cdr, %opt) = @_; $opt{money_char}. $opt{charge}; }, + + ], +); +$export_formats{'source_default'} = [ 'src', @{ $export_formats{'default'} }, ]; +$export_formats{'accountcode_default'} = + [ @{ $export_formats{'default'} }[0,1], + 'accountcode', + @{ $export_formats{'default'} }[2..5], + ]; sub downstream_csv { my( $self, %opt ) = @_; my $format = $opt{'format'}; - my %formats = $self->export_formats; - return "Unknown format $format" unless exists $formats{$format}; + return "Unknown format $format" unless exists $export_formats{$format}; #my $conf = new FS::Conf; #$opt{'money_char'} ||= $conf->config('money_char') || '$'; @@ -632,7 +606,7 @@ sub downstream_csv { map { ref($_) ? &{$_}($self, %opt) : $self->$_(); } - @{ $formats{$format} }; + @{ $export_formats{$format} }; my $status = $csv->combine(@columns); die "FS::CDR: error combining ". $csv->error_input(). "into downstream CSV" @@ -773,9 +747,6 @@ sub _cdr_date_parse { } elsif ( $date =~ /^\s*(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d+\.\d+)(\D|$)/ ) { # broadsoft: 20081223201938.314 ($year, $mon, $day, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6 ); - } elsif ( $date =~ /^\s*(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\d+(\D|$)/ ) { - # Taqua OM: 20050422203450943 - ($year, $mon, $day, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6 ); } elsif ( $date =~ /^\s*(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/ ) { # WIP: 20100329121420 ($year, $mon, $day, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6 ); @@ -845,10 +816,6 @@ my %import_options = ( { map { $_ => $cdr_info{$_}->{'fixedlength_format'}; } keys %cdr_info }, - - 'format_row_callbacks' => { map { $_ => $cdr_info{$_}->{'row_callback'}; } - keys %cdr_info - }, ); sub _import_options { @@ -899,14 +866,9 @@ sub _upgrade_data { my %cdrbatchnum = (); while (my $row = $sth->fetchrow_arrayref) { - - my $cdr_batch = qsearchs( 'cdr_batch', { 'cdrbatch' => $row->[0] } ); - unless ( $cdr_batch ) { - $cdr_batch = new FS::cdr_batch { 'cdrbatch' => $row->[0] }; - my $error = $cdr_batch->insert; - die $error if $error; - } - + my $cdr_batch = new FS::cdr_batch { 'cdrbatch' => $row->[0] }; + my $error = $cdr_batch->insert; + die $error if $error; $cdrbatchnum{$row->[0]} = $cdr_batch->cdrbatchnum; } diff --git a/FS/FS/cdr/taqua_om.pm b/FS/FS/cdr/taqua_om.pm deleted file mode 100644 index c94ea5923..000000000 --- a/FS/FS/cdr/taqua_om.pm +++ /dev/null @@ -1,19 +0,0 @@ -package FS::cdr::taqua_om; - -use strict; -use vars qw( %info ); -use base qw( FS::cdr::taqua ); - -%info = ( - %FS::cdr::taqua::info, - 'name' => 'Taqua OM', - 'weight' => 132, - 'header' => 0, - 'sep_char' => ';', - 'row_callback' => sub { my $row = shift; - $row =~ s/^<\d+>\|[\da-f\|]+\|(\d+;)/$1/; - $row; - }, -); - -1; diff --git a/FS/FS/cdr/wip.pm b/FS/FS/cdr/wip.pm index 19c45c680..070e25343 100644 --- a/FS/FS/cdr/wip.pm +++ b/FS/FS/cdr/wip.pm @@ -17,10 +17,7 @@ use FS::cdr qw(_cdr_date_parser_maker); # except that we assume that before all the fields mentioned in the # spec, there's a counter field. skip(4), # counter, id, APCSJursID, RecordType - sub { my($cdr, $data, $conf, $param) = @_; - $param->{skiprow} = 1 if $data == 1; - $cdr->uniqueid($data); - }, # CDRID; is 1 for line charge records + 'unique_id', # CDRID skip(1), # AccountNumber; empty 'charged_party', # ServiceNumber skip(1), # ServiceNumberType @@ -40,6 +37,10 @@ use FS::cdr qw(_cdr_date_parser_maker); 'upstream_price', # ISPBuy skip(2), # EUBuy, CDRFromCarrier ], +# Need clarification on: +# Values for RecordType, Jurisdiction, CompletionStatus, and ProviderClass +# Do we care about the following: +# AccountNumber, ServiceNumberType, CDRStatus ); diff --git a/FS/FS/cgp_rule.pm b/FS/FS/cgp_rule.pm index e9c50901a..ad5ab1e1b 100644 --- a/FS/FS/cgp_rule.pm +++ b/FS/FS/cgp_rule.pm @@ -100,12 +100,11 @@ sub insert { return $error; } - #conditions and actions not in yet - #$error = $self->svc_export; - #if ( $error ) { - # $dbh->rollback if $oldAutoCommit; - # return $error; - #} + $error = $self->svc_export; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -189,12 +188,11 @@ sub replace { return $error; } - #conditions and actions not in yet - #$error = $new->svc_export; - #if ( $error ) { - # $dbh->rollback if $oldAutoCommit; - # return $error; - #} + $error = $new->svc_export; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -248,47 +246,6 @@ sub check { $self->SUPER::check; } -=item clone NEW_SVCNUM - -Clones this rule into an identical rule for the specified new service. - -If there is an error, returns the error, otherwise returns false. - -=cut - -#should return the newly inserted rule instead? used in misc/clone-cgp_rule.html - -#i should probably be transactionalized so i'm all-or-nothing -sub clone { - my( $self, $svcnum ) = @_; - - my $new = $self->new( { $self->hash } ); - $new->rulenum(''); - $new->svcnum( $svcnum ); - my $error = $new->insert; - return $error if $error; - - my @dup = $self->cgp_rule_condition; - push @dup, $self->cgp_rule_action; - - foreach my $dup (@dup) { - my $new_dup = $dup->new( { $dup->hash } ); - my $pk = $new_dup->primary_key; - $new_dup->$pk(''); - $new_dup->rulenum( $new->rulenum ); - - $error = $new_dup->insert; - return $error if $error; - - } - - $error = $new->svc_export; - return $error if $error; - - ''; - -} - =item cust_svc =cut diff --git a/FS/FS/cgp_rule_condition.pm b/FS/FS/cgp_rule_condition.pm index 772e1899e..02ea1729d 100644 --- a/FS/FS/cgp_rule_condition.pm +++ b/FS/FS/cgp_rule_condition.pm @@ -36,7 +36,7 @@ currently supported: primary key -=item conditionname +=item condition condition @@ -113,7 +113,7 @@ sub check { my $error = $self->ut_numbern('ruleconditionnum') - || $self->ut_text('conditionname') + || $self->ut_text('condition') || $self->ut_textn('op') || $self->ut_textn('params') || $self->ut_foreign_key('rulenum', 'cgp_rule', 'rulenum') @@ -125,13 +125,13 @@ sub check { =item arrayref -Returns an array reference of the conditionname, op and params fields. +Returns an array reference of the condition, op and params fields. =cut sub arrayref { my $self = shift; - [ map $self->$_, qw( conditionname op params ) ]; + [ map $self->$_, qw( condition op params ) ]; } =back diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 4bd9aa16a..127053013 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -34,8 +34,6 @@ use FS::cust_bill_pay; use FS::cust_bill_pay_batch; use FS::part_bill_event; use FS::payby; -use FS::bill_batch; -use FS::cust_bill_batch; @ISA = qw( FS::cust_main_Mixin FS::Record ); @@ -1302,13 +1300,7 @@ sub print { 'notice_name' => $notice_name, ); - if($conf->exists('invoice_print_pdf')) { - # Add the invoice to the current batch. - $self->batch_invoice(\%opt); - } - else { - do_print $self->lpr_data(\%opt); - } + do_print $self->lpr_data(\%opt); } =item fax_invoice HASHREF | [ TEMPLATE ] @@ -1354,23 +1346,6 @@ sub fax_invoice { } -=item batch_invoice [ HASHREF ] - -Place this invoice into the open batch (see C<FS::bill_batch>). If there -isn't an open batch, one will be created. - -=cut - -sub batch_invoice { - my ($self, $opt) = @_; - my $batch = FS::bill_batch->get_open_batch; - my $cust_bill_batch = FS::cust_bill_batch->new({ - batchnum => $batch->batchnum, - invnum => $self->invnum, - }); - return $cust_bill_batch->insert($opt); -} - =item ftp_invoice [ TEMPLATENAME ] Sends this invoice data via FTP. @@ -2324,13 +2299,11 @@ sub print_generic { } - my $agentnum = $self->cust_main->agentnum; - my %invoice_data = ( #invoice from info - 'company_name' => scalar( $conf->config('company_name', $agentnum) ), - 'company_address' => join("\n", $conf->config('company_address', $agentnum) ). "\n", + 'company_name' => scalar( $conf->config('company_name', $self->cust_main->agentnum) ), + 'company_address' => join("\n", $conf->config('company_address', $self->cust_main->agentnum) ). "\n", 'returnaddress' => $returnaddress, 'agent' => &$escape_function($cust_main->agent->agent), @@ -2358,19 +2331,6 @@ sub print_generic { 'smallerfooter' => $conf->exists('invoice-smallerfooter'), 'balance_due_below_line' => $conf->exists('balance_due_below_line'), - #layout info -- would be fancy to calc some of this and bury the template - # here in the code - 'topmargin' => scalar($conf->config('invoice_latextopmargin', $agentnum)), - 'headsep' => scalar($conf->config('invoice_latexheadsep', $agentnum)), - 'textheight' => scalar($conf->config('invoice_latextextheight', $agentnum)), - 'extracouponspace' => scalar($conf->config('invoice_latexextracouponspace', $agentnum)), - 'couponfootsep' => scalar($conf->config('invoice_latexcouponfootsep', $agentnum)), - 'verticalreturnaddress' => $conf->exists('invoice_latexverticalreturnaddress', $agentnum), - 'addresssep' => scalar($conf->config('invoice_latexaddresssep', $agentnum)), - 'amountenclosedsep' => scalar($conf->config('invoice_latexcouponamountenclosedsep', $agentnum)), - 'coupontoaddresssep' => scalar($conf->config('invoice_latexcoupontoaddresssep', $agentnum)), - 'addcompanytoaddress' => $conf->exists('invoice_latexcouponaddcompanytoaddress', $agentnum), - # better hang on to conf_dir for a while (for old templates) 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc", @@ -2439,6 +2399,8 @@ sub print_generic { $invoice_data{'previous_balance'} = sprintf("%.2f", $pr_total); $invoice_data{'balance'} = sprintf("%.2f", $balance_due); + my $agentnum = $self->cust_main->agentnum; + my $summarypage = ''; if ( $conf->exists('invoice_usesummary', $agentnum) ) { $summarypage = 1; @@ -2621,12 +2583,6 @@ sub print_generic { foreach my $section (@sections, @$late_sections) { - # begin some normalization - $section->{'subtotal'} = $section->{'amount'} - if $multisection - && !exists($section->{subtotal}) - && exists($section->{amount}); - $invoice_data{finance_amount} = sprintf('%.2f', $section->{'subtotal'} ) if ( $invoice_data{finance_section} && $section->{'description'} eq $invoice_data{finance_section} ); @@ -2635,7 +2591,7 @@ sub print_generic { sprintf('%.2f', $section->{'subtotal'}) if $multisection; - # continue some normalization + # begin some normalization $section->{'amount'} = $section->{'subtotal'} if $multisection; @@ -3397,9 +3353,7 @@ my %condensed_format = ( 'fields' => [ sub { shift->{description} }, sub { shift->{quantity} }, - sub { my($href, %opt) = @_; - ($opt{dollar} || ''). $href->{amount}; - }, + sub { shift->{amount} }, ], 'align' => [ qw( l r r ) ], 'span' => [ qw( 5 1 1 ) ], # unitprices? @@ -3473,7 +3427,6 @@ sub _condensed_description_generator { my ( $f, $prefix, $suffix, $separator, $column ) = _condensed_generator_defaults($format); - my $money_char = '$'; if ($format eq 'latex') { $prefix = "\\hline\n\\multicolumn{1}{c}{\\rule{0pt}{2.5ex}~} &\n"; $suffix = '\\\\'; @@ -3482,7 +3435,6 @@ sub _condensed_description_generator { sub { my ($d,$a,$s,$w) = @_; return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{\\textbf{$d}}}"; }; - $money_char = '\\dollar'; }elsif ( $format eq 'html' ) { $prefix = '"><td align="center"></td>'; $suffix = ''; @@ -3491,22 +3443,16 @@ sub _condensed_description_generator { sub { my ($d,$a,$s,$w) = @_; return qq!<td align="$html_align{$a}">$d</td>!; }; - #$money_char = $conf->config('money_char') || '$'; - $money_char = ''; # this is madness } sub { - #my @args = @_; - my $href = shift; + my @args = @_; my @result = (); foreach (my $i = 0; $f->{label}->[$i]; $i++) { - my $dollar = ''; - $dollar = $money_char if $i == scalar(@{$f->{label}})-1; - push @result, - &{$column}( &{$f->{fields}->[$i]}($href, 'dollar' => $dollar), - map { $f->{$_}->[$i] } qw(align span width) - ); + push @result, &{$column}( &{$f->{fields}->[$i]}(@args), + map { $f->{$_}->[$i] } qw(align span width) + ); } $prefix. join( $separator, @result ). $suffix; @@ -3751,9 +3697,6 @@ sub _items_svc_phone_sections { foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) { next unless $cust_bill_pkg->pkgnum > 0; - my @header = $cust_bill_pkg->details_header; - next unless scalar(@header); - foreach my $detail ( $cust_bill_pkg->cust_bill_pkg_detail ) { my $phonenum = $detail->phonenum; @@ -3802,7 +3745,6 @@ sub _items_svc_phone_sections { 'duration' => 0, 'sort_weight' => $usage_class{$detail->classnum}->weight, 'phonenum' => $phonenum, - 'header' => [ @header ], }; $sections{"$phonenum $line"}{amount} += $amount; #subtotal $sections{"$phonenum $line"}{calls}++; @@ -3833,17 +3775,11 @@ sub _items_svc_phone_sections { my %sectionmap = (); my $simple = new FS::usage_class { format => 'simple' }; #bleh + my $usage_simple = new FS::usage_class { format => 'usage_simple' }; #bleh foreach ( keys %sections ) { - my @header = @{ $sections{$_}{header} || [] }; - my $usage_simple = - new FS::usage_class { format => 'usage_'. (scalar(@header) || 6). 'col' }; my $summary = $sections{$_}{sort_weight} < 0 ? 1 : 0; my $usage_class = $summary ? $simple : $usage_simple; my $ending = $summary ? ' usage charges' : ''; - my %gen_opt = (); - unless ($summary) { - $gen_opt{label} = [ map{ &{$escape}($_) } @header ]; - } $sectionmap{$_} = { 'description' => &{$escape}($_. $ending), 'amount' => $sections{$_}{amount}, #subtotal 'calls' => $sections{$_}{calls}, @@ -3854,7 +3790,7 @@ sub _items_svc_phone_sections { 'sort_weight' => $sections{$_}{sort_weight}, 'post_total' => $summary, #inspire pagebreak ( - ( map { $_ => $usage_class->$_($format, %gen_opt) } + ( map { $_ => $usage_class->$_($format) } qw( description_generator header_generator total_generator @@ -3963,12 +3899,12 @@ sub _items_pkg { } sub _taxsort { - return 0 unless $a->itemdesc cmp $b->itemdesc; - return -1 if $b->itemdesc eq 'Tax'; - return 1 if $a->itemdesc eq 'Tax'; - return -1 if $b->itemdesc eq 'Other surcharges'; - return 1 if $a->itemdesc eq 'Other surcharges'; - $a->itemdesc cmp $b->itemdesc; + return 0 unless $a cmp $b; + return -1 if $b eq 'Tax'; + return 1 if $a eq 'Tax'; + return -1 if $b eq 'Other surcharges'; + return 1 if $a eq 'Other surcharges'; + $a cmp $b; } sub _items_tax { diff --git a/FS/FS/cust_bill_ApplicationCommon.pm b/FS/FS/cust_bill_ApplicationCommon.pm index afb90f40e..322728fad 100644 --- a/FS/FS/cust_bill_ApplicationCommon.pm +++ b/FS/FS/cust_bill_ApplicationCommon.pm @@ -418,10 +418,10 @@ sub apply_to_lineitems { foreach my $cust_svc ( $cust_pkg->cust_svc ) { my $svc_x = $cust_svc->svc_x; - my @part_export = grep { $_->can('_export_insert_on_payment') } + my @part_export = grep { $_->can('export_insert_on_payment') } $cust_svc->part_svc->part_export; - foreach my $part_export ( @part_export ) { + foreach my $part_export ( $cust_svc->part_svc->part_export ) { $error = $part_export->_export_insert_on_payment($svc_x); if ( $error ) { $dbh->rollback if $oldAutoCommit; diff --git a/FS/FS/cust_bill_batch.pm b/FS/FS/cust_bill_batch.pm deleted file mode 100644 index 4569e6bc8..000000000 --- a/FS/FS/cust_bill_batch.pm +++ /dev/null @@ -1,70 +0,0 @@ -package FS::cust_bill_batch; - -use strict; -use vars qw( @ISA $me $DEBUG ); -use FS::Record qw( qsearch qsearchs dbh ); - -@ISA = qw( FS::option_Common ); -$me = '[ FS::cust_bill_batch ]'; -$DEBUG=0; - -sub table { 'cust_bill_batch' } - -=head1 NAME - -FS::cust_bill_batch - Object methods for cust_bill_batch records - -=head1 DESCRIPTION - -An FS::cust_bill_batch object represents the inclusion of an invoice in a -processing batch. FS::cust_bill_batch inherits from FS::option_Common. The -following fields are currently supported: - -=over 4 - -=item billbatchnum - primary key - -=item invnum - invoice number (see C<FS::cust_bill>) - -=item batchnum - batchn number (see C<FS::bill_batch>) - -=back - -=head1 METHODS - -=over 4 - -=item bill_batch - -Returns the C<FS::bill_batch> object. - -=cut - -sub bill_batch { - my $self = shift; - FS::bill_batch->by_key($self->batchnum); -} - -=item cust_bill - -Returns the C<FS::cust_bill> object. - -=cut - -sub cust_bill { - my $self = shift; - FS::cust_bill->by_key($self->invnum); -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/cust_bill_batch_option.pm b/FS/FS/cust_bill_batch_option.pm deleted file mode 100644 index 9bba830fd..000000000 --- a/FS/FS/cust_bill_batch_option.pm +++ /dev/null @@ -1,126 +0,0 @@ -package FS::cust_bill_batch_option; - -use strict; -use vars qw( @ISA ); -use FS::Record qw( qsearch qsearchs ); - -@ISA = qw(FS::Record); - -=head1 NAME - -FS::cust_bill_batch_option - Object methods for cust_bill_batch_option records - -=head1 SYNOPSIS - - use FS::cust_bill_batch_option; - - $record = new FS::cust_bill_batch_option \%hash; - $record = new FS::cust_bill_batch_option { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::cust_bill_batch_option object represents an option key and value for -an invoice batch entry. FS::cust_bill_batch_option inherits from -FS::Record. The following fields are currently supported: - -=over 4 - -=item optionnum - primary key - -=item billbatchnum - - -=item optionname - - -=item optionvalue - - - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new option. To add the option to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -# the new method can be inherited from FS::Record, if a table method is defined - -sub table { 'cust_bill_batch_option'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -# the insert method can be inherited from FS::Record - -=item delete - -Delete this record from the database. - -=cut - -# the delete method can be inherited from FS::Record - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -# the replace method can be inherited from FS::Record - -=item check - -Checks all fields to make sure this is a valid option. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -# the check method should currently be supplied - FS::Record contains some -# data checking routines - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('optionnum') - || $self->ut_foreign_key('billbatchnum', 'cust_bill_batch', 'billbatchnum') - || $self->ut_text('optionname') - || $self->ut_textn('optionvalue') - ; - return $error if $error; - - $self->SUPER::check; -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm index d396f8239..c825c1567 100644 --- a/FS/FS/cust_bill_pkg.pm +++ b/FS/FS/cust_bill_pkg.pm @@ -480,35 +480,6 @@ sub details { #qsearch ( 'cust_bill_pkg_detail', { 'lineitemnum' => $self->lineitemnum }); } -=item details_header [ OPTION => VALUE ... ] - -Returns a list representing an invoice line item detail header, if any. -This relies on the behavior of voip_cdr in that it expects the header -to be the first CSV formatted detail (as is expected by invoice generation -routines). Returns the empty list otherwise. - -=cut - -sub details_header { - my $self = shift; - return '' unless defined dbdef->table('cust_bill_pkg_detail'); - - eval "use Text::CSV_XS;"; - die $@ if $@; - my $csv = new Text::CSV_XS; - - my @detail = - qsearch ({ 'table' => 'cust_bill_pkg_detail', - 'hashref' => { 'billpkgnum' => $self->billpkgnum, - 'format' => 'C', - }, - 'order_by' => 'ORDER BY detailnum LIMIT 1', - }); - return() unless scalar(@detail); - $csv->parse($detail[0]->detail) or return (); - $csv->fields; -} - =item desc Returns a description for this line item. For typical line items, this is the diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm index 1ddcb8b9f..674bc1047 100644 --- a/FS/FS/cust_credit.pm +++ b/FS/FS/cust_credit.pm @@ -2,7 +2,7 @@ package FS::cust_credit; use strict; use base qw( FS::otaker_Mixin FS::cust_main_Mixin FS::Record ); -use vars qw( $conf $unsuspendauto $me $DEBUG $otaker_upgrade_kludge ); +use vars qw( $conf $unsuspendauto $me $DEBUG ); use Date::Format; use FS::UID qw( dbh getotaker ); use FS::Misc qw(send_email); @@ -19,8 +19,6 @@ use FS::cust_event; $me = '[ FS::cust_credit ]'; $DEBUG = 0; -$otaker_upgrade_kludge = 0; - #ask FS::UID to run this stuff for us later $FS::UID::callback{'FS::cust_credit'} = sub { @@ -310,7 +308,7 @@ sub check { return "amount must be > 0 " if $self->amount <= 0; return "amount must be greater or equal to amount applied" - if $self->unapplied < 0 && ! $otaker_upgrade_kludge; + if $self->unapplied < 0; return "Unknown customer" unless qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); @@ -550,7 +548,6 @@ sub _upgrade_data { # class method } } - local($otaker_upgrade_kludge) = 1; $class->_upgrade_otaker(%opts); } diff --git a/FS/FS/cust_credit_bill_pkg.pm b/FS/FS/cust_credit_bill_pkg.pm index 019a1a874..158fc73a7 100644 --- a/FS/FS/cust_credit_bill_pkg.pm +++ b/FS/FS/cust_credit_bill_pkg.pm @@ -131,7 +131,7 @@ sub insert { my $cust_tax_exempt_pkg = new FS::cust_tax_exempt_pkg { 'billpkgnum' => $self->billpkgnum, 'creditbillpkgnum' => $self->creditbillpkgnum, - 'amount' => sprintf('%.2f', 0-$amount), + 'amount' => 0-$amount, map { $_ => $exemption->$_ } split(',', $groupby) }; my $error = $cust_tax_exempt_pkg->insert; diff --git a/FS/FS/cust_event.pm b/FS/FS/cust_event.pm index 1407f43c8..52b5911dc 100644 --- a/FS/FS/cust_event.pm +++ b/FS/FS/cust_event.pm @@ -222,6 +222,9 @@ sub do_event { " (". $part_event->action. ") $for\n" if $DEBUG; + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $error; { local $SIG{__DIE__}; # don't want Mason __DIE__ handler active diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 002b0c1d1..c1a8aafde 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -16,8 +16,6 @@ use Exporter; use Scalar::Util qw( blessed ); use List::Util qw( min ); use Time::Local qw(timelocal); -use Storable qw(thaw); -use MIME::Base64; use Data::Dumper; use Tie::IxHash; use Digest::MD5 qw(md5_base64); @@ -57,7 +55,6 @@ use FS::cust_tax_location; use FS::part_pkg_taxrate; use FS::agent; use FS::cust_main_invoice; -use FS::cust_tag; use FS::cust_credit_bill; use FS::cust_bill_pay; use FS::prepay_credit; @@ -65,7 +62,6 @@ use FS::queue; use FS::part_pkg; use FS::part_event; use FS::part_event_condition; -use FS::part_export; #use FS::cust_event; use FS::type_pkgs; use FS::payment_gateway; @@ -90,7 +86,7 @@ $skip_fuzzyfiles = 0; @fuzzyfields = ( 'first', 'last', 'company', 'address1' ); @encrypted_fields = ('payinfo', 'paycvv'); -sub nohistory_fields { ('payinfo', 'paycvv'); } +sub nohistory_fields { ('paycvv'); } @paytypes = ('', 'Personal checking', 'Personal savings', 'Business checking', 'Business savings'); @@ -474,30 +470,6 @@ sub insert { $self->invoicing_list( $invoicing_list ); } - warn " setting customer tags\n" - if $DEBUG > 1; - - foreach my $tagnum ( @{ $self->tagnum || [] } ) { - my $cust_tag = new FS::cust_tag { 'tagnum' => $tagnum, - 'custnum' => $self->custnum }; - my $error = $cust_tag->insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } - } - - if ( $invoicing_list ) { - $error = $self->check_invoicing_list( $invoicing_list ); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - #return "checking invoicing_list (transaction rolled back): $error"; - return $error; - } - $self->invoicing_list( $invoicing_list ); - } - - warn " setting cust_main_exemption\n" if $DEBUG > 1; @@ -574,45 +546,6 @@ sub insert { } } - # cust_main exports! - warn " exporting\n" if $DEBUG > 1; - - my $export_args = $options{'export_args'} || []; - - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_main-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_insert($self, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; - } - } - - #foreach my $depend_jobnum ( @$depend_jobnums ) { - # warn "[$me] inserting dependancies on supplied job $depend_jobnum\n" - # if $DEBUG; - # foreach my $jobnum ( @jobnums ) { - # my $queue = qsearchs('queue', { 'jobnum' => $jobnum } ); - # warn "[$me] inserting dependancy for job $jobnum on $depend_jobnum\n" - # if $DEBUG; - # my $error = $queue->depend_insert($depend_jobnum); - # if ( $error ) { - # $dbh->rollback if $oldAutoCommit; - # return "error queuing job dependancy: $error"; - # } - # } - # } - # - #} - # - #if ( exists $options{'jobnums'} ) { - # push @{ $options{'jobnums'} }, @jobnums; - #} - warn " insert complete; committing transaction\n" if $DEBUG > 1; @@ -1381,13 +1314,23 @@ sub delete { } } - foreach my $table (qw( cust_main_invoice cust_main_exemption cust_tag )) { - foreach my $record ( qsearch( 'table', { 'custnum' => $self->custnum } ) ) { - my $error = $record->delete; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } + foreach my $cust_main_invoice ( #(email invoice destinations, not invoices) + qsearch( 'cust_main_invoice', { 'custnum' => $self->custnum } ) + ) { + my $error = $cust_main_invoice->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + foreach my $cust_main_exemption ( + qsearch( 'cust_main_exemption', { 'custnum' => $self->custnum } ) + ) { + my $error = $cust_main_exemption->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; } } @@ -1397,23 +1340,6 @@ sub delete { return $error; } - # cust_main exports! - - #my $export_args = $options{'export_args'} || []; - - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_main-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_delete( $self ); #, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; - } - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -1493,28 +1419,6 @@ sub replace { $self->invoicing_list( $invoicing_list ); } - if ( $self->exists('tagnum') ) { #so we don't delete these on edit by accident - - #this could be more efficient than deleting and re-inserting, if it matters - foreach my $cust_tag (qsearch('cust_tag', {'custnum'=>$self->custnum} )) { - my $error = $cust_tag->delete; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } - } - foreach my $tagnum ( @{ $self->tagnum || [] } ) { - my $cust_tag = new FS::cust_tag { 'tagnum' => $tagnum, - 'custnum' => $self->custnum }; - my $error = $cust_tag->insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } - } - - } - my %options = @param; my $tax_exemption = delete $options{'tax_exemption'}; @@ -1549,15 +1453,8 @@ sub replace { } - if ( $self->payby =~ /^(CARD|CHEK|LECB)$/ - && ( ( $self->get('payinfo') ne $old->get('payinfo') - && $self->get('payinfo') !~ /^99\d{14}$/ - ) - || grep { $self->get($_) ne $old->get($_) } qw(paydate payname) - ) - ) - { - + if ( $self->payby =~ /^(CARD|CHEK|LECB)$/ && + grep { $self->get($_) ne $old->get($_) } qw(payinfo paydate payname) ) { # card/check/lec info has changed, want to retry realtime_ invoice events my $error = $self->retry_realtime; if ( $error ) { @@ -1574,23 +1471,6 @@ sub replace { } } - # cust_main exports! - - my $export_args = $options{'export_args'} || []; - - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_main-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_replace( $self, $old, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; - } - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -1828,7 +1708,12 @@ sub check { # If it is encrypted and the private key is not availaible then we can't # check the credit card. - my $check_payinfo = ! $self->is_encrypted($self->payinfo); + + my $check_payinfo = 1; + + if ($self->is_encrypted($self->payinfo)) { + $check_payinfo = 0; + } if ( $check_payinfo && $self->payby =~ /^(CARD|DCRD)$/ ) { @@ -1842,8 +1727,7 @@ sub check { or return gettext('invalid_card'); # . ": ". $self->payinfo; return gettext('unknown_card_type') - if $self->payinfo !~ /^99\d{14}$/ #token - && cardtype($self->payinfo) eq "Unknown"; + if cardtype($self->payinfo) eq "Unknown"; my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref); if ( $ban ) { @@ -2220,9 +2104,6 @@ sub sort_packages { return 1 if !$a_num_cust_svc && $b_num_cust_svc; my @a_cust_svc = $a->cust_svc; my @b_cust_svc = $b->cust_svc; - return 0 if !scalar(@a_cust_svc) && !scalar(@b_cust_svc); - return -1 if scalar(@a_cust_svc) && !scalar(@b_cust_svc); - return 1 if !scalar(@a_cust_svc) && scalar(@b_cust_svc); $a_cust_svc[0]->svc_x->label cmp $b_cust_svc[0]->svc_x->label; } @@ -2501,42 +2382,6 @@ sub agent { qsearchs( 'agent', { 'agentnum' => $self->agentnum } ); } -=item agent_name - -Returns the agent name (see L<FS::agent>) for this customer. - -=cut - -sub agent_name { - my $self = shift; - $self->agent->agent; -} - -=item cust_tag - -Returns any tags associated with this customer, as FS::cust_tag objects, -or an empty list if there are no tags. - -=cut - -sub cust_tag { - my $self = shift; - qsearch('cust_tag', { 'custnum' => $self->custnum } ); -} - -=item part_tag - -Returns any tags associated with this customer, as FS::part_tag objects, -or an empty list if there are no tags. - -=cut - -sub part_tag { - my $self = shift; - map $_->part_tag, $self->cust_tag; -} - - =item cust_class Returns the customer class, as an FS::cust_class object, or the empty string @@ -2627,10 +2472,6 @@ Any other true value causes errors to die. Debugging level. Default is 0 (no debugging), or can be set to 1 (passed-in options), 2 (traces progress), 3 (more information), or 4 (include full search queries) -=item job - -Optional FS::queue entry to receive status updates. - =back Options are passed to the B<bill> and B<collect> methods verbatim, so all @@ -2647,9 +2488,7 @@ sub bill_and_collect { #pre-printing invoices $options{'actual_time'} ||= time; - my $job = $options{'job'}; - $job->update_statustext('0,cleaning expired packages') if $job; $error = $self->cancel_expired_pkgs( $options{actual_time} ); if ( $error ) { $error = "Error expiring custnum ". $self->custnum. ": $error"; @@ -2666,7 +2505,6 @@ sub bill_and_collect { else { warn $error; } } - $job->update_statustext('20,billing packages') if $job; $error = $self->bill( %options ); if ( $error ) { $error = "Error billing custnum ". $self->custnum. ": $error"; @@ -2675,7 +2513,6 @@ sub bill_and_collect { else { warn $error; } } - $job->update_statustext('50,applying payments and credits') if $job; $error = $self->apply_payments_and_credits; if ( $error ) { $error = "Error applying custnum ". $self->custnum. ": $error"; @@ -2684,7 +2521,6 @@ sub bill_and_collect { else { warn $error; } } - $job->update_statustext('70,running collection events') if $job; unless ( $conf->exists('cancelled_cust-noevents') && ! $self->num_ncancelled_pkgs ) { @@ -2696,7 +2532,6 @@ sub bill_and_collect { else { warn $error; } } } - $job->update_statustext('100,finished') if $job; ''; @@ -2846,14 +2681,8 @@ sub bill { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - warn "$me acquiring lock on customer ". $self->custnum. "\n" - if $DEBUG; - $self->select_for_update; #mutex - warn "$me running pre-bill events for customer ". $self->custnum. "\n" - if $DEBUG; - my $error = $self->do_cust_event( 'debug' => ( $options{'debug'} || 0 ), 'time' => $invoice_time, @@ -2865,9 +2694,6 @@ sub bill { return $error; } - warn "$me done running pre-bill events for customer ". $self->custnum. "\n" - if $DEBUG; - #keep auto-charge and non-auto-charge line items separate my @passes = ( '', 'no_auto' ); @@ -3793,17 +3619,19 @@ sub collect { } } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - - #never want to roll back an event just because it returned an error - local $FS::UID::AutoCommit = 1; #$oldAutoCommit; - - $self->do_cust_event( + my $error = $self->do_cust_event( 'debug' => ( $options{'debug'} || 0 ), 'time' => $invoice_time, 'check_freq' => $options{'check_freq'}, 'stage' => 'collect', ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; } @@ -3898,11 +3726,6 @@ sub do_cust_event { return $due_cust_event; } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - #never want to roll back an event just because it or a different one - # returned an error - local $FS::UID::AutoCommit = 1; #$oldAutoCommit; - foreach my $cust_event ( @$due_cust_event ) { #XXX lock event @@ -3911,7 +3734,11 @@ sub do_cust_event { unless ( $cust_event->test_conditions( 'time' => $time ) ) { #don't leave stray "new/locked" records around my $error = $cust_event->delete; - return $error if $error; + if ( $error ) { + #gah, even with transactions + $dbh->commit if $oldAutoCommit; #well. + return $error; + } next; } @@ -3920,16 +3747,20 @@ sub do_cust_event { warn " running cust_event ". $cust_event->eventnum. "\n" if $DEBUG > 1; + #if ( my $error = $cust_event->do_event(%options) ) { #XXX %options? if ( my $error = $cust_event->do_event() ) { #XXX wtf is this? figure out a proper dealio with return value #from do_event - return $error; - } + # gah, even with transactions. + $dbh->commit if $oldAutoCommit; #well. + return $error; + } } } + $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; } @@ -4408,7 +4239,6 @@ sub _bop_options { $options->{payment_gateway}->gatewaynum ? $options->{payment_gateway}->options : @{ $options->{payment_gateway}->get('options') }; - } sub _bop_defaults { @@ -4435,6 +4265,14 @@ sub _bop_content { my ($self, $options) = @_; my %content = (); + $content{address} = exists($options->{'address1'}) + ? $options->{'address1'} + : $self->address1; + my $address2 = exists($options->{'address2'}) + ? $options->{'address2'} + : $self->address2; + $content{address} .= ", ". $address2 if length($address2); + my $payip = exists($options->{'payip'}) ? $options->{'payip'} : $self->payip; $content{customer_ip} = $payip if length($payip); @@ -4445,30 +4283,14 @@ sub _bop_content { ( $conf->exists('business-onlinepayment-email_customer') || $conf->exists('business-onlinepayment-email-override') ); - my ($payname, $payfirst, $paylast); - if ( $options->{payname} && $options->{method} ne 'ECHECK' ) { - ($payname = $options->{payname}) =~ - /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ - or return "Illegal payname $payname"; - ($payfirst, $paylast) = ($1, $2); - } else { - $payfirst = $self->getfield('first'); - $paylast = $self->getfield('last'); - $payname = "$payfirst $paylast"; - } + $content{payfirst} = $self->getfield('first'); + $content{paylast} = $self->getfield('last'); - $content{last_name} = $paylast; - $content{first_name} = $payfirst; + $content{account_name} = "$content{payfirst} $content{paylast}" + if $options->{method} eq 'ECHECK'; - $content{name} = $payname; - - $content{address} = exists($options->{'address1'}) - ? $options->{'address1'} - : $self->address1; - my $address2 = exists($options->{'address2'}) - ? $options->{'address2'} - : $self->address2; - $content{address} .= ", ". $address2 if length($address2); + $content{name} = $options->{payname}; + $content{name} = $content{account_name} if exists($content{account_name}); $content{city} = exists($options->{city}) ? $options->{city} @@ -4482,11 +4304,10 @@ sub _bop_content { $content{country} = exists($options->{country}) ? $options->{country} : $self->country; - $content{referer} = 'http://cleanwhisker.420.am/'; #XXX fix referer :/ $content{phone} = $self->daytime || $self->night; - \%content; + (%content); } my %bop_method2payby = ( @@ -4562,8 +4383,13 @@ sub realtime_bop { # massage data ### - my $bop_content = $self->_bop_content(\%options); - return $bop_content unless ref($bop_content); + my (%bop_content) = $self->_bop_content(\%options); + + if ( $options{method} ne 'ECHECK' ) { + $options{payname} =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ + or return "Illegal payname $options{payname}"; + ($bop_content{payfirst}, $bop_content{paylast}) = ($1, $2); + } my @invoicing_list = $self->invoicing_list_emailonly; if ( $conf->exists('emailinvoiceautoalways') @@ -4629,9 +4455,6 @@ sub realtime_bop { $content{account_type} = exists($options{'paytype'}) ? uc($options{'paytype'}) || 'CHECKING' : uc($self->getfield('paytype')) || 'CHECKING'; - $content{account_name} = $self->getfield('first'). ' '. - $self->getfield('last'); - $content{customer_org} = $self->company ? 'B' : 'I'; $content{state_id} = exists($options{'stateid'}) ? $options{'stateid'} @@ -4716,7 +4539,7 @@ sub realtime_bop { 'amount' => $options{amount}, #'invoice_number' => $options{'invnum'}, 'customer_id' => $self->custnum, - %$bop_content, + %bop_content, 'reference' => $cust_pay_pending->paypendingnum, #for now 'email' => $email, %content, #after @@ -4731,8 +4554,6 @@ sub realtime_bop { my $BOP_TESTING_SUCCESS = 1; unless ( $BOP_TESTING ) { - $transaction->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $transaction->submit(); } else { if ( $BOP_TESTING_SUCCESS ) { @@ -4785,8 +4606,6 @@ sub realtime_bop { $capture->content( %capture ); - $capture->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $capture->submit(); unless ( $capture->is_success ) { @@ -4816,25 +4635,6 @@ sub realtime_bop { } ### - # Tokenize - ### - - - if ( $transaction->can('card_token') && $transaction->card_token ) { - - $self->card_token($transaction->card_token); - - if ( $options{'payinfo'} eq $self->payinfo ) { - $self->payinfo($transaction->card_token); - my $error = $self->replace; - if ( $error ) { - warn "WARNING: error storing token: $error, but proceeding anyway\n"; - } - } - - } - - ### # result handling ### @@ -4957,7 +4757,7 @@ sub _realtime_bop_result { 'paid' => $cust_pay_pending->paid, '_date' => '', 'payby' => $cust_pay_pending->payby, - 'payinfo' => $options{'payinfo'}, + #'payinfo' => $payinfo, 'paybatch' => $paybatch, 'paydate' => $cust_pay_pending->paydate, 'pkgnum' => $cust_pay_pending->pkgnum, @@ -5111,39 +4911,28 @@ sub _realtime_bop_result { && ! grep { $transaction->error_message =~ /$_/ } $conf->config('emaildecline-exclude') ) { + my @templ = $conf->config('declinetemplate'); + my $template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", @templ ], + ) or return "($perror) can't create template: $Text::Template::ERROR"; + $template->compile() + or return "($perror) can't compile template: $Text::Template::ERROR"; + + my $templ_hash = { + 'company_name' => + scalar( $conf->config('company_name', $self->agentnum ) ), + 'company_address' => + join("\n", $conf->config('company_address', $self->agentnum ) ), + 'error' => $transaction->error_message, + }; - # Send a decline alert to the customer. - my $msgnum = $conf->config('decline_msgnum', $self->agentnum); - my $error = ''; - if ( $msgnum ) { - my $msg_template = qsearchs('msg_template', { msgnum => $msgnum }); - $error = $msg_template->send( 'cust_main' => $self ); - } - else { #!$msgnum - - my @templ = $conf->config('declinetemplate'); - my $template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", @templ ], - ) or return "($perror) can't create template: $Text::Template::ERROR"; - $template->compile() - or return "($perror) can't compile template: $Text::Template::ERROR"; - - my $templ_hash = { - 'company_name' => - scalar( $conf->config('company_name', $self->agentnum ) ), - 'company_address' => - join("\n", $conf->config('company_address', $self->agentnum ) ), - 'error' => $transaction->error_message, - }; - - my $error = send_email( - 'from' => $conf->config('invoice_from', $self->agentnum ), - 'to' => [ grep { $_ ne 'POST' } $self->invoicing_list ], - 'subject' => 'Your payment could not be processed', - 'body' => [ $template->fill_in(HASH => $templ_hash) ], - ); - } + my $error = send_email( + 'from' => $conf->config('invoice_from', $self->agentnum ), + 'to' => [ grep { $_ ne 'POST' } $self->invoicing_list ], + 'subject' => 'Your payment could not be processed', + 'body' => [ $template->fill_in(HASH => $templ_hash) ], + ); $perror .= " (also received error sending decline notification: $error)" if $error; @@ -5372,7 +5161,7 @@ sub realtime_refund_bop { my $self = shift; my %options = (); - if (ref($_[0]) eq 'HASH') { + if (ref($_[0]) ne 'HASH') { %options = %{$_[0]}; } else { my $method = shift; @@ -5504,8 +5293,6 @@ sub realtime_refund_bop { } } $void->content( 'action' => 'void', %content ); - $void->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $void->submit(); if ( $void->is_success ) { my $error = $cust_pay->void($options{'reason'}); @@ -5608,8 +5395,6 @@ sub realtime_refund_bop { ); warn join('', map { " $_ => $sub_content{$_}\n" } keys %sub_content ) if $DEBUG > 1; - $refund->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $refund->submit(); return "$processor error: ". $refund->error_message @@ -6048,17 +5833,29 @@ sub total_owed_date { my $self = shift; my $time = shift; - my $custnum = $self->custnum; - - my $owed_sql = FS::cust_bill->owed_sql; - - my $sql = " - SELECT SUM($owed_sql) FROM cust_bill - WHERE custnum = $custnum - AND _date <= $time - "; +# my $custnum = $self->custnum; +# +# my $owed_sql = FS::cust_bill->owed_sql; +# +# my $sql = " +# SELECT SUM($owed_sql) FROM cust_bill +# WHERE custnum = $custnum +# AND _date <= $time +# "; +# +# my $sth = dbh->prepare($sql) or die dbh->errstr; +# $sth->execute() or die $sth->errstr; +# +# return sprintf( '%.2f', $sth->fetchrow_arrayref->[0] ); - sprintf( "%.2f", $self->scalar_sql($sql) ); + my $total_bill = 0; + foreach my $cust_bill ( + grep { $_->_date <= $time } + qsearch('cust_bill', { 'custnum' => $self->custnum, } ) + ) { + $total_bill += $cust_bill->owed; + } + sprintf( "%.2f", $total_bill ); } @@ -6128,18 +5925,9 @@ sub total_credited { sub total_unapplied_credits { my $self = shift; - - my $custnum = $self->custnum; - - my $unapplied_sql = FS::cust_credit->unapplied_sql; - - my $sql = " - SELECT SUM($unapplied_sql) FROM cust_credit - WHERE custnum = $custnum - "; - - sprintf( "%.2f", $self->scalar_sql($sql) ); - + my $total_credit = 0; + $total_credit += $_->credited foreach $self->cust_credit; + sprintf( "%.2f", $total_credit ); } =item total_unapplied_credits_pkgnum PKGNUM @@ -6166,18 +5954,9 @@ See L<FS::cust_pay/unapplied>. sub total_unapplied_payments { my $self = shift; - - my $custnum = $self->custnum; - - my $unapplied_sql = FS::cust_pay->unapplied_sql; - - my $sql = " - SELECT SUM($unapplied_sql) FROM cust_pay - WHERE custnum = $custnum - "; - - sprintf( "%.2f", $self->scalar_sql($sql) ); - + my $total_unapplied = 0; + $total_unapplied += $_->unapplied foreach $self->cust_pay; + sprintf( "%.2f", $total_unapplied ); } =item total_unapplied_payments_pkgnum PKGNUM @@ -6205,17 +5984,9 @@ customer. See L<FS::cust_refund/unapplied>. sub total_unapplied_refunds { my $self = shift; - my $custnum = $self->custnum; - - my $unapplied_sql = FS::cust_refund->unapplied_sql; - - my $sql = " - SELECT SUM($unapplied_sql) FROM cust_refund - WHERE custnum = $custnum - "; - - sprintf( "%.2f", $self->scalar_sql($sql) ); - + my $total_unapplied = 0; + $total_unapplied += $_->unapplied foreach $self->cust_refund; + sprintf( "%.2f", $total_unapplied ); } =item balance @@ -6227,7 +5998,12 @@ total_unapplied_credits minus total_unapplied_payments). sub balance { my $self = shift; - $self->balance_date_range; + sprintf( "%.2f", + $self->total_owed + + $self->total_unapplied_refunds + - $self->total_unapplied_credits + - $self->total_unapplied_payments + ); } =item balance_date TIME @@ -6242,13 +6018,19 @@ functions. sub balance_date { my $self = shift; - $self->balance_date_range(shift); + my $time = shift; + sprintf( "%.2f", + $self->total_owed_date($time) + + $self->total_unapplied_refunds + - $self->total_unapplied_credits + - $self->total_unapplied_payments + ); } -=item balance_date_range [ START_TIME [ END_TIME [ OPTION => VALUE ... ] ] ] +=item balance_date_range START_TIME [ END_TIME [ OPTION => VALUE ... ] ] -Returns the balance for this customer, optionally considering invoices with -date earlier than START_TIME, and not later than END_TIME +Returns the balance for this customer, only considering invoices with date +earlier than START_TIME, and optionally not later than END_TIME (total_owed_date minus total_unapplied_credits minus total_unapplied_payments). Times are specified as SQL fragments or numeric @@ -7312,8 +7094,6 @@ Returns a status string for this customer, currently: =item prospect - No packages have ever been ordered -=item ordered - Recurring packages all are new (not yet billed). - =item active - One or more recurring packages is active =item inactive - No active recurring packages, but otherwise unsuspended/uncancelled (the inactive status is new - previously inactive customers were mis-identified as cancelled) @@ -7330,8 +7110,7 @@ sub status { shift->cust_status(@_); } sub cust_status { my $self = shift; - # prospect ordered active inactive suspended cancelled - for my $status ( FS::cust_main->statuses() ) { + for my $status (qw( prospect active inactive suspended cancelled )) { my $method = $status.'_sql'; my $numnum = ( my $sql = $self->$method() ) =~ s/cust_main\.custnum/?/g; my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr; @@ -7366,7 +7145,6 @@ use vars qw(%statuscolor); tie %statuscolor, 'Tie::IxHash', 'prospect' => '7e0079', #'000000', #black? naw, purple 'active' => '00CC00', #green - 'ordered' => '009999', #teal? cyan? 'inactive' => '0000CC', #blue 'suspended' => 'FF9900', #yellow 'cancelled' => 'FF0000', #red @@ -7476,20 +7254,9 @@ sub select_count_pkgs_sql { $select_count_pkgs; } -sub prospect_sql { - " 0 = ( $select_count_pkgs ) "; -} - -=item ordered_sql - -Returns an SQL expression identifying ordered cust_main records (customers with -recurring packages not yet setup). - -=cut - -sub ordered_sql { - " 0 < ( $select_count_pkgs AND ". FS::cust_pkg->ordered_sql. " ) "; -} +sub prospect_sql { " + 0 = ( $select_count_pkgs ) +"; } =item active_sql @@ -7498,9 +7265,10 @@ active recurring packages). =cut -sub active_sql { - " 0 < ( $select_count_pkgs AND ". FS::cust_pkg->active_sql. " ) "; -} +sub active_sql { " + 0 < ( $select_count_pkgs AND ". FS::cust_pkg->active_sql. " + ) +"; } =item inactive_sql @@ -7589,10 +7357,10 @@ sub balance_sql { " WHERE cust_refund.custnum = cust_main.custnum ) "; } -=item balance_date_sql [ START_TIME [ END_TIME [ OPTION => VALUE ... ] ] ] +=item balance_date_sql START_TIME [ END_TIME [ OPTION => VALUE ... ] ] -Returns an SQL fragment to retreive the balance for this customer, optionally -considering invoices with date earlier than START_TIME, and not +Returns an SQL fragment to retreive the balance for this customer, only +considering invoices with date earlier than START_TIME, and optionally not later than END_TIME (total_owed_date minus total_unapplied_credits minus total_unapplied_payments). @@ -7675,11 +7443,9 @@ Available options are: =cut sub unapplied_payments_date_sql { - my( $class, $start, $end, %opt ) = @_; + my( $class, $start, $end, ) = @_; - my $cutoff = $opt{'cutoff'}; - - my $unapp_pay = FS::cust_pay->unapplied_sql($cutoff); + my $unapp_pay = FS::cust_pay->unapplied_sql; my $pay_where = $class->_money_table_where( 'cust_pay', $start, $end, 'unapplied_date'=>1 ); @@ -7790,7 +7556,7 @@ sub search { # parse status ## - #prospect ordered active inactive suspended cancelled + #prospect active inactive suspended cancelled if ( grep { $params->{'status'} eq $_ } FS::cust_main->statuses() ) { my $method = $params->{'status'}. '_sql'; #push @where, $class->$method(); @@ -8058,10 +7824,8 @@ sub email_search_result { my $subject = delete $params->{subject}; my $html_body = delete $params->{html_body}; my $text_body = delete $params->{text_body}; - my $error = ''; - my $job = delete $params->{'job'} - or die "email_search_result must run from the job queue.\n"; + my $job = delete $params->{'job'}; $params->{'payby'} = [ split(/\0/, $params->{'payby'}) ] unless ref($params->{'payby'}); @@ -8081,73 +7845,43 @@ sub email_search_result { my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo - my @retry_jobs = (); - my $success = 0; #eventually order+limit magic to reduce memory use? foreach my $cust_main ( qsearch($sql_query) ) { - #progressbar first, so that the count is right - $num++; - if ( time - $min_sec > $last ) { - my $error = $job->update_statustext( - int( 100 * $num / $num_cust ) - ); - die $error if $error; - $last = time; - } - my $to = $cust_main->invoicing_list_emailonly_scalar; + next unless $to; - if( $to ) { - my @message = ( + my $error = send_email( + generate_email( 'from' => $from, 'to' => $to, 'subject' => $subject, 'html_body' => $html_body, 'text_body' => $text_body, - ); - - $error = send_email( generate_email( @message ) ); + ) + ); + return $error if $error; - if($error) { - # queue the sending of this message so that the user can see what we - # tried to do, and retry if desired - my $queue = new FS::queue { - 'job' => 'FS::Misc::process_send_email', - 'custnum' => $cust_main->custnum, - 'status' => 'failed', - 'statustext' => $error, - }; - $queue->insert(@message); - push @retry_jobs, $queue; - } - else { - $success++; + if ( $job ) { #progressbar foo + $num++; + if ( time - $min_sec > $last ) { + my $error = $job->update_statustext( + int( 100 * $num / $num_cust ) + ); + die $error if $error; + $last = time; } } - if($success == 0 and - (scalar(@retry_jobs) > 10 or $num == $num_cust) - ) { - # 10 is arbitrary, but if we have enough failures, that's - # probably a configuration or network problem, and we - # abort the batch and run away screaming. - # We NEVER do this if anything was successfully sent. - $_->delete foreach (@retry_jobs); - return "multiple failures: '$error'\n"; - } - } - - if(@retry_jobs) { - # fail the job, but with a status message that makes it clear - # something was sent. - return "Sent $success, failed ".scalar(@retry_jobs).". Failed attempts placed in job queue.\n"; } return ''; } +use Storable qw(thaw); +use Data::Dumper; +use MIME::Base64; sub process_email_search_result { my $job = shift; #warn "$me process_re_X $method for job $job\n" if $DEBUG; @@ -8770,9 +8504,6 @@ sub batch_charge { =item notify CUSTOMER_OBJECT TEMPLATE_NAME OPTIONS -Deprecated. Use event notification and message templates -(L<FS::msg_template>) instead. - Sends a templated email notification to the customer (see L<Text::Template>). OPTIONS is a hash and may include @@ -9067,35 +8798,14 @@ sub _agent_plandata { } -=item queued_bill 'custnum' => CUSTNUM [ , OPTION => VALUE ... ] - -Subroutine (not a method), designed to be called from the queue. - -Takes a list of options and values. - -Pulls up the customer record via the custnum option and calls bill_and_collect. - -=cut - sub queued_bill { + ## actual sub, not a method, designed to be called from the queue. + ## sets up the customer, and calls the bill_and_collect my (%args) = @_; #, ($time, $invoice_time, $check_freq, $resetup) = @_; - my $cust_main = qsearchs( 'cust_main', { custnum => $args{'custnum'} } ); - warn 'bill_and_collect custnum#'. $cust_main->custnum. "\n";#log custnum w/pid - - $cust_main->bill_and_collect( %args ); -} - -sub process_bill_and_collect { - my $job = shift; - my $param = thaw(decode_base64(shift)); - my $cust_main = qsearchs( 'cust_main', { custnum => $param->{'custnum'} } ) - or die "custnum '$param->{custnum}' not found!\n"; - $param->{'job'} = $job; - $param->{'fatal'} = 1; # runs from job queue, will be caught - $param->{'retry'} = 1; - - $cust_main->bill_and_collect( %$param ); + $cust_main->bill_and_collect( + %args, + ); } sub _upgrade_data { #class method @@ -9106,7 +8816,6 @@ sub _upgrade_data { #class method $sth->execute or die $sth->errstr; local($ignore_expired_card) = 1; - local($skip_fuzzyfiles) = 1; $class->_upgrade_otaker(%opts); } diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index eee263a1d..ff8226c8d 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -179,7 +179,7 @@ sub insert { $error = $self->SUPER::insert; if ( $error ) { $dbh->rollback if $oldAutoCommit; - return "error inserting cust_pay: $error"; + return "error inserting $self: $error"; } if ( $self->invnum ) { @@ -192,11 +192,11 @@ sub insert { $error = $cust_bill_pay->insert(%options); if ( $error ) { if ( $ignore_noapply ) { - warn "warning: error inserting cust_bill_pay: $error ". + warn "warning: error inserting $cust_bill_pay: $error ". "(ignore_noapply flag set; inserting cust_pay record anyway)\n"; } else { $dbh->rollback if $oldAutoCommit; - return "error inserting cust_bill_pay: $error"; + return "error inserting $cust_bill_pay: $error"; } } } @@ -446,82 +446,76 @@ sub send_receipt { my $conf = new FS::Conf; - my @invoicing_list = $cust_main->invoicing_list_emailonly; - return '' unless @invoicing_list; + return '' + unless $conf->exists('payment_receipt_email') + && grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list; $cust_bill ||= ($cust_main->cust_bill)[-1]; #rather inefficient though? if ( ( exists($opt->{'manual'}) && $opt->{'manual'} ) - || ! $conf->exists('invoice_html_statement') # XXX msg_template + || ! $conf->exists('invoice_html_statement') || ! $cust_bill ) { - my $error = ''; + my $receipt_template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", $conf->config('payment_receipt_email') ], + ) or do { + warn "can't create payment receipt template: $Text::Template::ERROR"; + return ''; + }; + + my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } + $cust_main->invoicing_list; - if( $conf->exists('payment_receipt_msgnum') ) { - my $msg_template = - FS::msg_template->by_key($conf->config('payment_receipt_msgnum')); - $error = $msg_template->send('cust_main'=> $cust_main, 'object'=> $self); + my $payby = $self->payby; + my $payinfo = $self->payinfo; + $payby =~ s/^BILL$/Check/ if $payinfo; + if ( $payby eq 'CARD' || $payby eq 'CHEK' ) { + $payinfo = $self->paymask + } else { + $payinfo = $self->decrypt($payinfo); } - elsif ( $conf->exists('payment_receipt_email') ) { - my $receipt_template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", $conf->config('payment_receipt_email') ], - ) or do { - warn "can't create payment receipt template: $Text::Template::ERROR"; - return ''; - }; + $payby =~ s/^CHEK$/Electronic check/; + + my %fill_in = ( + 'date' => time2str("%a %B %o, %Y", $self->_date), + 'name' => $cust_main->name, + 'paynum' => $self->paynum, + 'paid' => sprintf("%.2f", $self->paid), + 'payby' => ucfirst(lc($payby)), + 'payinfo' => $payinfo, + 'balance' => $cust_main->balance, + 'company_name' => $conf->config('company_name', $cust_main->agentnum), + ); - my $payby = $self->payby; - my $payinfo = $self->payinfo; - $payby =~ s/^BILL$/Check/ if $payinfo; - if ( $payby eq 'CARD' || $payby eq 'CHEK' ) { - $payinfo = $self->paymask - } else { - $payinfo = $self->decrypt($payinfo); - } - $payby =~ s/^CHEK$/Electronic check/; - - my %fill_in = ( - 'date' => time2str("%a %B %o, %Y", $self->_date), - 'name' => $cust_main->name, - 'paynum' => $self->paynum, - 'paid' => sprintf("%.2f", $self->paid), - 'payby' => ucfirst(lc($payby)), - 'payinfo' => $payinfo, - 'balance' => $cust_main->balance, - 'company_name' => $conf->config('company_name', $cust_main->agentnum), - ); - - if ( $opt->{'cust_pkg'} ) { - $fill_in{'pkg'} = $opt->{'cust_pkg'}->part_pkg->pkg; - #setup date, other things? - } + if ( $opt->{'cust_pkg'} ) { + $fill_in{'pkg'} = $opt->{'cust_pkg'}->part_pkg->pkg; + #setup date, other things? + } - $error = send_email( - 'from' => $conf->config('invoice_from', $cust_main->agentnum), - #invoice_from??? well as good as any - 'to' => \@invoicing_list, - 'subject' => 'Payment receipt', - 'body' => [ $receipt_template->fill_in( HASH => \%fill_in ) ], - ); + send_email( + 'from' => $conf->config('invoice_from', $cust_main->agentnum), + #invoice_from??? well as good as any + 'to' => \@invoicing_list, + 'subject' => 'Payment receipt', + 'body' => [ $receipt_template->fill_in( HASH => \%fill_in ) ], + ); - } - else { # no payment_receipt_msgnum or payment_receipt_email + } else { - my $queue = new FS::queue { - 'paynum' => $self->paynum, - 'job' => 'FS::cust_bill::queueable_email', - }; + my $queue = new FS::queue { + 'paynum' => $self->paynum, + 'job' => 'FS::cust_bill::queueable_email', + }; + + $queue->insert( + 'invnum' => $cust_bill->invnum, + 'template' => 'statement', + ); + + } - $queue->insert( - 'invnum' => $cust_bill->invnum, - 'template' => 'statement', - ); - } - - warn "send_receipt: $error\n" if $error; - } #$opt{manual} || no invoice_html_statement || customer has no invoices } =item cust_bill_pay @@ -665,7 +659,7 @@ Returns an SQL fragment to retreive the unapplied amount. =cut sub unapplied_sql { - my ($class, $start, $end) = @_; + my ($class, $start, $end) = shift; my $bill_start = $start ? "AND cust_bill_pay._date <= $start" : ''; my $bill_end = $end ? "AND cust_bill_pay._date > $end" : ''; my $refund_start = $start ? "AND cust_pay_refund._date <= $start" : ''; @@ -699,10 +693,6 @@ sub _upgrade_data { #class method warn "$me upgrading $class\n" if $DEBUG; - ## - # otaker/ivan upgrade - ## - #not the most efficient, but hey, it only has to run once my $where = "WHERE ( otaker IS NULL OR otaker = '' OR otaker = 'ivan' ) ". @@ -758,43 +748,6 @@ sub _upgrade_data { #class method } - ### - # payinfo N/A upgrade - ### - - #XXX remove the 'N/A (tokenized)' part (or just this entire thing) - - my @na_cust_pay = qsearch( { - 'table' => 'cust_pay', - 'hashref' => {}, #could be encrypted# { 'payinfo' => 'N/A' }, - 'extra_sql' => "WHERE ( payinfo = 'N/A' OR paymask = 'N/AA' OR paymask = 'N/A (tokenized)' ) AND payby IN ( 'CARD', 'CHEK' )", - } ); - - foreach my $na ( @na_cust_pay ) { - - next unless $na->payinfo eq 'N/A'; - - my $cust_pay_pending = - qsearchs('cust_pay_pending', { 'paynum' => $na->paynum } ); - unless ( $cust_pay_pending ) { - warn " *** WARNING: not-yet recoverable N/A card for payment ". - $na->paynum. " (no cust_pay_pending)\n"; - next; - } - $na->$_($cust_pay_pending->$_) for qw( payinfo paymask ); - my $error = $na->replace; - if ( $error ) { - warn " *** WARNING: Error updating payinfo for payment paynum ". - $na->paynun. ": $error\n"; - next; - } - - } - - ### - # otaker->usernum upgrade - ### - $class->_upgrade_otaker(%opts); } diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 0f9a611eb..b851ac718 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -2,7 +2,7 @@ package FS::cust_pkg; use strict; use base qw( FS::otaker_Mixin FS::cust_main_Mixin FS::location_Mixin - FS::m2m_Common FS::option_Common ); + FS::m2m_Common FS::option_Common FS::Record ); use vars qw($disable_agentcheck $DEBUG $me); use Carp qw(cluck); use Scalar::Util qw( blessed ); @@ -708,21 +708,12 @@ sub cancel { my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $self->cust_main->invoicing_list; if ( !$options{'quiet'} && $conf->exists('emailcancel') && @invoicing_list ) { - my $msgnum = $conf->config('cancel_msgnum', $self->cust_main->agentnum); - my $error = ''; - if ( $msgnum ) { - my $msg_template = qsearchs('msg_template', { msgnum => $msgnum }); - $error = $msg_template->send( 'cust_main' => $self->cust_main, - 'object' => $self ); - } - else { - $error = send_email( - 'from' => $conf->config('invoice_from', $self->cust_main->agentnum), - 'to' => \@invoicing_list, - 'subject' => ( $conf->config('cancelsubject') || 'Cancellation Notice' ), - 'body' => [ map "$_\n", $conf->config('cancelmessage') ], - ); - } + my $error = send_email( + 'from' => $conf->config('invoice_from', $self->cust_main->agentnum), + 'to' => \@invoicing_list, + 'subject' => ( $conf->config('cancelsubject') || 'Cancellation Notice' ), + 'body' => [ map "$_\n", $conf->config('cancelmessage') ], + ); #should this do something on errors? } @@ -1774,16 +1765,6 @@ sub status { return 'active'; } -=item ucfirst_status - -Returns the status with the first character capitalized. - -=cut - -sub ucfirst_status { - ucfirst(shift->status); -} - =item statuses Class method that returns the list of possible status strings for packages @@ -1939,7 +1920,7 @@ sub _labels_short { my %labels; #tie %labels, 'Tie::IxHash'; push @{ $labels{$_->[0]} }, $_->[1] - foreach $self->$method(@_); + foreach $self->h_labels(@_); my @labels; foreach my $label ( keys %labels ) { my %seen = (); @@ -2445,25 +2426,14 @@ sub onetime_sql { " where cust_pkg.pkgpart = part_pkg.pkgpart ) "; } -=item ordered_sql - -Returns an SQL expression identifying ordered packages (recurring packages not -yet billed). - -=cut - -sub ordered_sql { - $_[0]->recurring_sql. " AND ". $_[0]->not_yet_billed_sql; -} - =item active_sql Returns an SQL expression identifying active packages. =cut -sub active_sql { - $_[0]->recurring_sql. " +sub active_sql { " + ". $_[0]->recurring_sql(). " AND cust_pkg.setup IS NOT NULL AND cust_pkg.setup != 0 AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 ) diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm index 39603701f..6d08c8621 100644 --- a/FS/FS/cust_refund.pm +++ b/FS/FS/cust_refund.pm @@ -343,7 +343,7 @@ Returns an SQL fragment to retreive the unapplied amount. =cut sub unapplied_sql { - my ($class, $start, $end) = @_; + my ($class, $start, $end) = shift; my $credit_start = $start ? "AND cust_credit_refund._date <= $start" : ''; my $credit_end = $end ? "AND cust_credit_refund._date > $end" : ''; my $pay_start = $start ? "AND cust_pay_refund._date <= $start" : ''; diff --git a/FS/FS/cust_tag.pm b/FS/FS/cust_tag.pm deleted file mode 100644 index 5dfd156b4..000000000 --- a/FS/FS/cust_tag.pm +++ /dev/null @@ -1,147 +0,0 @@ -package FS::cust_tag; - -use strict; -use base qw( FS::Record ); -use FS::Record qw( qsearchs ); -use FS::cust_main; -use FS::part_tag; - -=head1 NAME - -FS::cust_tag - Object methods for cust_tag records - -=head1 SYNOPSIS - - use FS::cust_tag; - - $record = new FS::cust_tag \%hash; - $record = new FS::cust_tag { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::cust_tag object represents a customer tag. FS::cust_tag inherits from -FS::Record. The following fields are currently supported: - -=over 4 - -=item custtagnum - -primary key - -=item custnum - -custnum - -=item tagnum - -tagnum - - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new customer tag. To add the tag to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -# the new method can be inherited from FS::Record, if a table method is defined - -sub table { 'cust_tag'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -# the insert method can be inherited from FS::Record - -=item delete - -Delete this record from the database. - -=cut - -# the delete method can be inherited from FS::Record - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -# the replace method can be inherited from FS::Record - -=item check - -Checks all fields to make sure this is a valid customer tag. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -# the check method should currently be supplied - FS::Record contains some -# data checking routines - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('custtagnum') - || $self->ut_foreign_key('custnum', 'cust_main', 'custnum') - || $self->ut_foreign_key('tagnum', 'part_tag', 'tagnum' ) - ; - return $error if $error; - - $self->SUPER::check; -} - -=item cust_main - -=cut - -sub cust_main { - my $self = shift; - qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); -} - -=item part_tag - -=cut - -sub part_tag { - my $self = shift; - qsearchs( 'part_tag', { 'tagnum' => $self->tagnum } ); -} - - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/h_inventory_item.pm b/FS/FS/h_inventory_item.pm deleted file mode 100644 index b4f016128..000000000 --- a/FS/FS/h_inventory_item.pm +++ /dev/null @@ -1,33 +0,0 @@ -package FS::h_inventory_item; - -use strict; -use vars qw( @ISA ); -use FS::h_Common; -use FS::inventory_item; - -@ISA = qw( FS::h_Common FS::inventory_item ); - -sub table { 'h_inventory_item' }; - -=head1 NAME - -FS::h_inventory_item - Historical record of inventory item activity - -=head1 SYNOPSIS - -=head1 DESCRIPTION - -An FS::h_inventory_item object represents a change in the state of an -inventory item. - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::inventory_item>, L<FS::h_Common>, L<FS::Record>, schema.html from the -base documentation. - -=cut - -1; - diff --git a/FS/FS/msg_template.pm b/FS/FS/msg_template.pm deleted file mode 100644 index 7d507f4fb..000000000 --- a/FS/FS/msg_template.pm +++ /dev/null @@ -1,476 +0,0 @@ -package FS::msg_template; - -use strict; -use base qw( FS::Record ); -use Text::Template; -use FS::Misc qw( generate_email send_email ); -use FS::Conf; -use FS::Record qw( qsearch qsearchs ); - -use Date::Format qw( time2str ); -use HTML::Entities qw( decode_entities encode_entities ) ; -use HTML::FormatText; -use HTML::TreeBuilder; -use vars '$DEBUG'; - -$DEBUG=0; - -=head1 NAME - -FS::msg_template - Object methods for msg_template records - -=head1 SYNOPSIS - - use FS::msg_template; - - $record = new FS::msg_template \%hash; - $record = new FS::msg_template { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::msg_template object represents a customer message template. -FS::msg_template inherits from FS::Record. The following fields are currently -supported: - -=over 4 - -=item msgnum - -primary key - -=item msgname - -Template name. - -=item agentnum - -Agent associated with this template. Can be NULL for a global template. - -=item mime_type - -MIME type. Defaults to text/html. - -=item from_addr - -Source email address. - -=item subject - -The message subject line, in L<Text::Template> format. - -=item body - -The message body, as plain text or HTML, in L<Text::Template> format. - -=item disabled - -disabled - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new template. To add the template to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -# the new method can be inherited from FS::Record, if a table method is defined - -sub table { 'msg_template'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -# the insert method can be inherited from FS::Record - -=item delete - -Delete this record from the database. - -=cut - -# the delete method can be inherited from FS::Record - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -# the replace method can be inherited from FS::Record - -=item check - -Checks all fields to make sure this is a valid template. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -# the check method should currently be supplied - FS::Record contains some -# data checking routines - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('msgnum') - || $self->ut_text('msgname') - || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum') - || $self->ut_textn('mime_type') - || $self->ut_anything('subject') - || $self->ut_anything('body') - || $self->ut_enum('disabled', [ '', 'Y' ] ) - || $self->ut_textn('from_addr') - ; - return $error if $error; - - $self->mime_type('text/html') unless $self->mime_type; - - $self->SUPER::check; -} - -=item prepare OPTION => VALUE - -Fills in the template and returns a hash of the 'from' address, 'to' -addresses, subject line, and body. - -Options are passed as a list of name/value pairs: - -=over 4 - -=item cust_main - -Customer object (required). - -=item object - -Additional context object (currently, can be a cust_main, cust_pkg, -cust_bill, svc_acct, or cust_pay object). - -=back - -=cut - -sub prepare { - my( $self, %opt ) = @_; - - my $cust_main = $opt{'cust_main'}; - my $object = $opt{'object'}; - warn "preparing template '".$self->msgname."' to cust#".$cust_main->custnum."\n" - if($DEBUG); - - my $subs = $self->substitutions; - - ### - # create substitution table - ### - my %hash; - foreach my $obj ($cust_main, $object || ()) { - foreach my $name (@{ $subs->{$obj->table} }) { - if(!ref($name)) { - # simple case - $hash{$name} = $obj->$name(); - } - elsif( ref($name) eq 'ARRAY' ) { - # [ foo => sub { ... } ] - $hash{$name->[0]} = $name->[1]->($obj); - } - else { - warn "bad msg_template substitution: '$name'\n"; - #skip it? - } - } - } - $_ = encode_entities($_) foreach values(%hash); - - - ### - # clean up template - ### - my $subject_tmpl = new Text::Template ( - TYPE => 'STRING', - SOURCE => $self->subject, - ); - my $subject = $subject_tmpl->fill_in( HASH => \%hash ); - - my $body = $self->body; - my ($skin, $guts) = eviscerate($body); - @$guts = map { - $_ = decode_entities($_); # turn all punctuation back into itself - s/\r//gs; # remove \r's - s/<br[^>]*>/\n/gsi; # and <br /> tags - s/<p>/\n/gsi; # and <p> - s/<\/p>//gsi; # and </p> - s/\240/ /gs; # and - $_ - } @$guts; - - $body = ''; - while(@$skin || @$guts) { - $body .= shift(@$skin) || ''; - $body .= shift(@$guts) || ''; - } - - ### - # fill-in - ### - - my $body_tmpl = new Text::Template ( - TYPE => 'STRING', - SOURCE => $body, - ); - - $body = $body_tmpl->fill_in( HASH => \%hash ); - - ### - # and email - ### - - my @to = $cust_main->invoicing_list_emailonly; - warn "prepared msg_template with no email destination (custnum ". - $cust_main->custnum.")\n" - if !@to; - - my $conf = new FS::Conf; - - ( - 'from' => $self->from || - scalar( $conf->config('invoice_from', $cust_main->agentnum) ), - 'to' => \@to, - 'subject' => $subject, - 'html_body' => $body, - 'text_body' => HTML::FormatText->new(leftmargin => 0, rightmargin => 70 - )->format( HTML::TreeBuilder->new_from_content($body) ), - ); - -} - -=item send OPTION => VALUE - -Fills in the template and sends it to the customer. Options are as for -'prepare'. - -=cut - -# broken out from prepare() in case we want to queue the sending, -# preview it, etc. -sub send { - my $self = shift; - send_email(generate_email($self->prepare(@_))); -} - -# helper sub for package dates -my $ymd = sub { $_[0] ? time2str('%Y-%m-%d', $_[0]) : '' }; - -# needed for some things -my $conf = new FS::Conf; - -#return contexts and fill-in values -# If you add anything, be sure to add a description in -# httemplate/edit/msg_template.html. -sub substitutions { - { 'cust_main' => [qw( - display_custnum agentnum agent_name - - last first company - name name_short contact contact_firstlast - address1 address2 city county state zip - country - daytime night fax - - has_ship_address - ship_last ship_first ship_company - ship_name ship_name_short ship_contact ship_contact_firstlast - ship_address1 ship_address2 ship_city ship_county ship_state ship_zip - ship_country - ship_daytime ship_night ship_fax - - paymask payname paytype payip - num_cancelled_pkgs num_ncancelled_pkgs num_pkgs - classname categoryname - balance - invoicing_list_emailonly - cust_status ucfirst_cust_status cust_statuscolor - - signupdate dundate - ), - [ signupdate_ymd => sub { time2str('%Y-%m-%d', shift->signupdate) } ], - [ dundate_ymd => sub { time2str('%Y-%m-%d', shift->dundate) } ], - [ paydate_my => sub { sprintf('%02d/%04d', shift->paydate_monthyear) } ], - [ otaker_first => sub { shift->access_user->first } ], - [ otaker_last => sub { shift->access_user->last } ], - [ payby => sub { FS::payby->shortname(shift->payby) } ], - [ company_name => sub { - $conf->config('company_name', shift->agentnum) - } ], - ], - # next_bill_date - 'cust_pkg' => [qw( - pkgnum pkg_label pkg_label_long - location_label - status statuscolor - - start_date setup bill last_bill - adjourn susp expire - labels_short - ), - [ cancel => sub { shift->getfield('cancel') } ], # grrr... - [ start_ymd => sub { $ymd->(shift->getfield('start_date')) } ], - [ setup_ymd => sub { $ymd->(shift->getfield('setup')) } ], - [ next_bill_ymd => sub { $ymd->(shift->getfield('bill')) } ], - [ last_bill_ymd => sub { $ymd->(shift->getfield('last_bill')) } ], - [ adjourn_ymd => sub { $ymd->(shift->getfield('adjourn')) } ], - [ susp_ymd => sub { $ymd->(shift->getfield('susp')) } ], - [ expire_ymd => sub { $ymd->(shift->getfield('expire')) } ], - [ cancel_ymd => sub { $ymd->(shift->getfield('cancel')) } ], - ], - 'cust_bill' => [qw( - invnum - _date - )], - #XXX not really thinking about cust_bill substitutions quite yet - - 'svc_acct' => [qw( - username - ), - [ password => sub { shift->getfield('_password') } ], - ], # for welcome messages - 'cust_pay' => [qw( - paynum - _date - ), - [ paid => sub { sprintf("%.2f", shift->paid) } ], - # overrides the one in cust_main in cases where a cust_pay is passed - [ payby => sub { FS::payby->shortname(shift->payby) } ], - [ date => sub { time2str("%a %B %o, %Y", shift->_date) } ], - [ payinfo => sub { - my $cust_pay = shift; - ($cust_pay->payby eq 'CARD' || $cust_pay->payby eq 'CHEK') ? - $cust_pay->paymask : $cust_pay->decrypt($cust_pay->payinfo) - } ], - ], - }; -} - -sub _upgrade_data { - my ($self, %opts) = @_; - - my @fixes = ( - [ 'alerter_msgnum', 'alerter_template', '', '' ], - [ 'cancel_msgnum', 'cancelmessage', 'cancelsubject', '' ], - [ 'decline_msgnum', 'declinetemplate', '', '' ], - [ 'impending_recur_msgnum', 'impending_recur_template', '', '' ], - [ 'payment_receipt_msgnum', 'payment_receipt_email', '', '' ], - [ 'welcome_msgnum', 'welcome_email', 'welcome_email-subject', 'welcome_email-from' ], - [ 'warning_msgnum', 'warning_email', 'warning_email-subject', 'warning_email-from' ], - ); - - my $conf = new FS::Conf; - my @agentnums = ('', map {$_->agentnum} qsearch('agent', {})); - foreach my $agentnum (@agentnums) { - foreach (@fixes) { - my ($newname, $oldname, $subject, $from) = @$_; - if ($conf->exists($oldname, $agentnum)) { - my $new = new FS::msg_template({ - 'msgname' => $oldname, - 'agentnum' => $agentnum, - 'from_addr' => ($from && $conf->config($from, $agentnum)) || - $conf->config('invoice_from', $agentnum), - 'subject' => ($subject && $conf->config($subject, $agentnum)) || '', - 'mime_type' => 'text/html', - 'body' => join('<BR>',$conf->config($oldname, $agentnum)), - }); - my $error = $new->insert; - die $error if $error; - $conf->set($newname, $new->msgnum, $agentnum); - $conf->delete($oldname, $agentnum); - $conf->delete($from, $agentnum) if $from; - $conf->delete($subject, $agentnum) if $subject; - } - } - } -} - -sub eviscerate { - # Every bit as pleasant as it sounds. - # - # We do this because Text::Template::Preprocess doesn't - # actually work. It runs the entire template through - # the preprocessor, instead of the code segments. Which - # is a shame, because Text::Template already contains - # the code to do this operation. - my $body = shift; - my (@outside, @inside); - my $depth = 0; - my $chunk = ''; - while($body || $chunk) { - my ($first, $delim, $rest); - # put all leading non-delimiters into $first - ($first, $rest) = - ($body =~ /^((?:\\[{}]|[^{}])*)(.*)$/s); - $chunk .= $first; - # put a leading delimiter into $delim if there is one - ($delim, $rest) = - ($rest =~ /^([{}]?)(.*)$/s); - - if( $delim eq '{' ) { - $chunk .= '{'; - if( $depth == 0 ) { - push @outside, $chunk; - $chunk = ''; - } - $depth++; - } - elsif( $delim eq '}' ) { - $depth--; - if( $depth == 0 ) { - push @inside, $chunk; - $chunk = ''; - } - $chunk .= '}'; - } - else { - # no more delimiters - if( $depth == 0 ) { - push @outside, $chunk . $rest; - } # else ? something wrong - last; - } - $body = $rest; - } - (\@outside, \@inside); -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/otaker_Mixin.pm b/FS/FS/otaker_Mixin.pm index 0da9aeedb..071958c33 100644 --- a/FS/FS/otaker_Mixin.pm +++ b/FS/FS/otaker_Mixin.pm @@ -9,15 +9,8 @@ sub otaker { my $self = shift; if ( scalar(@_) ) { #set my $otaker = shift; - my $access_user = qsearchs('access_user', { 'username' => $otaker } ); - if ( !$access_user && $otaker =~ /^(.+), (.+)$/ ) { #same as below.. - my($lastname, $firstname) = ($1, $2); - $otaker = lc($firstname.$lastname); - $access_user = qsearchs('access_user', { 'first' => $firstname, - 'last' => $lastname } ) - || qsearchs('access_user', { 'username' => $otaker } ); - } - croak "can't set otaker: $otaker not found!" unless $access_user; #confess? + my $access_user = qsearchs('access_user', { 'username' => $otaker } ) + or croak "can't set otaker: $otaker not found!"; #confess? $self->usernum( $access_user->usernum ); $otaker; #not sure return is used anywhere, but just in case } else { #get @@ -40,30 +33,22 @@ sub _upgrade_otaker { my $class = shift; my $table = $class->table; - my $limit = ( $table eq 'cust_attachment' ? 10 : 1000 ); - while ( 1 ) { my @records = qsearch({ 'table' => $table, 'hashref' => {}, - 'extra_sql' => "WHERE otaker IS NOT NULL LIMIT $limit", + 'extra_sql' => 'WHERE otaker IS NOT NULL LIMIT 1000', }); last unless @records; foreach my $record (@records) { eval { $record->otaker($record->otaker) }; if ( $@ ) { - my $username = $record->otaker; - my($lastname, $firstname) = ( 'User', 'Legacy' ); - if ( $username =~ /^(.+), (.+)$/ ) { - ($lastname, $firstname) = ($1, $2); - $username = lc($firstname.$lastname); - } my $access_user = new FS::access_user { - 'username' => $username, + 'username' => $record->otaker, '_password' => 'CHANGEME', - 'first' => $firstname, - 'last' => $lastname, + 'first' => 'Legacy', + 'last' => 'User', 'disabled' => 'Y', }; my $error = $access_user->insert; diff --git a/FS/FS/part_event/Action/notice.pm b/FS/FS/part_event/Action/notice.pm deleted file mode 100644 index 126965374..000000000 --- a/FS/FS/part_event/Action/notice.pm +++ /dev/null @@ -1,47 +0,0 @@ -package FS::part_event::Action::notice; - -use strict; -use base qw( FS::part_event::Action ); -use FS::Record qw( qsearchs ); -use FS::msg_template; - -sub description { 'Send a notice from a message template'; } - -#sub eventtable_hashref { -# { 'cust_main' => 1, -# 'cust_bill' => 1, -# 'cust_pkg' => 1, -# }; -#} - -sub option_fields { - ( - 'msgnum' => { 'label' => 'Template', - 'type' => 'select-table', - 'table' => 'msg_template', - 'name_col' => 'msgname', - 'disable_empty' => 1, - }, - ); -} - -sub default_weight { 55; } #? - -sub do_action { - my( $self, $object ) = @_; - - my $cust_main = $self->cust_main($object); - - my $msgnum = $self->option('msgnum'); - - my $msg_template = qsearchs('msg_template', { 'msgnum' => $msgnum } ) - or die "Template $msgnum not found"; - - $msg_template->send( - 'cust_main' => $cust_main, - 'object' => $object, - ); - -} - -1; diff --git a/FS/FS/part_event/Condition/pkg_freq.pm b/FS/FS/part_event/Condition/pkg_freq.pm deleted file mode 100644 index 1fb848426..000000000 --- a/FS/FS/part_event/Condition/pkg_freq.pm +++ /dev/null @@ -1,36 +0,0 @@ -package FS::part_event::Condition::pkg_freq; - -use strict; -use FS::Misc; -use FS::cust_pkg; - -use base qw( FS::part_event::Condition ); - -sub description { 'Package billing frequency'; } - -sub option_fields { - my $freqs = FS::Misc::pkg_freqs(); - ( - 'freq' => { 'label' => 'Frequency', - 'type' => 'select', - 'labels' => $freqs, - 'options' => [ keys(%$freqs) ], - }, - ); -} - -sub eventtable_hashref { - { 'cust_main' => 0, - 'cust_bill' => 0, - 'cust_pkg' => 1, - }; -} - -sub condition { - my($self, $cust_pkg) = @_; - - $cust_pkg->part_pkg->freq eq $self->option('freq') -} - -1; - diff --git a/FS/FS/part_export/communigate_pro.pm b/FS/FS/part_export/communigate_pro.pm index 3ac0dfd9c..edfd4b18e 100644 --- a/FS/FS/part_export/communigate_pro.pm +++ b/FS/FS/part_export/communigate_pro.pm @@ -383,16 +383,12 @@ sub _export_replace_svc_acct { sub _export_replace_svc_domain { my( $self, $new, $old ) = (shift, shift, shift); - #let's just do the rename part realtime rather than trying to queue - #w/dependencies. we don't want FS winding up out-of-sync with the wrong - #username and a queued job anyway. right?? if ( $old->domain ne $new->domain ) { - eval { $self->communigate_pro_runcommand( - 'RenameDomain', $old->domain, $new->domain, - ) }; - return $@ if $@; + my $error = $self->communigate_pro_queue( $new->svcnum, 'RenameDomain', + $old->domain, $new->domain, + ); + return $error if $error; } - my %settings = (); $settings{'AccountsLimit'} = $new->max_accounts if $old->max_accounts ne $new->max_accounts; @@ -835,23 +831,6 @@ sub export_getsettings_svc_acct { } -sub export_getsettings_svc_forward { - my($self, $svc_forward, $settingsref, $defaultref ) = @_; - - my $dest = eval { $self->communigate_pro_runcommand( - 'GetForwarder', - ($svc_forward->src || $svc_forward->srcsvc_acct->email), - ) }; - return $@ if $@; - - my $settings = { 'Destination' => $dest }; - - %{$settingsref} = %$settings; - %{$defaultref} = (); - - ''; -} - sub _rule2string { my $rule = shift; my($priority, $name, $conditions, $actions, $comment) = @$rule; diff --git a/FS/FS/part_export/cust_http.pm b/FS/FS/part_export/cust_http.pm deleted file mode 100644 index 59503e811..000000000 --- a/FS/FS/part_export/cust_http.pm +++ /dev/null @@ -1,45 +0,0 @@ -package FS::part_export::cust_http; - -use vars qw( @ISA %info ); -use FS::part_export::http; -use Tie::IxHash; - -@ISA = qw( FS::part_export::http ); - -tie my %options, 'Tie::IxHash', %FS::part_export::http::options; - -$options{'insert_data'}->{'default'} = join("\n", - "action 'insert'", - "custnum \$cust_main->custnum", - "first \$cust_main->first", - "last \$cust_main->get('last')", - ( map "$_ \$cust_main->$_", qw( company address1 address2 city county state zip country daytime night fax last ) ), - "email \$cust_main->invoicing_list_emailonly_scalar", -); -$options{'delete_data'}->{'default'} = join("\n", - "action 'delete'", - "custnum \$cust_main->custnum", -); -$options{'replace_data'}->{'default'} = join("\n", - "action 'replace'", - "custnum \$new_cust_main->custnum", - "first \$new_cust_main->first", - "last \$new_cust_main->get('last')", - ( map "$_ \$cust_main->$_", qw( company address1 address2 city county state zip country daytime night fax last ) ), - "email \$new_cust_main->invoicing_list_emailonly_scalar", -); - -%info = ( - 'svc' => 'cust_main', - 'desc' => 'Send an HTTP or HTTPS GET or POST request, for customers.', - 'options' => \%options, - 'notes' => <<'END' -Send an HTTP or HTTPS GET or POST to the specified URL on customer addition, -modification and deletion. For HTTPS support, -<a href="http://search.cpan.org/dist/Crypt-SSLeay">Crypt::SSLeay</a> -or <a href="http://search.cpan.org/dist/IO-Socket-SSL">IO::Socket::SSL</a> -is required. -END -); - -1; diff --git a/FS/FS/part_export/domreg_opensrs.pm b/FS/FS/part_export/domreg_opensrs.pm index 6554991d3..4d6ea8f91 100644 --- a/FS/FS/part_export/domreg_opensrs.pm +++ b/FS/FS/part_export/domreg_opensrs.pm @@ -259,6 +259,8 @@ sub _export_insert_on_payment { 'job' => 'FS::part_export::domreg_opensrs::renew_through', }; $queue->insert( $self, $svc_domain ); #_export_insert with 'R' action? + + return ''; } ## Domain registration exports do nothing on replace. Mainly because we haven't decided what they should do. @@ -480,8 +482,7 @@ sub renew { Attempts to renew the domain through the specified date. If no date is provided it is gleaned from the associated cust_pkg bill date -Like some export functions, dies on failure or returns undef on success. -It is always called from the queue. +Like most export functions, returns an error message on failure or undef on success. =cut @@ -490,24 +491,24 @@ sub renew_through { warn "$me: renew_through called\n" if $DEBUG; eval "use Net::OpenSRS;"; - die $@ if $@; + return $@ if $@; unless ( $date ) { my $cust_pkg = $svc_domain->cust_svc->cust_pkg; - die "Can't renew: no date specified and domain is not in a package." + return "Can't renew: no date specified and domain is not in a package." unless $cust_pkg; $date = $cust_pkg->bill; } my $err = $self->is_supported_domain( $svc_domain ); - die $err if $err; + return $err if $err; warn "$me: checking status\n" if $DEBUG; my $rv = $self->get_status($svc_domain); - die "Domain ". $svc_domain->domain. " is not renewable" + return "Domain ". $svc_domain->domain. " is not renewable" unless $rv->{expdate}; - die "Can't parse expiration date for ". $svc_domain->domain + return "Can't parse expiration date for ". $svc_domain->domain unless $rv->{expdate} =~ /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/; my ($year,$month,$day,$hour,$minute,$second) = ($1,$2,$3,$4,$5,$6); @@ -530,13 +531,11 @@ sub renew_through { $years++; $exp->add( 'years' => 1 ); - die "Can't renew ". $svc_domain->domain. " for more than 10 years." + return "Can't renew ". $svc_domain->domain. " for more than 10 years." if $years > 10; #no infinite loop } - return '' unless $years; - - warn "$me: renewing ". $svc_domain->domain. " for $years years\n" if $DEBUG; + warn "$me: renewing ". $svc_domain->domain. "for $years years\n" if $DEBUG; my $srs = $self->get_srs; $rv = $srs->make_request( { @@ -551,7 +550,7 @@ sub renew_through { } } ); - die $rv->{response_text} unless $rv->{is_success}; + return $rv->{response_text} unless $rv->{is_success}; return ''; # Should only get here if renewal succeeded } diff --git a/FS/FS/part_export/http.pm b/FS/FS/part_export/http.pm index e5e5a5c48..55d832966 100644 --- a/FS/FS/part_export/http.pm +++ b/FS/FS/part_export/http.pm @@ -1,10 +1,12 @@ package FS::part_export::http; -use base qw( FS::part_export ); -use vars qw( %options %info ); +use vars qw(@ISA %info); use Tie::IxHash; +use FS::part_export; -tie %options, 'Tie::IxHash', +@ISA = qw(FS::part_export); + +tie my %options, 'Tie::IxHash', 'method' => { label =>'Method', type =>'select', #options =>[qw(POST GET)], @@ -64,10 +66,6 @@ sub _export_command { return unless $self->option("${action}_data"); - my $cust_main = $svc_x->table eq 'cust_main' - ? $svc_x - : $svc_x->cust_svc->cust_pkg->cust_main; - $self->http_queue( $svc_x->svcnum, $self->option('method'), $self->option('url'), @@ -87,18 +85,12 @@ sub _export_replace { return unless $self->option('replace_data'); - my $new_cust_main = $new->table eq 'cust_main' - ? $new - : $new->cust_svc->cust_pkg->cust_main; - my $cust_main = $new_cust_main; #so folks can use $new_cust_main or $cust_main - - $self->http_queue( $new->svcnum, + $self->http_queue( $svc_x->svcnum, $self->option('method'), $self->option('url'), map { /^\s*(\S+)\s+(.*)$/ or /()()/; my( $field, $value_expression ) = ( $1, $2 ); - my $value = eval $value_expression; die $@ if $@; ( $field, $value ); } split(/\n/, $self->option('replace_data') ) @@ -108,8 +100,10 @@ sub _export_replace { sub http_queue { my($self, $svcnum) = (shift, shift); - my $queue = new FS::queue { 'job' => "FS::part_export::http::http" }; - $queue->svcnum($svcnum) if $svcnum; + my $queue = new FS::queue { + 'svcnum' => $svcnum, + 'job' => "FS::part_export::http::http", + }; $queue->insert( @_ ); } diff --git a/FS/FS/part_export/ldap.pm b/FS/FS/part_export/ldap.pm index 838532021..823d99dbf 100644 --- a/FS/FS/part_export/ldap.pm +++ b/FS/FS/part_export/ldap.pm @@ -11,8 +11,6 @@ tie my %options, 'Tie::IxHash', 'dn' => { label=>'Root DN' }, 'password' => { label=>'Root DN password' }, 'userdn' => { label=>'User DN' }, - 'key_attrib' => { label=>'Key attribute name', - default=>'uid' }, 'attributes' => { label=>'Attributes', type=>'textarea', default=>join("\n", @@ -51,50 +49,31 @@ END sub rebless { shift; } -sub svc_context_eval { - # This should possibly be in svc_Common? - # Except the only places we use it are here and in shellcommands, - # and it's not even the same version. - my $svc_acct = shift; - no strict 'refs'; - ${$_} = $svc_acct->getfield($_) foreach $svc_acct->fields; - ${$_} = $svc_acct->$_() foreach qw( domain ldap_password ); - my $cust_pkg = $svc_acct->cust_svc->cust_pkg; - if ( $cust_pkg ) { - my $cust_main = $cust_pkg->cust_main; - ${$_} = $cust_main->getfield($_) foreach qw(first last); +sub _export_insert { + my($self, $svc_acct) = (shift, shift); + + #false laziness w/shellcommands.pm + { + no strict 'refs'; + ${$_} = $svc_acct->getfield($_) foreach $svc_acct->fields; + ${$_} = $svc_acct->$_() foreach qw( domain ); + my $cust_pkg = $svc_acct->cust_svc->cust_pkg; + if ( $cust_pkg ) { + my $cust_main = $cust_pkg->cust_main; + ${$_} = $cust_main->getfield($_) foreach qw(first last); + } } - # DEPRECATED, probably fails for non-plain password encoding $crypt_password = ''; #surpress "used only once" warnings $crypt_password = '{crypt}'. crypt( $svc_acct->_password, $saltset[int(rand(64))].$saltset[int(rand(64))] ); - return map { eval(qq("$_")) } @_ ; -} - -sub key_attrib { - my $self = shift; - return $self->option('key_attrib') if $self->option('key_attrib'); - # otherwise, guess that it's the one that's set to $username - foreach ( split("\n",$self->option('attributes')) ) { - /^\s*(\w+)\s+\$username\s*$/ && return $1; - } - # can't recover from that, but we can fail in a more obvious way - # than the old code did... - die "no key_attrib set in LDAP export\n"; -} - -sub ldap_attrib { - # Convert the svc_acct to its LDAP attribute set. - my($self, $svc_acct) = (shift, shift); + my $username_attrib; my %attrib = map { /^\s*(\w+)\s+(.*\S)\s*$/; - ( $1 => $2 ); } + $username_attrib = $1 if $2 eq '$username'; + ( $1 => eval(qq("$2")) ); } grep { /^\s*(\w+)\s+(.*\S)\s*$/ } split("\n", $self->option('attributes')); - my @vals = svc_context_eval($svc_acct, values(%attrib)); - @attrib{keys(%attrib)} = @vals; - if ( $self->option('radius') ) { foreach my $table (qw(reply check)) { my $method = "radius_$table"; @@ -105,20 +84,22 @@ sub ldap_attrib { } } } - return %attrib; -} - -sub _export_insert { - my($self, $svc_acct) = (shift, shift); - my $err_or_queue = $self->ldap_queue( - $svc_acct->svcnum, - 'insert', - $self->key_attrib, - $self->ldap_attrib($svc_acct), - ); + my $err_or_queue = $self->ldap_queue( $svc_acct->svcnum, 'insert', + #$svc_acct->username, + $username_attrib, + %attrib ); return $err_or_queue unless ref($err_or_queue); + #groups with LDAP? + #my @groups = $svc_acct->radius_groups; + #if ( @groups ) { + # my $err_or_queue = $self->ldap_queue( + # $svc_acct->svcnum, 'usergroup_insert', + # $svc_acct->username, @groups ); + # return $err_or_queue unless ref($err_or_queue); + #} + ''; } @@ -132,42 +113,109 @@ sub _export_replace { local $SIG{TSTP} = 'IGNORE'; local $SIG{PIPE} = 'IGNORE'; + return "can't (yet?) change username with ldap" + if $old->username ne $new->username; + + return "ldap replace unimplemented"; + my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; my $jobnum = ''; + #if ( $old->username ne $new->username ) { + # my $err_or_queue = $self->ldap_queue( $new->svcnum, 'rename', + # $new->username, $old->username ); + # unless ( ref($err_or_queue) ) { + # $dbh->rollback if $oldAutoCommit; + # return $err_or_queue; + # } + # $jobnum = $err_or_queue->jobnum; + #} + + foreach my $table (qw(reply check)) { + my $method = "radius_$table"; + my %new = $new->$method(); + my %old = $old->$method(); + if ( grep { !exists $old{$_} #new attributes + || $new{$_} ne $old{$_} #changed + } keys %new + ) { + my $err_or_queue = $self->ldap_queue( $new->svcnum, 'insert', + $table, $new->username, %new ); + unless ( ref($err_or_queue) ) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + if ( $jobnum ) { + my $error = $err_or_queue->depend_insert( $jobnum ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + } - # the Lazy way: nuke the entry and recreate it. - # any reason this shouldn't work? Freeside _has_ to have - # write access to these entries and their parent DN. - my $key = $self->key_attrib; - my %attrib = $self->ldap_attrib($old); - my $err_or_queue = $self->ldap_queue( - $old->svcnum, - 'delete', - $key, - $attrib{$key} - ); - if( !ref($err_or_queue) ) { - $dbh->rollback if $oldAutoCommit; - return $err_or_queue; + my @del = grep { !exists $new{$_} } keys %old; + if ( @del ) { + my $err_or_queue = $self->ldap_queue( $new->svcnum, 'attrib_delete', + $table, $new->username, @del ); + unless ( ref($err_or_queue) ) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + if ( $jobnum ) { + my $error = $err_or_queue->depend_insert( $jobnum ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + } } - $jobnum = $err_or_queue->jobnum; - $err_or_queue = $self->ldap_queue( - $new->svcnum, - 'insert', - $key, - $self->ldap_attrib($new) - ); - if( !ref($err_or_queue) ) { - $dbh->rollback if $oldAutoCommit; - return $err_or_queue; + + # (sorta) false laziness with FS::svc_acct::replace + my @oldgroups = @{$old->usergroup}; #uuuh + my @newgroups = $new->radius_groups; + my @delgroups = (); + foreach my $oldgroup ( @oldgroups ) { + if ( grep { $oldgroup eq $_ } @newgroups ) { + @newgroups = grep { $oldgroup ne $_ } @newgroups; + next; + } + push @delgroups, $oldgroup; } - $err_or_queue = $err_or_queue->depend_insert($jobnum); - if( $err_or_queue ) { - $dbh->rollback if $oldAutoCommit; - return $err_or_queue; + + if ( @delgroups ) { + my $err_or_queue = $self->ldap_queue( $new->svcnum, 'usergroup_delete', + $new->username, @delgroups ); + unless ( ref($err_or_queue) ) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + if ( $jobnum ) { + my $error = $err_or_queue->depend_insert( $jobnum ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + } + + if ( @newgroups ) { + my $err_or_queue = $self->ldap_queue( $new->svcnum, 'usergroup_insert', + $new->username, @newgroups ); + unless ( ref($err_or_queue) ) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + if ( $jobnum ) { + my $error = $err_or_queue->depend_insert( $jobnum ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -177,13 +225,9 @@ sub _export_replace { sub _export_delete { my( $self, $svc_acct ) = (shift, shift); - - my $key = $self->key_attrib; - my ( $val ) = map { /^\s*$key\s+(.*\S)\s*$/ ? $1 : () } - split("\n", $self->option('attributes')); - ( $val ) = svc_context_eval($svc_acct, $val); + return "ldap delete unimplemented"; my $err_or_queue = $self->ldap_queue( $svc_acct->svcnum, 'delete', - $key, $val ); + $svc_acct->username ); ref($err_or_queue) ? '' : $err_or_queue; } @@ -204,9 +248,10 @@ sub ldap_queue { sub ldap_insert { #subroutine, not method my $ldap = ldap_connect(shift, shift, shift); - my( $userdn, $key_attrib, %attrib ) = @_; + my( $userdn, $username_attrib, %attrib ) = @_; - $userdn = "$key_attrib=$attrib{$key_attrib}, $userdn"; + $userdn = "$username_attrib=$attrib{$username_attrib}, $userdn" + if $username_attrib; #icky hack, but should be unsurprising to the LDAPers foreach my $key ( grep { $attrib{$_} =~ /,/ } keys %attrib ) { $attrib{$key} = [ split(/,/, $attrib{$key}) ]; @@ -218,32 +263,17 @@ sub ldap_insert { #subroutine, not method $ldap->unbind; } -sub ldap_delete { - my $ldap = ldap_connect(shift, shift, shift); - - my $entry = ldap_fetch($ldap, @_); - if($entry) { - my $status = $ldap->delete($entry); - die 'LDAP error: '.$status->error."\n" if $status->is_error; - } - $ldap->unbind; - # should failing to find the entry be fatal? - # if it is, it will block unprovisioning the service, which is a pain. -} - -sub ldap_fetch { - # avoid needless duplication in delete and modify - my( $ldap, $userdn, %key_data ) = @_; - my $filter = join('', map { "($_=$key_data{$_})" } keys(%key_data)); - - my $status = $ldap->search( base => $userdn, - scope => 'one', - filter => $filter ); - die 'LDAP error: '.$status->error."\n" if $status->is_error; - my ($entry) = $status->entries; - warn "Entry '$filter' not found in LDAP\n" if !$entry; - return $entry; -} +#sub ldap_delete { #subroutine, not method +# my $dbh = ldap_connect(shift, shift, shift); +# my $username = shift; +# +# foreach my $table (qw( radcheck radreply usergroup )) { +# my $sth = $dbh->prepare( "DELETE FROM $table WHERE UserName = ?" ); +# $sth->execute($username) +# or die "can't delete from $table table: ". $sth->errstr; +# } +# $dbh->disconnect; +#} sub ldap_connect { my( $machine, $dn, $password ) = @_; diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index f278d5ebd..ef7f55780 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -774,9 +774,34 @@ sub is_free { sub can_discount { 0; } sub freqs_href { - # moved to FS::Misc to make this accessible to other packages - # at initialization - FS::Misc::pkg_freqs(); + #method, class method or sub? #my $self = shift; + + tie my %freq, 'Tie::IxHash', + '0' => '(no recurring fee)', + '1h' => 'hourly', + '1d' => 'daily', + '2d' => 'every two days', + '3d' => 'every three days', + '1w' => 'weekly', + '2w' => 'biweekly (every 2 weeks)', + '1' => 'monthly', + '45d' => 'every 45 days', + '2' => 'bimonthly (every 2 months)', + '3' => 'quarterly (every 3 months)', + '4' => 'every 4 months', + '137d' => 'every 4 1/2 months (137 days)', + '6' => 'semiannually (every 6 months)', + '12' => 'annually', + '13' => 'every 13 months (annually +1 month)', + '24' => 'biannually (every 2 years)', + '36' => 'triannually (every 3 years)', + '48' => '(every 4 years)', + '60' => '(every 5 years)', + '120' => '(every 10 years)', + ; + + \%freq; + } =item freq_pretty diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 1d2f6733c..77b9af553 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -13,16 +13,9 @@ use FS::rate_prefix; use FS::rate_detail; use FS::part_pkg::recur_Common; -use List::Util qw(first min); - @ISA = qw(FS::part_pkg::recur_Common); -$DEBUG = 1; - -tie my %cdr_svc_method, 'Tie::IxHash', - 'svc_phone.phonenum' => 'Phone numbers (svc_phone.phonenum)', - 'svc_pbx.title' => 'PBX name (svc_pbx.title)', -; +$DEBUG = 0; tie my %rating_method, 'Tie::IxHash', 'prefix' => 'Rate calls by using destination prefix to look up a region and rate according to the internal prefix and rate tables', @@ -78,11 +71,6 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); 'select_options' => \%FS::part_pkg::recur_Common::recur_method, }, - 'cdr_svc_method' => { 'name' => 'CDR service matching method', - 'type' => 'radio', - 'options' => \%cdr_svc_method, - }, - 'rating_method' => { 'name' => 'Rating method', 'type' => 'radio', 'options' => \%rating_method, @@ -149,32 +137,12 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); 'use_cdrtypenum' => { 'name' => 'Do not charge for CDRs where the CDR Type is not set to: ', }, - 'skip_dst_prefix' => { 'name' => 'Do not charge for CDRs where the destination number starts with any of these values:', - }, - 'skip_dcontext' => { 'name' => 'Do not charge for CDRs where the dcontext is set to any of these (comma-separated) values:', }, 'skip_dstchannel_prefix' => { 'name' => 'Do not charge for CDRs where the dstchannel starts with:', }, - 'skip_src_length_more' => { 'name' => 'Do not charge for CDRs where the source is more than this many digits:', - }, - - 'noskip_src_length_accountcode_tollfree' => { 'name' => 'Do charge for CDRs where source is equal or greater than the specified digits and accountcode is toll free', - 'type' => 'checkbox', - }, - - 'accountcode_tollfree_ratenum' => { - 'name' => 'Optional alternate rate plan when accountcode is toll free', - 'type' => 'select', - 'select_table' => 'rate', - 'select_key' => 'ratenum', - 'select_label' => 'ratename', - 'disable_empty' => 0, - 'empty_label' => '', - }, - 'skip_dst_length_less' => { 'name' => 'Do not charge for CDRs where the destination is less than this many digits:', }, @@ -242,7 +210,6 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); 'fieldorder' => [qw( setup_fee recur_fee recur_temporality unused_credit recur_method cutoff_day - cdr_svc_method rating_method ratenum min_charge sec_granularity ignore_unrateable default_prefix @@ -251,10 +218,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); disable_tollfree use_amaflags use_disposition use_disposition_taqua use_carrierid use_cdrtypenum - skip_dcontext skip_dst_prefix - skip_dstchannel_prefix skip_src_length_more - noskip_src_length_accountcode_tollfree - accountcode_tollfree_ratenum + skip_dcontext skip_dstchannel_prefix skip_dst_length_less skip_lastapp use_duration 411_rewrite @@ -314,7 +278,6 @@ sub calc_usage { # my $downstream_cdr = ''; - my $cdr_svc_method = $self->option('cdr_svc_method')||'svc_phone.phonenum'; my $rating_method = $self->option('rating_method') || 'prefix'; my $intl = $self->option('international_prefix') || '011'; my $domestic_prefix = $self->option('domestic_prefix'); @@ -335,8 +298,6 @@ sub calc_usage { @dirass = split(',', $dirass); } - my %interval_cache = (); # for timed rates - #for check_chargable, so we don't keep looking up options inside the loop my %opt_cache = (); @@ -344,15 +305,13 @@ sub calc_usage { die $@ if $@; my $csv = new Text::CSV_XS; - my($svc_table, $svc_field) = split('\.', $cdr_svc_method); - foreach my $cust_svc ( - grep { $_->part_svc->svcdb eq $svc_table } $cust_pkg->cust_svc + grep { $_->part_svc->svcdb eq 'svc_phone' } $cust_pkg->cust_svc ) { - my $svc_x = $cust_svc->svc_x; + my $svc_phone = $cust_svc->svc_x; foreach my $cdr ( - $svc_x->get_cdrs( + $svc_phone->get_cdrs( 'disable_src' => $self->option('disable_src'), 'default_prefix' => $self->option('default_prefix'), 'status' => '', @@ -366,16 +325,11 @@ sub calc_usage { my $rate_detail; my( $rate_region, $regionnum ); - my $rate; my $pretty_destnum; my $charge = ''; my $seconds = ''; - my $weektime = ''; my $regionname = ''; my $classnum = ''; - my $countrycode; - my $number; - my @call_details = (); if ( $rating_method eq 'prefix' ) { @@ -402,7 +356,7 @@ sub calc_usage { # (or calling station id for toll free calls) ### - my( $to_or_from ); + my( $to_or_from, $number ); if ( $cdr->is_tollfree && ! $disable_tollfree ) { #tollfree call $to_or_from = 'from'; @@ -422,7 +376,7 @@ sub calc_usage { # $dest =~ s/\@(.*)$// and $siphost = $1; # @10.54.32.1, @sip.example.com #determine the country code - $countrycode = ''; + my $countrycode; if ( $number =~ /^$intl(((\d)(\d))(\d))(\d+)$/ || $number =~ /^\+(((\d)(\d))(\d))(\d+)$/ ) @@ -451,24 +405,11 @@ sub calc_usage { #asterisks here causes inserting the detail to barf, so: $pretty_destnum =~ s/\*//g; - my $eff_ratenum = $cdr->is_tollfree('accountcode') - ? $cust_pkg->part_pkg->option('accountcode_tollfree_ratenum') - : ''; - $eff_ratenum ||= $ratenum; - $rate = qsearchs('rate', { 'ratenum' => $eff_ratenum }) - or die "ratenum $eff_ratenum not found!"; - - my @ltime = localtime($cdr->startdate); - $weektime = $ltime[0] + - $ltime[1]*60 + #minutes - $ltime[2]*3600 + #hours - $ltime[6]*86400; #days since sunday - # if there's no timed rate_detail for this time/region combination, - # dest_detail returns the default. There may still be a timed rate - # that applies after the starttime of the call, so be careful... + my $rate = qsearchs('rate', { 'ratenum' => $ratenum }) + or die "ratenum $ratenum not found!"; + $rate_detail = $rate->dest_detail({ 'countrycode' => $countrycode, 'phonenum' => $number, - 'weektime' => $weektime, }); if ( $rate_detail ) { @@ -480,17 +421,6 @@ sub calc_usage { "and rate detail $rate_detail\n" if $DEBUG; - if ( !exists($interval_cache{$regionnum}) ) { - my @intervals = ( - sort { $a->stime <=> $b->stime } - map { my $r = $_->rate_time; $r ? $r->intervals : () } - $rate->rate_detail - ); - $interval_cache{$regionnum} = \@intervals; - warn " cached ".scalar(@intervals)." interval(s)\n" - if $DEBUG; - } - } elsif ( $ignore_unrateable ) { $rate_region = ''; @@ -525,7 +455,6 @@ sub calc_usage { # } else { #pass upstream price through # # $charge = sprintf('%.2f', $cdr->upstream_price); -# warn "Incrementing \$charges by $charge. Now $charges\n" if $DEBUG; # $charges += $charge; # # @call_details = ( @@ -544,7 +473,6 @@ sub calc_usage { #XXX $charge = sprintf('%.2f', $cdr->upstream_price); $charge = sprintf('%.3f', $cdr->upstream_price); $charges += $charge; - warn "Incrementing \$charges by $charge. Now $charges\n" if $DEBUG; @call_details = ($cdr->downstream_csv( 'format' => $output_format, 'charge' => $charge, @@ -575,7 +503,6 @@ sub calc_usage { $charge = sprintf('%.4f', ( $self->option('min_charge') * $minutes ) + 0.0000000001 ); #so 1.00005 rounds to 1.0001 - warn "Incrementing \$charges by $charge. Now $charges\n" if $DEBUG; $charges += $charge; @call_details = ($cdr->downstream_csv( 'format' => $output_format, @@ -605,121 +532,59 @@ sub calc_usage { unless ( @call_details || ( $charge ne '' && $charge == 0 ) ) { - my $seconds_left = $use_duration ? $cdr->duration : $cdr->billsec; - # charge for the first (conn_sec) seconds - $seconds = min($seconds_left, $rate_detail->conn_sec); - $seconds_left -= $seconds; - $weektime += $seconds; - $charge = sprintf("%.02f", $rate_detail->conn_charge); - - my $total_minutes = 0; - my $whole_minutes = 1; - my $etime; - while($seconds_left) { - my $ratetimenum = $rate_detail->ratetimenum; # may be empty - - # find the end of the current rate interval - if(@{ $interval_cache{$regionnum} } == 0) { - # There are no timed rates in this group, so just stay - # in the default rate_detail for the entire duration. - # Set an "end" of 1 past the end of the current call. - $etime = $weektime + $seconds_left + 1; - } - elsif($ratetimenum) { - # This is a timed rate, so go to the etime of this interval. - # If it's followed by another timed rate, the stime of that - # interval should match the etime of this one. - my $interval = $rate_detail->rate_time->contains($weektime); - $etime = $interval->etime; - } - else { - # This is a default rate, so use the stime of the next - # interval in the sequence. - my $next_int = first { $_->stime > $weektime } - @{ $interval_cache{$regionnum} }; - if ($next_int) { - $etime = $next_int->stime; - } - else { - # weektime is near the end of the week, so decrement - # it by a full week and use the stime of the first - # interval. - $weektime -= (3600*24*7); - $etime = $interval_cache{$regionnum}->[0]->stime; - } - } - - my $charge_sec = min($seconds_left, $etime - $weektime); + $included_min{$regionnum} = $rate_detail->min_included + unless exists $included_min{$regionnum}; - $seconds_left -= $charge_sec; + my $granularity = $rate_detail->sec_granularity; - $included_min{$regionnum}{$ratetimenum} = $rate_detail->min_included - unless exists $included_min{$regionnum}{$ratetimenum}; + # length($cdr->billsec) ? $cdr->billsec : $cdr->duration; + $seconds = $use_duration ? $cdr->duration : $cdr->billsec; - my $granularity = $rate_detail->sec_granularity; - $whole_minutes = 0 if $granularity; + $seconds -= $rate_detail->conn_sec; + $seconds = 0 if $seconds < 0; - # should this be done in every rate interval? - $charge_sec += $granularity - ( $charge_sec % $granularity ) - if $charge_sec # don't granular-ize 0 billsec calls (bills them) - && $granularity; # 0 is per call - my $minutes = sprintf("%.1f", $charge_sec / 60); - $minutes =~ s/\.0$// if $granularity == 60; + $seconds += $granularity - ( $seconds % $granularity ) + if $seconds # don't granular-ize 0 billsec calls (bills them) + && $granularity; # 0 is per call + my $minutes = sprintf("%.1f", $seconds / 60); + $minutes =~ s/\.0$// if $granularity == 60; - $seconds += $charge_sec; + # per call rather than per minute + $minutes = 1 unless $granularity; - # per call rather than per minute - $minutes = 1 unless $granularity; - $seconds_left = 0 unless $granularity; + $included_min{$regionnum} -= $minutes; - $included_min{$regionnum}{$ratetimenum} -= $minutes; - - if ( $included_min{$regionnum}{$ratetimenum} <= 0 ) { - my $charge_min = 0 - $included_min{$regionnum}{$ratetimenum}; #XXX should preserve - #(display?) this - $included_min{$regionnum}{$ratetimenum} = 0; - $charge += sprintf('%.2f', ($rate_detail->min_charge * $charge_min) - + 0.00000001 ); #so 1.005 rounds to 1.01 - } + $charge = sprintf('%.2f', $rate_detail->conn_charge); - # choose next rate_detail - $rate_detail = $rate->dest_detail({ 'countrycode' => $countrycode, - 'phonenum' => $number, - 'weektime' => $etime }) - if($seconds_left); - # we have now moved forward to $etime - $weektime = $etime; + if ( $included_min{$regionnum} < 0 ) { + my $charge_min = 0 - $included_min{$regionnum}; #XXX should preserve + #(display?) this + $included_min{$regionnum} = 0; + $charge += sprintf('%.2f', ($rate_detail->min_charge * $charge_min) + + 0.00000001 ); #so 1.005 rounds to 1.01 + $charge = sprintf('%.2f', $charge); + $charges += $charge; + } - } #while $seconds_left # this is why we need regionnum/rate_region.... warn " (rate region $rate_region)\n" if $DEBUG; - $total_minutes = sprintf("%.1f", $seconds / 60); - $total_minutes =~ s/\.0$// if $whole_minutes; + @call_details = ( + $cdr->downstream_csv( 'format' => $output_format, + 'granularity' => $granularity, + 'minutes' => $minutes, + 'charge' => $charge, + 'pretty_dst' => $pretty_destnum, + 'dst_regionname' => $regionname, + ) + ); $classnum = $rate_detail->classnum; - $charge = sprintf('%.2f', $charge); - @call_details = ( - $cdr->downstream_csv( 'format' => $output_format, - 'granularity' => $rate_detail->sec_granularity, - 'minutes' => $total_minutes, - # why do we go through this hocus-pocus? - # the cdr *will* show duration here - # if we forego the 'minutes' key - # duration vs billsec? - 'charge' => $charge, - 'pretty_dst' => $pretty_destnum, - 'dst_regionname' => $regionname, - ) - ); - } #if(there is a rate_detail) - + } if ( $charge > 0 ) { #just use FS::cust_bill_pkg_detail objects? - warn "Incrementing \$charges by $charge. Now $charges\n" if $DEBUG; - $charges += $charge; my $call_details; my $phonenum = $cust_svc->svc_x->phonenum; @@ -823,10 +688,8 @@ sub check_chargable { use_disposition_taqua use_carrierid use_cdrtypenum - skip_dst_prefix skip_dcontext skip_dstchannel_prefix - skip_src_length_more noskip_src_length_accountcode_tollfree skip_dst_length_less skip_lastapp ); @@ -853,11 +716,6 @@ sub check_chargable { if length($opt{'use_cdrtypenum'}) && $cdr->cdrtypenum ne $opt{'use_cdrtypenum'}; #ne otherwise 0 matches '' - foreach(split(',',$opt{'skip_dst_prefix'})) { - return "dst starts with '$_'" - if length($_) && substr($cdr->dst,0,length($_)) eq $_; - } - return "dcontext IN ( $opt{'skip_dcontext'} )" if $opt{'skip_dcontext'} =~ /\S/ && grep { $cdr->dcontext eq $_ } split(/\s*,\s*/, $opt{'skip_dcontext'}); @@ -874,26 +732,6 @@ sub check_chargable { return "lastapp is $opt{'skip_lastapp'}" if length($opt{'skip_lastapp'}) && $cdr->lastapp eq $opt{'skip_lastapp'}; - my $src_length = $opt{'skip_src_length_more'}; - if ( $src_length ) { - - if ( $opt{'noskip_src_length_accountcode_tollfree'} ) { - - if ( $cdr->is_tollfree('accountcode') ) { - return "source less than or equal to $src_length digits" - if length($cdr->src) <= $src_length; - } else { - return "source more than $src_length digits" - if length($cdr->src) > $src_length; - } - - } else { - return "source more than $src_length digits" - if length($cdr->src) > $src_length; - } - - } - #all right then, rate it ''; } diff --git a/FS/FS/part_pkg_taxrate.pm b/FS/FS/part_pkg_taxrate.pm index fb1afce18..5a1e7baa9 100644 --- a/FS/FS/part_pkg_taxrate.pm +++ b/FS/FS/part_pkg_taxrate.pm @@ -296,7 +296,7 @@ sub batch_import { $hash->{'country'} = 'US'; # CA is available - $hash->{'taxable'} = '' if ($hash->{'taxable'} eq 'N'); + delete($hash->{'taxable'}) if ($hash->{'taxable'} eq 'N'); if (exists($hash->{actionflag}) && $hash->{actionflag} eq 'D') { delete($hash->{actionflag}); diff --git a/FS/FS/part_tag.pm b/FS/FS/part_tag.pm deleted file mode 100644 index 0229e3aaa..000000000 --- a/FS/FS/part_tag.pm +++ /dev/null @@ -1,132 +0,0 @@ -package FS::part_tag; - -use strict; -use base qw( FS::Record ); -use FS::Record qw( qsearch qsearchs ); - -=head1 NAME - -FS::part_tag - Object methods for part_tag records - -=head1 SYNOPSIS - - use FS::part_tag; - - $record = new FS::part_tag \%hash; - $record = new FS::part_tag { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::part_tag object represents a tag. FS::part_tag inherits from -FS::Record. The following fields are currently supported: - -=over 4 - -=item tagnum - -primary key - -=item tagname - -tagname - -=item tagdesc - -tagdesc - -=item tagcolor - -tagcolor - - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new tag. To add the tag to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -# the new method can be inherited from FS::Record, if a table method is defined - -sub table { 'part_tag'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -# the insert method can be inherited from FS::Record - -=item delete - -Delete this record from the database. - -=cut - -# the delete method can be inherited from FS::Record - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -# the replace method can be inherited from FS::Record - -=item check - -Checks all fields to make sure this is a valid tag. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -# the check method should currently be supplied - FS::Record contains some -# data checking routines - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('tagnum') - || $self->ut_text('tagname') - || $self->ut_textn('tagdesc') - || $self->ut_textn('tagcolor') - || $self->ut_enum('disabled', [ '', 'Y' ] ) - ; - return $error if $error; - - $self->SUPER::check; -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/pay_batch.pm b/FS/FS/pay_batch.pm index 3abb06d2a..6a2755494 100644 --- a/FS/FS/pay_batch.pm +++ b/FS/FS/pay_batch.pm @@ -195,9 +195,6 @@ sub import_results { my $info = $import_info{$format} or die "unknown format $format"; - my $job = $param->{'job'}; - $job->update_statustext(0) if $job; - my $filetype = $info->{'filetype'}; # CSV or fixed my @fields = @{ $info->{'fields'}}; my $formatre = $info->{'formatre'}; # for fixed @@ -289,12 +286,7 @@ sub import_results { } } - my $num = 0; foreach (@all_values) { - if($job) { - $num++; - $job->update_statustext(int(100 * $num/scalar(@all_values))); - } my @values = @$_; my %hash; @@ -362,8 +354,7 @@ sub import_results { 'custnum' => $custnum, 'payby' => $payby, 'paybatch' => $self->batchnum, - 'payinfo' => ( $hash{'payinfo'} || $cust_pay_batch->payinfo ), - map { $_ => $hash{$_} } (qw( paid _date )), + map { $_ => $hash{$_} } (qw( paid _date payinfo )), } ); $error = $cust_pay->insert; if ( $error ) { @@ -413,29 +404,6 @@ sub import_results { } -use MIME::Base64; -use Storable 'thaw'; -use Data::Dumper; -sub process_import_results { - my $job = shift; - my $param = thaw(decode_base64(shift)); - $param->{'job'} = $job; - warn Dumper($param) if $DEBUG; - my $batchnum = delete $param->{'batchnum'} or die "no batchnum specified\n"; - my $batch = FS::pay_batch->by_key($batchnum) or die "batchnum '$batchnum' not found\n"; - - my $file = $param->{'uploaded_files'} or die "no files provided\n"; - $file =~ s/^(\w+):([\.\w]+)$/$2/; - my $dir = '%%%FREESIDE_CACHE%%%/cache.' . $FS::UID::datasrc; - open( $param->{'filehandle'}, - '<', - "$dir/$file" ) - or die "unable to open '$file'.\n"; - my $error = $batch->import_results($param); - unlink $file; - die $error if $error; -} - # Formerly httemplate/misc/download-batch.cgi sub export_batch { my $self = shift; diff --git a/FS/FS/payinfo_Mixin.pm b/FS/FS/payinfo_Mixin.pm index 9995183d8..99cca6a8a 100644 --- a/FS/FS/payinfo_Mixin.pm +++ b/FS/FS/payinfo_Mixin.pm @@ -18,6 +18,12 @@ use vars qw(@ISA); This is a mixin class for records that contain payinfo. +This class handles the following functions for payinfo... + +Payment Mask (Generation and Storage) +Data Validation (parent checks need to be sure to call this) +Pretty printing + =head1 FIELDS =over 4 @@ -66,12 +72,12 @@ Card Number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or sub payinfo { my($self,$payinfo) = @_; - if ( defined($payinfo) ) { - $self->setfield('payinfo', $payinfo); - $self->paymask($self->mask_payinfo) unless $payinfo =~ /^99\d{14}$/; #token + $self->setfield('payinfo', $payinfo); # This is okay since we are the 'setter' + $self->paymask($self->mask_payinfo()); } else { - $self->getfield('payinfo'); + $payinfo = $self->getfield('payinfo'); # This is okay since we are the 'getter' + return $payinfo; } } @@ -104,11 +110,25 @@ sub paycvv { sub paymask { my($self, $paymask) = @_; - if ( defined($paymask) ) { - $self->setfield('paymask', $paymask); + if ( defined($paymask) && $paymask ne '' ) { + # I hate this little bit of magic... I don't expect it to cause a problem, + # but who knows... If the payinfo is passed in masked then ignore it and + # set it based on the payinfo. The only guy that should call this in this + # way is... $self->payinfo + $self->setfield('paymask', $self->mask_payinfo()); + } else { - $self->getfield('paymask') || $self->mask_payinfo; + + $paymask=$self->getfield('paymask'); + if (!defined($paymask) || $paymask eq '') { + # Generate it if it's blank - Note that we're not going to set it - just + # generate + $paymask = $self->mask_payinfo(); + } + } + + return $paymask; } =back @@ -135,8 +155,6 @@ sub mask_payinfo { my $paymask; if ( $self->is_encrypted($payinfo) ) { $paymask = 'N/A'; - } elsif ( $payinfo =~ /^99\d{14}$/ || $payinfo eq 'N/A' ) { #token - $paymask = 'N/A (tokenized)'; #? } else { # if not, mask it... if ($payby eq 'CARD' || $payby eq 'DCRD' || $payby eq 'MCRD') { @@ -159,7 +177,7 @@ sub mask_payinfo { $paymask = $payinfo; } } - $paymask; + return $paymask; } =item payinfo_check @@ -200,8 +218,7 @@ sub payinfo_check { or return "Illegal (mistyped?) credit card number (payinfo)"; $self->payinfo($1); validate($self->payinfo) or return "Illegal credit card number"; - return "Unknown card type" if $self->payinfo !~ /^99\d{14}$/ #token - && cardtype($self->payinfo) eq "Unknown"; + return "Unknown card type" if cardtype($self->payinfo) eq "Unknown"; } else { $self->payinfo('N/A'); #??? } @@ -258,6 +275,11 @@ sub payby_payinfo_pretty { =head1 BUGS +Future items? + Encryption - In the Future (Pull from Record.pm) + Bad Card Stuff - In the Future (Integrate Banned Pay) + Currency - In the Future + =head1 SEE ALSO L<FS::payby>, L<FS::Record> diff --git a/FS/FS/queue.pm b/FS/FS/queue.pm index 3f8763da8..99e349c61 100644 --- a/FS/FS/queue.pm +++ b/FS/FS/queue.pm @@ -12,7 +12,7 @@ use FS::Record qw( qsearch qsearchs dbh ); use FS::queue_arg; use FS::queue_depend; use FS::cust_svc; -use FS::CGI qw(rooturl); +use FS::CGI qw (rooturl); @ISA = qw(FS::Record); @EXPORT_OK = qw( joblisting ); @@ -67,20 +67,6 @@ Job status (new, locked, or failed) Freeform text status message -=cut - -sub statustext { - my $self = shift; - if ( defined ( $_[0] ) ) { - $self->SUPER::statustext(@_); - } else { - my $value = $self->SUPER::statustext(); - my $rooturl = rooturl(); - $value =~ s/%%%ROOTURL%%%/$rooturl/g; - $value; - } -} - =item _date UNIX timestamp @@ -377,7 +363,7 @@ If there is an error, returns the error, otherwise returns false. use vars qw($_update_statustext_dbh); sub update_statustext { my( $self, $statustext ) = @_; - return '' if $statustext eq $self->get('statustext'); #avoid rooturl expansion + return '' if $statustext eq $self->statustext; warn "updating statustext for $self to $statustext" if $DEBUG; $_update_statustext_dbh ||= myconnect; @@ -388,7 +374,7 @@ sub update_statustext { $sth->execute($statustext, $self->jobnum) or return $sth->errstr; $_update_statustext_dbh->commit or die $_update_statustext_dbh->errstr; - $self->set('statustext', $statustext); #avoid rooturl expansion + $self->statustext($statustext); ''; #my $new = new FS::queue { $self->hash }; diff --git a/FS/FS/rate.pm b/FS/FS/rate.pm index f30e4c772..793846a7f 100644 --- a/FS/FS/rate.pm +++ b/FS/FS/rate.pm @@ -279,22 +279,16 @@ Destination can be specified as an FS::rate_detail object or regionnum (see L<FS::rate_detail>), or as a hashref with two keys: I<countrycode> and I<phonenum>. -An optional third key, I<weektime>, will return a timed rate (one with -a non-null I<ratetimenum>) if one exists for a call at that time. If -no matching timed rate exists, the non-timed rate will be returned. - =cut sub dest_detail { my $self = shift; my $regionnum; - my $weektime; if ( ref($_[0]) eq 'HASH' ) { my $countrycode = $_[0]->{'countrycode'}; my $phonenum = $_[0]->{'phonenum'}; - $weektime = $_[0]->{'weektime'}; #find a rate prefix, first look at most specific, then fewer digits, # finally trying the country code only @@ -320,31 +314,9 @@ sub dest_detail { } else { $regionnum = ref($_[0]) ? shift->regionnum : shift; } - - if(!defined($weektime)) { - return qsearchs( 'rate_detail', - { 'ratenum' => $self->ratenum, - 'dest_regionnum' => $regionnum, - 'ratetimenum' => '', - } ); - } - else { - my @details = grep { my $rate_time = $_->rate_time; - $rate_time && $rate_time->contains($weektime) } - qsearch( 'rate_detail', - { 'ratenum' => $self->ratenum, - 'dest_regionnum' => $regionnum, } ); - if(!@details) { - # this may change at some point - return $self->dest_detail($regionnum); - } - elsif(@details == 1) { - return $details[0]; - } - else { - die "overlapping rate_detail times (region $regionnum, time $weektime)\n"; - } - } + + qsearchs( 'rate_detail', { 'ratenum' => $self->ratenum, + 'dest_regionnum' => $regionnum, } ); } =item rate_detail diff --git a/FS/FS/rate_detail.pm b/FS/FS/rate_detail.pm index 7b9045205..f6cdedf6e 100644 --- a/FS/FS/rate_detail.pm +++ b/FS/FS/rate_detail.pm @@ -5,7 +5,6 @@ use vars qw( @ISA $DEBUG $me ); use FS::Record qw( qsearch qsearchs dbh ); use FS::rate; use FS::rate_region; -use FS::rate_time; use Tie::IxHash; @ISA = qw(FS::Record); @@ -55,8 +54,6 @@ inherits from FS::Record. The following fields are currently supported: =item classnum - usage class (see L<FS::usage_class>) if any for this rate -=item ratetimenum - rating time period (see L<FS::rate_time) if any - =back =head1 METHODS @@ -197,30 +194,6 @@ sub dest_prefixes_short { $self->dest_region->prefixes_short; } -=item rate_time - -Returns the L<FS::rate_time> object associated with this call -plan rate, if there is one. - -=cut - -sub rate_time { - my $self = shift; - $self->ratetimenum ? FS::rate_time->by_key($self->ratetimenum) : (); -} - -=item rate_time_name - -Returns the I<ratetimename> field of the L<FS::rate_time> object -associated with this rate plan. - -=cut - -sub rate_time_name { - my $self = shift; - $self->ratetimenum ? $self->rate_time->ratetimename : '(default)'; -} - =item classname Returns the name of the usage class (see L<FS::usage_class>) associated with diff --git a/FS/FS/rate_time.pm b/FS/FS/rate_time.pm deleted file mode 100644 index 40cd23e9c..000000000 --- a/FS/FS/rate_time.pm +++ /dev/null @@ -1,168 +0,0 @@ -package FS::rate_time; - -use strict; -use base qw( FS::Record ); -use FS::Record qw( qsearch qsearchs ); -use FS::rate_time_interval; - -=head1 NAME - -FS::rate_time - Object methods for rate_time records - -=head1 SYNOPSIS - - use FS::rate_time; - - $record = new FS::rate_time \%hash; - $record = new FS::rate_time { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::rate_time object represents a time period for selection of CDR billing -rates. FS::rate_time inherits from FS::Record. The following fields are -currently supported: - -=over 4 - -=item ratetimenum - -primary key - -=item ratetimename - -A label (like "Daytime" or "Weekend"). - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new example. To add the example to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -# the new method can be inherited from FS::Record, if a table method is defined - -sub table { 'rate_time'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -# the insert method can be inherited from FS::Record - -=item delete - -Delete this record from the database. - -=cut - -# the delete method can be inherited from FS::Record - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -# the replace method can be inherited from FS::Record - -=item check - -Checks all fields to make sure this is a valid example. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('ratetimenum') - || $self->ut_text('ratetimename') - ; - return $error if $error; - - $self->SUPER::check; -} - -=item intervals - -Return the L<FS::rate_time_interval> objects included in this rating period. - -=cut - -sub intervals { - my $self = shift; - return qsearch({ table => 'rate_time_interval', - hashref => { ratetimenum => $self->ratetimenum }, - order_by => 'ORDER BY stime ASC', - }); -} - -=item contains TIME - -Return the L<FS::rate_time_interval> object that contains the specified -time-of-week (in seconds from the start of Sunday). The primary use of -this is to test whether that time falls within this rating period. - -=cut - -sub contains { - my $self = shift; - my $weektime = shift; - return qsearchs('rate_time_interval', { ratetimenum => $self->ratetimenum, - stime => { op => '<=', - value => $weektime }, - etime => { op => '>', - value => $weektime }, - } ); -} - -=item description - -Returns a list of arrayrefs containing the starting and -ending times of each interval in this period, in a readable -format. - -=cut - -sub description { - my $self = shift; - return map { [ $_->description ] } $self->intervals; -} - - -=back - -=head1 BUGS - -To be seen. - -=head1 SEE ALSO - -L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/rate_time_interval.pm b/FS/FS/rate_time_interval.pm deleted file mode 100644 index 1a82edbe5..000000000 --- a/FS/FS/rate_time_interval.pm +++ /dev/null @@ -1,178 +0,0 @@ -package FS::rate_time_interval; - -use strict; -use base qw( FS::Record ); -use FS::Record qw( qsearch qsearchs ); -use List::Util 'first'; - -=head1 NAME - -FS::rate_time_interval - Object methods for rate_time_interval records - -=head1 SYNOPSIS - - use FS::rate_time_interval; - - $record = new FS::rate_time_interval \%hash; - $record = new FS::rate_time_interval { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - -=head1 DESCRIPTION - -An FS::rate_time_interval object represents an interval of clock time during -the week, such as "Monday, 7 AM to 8 PM". FS::rate_time_interval inherits -from FS::Record. The following fields are currently supported: - -=over 4 - -=item intervalnum - -primary key - -=item stime - -Start of the interval, in seconds from midnight on Sunday. - -=item etime - -End of the interval. - -=item ratetimenum - -A foreign key to an L<FS::rate_time> object representing the set of intervals -to which this belongs. - - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF - -Creates a new example. To add the example to the database, see L<"insert">. - -Note that this stores the hash reference, not a distinct copy of the hash it -points to. You can ask the object for a copy with the I<hash> method. - -=cut - -# the new method can be inherited from FS::Record, if a table method is defined - -sub table { 'rate_time_interval'; } - -=item insert - -Adds this record to the database. If there is an error, returns the error, -otherwise returns false. - -=cut - -# the insert method can be inherited from FS::Record - -=item delete - -Delete this record from the database. - -=cut - -# the delete method can be inherited from FS::Record - -=item replace OLD_RECORD - -Replaces the OLD_RECORD with this one in the database. If there is an error, -returns the error, otherwise returns false. - -=cut - -# the replace method can be inherited from FS::Record - -=item check - -Checks all fields to make sure this is a valid interval. If there is -an error, returns the error, otherwise returns false. Called by the insert -and replace methods. - -=cut - -sub check { - my $self = shift; - - my $error = - $self->ut_numbern('intervalnum') - || $self->ut_number('stime') - || $self->ut_number('etime') - || $self->ut_number('ratetimenum') - ; - return $error if $error; - # Disallow backward intervals. As a special case, an etime of 0 - # should roll to the last second of the week. - $self->etime(7*24*60*60) if $self->etime == 0; - return "end of interval is before start" if ($self->etime < $self->stime); - - # Detect overlap between intervals within the same rate_time. - # Since intervals are added one at a time, we only need to look - # for an existing interval that contains one of the endpoints of - # this one or that is completely inside this one. - my $overlap = $self->rate_time->contains($self->stime + 1) || - $self->rate_time->contains($self->etime - 1) || - first { $self->stime <= $_->stime && $self->etime >= $_->etime } - ( $self->rate_time->intervals ); - return "interval overlap: (".join('-',$self->description).') with ('. - join('-',$overlap->description).')' if $overlap; - - $self->SUPER::check; -} - -=item rate_time - -Returns the L<FS::rate_time> comprising this interval. - -=cut - -sub rate_time { - my $self = shift; - FS::rate_time->by_key($self->ratetimenum); -} - -=item description - -Returns two strings containing stime and etime, formatted -"Day HH:MM AM/PM". Example: "Mon 5:00 AM". Seconds are -not displayed, so be careful. - -=cut - -my @days = qw(Sun Mon Tue Wed Thu Fri Sat); - -sub description { - my $self = shift; - return map { - sprintf('%s %02d:%02d %s', - $days[int($_/86400) % 7], - int($_/3600) % 12, - int($_/60) % 60, - (($_/3600) % 24 < 12) ? 'AM' : 'PM' ) - } ( $self->stime, $self->etime ); -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -L<FS::rate_time>, L<FS::Record>, schema.html from the base documentation. - -=cut - -1; - diff --git a/FS/FS/svc_CGPRule_Mixin.pm b/FS/FS/svc_CGPRule_Mixin.pm index cf2eca76c..45015806c 100644 --- a/FS/FS/svc_CGPRule_Mixin.pm +++ b/FS/FS/svc_CGPRule_Mixin.pm @@ -22,7 +22,7 @@ This is a mixin class for svc_ classes that can have Communigate Pro rules =over 4 -=item cgp_rule +=item Returns the rules associated with this service, as FS::cgp_rule objects. diff --git a/FS/FS/svc_CGP_Mixin.pm b/FS/FS/svc_CGP_Mixin.pm deleted file mode 100644 index 489e9791f..000000000 --- a/FS/FS/svc_CGP_Mixin.pm +++ /dev/null @@ -1,142 +0,0 @@ -package FS::svc_CGP_Mixin; - -use strict; - -=head1 NAME - -FS::svc_CGP_Mixin - Mixin class for svc_classes which can be related to cgp_rule - -=head1 SYNOPSIS - -package FS::svc_table; -use base qw( FS::svc_CGP_Mixin FS::svc_Common ); - -=head1 DESCRIPTION - -This is a mixin class for svc_ classes that are exported to Communigate Pro. - -It currently contains timezone data for domains and accounts. - -=head1 METHODS - -=over 4 - -=item cgp_timezone - -Returns an arrayref of Communigate time zones. - -=cut - -#http://www.communigate.com/pub/client/TimeZones.data -#http://www.communigate.com/cgatepro/WebMail.html#Settings - -sub cgp_timezone_values { - #my $self = shift; #i'm used as a class and object method but just return data - - [ '', - 'HostOS', - '(+0100) Algeria/Congo', - '(+0200) Egypt/South Africa', - '(+0300) Saudi Arabia', - '(+0400) Oman', - '(+0500) Pakistan', - '(+0600) Bangladesh', - '(+0700) Thailand/Vietnam', - '(+0800) China/Malaysia', - '(+0900) Japan/Korea', - '(+1000) Queensland', - '(+1100) Micronesia', - '(+1200) Fiji', - '(+1300) Tonga/Kiribati', - '(+1400) Christmas Islands', - '(-0100) Azores/Cape Verde', - '(-0200) Fernando de Noronha', - '(-0300) Argentina/Uruguay', - '(-0400) Venezuela/Guyana', - '(-0500) Haiti/Peru', - '(-0600) Central America', - '(-0700) Arisona', #Arizona? - '(-0800) Adamstown', - '(-0900) Marquesas Islands', - '(-1000) Hawaii/Tahiti', - '(-1100) Samoa', - 'Asia/Afghanistan', - 'Asia/India', - 'Asia/Iran', - 'Asia/Iraq', - 'Asia/Israel', - 'Asia/Jordan', - 'Asia/Lebanon', - 'Asia/Syria', - 'Australia/Adelaide', - 'Australia/East', - 'Australia/NorthernTerritory', - 'Europe/Central', - 'Europe/Eastern', - 'Europe/Moscow', - 'Europe/Western', - 'GMT (+0000)', - 'Newfoundland', - 'NewZealand/Auckland', - 'NorthAmerica/Alaska', - 'NorthAmerica/Atlantic', - 'NorthAmerica/Central', - 'NorthAmerica/Eastern', - 'NorthAmerica/Mountain', - 'NorthAmerica/Pacific', - 'Russia/Ekaterinburg', - 'Russia/Irkutsk', - 'Russia/Kamchatka', - 'Russia/Krasnoyarsk', - 'Russia/Magadan', - 'Russia/Novosibirsk', - 'Russia/Vladivostok', - 'Russia/Yakutsk', - 'SouthAmerica/Brasil', - 'SouthAmerica/Chile', - 'SouthAmerica/Paraguay', - ]; -} - -=item cgp_emptytrash_values - -Returns an arrayref of possible EmptyTrash values. - -=cut - -#http://www.communigate.com/cgatepro/WebMail.html#Trash - -sub cgp_emptytrash_values { - #my $self = shift; #i'm used as a class and object method but just return data - - [ '', #<option value="-1">default(92 days) - '0 seconds', - '60 minutes', - '2 hours', - '3 hours', - '6 hours', - '12 hours', - '24 hours', - '2 days', - '3 days', - '7 days', - '10 days', - '2 weeks', - '3 weeks', - '30 days', - '60 days', - '90 days', - '180 days', - '360 days', - ]; -} - -=back - -=head1 BUGS - -=head1 SEE ALSO - -=cut - -1; diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 3b26688bf..9236067f0 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -1,8 +1,7 @@ package FS::svc_acct; use strict; -use base qw( FS::svc_Domain_Mixin FS::svc_CGP_Mixin FS::svc_CGPRule_Mixin - FS::svc_Common ); +use base qw( FS::svc_Domain_Mixin FS::svc_CGPRule_Mixin FS::svc_Common ); use vars qw( $DEBUG $me $conf $skip_fuzzyfiles $dir_prefix @shells $usernamemin $usernamemax $passwordmin $passwordmax @@ -451,9 +450,8 @@ sub table_info { disable_select => 1, }, 'cgp_emptytrash' => { - label => 'Communigate on logout remove trash', - type => 'select', - select_list => __PACKAGE__->cgp_emptytrash_values, + label => 'Communigate on logout remove trash', + type => 'text', disable_inventory => 1, disable_select => 1, }, @@ -465,9 +463,71 @@ sub table_info { disable_select => 1, }, 'cgp_timezone' => { - label => 'Communigate time zone', - type => 'select', - select_list => __PACKAGE__->cgp_timezone_values, + label => 'Communigate time zone', + type => 'select', + select_list => [ '', + 'HostOS', + '(+0100) Algeria/Congo', + '(+0200) Egypt/South Africa', + '(+0300) Saudi Arabia', + '(+0400) Oman', + '(+0500) Pakistan', + '(+0600) Bangladesh', + '(+0700) Thailand/Vietnam', + '(+0800) China/Malaysia', + '(+0900) Japan/Korea', + '(+1000) Queensland', + '(+1100) Micronesia', + '(+1200) Fiji', + '(+1300) Tonga/Kiribati', + '(+1400) Christmas Islands', + '(-0100) Azores/Cape Verde', + '(-0200) Fernando de Noronha', + '(-0300) Argentina/Uruguay', + '(-0400) Venezuela/Guyana', + '(-0500) Haiti/Peru', + '(-0600) Central America', + '(-0700) Arisona', + '(-0800) Adamstown', + '(-0900) Marquesas Islands', + '(-1000) Hawaii/Tahiti', + '(-1100) Samoa', + 'Asia/Afghanistan', + 'Asia/India', + 'Asia/Iran', + 'Asia/Iraq', + 'Asia/Israel', + 'Asia/Jordan', + 'Asia/Lebanon', + 'Asia/Syria', + 'Australia/Adelaide', + 'Australia/East', + 'Australia/NorthernTerritory', + 'Europe/Central', + 'Europe/Eastern', + 'Europe/Moscow', + 'Europe/Western', + 'GMT (+0000)', + 'Newfoundland', + 'NewZealand/Auckland', + 'NorthAmerica/Alaska', + 'NorthAmerica/Atlantic', + 'NorthAmerica/Central', + 'NorthAmerica/Eastern', + 'NorthAmerica/Mountain', + 'NorthAmerica/Pacific', + 'Russia/Ekaterinburg', + 'Russia/Irkutsk', + 'Russia/Kamchatka', + 'Russia/Krasnoyarsk', + 'Russia/Magadan', + 'Russia/Novosibirsk', + 'Russia/Vladivostok', + 'Russia/Yakutsk', + 'SouthAmerica/Brasil', + 'SouthAmerica/Chile', + 'SouthAmerica/Paraguay', + ], disable_inventory => 1, disable_select => 1, }, @@ -721,89 +781,82 @@ sub insert { } #welcome email - my $error = ''; - my $msgnum = $conf->config('welcome_msgnum', $agentnum); - if ( $msgnum ) { - my $msg_template = qsearchs('msg_template', { msgnum => $msgnum }); - $error = $msg_template->send('cust_main' => $cust_main); + my ($to,$welcome_template,$welcome_from,$welcome_subject,$welcome_subject_template,$welcome_mimetype) + = ('','','','','',''); + + if ( $conf->exists('welcome_email', $agentnum) ) { + $welcome_template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", $conf->config('welcome_email', $agentnum) ] + ) or warn "can't create welcome email template: $Text::Template::ERROR"; + $welcome_from = $conf->config('welcome_email-from', $agentnum); + # || 'your-isp-is-dum' + $welcome_subject = $conf->config('welcome_email-subject', $agentnum) + || 'Welcome'; + $welcome_subject_template = new Text::Template ( + TYPE => 'STRING', + SOURCE => $welcome_subject, + ) or warn "can't create welcome email subject template: $Text::Template::ERROR"; + $welcome_mimetype = $conf->config('welcome_email-mimetype', $agentnum) + || 'text/plain'; } - else { #!$msgnum - my ($to,$welcome_template,$welcome_from,$welcome_subject,$welcome_subject_template,$welcome_mimetype) - = ('','','','','',''); - - if ( $conf->exists('welcome_email', $agentnum) ) { - $welcome_template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", $conf->config('welcome_email', $agentnum) ] - ) or warn "can't create welcome email template: $Text::Template::ERROR"; - $welcome_from = $conf->config('welcome_email-from', $agentnum); - # || 'your-isp-is-dum' - $welcome_subject = $conf->config('welcome_email-subject', $agentnum) - || 'Welcome'; - $welcome_subject_template = new Text::Template ( - TYPE => 'STRING', - SOURCE => $welcome_subject, - ) or warn "can't create welcome email subject template: $Text::Template::ERROR"; - $welcome_mimetype = $conf->config('welcome_email-mimetype', $agentnum) - || 'text/plain'; - } - if ( $welcome_template ) { - my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ); - if ( $to ) { - - my %hash = ( - 'custnum' => $self->custnum, - 'username' => $self->username, - 'password' => $self->_password, - 'first' => $cust_main->first, - 'last' => $cust_main->getfield('last'), - 'pkg' => $cust_pkg->part_pkg->pkg, - ); - my $wqueue = new FS::queue { - 'svcnum' => $self->svcnum, - 'job' => 'FS::svc_acct::send_email' - }; - my $error = $wqueue->insert( - 'to' => $to, - 'from' => $welcome_from, - 'subject' => $welcome_subject_template->fill_in( HASH => \%hash, ), - 'mimetype' => $welcome_mimetype, - 'body' => $welcome_template->fill_in( HASH => \%hash, ), - ); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "error queuing welcome email: $error"; - } + if ( $welcome_template && $cust_pkg ) { + my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ); + if ( $to ) { + + my %hash = ( + 'custnum' => $self->custnum, + 'username' => $self->username, + 'password' => $self->_password, + 'first' => $cust_main->first, + 'last' => $cust_main->getfield('last'), + 'pkg' => $cust_pkg->part_pkg->pkg, + ); + my $wqueue = new FS::queue { + 'svcnum' => $self->svcnum, + 'job' => 'FS::svc_acct::send_email' + }; + my $error = $wqueue->insert( + 'to' => $to, + 'from' => $welcome_from, + 'subject' => $welcome_subject_template->fill_in( HASH => \%hash, ), + 'mimetype' => $welcome_mimetype, + 'body' => $welcome_template->fill_in( HASH => \%hash, ), + ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error queuing welcome email: $error"; + } - if ( $options{'depend_jobnum'} ) { - warn "$me depend_jobnum found; adding to welcome email dependancies" + if ( $options{'depend_jobnum'} ) { + warn "$me depend_jobnum found; adding to welcome email dependancies" + if $DEBUG; + if ( ref($options{'depend_jobnum'}) ) { + warn "$me adding jobs ". join(', ', @{$options{'depend_jobnum'}} ). + "to welcome email dependancies" if $DEBUG; - if ( ref($options{'depend_jobnum'}) ) { - warn "$me adding jobs ". join(', ', @{$options{'depend_jobnum'}} ). - "to welcome email dependancies" - if $DEBUG; - push @jobnums, @{ $options{'depend_jobnum'} }; - } else { - warn "$me adding job $options{'depend_jobnum'} ". - "to welcome email dependancies" - if $DEBUG; - push @jobnums, $options{'depend_jobnum'}; - } + push @jobnums, @{ $options{'depend_jobnum'} }; + } else { + warn "$me adding job $options{'depend_jobnum'} ". + "to welcome email dependancies" + if $DEBUG; + push @jobnums, $options{'depend_jobnum'}; } + } - foreach my $jobnum ( @jobnums ) { - my $error = $wqueue->depend_insert($jobnum); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "error queuing welcome email job dependancy: $error"; - } + foreach my $jobnum ( @jobnums ) { + my $error = $wqueue->depend_insert($jobnum); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error queuing welcome email job dependancy: $error"; } - } - } # if $welcome_template - } # if !$msgnum - } # if $cust_pkg + } + + } + + } # if ( $cust_pkg ) $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; #no error @@ -1175,10 +1228,6 @@ sub check { || $self->ut_snumbern('upbytes') || $self->ut_snumbern('downbytes') || $self->ut_snumbern('totalbytes') - || $self->ut_snumbern('seconds_threshold') - || $self->ut_snumbern('upbytes_threshold') - || $self->ut_snumbern('downbytes_threshold') - || $self->ut_snumbern('totalbytes_threshold') || $self->ut_enum('_password_encoding', ['',qw(plain crypt ldap)]) || $self->ut_enum('password_selfchange', [ '', 'Y' ]) || $self->ut_enum('password_recover', [ '', 'Y' ]) @@ -1192,7 +1241,7 @@ sub check { || $self->ut_enum('cgp_addmailtrailer', [ '', 'Y' ]) #preferences || $self->ut_alphasn('cgp_deletemode') - || $self->ut_enum('cgp_emptytrash', $self->cgp_emptytrash_values) + || $self->ut_alphan('cgp_emptytrash') || $self->ut_alphan('cgp_language') || $self->ut_textn('cgp_timezone') || $self->ut_textn('cgp_skinname') @@ -2234,7 +2283,7 @@ sub set_usage { my $reset = 0; my %handyhash = (); if ( $options{null} ) { - %handyhash = ( map { ( $_ => undef, $_."_threshold" => undef ) } + %handyhash = ( map { ( $_ => 'NULL', $_."_threshold" => 'NULL' ) } qw( seconds upbytes downbytes totalbytes ) ); } @@ -2256,7 +2305,7 @@ sub set_usage { #die $error if $error; #services not explicity changed via the UI my $sql = "UPDATE svc_acct SET " . - join (',', map { "$_ = ?" } (keys %handyhash) ). + join (',', map { "$_ = $handyhash{$_}" } (keys %handyhash) ). " WHERE svcnum = ". $self->svcnum; warn "$me $sql\n" @@ -2265,7 +2314,7 @@ sub set_usage { if (scalar(keys %handyhash)) { my $sth = $dbh->prepare( $sql ) or die "Error preparing $sql: ". $dbh->errstr; - my $rv = $sth->execute(values %handyhash); + my $rv = $sth->execute(); die "Error executing $sql: ". $sth->errstr unless defined($rv); die "Can't update usage for svcnum ". $self->svcnum diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm index 4d85060d3..8823c7741 100644 --- a/FS/FS/svc_domain.pm +++ b/FS/FS/svc_domain.pm @@ -1,8 +1,7 @@ package FS::svc_domain; use strict; -use base qw( FS::svc_Parent_Mixin FS::svc_CGP_Mixin FS::svc_CGPRule_Mixin - FS::svc_Common ); +use base qw( FS::svc_Parent_Mixin FS::svc_CGPRule_Mixin FS::svc_Common ); use vars qw( $whois_hack $conf @defaultrecords $soadefaultttl $soaemail $soaexpire $soamachine $soarefresh $soaretry @@ -159,8 +158,7 @@ sub table_info { }, 'acct_def_cgp_emptytrash' => { label => 'Acct. default Communigate on logout remove trash', - type => 'select', - select_list => __PACKAGE__->cgp_emptytrash_values, + type => 'text', disable_inventory => 1, disable_select => 1, }, @@ -221,9 +219,71 @@ sub table_info { disable_select => 1, }, 'acct_def_cgp_timezone' => { - label => 'Acct. default time zone', - type => 'select', - select_list => __PACKAGE__->cgp_timezone_values, + label => 'Acct. default time zone', + type => 'select', + select_list => [ '', + 'HostOS', + '(+0100) Algeria/Congo', + '(+0200) Egypt/South Africa', + '(+0300) Saudi Arabia', + '(+0400) Oman', + '(+0500) Pakistan', + '(+0600) Bangladesh', + '(+0700) Thailand/Vietnam', + '(+0800) China/Malaysia', + '(+0900) Japan/Korea', + '(+1000) Queensland', + '(+1100) Micronesia', + '(+1200) Fiji', + '(+1300) Tonga/Kiribati', + '(+1400) Christmas Islands', + '(-0100) Azores/Cape Verde', + '(-0200) Fernando de Noronha', + '(-0300) Argentina/Uruguay', + '(-0400) Venezuela/Guyana', + '(-0500) Haiti/Peru', + '(-0600) Central America', + '(-0700) Arisona', + '(-0800) Adamstown', + '(-0900) Marquesas Islands', + '(-1000) Hawaii/Tahiti', + '(-1100) Samoa', + 'Asia/Afghanistan', + 'Asia/India', + 'Asia/Iran', + 'Asia/Iraq', + 'Asia/Israel', + 'Asia/Jordan', + 'Asia/Lebanon', + 'Asia/Syria', + 'Australia/Adelaide', + 'Australia/East', + 'Australia/NorthernTerritory', + 'Europe/Central', + 'Europe/Eastern', + 'Europe/Moscow', + 'Europe/Western', + 'GMT (+0000)', + 'Newfoundland', + 'NewZealand/Auckland', + 'NorthAmerica/Alaska', + 'NorthAmerica/Atlantic', + 'NorthAmerica/Central', + 'NorthAmerica/Eastern', + 'NorthAmerica/Mountain', + 'NorthAmerica/Pacific', + 'Russia/Ekaterinburg', + 'Russia/Irkutsk', + 'Russia/Kamchatka', + 'Russia/Krasnoyarsk', + 'Russia/Magadan', + 'Russia/Novosibirsk', + 'Russia/Vladivostok', + 'Russia/Yakutsk', + 'SouthAmerica/Brasil', + 'SouthAmerica/Chile', + 'SouthAmerica/Paraguay', + ], disable_inventory => 1, disable_select => 1, }, @@ -493,8 +553,7 @@ sub check { #XXX archive messages #preferences || $self->ut_alphasn('acct_def_cgp_deletemode') - || $self->ut_enum('acct_def_cgp_emptytrash', - $self->cgp_emptytrash_values ) + || $self->ut_alphan('acct_def_cgp_emptytrash') || $self->ut_alphan('acct_def_cgp_language') || $self->ut_textn('acct_def_cgp_timezone') || $self->ut_textn('acct_def_cgp_skinname') diff --git a/FS/FS/svc_pbx.pm b/FS/FS/svc_pbx.pm index d2760a504..6ae04189c 100644 --- a/FS/FS/svc_pbx.pm +++ b/FS/FS/svc_pbx.pm @@ -3,7 +3,6 @@ package FS::svc_pbx; use strict; use base qw( FS::svc_External_Common ); use FS::Record qw( qsearch qsearchs dbh ); -use FS::Conf; use FS::cust_svc; use FS::svc_phone; use FS::svc_acct; @@ -56,10 +55,6 @@ PBX name Maximum number of extensions -=item max_simultaneous - -Maximum number of simultaneous users - =back =head1 METHODS @@ -90,7 +85,6 @@ sub table_info { 'id' => 'ID', 'title' => 'Name', 'max_extensions' => 'Maximum number of User Extensions', - 'max_simultaneous' => 'Maximum number of simultaneous users', # 'field' => 'Description', # 'another_field' => { # 'label' => 'Description', @@ -212,15 +206,15 @@ returns the error, otherwise returns false. =cut -#sub replace { -# my ( $new, $old ) = ( shift, shift ); -# my $error; -# -# $error = $new->SUPER::replace($old); -# return $error if $error; -# -# ''; -#} +sub replace { + my ( $new, $old ) = ( shift, shift ); + my $error; + + $error = $new->SUPER::replace($old); + return $error if $error; + + ''; +} =item suspend @@ -259,9 +253,6 @@ sub check { sub _check_duplicate { my $self = shift; - my $conf = new FS::Conf; - return '' if $conf->config('global_unique-pbx_title') eq 'disabled'; - $self->lock_table; if ( qsearchs( 'svc_pbx', { 'title' => $self->title } ) ) { @@ -271,75 +262,6 @@ sub _check_duplicate { } } -=item get_cdrs - -Returns a set of Call Detail Records (see L<FS::cdr>) associated with this -service. By default, "associated with" means that the "charged_party" field of -the CDR matches the "title" field of the service. - -=over 2 - -Accepts the following options: - -=item for_update => 1: SELECT the CDRs "FOR UPDATE". - -=item status => "" (or "done"): Return only CDRs with that processing status. - -=item inbound => 1: No-op for svc_pbx CDR processing. - -=item default_prefix => "XXX": Also accept the phone number of the service prepended -with the chosen prefix. - -=item disable_src => 1: No-op for svc_pbx CDR processing. - -=back - -=cut - -sub get_cdrs { - my($self, %options) = @_; - my %hash = (); - my @where = (); - - my @fields = ( 'charged_party' ); - $hash{'freesidestatus'} = $options{'status'} - if exists($options{'status'}); - - my $for_update = $options{'for_update'} ? 'FOR UPDATE' : ''; - - my $title = $self->title; - - my $prefix = $options{'default_prefix'}; - - my @orwhere = map " $_ = '$title' ", @fields; - push @orwhere, map " $_ = '$prefix$title' ", @fields - if length($prefix); - if ( $prefix =~ /^\+(\d+)$/ ) { - push @orwhere, map " $_ = '$1$title' ", @fields - } - - push @where, ' ( '. join(' OR ', @orwhere ). ' ) '; - - if ( $options{'begin'} ) { - push @where, 'startdate >= '. $options{'begin'}; - } - if ( $options{'end'} ) { - push @where, 'startdate < '. $options{'end'}; - } - - my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where ); - - my @cdrs = - qsearch( { - 'table' => 'cdr', - 'hashref' => \%hash, - 'extra_sql' => $extra_sql, - 'order_by' => "ORDER BY startdate $for_update", - } ); - - @cdrs; -} - =back =head1 BUGS diff --git a/FS/FS/tax_rate.pm b/FS/FS/tax_rate.pm index b518a3771..87f2014f5 100644 --- a/FS/FS/tax_rate.pm +++ b/FS/FS/tax_rate.pm @@ -27,6 +27,8 @@ use FS::part_pkg_taxproduct; use FS::cust_main; use FS::Misc qw( csv_from_fixed ); +#i'd like to dump these +use FS::CGI qw(rooturl popurl); use URI::Escape; @ISA = qw( FS::Record ); @@ -1316,7 +1318,7 @@ sub _restore_remembered_tax_products { unless ( $part_pkg_taxproduct ) { return "failed to find part_pkg_taxproduct (". - $taxproduct->{$pkgpart}->{$class}. ") for pkgpart $pkgpart\n"; + $taxproduct->{pkgpart}->{$class}. ") for pkgpart $pkgpart\n"; } if ( $class eq '' ) { @@ -1765,21 +1767,17 @@ Launches a tax liability report. =cut sub queue_liability_report { - my $job = shift; - my $param = thaw(decode_base64(shift)); - - my $cgi = new CGI; - $cgi->param('beginning', $param->{beginning}); - $cgi->param('ending', $param->{ending}); + my $cgi = shift; my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); - my $agentnum = $param->{agentnum}; - if ($agentnum =~ /^(\d+)$/) { $agentnum = $1; } else { $agentnum = ''; }; - generate_liability_report( + my $agentnum = $cgi->param('agentnum'); + $agentnum =~ /^(\d+)$/ ? $agentnum = $1 : $agentnum = ''; + my $job = new FS::queue { job => 'FS::tax_rate::generate_liability_report' }; + $job->insert( 'beginning' => $beginning, 'ending' => $ending, 'agentnum' => $agentnum, - 'p' => $param->{RootURL}, - 'job' => $job, + 'p' => popurl(2), + 'rooturl' => rooturl, ); } @@ -1793,8 +1791,6 @@ agentnum, beginning, and ending sub generate_liability_report { my %args = @_; - my ( $count, $last, $min_sec ) = _progressbar_foo(); - #let us open the temp file early my $dir = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc; my $report = new File::Temp( TEMPLATE => 'report.tax.liability.XXXXXXXX', @@ -1849,25 +1845,14 @@ sub generate_liability_report { my $credit = 0; my %taxes = (); my %basetaxes = (); - my $calculated = 0; - my @tax_and_location = qsearch({ table => 'cust_bill_pkg', - select => $select, - hashref => { pkgpart => 0 }, - addl_from => $addl_from, - extra_sql => $where, - }); - $count = scalar(@tax_and_location); - foreach my $t ( @tax_and_location ) { - - if ( $args{job} ) { - if ( time - $min_sec > $last ) { - $args{job}->update_statustext( int( 100 * $calculated / $count ). - ",Calculated" - ); - $last = time; - } - } - + foreach my $t (qsearch({ table => 'cust_bill_pkg', + select => $select, + hashref => { pkgpart => 0 }, + addl_from => $addl_from, + extra_sql => $where, + }) + ) + { my @params = map { my $f = $_; $f =~ s/.*\.//; $f } @taxparam; my $label = join('~', map { $t->$_ } @params); $label = 'Tax'. $label if $label =~ /^~/; @@ -1922,12 +1907,6 @@ sub generate_liability_report { #ordering - - if ( $args{job} ) { - $args{job}->update_statustext( "0,Sorted" ); - $last = time; - } - my @taxes = (); foreach my $tax ( sort { $a cmp $b } keys %taxes ) { @@ -1989,19 +1968,8 @@ EOF my $bgcolor2 = '#ffffff'; my $bgcolor = ''; - $count = scalar(@taxes); - $calculated = 0; foreach my $tax ( @taxes ) { - if ( $args{job} ) { - if ( time - $min_sec > $last ) { - $args{job}->update_statustext( int( 100 * $calculated / $count ). - ",Generated" - ); - $last = time; - } - } - if ( $bgcolor eq $bgcolor1 ) { $bgcolor = $bgcolor2; } else { @@ -2016,13 +1984,13 @@ EOF print $report <<EOF; <TR> <TD CLASS="grid" BGCOLOR="<% '$bgcolor' %>"><% '$tax->{label}' %></TD> - <% ($tax->{base}) ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %> + <% $tax->{base} ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %> <TD CLASS="grid" BGCOLOR="<% '$bgcolor' %>" ALIGN="right"> <A HREF="<% '$baselink$link' %>;istax=1"><% '$money_char' %><% sprintf('%.2f', $tax->{'tax'} ) %></A> </TD> <% !($tax->{base}) ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %> <TD CLASS="grid" BGCOLOR="<% '$bgcolor' %>"></TD> - <% ($tax->{base}) ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %> + <% $tax->{base} ? qq!<TD CLASS="grid" BGCOLOR="$bgcolor"></TD>! : '' %> <TD CLASS="grid" BGCOLOR="<% '$bgcolor' %>" ALIGN="right"> <A HREF="<% '$baselink$link' %>;istax=1;iscredit=rate"><% '$money_char' %><% sprintf('%.2f', $tax->{'credit'} ) %></A> </TD> @@ -2044,7 +2012,7 @@ EOF my $dropstring = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc. '/report.'; $reportname =~ s/^$dropstring//; - my $reporturl = "%%%ROOTURL%%%/misc/queued_report?report=$reportname"; + my $reporturl = $args{rooturl}. "/misc/queued_report?report=$reportname"; die "<a href=$reporturl>view</a>\n"; } diff --git a/FS/FS/usage_class.pm b/FS/FS/usage_class.pm index 7b73c611f..b64d26ac4 100644 --- a/FS/FS/usage_class.pm +++ b/FS/FS/usage_class.pm @@ -3,9 +3,6 @@ package FS::usage_class; use strict; use vars qw( @ISA ); use FS::Record qw( qsearch qsearchs ); -use FS::Conf; - -my $conf = new FS::Conf; @ISA = qw(FS::Record); @@ -125,28 +122,22 @@ my %summary_formats = ( sub { shift->{description} }, sub { shift->{calls} }, sub { sprintf( '%.1f', shift->{duration}/60 ) }, - sub { my($href, %opt) = @_; - ($opt{dollar} || ''). $href->{amount}; - }, + sub { shift->{amount} }, ], 'align' => [ qw( l r r r ) ], 'span' => [ qw( 4 1 1 1 ) ], # unitprices? 'width' => [ qw( 8.2cm 2.5cm 1.4cm 1.6cm ) ], # don't like this - 'show' => 1, }, 'simpler' => { 'label' => [ qw( Description Calls Amount ) ], 'fields' => [ sub { shift->{description} }, sub { shift->{calls} }, - sub { my($href, %opt) = @_; - ($opt{dollar} || ''). $href->{amount}; - }, + sub { shift->{amount} }, ], 'align' => [ qw( l r r ) ], 'span' => [ qw( 5 1 1 ) ], 'width' => [ qw( 10.7cm 1.4cm 1.6cm ) ], # don't like this - 'show' => 1, }, 'usage_simple' => { 'label' => [ qw( Date Time Number Destination Duration Amount ) ], @@ -156,56 +147,16 @@ my %summary_formats = ( sub { ' ' }, sub { ' ' }, sub { ' ' }, - sub { my $href = shift; #ugh! making bunk of 'normalization' - $href->{subtotal} ? $href->{subtotal} : ' ' - }, - ], - 'align' => [ qw( l l l l r r ) ], - 'span' => [ qw( 1 1 1 1 1 2 ) ], # unitprices? - 'width' => [ qw( 4.3cm 1.4cm 2.5cm 2.5cm 1.4cm 1.6cm ) ],# don't like this - 'show' => 0, - }, - 'usage_6col' => { - 'label' => [ qw( col1 col2 col3 col4 col5 col6 ) ], - 'fields' => [ - sub { ' ' }, - sub { ' ' }, - sub { ' ' }, - sub { ' ' }, sub { ' ' }, - sub { my $href = shift; #ugh! making bunk of 'normalization' - $href->{subtotal} ? $href->{subtotal} : ' ' - }, ], 'align' => [ qw( l l l l r r ) ], - 'span' => [ qw( 1 1 1 1 1 2 ) ], # unitprices? + 'span' => [ qw( 2 1 1 1 1 1 ) ], # unitprices? 'width' => [ qw( 4.3cm 1.4cm 2.5cm 2.5cm 1.4cm 1.6cm ) ],# don't like this - 'show' => 0, - }, - 'usage_7col' => { - 'label' => [ qw( col1 col2 col3 col4 col5 col6 col7 ) ], - 'fields' => [ - sub { ' ' }, - sub { ' ' }, - sub { ' ' }, - sub { ' ' }, - sub { ' ' }, - sub { ' ' }, - sub { my $href = shift; #ugh! making bunk of 'normalization' - $href->{subtotal} ? $href->{subtotal} : ' ' - }, - ], - 'align' => [ qw( l l l l l r r ) ], - 'span' => [ qw( 1 1 1 1 1 1 1 ) ], # unitprices? - 'width' => [ qw( 2.9cm 1.4cm 1.4cm 2.5cm 2.5cm 1.4cm 1.6cm ) ],# don't like this - 'show' => 0, }, ); sub summary_formats_labelhash { - map { $_ => join(',', @{$summary_formats{$_}{label}}) } - grep { $summary_formats{$_}{show} } - keys %summary_formats; + map { $_ => join(',', @{$summary_formats{$_}{label}}) } keys %summary_formats; } =item header_generator FORMAT @@ -222,16 +173,15 @@ my %html_align = ( ); sub _generator_defaults { - my ( $self, $format, %opt ) = @_; - my %format = ( %{ $summary_formats{$self->format} }, %opt ); - return ( \%format, ' ', ' ', ' ', sub { shift } ); + my ( $self, $format ) = ( shift, shift ); + return ( $summary_formats{$self->format}, ' ', ' ', ' ', sub { shift } ); } sub header_generator { - my ( $self, $format, %opt ) = @_; + my ( $self, $format ) = ( shift, shift ); my ( $f, $prefix, $suffix, $separator, $column ) = - $self->_generator_defaults($format, %opt); + $self->_generator_defaults($format); if ($format eq 'latex') { $prefix = "\\hline\n\\rule{0pt}{2.5ex}\n\\makebox[1.4cm]{}&\n"; @@ -255,7 +205,7 @@ sub header_generator { my @args = @_; my @result = (); - foreach (my $i = 0; exists($f->{label}->[$i]); $i++) { + foreach (my $i = 0; $f->{label}->[$i]; $i++) { push @result, &{$column}( map { $f->{$_}->[$i] } qw(label align span width) ); } @@ -273,12 +223,11 @@ usage_class. FORMAT is either html or latex =cut sub description_generator { - my ( $self, $format, %opt ) = @_; + my ( $self, $format ) = ( shift, shift ); my ( $f, $prefix, $suffix, $separator, $column ) = - $self->_generator_defaults($format, %opt); + $self->_generator_defaults($format); - my $money_char = '$'; if ($format eq 'latex') { $prefix = "\\hline\n\\multicolumn{1}{c}{\\rule{0pt}{2.5ex}~} &\n"; $suffix = '\\\\'; @@ -287,7 +236,6 @@ sub description_generator { sub { my ($d,$a,$s,$w) = @_; return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{\\textbf{$d}}}"; }; - $money_char = '\\dollar'; }elsif ( $format eq 'html' ) { $prefix = '"><td align="center"></td>'; $suffix = ''; @@ -296,21 +244,16 @@ sub description_generator { sub { my ($d,$a,$s,$w) = @_; return qq!<td align="$html_align{$a}">$d</td>!; }; - $money_char = $conf->config('money_char') || '$'; } sub { - #my @args = @_; - my ($href) = shift; + my @args = @_; my @result = (); foreach (my $i = 0; $f->{label}->[$i]; $i++) { - my $dollar = ''; - $dollar = $money_char if $i == scalar(@{$f->{label}})-1; - push @result, - &{$column}( &{$f->{fields}->[$i]}($href, 'dollar' => $dollar), - map { $f->{$_}->[$i] } qw(align span width) - ); + push @result, &{$column}( &{$f->{fields}->[$i]}(@args), + map { $f->{$_}->[$i] } qw(align span width) + ); } $prefix. join( $separator, @result ). $suffix; @@ -326,13 +269,13 @@ usage_class. FORMAT is either html or latex =cut sub total_generator { - my ( $self, $format, %opt ) = @_; + my ( $self, $format ) = ( shift, shift ); # $OUT .= '\FStotaldesc{' . $section->{'description'} . ' Total}' . # '{' . $section->{'subtotal'} . '}' . "\n"; my ( $f, $prefix, $suffix, $separator, $column ) = - $self->_generator_defaults($format, %opt); + $self->_generator_defaults($format); my $style = ''; if ($format eq 'latex') { @@ -385,13 +328,13 @@ usage_class. FORMAT is either html or latex # total_item and amount vs total_amount -- another array of functions? sub total_line_generator { - my ( $self, $format, %opt ) = @_; + my ( $self, $format ) = ( shift, shift ); # $OUT .= '\FStotaldesc{' . $line->{'total_item'} . '}' . # '{' . $line->{'total_amount'} . '}' . "\n"; my ( $f, $prefix, $suffix, $separator, $column ) = - $self->_generator_defaults($format, %opt); + $self->_generator_defaults($format); my $style = ''; if ($format eq 'latex') { diff --git a/FS/MANIFEST b/FS/MANIFEST index 1b2e08df8..5537c2f6e 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -17,7 +17,6 @@ bin/freeside-queued bin/freeside-radgroup bin/freeside-reexport bin/freeside-selfservice-server -bin/freeside-selfservice-xmlrpcd bin/freeside-setinvoice bin/freeside-setup bin/freeside-sqlradius-radacctd @@ -29,22 +28,14 @@ FS/CGI.pm FS/InitHandler.pm FS/ClientAPI.pm FS/ClientAPI_SessionCache.pm -FS/ClientAPI_XMLRPC.pm FS/ClientAPI/passwd.pm -FS/ClientAPI/Agent.pm -FS/ClientAPI/Bulk.pm -FS/ClientAPI/MasonComponent.pm FS/ClientAPI/MyAccount.pm -FS/ClientAPI/PrepaidPhone.pm -FS/ClientAPI/SGNG.pm -FS/ClientAPI/Signup.pm FS/Conf.pm FS/ConfItem.pm FS/Cron/backup.pm FS/Cron/bill.pm FS/Cron/vacuum.pm FS/Daemon.pm -FS/Maestro.pm FS/Misc.pm FS/Record.pm FS/Report.pm @@ -520,11 +511,3 @@ FS/cgp_rule_condition.pm t/cgp_rule_condition.t FS/cgp_rule_action.pm t/cgp_rule_action.t -FS/msg_template.pm -t/msg_template.t -FS/cust_tag.pm -t/cust_tag.t -FS/part_tag.pm -t/part_tag.t -FS/svc_CGP_Mixin.pm -FS/svc_CGPRule_Mixin.pm diff --git a/FS/bin/freeside-cdr-sftp_and_import b/FS/bin/freeside-cdr-sftp_and_import index ba9d6f3cc..d90695f8f 100755 --- a/FS/bin/freeside-cdr-sftp_and_import +++ b/FS/bin/freeside-cdr-sftp_and_import @@ -11,8 +11,8 @@ use FS::cdr; # parse command line ### -use vars qw( $opt_m $opt_p $opt_r $opt_e $opt_d $opt_v $opt_P $opt_a ); -getopts('m:p:r:e:d:v:P:a'); +use vars qw( $opt_m $opt_p $opt_r $opt_e $opt_d $opt_v ); +getopts('m:p:r:e:d:v'); $opt_e ||= 'csv'; #$opt_e = ".$opt_e" unless $opt_e =~ /^\./; @@ -20,13 +20,11 @@ $opt_e =~ s/^\.//; $opt_p ||= ''; -my %options = (); - my $user = shift or die &usage; adminsuidsetup $user; # %%%FREESIDE_CACHE%%% -my $cachedir = '%%%FREESIDE_CACHE%%%/cache.'. datasrc. '/cdrs'; +my $cachedir = '/usr/local/etc/freeside/cache.'. datasrc. '/cdrs'; mkdir $cachedir unless -d $cachedir; my $format = shift or die &usage; @@ -46,18 +44,11 @@ $opt_m = lc($opt_m); my $ls; if($opt_m eq 'ftp') { - $options{'Port'} = $opt_P if $opt_P; - $options{'Debug'} = $opt_v if $opt_v; - $options{'Passive'} = $opt_a if $opt_a; - my $ls_ftp = ftp(); $ls = [ grep { /^$opt_p.*\.$opt_e$/i } $ls_ftp->ls ]; } elsif($opt_m eq 'sftp') { - $options{'port'} = $opt_P if $opt_P; - $options{'debug'} = $opt_v if $opt_v; - my $ls_sftp = sftp(); $ls_sftp->setcwd($opt_r) or die "can't chdir to $opt_r\n" @@ -133,8 +124,7 @@ sub ftp { my ($hostname, $user) = reverse split('@', $servername); my ($user, $pass) = split(':', $user); - my $ftp = Net::FTP->new($hostname, %options) - or die "FTP connection to '$hostname' failed."; + my $ftp = Net::FTP->new($hostname) or die "FTP connection to '$hostname' failed."; $ftp->login($user, $pass) or die "FTP login failed: ".$ftp->message; $ftp->cwd($opt_r) or die "can't chdir to $opt_r\n" if $opt_r; return $ftp; @@ -159,14 +149,12 @@ cdr.sftp_and_import - Download CDR files from a remote server via SFTP =head1 SYNOPSIS - cdr.sftp_and_import [ -m method ] [ -p prefix ] [ -e extension ] - [ -r remotefolder ] [ -d donefolder ] [ -v level ] [ -P port ] - [ -a ] user format [sftpuser@]servername + cdr.sftp_and_import [ -m method ][ -p prefix ] [ -e extension ] [ -r remotefolder ] [ -d donefolder ] [ -v ] user format [sftpuser@]servername =head1 DESCRIPTION -Command line tool to download CDR files from a remote server via SFTP -or FTP and then import them into the database. +Command line tool to download CDR files from a remote server via SFTP or FTP and then +import them into the database. -m: transfer method (sftp or ftp), defaults to sftp @@ -178,12 +166,7 @@ or FTP and then import them into the database. -d: if specified, moves files to the specified folder when done --P: if specified, sets the port to use - --a: use ftp passive mode - --v: set verbosity level; this script only has one level, but it will - be passed as the 'debug' argument to the transport method +-v: verbose user: freeside username diff --git a/FS/bin/freeside-dbdef-create b/FS/bin/freeside-dbdef-create index 6c448c74c..a04f42521 100755 --- a/FS/bin/freeside-dbdef-create +++ b/FS/bin/freeside-dbdef-create @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl -Tw use strict; use DBI; diff --git a/FS/bin/freeside-fetch b/FS/bin/freeside-fetch index f689bfd93..7b674ed7e 100755 --- a/FS/bin/freeside-fetch +++ b/FS/bin/freeside-fetch @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl -Tw use strict; use LWP::UserAgent; diff --git a/FS/bin/freeside-selfservice-xmlrpcd b/FS/bin/freeside-selfservice-xmlrpcd deleted file mode 100755 index fa745ecf2..000000000 --- a/FS/bin/freeside-selfservice-xmlrpcd +++ /dev/null @@ -1,349 +0,0 @@ -#!/usr/bin/perl -# -# based on http://www.perlmonks.org/?node_id=582781 by Justin Hawkins -# and http://poe.perl.org/?POE_Cookbook/Web_Server_With_Forking - -### -# modules and constants and variables, oh my -### - -use warnings; -use strict; - -use constant DEBUG => 1; # Enable much runtime information. -use constant MAX_PROCESSES => 10; # Total server process count. -use constant SERVER_PORT => 8080; # Server port. -use constant TESTING_CHURN => 0; # Randomly test process respawning. - -use POE 1.2; # Base features. -use POE::Filter::HTTPD; # For serving HTTP content. -use POE::Wheel::ReadWrite; # For socket I/O. -use POE::Wheel::SocketFactory; # For serving socket connections. - -use XMLRPC::Transport::HTTP; #SOAP::Transport::HTTP; -use XMLRPC::Lite; # for XMLRPC::Serializer - -use FS::Daemon qw( daemonize1 drop_root logfile daemonize2 ); -use FS::UID qw( adminsuidsetup forksuidsetup dbh ); -use FS::Conf; -use FS::ClientAPI qw( load_clientapi_modules ); -use FS::ClientAPI_XMLRPC; #FS::SelfService::XMLRPC; - -#freeside -my $FREESIDE_LOG = "%%%FREESIDE_LOG%%%"; -my $FREESIDE_LOCK = "%%%FREESIDE_LOCK%%%"; -my $lock_file = "$FREESIDE_LOCK/selfservice-xmlrpcd.writelock"; - -#freeside xmlrpc.cgi -my %typelookup = ( - base64 => [10, sub {$_[0] =~ /[^\x09\x0a\x0d\x20-\x7f]/}, 'as_base64'], - dateTime => [35, sub {$_[0] =~ /^\d{8}T\d\d:\d\d:\d\d$/}, 'as_dateTime'], - string => [40, sub {1}, 'as_string'], -); - -### -# freeside init -### - -my $user = shift or die &usage; - -$FS::Daemon::NOSIG = 1; -$FS::Daemon::PID_NEWSTYLE = 1; -daemonize1('selfservice-xmlrpcd'); - -POE::Kernel->has_forked(); #daemonize forks... - -drop_root(); - -adminsuidsetup($user); - -load_clientapi_modules; - -logfile("$FREESIDE_LOG/selfservice-xmlrpcd.log"); - -daemonize2(); - -my $conf = new FS::Conf; - -die "not running; selfservice-xmlrpc conf option is off\n" - unless $conf->exists('selfservice-xmlrpc'); - -#parent doesn't need to hold a DB connection open -dbh->disconnect; -undef $FS::UID::dbh; - -### -# the main loop -### - -server_spawn(MAX_PROCESSES); -POE::Kernel->run(); -exit; - -### -# the subroutines -### - -### Spawn the main server. This will run as the parent process. - -sub server_spawn { - my ($max_processes) = @_; - - POE::Session->create( - inline_states => { - _start => \&server_start, - _stop => \&server_stop, - do_fork => \&server_do_fork, - got_error => \&server_got_error, - got_sig_int => \&server_got_sig_int, - got_sig_child => \&server_got_sig_child, - got_connection => \&server_got_connection, - _child => sub { undef }, - }, - heap => { max_processes => MAX_PROCESSES }, - ); -} - -### The main server session has started. Set up the server socket and -### bookkeeping information, then fork the initial child processes. - -sub server_start { - my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; - - $heap->{server} = POE::Wheel::SocketFactory->new - ( BindPort => SERVER_PORT, - SuccessEvent => "got_connection", - FailureEvent => "got_error", - Reuse => "yes", - ); - - $kernel->sig( INT => "got_sig_int" ); - $kernel->sig( TERM => "got_sig_int" ); #huh - - $heap->{children} = {}; - $heap->{is_a_child} = 0; - - warn "Server $$ has begun listening on port ", SERVER_PORT, "\n"; - - $kernel->yield("do_fork"); -} - -### The server session has shut down. If this process has any -### children, signal them to shutdown too. - -sub server_stop { - my $heap = $_[HEAP]; - DEBUG and warn "Server $$ stopped.\n"; - - if ( my @children = keys %{ $heap->{children} } ) { - DEBUG and warn "Server $$ is signaling children to stop.\n"; - kill INT => @children; - } -} - -### The server session has encountered an error. Shut it down. - -sub server_got_error { - my ( $heap, $syscall, $errno, $error ) = @_[ HEAP, ARG0 .. ARG2 ]; - warn( "Server $$ got $syscall error $errno: $error\n", - "Server $$ is shutting down.\n", - ); - delete $heap->{server}; -} - -### The server has a need to fork off more children. Only honor that -### request form the parent, otherwise we would surely "forkbomb". -### Fork off as many child processes as we need. - -sub server_do_fork { - my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; - - return if $heap->{is_a_child}; - - #my $current_children = keys %{ $heap->{children} }; - #for ( $current_children + 2 .. $heap->{max_processes} ) { - while (scalar(keys %{$heap->{children}}) < $heap->{max_processes}) { - - DEBUG and warn "Server $$ is attempting to fork.\n"; - - my $pid = fork(); - - unless ( defined($pid) ) { - DEBUG and - warn( "Server $$ fork failed: $!\n", - "Server $$ will retry fork shortly.\n", - ); - $kernel->delay( do_fork => 1 ); - return; - } - - # Parent. Add the child process to its list. - if ($pid) { - $heap->{children}->{$pid} = 1; - $kernel->sig_child($pid, "got_sig_child"); - next; - } - - # Child. Clear the child process list. - $kernel->has_forked(); - DEBUG and warn "Server $$ forked successfully.\n"; - $heap->{is_a_child} = 1; - $heap->{children} = {}; - - #freeside db connection, etc. - forksuidsetup($user); - - return; - } -} - -### The server session received SIGINT. Don't handle the signal, -### which in turn will trigger the process to exit gracefully. - -sub server_got_sig_int { - my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; - DEBUG and warn "Server $$ received SIGINT/TERM.\n"; - - if ( my @children = keys %{ $heap->{children} } ) { - DEBUG and warn "Server $$ is signaling children to stop.\n"; - kill INT => @children; - } - - delete $heap->{server}; - $kernel->sig_handled(); -} - -### The server session received a SIGCHLD, indicating that some child -### server has gone away. Remove the child's process ID from our -### list, and trigger more fork() calls to spawn new children. - -sub server_got_sig_child { - my ( $kernel, $heap, $child_pid ) = @_[ KERNEL, HEAP, ARG1 ]; - - return unless delete $heap->{children}->{$child_pid}; - - DEBUG and warn "Server $$ reaped child $child_pid.\n"; - $kernel->yield("do_fork") if exists $_[HEAP]->{server}; -} - -### The server session received a connection request. Spawn off a -### client handler session to parse the request and respond to it. - -sub server_got_connection { - my ( $heap, $socket, $peer_addr, $peer_port ) = @_[ HEAP, ARG0, ARG1, ARG2 ]; - - DEBUG and warn "Server $$ received a connection.\n"; - - POE::Session->create( - inline_states => { - _start => \&client_start, - _stop => \&client_stop, - got_request => \&client_got_request, - got_flush => \&client_flushed_request, - got_error => \&client_got_error, - _parent => sub { 0 }, - }, - heap => { - socket => $socket, - peer_addr => $peer_addr, - peer_port => $peer_port, - }, - ); - - # Gracefully exit if testing process churn. - delete $heap->{server} - if TESTING_CHURN and $heap->{is_a_child} and ( rand() < 0.1 ); -} - -### The client handler has started. Wrap its socket in a ReadWrite -### wheel to begin interacting with it. - -sub client_start { - my $heap = $_[HEAP]; - - $heap->{client} = POE::Wheel::ReadWrite->new - ( Handle => $heap->{socket}, - Filter => POE::Filter::HTTPD->new(), - InputEvent => "got_request", - ErrorEvent => "got_error", - FlushedEvent => "got_flush", - ); - - DEBUG and warn "Client handler $$/", $_[SESSION]->ID, " started.\n"; -} - -### The client handler has stopped. Log that fact. - -sub client_stop { - DEBUG and warn "Client handler $$/", $_[SESSION]->ID, " stopped.\n"; -} - -### The client handler has received a request. If it's an -### HTTP::Response object, it means some error has occurred while -### parsing the request. Send that back and return immediately. -### Otherwise parse and process the request, generating and sending an -### HTTP::Response object in response. - -sub client_got_request { - my ( $heap, $request ) = @_[ HEAP, ARG0 ]; - - forksuidsetup($user) unless dbh && dbh->ping; - - my $serializer = new XMLRPC::Serializer(typelookup => \%typelookup); - - #my $soap = SOAP::Transport::HTTP::Server - my $soap = XMLRPC::Transport::HTTP::Server - -> new - -> dispatch_to('FS::ClientAPI_XMLRPC') - -> serializer($serializer); - - DEBUG and - warn "Client handler $$/", $_[SESSION]->ID, " is handling a request.\n"; - - if ( $request->isa("HTTP::Response") ) { - $heap->{client}->put($request); - return; - } - - $soap->request($request); - $soap->handle; - my $response = $soap->response; - - $heap->{client}->put($response); -} - -### The client handler received an error. Stop the ReadWrite wheel, -### which also closes the socket. - -sub client_got_error { - my ( $heap, $operation, $errnum, $errstr ) = @_[ HEAP, ARG0, ARG1, ARG2 ]; - DEBUG and - warn( "Client handler $$/", $_[SESSION]->ID, - " got $operation error $errnum: $errstr\n", - "Client handler $$/", $_[SESSION]->ID, " is shutting down.\n" - ); - delete $heap->{client}; -} - -### The client handler has flushed its response to the socket. We're -### done with the client connection, so stop the ReadWrite wheel. - -sub client_flushed_request { - my $heap = $_[HEAP]; - DEBUG and - warn( "Client handler $$/", $_[SESSION]->ID, - " flushed its response.\n", - "Client handler $$/", $_[SESSION]->ID, " is shutting down.\n" - ); - delete $heap->{client}; -} - -sub usage { - die "Usage:\n\n freeside-selfservice-xmlrpcd user\n"; -} - -### -# the end -### - -1; diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index 155c74aa0..ddff81ef9 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl -Tw #to delay loading dbdef until we're ready BEGIN { $FS::Schema::setup_hack = 1; } @@ -9,7 +9,7 @@ $FS::part_pkg::setup_hack = 1; $FS::part_pkg::setup_hack = 1; use strict; -use vars qw($opt_u $opt_d $opt_v $opt_q); +use vars qw($opt_u $opt_d $opt_v); use Getopt::Std; use FS::UID qw(adminsuidsetup datasrc checkeuid getsecrets); use FS::CurrentUser; @@ -24,9 +24,7 @@ die "Not running uid freeside!" unless checkeuid(); #my %attrib2db = # map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib; -getopts("u:vqd:"); -$opt_v = 1 unless $opt_q; #verbose by default now - +getopts("u:vd:"); my $config_dir = shift || '%%%DIST_CONF%%%' ; $config_dir =~ /^([\w.:=\/]+)$/ or die "unacceptable configuration directory name"; @@ -86,8 +84,6 @@ my $username_len = 32; # create a dbdef object from the old data structure ### -warn "Loading schema objects\n" if $opt_v; - my $dbdef = dbdef_dist(datasrc); #important @@ -98,8 +94,6 @@ $dbdef->save($dbdef_file); # create 'em ### -warn "Connecting to database\n" if $opt_v; - $FS::CurrentUser::upgrade_hack = 1; $FS::UID::callback_hack = 1; my $dbh = adminsuidsetup $opt_u; #$user; @@ -108,8 +102,6 @@ $FS::UID::callback_hack = 0; #create tables $|=1; -warn "Creating tables and indices\n" if $opt_v; - foreach my $statement ( $dbdef->sql($dbh) ) { $dbh->do( $statement ) or die "CREATE error: ". $dbh->errstr. "\ndoing statement: $statement"; @@ -121,12 +113,14 @@ dbdef_create($dbh, $dbdef_file); delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload reload_dbdef($dbdef_file); -warn "Tables and indices created - commiting transaction\n" if $opt_v; +warn "Freeside schema initialized - commiting transaction\n" if $opt_v; + $dbh->commit or die $dbh->errstr; $dbh->disconnect or die $dbh->errstr; + warn "Database schema committed successfully\n" if $opt_v; -warn "Initializing configuration\n" if $opt_v; +warn "Initializing freeside configuration\n" if $opt_v; $FS::UID::callback_hack = 1; $dbh = adminsuidsetup $opt_u; $FS::UID::callback_hack = 0; @@ -138,17 +132,21 @@ if (!scalar(qsearch('conf', {}))) { } } -warn "Configuration initialized - commiting transaction\n" if $opt_v; +warn "Freeside configuration initialized - commiting transaction\n" if $opt_v; + $dbh->commit or die $dbh->errstr; $dbh->disconnect or die $dbh->errstr; -warn "Configuration committed successfully\n" if $opt_v; + +warn "Freeside configuration committed successfully\n" if $opt_v; $dbh = adminsuidsetup $opt_u; create_initial_data('domain' => $opt_d); -warn "Database initialized - commiting transaction\n" if $opt_v; +warn "Freeside database initialized - commiting transaction\n" if $opt_v; + $dbh->commit or die $dbh->errstr; $dbh->disconnect or die $dbh->errstr; + warn "Database initialization committed successfully\n" if $opt_v; sub dbdef_create { # reverse engineer the schema from the DB and save to file @@ -158,7 +156,7 @@ sub dbdef_create { # reverse engineer the schema from the DB and save to file } sub usage { - die "Usage:\n freeside-setup -d domain.name [ -q ] [ config/dir ]\n" + die "Usage:\n freeside-setup -d domain.name [ -v ] [ config/dir ]\n" # [ -u user ] for devel/multi-db installs } diff --git a/FS/bin/freeside-upgrade b/FS/bin/freeside-upgrade index 4a6fac293..f4ff1c28e 100755 --- a/FS/bin/freeside-upgrade +++ b/FS/bin/freeside-upgrade @@ -61,33 +61,6 @@ if (dbdef->table('cust_main')->column('agent_custid') && ! $opt_s) { if (dbdef->table('h_cust_main')); } -if ( dbdef->table('cgp_rule_condition') && - dbdef->table('cgp_rule_condition')->column('condition') - ) -{ - push @bugfix, - "ALTER TABLE ${_}cgp_rule_condition RENAME COLUMN condition TO conditionname" - for '', 'h_'; - -} - -if ( $DRY_RUN ) { - print - join(";\n", @bugfix ). ";\n"; -} elsif ( @bugfix ) { - - foreach my $statement ( @bugfix ) { - warn "$statement\n"; - $dbh->do( $statement ) - or die "Error: ". $dbh->errstr. "\n executing: $statement"; - } - - dbdef_create($dbh, $dbdef_file); - delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload - reload_dbdef($dbdef_file); - -} - #you should have run fs-migrate-part_svc ages ago, when you upgraded #from 1.3 to 1.4... if not, it needs to be hooked into -upgrade here or #you'll lose all the part_svc settings it migrates to part_svc_column @@ -110,10 +83,10 @@ unless ( driver_name =~ /^mysql/i ) { if ( $DRY_RUN ) { print - join(";\n", @statements ). ";\n"; + join(";\n", @bugfix, @statements ). ";\n"; exit; } else { - foreach my $statement ( @statements ) { + foreach my $statement ( @bugfix, @statements ) { warn "$statement\n"; $dbh->do( $statement ) or die "Error: ". $dbh->errstr. "\n executing: $statement"; @@ -190,8 +163,6 @@ unless ( $DRY_RUN || $opt_s ) { $dbh->commit or die $dbh->errstr; $dbh->disconnect or die $dbh->errstr; -$FS::UID::AutoCommit = 1; - $dbh = adminsuidsetup($user); warn "Re-initialization with updated schema completed in ". (time-$start). " seconds\n"; # if $DEBUG; diff --git a/FS/t/cust_tag.t b/FS/t/cust_tag.t deleted file mode 100644 index d81042ca2..000000000 --- a/FS/t/cust_tag.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::cust_tag; -$loaded=1; -print "ok 1\n"; diff --git a/FS/t/msg_template.t b/FS/t/msg_template.t deleted file mode 100644 index cec1d41af..000000000 --- a/FS/t/msg_template.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::msg_template; -$loaded=1; -print "ok 1\n"; diff --git a/FS/t/part_tag.t b/FS/t/part_tag.t deleted file mode 100644 index 12b7b6533..000000000 --- a/FS/t/part_tag.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::part_tag; -$loaded=1; -print "ok 1\n"; diff --git a/FS/t/rate_time.t b/FS/t/rate_time.t deleted file mode 100644 index ece37d198..000000000 --- a/FS/t/rate_time.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::rate_time; -$loaded=1; -print "ok 1\n"; diff --git a/FS/t/rate_time_interval.t b/FS/t/rate_time_interval.t deleted file mode 100644 index 68f9a9590..000000000 --- a/FS/t/rate_time_interval.t +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN { $| = 1; print "1..1\n" } -END {print "not ok 1\n" unless $loaded;} -use FS::rate_time_interval; -$loaded=1; -print "ok 1\n"; @@ -123,8 +123,8 @@ RT_PATH = /opt/rt3 FREESIDE_PATH = `pwd` PERL_INC_DEV_KLUDGE = /usr/local/share/perl/5.10.1/ -VERSION=2.1.1cvs -TAG=freeside_2_1_1 +VERSION=2.1.0 +TAG=freeside_2_1_0 DEBVERSION = `echo ${VERSION} | perl -pe 's/(\d)([a-z])/\1~\2/'`-1 diff --git a/bin/merge-user b/bin/merge-user deleted file mode 100755 index e7833595e..000000000 --- a/bin/merge-user +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/perl -w - -use strict; -use FS::UID qw(adminsuidsetup dbh); -use FS::Schema; -use FS::Record qw(qsearch qsearchs); - -my $DRY_RUN = 1; -$FS::UID::AutoCommit = 0; - -my ($user, $from_usernum, $to_usernum, $go) = @ARGV; -die usage() if not ($user and $from_usernum and $to_usernum); -$DRY_RUN = 0 if defined($go) and $go eq 'go'; - -my $dbh = adminsuidsetup($user); - -# Sanity checks. -die "Can't merge a user to itself." if $from_usernum == $to_usernum; -my $from_user = FS::access_user->by_key($from_usernum) or - die "Usernum '$from_usernum' not found.\n"; -my $to_user = FS::access_user->by_key($to_usernum) or - die "Usernum '$to_usernum' not found.\n"; - -my $tables = FS::Schema::tables_hashref; -foreach my $table (keys %$tables) { - if( grep /^usernum$/, FS::Record::real_fields($table) ) { - next if $table eq 'access_user'; - foreach ($table, "h_$table") { - print "$_: "; - my $sql; - if( $table =~ /^access_(.*)$/ ) { - print "deleting "; - $sql = "DELETE FROM $_ WHERE usernum = $from_usernum"; - } - else { - print "updating "; - $sql = "UPDATE $_ SET usernum = $to_usernum WHERE usernum = $from_usernum"; - } - #print $sql; - my $sth = $dbh->prepare($sql); - $sth->execute; - if($dbh->err) { - print $dbh->errstr."\n"; - $dbh->rollback; - exit(1); - } - print $sth->rows, "\n"; - } - } -} - -if($DRY_RUN) { - warn "Dry run complete. Reverting all changes.\n"; - $dbh->rollback; -} -else { -# Warning: access_user->delete does not transactionize because of -# htpasswd issues. - print "Deleting merged user.\n"; - my $error = $from_user->delete; - die $error if $error; - - warn "Committing changes.\n"; - $dbh->commit; -} -exit(0); - -sub usage { - "Usage:\n merge-user admin_user from_usernum to_usernum [ 'go' ]\n - (Specify 'go' to actually apply changes.)\n\n"; -} diff --git a/bin/rt-update-customfield-dates b/bin/rt-update-customfield-dates deleted file mode 100755 index 73fbd09a4..000000000 --- a/bin/rt-update-customfield-dates +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use Date::Parse; -use Date::Format; -use FS::UID qw(adminsuidsetup); -use FS::Record; - -my @date_fields = ( - 'Circuit Ordered Date', - 'Circuit Due Date (s)', - 'Install Date', - 'Site Audit Date', - 'LOCAL PORT COMPLETE', - 'TF PORTING COMPLETE', - '411 Submission', - 'Billed in Freeside', - 'Billed in Quickbooks', -); -#@date_fields = ( 'Custom thingie' ); - -my $dbh = adminsuidsetup(shift) or die "Usage: rt-update-customfield-dates username\n"; - -foreach my $date_field ( @date_fields ) { - - my $cf_sql = 'SELECT id FROM CustomFields where name = '. $dbh->quote($date_field); - my $cf_sth = $dbh->prepare($cf_sql) or die $dbh->errstr; - $cf_sth->execute or die $cf_sth->errstr; - my $result = $cf_sth->fetchrow_arrayref - or do { warn "$date_field not found; skipping\n"; next }; - my $customfield_id = $result->[0]; - - my $ocfv_sql = "SELECT id, content FROM ObjectCustomFieldValues WHERE customfield = $customfield_id and content !~ '^[0-9]+\$' "; - my $ocfv_sth = $dbh->prepare($ocfv_sql) or die $dbh->errstr; - $ocfv_sth->execute or die $ocfv_sth->errstr; - - while (my $row = $ocfv_sth->fetchrow_arrayref) { - - my($id, $content) = @$row; - - my $origcontent = $content; - - #April 21 KW / April 21 Mont - $content =~ s/^April (\d\d) [a-zA-Z]+$/April $1/; - - #SAL April 29 / other May 3 - $content =~ s/^[a-zA-Z]+ (April|May) (\d\d?)$/$1 $2/; - - #things like "July 8/2010 and "JUNE 24/10" are not doing what we want - $content =~ s/^(June|July) (\d\d?)\/(20)?10$/$1 $2, 2010/i; - - #28/04/2010 - $content =~ s{^(2\d|1[3-9])/(0\d)/2010$}{$2/$1/2010}; - - my $unixdate = str2time($content); #current timezone is what we want here - - #things like "DONE"/"ORDERED" are returning a 0 here.. should stay blank - my $prettynew = $unixdate ? time2str('%Y-%m-%d %T', $unixdate, 'GMT') : ''; - - print "$id: $origcontent -> $prettynew \n" unless $content =~ qr(^0\d/\d\d/2010$); - - my $update_sql = - "UPDATE ObjectCustomFieldValues SET content = '$prettynew'". - " WHERE id = $id"; - - my $update_sth = $dbh->prepare($update_sql) or die $dbh->errstr; - $update_sth->execute or die $update_sth->errstr; - $dbh->commit or die $dbh->errstr; - - } - -} diff --git a/conf/invoice_html b/conf/invoice_html index 2073d7ff4..fe2a9a976 100644 --- a/conf/invoice_html +++ b/conf/invoice_html @@ -87,7 +87,6 @@ <%= $summary %> <%= my $notfirst = 0; - my $columncount = $unitprices ? 5 : 3; foreach my $section ( grep { !$summary || $_->{description} ne $finance_section } @sections ) { if ($section->{'pretotal'} && !$summary) { $OUT .= '</table>' if $notfirst; @@ -121,9 +120,7 @@ '<tr>'; if ($section->{header_generator}) { - my $header = &{$section->{header_generator}}(); - $OUT .= $header; - $columncount = scalar(my @array = split /<\/th><th/i, $header); + $OUT .= &{$section->{header_generator}}(); } else { $OUT .= '<th align="center">Ref</th>'. '<th align="left">Description</th>'. @@ -165,25 +162,19 @@ $OUT .= '</tr>'; $lastref = $line->{'ref'}; if ( @{$line->{'ext_description'} } ) { - unless ( $section->{description_generator} ) { - $OUT .= '<tr class="invoice_extdesc"><td></td><td'; - $OUT .= $unitprices ? ' colspan=3' : ''; - $OUT .= '><table width="100%">'; - } + $OUT .= '<tr class="invoice_extdesc"><td></td><td'; + $OUT .= $unitprices ? ' colspan=3>' : '>'; + $OUT .= '<table width="100%">'; foreach my $ext_desc ( @{$line->{'ext_description'} } ) { $OUT .= '<tr class="invoice_extdesc">'. - ( $section->{'description_generator'} ? '<td></td>' : '' ). '<td align="left" '. ( $ext_desc =~ /<\/?TD>/i ? '' : 'colspan=99' ). '>'. ' '. $ext_desc. '</td>'. '</tr>' } - unless ( $section->{description_generator} ) { - $OUT .= '</table></td><td></td>'; - } - $OUT .= '</tr>'; + $OUT .= '</table></td><td></td></tr>'; } } @@ -207,7 +198,7 @@ } } if ($section->{'posttotal'}) { - $OUT .= '<tr><td align="right" colspan='. $columncount. '>'; + $OUT .= '<tr><td align="right" colspan=5>'; $OUT .= '<p><font size="+1">'. $section->{'posttotal'}. '</font>'. @@ -233,8 +224,8 @@ $OUT .= &{$section->{total_line_generator}}($line); } else { $OUT .= qq(<td style="$style"> </td>). - qq(<td align="left" style="$style" colspan="). - ( $columncount - 2 ). '">'. + qq(<td align="left" style="$style"). + ( $unitprices ? ' colspan=3>' : '>' ). $line->{'total_item'}. '</td>'. qq(<td align="right" style="$style">). $line->{'total_amount'}. '</td>'; diff --git a/conf/invoice_latex b/conf/invoice_latex index 29a901df1..d37eeba3a 100644 --- a/conf/invoice_latex +++ b/conf/invoice_latex @@ -24,14 +24,14 @@ \addtolength{\voffset}{-0.0cm} % top margin to top of header
\addtolength{\hoffset}{-0.6cm} % left margin on page
-\addtolength{\topmargin}{[@-- defined($topmargin) ? $topmargin : '-1.25cm' --@]}
+\addtolength{\topmargin}{-1.25cm} % top margin to top of header
\setlength{\headheight}{2.0cm} % height of header
-\setlength{\headsep}{[@-- defined($headsep) ? $headsep : '1.0cm' --@]}
+\setlength{\headsep}{1.0cm} % between header and text
\setlength{\footskip}{1.0cm} % bottom of footer from bottom of text
%\addtolength{\textwidth}{2.1in} % width of text
\setlength{\textwidth}{19.5cm}
-\setlength{\textheight}{[@-- defined($textheight) ? $textheight : '19.5cm' --@]}
+\setlength{\textheight}{19.5cm}
\setlength{\oddsidemargin}{-0.9cm} % odd page left margin
\setlength{\evensidemargin}{-0.9cm} % even page left margin
@@ -51,7 +51,7 @@ }
}
-\newcommand{\extracouponspace}{[@-- defined($extracouponspace) ? $extracouponspace : '3.6cm' --@]}
+\newcommand{\extracouponspace}{3.6cm}
% Adjust the inset of the mailing address
\newcommand{\addressinset}[1][]{\hspace{1.0cm}}
@@ -80,7 +80,6 @@ $OUT .= '\vspace{-\extracouponspace}';
$OUT .= '\rule[0.5em]{\textwidth}{\footrulewidth}\\\\';
$OUT .= $coupon;
- $OUT .= '\vspace{'. $couponfootsep. '}' if defined($couponfootsep);
}
'';
--@] [@-- $smallerfooter ? '\scriptsize{' : '\small{' --@]
@@ -109,10 +108,10 @@ \returninset
\makebox{
\begin{tabular}{ll}
- \includegraphics{[@-- $logo_file --@]} & [@-- $verticalreturnaddress ? '\\\\' : '' --@]
+ \includegraphics{[@-- $logo_file --@]} &
\begin{minipage}[b]{5.5cm}
[@-- $returnaddress --@]
- \end{minipage}\\
+ \end{minipage}
\end{tabular}
}
}
@@ -202,7 +201,7 @@ \addressinset \rule{0.5cm}{0cm}
\makebox{
\begin{minipage}[t]{7.0cm}
-\vspace{[@-- defined($addresssep) ? $addresssep : '0.25cm' --@]}
+\vspace{0.25cm}
\textbf{[@-- $payname --@]}\\
\addressline{[@-- $company --@]}
\addressline{[@-- $address1 --@]}
diff --git a/conf/invoice_latexcoupon b/conf/invoice_latexcoupon index a4ccddda7..327c1213b 100644 --- a/conf/invoice_latexcoupon +++ b/conf/invoice_latexcoupon @@ -3,13 +3,13 @@ Detach and return this remittance form with your your payment.\\ \begin{tabular}{ll}
\returninset
\begin{tabular}{ll}
- \makebox{ \includegraphics{[@-- $logo_file --@]}} & [@-- $verticalreturnaddress ? '\\\\' : '' --@]
+ \makebox{ \includegraphics{[@-- $logo_file --@]}} &
\begin{minipage}[b]{5.5cm}
[@-- $returnaddress --@]
- \end{minipage}\\
+ \end{minipage}
\end{tabular}&
\begin{tabular}{r@{: }lr}
-Invoice date & \textbf{[@-- $date --@]} & \multirow{4}*{[@-- $verticalreturnaddress ? '\\rule{1.5cm}{0cm}' : '' --@]
+Invoice date & \textbf{[@-- $date --@]} & \multirow{4}*{
\makebox{
\begin{minipage}[t]{7.0cm}
\textbf{[@-- $payname --@]}\\
@@ -21,15 +21,15 @@ Invoice date & \textbf{[@-- $date --@]} & \multirow{4}*{[@-- $verticalreturnaddr \end{minipage}}}\\
Customer\#& \textbf{[@-- $custnum --@]} & \\
Total Due & \textbf{[@-- $balance --@]} & \\
-\rule{0pt}{[@-- defined($amountenclosedsep) ? $amountenclosedsep : '2.25em' --@]}Amount Enclosed & \rule{2cm}{1pt}& \\
+\rule{0pt}{2.25em}Amount Enclosed & \rule{2cm}{1pt}& \\
\end{tabular}\\
-\rule{0pt}{[@-- defined($coupontoaddresssep) ? $coupontoaddresssep : '1cm' --@]} &\\
+\rule{0pt}{1cm} &\\
\end{tabular}\\
\begin{tabular}{ll}
\addressinset \rule{0.5cm}{0cm} &
\makebox{
\begin{minipage}[t]{7.0cm}
-[@-- $addcompanytoaddress ? $company_name. '\\\\' : '' --@][@-- $returnaddress --@]
+[@-- $returnaddress --@]
\end{minipage}}
\hfill
\end{tabular}\\
diff --git a/fs_selfservice/perl/xmlrpc_local-phonenum_balance.pl b/fs_selfservice/perl/xmlrpc_local-phonenum_balance.pl deleted file mode 100755 index 8cbb5b0f0..000000000 --- a/fs_selfservice/perl/xmlrpc_local-phonenum_balance.pl +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/perl - -use strict; -use Frontier::Client; -use Data::Dumper; - -my $phonenum = shift @ARGV; - -my $server = new Frontier::Client ( - url => 'http://localhost:8080/selfservice/xmlrpc.cgi', -); - -my $result = $server->call('FS.ClientAPI_XMLRPC.phonenum_balance', - 'phonenum' => $server->string($phonenum), # '3615588197', -); - -#print Dumper($result); -die $result->{'error'} if $result->{'error'}; - -warn Dumper($result); - -1; diff --git a/htetc/freeside-rt.conf b/htetc/freeside-rt.conf index 2753bc6cc..9b5ccf807 100644 --- a/htetc/freeside-rt.conf +++ b/htetc/freeside-rt.conf @@ -25,11 +25,6 @@ SetHandler perl-script PerlHandler HTML::Mason </Directory> -<Directory %%%FREESIDE_DOCUMENT_ROOT%%%/rt/Ticket/Graphs> -SetHandler perl-script -PerlHandler HTML::Mason -</Directory> - <Directory %%%FREESIDE_DOCUMENT_ROOT%%%/rt/Search> SetHandler perl-script PerlHandler HTML::Mason diff --git a/httemplate/browse/cgp_rule.html b/httemplate/browse/cgp_rule.html index 8a427b828..6f7b3e087 100644 --- a/httemplate/browse/cgp_rule.html +++ b/httemplate/browse/cgp_rule.html @@ -26,45 +26,25 @@ my $svcnum = $1; #agent virt so you can't do cross-agent communigate rules my $cust_svc = qsearchs('cust_svc', { 'svcnum' => $svcnum }) or die 'unknown svcnum'; -my $part_svc = $cust_svc->part_svc; my $count_query = "SELECT COUNT(*) FROM cgp_rule WHERE svcnum = $svcnum"; my($svc_label, $svc_value, $svcdb) = $cust_svc->label; + my $view = FS::UI::Web::svc_url( 'm' => $m, 'action' => 'view', - 'part_svc' => $part_svc, + 'part_svc' => $cust_svc->part_svc, 'svc' => $cust_svc, ); my $html_init = qq(<A HREF="$view">View this $svc_label</A><BR><BR>). - qq!<A HREF="${p}edit/cgp_rule.html?svcnum=$svcnum">Add new rule</A><BR>!; - -if ( $part_svc->svcdb eq 'svc_domain' ) { - - #areyousure for adding these? - - foreach my $line ( FS::Conf->new->config('cgp_rule-domain_templates') ) { - $line =~ /^\s*(\d+)\s+(.+)\s*$/ or next; - my($t_svcnum, $t_name) = ( $1, $2 ); - $html_init .= - qq!<A HREF="${p}misc/clone-cgp_rule.html?clone=$t_svcnum;svcnum=$svcnum">! - ."Add $t_name rule</A><BR>"; - } - -} - -$html_init .= - '<BR>'. + qq!<A HREF="${p}edit/cgp_rule.html?svcnum=$svcnum">Add new rule</A><BR><BR>!. qq! <SCRIPT> - function areyousure_delete(href) { - areyousure(href,"Are you sure you want to delete this rule?"); - } - function areyousure(href,message) { - if (confirm(message) == true) + function areyousure(href) { + if (confirm("Are you sure you want to delete this rule?") == true) window.location.href = href; } </SCRIPT> @@ -75,7 +55,7 @@ my $condition_sub = sub { [ map { [ - { data => $_->conditionname, + { data => $_->condition, #align => }, { data => $_->op, @@ -107,7 +87,7 @@ my $action_sub = sub { my $edit_sub = [ $p.'edit/cgp_rule.html?', 'rulenum' ]; my $del_sub = sub { my $rulenum = shift->rulenum; - [ "javascript:areyousure_delete('${p}misc/delete-cgp_rule.html?$rulenum')", '' ]; + [ "javascript:areyousure('${p}misc/delete-cgp_rule.html?$rulenum')", '' ]; }; </%init> diff --git a/httemplate/browse/msg_template.html b/httemplate/browse/msg_template.html deleted file mode 100644 index 0cd33c797..000000000 --- a/httemplate/browse/msg_template.html +++ /dev/null @@ -1,28 +0,0 @@ -<% include( 'elements/browse.html', - 'title' => 'Message templates', - 'name_singular' => 'template', - 'menubar' => [ 'Add a new template' => - $p.'edit/msg_template.html', - ], - 'query' => { 'table' => 'msg_template', }, - 'count_query' => 'SELECT COUNT(*) FROM msg_template', - 'disableable' => 1, - 'disabled_statuspos' => 2, - 'agent_virt' => 1, - 'agent_null_right' => 'Edit global templates', - 'agent_pos' => 3, - 'header' => [ 'Name' ], - 'fields' => [ 'msgname' ], - 'links' => [ $link ], - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Edit templates') - || $FS::CurrentUser::CurrentUser->access_right('Edit global templates') - || $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -my $link = [ "${p}edit/msg_template.html?", 'msgnum' ]; - -</%init> diff --git a/httemplate/browse/part_event.html b/httemplate/browse/part_event.html index 3d7c245ac..674004bc7 100644 --- a/httemplate/browse/part_event.html +++ b/httemplate/browse/part_event.html @@ -158,8 +158,7 @@ $html_init .= '</SELECT><INPUT TYPE="submit" VALUE="Clone existing event">'. my $count_query = 'SELECT COUNT(*) FROM part_event WHERE '. $FS::CurrentUser::CurrentUser->agentnums_sql( - 'null_right' => 'Edit global billing events', - 'viewall_right' => 'None', + 'null_right' => 'Edit global billing events', ); my $join_conditions = FS::part_event_condition->join_conditions_sql; diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi index 42eb5dfcb..e226ce13e 100755 --- a/httemplate/browse/part_pkg.cgi +++ b/httemplate/browse/part_pkg.cgi @@ -84,11 +84,11 @@ my $extra_sql = scalar(@where) join( 'AND ', @where) : ''; -my $agentnums_sql = $curuser->agentnums_sql( 'table'=>'cust_main' ); +my $agentnums = join(',', $curuser->agentnums); my $count_cust_pkg = " SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum ) WHERE cust_pkg.pkgpart = part_pkg.pkgpart - AND $agentnums_sql + AND cust_main.agentnum IN ($agentnums) "; $select = " diff --git a/httemplate/browse/part_tag.html b/httemplate/browse/part_tag.html deleted file mode 100644 index d0ef72ec3..000000000 --- a/httemplate/browse/part_tag.html +++ /dev/null @@ -1,26 +0,0 @@ -<% include( 'elements/browse.html', - 'title' => 'Tags', - 'name_singular' => 'tag', - 'menubar' => [ 'Add a new tag' => - $p.'edit/part_tag.html', - ], - 'query' => { 'table' => 'part_tag', }, - 'count_query' => 'SELECT COUNT(*) FROM part_tag', - 'header' => [ 'Tag', 'Message', ], - 'fields' => [ 'tagname', 'tagdesc', ], - 'links' => [ $link, '', ], - 'cell_style' => [ '', $tagdesc_style ], - 'disableable' => 1, - 'disabled_statuspos' => 1, - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -my $tagdesc_style = sub { 'background-color:#'.shift->tagcolor }; - -my $link = [ "${p}edit/part_tag.html?", 'tagnum' ]; - -</%init> diff --git a/httemplate/browse/rate.cgi b/httemplate/browse/rate.cgi index 428158a6d..02d670fbd 100644 --- a/httemplate/browse/rate.cgi +++ b/httemplate/browse/rate.cgi @@ -2,8 +2,6 @@ 'title' => 'Rate plans', 'menubar' => [ 'Regions and Prefixes' => $p.'browse/rate_region.html', - 'Time Periods' => - $p.'browse/rate_time.html', ], 'html_init' => $html_init, 'name' => 'rate plans', diff --git a/httemplate/browse/rate_detail.html b/httemplate/browse/rate_detail.html index aef550513..3371926b4 100644 --- a/httemplate/browse/rate_detail.html +++ b/httemplate/browse/rate_detail.html @@ -1,21 +1,72 @@ -<% include('/elements/init_overlib.html') %> -<% include('/elements/header.html',$title) %> -<% include('/elements/menubar.html',@menubar) %> -<% include('/edit/elements/rate_detail.html', - 'ratenum' => $ratenum, - 'countrycode' => $countrycode, -) %> -<% include('/elements/footer.html') %> - +<% include( 'elements/browse.html', + 'title' => $title, + 'name_singular' => 'rate', + 'html_init' => $html_init, + 'menubar' => [ 'Rate plans' => $p.'browse/rate.cgi' ], + 'query' => { + 'table' => 'rate_detail', + 'addl_from' => $join, + 'hashref' => { 'ratenum' => $ratenum }, + 'extra_sql' => $where, + }, + 'count_query' => "SELECT COUNT(*) FROM rate_detail $join". + " WHERE ratenum = $ratenum $where", + 'header' => [ + 'Region', + 'Prefix(es)', + 'Included<BR>minutes', + 'Connection<BR>charge', + 'Charge per<BR>minute', + 'Granularity', + 'Usage class', + ], + 'fields' => [ + 'regionname', + sub { shift->dest_region->prefixes_short }, + sub { shift->min_included. $edit_hint }, + $conn_charge_sub, + sub { $money_char. shift->min_charge. $edit_hint }, + sub { $granularity{ shift->sec_granularity } }, + 'classname', + ], + 'links' => [ '', '', $edit_link, $edit_link, '', '' ], + 'link_onclicks' => [ '', '', $edit_onclick, $edit_onclick, '', '' ], + 'align' => 'llrrcc', + ) +%> <%once> +tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); +tie my %conn_secs, 'Tie::IxHash', FS::rate_detail::conn_secs(); + my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; -my @menubar = ( 'Rate plans' => $p.'browse/rate.cgi', - 'Regions and Prefixes' => $p.'browse/rate_region.html', - 'Time Periods' => $p.'browse/rate_time.html', - ); +my $join = + ' JOIN rate_region ON ( rate_detail.dest_regionnum = rate_region.regionnum )'; + +my $edit_link = [ 'javascript:void(0);', sub { ''; } ]; + +my $edit_onclick = sub { + my $rate_detail = shift; + my $ratedetailnum = $rate_detail->ratedetailnum; + include( '/elements/popup_link_onclick.html', + 'action' => "${p}edit/rate_detail.html?$ratedetailnum", + 'actionlabel' => 'Edit rate', + 'height' => 420, + #default# 'width' => 540, + #default# 'color' => '#333399', + ); +}; +my $edit_hint = ' <FONT SIZE="-1">(edit)</FONT>'; + +my $conn_charge_sub = sub { + my $rate_detail = shift; + #return '' unless $rate_detail->conn_charge > 0 || $rate_detail->conn_sec; + $money_char. $rate_detail->conn_charge. + ($rate_detail->conn_sec ? ' for '.$conn_secs{$rate_detail->conn_sec} : ''). + $edit_hint; +}; </%once> <%init> @@ -23,6 +74,8 @@ my @menubar = ( 'Rate plans' => $p.'browse/rate.cgi', die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); +my $html_init = include('/elements/init_overlib.html'); + $cgi->param('ratenum') =~ /^(\d+)$/ or die "unparsable ratenum"; my $ratenum = $1; my $rate = qsearchs('rate', { 'ratenum' => $ratenum } ) @@ -30,11 +83,18 @@ my $rate = qsearchs('rate', { 'ratenum' => $ratenum } ) my $ratename = $rate->ratename; my $title = "$ratename rates"; -my $where; -my $countrycode = ''; +my @where = (); + if ( $cgi->param('countrycode') =~ /^(\d+)$/ ) { - $countrycode = $1; + my $countrycode = $1; + push @where, "0 < ( SELECT COUNT(*) FROM rate_prefix + WHERE rate_prefix.regionnum = rate_region.regionnum + AND countrycode = '$countrycode' + ) + "; $title .= " for +$countrycode"; } +my $where = scalar(@where) ? ' AND '.join(' AND ', @where ) : ''; + </%init> diff --git a/httemplate/browse/rate_time.html b/httemplate/browse/rate_time.html deleted file mode 100644 index 416ded41f..000000000 --- a/httemplate/browse/rate_time.html +++ /dev/null @@ -1,48 +0,0 @@ -<% include( 'elements/browse.html', - 'title' => 'Rating Time Periods', - 'name_singular' => 'period', - 'menubar' => [ 'Rate plans' => $p.'browse/rate.cgi' ], - 'html_init' => $html_init, - 'query' => { - 'table' => 'rate_time', - 'order_by' => 'ratetimenum', # lacking anything else - 'hashref' => {}, - }, - 'count_query' => 'SELECT COUNT(*) FROM rate_time', - 'header' => \@header, - 'fields' => \@fields, - 'links' => \@links, - 'align' => \@align, - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -my $edit_url = $p.'edit/rate_time.cgi'; - -my $link = [ "$edit_url?", 'ratetimenum' ]; - -my $html_init = - 'Time periods for VoIP and call billing.<BR><BR>'. - qq(<A HREF="$edit_url"><I>Add a new period</I></A><BR><BR>); - -sub interval { - my $i = shift; - '<TABLE>' - .join('', map { '<TR><TD>'.($_->description)[$i].'</TR></TD>' } - shift->intervals - ) . '</TABLE>'; -} - -# inefficient but readable -my $stime_sub = sub { interval(0,shift) }; -my $etime_sub = sub { interval(1,shift) }; - -my @header = ( '#', 'Period', 'Start', 'End' ); -my @fields = ( 'ratetimenum', 'ratetimename', $stime_sub, $etime_sub ); -my @links = ( ($link) x 2 ); -my @align = ( 'right', 'left', 'left' ); - -</%init> diff --git a/httemplate/config/config-delete.cgi b/httemplate/config/config-delete.cgi index 488886824..a05cb1e14 100644 --- a/httemplate/config/config-delete.cgi +++ b/httemplate/config/config-delete.cgi @@ -1,17 +1,6 @@ <%init> - -my $curuser = $FS::CurrentUser::CurrentUser; -die "access denied\n" unless $curuser->access_right('Configuration'); - -my $fsconf = new FS::Conf; -if ( $fsconf->exists('disable_settings_changes') ) { - my @changers = split(/\s*,\s*/, $fsconf->config('disable_settings_changes')); - my %changers = map { $_=>1 } @changers; - unless ( $changers{$curuser->username} ) { - errorpage("Disabled in web demo"); - die "shouldn't be reached"; - } -} +die "access denied\n" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); $cgi->param('confnum') =~ /^(\d+)$/ or die "illegal or missing confnum"; my $confnum = $1; diff --git a/httemplate/config/config-process.cgi b/httemplate/config/config-process.cgi index 4e1c85a03..788d9016e 100644 --- a/httemplate/config/config-process.cgi +++ b/httemplate/config/config-process.cgi @@ -1,30 +1,3 @@ -%if ( scalar(@error) ) { -% -% my $url = popurl(1)."config.cgi"; -% if ( length($cgi->query_string) > 1920 ) { #stupid IE 2083 URL limit -% -% my $session = int(rand(4294967296)); #XXX -% my $pref = new FS::access_user_pref({ -% 'usernum' => $FS::CurrentUser::CurrentUser->usernum, -% 'prefname' => "redirect$session", -% 'prefvalue' => $cgi->query_string, -% 'expiration' => time + 3600, #1h? 1m? -% }); -% my $pref_error = $pref->insert; -% if ( $pref_error ) { -% die "FATAL: couldn't even set redirect cookie: $pref_error". -% " attempting to set redirect$session to ". $cgi->query_string."\n"; -% } -% -<% $cgi->redirect("$url?redirect=$session") %> -% -% } else { -% -<% $cgi->redirect("$url?". $cgi->query_string ) %> -% -% } -% -%} else { <% header('Configuration set') %> <SCRIPT TYPE="text/javascript"> % my $n = 0; @@ -73,7 +46,7 @@ % my $record = qsearchs($table, { $pkey => $key }); % my $value = $record ? "$key: ".$record->$namecol() : $key; configCell.innerHTML = <% $value |js_string %>; -% } elsif ( $type eq 'select-sub' && ! $i->multiple ) { +% } elsif ( $type eq 'select-sub' ) { configCell.innerHTML = <% $conf->config($i->key, $agentnum) |js_string %> + ': ' + <% &{ $i->option_sub }( $conf->config($i->key, $agentnum) ) |js_string %>; @@ -88,7 +61,6 @@ </SCRIPT> </BODY> </HTML> -%} <%once> #false laziness w/config-view.cgi my %namecol = ( @@ -98,21 +70,10 @@ my %namecol = ( ); </%once> <%init> - -my $curuser = $FS::CurrentUser::CurrentUser; -die "access denied\n" unless $curuser->access_right('Configuration'); +die "access denied\n" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); my $conf = new FS::Conf; - -if ( $conf->exists('disable_settings_changes') ) { - my @changers = split(/\s*,\s*/, $conf->config('disable_settings_changes')); - my %changers = map { $_=>1 } @changers; - unless ( $changers{$curuser->username} ) { - errorpage_popup("Disabled in web demo"); - die "shouldn't be reached"; - } -} - $FS::Conf::DEBUG = 1; my @config_items = grep { $_->key != ~/^invoice_(html|latex|template)/ } $conf->config_items; @@ -122,7 +83,6 @@ my $agentnum = $cgi->param('agentnum'); my $key = $cgi->param('key'); my $i = $confitems{$key}; -my @error = (); my @touch = (); my @delete = (); my $n = 0; @@ -132,8 +92,6 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) { if ( $cgi->param($i->key.$n) ne '' ) { my $value = $cgi->param($i->key.$n); $value =~ s/\r\n/\n/g; #browsers? - my $error = &{$i->validate}($value, $n) if $i->validate; - push @error, $error if $error; $conf->set($i->key, $value, $agentnum); } else { $conf->delete($i->key, $agentnum); @@ -141,8 +99,6 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) { } elsif ( $type eq 'binary' || $type eq 'image' ) { if ( defined($cgi->param($i->key.$n)) && $cgi->param($i->key.$n) ) { my $fh = $cgi->upload($i->key.$n); - my $error = &{$i->validate}($fh, $n) if $i->validate; - push @error, $error if $error; if (defined($fh)) { local $/; $conf->set_binary($i->key, <$fh>, $agentnum); @@ -162,16 +118,12 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) { || $i->multiple ) ) { if ( scalar(@{[ $cgi->param($i->key.$n) ]}) ) { - my $error = &{$i->validate}([ $cgi->param($i->key.$n) ], $n) if $i->validate; - push @error, $error if $error; $conf->set($i->key, join("\n", @{[ $cgi->param($i->key.$n) ]} ), $agentnum); } else { $conf->delete($i->key, $agentnum); } } elsif ( $type =~ /^(text|select(-(sub|part_svc|part_pkg|pkg_class))?)$/ ) { if ( $cgi->param($i->key.$n) ne '' ) { - my $error = &{$i->validate}($cgi->param($i->key.$n), $n) if $i->validate; - push @error, $error if $error; $conf->set($i->key, $cgi->param($i->key.$n), $agentnum); } else { $conf->delete($i->key, $agentnum); @@ -183,8 +135,4 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) { $conf->touch($_, $agentnum) foreach @touch; $conf->delete($_, $agentnum) foreach @delete; -if (scalar(@error)) { - $cgi->param('error', join(' ', @error)); -} - </%init> diff --git a/httemplate/config/config-view.cgi b/httemplate/config/config-view.cgi index 11e75707c..08f6c1020 100644 --- a/httemplate/config/config-view.cgi +++ b/httemplate/config/config-view.cgi @@ -349,7 +349,7 @@ my @config_items = grep { $page_agent ? $_->per_agent : 1 } my @deleteable = qw( invoice_latexreturnaddress invoice_htmlreturnaddress ); my %deleteable = map { $_ => 1 } @deleteable; -my @sections = qw(required billing invoicing notification UI self-service username password session shell BIND ); +my @sections = qw(required billing invoicing UI self-service username password session shell BIND ); push @sections, '', 'deprecated'; my %section_items = (); diff --git a/httemplate/config/config.cgi b/httemplate/config/config.cgi index cde48382a..ce96bc162 100644 --- a/httemplate/config/config.cgi +++ b/httemplate/config/config.cgi @@ -131,11 +131,7 @@ Setting <b><% $key %></b> % } elsif ( $type eq 'select-sub' ) { - <select name="<% "$key$n" %>" <% $config_item->multiple ? 'MULTIPLE' : '' %>> - -% unless ( $config_item->multiple ) { - <option value=""> -% } + <select name="<% "$key$n" %>"><option value=""> % my %options = &{$config_item->options_sub}; % my @options = sort { $a <=> $b } keys %options; @@ -143,17 +139,7 @@ Setting <b><% $key %></b> % foreach my $value ( @options ) { % local($^W)=0; next if $saw{$value}++; - <option value="<% $value %>" - -% if ( $value eq $conf->config($key, $agentnum) -% || ( $config_item->multiple -% && grep { $_ eq $value } $conf->config($key, $agentnum) ) ){ - - SELECTED - -% } - - ><% $value %>: <% $options{$value} %> + <option value="<% $value %>" <% $value eq $conf->config($key, $agentnum) ? 'SELECTED' : '' %>><% $value %>: <% $options{$value} %> % } % my $curvalue = $conf->config($key, $agentnum); diff --git a/httemplate/docs/about.html b/httemplate/docs/about.html index 2a0e83261..50600a460 100644 --- a/httemplate/docs/about.html +++ b/httemplate/docs/about.html @@ -29,7 +29,7 @@ GNU <b>Affero</b> General Public License.<BR> <BR> <CENTER> -<FONT SIZE="-3">"Brown eyed women and red grenadine / the bottle was dusty but the liquor was clean" -R. Hunter</FONT> +<FONT SIZE="-3">"Once in a while you get shown the light, in the strangest of places if you look at it right" -R. Hunter</FONT> </CENTER> <SCRIPT TYPE="text/javascript"> diff --git a/httemplate/docs/credits.html b/httemplate/docs/credits.html index 6500e73ba..641be46bb 100644 --- a/httemplate/docs/credits.html +++ b/httemplate/docs/credits.html @@ -31,6 +31,7 @@ <CENTER> <H3>Core Team</H3> +Peter Bowen<BR> Jeremy Davis<BR> Jeff Finucane<BR> Jason Hall<BR> @@ -40,7 +41,6 @@ Mark Wells<BR> <BR> <H3>Core Emeritus</H3> -Peter Bowen<BR> Kristian Hoffman<BR> Brian McCane<BR> Matt Simerson<BR> diff --git a/httemplate/edit/cgp_rule-redirect_all.html b/httemplate/edit/cgp_rule-redirect_all.html deleted file mode 100644 index 898eef8fc..000000000 --- a/httemplate/edit/cgp_rule-redirect_all.html +++ /dev/null @@ -1,57 +0,0 @@ -<% include('/elements/header-popup.html', 'Redirect all mail') %> - -<FORM NAME="RedirectAllForm" ACTION="process/cgp_rule-redirect_all.html" METHOD=POST> - -%# XXX upstream Redirect 1 - -<% ntable("#cccccc", 2) %> - -<TR> - <TD ALIGN="right">Redirect all mail to</TD> - <TD><textarea name="RedirectText" rows="5" cols="50"></textarea></TD> -</TR> - -<% include('/elements/tr-checkbox.html', - 'name' => 'RedirKeep', - 'label' => 'Keep a copy', - 'value' => 1, - 'curr_value' => '', #XXX - ) -%> - -<% include('/elements/tr-checkbox.html', - 'name' => 'RedirHuman', - 'label' => 'Do not redirect automatic messages', - 'value' => 1, - 'curr_value' => '', #XXX - ) -%> - -<% include('/elements/tr-checkbox.html', - 'name' => 'KeepToAndCc', - 'label' => 'Preserve To/Cc fields', - 'value' => 1, - 'curr_value' => '', #XXX - ) -%> - -</TABLE> - -<BR> -<INPUT TYPE="submit" VALUE="Redirect all mail"> -%#XXX Add/Edit - -</FORM> - -</BODY> -</HTML> -<%init> - -my %opt = @_; - -my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $opt{'svcnum'} } ) - or die "unknown svcnum"; - -#XXX look for existing redirect all rule - -</%init> diff --git a/httemplate/edit/cgp_rule-vacation.html b/httemplate/edit/cgp_rule-vacation.html deleted file mode 100644 index efdc5417e..000000000 --- a/httemplate/edit/cgp_rule-vacation.html +++ /dev/null @@ -1,47 +0,0 @@ -<% include('/elements/header-popup.html', 'Vacation rule') %> - -<FORM NAME="VacationForm" ACTION="process/cgp_rule-vacation.html" METHOD=POST> - -%# XXX upstream Vacation 1 - -<% ntable("#cccccc", 2) %> - -<TR> - <TD ALIGN="right">Vacation message</TD> - <TD><textarea name="VacationText" rows="5" cols="50"></textarea></TD> -</TR> - -<% include('/elements/tr-input-date-field.html', { - 'label' => 'Ends', - 'name' => 'vacationTill', - 'value' => '', #XXX - }) -%> -%# XXX upstream: -%# VacationTill 1 -%# vacationDay -%# vacationMonth -%# vacationYear - -%#XXX Clear 'Replied Addresses' List - -</TABLE> - -<BR> -<INPUT TYPE="submit" VALUE="Add vacation message"> -%#XXX Add/Edit - -</FORM> - -</BODY> -</HTML> -<%init> - -my %opt = @_; - -my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $opt{'svcnum'} } ) - or die "unknown svcnum"; - -#XXX look for existing vacation rule - -</%init> diff --git a/httemplate/edit/cgp_rule.html b/httemplate/edit/cgp_rule.html index 41275aba7..d9c19a150 100644 --- a/httemplate/edit/cgp_rule.html +++ b/httemplate/edit/cgp_rule.html @@ -51,7 +51,7 @@ my %opt = @_; my $m2_error_callback_cond = sub { my($cgi, $object) = @_; - my @fields = qw( conditionname op params ); + my @fields = qw( condition op params ); my @gfields = ( '', map "_$_", @fields ); map { @@ -83,7 +83,7 @@ my $m2_error_callback_action = sub { if ( /^ruleactionnum(\d+)$/ ) { my $num = $1; if ( grep $cgi->param("ruleactionnum$num$_"), @gfields ) { - my $x = new FS::cgp_rule_action { + my $x = new FS::cgp_rule_condition { 'ruleactionnum' => $cgi->param("ruleactionnum$num"), map { $_ => scalar($cgi->param("ruleactionnum${num}_$_")) } @fields, }; diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index 57dc3597a..fac7ef27c 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -1,5 +1,5 @@ <% include('/elements/header.html', - $title, + "Customer $action", '', ' onUnload="myclose()"' #hmm, in billing.html ) %> @@ -190,7 +190,7 @@ function samechanged(what) { % } -<INPUT TYPE="hidden" NAME="usernum" VALUE="<% $cust_main->usernum %>"> +<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>"> %# cust_main/bottomfixup.js % foreach my $hidden ( @@ -313,8 +313,8 @@ my $error = $cgi->param('error'); $cgi->delete_all(); $cgi->param('error', $error); -my $title = $custnum ? 'Edit Customer' : 'Add Customer'; -$title .= ": ". $cust_main->name if $custnum; +my $action = $custnum ? 'Edit' : 'Add'; +$action .= ": ". $cust_main->name if $custnum; my $r = qq!<font color="#ff0000">*</font> !; diff --git a/httemplate/edit/cust_main/birthdate.html b/httemplate/edit/cust_main/birthdate.html index b4e78e3b9..415aba3c4 100644 --- a/httemplate/edit/cust_main/birthdate.html +++ b/httemplate/edit/cust_main/birthdate.html @@ -1,11 +1,10 @@ <% ntable("#cccccc", 2) %> - <% include( '/elements/tr-input-date-field.html', - 'birthdate', - $cust_main->birthdate, - 'Date of Birth', - ( $conf->config('date_format') || "%m/%d/%Y" ), - 1 - ) + <% include ('/elements/tr-input-date-field.html', + 'birthdate', + $cust_main->birthdate, + 'Date of Birth', + $conf->config('date_format') || "%m/%d/%Y", + 1) %> </TABLE> <%init> diff --git a/httemplate/edit/cust_main/top_misc.html b/httemplate/edit/cust_main/top_misc.html index 441a36334..36add3721 100644 --- a/httemplate/edit/cust_main/top_misc.html +++ b/httemplate/edit/cust_main/top_misc.html @@ -1,19 +1,11 @@ <% &ntable("#cccccc") %> -%# tags -<% include('/elements/tr-select-cust_tag.html', - 'custnum' => $custnum, - 'cgi' => $cgi, - ) -%> - %# agent <% include('/elements/tr-select-agent.html', 'curr_value' => $cust_main->agentnum, 'label' => "<B>${r}Agent</B>", 'empty_label' => 'Select agent', 'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ), - 'viewall_right' => 'None', #override default 'View customers of all agents' ) %> diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index b19b3618c..0417dc536 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -307,11 +307,6 @@ Example: % foreach grep exists($f->{$_}), % qw( hashref agent_virt agent_null agent_null_right ); % -% #htmlarea -% $include_common{$_} = $f->{$_} -% foreach grep exists($f->{$_}), qw( width height ); -% -% % if ( $type eq 'tablebreak-tr-title' ) { % $include_common{'table_id'} = 'TableNumber'. $tablenum++; % } @@ -541,7 +536,7 @@ Example: var field_regex = /(\d+)(_[a-z]+)?$/; var match = field_regex.exec(what.name); if ( !match ) { - alert(what.name + " didn't match for " + what); + alert(what.name + " didn't match?!"); return; } if ( match[1] != <%$field%>_fieldnum ) { diff --git a/httemplate/edit/elements/rate_detail.html b/httemplate/edit/elements/rate_detail.html deleted file mode 100644 index faf11f844..000000000 --- a/httemplate/edit/elements/rate_detail.html +++ /dev/null @@ -1,239 +0,0 @@ -<%doc> -<% include('/edit/elements/rate_detail.html', - # required - 'ratenum' => '1', - - # optional - 'regionnum' => '25', - # or - 'countrycode' => '237', -) %> - -If regionnum is specified, this produces column headers plus -one row of rate details for that region (in all time periods). -Otherwise, there's one row for each region in the specified -countrycode (or each region anywhere, if there is no countrycode), -with row headers showing the region name and prefixes. - -</%doc> -<% include('/elements/table-grid.html') %> -<TR> -% my $col = 0; -% foreach (@header) { -% my $hlink = $hlinks[$col]; - <TH CLASS = "grid", - BGCOLOR = "#cccccc"> - <% $hlink ? qq!<A HREF="$hlink">$_</A>! : $_ %> - </TH> -% $col++; -% } #foreach @header -</TR><TR> -% my $row = 0; -% foreach my $r (@rows) { -% $col = 0; -% if ( !$opt{'regionnum'} ) { -% $region = $r; -% foreach ($r->regionname, $r->prefixes_short) { - <TD> - <A HREF="<% $p.'edit/rate_region.cgi?'.$r->regionnum %>"><% $_ %></A> - </TD> -% } -% } -% elsif ( !$opt{'ratenum'} ) { -% $rate = $r; - <TD> - <A HREF="<% $p.'edit/rate.cgi?'.$r->ratenum %>"><% $r->ratename %></A> - </TD> -% } -% foreach my $rate_time (@rate_time, '') { - <TD> -% my $detail = $details[$row][$col]; -% if($detail) { - <TABLE CLASS="inv" STYLE="border:none"> - <TR><TD><% edit_link($detail) %><% $money_char.$detail->min_charge %> - <% $detail->sec_granularity ? ' / minute':' / call' %> - <% $edit_hint %></A> - </TD></TR> - <% granularity_detail($detail) %> - <% min_included_detail($detail) %> - <% conn_charge_detail($detail) %> - <TR><TD><% $rate_time ? delete_link($detail) : '' %></TD></TR> - </TABLE> -% } -% else { #!$detail - <% add_link($rate, $region, $rate_time) %> -% } -% $col++; - </TD> -% } # foreach @rate_time -</TR> -% $row++; -% }# foreach @rate_region -</TABLE> - -<%once> - -tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities(); -tie my %conn_secs, 'Tie::IxHash', FS::rate_detail::conn_secs(); - -my $conf = new FS::Conf; -my $money_char = $conf->config('money_char') || '$'; - -sub small { - '<FONT SIZE="-1">'.shift.'</FONT>' -} -my $edit_hint = small('(edit)'); - -sub edit_link { - my $rate_detail = shift; - my $ratedetailnum = $rate_detail->ratedetailnum; - '<A HREF="javascript:void(0);" onclick="'. - include( '/elements/popup_link_onclick.html', - 'action' => "${p}edit/rate_detail.html?$ratedetailnum", - 'actionlabel' => 'Edit rate', - 'height' => 420, - #default# 'width' => 540, - #default# 'color' => '#333399', - ) . '">' -} - -sub add_link { - my ($rate, $region, $rate_time) = @_; - '<A HREF="javascript:void(0);" onclick="'. - include( '/elements/popup_link_onclick.html', - 'action' => "${p}edit/rate_detail.html?ratenum=". - $rate->ratenum. - ';dest_regionnum='. - $region->regionnum. - ($rate_time ? - ';ratetimenum='.$rate_time->ratetimenum : - ''), - 'actionlabel' => 'Add rate', - 'height' => 420, - ).'">'.small('(add)').'</A>' -} - -sub delete_link { - my $rate_detail = shift; - my $ratedetailnum = $rate_detail->ratedetailnum; - my $onclick = include( '/elements/popup_link_onclick.html', - 'action' => "${p}misc/delete-rate_detail.html?$ratedetailnum", - 'actionlabel' => 'Delete rate', - 'width' => 510, - 'height' => 315, - 'frame' => 'top', - ); - $onclick = "if(confirm('Delete this rate?')) { $onclick }"; - qq!<A HREF="javascript:void(0);" onclick="$onclick">!.small('(delete)').'</A>' -} - -sub granularity_detail { - my $rate_detail = shift; - if($rate_detail->sec_granularity != 60 && $rate_detail->sec_granularity > 0) { - '<TR><TD>'. - small('in '.$granularity{$rate_detail->sec_granularity}.' increments'). - '</TD></TR>'; - } - else { '' } -} - -sub min_included_detail { - my $rate_detail = shift; - if($rate_detail->min_included) { - '<TR><TD>'. - small( $rate_detail->min_included . - ($rate_detail->sec_granularity ? - ' minutes included' : - ' calls included') ). - '</TD></TR>' - } - else { '' } -} - -sub conn_charge_detail { - my $rate_detail = shift; - if($rate_detail->conn_charge > 0) { - #return '' unless $rate_detail->conn_charge > 0 || $rate_detail->conn_sec; - '<TR><TD>'. - small( $money_char. $rate_detail->conn_charge. - ' for '.$conn_secs{$rate_detail->conn_sec} - ). - '</TD></TR>' - } - else { '' } -} - -</%once> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -my %opt = @_; -my $ratenum = $opt{'ratenum'} || ''; -my $regionnum = $opt{'regionnum'} || ''; - -# either of these, if the $opt isn't passed, will be set to the -# correct object when generating each row. -my $rate = qsearchs('rate', { 'ratenum' => $ratenum } ) if $ratenum; -my $region = qsearchs('rate_region', { 'regionnum' => $regionnum }) if $regionnum; - -my @rate_time = qsearch('rate_time', {}); -my @header = ( - map( { $_->ratetimename } @rate_time ), - 'Default rate'); -my @hlinks = map( {$p.'edit/rate_time.cgi?'.$_->ratetimenum} @rate_time ), ''; -my @rtns = ( map( { $_->ratetimenum } @rate_time ), '' ); - -my @details; -my @rows; -if ( $ratenum ) { - if ( $regionnum ) { - @rows = qsearch('rate_region', - { ratenum => $ratenum, regionnum => $regionnum }); - } - else { - my $where = ''; - if ( $opt{'countrycode'} ) { - $where = "WHERE 0 < ( - SELECT COUNT(*) FROM rate_prefix - WHERE rate_prefix.regionnum = rate_region.regionnum - AND countrycode = '$opt{countrycode}' - )"; - } - @rows = qsearch({ table => 'rate_region', - hashref => { }, - extra_sql => $where, - }); - die "no region found" if !@rows; - - unshift @header, 'Region', 'Prefix(es)'; - unshift @hlinks, '', ''; - } - foreach my $region (@rows) { - push @details, [ map { qsearchs('rate_detail', - { 'ratenum' => $ratenum, - 'dest_regionnum' => $region->regionnum, - 'ratetimenum' => $_ } ) or '' - } @rtns - ]; - } -} -elsif ( $regionnum ) { - @rows = qsearch('rate', {}) or die "no rate plans found"; - unshift @header, 'Rate plan'; - unshift @hlinks, ''; - foreach my $rate (@rows) { - push @details, [ map { qsearchs('rate_detail', - { 'ratenum' => $rate->ratenum, - 'dest_regionnum' => $regionnum, - 'ratetimenum' => $_ } ) or '' - } @rtns - ]; - } -} -else { - die "no ratenum or regionnum specified"; -} - -</%init> diff --git a/httemplate/edit/msg_template.html b/httemplate/edit/msg_template.html deleted file mode 100644 index 67eae185d..000000000 --- a/httemplate/edit/msg_template.html +++ /dev/null @@ -1,158 +0,0 @@ -<% include( 'elements/edit.html', - 'html_init' => '<TABLE id="outerTable"><TR><TD>', - 'name_singular' => 'template', - 'table' => 'msg_template', - 'viewall_dir' => 'browse', - 'agent_virt' => 1, - 'agent_null' => 1, - 'agent_null_right' => 'Edit global templates', - - 'fields' => [ 'msgname', - 'subject', - 'from_addr', - { field=>'body', type=>'htmlarea', width=>763 }, - ], - 'labels' => { 'msgnum' => 'Template', - 'msgname' => 'Template name', - 'from_addr' => 'Return address', - 'subject' => 'Message subject', - 'body' => 'Message template', - }, - 'html_foot' => "</TD>$sidebar</TR></TABLE>", - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Edit templates') - || $FS::CurrentUser::CurrentUser->access_right('Edit global templates') - || $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -# Create hints pane - -my %substitutions = ( - 'cust_main' => [ - '$display_custnum'=> 'Customer#', - '$agentnum' => 'Agent#', - '$agent_name' => 'Agent name', - '$payby' => 'Payment method', - '$paymask' => 'Card/account# (masked)', - '$payname' => 'Name on card/bank name', - '$paytype' => 'Account type', - '$payip' => 'IP address used to submit payment info', - '$num_ncancelled_pkgs' => '# of active packages', - '$num_cancelled_pkgs' => '# of cancelled packages', - '$num_pkgs' => '# of packages', - '$classname' => 'Customer class', - '$categoryname' => 'Customer category', - '$balance' => 'Current balance', - '$invoicing_list_emailonly' => 'Billing email address', - '$cust_status' => 'Status', - '$ucfirst_cust_status' => 'Status, capitalized', - '$cust_statuscolor' => 'Status color code', - '$company_name' => 'Our company name', - ], - 'contact' => [ # duplicate this for shipping - '$name' => 'Company and contact name', - '$name_short' => 'Company or contact name', - '$company' => 'Company name', - '$contact' => 'Contact name (last, first)', - '$contact_firstlast'=> 'Contact name (first last)', - '$first' => 'First name', - '$last' => 'Last name', - '$address1' => 'Address line 1', - '$address2' => 'Address line 2', - '$city' => 'City', - '$county' => 'County', - '$state' => 'State', - '$zip' => 'Zip', - '$country' => 'Country', - '$daytime' => 'Day phone', - '$night' => 'Night phone', - '$fax' => 'Fax', - ], - 'cust_bill' => [ - '$invnum' => 'Invoice#', - ], - 'cust_pkg' => [ - '$pkgnum' => 'Package#', - '$pkg_label' => 'Package label (short)', - '$pkg_label_long' => 'Package label (long)', - '$status' => 'Status', - '$statuscolor' => 'Status color code', - '$start_ymd' => 'Start date', - '$setup_ymd' => 'Setup date', - '$last_bill_ymd' => 'Last bill date', - '$next_bill_ymd' => 'Next bill date', - '$susp_ymd' => 'Suspended on date', - '$cancel_ymd' => 'Canceled on date', - '$adjourn_ymd' => 'Adjournment date', - '$expire_ymd' => 'Expiration date', - '$labels_short' => 'Service labels', - '$location_label' => 'Service location', - ], - 'svc_acct' => [ - '$username' => 'Login name', - '$password' => 'Password', - ], - 'cust_pay' => [ - '$paynum' => 'Payment#', - '$paid' => 'Amount', - '$payby' => 'Payment method', - '$date' => 'Payment date', - '$payinfo' => 'Card/account# (masked)', - ], -); -my @c = @{ $substitutions{'contact'} }; -for (my $i=0; $i<scalar(@c); $i += 2) { - $c[$i] =~ s/\$(.*)/\$ship_$1/; -} -$substitutions{'shipping'} = \@c; - -tie my %sections, 'Tie::IxHash', ( -'contact' => 'Name and contact info (billing)', -'shipping' => 'Name and contact info (shipping)', -'cust_main' => 'Customer status and payment info', -'cust_pkg' => 'Package fields', -'cust_bill' => 'Invoice fields', -'cust_pay' => 'Payment fields', -'svc_acct' => 'Login service fields', -); - -my $widget = new HTML::Widgets::SelectLayers( - 'options' => \%sections, - 'form_name' => 'dummy', - 'html_between'=>'</FORM><FONT SIZE=-1>', - 'selected_layer'=>(keys(%sections))[0], - 'layer_callback' => sub { - my $section = shift; - my $html = include('/elements/table-grid.html'); - my @hints = @{ $substitutions{$section} }; - while(@hints) { - my $key = shift @hints; - $html .= qq!\n<TR><TD><A href="javascript:insertHtml('{$key}')">$key</A></TD>!; - $html .= "\n<TD>".shift(@hints).'</TD></TR>'; - } - $html .= "\n</TABLE>"; - return $html; - }, -); - -my $sidebar = ' -<SCRIPT TYPE="text/javascript"> -function insertHtml(what) { - var oEditor = FCKeditorAPI.GetInstance("body"); - oEditor.InsertHtml(what); -}; -</SCRIPT> -<TD valign="top"><FORM name="dummy"> -Substitutions: ' -. $widget->html . -'<BR>Click links to insert. -<BR>Enclose substitutions and other Perl expressions in braces: -<BR>{ $name } = ExampleCo (Smith, John) -<BR>{ time2str("%D", time) } = '.time2str("%D", time).' -</FONT></TD> -'; - -</%init> diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index deefa9cc1..c8b7ecb58 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -563,10 +563,6 @@ my $html_bottom = sub { $html .= ' MULTIPLE' if $href->{$field}{'type'} eq 'select_multiple'; $html .= qq! NAME="${layer}__$field">!; - - $html .= '<OPTION VALUE="">'. $href->{$field}{'empty_label'} - if exists($href->{$field}{'disable_empty'}) - && ! $href->{$field}{'disable_empty'}; if ( $href->{$field}{'select_table'} ) { foreach my $record ( diff --git a/httemplate/edit/part_tag.html b/httemplate/edit/part_tag.html deleted file mode 100644 index 87c77fa98..000000000 --- a/httemplate/edit/part_tag.html +++ /dev/null @@ -1,29 +0,0 @@ -<% include( 'elements/edit.html', - 'table' => 'part_tag', - 'name_singular' => 'tag', - 'fields' => [ - { field=>'tagname', type=>'text', size=>10 }, - { field=>'disabled', type=>'checkbox', value=>'Y' }, - { field=>'tagdesc', type=>'text', size=>60 }, - $tagcolor, - ], - 'labels' => { 'tagnum' => 'Tag #', - 'tagname' => 'Tag', - 'tagdesc' => 'Message', - 'tagcolor' => 'Highlight Color', - 'disabled' => 'Disabled', - }, - 'viewall_dir' => 'browse', - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -my $tagcolor = { - field => 'tagcolor', - type => 'pickcolor', -}; - -</%init> diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html index 2d125c387..ab25cb3a2 100644 --- a/httemplate/edit/process/access_group.html +++ b/httemplate/edit/process/access_group.html @@ -1,3 +1,6 @@ +% if ( $conf->exists('disable_acl_changes') ) { + ACL changes disabled in public demo. +% } else { <% include( 'elements/process.html', 'table' => 'access_group', 'viewall_dir' => 'browse', @@ -14,14 +17,12 @@ }, ) %> +% } <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); -if ( FS::Conf->new->exists('disable_acl_changes') ) { - errorpage('ACL changes disabled in public demo.'); - die "shouldn't be reached"; -} +my $conf = new FS::Conf; </%init> diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html index e6258a9b1..ca6bb603f 100644 --- a/httemplate/edit/process/access_user.html +++ b/httemplate/edit/process/access_user.html @@ -18,9 +18,4 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); -if ( FS::Conf->new->exists('disable_acl_changes') ) { - errorpage('ACL changes disabled in public demo.'); - die "shouldn't be reached"; -} - </%init> diff --git a/httemplate/edit/process/agent.cgi b/httemplate/edit/process/agent.cgi index e776d281c..3cdf40c9b 100755 --- a/httemplate/edit/process/agent.cgi +++ b/httemplate/edit/process/agent.cgi @@ -13,9 +13,4 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); -if ( FS::Conf->new->exists('disable_acl_changes') ) { - errorpage('ACL changes disabled in public demo.'); - die "shouldn't be reached"; -} - </%init> diff --git a/httemplate/edit/process/cgp_rule.html b/httemplate/edit/process/cgp_rule.html index 5326587cb..f427b6ccf 100644 --- a/httemplate/edit/process/cgp_rule.html +++ b/httemplate/edit/process/cgp_rule.html @@ -4,19 +4,13 @@ 'process_o2m' => [ { 'table' => 'cgp_rule_condition', - 'fields' => [qw( conditionname op params )], + 'fields' => [qw( condition op params )], }, { 'table' => 'cgp_rule_action', 'fields' => [qw( action params )], }, ], - 'noerror_callback' => sub { - my( $cgi, $object ) = @_; - my $error = $object->svc_export; - #shit, not a good place for error handling :/ - die $error if $error; - }, ) %> <%init> diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi index 3158d7bbf..1311ba4f3 100755 --- a/httemplate/edit/process/cust_main.cgi +++ b/httemplate/edit/process/cust_main.cgi @@ -73,8 +73,6 @@ if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) { ); } -$new->tagnum( [ $cgi->param('tagnum') ] ); - my %usedatetime = ( 'birthdate' => 1 ); foreach my $dfield (qw( birthdate signupdate )) { diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index 53419cde0..87cadb774 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -65,9 +65,6 @@ Example: #return an error string or empty for no error 'precheck_callback' => sub { my( $cgi ) = @_; }, - #after everything's inserted - 'noerror_callback' => sub { my( $cgi, $object ) = @_; }, - #supplies arguments to insert() and replace() # for use with tables that are FS::option_Common (among other things) 'args_callback' => sub { my( $cgi, $object ) = @_; }, @@ -207,7 +204,6 @@ if ( $opt{'agent_virt'} ) { die "illegal agentnum" unless $curuser->agentnums_href->{$new->agentnum} - or $curuser->access_right('View customers of all agents') or $opt{'agent_null_right'} && ! $new->agentnum && $curuser->access_right($opt{'agent_null_right'}); @@ -302,20 +298,12 @@ if ( !$error && $opt{'process_o2m'} ) { if ( $error ) { - $cgi->param('error', $error); if ( $opt{'clear_on_error'} && scalar(@{$opt{'clear_on_error'}}) ) { foreach my $field (@{$opt{'clear_on_error'}}) { $cgi->param($field, '') } } - -} else { - - if ( $opt{'noerror_callback'} ) { - &{ $opt{'noerror_callback'} }( $cgi, $new ); - } - } </%init> diff --git a/httemplate/edit/process/elements/svc_Common.html b/httemplate/edit/process/elements/svc_Common.html index 5a8afbd6c..8e8c99a42 100644 --- a/httemplate/edit/process/elements/svc_Common.html +++ b/httemplate/edit/process/elements/svc_Common.html @@ -1,14 +1,15 @@ +% +% +% my %opt = @_; +% my $table = $opt{'table'}; +% $opt{'fields'} ||= [ fields($table) ]; +% push @{ $opt{'fields'} }, qw( pkgnum svcpart ); +% +% <% include( 'process.html', 'edit_ext' => 'cgi', 'redirect' => popurl(3)."view/$table.cgi?", %opt, ) %> -<%init> -my %opt = @_; -my $table = $opt{'table'}; -$opt{'fields'} ||= [ fields($table) ]; -push @{ $opt{'fields'} }, qw( pkgnum svcpart ); - -</%init> diff --git a/httemplate/edit/process/msg_template.html b/httemplate/edit/process/msg_template.html deleted file mode 100644 index 70d451b72..000000000 --- a/httemplate/edit/process/msg_template.html +++ /dev/null @@ -1,13 +0,0 @@ -<% include( 'elements/process.html', - 'table' => 'msg_template', - 'viewall_dir' => 'browse', - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Edit templates') - || $FS::CurrentUser::CurrentUser->access_right('Edit global templates') - || $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -</%init> diff --git a/httemplate/edit/process/part_tag.html b/httemplate/edit/process/part_tag.html deleted file mode 100644 index 077dc4cd9..000000000 --- a/httemplate/edit/process/part_tag.html +++ /dev/null @@ -1,11 +0,0 @@ -<% include( 'elements/process.html', - 'table' => 'part_tag', - 'viewall_dir' => 'browse', - ) -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -</%init> diff --git a/httemplate/edit/process/rate_region.cgi b/httemplate/edit/process/rate_region.cgi index d342e605a..8036f7388 100755 --- a/httemplate/edit/process/rate_region.cgi +++ b/httemplate/edit/process/rate_region.cgi @@ -1,8 +1,6 @@ %if ( $error ) { % $cgi->param('error', $error); <% $cgi->redirect(popurl(2). "rate_region.cgi?". $cgi->query_string ) %> -%} elsif ( $action eq 'Add' ) { -<% $cgi->redirect(popurl(2). "rate_region.cgi?$regionnum") %> %} else { <% $cgi->redirect(popurl(3). "browse/rate_region.html") %> %} @@ -13,7 +11,6 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); my $regionnum = $cgi->param('regionnum'); -my $action = $regionnum ? 'Edit' : 'Add'; my $old = qsearchs('rate_region', { 'regionnum' => $regionnum } ) if $regionnum; @@ -36,12 +33,24 @@ my @rate_prefix = map { 'npa' => $_, } } @npa; -# we no longer process dest_detail records here + +my @dest_detail = map { + my $ratenum = $_->ratenum; + new FS::rate_detail { + 'ratenum' => $ratenum, + map { $_ => $cgi->param("$_$ratenum") } + qw( min_included conn_charge conn_sec min_charge sec_granularity classnum ) + }; +} qsearch('rate', {} ); + + my $error; if ( $regionnum ) { - $error = $new->replace($old, 'rate_prefix' => \@rate_prefix ); + $error = $new->replace($old, 'rate_prefix' => \@rate_prefix, + 'dest_detail' => \@dest_detail, ); } else { - $error = $new->insert( 'rate_prefix' => \@rate_prefix ); + $error = $new->insert( 'rate_prefix' => \@rate_prefix, + 'dest_detail' => \@dest_detail, ); $regionnum = $new->getfield('regionnum'); } diff --git a/httemplate/edit/process/rate_time.cgi b/httemplate/edit/process/rate_time.cgi deleted file mode 100644 index 4fa78ce6d..000000000 --- a/httemplate/edit/process/rate_time.cgi +++ /dev/null @@ -1,94 +0,0 @@ -% if ( $error ) { -% $cgi->param('error', $error); -<% $cgi->redirect(popurl(2). "rate_time.cgi?". $cgi->query_string ) %> -% } else { -<% $cgi->redirect(popurl(3). "browse/rate_time.html" ) %> -% } -%# dumper_html(\%vars, \%old_ints, {$rate_time->intervals}) %> -<%init> -my $error = ''; -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); -my $ratetimenum = $cgi->param('ratetimenum'); -my $ratetimename = $cgi->param('ratetimename'); -my $delete = $cgi->param('delete'); - -my %vars = $cgi->Vars; -#warn Dumper(\%vars)."\n"; - -my $rate_time; - -my %old_ints; -if( $ratetimenum ) { - # editing - $rate_time = FS::rate_time->by_key($ratetimenum); - - # make a list of existing intervals that will be deleted - foreach ($rate_time->intervals) { - $old_ints{$_->intervalnum} = $_; - } - - if ( $delete ) { - $error = $rate_time->delete; - # intervals will be deleted later - } - elsif( $ratetimename ne $rate_time->ratetimename ) { - # the only case where the rate_time itself must be replaced - $rate_time->ratetimename($ratetimename); - $error = $rate_time->replace; - } -} -else { #!$ratetimenum, adding new - $rate_time = FS::rate_time->new({ ratetimename => $ratetimename }); - $error = $rate_time->insert; - $ratetimenum = $rate_time->ratetimenum; -} - -my @new_ints; -if(!$delete and !$error) { - foreach my $i (map { /^sd(\d+)$/ } keys(%vars)) { - my $stime = l2wtime(@vars{"sd$i", "sh$i", "sm$i", "sa$i"}); - my $etime = l2wtime(@vars{"ed$i", "eh$i", "em$i", "ea$i"}); - #warn "$i: $stime - $etime"; - next if !defined($stime) or !defined($etime) or $etime == $stime; - # try to avoid needlessly wiping and replacing intervals every - # time this is edited. - if( %old_ints ) { - my $this_int = qsearchs('rate_time_interval', - { ratetimenum => $ratetimenum, - stime => $stime, - etime => $etime, } ); - if($this_int) { - delete $old_ints{$this_int->intervalnum}; - #warn "not deleting $stime-$etime\n"; - next; #$i - } - } - push @new_ints, FS::rate_time_interval->new({ ratetimenum => $ratetimenum, - stime => $stime, - etime => $etime, } ); - } -} -if(!$error) { - foreach (values(%old_ints)) { - $error = $_->delete; - #warn "deleting ".$_->stime.' '.$_->etime."\n"; - last if $error; - } -} -if(!$error) { - # do this last to avoid overlap errors with deleted intervals - foreach (@new_ints) { - $error = $_->insert; - #warn "inserting $stime-$etime\n"; - last if $error; - } -} - -sub l2wtime { - my ($d, $h, $m, $a) = @_; - $h += 24*$d + 12*$a; - $m += 60*$h; - return 60*$m -} -</%init> diff --git a/httemplate/edit/process/svc_acct.cgi b/httemplate/edit/process/svc_acct.cgi index 0b272b5b1..0d2c007f1 100755 --- a/httemplate/edit/process/svc_acct.cgi +++ b/httemplate/edit/process/svc_acct.cgi @@ -70,7 +70,6 @@ if ( $svcnum ) { grep { $new->$_ } qw( seconds upbytes downbytes totalbytes ); - $error ||= "invalid $_" foreach grep { $hash{$_} !~ /^\d+$/ } keys %hash; $error ||= $new->set_usage(\%hash); #unoverlimit and trigger radius changes last; #once is enough } diff --git a/httemplate/edit/prospect_main.html b/httemplate/edit/prospect_main.html index e867907ed..8ae76a9a1 100644 --- a/httemplate/edit/prospect_main.html +++ b/httemplate/edit/prospect_main.html @@ -98,6 +98,7 @@ my $m2_error_callback = sub { 'contactnum' => $cgi->param("contactnum$num"), map { $_ => scalar($cgi->param("contactnum${num}_$_")) } @fields, }; + use Data::Dumper; warn Dumper $x; $x; } else { (); @@ -109,6 +110,6 @@ my $m2_error_callback = sub { $cgi->param; }; -#my @agentnums = $FS::CurrentUser::CurrentUser->agentnums; +my @agentnums = $FS::CurrentUser::CurrentUser->agentnums; </%init> diff --git a/httemplate/edit/rate.cgi b/httemplate/edit/rate.cgi index 13717dc1a..75c714322 100644 --- a/httemplate/edit/rate.cgi +++ b/httemplate/edit/rate.cgi @@ -22,14 +22,8 @@ Rate plan <INPUT NAME="submit" TYPE="button" VALUE="<% $rate->ratenum ? "Apply changes" : "Add rate plan" %>" onClick="document.OneTrueForm.submit.disabled=true; process();"> -</FORM> -% if($rate->ratenum) { -<BR><BR><FONT SIZE="+2">Rates in this plan</FONT> -<% include('/edit/elements/rate_detail.html', - 'ratenum' => $rate->ratenum -) %> -% } +</FORM> <% include('/elements/footer.html') %> diff --git a/httemplate/edit/rate_detail.html b/httemplate/edit/rate_detail.html index ec04e4cbb..869ace8d4 100644 --- a/httemplate/edit/rate_detail.html +++ b/httemplate/edit/rate_detail.html @@ -5,7 +5,6 @@ 'labels' => { 'ratedetailnum' => 'Rate', #should hide... 'dest_regionname' => 'Region', 'dest_prefixes_short' => 'Prefix(es)', - 'rate_time_name' => 'Time period', 'min_included' => 'Included minutes/calls', 'conn_charge' => 'Connection charge', 'conn_sec' => 'For', @@ -17,10 +16,8 @@ { field=>'ratenum', type=>'hidden', }, { field=>'orig_regionnum', type=>'hidden', }, { field=>'dest_regionnum', type=>'hidden', }, - { field=>'ratetimenum', type=>'hidden', }, { field=>'dest_regionname', type=>'fixed', }, { field=>'dest_prefixes_short', type=>'fixed', }, - { field=>'rate_time_name', type=>'fixed', }, { field=>'min_included', type=>'text', size=>5 }, { field=>'conn_charge', type=>'money', size=>4 }, { field =>'conn_sec', @@ -45,12 +42,6 @@ }, ], - 'new_hashref_callback' => sub { - { ratenum => $cgi->param('ratenum'), - dest_regionnum => $cgi->param('dest_regionnum'), - ratetimenum => $cgi->param('ratetimenum'), - } - }, ) %> <%once> diff --git a/httemplate/edit/rate_region.cgi b/httemplate/edit/rate_region.cgi index cae30030a..f77c0dbe7 100644 --- a/httemplate/edit/rate_region.cgi +++ b/httemplate/edit/rate_region.cgi @@ -35,20 +35,114 @@ </TABLE> -<BR><BR> -<INPUT TYPE="submit" VALUE="<% $rate_region->regionnum ? "Apply changes" : "Add region" %>"> -</FORM> -%# rate plan info, if the region has been created yet +%# rate plan info -% if($rate_region->regionnum) { <BR> -<BR> -<FONT SIZE="+2">Rates in this region</FONT> -<% include('/edit/elements/rate_detail.html', - 'regionnum' => $rate_region->regionnum, -) %> + +<% include('/elements/table-grid.html') %> +% my $bgcolor1 = '#eeeeee'; +% my $bgcolor2 = '#ffffff'; +% my $bgcolor = ''; + + <TR> + <TH CLASS="grid" BGCOLOR="#cccccc"> + Rate plan + </TH> + <TH CLASS="grid" BGCOLOR="#cccccc"> + <FONT SIZE=-1>Included<BR>minutes/calls</FONT> + </TH> + <TH CLASS="grid" BGCOLOR="#cccccc"> + <FONT SIZE=-1>Connection<BR>charge</FONT> + </TH> + <TH CLASS="grid" BGCOLOR="#cccccc"> + <FONT SIZE=-1>Connection<BR>charge for</FONT> + </TH> + <TH CLASS="grid" BGCOLOR="#cccccc"> + <FONT SIZE=-1>Charge per<BR>minute/call</FONT> + </TH> + <TH CLASS="grid" BGCOLOR="#cccccc"> + <FONT SIZE=-1>Granularity</FONT> + </TH> + <TH CLASS="grid" BGCOLOR="#cccccc"> + <FONT SIZE=-1>Usage class</FONT> + </TH> + </TR> + +% foreach my $rate ( qsearch('rate', {}) ) { +% +% my $n = $rate->ratenum; +% my $rate_detail = $rate->dest_detail($rate_region) +% || new FS::rate_region { 'min_included' => 0, +% 'min_charge' => 0, +% 'sec_granularity' => '60' +% }; +% +% if ( $bgcolor eq $bgcolor1 ) { +% $bgcolor = $bgcolor2; +% } else { +% $bgcolor = $bgcolor1; % } + <TR> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <A HREF="<%$p%>edit/rate.cgi?<% $rate->ratenum %>"><% $rate->ratename %></A> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <INPUT TYPE="text" SIZE=9 NAME="min_included<%$n%>" VALUE="<% $cgi->param("min_included$n") || $rate_detail->min_included |h %>"> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <%$money_char%><INPUT TYPE="text" SIZE=9 NAME="conn_charge<%$n%>" VALUE="<% $cgi->param("conn_charge$n") || $rate_detail->conn_charge |h %>"> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <SELECT NAME="conn_sec<%$n%>"> +% foreach my $conn_sec ( keys %conn_secs ) { +% my $curr_value = $cgi->param("conn_sec$n") || $rate_detail->conn_sec; +% my $selected = ($conn_sec==$curr_value) ? ' SELECTED' : ''; + <OPTION VALUE="<% $conn_sec %>" <%$selected%>><% $conn_secs{$conn_sec} %></OPTION> +% } + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <%$money_char%><INPUT TYPE="text" SIZE=6 NAME="min_charge<%$n%>" VALUE="<% $cgi->param("min_charge$n") || $rate_detail->min_charge |h %>"> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <SELECT NAME="sec_granularity<%$n%>"> +% foreach my $granularity ( keys %granularity ) { + <OPTION VALUE="<%$granularity%>"<% $granularity == ( $cgi->param("sec_granularity$n") || $rate_detail->sec_granularity ) ? ' SELECTED' : '' %>><%$granularity{$granularity}%> +% } + </SELECT> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% include( '/elements/select-table.html', + 'element_name' => "classnum$n", + 'table' => 'usage_class', + 'name_col' => 'classname', + 'empty_label' => '(default)', + 'hashref' => { disabled => '' }, + 'curr_value' => ( $cgi->param("classnum$n") || + $rate_detail->classnum ), + ) + %> + </TD> + + </TR> + +% } + +</TABLE> + + +<BR><BR> +<INPUT TYPE="submit" VALUE="<% $rate_region->regionnum ? "Apply changes" : "Add region" %>"> + +</FORM> + <% include('/elements/footer.html') %> <%once> diff --git a/httemplate/edit/rate_time.cgi b/httemplate/edit/rate_time.cgi deleted file mode 100644 index eca8fbb61..000000000 --- a/httemplate/edit/rate_time.cgi +++ /dev/null @@ -1,69 +0,0 @@ -<% include("/elements/header.html", { title => "$action Time Period" }) %> -<% include("/elements/menubar.html", - 'Rate plans' => "${p}browse/rate.cgi", - ) %> -<BR> -<% include('/elements/error.html') %> -<BR> - -<FORM METHOD="POST" ACTION="<% "${p}edit/process/rate_time.cgi" %>"> -<INPUT TYPE="hidden" NAME="ratetimenum" VALUE="<% $ratetimenum %>"> -<% ntable('#cccccc',2) %> -<TABLE> - <TR> - <TH ALIGN="right">Period name</TH> - <TD><INPUT TYPE="text" NAME="ratetimename" VALUE="<% $rate_time ? $rate_time->ratetimename : '' %>"></TD> - </TR> -</TABLE> -<% include('/elements/auto-table.html', - 'header' => [ '', 'Start','','', '','End','','' ], - 'fields' => [ qw(sd sh sm sa ed eh em ea) ], - 'select' => [ ($day, $hour, $min, $ampm) x 2 ], - 'data' => \@data, - ) %> -<INPUT TYPE="submit" VALUE="<% $rate_time ? 'Apply changes' : 'Add period'%>"> -</FORM> -<BR> -<A HREF="<% "${p}edit/process/rate_time.cgi?ratetimenum=$ratetimenum;delete=1" %>">Delete this period</A> -<% include('/elements/footer.html') %> - -<%init> -my $ratetimenum = ($cgi->keywords)[0] || $cgi->param('ratetimenum') || ''; -my $action = 'Add'; -my $rate_time; -my @data = (); -my $day = [ 0 => 'Sun', - 1 => 'Mon', - 2 => 'Tue', - 3 => 'Wed', - 4 => 'Thu', - 5 => 'Fri', - 6 => 'Sat', ]; -my $hour = [ map( {$_, sprintf('%02d',$_) } 0..11 )]; -my $min = [ map( {$_, sprintf('%02d',$_) } 0,30 )]; -my $ampm = [ 0 => 'AM', 1 => 'PM' ]; - -if($ratetimenum) { - $action = 'Edit'; - $rate_time = qsearchs('rate_time', {ratetimenum => $ratetimenum}) - or die "ratetimenum $ratetimenum not found"; - if($cgi->param('error')) { - my %vars = $cgi->Vars; - foreach my $i (sort {$a <=> $b } map { /^sd(\d+)$/ } keys(%vars)) { - push @data, [ @vars{"sd$i", "sh$i", "sm$i", "sa$i", - "ed$i", "eh$i", "em$i", "ea$i"} ]; - } - } - else { - foreach my $interval ($rate_time->intervals) { - push @data, [ map { int($_/86400) % 7, - int($_/3600) % 12, - int($_/60) % 60, - int($_/43200) % 2, } - ( $interval->stime, $interval->etime ) - ]; - } - } -} - -</%init> diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi index 59b5d10f3..5c2d5f495 100755 --- a/httemplate/edit/svc_acct.cgi +++ b/httemplate/edit/svc_acct.cgi @@ -392,16 +392,10 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR> </TD> </TR> - <% include('/elements/tr-select.html', - 'label' => 'On logout remove trash', - 'field' => 'cgp_emptytrash', - 'options' => $svc_acct->cgp_emptytrash_values, - 'labels' => { - '' => 'default (92 days)', #right? - }, - 'curr_value' => $svc_acct->cgp_emptytrash, - ) - %> + <TR> + <TD ALIGN="right">On logout remove trash</TD> + <TD><INPUT TYPE="text" NAME="cgp_emptytrash" VALUE="<% $svc_acct->cgp_emptytrash %>"></TD> + </TR> <% include('/elements/tr-select.html', 'label' => 'Language', @@ -417,7 +411,69 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR> <% include('/elements/tr-select.html', 'label' => 'Time zone', 'field' => 'cgp_timezone', - 'options' => $svc_acct->cgp_timezone_values, + 'options' => [ + 'HostOS', + '(+0100) Algeria/Congo', + '(+0200) Egypt/South Africa', + '(+0300) Saudi Arabia', + '(+0400) Oman', + '(+0500) Pakistan', + '(+0600) Bangladesh', + '(+0700) Thailand/Vietnam', + '(+0800) China/Malaysia', + '(+0900) Japan/Korea', + '(+1000) Queensland', + '(+1100) Micronesia', + '(+1200) Fiji', + '(+1300) Tonga/Kiribati', + '(+1400) Christmas Islands', + '(-0100) Azores/Cape Verde', + '(-0200) Fernando de Noronha', + '(-0300) Argentina/Uruguay', + '(-0400) Venezuela/Guyana', + '(-0500) Haiti/Peru', + '(-0600) Central America', + '(-0700) Arisona', + '(-0800) Adamstown', + '(-0900) Marquesas Islands', + '(-1000) Hawaii/Tahiti', + '(-1100) Samoa', + 'Asia/Afghanistan', + 'Asia/India', + 'Asia/Iran', + 'Asia/Iraq', + 'Asia/Israel', + 'Asia/Jordan', + 'Asia/Lebanon', + 'Asia/Syria', + 'Australia/Adelaide', + 'Australia/East', + 'Australia/NorthernTerritory', + 'Europe/Central', + 'Europe/Eastern', + 'Europe/Moscow', + 'Europe/Western', + 'GMT (+0000)', + 'Newfoundland', + 'NewZealand/Auckland', + 'NorthAmerica/Alaska', + 'NorthAmerica/Atlantic', + 'NorthAmerica/Central', + 'NorthAmerica/Eastern', + 'NorthAmerica/Mountain', + 'NorthAmerica/Pacific', + 'Russia/Ekaterinburg', + 'Russia/Irkutsk', + 'Russia/Kamchatka', + 'Russia/Krasnoyarsk', + 'Russia/Magadan', + 'Russia/Novosibirsk', + 'Russia/Vladivostok', + 'Russia/Yakutsk', + 'SouthAmerica/Brasil', + 'SouthAmerica/Chile', + 'SouthAmerica/Paraguay', + ], 'labels' => { '' => 'default (HostOS)', }, diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi index 5abe9d6b5..b19e9ee15 100755 --- a/httemplate/edit/svc_domain.cgi +++ b/httemplate/edit/svc_domain.cgi @@ -220,17 +220,11 @@ Account defaults </TD> </TR> - <% include('/elements/tr-select.html', + <% include('/elements/tr-input-text.html', 'label' => 'On logout remove trash', - 'field' => 'acct_def_cgp_emptytrash', - 'options' => $svc_domain->cgp_emptytrash_values, - 'labels' => { - '' => 'default (92 days)', #right? - }, 'curr_value' => $svc_domain->acct_def_cgp_emptytrash, ) %> - <% include('/elements/tr-select.html', 'label' => 'Language', 'field' => 'acct_def_cgp_language', @@ -245,7 +239,69 @@ Account defaults <% include('/elements/tr-select.html', 'label' => 'Time zone', 'field' => 'acct_def_cgp_timezone', - 'options' => $svc_domain->cgp_timezone_values, + 'options' => [ + 'HostOS', + '(+0100) Algeria/Congo', + '(+0200) Egypt/South Africa', + '(+0300) Saudi Arabia', + '(+0400) Oman', + '(+0500) Pakistan', + '(+0600) Bangladesh', + '(+0700) Thailand/Vietnam', + '(+0800) China/Malaysia', + '(+0900) Japan/Korea', + '(+1000) Queensland', + '(+1100) Micronesia', + '(+1200) Fiji', + '(+1300) Tonga/Kiribati', + '(+1400) Christmas Islands', + '(-0100) Azores/Cape Verde', + '(-0200) Fernando de Noronha', + '(-0300) Argentina/Uruguay', + '(-0400) Venezuela/Guyana', + '(-0500) Haiti/Peru', + '(-0600) Central America', + '(-0700) Arisona', + '(-0800) Adamstown', + '(-0900) Marquesas Islands', + '(-1000) Hawaii/Tahiti', + '(-1100) Samoa', + 'Asia/Afghanistan', + 'Asia/India', + 'Asia/Iran', + 'Asia/Iraq', + 'Asia/Israel', + 'Asia/Jordan', + 'Asia/Lebanon', + 'Asia/Syria', + 'Australia/Adelaide', + 'Australia/East', + 'Australia/NorthernTerritory', + 'Europe/Central', + 'Europe/Eastern', + 'Europe/Moscow', + 'Europe/Western', + 'GMT (+0000)', + 'Newfoundland', + 'NewZealand/Auckland', + 'NorthAmerica/Alaska', + 'NorthAmerica/Atlantic', + 'NorthAmerica/Central', + 'NorthAmerica/Eastern', + 'NorthAmerica/Mountain', + 'NorthAmerica/Pacific', + 'Russia/Ekaterinburg', + 'Russia/Irkutsk', + 'Russia/Kamchatka', + 'Russia/Krasnoyarsk', + 'Russia/Magadan', + 'Russia/Novosibirsk', + 'Russia/Vladivostok', + 'Russia/Yakutsk', + 'SouthAmerica/Brasil', + 'SouthAmerica/Chile', + 'SouthAmerica/Paraguay', + ], 'labels' => { '' => 'default (HostOS)', }, diff --git a/httemplate/elements/auto-table.html b/httemplate/elements/auto-table.html deleted file mode 100644 index 9c7dfd09a..000000000 --- a/httemplate/elements/auto-table.html +++ /dev/null @@ -1,161 +0,0 @@ -<%doc> - -Example: -<% include('/elements/auto-table.html', - - ### - # required - ### - - 'header' => [ '#', 'Item', 'Amount' ], - 'fields' => [ 'id', 'name', 'amount' ], - - ### - # highly recommended - ### - - 'size' => [ 4, 12, 8 ], - 'maxl' => [ 4, 12, 8 ], - 'align' => [ 'right', 'left', 'right' ], - - ### - # optional - ### - - 'data' => [ [ 1, 'Widget', 25 ], - [ 12, 'Super Widget, 7 ] ], - #or - 'records' => [ qsearch('item', { } ) ], - # or any other array of FS::Record objects - - 'select' => [ '', - [ 1 => 'option 1', - 2 => 'option 2', ... - ], # options for second field - '' ], - - 'prefix' => 'mytable_', -) %> - -Values will be passed through as "mytable_id1", etc. -</%doc> - -<TABLE ID="<% $prefix %>AutoTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0> - <TR> -% foreach (@header) { - <TH><% $_ %></TH> -% } - </TR> -% my $row = 0; -% for ( $row = 0; $row < scalar @data; $row++ ) { - <TR> -% my $col = 0; -% for ( $col = 0; $col < scalar @fields; $col++ ) { -% my $id = $prefix . $fields[$col] . $row; - <TD> -% my @o = @{ $select[$col] }; -% if( @o ) { - <SELECT NAME="<% $id %>" ID="<% $id %>"> -% while(@o) { -% my $val = shift @o; - <OPTION VALUE=<% $val %><% -$val eq $data[$row][$col] ? ' SELECTED' : ''%>><% shift @o %></OPTION> -% } - </SELECT> -% } -% else { - <INPUT TYPE = "text" - NAME = "<% $id %>" - ID = "<% $id %>" - SIZE = <% $size[$col] %> - MAXLENGTH = <% $maxl[$col] %> - STYLE = "text-align:<% $align[$col] %>" - VALUE = "<% $data[$row][$col] %>" -% if( $opt{'autoadd'} ) { - onchange = "possiblyAddRow(this);" -% } - > - </TD> -% } -% } - <TD> - <IMG SRC = "<% "${p}images/cross.png" %>" - ALT = "X" - onclick = "deleteRow(this);" - > - </TD> - </TR> -% } -</TABLE> -% if( !$opt{'autoadd'} ) { -<INPUT TYPE="button" VALUE="Add" onclick="<% $prefix %>addRow();"><BR> -% } - -<SCRIPT TYPE="text/javascript"> - var <% $prefix %>rownum = <% $row %>; - var <% $prefix %>table = document.getElementById('<% $prefix %>AutoTable'); - // last row is initially blank, clone it and remove it - var <% $prefix %>_blank = - <% $prefix %>table.rows[<% $prefix %>table.rows.length-1].cloneNode(true); -% if( !$opt{'autoadd'} ) { - <% $prefix %>table.deleteRow(<% $prefix %>table.rows.length-1); -% } - - - - function rownum_of(obj) { - return (obj.parentNode.parentNode.sectionRowIndex); - } - - function <% $prefix %>possiblyAddRow(obj) { - if ( <% $prefix %>rownum == rownum_of(obj) ) { - <% $prefix %>addRow(); - } - } - - function <% $prefix %>addRow() { - var row = <% $prefix %>table.insertRow(-1); - var cells = <% $prefix %>_blank.cells; - for (i=0; i<cells.length; i++) { - row.appendChild(cells[i].cloneNode(true)); - } - <% $prefix %>rownum++; - } - - function deleteRow(obj) { - if(<% $prefix %>rownum == rownum_of(obj)) { - <% $prefix %>addRow(); - } - <% $prefix %>table.deleteRow(rownum_of(obj)); - <% $prefix %>rownum--; - return(false); - } - -</SCRIPT> - -<%init> -my %opt = @_; - -my @header = @{ $opt{'header'} }; -my @fields = @{ $opt{'fields'} }; -my @data = (); -if($opt{'data'}) { - @data = @{ $opt{'data'} }; -} -elsif($opt{'records'}) { - foreach my $rec (@{ $opt{'records'} }) { - push @data, [ map { $rec->getfield($_) } @fields ]; - } -} -# else @data = (); -push @data, [ map {''} @fields ]; # make a blank row - -my $prefix = $opt{'prefix'}; -my @size = $opt{'size'} ? @{ $opt{'size'} } : (map {16} @fields); -my @maxl = $opt{'maxl'} ? @{ $opt{'maxl'} } : @size; -my @align = $opt{'align'} ? @{ $opt{'align'} } : (map {'right'} @fields); -my @select = @{ $opt{'select'} || [] }; -foreach (0..scalar(@fields)-1) { - $select[$_] ||= []; -} -</%init> diff --git a/httemplate/elements/bill.html b/httemplate/elements/bill.html deleted file mode 100644 index 64a1a6d2c..000000000 --- a/httemplate/elements/bill.html +++ /dev/null @@ -1,55 +0,0 @@ -<%doc> - -Clickable link to bill a customer. - -Example: -<% include( '/elements/bill.html', - ### - # required - ### - custnum => $custnum, - label => 'Bill Now!', - - ### - # recommended - ### - url => $p.'view/cust_main.cgi?'.$custnum, - - ### - # optional, can contain any FS::cust_main::bill_and_collect options - ### - bill_opts => { 'batch_card' => 'yes' }, - formname => 'MyBillNowLink', # if for some reason you want this -) %> - -</%doc> -<FORM NAME="<%$formname%>" STYLE="display:inline"> -<% include('/elements/progress-init.html', - $formname, - [ 'custnum', @opt_keys ], - $p.'misc/bill.cgi', - $url ? { url => $url } : { message => $message }, - $formname, # use it as 'key' -) %> -<A HREF="javascript:void(0);" onclick="javascript:<%$formname%>process();"><%$label%></A> -<INPUT TYPE="hidden" NAME="custnum" VALUE="<%$custnum%>"> -% foreach(@opt_keys) { -<INPUT TYPE="hidden" NAME="<%$_%>" VALUE="<%$bill_opts->{$_}%>"> -% } -</FORM> -<%init> - -my %opt = @_; -my $custnum = $opt{'custnum'}; -my $label = $opt{'label'}; -# formname no longer needs to be passed from outside, but we still -# need one and it needs to be unique -my $formname = $opt{'formname'} || - 'bill'.sprintf('%04d',int(rand(10000))).$custnum; -my $url = $opt{'url'} || ''; -my $message = $opt{'message'} || 'Finished!'; -my $bill_opts = $opt{'bill_opts'} || {}; -my @opt_keys = keys(%$bill_opts); -my @opt_vals = values(%$bill_opts); - -</%init> diff --git a/httemplate/elements/communigate_pro-accessmodes.html b/httemplate/elements/communigate_pro-accessmodes.html index b5fa53c37..6ce9ca587 100644 --- a/httemplate/elements/communigate_pro-accessmodes.html +++ b/httemplate/elements/communigate_pro-accessmodes.html @@ -11,11 +11,8 @@ my @names = (qw( Mail Relay Signal Mobile TLS POP IMAP MAPI AirSync SIP XMPP WebMail XIMSS FTP ACAP PWD LDAP RADIUS S/MIME WebCAL WebSite PBX HTTP - MobilePBX YMedia )); -#GIPS Media? - </%once> <%init> diff --git a/httemplate/elements/file-upload.html b/httemplate/elements/file-upload.html index 034eaec38..7e2eeefcd 100644 --- a/httemplate/elements/file-upload.html +++ b/httemplate/elements/file-upload.html @@ -54,15 +54,10 @@ <INPUT TYPE="hidden" NAME="upload_fields" VALUE="<% join(',', @field) %>" /> % foreach (@field) { -% if($param{'no_table'}) { - <% shift @label %> <INPUT TYPE="file" NAME="<% $_ %>" /> -% } -% else { <TR> <TH ALIGN="<% $param{'label_align'} || 'right' %>"><% shift @label %></TH> <TD><INPUT TYPE="file" NAME="<% $_ %>" /></TD> </TR> -% } % } <DIV STYLE="display:<% $param{debug} ? 'visible' : 'none' %>"> diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css index dfb56e959..3816f9878 100644 --- a/httemplate/elements/freeside.css +++ b/httemplate/elements/freeside.css @@ -109,8 +109,6 @@ a.fstab { font-weight:bold; text-decoration:none; overflow:visible; - margin-left:6px; - margin-right:6px; } a.fstab:hover { text-decoration:none; @@ -121,12 +119,13 @@ a.fstab:hover { a:visited:hover.fsblackbutton */ a.fstabselected { - background-color:#ffffff; + background-color:#f8f8f8; color: #000000; - border-top:1px solid #7e0079; - border-left:1px solid #7e0079; - border-right:1px solid #7e0079; - border-bottom:1px solid #ffffff; + border:1px solid; + border-top-color:#7e0079; + border-left-color:#7e0079; + border-right-color:#7e0079; + border-bottom-color:#ffffff; -moz-border-radius-topleft:8px; -moz-border-radius-topright:8px; -webkit-border-radius-topleft:8px; @@ -142,37 +141,12 @@ a.fstabselected { font-weight:bold; text-decoration:none; overflow:visible; - margin-left:6px; - margin-right:6px; } a.fstabselected:hover { text-decoration:none; color: #000000; } -div.fstabs { - padding-left:8px; - border-bottom:1px solid #7e0079; -} - -div.fstabcontainer { - background-color:#ffffff; - padding:8px; - border-left:1px solid #7e0079; - border-right:1px solid #7e0079; - border-bottom:1px solid #7e0079; - -moz-border-radius-bottomleft:8px; - -moz-border-radius-bottomright:8px; - -webkit-border-radius-bottomleft:8px; - -webkit-border-radius-bottomright:8px; - border-radius-bottomleft:8px; - border-radius-bottomright:8px; - -moz-box-shadow: #666666 1px 1px 2px; - -webkit-box-shadow: #666666 1px 1px 2px; - box-shadow: #666666 1px 1px 2px; - filter: progid:DXImageTransform.Microsoft.Shadow(color='#666666', Direction=135, Strength=2); -} - .background { background-color:#f8f8f8; } diff --git a/httemplate/elements/header-popup.html b/httemplate/elements/header-popup.html index 2bd4a96e8..cd8da5657 100644 --- a/httemplate/elements/header-popup.html +++ b/httemplate/elements/header-popup.html @@ -1,21 +1,3 @@ -<%doc> - -Example: - - include( '/elements/header-popup.html', - { - 'title' => 'Title', - 'menubar' => \@menubar, - 'etc' => '', #included in <BODY> tag, for things like onLoad= - 'head' => '', #included before closing </HEAD> tag - 'nobr' => 0, #1 for no <BR><BR> after the title - } - ); - - #old-style - include( '/elements/header.html', 'Title', $menubar, $etc, $head); - -</%doc> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML> <HEAD> diff --git a/httemplate/elements/htmlarea.html b/httemplate/elements/htmlarea.html index f00c77360..dca4328ab 100644 --- a/httemplate/elements/htmlarea.html +++ b/httemplate/elements/htmlarea.html @@ -22,9 +22,6 @@ Example: oFCKeditor.BasePath = '<% $p %>elements/fckeditor/'; oFCKeditor.Config['SkinPath'] = '<% $p %>elements/fckeditor/editor/skins/silver/'; -% if ( $opt{'width'} ) { - oFCKeditor.Width = '<% $opt{'width'} %>'; -% } oFCKeditor.Height = '<% $opt{'height'} || 420 %>'; oFCKeditor.Config['StartupFocus'] = true; oFCKeditor.Config['EnterMode'] = 'br'; diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index a5bcdeb19..2d28e49d4 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -215,7 +215,7 @@ $report_packages{'Advanced package reports'} = [ $fsurl.'search/report_cust_pkg tie my %report_inventory, 'Tie::IxHash', 'Inventory by agent' => [ $fsurl.'search/report_agent_inventory.html', '' ], - 'Inventory activity' => [ $fsurl.'search/report_h_inventory_item.html', '' ], + #'Inventory activity' => [ $fsurl.'search/report_h_inventory_item.html', '' ], ; tie my %report_rating, 'Tie::IxHash', @@ -357,8 +357,6 @@ $tools_menu{'Quick payment entry'} = [ $fsurl.'misc/batch-cust_pay.html', 'Ente $tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_date;open=1;intransit=1', 'Process credit card and electronic check batches' ] if ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') ) && $curuser->access_right('Process batches'); -$tools_menu{'Process invoice batches'} = [ $fsurl.'search/bill_batch.cgi' ] - if ( $conf->exists('invoice_print_pdf') ); $tools_menu{'Job Queue'} = [ $fsurl.'search/queue.html', 'View pending job queue' ] if $curuser->access_right('Job queue'); $tools_menu{'Ticketing'} = [ \%tools_ticketing, 'Ticketing tools' ] @@ -421,7 +419,6 @@ tie my %config_billing_rates, 'Tie::IxHash', 'Rate plans' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans' ], 'Regions and prefixes' => [ $fsurl.'browse/rate_region.html', 'Manage regions and prefixes' ], 'Usage classes' => [ $fsurl.'browse/usage_class.html', 'Usage classes define groups of usage for taxation.' ], - 'Time periods' => [ $fsurl.'browse/rate_time.html', 'Time periods define days and hours for rate plans' ], 'Edit rates with Excel' => [ $fsurl.'misc/rate_edit_excel.html', 'Download and edit rates with Excel, then upload changes.' ], #"Edit with Excel" ? ; @@ -473,18 +470,12 @@ tie my %config_phone, 'Tie::IxHash', ; tie my %config_misc, 'Tie::IxHash'; -$config_misc{'Message templates'} = [ $fsurl.'browse/msg_template.html', 'Templates for customer notices' ] - if $curuser->access_right('Edit templates') - || $curuser->access_right('Edit global templates') - || $curuser->access_right('Configuration'); -$config_misc{'Tags'} = [ $fsurl.'browse/part_tag.html', '' ] - if $curuser->access_right('Configuration'); $config_misc{'Advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service.' ] if $curuser->access_right('Edit advertising sources') || $curuser->access_right('Edit global advertising sources'); if ( $curuser->access_right('Configuration') ) { $config_misc{'Virtual fields'} = [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ]; - $config_misc{'Error catalog'} = [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ]; + $config_misc{'Message catalog'} = [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ]; } $config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ] if $curuser->access_right('Edit inventory') @@ -522,8 +513,7 @@ $config_menu{'Broadband'} = [ \%config_broadband, '' ] $config_menu{'Phone'} = [ \%config_phone, '' ] if ( $curuser->access_right('Configuration') ); $config_menu{'Miscellaneous'} = [ \%config_misc, '' ] - if $curuser->access_right('Configuration' ) - || $curuser->access_right('Edit advertising sources') + if $curuser->access_right('Edit advertising sources') || $curuser->access_right('Edit global advertising sources'); diff --git a/httemplate/elements/menubar.html b/httemplate/elements/menubar.html index c14904337..fe49f7b2e 100644 --- a/httemplate/elements/menubar.html +++ b/httemplate/elements/menubar.html @@ -19,10 +19,10 @@ Example: </%doc> %if ( $opt->{'newstyle'} ) { +% my $s = '<FONT STYLE="border-bottom:1px solid #7e0079">'; - <DIV CLASS="fstabs"> - <% join('', @html ) %> - </DIV> + <% join("$s </FONT>", ( '', @html, '' ) ) %> + <BR> %} else { diff --git a/httemplate/elements/pickcolor.html b/httemplate/elements/pickcolor.html deleted file mode 100644 index d410ebfc7..000000000 --- a/httemplate/elements/pickcolor.html +++ /dev/null @@ -1,60 +0,0 @@ -<INPUT TYPE="hidden" NAME="<% $opt{'field'} %>" ID="<%$id%>" VALUE="<%$value%>"> -<TABLE BGCOLOR="#FFFFFF" ID="showcolor<%$unum%>"> -<TR> - <TD STYLE="border:1px solid blue;background-color:#<%$value%>" WIDTH=16 HEIGHT=16 ID="currcolor<%$unum%>"></TD> - <TD> <A HREF="javascript:void(0);" onClick="change_clicked<%$unum%>()">change</A></TD> -</TR> -</TABLE> -<TABLE BGCOLOR="#FFFFFF" ID="pickcolor<%$unum%>" STYLE="display:none"> -% for (1..$rows) { - <TR> -% for (1..$cols) { -% last unless @colors; -% my $color = shift(@colors); - <TD STYLE="border:1px solid blue;cursor:pointer;cursor:hand" BGCOLOR="#<% $color %>" WIDTH=16 HEIGHT=16 onClick="color_clicked<%$unum%>('<%$color%>')"></TD> -% } - </TR> -% } -</TABLE> -<SCRIPT TYPE="text/javascript"> - - function change_clicked<%$unum%>() { - document.getElementById('showcolor<%$unum%>').style.display = 'none'; - document.getElementById('pickcolor<%$unum%>').style.display = ''; - } - - function color_clicked<%$unum%>(color) { - document.getElementById('<%$id%>').value = color; //update hidden - if ( color == '' ) { color = 'ffffff'; } - document.getElementById('currcolor<%$unum%>').style.backgroundColor = '#' + color; - document.getElementById('showcolor<%$unum%>').style.display = ''; - document.getElementById('pickcolor<%$unum%>').style.display = 'none'; - } - -</SCRIPT> -<%init> - -my %opt = @_; - -my $value = length($opt{curr_value}) ? $opt{curr_value} : $opt{value}; - -my $unum = int(rand(100000)); - -my $id = $opt{'id'} || $opt{'field'}.$unum; - -my @colors = ( - '', #none/white - 'FF6666', #red - 'FF9966', #orange - 'FFFF66', #yellow - '66FF66', #green - '66FFFF', #cyan? - '6666FF', #blue - 'CC66FF', #purple? FF66FF looks more like pink. -); - -my $rows = 2; - -my $cols = int(.5+scalar(@colors)/$rows); - -</%init> diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html index 8b8da66c8..194fc7480 100644 --- a/httemplate/elements/progress-init.html +++ b/httemplate/elements/progress-init.html @@ -1,45 +1,3 @@ -<%doc> -Example: -In misc/something.html: - - <FORM NAME="MyForm"> - <INPUT TYPE="hidden" NAME="recordnum" VALUE="42"> - <INPUT TYPE="hidden" NAME="what_to_do" VALUE="delete"> - <% include( '/elements/progress-init.html', - 'MyForm', - [ 'recordnum', 'what_to_do' ], - $p.'misc/process_something.html', - { url => $p.'where_to_go_next.html' }, - #or { message => 'Finished!' }, - ) %> - </FORM> - <SCRIPT TYPE="text/javascript>process();</SCRIPT> - -In misc/process_something.html: - -<%init> -my $server = FS::UI::Web::JSRPC->new('FS::something::process_whatever', $cgi); -</%init> -<% $server->process %> - -In FS/something.pm: - -sub process_whatever { #class method - my $job = shift; - my $param = thaw(base64_decode(shift)); - # param = { 'recordnum' => 42, 'what_to_do' => delete } - # make use of this as you like - do_phase1; - $job->update_statustext(20); - do_phase2; - $job->update_statustext(40); - do_phase3; - $job->update_statustext(60); - # etc. - return 'this value will be ignored'; -} - -</%doc> <% include('/elements/xmlhttp.html', 'method' => 'POST', 'url' => $action, diff --git a/httemplate/elements/progress-popup.html b/httemplate/elements/progress-popup.html index a29210201..8a55efb4a 100644 --- a/httemplate/elements/progress-popup.html +++ b/httemplate/elements/progress-popup.html @@ -69,14 +69,6 @@ function updateStatus( status_statustext ) { alert('job done but no url or message specified'); % } - } else if ( status.indexOf('done') > -1 ) { - - document.getElementById("progress_message").innerHTML = "Loading report"; - document.getElementById("progress_bar").innerHTML = ''; - document.getElementById("progress_percent").innerHTML = ''; - document.getElementById("progress_jobnum").innerHTML = ''; - window.top.location.href = statustext.substr(8, statustext.length-18); - } else if ( status.indexOf('error') > -1 ) { document.getElementById("progress_message").innerHTML = '<FONT SIZE="+1" COLOR="#FF0000">Error: ' + statustext + '</FONT>'; document.getElementById("progress_bar").innerHTML = ''; diff --git a/httemplate/elements/select-cgp_rule_condition.html b/httemplate/elements/select-cgp_rule_condition.html index bc96ab487..622cbe86d 100644 --- a/httemplate/elements/select-cgp_rule_condition.html +++ b/httemplate/elements/select-cgp_rule_condition.html @@ -3,10 +3,10 @@ <INPUT TYPE="hidden" NAME="<%$name%>" ID="<%$id%>" VALUE="<% $curr_value %>"> <% include( 'select.html', - 'field' => $name.'_conditionname', - 'id' => $id.'_conditionname', + 'field' => $name.'_condition', + 'id' => $id.'_condition', 'options' => \@conditions, - 'curr_value' => $conditionname, + 'curr_value' => $condition, 'labels' => { '' => 'Select Condition' }, 'onchange' => $name.'_changed', ) @@ -189,10 +189,10 @@ if ( $curr_value ) { $cgp_rule_condition = new FS::cgp_rule_condition {}; } -my $conditionname = scalar($cgi->param($name.'_conditionname')) - || $cgp_rule_condition->conditionname; +my $condition = scalar($cgi->param($name.'_condition')) + || $cgp_rule_condition->condition; -my @op = &$cond2op($conditionname); +my @op = &$cond2op($condition); my $disabled = scalar(@op) ? '' : 1; my $style = $disabled ? 'visibility:hidden' : ''; diff --git a/httemplate/elements/select-cust_tag.html b/httemplate/elements/select-cust_tag.html deleted file mode 100644 index 61d4dca3b..000000000 --- a/httemplate/elements/select-cust_tag.html +++ /dev/null @@ -1,20 +0,0 @@ -<% include( '/elements/select-table.html', - 'table' => 'part_tag', - 'name_col' => 'tagname', #tagname - tagdesc?? - 'multiple' => 1, - #'value' => $agentnum || '', - #'agent_virt' => 1, - 'hashref' => { 'disabled' => '' }, - 'order_by' => ' ORDER BY tagname', - %opt, - ) -%> -<%init> - -my %opt = @_; -#my $agentnum = $opt{'curr_value'} || $opt{'value'}; - -$opt{'records'} = delete $opt{'part_tag'} - if $opt{'part_tag'}; - -</%init> diff --git a/httemplate/elements/tr-htmlarea.html b/httemplate/elements/tr-htmlarea.html deleted file mode 100644 index 1a4e25080..000000000 --- a/httemplate/elements/tr-htmlarea.html +++ /dev/null @@ -1,25 +0,0 @@ -<% include('tr-td-label.html', @_ ) %> - - <TD <% $cell_style %>> - - <% include('htmlarea.html', @_ ) %> - - </TD> - -</TR> - -<%init> - -my %opt = @_; - -my $onchange = $opt{'onchange'} - ? 'onChange="'. $opt{'onchange'}. '(this)"' - : ''; - -#my $rows = $opt{'rows'} ? 'ROWS="'.$opt{'rows'}.'"' : ''; -#my $cols = $opt{'cols'} ? 'COLS="'.$opt{'cols'}.'"' : ''; - -my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : ''; -#my $curr_value = $opt{'curr_value'}; - -</%init> diff --git a/httemplate/elements/tr-pickcolor.html b/httemplate/elements/tr-pickcolor.html deleted file mode 100644 index 2b6cc23ca..000000000 --- a/httemplate/elements/tr-pickcolor.html +++ /dev/null @@ -1,11 +0,0 @@ -<% include('tr-td-label.html', @_ ) %> - <TD <% $colspan %> <% $cell_style %> ID="<% $opt{input_id} || $opt{id}.'_input0' %>"><% include('pickcolor.html', @_ ) %></TD> -<%init> - -my %opt = @_; - -my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : ''; - -my $colspan = $opt{'colspan'} ? 'COLSPAN="'.$opt{'colspan'}.'"' : ''; - -</%init> diff --git a/httemplate/elements/tr-select-agent.html b/httemplate/elements/tr-select-agent.html index 9f2f76a6c..fcfa9f300 100644 --- a/httemplate/elements/tr-select-agent.html +++ b/httemplate/elements/tr-select-agent.html @@ -1,27 +1,3 @@ -<%doc> - -Example: - - include( '/elements/tr-select-agent.html', - - #recommended to keep things "sticky" on errors - 'curr_value' => $curr_value, - - ## - # optional - ## - - 'label' => 'Agent for this thing', - 'empty_label' => 'Select agent', #override default - 'disable_empty' => 1, - - #set to 'None' or something to override default of showing all agents - #for employees w/ 'View customers of all agents' right - viewall_right => 'None', - - ); - -</%doc> % if ( scalar(@agents) == 1 ) { <INPUT TYPE="hidden" NAME="<% $opt{'field'} || 'agentnum' %>" VALUE="<% $agents[0]->agentnum %>"> @@ -50,11 +26,8 @@ Example: my %opt = @_; my $agentnum = $opt{'curr_value'} || $opt{'value'}; -my @agents = - $opt{'agents'} - ? @{ $opt{'agents'} } - : $FS::CurrentUser::CurrentUser->agents( - 'viewall_right' => $opt{'viewall_right'}, - ); +my @agents = $opt{'agents'} + ? @{ $opt{'agents'} } + : $FS::CurrentUser::CurrentUser->agents; </%init> diff --git a/httemplate/elements/tr-select-cust_tag.html b/httemplate/elements/tr-select-cust_tag.html deleted file mode 100644 index d88f3a894..000000000 --- a/httemplate/elements/tr-select-cust_tag.html +++ /dev/null @@ -1,46 +0,0 @@ -% if ( $curuser->access_right('Edit customer tags') && @part_tag ) { - - <TR> - <TD ALIGN="right"><% $opt{'label'} || 'Tags' %></TD> - <TD> - <% include( '/elements/select-cust_tag.html', - 'curr_value' => \@curr_tagnum, - 'part_tag' => \@part_tag, - %opt, - ) - %> - </TD> - </TR> - -% } else { - -% foreach my $tagnum (@curr_tagnum) { - <INPUT TYPE="hidden" NAME="tagnum" VALUE="<% $tagnum %>"> -% } - -% } -<%init> - -my $curuser = $FS::CurrentUser::CurrentUser; - -my %opt = @_; -my $cgi = $opt{'cgi'}; - -my @curr_tagnum = (); -if ( $cgi->param('error') ) { - @curr_tagnum = $cgi->param('tagnum'); -} elsif ( $opt{'custnum'} ) { - @curr_tagnum = map $_->tagnum, - qsearch('cust_tag', { 'custnum' => $opt{'custnum'} } ); -} - -my $extra_sql = "WHERE disabled IS NULL OR disabled = '' "; -$extra_sql .= ' OR tagnum IN ('. join(',', @curr_tagnum). ')' if @curr_tagnum; - -my @part_tag = qsearch({ - 'table' => 'part_tag', - 'hashref' => {}, - 'extra_sql' => $extra_sql, -}); - -</%init> diff --git a/httemplate/graph/cust_bill_pkg.cgi b/httemplate/graph/cust_bill_pkg.cgi index 03e29b901..1fad5e1cd 100644 --- a/httemplate/graph/cust_bill_pkg.cgi +++ b/httemplate/graph/cust_bill_pkg.cgi @@ -19,7 +19,7 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); -my $link = "${p}search/cust_bill_pkg.cgi?nottax=1"; +my $link = "${p}search/cust_bill_pkg.cgi?nottax=1;include_comp_cust=1"; my $bottom_link = "$link;"; my $use_override = $cgi->param('use_override') ? 1 : 0; diff --git a/httemplate/images/square.png b/httemplate/images/square.png Binary files differdeleted file mode 100644 index 4998e349e..000000000 --- a/httemplate/images/square.png +++ /dev/null diff --git a/httemplate/images/square_add.png b/httemplate/images/square_add.png Binary files differdeleted file mode 100644 index d1da175fd..000000000 --- a/httemplate/images/square_add.png +++ /dev/null diff --git a/httemplate/index.html b/httemplate/index.html index 5b550dba7..c813991f9 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -2,8 +2,6 @@ <% include('/elements/header.html', 'Billing Main' ) %> -<% include('/elements/dashboard-install_welcome.html') %> - <% include('/elements/dashboard-toplist.html') %> % my $sth = dbh->prepare( diff --git a/httemplate/misc/bill.cgi b/httemplate/misc/bill.cgi index 2bc43d7b3..6151dce51 100755 --- a/httemplate/misc/bill.cgi +++ b/httemplate/misc/bill.cgi @@ -1,8 +1,38 @@ -<% $server->process %> +%if ( $error ) { +% errorpage($error); +%} else { +<% $cgi->redirect(popurl(2). "view/cust_main.cgi?$custnum") %> +%} <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Bill customer now'); -my $server = FS::UI::Web::JSRPC->new('FS::cust_main::process_bill_and_collect', $cgi); -</%init> +#untaint custnum +my($query) = $cgi->keywords; +$query =~ /^(\d*)$/; +my $custnum = $1; +my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum}); +die "Can't find customer!\n" unless $cust_main; + +my $conf = new FS::Conf; + +my $error = $cust_main->bill_and_collect( 'fatal' => 'return', + 'retry' => 'yes', + ); + + #'invoice-time'=>$time, + #'batch_card'=> 'yes', + #'batch_card'=> 'no', + #'report_badcard'=> 'yes', + #'retry_card' => 'yes', + + #this is used only by cust_main::batch_card + #need to pick & create an actual config + #value if we're going to turn this on + #("realtime-backend" doesn't exist, + # "backend-realtime" is for something + # entirely different) + #'realtime' => $conf->exists('realtime-backend'), + +</%init> diff --git a/httemplate/misc/cdr-post.cgi b/httemplate/misc/cdr-post.cgi deleted file mode 100644 index 541dac3e3..000000000 --- a/httemplate/misc/cdr-post.cgi +++ /dev/null @@ -1,58 +0,0 @@ -% if ( $error ) { -0,"<% $error %>",, -% } else { -1,"CDR import successful",<% $cdr_batch->cdrbatchnum %>,"<% $cdrbatch %>" -% } -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Import'); - -my $error = ''; -my $cdr_batch; -my $cdrbatch = ''; - -{ - - my $filename = $cgi->param('cdr_file'); - unless ( $filename ) { - $error = "No cdr_file filename"; - last; - } - - my $fh = $cgi->upload('cdr_file'); - unless ( defined($fh) ) { - $error = 'No cdr_file file'; - last; - } - - #i should probably be transactionalized. - - my $csv = new Text::CSV_XS or die Text::CSV->error_diag; - - $cdrbatch = time2str('post-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time); - $cdr_batch = new FS::cdr_batch { 'cdrbatch' => $cdrbatch }; - $error = $cdr_batch->insert and last; - - chomp(my $hline = scalar(<$fh>)); - $csv->parse($hline); - my @header = $csv->fields; - - #while ( my $row = $csv->getline($fh) ) { - while (<$fh>) { - - $csv->parse($_); - my @row = $csv->fields; - - my $cdr = new FS::cdr { 'cdrbatchnum' => $cdr_batch->cdrbatchnum }; - $cdr->set( lc($_) => shift(@row) ) foreach @header; - - $error = $cdr->insert and last; - - } - -} - -$error =~ s/"/""/g; #CSV - -</%init> diff --git a/httemplate/misc/cdr-post.html b/httemplate/misc/cdr-post.html deleted file mode 100644 index 5d34272f7..000000000 --- a/httemplate/misc/cdr-post.html +++ /dev/null @@ -1,11 +0,0 @@ -<% include("/elements/header.html",'Call Detail Record - POST Import') %> - -<FORM METHOD="POST" ACTION="cdr-post.cgi" enctype="multipart/form-data"> - - cdr_file: <INPUT TYPE="file" NAME="cdr_file"><BR><BR> - - <INPUT TYPE="submit" VALUE="upload"> - -</FORM> - -<% include("/elements/footer.html") %> diff --git a/httemplate/misc/clone-cgp_rule.html b/httemplate/misc/clone-cgp_rule.html deleted file mode 100644 index d821a2dff..000000000 --- a/httemplate/misc/clone-cgp_rule.html +++ /dev/null @@ -1,27 +0,0 @@ -% if ( $error ) { -% errorpage($error); -% } else { -<% $cgi->redirect($p. "browse/cgp_rule.html?svcnum=". $svcnum) %> -% } -<%init> - -# :/ needs agent-virt so you can't futz with arbitrary rules - -#die "access denied" -# unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); - -#untaint svcnum and clone -$cgi->param('svcnum') =~ /^(\d+)$/ || die "Illegal svcnum"; -my $svcnum = $1; -$cgi->param('clone') =~ /^(\d+)$/ || die "Illegal clone"; -my $clone = $1; - -my @cgp_rule = qsearch('cgp_rule', { 'svcnum' => $clone } ); - -my $error = ''; -foreach my $cgp_rule ( @cgp_rule ) { - $error = $cgp_rule->clone( $svcnum ); - last if $error; -} - -</%init> diff --git a/httemplate/misc/delete-cgp_rule.html b/httemplate/misc/delete-cgp_rule.html index 0415bc9dd..a2ba2dbc9 100644 --- a/httemplate/misc/delete-cgp_rule.html +++ b/httemplate/misc/delete-cgp_rule.html @@ -10,7 +10,7 @@ #die "access denied" # unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); -#untaint rulenum +#untaint devicenum my($query) = $cgi->keywords; $query =~ /^(\d+)$/ || die "Illegal rulenum"; my $rulenum = $1; diff --git a/httemplate/misc/delete-rate_detail.html b/httemplate/misc/delete-rate_detail.html deleted file mode 100755 index 30856a73a..000000000 --- a/httemplate/misc/delete-rate_detail.html +++ /dev/null @@ -1,20 +0,0 @@ -% if ( $error ) { -% errorpage($error); -% } else { -<% header('Rate deleted') %> - <SCRIPT TYPE="text/javascript"> - window.top.location.reload(); - </SCRIPT> - </BODY></HTML> -% } -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); - -my ($query) = $cgi->keywords; -$query =~ /^(\d+)$/ or die "Illegal ratedetailnum"; -my $rate_detail = FS::rate_detail->by_key($1); -my $error = $rate_detail->delete; - -</%init> diff --git a/httemplate/misc/inventory_item-import.html b/httemplate/misc/inventory_item-import.html index d264bafc5..990c14ffc 100644 --- a/httemplate/misc/inventory_item-import.html +++ b/httemplate/misc/inventory_item-import.html @@ -24,10 +24,7 @@ Import a file containing <% PL($inventory_class->classname) %>, one per line. %# <INPUT TYPE="hidden" NAME="itembatch" VALUE="<% $itembatch %>"> - <% include('/elements/tr-select-agent.html', - 'viewall_right' => 'None', - ) - %> + <% include('/elements/tr-select-agent.html') %> <% include( '/elements/file-upload.html', 'field' => 'file', diff --git a/httemplate/misc/maestro-customer_status-test.html b/httemplate/misc/maestro-customer_status-test.html deleted file mode 100644 index 006492919..000000000 --- a/httemplate/misc/maestro-customer_status-test.html +++ /dev/null @@ -1,34 +0,0 @@ -<% include('/elements/header.html', { - 'title' => "Customer $custnum status", - }) %> - -<% include('/elements/small_custview.html', $custnum, '', 1) %> -<BR> - -<table style="border:1px solid #000000"> -% foreach my $key (keys %$return) { -% my $value = $return->{$key}; -% $value = join(', ', @$value) if ref($value) eq 'ARRAY'; - <TR> - <TD ALIGN="right"><% $key %>:</TD> - <TD><B><% $value %></B></TD> - </TR> -% } -</table> - -<% include('/elements/footer.html') %> -<%init> - -my $return; - -my($custnum, $svcnum) = $cgi->keywords; -if ( $custnum =~ /^(\d+)$/ ) { - - use FS::Maestro; - $return = FS::Maestro::customer_status($1, $svcnum); - -} else { - $return = { 'error' => 'No custnum' }; -} - -</%init> diff --git a/httemplate/misc/maestro-customer_status.cgi b/httemplate/misc/maestro-customer_status.cgi deleted file mode 100644 index ffeb53c91..000000000 --- a/httemplate/misc/maestro-customer_status.cgi +++ /dev/null @@ -1,16 +0,0 @@ -<% $uri->query %> -<%init> - -my $uri = new URI; - -my($custnum, $svcnum) = $cgi->keywords; -if ( $custnum =~ /^(\d+)$/ ) { - - use FS::Maestro; - $uri->query_form( FS::Maestro::customer_status($1) ); - -} else { - $uri->query_form( { 'error' => 'No custnum' } ); -} - -</%init> diff --git a/httemplate/misc/maestro-customer_status.html b/httemplate/misc/maestro-customer_status.html deleted file mode 100644 index 8acae2b2a..000000000 --- a/httemplate/misc/maestro-customer_status.html +++ /dev/null @@ -1,16 +0,0 @@ -<% objToJson( $return ) %> -<%init> - -my $return; - -my($custnum, $svcnum) = $cgi->keywords; -if ( $custnum =~ /^(\d+)$/ ) { - - use FS::Maestro; - $return = FS::Maestro::customer_status($1, $svcnum); - -} else { - $return = { 'error' => 'No custnum' }; -} - -</%init> diff --git a/httemplate/misc/process/bill_batch-print.html b/httemplate/misc/process/bill_batch-print.html deleted file mode 100644 index 54d639eeb..000000000 --- a/httemplate/misc/process/bill_batch-print.html +++ /dev/null @@ -1,5 +0,0 @@ -% die "access denied" -% unless $FS::CurrentUser::CurrentUser->access_right('View invoices'); -% my $server = FS::UI::Web::JSRPC->new('FS::bill_batch::process_print_pdf', $cgi); -<% $server->process %> -<%init></%init> diff --git a/httemplate/misc/process/payment.cgi b/httemplate/misc/process/payment.cgi index 665001ea9..906c99663 100644 --- a/httemplate/misc/process/payment.cgi +++ b/httemplate/misc/process/payment.cgi @@ -96,10 +96,8 @@ if ( $payby eq 'CHEK' ) { $payinfo = $1; validate($payinfo) or errorpage(gettext('invalid_card')); # . ": ". $self->payinfo; - errorpage(gettext('unknown_card_type')) - if $payinfo !~ /^99\d{14}$/ #token - && cardtype($payinfo) eq "Unknown"; + if $payinfo !~ /^99\d{14}$/ && cardtype($payinfo) eq "Unknown"; if ( defined $cust_main->dbdef_table->column('paycvv') ) { if ( length($cgi->param('paycvv') ) ) { diff --git a/httemplate/misc/process/recharge_svc.html b/httemplate/misc/process/recharge_svc.html index b56f8a282..5f68bf151 100755 --- a/httemplate/misc/process/recharge_svc.html +++ b/httemplate/misc/process/recharge_svc.html @@ -62,7 +62,6 @@ unless ($error) { $error = $cust_main->charge($amount, "Recharge " . $svc_acct->label, $description, $part_pkg->taxclass); - $error ||= "invalid $_" foreach grep { $rhash{$_} !~ /^\d*$/ } keys %rhash; if ($part_pkg->option('recharge_reset', 1)) { $error ||= $svc_acct->set_usage(\%rhash, 'null' => 1); }else{ diff --git a/httemplate/misc/upload-batch.cgi b/httemplate/misc/upload-batch.cgi index be80b1ff7..d1a84fd02 100644 --- a/httemplate/misc/upload-batch.cgi +++ b/httemplate/misc/upload-batch.cgi @@ -1,10 +1,36 @@ -<% $server->process %> +% if ( $error ) { +% errorpage($error); +% } else { + <% include('/elements/header.html','Batch results upload successful') %> + <% include('/elements/footer.html') %> +% } <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Process batches'); -my $server = - new FS::UI::Web::JSRPC 'FS::pay_batch::process_import_results', $cgi; +my $error; + +my $fh = $cgi->upload('batch_results'); +$error = 'No file uploaded' unless defined($fh); + +unless ( $error ) { + + $cgi->param('batchnum') =~ /^(\d+)$/; + my $batchnum = $1; + + my $pay_batch = qsearchs( 'pay_batch', { 'batchnum' => $batchnum } ); + if ( ! $pay_batch ) { + $error = "batchnum $batchnum not found"; + } elsif ( $pay_batch->status ne 'I' ) { + $error = "batch $batchnum is not in transit"; + } else { + $error = $pay_batch->import_results( + 'filehandle' => $fh, + 'format' => $cgi->param('format'), + ); + } + +} </%init> diff --git a/httemplate/misc/xmlrpc.cgi b/httemplate/misc/xmlrpc.cgi index 14bf9ef92..1d0383f2a 100644 --- a/httemplate/misc/xmlrpc.cgi +++ b/httemplate/misc/xmlrpc.cgi @@ -1,16 +1,18 @@ -<% $response_xml %>\ -<%init> +% +% +% my $request_xml = $cgi->param('POSTDATA'); +% +% #$r->log_error($request_xml); +% +% my $fsxmlrpc = new FS::XMLRPC; +% my ($error, $response_xml) = $fsxmlrpc->serve($request_xml); +% +% #$r->log_error($error) if $error; +% +% http_header('Content-Type' => 'text/xml', +% 'Content-Length' => length($response_xml)); +% +% print $response_xml; +% +% -my $request_xml = $cgi->param('POSTDATA'); - -#warn $request_xml; - -my $fsxmlrpc = new FS::XMLRPC; -my ($error, $response_xml) = $fsxmlrpc->serve($request_xml); - -#warn $error; - -http_header('Content-Type' => 'text/xml', - 'Content-Length' => length($response_xml)); - -</%init> diff --git a/httemplate/pref/pref-process.html b/httemplate/pref/pref-process.html index a340b7fc9..47f80afd0 100644 --- a/httemplate/pref/pref-process.html +++ b/httemplate/pref/pref-process.html @@ -7,11 +7,6 @@ % } <%init> -if ( FS::Conf->new->exists('disable_acl_changes') ) { - errorpage("Preference changes disabled in public demo"); - die "shouldn't be reached"; -} - my $error = ''; my $access_user = ''; diff --git a/httemplate/search/477.html b/httemplate/search/477.html index 63eab7ac8..bd7fb2d8b 100755 --- a/httemplate/search/477.html +++ b/httemplate/search/477.html @@ -43,7 +43,7 @@ % if ( $part eq 'IA' ) { % for ( my $tech = 0; $tech < scalar(@technology_option); $tech++ ) { % next unless $technology_option[$tech]; -% my $url = &{$url_mangler}($part); +% my $url = &{$url_mangler}($cgi->self_url, $part); % if ( $type eq 'xml' ) { <<% 'Part_IA_'. chr(65 + $tech) %>> % } @@ -57,7 +57,7 @@ % if ( $type eq 'xml' ) { <<% 'Part_'. uc($part) %>> % } -% my $url = &{$url_mangler}($part); +% my $url = &{$url_mangler}($cgi->self_url, $part); <% include( "477part${part}.html", 'url' => $url ) %> % if ( $type eq 'xml' ) { </<% 'Part_'. uc($part) %>> @@ -83,8 +83,7 @@ my $type = $cgi->param('_type') || 'html'; my $xlsname = '477report'; my @technology_option = &FS::Report::FCC_477::parse_technology_option($cgi); my $url_mangler = sub { - my $part = shift; - my $url = $cgi->url('-path_info' => 1, '-full' => 1); + my ($url, $part) = (shift, shift); $url =~ s/477\./477part$part./; $url; }; diff --git a/httemplate/search/477partV.html b/httemplate/search/477partV.html index 885294d28..c6ceac4db 100755 --- a/httemplate/search/477partV.html +++ b/httemplate/search/477partV.html @@ -9,7 +9,7 @@ 'xml_elements' => [ 'zip codes' ], 'no_field_elements' => 1, 'fields' => [ 'zip' ], - 'url' => $opt{url} || '', + 'url' => $opt{url} || $cgi->self_url, ) %> diff --git a/httemplate/search/477partVI.html b/httemplate/search/477partVI.html index db572bcde..dbd17032c 100755 --- a/httemplate/search/477partVI.html +++ b/httemplate/search/477partVI.html @@ -47,7 +47,7 @@ [ $link, $link_suffix ], [ $link, $link_suffix ], ], - 'url' => $opt{url} || '', + 'url' => $opt{url} || $cgi->self_url, 'xml_row_element' => 'Datarow', ) %> diff --git a/httemplate/search/bill_batch.cgi b/httemplate/search/bill_batch.cgi deleted file mode 100755 index e5abc8955..000000000 --- a/httemplate/search/bill_batch.cgi +++ /dev/null @@ -1,65 +0,0 @@ -<% include( 'elements/search.html', - 'title' => 'Invoice Batches', - 'name_singular' => 'batch', - 'query' => { 'table' => 'bill_batch', - 'hashref' => $hashref, - 'extra_sql' => $extra_sql. - 'ORDER BY batchnum DESC', - }, - 'count_query' => "$count_query $extra_sql", - 'header' => [ 'Batch', - 'Item Count', - 'Status', - '', - ], - 'align' => 'rrcc', - 'fields' => [ 'batchnum', - sub { - my $st = "SELECT COUNT(*) from cust_bill_batch WHERE batchnum=" . shift->batchnum; - my $sth = dbh->prepare($st) - or die dbh->errstr. "doing $st"; - $sth->execute - or die "Error executing \"$st\": ". $sth->errstr; - $sth->fetchrow_arrayref->[0]; - }, - sub { - $statusmap{shift->status}; - }, - sub { shift->status eq 'O' ? - 'Download and close' : 'Download' - }, - ], - 'links' => [ - $link, - $link, - $link, - $dlink, - ], - 'style' => [ - '', - '', - '', - sub { shift->status eq 'O' ? "b" : '' }, - ], - 'really_disable_download' => 1, - ) - -%> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('View invoices'); - -my %statusmap = ('O'=>'Open', 'R'=>'Closed'); -my $hashref = {}; -my $count_query = 'SELECT COUNT(*) FROM bill_batch'; - -my $extra_sql = ''; # may add something here later -my $link = [ "${p}view/bill_batch.cgi?batchnum=", 'batchnum' ]; -my $dlink = sub { - [ "${p}view/bill_batch.cgi?magic=print;". - (shift->status eq 'O' ? 'close=1;' : ''). - 'batchnum=', - 'batchnum'] -}; -</%init> diff --git a/httemplate/search/cdr.html b/httemplate/search/cdr.html index a5575967c..6b38d3ba7 100644 --- a/httemplate/search/cdr.html +++ b/httemplate/search/cdr.html @@ -126,7 +126,7 @@ foreach my $param ( grep /^termpart\d+status$/, $cgi->param ) { $search = "NOT EXISTS ( SELECT 1 FROM cdr_termination WHERE $where_term )"; - } elsif ( $status =~ /^([\w ]+)$/ ) { + } elsif ( $cgi->param('freesidestatus') =~ /^([\w ]+)$/ ) { #false lazienss w/cdr_termination.pm (i should be a part_termination method) my $where_term = diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi index 98a1da9d9..77901de87 100644 --- a/httemplate/search/cust_bill_pkg.cgi +++ b/httemplate/search/cust_bill_pkg.cgi @@ -139,6 +139,9 @@ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); push @where, "_date >= $beginning", "_date <= $ending"; +push @where , " payby != 'COMP' " + unless $cgi->param('include_comp_cust'); + if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { push @where, "cust_main.agentnum = $1"; } diff --git a/httemplate/search/cust_credit_bill_pkg.html b/httemplate/search/cust_credit_bill_pkg.html index 0f7834446..52e0ac6fe 100644 --- a/httemplate/search/cust_credit_bill_pkg.html +++ b/httemplate/search/cust_credit_bill_pkg.html @@ -92,6 +92,9 @@ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); push @where, "cust_bill._date >= $beginning", "cust_bill._date <= $ending"; +push @where , " payby != 'COMP' " + unless $cgi->param('include_comp_cust'); + if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { push @where, "cust_main.agentnum = $1"; } diff --git a/httemplate/search/cust_pay_batch.cgi b/httemplate/search/cust_pay_batch.cgi index 825d21c8a..7376e9dcb 100755 --- a/httemplate/search/cust_pay_batch.cgi +++ b/httemplate/search/cust_pay_batch.cgi @@ -124,7 +124,7 @@ $sql_query = "SELECT paybatchnum,invnum,custnum,cpb.last,cpb.first," . 'LEFT JOIN pay_batch USING ( batchnum ) ' . "$search ORDER BY $orderby"; -my $html_init = '<TABLE>'; +my $html_init = ''; if ( $pay_batch ) { my $fixed = $conf->config('batch-fixed_format-'. $pay_batch->payby); if ( @@ -136,12 +136,11 @@ if ( $pay_batch ) { && $FS::CurrentUser::CurrentUser->access_right('Redownload resolved batches') ) ) { - $html_init .= qq!<TR><FORM ACTION="$p/misc/download-batch.cgi" METHOD="POST">!; + $html_init .= qq!<FORM ACTION="$p/misc/download-batch.cgi" METHOD="POST">!; if ( $fixed ) { $html_init .= qq!<INPUT TYPE="hidden" NAME="format" VALUE="$fixed">!; } else { - $html_init .= qq!Download batch in format !. - qq!<SELECT NAME="format">!. + $html_init .= qq!Download batch in format <SELECT NAME="format">!. qq!<OPTION VALUE="">Default batch mode</OPTION>!. qq!<OPTION VALUE="csv-td_canada_trust-merchant_pc_batch">CSV file for TD Canada Trust Merchant PC Batch</OPTION>!. qq!<OPTION VALUE="csv-chase_canada-E-xactBatch">CSV file for Chase Canada E-xactBatch</OPTION>!. @@ -152,7 +151,7 @@ if ( $pay_batch ) { qq!<OPTION VALUE="RBC">Royal Bank of Canada PDS</OPTION>!. qq!</SELECT>!; } - $html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum"><INPUT TYPE="submit" VALUE="Download"></FORM><BR><BR></TR>!; + $html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum"><INPUT TYPE="submit" VALUE="Download"></FORM><BR>!; } if ( @@ -161,28 +160,13 @@ if ( $pay_batch ) { && $FS::CurrentUser::CurrentUser->access_right('Reprocess batches') ) ) { - $html_init .= '<TR>'. - include('/elements/form-file_upload.html', - 'name' => 'FileUpload', - 'action' => "$p/misc/upload-batch.cgi", - 'num_files' => 1, - 'fields' => [ 'batchnum', 'format' ], - 'message' => 'Batch results uploaded.', - ) . - 'Upload results<BR></TR><TR>'. - include('/elements/file-upload.html', - 'field' => 'file', - 'label' => 'Filename', - 'no_table'=> 1 - ). - '<BR></TR>' - ; + $html_init .= qq!<FORM ACTION="$p/misc/upload-batch.cgi" METHOD="POST" ENCTYPE="multipart/form-data">!. + qq!Upload results<BR>!. + qq!Filename <INPUT TYPE="file" NAME="batch_results"><BR>!; if ( $fixed ) { $html_init .= qq!<INPUT TYPE="hidden" NAME="format" VALUE="$fixed">!; } else { - # should pull this from %import_info - $html_init .= qq!<TR>Format !. - qq!<SELECT NAME="format">!. + $html_init .= qq!Format <SELECT NAME="format">!. qq!<OPTION VALUE="">Default batch mode</OPTION>!. qq!<OPTION VALUE="csv-td_canada_trust-merchant_pc_batch">CSV results from TD Canada Trust Merchant PC Batch</OPTION>!. qq!<OPTION VALUE="csv-chase_canada-E-xactBatch">CSV file for Chase Canada E-xactBatch</OPTION>!. @@ -191,12 +175,12 @@ if ( $pay_batch ) { qq!<OPTION VALUE="ach-spiritone">Spiritone ACH batch</OPTION>!. qq!<OPTION VALUE="paymentech">Chase Paymentech XML</OPTION>!. qq!<OPTION VALUE="RBC">Royal Bank of Canada PDS</OPTION>!. - qq!</SELECT><BR></TR>!; + qq!</SELECT><BR>!; } $html_init .= qq!<INPUT TYPE="hidden" NAME="batchnum" VALUE="$batchnum">!; - $html_init .= '<TR> <INPUT TYPE="submit" VALUE="Upload"></FORM><BR> </TR>'; + $html_init .= '<INPUT TYPE="submit" VALUE="Upload"></FORM><BR>'; } - $html_init .= '</TABLE>' + } if ($pay_batch) { diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi index 74a3a6d1e..adbec7a74 100755 --- a/httemplate/search/cust_pkg.cgi +++ b/httemplate/search/cust_pkg.cgi @@ -80,18 +80,6 @@ # '</table>'; # }, sub { - my $cust_pkg = shift; - my $type = $cgi->param('_type') || ''; - if ($type =~ /xls|csv/) { - my $cust_svc = $cust_pkg->primary_cust_svc; - if($cust_svc) { - return join ": ",($cust_svc->label)[0,1]; - } - else { - return ''; - } - } - else { [ map { [ { 'data' => $_->[0]. ':', @@ -103,10 +91,9 @@ $_->[2]. '.cgi?'. $_->[3], }, ]; - } $cust_pkg->labels + } shift->labels ]; - } - } + }, ], 'color' => [ '', diff --git a/httemplate/search/elements/cust_main_dayranges.html b/httemplate/search/elements/cust_main_dayranges.html index 9b8b08f47..c53e68016 100644 --- a/httemplate/search/elements/cust_main_dayranges.html +++ b/httemplate/search/elements/cust_main_dayranges.html @@ -11,7 +11,6 @@ Example: my( $start, $end ) = @_; "SQL EXPRESSION BASED ON $start AND $end"; - # where $start and $end are unix timestamps }; </%doc> @@ -146,7 +145,7 @@ unless ( $cgi->param('all_customers') ) { } push @where, - call_range_sub($range_sub, $days, 0, 'offset' => $offset, 'no_as'=>1). ' > 0'; # != 0'; + call_range_sub($range_sub, $days + $offset, 0, 'no_as'=>1). ' > 0'; # != 0'; } if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { @@ -249,25 +248,11 @@ my $money_char = $conf->config('money_char') || '$'; # ) sub call_range_sub { - my($range_sub, $startdays, $enddays, %opt) = @_; + my($range_sub, $start, $end, %opt) = @_; - my $as = $opt{'no_as'} ? '' : " AS rangecol_${startdays}_$enddays"; + my $as = $opt{'no_as'} ? '' : " AS rangecol_${start}_$end"; - my $offset = $opt{'offset'} || 0; - # Always use $offset - 1day + 1sec = the last second of that day - my $cutoff = DateTime->now->set(hour => 23, minute => 59, second => 59); - $cutoff->subtract(days => $offset); - - my $start = $cutoff->clone; - $start->subtract(days => $startdays); - - my $end = $cutoff->clone; - $end->subtract(days => $enddays); - - #warn "offset $offset (".$cutoff->epoch."), range $startdays-$enddays (".$start->epoch . '-' . ($enddays ? $end->epoch : '').")\n"; - my $sql = &{$range_sub}( $start->epoch, - $enddays ? $end->epoch : '', - $cutoff->epoch ); #%opt? + my $sql = &{$range_sub}( $start, $end, $opt{'offset'} ); #%opt? $sql = "SUM($sql)" if $opt{'sum'}; diff --git a/httemplate/search/elements/search-html.html b/httemplate/search/elements/search-html.html index 98f9c4476..e5e6ca954 100644 --- a/httemplate/search/elements/search-html.html +++ b/httemplate/search/elements/search-html.html @@ -1,3 +1,4 @@ +% % if ( exists($opt{'redirect'}) && $opt{'redirect'} % && scalar(@$rows) == 1 && $total == 1 % && $type ne 'html-print' @@ -102,7 +103,7 @@ % $cgi->delete('maxrecords'); % $cgi->param('_dummy', 1); - ( show <SELECT NAME="maxrecords" onChange="window.location = '<% "$self_url?". $cgi->query_string %>;maxrecords=' + this.options[this.selectedIndex].value;"> + ( show <SELECT NAME="maxrecords" onChange="window.location = '<% $self_url %>;maxrecords=' + this.options[this.selectedIndex].value;"> % foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) { <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION> @@ -143,18 +144,18 @@ Download full results<BR> % $cgi->param('_type', "$xlsname.xls" ); - as <A HREF="<% "$self_url?". $cgi->query_string %>">Excel spreadsheet</A><BR> + as <A HREF="<% $self_url %>">Excel spreadsheet</A><BR> % $cgi->param('_type', 'csv'); - as <A HREF="<% "$self_url?". $cgi->query_string %>">CSV file</A><BR> + as <A HREF="<% $self_url %>">CSV file</A><BR> % if ( defined($opt{xml_elements}) ) { % $cgi->param('_type', 'xml'); - as <A HREF="<% "$self_url?". $cgi->query_string %>">XML file</A><BR> + as <A HREF="<% $self_url %>">XML file</A><BR> % } % $cgi->param('_type', 'html-print'); - as <A HREF="<% "$self_url?". $cgi->query_string %>">printable copy</A> + as <A HREF="<% $self_url %>">printable copy</A> </TD> % $cgi->param('_type', "html" ); @@ -464,7 +465,7 @@ my $confmax = $args{'confmax'}; my $maxrecords = $args{'maxrecords'}; my $offset = $args{'offset'}; my %opt = %{ $args{'opt'} }; -my $self_url = $opt{'url'} || $cgi->url('-path_info' => 1, '-full' =>1); +my $self_url = $opt{'url'} || $cgi->self_url; my $count_sth = dbh->prepare($opt{'count_query'}) or die "Error preparing $opt{'count_query'}: ". dbh->errstr; diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html index 218816938..a258f1721 100644 --- a/httemplate/search/elements/search.html +++ b/httemplate/search/elements/search.html @@ -335,7 +335,7 @@ if ( $opt{'disableable'} ) { my $limit = ''; my($confmax, $maxrecords, $offset ); -unless ( $type =~ /^(csv|\w*.xls)$/) { +if ( !$type =~ /^(csv|\w*.xls)$/) { # html mode unless (exists($opt{count_query}) && length($opt{count_query})) { ( $opt{count_query} = $opt{query} ) =~ diff --git a/httemplate/search/h_inventory_item.html b/httemplate/search/h_inventory_item.html deleted file mode 100644 index b0f9b8aa8..000000000 --- a/httemplate/search/h_inventory_item.html +++ /dev/null @@ -1,135 +0,0 @@ -<% include('/elements/header.html', "$classname Inventory Activity Report") %> -<% include('/elements/table-grid.html') %> - <TR> -% my $TH = 'TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=1'; - <<%$TH%> WIDTH="10%" ALIGN="left">Day (<% time2str("%B %Y", $sdate) %>)</TH> -% foreach my $day (0..$numdays-1) { - <<%$TH%> WIDTH="2%" ALIGN="right"><% $day+1 %></TH> -% } - </TR> -% for (my $r=0; $r < scalar(@rows); $r++) { - <TR> -% my $TD = 'TD CLASS="grid" BGCOLOR="'.($r % 2 ? '#ffffff' : '#eeeeee').'"'; - <<%$TD%>><% $labels[$r] %></TD> -% for my $day (0..$numdays-1) { - <<%$TD%> ALIGN="right"><% $rows[$r][$day] %></TD> -% } - </TR> -% } -</TABLE> - -<%init> -use Date::Parse 'str2time'; -use Date::Format 'time2str'; -use Data::Dumper 'Dumper'; - -my ($agentnum, $classnum, $month, $year, $sdate, $edate); -$classnum = $cgi->param('classnum'); # may be empty -$agentnum = $cgi->param('agentnum'); # may also be empty -my $classname = ''; -if($classnum) { - my $class = qsearchs('inventory_class', { classnum => $classnum }); - die "classnum $classnum not found!" if !$class; - $classname = $class->classname . ' '; -} - -$month = $cgi->param('_month') || time2str('%m', time); -$year = $cgi->param('_year') || time2str('%Y', time); - -$sdate = str2time("$year-$month-01"); -$edate = str2time($year + ($month == 12 ? 1 : 0) . - '-' . - (($month + 1) % 12 || 12) . - '-01'); -my $numdays = sprintf("%.0f",($edate-$sdate)/86400); -my @days = (0..$numdays - 1); -# Initialize each row with zeroes. -my @labels = ( - 'Opening Balance', - 'Quantity Received', - 'Quantity Sold', - 'Quantity Returned', -); - -if($agentnum) { - push @labels, 'Transfer In', 'Transfer Out'; -} -push @labels, 'Closing Balance'; - -my %agent = ('agentnum' => $agentnum) if $agentnum; -my %class = ('classnum' => $classnum) if $classnum; - -my @rows = ( map {[ (0) x $numdays ]} @labels); -my $opening_balance = scalar( - qsearch('h_inventory_item', - { 'svcnum' => '', - %agent, - %class }, - FS::h_inventory_item->sql_h_search($sdate) ) - ) || 0; - -foreach my $day (0..$numdays-1) { - $rows[0][$day] = ($day == 0) ? - $opening_balance : - $rows[-1][$day-1]; - - my %history; - foreach my $action (qw(insert replace_new replace_old)) { - $history{$action} = [ - qsearch({ - 'table' => 'h_inventory_item', - 'hashref' => { 'history_action' => $action, - %class }, - 'order_by' => 'ORDER BY itemnum, history_date', - 'extra_sql' => - ' AND history_date >= '.($sdate + 86400*$day). - ' AND history_date < ' .($sdate + 86400*($day+1)), - } ) - ]; - } - # Incoming items: simple, just count the inserts - $rows[1][$day] = scalar(grep {!$agentnum or $_->agentnum == $agentnum} - @{ $history{'insert'} }); - - # Other item changes: trickier. - # Notice the order_by parameter above. - # Both lists are sorted by itemnum, then by date, so unless some villain has - # been rapidly replacing the same record several times per second, the - # replace_old and replace_new from the same operation will be in the same - # position. - while(my $h_new = shift @{ $history{'replace_new'} }) { - my $h_old = shift @{ $history{'replace_old'} }; - die "history error" if !defined($h_old) - or $h_old->itemnum != $h_new->itemnum; - if(!$agentnum or $h_new->agentnum == $agentnum) { - if(!$h_old->svcnum and $h_new->svcnum) { - # item was put into service. - $rows[2][$day]++; - } - elsif($h_old->svcnum and !$h_new->svcnum) { - # item was taken out of service. - $rows[3][$day]++; - } - } - if($agentnum and $h_old->agentnum != $agentnum and $h_new->agentnum == $agentnum) { - # item was transferred from another agent - $rows[4][$day]++; - } - elsif($agentnum and $h_old->agentnum == $agentnum and $h_new->agentnum != $agentnum) { - # item was transferred to another agent - $rows[5][$day]++; - } - # Add other cases here. - } - # Closing balance - $rows[-1][$day] = $rows[0][$day] - + $rows[1][$day] - - $rows[2][$day] - + $rows[3][$day]; - if($agentnum) { - $rows[-1][$day] += $rows[4][$day] - $rows[5][$day]; - } -} - -</%init> - diff --git a/httemplate/search/report_h_inventory_item.html b/httemplate/search/report_h_inventory_item.html deleted file mode 100644 index d0b3667c8..000000000 --- a/httemplate/search/report_h_inventory_item.html +++ /dev/null @@ -1,26 +0,0 @@ -<% include('/elements/header.html', 'Inventory Activity Report') %> - -<FORM ACTION="h_inventory_item.html" METHOD="GET"> -<TABLE BGCOLOR="#cccccc" CELLSPACING="0"> - <TR> - <TD ALIGN="right">Inventory class: </TD> - <TD><% include('/elements/select-table.html', - 'element_name' => 'classnum', - 'table' => 'inventory_class', - 'name_col' => 'classname', - 'value' => '', - 'empty_label' => '(all)') %></TD> - </TR> - <TR> - <TD ALIGN="right">Time period: </TD> - <TD><% include('/elements/select-month_year.html') %></TD> - </TR> - <% include('/elements/tr-select-agent.html') %> -</TABLE> - -<BR> -<INPUT TYPE="submit" VALUE="Get Report"> -</FORM> - -<%init> -</%init> diff --git a/httemplate/search/report_newtax.html b/httemplate/search/report_newtax.html index 739652675..2588b48d3 100755 --- a/httemplate/search/report_newtax.html +++ b/httemplate/search/report_newtax.html @@ -1,6 +1,6 @@ <% include('/elements/header.html', 'Tax Report' ) %> -<FORM NAME="newtax"> +<FORM ACTION="report_queued_newtax.cgi" METHOD="GET"> <TABLE> @@ -10,17 +10,10 @@ </TABLE> -<BR><INPUT TYPE="button" NAME='fetch' VALUE="Get Report" onClick="document.newtax.fetch.disabled=true; process();"> +<BR><INPUT TYPE="submit" VALUE="Get Report"> </FORM> -<% include( '/elements/progress-init.html', - 'newtax', - [ qw( agentnum beginning ending ) ], - 'report_queued_newtax.cgi', - ) -%> - <% include('/elements/footer.html') %> <%init> diff --git a/httemplate/search/report_prepaid_income.cgi b/httemplate/search/report_prepaid_income.cgi index 2fe5b6f10..bfb699b54 100644 --- a/httemplate/search/report_prepaid_income.cgi +++ b/httemplate/search/report_prepaid_income.cgi @@ -108,6 +108,10 @@ my @where = (); #here is the agent virtualization push @where, $curuser->agentnums_sql( 'table'=>'cust_main' ); +#well, because cust_bill_pkg.cgi has it and without it the numbers don't match.. +push @where , " payby != 'COMP' " + unless $cgi->param('include_comp_cust'); + my %total = (); my %total_legacy = (); foreach my $agentnum (@agentnums) { diff --git a/httemplate/search/report_queued_newtax.cgi b/httemplate/search/report_queued_newtax.cgi index a375fce62..1d5813ece 100755 --- a/httemplate/search/report_queued_newtax.cgi +++ b/httemplate/search/report_queued_newtax.cgi @@ -1,10 +1,16 @@ -<% $server->process %> +<% include("/elements/header.html", "Queue Tax Report") %> +<% include("/elements/error.html") %> +% unless ($error) { + <CENTER> + Report queued. Check the job queue for status. + </CENTER> +% } +<% include("/elements/footer.html") %> <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); -my $server = - new FS::UI::Web::JSRPC 'FS::tax_rate::queue_liability_report', $cgi; +my $error = FS::tax_rate::queue_liability_report($cgi); </%init> diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index 57228a501..3696ed40d 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -29,12 +29,24 @@ die "access denied" # ) sub balance { - my($start, $end, $cutoff) = @_; #, %opt ? + my($start, $end, $offset) = @_; #, %opt ? + #handle start and end ranges (86400 = 24h * 60m * 60s) + my $str2time = str2time_sql; + my $closing = str2time_sql_closing; + + # $end == 0 means "+infinity", while $start == 0 really means 0 + # so we should always include a start condition + $start = "( $str2time now() $closing - ". ($start + $offset) * 86400 . ' )'; + # but only include an end condition if $end != 0 + $end = $end ? + "( $str2time now() $closing - ". ($end + $offset) * 86400 . ' )' + : ''; + + #$opt{'unapplied_date'} = 1; + + FS::cust_main->balance_date_sql( $start, $end, 'unapplied_date'=>1, + 'cutoff' => "( $str2time now() $closing - ".$offset * 86400 . ')' ); - FS::cust_main->balance_date_sql( $start, $end, - 'cutoff' => $cutoff, - 'unapplied_date'=>1, - ); } </%once> diff --git a/httemplate/search/report_rt_transaction.html b/httemplate/search/report_rt_transaction.html index 61445bd1e..9b7b7cbbb 100644 --- a/httemplate/search/report_rt_transaction.html +++ b/httemplate/search/report_rt_transaction.html @@ -8,24 +8,6 @@ <% include ( '/elements/tr-select-otaker.html' ) %> - <% include ( '/elements/tr-input-text.html', - 'label' => 'Ticket #', - 'field' => 'ticketid', - ) - %> - - <TR> - <TD>Account</TD> - <TD> - <SELECT NAME="svcnum"> - <OPTION VALUE="">(all) -% foreach my $svc_acct (@svc_acct) { - <OPTION VALUE="<% $svc_acct->svcnum %>"><% $svc_acct->username %></OPTION> -% } - </SELECT> - </TD> - </TR> - </TABLE> <BR> @@ -39,18 +21,4 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List rating data'); -my $conf = new FS::Conf; - -my @pkgparts = $conf->config('support_packages'); - -my @svc_acct = (); -if ( @pkgparts ) { - @svc_acct = qsearch({ - 'table' => 'svc_acct', - 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '. - ' LEFT JOIN cust_pkg USING ( pkgnum ) ', - 'extra_sql' => 'WHERE pkgpart IN ('. join(',', @pkgparts). ')', - }); -} - </%init> diff --git a/httemplate/search/rt_transaction.html b/httemplate/search/rt_transaction.html index 8dda4baea..651f2896d 100644 --- a/httemplate/search/rt_transaction.html +++ b/httemplate/search/rt_transaction.html @@ -3,12 +3,11 @@ 'name_singular' => 'transaction', 'query' => $query, 'count_query' => $count_query, - 'count_addl' => [ $format_seconds_sub, $format_seconds_sub, ], + 'count_addl' => [ $format_seconds_sub, ], 'header' => [ 'Ticket #', 'Ticket', 'Date', 'Time', - 'Applied', ], 'fields' => [ 'ticketid', sub { encode_entities(shift->get('subject')) }, @@ -16,16 +15,12 @@ sub { my $seconds = shift->get('transaction_time'); &{ $format_seconds_sub }( $seconds ); }, - sub { my $seconds = shift->get('support'); - &{ $format_seconds_sub }( $seconds ); - }, ], 'links' => [ $link, $link, '', '', - '', ], ) %> @@ -33,9 +28,7 @@ my $format_seconds_sub = sub { my $seconds = shift; - #(($seconds < 0) ? '-' : '') . concise(duration($seconds)); - (($seconds < 0) ? '-' : '' ). int(abs($seconds)/3600)."h".sprintf("%02d",(abs( -$seconds)%3600)/60)."m"; + (($seconds < 0) ? '-' : '') . concise(duration($seconds)); }; </%once> @@ -54,9 +47,8 @@ my $transactiontime = " "; my $join = 'JOIN Tickets ON Transactions.ObjectId = Tickets.Id '. - 'JOIN Users ON Transactions.Creator = Users.Id '. - 'LEFT JOIN acct_rt_transaction '. - ' ON Transactions.Id = acct_rt_transaction.transaction_id'; + 'JOIN Users ON Transactions.Creator = Users.Id '; + my $where = " WHERE objecttype='RT::Ticket' AND ( ( Transactions.Type = 'Set' @@ -85,26 +77,20 @@ if ( $cgi->param('otaker') && $cgi->param('otaker') =~ /^([\w\.\-]+)$/ ) { $where .= " AND Users.name = '$1' "; } -if ( $cgi->param('ticketid') =~ /^\s*(\d+)\s*$/ ) { - $where .= " AND Tickets.ID = $1"; -} - -if ( $cgi->param('svcnum') =~ /^\s*(\d+)\s*$/ ) { - $where .= " AND acct_rt_transaction.svcnum = $1"; -} - my $query = { - 'select' => "Transactions.*, Tickets.Id AS ticketid, Tickets.Subject, Users.name as otaker, $transactiontime AS transaction_time, acct_rt_transaction.support", + 'select' => "Transactions.*, Tickets.Id AS ticketid, Tickets.Subject, Users.name as otaker, $transactiontime AS transaction_time", #'table' => 'Transactions', 'table' => 'transactions', - 'addl_from' => $join, + 'addl_from' => $join. + 'LEFT JOIN acct_rt_transaction '. + ' ON Transactions.Id = acct_rt_transaction.transaction_id', 'extra_sql' => $where, 'order by' => 'ORDER BY Created', }; my $count_query = - "SELECT COUNT(*), SUM($transactiontime), SUM(acct_rt_transaction.support) FROM Transactions $join $where"; + "SELECT COUNT(*), SUM($transactiontime) FROM Transactions $join $where"; -my $link = [ "${p}rt/Ticket/Display.html?id=", sub { shift->get('ticketid'); } ]; +my $link = [ "${p}rt/Ticket/Display.html?id=", sub { shift->get('id'); } ]; </%init> diff --git a/httemplate/search/sql.html b/httemplate/search/sql.html index bf5446975..df9b8cddb 100644 --- a/httemplate/search/sql.html +++ b/httemplate/search/sql.html @@ -1,15 +1,13 @@ <% include( 'elements/search.html', 'title' => 'Query Results', 'name' => 'rows', - 'query' => "SELECT $sql", - ) + 'query' => 'SELECT '. ( $cgi->param('sql') + || errorpage('Empty query') ), + ) %> <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Raw SQL'); -my $sql = $cgi->param('sql') or errorpage('Empty query'); -$sql =~ s/;+\s*$//; #remove trailing ; - </%init> diff --git a/httemplate/search/unapplied_cust_pay.html b/httemplate/search/unapplied_cust_pay.html index e232291fe..73361c00b 100755 --- a/httemplate/search/unapplied_cust_pay.html +++ b/httemplate/search/unapplied_cust_pay.html @@ -13,11 +13,18 @@ die "access denied" <%once> sub unapplied_payments { - my($start, $end, $cutoff) = @_; + my($start, $end, $offset) = @_; + + #handle start and end ranges (86400 = 24h * 60m * 60s) + my $str2time = str2time_sql; + my $closing = str2time_sql_closing; + $start = "( $str2time now() $closing - ".($start + $offset) * 86400 . ' )'; + $end = $end ? + "( $str2time now() $closing - ".($end + $offset) * 86400 . ' )' + : ''; + + FS::cust_main->unapplied_payments_date_sql( $start, $end ); - FS::cust_main->unapplied_payments_date_sql( $start, $end, - 'cutoff' => $cutoff, - ); } </%once> diff --git a/httemplate/view/bill_batch.cgi b/httemplate/view/bill_batch.cgi deleted file mode 100644 index 3fca6ebbe..000000000 --- a/httemplate/view/bill_batch.cgi +++ /dev/null @@ -1,99 +0,0 @@ -% if($magic eq 'print') { -<% include('/elements/header.html', "Download Batch") %> -<FORM NAME="OneTrueForm"> -<INPUT TYPE="hidden" NAME="batchnum" VALUE="<% $batchnum %>"> -% $cgi->delete('magic'); -<% include('/elements/progress-init.html', - 'OneTrueForm', - [ 'batchnum' ], - $p.'misc/process/bill_batch-print.html', - {'url' => $cgi->self_url . ';magic=download'}, - '', -) %></FORM> -<SCRIPT TYPE="text/javascript">process();</SCRIPT> -<% include('/elements/footer.html') %> -% } -% -% elsif($magic eq 'download') { -% $m->clear_buffer; -% $r->content_type('application/pdf'); -% $r->headers_out->add('Content-Disposition' => 'attachment;filename="invoice_batch_'.$batchnum.'.pdf"'); -<% $batch->pdf %> -% $batch->pdf(''); -% my $error = $batch->replace; -% warn "error deleting cached PDF: '$error'\n" if $error; -% } -% else { -<% include('/search/elements/search.html', - 'title' => $close ? - "Batch $batchnum closed." : - "Invoice Batch $batchnum", - 'name' => 'invoices', - 'query' => { 'table' => 'cust_bill_batch', - 'select' => join(', ', - 'cust_bill.*', - FS::UI::Web::cust_sql_fields(), - 'cust_main.custnum AS cust_main_custnum', - ), - 'hashref' => { }, - 'addl_from' => - 'LEFT JOIN cust_bill USING ( invnum ) '. - 'LEFT JOIN cust_main USING ( custnum )', - 'extra_sql' => '', - " WHERE batchnum = $batchnum", - }, - 'count_query' => "SELECT COUNT(*) FROM cust_bill_batch WHERE batchnum = $batchnum", - 'html_init' => $html_init, - 'header' => [ 'Invoice #', - 'Amount', - 'Date', - 'Customer', - ], - 'fields' => [ sub { shift->cust_bill->display_invnum }, - sub { sprintf($money_char.'%.2f', - shift->cust_bill->charged ) }, - sub { time2str('%b %d %Y', - shift->cust_bill->_date ) }, - sub { shift->cust_bill->cust_main->name }, - ], - 'align' => 'rrll', - 'links' => [ ($link) x 3, $clink, - ], - 'really_disable_download' => 1, -) %> -% } -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('View invoices'); - -my $conf = new FS::Conf; -my $batch; -my $batchnum = $cgi->param('batchnum'); - -$batch = FS::bill_batch->by_key($batchnum); -die "Batch '$batchnum' not found!\n" if !$batch; - -my $magic = $cgi->param('magic'); -my $html_init = ''; - -my $close = $cgi->param('close'); -$batch->close if $close; - -if(!$magic) { - $cgi->param('magic' => 'print'); - $cgi->delete('close'); - $html_init = '<A HREF="'.$cgi->self_url.'">Download this batch</A><BR>'; - if($batch->status eq 'O') { - $cgi->param('close' => 1); - $cgi->delete('magic'); - $html_init .= '<A HREF="'.$cgi->self_url.'">Close this batch</A><BR>'; - } - $html_init .= '<BR>'; -} - -my $link = [ "$p/view/cust_bill.cgi?", 'invnum' ]; -my $clink = [ "$p/view/cust_main.cgi?", 'custnum' ]; -my $money_char = $conf->config('money_char') || '$'; - -</%init> diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index f6bef43ba..ca8bf5442 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -4,22 +4,6 @@ }) %> <BR> -% my @part_tag = $cust_main->part_tag; -% if ( $conf->config('cust_tag-location') eq 'top' && @part_tag ) { -<TABLE STYLE="margin-bottom:8px" CELLSPACING=2> -% foreach my $part_tag ( @part_tag ) { -<TR> - <TD> - <FONT SIZE="+1" - <% length($part_tag->tagcolor) - ? 'STYLE="background-color:#'.$part_tag->tagcolor.'"' - : '' - %>><% $part_tag->tagname.': '. $part_tag->tagdesc |h %></FONT> - </TD> -</TR> -% } -</TABLE> -% } <% include('/elements/menubar.html', { 'newstyle' => 1, @@ -29,7 +13,7 @@ %views, ) %> -<DIV CLASS="fstabcontainer"> +<BR> <% include('/elements/init_overlib.html') %> @@ -90,9 +74,6 @@ function areyousure(href, message) { This customer's signup URL: <A HREF="<% $signupurl %>?ref=<% $custnum %>"><% $signupurl %>?ref=<% $custnum %></A><BR><BR> % } -%if ( $conf->exists('maestro-status_test') ) { - <A HREF="<% $p %>misc/maestro-customer_status-test.html?<% $custnum %>">Test maestro status</A><BR><BR> -% } <A NAME="cust_main"></A> <TABLE BORDER=0> @@ -233,7 +214,6 @@ Comments <% include('cust_main/change_history.html', $cust_main ) %> % } -</DIV> <% include('/elements/footer.html') %> <%init> diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html index 54c180bdd..c8d0c47cd 100644 --- a/httemplate/view/cust_main/billing.html +++ b/httemplate/view/cust_main/billing.html @@ -5,12 +5,7 @@ Billing information %if ( $FS::CurrentUser::CurrentUser->access_right('Bill customer now') % && ! $cust_main->is_encrypted($cust_main->payinfo) % ) { -%# (<A HREF="<% $p %>misc/bill.cgi?<% $cust_main->custnum %>">Bill now</A>) - (<% include('/elements/bill.html', - custnum => $cust_main->custnum, - label => 'Bill now', - url => $p.'view/cust_main.cgi?'.$cust_main->custnum, - ) %>) + (<A HREF="<% $p %>misc/bill.cgi?<% $cust_main->custnum %>">Bill now</A>) % } <% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %> diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html index 6e90a0b4c..2cfe0263f 100644 --- a/httemplate/view/cust_main/misc.html +++ b/httemplate/view/cust_main/misc.html @@ -10,25 +10,12 @@ <TD BGCOLOR="#ffffff"><FONT COLOR="#<% $cust_main->statuscolor %>"><B><% ucfirst($cust_main->status) %></B></FONT></TD> </TR> -% my @part_tag = $cust_main->part_tag; -% if ( $conf->config('cust_tag-location') =~ /^(cust_misc|)$/ && @part_tag ) { -<TR> - <TD ALIGN="right">Tags</TD> - <TD BGCOLOR="#ffffff"> -% foreach my $part_tag ( @part_tag ) { - <FONT <% length($part_tag->tagcolor) - ? 'STYLE="background-color:#'.$part_tag->tagcolor.'"' - : '' %> - ><% $part_tag->tagname.': '. $part_tag->tagdesc |h %></FONT> - <BR> -% } - </TD> -</TR> -% } - -%unless ( scalar(@agentnums) == 1 -% && !$curuser->access_right('View customers of all agents') ) { -% my $agent = qsearchs('agent',{ 'agentnum' => $cust_main->agentnum } ); +%my $agent; +%if ( $num_agents == 1 ) { +% my @agents = qsearchs( 'agent', {} ); +% $agent = $agents[0]; +%} else { +% $agent = qsearchs('agent',{ 'agentnum' => $cust_main->agentnum } ); <TR> <TD ALIGN="right">Agent</TD> <TD BGCOLOR="#ffffff"><% $agent->agentnum %>: <% $agent->agent %></TD> @@ -132,8 +119,8 @@ my( $cust_main ) = @_; my $conf = new FS::Conf; my $date_format = ($conf->config('date_format') || "%m/%d/%Y"); -my $curuser = $FS::CurrentUser::CurrentUser; - -my @agentnums = $curuser->agentnums; +my $sth = dbh->prepare('SELECT COUNT(*) FROM agent') or die dbh->errstr; +$sth->execute or die $sth->errstr; +my $num_agents = $sth->fetchrow_arrayref->[0]; </%init> diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index 811ac3c98..3ac4861c3 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -159,8 +159,7 @@ my %conf_opt = ( #for services.html 'svc_external-skip_manual' => $conf->exists('svc_external-skip_manual'), 'legacy_link' => $conf->exists('legacy_link'), - 'svc_broadband-manage_link' => scalar($conf->config('svc_broadband-manage_link')), - 'maestro-status_test' => $conf->exists('maestro-status_test'), + 'svc_broadband-manage_link' => $conf->config('svc_broadband-manage_link'), ); #subroutines diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html index 6e30922c5..0fe7931d8 100644 --- a/httemplate/view/cust_main/packages/services.html +++ b/httemplate/view/cust_main/packages/services.html @@ -58,11 +58,6 @@ % if ( $curuser->access_right('Unprovision customer service') ) { <FONT SIZE="-2">( <%svc_unprovision_link($cust_svc)%> )</FONT> % } - -% if ( $part_svc->svcdb eq 'svc_pbx' && $opt{'maestro-status_test'} ){ - <FONT SIZE="-2">( <A HREF="<% $p %>misc/maestro-customer_status-test.html?<% $cust_pkg->custnum.'+'.$cust_svc->svcnum %>">Test maestro status</A> )</FONT> -% } - </TD> </TR> % } diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html index e90ae5276..e1f9a131e 100644 --- a/httemplate/view/cust_main/tickets.html +++ b/httemplate/view/cust_main/tickets.html @@ -1,31 +1,17 @@ -<FORM METHOD="GET" NAME="CreateTicketForm" STYLE="display:inline"> -<SCRIPT TYPE="text/javascript"> -function updateTicketLink() { - var link = document.getElementById('CreateTicketLink'); - var selector = document.getElementById('Queue') - link.href = "<% $new_base.'?'. - join(';', map( - { ($_ eq 'Queue') ? () : "$_=$new_param{$_}"} - keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value; -} -</SCRIPT> -<A id="CreateTicketLink" HREF="<% $new_link %>">Create new ticket</A> - in queue +<FORM METHOD="GET" ACTION="<% $new_base %>" NAME="CreateTicketForm"> +<INPUT TYPE="submit" VALUE="Create new ticket"> +in queue +<SELECT NAME="Queue"> % my %queues = FS::TicketSystem->queues(); -% if( $conf->exists('ticket_system-force_default_queueid') ) { -<B><% $queues{$new_param{'Queue'}} %></B> -<INPUT TYPE="hidden" NAME="Queue" VALUE="<% $new_param{'Queue'} %>"> -% } -% else { -<SELECT NAME="Queue" id="Queue" onchange="updateTicketLink()"> -% foreach my $queueid ( sort { $queues{$a} cmp $queues{$b} } keys %queues ) { +% foreach my $queueid ( keys %queues ) { % #should consider whether the user has ACL to create ticket in each queue <OPTION VALUE="<% $queueid %>" <% $queueid == $new_param{'Queue'} ? 'SELECTED' : '' %> ><% $queues{$queueid} |h %> % } </SELECT> -<SCRIPT DEFER TYPE="text/javascript">updateTicketLink();</SCRIPT> +% foreach my $param ( grep { $_ ne 'Queue' } keys %new_param ) { + <INPUT TYPE="hidden" NAME="<% $param %>" VALUE="<% $new_param{$param} |h %>"> % } </FORM> <BR> @@ -93,7 +79,6 @@ function updateTicketLink() { <%init> -my( $conf ) = new FS::Conf; my( $cust_main ) = @_; my( @tickets ) = $cust_main->tickets; diff --git a/httemplate/view/prospect_main.html b/httemplate/view/prospect_main.html index 9517e3920..9883e6766 100644 --- a/httemplate/view/prospect_main.html +++ b/httemplate/view/prospect_main.html @@ -14,8 +14,7 @@ <TD BGCOLOR="#FFFFFF"><B><% $prospectnum %></B></TD> </TR> -%unless ( scalar(@agentnums) == 1 -% && !$curuser->access_right('View customers of all agents') ) { +%unless ( scalar(@agentnums) == 1 ) { % my $agent = qsearchs('agent',{ 'agentnum' => $prospect_main->agentnum } ); <TR> <TD ALIGN="right">Agent</TD> diff --git a/httemplate/view/svc_acct/communigate.html b/httemplate/view/svc_acct/communigate.html index 0f090fdb9..9d6680750 100644 --- a/httemplate/view/svc_acct/communigate.html +++ b/httemplate/view/svc_acct/communigate.html @@ -53,45 +53,7 @@ <% include('/view/elements/tr.html', label=>'Send read receipts', value=>$svc_acct->cgp_sendmdnmode ) %> -%# vacation message -%#XXX finish me... do we need to search for specific rules -%# (and hide them?) need to see what CGP gives back after we've added a rule - <% include('/elements/init_overlib.html') %> - - <TR> - <TD ALIGN="right">Vacation message</TD> - <TD BGCOLOR="#FFFFFF"> - <% include('/elements/popup_link.html', - 'action' => $p.'edit/cgp_rule-vacation.html?'. - 'svcnum='. $svc_acct->svcnum, - 'label' => '(add)', #XXX (edit) - 'actionlabel' => 'Vacation message', - 'width' => 600, - 'height' => 300, - #'color' - ) - %> - </TD> - </TR> - -%# redirect all mail -%#XXX finish me... - - <TR> - <TD ALIGN="right">Redirect all mail</TD> - <TD BGCOLOR="#FFFFFF"> - <% include('/elements/popup_link.html', - 'action' => $p.'edit/cgp_rule-redirect_all.html?'. - 'svcnum='. $svc_acct->svcnum, - 'label' => '(add)', #XXX (edit) - 'actionlabel' => 'Redirect all mail', - 'width' => 763, - #'height' - #'color' - ) - %> - </TD> - </TR> +%#XXX vacation message, redirect all mail %# mail rules diff --git a/httemplate/view/svc_domain/acct_defaults.html b/httemplate/view/svc_domain/acct_defaults.html index 3a4e187be..b6d03e2df 100644 --- a/httemplate/view/svc_domain/acct_defaults.html +++ b/httemplate/view/svc_domain/acct_defaults.html @@ -36,7 +36,7 @@ %> <% include('/view/elements/tr.html', - label=>'Files limit', + label=>'Files limt', value=>$svc_domain->acct_def_file_maxnum, ) %> diff --git a/httemplate/view/svc_domain/dns.html b/httemplate/view/svc_domain/dns.html index 88a9bda95..f6f8c71c7 100644 --- a/httemplate/view/svc_domain/dns.html +++ b/httemplate/view/svc_domain/dns.html @@ -71,11 +71,10 @@ DNS records <FORM NAME="SlaveForm" METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi"> <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>"> - Or % if ( @records ) { - delete all records and + Delete all records and % } - slave from nameserver IP + Or slave from nameserver IP <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>"> <INPUT TYPE="hidden" NAME="reczone" VALUE="@"> <INPUT TYPE="hidden" NAME="recaf" VALUE="IN"> diff --git a/httemplate/view/svc_forward.cgi b/httemplate/view/svc_forward.cgi index 15b5ae56f..43d8a4e8b 100755 --- a/httemplate/view/svc_forward.cgi +++ b/httemplate/view/svc_forward.cgi @@ -50,9 +50,6 @@ </TABLE> <BR> - -<% include('elements/svc_export_settings.html', $svc_forward) %> - <% joblisting({'svcnum'=>$svcnum}, 1) %> <% include('/elements/footer.html') %> diff --git a/init.d/freeside-init b/init.d/freeside-init index 1acefdc41..b4609d48a 100644 --- a/init.d/freeside-init +++ b/init.d/freeside-init @@ -48,10 +48,6 @@ case "$1" in echo "done." done - echo -n "Starting freeside-selfservice-xmlrpcd: " - freeside-selfservice-xmlrpcd $SELFSERVICE_USER - echo "done." - #ip=`/sbin/ifconfig $IF | grep 'inet addr:' | cut -d: -f2- | cut -d' ' -f1` #cp /opt/rt3/etc/RT_SiteConfig.pm.ORIG /opt/rt3/etc/RT_SiteConfig.pm #perl -pi -e "s/localhost/$ip/" /opt/rt3/etc/RT_SiteConfig.pm @@ -108,12 +104,6 @@ case "$1" in fi done - if [ -e /var/run/freeside/selfservice-xmlrpcd.pid ]; then - echo -n "Stopping freeside-selfservice-xmlrpcd: " - kill `cat /var/run/freeside/selfservice-xmlrpcd.pid` - echo "done." - fi - ;; restart) diff --git a/rpm/build/BOOTSTRAP b/rpm/build/BOOTSTRAP deleted file mode 100644 index 6ddf5b54d..000000000 --- a/rpm/build/BOOTSTRAP +++ /dev/null @@ -1,146 +0,0 @@ -# its more notes than a script, so no #!/bin/sh yet - -# s/ivan/username/ in buildsysrc and below - - -### -# host dirs -### - - -cd -mkdir public_html -mkdir mock -mkdir redhat -mkdir redhat/SRPMS -mkdir buildsys -mkdir buildsys/ref -mkdir buildsys/ref/SRPMS - -cd buildsys -for a in build-freeside buildsysrc cvs-check-and-build enrpm expect-addsign expect-signrepo ovid2flute refresh-repo; do -ln -s ~/freeside/rpm/build/$a . -done - - -### -# vserver setup -### - - -#ftp://ftp.pld-linux.org/people/hawk/vserver-templates/Centos -#sudo vserver centos5 build -m template --context 5 --hostname centos5.freeside.biz --interface dummy0:10.5.4.5/24 -- -d centos5 -t centos5-i686.tar.bz2 -sudo vserver centos5 build -m template --context 5 --hostname centos5.freeside.biz --interface dummy0:10.5.4.5/24 -- -d centos5 -t centos5-x86_64.tar.bz2 - -#something like this as /etc/init.d/vserver-nat: -!/bin/sh -iptables -t nat -F -iptables -t nat -A POSTROUTING -s 10.5.4.0/24 -d ! 10.5.4.0/24 -j SNAT --to-source 192.168.1.143 - -vserver centos5 start -vserver centos5 enter -#edit /etc/resolv.conf (easier from outside, no vi inside yet) - -yum update -yum install openssh-server vim-minimal zsh screen sudo perl patch cvs diffutils rpm-build rsync - -adduser ivan #username -cd ~ivan #username -mkdir .ssh -vi .ssh/authorized_keys - -mkdir redhat -mkdir redhat/BUILD -mkdir redhat/RPMS -mkdir redhat/SOURCES -mkdir redhat/SPECS -mkdir redhat/SRPMS -chown -R ivan:ivan redhat - -vi ~/.rpmmacros -%_gpg_path /home/ivan/.gnupg -%_gpg_name Freeside Internet Services, Inc. RPM Signing Key - -vi /etc/ssh/sshd_config #ListenAddress -#also need to edit on the host so the vserver can claim its address - -vi /etc/pam.d/sshd -#comment out: -#session required pam_loginuid.so - -/etc/init.d/sshd restart - -vi /etc/sudoers - -exit #and test ssh'ing in - -### -# more... -### - -#copy the stuff from rpm/build/native into /home/ivan (#username) in the vserver -cd rpm/build/native -for a in build-from-cvs freeside-cvs makesrpm ovid2flute ovid-0.12-1.x86_64.rpm Ovid.diff; do - cp $a /var/lib/vservers/centos5/home/ivan/ -done - -for a in build-from-cvs freeside-cvs makesrpm ovid2flute; do - chmod a+rx /var/lib/vservers/centos5/home/ivan/$a -done - -vserver centos5 enter #or ssh 10.5.4.5 and sudo - -rpm -i ovid-0.12-1.x86_64.rpm -cd /usr/lib/perl5/site_perl/5.*/Ovid -patch < ~ivan/Ovid.diff - -#also checkout the necessary freeside versions... -export CVSROOT=":pserver:anonymous:anonymous@cvs.freeside.biz:/home/cvs/cvsroot" - -cvs checkout -rFREESIDE_1_7_BRANCH -d freeside-1.7 freeside -#cvs checkout -rFREESIDE_1_9_BRANCH -d freeside-1.9 freeside - -### -# yet more -### - -cp -i /var/lib/vservers/centos5/etc/yum.repos.d/CentOS-Base.repo /etc/yum/repos.d/ -#and s/$releasever/5/g; - -cp expect-* /usr/local/bin/ -#edit them and set your real passphrase for the gpg key you're using -#(as per that dir above) - -### -# and the repository -### - -cd -mkdir -p public_html/repo/centos/5/freeside-1.7/testing/x86_64/ -mkdir public_html/repo/centos/5/freeside-1.7/testing/i686 - -### -# and for enrpm! -### - -vserver centos5 enter -yum install perl-libwww-perl make -cpan -install RPM::Specfile -#if it fails, might need to go to /root/.cpan/build/RPM-Specfile-* and do it manually -install YAML - -#for user cpan-ability -mkdir .cpan -mkdir .cpan/CPAN -cp /usr/lib/perl5/5.8.8/CPAN/Config.pm .cpan/CPAN/MyConfig.pm -vi .cpan/CPAN/MyConfig.pm #and just leave and change the /root ones -chmod a+rx .cpan/CPAN/MyConfig.pm - -#edit ovid2flue and set user - -### -# references -### - -http://www.freeside.biz/mediawiki/index.php/Freeside:Documentation:CreatingRPMRepo diff --git a/rpm/build/build-freeside b/rpm/build/build-freeside deleted file mode 100755 index afef96ab6..000000000 --- a/rpm/build/build-freeside +++ /dev/null @@ -1,192 +0,0 @@ -#!/bin/sh -# -# Copyright 2008, Elirion, Inc. All rights reserved. -# This software is licensed under the same terms as Freeside itself. -# -# This script rebuilds SRPMs of Freeside builds or the required Perl modules on all the target -# distributions and versions using mock. After a successful build, it signs the resulting RPMs -# and scp's them to the server where the yum repositories are hosted. -# (Of course, koji is supposed to do all this, including updating the repo.) - -VERSIONS='1.7 1.9' -#VERSIONS='1.7 1.9 2.1' -REPO=testing -BRANCH= -DISTROS='centos sles' -CENTOSVERS='5' -SLESVERS=10 -WHICHVERS= -ARCHS='i386 x86_64' - -BUILDSYSDIR=`dirname $0` - -MOCKWORK="$BUILDSYSDIR/mockwork" - -#MOCKARGS='--autocache' -MOCKARGS="--configdir=$BUILDSYSDIR/mock --resultdir=$MOCKWORK" - -if [ -f $BUILDSYSDIR/buildsysrc ]; then - #chmod a+x $BUILDSYSDIR/buildsysrc - #echo $BUILDSYSDIR/buildsysrc - . $BUILDSYSDIR/buildsysrc -fi -if [ -f $HOME/buildsysrc ]; then - #chmod a+x $HOME/buildsysrc - #echo $HOME/buildsysrc - . $HOME/buildsysrc -fi - -EXPECT_ADDSIGN=$BUILDSYSDIR/expect-addsign -if [ -f /usr/local/bin/expect-addsign ]; then - EXPECT_ADDSIGN=/usr/local/bin/expect-addsign -fi - -usage() { - echo "build-freeside: build RPMs for all target distros and architectures using mock" - echo "where:" - echo " -a <archs>: change architectures (currently: $ARCHS)" - echo " -b <branch>: change branch (currently: $BRANCH)" - echo " -d <distros>: change distributions (currently: $DISTROS)" - echo " -m <arguments>: change arguments passed to 'mock' (currently: $MOCKARGS)" - echo " -r <repo>: change repositories (currently: $REPO)" - echo " -s <srpms>: build these SRPMs instead of new ones in staging area" - echo " -v <versions>: change versions (currently: $VERSIONS)" - echo " -w <distvers>: change distro version (currently: $WHICHVERS)" - exit 0 -} - -while getopts "a:b:d:hm:r:s:v:w:" flag -do - case $flag in - a) - echo "Changing architectures from $ARCHS to $OPTARG" - ARCHS=$OPTARG;; - b) - echo "Changing branch from $BRANCH to $OPTARG" - BRANCH=$OPTARG;; - d) - echo "Changing distros from $DISTROS to $OPTARG" - DISTROS=$OPTARG;; - m) - echo "Changing mock arguments from $MOCKARGS to $OPTARG" - MOCKARGS=$OPTARG;; - r) - echo "Changing repository from $REPO to $OPTARG" - REPO=$OPTARG;; - s) - echo "Changing SRPMS from $SRPMS to $OPTARG" - SRPMS=$OPTARG;; - v) - echo "Changing versions from $VERSIONS to $OPTARG" - VERSIONS=$OPTARG;; - w) - echo "Changing which distro versions from $WHICHVERS to $OPTARG" - WHICHVERS=$OPTARG;; - *) - usage;; - esac -done - -if [ "${SRCFOLDER}x" = "x" ]; then - PWD=`pwd` - echo "No source folder defined! (BUILDSYSDIR=$BUILDSYSDIR pwd=$PWD)" - exit -fi - -if [ "${REFFOLDER}x" = "x" ]; then - echo "No reference folder defined!" - exit -fi - -if [ "${SRPMS}x" = "x" ]; then - # Work out the new SRPMs on grosbeak - SRPMS=`/usr/bin/rsync -Cavz --dry-run $SRCFOLDER/ $REFFOLDER | grep .src.rpm | grep -v safecat | tr '\n' ' '` - - # Go and get the SRPMs - /usr/bin/rsync -Cavz $SRCFOLDER/ $REFFOLDER -fi - -# Make sure the SRPMs are there -for srpm in ${SRPMS} -do - if [ ! -f $REFFOLDER/${srpm} ] - then - echo "No such file: $REFFOLDER/${srpm}" - exit - fi -done - -# Build all the SRPMs -for srpm in ${SRPMS} -do - for distro in $DISTROS - do - if [ "${WHICHVERS}x" = "x" ]; then - if [ "$distro" = "centos" ]; then - DISTVERS=$CENTOSVERS - fi - if [ "$distro" = "sles" ]; then - DISTVERS=$SLESVERS - fi - else - DISTVERS=$WHICHVERS - fi - for distver in $DISTVERS - do - os=${distro}-${distver} - for arch in $ARCHS - do - echo "$os - $arch: $srpm" - echo mock $MOCKARGS -r ${os}-${arch} $REFFOLDER/${srpm} - time mock $MOCKARGS -r ${os}-${arch} $REFFOLDER/${srpm} - if true #[ -f $MOCKWORK/${os}-${arch}/state/status ] && grep done $MOCKWORK/${os}-${arch}/state/status - then - for VERSION in $VERSIONS - do - DEST=$VERSION - if [ "${BRANCH}x" != "x" ] - then - DEST=$BRANCH - fi - # Copy freeside RPMs for this version only - #FILES=`ls -1 $MOCKWORK/${os}-${arch}/result/freeside*-${VERSION}-*.rpm | grep -v .src.rpm | tr '\n' ' '` - FILES=`ls -1 $MOCKWORK/freeside*-${VERSION}-*.rpm | grep -v .src.rpm | tr '\n' ' '` - echo $FILES - if [ "${FILES}x" != "x" ] - then - for FILE in $FILES - do - $EXPECT_ADDSIGN $FILE - done - if [ "${REPOMACHINE}x" != "x" ] - then - scp -p $FILES $REPOUSER@$REPOMACHINE:$REPOFOLDER/repo/${distro}/${distver}/freeside-${DEST}/${REPO}/${arch} - else - cp -p $FILES $REPOFOLDER/repo/${distro}/${distver}/freeside-${DEST}/${REPO}/${arch} - fi - fi - # Copy non-freeside RPMs to all versions - #FILES=`ls -1 $MOCKWORK/${os}-${arch}/result/*.rpm | grep -v freeside | grep -v .src.rpm | tr '\n' ' '` - FILES=`ls -1 $MOCKWORK/*.rpm | grep -v freeside | grep -v .src.rpm | tr '\n' ' '` - echo $FILES - if [ "${FILES}x" != "x" ] - then - for FILE in $FILES - do - $EXPECT_ADDSIGN $FILE - done - if [ "${REPOMACHINE}x" != "x" ] - then - scp -p $FILES $REPOUSER@$REPOMACHINE:$REPOFOLDER/repo/${distro}/${distver}/freeside-${DEST}/${REPO}/${arch} - else - cp -p $FILES $REPOFOLDER/repo/${distro}/${distver}/freeside-${DEST}/${REPO}/${arch} - fi - fi - done - fi - done - done - done -done - -echo "build-freeside done" diff --git a/rpm/build/buildsysrc b/rpm/build/buildsysrc deleted file mode 100755 index c8d0beeb0..000000000 --- a/rpm/build/buildsysrc +++ /dev/null @@ -1,14 +0,0 @@ -# Define shell variables for the Freeside RPM build system -# - -SRCFOLDER=ivan@10.5.4.5:/home/ivan/redhat/SRPMS -REFFOLDER=$HOME/buildsys/ref/SRPMS -#ARCHS='i386 x86_64' -REPOFOLDER=/home/ivan/public_html -REPOBASEFOLDER=/home/ivan/public_html -KEYID=rpm - -VERSIONS='1.7' -DISTROS='centos' -CENTOSVERS='5' -#ARCHS='x86_64' diff --git a/rpm/build/cvs-check-and-build b/rpm/build/cvs-check-and-build deleted file mode 100755 index e8cd52104..000000000 --- a/rpm/build/cvs-check-and-build +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# -# Copyright 2009, Elirion, Inc. All rights reserved. -# This software is licensed under the same terms as Freeside itself. -# -# This script wraps other scripts in the build system. It does a CVS comparison on the vserver -# to determine if the CVS contents have changed. If so, an SRPM is built. The script then invokes -# the local build script which pulls down this SRPM and uses mock to build binary RPMs for the -# default targets. Finally, the repository is updated. -# -# There's currently no testing for failure. - -FORCE_FLAG= -QUIET_FLAG= - -usage() { - echo "cvs-check-and-build: check Freeside CVS and build RPMs if changed" - echo "where:" - echo " -f: force SRPM rebuild even if CVS contents have not changed" - echo " -h: print this help message" - echo " -q: run yum-arch and createrepo in quiet mode" - exit 0 -} - -while getopts "fhq" flag -do - case $flag in - f) - echo "Force mode" - FORCE_FLAG=-f;; - q) - echo "Quiet mode" - QUIET_FLAG=-q;; - *) - usage;; - esac -done - -#ssh 10.5.4.5 /home/rsiddall/build-from-cvs $FORCE_FLAG -#cd /home/rsiddall/buildsys; ./build-freeside; ./refresh-repo $QUIET_FLAG - -ssh 10.5.4.5 ./build-from-cvs $FORCE_FLAG - -cd ~/buildsys; ./build-freeside; ./refresh-repo $QUIET_FLAG - diff --git a/rpm/build/enrpm b/rpm/build/enrpm deleted file mode 100755 index 3e674bc3a..000000000 --- a/rpm/build/enrpm +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/perl -w -# -# Attempt to build RPMs for Freeside from a tarball or module -# -# Contains portions of "cpanspec" http://cpanspec.sourceforge.net/ - -=head1 NAME - -enrpm - Attempt to build RPMs for Freeside from a tarball or a module - -=head1 SYNOPSIS - -enrpm [options] [tarball|module-name [...]] - - Options: - --help -h Help message - -=head1 DESCRIPTION - -B<enrpm> will generate a spec file to build a rpm from a CPAN-style -Perl module distribution, then try to build RPMs from that spec file -under mock, and update the repositories if successful. - -B<enrpm> uses the file extension of the tarball or module-name specified -on the command line to determine if the argument is a tarball or a module name. - -Modules are downloaded from the CPAN. You must have initialized CPAN on the machine -for B<enrpm> to be able to do this. - -For tarballs B<enrpm> attempts to build a usable .spec file using cpanflute2, and then builds -an SRPM from the .spec file and the tarball. - -Once an SRPM has been built, B<enrpm> uses an external script to build binary RPMs under "mock". -It then uses a second script to update the repositories. - -=head1 OPTIONS - -=over 4 - -=item B<--help> - -Print a brief help message and exit. - -=item B<--packager> - -Specify the name and e-mail address of the packager. This winds up in auto-generated .spec files. - -=item B<--server> - -Specify the host name or IP address of the server on which the SRPM will be built. This server must be -set up for SRPM building, which means it must have both B<ovid> and B<cpanflute2> installed on it. - -=item B<--dry-run> - -Just print out commands, don't actually run them. - -=back - -=head1 BUGS - -Currently has little in the way of error detection and diagnostics. - -The back-end should be replaced with an existing build system such as koji. - -=head1 AUTHOR - -Richard Siddall <richard.siddall@elirion.net> - -=head1 SEE ALSO - -L<perl(1)>, L<cpan2rpm(1)>, L<cpanflute2(1)> - -=cut - -use strict; -use Getopt::Long; -use Cwd qw/getcwd abs_path/; -use File::Basename; -use Sys::Hostname; # False laziness to get around a real config file... - -my %opts; - -GetOptions(\%opts, 'packager=s', 'release=s', 'server=s', 'dryrun'); - -$ENV{PATH} = "/bin:/usr/bin"; - -sub usage { - print STDERR "usage: enrpm --packager <Your Name <you\@example.com>> [--release=<rpm-release-string>] --server <server-name> [--dryrun] tarball|module-name\n"; - print STDERR "where:\n\t--packager is the name and e-mail address of the packager for the .spec file\n\t--release is the rpm release number for the .spec file\n\t--server is the server to build the SRPM on\n\t--dryrun means do not actually run the commands\n\n"; - print STDERR "\ttarball is the name of a tarball containing the Perl module to be packaged\n"; - print STDERR "\tmodule-name is the name of a CPAN Perl module to be packaged\n"; - exit; -} - -# Feeble excuse for not having a real configuration file -my $user = 'ivan'; -my $buildsys = "/home/$user/buildsys"; -#my $rembuild = '/home/rsiddall/buildsys/ref'; -my $remdeps = '/home/ivan'; -my $rpmtopdir = "/home/$user/redhat"; -my $packager = 'Ivan Kohler <ivan@freeside.biz>'; -my $server = '10.5.4.5'; - -$server = $opts{server} if defined($opts{server}); -$user = $1 if $server =~ /(\w+)\@[\w\d\.]+/; - -$packager = $opts{packager} if defined($opts{packager}); - -# Go ahead and build an SRPM... - -my $ovidignore = '--ignore ' . join ('--ignore ', qw/libwww/); - - -for my $file (@ARGV) { - my ($name,$version,$type); - - if ($file =~ /^(?:.*\/)?(.*)-(?:v\.?)?([^-]+)\.(tar)\.(?:gz|bz2)$/) { - $name = $1; - $version = $2; - $type = $3; - } elsif ($file =~ /^(?:.*\/)?(.*)-(?:v\.?)?([^-]+)\.tgz$/) { - $name = $1; - $version = $2; - $type = 'tar'; - } elsif ($file =~ /^(?:.*\/)?(.*)-(?:v\.?)?([^-]+)\.(zip)$/) { - $name = $1; - $version = $2; - $type = $3; - } else { - # keep things happy if we get "Foo-Bar" instead of "Foo::Bar" - $file =~ s/-/::/g; - $name = $file; - $version = undef; - $type = 'module'; - } - - if ($type eq 'module') { - my $fluteopts = ''; - $fluteopts .= "--packager='$packager' " if defined($packager); - $fluteopts .= "--release='$opts{release}' " if defined($opts{release}); - do_cmd("ssh $user\@$server \"ovid --deps $ovidignore $name | tail -1 | $remdeps/ovid2flute $fluteopts | /bin/sh\""); - } else { - my $absfile = abs_path($file); - my $fname = basename($file); - die "Packager name and e-mail required" if !defined($packager); - die "RPM release string required" if !defined($opts{release}); - do_cmd("scp $absfile $user\@$server:/home/$user/$fname"); -# do_cmd("ssh $user\@$server 'cpanflute2 --just-spec --noperlreqs --email=\\\"$packager\\\" --release=$opts{release} /home/$user/$fname > /home/$user/work/redhat/SPECS/$name.spec;'"); -# do_cmd("ssh $user\@$server 'perl -pi -e \\\"s/perl\(perl\)/perl/g\\\" /home/$user/work/redhat/SPECS/$name.spec;'"); -# do_cmd("ssh $user\@$server 'rpmbuild -bs --nodeps --define \\\"_sourcedir /home/$user/\\\" --define \\\"_srcrpmdir /home/$user/work/redhat/SRPMS\\\" /home/$user/work/redhat/SPECS/$name.spec'"); - open SCRIPT, ">/home/$user/makesrpm" or die "Can't create SRPM construction script: ", $!; - print SCRIPT "#!/bin/sh\n\n"; - print SCRIPT "cpanflute2 --just-spec --noperlreqs --email='$packager' --release=$opts{release} /home/$user/$fname > $rpmtopdir/SPECS/$name.spec;\n"; - print SCRIPT "perl -pi -e 's/perl(perl)/perl/g' $rpmtopdir/SPECS/$name.spec\n"; - print SCRIPT "rpmbuild -bs --nodeps --define '_sourcedir /home/$user/' --define '_srcrpmdir $rpmtopdir/SRPMS' $rpmtopdir/SPECS/$name.spec\n"; - close SCRIPT or die "Can't close SRPM construction script: ", $!; - chmod(0711, "/home/$user/makesrpm"); - do_cmd("scp /home/$user/makesrpm $user\@$server:/home/$user/makesrpm"); - do_cmd("ssh $user\@$server /home/$user/makesrpm"); - } - my $olddir = getcwd(); - do_cmd("$buildsys/build-freeside"); -# if (-x "$buildsys/refresh-repo") { - do_cmd("$buildsys/refresh-repo"); -# } else { -# do_cmd("ssh $user\@$server $rembuild/refresh-repo"); -# } -} - -sub do_cmd { - my $cmd = shift; - - print "$cmd\n"; - `$cmd` if !exists($opts{dryrun}); -} - -1; - diff --git a/rpm/build/expect-addsign b/rpm/build/expect-addsign deleted file mode 100755 index 5634ed47b..000000000 --- a/rpm/build/expect-addsign +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/expect -set p "not our actual passphrase" -set f [lindex $argv 0] -#spawn /bin/rpm --resign $f -spawn /usr/bin/rpm --resign $f -expect "Enter pass phrase:" -send -- "$p\r" -expect eof diff --git a/rpm/build/expect-signrepo b/rpm/build/expect-signrepo deleted file mode 100755 index 81035f9f2..000000000 --- a/rpm/build/expect-signrepo +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/expect -set password "not our actual passphrase" -set key [lindex $argv 0] -set output [lindex $argv 1] -set input [lindex $argv 2] -spawn gpg -sab --yes -u "$key" -o $output $input -expect "Enter passphrase:" -send -- "$password\r" -expect eof diff --git a/rpm/build/mock/centos-5-i386.cfg b/rpm/build/mock/centos-5-i386.cfg deleted file mode 100644 index 203d4fd13..000000000 --- a/rpm/build/mock/centos-5-i386.cfg +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/python -tt -import os -config_opts['root'] = 'centos-5-i386' -config_opts['target_arch'] = 'i386' - -config_opts['cleanup_on_failure'] = 0 - -config_opts['chroot_setup_cmd'] = 'install buildsys-build' - -# caching related options -#these are probably obsolete? -config_opts['rebuild_cache'] = False -#config_opts['use_cache'] = False -config_opts['use_cache'] = True -config_opts['pack_cmd'] = "/usr/sbin/mock-helper pack" -config_opts['unpack_cmd'] = "/usr/sbin/mock-helper unpack" -config_opts['cache_ext'] = ".tar.gz" -config_opts['cache_topdir'] = "/var/cache/mock" -#config_opts['max_cache_age_days'] = 15 -config_opts['max_cache_age_days'] = 150 - -# config_opts['plugin_conf']['ccache_enable'] = True -config_opts['plugin_conf']['ccache_enable'] = False -# config_opts['plugin_conf']['ccache_opts']['max_cache_size'] = '4G' -# config_opts['plugin_conf']['ccache_opts']['dir'] = "%(cache_topdir)s/%(root)s/ccache/" -config_opts['plugin_conf']['yum_cache_enable'] = True -config_opts['plugin_conf']['yum_cache_opts']['max_age_days'] = 30 -config_opts['plugin_conf']['yum_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/yum_cache/" -config_opts['plugin_conf']['root_cache_enable'] = True -config_opts['plugin_conf']['root_cache_opts']['max_age_days'] = 15 -config_opts['plugin_conf']['root_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/root_cache/" -config_opts['plugin_conf']['root_cache_opts']['compress_program'] = "gzip" -config_opts['plugin_conf']['root_cache_opts']['extension'] = ".gz" - - -config_opts['yum.conf'] = """ - -[main] -cachedir=/var/cache/yum -debuglevel=1 -reposdir=/dev/null -logfile=/var/log/yum.log -retries=20 -obsoletes=1 -gpgcheck=0 -assumeyes=1 - -# repos - -[os] -name=os -mirrorlist=http://mirrorlist.centos.org/?release=5&arch=i386&repo=os -baseurl=http://mirror.centos.org/centos/5/os/i386/ -#baseurl=file:///home/rsiddall/mock/repos/centos/5/os/i386/ - -[updates] -name=updates -mirrorlist=http://mirrorlist.centos.org/?release=5&arch=i386&repo=updates -baseurl=http://mirror.centos.org/centos/5/updates/i386/ -#baseurl=file:///home/rsiddall/mock/repos/centos/5/updates/i386/ - -[groups] -name=groups -baseurl=http://dev.centos.org/centos/buildsys/5/ - -""" - -#something here is causing a problem, don't know what, see if we need anything -#config_opts['macros'] = """ -#%_topdir /builddir/build -#%_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm -# -## Change the next two lines to reflect yourself. -# -#%packager Freeside Internet Services, Inc. <rpm@freeside.biz> -##%vendor -##%distribution -# -## please change this to reflect the Distro Tree and Repo hosting packages! -##%dist <distro>.<yourtag> -#%centos_ver 5 -# -##%_smp_mflags -j1 -# -#""" - - diff --git a/rpm/build/mock/centos-5-x86_64.cfg b/rpm/build/mock/centos-5-x86_64.cfg deleted file mode 100644 index 174136909..000000000 --- a/rpm/build/mock/centos-5-x86_64.cfg +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/python -tt -import os - -config_opts['root'] = 'centos-5-x86_64' -config_opts['target_arch'] = 'x86_64' - -config_opts['cleanup_on_failure'] = 0 - -config_opts['chroot_setup_cmd'] = 'install buildsys-build' - -# caching related options -#these are probably obsolete? -config_opts['rebuild_cache'] = False -#config_opts['use_cache'] = False -config_opts['use_cache'] = True -config_opts['pack_cmd'] = "/usr/sbin/mock-helper pack" -config_opts['unpack_cmd'] = "/usr/sbin/mock-helper unpack" -config_opts['cache_ext'] = ".tar.gz" -config_opts['cache_topdir'] = "/var/cache/mock" -#config_opts['max_cache_age_days'] = 15 -config_opts['max_cache_age_days'] = 150 - -# config_opts['plugin_conf']['ccache_enable'] = True -config_opts['plugin_conf']['ccache_enable'] = False -# config_opts['plugin_conf']['ccache_opts']['max_cache_size'] = '4G' -# config_opts['plugin_conf']['ccache_opts']['dir'] = "%(cache_topdir)s/%(root)s/ccache/" -config_opts['plugin_conf']['yum_cache_enable'] = True -config_opts['plugin_conf']['yum_cache_opts']['max_age_days'] = 30 -config_opts['plugin_conf']['yum_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/yum_cache/" -config_opts['plugin_conf']['root_cache_enable'] = True -config_opts['plugin_conf']['root_cache_opts']['max_age_days'] = 15 -config_opts['plugin_conf']['root_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/root_cache/" -config_opts['plugin_conf']['root_cache_opts']['compress_program'] = "gzip" -config_opts['plugin_conf']['root_cache_opts']['extension'] = ".gz" - - -config_opts['yum.conf'] = """ - -[main] -cachedir=/var/cache/yum -debuglevel=1 -reposdir=/dev/null -logfile=/var/log/yum.log -retries=20 -obsoletes=1 -gpgcheck=0 -assumeyes=1 -exclude=[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz]*.i*86 g[abcdefghijkmnopqrstuvwxyz]*.i?86 glib2.i?86 glib.i?86 *-devel.i?86 -# repos - -[os] -name=os -mirrorlist=http://mirrorlist.centos.org/?release=5&arch=x86_64&repo=os -baseurl=http://mirror.centos.org/centos/5/os/x86_64/ -#baseurl=file:///home/rsiddall/mock/repos/centos/5/os/x86_64/ - -[updates] -name=updates -mirrorlist=http://mirrorlist.centos.org/?release=5&arch=x86_64&repo=updates -baseurl=http://mirror.centos.org/centos/5/updates/x86_64/ -#baseurl=file:///home/rsiddall/mock/repos/centos/5/updates/x86_64/ - -[groups] -name=groups -baseurl=http://dev.centos.org/centos/buildsys/5/ -""" - -#something here is causing a problem, don't know what, see if we need anything -#re-enabled -#config_opts['macros'] = """ -#%_topdir /builddir/build -#%_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm -# -## Change the next two lines to reflect yourself. -# -#%packager Freeside Internet Services, Inc. <rpm@freeside.biz> -##%vendor -##%distribution -# -## please change this to reflect the Distro Tree and Repo hosting packages! -##%dist <distro>.<yourtag> -#%centos_ver 5 -# -##%_smp_mflags -j1 -# -#""" - - diff --git a/rpm/build/mock/defaults.cfg b/rpm/build/mock/defaults.cfg deleted file mode 100644 index 3f9fcf6c2..000000000 --- a/rpm/build/mock/defaults.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# mock defaults -# -# Define default values here. -# These values are overwritten in the /etc/mock/CHROOT.cfg files. -# -# Example: -# -# config_opts['foo'] = bar -config_opts['basedir'] = '/var/lib/mock/' -config_opts['chroot'] = '/usr/sbin/mock-helper chroot' -config_opts['mount'] = '/usr/sbin/mock-helper mount' -config_opts['umount'] = '/usr/sbin/mock-helper umount' -config_opts['rm'] = '/usr/sbin/mock-helper rm' -config_opts['mknod'] = '/usr/sbin/mock-helper mknod' -config_opts['yum'] = '/usr/sbin/mock-helper yum' -config_opts['runuser'] = '/sbin/runuser' -config_opts['chrootuser'] = 'mockbuild' -config_opts['chrootgroup'] = 'mockbuild' -config_opts['chrootuid'] = os.geteuid() -config_opts['chrootgid'] = os.getegid() -config_opts['chroothome'] = '/builddir' -config_opts['clean'] = True - -# caching related options -config_opts['rebuild_cache'] = False -config_opts['use_cache'] = False -config_opts['pack_cmd'] = "/usr/sbin/mock-helper pack" -config_opts['unpack_cmd'] = "/usr/sbin/mock-helper unpack" -config_opts['cache_ext'] = ".tar.gz" -config_opts['cache_topdir'] = "root-cache" -config_opts['max_cache_age_days'] = 15 - -# allow some network tests to run under the chroot -config_opts['files']['/etc/resolv.conf'] = open("/etc/resolv.conf","r").read() -config_opts['files']['/etc/hosts'] = open("/etc/hosts","r").read() - -config_opts['chroot_setup_cmd'] = 'install buildsys-build' -#config_opts['chroot_setup_cmd'] = 'groupinstall build' - diff --git a/rpm/build/mock/logging.ini b/rpm/build/mock/logging.ini deleted file mode 100644 index fadc6a85b..000000000 --- a/rpm/build/mock/logging.ini +++ /dev/null @@ -1,84 +0,0 @@ -[formatters] -keys: detailed,simple,unadorned,state - -[handlers] -keys: simple_console,detailed_console,unadorned_console,simple_console_warnings_only - -[loggers] -keys: root,build,state,mock - -[formatter_state] -format: %(asctime)s - %(message)s - -[formatter_unadorned] -format: %(message)s - -[formatter_simple] -format: %(levelname)s: %(message)s - -;useful for debugging: -[formatter_detailed] -format: %(levelname)s %(filename)s:%(lineno)d: %(message)s - -[handler_unadorned_console] -class: StreamHandler -args: [] -formatter: unadorned -level: INFO - -[handler_simple_console] -class: StreamHandler -args: [] -formatter: simple -level: INFO - -[handler_simple_console_warnings_only] -class: StreamHandler -args: [] -formatter: simple -level: WARNING - -[handler_detailed_console] -class: StreamHandler -args: [] -formatter: detailed -level: WARNING - -; usually dont want to set a level for loggers -; this way all handlers get all messages, and messages can be filtered -; at the handler level -; -; all these loggers default to a console output handler -; -[logger_root] -level: NOTSET -handlers: simple_console - -; mock logger normally has no output -; catches stuff like mock.trace_decorator and mock.util -; dont normally want to propagate to root logger, either -[logger_mock] -level: NOTSET -handlers: -qualname: mock -propagate: 1 - -[logger_state] -level: NOTSET -; unadorned_console only outputs INFO or above -handlers: unadorned_console -qualname: mock.Root.state -propagate: 0 - -[logger_build] -level: NOTSET -handlers: simple_console_warnings_only -qualname: mock.Root.build -propagate: 0 - -; the following is a list mock logger qualnames used within the code: -; -; qualname: mock.util -; qualname: mock.uid -; qualname: mock.trace_decorator - diff --git a/rpm/build/mock/site-defaults.cfg b/rpm/build/mock/site-defaults.cfg deleted file mode 100644 index 0ee2082eb..000000000 --- a/rpm/build/mock/site-defaults.cfg +++ /dev/null @@ -1,98 +0,0 @@ -# mock defaults -# vim:tw=0:ts=4:sw=4:et: -# -# This config file is for site-specific default values that apply across all -# configurations. Options specified in this config file can be overridden in -# the individual mock config files. -# -# The defaults.cfg delivered by default has NO options set. Only set options -# here if you want to override the defaults. -# -# Entries in this file follow the same format as other mock config files. -# config_opts['foo'] = bar - -############################################################################# -# -# Things that we recommend you set in defaults.cfg: -# -# config_opts['basedir'] = '/var/lib/mock/' -# config_opts['cache_topdir'] = '/var/cache/mock' -# Note: the path pointed to by basedir and cache_topdir must be owned -# by group 'mock' and must have mode: g+rws -# config_opts['rpmbuild_timeout'] = 0 -# config_opts['use_host_resolv'] = True - -# You can configure log format to pull from logging.ini formats of these names: -# config_opts['build_log_fmt_name'] = "unadorned" -# config_opts['root_log_fmt_name'] = "detailed" -# config_opts['state_log_fmt_name'] = "state" -# -# mock will normally set up a minimal chroot /dev. -# If you want to use a pre-configured /dev, disable this and use the bind-mount -# plugin to mount your special /dev -# config_opts['internal_dev_setup'] = True -# -# internal_setarch defaults to 'True' if the python 'ctypes' package is -# available. It is in the python std lib on >= python 2.5. On older versions, -# it is available as an addon. On systems w/o ctypes, it will default to -# 'False' -# config_opts['internal_setarch'] = False -# -# the cleanup_on_* options allow you to automatically clean and remove the -# mock build directory, but only take effect if --resultdir is used. -# config_opts provides fine-grained control. cmdline only has big hammer -# -# config_opts['cleanup_on_success'] = 1 -# config_opts['cleanup_on_failure'] = 1 - -############################################################################# -# -# plugin related. Below are the defaults. Change to suit your site -# policy. defaults.cfg is a good place to do this. -# -# NOTE: Some of the caching options can theoretically affect build -# reproducability. Change with care. -# -# config_opts['plugin_conf']['ccache_enable'] = True -# config_opts['plugin_conf']['ccache_opts']['max_cache_size'] = '4G' -# config_opts['plugin_conf']['ccache_opts']['dir'] = "%(cache_topdir)s/%(root)s/ccache/" -# config_opts['plugin_conf']['yum_cache_enable'] = True -# config_opts['plugin_conf']['yum_cache_opts']['max_age_days'] = 30 -# config_opts['plugin_conf']['yum_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/yum_cache/" -# config_opts['plugin_conf']['root_cache_enable'] = True -# config_opts['plugin_conf']['root_cache_opts']['max_age_days'] = 15 -# config_opts['plugin_conf']['root_cache_opts']['dir'] = "%(cache_topdir)s/%(root)s/root_cache/" -# config_opts['plugin_conf']['root_cache_opts']['compress_program'] = "gzip" -# config_opts['plugin_conf']['root_cache_opts']['extension'] = ".gz" -# -# bind mount plugin is enabled by default but has no configured directories to mount -# config_opts['plugin_conf']['bind_mount_enable'] = True -# config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/host/path', '/bind/mount/path/in/chroot/' )) -# -# config_opts['plugin_conf']['tmpfs_enable'] = False -# config_opts['plugin_conf']['tmpfs_opts'] = {'required_ram_mb': 1024} - -############################################################################# -# -# Things that you can change, but we dont recommend it: -# config_opts['chroothome'] = '/builddir' -# config_opts['clean'] = True - -############################################################################# -# -# Things that are best suited for individual chroot config files: -# -# MUST SET (in individual chroot cfg file): -# config_opts['root'] = 'name-of-yum-build-dir' -# config_opts['target_arch'] = 'i386' -# config_opts['yum.conf'] = '' -# -# CAN SET, defaults usually work ok: -# config_opts['chroot_setup_cmd'] = 'install buildsys-build' -# config_opts['log_config_file'] = 'logging.ini' -# config_opts['more_buildreqs']['srpm_name-version-release'] = 'dependencies' -# config_opts['macros']['Add_your_macro_name_here'] = "add macro value here" -# config_opts['files']['path/name/no/leading/slash'] = "put file contents here." -# config_opts['chrootuid'] = os.getuid() -# config_opts['chrootgid'] = grp.getgrnam("mock")[2] -# config_opts['useradd'] = '/usr/sbin/useradd -m -u %(uid)s -g %(gid)s -d %(home)s -n %(user)s' # Fedora/RedHat diff --git a/rpm/build/mock/sles-10-i386.cfg b/rpm/build/mock/sles-10-i386.cfg deleted file mode 100644 index ad1a62b40..000000000 --- a/rpm/build/mock/sles-10-i386.cfg +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python -tt - -import os - -config_opts['root'] = 'sles-10-i386' -config_opts['basedir'] = '/var/lib/mock/' -config_opts['chroot'] = '/usr/sbin/mock-helper chroot' -config_opts['mount'] = '/usr/sbin/mock-helper mount' -config_opts['umount'] = '/usr/sbin/mock-helper umount' -config_opts['rm'] = '/usr/sbin/mock-helper rm' -config_opts['mknod'] = '/usr/sbin/mock-helper mknod' -config_opts['yum'] = '/usr/sbin/mock-helper yum' -config_opts['runuser'] = '/bin/su' -config_opts['chroot_setup_cmd'] = 'groupinstall build build-minimal build-base' -config_opts['chrootuser'] = 'mockbuild' -config_opts['chrootgroup'] = 'users' -config_opts['chrootuid'] = os.geteuid() -config_opts['chrootgid'] = os.getegid() -config_opts['chroothome'] = '/builddir' -config_opts['clean'] = True -config_opts['target_arch'] = 'i386' -config_opts['use_cache'] = 1 - - -config_opts['yum.conf'] = """ -[main] -cachedir=/var/cache/yum -debuglevel=1 -logfile=/var/log/yum.log -reposdir=/dev/null -retries=20 -obsoletes=1 -gpgcheck=0 -assumeyes=1 - -# repos - -[base] -name=base -#baseurl=http://hb.linuxdev.us.dell.com/pub/yum/sles10/base/i386/ -#baseurl=http://redshank.elirion.net/sles -baseurl=file:///home/rsiddall/mock/repos/sles10/i386 - -[build] -name=build -#baseurl=http://hb.linuxdev.us.dell.com/pub/yum/sles10/base/i386/ -#baseurl=http://grosbeak.elirion.net/repo/sles/10/build/i386/ -baseurl=file:///home/rsiddall/public_html/repo/sles/10/build/i386 - -[groups] -name=groups -#baseurl=http://hb.linuxdev.us.dell.com/pub/yum/mock/buildgroups/sles10/i386/ -#baseurl=http://redshank.elirion.net/slesgroup/sles10/i386/ -baseurl=file:///home/rsiddall/mock/buildgroups/sles10/i386 - -""" - - - diff --git a/rpm/build/mock/sles-10-x86_64.cfg b/rpm/build/mock/sles-10-x86_64.cfg deleted file mode 100644 index d55b40ad6..000000000 --- a/rpm/build/mock/sles-10-x86_64.cfg +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python -tt - -import os - -config_opts['root'] = 'sles-10-x86_64' -config_opts['basedir'] = '/var/lib/mock/' -config_opts['chroot'] = '/usr/sbin/mock-helper chroot' -config_opts['mount'] = '/usr/sbin/mock-helper mount' -config_opts['umount'] = '/usr/sbin/mock-helper umount' -config_opts['rm'] = '/usr/sbin/mock-helper rm' -config_opts['mknod'] = '/usr/sbin/mock-helper mknod' -config_opts['yum'] = '/usr/sbin/mock-helper yum' -config_opts['runuser'] = '/bin/su' -config_opts['chroot_setup_cmd'] = 'groupinstall build build-minimal build-base' -config_opts['chrootuser'] = 'mockbuild' -config_opts['chrootgroup'] = 'users' -config_opts['chrootuid'] = os.geteuid() -config_opts['chrootgid'] = os.getegid() -config_opts['chroothome'] = '/builddir' -config_opts['clean'] = True -config_opts['target_arch'] = 'x86_64' -config_opts['use_cache'] = 1 - - -config_opts['yum.conf'] = """ -[main] -cachedir=/var/cache/yum -debuglevel=1 -logfile=/var/log/yum.log -reposdir=/dev/null -retries=20 -obsoletes=1 -gpgcheck=0 -assumeyes=1 - -# repos - -[base] -name=base -#baseurl=http://hb.linuxdev.us.dell.com/pub/yum/sles10/base/x86_64/ -#baseurl=http://redshank.elirion.net/sles -baseurl=file:///home/rsiddall/mock/repos/sles10/x86_64 - -[build] -name=build -#baseurl=http://hb.linuxdev.us.dell.com/pub/yum/sles10/base/x86_64/ -#baseurl=http://grosbeak.elirion.net/repo/sles/10/build/x86_64/ -baseurl=file:///home/rsiddall/public_html/repo/sles/10/build/x86_64 - -[groups] -name=groups -#baseurl=http://hb.linuxdev.us.dell.com/pub/yum/mock/buildgroups/sles10/x86_64/ -#baseurl=http://redshank.elirion.net/slesgroup/sles10/x86_64/ -baseurl=file:///home/rsiddall/mock/buildgroups/sles10/x86_64 - -""" - - - diff --git a/rpm/build/native/Ovid.diff b/rpm/build/native/Ovid.diff deleted file mode 100644 index 81db7c5a8..000000000 --- a/rpm/build/native/Ovid.diff +++ /dev/null @@ -1,30 +0,0 @@ ---- Package.pm.orig 2007-05-25 09:54:14.000000000 -0400 -+++ Package.pm 2007-07-07 15:35:20.000000000 -0400 -@@ -165,6 +165,7 @@ - push @out, $self->provreq($n); - } - -+ return join("\n", map { "Provides: $_"; } @out) if scalar(@out) > 5; - return join('', 'Provides: ', join ' ', @out); - } - -@@ -376,10 +377,15 @@ - - %install - --make PREFIX=%{_prefix} \ -- DESTDIR=%{buildroot} \ -- INSTALLDIRS=@installdirs@ \ -- install -+if [ -f Build.PL -a -f Build ] ; then -+ ./Build destdir=%{buildroot} \ -+ install -+else -+ make PREFIX=%{_prefix} \ -+ DESTDIR=%{buildroot} \ -+ INSTALLDIRS=@installdirs@ \ -+ install -+fi - - [ -x /usr/lib/rpm/brp-compress ] && /usr/lib/rpm/brp-compress - diff --git a/rpm/build/native/build-from-cvs b/rpm/build/native/build-from-cvs deleted file mode 100755 index aa1319b96..000000000 --- a/rpm/build/native/build-from-cvs +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh -# -# Copyright 2008, Elirion, Inc. All rights reserved. -# This software is licensed under the same terms as Freeside itself. -# -# This script builds SRPMs if the Freeside CVS contents have changed. -# It must have reference copies of the Freeside versions it builds. -# Each SRPM's "release" is set to the date & time the script is run. -# The version number is forced to the CVS version. The version and release -# hard-coded in the last .spec file committed to CVS are NOT used. -# -source $HOME/freeside-cvs -RELEASE=`date +%Y%m%d%H%M%S` -QUIET_FLAG= -#FORCE_FLAG=0 -FORCE_FLAG=1 -#VERSIONS='1.7 1.9' -VERSIONS='1.7' - -while getopts "fhqv:" flag -do - case $flag in - f) - echo "Force mode" - FORCE_FLAG=1;; - q) - echo "Quiet mode" - QUIET_FLAG=-q;; - v) - echo "Changing versions from $VERSIONS to $OPTARG" - VERSIONS=$OPTARG;; - *) - usage;; - esac -done - -usage() { - echo "build-from-cvs: build SRPMs if the Freeside CVS contents have changed" - echo "where:" - echo " -f: force building SRPMs even if CVS is unchanged" - echo " -h: print this usage information" - echo " -q: run quietly" - echo " -v <versions>: change versions (currently: $VERSIONS)" - exit 0 -} - -for VERSION in $VERSIONS; do - echo ${VERSION} - /bin/rm -rf ref-${VERSION} - cp -pr freeside-${VERSION} ref-${VERSION} - cd freeside-${VERSION} - cvs update -d -P - cd .. - diff -qr --exclude=CVS freeside-${VERSION} ref-${VERSION} - RETVAL=$? - if [ $FORCE_FLAG = 1 -o $RETVAL -gt 0 ]; then - # Build the tarball with the modified .spec file in it, hard-coding the release into the .spec file - cd freeside-${VERSION} - for SPECFILE in install/rpm/freeside.spec rpm/freeside.spec; do - if [ -f $SPECFILE ]; then - cp -pf $SPECFILE .. - perl -p -i -e "s/\d+[^\}]+/${VERSION}/ if /%define\s+version\s+(\d+[^\}]+)\}/;" ${SPECFILE} - perl -pi -e "s/\$1/${RELEASE}/ if /%define\s+release\s+(\d+)/;" $SPECFILE - tar zcvf $HOME/redhat/SOURCES/freeside-${VERSION}.tar.gz --exclude CVS ../freeside-${VERSION} - mv -f ../`basename $SPECFILE` `dirname $SPECFILE` - fi - done - cd .. - rpmbuild -ts $HOME/redhat/SOURCES/freeside-${VERSION}.tar.gz - # Could do a koji-build here - # Or move the SRPM to a staging directory for the build machine to check - # Should make the Bundles and check the dependencies for changes - fi - /bin/rm -rf ref-${VERSION} -done diff --git a/rpm/build/native/freeside-cvs b/rpm/build/native/freeside-cvs deleted file mode 100755 index 88d12b4dc..000000000 --- a/rpm/build/native/freeside-cvs +++ /dev/null @@ -1,2 +0,0 @@ -export CVSROOT=":pserver:anonymous:anonymous@cvs.freeside.biz:/home/cvs/cvsroot" -export CVS_RSH="ssh" diff --git a/rpm/build/native/makesrpm b/rpm/build/native/makesrpm deleted file mode 100755 index fc9703ebc..000000000 --- a/rpm/build/native/makesrpm +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -cpanflute2 --just-spec --noperlreqs --email='Ivan Kohler <ivan@freeside.biz>' --release=1 /home/rsiddall/Business-OnlinePayment-Jety-0.06.tar.gz > /home/rsiddall/redhat/SPECS/Business-OnlinePayment-Jety.spec; -perl -pi -e 's/perl(perl)/perl/g' /home/rsiddall/redhat/SPECS/Business-OnlinePayment-Jety.spec -rpmbuild -bs --nodeps --define '_sourcedir /home/rsiddall/' --define '_srcrpmdir /home/rsiddall/redhat/SRPMS' /home/rsiddall/redhat/SPECS/Business-OnlinePayment-Jety.spec diff --git a/rpm/build/native/ovid-0.12-1.x86_64.rpm b/rpm/build/native/ovid-0.12-1.x86_64.rpm Binary files differdeleted file mode 100644 index 363e08922..000000000 --- a/rpm/build/native/ovid-0.12-1.x86_64.rpm +++ /dev/null diff --git a/rpm/build/native/ovid2flute b/rpm/build/native/ovid2flute deleted file mode 100755 index 5bb836116..000000000 --- a/rpm/build/native/ovid2flute +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/perl -w -# -# Convert the output from ovid --deps into a list of modules to run through cpanflute2 to get -# better .spec files, and generate SRPMs from these. - -use strict; -use Getopt::Long; - -# Need to fix up modules where Ovid parses the name incorrectly -my %badparse=( - 'Crypt-PasswdMD-5' => 'Crypt-PasswdMD5', - 'IPC-Run-3' => 'IPC-Run3', - 'Digest-SHA-1' => 'Digest-SHA1', - 'Digest-MD-4' => 'Digest-MD4', -); - -my %extra_buildreqs=( - 'File-Rsync' => [ qw/rsync/ ], - 'MIMETools' => [ qw/perl(Mail::Header) perl(Mail::Internet) perl(Mail::Field) perl(IO::Stringy) perl(File::Temp)/ ], - 'HTML::Scrubber' => [ qw/perl(HTML::Parser) perl(HTML::Tagset)/ ], -# 'Time::Duration' => [ qw/perl(Test::Pod) perl(Test::Pod::Coverage)/ ], -); - -my %extra_reqs=( - 'File-Rsync' => [ qw/rsync/ ], -); - -my %opts; - -GetOptions(\%opts, 'packager=s', 'release=s'); - -$opts{packager} = 'Richard Siddall <richard.siddall@elirion.net>' if !defined($opts{packager}); - -# Need to process modules that cause Ovid to crash -#my @extramods= qw/Text::CSV_XS Pod::Simple Crypt::SSLeay/; -#my @extramods= qw/Crypt::SSLeay/; -my @extramods= qw/IPC::ShareLite/; - -my $specfiledir="/home/ivan/work/redhat/SPECS"; -$specfiledir = "/home/ivan/redhat/SPECS" if ! -d $specfiledir; -my $srpmdir="/home/ivan/work/redhat/SRPMS"; -$srpmdir = "/home/ivan/redhat/SRPMS" if ! -d $srpmdir; - -foreach (reverse <STDIN>) { - next if !defined($_); - #print $_; - last if $_ !~ /^([-\w:]+) perl-([-\w\.]+)(-\d+[\w\.]+?)$/; - #print "$1 = $2\n" - my ($name, $rpm, $ver) = ($1, $2, $3); - print "# $name ($rpm - $ver)\n"; - foreach my $cand (keys %badparse) { - if ($rpm =~ /^$cand/) { - $rpm =~ s/^$cand/$badparse{$cand}/; - print "# Fixed up $rpm\n"; - last; - } - } - printcmds($name, "$rpm$ver"); - #print "cpanspec -v --packager 'Unknown <nobody\@example.com>' $name\n"; - #print "echo $rpm\n"; - #print "repoquery perl-$rpm\n"; - #touchsrpms($name, "$rpm$ver"); -} - -exit; - -foreach my $name (@extramods) { - my $rpm = $name; - $rpm =~ s/::/-/g; - my $tarball = `find ~/.cpan/sources -name '$rpm-*' -print | tail -1`; - #print "$name (Extra!)\n" - if ($tarball =~ /\/($rpm-.*?)(\.tar\.gz|\.tgz)\s*$/) { - $rpm = $1; - printcmds($name, $rpm); - } else { - die "Can't find full rpm name for $name in \"$tarball\"\n"; - } -} - -sub touchsrpms { - my ($name, $rpm) = @_; - my $repofolder ="/var/www/html/repo/sles/10/freeside-1.9/stable/x86_64"; - my $srpmfolder ="/home/ivan/work/redhat/SRPMS"; - my @files = glob "$repofolder/perl-$rpm-*.rpm"; - if (! scalar(@files)) { - print "Can't find $rpm in $repofolder\n"; - @files = glob "$srpmfolder/perl-$rpm-*.src.rpm\n"; - if (scalar(@files)) { - my $file = pop @files; - print "touch $file\n"; - } else { - print STDERR "No corresponding SRPM: $srpmfolder/perl-$rpm-*.src.rpm\n"; - printcmds($name, $rpm); - } - } -} - -sub printcmds { - my ($name, $rpm) = @_; - - my $tarball = `find ~/.cpan -name '$rpm.tar.gz' -print`; - $tarball = `find ~/.cpan -name '$rpm.tgz' -print` if ! $tarball; - chomp($tarball); -# my $specfile = "$specfiledir/$name.spec"; - my $rpmname = $rpm; - $rpmname = $1 if $rpm =~ /^(?:.*\/)?(.*)-(?:v\.?)?([^-]+)$/; - my $specfile = "$specfiledir/perl-$rpmname.spec"; - $specfile =~ s/::/-/g; - # Work out which version of the SRPM we're going to generate. - my $rel; - if (!defined($opts{release})) { - for ($rel = 1; ; $rel++) { - my $srpm = "$srpmdir/perl-$rpm-$rel.src.rpm"; - last if ! -e $srpm; - print "# File exists: $srpm\n"; - } - } else { - $rel = $opts{release}; - } - my $fluteopts = ""; - foreach my $cand (keys %extra_buildreqs) { - if ($rpm =~ /^$cand/) { - $fluteopts .= join "", map { "--buildrequires $_ " } @{$extra_buildreqs{$cand}}; - last; - } - } - foreach my $cand (keys %extra_reqs) { - if ($rpm =~ /^$cand/) { - $fluteopts .= join "", map { "--requires $_ " } @{$extra_reqs{$cand}}; - last; - } - } - print "cpanflute2 --just-spec --noperlreqs --email='$opts{packager}' --release=$rel $fluteopts $tarball > $specfile;\n"; - # Should fix up the .spec file - print "perl -pi -e 's/perl\\(perl\\)/perl/g' $specfile;\n"; - my $tarballdir = `dirname $tarball` or die "Can't find tarball for $name: $tarball\n"; - chomp($tarballdir); - print "rpmbuild -bs --nodeps --define '_sourcedir $tarballdir' --define '_srcrpmdir $srpmdir' $specfile\n"; - print "# Generates: $srpmdir/perl-$rpm-$rel.src.rpm\n"; -} - diff --git a/rpm/build/ovid2flute b/rpm/build/ovid2flute deleted file mode 100755 index 403b1d93f..000000000 --- a/rpm/build/ovid2flute +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/perl -w -# -# Convert the output from ovid --deps into a list of modules to run through cpanflute2 to get -# better .spec files, and generate SRPMs from these. - -use strict; -use Getopt::Long; - -# Need to fix up modules where Ovid parses the name incorrectly -my %badparse=( - 'Crypt-PasswdMD-5' => 'Crypt-PasswdMD5', - 'IPC-Run-3' => 'IPC-Run3', - 'Digest-SHA-1' => 'Digest-SHA1', - 'Digest-MD-4' => 'Digest-MD4', -); - -my %extra_buildreqs=( - 'File-Rsync' => [ qw/rsync/ ], - 'MIMETools' => [ qw/perl(Mail::Header) perl(Mail::Internet) perl(Mail::Field) perl(IO::Stringy) perl(File::Temp)/ ], - 'HTML::Scrubber' => [ qw/perl(HTML::Parser) perl(HTML::Tagset)/ ], -# 'Time::Duration' => [ qw/perl(Test::Pod) perl(Test::Pod::Coverage)/ ], -); - -my %extra_reqs=( - 'File-Rsync' => [ qw/rsync/ ], -); - -my %opts; - -GetOptions(\%opts, 'packager=s', 'release=s'); - -$opts{packager} = 'Richard Siddall <richard.siddall@elirion.net>' if !defined($opts{packager}); - -# Need to process modules that cause Ovid to crash -#my @extramods= qw/Text::CSV_XS Pod::Simple Crypt::SSLeay/; -#my @extramods= qw/Crypt::SSLeay/; -my @extramods= qw/IPC::ShareLite/; - -my $specfiledir="/home/rsiddall/work/redhat/SPECS"; -my $srpmdir="/home/rsiddall/work/redhat/SRPMS"; - -foreach (reverse <STDIN>) { - next if !defined($_); - #print $_; - last if $_ !~ /^([-\w:]+) perl-([-\w\.]+)(-\d+[\w\.]+?)$/; - #print "$1 = $2\n" - my ($name, $rpm, $ver) = ($1, $2, $3); - print "# $name ($rpm - $ver)\n"; - foreach my $cand (keys %badparse) { - if ($rpm =~ /^$cand/) { - $rpm =~ s/^$cand/$badparse{$cand}/; - print "# Fixed up $rpm\n"; - last; - } - } - printcmds($name, "$rpm$ver"); - #print "cpanspec -v --packager 'Unknown <nobody\@example.com>' $name\n"; - #print "echo $rpm\n"; - #print "repoquery perl-$rpm\n"; - #touchsrpms($name, "$rpm$ver"); -} - -exit; - -foreach my $name (@extramods) { - my $rpm = $name; - $rpm =~ s/::/-/g; - my $tarball = `find ~/.cpan/sources -name '$rpm-*' -print | tail -1`; - #print "$name (Extra!)\n" - if ($tarball =~ /\/($rpm-.*?)(\.tar\.gz|\.tgz)\s*$/) { - $rpm = $1; - printcmds($name, $rpm); - } else { - die "Can't find full rpm name for $name in \"$tarball\"\n"; - } -} - -sub touchsrpms { - my ($name, $rpm) = @_; - my $repofolder ="/var/www/html/repo/sles/10/freeside-1.9/stable/x86_64"; - my $srpmfolder ="/home/rsiddall/work/redhat/SRPMS"; - my @files = glob "$repofolder/perl-$rpm-*.rpm"; - if (! scalar(@files)) { - print "Can't find $rpm in $repofolder\n"; - @files = glob "$srpmfolder/perl-$rpm-*.src.rpm\n"; - if (scalar(@files)) { - my $file = pop @files; - print "touch $file\n"; - } else { - print STDERR "No corresponding SRPM: $srpmfolder/perl-$rpm-*.src.rpm\n"; - printcmds($name, $rpm); - } - } -} - -sub printcmds { - my ($name, $rpm) = @_; - - my $tarball = `find ~/.cpan -name '$rpm.tar.gz' -print`; - $tarball = `find ~/.cpan -name '$rpm.tgz' -print` if ! $tarball; - chomp($tarball); -# my $specfile = "$specfiledir/$name.spec"; - my $rpmname = $rpm; - $rpmname = $1 if $rpm =~ /^(?:.*\/)?(.*)-(?:v\.?)?([^-]+)$/; - my $specfile = "$specfiledir/perl-$rpmname.spec"; - $specfile =~ s/::/-/g; - # Work out which version of the SRPM we're going to generate. - my $rel; - if (!defined($opts{release})) { - for ($rel = 1; ; $rel++) { - my $srpm = "$srpmdir/perl-$rpm-$rel.src.rpm"; - last if ! -e $srpm; - print "# File exists: $srpm\n"; - } - } else { - $rel = $opts{release}; - } - my $fluteopts = ""; - foreach my $cand (keys %extra_buildreqs) { - if ($rpm =~ /^$cand/) { - $fluteopts .= join "", map { "--buildrequires $_ " } @{$extra_buildreqs{$cand}}; - last; - } - } - foreach my $cand (keys %extra_reqs) { - if ($rpm =~ /^$cand/) { - $fluteopts .= join "", map { "--requires $_ " } @{$extra_reqs{$cand}}; - last; - } - } - print "cpanflute2 --just-spec --noperlreqs --email='$opts{packager}' --release=$rel $fluteopts $tarball > $specfile;\n"; - # Should fix up the .spec file - print "perl -pi -e 's/perl\\(perl\\)/perl/g' $specfile;\n"; - my $tarballdir = `dirname $tarball` or die "Can't find tarball for $name: $tarball\n"; - chomp($tarballdir); - print "rpmbuild -bs --nodeps --define '_sourcedir $tarballdir' --define '_srcrpmdir $srpmdir' $specfile\n"; - print "# Generates: $srpmdir/perl-$rpm-$rel.src.rpm\n"; -} - diff --git a/rpm/build/refresh-repo b/rpm/build/refresh-repo deleted file mode 100755 index 32d07ad97..000000000 --- a/rpm/build/refresh-repo +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/sh -# -# Copyright 2008, Elirion, Inc. All rights reserved. -# This software is licensed under the same terms as Freeside itself. -# -# This script iterates through all the specified Freeside repositories, running -# both yum-arch and createrepo to update the yum repository meta-data. -# The script should be run after the repository contents are changed. -# -# TBD: Run yum-arch, createrepo, or both, as appropriate for the distro and version -# the repository is targetted for. -# -DISTROS='centos sles' -CENTOSVERS='4 5' -SLESVERS=10 -WHICHVERS= -VERSIONS='1.7 1.9' -ARCHS='i386 x86_64' -REPOS='testing stable prerelease' -RPMS= -KEYID=rsiddall -SAVEDIR=$HOME - -REPOBASEFOLDER=/var/www/html - -QUIET_FLAG= - -BUILDSYSDIR=`dirname $0` - -if [ -f $BUILDSYSDIR/buildsysrc ]; then - #chmod a+x $BUILDSYSDIR/buildsysrc - #echo $BUILDSYSDIR/buildsysrc - . $BUILDSYSDIR/buildsysrc -fi -if [ -f $HOME/buildsysrc ]; then - #chmod a+x $HOME/buildsysrc - #echo $HOME/buildsysrc - . $HOME/buildsysrc -fi - - -usage() { - echo "refresh-repo: refresh yum metadata for all yum repositories" - echo "where:" - echo " -a <archs>: change architectures (currently: $ARCHS)" - echo " -d <distros>: change distributions (currently: $DISTROS)" - echo " -r <repos>: change repositories (currently: $REPOS)" - echo " -v <versions>: change versions (currently: $VERSIONS)" - echo " -w <distvers>: change distro version (currently: $WHICHVERS)" - exit 0 -} - -while getopts "a:d:hqr:v:w:" flag -do - case $flag in - a) - echo "Changing architectures from $ARCHS to $OPTARG" - ARCHS=$OPTARG;; - d) - echo "Changing distros from $DISTROS to $OPTARG" - DISTROS=$OPTARG;; - q) - echo "Quiet mode" - QUIET_FLAG=-q;; - r) - echo "Changing repository from $REPOS to $OPTARG" - REPOS=$OPTARG;; - v) - echo "Changing versions from $VERSIONS to $OPTARG" - VERSIONS=$OPTARG;; - w) - echo "Changing which distro versions from $WHICHVERS to $OPTARG" - WHICHVERS=$OPTARG;; - *) - usage;; - esac -done - -#for DISTRO in ${DISTROS}; do -# for VERSION in ${VERSIONS}; do -# for REPO in ${REPOS}; do -# for ARCH in ${ARCHS}; do -# # Determine which RPMs need to be signed -# NEWRPMS=`rpm --checksig $REPOBASEFOLDER/repo/$DISTROS/$DISTVERS/freeside-${VERSION}/${REPO}/${ARCH}/*.rpm | grep -v ' gpg ' | cut -d ':' -f 1 | tr '\n' ' '` -# RPMS=`echo "$RPMS $NEWRPMS"` -# done -# done -# done -#done -##rpm --addsign $RPMS -#for RPM in $RPMS; do -# ./expect-addsign $RPM -#done -for DISTRO in ${DISTROS}; do - for VERSION in ${VERSIONS}; do - for REPO in ${REPOS}; do - for ARCH in ${ARCHS}; do - if [ "${WHICHVERS}x" = "x" ]; then - if [ "$DISTRO" = "centos" ]; then - DISTVERS=$CENTOSVERS - fi - if [ "$DISTRO" = "sles" ]; then - DISTVERS=$SLESVERS - fi - else - DISTVERS=$WHICHVERS - fi - for distver in $DISTVERS - do - # Update the repo information - echo "${DISTRO}-${distver}: $VERSION - $REPO - $ARCH" - DIR=$REPOBASEFOLDER/repo/$DISTRO/$distver/freeside-${VERSION}/${REPO}/${ARCH} - if [ -d $DIR ] - then - # SLES requires signed repodata. Save any existing files so we don't regenerate - for ext in asc key - do - if [ -e $DIR/repodata/repomd.xml.${ext} ] - then - mv $DIR/repodata/repomd.xml.${ext} $SAVEDIR - fi - done - if [ "$DISTRO" = "sles" ] - then - for file in $DIR/freeside-mysql-*.rpm - do - mv $file $file.old - done - for file in $DIR/freeside-selfservice-*.rpm - do - mv $file $DIR/../self-service/$ARCH - done - fi - if [ "$DISTRO-$distver" = "centos-4" ] - then - yum-arch $QUIET_FLAG $DIR/ - fi -# createrepo $QUIET_FLAG --checkts $DIR/ - createrepo $QUIET_FLAG $DIR/ - if [ "$DISTRO" = "sles" ] - then - # SLES requires signed repodata... - if [ -e $SAVEDIR/repomd.xml.asc ] - then - mv $SAVEDIR/repomd.xml.asc $DIR/repodata - fi - -# gpg -sab --yes -u "$KEYID" -o $DIR/repodata/repomd.xml.asc $DIR/repodata/repomd.xml - ./expect-signrepo $KEYID $DIR/repodata/repomd.xml.asc $DIR/repodata/repomd.xml - if [ -e $SAVEDIR/repomd.xml.key ] - then - mv $SAVEDIR/repomd.xml.key $DIR/repodata - else - gpg -a --yes -u "$KEYID" --export -o $DIR/repodata/repomd.xml.key - fi - fi - else - echo "No such folder $DIR - skipping" - fi - done - done - done - done -done diff --git a/rt/FREESIDE_MODIFIED b/rt/FREESIDE_MODIFIED index 71ec13508..d1f214681 100644 --- a/rt/FREESIDE_MODIFIED +++ b/rt/FREESIDE_MODIFIED @@ -5,13 +5,10 @@ config.layout.in etc/RT_Config.pm etc/RT_SiteConfig.pm lib/RT/Config.pm -lib/RT/CustomField_Overlay.pm #customfield date patch -lib/RT/Interface/Web.pm #customfield date patch lib/RT/Interface/Web_Vendor.pm - lib/RT/Record.pm #and customfield date patch + lib/RT/Record.pm lib/RT/SearchBuilder.pm #need DBIx::SearchBuilder >= 1.36 for Pg 8.1+ lib/RT/Transaction_Overlay.pm -lib/RT/Tickets_Overlay.pm #customfield date patch lib/RT/Ticket_Overlay.pm lib/RT/Users_Overlay.pm lib/RT/Groups_Overlay.pm @@ -21,33 +18,20 @@ lib/RT/URI/freeside/XMLRPC.pm share/html/Admin/Users/Modify.html share/html/Elements/ColumnMap share/html/Elements/CollectionList -share/html/Elements/EditCustomFieldDate #customfield date patch (NEW) share/html/Elements/Header share/html/Elements/PageLayout #html/Elements/QuickCreate - share/html/Elements/RefreshHomepage - share/html/Elements/RT__CustomField/ColumnMap - share/html/Elements/RT__Ticket/ColumnMap - share/html/Elements/ShowCustomFieldDate #customfield date patch (NEW) share/html/Elements/SelectDate -share/html/Elements/ShowLink_Checklist - share/html/Elements/ShowUserVerbose share/html/Elements/Footer html/Ticket/Create.html #XXX TODO share/html/Search/Build.html - share/html/Search/Elements/BuildFormatString - share/html/Search/Elements/PickCFs #customfield date patch -share/html/Ticket/Checklist.html share/html/Ticket/Display.html share/html/Ticket/Elements/AddCustomers share/html/Ticket/Elements/EditCustomers share/html/Ticket/Elements/ShowCustomers -share/html/Ticket/Elements/ShowMembers_Checklist - share/html/Ticket/Elements/BulkLinks share/html/Ticket/Elements/ShowSummary share/html/Ticket/Elements/ShowTransactionAttachments share/html/Ticket/Elements/Tabs - share/html/Ticket/Graph/index.html share/html/Ticket/ModifyCustomers.html html/NoAuth/css/3.5-default/main.css html/NoAuth/css/3.5-default/misc.css @@ -64,5 +48,3 @@ share/html/Elements/EditCustomers share/html/Prefs/SearchOptions.html share/html/Widgets/TitleBoxEnd - -share/html/Callbacks/RTx-Checklist/* diff --git a/rt/bin/standalone_httpd b/rt/bin/standalone_httpd deleted file mode 100755 index 7b447050b..000000000 --- a/rt/bin/standalone_httpd +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/perl -w -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work 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., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -# -# -# CONTRIBUTION SUBMISSION POLICY: -# -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -# -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -# -# END BPS TAGGED BLOCK }}} -use warnings; -use strict; - -# fix lib paths, some may be relative -BEGIN { - require File::Spec; - my @libs = ("lib", "local/lib"); - my $bin_path; - - for my $lib (@libs) { - unless ( File::Spec->file_name_is_absolute($lib) ) { - unless ($bin_path) { - if ( File::Spec->file_name_is_absolute(__FILE__) ) { - $bin_path = ( File::Spec->splitpath(__FILE__) )[1]; - } - else { - require FindBin; - no warnings "once"; - $bin_path = $FindBin::Bin; - } - } - $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib ); - } - unshift @INC, $lib; - } - -} - -use RT; -RT::LoadConfig(); -RT->InitLogging(); -if (RT->Config->Get('DevelMode')) { require Module::Refresh; } - -RT::CheckPerlRequirements(); -RT->InitPluginPaths(); - -my $explicit_port = shift @ARGV; -my $port = $explicit_port || RT->Config->Get('WebPort') || '8080'; - - -require RT::Handle; -my ($integrity, $state, $msg) = RT::Handle->CheckIntegrity; - -unless ( $integrity ) { - print STDERR <<EOF; - -RT couldn't connect to the database where tickets are stored. -If this is a new installation of RT, you should visit the URL below -to configure RT and initialize your database. - -If this is an existing RT installation, this may indicate a database -connectivity problem. - -The error RT got back when trying to connect to your database was: - -$msg - -EOF - - require RT::Installer; - # don't enter install mode if the file exists but is unwritable - if (-e RT::Installer->ConfigFile && !-w _) { - die 'Since your configuration exists (' - . RT::Installer->ConfigFile - . ") but is not writable, I'm refusing to do anything.\n"; - } - - RT->Config->Set( 'LexiconLanguages' => '*' ); - RT::I18N->Init; - - RT->InstallMode(1); -} else { - RT->ConnectToDatabase(); - RT->InitSystemObjects(); - RT->InitClasses( Heavy => 1 ); - RT->InitPlugins(); - RT->Config->PostLoadCheck(); - - my ($status, $msg) = RT::Handle->CheckCompatibility( - $RT::Handle->dbh, 'post' - ); - unless ( $status ) { - print STDERR $msg, "\n\n"; - exit -1; - } -} - -require RT::Interface::Web::Standalone; -my $server = RT::Interface::Web::Standalone->new; -run_server($port); -exit 0; - -sub run_server { - my $port = shift; - $server->port($port); - eval { $server->run() }; - - if ( my $err = $@ ) { - handle_startup_error($err); - } -} - -sub handle_startup_error { - my $err = shift; - if ( $err =~ /bind: Permission denied/ ) { - handle_bind_error(); - } else { - die - "Something went wrong while trying to run RT's standalone web server:\n\t" - . $err; - } -} - - -sub handle_bind_error { - - print STDERR <<EOF; -WARNING: RT couldn't start up a web server on port @{[$port]}. -This is often the case if you're running @{[$0]} as -someone other than your system's "root" user. -EOF - - if ($explicit_port) { - print STDERR - "Please check your system configuration or choose another port\n\n"; - } else { - print STDERR "\nFor now, RT has chosen an alternate port to run on.\n\n"; - if ( !$integrity ) { - print STDERR <<EOF; -You can use this server to configure and explore RT. While configuring -RT, you'll have a chance to set a permanent port and URL for your -server. - -EOF - } - run_server( 8000 + int( rand(1024) ) ); - } -} diff --git a/rt/etc/RT_Config.pm b/rt/etc/RT_Config.pm index 21d837546..a976fb366 100644 --- a/rt/etc/RT_Config.pm +++ b/rt/etc/RT_Config.pm @@ -868,7 +868,7 @@ EmailAddress. =cut -Set($UsernameFormat, 'verbose'); +Set($UsernameFormat, 'concise'); =item C<$WebDomain> @@ -1370,7 +1370,6 @@ C<$DefaultSearchResultFormat> is the default format for RT search results Set ($DefaultSearchResultFormat, qq{ '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__id__</a></B>/TITLE:#', '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a></B>/TITLE:Subject', - Customer, Status, QueueName, OwnerName, @@ -1378,7 +1377,6 @@ Set ($DefaultSearchResultFormat, qq{ '__NEWLINE__', '', '<small>__Requestors__</small>', - '', '<small>__CreatedRelative__</small>', '<small>__ToldRelative__</small>', '<small>__LastUpdatedRelative__</small>', @@ -1780,7 +1778,7 @@ C<Set(@Plugins, (qw(Extension::QuickDelete RT::FM)));> =cut -Set(@Plugins, qw( RTx::Calendar )); #RTx::Checklist )); +Set(@Plugins, (qw(RTx::Calendar))); =back diff --git a/rt/etc/RT_Config.pm.in b/rt/etc/RT_Config.pm.in index c73a1e52f..564682b62 100644 --- a/rt/etc/RT_Config.pm.in +++ b/rt/etc/RT_Config.pm.in @@ -868,7 +868,7 @@ EmailAddress. =cut -Set($UsernameFormat, 'verbose'); +Set($UsernameFormat, 'concise'); =item C<$WebDomain> @@ -1370,7 +1370,6 @@ C<$DefaultSearchResultFormat> is the default format for RT search results Set ($DefaultSearchResultFormat, qq{ '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__id__</a></B>/TITLE:#', '<B><A HREF="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a></B>/TITLE:Subject', - Customer, Status, QueueName, OwnerName, @@ -1378,7 +1377,6 @@ Set ($DefaultSearchResultFormat, qq{ '__NEWLINE__', '', '<small>__Requestors__</small>', - '', '<small>__CreatedRelative__</small>', '<small>__ToldRelative__</small>', '<small>__LastUpdatedRelative__</small>', @@ -1780,7 +1778,7 @@ C<Set(@Plugins, (qw(Extension::QuickDelete RT::FM)));> =cut -Set(@Plugins, (qw(RTx::Calendar))); #RTx::Checklist )); +Set(@Plugins, (qw(RTx::Calendar))); =back diff --git a/rt/etc/RT_SiteConfig.pm b/rt/etc/RT_SiteConfig.pm index eb2d09af5..bfdfbbb89 100644 --- a/rt/etc/RT_SiteConfig.pm +++ b/rt/etc/RT_SiteConfig.pm @@ -41,7 +41,6 @@ Set($DatabaseHost , ''); # These settings are user-editable. Set($WebDefaultStylesheet, 'freeside2.1'); -Set($UsernameFormat, 'verbose'); #back to concise to hide email addresses #uncomment to use #Set($DefaultSummaryRows, 10); diff --git a/rt/lib/RT/Config.pm b/rt/lib/RT/Config.pm index ce66bb6cc..3f8581cc5 100644 --- a/rt/lib/RT/Config.pm +++ b/rt/lib/RT/Config.pm @@ -340,15 +340,13 @@ our %META = ( my $value = $self->Get('RTAddressRegexp'); return if $value; - #XXX freeside - should fix this at some point, but it is being WAY - #too noisy in the logs - #$RT::Logger->error( - # 'The RTAddressRegexp option is not set in the config.' - # .' Not setting this option results in additional SQL queries to' - # .' check whether each address belongs to RT or not.' - # .' It is especially important to set this option if RT recieves' - # .' emails on addresses that are not in the database or config.' - #); + $RT::Logger->error( + 'The RTAddressRegexp option is not set in the config.' + .' Not setting this option results in additional SQL queries to' + .' check whether each address belongs to RT or not.' + .' It is especially important to set this option if RT recieves' + .' emails on addresses that are not in the database or config.' + ); }, }, # User overridable mail options diff --git a/rt/lib/RT/CustomField_Overlay.pm b/rt/lib/RT/CustomField_Overlay.pm index c91f12037..355dd203c 100644 --- a/rt/lib/RT/CustomField_Overlay.pm +++ b/rt/lib/RT/CustomField_Overlay.pm @@ -97,11 +97,6 @@ our %FieldTypes = ( 'Enter one value with autocompletion', # loc 'Enter up to [_1] values with autocompletion', # loc ], - Date => [ - 'Select multiple dates', # loc - 'Select date', # loc - 'Select up to [_1] dates', # loc - ], ); @@ -834,7 +829,7 @@ Returns an array of all possible composite values for custom fields. sub TypeComposites { my $self = shift; - return grep !/(?:[Tt]ext|Combobox|Date)-0/, map { ("$_-1", "$_-0") } $self->Types; + return grep !/(?:[Tt]ext|Combobox)-0/, map { ("$_-1", "$_-0") } $self->Types; } =head2 SetLookupType @@ -1165,15 +1160,6 @@ sub AddValueForObject { $extra_values--; } } - # For date, we need to store Content as ISO date - if ($self->Type eq 'Date') { - my $DateObj = new RT::Date( $self->CurrentUser ); - $DateObj->Set( - Format => 'unknown', - Value => $args{'Content'}, - ); - $args{'Content'} = $DateObj->ISO; - } my $newval = RT::ObjectCustomFieldValue->new( $self->CurrentUser ); my $val = $newval->Create( ObjectType => ref($obj), diff --git a/rt/lib/RT/Interface/Web.pm b/rt/lib/RT/Interface/Web.pm index edb719df5..d6b854f4e 100644 --- a/rt/lib/RT/Interface/Web.pm +++ b/rt/lib/RT/Interface/Web.pm @@ -1714,9 +1714,6 @@ sub _ProcessObjectCustomFieldUpdates { $values_hash{$val} = 1 if $val; } - # For Date Cfs, @values is empty when there is no changes (no datas in form input) - return @results if ( $cf->Type eq 'Date' && ! @values ); - $cf_values->RedoSearch; while ( my $cf_value = $cf_values->Next ) { next if $values_hash{ $cf_value->id }; diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm index 78bbe915d..bee94420d 100755 --- a/rt/lib/RT/Record.pm +++ b/rt/lib/RT/Record.pm @@ -1744,25 +1744,6 @@ sub _AddCustomFieldValue { } my $new_content = $new_value->Content; - - # For date, we need to display them in "human" format in result message - if ($cf->Type eq 'Date') { - my $DateObj = new RT::Date( $self->CurrentUser ); - $DateObj->Set( - Format => 'ISO', - Value => $new_content, - ); - $new_content = $DateObj->AsString; - - if ( defined $old_content && length $old_content ) { - $DateObj->Set( - Format => 'ISO', - Value => $old_content, - ); - $old_content = $DateObj->AsString; - } - } - unless ( defined $old_content && length $old_content ) { return ( $new_value_id, $self->loc( "[_1] [_2] added", $cf->Name, $new_content )); } @@ -1851,21 +1832,11 @@ sub DeleteCustomFieldValue { return ( 0, $self->loc( "Couldn't create a transaction: [_1]", $Msg ) ); } - my $old_value = $TransactionObj->OldValue; - # For date, we need to display them in "human" format in result message - if ( $cf->Type eq 'Date' ) { - my $DateObj = new RT::Date( $self->CurrentUser ); - $DateObj->Set( - Format => 'ISO', - Value => $old_value, - ); - $old_value = $DateObj->AsString; - } return ( $TransactionId, $self->loc( "[_1] is no longer a value for custom field [_2]", - $old_value, $cf->Name + $TransactionObj->OldValue, $cf->Name ) ); } diff --git a/rt/lib/RT/Ticket_Overlay.pm b/rt/lib/RT/Ticket_Overlay.pm index b60ae38bd..83737c168 100644 --- a/rt/lib/RT/Ticket_Overlay.pm +++ b/rt/lib/RT/Ticket_Overlay.pm @@ -560,6 +560,68 @@ sub Create { # }}} + # {{{ Deal with auto-customer association + + #unless we already have (a) customer(s)... + unless ( $self->Customers->Count ) { + + #first find any requestors with emails but *without* customer targets + my @NoCust_Requestors = + grep { $_->EmailAddress && ! $_->Customers->Count } + @{ $self->_Requestors->UserMembersObj->ItemsArrayRef }; + + for my $Requestor (@NoCust_Requestors) { + + #perhaps the stuff in here should be in a User method?? + my @Customers = + &RT::URI::freeside::email_search( email=>$Requestor->EmailAddress ); + + foreach my $custnum ( map $_->{'custnum'}, @Customers ) { + + ## false laziness w/RT/Interface/Web_Vendor.pm + my @link = ( 'Type' => 'MemberOf', + 'Target' => "freeside://freeside/cust_main/$custnum", + ); + + my( $val, $msg ) = $Requestor->_AddLink(@link); + #XXX should do something with $msg# push @non_fatal_errors, $msg; + + } + + } + + #find any requestors with customer targets + + my %cust_target = (); + + my @Requestors = + grep { $_->Customers->Count } + @{ $self->_Requestors->UserMembersObj->ItemsArrayRef }; + + foreach my $Requestor ( @Requestors ) { + foreach my $cust_link ( @{ $Requestor->Customers->ItemsArrayRef } ) { + $cust_target{ $cust_link->Target } = 1; + } + } + + #and then auto-associate this ticket with those customers + + foreach my $cust_target ( keys %cust_target ) { + + my @link = ( 'Type' => 'MemberOf', + #'Target' => "freeside://freeside/cust_main/$custnum", + 'Target' => $cust_target, + ); + + my( $val, $msg ) = $self->_AddLink(@link); + push @non_fatal_errors, $msg; + + } + + } + + # }}} + # {{{ Add all the custom fields foreach my $arg ( keys %args ) { @@ -617,16 +679,11 @@ sub Create { next; } } - - #don't show transactions for reminders - my $silent = ( !$args{'_RecordTransaction'} - || $self->Type eq 'reminder' - ); - + my ( $wval, $wmsg ) = $self->_AddLink( Type => $LINKTYPEMAP{$type}->{'Type'}, $LINKTYPEMAP{$type}->{'Mode'} => $link, - Silent => $silent, + Silent => !$args{'_RecordTransaction'}, 'Silent'. ( $LINKTYPEMAP{$type}->{'Mode'} eq 'Base'? 'Target': 'Base' ) => 1, ); @@ -636,69 +693,6 @@ sub Create { } # }}} - - # {{{ Deal with auto-customer association - - #unless we already have (a) customer(s)... - unless ( $self->Customers->Count ) { - - #first find any requestors with emails but *without* customer targets - my @NoCust_Requestors = - grep { $_->EmailAddress && ! $_->Customers->Count } - @{ $self->_Requestors->UserMembersObj->ItemsArrayRef }; - - for my $Requestor (@NoCust_Requestors) { - - #perhaps the stuff in here should be in a User method?? - my @Customers = - &RT::URI::freeside::email_search( email=>$Requestor->EmailAddress ); - - foreach my $custnum ( map $_->{'custnum'}, @Customers ) { - - ## false laziness w/RT/Interface/Web_Vendor.pm - my @link = ( 'Type' => 'MemberOf', - 'Target' => "freeside://freeside/cust_main/$custnum", - ); - - my( $val, $msg ) = $Requestor->_AddLink(@link); - #XXX should do something with $msg# push @non_fatal_errors, $msg; - - } - - } - - #find any requestors with customer targets - - my %cust_target = (); - - my @Requestors = - grep { $_->Customers->Count } - @{ $self->_Requestors->UserMembersObj->ItemsArrayRef }; - - foreach my $Requestor ( @Requestors ) { - foreach my $cust_link ( @{ $Requestor->Customers->ItemsArrayRef } ) { - $cust_target{ $cust_link->Target } = 1; - } - } - - #and then auto-associate this ticket with those customers - - foreach my $cust_target ( keys %cust_target ) { - - my @link = ( 'Type' => 'MemberOf', - #'Target' => "freeside://freeside/cust_main/$custnum", - 'Target' => $cust_target, - ); - - my( $val, $msg ) = $self->_AddLink(@link); - push @non_fatal_errors, $msg; - - } - - } - - # }}} - # Now that we've created the ticket and set up its metadata, we can actually go and check OwnTicket on the ticket itself. # This might be different than before in cases where extensions like RTIR are doing clever things with RT's ACL system if ( $DeferOwner ) { @@ -721,8 +715,7 @@ sub Create { ); } - #don't make a transaction or fire off any scrips for reminders either - if ( $args{'_RecordTransaction'} && $self->Type ne 'reminder' ) { + if ( $args{'_RecordTransaction'} ) { # {{{ Add a transaction for the create my ( $Trans, $Msg, $TransObj ) = $self->_NewTransaction( diff --git a/rt/lib/RT/Tickets_Overlay.pm b/rt/lib/RT/Tickets_Overlay.pm index f2949ed7a..e8d350dea 100644 --- a/rt/lib/RT/Tickets_Overlay.pm +++ b/rt/lib/RT/Tickets_Overlay.pm @@ -136,7 +136,6 @@ our %FIELD_METADATA = ( QueueAdminCc => [ 'WATCHERFIELD' => 'AdminCc' => 'Queue', ], #loc_left_pair QueueWatcher => [ 'WATCHERFIELD' => undef => 'Queue', ], #loc_left_pair CustomFieldValue => [ 'CUSTOMFIELD', ], #loc_left_pair - DateCustomFieldValue => [ 'DATECUSTOMFIELD', ], CustomField => [ 'CUSTOMFIELD', ], #loc_left_pair CF => [ 'CUSTOMFIELD', ], #loc_left_pair Updated => [ 'TRANSDATE', ], #loc_left_pair @@ -161,7 +160,6 @@ our %dispatch = ( WATCHERFIELD => \&_WatcherLimit, MEMBERSHIPFIELD => \&_WatcherMembershipLimit, CUSTOMFIELD => \&_CustomFieldLimit, - DATECUSTOMFIELD => \&_DateCustomFieldLimit, HASATTRIBUTE => \&_HasAttributeLimit, ); our %can_bundle = ();# WATCHERFIELD => "yes", ); @@ -1342,101 +1340,6 @@ sub _CustomFieldJoin { return ($TicketCFs, $CFs); } -=head2 _DateCustomFieldLimit - -Limit based on CustomFields of type Date - -Meta Data: - none - -=cut - -sub _DateCustomFieldLimit { - my ( $self, $_field, $op, $value, %rest ) = @_; - - my $field = $rest{'SUBKEY'} || die "No field specified"; - - # For our sanity, we can only limit on one queue at a time - - my ($queue, $cfid, $column); - ($queue, $field, $cfid, $column) = $self->_CustomFieldDecipher( $field ); - -# If we're trying to find custom fields that don't match something, we -# want tickets where the custom field has no value at all. Note that -# we explicitly don't include the "IS NULL" case, since we would -# otherwise end up with a redundant clause. - - my $null_columns_ok; - if ( ( $op =~ /^NOT LIKE$/i ) or ( $op eq '!=' ) ) { - $null_columns_ok = 1; - } - - my $cfkey = $cfid ? $cfid : "$queue.$field"; - my ($TicketCFs, $CFs) = $self->_CustomFieldJoin( $cfkey, $cfid, $field ); - - $self->_OpenParen; - - if ( $CFs && !$cfid ) { - $self->SUPER::Limit( - ALIAS => $CFs, - FIELD => 'Name', - VALUE => $field, - ENTRYAGGREGATOR => 'AND', - ); - } - - $self->_OpenParen if $null_columns_ok; - - my $date = RT::Date->new( $self->CurrentUser ); - $date->Set( Format => 'unknown', Value => $value ); - - if ( $op eq "=" ) { - - # if we're specifying =, that means we want everything on a - # particular single day. in the database, we need to check for > - # and < the edges of that day. - - $date->SetToMidnight( Timezone => 'server' ); - my $daystart = $date->ISO; - $date->AddDay; - my $dayend = $date->ISO; - - $self->_OpenParen; - - $self->_SQLLimit( - ALIAS => $TicketCFs, - FIELD => 'Content', - OPERATOR => ">=", - VALUE => $daystart, - %rest, - ); - - $self->_SQLLimit( - ALIAS => $TicketCFs, - FIELD => 'Content', - OPERATOR => "<=", - VALUE => $dayend, - %rest, - ENTRYAGGREGATOR => 'AND', - ); - - $self->_CloseParen; - - } - else { - $self->_SQLLimit( - ALIAS => $TicketCFs, - FIELD => 'Content', - OPERATOR => $op, - VALUE => $date->ISO, - %rest, - ); - } - - $self->_CloseParen; - -} - =head2 _CustomFieldLimit Limit based on CustomFields @@ -1830,60 +1733,7 @@ sub OrderByCols { } push @res, { %$row, FIELD => "Priority", ORDER => $order } ; - - } elsif ( $field eq 'Customer' ) { #Freeside - - my $linkalias = $self->Join( - TYPE => 'LEFT', - ALIAS1 => 'main', - FIELD1 => 'id', - TABLE2 => 'Links', - FIELD2 => 'LocalBase' - ); - - $self->SUPER::Limit( - LEFTJOIN => $linkalias, - FIELD => 'Type', - OPERATOR => '=', - VALUE => 'MemberOf', - ); - $self->SUPER::Limit( - LEFTJOIN => $linkalias, - FIELD => 'Target', - OPERATOR => 'STARTSWITH', - VALUE => 'freeside://freeside/cust_main/', - ); - - #if there was a Links.RemoteTarget int, this bs wouldn't be necessary - my $custnum_sql = "CAST(SUBSTR($linkalias.Target,31) AS INTEGER)"; - - if ( $subkey eq 'Number' ) { - - push @res, { %$row, - ALIAS => '', - FIELD => $custnum_sql, - }; - - } elsif ( $subkey eq 'Name' ) { - - my $custalias = $self->Join( - TYPE => 'LEFT', - EXPRESSION => $custnum_sql, - TABLE2 => 'cust_main', - FIELD2 => 'custnum', - - ); - - my $field = "COALESCE( $custalias.company, - $custalias.last || ', ' || $custalias.first - )"; - - push @res, { %$row, ALIAS => '', FIELD => $field }; - - } - - } #Freeside - + } else { push @res, $row; } @@ -2817,11 +2667,6 @@ sub LimitCustomField { $args{CUSTOMFIELD} = $CF->Id; } - # Handle special customfields types - if ($CF->Type eq 'Date') { - $args{FIELD} = 'DateCustomFieldValue'; - } - #If we are looking to compare with a null value. if ( $args{'OPERATOR'} =~ /^is$/i ) { $args{'DESCRIPTION'} diff --git a/rt/lib/RT/URI/freeside.pm b/rt/lib/RT/URI/freeside.pm index 1bd2f534a..6194fd0cb 100644 --- a/rt/lib/RT/URI/freeside.pm +++ b/rt/lib/RT/URI/freeside.pm @@ -202,7 +202,7 @@ sub ParseURI { $pkey = $2; unless ( $pkey ) { - #way too noisy, using this prefix is normal usage# cluck "bad URL $uri"; + cluck "bad URL $uri"; return(undef); } diff --git a/rt/sbin/rt-dump-database b/rt/sbin/rt-dump-database deleted file mode 100755 index ce023adab..000000000 --- a/rt/sbin/rt-dump-database +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/perl -w -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC -# <jesse@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work 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., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -# -# -# CONTRIBUTION SUBMISSION POLICY: -# -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -# -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -# -# END BPS TAGGED BLOCK }}} -use strict; - -# As we specify that XML is UTF-8 and we output it to STDOUT, we must be sure -# it is UTF-8 so further XMLin will not break -binmode(STDOUT, ":utf8"); - -# fix lib paths, some may be relative -BEGIN { - require File::Spec; - my @libs = ("lib", "local/lib"); - my $bin_path; - - for my $lib (@libs) { - unless ( File::Spec->file_name_is_absolute($lib) ) { - unless ($bin_path) { - if ( File::Spec->file_name_is_absolute(__FILE__) ) { - $bin_path = ( File::Spec->splitpath(__FILE__) )[1]; - } - else { - require FindBin; - no warnings "once"; - $bin_path = $FindBin::Bin; - } - } - $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib ); - } - unshift @INC, $lib; - } - -} - -use RT; -use XML::Simple; - -RT::LoadConfig(); -RT::Init(); - -my $LocalOnly = @ARGV ? shift(@ARGV) : 1; - -my %RV; -my %Ignore = ( - All => [qw( - id Created Creator LastUpdated LastUpdatedBy - )], - Templates => [qw( - TranslationOf - )], -); - -my $SystemUserId = $RT::SystemUser->Id; -my @classes = qw( - Users Groups Queues ScripActions ScripConditions - Templates Scrips ACL CustomFields -); -foreach my $class (@classes) { - require "RT/$class.pm"; - my $objects = "RT::$class"->new($RT::SystemUser); - $objects->{find_disabled_rows} = 1; - $objects->UnLimit; - - if ($class eq 'CustomFields') { - $objects->OrderByCols( - { FIELD => 'LookupType' }, - { FIELD => 'SortOrder' }, - { FIELD => 'Id' }, - ); - } - else { - $objects->OrderBy( FIELD => 'Id' ); - } - - if ($LocalOnly) { - next if $class eq 'ACL'; # XXX - would go into infinite loop - XXX - $objects->Limit( FIELD => 'LastUpdatedBy', OPERATOR => '!=', VALUE => $SystemUserId ) - unless $class eq 'Groups'; - $objects->Limit( FIELD => 'Id', OPERATOR => '!=', VALUE => $SystemUserId ) - if $class eq 'Users'; - $objects->Limit( FIELD => 'Domain', OPERATOR => '=', VALUE => 'UserDefined' ) - if $class eq 'Groups'; - } - - my %fields; - while (my $obj = $objects->Next) { - next if $obj->can('LastUpdatedBy') and $obj->LastUpdatedBy == $SystemUserId; - - if (!%fields) { - %fields = map { $_ => 1 } keys %{$obj->_ClassAccessible}; - delete @fields{ - @{$Ignore{$class}||=[]}, - @{$Ignore{All}||=[]}, - }; - } - - my $rv; - # next if $obj-> # skip default names - foreach my $field (sort keys %fields) { - my $value = $obj->__Value($field); - $rv->{$field} = $value if ( defined ($value) && length($value) ); - } - delete $rv->{Disabled} unless $rv->{Disabled}; - - foreach my $record (map { /ACL/ ? 'ACE' : substr($_, 0, -1) } @classes) { - foreach my $key (map "$record$_", ('', 'Id')) { - next unless exists $rv->{$key}; - my $id = $rv->{$key} or next; - my $obj = "RT::$record"->new($RT::SystemUser); - $obj->LoadByCols( Id => $id ) or next; - $rv->{$key} = $obj->__Value('Name') || 0; - } - } - - if ($class eq 'Users' and defined $obj->Privileged) { - $rv->{Privileged} = int($obj->Privileged); - } - elsif ($class eq 'CustomFields') { - my $values = $obj->Values; - while (my $value = $values->Next) { - push @{$rv->{Values}}, { - map { ($_ => $value->__Value($_)) } qw( - Name Description SortOrder - ), - }; - } - } - - if (eval { require RT::Attributes; 1 }) { - my $attributes = $obj->Attributes; - while (my $attribute = $attributes->Next) { - my $content = $attribute->Content; - $rv->{Attributes}{$attribute->Name} = $content if length($content); - } - } - - push @{$RV{$class}}, $rv; - } -} - -print(<< "."); -no strict; use XML::Simple; *_ = XMLin(do { local \$/; readline(DATA) }, ForceArray => [qw( - @classes Values -)], NoAttr => 1, SuppressEmpty => ''); *\$_ = (\$_{\$_} || []) for keys \%_; 1; # vim: ft=xml -__DATA__ -. - -print XMLout( - { map { ($_ => ($RV{$_} || [])) } @classes }, - RootName => 'InitialData', - NoAttr => 1, - SuppressEmpty => '', - XMLDecl => '<?xml version="1.0" encoding="UTF-8"?>', -); diff --git a/rt/share/html/Elements/EditCustomFieldDate b/rt/share/html/Elements/EditCustomFieldDate deleted file mode 100644 index b6359d7e0..000000000 --- a/rt/share/html/Elements/EditCustomFieldDate +++ /dev/null @@ -1,62 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC -%# <jesse@bestpractical.com> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work 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., 51 Franklin Street, Fifth Floor, Boston, MA -%# 02110-1301 or visit their web page on the internet at -%# http://www.gnu.org/copyleft/gpl.html. -%# -%# -%# CONTRIBUTION SUBMISSION POLICY: -%# -%# (The following paragraph is not intended to limit the rights granted -%# to you to modify and distribute this software under the terms of -%# the GNU General Public License and is only of importance to you if -%# you choose to contribute your changes and enhancements to the -%# community by submitting them to Best Practical Solutions, LLC.) -%# -%# By intentionally submitting any modifications, corrections or -%# derivatives to this work, or any other work intended for use with -%# Request Tracker, to Best Practical Solutions, LLC, you confirm that -%# you are the copyright holder for those contributions and you grant -%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -%# royalty-free, perpetual, license to use, copy, create derivative -%# works based on those contributions, and sublicense and distribute -%# those contributions and any derivatives thereof. -%# -%# END BPS TAGGED BLOCK }}} -% my $name = $NamePrefix.$CustomField->Id.'-Values'; -<& /Elements/SelectDate, Name => "$name", ShowTime => 0, current => 0 &> (<%$DateObj->AsString%>) - -<%INIT> -my $DateObj = new RT::Date ( $session{'CurrentUser'} ); -$DateObj->Set( Format => 'ISO', Value => $Default ); -</%INIT> -<%ARGS> -$Object => undef -$CustomField => undef -$NamePrefix => undef -$Default => undef -$Values => undef -$MaxValues => 1 -</%ARGS> diff --git a/rt/share/html/Elements/RT__CustomField/ColumnMap b/rt/share/html/Elements/RT__CustomField/ColumnMap index 0a867eb26..6d8d76a4c 100644 --- a/rt/share/html/Elements/RT__CustomField/ColumnMap +++ b/rt/share/html/Elements/RT__CustomField/ColumnMap @@ -155,9 +155,7 @@ my $COLUMN_MAP = { : ($args->{'PassArguments'}); my %pass = map { $_ => $args->{$_} } grep exists $args->{$_}, @pass; - my $path = $m->request_path; - $path =~ s(^/rt)(); #hacky, dunno why this happens - my $uri = RT->Config->Get('WebPath') . $path; + my $uri = RT->Config->Get('WebPath') . $m->request_path; my @res = ( \'<a href="', diff --git a/rt/share/html/Elements/RT__Ticket/ColumnMap b/rt/share/html/Elements/RT__Ticket/ColumnMap index e848939e1..c1f9e319a 100644 --- a/rt/share/html/Elements/RT__Ticket/ColumnMap +++ b/rt/share/html/Elements/RT__Ticket/ColumnMap @@ -313,25 +313,6 @@ $COLUMN_MAP = { return \$bookmark; }, }, - - Customer => { - title => 'Customer', #loc - attribute => 'Customer', #title/attribute/name... what does it all mean? - value => sub { - my $Ticket = shift; - my @Customers = @{ $Ticket->Customers->ItemsArrayRef }; - my @CustResolvers = map $_->TargetURI->Resolver, @Customers; - my @return = (); - for ( 0 .. $#CustResolvers ) { - my $c = @CustResolvers[$_]; - push @return, \'<A HREF="', $c->HREF, \'">', $c->AsString, \'</A>'; - push @return, \'<BR>' if scalar(@CustResolvers) > 1 - && $_ != $#CustResolvers; - } - @return; - }, - }, - }; # if no GPG support, then KeyOwnerName and KeyRequestors fall back to the regular diff --git a/rt/share/html/Elements/RefreshHomepage b/rt/share/html/Elements/RefreshHomepage index 7840f59cc..bf91a9522 100644 --- a/rt/share/html/Elements/RefreshHomepage +++ b/rt/share/html/Elements/RefreshHomepage @@ -46,13 +46,9 @@ %# %# END BPS TAGGED BLOCK }}} <&|/Widgets/TitleBox, title => loc('Refresh')&> -<form method="get" action="<% RT->Config->Get('WebPath') . $path %>"> +<form method="get" action="<% RT->Config->Get('WebPath') . $m->request_path %>"> <& /Elements/Refresh, Name => 'HomeRefreshInterval', Default => $session{'home_refresh_interval'}||RT->Config->Get('HomePageRefreshInterval', $session{'CurrentUser'}) &> <& /Elements/Submit, Label => loc('Go!') &> </&> </form> -<%init> -my $path = $m->request_path; -$path =~ s(^/rt)(); #hacky, dunno why this happens -</%init> diff --git a/rt/share/html/Elements/SelectDate b/rt/share/html/Elements/SelectDate index 46092ce23..183086f3d 100755 --- a/rt/share/html/Elements/SelectDate +++ b/rt/share/html/Elements/SelectDate @@ -50,14 +50,14 @@ <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $Name %>_date_button" STYLE="cursor: pointer" TITLE="Select date"> <script type="text/javascript"> Calendar.setup({ - inputField: <% $Name |n,js_string %>, + inputField: "<%$Name%>", % if ( defined($ShowTime) && $ShowTime ) { ifFormat: "%Y-%m-%d %H:%M", showsTime: true, % } else { ifFormat: "%Y-%m-%d", % } - button: <% $Name.'_date_button' |n,js_string %>, + button: "<%$Name%>_date_button", }); </script> <%init> diff --git a/rt/share/html/Elements/ShowCustomFieldDate b/rt/share/html/Elements/ShowCustomFieldDate deleted file mode 100644 index 4e8ad676c..000000000 --- a/rt/share/html/Elements/ShowCustomFieldDate +++ /dev/null @@ -1,57 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2008 Best Practical Solutions, LLC -%# <jesse@bestpractical.com> -%# -%# (Except where explicitly superseded by other copyright notices) -%# -%# -%# LICENSE: -%# -%# This work is made available to you under the terms of Version 2 of -%# the GNU General Public License. A copy of that license should have -%# been provided with this software, but in any event can be snarfed -%# from www.gnu.org. -%# -%# This work 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., 51 Franklin Street, Fifth Floor, Boston, MA -%# 02110-1301 or visit their web page on the internet at -%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -%# -%# -%# CONTRIBUTION SUBMISSION POLICY: -%# -%# (The following paragraph is not intended to limit the rights granted -%# to you to modify and distribute this software under the terms of -%# the GNU General Public License and is only of importance to you if -%# you choose to contribute your changes and enhancements to the -%# community by submitting them to Best Practical Solutions, LLC.) -%# -%# By intentionally submitting any modifications, corrections or -%# derivatives to this work, or any other work intended for use with -%# Request Tracker, to Best Practical Solutions, LLC, you confirm that -%# you are the copyright holder for those contributions and you grant -%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -%# royalty-free, perpetual, license to use, copy, create derivative -%# works based on those contributions, and sublicense and distribute -%# those contributions and any derivatives thereof. -%# -%# END BPS TAGGED BLOCK }}} -<%INIT> - my $content = $Object->Content; - my $DateObj = new RT::Date ( $session{'CurrentUser'} ); - $DateObj->Set( Format => 'ISO', Value => $content ); - $content = $DateObj->AsString; -</%INIT> -<%$content|n%> -<%ARGS> -$Object -</%ARGS> diff --git a/rt/share/html/Elements/ShowLink_Checklist b/rt/share/html/Elements/ShowLink_Checklist deleted file mode 100644 index 945305fb6..000000000 --- a/rt/share/html/Elements/ShowLink_Checklist +++ /dev/null @@ -1,36 +0,0 @@ -<a href="<%$URI->Resolver->HREF%>"> -% if ($URI->IsLocal) { -% my $member = $URI->Object; -% if (UNIVERSAL::isa($member, "RT::Ticket")) { -% my $inactive = 0; #$member->QueueObj->IsInactiveStatus($member->Status); - -<span class="<% $inactive ? 'ticket-inactive' : '' %>"> -<IMG SRC="<%$fsurl%>images/<% $status2image{$member->Status} %>.png" BORDER=0> -<%$member->Id%>: (<%$member->OwnerObj->Name%>) <%$member->Subject%> -%# [<% loc($member->Status) %>] -</span> - -% } elsif ( UNIVERSAL::can($member, 'Name')) { -<%$URI->Resolver->AsString%>: <%$member->Name%> -% } else { -<%$URI->Resolver->AsString%> -% } -% } else { -<%$URI->Resolver->AsString%> -% } -</a> -<%ARGS> -$URI => undef -</%ARGS> -<%once> - -my %status2image = ( - 'new' => 'square_add', #'bullet_add', - 'open' => 'square', #'bullet_black', - 'stalled' => 'error', - 'resolved' => 'tick', - 'rejected' => 'cross', - #'deleted' => 'delete', -); - -</%once> diff --git a/rt/share/html/Elements/ShowUserVerbose b/rt/share/html/Elements/ShowUserVerbose index 9b61ea74a..82d65b0b3 100644 --- a/rt/share/html/Elements/ShowUserVerbose +++ b/rt/share/html/Elements/ShowUserVerbose @@ -46,11 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} %# Released under the terms of version 2 of the GNU Public License -% if ( $Address->phrase || $Address->comment ) { -<% sprintf q{%s <%s> %s}, map $Address->$_, qw( phrase address comment ) %> -% } else { -<% $Address->address %> -% } +<%$Address->format%>\ <%INIT> my ($phrase, $address, $comment); diff --git a/rt/share/html/Search/Elements/BuildFormatString b/rt/share/html/Search/Elements/BuildFormatString index 9935fdf91..972851160 100644 --- a/rt/share/html/Search/Elements/BuildFormatString +++ b/rt/share/html/Search/Elements/BuildFormatString @@ -71,9 +71,6 @@ $CurrentDisplayColumns => undef # All the things we can display in the format string by default my @fields = qw( id QueueName Subject - - Customer - Status ExtendedStatus UpdateStatus Type @@ -99,7 +96,6 @@ my @fields = qw( Bookmark NEWLINE - ); # loc_qw $m->callback( CallbackOnce => 1, CallbackName => 'SetFieldsOnce', Fields => \@fields ); diff --git a/rt/share/html/Search/Elements/DisplayOptions b/rt/share/html/Search/Elements/DisplayOptions index 7464ae936..40d976cfd 100644 --- a/rt/share/html/Search/Elements/DisplayOptions +++ b/rt/share/html/Search/Elements/DisplayOptions @@ -115,8 +115,6 @@ $fields{$_}=1 for @cfs; # Add PAW sort $fields{'Custom.Ownership'} = 1; -$fields{"Customer.$_"} = 1 foreach qw( Number Name ); #Freeside - my @Order = split /\|/, $Order; my @OrderBy = split /\|/, $OrderBy; if ($Order =~ /\|/) { diff --git a/rt/share/html/Search/Elements/PickCFs b/rt/share/html/Search/Elements/PickCFs index beda9f733..ba25cdeda 100644 --- a/rt/share/html/Search/Elements/PickCFs +++ b/rt/share/html/Search/Elements/PickCFs @@ -78,41 +78,20 @@ while ( my $CustomField = $CustomFields->Next ) { my %line; $line{'Name'} = "'CF.{" . $CustomField->Name . "}'"; $line{'Field'} = $CustomField->Name; - - # Op - if ($CustomField->Type eq 'Date') { - $line{'Op'} = { - Type => 'component', - Path => '/Elements/SelectDateRelation', - Arguments => {}, - }; - } else { - $line{'Op'} = { - Type => 'component', - Path => '/Elements/SelectCustomFieldOperator', - Arguments => { True => loc("is"), - False => loc("isn't"), - TrueVal=> '=', - FalseVal => '!=', - }, - }; - } - - # Value - if ($CustomField->Type eq 'Date') { - $line{'Value'} = { - Type => 'component', - Path => '/Elements/SelectDate', - Arguments => {}, - }; - } else { - $line{'Value'} = { - Type => 'component', - Path => '/Elements/SelectCustomFieldValue', - Arguments => { CustomField => $CustomField }, - }; - } - + $line{'Op'} = { + Type => 'component', + Path => '/Elements/SelectCustomFieldOperator', + Arguments => { True => loc("is"), + False => loc("isn't"), + TrueVal=> '=', + FalseVal => '!=', + }, + }; + $line{'Value'} = { + Type => 'component', + Path => '/Elements/SelectCustomFieldValue', + Arguments => { CustomField => $CustomField }, + }; push @lines, \%line; } diff --git a/rt/share/html/Ticket/Checklist.html b/rt/share/html/Ticket/Checklist.html deleted file mode 100644 index 7394b0c10..000000000 --- a/rt/share/html/Ticket/Checklist.html +++ /dev/null @@ -1,30 +0,0 @@ -<& /Elements/Header, Title => loc("Checklist for Ticket #[_1] [_2]", $Ticket->Id, $Ticket->Subject) &> -<& /Ticket/Elements/Tabs, - Ticket => $Ticket, current_tab => 'Ticket/Checklist.html?id='.$Ticket->id, - Title => loc("Ticket Checklist # [_1] [_2]", $Ticket->Id, $Ticket->Subject) &> - -<& /Ticket/Elements/ShowMembers_Checklist, Ticket => $Ticket &> - -% if ( $show_hint ) { - -<A HREF="ModifyLinks.html?id=<%$Ticket->id%>">Link</A> -or <A HREF="Create.html?Queue=<%$Ticket->QueueObj->Id%>&new-MemberOf=<%$Ticket->id%>">create</A> -create child tickets to make a checklist. - -% } - -<%ARGS> -$id => undef -</%ARGS> - -<%INIT> - -my $Ticket = LoadTicket ($id); - -unless ($Ticket->CurrentUserHasRight('ShowTicket')) { - Abort("No permission to view ticket"); -} - -my $show_hint = ! $Ticket->Members->Count; - -</%INIT> diff --git a/rt/share/html/Ticket/Elements/BulkLinks b/rt/share/html/Ticket/Elements/BulkLinks index d04eba426..7f87cefb8 100755 --- a/rt/share/html/Ticket/Elements/BulkLinks +++ b/rt/share/html/Ticket/Elements/BulkLinks @@ -163,7 +163,7 @@ $Tickets => undef <%INIT> my %hash; if ( $Tickets && $Tickets->Count ) { - my $first_ticket = $Tickets->Next or last; #avoid errors on bulk delete + my $first_ticket = $Tickets->Next; # we only show current links that eixst on all the tickets for my $type ( qw/DependsOn DependedOnBy Members MemberOf RefersTo ReferredToBy/ ) { diff --git a/rt/share/html/Ticket/Elements/ShowMembers_Checklist b/rt/share/html/Ticket/Elements/ShowMembers_Checklist deleted file mode 100644 index 68fb3b2c5..000000000 --- a/rt/share/html/Ticket/Elements/ShowMembers_Checklist +++ /dev/null @@ -1,29 +0,0 @@ - -<style type="text/css"> -ul.checklist { - list-style-type: none -} -</style> - -<ul class="checklist"> -% while (my $link = $members->Next) { -<li><& /Elements/ShowLink_Checklist, URI => $link->BaseURI &><br /> -% if ($depth < 8) { #why only 8? -<& /Ticket/Elements/ShowMembers_Checklist, Ticket => $link->BaseObj, depth => ($depth+1) &> -% } -</li> -% } -</ul> - -<%INIT> - -return unless $Ticket; -my $members = $Ticket->Members; -return unless $members->Count; - -</%INIT> - -<%ARGS> -$Ticket => undef -$depth => 1 -</%ARGS> diff --git a/rt/share/html/Ticket/Elements/Tabs b/rt/share/html/Ticket/Elements/Tabs index 6943a2703..c893a350c 100755 --- a/rt/share/html/Ticket/Elements/Tabs +++ b/rt/share/html/Ticket/Elements/Tabs @@ -142,10 +142,6 @@ if ($Ticket) { title => loc('Links'), path => "Ticket/ModifyLinks.html?id=" . $id, }, - _Ea => { - title => loc('Checklist'), - path => "Ticket/Checklist.html?id=" . $id, - }, _Eb=> { title => loc('Customers'), path => "Ticket/ModifyCustomers.html?id=" . $id, diff --git a/rt/share/html/Ticket/Graphs/index.html b/rt/share/html/Ticket/Graphs/index.html index 211d3a0cb..e23737c8e 100644 --- a/rt/share/html/Ticket/Graphs/index.html +++ b/rt/share/html/Ticket/Graphs/index.html @@ -56,9 +56,7 @@ <& Elements/ShowGraph, %ARGS, Ticket => $ticket &> -% my $path = $m->request_comp->path; -% $path =~ s(^/rt)(); #hacky, dunno why this happens -<form action="<% RT->Config->Get('WebPath') . $path %>"> +<form action="<% RT->Config->Get('WebPath') . $m->request_comp->path %>"> <input type="hidden" class="hidden" name="id" value="<% $id %>" /> <& Elements/EditGraphProperties, %ARGS, Ticket => $ticket &> |