This commit was manufactured by cvs2svn to create tag 'freeside_2_1_1'. freeside_2_1_1
authorcvs2git <cvs2git>
Fri, 5 Nov 2010 19:05:58 +0000 (19:05 +0000)
committercvs2git <cvs2git>
Fri, 5 Nov 2010 19:05:58 +0000 (19:05 +0000)
163 files changed:
FS/FS/AccessRight.pm
FS/FS/ClientAPI/MyAccount.pm
FS/FS/ClientAPI/Signup.pm
FS/FS/Conf.pm
FS/FS/ConfDefaults.pm
FS/FS/Cron/backup.pm
FS/FS/Cron/bill.pm
FS/FS/Cron/notify.pm
FS/FS/Mason.pm
FS/FS/Misc.pm
FS/FS/Record.pm
FS/FS/Schema.pm
FS/FS/access_right.pm
FS/FS/access_user.pm
FS/FS/agent_type.pm
FS/FS/cdr.pm
FS/FS/contact.pm
FS/FS/contact_phone.pm
FS/FS/cust_bill.pm
FS/FS/cust_bill_pkg_detail.pm
FS/FS/cust_credit.pm
FS/FS/cust_location.pm
FS/FS/cust_main.pm
FS/FS/cust_main/Billing.pm
FS/FS/cust_main/Packages.pm
FS/FS/cust_main/Search.pm
FS/FS/cust_main_Mixin.pm
FS/FS/cust_pay.pm
FS/FS/cust_pay_void.pm
FS/FS/cust_pkg.pm
FS/FS/cust_refund.pm
FS/FS/domain_record.pm
FS/FS/geocode_Mixin.pm [deleted file]
FS/FS/msg_template.pm
FS/FS/option_Common.pm
FS/FS/part_event/Condition/cust_status.pm
FS/FS/part_event/Condition/has_referral_custnum.pm
FS/FS/part_event/Condition/pkg_age.pm
FS/FS/part_event/Condition/pkg_recurring.pm
FS/FS/part_event/Condition/pkg_status.pm
FS/FS/part_export/acct_http.pm [deleted file]
FS/FS/part_export/cust_http.pm
FS/FS/part_export/http.pm
FS/FS/part_export/rt_ticket.pm [deleted file]
FS/FS/part_export/sqlradius.pm
FS/FS/part_pkg.pm
FS/FS/part_pkg/agent.pm
FS/FS/part_pkg/bulk.pm
FS/FS/part_pkg/cdr_termination.pm
FS/FS/part_pkg/discount_Mixin.pm [deleted file]
FS/FS/part_pkg/flat.pm
FS/FS/part_pkg/prorate.pm
FS/FS/part_pkg/prorate_Mixin.pm
FS/FS/part_pkg/recur_Common.pm
FS/FS/part_pkg/sql_external.pm
FS/FS/part_pkg/subscription.pm
FS/FS/part_pkg/voip_cdr.pm
FS/FS/part_pkg/voip_inbound.pm
FS/FS/part_pkg_option.pm
FS/FS/svc_Common.pm
FS/FS/svc_acct.pm
FS/FS/svc_pbx.pm
FS/FS/svc_phone.pm
FS/bin/freeside-daily
FS/bin/freeside-monthly
FS/bin/freeside-radgroup
FS/bin/freeside-upgrade
Makefile
bin/cust_main-find_bogus_geocode [deleted file]
bin/freeside-backup [deleted file]
bin/merge-referrals [deleted file]
bin/rt-trim-whitespace [deleted file]
conf/invoice_latex_statement
eg/cdr_template.pm
httemplate/browse/part_event.html
httemplate/browse/part_pkg.cgi
httemplate/edit/REAL_cust_pkg.cgi
httemplate/edit/access_user.html
httemplate/edit/bulk-cust_pkg.html [deleted file]
httemplate/edit/cust_main.cgi
httemplate/edit/cust_main/billing.html
httemplate/edit/cust_main/bottomfixup.js
httemplate/edit/cust_main/contact.html
httemplate/edit/cust_main/first_pkg.html
httemplate/edit/cust_main/first_pkg/select-part_pkg.html
httemplate/edit/cust_main/top_misc.html
httemplate/edit/cust_pay.cgi
httemplate/edit/cust_pay_pending.html
httemplate/edit/cust_refund.cgi
httemplate/edit/domain_record.html [deleted file]
httemplate/edit/elements/edit.html
httemplate/edit/msg_template.html
httemplate/edit/part_export.cgi
httemplate/edit/part_pkg.cgi
httemplate/edit/process/REAL_cust_pkg.cgi
httemplate/edit/process/access_user.html
httemplate/edit/process/bulk-cust_pkg.cgi [deleted file]
httemplate/edit/process/cust_pay.cgi
httemplate/edit/process/cust_refund.cgi
httemplate/edit/process/domain_record.cgi
httemplate/edit/process/part_pkg.cgi
httemplate/edit/process/prospect_main.html
httemplate/edit/process/quick-cust_pkg.cgi
httemplate/edit/process/svc_domain-defaultrecords.cgi
httemplate/edit/prospect_main-ocr.html [deleted file]
httemplate/edit/prospect_main-upload.html [deleted file]
httemplate/edit/prospect_main.html
httemplate/elements/contact.html
httemplate/elements/freeside.css
httemplate/elements/input-date-field.html
httemplate/elements/menu.html
httemplate/elements/popup_link.html
httemplate/elements/search-cust_main.html
httemplate/elements/select-month_year.html
httemplate/elements/select-state.html
httemplate/elements/select-terms.html
httemplate/elements/standardize_locations.html [deleted file]
httemplate/elements/standardize_locations.js [deleted file]
httemplate/elements/tr-pkg_svc.html
httemplate/elements/tr-select-cust_tag.html
httemplate/misc/change_pkg.cgi
httemplate/misc/choose_tax_location.html [deleted file]
httemplate/misc/cust_main-merge.html [deleted file]
httemplate/misc/delete-domain_record.cgi
httemplate/misc/email-customers.html
httemplate/misc/merge_cust.html [deleted file]
httemplate/misc/order_pkg.html
httemplate/misc/unprovision.cgi
httemplate/misc/xmlhttp-cust_main-address_standardize.html
httemplate/misc/xmlhttp-cust_main-search.cgi
httemplate/search/cdr.html
httemplate/search/cust_bill_pkg.cgi
httemplate/search/cust_main.cgi
httemplate/search/cust_main.html
httemplate/search/cust_pay_pending.html
httemplate/search/cust_pkg.cgi
httemplate/search/cust_pkg_svc.html [deleted file]
httemplate/search/report_cdr.html
httemplate/search/report_cust_main.html
httemplate/search/report_cust_pkg.html
httemplate/search/svc_acct.cgi
httemplate/view/cust_bill.cgi
httemplate/view/cust_main.cgi
httemplate/view/cust_main/billing.html
httemplate/view/cust_main/contacts.html
httemplate/view/cust_main/packages.html
httemplate/view/cust_main/packages/services.html
httemplate/view/cust_main/packages/status.html
httemplate/view/cust_main/payment_history.html
httemplate/view/cust_main/payment_history/payment.html
httemplate/view/cust_main/payment_history/pending_payment.html [deleted file]
httemplate/view/cust_main/payment_history/voided_payment.html
httemplate/view/cust_pay.html
httemplate/view/elements/svc_Common.html
httemplate/view/image.cgi [deleted file]
httemplate/view/svc_domain/dns.html
httemplate/view/svc_pbx.cgi [deleted file]
rt/FREESIDE_MODIFIED
rt/etc/schema.mysql-4.1
rt/lib/RT/Tickets_Overlay.pm
rt/share/html/Admin/CustomFields/Modify.html
rt/share/html/Elements/AddCustomers
rt/share/html/Ticket/Elements/AddCustomers

index e7d77b5..92c4d22 100644 (file)
@@ -113,7 +113,6 @@ tie my %rights, 'Tie::IxHash',
     'View customer history',
     'Cancel customer',
     'Complimentary customer', #aka users-allow_comp 
-    'Merge customer',
     { 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
@@ -183,16 +182,15 @@ tie my %rights, 'Tie::IxHash',
   # customer payment rights
   ###
   'Customer payment rights' => [
-    { rightname=>'Post payment', desc=>'Make check or cash payments.' },
-    'Post check payment',
-    'Post cash payment',
+    'Post payment',
     'Post payment batch',
     'Apply payment', #NEWNEW
     { rightname=>'Unapply payment', desc=>'Enable "unapplication" of unclosed payments from specific invoices.' }, #aka. unapplypayments
-    { rightname=>'Process payment', desc=>'Process credit card or e-check payments' },
-    'Process credit card payment',
-    'Process Echeck payment',
+    'Process payment',
+    { rightname=>'Refund payment', desc=>'Enable refund of existing customer payments.' },
+
     { rightname=>'Delete payment', desc=>'Enable deletion of unclosed payments. Be very careful!  Only delete payments that were data-entry errors, not adjustments.' }, #aka. deletepayments Optionally specify one or more comma-separated email addresses to be notified when a payment is deleted.
+  
   ],
   
   ###
@@ -204,12 +202,7 @@ tie my %rights, 'Tie::IxHash',
     { rightname=>'Unapply credit', desc=>'Enable "unapplication" of unclosed credits.' }, #aka unapplycredits
     { rightname=>'Delete credit', desc=>'Enable deletion of unclosed credits. Be very careful!  Only delete credits that were data-entry errors, not adjustments.' }, #aka. deletecredits Optionally specify one or more comma-separated email addresses to be notified when a credit is deleted.
     { rightname=>'Post refund', desc=>'Enable posting of check and cash refunds.' },
-    'Post check refund',
-    'Post cash refund',
 #    { rightname=>'Process refund', desc=>'Enable processing of generic credit card/ACH refunds (i.e. not associated with a specific prior payment).' },
-    { rightname=>'Refund payment', desc=>'Enable refund of existing customer credit card or e-check payments.' },
-    'Refund credit card payment',
-    'Refund Echeck payment',
     'Delete refund', #NEW
     'Add on-the-fly credit reason', #NEW
   ],
@@ -353,8 +346,6 @@ sub default_superuser_rights {
     'Redownload resolved batches',
     'Raw SQL',
     'Configuration download',
-    'View customers of all agents',
-    'View/link unlinked services',
   );
 
   no warnings 'uninitialized';
index 1e1d1d3..dbcef7d 100644 (file)
@@ -596,7 +596,7 @@ sub process_payment {
   my $amount = $1;
   return { error => 'Amount must be greater than 0' } unless $amount > 0;
 
-  $p->{'discount_term'} =~ /^\s*(\d*)\s*$/
+  $p->{'discount_term'} =~ /^\s*(\d+)\s*$/
     or return { 'error' => gettext('illegal_discount_term'). ': '. $p->{'discount_term'} };
   my $discount_term = $1;
 
index 65bb4e3..ec45e79 100644 (file)
@@ -93,31 +93,7 @@ sub signup_info {
 
     my @agent_fields = qw( agentnum agent );
 
-    my @bools = qw( emailinvoiceonly security_phrase );
-
-    my @signup_bools = qw( no_company recommend_daytime recommend_email );
-
-    my @signup_server_scalars = qw( default_pkgpart default_svcpart );
-
-    my @selfservice_textareas = qw( head body_header body_footer );
-
-    my @selfservice_scalars = qw(
-      body_bgcolor box_bgcolor
-      text_color link_color vlink_color hlink_color alink_color
-      font title_color title_align title_size menu_bgcolor menu_fontsize
-    );
-
-    #XXX my @selfservice_bools = qw(
-    #  menu_skipblanks menu_skipheadings menu_nounderline
-    #);
-
-    #my $selfservice_binaries = qw(
-    #  title_left_image title_right_image
-    #  menu_top_image menu_body_image menu_bottom_image
-    #);
-
     $signup_info_cache = {
-
       'cust_main_county' => [ map $_->hashref,
                                   qsearch('cust_main_county', {} )
                             ],
@@ -149,44 +125,46 @@ sub signup_info {
 
       'card_types' => card_types(),
 
-      ( map { $_ => $conf->exists("signup-$_") } @signup_bools ),
-
-      ( map { $_ => scalar($conf->config("signup_server-$_")) }
-            @signup_server_scalars
-      ),
-
-      ( map { $_ => join("\n", $conf->config("selfservice-$_")) }
-            @selfservice_textareas
-      ),
-      ( map { $_ => scalar($conf->config("selfservice-$_")) }
-            @selfservice_scalars
-      ),
-
-      #( map { $_ => scalar($conf->config_binary("selfservice-$_")) }
-      #      @selfservice_binaries
-      #),
-
-      'agentnum2part_pkg'  => $agentnum2part_pkg,
-      'svc_acct_pop'       => [ map $_->hashref, qsearch('svc_acct_pop',{} ) ],
-      'nomadix'            => $conf->exists('signup_server-nomadix'),
-      'payby'              => [ $conf->config('signup_server-payby') ],
-      'card_types'         => card_types(),
-      'paytypes'           => [ @FS::cust_main::paytypes ],
-      'cvv_enabled'        => 1,
-      'stateid_enabled'    => $conf->exists('show_stateid'),
-      'paystate_enabled'   => $conf->exists('show_bankstate'),
-      'ship_enabled'       => 1,
-      'msgcat'             => $msgcat,
-      'label'              => $label,
-      'statedefault'       => scalar($conf->config('statedefault')) || 'CA',
-      'countrydefault'     => scalar($conf->config('countrydefault')) || 'US',
-      'refnum'             => scalar($conf->config('signup_server-default_refnum')),
-      'signup_service'     => $svc_x,
-      'company_name'       => scalar($conf->config('company_name')),
+      'paytypes' => [ @FS::cust_main::paytypes ],
+
+      'cvv_enabled' => 1,
+
+      'stateid_enabled' => $conf->exists('show_stateid'),
+
+      'paystate_enabled' => $conf->exists('show_bankstate'),
+
+      'ship_enabled' => 1,
+
+      'msgcat' => $msgcat,
+
+      'label' => $label,
+
+      'statedefault' => scalar($conf->config('statedefault')) || 'CA',
+
+      'countrydefault' => scalar($conf->config('countrydefault')) || 'US',
+
+      'refnum' => scalar($conf->config('signup_server-default_refnum')),
+
+      'default_pkgpart' => scalar($conf->config('signup_server-default_pkgpart')),
+
+      'signup_service' => $svc_x,
+      'default_svcpart' => scalar($conf->config('signup_server-default_svcpart')),
+
+      'head'         => join("\n", $conf->config('selfservice-head') ),
+      'body_header'  => join("\n", $conf->config('selfservice-body_header') ),
+      'body_footer'  => join("\n", $conf->config('selfservice-body_footer') ),
+      'body_bgcolor' => scalar( $conf->config('selfservice-body_bgcolor') ),
+      'box_bgcolor'  => scalar( $conf->config('selfservice-box_bgcolor')  ),
+
+      'company_name'   => scalar($conf->config('company_name')),
+
       #per-agent?
       'agent_ship_address' => scalar($conf->exists('agent-ship_address')),
-      'require_phone'      => scalar($conf->exists('cust_main-require_phone')),
-      'logo'               => scalar($conf->config_binary('logo.png')),
+
+      'no_company'        => scalar($conf->exists('signup-no_company')),
+      'require_phone'     => scalar($conf->exists('cust_main-require_phone')),
+      'recommend_daytime' => scalar($conf->exists('signup-recommend_daytime')),
+      'recommend_email'   => scalar($conf->exists('signup-recommend_email')),
 
     };
 
@@ -390,7 +368,7 @@ sub signup_info {
         #( map { $_ => scalar( $conf->config($_, $agentnum) ) }
         #  qw( company_name ) ),
         ( map { $_ => scalar( $conf->config("selfservice-$_", $agentnum ) ) }
-          qw( body_bgcolor box_bgcolor menu_bgcolor ) ),
+          qw( body_bgcolor box_bgcolor) ),
         ( map { $_ => join("\n", $conf->config("selfservice-$_", $agentnum ) ) }
           qw( head body_header body_footer ) ),
       };
@@ -609,7 +587,7 @@ sub new_customer {
       push @acct_snarf, $acct_snarf;
     }
     $svc->child_objects( \@acct_snarf );
-    push @svc, $svc;
+
 
   } elsif ( $svc_x eq 'svc_phone' ) {
 
@@ -630,6 +608,8 @@ sub new_customer {
   } else {
     die "unknown signup service $svc_x";
   }
+  my $y = $svc[0]->setdefault; # arguably should be in new method
+  return { 'error' => $y } if $y && !ref($y);
 
   if ($packet->{'mac_addr'} && $conf->exists('signup_server-mac_addr_svcparts'))
   {
@@ -648,16 +628,15 @@ sub new_customer {
       '_password' => '', #blank as requested (set passwordmin to 0)
     };
 
+    my $y = $svc->setdefault; # arguably should be in new method
+    return { 'error' => $y } if $y && !ref($y);
+
     push @svc, $svc;
 
   }
 
-  foreach my $svc ( @svc ) {
-    my $y = $svc->setdefault; # arguably should be in new method
-    return { 'error' => $y } if $y && !ref($y);
-    #$error = $svc->check;
-    #return { 'error' => $error } if $error;
-  }
+  #$error = $svc->check;
+  #return { 'error' => $error } if $error;
 
   #setup a job dependancy to delay provisioning
   my $placeholder = new FS::queue ( {
@@ -751,25 +730,20 @@ sub new_customer {
 
   my %return = ( 'error'          => '',
                  'signup_service' => $svc_x,
+                 'svcnum'         => $svc[0]->svcnum,
                  'custnum'        => $cust_main->custnum,
                );
 
-  if ( $svc[0] ) {
-
-    $return{'svcnum'} = $svc[0]->svcnum;
-
-    if ( $svc_x eq 'svc_acct' ) {
-      $return{$_} = $svc[0]->$_() for qw( username _password );
-    } elsif ( $svc_x eq 'svc_phone' ) {
-      $return{$_} = $svc[0]->$_() for qw(countrycode phonenum sip_password pin);
-    } elsif ( $svc_x eq 'svc_pbx' ) {
-      #$return{$_} = $svc[0]->$_() for qw( ) #nothing yet
-     } else {
-      return {'error' => "configuration error: unknown signup service $svc_x"};
-      #die "unknown signup service $svc_x";
-      # return an error that's visible to someone somewhere
-    }
-
+  if ( $svc_x eq 'svc_acct' ) {
+    $return{$_} = $svc[0]->$_() for qw( username _password );
+  } elsif ( $svc_x eq 'svc_phone' ) {
+    $return{$_} = $svc[0]->$_() for qw( countrycode phonenum sip_password pin );
+  } elsif ( $svc_x eq 'svc_pbx' ) {
+    #$return{$_} = $svc[0]->$_() for qw( ) #nothing yet
+  } else {
+    return { 'error' => "configuration error: unknown signup service $svc_x" };
+    #die "unknown signup service $svc_x";
+    # return an error that's visible to someone somewhere
   }
 
   return \%return;
index 8fce990..b3e5477 100644 (file)
@@ -395,7 +395,6 @@ sub verify_config_item {
 
   } else {
 
-    no warnings 'uninitialized';
     $error .= "$key fails binary comparison; "
       unless scalar($self->config_binary($key)) eq scalar($compat->config_binary($key));
 
@@ -1182,7 +1181,7 @@ and customer address. Include units.',
     'section'     => 'invoicing',
     'description' => 'Optional default invoice term, used to calculate a due date printed on invoices.',
     'type'        => 'select',
-    'select_enum' => [ '', 'Payable upon receipt', 'Net 0', 'Net 10', 'Net 15', 'Net 20', 'Net 30', 'Net 45', 'Net 60', 'Net 90' ],
+    'select_enum' => [ '', 'Payable upon receipt', 'Net 0', 'Net 10', 'Net 15', 'Net 20', 'Net 30', 'Net 45', 'Net 60' ],
   },
 
   { 
@@ -1626,20 +1625,6 @@ and customer address. Include units.',
     'type'        => 'checkbox',
   },
 
-  { 
-    'key'         => 'username-slash',
-    'section'     => 'username',
-    'description' => 'Allow the slash character (/) in usernames.  When using, make sure to set "Home directory" to fixed and blank in all svc_acct service definitions.',
-    'type'        => 'checkbox',
-  },
-
-  { 
-    'key'         => 'username-equals',
-    'section'     => 'username',
-    'description' => 'Allow the equal sign character (=) in usernames.',
-    'type'        => 'checkbox',
-  },
-
   {
     'key'         => 'safe-part_bill_event',
     'section'     => 'UI',
@@ -2319,15 +2304,7 @@ and customer address. Include units.',
   {
     'key'         => 'global_unique-pbx_title',
     'section'     => '',
-    'description' => 'Global phone number uniqueness control: none (check uniqueness per exports), enabled (check across all services), or disabled (no duplicate checking).',
-    'type'        => 'select',
-    'select_enum' => [ 'enabled', 'disabled' ],
-  },
-
-  {
-    'key'         => 'global_unique-pbx_id',
-    'section'     => '',
-    'description' => 'Global PBX id uniqueness control: none (check uniqueness per exports), enabled (check across all services), or disabled (no duplicate checking).',
+    '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' ],
   },
@@ -2499,7 +2476,7 @@ and customer address. Include units.',
   {
     'key'         => 'address1-search',
     'section'     => 'UI',
-    'description' => 'Enable the ability to search the address1 field from the quick customer search.  Not recommended in most cases as it tends to bring up too many search results - use explicit address searching from the advanced customer search instead.',
+    'description' => 'Enable the ability to search the address1 field from customer search.',
     'type'        => 'checkbox',
   },
 
@@ -2654,13 +2631,6 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'cust_pkg-large_pkg_size',
-    'section'     => 'UI',
-    'description' => "In customer view, summarize packages with more than this many services.  Set to zero to never summarize packages.",
-    'type'        => 'text',
-  },
-
-  {
     'key'         => 'svc_acct-edit_uid',
     'section'     => 'shell',
     'description' => 'Allow UID editing.',
@@ -2705,7 +2675,7 @@ and customer address. Include units.',
   {
     'key'         => 'voip-cdr_email',
     'section'     => '',
-    'description' => 'Include the call details on emailed invoices (and HTML invoices viewed in the backend), even if the customer is configured for not printing them on the invoices.',
+    'description' => 'Include the call details on emailed invoices even if the customer is configured for not printing them on the invoices.',
     'type'        => 'checkbox',
   },
 
@@ -2747,7 +2717,7 @@ and customer address. Include units.',
   {
     'key'         => 'tax-pkg_address',
     'section'     => 'billing',
-    'description' => 'By default, tax calculations are done based on the billing address.  Enable this switch to calculate tax based on the package address instead (when present).',
+    'description' => 'By default, tax calculations are done based on the billing address.  Enable this switch to calculate tax based on the package address instead (when present).  Note that this option is currently incompatible with vendor data taxation enabled by enable_taxproducts.',
     'type'        => 'checkbox',
   },
 
@@ -4021,13 +3991,6 @@ and customer address. Include units.',
     'type'        => 'text',
   },
 
-  {
-    'key'         => 'part_pkg-default_suspend_bill',
-    'section'     => 'billing',
-    'description' => 'Default the "Continue recurring billing while suspended" flag to on for new package definitions.',
-    '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" },
index de65b44..12c82e6 100644 (file)
@@ -49,22 +49,22 @@ sub cust_fields_avail { (
     'custnum | Status | Last, First | Company | (same for service contact if present)',
 
   'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Invoicing email(s)' => 
-    'custnum | Status | Last, First | Company | (address) | Day phone | Night phone | Invoicing email(s)',
+    'custnum | Status | Last, First | Company | (all address fields) | Day phone | Night phone | Invoicing email(s)',
 
   'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Fax number | Invoicing email(s) | Payment Type' => 
-    'custnum | Status | Last, First | Company | (address) | (all phones) | Invoicing email(s) | Payment Type',
+    'custnum | Status | Last, First | Company | (all address fields) | (all phones) | Invoicing email(s) | Payment Type',
 
   'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Fax number | Invoicing email(s) | Payment Type | Current Balance' => 
-    'custnum | Status | Last, First | Company | (address) | (all phones) | Invoicing email(s) | Payment Type | Current Balance',
+    'custnum | Status | Last, First | Company | (all address fields) | (all phones) | Invoicing email(s) | Payment Type | Current Balance',
 
   'Cust# | Cust. Status | (bill) Name | (bill) Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Day phone | (bill) Night phone | (service) Name | (service) Company | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Day phone | (service) Night phone | Invoicing email(s)' => 
-    'custnum | Status | Last, First | Company | (address) | Day phone | Night phone | (service address) | Invoicing email(s)',
+    'custnum | Status | Last, First | Company | (all address fields) | Day phone | Night phone | (service address) | Invoicing email(s)',
 
   'Cust# | Cust. Status | (bill) Name | (bill) Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Day phone | (bill) Night phone | (bill) Fax number | (service) Name | (service) Company | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Day phone | (service) Night phone | (service) Fax number | Invoicing email(s) | Payment Type' => 
-    'custnum | Status | Last, First | Company | (address) | (all phones) | (service address) | Invoicing email(s) | Payment Type',
+    'custnum | Status | Last, First | Company | (all address fields) | (all phones) | (service address) | Invoicing email(s) | Payment Type',
 
   'Cust# | Cust. Status | (bill) Name | (bill) Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Day phone | (bill) Night phone | (bill) Fax number | (service) Name | (service) Company | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Day phone | (service) Night phone | (service) Fax number | Invoicing email(s) | Payment Type | Current Balance' => 
-    'custnum | Status | Last, First | Company | (address) | (all phones) | (service address) | Invoicing email(s) | Payment Type | Current Balance',
+    'custnum | Status | Last, First | Company | (all address fields) | (all phones) | (service address) | Invoicing email(s) | Payment Type | Current Balance',
 
   'Invoicing email(s)' => 'Invoicing email(s)',
   'Cust# | Invoicing email(s)' => 'custnum | Invoicing email(s)',
index 9d88261..204069a 100644 (file)
@@ -3,7 +3,6 @@ package FS::Cron::backup;
 use strict;
 use vars qw( @ISA @EXPORT_OK );
 use Exporter;
-use Date::Format;
 use FS::UID qw(driver_name datasrc);
 
 @ISA = qw( Exporter );
@@ -13,7 +12,6 @@ sub backup_scp {
   my $conf = new FS::Conf;
   my $dest = $conf->config('dump-scpdest');
   if ( $dest ) {
-    $dest .= time2str('/%Y%m%d%H%M%S',time);
     datasrc =~ /dbname=([\w\.]+)$/ or die "unparsable datasrc ". datasrc;
     my $database = $1;
     eval "use Net::SCP qw(scp);";
@@ -32,11 +30,11 @@ sub backup_scp {
                      recipient => $conf->config('dump-pgpid'),
                    );
       chmod 0600, '/var/tmp/$database.gpg';
-      scp("/var/tmp/$database.gpg", "$dest.gpg");
+      scp("/var/tmp/$database.gpg", $dest);
       unlink "/var/tmp/$database.gpg" or die $!;
     } else {
       chmod 0600, '/var/tmp/$database.sql';
-      scp("/var/tmp/$database.sql", "$dest.sql");
+      scp("/var/tmp/$database.sql", $dest);
     }
     unlink "/var/tmp/$database.sql" or die $!;
   }
index 7388733..5de2ee3 100644 (file)
@@ -5,7 +5,7 @@ use vars qw( @ISA @EXPORT_OK );
 use Exporter;
 use Date::Parse;
 use DBI 1.33; #The "clone" method was added in DBI 1.33. 
-use FS::UID qw( dbh driver_name );
+use FS::UID qw(dbh);
 use FS::Record qw( qsearch qsearchs );
 use FS::queue;
 use FS::cust_main;
@@ -56,20 +56,14 @@ sub bill {
 
   my $cursor_dbh = dbh->clone;
 
-  my $select = 'SELECT custnum FROM cust_main WHERE '. bill_where( %opt );
-
-  unless ( driver_name =~ /^mysql/ ) {
-    $cursor_dbh->do( "DECLARE cron_bill_cursor CURSOR FOR $select" )
-      or die $cursor_dbh->errstr;
-  }
+  $cursor_dbh->do(
+    "DECLARE cron_bill_cursor CURSOR FOR ".
+    "  SELECT custnum FROM cust_main WHERE ". bill_where( %opt )
+  ) or die $cursor_dbh->errstr;
 
   while ( 1 ) {
 
-    my $sql = (driver_name =~ /^mysql/)
-      ? $select
-      : 'FETCH 100 FROM cron_bill_cursor';
-
-    my $sth = $cursor_dbh->prepare($sql);
+    my $sth = $cursor_dbh->prepare('FETCH 100 FROM cron_bill_cursor'); #mysql?
 
     $sth->execute or die $sth->errstr;
 
@@ -126,8 +120,6 @@ sub bill {
 
     }
 
-    last if driver_name =~ /^mysql/;
-
   }
 
   $cursor_dbh->commit or die $cursor_dbh->errstr;
index 3d427b2..dcc7b30 100644 (file)
@@ -37,7 +37,7 @@ sub notify_flat_delay {
                 and 0 < ( select count(*) from part_pkg_option
                             where part_pkg.pkgpart = part_pkg_option.pkgpart
                               and part_pkg_option.optionname = 'recur_notify'
-                              and CAST( part_pkg_option.optionvalue AS $integer ) > 0
+                              and CAST( part_pkg_option.optionvalue AS INTEGER ) > 0
                               and 0 <= ( $time
                                          + CAST( part_pkg_option.optionvalue AS $integer )
                                            * 86400
@@ -64,7 +64,7 @@ END
       0 = ( select count(*) from cust_pkg_option
               where cust_pkg.pkgnum = cust_pkg_option.pkgnum
                 and cust_pkg_option.optionname = 'impending_recur_notification_sent'
-                and CAST( cust_pkg_option.optionvalue AS $integer ) = 1
+                and CAST( cust_pkg_option.optionvalue AS INTEGER ) = 1
           )
 END
   
index 550ea1a..2282bc5 100644 (file)
@@ -126,7 +126,7 @@ if ( -e $addl_handler_use_file ) {
   use FS::UI::Web::small_custview qw(small_custview);
   use FS::UI::bytecount;
   use FS::Msgcat qw(gettext geterror);
-  use FS::Misc qw( send_email send_fax ocr_image
+  use FS::Misc qw( send_email send_fax
                    states_hash counties cities state_label
                  );
   use FS::Misc::eps2png qw( eps2png );
index fe8ac60..0e8d92b 100644 (file)
@@ -20,7 +20,6 @@ use Tie::IxHash;
                  pkg_freqs
                  generate_ps generate_pdf do_print
                  csv_from_fixed
-                 ocr_image
                );
 
 $DEBUG = 0;
@@ -851,41 +850,6 @@ sub csv_from_fixed {
   '';
 }
 
-=item ocr_image IMAGE_SCALAR
-
-Runs OCR on the provided image data and returns a list of text lines.
-
-=cut
-
-sub ocr_image {
-  my $logo_data = shift;
-
-  #XXX use conf dir location from Makefile
-  my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
-  my $fh = new File::Temp(
-    TEMPLATE => 'bizcard.XXXXXXXX',
-    SUFFIX   => '.png', #XXX assuming, but should handle jpg, gif, etc. too
-    DIR      => $dir,
-    UNLINK   => 0,
-  ) or die "can't open temp file: $!\n";
-
-  my $filename = $fh->filename;
-
-  print $fh $logo_data;
-  close $fh;
-
-  run( [qw(ocroscript recognize), $filename], '>'=>"$filename.hocr" )
-    or die "ocroscript recognize failed\n";
-
-  run( [qw(ocroscript hocr-to-text), "$filename.hocr"], '>pipe'=>\*OUT )
-    or die "ocroscript hocr-to-text failed\n";
-
-  my @lines = split(/\n/, <OUT> );
-
-  foreach (@lines) { s/\.c0m\s*$/.com/; }
-
-  @lines;
-}
 
 =back
 
index 92f503f..4f0984c 100644 (file)
@@ -2171,7 +2171,7 @@ sub ut_text {
   #warn "notexist ". \&notexist. "\n";
   #warn "AUTOLOAD ". \&AUTOLOAD. "\n";
   $self->getfield($field)
-    =~ /^([µ_0123456789aAáÁàÀâÂåÅäÄãêæÆbBcCçÇdDðÐeEéÉèÈêÊëËfFgGhHiIíÍìÌîÎïÏjJkKlLmMnNñÑoOóÓòÒôÔöÖõÕøغpPqQrRsSßtTuUúÚùÙûÛüÜvVwWxXyYýÝÿzZþÞ \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]\<\>]+)$/
+    =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]\<\>]+)$/
       or return gettext('illegal_or_empty_text'). " $field: ".
                  $self->getfield($field);
   $self->setfield($field,$1);
@@ -2458,9 +2458,7 @@ May not be null.
 
 sub ut_name {
   my( $self, $field ) = @_;
-#  warn "ut_name allowed alphanumerics: +(sort grep /\w/, map { chr() } 0..255), "\n";
-  #$self->getfield($field) =~ /^([\w \,\.\-\']+)$/
-  $self->getfield($field) =~ /^([µ_0123456789aAáÁàÀâÂåÅäÄãêæÆbBcCçÇdDðÐeEéÉèÈêÊëËfFgGhHiIíÍìÌîÎïÏjJkKlLmMnNñÑoOóÓòÒôÔöÖõÕøغpPqQrRsSßtTuUúÚùÙûÛüÜvVwWxXyYýÝÿzZþÞ \,\.\-\']+)$/
+  $self->getfield($field) =~ /^([\w \,\.\-\']+)$/
     or return gettext('illegal_name'). " $field: ". $self->getfield($field);
   $self->setfield($field,$1);
   '';
index 1838036..a601843 100644 (file)
@@ -831,8 +831,8 @@ sub tables_hashref {
         'last',      'varchar',     '', $char_d, '', '', 
 #        'middle',    'varchar', 'NULL', $char_d, '', '', 
         'first',     'varchar',     '', $char_d, '', '', 
-        'title',     'varchar', 'NULL', $char_d, '', '', #eg Head Bottle Washer
-        'comment',   'varchar', 'NULL', $char_d, '', '', 
+        'title',     'varchar',     '', $char_d, '', '', #eg Head Bottle Washer
+        'comment',   'varchar',     '', $char_d, '', '', 
         'disabled',     'char', 'NULL',       1, '', '', 
       ],
       'primary_key' => 'contactnum',
@@ -844,13 +844,13 @@ sub tables_hashref {
 
     'contact_phone' => {
       'columns' => [
-        'contactphonenum', 'serial',     '', '', '', '',
-        'contactnum',         'int',     '', '', '', '',
-        'phonetypenum',       'int',     '', '', '', '',
-        'countrycode',    'varchar',     '',  3, '', '', 
-        'phonenum',       'varchar',     '', 14, '', '', 
-        'extension',      'varchar', 'NULL',  7, '', '',
-        #?#'comment',        'varchar',     '', $char_d, '', '', 
+        'contactphonenum', 'serial', '', '', '', '',
+        'contactnum',         'int', '', '', '', '',
+        'phonetypenum',       'int', '', '', '', '',
+        'countrycode',    'varchar', '',  3, '', '', 
+        'phonenum',       'varchar', '', 14, '', '', 
+        'extension',      'varchar', '',  7, '', '',
+        #?#'comment',   'varchar',     '', $char_d, '', '', 
       ],
       'primary_key' => 'contactphonenum',
       'unique'      => [],
@@ -1194,11 +1194,10 @@ sub tables_hashref {
         'reason',    'varchar',   'NULL', $char_d, '', '', 
         'otaker',   'varchar', 'NULL', 32, '', '', 
         'usernum',   'int', 'NULL', '', '', '',
-        'void_usernum',   'int', 'NULL', '', '', '',
       ],
       'primary_key' => 'paynum',
       'unique' => [],
-      'index' => [ [ 'custnum' ], [ 'usernum' ], [ 'void_usernum' ] ],
+      'index' => [ [ 'custnum' ], [ 'usernum' ], ],
     },
 
     'cust_bill_pay' => {
@@ -1304,7 +1303,6 @@ sub tables_hashref {
         'adjourn',        @date_type,             '', '', 
         'cancel',         @date_type,             '', '', 
         'expire',         @date_type,             '', '', 
-        'contract_end',   @date_type,             '', '',
         'change_date',    @date_type,             '', '',
         'change_pkgnum',       'int', 'NULL', '', '', '',
         'change_pkgpart',      'int', 'NULL', '', '', '',
@@ -2970,18 +2968,7 @@ sub tables_hashref {
       'index'       => [ ['agentnum'], ]
     },
 
-    'svc_cert' => {
-      'columns' => [
-        'svcnum',            'int',     '',            '', '', '', 
-        'recnum',   'int',      '',  '', '', '', 
-        'something', 'text', '', '', '', '',
-        #XXX more fields
-      ],
-      'primary_key' => 'svcnum',
-      'unique' => [],
-      'index'  => [], #recnum
-    },
-   
+
 
     # name type nullability length default local
 
index ef8cc6c..bc6dd5d 100644 (file)
@@ -145,41 +145,6 @@ sub _upgrade_data { # class method
       if $error;
   }
 
-  my %migrate = (
-    'Post payment'    => [ 'Post check payment', 'Post cash payment' ],
-    'Process payment' => [ 'Process credit card payment', 'Process Echeck payment' ],
-    'Post refund'     => [ 'Post check refund', 'Post cash refund' ],
-    'Refund payment'  => [ 'Refund credit card payment', 'Refund Echeck payment' ],
-  );
-
-  foreach my $oldright (keys %migrate) {
-    my @old = qsearch('access_right', { 'righttype'=>'FS::access_group',
-                                        'rightname'=>$oldright,
-                                      }
-                     );
-
-    foreach my $old ( @old ) {
-
-      foreach my $newright ( @{ $migrate{$oldright} } ) {
-        my %hash = (
-          'righttype'   => 'FS::access_group',
-          'rightobjnum' => $old->rightobjnum,
-          'rightname'   => $newright,
-        );
-        next if qsearchs('access_right', \%hash);
-        my $access_right = new FS::access_right \%hash;
-        my $error = $access_right->insert;
-        die $error if $error;
-      }
-
-      #after the WEST stuff is sorted, etc.
-      #my $error = $old->delete;
-      #die $error if $error;
-
-    }
-
-  }
-
   '';
 
 }
index 075733a..72e9140 100644 (file)
@@ -132,8 +132,9 @@ sub insert {
 
 sub htpasswd_kludge {
   my $self = shift;
-
-  return '' if $self->is_system_user;
+  
+  #awful kludge to skip setting htpasswd for fs_* users
+  return '' if $self->username =~ /^fs_/;
 
   unshift @_, '-c' unless -e $htpasswd_file;
   if ( 
@@ -511,25 +512,6 @@ sub default_customer_view {
 
 }
 
-=item is_system_user
-
-Returns true if this user has the name of a known system account.  These 
-users will not appear in the htpasswd file and can't have passwords set.
-
-=cut
-
-sub is_system_user {
-  my $self = shift;
-  return grep { $_ eq $self->username } ( qw(
-    fs_queue
-    fs_daily
-    fs_selfservice
-    fs_signup
-    fs_bootstrap
-    fs_selfserv
-) );
-}
-
 =back
 
 =head1 BUGS
index 5d6b94e..2660bb4 100644 (file)
@@ -2,7 +2,7 @@ package FS::agent_type;
 
 use strict;
 use vars qw( @ISA );
-use FS::Record qw( qsearch dbh );
+use FS::Record qw( qsearch );
 use FS::m2m_Common;
 use FS::agent;
 use FS::type_pkgs;
@@ -119,7 +119,9 @@ L<FS::part_pkg>.
 sub pkgpart_hashref {
   my $self = shift;
   my %pkgpart;
-  $pkgpart{$_}++ foreach $self->pkgpart;
+  #$pkgpart{$_}++ foreach $self->pkgpart;
+  # not compatible w/5.004_04 (fixed in 5.004_05)
+  foreach ( $self->pkgpart ) { $pkgpart{$_}++; }
   \%pkgpart;
 }
 
@@ -164,13 +166,7 @@ agent type.
 
 sub pkgpart {
   my $self = shift;
-
-  #map $_->pkgpart, $self->type_pkgs;
-
-  my $sql = 'SELECT pkgpart FROM type_pkgs WHERE typenum = ?';
-  my $sth = dbh->prepare($sql)    or die  dbh->errstr;
-  $sth->execute( $self->typenum ) or die $sth->errstr;
-  map $_->[0], @{ $sth->fetchall_arrayref };
+  map $_->pkgpart, $self->type_pkgs;
 }
 
 =back
index 8f6a43c..002e2d2 100644 (file)
@@ -285,7 +285,7 @@ sub check {
 #  ;
 #  return $error if $error;
 
-  for my $f ( grep { $self->$_ =~ /\D/ } qw(startdate answerdate enddate)){
+  for my $f ( grep { $self->$_ =~ /[a-z ]/i } qw( startdate enddate ) ) {
     $self->$f( str2time($self->$f) );
   }
 
index 774aed0..d3ab411 100644 (file)
@@ -2,12 +2,10 @@ package FS::contact;
 
 use strict;
 use base qw( FS::Record );
-use FS::Record qw( qsearch qsearchs dbh );
+use FS::Record qw( qsearch qsearchs );
 use FS::prospect_main;
 use FS::cust_main;
 use FS::cust_location;
-use FS::contact_phone;
-use FS::contact_email;
 
 =head1 NAME
 
@@ -98,59 +96,7 @@ otherwise returns false.
 
 =cut
 
-sub insert {
-  my $self = shift;
-
-  local $SIG{INT} = 'IGNORE';
-  local $SIG{QUIT} = 'IGNORE';
-  local $SIG{TERM} = 'IGNORE';
-  local $SIG{TSTP} = 'IGNORE';
-  local $SIG{PIPE} = 'IGNORE';
-
-  my $oldAutoCommit = $FS::UID::AutoCommit;
-  local $FS::UID::AutoCommit = 0;
-  my $dbh = dbh;
-
-  my $error = $self->SUPER::insert;
-  if ( $error ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $error;
-  }
-
-  foreach my $pf ( grep { /^phonetypenum(\d+)$/ && $self->get($_) =~ /\S/ }
-                        keys %{ $self->hashref } ) {
-    $pf =~ /^phonetypenum(\d+)$/ or die "wtf (daily, the)";
-    my $phonetypenum = $1;
-
-    my $contact_phone = new FS::contact_phone {
-      'contactnum' => $self->contactnum,
-      'phonetypenum' => $phonetypenum,
-      _parse_phonestring( $self->get($pf) ),
-    };
-    $error = $contact_phone->insert;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return $error;
-    }
-  }
-
-  if ( $self->get('emailaddress') =~ /\S/ ) {
-    my $contact_email = new FS::contact_email {
-      'contactnum'   => $self->contactnum,
-      'emailaddress' => $self->get('emailaddress'),
-    };
-    $error = $contact_email->insert;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return $error;
-    }
-  }
-
-  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
-  '';
-
-}
+# the insert method can be inherited from FS::Record
 
 =item delete
 
@@ -160,8 +106,6 @@ Delete this record from the database.
 
 # the delete method can be inherited from FS::Record
 
-# XXX delete contact_phone, contact_email
-
 =item replace OLD_RECORD
 
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
@@ -169,76 +113,7 @@ returns the error, otherwise returns false.
 
 =cut
 
-sub replace {
-  my $self = shift;
-
-  local $SIG{INT} = 'IGNORE';
-  local $SIG{QUIT} = 'IGNORE';
-  local $SIG{TERM} = 'IGNORE';
-  local $SIG{TSTP} = 'IGNORE';
-  local $SIG{PIPE} = 'IGNORE';
-
-  my $oldAutoCommit = $FS::UID::AutoCommit;
-  local $FS::UID::AutoCommit = 0;
-  my $dbh = dbh;
-
-  my $error = $self->SUPER::replace(@_);
-  if ( $error ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $error;
-  }
-
-  foreach my $pf ( grep { /^phonetypenum(\d+)$/ && $self->get($_) }
-                        keys %{ $self->hashref } ) {
-    $pf =~ /^phonetypenum(\d+)$/ or die "wtf (daily, the)";
-    my $phonetypenum = $1;
-
-    my %cp = ( 'contactnum'   => $self->contactnum,
-               'phonetypenum' => $phonetypenum,
-             );
-    my $contact_phone = qsearchs('contact_phone', \%cp)
-                        || new FS::contact_phone   \%cp;
-
-    my %cpd = _parse_phonestring( $self->get($pf) );
-    $contact_phone->set( $_ => $cpd{$_} ) foreach keys %cpd;
-
-    my $method = $contact_phone->contactphonenum ? 'replace' : 'insert';
-
-    $error = $contact_phone->$method;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return $error;
-    }
-  }
-
-  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
-  '';
-
-}
-
-#i probably belong in contact_phone.pm
-sub _parse_phonestring {
-  my $value = shift;
-
-  my($countrycode, $extension) = ('1', '');
-
-  #countrycode
-  if ( $value =~ s/^\s*\+\s*(\d+)// ) {
-    $countrycode = $1;
-  } else {
-    $value =~ s/^\s*1//;
-  }
-  #extension
-  if ( $value =~ s/\s*(ext|x)\s*(\d+)\s*$//i ) {
-     $extension = $2;
-  }
-
-  ( 'countrycode' => $countrycode,
-    'phonenum'    => $value,
-    'extension'   => $extension,
-  );
-}
+# the replace method can be inherited from FS::Record
 
 =item check
 
@@ -290,6 +165,8 @@ sub line {
 
 =head1 BUGS
 
+The author forgot to customize this manpage.
+
 =head1 SEE ALSO
 
 L<FS::Record>, schema.html from the base documentation.
index ad8e8f7..bb9cf03 100644 (file)
@@ -120,7 +120,7 @@ sub check {
     || $self->ut_number('phonetypenum')
     || $self->ut_text('countrycode')
     || $self->ut_text('phonenum')
-    || $self->ut_textn('extension')
+    || $self->ut_text('extension')
   ;
   return $error if $error;
 
index 335c4b6..d364ac5 100644 (file)
@@ -263,13 +263,13 @@ sub delete {
 
 }
 
-=item replace [ OLD_RECORD ]
+=item replace OLD_RECORD
 
-You can, but probably shouldn't modify invoices...
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
 
-Replaces the OLD_RECORD with this one in the database, or, if OLD_RECORD is not
-supplied, replaces this record.  If there is an error, returns the error,
-otherwise returns false.
+Only printed may be changed.  printed is normally updated by calling the
+collect method of a customer object (see L<FS::cust_main>).
 
 =cut
 
@@ -280,11 +280,11 @@ otherwise returns false.
 
 sub replace_check {
   my( $new, $old ) = ( shift, shift );
-  return "Can't modify closed invoice" if $old->closed =~ /^Y/i;
+  return "Can't change custnum!" unless $old->custnum == $new->custnum;
   #return "Can't change _date!" unless $old->_date eq $new->_date;
-  return "Can't change _date" unless $old->_date == $new->_date;
-  return "Can't change charged" unless $old->charged == $new->charged
-                                    || $old->charged == 0;
+  return "Can't change _date!" unless $old->_date == $new->_date;
+  return "Can't change charged!" unless $old->charged == $new->charged
+                                     || $old->charged == 0;
 
   '';
 }
@@ -2291,12 +2291,10 @@ sub print_generic {
   my $nbsp = $nbsps{$format};
 
   my %escape_functions = ( 'latex'    => \&_latex_escape,
-                           'html'     => \&_html_escape_nbsp,#\&encode_entities,
+                           'html'     => \&encode_entities,
                            'template' => sub { shift },
                          );
   my $escape_function = $escape_functions{$format};
-  my $escape_function_nonbsp = ($format eq 'html')
-                                 ? \&_html_escape : $escape_function;
 
   my %date_formats = ( 'latex'    => '%b %o, %Y',
                        'html'     => '%b&nbsp;%o,&nbsp;%Y',
@@ -2600,7 +2598,7 @@ sub print_generic {
   my $extra_lines = ();
   if ( $multisection ) {
     ($extra_sections, $extra_lines) =
-      $self->_items_extra_usage_sections($escape_function_nonbsp, $format)
+      $self->_items_extra_usage_sections($escape_function, $format)
       if $conf->exists('usage_class_as_a_section', $cust_main->agentnum);
 
     push @$extra_sections, $adjust_section if $adjust_section->{sort_weight};
@@ -2609,13 +2607,13 @@ sub print_generic {
     push @sections,
       $self->_items_sections( $late_sections,      # this could stand a refactor
                               $summarypage,
-                              $escape_function_nonbsp,
+                              $escape_function,
                               $extra_sections,
                               $format,             #bah
                             );
     if ($conf->exists('svc_phone_sections')) {
       my ($phone_sections, $phone_lines) =
-        $self->_items_svc_phone_sections($escape_function_nonbsp, $format);
+        $self->_items_svc_phone_sections($escape_function, $format);
       push @{$late_sections}, @$phone_sections;
       push @detail_items, @$phone_lines;
     }
@@ -3167,18 +3165,6 @@ sub _latex_escape {
   $value;
 }
 
-sub _html_escape {
-  my $value = shift;
-  encode_entities($value);
-  $value;
-}
-
-sub _html_escape_nbsp {
-  my $value = _html_escape(shift);
-  $value =~ s/ +/&nbsp;/g;
-  $value;
-}
-
 #utility methods for print_*
 
 sub _translate_old_latex_format {
@@ -4100,20 +4086,15 @@ sub _items_cust_bill_pkg {
           unless ( $cust_pkg->part_pkg->hide_svc_detail
                 || $cust_bill_pkg->hidden )
           {
-
             push @d, map &{$escape_function}($_),
-                         $cust_pkg->h_labels_short($self->_date)
-              unless $cust_bill_pkg->pkgpart_override; #don't redisplay services
-
+                         $cust_pkg->h_labels_short($self->_date);
             if ( $multilocation ) {
               my $loc = $cust_pkg->location_label;
-              $loc = substr($loc, 0, 50). '...'
+              $loc = substr($desc, 0, 50). '...'
                 if $format eq 'latex' && length($loc) > 50;
               push @d, &{$escape_function}($loc);
             }
-
           }
-
           push @d, $cust_bill_pkg->details(%details_opt)
             if $cust_bill_pkg->recur == 0;
 
@@ -4162,20 +4143,17 @@ sub _items_cust_bill_pkg {
                 || $cust_bill_pkg->hidden
                 || $is_summary && $type && $type eq 'U' )
           {
-
             push @d, map &{$escape_function}($_),
                          $cust_pkg->h_labels_short(@dates)
                                                    #$cust_bill_pkg->edate,
                                                    #$cust_bill_pkg->sdate)
-              unless $cust_bill_pkg->pkgpart_override; #don't redisplay services
-
+            ;
             if ( $multilocation ) {
               my $loc = $cust_pkg->location_label;
-              $loc = substr($loc, 0, 50). '...'
+              $loc = substr($desc, 0, 50). '...'
                 if $format eq 'latex' && length($loc) > 50;
               push @d, &{$escape_function}($loc);
             }
-
           }
 
           push @d, $cust_bill_pkg->details(%details_opt)
index 7badaa3..b8af013 100644 (file)
@@ -238,10 +238,7 @@ sub _upgrade_schema { # class method
 
   warn "$me upgrading $class\n" if $DEBUG;
 
-  my $classnum = dbdef->table($class->table)->column('classnum')
-    or return;
-
-  my $type = $classnum->type;
+  my $type = dbdef->table($class->table)->column('classnum')->type;
   unless ( $type =~ /^int/i || $type =~ /int$/i ) {
 
     my $dbh = dbh;
index 6185fc4..0f8ac97 100644 (file)
@@ -270,17 +270,14 @@ sub delete {
 
 }
 
-=item replace [ OLD_RECORD ]
+=item replace OLD_RECORD
 
 You can, but probably shouldn't modify credits... 
 
-Replaces the OLD_RECORD with this one in the database, or, if OLD_RECORD is not
-supplied, replaces this record.  If there is an error, returns the error,
-otherwise returns false.
-
 =cut
 
 sub replace {
+  #return "Can't modify credit!"
   my $self = shift;
   return "Can't modify closed credit" if $self->closed =~ /^Y/i;
   $self->SUPER::replace(@_);
index ab80941..0c5c023 100644 (file)
@@ -1,7 +1,7 @@
 package FS::cust_location;
 
 use strict;
-use base qw( FS::geocode_Mixin FS::Record );
+use base qw( FS::Record );
 use Locale::Country;
 use FS::Record qw( qsearch ); #qsearchs );
 use FS::prospect_main;
@@ -163,35 +163,91 @@ sub country_full {
   code2country($self->country);
 }
 
-=item line
+=item location_label [ OPTION => VALUE ... ]
 
-Synonym for location_label
+Returns the label of the service location for this customer.
+
+Options are
+
+=over 4
+
+=item join_string
+
+used to separate the address elements (defaults to ', ')
+
+=item escape_function
+
+
+a callback used for escaping the text of the address elements
+
+=back
 
 =cut
 
-sub line {
+# false laziness with FS::cust_main::location_label
+
+sub location_label {
   my $self = shift;
-  $self->location_label;
+  my %opt = @_;
+
+  my $separator = $opt{join_string} || ', ';
+  my $escape = $opt{escape_function} || sub{ shift };
+  my $ds = $opt{double_space} || '  ';
+  my $line = '';
+  my $cydefault =
+    $opt{'countrydefault'} || FS::Conf->new->config('countrydefault') || 'US';
+  my $prefix = '';
+
+  my $notfirst = 0;
+  foreach (qw ( address1 address2 ) ) {
+    my $method = "$prefix$_";
+    $line .= ($notfirst ? $separator : ''). &$escape($self->$method)
+      if $self->$method;
+    $notfirst++;
+  }
+  $notfirst = 0;
+  foreach (qw ( city county state zip ) ) {
+    my $method = "$prefix$_";
+    if ( $self->$method ) {
+      $line .= ($notfirst ? ($method eq 'zip' ? $ds : ' ') : $separator);
+      $line .= '(' if $method eq 'county';
+      $line .= &$escape($self->$method);
+      $line .= ')' if $method eq 'county';
+      $notfirst++;
+    }
+    $line .= ',' if $method eq 'county';
+  }
+  $line .= $separator. &$escape(code2country($self->country))
+    if $self->country ne $cydefault;
+
+  $line;
 }
 
-=item has_ship_address
+=item line
 
-Returns false since cust_location objects do not have a separate shipping
-address.
+Synonym for location_label
 
 =cut
 
-sub has_ship_address {
-  '';
+sub line {
+  my $self = shift;
+  $self->location_label;
 }
 
 =item location_hash
 
-Returns a list of key/value pairs, with the following keys: address1, address2,
-city, county, state, zip, country, geocode.
+Returns a list of key/value pairs, with the following keys: address1, adddress2,
+city, county, state, zip, country.
 
 =cut
 
+#geocode?  not yet set
+
+sub location_hash {
+  my $self = shift;
+  map { $_ => $self->$_ } qw( address1 address2 city county state zip country );
+}
+
 =back
 
 =head1 BUGS
index 7969965..fc781d2 100644 (file)
@@ -6,7 +6,6 @@ use strict;
 use base qw( FS::cust_main::Packages
              FS::cust_main::Billing FS::cust_main::Billing_Realtime
              FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
-             FS::geocode_Mixin
              FS::Record
            );
 use vars qw( $DEBUG $me $conf
@@ -26,7 +25,7 @@ use Tie::IxHash;
 use Digest::MD5 qw(md5_base64);
 use Date::Format;
 #use Date::Manip;
-use File::Temp; #qw( tempfile );
+use File::Temp qw( tempfile );
 use Business::CreditCard 0.28;
 use Locale::Country;
 use FS::UID qw( getotaker dbh driver_name );
@@ -1159,227 +1158,6 @@ sub delete {
 
 }
 
-=item merge NEW_CUSTNUM [ , OPTION => VALUE ... ]
-
-This merges this customer into the provided new custnum, and then deletes the
-customer.  If there is an error, returns the error, otherwise returns false.
-
-The source customer's name, company name, phone numbers, agent,
-referring customer, customer class, advertising source, order taker, and
-billing information (except balance) are discarded.
-
-All packages are moved to the target customer.  Packages with package locations
-are preserved.  Packages without package locations are moved to a new package
-location with the source customer's service/shipping address.
-
-All invoices, statements, payments, credits and refunds are moved to the target
-customer.  The source customer's balance is added to the target customer.
-
-All notes, attachments, tickets and customer tags are moved to the target
-customer.
-
-Change history is not currently moved.
-
-=cut
-
-sub merge {
-  my( $self, $new_custnum, %opt ) = @_;
-
-  return "Can't merge a customer into self" if $self->custnum == $new_custnum;
-
-  unless ( qsearchs( 'cust_main', { 'custnum' => $new_custnum } ) ) {
-    return "Invalid new customer number: $new_custnum";
-  }
-
-  local $SIG{HUP} = 'IGNORE';
-  local $SIG{INT} = 'IGNORE';
-  local $SIG{QUIT} = 'IGNORE';
-  local $SIG{TERM} = 'IGNORE';
-  local $SIG{TSTP} = 'IGNORE';
-  local $SIG{PIPE} = 'IGNORE';
-
-  my $oldAutoCommit = $FS::UID::AutoCommit;
-  local $FS::UID::AutoCommit = 0;
-  my $dbh = dbh;
-
-  if ( qsearch('agent', { 'agent_custnum' => $self->custnum } ) ) {
-     $dbh->rollback if $oldAutoCommit;
-     return "Can't merge a master agent customer";
-  }
-
-  #use FS::access_user
-  if ( qsearch('access_user', { 'user_custnum' => $self->custnum } ) ) {
-     $dbh->rollback if $oldAutoCommit;
-     return "Can't merge a master employee customer";
-  }
-
-  if ( qsearch('cust_pay_pending', { 'custnum' => $self->custnum,
-                                     'status'  => { op=>'!=', value=>'done' },
-                                   }
-              )
-  ) {
-     $dbh->rollback if $oldAutoCommit;
-     return "Can't merge a customer with pending payments";
-  }
-
-  tie my %financial_tables, 'Tie::IxHash',
-    'cust_bill'      => 'invoices',
-    'cust_statement' => 'statements',
-    'cust_credit'    => 'credits',
-    'cust_pay'       => 'payments',
-    'cust_pay_void'  => 'voided payments',
-    'cust_refund'    => 'refunds',
-  ;
-   
-  foreach my $table ( keys %financial_tables ) {
-
-    my @records = $self->$table();
-
-    foreach my $record ( @records ) {
-      $record->custnum($new_custnum);
-      my $error = $record->replace;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return "Error merging ". $financial_tables{$table}. ": $error\n";
-      }
-    }
-
-  }
-
-  my $name = $self->ship_name;
-
-  my $locationnum = '';
-  foreach my $cust_pkg ( $self->all_pkgs ) {
-    $cust_pkg->custnum($new_custnum);
-
-    unless ( $cust_pkg->locationnum ) {
-      unless ( $locationnum ) {
-        my $cust_location = new FS::cust_location {
-          $self->location_hash,
-          'custnum' => $new_custnum,
-        };
-        my $error = $cust_location->insert;
-        if ( $error ) {
-          $dbh->rollback if $oldAutoCommit;
-          return $error;
-        }
-        $locationnum = $cust_location->locationnum;
-      }
-      $cust_pkg->locationnum($locationnum);
-    }
-
-    my $error = $cust_pkg->replace;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return $error;
-    }
-
-    # add customer (ship) name to svc_phone.phone_name if blank
-    my @cust_svc = $cust_pkg->cust_svc;
-    foreach my $cust_svc (@cust_svc) {
-      my($label, $value, $svcdb) = $cust_svc->label;
-      next unless $svcdb eq 'svc_phone';
-      my $svc_phone = $cust_svc->svc_x;
-      next if $svc_phone->phone_name;
-      $svc_phone->phone_name($name);
-      my $error = $svc_phone->replace;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return $error;
-      }
-    }
-
-  }
-
-  #not considered:
-  # cust_tax_exempt (texas tax exemptions)
-  # cust_recon (some sort of not-well understood thing for OnPac)
-
-  #these are moved over
-  foreach my $table (qw(
-    cust_tag cust_location contact cust_attachment cust_main_note
-    cust_tax_adjustment cust_pay_batch queue
-  )) {
-    foreach my $record ( qsearch( $table, { 'custnum' => $self->custnum } ) ) {
-      $record->custnum($new_custnum);
-      my $error = $record->replace;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return $error;
-      }
-    }
-  }
-
-  #these aren't preserved
-  foreach my $table (qw(
-    cust_main_exemption cust_main_invoice
-  )) {
-    foreach my $record ( qsearch( $table, { 'custnum' => $self->custnum } ) ) {
-      my $error = $record->delete;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return $error;
-      }
-    }
-  }
-
-
-  my $sth = $dbh->prepare(
-    'UPDATE cust_main SET referral_custnum = ? WHERE referral_custnum = ?'
-  ) or do {
-    my $errstr = $dbh->errstr;
-    $dbh->rollback if $oldAutoCommit;
-    return $errstr;
-  };
-  $sth->execute($new_custnum, $self->custnum) or do {
-    my $errstr = $sth->errstr;
-    $dbh->rollback if $oldAutoCommit;
-    return $errstr;
-  };
-
-  #tickets
-
-  my $ticket_dbh = '';
-  if ($conf->config('ticket_system') eq 'RT_Internal') {
-    $ticket_dbh = $dbh;
-  } elsif ($conf->config('ticket_system') eq 'RT_External') {
-    my ($datasrc, $user, $pass) = $conf->config('ticket_system-rt_external_datasrc');
-    $ticket_dbh = DBI->connect($datasrc, $user, $pass, { 'ChopBlanks' => 1 });
-      #or die "RT_External DBI->connect error: $DBI::errstr\n";
-  }
-
-  if ( $ticket_dbh ) {
-
-    my $ticket_sth = $ticket_dbh->prepare(
-      'UPDATE Links SET Target = ? WHERE Target = ?'
-    ) or do {
-      my $errstr = $ticket_dbh->errstr;
-      $dbh->rollback if $oldAutoCommit;
-      return $errstr;
-    };
-    $ticket_sth->execute('freeside://freeside/cust_main/'.$new_custnum,
-                         'freeside://freeside/cust_main/'.$self->custnum)
-      or do {
-        my $errstr = $ticket_sth->errstr;
-        $dbh->rollback if $oldAutoCommit;
-        return $errstr;
-      };
-
-  }
-
-  #delete the customer record
-
-  my $error = $self->delete;
-  if ( $error ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $error;
-  }
-
-  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-  '';
-
-}
-
 =item replace [ OLD_RECORD ] [ INVOICING_LIST_ARYREF ] [ , OPTION => VALUE ... ] ]
 
 
@@ -1421,17 +1199,6 @@ sub replace {
     return "You are not permitted to create complimentary accounts.";
   }
 
-  if ( $old->get('geocode') && $old->get('geocode') eq $self->get('geocode')
-       && $conf->exists('enable_taxproducts')
-     )
-  {
-    my $pre = ($conf->exists('tax-ship_address') && $self->ship_zip)
-                ? 'ship_' : '';
-    $self->set('geocode', '')
-      if $old->get($pre.'zip') ne $self->get($pre.'zip')
-      && length($self->get($pre.'zip')) >= 10;
-  }
-
   local($ignore_expired_card) = 1
     if $old->payby  =~ /^(CARD|DCRD)$/
     && $self->payby =~ /^(CARD|DCRD)$/
@@ -1888,14 +1655,12 @@ sub check {
     $self->payinfo($payinfo);
     $self->paycvv('');
 
-    unless ( $ignore_banned_card ) {
-      my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref);
-      if ( $ban ) {
-        return 'Banned ACH account: banned on '.
-               time2str('%a %h %o at %r', $ban->_date).
-               ' by '. $ban->otaker.
-               ' (ban# '. $ban->bannum. ')';
-      }
+    my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref);
+    if ( $ban ) {
+      return 'Banned ACH account: banned on '.
+             time2str('%a %h %o at %r', $ban->_date).
+             ' by '. $ban->otaker.
+             ' (ban# '. $ban->bannum. ')';
     }
 
   } elsif ( $self->payby eq 'LECB' ) {
@@ -1955,7 +1720,6 @@ sub check {
     } else {
       return "Illegal expiration date: ". $self->paydate;
     }
-    $m = sprintf('%02d',$m);
     $self->paydate("$y-$m-01");
     my($nowm,$nowy)=(localtime(time))[4,5]; $nowm++; $nowy+=1900;
     return gettext('expired_card')
@@ -1970,7 +1734,7 @@ sub check {
   ) {
     $self->payname( $self->first. " ". $self->getfield('last') );
   } else {
-    $self->payname =~ /^([µ_0123456789aAáÁàÀâÂåÅäÄãêæÆbBcCçÇdDðÐeEéÉèÈêÊëËfFgGhHiIíÍìÌîÎïÏjJkKlLmMnNñÑoOóÓòÒôÔöÖõÕøغpPqQrRsSßtTuUúÚùÙûÛüÜvVwWxXyYýÝÿzZþÞ \,\.\-\'\&]+)$/
+    $self->payname =~ /^([\w \,\.\-\'\&]+)$/
       or return gettext('illegal_name'). " payname: ". $self->payname;
     $self->payname($1);
   }
@@ -2015,10 +1779,22 @@ sub has_ship_address {
 =item location_hash
 
 Returns a list of key/value pairs, with the following keys: address1, adddress2,
-city, county, state, zip, country, and geocode.  The shipping address is used if present.
+city, county, state, zip, country.  The shipping address is used if present.
 
 =cut
 
+#geocode?  dependent on tax-ship_address config, not available in cust_location
+#mostly.  not yet then.
+
+sub location_hash {
+  my $self = shift;
+  my $prefix = $self->has_ship_address ? 'ship_' : '';
+
+  map { $_ => $self->get($prefix.$_) }
+      qw( address1 address2 city county state zip country geocode );
+      #fields that cust_location has
+}
+
 =item cust_location
 
 Returns all locations (see L<FS::cust_location>) for this customer.
@@ -2030,6 +1806,61 @@ sub cust_location {
   qsearch('cust_location', { 'custnum' => $self->custnum } );
 }
 
+=item location_label [ OPTION => VALUE ... ]
+
+Returns the label of the service location (see analog in L<FS::cust_location>) for this customer.
+
+Options are
+
+=over 4
+
+=item join_string
+
+used to separate the address elements (defaults to ', ')
+
+=item escape_function
+
+a callback used for escaping the text of the address elements
+
+=back
+
+=cut
+
+# false laziness with FS::cust_location::line
+
+sub location_label {
+  my $self = shift;
+  my %opt = @_;
+
+  my $separator = $opt{join_string} || ', ';
+  my $escape = $opt{escape_function} || sub{ shift };
+  my $line = '';
+  my $cydefault = FS::conf->new->config('countrydefault') || 'US';
+  my $prefix = length($self->ship_last) ? 'ship_' : '';
+
+  my $notfirst = 0;
+  foreach (qw ( address1 address2 ) ) {
+    my $method = "$prefix$_";
+    $line .= ($notfirst ? $separator : ''). &$escape($self->$method)
+      if $self->$method;
+    $notfirst++;
+  }
+  $notfirst = 0;
+  foreach (qw ( city county state zip ) ) {
+    my $method = "$prefix$_";
+    if ( $self->$method ) {
+      $line .= ' (' if $method eq 'county';
+      $line .= ($notfirst ? ' ' : $separator). &$escape($self->$method);
+      $line .= ' )' if $method eq 'county';
+      $notfirst++;
+    }
+  }
+  $line .= $separator. &$escape(code2country($self->country))
+    if $self->country ne $cydefault;
+
+  $line;
+}
+
 =item unsuspend
 
 Unsuspends all unflagged suspended packages (see L</unflagged_suspended_pkgs>
@@ -2502,7 +2333,7 @@ sub total_owed_date {
         AND _date <= $time
   ";
 
-  sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+  sprintf( "%.2f", $self->scalar_sql($sql) );
 
 }
 
@@ -2582,7 +2413,7 @@ sub total_unapplied_credits {
       WHERE custnum = $custnum
   ";
 
-  sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+  sprintf( "%.2f", $self->scalar_sql($sql) );
 
 }
 
@@ -2620,7 +2451,7 @@ sub total_unapplied_payments {
       WHERE custnum = $custnum
   ";
 
-  sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+  sprintf( "%.2f", $self->scalar_sql($sql) );
 
 }
 
@@ -2658,7 +2489,7 @@ sub total_unapplied_refunds {
       WHERE custnum = $custnum
   ";
 
-  sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+  sprintf( "%.2f", $self->scalar_sql($sql) );
 
 }
 
@@ -2716,7 +2547,7 @@ sub balance_date_range {
   my $self = shift;
   my $sql = 'SELECT SUM('. $self->balance_date_sql(@_).
             ') FROM cust_main WHERE custnum='. $self->custnum;
-  sprintf( '%.2f', $self->scalar_sql($sql) || 0 );
+  sprintf( '%.2f', $self->scalar_sql($sql) );
 }
 
 =item balance_pkgnum PKGNUM
@@ -3785,6 +3616,38 @@ Currently this only makes sense for "CCH" as DATA_VENDOR.
 
 =cut
 
+sub geocode {
+  my ($self, $data_vendor) = (shift, shift);  #always cch for now
+
+  my $geocode = $self->get('geocode');  #XXX only one data_vendor for geocode
+  return $geocode if $geocode;
+
+  my $prefix = ( $conf->exists('tax-ship_address') && length($self->ship_last) )
+               ? 'ship_'
+               : '';
+
+  my($zip,$plus4) = split /-/, $self->get("${prefix}zip")
+    if $self->country eq 'US';
+
+  $zip ||= '';
+  $plus4 ||= '';
+  #CCH specific location stuff
+  my $extra_sql = "AND plus4lo <= '$plus4' AND plus4hi >= '$plus4'";
+
+  my @cust_tax_location =
+    qsearch( {
+               'table'     => 'cust_tax_location', 
+               'hashref'   => { 'zip' => $zip, 'data_vendor' => $data_vendor },
+               'extra_sql' => $extra_sql,
+               'order_by'  => 'ORDER BY plus4hi',#overlapping with distinct ends
+             }
+           );
+  $geocode = $cust_tax_location[0]->geocode
+    if scalar(@cust_tax_location);
+
+  $geocode;
+}
+
 =item cust_status
 
 =item status
@@ -3813,6 +3676,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() ) {
     my $method = $status.'_sql';
     my $numnum = ( my $sql = $self->$method() ) =~ s/cust_main\.custnum/?/g;
@@ -3849,9 +3713,9 @@ 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
-  'inactive'  => '0000CC', #blue
 ;
 
 sub statuscolor { shift->cust_statuscolor(@_); }
@@ -3958,24 +3822,6 @@ sub statuses {
   keys %statuscolor;
 }
 
-=item cust_status_sql
-
-Returns an SQL fragment to determine the status of a cust_main record, as a 
-string.
-
-=cut
-
-sub cust_status_sql {
-  my $sql = 'CASE';
-  for my $status ( FS::cust_main->statuses() ) {
-    my $method = $status.'_sql';
-    $sql .= ' WHEN ('.FS::cust_main->$method.") THEN '$status'";
-  }
-  $sql .= ' END';
-  return $sql;
-}
-
-
 =item prospect_sql
 
 Returns an SQL expression identifying prospective cust_main records (customers
@@ -4076,8 +3922,8 @@ sub cancel_sql {
     AND 0 = ( $select_count_pkgs AND $recurring_sql
                   AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
             )
+    AND 0 = (  $select_count_pkgs AND ". FS::cust_pkg->inactive_sql. " )
   ";
-#    AND 0 = (  $select_count_pkgs AND ". FS::cust_pkg->inactive_sql. " )
 
 }
 
@@ -4763,21 +4609,10 @@ sub process_bill_and_collect {
 sub _upgrade_data { #class method
   my ($class, %opts) = @_;
 
-  my @statements = (
+  foreach my $sql (
     'UPDATE h_cust_main SET paycvv = NULL WHERE paycvv IS NOT NULL',
-    'UPDATE cust_main SET signupdate = (SELECT signupdate FROM h_cust_main WHERE signupdate IS NOT NULL AND h_cust_main.custnum = cust_main.custnum ORDER BY historynum DESC LIMIT 1) WHERE signupdate IS NULL',
-  );
-  # fix yyyy-m-dd formatted paydates
-  if ( driver_name =~ /^mysql$/i ) {
-    push @statements,
-    "UPDATE cust_main SET paydate = CONCAT( SUBSTRING(paydate FROM 1 FOR 5), '0', SUBSTRING(paydate FROM 6) ) WHERE SUBSTRING(paydate FROM 7 FOR 1) = '-'";
-  }
-  else { # the SQL standard
-    push @statements, 
-    "UPDATE cust_main SET paydate = SUBSTRING(paydate FROM 1 FOR 5) || '0' || SUBSTRING(paydate FROM 6) WHERE SUBSTRING(paydate FROM 7 FOR 1) = '-'";
-  }
-
-  foreach my $sql ( @statements ) {
+    'UPDATE cust_main SET signupdate = (SELECT signupdate FROM h_cust_main WHERE h_cust_main.custnum = cust_main.custnum ORDER BY historynum ASC LIMIT 1) WHERE signupdate IS NULL',
+  ) {
     my $sth = dbh->prepare($sql) or die dbh->errstr;
     $sth->execute or die $sth->errstr;
   }
index e004788..0cd304b 100644 (file)
@@ -856,14 +856,15 @@ sub _make_lines {
   my $recur = 0;
   my $unitrecur = 0;
   my $sdate;
-  if (     ! $cust_pkg->start_date
-       and ( ! $cust_pkg->susp || $part_pkg->option('suspend_bill') )
-       and
-            ( $part_pkg->freq ne '0' && ( $cust_pkg->bill || 0 ) <= $time )
-         || ( $part_pkg->plan eq 'voip_cdr'
-               && $part_pkg->option('bill_every_call')
-            )
-         || $options{cancel}
+  if (     ! $cust_pkg->get('susp')
+       and ! $cust_pkg->get('start_date')
+       and ( $part_pkg->getfield('freq') ne '0'
+             && ( $cust_pkg->getfield('bill') || 0 ) <= $time
+           )
+        || ( $part_pkg->plan eq 'voip_cdr'
+              && $part_pkg->option('bill_every_call')
+           )
+        || ( $options{cancel} )
   ) {
 
     # XXX should this be a package event?  probably.  events are called
@@ -1047,14 +1048,18 @@ sub _handle_taxes {
        )
     {
 
+      if ( $conf->exists('tax-pkg_address') && $cust_pkg->locationnum ) {
+        return "fatal: Can't (yet) use tax-pkg_address with taxproducts";
+      }
+
       foreach my $class (@classes) {
-        my $err_or_ref = $self->_gather_taxes( $part_pkg, $class, $cust_pkg );
+        my $err_or_ref = $self->_gather_taxes( $part_pkg, $class );
         return $err_or_ref unless ref($err_or_ref);
         $taxes{$class} = $err_or_ref;
       }
 
       unless (exists $taxes{''}) {
-        my $err_or_ref = $self->_gather_taxes( $part_pkg, '', $cust_pkg );
+        my $err_or_ref = $self->_gather_taxes( $part_pkg, '' );
         return $err_or_ref unless ref($err_or_ref);
         $taxes{''} = $err_or_ref;
       }
@@ -1221,18 +1226,11 @@ sub _gather_taxes {
   my $self = shift;
   my $part_pkg = shift;
   my $class = shift;
-  my $cust_pkg = shift;
 
   local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG;
 
-  my $geocode;
-  if ( $cust_pkg->locationnum && $conf->exists('tax-pkg_address') ) {
-    $geocode = $cust_pkg->cust_location->geocode('cch');
-  } else {
-    $geocode = $self->geocode('cch');
-  }
-
   my @taxes = ();
+  my $geocode = $self->geocode('cch');
 
   my @taxclassnums = map { $_->taxclassnum }
                      $part_pkg->part_pkg_taxoverride($class);
index ab7bde3..316ae37 100644 (file)
@@ -385,21 +385,6 @@ sub unsuspended_pkgs {
   grep { ! $_->susp } $self->ncancelled_pkgs;
 }
 
-=item active_pkgs
-
-Returns all unsuspended (and uncancelled) packages (see L<FS::cust_pkg>) for
-this customer that are active (recurring).
-
-=cut
-
-sub active_pkgs {
-  my $self = shift; 
-  grep { my $part_pkg = $_->part_pkg;
-         $part_pkg->freq ne '' && $part_pkg->freq ne '0';
-       }
-       $self->unsuspended_pkgs;
-}
-
 =item next_bill_date
 
 Returns the next date this customer will be billed, as a UNIX timestamp, or
@@ -409,7 +394,7 @@ undef if no active package has a next bill date.
 
 sub next_bill_date {
   my $self = shift;
-  min( map $_->get('bill'), grep $_->get('bill'), $self->active_pkgs );
+  min( map $_->get('bill'), grep $_->get('bill'), $self->unsuspended_pkgs );
 }
 
 =item num_cancelled_pkgs
index ad24ff8..3813f89 100644 (file)
@@ -203,7 +203,7 @@ sub smart_search {
     } elsif ( ! $NameParse->parse($value) ) {
 
       my %name = $NameParse->components;
-      $first = $name{'given_name_1'} || $name{'initials_1'}; #wtf NameParse, Ed?
+      $first = $name{'given_name_1'};
       $last  = $name{'surname_1'};
 
     }
@@ -422,8 +422,6 @@ HASHREF.  Valid parameters are
 
 =item status
 
-=item address
-
 =item cancelled_pkgs
 
 bool
@@ -490,19 +488,7 @@ sub search {
     #push @where, $class->$method();
     push @where, FS::cust_main->$method();
   }
-
-  ##
-  # address
-  ##
-  if ( $params->{'address'} =~ /\S/ ) {
-    my $address = dbh->quote('%'. lc($params->{'address'}). '%');
-    push @where, '('. join(' OR ',
-                             map "LOWER($_) LIKE $address",
-                               qw(address1 address2 ship_address1 ship_address2)
-                          ).
-                 ')';
-  }
-
+  
   ##
   # parse cancelled package checkbox
   ##
@@ -520,13 +506,6 @@ sub search {
     if $params->{'no_censustract'};
 
   ##
-  # parse with hardcoded tax location checkbox
-  ##
-
-  push @where, "geocode is not null"
-    if $params->{'with_geocode'};
-
-  ##
   # dates
   ##
 
@@ -541,13 +520,11 @@ sub search {
       "cust_main.$field >= $beginning",
       "cust_main.$field <= $ending";
 
+    # XXX: do this for mysql and/or pull it out of here
     if(defined $hour) {
-      if ($dbh->{Driver}->{Name} =~ /Pg/i) {
+      if ($dbh->{Driver}->{Name} eq 'Pg') {
         push @where, "extract(hour from to_timestamp(cust_main.$field)) = $hour";
       }
-      elsif( $dbh->{Driver}->{Name} =~ /mysql/i) {
-        push @where, "hour(from_unixtime(cust_main.$field)) = $hour"
-      }
       else {
         warn "search by time of day not supported on ".$dbh->{Driver}->{Name}." databases";
       }
@@ -658,21 +635,6 @@ sub search {
     push @where,
       "cust_main.custbatch = '$1'";
   }
-  
-  if ( $params->{'tagnum'} ) {
-    my @tagnums = ref( $params->{'tagnum'} ) ? @{ $params->{'tagnum'} } : ( $params->{'tagnum'} );
-
-    @tagnums = grep /^(\d+)$/, @tagnums;
-
-    if ( @tagnums ) {
-       my $tags_where = "0 < (select count(1) from cust_tag where " 
-               . " cust_tag.custnum = cust_main.custnum and tagnum in ("
-               . join(',', @tagnums) . "))";
-
-       push @where, $tags_where;
-    }
-  }
-
 
   ##
   # setup queries, subs, etc. for the search
@@ -689,7 +651,7 @@ sub search {
 
   my $count_query = "SELECT COUNT(*) FROM cust_main $extra_sql";
 
-  my @select = (
+  my $select = join(', ', 
                  'cust_main.custnum',
                  FS::UI::Web::cust_sql_fields($params->{'cust_fields'}),
                );
@@ -701,10 +663,10 @@ sub search {
 
     if ($dbh->{Driver}->{Name} eq 'Pg') {
 
-      push @select, "array_to_string(array(select pkg from cust_pkg left join part_pkg using ( pkgpart ) where cust_main.custnum = cust_pkg.custnum $pkgwhere),'|') as magic";
+      $select .= ", array_to_string(array(select pkg from cust_pkg left join part_pkg using ( pkgpart ) where cust_main.custnum = cust_pkg.custnum $pkgwhere),'|') as magic";
 
     }elsif ($dbh->{Driver}->{Name} =~ /^mysql/i) {
-      push @select, "GROUP_CONCAT(pkg SEPARATOR '|') as magic";
+      $select .= ", GROUP_CONCAT(pkg SEPARATOR '|') as magic";
       $addl_from .= " LEFT JOIN part_pkg using ( pkgpart )";
     }else{
       warn "warning: unknown database type ". $dbh->{Driver}->{Name}. 
@@ -728,21 +690,6 @@ sub search {
 
   }
 
-  if ( $params->{'with_geocode'} ) {
-
-    unshift @extra_headers, 'Tax location override', 'Calculated tax location';
-    unshift @extra_fields, sub { my $c = shift; $c->get('geocode'); },
-                           sub { my $c = shift;
-                                 $c->set('geocode', '');
-                                 $c->geocode('cch'); #XXX only cch right now
-                               };
-    push @select, 'geocode';
-    push @select, 'zip' unless grep { $_ eq 'zip' } @select;
-    push @select, 'ship_zip' unless grep { $_ eq 'ship_zip' } @select;
-  }
-
-  my $select = join(', ', @select);
-
   my $sql_query = {
     'table'         => 'cust_main',
     'select'        => $select,
index 8c8553c..b446d69 100644 (file)
@@ -423,9 +423,7 @@ sub email_search_result {
 
   my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
   my @retry_jobs = ();
-  my $dups = 0;
   my $success = 0;
-  my %sent_to = ();
 
   #eventually order+limit magic to reduce memory use?
   foreach my $obj ( qsearch($sql_query) ) {
@@ -445,21 +443,9 @@ sub email_search_result {
     if ( !$cust_main ) { 
       next; # unlinked object; nothing else we can do
     }
-
-    if( $sent_to{$cust_main->custnum} ) {
-      # avoid duplicates
-      $dups++;
-      next;
-    }
-
-    $sent_to{$cust_main->custnum} = 1;
     
     if ( $msg_template ) {
       # XXX add support for other context objects?
-      # If we do that, handling of "duplicates" will 
-      # have to be smarter.  Currently we limit to 
-      # one message per custnum because they'd all
-      # be identical.
       @message = $msg_template->prepare( 'cust_main' => $cust_main );
     }
     else {
@@ -508,7 +494,7 @@ sub email_search_result {
   if(@retry_jobs) {
     # fail the job, but with a status message that makes it clear
     # something was sent.
-    return "Sent $success, skipped $dups duplicate(s), failed ".scalar(@retry_jobs).". Failed attempts placed in job queue.\n";
+    return "Sent $success, failed ".scalar(@retry_jobs).". Failed attempts placed in job queue.\n";
   }
 
   return '';
index 014affe..e0c99f8 100644 (file)
@@ -264,36 +264,6 @@ sub insert {
   }
   #eslaf
 
-  #bill setup fees for voip_cdr bill_every_call packages
-  #some false laziness w/search in freeside-cdrd
-  my $addl_from =
-    'LEFT JOIN part_pkg USING ( pkgpart ) '.
-    "LEFT JOIN part_pkg_option
-       ON ( cust_pkg.pkgpart = part_pkg_option.pkgpart
-            AND part_pkg_option.optionname = 'bill_every_call' )";
-
-  my $extra_sql = " AND plan = 'voip_cdr' AND optionvalue = '1' ".
-                  " AND ( cust_pkg.setup IS NULL OR cust_pkg.setup = 0 ) ";
-
-  my @cust_pkg = qsearch({
-    'table'     => 'cust_pkg',
-    'addl_from' => $addl_from,
-    'hashref'   => { 'custnum' => $self->custnum,
-                     'susp'    => '',
-                     'cancel'  => '',
-                   },
-    'extra_sql' => $extra_sql,
-  });
-
-  if ( @cust_pkg ) {
-    warn "voip_cdr bill_every_call packages found; billing customer\n";
-    my $bill_error = $self->cust_main->bill_and_collect( 'fatal' => 'return' );
-    if ( $bill_error ) {
-      warn "WARNING: Error billing customer: $bill_error\n";
-    }
-  }
-  #end of billing setup fees for voip_cdr bill_every_call packages
-
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
   #payment receipt
@@ -431,17 +401,14 @@ sub delete {
 
 }
 
-=item replace [ OLD_RECORD ]
+=item replace OLD_RECORD
 
 You can, but probably shouldn't modify payments...
 
-Replaces the OLD_RECORD with this one in the database, or, if OLD_RECORD is not
-supplied, replaces this record.  If there is an error, returns the error,
-otherwise returns false.
-
 =cut
 
 sub replace {
+  #return "Can't modify payment!"
   my $self = shift;
   return "Can't modify closed payment" if $self->closed =~ /^Y/i;
   $self->SUPER::replace(@_);
@@ -833,10 +800,9 @@ sub _upgrade_data {  #class method
     my $h_cust_pay = $cust_pay->h_search('insert');
     if ( $h_cust_pay ) {
       next if $cust_pay->otaker eq $h_cust_pay->history_user;
-      #$cust_pay->otaker($h_cust_pay->history_user);
-      $cust_pay->set('otaker', $h_cust_pay->history_user);
+      $cust_pay->otaker($h_cust_pay->history_user);
     } else {
-      $cust_pay->set('otaker', 'legacy');
+      $cust_pay->otaker('legacy');
     }
 
     delete $FS::payby::hash{'COMP'}->{cust_pay}; #quelle kludge
index 3a30acb..9293ef6 100644 (file)
@@ -1,14 +1,12 @@
 package FS::cust_pay_void; 
 
 use strict;
-use base qw( FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
-             FS::Record );
+use base qw( FS::otaker_Mixin FS::payinfo_Mixin FS::Record );
 use vars qw( @encrypted_fields $otaker_upgrade_kludge );
 use Business::CreditCard;
 use FS::UID qw(getotaker);
-use FS::Record qw(qsearch qsearchs dbh fields);
+use FS::Record qw(qsearchs dbh fields); # qsearch );
 use FS::CurrentUser;
-use FS::access_user;
 use FS::cust_pay;
 #use FS::cust_bill;
 #use FS::cust_bill_pay;
@@ -157,13 +155,16 @@ sub unvoid {
 Deletes this voided payment.  You probably don't want to use this directly; see
 the B<unvoid> method to add the original payment back.
 
-=item replace [ OLD_RECORD ]
+=item replace OLD_RECORD
 
-You can, but probably shouldn't modify voided payments...
+Currently unimplemented.
 
-Replaces the OLD_RECORD with this one in the database, or, if OLD_RECORD is not
-supplied, replaces this record.  If there is an error, returns the error,
-otherwise returns false.
+=cut
+
+sub replace {
+   return "Can't modify voided payments!" unless $otaker_upgrade_kludge;
+   shift->SUPER::replace(@_);
+}
 
 =item check
 
@@ -221,8 +222,7 @@ sub check {
     return $error if $error;
   }
 
-  $self->void_usernum($FS::CurrentUser::CurrentUser->usernum)
-    unless $self->void_usernum;
+  $self->usernum($FS::CurrentUser::CurrentUser->usernum) unless $self->usernum;
 
   $self->SUPER::check;
 }
@@ -238,41 +238,11 @@ sub cust_main {
   qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
 }
 
-=item void_access_user
-
-Returns the voiding employee object (see L<FS::access_user>).
-
-=cut
-
-sub void_access_user {
-  my $self = shift;
-  qsearchs('access_user', { 'usernum' => $self->void_usernum } );
-}
-
 # Used by FS::Upgrade to migrate to a new database.
 sub _upgrade_data {  # class method
   my ($class, %opts) = @_;
-
-  my $sql = "SELECT usernum FROM access_user WHERE username = ( SELECT history_user FROM h_cust_pay_void WHERE paynum = ? AND history_action = 'insert' ORDER BY history_date LIMIT 1 ) ";
-  my $sth = dbh->prepare($sql) or die dbh->errstr;
-
-  foreach my $cust_pay_void (qsearch('cust_pay_void', {'void_usernum' => ''})) {
-    $sth->execute($cust_pay_void->paynum) or die $sth->errstr;
-    my $usernum = $sth->fetchrow_arrayref->[0] or next;
-    if ( $usernum ) {
-      $cust_pay_void->void_usernum($usernum);
-      my $error = $cust_pay_void->replace;
-      die $error if $error;
-    } else {
-      warn "cust_pay_void upgrade: can't find access_user record for ". $cust_pay_void->paynum. "\n";
-    }
-  }
-
   local($otaker_upgrade_kludge) = 1;
   $class->_upgrade_otaker(%opts);
-
-  #XXX look for the h_cust_pay delete records and when that's a different
-  # usernum, set usernum
 }
 
 =back
index ce5ee11..3e37ec9 100644 (file)
@@ -153,10 +153,6 @@ date
 
 date
 
-=item contract_end
-
-date
-
 =item cancel
 
 date
@@ -263,7 +259,7 @@ sub insert {
     $self->start_date( timelocal_nocheck(0,0,0,1,$mon,$year) );
   }
 
-  foreach my $action ( qw(expire adjourn contract_end) ) {
+  foreach my $action ( qw(expire adjourn) ) {
     my $months = $self->part_pkg->option("${action}_months",1);
     if($months and !$self->$action) {
       my $start = $self->start_date || $self->setup || time;
@@ -1118,7 +1114,7 @@ Options are:
 
 =over 4
 
-=item locationnum
+=item locaitonnum
 
 New locationnum, to change the location for this package.
 
@@ -1135,15 +1131,9 @@ New pkgpart (see L<FS::part_pkg>).
 
 New refnum (see L<FS::part_referral>).
 
-=item keep_dates
-
-Set to true to transfer billing dates (start_date, setup, last_bill, bill, 
-susp, adjourn, cancel, expire, and contract_end) to the new package.
-
 =back
 
-At least one of locationnum, cust_location, pkgpart, refnum must be specified 
-(otherwise, what's the point?)
+At least one option must be specified (otherwise, what's the point?)
 
 Returns either the new FS::cust_pkg object or a scalar error.
 
@@ -1201,13 +1191,6 @@ sub change {
     $opt->{'locationnum'} = $opt->{'cust_location'}->locationnum;
   }
 
-  if ( $opt->{'keep_dates'} ) {
-    foreach my $date ( qw(setup bill last_bill susp adjourn cancel expire 
-                          start_date contract_end ) ) {
-      $hash{$date} = $self->getfield($date);
-    }
-  }
-
   # Create the new package.
   my $cust_pkg = new FS::cust_pkg {
     custnum      => $self->custnum,
@@ -1257,7 +1240,7 @@ sub change {
                                                  ? ()
                                                  : ( 'null' => 1 )
                                    )
-      if $part_pkg->can('reset_usage') && ! $part_pkg->option('usage_rollover',1);
+      if $part_pkg->can('reset_usage') && ! $part_pkg->option('usage_rollover');
 
     if ($error) {
       $dbh->rollback if $oldAutoCommit;
@@ -1287,60 +1270,6 @@ sub change {
 
 }
 
-use Data::Dumper;
-use Storable 'thaw';
-use MIME::Base64;
-sub process_bulk_cust_pkg {
-  my $job = shift;
-  my $param = thaw(decode_base64(shift));
-  warn Dumper($param) if $DEBUG;
-
-  my $old_part_pkg = qsearchs('part_pkg', 
-                              { pkgpart => $param->{'old_pkgpart'} });
-  my $new_part_pkg = qsearchs('part_pkg',
-                              { pkgpart => $param->{'new_pkgpart'} });
-  die "Must select a new package type\n" unless $new_part_pkg;
-  #my $keep_dates = $param->{'keep_dates'} || 0;
-  my $keep_dates = 1; # there is no good reason to turn this off
-
-  local $SIG{HUP} = 'IGNORE';
-  local $SIG{INT} = 'IGNORE';
-  local $SIG{QUIT} = 'IGNORE';
-  local $SIG{TERM} = 'IGNORE';
-  local $SIG{TSTP} = 'IGNORE';
-  local $SIG{PIPE} = 'IGNORE';
-
-  my $oldAutoCommit = $FS::UID::AutoCommit;
-  local $FS::UID::AutoCommit = 0;
-  my $dbh = dbh;
-
-  my @cust_pkgs = qsearch('cust_pkg', { 'pkgpart' => $param->{'old_pkgpart'} } );
-
-  my $i = 0;
-  foreach my $old_cust_pkg ( @cust_pkgs ) {
-    $i++;
-    $job->update_statustext(int(100*$i/(scalar @cust_pkgs)));
-    if ( $old_cust_pkg->getfield('cancel') ) {
-      warn '[process_bulk_cust_pkg ] skipping canceled pkgnum '.
-        $old_cust_pkg->pkgnum."\n"
-        if $DEBUG;
-      next;
-    }
-    warn '[process_bulk_cust_pkg] changing pkgnum '.$old_cust_pkg->pkgnum."\n"
-      if $DEBUG;
-    my $error = $old_cust_pkg->change(
-      'pkgpart'     => $param->{'new_pkgpart'},
-      'keep_dates'  => $keep_dates
-    );
-    if ( !ref($error) ) { # change returns the cust_pkg on success
-      $dbh->rollback;
-      die "Error changing pkgnum ".$old_cust_pkg->pkgnum.": '$error'\n";
-    }
-  }
-  $dbh->commit if $oldAutoCommit;
-  return;
-}
-
 =item last_bill
 
 Returns the last bill date, or if there is no last bill date, the setup date.
@@ -1879,7 +1808,7 @@ Class method that returns the list of possible status strings for packages
 =cut
 
 tie my %statuscolor, 'Tie::IxHash', 
-  'not yet billed'  => '009999', #teal? cyan?
+  'not yet billed'  => '000000',
   'one-time charge' => '000000',
   'active'          => '00CC00',
   'suspended'       => 'FF9900',
@@ -2609,22 +2538,6 @@ sub cancel_sql {
   "cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0";
 }
 
-=item status_sql
-
-Returns an SQL expression to give the package status as a string.
-
-=cut
-
-sub status_sql {
-"CASE
-  WHEN cust_pkg.cancel IS NOT NULL THEN 'cancelled'
-  WHEN cust_pkg.susp IS NOT NULL THEN 'suspended'
-  WHEN cust_pkg.setup IS NULL THEN 'not yet billed'
-  WHEN ".onetime_sql()." THEN 'one-time charge'
-  ELSE 'active'
-END"
-}
-
 =item search HASHREF
 
 (Class method)
@@ -2893,7 +2806,7 @@ sub search {
       "NOT (".FS::cust_pkg->onetime_sql . ")";
   }
   else {
-    foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end cancel )) {
+    foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
 
       next unless exists($params->{$field});
 
@@ -3318,9 +3231,6 @@ sub bulk_change {
 sub _upgrade_data {  # class method
   my ($class, %opts) = @_;
   $class->_upgrade_otaker(%opts);
-  my $sql =('UPDATE cust_pkg SET contract_end = NULL WHERE contract_end = -1');
-  my $sth = dbh->prepare($sql);
-  $sth->execute or die $sth->errstr;
 }
 
 =back
index 7df7a55..4086f0f 100644 (file)
@@ -238,17 +238,12 @@ sub delete {
 
 =item replace OLD_RECORD
 
-You can, but probably shouldn't modify refunds... 
-
-Replaces the OLD_RECORD with this one in the database, or, if OLD_RECORD is not
-supplied, replaces this record.  If there is an error, returns the error,
-otherwise returns false.
+Modifying a refund?  Well, don't say I didn't warn you.
 
 =cut
 
 sub replace {
   my $self = shift;
-  return "Can't modify closed refund" if $self->closed =~ /^Y/i;
   $self->SUPER::replace(@_);
 }
 
index 8d767d5..9f1eb53 100644 (file)
@@ -440,7 +440,7 @@ sub reverse_record {
 #http://en.wikipedia.org/wiki/List_of_DNS_record_types
 #DHCID?  other things?
 sub rectypes {
-  [ qw(SOA A AAAA CNAME MX NS PTR SPF SRV TXT), #most common types
+  [ qw(A AAAA CNAME MX NS PTR SPF SRV TXT), #most common types
     #qw(DNAME), #uncommon types
     qw(DLV DNSKEY DS NSEC NSEC3 NSEC3PARAM RRSIG), #DNSSEC types
   ];
diff --git a/FS/FS/geocode_Mixin.pm b/FS/FS/geocode_Mixin.pm
deleted file mode 100644 (file)
index c153914..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-package FS::geocode_Mixin;
-
-use strict;
-use vars qw( $DEBUG $me );
-use Carp;
-use Locale::Country;
-use FS::Record qw( qsearchs qsearch );
-use FS::Conf;
-use FS::cust_pkg;
-use FS::cust_location;
-use FS::cust_tax_location;
-use FS::part_pkg;
-
-$DEBUG = 0;
-$me = '[FS::geocode_Mixin]';
-
-=head1 NAME
-
-FS::geocode_Mixin - Mixin class for records that contain address and other
-location fields.
-
-=head1 SYNOPSIS
-
-  package FS::some_table;
-  use base ( FS::geocode_Mixin FS::Record );
-
-=head1 DESCRIPTION
-
-FS::geocode_Mixin - This is a mixin class for records that contain address
-and other location fields.
-
-=head1 METHODS
-
-=over 4
-
-=cut
-
-=item location_hash
-
-Returns a list of key/value pairs, with the following keys: address1, address2,
-city, county, state, zip, country.  The shipping address is used if present.
-
-=cut
-
-#geocode dependent on tax-ship_address config
-
-sub location_hash {
-  my $self = shift;
-  my $prefix = $self->has_ship_address ? 'ship_' : '';
-
-  map { my $method = ($_ eq 'geocode') ? $_ : $prefix.$_;
-        $_ => $self->get($method);
-      }
-      qw( address1 address2 city county state zip country geocode );
-}
-
-=item location_label [ OPTION => VALUE ... ]
-
-Returns the label of the service location (see analog in L<FS::cust_location>) for this customer.
-
-Options are
-
-=over 4
-
-=item join_string
-
-used to separate the address elements (defaults to ', ')
-
-=item escape_function
-
-a callback used for escaping the text of the address elements
-
-=back
-
-=cut
-
-sub location_label {
-  my $self = shift;
-  my %opt = @_;
-
-  my $separator = $opt{join_string} || ', ';
-  my $escape = $opt{escape_function} || sub{ shift };
-  my $ds = $opt{double_space} || '  ';
-  my $line = '';
-  my $cydefault = 
-    $opt{'countrydefault'} || FS::Conf->new->config('countrydefault') || 'US';
-  my $prefix = $self->has_ship_address ? 'ship_' : '';
-
-  my $notfirst = 0;
-  foreach (qw ( address1 address2 ) ) {
-    my $method = "$prefix$_";
-    $line .= ($notfirst ? $separator : ''). &$escape($self->$method)
-      if $self->$method;
-    $notfirst++;
-  }
-  $notfirst = 0;
-  foreach (qw ( city county state zip ) ) {
-    my $method = "$prefix$_";
-    if ( $self->$method ) {
-      $line .= ' (' if $method eq 'county';
-      $line .= ($notfirst ? ' ' : $separator). &$escape($self->$method);
-      $line .= ' )' if $method eq 'county';
-      $notfirst++;
-    }
-  }
-  $line .= $separator. &$escape(code2country($self->country))
-    if $self->country ne $cydefault;
-
-  $line;
-}
-
-=item geocode DATA_VENDOR
-
-Returns a value for the customer location as encoded by DATA_VENDOR.
-Currently this only makes sense for "CCH" as DATA_VENDOR.
-
-=cut
-
-sub geocode {
-  my ($self, $data_vendor) = (shift, shift);  #always cch for now
-
-  my $geocode = $self->get('geocode');  #XXX only one data_vendor for geocode
-  return $geocode if $geocode;
-
-  my $prefix =
-   ( FS::Conf->new->exists('tax-ship_address') && $self->has_ship_address )
-   ? 'ship_'
-   : '';
-
-  my($zip,$plus4) = split /-/, $self->get("${prefix}zip")
-    if $self->country eq 'US';
-
-  $zip ||= '';
-  $plus4 ||= '';
-  #CCH specific location stuff
-  my $extra_sql = "AND plus4lo <= '$plus4' AND plus4hi >= '$plus4'";
-
-  my @cust_tax_location =
-    qsearch( {
-               'table'     => 'cust_tax_location', 
-               'hashref'   => { 'zip' => $zip, 'data_vendor' => $data_vendor },
-               'extra_sql' => $extra_sql,
-               'order_by'  => 'ORDER BY plus4hi',#overlapping with distinct ends
-             }
-           );
-  $geocode = $cust_tax_location[0]->geocode
-    if scalar(@cust_tax_location);
-
-  $geocode;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
index 270eb1f..7321351 100644 (file)
@@ -166,13 +166,7 @@ Customer object (required).
 =item object
 
 Additional context object (currently, can be a cust_main, cust_pkg, 
-cust_bill, svc_acct, cust_pay, or cust_pay_pending).  If the object 
-is a svc_acct, its cust_pkg will be fetched and used for substitution.
-
-As a special case, this may be an arrayref of two objects.  Both 
-objects will be available for substitution, with their field names 
-prefixed with 'new_' and 'old_' respectively.  This is used in the 
-rt_ticket export when exporting "replace" events.
+cust_bill, svc_acct, cust_pay, or cust_pay_pending object).
 
 =item to
 
@@ -197,37 +191,15 @@ sub prepare {
   # create substitution table
   ###  
   my %hash;
-  my @objects = ($cust_main);
-  my @prefixes = ('');
-  my $svc;
-  if( ref $object ) {
-    if( ref($object) eq 'ARRAY' ) {
-      # [new, old], for provisioning tickets
-      push @objects, $object->[0], $object->[1];
-      push @prefixes, 'new_', 'old_';
-      $svc = $object->[0] if $object->[0]->isa('FS::svc_Common');
-    }
-    else {
-      push @objects, $object;
-      push @prefixes, '';
-      $svc = $object if $object->isa('FS::svc_Common');
-    }
-  }
-  if( $svc ) {
-    push @objects, $svc->cust_svc->cust_pkg;
-    push @prefixes, '';
-  }
-
-  foreach my $obj (@objects) {
-    my $prefix = shift @prefixes;
+  foreach my $obj ($cust_main, $object || ()) {
     foreach my $name (@{ $subs->{$obj->table} }) {
       if(!ref($name)) {
         # simple case
-        $hash{$prefix.$name} = $obj->$name();
+        $hash{$name} = $obj->$name();
       }
       elsif( ref($name) eq 'ARRAY' ) {
         # [ foo => sub { ... } ]
-        $hash{$prefix.($name->[0])} = $name->[1]->($obj);
+        $hash{$name->[0]} = $name->[1]->($obj);
       }
       else {
         warn "bad msg_template substitution: '$name'\n";
@@ -368,7 +340,7 @@ sub substitutions {
     ],
     # next_bill_date
     'cust_pkg'  => [qw( 
-      pkgnum pkg pkg_label pkg_label_long
+      pkgnum pkg_label pkg_label_long
       location_label
       status statuscolor
     
@@ -394,9 +366,7 @@ sub substitutions {
     
     # for welcome and limit warning messages
     'svc_acct' => [qw(
-      svcnum
       username
-      domain
       ),
       [ password          => sub { shift->getfield('_password') } ],
     ],
index 26bb7ca..a786ae3 100644 (file)
@@ -173,15 +173,10 @@ sub replace {
               ? shift
               : $self->replace_old;
 
-  my $options;
-  my $options_supplied = 0;
-  if ( ref($_[0]) eq 'HASH' ) {
-    $options = shift;
-    $options_supplied = 1;
-  } else {
-    $options = { @_ };
-    $options_supplied = scalar(@_) ? 1 : 0;
-  }
+  my $options = 
+    ( ref($_[0]) eq 'HASH' )
+      ? shift
+      : { @_ };
 
   warn "FS::option_Common::replace called on $self with options ".
        join(', ', map "$_ => ". $options->{$_}, keys %$options)
@@ -257,15 +252,13 @@ sub replace {
   }
 
   #remove extraneous old options
-  if ( $options_supplied ) {
-    foreach my $opt (
-      grep { !exists $options->{$_->$namecol()} } $old->option_objects
-    ) {
-      my $error = $opt->delete;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return $error;
-      }
+  foreach my $opt (
+    grep { !exists $options->{$_->$namecol()} } $old->option_objects
+  ) {
+    my $error = $opt->delete;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
     }
   }
 
index 066ee48..fbdff25 100644 (file)
@@ -29,12 +29,4 @@ sub condition {
   $hashref->{ $cust_main->status };
 }
 
-sub condition_sql {
-  my( $self, $table ) = @_;
-
-  '('.FS::cust_main->cust_status_sql . ') IN '.
-    $self->condition_sql_option_option('status');
-}
-
-
 1;
index 70c9c7f..61a8155 100644 (file)
@@ -38,13 +38,11 @@ sub condition {
 }
 
 sub condition_sql {
-  my( $class, $table ) = @_;
+  #my( $class, $table ) = @_;
 
-  my $sql = FS::cust_main->active_sql;
-  $sql =~ s/cust_main.custnum/cust_main.referral_custnum/;
-  $sql = 'cust_main.referral_custnum IS NOT NULL AND ('.
-          $class->condition_sql_option('active') . ' IS NULL OR '.$sql.')';
-  return $sql;
+  "cust_main.referral_custnum IS NOT NULL";
+
+  #XXX a bit harder to check active status here
 }
 
 1;
index 4a85387..8b3b4c9 100644 (file)
@@ -49,18 +49,10 @@ sub condition {
 
 }
 
-sub condition_sql {
-  my( $class, $table, %opt ) = @_;
-  my $age   = $class->condition_sql_option_age_from('age', $opt{'time'});
-  my $field = $class->condition_sql_option('field');
-#amazingly, this is actually faster 
-  my $sql = '( CASE';
-  foreach( qw(setup last_bill bill adjourn susp expire cancel) ) {
-    $sql .= " WHEN $field = '$_' THEN (cust_pkg.$_ IS NOT NULL AND cust_pkg.$_ <= $age)";
-  }
-  $sql .= ' END )';
-  return $sql;
-}
+#XXX write me for efficiency
+#sub condition_sql {
+#
+#}
 
 1;
 
index 1a08869..1b66821 100644 (file)
@@ -20,9 +20,12 @@ sub condition {
 
 }
 
-sub condition_sql {
-  FS::cust_pkg->recurring_sql()
-}
+
+#XXX  join part_pkg USING (pkgpart) 
+#  part_pkg.freq != '0'
+#sub condition_sql {
+#
+#}
 
 1;
 
index 3fb374e..6c1c9cc 100644 (file)
@@ -34,11 +34,4 @@ sub condition {
   $hashref->{ $cust_pkg->status };
 }
 
-sub condition_sql {
-  my( $self, $table ) = @_;
-
-  '('.FS::cust_pkg->status_sql . ') IN '.
-  $self->condition_sql_option_option('status');
-}
-
 1;
diff --git a/FS/FS/part_export/acct_http.pm b/FS/FS/part_export/acct_http.pm
deleted file mode 100644 (file)
index b4c64ac..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-package FS::part_export::acct_http;
-
-use vars qw( @ISA %info );
-use FS::part_export::http;
-use Tie::IxHash;
-
-@ISA = qw( FS::part_export::http );
-
-tie %options, 'Tie::IxHash',
-  'method' => { label   =>'Method',
-                type    =>'select',
-                #options =>[qw(POST GET)],
-                options =>[qw(POST)],
-                default =>'POST' },
-  'url'    => { label   => 'URL', default => 'http://', },
-  'insert_data' => {
-    label   => 'Insert data',
-    type    => 'textarea',
-    default => join("\n",
-      "action 'add'",
-      "username \$svc_x->username",
-      "password \$svc_x->_password",
-      "prismid \$cust_main->agent_custid ? \$cust_main->agent_custid : \$cust_main->custnum ",
-      "name \$cust_main->first.' '.\$cust_main->last",
-    ),
-  },
-  'delete_data' => {
-    label   => 'Delete data',
-    type    => 'textarea',
-    default => join("\n",
-      "action  'remove'",
-      "username \$svc_x->username",
-    ),
-  },
-  'replace_data' => {
-    label   => 'Replace data',
-    type    => 'textarea',
-    default => join("\n",
-      "action  'update'",
-      "username \$old->username",
-      "password \$new->_password",
-    ),
-  },
-  'success_regexp' => {
-    label  => 'Success Regexp',
-    default => '',
-  },
-;
-
-%info = (
-  'svc'     => 'svc_acct',
-  'desc'    => 'Send an HTTP or HTTPS GET or POST request, for accounts.',
-  'options' => \%options,
-  'notes'   => <<'END'
-Send an HTTP or HTTPS GET or POST to the specified URL on account 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;
index e8b677b..59503e8 100644 (file)
@@ -6,50 +6,28 @@ use Tie::IxHash;
 
 @ISA = qw( FS::part_export::http );
 
-tie %options, 'Tie::IxHash',
-  'method' => { label   =>'Method',
-                type    =>'select',
-                #options =>[qw(POST GET)],
-                options =>[qw(POST)],
-                default =>'POST' },
-  'url'    => { label   => 'URL', default => 'http://', },
-  'insert_data' => {
-    label   => 'Insert data',
-    type    => 'textarea',
-    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",
-    ),
-  },
-  'delete_data' => {
-    label   => 'Delete data',
-    type    => 'textarea',
-    default => join("\n",
-      "action  'delete'",
-      "custnum \$cust_main->custnum",
-    ),
-  },
-  'replace_data' => {
-    label   => 'Replace data',
-    type    => 'textarea',
-    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",
-    ),
-  },
-  'success_regexp' => {
-    label  => 'Success Regexp',
-    default => '',
-  },
-;
+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',
index 3749224..e5e5a5c 100644 (file)
@@ -33,10 +33,6 @@ tie %options, 'Tie::IxHash',
     default => join("\n",
     ),
   },
-  'success_regexp' => {
-    label  => 'Success Regexp',
-    default => '',
-  },
 ;
 
 %info = (
@@ -75,7 +71,6 @@ sub _export_command {
   $self->http_queue( $svc_x->svcnum,
     $self->option('method'),
     $self->option('url'),
-    $self->option('success_regexp'),
     map {
       /^\s*(\S+)\s+(.*)$/ or /()()/;
       my( $field, $value_expression ) = ( $1, $2 );
@@ -100,7 +95,6 @@ sub _export_replace {
   $self->http_queue( $new->svcnum,
     $self->option('method'),
     $self->option('url'),
-    $self->option('success_regexp'),
     map {
       /^\s*(\S+)\s+(.*)$/ or /()()/;
       my( $field, $value_expression ) = ( $1, $2 );
@@ -120,7 +114,7 @@ sub http_queue {
 }
 
 sub http {
-  my($method, $url, $success_regexp, @data) = @_;
+  my($method, $url, @data) = @_;
 
   $method = lc($method);
 
@@ -140,11 +134,6 @@ sub http {
 
   die $response->error_as_HTML if $response->is_error;
 
-  if(length($success_regexp) > 1) {
-    my $response_content = $response->content;
-    die $response_content unless $response_content =~ /$success_regexp/;
-  }
-
 }
 
 1;
diff --git a/FS/FS/part_export/rt_ticket.pm b/FS/FS/part_export/rt_ticket.pm
deleted file mode 100644 (file)
index 13a0367..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-package FS::part_export::rt_ticket;
-
-use vars qw(@ISA %info);
-use Tie::IxHash;
-use FS::part_export;
-use FS::Record qw(qsearch qsearchs);
-use FS::Conf;
-use FS::TicketSystem;
-
-@ISA = qw(FS::part_export);
-
-my %templates;
-my %queues;
-my %template_select = (
-  type          => 'select',
-  freeform      => 1,
-  option_label  => sub {
-    $templates{$_[0]};
-  },
-  option_values => sub {
-    %templates = (0 => '',
-      map { $_->msgnum, $_->msgname } 
-      qsearch({ table => 'msg_template',
-                hashref => {},
-                order_by => 'ORDER BY msgnum ASC'
-              })
-    );
-    sort keys (%templates);
-  },
-);
-
-my %queue_select = (
-  type          => 'select',
-  freeform      => 1,
-  option_label  => sub {
-    $queues{$_[0]};
-  },
-  option_values => sub {
-    %queues = (0 => '', FS::TicketSystem->queues());
-    sort {$queues{$a} cmp $queues{$b}} keys %queues;
-  },
-);
-
-tie my %options, 'Tie::IxHash', (
-  'insert_queue' => {
-    before  => '
-<TR><TD COLSPAN=2>
-<TABLE>
-  <TR><TH></TH><TH>Queue</TH><TH>Template</TH></TR>
-  <TR><TD>New service</TD><TD>',
-    %queue_select,
-    after   => '</TD>'
-  },
-  'insert_template' => {
-    before  => '<TD>',
-    %template_select,
-    after   => '</TD></TR>
-',
-  },
-  'delete_queue' => {
-    before  => '
-  <TR><TD>Delete</TD><TD>',
-    %queue_select,
-    after   => '</TD>',
-  },
-  'delete_template' => {
-    before  => '<TD>',
-    %template_select,
-    after   => '</TD></TR>
-',
-  },
-  'replace_queue' => {
-    before  => '
-  <TR><TD>Modify</TD><TD>',
-    %queue_select,
-    after   => '</TD>',
-  },
-  'replace_template' => {
-    before  => '<TD>',
-    %template_select,
-    after   => '</TD></TR>
-',
-  },
-  'suspend_queue' => {
-    before  => '
-  <TR><TD>Suspend</TD><TD>',
-    %queue_select,
-    after   => '</TD>',
-  },
-  'suspend_template' => {
-    before  => '<TD>',
-    %template_select,
-    after   => '</TD></TR>
-',
-  },
-  'unsuspend_queue' => {
-    before  => '
-  <TR><TD>Unsuspend</TD><TD>',
-    %queue_select,
-    after   => '</TD>',
-  },
-  'unsuspend_template' => {
-    before  => '<TD>',
-    %template_select,
-    after   => '</TD></TR>
-  </TABLE>
-</TD></TR>',
-  },
-  'requestor' => {
-    freeform  => 0,
-    label     => 'Requestor',
-    'type'    => 'select',
-    option_label => sub {
-      my @labels = (
-        'Template From: address',
-        'Customer\'s invoice address',
-      );
-      $labels[shift];
-    },
-    option_values => sub { (0, 1) },
-  },
-);
-
-%info = (
-  'svc'      => [qw( svc_acct )], #others?
-  'desc'     =>
-    'Create an RT ticket',
-  'options'  => \%options,
-  'nodomain' => '',
-  'notes'    => <<'END'
-Create a ticket in RT.  The subject and body of the ticket 
-will be generated from a message template.
-END
-);
-
-sub _export_ticket {
-  my( $self, $action, $svc ) = (shift, shift, shift);
-  my $msgnum = $self->option($action.'_template');
-  return if !$msgnum;
-
-  my $queue = $self->option($action.'_queue');
-  return if !$queue;
-
-  my $msg_template = FS::msg_template->by_key($msgnum);
-  return "Template $msgnum not found\n" if !$msg_template;
-
-  my $cust_pkg = $svc->cust_svc->cust_pkg;
-  my $cust_main = $svc->cust_svc->cust_pkg->cust_main if $cust_pkg;
-  my $custnum = $cust_main->custnum if $cust_main;
-  my $svcnum = $svc->svcnum if $action ne 'delete';
-
-  my %msg;
-  if ( $action eq 'replace' ) {
-    my $old = shift;
-    %msg = $msg_template->prepare(
-      'cust_main' => $cust_main,
-      'object'    => [ $svc, $old ],
-    );
-
-  }
-  else {
-    %msg = $msg_template->prepare(
-      'cust_main' => $cust_main,
-      'object'    => $svc,
-    );
-  }
-  my $requestor = $msg{'from'};
-  $requestor = [ $cust_main->invoicing_list_emailonly ]
-    if $cust_main and $self->option('requestor') == 1;
-
-  my $err_or_ticket = FS::TicketSystem->create_ticket(
-    '', #session should already exist
-    'queue'     => $queue,
-    'subject'   => $msg{'subject'},
-    'requestor' => $requestor,
-    'message'   => $msg{'html_body'},
-    'mime_type' => 'text/html',
-    'custnum'   => $custnum,
-    'svcnum'    => $svcnum,
-  );
-  if( ref($err_or_ticket) ) {
-    return '';
-  }
-  else {
-    return $err_or_ticket;
-  }
-}
-
-sub _export_insert {
-  my($self, $svc) = (shift, shift);
-  $self->_export_ticket('insert', $svc);
-}
-
-sub _export_replace {
-  my($self, $new, $old) = (shift, shift, shift);
-  $self->_export_ticket('replace', $new, $old);
-}
-
-sub _export_delete {
-  my($self, $svc) = (shift, shift);
-  $self->_export_ticket('delete', $svc);
-}
-
-sub _export_suspend {
-  my($self, $svc) = (shift, shift);
-  $self->_export_ticket('suspend', $svc);
-}
-
-sub _export_unsuspend {
-  my($self, $svc) = (shift, shift);
-  $self->_export_ticket('unsuspend', $svc);
-}
-
-1;
index 15aa986..f1ba3d2 100644 (file)
@@ -18,10 +18,6 @@ tie %options, 'Tie::IxHash',
   'datasrc'  => { label=>'DBI data source ' },
   'username' => { label=>'Database username' },
   'password' => { label=>'Database password' },
-  'usergroup' => { label   => 'Group table',
-                   type    => 'select',
-                   options => [qw( usergroup radusergroup ) ],
-                 },
   'ignore_accounting' => {
     type  => 'checkbox',
     label => 'Ignore accounting records from this database'
@@ -56,7 +52,7 @@ tie %options, 'Tie::IxHash',
 ;
 
 $notes1 = <<'END';
-Real-time export of <b>radcheck</b>, <b>radreply</b> and <b>usergroup</b>/<b>radusergroup</b>
+Real-time export of <b>radcheck</b>, <b>radreply</b> and <b>usergroup</b>
 tables to any SQL database for
 <a href="http://www.freeradius.org/">FreeRADIUS</a>
 or <a href="http://radius.innercite.com/">ICRADIUS</a>.
@@ -125,10 +121,9 @@ sub _export_insert {
     cluck localtime(). ": queuing usergroup_insert for ". $svc_x->svcnum.
           " (". $self->export_username($svc_x). " with ". join(", ", @groups)
       if $DEBUG;
-    my $usergroup = $self->option('usergroup') || 'usergroup';
     my $err_or_queue = $self->sqlradius_queue(
       $svc_x->svcnum, 'usergroup_insert',
-      $self->export_username($svc_x), $usergroup, @groups );
+      $self->export_username($svc_x), @groups );
     return $err_or_queue unless ref($err_or_queue);
   }
   '';
@@ -150,9 +145,8 @@ sub _export_replace {
 
   my $jobnum = '';
   if ( $self->export_username($old) ne $self->export_username($new) ) {
-    my $usergroup = $self->option('usergroup') || 'usergroup';
     my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'rename',
-      $self->export_username($new), $self->export_username($old), $usergroup );
+      $self->export_username($new), $self->export_username($old) );
     unless ( ref($err_or_queue) ) {
       $dbh->rollback if $oldAutoCommit;
       return $err_or_queue;
@@ -301,9 +295,8 @@ sub _export_unsuspend {
 
 sub _export_delete {
   my( $self, $svc_x ) = (shift, shift);
-  my $usergroup = $self->option('usergroup') || 'usergroup';
   my $err_or_queue = $self->sqlradius_queue( $svc_x->svcnum, 'delete',
-    $self->export_username($svc_x), $usergroup );
+    $self->export_username($svc_x) );
   ref($err_or_queue) ? '' : $err_or_queue;
 }
 
@@ -394,16 +387,14 @@ sub sqlradius_insert { #subroutine, not method
 
 sub sqlradius_usergroup_insert { #subroutine, not method
   my $dbh = sqlradius_connect(shift, shift, shift);
-  my $username = shift;
-  my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
-  my @groups = @_;
+  my( $username, @groups ) = @_;
 
   my $s_sth = $dbh->prepare(
-    "SELECT COUNT(*) FROM $usergroup WHERE UserName = ? AND GroupName = ?"
+    "SELECT COUNT(*) FROM usergroup WHERE UserName = ? AND GroupName = ?"
   ) or die $dbh->errstr;
 
   my $sth = $dbh->prepare( 
-    "INSERT INTO $usergroup ( UserName, GroupName ) VALUES ( ?, ? )"
+    "INSERT INTO usergroup ( UserName, GroupName ) VALUES ( ?, ? )"
   ) or die $dbh->errstr;
 
   foreach my $group ( @groups ) {
@@ -430,12 +421,10 @@ sub sqlradius_usergroup_insert { #subroutine, not method
 
 sub sqlradius_usergroup_delete { #subroutine, not method
   my $dbh = sqlradius_connect(shift, shift, shift);
-  my $username = shift;
-  my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
-  my @groups = @_;
+  my( $username, @groups ) = @_;
 
   my $sth = $dbh->prepare( 
-    "DELETE FROM $usergroup WHERE UserName = ? AND GroupName = ?"
+    "DELETE FROM usergroup WHERE UserName = ? AND GroupName = ?"
   ) or die $dbh->errstr;
   foreach my $group ( @groups ) {
     $sth->execute( $username, $group )
@@ -446,9 +435,8 @@ sub sqlradius_usergroup_delete { #subroutine, not method
 
 sub sqlradius_rename { #subroutine, not method
   my $dbh = sqlradius_connect(shift, shift, shift);
-  my($new_username, $old_username) = (shift, shift);
-  my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
-  foreach my $table (qw(radreply radcheck), $usergroup ) {
+  my($new_username, $old_username) = @_;
+  foreach my $table (qw(radreply radcheck usergroup )) {
     my $sth = $dbh->prepare("UPDATE $table SET Username = ? WHERE UserName = ?")
       or die $dbh->errstr;
     $sth->execute($new_username, $old_username)
@@ -474,9 +462,8 @@ sub sqlradius_attrib_delete { #subroutine, not method
 sub sqlradius_delete { #subroutine, not method
   my $dbh = sqlradius_connect(shift, shift, shift);
   my $username = shift;
-  my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
 
-  foreach my $table (qw( radcheck radreply), $usergroup ) {
+  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;
@@ -505,11 +492,9 @@ sub sqlreplace_usergroups {
     push @delgroups, $oldgroup;
   }
 
-  my $usergroup = $self->option('usergroup') || 'usergroup';
-
   if ( @delgroups ) {
     my $err_or_queue = $self->sqlradius_queue( $svcnum, 'usergroup_delete',
-      $username, $usergroup, @delgroups );
+      $username, @delgroups );
     return $err_or_queue
       unless ref($err_or_queue);
     if ( $jobnum ) {
@@ -523,7 +508,7 @@ sub sqlreplace_usergroups {
           "with ".  join(", ", @newgroups)
       if $DEBUG;
     my $err_or_queue = $self->sqlradius_queue( $svcnum, 'usergroup_insert',
-      $username, $usergroup, @newgroups );
+      $username, @newgroups );
     return $err_or_queue
       unless ref($err_or_queue);
     if ( $jobnum ) {
index a073cf2..85269c5 100644 (file)
@@ -941,8 +941,6 @@ sub _part_pkg_link {
   qsearch({ table    => 'part_pkg_link',
             hashref  => { 'src_pkgpart' => $self->pkgpart,
                           'link_type'   => $type,
-                          #protection against infinite recursive links
-                          'dst_pkgpart' => { op=>'!=', value=> $self->pkgpart },
                         },
             order_by => "ORDER BY hidden",
          });
index 69ecf77..e5bd163 100644 (file)
@@ -38,10 +38,6 @@ $me = '[FS::part_pkg::agent]';
     'cutoff_day'    => { 'name' => 'Billing Day (1 - 28)',
                          'default' => '1',
                        },
-    'add_full_period'=> { 'name' => 'When prorating first month, also bill '.
-                                    'for one full period after that',
-                          'type' => 'checkbox',
-                        },
 
     'no_pkg_prorate'   => { 'name' => 'Disable prorating bulk packages (charge full price for packages active only a portion of the month)',
                             'type' => 'checkbox',
@@ -50,7 +46,7 @@ $me = '[FS::part_pkg::agent]';
   },
 
   #'fieldorder' => [qw( setup_fee recur_fee recur_method cutoff_day ) ],
-  'fieldorder' => [qw( setup_fee recur_fee cutoff_day add_full_period no_pkg_prorate ) ],
+  'fieldorder' => [qw( setup_fee recur_fee cutoff_day no_pkg_prorate ) ],
 
   'weight' => 51,
 
index b28fd30..69fe98e 100644 (file)
@@ -7,7 +7,7 @@ use FS::part_pkg::flat;
 
 @ISA = qw(FS::part_pkg::flat);
 
-$DEBUG = 0;
+$DEBUG = 1;
 $me = '[FS::part_pkg::bulk]';
 
 %info = (
@@ -29,17 +29,9 @@ $me = '[FS::part_pkg::bulk]';
                                    ' of service at cancellation',
                          'type' => 'checkbox',
                        },
-    'summarize_svcs'=> { 'name' => 'Show a count of services on the invoice, '.
-                                   'instead of a detailed list',
-                         'type' => 'checkbox',
-                       },
-    'no_prorate'    => { 'name' => 'Don\'t prorate recurring fees on services '.
-                                   'active for a partial month',
-                         'type' => 'checkbox',
-                       },
   },
   'fieldorder' => [ 'setup_fee', 'recur_fee', 'svc_setup_fee', 'svc_recur_fee',
-                    'unused_credit', 'summarize_svcs', 'no_prorate' ],
+                    'unused_credit', ],
   'weight' => 50,
 );
 
@@ -58,11 +50,6 @@ sub calc_recur {
     unless $$sdate > $last_bill;
 
   my $total_svc_charge = 0;
-  my %n_setup = ();
-  my %n_recur = ();
-  my %part_svc_label = ();
-
-  my $summarize = $self->option('summarize_svcs',1);
 
   warn "$me billing for bulk services from ". time2str('%x', $last_bill).
                                       " to ". time2str('%x', $$sdate). "\n"
@@ -74,7 +61,6 @@ sub calc_recur {
     my @label = $h_cust_svc->label_long( $$sdate, $last_bill );
     die "fatal: no historical label found, wtf?" unless scalar(@label); #?
     my $svc_details = $label[0]. ': '. $label[1]. ': ';
-    $part_svc_label{$h_cust_svc->svcpart} ||= $label[0];
 
     my $svc_charge = 0;
 
@@ -84,21 +70,14 @@ sub calc_recur {
     } elsif ( $svc_setup_fee ) {
       $svc_charge += $svc_setup_fee;
       $svc_details .= $money_char. sprintf('%.2f setup, ', $svc_setup_fee);
-      $n_setup{$h_cust_svc->svcpart}++;
     }
 
     my $svc_end = $h_cust_svc->date_deleted;
     $svc_end = ( !$svc_end || $svc_end > $$sdate ) ? $$sdate : $svc_end;
 
-    my $recur_charge;
-    if ( $self->option('no_prorate',1) ) {
-      $recur_charge = $self->option('svc_recur_fee');
-    }
-    else {
-      $recur_charge = $self->option('svc_recur_fee') 
-                                     * ( $svc_end - $svc_start )
+    my $recur_charge =
+      $self->option('svc_recur_fee') * ( $svc_end - $svc_start )
                                      / ( $$sdate  - $last_bill );
-    }
 
     $svc_details .= $money_char. sprintf('%.2f', $recur_charge ).
                     ' ('.  time2str('%x', $svc_start).
@@ -106,21 +85,11 @@ sub calc_recur {
       if $recur_charge;
 
     $svc_charge += $recur_charge;
-    $n_recur{$h_cust_svc->svcpart}++;
-    push @$details, $svc_details if !$summarize;
+
+    push @$details, $svc_details;
     $total_svc_charge += $svc_charge;
 
   }
-  if ( $summarize ) {
-    foreach my $svcpart (keys %part_svc_label) {
-      push @$details, sprintf('Setup fee: %d @ '.$money_char.'%.2f',
-        $n_setup{$svcpart}, $svc_setup_fee )
-        if $svc_setup_fee and $n_setup{$svcpart};
-      push @$details, sprintf('%d services @ '.$money_char.'%.2f',
-        $n_recur{$svcpart}, $self->option('svc_recur_fee') )
-        if $n_recur{$svcpart};
-    }
-  }
 
   sprintf('%.2f', $self->base_recur($cust_pkg) + $total_svc_charge );
 }
index 0666d79..cfd6b4e 100644 (file)
@@ -58,10 +58,6 @@ tie my %temporalities, 'Tie::IxHash',
                                    'subscription',
                          'default' => '1',
                        },
-    'add_full_period'=> { 'name' => 'When prorating first month, also bill '.
-                                    'for one full period after that',
-                          'type' => 'checkbox',
-                        },
 
     'recur_method'  => { 'name' => 'Recurring fee method',
                          #'type' => 'radio',
@@ -94,7 +90,6 @@ tie my %temporalities, 'Tie::IxHash',
   'fieldorder' => [qw(
                        setup_fee recur_fee
                        recur_temporality unused_credit recur_method cutoff_day
-                       add_full_period
                        output_format usage_section summarize_usage usage_mandate
                      )
                   ],
diff --git a/FS/FS/part_pkg/discount_Mixin.pm b/FS/FS/part_pkg/discount_Mixin.pm
deleted file mode 100644 (file)
index df65e97..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-package FS::part_pkg::discount_Mixin;
-
-use strict;
-use vars qw(@ISA %info);
-use FS::part_pkg;
-use FS::cust_pkg;
-use FS::cust_bill_pkg_discount;
-use Time::Local qw(timelocal);
-use List::Util 'min';
-
-@ISA = qw(FS::part_pkg);
-%info = ( 'disabled' => 1 );
-
-=head1 NAME
-
-FS::part_pkg::discount_Mixin - Mixin class for part_pkg:: classes that 
-can be discounted.
-
-=head1 SYNOPSIS
-
-package FS::part_pkg::...;
-use base qw( FS::part_pkg::discount_Mixin );
-
-sub calc_recur {
-  ...
-  my $discount = $self->calc_discount($cust_pkg, $$sdate, $details, $param);
-  $charge -= $discount;
-  ...
-}
-
-=head METHODS
-
-=item calc_discount
-
-Takes all the arguments of calc_recur.  Calculates and returns  the amount 
-by which to reduce the recurring fee; also increments months used on the 
-discount and generates an invoice detail describing it.
-
-=cut
-
-sub calc_discount {
-  my($self, $cust_pkg, $sdate, $details, $param ) = @_;
-
-  my $br = $self->base_recur($cust_pkg);
-
-  my $tot_discount = 0;
-  #UI enforces just 1 for now, will need ordering when they can be stacked
-
-  if ( $param->{freq_override} ) {
-    # When a customer pays for more than one month at a time to receive a 
-    # term discount, freq_override is set to the number of months.
-    my $real_part_pkg = new FS::part_pkg { $self->hash };
-    $real_part_pkg->pkgpart($param->{real_pkgpart} || $self->pkgpart);
-    # Find a discount with that duration...
-    my @discount = grep { $_->months == $param->{freq_override} }
-                    map { $_->discount } $real_part_pkg->part_pkg_discount;
-    my $discount = shift @discount;
-    # and default to bill that many months at once.
-    $param->{months} = $param->{freq_override} unless $param->{months};
-    my $error;
-    if ($discount) {
-      # Then set the cust_pkg discount.
-      if ($discount->months == $param->{months}) {
-        $cust_pkg->discountnum($discount->discountnum);
-        $error = $cust_pkg->insert_discount;
-      } else {
-        $cust_pkg->discountnum(-1);
-        foreach ( qw( amount percent months ) ) {
-          my $method = "discountnum_$_";
-          $cust_pkg->$method($discount->$_);
-        }
-        $error = $cust_pkg->insert_discount;
-      }
-      die "error discounting using part_pkg_discount: $error" if $error;
-    }
-  }
-
-  my @cust_pkg_discount = $cust_pkg->cust_pkg_discount_active;
-  foreach my $cust_pkg_discount ( @cust_pkg_discount ) {
-    my $discount = $cust_pkg_discount->discount;
-    #UI enforces one or the other (for now?  probably for good)
-    my $amount = 0;
-    $amount += $discount->amount
-    if $cust_pkg->pkgpart == $param->{real_pkgpart};
-    $amount += sprintf('%.2f', $discount->percent * $br / 100 );
-    my $chg_months = $param->{'months'} || $cust_pkg->part_pkg->freq;
-
-    my $months = $discount->months
-    ? min( $chg_months,
-      $discount->months - $cust_pkg_discount->months_used )
-    : $chg_months;
-
-    my $error = $cust_pkg_discount->increment_months_used($months)
-    if $cust_pkg->pkgpart == $param->{real_pkgpart};
-    die "error discounting: $error" if $error;
-
-    $amount *= $months;
-    $amount = sprintf('%.2f', $amount);
-
-    next unless $amount > 0;
-
-    #record details in cust_bill_pkg_discount
-    my $cust_bill_pkg_discount = new FS::cust_bill_pkg_discount {
-      'pkgdiscountnum' => $cust_pkg_discount->pkgdiscountnum,
-      'amount'         => $amount,
-      'months'         => $months,
-    };
-    push @{ $param->{'discounts'} }, $cust_bill_pkg_discount;
-
-    #add details on discount to invoice
-    my $conf = new FS::Conf;
-    my $money_char = $conf->config('money_char') || '$';
-    $months = sprintf('%.2f', $months) if $months =~ /\./;
-
-    my $d = 'Includes ';
-    $d .= $discount->name. ' ' if $discount->name;
-    $d .= 'discount of '. $discount->description_short;
-    $d .= " for $months month". ( $months!=1 ? 's' : '' );
-    $d .= ": $money_char$amount" if $months != 1 || $discount->percent;
-    push @$details, $d;
-
-    $tot_discount += $amount;
-  }
-
-  sprintf('%.2f', $tot_discount);
-}
-
-1;
index a17813b..975e80a 100644 (file)
@@ -11,21 +11,15 @@ use List::Util qw(min); # max);
 use FS::UI::bytecount;
 use FS::Conf;
 use FS::part_pkg;
+use FS::cust_bill_pkg_discount;
 
-@ISA = qw(FS::part_pkg 
-          FS::part_pkg::prorate_Mixin
-          FS::part_pkg::discount_Mixin);
+@ISA = qw(FS::part_pkg FS::part_pkg::prorate_Mixin);
 
 tie my %temporalities, 'Tie::IxHash',
   'upcoming'  => "Upcoming (future)",
   'preceding' => "Preceding (past)",
 ;
 
-tie my %contract_years, 'Tie::IxHash', (
-  '' => '(none)',
-  map { $_*12 => $_ } (1..5),
-);
-
 %usage_fields = (
 
     'seconds'       => { 'name' => 'Time limit for this package',
@@ -123,11 +117,6 @@ tie my %contract_years, 'Tie::IxHash', (
                        },
     'adjourn_months'=> { 'name' => 'Auto-add a suspension date this number of months out',
                        },
-    'contract_end_months'=> { 
-                        'name' => 'Auto-add a contract end date this number of years out',
-                        'type' => 'select',
-                        'select_options' => \%contract_years,
-                      },
     #used in cust_pkg.pm so could add to any price plan where it made sense
     'start_1st'     => { 'name' => 'Auto-add a start date to the 1st, ignoring the current month.',
                          'type' => 'checkbox',
@@ -136,9 +125,6 @@ tie my %contract_years, 'Tie::IxHash', (
                                     'with the customer\'s other packages',
                           'type' => 'checkbox',
                         },
-    'suspend_bill' => { 'name' => 'Continue recurring billing while suspended',
-                        'type' => 'checkbox',
-                      },
     'unsuspend_adjust_bill' => 
                         { 'name' => 'Adjust next bill date forward when '.
                                     'unsuspending',
@@ -155,9 +141,8 @@ tie my %contract_years, 'Tie::IxHash', (
   'fieldorder' => [ qw( setup_fee recur_fee
                         recur_temporality unused_credit
                         expire_months adjourn_months
-                        contract_end_months
                         start_1st sync_bill_date
-                        suspend_bill unsuspend_adjust_bill
+                        unsuspend_adjust_bill
                       ),
                     @usage_fieldorder, @usage_recharge_fieldorder,
                     qw( externalid ),
@@ -195,23 +180,100 @@ sub calc_recur {
   return 0
     if $self->option('recur_temporality', 1) eq 'preceding' && $last_bill == 0;
 
-  my $charge = $self->base_recur($cust_pkg);
-  if ( $self->option('sync_bill_date',1) ) {
-    my $next_bill = $cust_pkg->cust_main->next_bill_date;
-    if ( defined($next_bill) and $next_bill != $$sdate ) {
-      my $cutoff_day = (localtime($next_bill))[3];
-      $charge = $self->calc_prorate(@_, $cutoff_day);
-    }
+  if( $self->option('sync_bill_date',1) ) {
+    return $self->calc_prorate(@_);
   }
-  elsif ( $param->{freq_override} ) {
-    # XXX not sure if this should be mutually exclusive with sync_bill_date.
-    # Given the very specific problem that freq_override is meant to 'solve',
-    # it probably should.
+  else {
+    my $charge = $self->base_recur($cust_pkg);
     $charge *= $param->{freq_override} if $param->{freq_override};
+    my $discount = $self->calc_discount($cust_pkg, $sdate, $details, $param);
+
+    return sprintf('%.2f', $charge - $discount);
+  }
+}
+
+sub calc_discount {
+  my($self, $cust_pkg, $sdate, $details, $param ) = @_;
+
+  my $br = $self->base_recur($cust_pkg);
+
+  my $tot_discount = 0;
+  #UI enforces just 1 for now, will need ordering when they can be stacked
+
+  if ( $param->{freq_override} ) {
+    my $real_part_pkg = new FS::part_pkg { $self->hash };
+    $real_part_pkg->pkgpart($param->{real_pkgpart} || $self->pkgpart);
+    my @discount = grep { $_->months == $param->{freq_override} }
+                   map { $_->discount }
+                   $real_part_pkg->part_pkg_discount;
+    my $discount = shift @discount;
+    $param->{months} = $param->{freq_override} unless $param->{months};
+    my $error;
+    if ($discount) {
+      if ($discount->months == $param->{months}) {
+        $cust_pkg->discountnum($discount->discountnum);
+        $error = $cust_pkg->insert_discount;
+      } else {
+        $cust_pkg->discountnum(-1);
+        foreach ( qw( amount percent months ) ) {
+          my $method = "discountnum_$_";
+          $cust_pkg->$method($discount->$_);
+        }
+        $error = $cust_pkg->insert_discount;
+      }
+      die "error discounting using part_pkg_discount: $error" if $error;
+    }
+  }
+
+  my @cust_pkg_discount = $cust_pkg->cust_pkg_discount_active;
+  foreach my $cust_pkg_discount ( @cust_pkg_discount ) {
+     my $discount = $cust_pkg_discount->discount;
+     #UI enforces one or the other (for now?  probably for good)
+     my $amount = 0;
+     $amount += $discount->amount
+       if $cust_pkg->pkgpart == $param->{real_pkgpart};
+     $amount += sprintf('%.2f', $discount->percent * $br / 100 );
+
+     my $chg_months = $param->{'months'} || $cust_pkg->part_pkg->freq;
+     
+     my $months = $discount->months
+                    ? min( $chg_months,
+                           $discount->months - $cust_pkg_discount->months_used )
+                    : $chg_months;
+
+     my $error = $cust_pkg_discount->increment_months_used($months)
+       if $cust_pkg->pkgpart == $param->{real_pkgpart};
+     die "error discounting: $error" if $error;
+
+     $amount *= $months;
+     $amount = sprintf('%.2f', $amount);
+
+     next unless $amount > 0;
+
+     #record details in cust_bill_pkg_discount
+     my $cust_bill_pkg_discount = new FS::cust_bill_pkg_discount {
+       'pkgdiscountnum' => $cust_pkg_discount->pkgdiscountnum,
+       'amount'         => $amount,
+       'months'         => $months,
+     };
+     push @{ $param->{'discounts'} }, $cust_bill_pkg_discount;
+
+     #add details on discount to invoice
+     my $conf = new FS::Conf;
+     my $money_char = $conf->config('money_char') || '$';  
+     $months = sprintf('%.2f', $months) if $months =~ /\./;
+
+     my $d = 'Includes ';
+     $d .= $discount->name. ' ' if $discount->name;
+     $d .= 'discount of '. $discount->description_short;
+     $d .= " for $months month". ( $months!=1 ? 's' : '' );
+     $d .= ": $money_char$amount" if $months != 1 || $discount->percent;
+     push @$details, $d;
+
+     $tot_discount += $amount;
   }
 
-  my $discount = $self->calc_discount($cust_pkg, $sdate, $details, $param);
-  return sprintf('%.2f', $charge - $discount);
+  sprintf('%.2f', $tot_discount);
 }
 
 sub base_recur {
index 4abdb8d..918b910 100644 (file)
@@ -79,15 +79,6 @@ use FS::part_pkg::flat;
                                     'package recharge',
                           'type' => 'checkbox',
                         },
-    'add_full_period'=> { 'name' => 'When prorating first month, also bill '.
-                                    'for one full period after that',
-                          'type' => 'checkbox',
-                        },
-    'prorate_round_day'=> {
-                          'name' => 'When prorating first month, round to '.
-                                    'the nearest full day',
-                          'type' => 'checkbox',
-                        },
 
     #it would be better if this had to be turned on, its confusing
     'externalid' => { 'name'   => 'Optional External ID',
@@ -98,16 +89,14 @@ use FS::part_pkg::flat;
                     'seconds', 'upbytes', 'downbytes', 'totalbytes',
                     'recharge_amount', 'recharge_seconds', 'recharge_upbytes',
                     'recharge_downbytes', 'recharge_totalbytes',
-                    'usage_rollover', 'recharge_reset', 'add_full_period',
-                    'prorate_round_day', 'externalid', ],
+                    'usage_rollover', 'recharge_reset', 'externalid', ],
   'freq' => 'm',
   'weight' => 20,
 );
 
 sub calc_recur {
   my $self = shift;
-  my $cutoff_day = $self->option('cutoff_day') || 1;
-  return $self->calc_prorate(@_, $cutoff_day) - $self->calc_discount(@_);
+  $self->calc_prorate(@_);
 }
 
 1;
index 9c0c266..2adf2f1 100644 (file)
@@ -5,9 +5,7 @@ use vars qw(@ISA %info);
 use Time::Local qw(timelocal);
 
 @ISA = qw(FS::part_pkg);
-%info = ( 
-  'disabled'  => 1,
-);
+%info = ( 'disabled' => 1 );
 
 =head1 NAME
 
@@ -30,34 +28,44 @@ sub calc_recur {
 
 =head METHODS
 
-=item calc_prorate CUST_PKG
+=item calc_prorate
 
-Takes all the arguments of calc_recur, followed by a day of the month 
-to prorate to.  Calculates a prorated charge from the $sdate to that day, 
-and sets the $sdate and $param->{months} accordingly.
+Takes all the arguments of calc_recur, and calculates a prorated charge 
+in one of two ways:
 
-Options:
-- recur_fee: The charge to use for a complete billing period.
-- add_full_period: Bill for the time up to the prorate day plus one full
-billing period after that.
-- prorate_round_day: Round the current time to the nearest full day, 
-instead of using the exact time.
+- If 'sync_bill_date' is set: Charge for a number of days to synchronize 
+  this package to the customer's next bill date.  If this is their only 
+  package (or they're already synchronized), that will take them through 
+  one billing cycle.
+- If 'cutoff_day' is set: Prorate this package so that its next bill date 
+  falls on that day of the month.
 
 =cut
 
 sub calc_prorate {
   my $self  = shift;
-  my ($cust_pkg, $sdate, $details, $param, $cutoff_day) = @_;
+  my ($cust_pkg, $sdate, $details, $param) = @_;
  
-  my $charge = $self->option('recur_fee',1) || 0;
+  my $charge = $self->option('recur_fee') || 0;
+  my $cutoff_day;
+  if( $self->option('sync_bill_date',1) ) {
+    my $next_bill = $cust_pkg->cust_main->next_bill_date;
+    if( defined($next_bill) and $next_bill != $$sdate ) {
+      $cutoff_day = (localtime($next_bill))[3];
+    }
+    else {
+      # don't prorate, assume a full month
+      $param->{'months'} = $self->freq;
+    }
+  }
+  else { # no sync, use cutoff_day or day 1
+    $cutoff_day = $self->option('cutoff_day') || 1;
+  }
+
   if($cutoff_day) {
     # only works for freq >= 1 month; probably can't be fixed
     my $mnow = $$sdate;
     my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($mnow))[0..5];
-    if( $self->option('prorate_round_day',1) ) {
-      $mday++ if $hour >= 12;
-      $mnow = timelocal(0,0,0,$mday,$mon,$year);
-    }
     my $mend;
     my $mstart;
     if ( $mday >= $cutoff_day ) {
@@ -72,23 +80,17 @@ sub calc_prorate {
       $mstart = 
         timelocal(0,0,0,$cutoff_day,$mon == 0 ? 11 : $mon - 1,$year-($mon==11));
     }
-   
-    # next bill date will be figured as $$sdate + one period
+    
     $$sdate = $mstart;
 
-    my $permonth = $charge / $self->freq;
+    my $permonth = $self->option('recur_fee', 1) / $self->freq;
     my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) );
-
-    if ( $self->option('add_full_period',1) ) {
-      # charge a full period in addition to the partial month
-      $months += $self->freq;
-      $$sdate = $self->add_freq($mstart);
-    }
-
+    
     $param->{'months'} = $months;
     $charge = sprintf('%.2f', $permonth * $months);
   }
-  return $charge;
+  my $discount =  $self->calc_discount(@_);
+  return ($charge - $discount);
 }
 
 1;
index 7614d7a..ec17c16 100644 (file)
@@ -4,9 +4,9 @@ use strict;
 use vars qw( @ISA %info %recur_method );
 use Tie::IxHash;
 use Time::Local;
-use FS::part_pkg::flat;
+use FS::part_pkg::prorate;
 
-@ISA = qw(FS::part_pkg::flat);
+@ISA = qw(FS::part_pkg::prorate);
 
 %info = ( 'disabled' => 1 ); #recur_Common not a usable price plan directly
 
@@ -16,11 +16,6 @@ tie %recur_method, 'Tie::IxHash',
   'subscription' => 'Charge the full fee for the first partial period (selectable billing date)',
 ;
 
-sub base_recur {
-  my $self = shift;
-  $self->option('recur_fee', 1) || 0;
-}
-
 sub calc_recur_Common {
   my $self = shift;
   my($cust_pkg, $sdate, $details, $param ) = @_; #only need $sdate & $param
@@ -30,37 +25,32 @@ sub calc_recur_Common {
   if ( $param->{'increment_next_bill'} ) {
 
     my $recur_method = $self->option('recur_method', 1) || 'anniversary';
-    
-    $charges = $self->base_recur;
-
-    if ( $recur_method eq 'prorate' ) {
-      my $cutoff_day = $self->option('cutoff_day') || 1;
-      $charges = $self->calc_prorate(@_, $cutoff_day);
-    }
-    elsif ( $recur_method eq 'anniversary' and 
-            $self->option('sync_bill_date',1) ) {
-      my $next_bill = $cust_pkg->cust_main->next_bill_date;
-      if ( defined($next_bill) ) {
-        my $cutoff_day = (localtime($next_bill))[3];
-        $charges = $self->calc_prorate(@_, $cutoff_day);
-      }
+                  
+    if ( $recur_method eq 'prorate' 
+        or ($recur_method eq 'anniversary' and $self->option('sync_bill_date',1))
+      ) {
+      $charges = $self->calc_prorate(@_);
     } 
-    elsif ( $recur_method eq 'subscription' ) {
+    else {
+
+      $charges = $self->option('recur_fee');
 
-      my $cutoff_day = $self->option('cutoff_day', 1) || 1;
-      my ($day, $mon, $year) = ( localtime($$sdate) )[ 3..5 ];
+      if ( $recur_method eq 'subscription' ) {
 
-      if ( $day < $cutoff_day ) {
-        if ( $mon == 0 ) { $mon=11; $year--; }
-        else { $mon--; }
-      }
+        my $cutoff_day = $self->option('cutoff_day', 1) || 1;
+        my ($day, $mon, $year) = ( localtime($$sdate) )[ 3..5 ];
 
-      $$sdate = timelocal(0, 0, 0, $cutoff_day, $mon, $year);
+        if ( $day < $cutoff_day ) {
+          if ( $mon == 0 ) { $mon=11; $year--; }
+          else { $mon--; }
+        }
 
-    }#$recur_method eq 'subscription'
+        $$sdate = timelocal(0, 0, 0, $cutoff_day, $mon, $year);
 
+      }#$recur_method eq 'subscription'
     $charges -= $self->calc_discount( $cust_pkg, $sdate, $details, $param );
 
+    }#$recur_method eq 'prorate' or ...
   }#increment_next_bill
 
   return $charges;
index 8e803f9..3cf2064 100644 (file)
@@ -24,10 +24,6 @@ use DBI;
                                    'subscription',
                          'default' => '1',
                        },
-    'add_full_period'=> { 'name' => 'When prorating first month, also bill '.
-                                    'for one full period after that',
-                          'type' => 'checkbox',
-                       },
 
     'recur_method'  => { 'name' => 'Recurring fee method',
                          #'type' => 'radio',
@@ -49,7 +45,7 @@ use DBI;
                },
   },
   'fieldorder' => [qw( setup_fee recur_fee unused_credit recur_method cutoff_day
-                      add_full_period datasrc db_username db_password query 
+                       datasrc db_username db_password query 
                   )],
   'weight' => '58',
 );
index 5495e3a..a5e0262 100644 (file)
@@ -18,7 +18,7 @@ use FS::part_pkg::flat;
     'recur_fee' => { 'name' => 'Recurring fee for this package',
                      'default' => 0,
                           },
-    'cutoff_day' => { 'name' => 'Billing day',
+    'cutoff_day' => { 'name' => 'billing day',
                       'default' => 1,
                     },
     'seconds'       => { 'name' => 'Time limit for this package',
index 768f894..005009a 100644 (file)
@@ -22,7 +22,6 @@ $DEBUG = 0;
 tie my %cdr_svc_method, 'Tie::IxHash',
   'svc_phone.phonenum' => 'Phone numbers (svc_phone.phonenum)',
   'svc_pbx.title'      => 'PBX name (svc_pbx.title)',
-  'svc_pbx.svcnum'     => 'Freeside service # (svc_pbx.svcnum)',
 ;
 
 tie my %rating_method, 'Tie::IxHash',
@@ -71,10 +70,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
                                    'subscription',
                          'default' => '1',
                        },
-    'add_full_period'=> { 'name' => 'When prorating first month, also bill '.
-                                    'for one full period after that',
-                          'type' => 'checkbox',
-                        },
+
     'recur_method'  => { 'name' => 'Recurring fee method',
                          #'type' => 'radio',
                          #'options' => \%recur_method,
@@ -222,14 +218,10 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
                        },
     #eofalse
 
-    'bill_every_call' => { 'name' => 'Generate an invoice immediately for every call (as well any setup fee, upon first payment).  Useful for prepaid.',
+    'bill_every_call' => { 'name' => 'Generate an invoice immediately for every call.  Useful for prepaid.',
                            'type' => 'checkbox',
                          },
 
-    'bill_inactive_svcs' => { 'name' => 'Bill for all phone numbers that were active during the billing period',
-                              'type' => 'checkbox',
-                            },
-
     'count_available_phones' => { 'name' => 'Consider for tax purposes the number of lines to be svc_phones that may be provisioned rather than those that actually are.',
                            'type' => 'checkbox',
                          },
@@ -261,7 +253,6 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
   'fieldorder' => [qw(
                        setup_fee recur_fee recur_temporality unused_credit
                        recur_method cutoff_day
-                       add_full_period
                        cdr_svc_method
                        rating_method ratenum min_charge sec_granularity
                        ignore_unrateable
@@ -282,7 +273,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
                        use_duration
                        411_rewrite
                        output_format usage_mandate summarize_usage usage_section
-                       bill_every_call bill_inactive_svcs
+                       bill_every_call
                        count_available_phones
                      )
                   ],
@@ -369,35 +360,18 @@ sub calc_usage {
 
   my($svc_table, $svc_field) = split('\.', $cdr_svc_method);
 
-  my @cust_svc;
-  if( $self->option('bill_inactive_svcs',1) ) {
-    #XXX in this mode do we need to restrict the set of CDRs by date also?
-    @cust_svc = $cust_pkg->h_cust_svc($$sdate, $last_bill);
-  }
-  else {
-    @cust_svc = $cust_pkg->cust_svc;
-  }
-  @cust_svc = grep { $_->part_svc->svcdb eq $svc_table } @cust_svc;
-
-  foreach my $cust_svc (@cust_svc) {
+  foreach my $cust_svc (
+    grep { $_->part_svc->svcdb eq $svc_table } $cust_pkg->cust_svc
+  ) {
 
-    my $svc_x;
-    if( $self->option('bill_inactive_svcs',1) ) {
-      $svc_x = $cust_svc->h_svc_x($$sdate, $last_bill);
-    }
-    else {
-      $svc_x = $cust_svc->svc_x;
-    }
-    my %options = (
+    my $svc_x = $cust_svc->svc_x;
+    foreach my $cdr (
+      $svc_x->get_cdrs(
         'disable_src'    => $self->option('disable_src'),
         'default_prefix' => $self->option('default_prefix'),
         'status'         => '',
         'for_update'     => 1,
-      );  # $last_bill, $$sdate )
-    $options{'by_svcnum'} = 1 if $svc_field eq 'svcnum';
-
-    foreach my $cdr (
-      $svc_x->get_cdrs( %options )
+      )  # $last_bill, $$sdate )
     ) {
       if ( $DEBUG > 1 ) {
         warn "rating CDR $cdr\n".
@@ -727,7 +701,7 @@ sub calc_usage {
         if ( $charge > 0 ) {
           #just use FS::cust_bill_pkg_detail objects?
           my $call_details;
-          my $phonenum = $svc_x->phonenum;
+          my $phonenum = $cust_svc->svc_x->phonenum;
 
           if ( scalar(@call_details) == 1 ) {
             $call_details =
index 8b1844a..4937bb8 100644 (file)
@@ -47,10 +47,6 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
                                    'subscription',
                          'default' => '1',
                        },
-    'add_full_period'=> { 'name' => 'When prorating first month, also bill '.
-                                    'for one full period after that',
-                          'type' => 'checkbox',
-                        },
 
     'recur_method'  => { 'name' => 'Recurring fee method',
                          'type' => 'select',
@@ -156,7 +152,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
   },
   'fieldorder' => [qw(
                        setup_fee recur_fee recur_temporality unused_credit
-                       recur_method cutoff_day add_full_period
+                       recur_method cutoff_day
                        min_charge sec_granularity
                        default_prefix
                        disable_tollfree
index 142622b..3cb330b 100644 (file)
@@ -137,10 +137,6 @@ sub _upgrade_data {  # class method
   $sth = dbh->prepare($sql) or die dbh->errstr;
   $sth->execute or die $sth->errstr;
 
-  $sql = "UPDATE part_pkg_option SET optionvalue = NULL WHERE ".
-            "optionname = 'contract_end_months' AND optionvalue = '(none)'";
-  $sth = dbh->prepare($sql) or die dbh->errstr;
-  $sth->execute or die $sth->errstr;
   '';
 
 }
index e0f1e33..71290f4 100644 (file)
@@ -1013,42 +1013,6 @@ sub clone_kludge_unsuspend {
   shift;
 }
 
-=item find_duplicates MODE FIELDS...
-
-Method used by _check_duplicate routines to find services with duplicate 
-values in specified fields.  Set MODE to 'global' to search across all 
-services, or 'export' to limit to those that share one or more exports 
-with this service.  FIELDS is a list of field names; only services 
-matching in all fields will be returned.  Empty fields will be skipped.
-
-=cut
-
-sub find_duplicates {
-  my $self = shift;
-  my $mode = shift;
-  my @fields = @_;
-
-  my %search = map { $_ => $self->getfield($_) } 
-               grep { length($self->getfield($_)) } @fields;
-  return () if !%search;
-  my @dup = grep { ! $self->svcnum or $_->svcnum != $self->svcnum }
-            qsearch( $self->table, \%search );
-  return () if !@dup;
-  return @dup if $mode eq 'global';
-  die "incorrect find_duplicates mode '$mode'" if $mode ne 'export';
-
-  my $exports = FS::part_export::export_info($self->table);
-  my %conflict_svcparts;
-  my $part_svc = $self->part_svc;
-  foreach my $part_export ( $part_svc->part_export ) {
-    %conflict_svcparts = map { $_->svcpart => 1 } $part_export->export_svc;
-  }
-  return grep { $conflict_svcparts{$_->cust_svc->svcpart} } @dup;
-}
-
-
-
-
 =back
 
 =head1 BUGS
index 94a839b..d401e1d 100644 (file)
@@ -9,7 +9,6 @@ use vars qw( $DEBUG $me $conf $skip_fuzzyfiles
              $username_ampersand $username_letter $username_letterfirst
              $username_noperiod $username_nounderscore $username_nodash
              $username_uppercase $username_percent $username_colon
-             $username_slash $username_equals
              $password_noampersand $password_noexclamation
              $warning_template $warning_from $warning_subject $warning_mimetype
              $warning_cc
@@ -75,8 +74,6 @@ FS::UID->install_callback( sub {
   $username_ampersand = $conf->exists('username-ampersand');
   $username_percent = $conf->exists('username-percent');
   $username_colon = $conf->exists('username-colon');
-  $username_slash = $conf->exists('username-slash');
-  $username_equals = $conf->exists('username-equals');
   $password_noampersand = $conf->exists('password-noexclamation');
   $password_noexclamation = $conf->exists('password-noexclamation');
   $dirhash = $conf->config('dirhash') || 0;
@@ -1243,14 +1240,16 @@ sub check {
   }
 
   my $ulen = $usernamemax || $self->dbdef_table->column('username')->length;
-
-  $recref->{username} =~ /^([a-z0-9_\-\.\&\%\:\/\=]{$usernamemin,$ulen})$/i
-    or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
-  $recref->{username} = $1;
-
-  unless ( $username_uppercase ) {
-    $recref->{username} =~ /[A-Z]/ and return gettext('illegal_username');
+  if ( $username_uppercase ) {
+    $recref->{username} =~ /^([a-z0-9_\-\.\&\%\:]{$usernamemin,$ulen})$/i
+      or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
+    $recref->{username} = $1;
+  } else {
+    $recref->{username} =~ /^([a-z0-9_\-\.\&\%\:]{$usernamemin,$ulen})$/
+      or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
+    $recref->{username} = $1;
   }
+
   if ( $username_letterfirst ) {
     $recref->{username} =~ /^[a-z]/ or return gettext('illegal_username');
   } elsif ( $username_letter ) {
@@ -1274,12 +1273,6 @@ sub check {
   unless ( $username_colon ) {
     $recref->{username} =~ /\:/ and return gettext('illegal_username');
   }
-  unless ( $username_slash ) {
-    $recref->{username} =~ /\// and return gettext('illegal_username');
-  }
-  unless ( $username_equals ) {
-    $recref->{username} =~ /\=/ and return gettext('illegal_username');
-  }
 
   $recref->{popnum} =~ /^(\d*)$/ or return "Illegal popnum: ".$recref->{popnum};
   $recref->{popnum} = $1;
@@ -1359,7 +1352,7 @@ sub check {
     }
   }
   $self->getfield('finger') =~
-    /^([µ_0123456789aAáÁàÀâÂåÅäÄãêæÆbBcCçÇdDðÐeEéÉèÈêÊëËfFgGhHiIíÍìÌîÎïÏjJkKlLmMnNñÑoOóÓòÒôÔöÖõÕøغpPqQrRsSßtTuUúÚùÙûÛüÜvVwWxXyYýÝÿzZþÞ \t\!\@\#\$\%\&\(\)\-\+\;\'\"\,\.\?\/\*\<\>]*)$/
+    /^([\w \t\!\@\#\$\%\&\(\)\-\+\;\'\"\,\.\?\/\*\<\>]*)$/
       or return "Illegal finger: ". $self->getfield('finger');
   $self->setfield('finger', $1);
 
index 0eb5443..d2760a5 100644 (file)
@@ -253,27 +253,22 @@ sub check {
   $self->SUPER::check;
 }
 
+#XXX this is a way-too simplistic implementation
+# at the very least, title should be unique across exports that need that or
+# controlled by a conf setting or something
 sub _check_duplicate {
   my $self = shift;
 
   my $conf = new FS::Conf;
-  
+  return '' if $conf->config('global_unique-pbx_title') eq 'disabled';
+
   $self->lock_table;
 
-  foreach my $field ('title', 'id') {
-    my $global_unique = $conf->config("global_unique-pbx_$field");
-    # can be 'disabled', 'enabled', or empty.
-    # if empty, check per exports; if not empty or disabled, check 
-    # globally.
-    next if $global_unique eq 'disabled';
-    my @dup = $self->find_duplicates(
-      ($global_unique ? 'global' : 'export') , $field
-    );
-    next if !@dup;
-    return "duplicate $field '".$self->getfield($field).
-           "': conflicts with svcnum ".$dup[0]->svcnum;
+  if ( qsearchs( 'svc_pbx', { 'title' => $self->title } ) ) {
+    return "Name in use";
+  } else {
+    return '';
   }
-  return '';
 }
 
 =item get_cdrs
@@ -297,9 +292,6 @@ with the chosen prefix.
 
 =item disable_src => 1: No-op for svc_pbx CDR processing.
 
-=item by_svcnum => 1: Select CDRs where the svcnum field matches, instead of 
-title/charged_party.  Normally this field is set after processing.
-
 =back
 
 =cut
@@ -315,25 +307,19 @@ sub get_cdrs {
   
   my $for_update = $options{'for_update'} ? 'FOR UPDATE' : '';
 
-  if ( $options{'by_svcnum'} ) {
-    $hash{'svcnum'} = $self->svcnum;
-  }
-  else {
-    #matching by title
-    my $title = $self->title;
+  my $title = $self->title;
 
-    my $prefix = $options{'default_prefix'};
+  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 ). ' ) ';
+  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'};
   }
@@ -341,8 +327,7 @@ sub get_cdrs {
     push @where, 'startdate < '.  $options{'end'};
   }
 
-  my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where )
-    if @where;
+  my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where );
 
   my @cdrs =
     qsearch( {
index a599ea2..a0a2c3e 100644 (file)
@@ -547,8 +547,6 @@ with the chosen prefix.
 
 =item disable_src => 1: Only match on "charged_party", not "src".
 
-=item by_svcnum: not supported for svc_phone
-
 =back
 
 =cut
index 6a542c7..e16cc5c 100755 (executable)
@@ -99,7 +99,7 @@ the bill and collect methods of a cust_main object.  See L<FS::cust_main>.
       with today's date, irregardless of the pretend date used to pre-generate
       the invoices.
 
-  -p: Only process customers with the specified payby (CARD, DCRD, CHEK, DCHK, BILL, COMP, LECB)
+  -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
 
   -a: Only process customers with the specified agentnum.  Multiple agentnums can be specified, separated with commas.
 
index 0d6ea14..a81e3e9 100755 (executable)
@@ -64,7 +64,7 @@ the bill and collect methods of a cust_main object.  See L<FS::cust_main>.
       "pretend date" 15 days from whatever was specified by the -d switch
       (or now, if no -d switch was given).
 
-  -p: Only process customers with the specified payby (CARD, DCRD, CHEK, DCHK, BILL, COMP, LECB)
+  -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
 
   -a: Only process customers with the specified agentnum
 
index 3326329..ed85626 100644 (file)
@@ -52,13 +52,13 @@ freeside-radgroup - Command line utility to manipulate radius groups
 
 =head1 DESCRIPTION
 
-B<user> is a freeside user as added with freeside-adduser.
+  B<user> is a freeside user as added with freeside-adduser.
 
-B<command> is the action to take.  Available actions are: I<add>
+  B<command> is the action to take.  Available actions are: I<add>
 
-B<groupname> is the group to add (or remove, etc.)
+  B<groupname> is the group to add (or remove, etc.)
 
-B<svcpart> specifies which accounts will be updated.
+  B<svcpart> specifies which accounts will be updated.
 
 =head1 EXAMPLES
 
index aca545b..d3723a1 100755 (executable)
@@ -71,21 +71,6 @@ if ( dbdef->table('cgp_rule_condition') &&
 
 }
 
-# RT required field flag
-# for consistency with RT schema: mysql is in CamelCase,
-# pg is in lowercase, and they use different data types.
-my ($t, $creq, $cdis) = 
-  map { driver_name =~ /^mysql/i ? $_ : lc($_) }
-  ('CustomFields','Required','Disabled');
-
-if ( dbdef->table($t) && 
-     ! dbdef->table($t)->column($creq) ) {
-  push @bugfix,
-    "ALTER TABLE $t ADD COLUMN $creq ".
-    dbdef->table($t)->column($cdis)->type .
-    ' NOT NULL DEFAULT 0';
-}
-
 if ( $DRY_RUN ) {
   print
     join(";\n", @bugfix ). ";\n";
index b0d43ea..bece052 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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.2cvs
-TAG=freeside_2_1_2
+VERSION=2.1.1
+TAG=freeside_2_1_1
 
 DEBVERSION = `echo ${VERSION} | perl -pe 's/(\d)([a-z])/\1~\2/'`-1
 
diff --git a/bin/cust_main-find_bogus_geocode b/bin/cust_main-find_bogus_geocode
deleted file mode 100755 (executable)
index 04a38a9..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use FS::UID qw(adminsuidsetup);
-use FS::Record qw( qsearch );
-use FS::cust_main;
-
-my $user = shift or die "usage: cust_main-find_bogus_geocode username\n";
-adminsuidsetup $user;
-
-my @cust_main = qsearch({
-  'table' => 'cust_main',
-  'extra_sql' => 'WHERE geocode IS NOT NULL',
-});
-
-foreach my $cust_main ( @cust_main ) {
-
-  my $db_geocode = $cust_main->geocode;
-
-  $cust_main->set('geocode', '');
-
-  my $calc_geocode = $cust_main->geocode('cch');
-
-  next unless $calc_geocode;
-
-  my $cust = $cust_main->custnum.': '. $cust_main->name. "\n";
-
-  if ( $db_geocode eq $calc_geocode ) {
-    warn "unnecessary geocode override for $cust";
-  } else {
-    warn "bogus geocode override $db_geocode overrides $calc_geocode for $cust";
-  }
-
-}
-
-1;
diff --git a/bin/freeside-backup b/bin/freeside-backup
deleted file mode 100644 (file)
index 97a4899..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use Getopt::Std;
-use FS::UID qw(adminsuidsetup);
-use FS::Conf;
-
-my $user = shift or die &usage;
-adminsuidsetup $user;
-
-#you can skip this just by not having the config
-use FS::Cron::backup qw(backup_scp);
-backup_scp();
-
-sub usage {
-  die "Usage:\n\n  freeside-backup user\n";
-}
-
-###
-# documentation
-###
-
-=head1 NAME
-
-freeside-backup - Runs a backup
-
-=head1 SYNOPSIS
-
-  freeside-backup user
-
-=head1 DESCRIPTION
-
-Runs a backup.  See the dump-scpdest configuration option.
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-=cut
-
-1;
-
diff --git a/bin/merge-referrals b/bin/merge-referrals
deleted file mode 100644 (file)
index ba07a81..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use FS::UID qw(adminsuidsetup);
-use FS::Record qw(qsearchs);
-use FS::cust_main;
-
-my $user = shift or die "usage: merge-customers username custnum\n";
-adminsuidsetup $user;
-
-my $custnum = shift or die "usage: merge-customers username custnum\n";
-
-foreach my $cust_main (
-  qsearch('cust_main', { 'referral_custnum' => $custnum })
-) {
-  my $error = $cust_main->merge($custnum);
-  die $error if $error;
-}
-
-1;
diff --git a/bin/rt-trim-whitespace b/bin/rt-trim-whitespace
deleted file mode 100755 (executable)
index 503d9cf..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-use FS::Record;
-use FS::UID qw(adminsuidsetup dbh driver_name);
-
-# Remove trailing whitespace from custom field option lists and values.
-
-my $dbh = adminsuidsetup(shift) or die "Usage: rt-trim-whitespace username\n";
-die "rt-trim-whitespace only works on Pg databases" if driver_name ne 'Pg';
-
-my @updates = (
-  customfieldvalues       => 'name',
-  objectcustomfieldvalues => 'content',
-);
-
-while(@updates) {
-  my $table = shift @updates;
-  my $field = shift @updates;
-  my $select = 
-"SELECT $field FROM $table WHERE $field != substring($field from ".
-  q!E'^(.*\\\\S)\\\\s*$'! . ')';
-  
-  print "$select\n";
-  my $rows = $dbh->do($select);
-  print "$rows rows found.\n";
-  
-  if($rows) {
-    my $update =
-"UPDATE $table SET $field = substring($field from ".q!E'^(.*\\\\S)\\\\s*$'!.')'.
-" WHERE $field != substring($field from ".q!E'^(.*\\\\S)\\\\s*$'!.')';
-    print "$update\n";
-    my $rows = $dbh->do($update);
-    print "$rows updated.\n";
-  }
-}
-$dbh->commit or die $dbh->errstr;
index 98d4f70..302306a 100644 (file)
@@ -86,7 +86,7 @@
     \returninset\r
     \makebox{\r
       \begin{tabular}{ll}\r
-        \includegraphics{[@-- $logo_file --@]} &\r
+        \includegraphics{[@-- $conf_dir --@]/logo.eps} &\r
         \begin{minipage}[b]{5.5cm}\r
 [@-- $returnaddress --@]\r
         \end{minipage}\r
index b423305..4e55c65 100644 (file)
@@ -64,40 +64,38 @@ list of freeside CDR fields, useful ones marked with *
        lastapp - Last application if appropriate
        lastdata - Last application data
 *      startdate - Start of call (UNIX-style integer timestamp)
-*      answerdate - Answer time of call (UNIX-style integer timestamp)
+       answerdate - Answer time of call (UNIX-style integer timestamp)
 *      enddate - End time of call (UNIX-style integer timestamp)
-*[2]   duration - Total time in system, in seconds
-*[3]   billsec - Total time call is up, in seconds
-*[4]   disposition - What happened to the call: ANSWERED, NO ANSWER, BUSY
+*      duration - Total time in system, in seconds
+*      billsec - Total time call is up, in seconds
+*[2]   disposition - What happened to the call: ANSWERED, NO ANSWER, BUSY
        amaflags - What flags to use: BILL, IGNORE etc, specified on a per
        channel basis like accountcode.
-*[5]   accountcode - CDR account number to use: account
+*[3]   accountcode - CDR account number to use: account
        uniqueid - Unique channel identifier
        userfield - CDR user-defined field
        cdr_type - CDR type - see FS::cdr_type (Usage = 1, S&E = 7, OC&C = 8)
-*[6]   charged_party - Service number to be billed
+*[4]   charged_party - Service number to be billed
        upstream_currency - Wholesale currency from upstream
-*[7]   upstream_price - Wholesale price from upstream
+*[5]   upstream_price - Wholesale price from upstream
        upstream_rateplanid - Upstream rate plan ID
        rated_price - Rated (or re-rated) price
        distance - km (need units field?)
        islocal - Local - 1, Non Local = 0
-*[8]   calltypenum - Type of call - see FS::cdr_calltype
+*[6]   calltypenum - Type of call - see FS::cdr_calltype
        description - Description (cdr_type 7&8 only) (used for
        cust_bill_pkg.itemdesc)
        quantity - Number of items (cdr_type 7&8 only)
-*[9]   carrierid - Upstream Carrier ID (see FS::cdr_carrier)
+*[7]   carrierid - Upstream Carrier ID (see FS::cdr_carrier)
        upstream_rateid - Upstream Rate ID
        svcnum - Link to customer service (see FS::cust_svc)
        freesidestatus - NULL, done (or something)
 
 [1] Auto-populated from startdate if not present
-[2] Auto-populated to enddate - startdate on insert if not specified
-[3] Auto-populated to enddate - answerdate on insert if not specified
-[4] Package options available to ignore calls without a specific disposition
-[5] When using 'cdr-charged_party-accountcode' config
-[6] Auto-populated from src (normal calls) or dst (toll free calls) if not present
-[7] When using 'upstream_simple' rating method.
-[8] Set to usage class classnum when using pre-rated CDRs and usage class-based
+[2] Package options available to ignore calls without a specific disposition
+[3] When using 'cdr-charged_party-accountcode' config
+[4] Auto-populated from src (normal calls) or dst (toll free calls) if not present
+[5] When using 'upstream_simple' rating method.
+[6] Set to usage class classnum when using pre-rated CDRs and usage class-based
     taxation (local/intrastate/interstate/international)
-[9] If doing settlement charging
+[7] If doing settlement charging
index f68f06b..3d7c245 100644 (file)
@@ -150,7 +150,7 @@ my $html_init =
 
 foreach my $part_event ( qsearch('part_event', {'diabled'=>''}) ) {
   $html_init .=  '<OPTION VALUE="'. $part_event->eventpart. '">'.
-                  $part_event->eventpart. ': '. $part_event->event. '</OPTION>';
+                 $part_event->event. '</OPTION>';
 }
 
 $html_init .= '</SELECT><INPUT TYPE="submit" VALUE="Clone existing event">'.
index 26e0170..3c3016b 100755 (executable)
@@ -32,7 +32,6 @@ my $acl_edit        = $curuser->access_right($edit);
 my $acl_edit_global = $curuser->access_right($edit_global);
 my $acl_config      = $curuser->access_right('Configuration'); #to edit services
                                                                #and agent types
-                                                               #and bulk change
 
 die "access denied"
   unless $acl_edit || $acl_edit_global;
@@ -97,13 +96,6 @@ $select = "
   *,
 
   ( $count_cust_pkg
-      AND ( setup IS NULL OR setup = 0 )
-      AND ( cancel IS NULL OR cancel = 0 )
-      AND ( susp IS NULL OR susp = 0 )
-  ) AS num_not_yet_billed,
-
-  ( $count_cust_pkg
-      AND setup IS NOT NULL AND setup != 0
       AND ( cancel IS NULL OR cancel = 0 )
       AND ( susp IS NULL OR susp = 0 )
   ) AS num_active,
@@ -317,7 +309,6 @@ if ( $acl_edit_global ) {
 #if ( $cgi->param('active') ) {
   push @header, 'Customer<BR>packages';
   my %col = (
-    'not yet billed'  => '009999', #teal? cyan?
     'active'          => '00CC00',
     'suspended'       => 'FF9900',
     'cancelled'       => 'FF0000',
@@ -326,8 +317,8 @@ if ( $acl_edit_global ) {
   );
   my $cust_pkg_link = $p. 'search/cust_pkg.cgi?pkgpart=';
   push @fields, sub { my $part_pkg = shift;
-                        [
-                        map( {
+                      [
+                        map {
                               my $magic = $_;
                               my $label = $_;
                               if ( $magic eq 'active' && $part_pkg->freq == 0 ) {
@@ -335,7 +326,6 @@ if ( $acl_edit_global ) {
                                 #$label = 'one-time charge',
                                 $label = 'charge',
                               }
-                              $label= 'not yet billed' if $magic eq 'not_yet_billed';
                           
                               [
                                 {
@@ -360,24 +350,8 @@ if ( $acl_edit_global ) {
                                             ),
                                 },
                               ],
-                            } (qw( not_yet_billed active suspended cancelled ))
-                          ),
-                      ($acl_config ? 
-                        [ {}, 
-                          { 'data'  => '<FONT SIZE="-1">[ '.
-                              include('/elements/popup_link.html',
-                                'label'       => 'change',
-                                'action'      => "${p}edit/bulk-cust_pkg.html?".
-                                                 'pkgpart='.$part_pkg->pkgpart,
-                                'actionlabel' => 'Change Packages',
-                                'width'       => 569,
-                                'height'      => 210,
-                              ).' ]</FONT>',
-                            'align' => 'left',
-                          } 
-                        ] : () ),
-                      ]; 
-  };
+                            } (qw( active suspended cancelled ))
+                      ]; };
   $align .= 'r';
 #}
 
index ba217eb..77e5da1 100755 (executable)
   <& .row_edit, cust_pkg=>$cust_pkg, column=>'setup',     label=>'Setup' &>
   <& .row_edit, cust_pkg=>$cust_pkg, column=>'last_bill', label=>$last_bill_or_renewed &>
   <& .row_edit, cust_pkg=>$cust_pkg, column=>'bill',      label=>$next_bill_or_prepaid_until &>
-%#if ( $cust_pkg->contract_end or $part_pkg->option('contract_end_months',1) ) {
-    <& .row_edit, cust_pkg=>$cust_pkg, column=>'contract_end',label=>'Contract end' &>
-%#}
-  <& .row_display, cust_pkg=>$cust_pkg, column=>'adjourn',  label=>'Adjournment', note=>'(will <b>suspend</b> this package when the date is reached)' &>
-  <& .row_display, cust_pkg=>$cust_pkg, column=>'susp',     label=>'Suspension' &>
+  <& .row_display, cust_pkg=>$cust_pkg, column=>'adjourn',   label=>'Adjournment', note=>'(will <b>suspend</b> this package when the date is reached)' &>
+  <& .row_display, cust_pkg=>$cust_pkg, column=>'susp',   label=>'Suspension' &>
 
   <& .row_display, cust_pkg=>$cust_pkg, column=>'expire',   label=>'Expiration', note=>'(will <b>cancel</b> this package when the date is reached)' &>
   <& .row_display, cust_pkg=>$cust_pkg, column=>'cancel',   label=>'Cancellation' &>
 
-
 <%def .row_edit>
 <%args>
   $cust_pkg
index 86ce253..22cf896 100644 (file)
@@ -20,8 +20,9 @@
                                'user_custnum' => 'Customer (optional)',
                                'disabled'     => 'Disable employee',
                              },
-                 'edit_callback' => \&edit_callback,
-                 'field_callback'=> \&field_callback,
+                 'edit_callback' => sub { my( $c, $o ) = @_; 
+                                          $o->set('_password', '');
+                                        },
                  'viewall_dir' => 'browse',
                  'html_bottom' =>
                    sub {
@@ -61,17 +62,4 @@ my $check_user_custnum_search = <<END;
   </SCRIPT>
 END
 
-sub edit_callback {
-  my ($c, $o, $f, $opt) = @_;
-  $o->set('_password', '');
-}
-
-sub field_callback {
-  my ($c, $o, $f) = @_;
-  if($f->{'type'} eq 'password' and $o->is_system_user) {
-    $f->{'type'} = 'hidden';
-    $f->{'disabled'} = 1;
-  }
-}
-
 </%init>
diff --git a/httemplate/edit/bulk-cust_pkg.html b/httemplate/edit/bulk-cust_pkg.html
deleted file mode 100644 (file)
index 2ff38ca..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<% include('/elements/header-popup.html', 'Bulk package change') %>
-
-<% include('/elements/init_overlib.html') %>
-
-<% include('/elements/progress-init.html',
-              'OneTrueForm',
-              [qw( old_pkgpart new_pkgpart )],
-              'process/bulk-cust_pkg.cgi',
-              $p.'browse/part_pkg.cgi',
-           )
-%>
-
-<SCRIPT TYPE="text/javascript">
-function areyousure() {
-  var warning = 'Change these packages?';
-  if(confirm(warning)) {
-    process();
-  }
-}
-</SCRIPT>
-<FORM NAME="OneTrueForm">
-% #false laziness with bulk-cust_svc.html
-%  $cgi->param('pkgpart') =~ /^(\d+)$/
-%    or die "illegal pkgpart: ". $cgi->param('pkgpart');
-%
-%  my $old_pkgpart = $1;
-%  my $src_part_pkg = qsearchs('part_pkg', { 'pkgpart' => $old_pkgpart } )
-%    or die "unknown pkgpart: $old_pkgpart";
-%
-
-
-<INPUT NAME="old_pkgpart" TYPE="hidden" VALUE="<% $old_pkgpart %>">
-Change <B><% $src_part_pkg->pkg_comment %></B><BR>
-
-to new package definition
-<SELECT NAME="new_pkgpart">
-% foreach my $dest_part_pkg ( qsearch('part_pkg', { 'disabled' => '' } ) ) {
-
-  <OPTION VALUE="<% $dest_part_pkg->pkgpart %>"><% $dest_part_pkg->pkgpart %>: <% $dest_part_pkg->pkg %>
-% } 
-
-</SELECT>
-<BR>
-<BR>
-%#<INPUT TYPE="checkbox" NAME="keep_dates" CHECKED> Preserve all billing dates <I>(strongly recommended)</I>
-%#<BR>
-%#<BR>
-
-<INPUT TYPE="button" VALUE="Bulk change packages" onclick="areyousure()">
-
-</FORM>
-
-<% include('/elements/footer.html') %>
-
-<%init>
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-
-</%init>
index 07629dc..57dc359 100755 (executable)
@@ -179,8 +179,6 @@ function samechanged(what) {
 
     <% include('cust_main/first_pkg.html', $cust_main,
                  'pkgpart_svcpart' => $pkgpart_svcpart,
-                 'disable_empty'   =>
-                   scalar( $cgi->param('lock_pkgpart') =~ /^(\d+)$/ ),
                  #svc_acct
                  'username'        => $username,
                  'password'        => $password,
@@ -309,18 +307,11 @@ if ( $cgi->param('error') ) {
   $stateid = '';
   $payinfo = '';
 
-  if ( $cgi->param('lock_pkgpart') =~ /^(\d+)$/ ) {
-    my $pkgpart = $1;
-    my $part_pkg = qsearchs('part_pkg', { 'pkgpart' => $pkgpart } )
-      or die "unknown pkgpart $pkgpart";
-    my $svcpart = $part_pkg->svcpart;
-    $pkgpart_svcpart = $pkgpart.'_'.$svcpart;
-  }
-
 }
 
-my %keep = map { $_=>1 } qw( error tagnum lock_agentnum lock_pkgpart );
-$cgi->delete( grep !$keep{$_}, $cgi->param );
+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;
index d121982..aeb67b6 100644 (file)
 %        qq!<INPUT TYPE="hidden" NAME="BILL_exp_year" VALUE="2037">!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">Attention </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payname" VALUE="!. encode_entities( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payname" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
index 942fc0e..5d06f3c 100644 (file)
@@ -20,14 +20,223 @@ function bottomfixup(what) {
   }
 
   //this part does USPS address correction
-  standardize_locations();
+
+  // XXX should this be first and should we update the form fields that are
+  // displayed???
+
+  var cf = document.CustomerForm;
+
+  var state_el      = cf.elements['state'];
+  var ship_state_el = cf.elements['ship_state'];
+
+  //address_standardize(
+  var cust_main = new Array(
+    'company',  cf.elements['company'].value,
+    'address1', cf.elements['address1'].value,
+    'address2', cf.elements['address2'].value,
+    'city',     cf.elements['city'].value,
+    'state',    state_el.options[ state_el.selectedIndex ].value,
+    'zip',      cf.elements['zip'].value,
+
+    'ship_company',  cf.elements['ship_company'].value,
+    'ship_address1', cf.elements['ship_address1'].value,
+    'ship_address2', cf.elements['ship_address2'].value,
+    'ship_city',     cf.elements['ship_city'].value,
+    'ship_state',    ship_state_el.options[ ship_state_el.selectedIndex ].value,
+    'ship_zip',      cf.elements['ship_zip'].value
+  );
+
+  address_standardize( cust_main, update_address );
 
 }
 
-<% include( '/elements/standardize_locations.js',
-            'callback', 'post_geocode();'
-          )
-%>
+var standardize_address;
+
+function update_address(arg) {
+
+  var argsHash = eval('(' + arg + ')');
+
+  var changed  = argsHash['address_standardized'];
+  var ship_changed = argsHash['ship_address_standardized'];
+  var error = argsHash['error'];
+  var ship_error = argsHash['ship_error'];
+  
+
+  //yay closures
+  standardize_address = function () {
+
+    var cf = document.CustomerForm;
+    var state_el      = cf.elements['state'];
+    var ship_state_el = cf.elements['ship_state'];
+
+    if ( changed ) {
+      cf.elements['company'].value  = argsHash['new_company'];
+      cf.elements['address1'].value = argsHash['new_address1'];
+      cf.elements['address2'].value = argsHash['new_address2'];
+      cf.elements['city'].value     = argsHash['new_city'];
+      setselect(cf.elements['state'], argsHash['new_state']);
+      cf.elements['zip'].value      = argsHash['new_zip'];
+    }
+
+    if ( ship_changed ) {
+      cf.elements['ship_company'].value  = argsHash['new_ship_company'];
+      cf.elements['ship_address1'].value = argsHash['new_ship_address1'];
+      cf.elements['ship_address2'].value = argsHash['new_ship_address2'];
+      cf.elements['ship_city'].value     = argsHash['new_ship_city'];
+      setselect(cf.elements['ship_state'], argsHash['new_ship_state']);
+      cf.elements['ship_zip'].value      = argsHash['new_ship_zip'];
+    }
+
+    post_standardization();
+
+  }
+
+
+
+  if ( changed || ship_changed ) {
+
+%   if ( $conf->exists('cust_main-auto_standardize_address') ) {
+
+    standardize_address();
+
+%   } else {
+
+    // popup a confirmation popup
+
+    var confirm_change =
+      '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
+      '<TABLE>';
+    
+    if ( changed ) {
+
+      confirm_change = confirm_change + 
+        '<TR><TH>Entered billing address</TH>' +
+          '<TH>Standardized billing address</TH></TR>';
+        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+      
+      if ( argsHash['company'] || argsHash['new_company'] ) {
+        confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['company'] +
+          '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
+      }
+      
+      confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['address1'] +
+          '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['address2'] +
+          '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + '  ' + argsHash['zip'] +
+          '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + '  ' + argsHash['new_zip'] + '</TD></TR>' +
+          '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+    }
+
+    if ( ship_changed ) {
+
+      confirm_change = confirm_change + 
+        '<TR><TH>Entered service address</TH>' +
+          '<TH>Standardized service address</TH></TR>';
+        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+      
+      if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
+        confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['ship_company'] +
+          '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
+      }
+      
+      confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['ship_address1'] +
+          '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['ship_address2'] +
+          '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + '  ' + argsHash['ship_zip'] +
+          '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + '  ' + argsHash['new_ship_zip'] + '</TD></TR>' +
+        '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+    }
+
+    var addresses = 'address';
+    var height = 268;
+    if ( changed && ship_changed ) {
+      addresses = 'addresses';
+      height = 396; // #what
+    }
+
+    confirm_change = confirm_change +
+      '<TR><TD>' +
+        '<BUTTON TYPE="button" onClick="post_standardization();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' + 
+      '</TD><TD>' +
+        '<BUTTON TYPE="button" onClick="standardize_address();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' + 
+      '</TD></TR>' +
+      '<TR><TD COLSPAN=2 ALIGN="center">' +
+        '<BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
+        
+      '</TABLE></CENTER>';
+
+    overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+%   }
+
+  } else {
+
+    post_standardization();
+
+  }
+
+
+}
+
+function post_standardization() {
+
+  var cf = document.CustomerForm;
+
+% if ( $conf->exists('enable_taxproducts') ) {
+
+  if ( new String(cf.elements['<% $taxpre %>zip'].value).length < 10 )
+  {
+
+    var country_el = cf.elements['<% $taxpre %>country'];
+    var country = country_el.options[ country_el.selectedIndex ].value;
+    var geocode = cf.elements['geocode'].value;
+
+    if ( country == 'CA' || country == 'US' ) {
+
+      var state_el = cf.elements['<% $taxpre %>state'];
+      var state = state_el.options[ state_el.selectedIndex ].value;
+
+      var url = "cust_main/choose_tax_location.html" +
+                  "?data_vendor=cch-zip" + 
+                  ";city="    + cf.elements['<% $taxpre %>city'].value +
+                  ";state="   + state + 
+                  ";zip="     + cf.elements['<% $taxpre %>zip'].value +
+                  ";country=" + country +
+                  ";geocode=" + geocode +
+                  ";";
+
+      // popup a chooser
+      OLgetAJAX( url, update_geocode, 300 );
+
+    } else {
+
+      cf.elements['geocode'].value = 'DEFAULT';
+      post_geocode();
+
+    }
+
+  } else {
+
+    cf.elements['geocode'].value = '';
+    post_geocode();
+
+  }
+
+% } else {
+
+  post_geocode();
+
+% }
+
+}
 
 function post_geocode() {
 
@@ -54,6 +263,29 @@ function post_geocode() {
 
 }
 
+function update_geocode() {
+
+  //yay closures
+  set_geocode = function (what) {
+
+    var cf = document.CustomerForm;
+
+    //alert(what.options[what.selectedIndex].value);
+    var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
+    cf.elements['<% $taxpre %>city'].value     = argsHash['city'];
+    setselect(cf.elements['<% $taxpre %>state'], argsHash['state']);
+    cf.elements['<% $taxpre %>zip'].value      = argsHash['zip'];
+    cf.elements['geocode'].value  = argsHash['geocode'];
+    post_geocode();
+
+  }
+
+  // popup a chooser
+
+  overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+}
+
 var set_censustract;
 
 function update_censustract(arg) {
@@ -149,8 +381,19 @@ function copyelement(from, to) {
   //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
 }
 
+function setselect(el, value) {
+
+  for ( var s = 0; s < el.options.length; s++ ) {
+     if ( el.options[s].value == value ) {
+       el.selectedIndex = s;
+     }
+  }
+
+}
 <%init>
 
 my $conf = new FS::Conf;
 
+my $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : '';
+
 </%init>
index 99bc558..feb61db 100644 (file)
@@ -3,8 +3,8 @@
 <TR>
   <TH ALIGN="right"><%$r%>Contact&nbsp;name<BR>(last,&nbsp;first)</TH>
   <TD COLSPAN=5>
-    <INPUT TYPE="text" NAME="<%$pre%>last" VALUE="<% $cust_main->get($pre.'last') |h %>" onChange="<% $onchange %>" <%$disabled%> <%$style%>> , 
-    <INPUT TYPE="text" NAME="<%$pre%>first" VALUE="<% $cust_main->get($pre.'first') |h %>" onChange="<% $onchange %>" <%$disabled%> <%$style%>>
+    <INPUT TYPE="text" NAME="<%$pre%>last" VALUE="<% $cust_main->get($pre.'last') %>" onChange="<% $onchange %>" <%$disabled%> <%$style%>> , 
+    <INPUT TYPE="text" NAME="<%$pre%>first" VALUE="<% $cust_main->get($pre.'first') %>" onChange="<% $onchange %>" <%$disabled%> <%$style%>>
   </TD>
 % if ( $conf->exists('show_ss') && !$pre ) { 
 
@@ -21,7 +21,7 @@
 <TR>
   <TD ALIGN="right">Company</TD>
   <TD COLSPAN=7>
-    <INPUT TYPE="text" NAME="<%$pre%>company" VALUE="<% $cust_main->get($pre.'company') |h %>" SIZE=70 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
+    <INPUT TYPE="text" NAME="<%$pre%>company" VALUE="<% $cust_main->get($pre.'company') %>" SIZE=70 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
   </TD>
 </TR>
 
index 7c131ea..0de33c0 100644 (file)
@@ -1,9 +1,3 @@
-% if ( $cgi->param('lock_pkgpart') =~ /^([\d, ]+)$/ ) {
-
-    <INPUT TYPE="hidden" NAME="lock_pkgpart" VALUE="<% $1 %>">
-
-% }
-%
 % if ( @part_pkg ) {
 
     <BR><BR>
@@ -34,11 +28,6 @@ if ( scalar(@agents) == 1 ) {
   # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
   $pkgpart = $agents[0]->pkgpart_hashref;
   $agentnum = $agents[0]->agentnum;
-} elsif ( $cgi->param('lock_agentnum') =~ /^(\d+)$/
-            && $FS::CurrentUser::CurrentUser->agentnum($1) ) {
-  $agentnum = $1;
-  my $agent = (grep { $_->agentnum == $agentnum } @agents)[0];
-  $pkgpart = $agent->pkgpart_hashref;
 } else {
   #can't know (agent not chosen), so, allow all
   $agentnum = 'all';
@@ -50,28 +39,9 @@ if ( scalar(@agents) == 1 ) {
 }
 #eslaf
 
-my @part_pkg = ();
-if ( $cgi->param('lock_pkgpart') =~ /^([\d, ]+)$/ ) {
-
-  my $lock_pkgpart = $1;
-
-  @part_pkg = qsearch({
-                        'table'     => 'part_pkg',
-                        'hashref'   => { 'disabled' => '' },
-                        'extra_sql' => "AND pkgpart IN ($lock_pkgpart)",
-                        'order_by'  => 'ORDER BY pkg', # case?
-                     });
-
-} else {
-
-  @part_pkg =
-    qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
-
-}
-
 my @first_svc = ( 'svc_acct', 'svc_phone' );
 
-@part_pkg =
+my @part_pkg =
   grep { $_->svcpart(\@first_svc)
          && ( $pkgpart->{ $_->pkgpart } 
               || $agentnum eq 'all'
@@ -80,6 +50,6 @@ my @first_svc = ( 'svc_acct', 'svc_phone' );
                  )
             )
        }
-  @part_pkg;
+  qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
 
 </%init>
index 20f0e19..871e1cd 100644 (file)
@@ -147,9 +147,7 @@ foreach my $part_pkg ( @part_pkg ) {
   $layermap{$pkgpart_svcpart} = $svcdb{$pkgpart};
 }
 
-my @options = ();
-push @options, '' unless $opt{'disable_empty'};
-push @options, map $pkgpart_svcpart{ $_->pkgpart }, @part_pkg;
+my @options = ( '', map $pkgpart_svcpart{ $_->pkgpart }, @part_pkg );
 my %labels = ( '' => ( $opt{'empty_label'} || '(none)' ),
                map { $pkgpart_svcpart{ $_->pkgpart } => $_->pkg_comment }
                    @part_pkg
index a2381f3..441a363 100644 (file)
@@ -8,30 +8,14 @@
 %>
 
 %# agent
-% if ( $cgi->param('lock_agentnum') =~ /^(\d+)$/ && $curuser->agentnum($1) ) {
-%
-%   my $agentnum = $1;
-%   $cust_main->agentnum($agentnum);
-
-    <INPUT TYPE="hidden" NAME="lock_agentnum" VALUE="<% $agentnum %>">
-    <INPUT TYPE="hidden" NAME="agentnum"      VALUE="<% $agentnum %>">
-    <TR>
-      <TD ALIGN="right">Agent</TD>
-      <TD CLASS="fsdisabled"><% $cust_main->agent->agent |h %></TD>
-    </TR>
-% } else {
-
-  <% 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'
-             )
-  %>
-
-% }
+<% 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'
+           )
+%>
 
 %# agent_custid
 % if ( $conf->exists('cust_main-edit_agent_custid') ) {
index 8e1c779..7c4e662 100755 (executable)
@@ -109,6 +109,9 @@ my $conf = new FS::Conf;
 my $money_char  = $conf->config('money_char')  || '$';
 my $date_format = $conf->config('date_format') || '%m/%d/%Y';
 
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Post payment');
+
 my($link, $linknum, $paid, $payby, $payinfo, $_date);
 if ( $cgi->param('error') ) {
   $link     = $cgi->param('link');
@@ -135,13 +138,6 @@ if ( $cgi->param('error') ) {
   die "illegal query ". $cgi->keywords;
 }
 
-my @rights = ('Post payment');
-push @rights, 'Post check payment' if $payby eq 'BILL';
-push @rights, 'Post cash payment'  if $payby eq 'CASH';
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right(\@rights);
-
 my $paybatch = "webui-$_date-$$-". rand() * 2**32;
 
 my $title = 'Post '. FS::payby->payname($payby). ' payment';
index 0056bb9..0916a1c 100644 (file)
@@ -8,10 +8,6 @@
 
     <CENTER><FONT SIZE="+1"><B>No response was received from <% $cust_pay_pending->processor || 'the payment gateway' %> for this transaction.  Check <% $cust_pay_pending->processor || 'the payment gateway' %>'s reporting and determine if this transaction completed successfully.</B></FONT></CENTER>
 
-% } elsif ( $action eq 'capture' ) {
-
-    <CENTER><FONT SIZE="+1"><B>Captured payment not recorded in database - check logs for errors.</B></FONT></CENTER>
-
 % }
 
 <BR>
@@ -95,9 +91,7 @@
       </TD>
     </TR>
 
-% } else {
-
-%#   if ( $action eq 'complete' ) {
+% } elsif ( $action eq 'complete' ) {
 
     <INPUT TYPE="hidden" NAME="action" VALUE="">
 
       <TD ALIGN="center">
         <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'insert_cust_pay'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/tick.png" ALT=""-->Yes, transaction completed sucessfully.</BUTTON>
       </TD>
-
-%     if ( $action eq 'complete' ) {
-        <TD>&nbsp;&nbsp;&nbsp;</TD>
-        <TD ALIGN="center">
-          <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'decline'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was declined</BUTTON>
-        </TD>
-        <TD>&nbsp;&nbsp;&nbsp;</TD>
-        <TD ALIGN="center">
-          <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'delete'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was not received</BUTTON>
-        </TD>
-      </TR>
-%   }
+      <TD>&nbsp;&nbsp;&nbsp;</TD>
+      <TD ALIGN="center">
+        <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'decline'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was declined</BUTTON>
+      </TD>
+      <TD>&nbsp;&nbsp;&nbsp;</TD>
+      <TD ALIGN="center">
+        <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'delete'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was not received</BUTTON>
+      </TD>
+    </TR>
 
     <TR><TD COLSPAN=5></TD></TR>
 
index 612e337..59417b4 100755 (executable)
 
 <%init>
 
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Refund payment');
+
 my $conf = new FS::Conf;
 my $date_format = $conf->config('date_format') || '%m/%d/%Y';
 
@@ -140,17 +143,6 @@ my $payinfo = $cgi->param('payinfo');
 my $reason  = $cgi->param('reason');
 my $link    = $cgi->param('popup') ? 'popup' : '';
 
-my @rights = ();
-push @rights, 'Post refund'                if $payby /^(BILL|CASH)$/;
-push @rights, 'Post check refund'          if $payby eq 'BILL';
-push @rights, 'Post cash refund '          if $payby eq 'CASH';
-push @rights, 'Refund payment'             if $payby /^(CARD|CHEK)$/;
-push @rights, 'Refund credit card payment' if $payby eq 'CARD';
-push @rights, 'Refund Echeck payment'      if $payby eq 'CHEK';
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right(\@rights);
-
 my( $paynum, $cust_pay ) = ( '', '' );
 if ( $cgi->param('paynum') =~ /^(\d+)$/ ) {
   $paynum = $1;
diff --git a/httemplate/edit/domain_record.html b/httemplate/edit/domain_record.html
deleted file mode 100644 (file)
index 3ea6c77..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<% include('/elements/header-popup.html', 'Edit nameservice record') %>
-
-<% include('/elements/error.html') %>
-
-<FORM METHOD="POST" ACTION="process/domain_record.cgi">
-
-<INPUT TYPE="hidden" NAME="recnum" VALUE="<% $opt{'recnum'} %>">
-
-<% ntable("#cccccc", 2) %>
-
-    <tr>
-      <td>
-        <INPUT TYPE="text" NAME="reczone" VALUE="<% $domain_record->reczone %>">
-        <BR>
-        <FONT SIZE="-1"><I>Zone</I></FONT>
-      </TD>
-      <TD>
-        <INPUT TYPE="hidden" NAME="recaf" VALUE="IN">
-          <SELECT NAME="rectype">
-%           foreach ( @{ FS::domain_record->rectypes } ) { 
-              <OPTION VALUE="<%$_%>"
-                      <% $_ eq $domain_record->rectype ? 'SELECTED' : '' %>
-              >IN <%$_%></OPTION>
-%           } 
-          </SELECT><BR>
-          <FONT SIZE="-1"><I>Type</I></FONT>
-      </TD>
-      <TD>
-        <INPUT TYPE="text" NAME="recdata" VALUE="<% $domain_record->recdata |h %>">
-        <BR>
-        <FONT SIZE="-1"><I>Data</I></FONT>
-      </TD>
-      <TD>
-        <INPUT TYPE="text" NAME="ttl" size="6" VALUE="<% $domain_record->ttl %>">
-        <BR>
-        <FONT SIZE="-1"><I>TTL</I></FONT>
-      </TD>
-
-</TABLE>
-
-<BR>
-<INPUT TYPE="submit" VALUE="Edit record">
-
-</FORM>
-
-<%init>
-
-my %opt = @_;
-
-my $domain_record = qsearchs('domain_record', { 'recnum' => $opt{'recnum'} } )
-  or die "unknown recnum";
-
-</%init>
index 3d82847..b19b361 100644 (file)
@@ -292,11 +292,7 @@ Example:
 %
 %   #select-table
 %   $include_common{$_} = $f->{$_}
-%     foreach grep exists($f->{$_}), qw( value_col );
-%   $include_common{$_} = ref( $f->{$_} ) eq 'CODE'
-%                           ? &{ $f->{$_} }( $cgi, $object ) #, $f )
-%                           : $f->{$_}
-%     foreach grep exists($f->{$_}), qw( extra_sql );
+%     foreach grep exists($f->{$_}), qw( value_col extra_sql );
 %
 %   #select-table, checkboxes-table
 %   $include_common{$_} = $f->{$_}
index be917d6..4546db9 100644 (file)
@@ -80,8 +80,8 @@ my %substitutions = (
   ],
   'cust_pkg' => [
     '$pkgnum'         => 'Package#',
-    '$pkg'            => 'Package description',
-    '$pkg_label'      => 'Description + comment',
+    '$pkg_label'      => 'Package label (short)',
+    '$pkg_label_long' => 'Package label (long)',
     '$status'         => 'Status',
     '$statuscolor'    => 'Status color code',
     '$start_ymd'      => 'Start date',
@@ -96,10 +96,8 @@ my %substitutions = (
     '$location_label' => 'Service location',
   ],
   'svc_acct'  => [
-    '$svcnum'         => 'Service#',
     '$username'       => 'Login name',
     '$password'       => 'Password',
-    '$domain'         => 'Domain name',
   ],
   'cust_pay'  => [
     '$paynum'         => 'Payment#',
index a2fad56..8b697e1 100644 (file)
@@ -77,16 +77,7 @@ my $widget = new HTML::Widgets::SelectLayers(
                       ? $optinfo->{default}
                       : ''
                     );
-      # 'freeform': disables table formatting of options.  Instead, each 
-      # option can define "before" and "after" strings which are inserted 
-      # around the selector.
-      my $freeform = $optinfo->{freeform};
-      if ( $freeform ) {
-        $html .= $optinfo->{before} || '';
-      }
-      else {
-        $html .= qq!<TR><TD ALIGN="right">$label</TD><TD>!;
-      }
+      $html .= qq!<TR><TD ALIGN="right">$label</TD><TD>!;
       if ( $type eq 'select' ) {
         my $size = defined($optinfo->{size}) ? " SIZE=" . $optinfo->{size} : '';
         my $multi = defined($optinfo->{multi}) ? ' MULTIPLE' : '';
@@ -117,7 +108,7 @@ my $widget = new HTML::Widgets::SelectLayers(
         $html .= qq!<TEXTAREA NAME="$option" COLS=80 ROWS=8 WRAP="virtual">!.
                  encode_entities($value). '</TEXTAREA>';
       } elsif ( $type eq 'text' ) {
-        $html .= qq!<INPUT TYPE="text" NAME="$option" VALUE="!. #"
+        $html .= qq!<INPUT TYPE="text" NAME="$option" VALUE="!.
                  encode_entities($value). '" SIZE=64>';
       } elsif ( $type eq 'checkbox' ) {
         $html .= qq!<INPUT TYPE="checkbox" NAME="$option" VALUE="1"!;
@@ -126,12 +117,7 @@ my $widget = new HTML::Widgets::SelectLayers(
       } else {
         $html .= "unknown type $type";
       }
-      if ( $freeform ) {
-        $html .= $optinfo->{after} || '';
-      }
-      else {
-        $html .= '</TD></TR>';
-      }
+      $html .= '</TD></TR>';
     }
     $html .= '</TABLE>';
 
index be8b0f6..9144c49 100755 (executable)
                             },
                             { 'field'      => 'bill_dst_pkgpart',
                               'type'       => 'select-part_pkg',
-                              'extra_sql'  => sub { $pkgpart
-                                                     ? "AND pkgpart != $pkgpart"
-                                                     : ''
-                                                  },
                               'm2_label'   => 'Include line item(s) from package',
                               'm2m_method' => 'bill_part_pkg_link',
                               'm2m_dstcol' => 'dst_pkgpart',
                             { 'field'      => 'svc_dst_pkgpart',
                               'label'      => 'Also include services from package: ',
                               'type'       => 'select-part_pkg',
-                              'extra_sql'  => sub { $pkgpart
-                                                     ? "AND pkgpart != $pkgpart"
-                                                     : ''
-                                                  },
                               'm2_label'   => 'Include services of package: ',
                               'm2m_method' => 'svc_part_pkg_link',
                               'm2m_dstcol' => 'dst_pkgpart',
@@ -325,8 +317,6 @@ my @taxproductnums = ( qw( setup recur ), sort (keys %taxproductnums) );
 my %options = ();
 my $recur_disabled = 1;
 
-my $pkgpart = '';
-
 my $error_callback = sub {
   my($cgi, $object, $fields, $opt ) = @_;
 
@@ -360,8 +350,6 @@ my $error_callback = sub {
   $object->set($_ => scalar($cgi->param($_)) )
     foreach (qw( setup_fee recur_fee ));
 
-  $pkgpart = $object->pkgpart;
-
 };
 
 my $new_hashref_callback = sub { { 'plan' => 'flat' }; };
@@ -411,22 +399,17 @@ my $edit_callback = sub {
   $object->set($_ => $object->option($_))
     foreach (qw( setup_fee recur_fee ));
 
-  $pkgpart = $object->pkgpart;
-
 };
 
 my $new_callback = sub {
   my( $cgi, $object, $fields ) = @_;
 
   my $conf = new FS::Conf; 
-
   if ( $conf->exists('agent_defaultpkg') ) {
     #my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
     @agent_type = map {$_->typenum} qsearch('agent_type',{});
   }
 
-  $options{'suspend_bill'}=1 if $conf->exists('part_pkg-default_suspend_bill');
-
 };
 
 my $clone_callback = sub {
index 3a62ee0..570f0e0 100755 (executable)
@@ -20,7 +20,7 @@ my $pkgnum = $cgi->param('pkgnum') or die;
 my $old = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
 my %hash = $old->hash;
 $hash{$_}= $cgi->param($_) ? parse_datetime($cgi->param($_)) : ''
-  foreach qw( start_date setup bill last_bill adjourn expire contract_end );
+  foreach qw( start_date setup bill last_bill adjourn expire );
 
 my @errors = ();
 
index 8e7e70a..e6258a9 100644 (file)
@@ -10,7 +10,6 @@
                  'process_m2m' => { 'link_table'   => 'access_usergroup',
                                     'target_table' => 'access_group',
                                   },
-                 'precheck_callback'=> \&precheck_callback,
              )
 %>
 %   }
@@ -24,13 +23,4 @@ if ( FS::Conf->new->exists('disable_acl_changes') ) {
   die "shouldn't be reached";
 }
 
-sub precheck_callback {
-  my $cgi = shift;
-  my $o = FS::access_user->new({username => $cgi->param('username')});
-  if( $o->is_system_user and !$cgi->param('usernum') ) {
-    $cgi->param('username','');
-    return "username '".$o->username."' reserved for system account."
-  }
-  return '';
-}
 </%init>
diff --git a/httemplate/edit/process/bulk-cust_pkg.cgi b/httemplate/edit/process/bulk-cust_pkg.cgi
deleted file mode 100644 (file)
index ede3ee8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<% $server->process %>
-<%init>
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-
-my $server = new FS::UI::Web::JSRPC 'FS::cust_pkg::process_bulk_cust_pkg', $cgi;
-
-</%init>
index d6bbf06..c8b0aa7 100755 (executable)
@@ -27,6 +27,9 @@
 %}
 <%init>
 
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Post payment');
+
 $cgi->param('linknum') =~ /^(\d+)$/
   or die "Illegal linknum: ". $cgi->param('linknum');
 my $linknum = $1;
@@ -49,13 +52,6 @@ my $new = new FS::cust_pay ( {
   #} fields('cust_pay')
 } );
 
-my @rights = ('Post payment');
-push @rights, 'Post check payment' if $new->payby eq 'BILL';
-push @rights, 'Post cash payment'  if $new->payby eq 'CASH';
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right(\@rights);
-
 my $error = $new->insert( 'manual' => 1 );
 
 </%init>
index 389bc99..5749e53 100755 (executable)
@@ -28,21 +28,8 @@ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
 
 my $link    = $cgi->param('popup') ? 'popup' : '';
 
-my $payby = $cgi->param('payby');
-
-my @rights = ();
-push @rights, 'Post refund'                if $payby /^(BILL|CASH)$/;
-push @rights, 'Post check refund'          if $payby eq 'BILL';
-push @rights, 'Post cash refund '          if $payby eq 'CASH';
-push @rights, 'Refund payment'             if $payby /^(CARD|CHEK)$/;
-push @rights, 'Refund credit card payment' if $payby eq 'CARD';
-push @rights, 'Refund Echeck payment'      if $payby eq 'CHEK';
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right(\@rights);
-
 my $error = '';
-if ( $payby =~ /^(CARD|CHEK)$/ ) { 
+if ( $cgi->param('payby') =~ /^(CARD|CHEK)$/ ) { 
   my %options = ();
   my $bop = $FS::payby::payby2bop{$1};
   $cgi->param('refund') =~ /^(\d*)(\.\d{2})?$/
index 8369f71..ff0f2d4 100755 (executable)
@@ -1,14 +1,8 @@
 %if ( $error ) {
 %  errorpage($error);
-%} elsif ( $recnum ) { #editing
-<% header('Nameservice record changed') %>
-  <SCRIPT TYPE="text/javascript">
-    window.top.location.reload();
-  </SCRIPT>
-  </BODY></HTML>
-%} else { #adding
+%} else { 
 %  my $svcnum = $new->svcnum;
-<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum#dns") %>
+<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %>
 %}
 <%init>
 
@@ -27,11 +21,10 @@ my $new = new FS::domain_record ( {
 
 my $error;
 if ( $recnum ) {
-  $new->svcnum( $old->svcnum );
-  $error = $new->replace($old);
+  $error=$new->replace($old);
 } else {
-  $error = $new->insert;
-  #$recnum = $new->getfield('recnum');
+  $error=$new->insert;
+  $recnum=$new->getfield('recnum');
 }
 
 </%init>
index 97ae4e7..08cc140 100755 (executable)
@@ -103,7 +103,7 @@ my $args_callback = sub {
     $options{"usage_taxproductnum_$_"} = $value;
   }
 
-  foreach ( grep $_, $cgi->param('report_option') ) {
+  foreach ( $cgi->param('report_option') ) {
     $error ||= "Illegal optional report class: $_" unless ( $_ =~ /^\d*$/  );
     $options{"report_option_$_"} = 1;
   }
index ca4dfab..34d2642 100644 (file)
@@ -4,7 +4,7 @@
      'agent_virt'     => 1,
      'process_o2m' => {
        'table'  => 'contact',
-       'fields' => \@contact_fields,
+       'fields' => [qw( first last title comment )],
      },
      'redirect' => popurl(3). 'view/prospect_main.html?',
    )
@@ -31,9 +31,4 @@ my $args_callback = sub {
 
 };
 
-my @contact_fields = qw( first last title comment emailaddress );
-foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
-  push @contact_fields, 'phonetypenum'.$phone_type->phonetypenum;
-}
-
 </%init>
index 599f760..2fde17f 100644 (file)
@@ -66,10 +66,6 @@ my $cust_pkg = new FS::cust_pkg {
   'discountnum_amount'   => scalar($cgi->param('discountnum_amount')),
   'discountnum_percent'  => scalar($cgi->param('discountnum_percent')),
   'discountnum_months'   => scalar($cgi->param('discountnum_months')),
-  'contract_end'         => ( scalar($cgi->param('contract_end'))
-                                ? parse_datetime($cgi->param('contract_end'))
-                                : ''
-                            ),
   #'discountnum_disabled' => scalar($cgi->param('discountnum_disabled')),
 };
 
@@ -78,7 +74,7 @@ my %opt = ( 'cust_pkg' => $cust_pkg );
 if ( $locationnum == -1 ) {
   my $cust_location = new FS::cust_location {
     map { $_ => scalar($cgi->param($_)) }
-        qw( custnum address1 address2 city county state zip country geocode )
+        qw( custnum address1 address2 city county state zip country )
   };
   $opt{'cust_location'} = $cust_location;
 }
index ec3d221..feb5840 100644 (file)
@@ -1,8 +1,4 @@
-% if ( $error ) {
-%   errorpage($error);
-% } else {
-<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum#dns") %>
-% }
+<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %>
 <%init>
 
 die "access denied"
diff --git a/httemplate/edit/prospect_main-ocr.html b/httemplate/edit/prospect_main-ocr.html
deleted file mode 100644 (file)
index 41fc4c1..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-<%  include("/elements/header.html", 'Upload business card' ) %>
-
-% if ( $error ) { 
-  <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error %></FONT>
-  <BR><BR>
-% } else {
-
-    <FORM ACTION="prospect_main.html" METHOD="POST">
-    <INPUT TYPE="hidden" NAME="session" VALUE="<% $session %>">
-
-    <TABLE>
-
-%   my $num = 0;
-%   foreach my $line ( @lines ) { 
-      <TR>
-        <TD>
-          <INPUT TYPE="hidden" NAME="val<%$num%>" VALUE="<% $line |h %>">
-          <SELECT NAME="sel<%$num%>">
-            <OPTION VALUE="">
-            <OPTION VALUE="name">Name
-            <OPTION VALUE="contactnum0_title">Title
-            <OPTION VALUE="company">Company
-            <OPTION VALUE="contactnum0_emailaddress">Email
-            <OPTION VALUE="address1">Address (1)
-            <OPTION VALUE="address2">Address (2)
-            <OPTION VALUE="city_state_zip">City, State, Zip
-%           my @phone_types = qsearch({table=>'phone_type',order_by=>'weight'});
-%           foreach my $phone_type ( @phone_types ) {
-%             next if $phone_type->typename eq 'Home';
-              <OPTION VALUE="contactnum0_phonetypenum<% $phone_type->phonetypenum %>"><% $phone_type->typename |h %> phone
-%           }
-            <OPTION VALUE="contactnum0_comment">Comment
-          </SELECT>
-        </TD>
-        <TD><% $line %></TD>
-
-%       unless ( $num++) {
-
-          <TD ROWSPAN="9999"><IMG SRC="<%$p%>view/image.cgi?type=png;prefname=bizcard<%$session%>" WIDTH=604 HEIGHT=328></IMG></TD>
-
-%       }
-
-      </TR>
-%   }
-
-    </TABLE>
-
-    <BR>
-    <INPUT TYPE="submit" VALUE="Create prospect">
-
-% }
-<% include('/elements/footer.html') %>
-<%init>
-
-my $fh = $cgi->upload('card');
-
-my $error = '';
-my @lines = ();
-my $session = '';
-if ( defined $fh ) {
-
-  local $/;
-  my $logo_data = <$fh>;
-
-  $session = int(rand(4294967296)); #XXX
-  my $pref = new FS::access_user_pref({
-    'usernum'    => $FS::CurrentUser::CurrentUser->usernum,
-    'prefname'   => "bizcard$session",
-    'prefvalue'  => encode_base64($logo_data),
-    'expiration' => time + 3600, #1h?  1m?
-  });
-  my $pref_error = $pref->insert;
-  if ( $pref_error ) {
-    die "FATAL: couldn't set preview cookie: $pref_error\n";
-  }
-
-  @lines = eval { ocr_image($logo_data); };
-  $error = $@ if $error;
-
-} else {
-
-  $error = 'No file uploaded';
-
-}
-
-</%init>
diff --git a/httemplate/edit/prospect_main-upload.html b/httemplate/edit/prospect_main-upload.html
deleted file mode 100644 (file)
index 24b1caa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<%  include("/elements/header.html", 'Upload business card' ) %>
-
-  <FORM ACTION="prospect_main-ocr.html" METHOD="POST" ENCTYPE="multipart/form-data">
-  <INPUT TYPE="file" NAME="card">
-  <BR><INPUT TYPE="submit" NAME="submit" VALUE="Upload">
-
-<% include('/elements/footer.html') %>
index c260eb8..e867907 100644 (file)
@@ -5,7 +5,6 @@
                             'agentnum'    => 'Agent',
                             'company'     => 'Company',
                             'contactnum'  => 'Contact',
-                            'locationnum' => '&nbsp;',
                           },
      'fields'          => [
        { 'field'       => 'agentnum',
@@ -35,7 +34,6 @@
          'empty_label' => 'No address',
        },
      ],
-     'new_callback'    => $new_callback,
      'edit_callback'   => $edit_callback,
      'error_callbacck' => $error_callback,
      'agent_virt'      => 1,
@@ -64,48 +62,6 @@ if ( $cgi->param('error') ) {
 
 }
 
-my $new_callback = sub {
-  my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
-
-  if ( $cgi->param('session') =~ /^(\w+)$/ ) {
-    my $session = $1;
-
-    #add a link to the image.cgi for this card
-    $opt_hashref->{'html_bottom'} .=
-      qq(<BR><IMG SRC="${p}view/image.cgi?type=png;prefname=bizcard$session" ).
-      ' WIDTH=604 HEIGHT=328><BR>';
-
-    #fill in the incoming params: name, address1/address2, city_state_zip
-    foreach my $param ( grep /^sel\d+$/, $cgi->param ) {
-      $param =~ /^sel(\d+)$/ or die 'again, wtf (daily)';
-      my $num = $1;
-      my $field = $cgi->param($param);
-      my $value = $cgi->param("val$num");
-      $cgi->param($field => $value);
-    }
-
-    if ( $cgi->param('company') ) {
-      $prospect_main->company( $cgi->param('company') );
-    }
-
-    if ( $cgi->param('name') =~ /^(.*\S+)\s+(\w+)\s*$/ ) {
-      $cgi->param('contactnum0_first' => $1);
-      $cgi->param('contactnum0_last'  => $2);
-    }
-
-    if ( grep $cgi->param($_), qw( address1 address2 city_state_zip ) ) {
-      $cgi->param('locationnum', -1);
-      if ( $cgi->param('city_state_zip') =~ /^(\s*)([\w\s]+)[\., ]+(\w{2})[, ]+(\d{5}(-\d{4})?)/ ) {
-         $cgi->param('city'  => $2);
-         $cgi->param('state' => $3);
-         $cgi->param('zip'   => $4);
-      }
-    }
-
-  }
-
-};
-
 my $edit_callback = sub {
   #my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
   my( $cgi, $prospect_main ) = @_;
index eea3694..a7a33b1 100644 (file)
@@ -5,38 +5,12 @@
   <TABLE>
     <TR>
 %     foreach my $field ( @fields ) {
-%
-%       my $value = '';
-%       if ( $field =~ /^phonetypenum(\d+)$/ ) {
-%         my $contact_phone = qsearchs('contact_phone', {
-%           'contactnum'   => $curr_value,
-%           'phonetypenum' => $1,
-%         });
-%         if ( $contact_phone ) {
-%           $value = $contact_phone->phonenum;
-%           $value .= 'x'.$contact_phone->extension
-%             if $contact_phone->extension;
-%           $value = '+'. $contact_phone->countrycode. " $value"
-%             if $contact_phone->countrycode
-%             && $contact_phone->countrycode ne '1';
-%         }
-%       } elsif ( $field eq 'emailaddress' ) {
-%         #XXX multiple not yet supported
-%         my $contact_email = qsearchs('contact_email', {
-%           'contactnum' => $curr_value,
-%         });
-%         $value = $contact_email->emailaddress if $contact_email;
-%       } else {
-%         $value = $contact->get($field);
-%       }
-
         <TD>
-          <INPUT TYPE  = "text"
-                 NAME  = "<%$name%>_<%$field%>"
-                 ID    = "<%$id%>_<%$field%>"
-                 SIZE  = "<% $size{$field} || 15 %>"
+          <INPUT TYPE = "text"
+                 NAME = "<%$name%>_<%$field%>"
+                 ID   = "<%$id%>_<%$field%>"
                  VALUE = "<% scalar($cgi->param($name."_$field"))
-                             || $value |h %>"
+                             || $contact->get($field) |h %>"
                  <% $onchange %>
           ><BR>
           <FONT SIZE="-1"><% $label{$field} %></FONT>
@@ -71,25 +45,12 @@ if ( $curr_value ) {
   $contact = new FS::contact {};
 }
 
-my %size = ( 'title' => 12 );
-
 tie my %label, 'Tie::IxHash',
-  'first'        => 'First name',
-  'last'         => 'Last name',
-  'title'        => 'Title/Position',
-  'emailaddress' => 'Email',
+  'first'  => 'First name',
+  'last'    => 'Last name',
+  'title'   => 'Title/Position',
+  'comment' => 'Comment',
 ;
-
-my $first = 0;
-foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
-  next if $phone_type->typename eq 'Home';
-  my $f = 'phonetypenum'.$phone_type->phonetypenum;
-  $label{$f} = $phone_type->typename. ' phone';
-  $size{$f} = $first++ ? 11 : 15;
-}
-
-$label{'comment'} = 'Comment';
-
 my @fields = keys %label;
 
 </%init>
index 6cb1503..18b14e3 100644 (file)
@@ -40,16 +40,6 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus {
         border-radius: 2px;
 }
 
-.fsdisabled {
-  background-color: #dddddd;
-  color: #666666;
-  border: 1px solid #999999;
-  padding: 1px;
-        -moz-border-radius: 2px;
-        -webkit-border-radius: 2px;
-        border-radius: 2px;
-}
-
 input[type="reset"], input[type="submit"], input[type="button"] {
   background-color: #dddddd;
   border: 1px solid #666666;
index 2a9bc1d..0ea4be7 100644 (file)
@@ -1,9 +1,8 @@
-% if(!$noinit) {
+
 <LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar_stripped.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-en.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
-% }
 
 <INPUT TYPE="text" NAME="<% $name %>" ID="<% $name %>_text" VALUE="<% $value %>">
 <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $name  %>_button" STYLE="cursor: pointer" TITLE="Select date">
 
 <%init>
 
-my($name, $value, $format, $usedatetime, $noinit);
+my($name, $value, $format, $usedatetime);
 if ( ref($_[0]) ) {
   my $opt = shift;
   $name        = $opt->{'name'};
   $value       = $opt->{'value'};
   $format      = $opt->{'format'};
   $usedatetime = $opt->{'usedatetime'};
-  $noinit      = $opt->{'noinit'};
 } else {
   ($name, $value, $format, $usedatetime) = @_;
 }
index 1909d90..b852a40 100644 (file)
@@ -190,11 +190,6 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
       [ $fsurl."search/report_$svcdb.html", '' ];
   }
 
-  if ( $svcdb eq 'svc_phone' ) {
-    $report_svc{"Avaialble phone numbers (DIDs)"} =
-      [ $fsurl."search/phone_avail.html", '' ];
-  }
-
   $report_services{$name} = [ \%report_svc, $longname ];
 
 }
@@ -369,13 +364,11 @@ $tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_d
   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');
+  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' ]
   if $conf->config('ticket_system');
-$tools_menu{'Business card scan'} = [ $fsurl.'edit/prospect_main-upload.html' ]
-  if $curuser->access_right('New prospect');
 $tools_menu{'Time Queue'} =  [ $fsurl.'search/report_timeworked.html', 'View pending support time' ]
   if $curuser->access_right('Time queue');
 $tools_menu{'Attachments'} = [ $fsurl.'browse/cust_attachment.html', 'View customer attachments' ]
@@ -544,8 +537,8 @@ my $wiki = 'http://www.freeside.biz/mediawiki/index.php';
 my $doc_link = $conf->config('support-key')
                  ? "$wiki/Supported:Documentation"
                  : $curuser->access_right('Configuration')
-                   ? "$wiki/Freeside:2.1:Documentation"
-                   : "$wiki/Freeside:2.1:Documentation:User";
+                   ? "$wiki/Freeside:1.9:Documentation"
+                   : "$wiki/Freeside:1.9:Documentation:User";
 
 eval "use RT;"
   if $conf->config('ticket_system') eq 'RT_Internal';
index fbb6ce3..49b624c 100644 (file)
@@ -11,7 +11,7 @@ Example:
     'label'          => 'click me',     # text of <A> tag
    
     #strongly recommended
-    'actionlabel'    => 'You clicked',  # popup title
+    'actionlabel     => 'You clicked',  # popup title
    
     #opt
     'width'          => 540,
index e8c645e..317922d 100644 (file)
@@ -11,7 +11,7 @@ Example:
   );
 
 </%doc>
-<INPUT TYPE="hidden" NAME="<% $field %>" ID="<% $field %>" VALUE="<% $value %>">
+<INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $value %>">
 
 <!-- some false laziness w/ misc/batch-cust_pay.html, though not as bad as i'd thought at first... -->
 
@@ -60,9 +60,6 @@ Example:
 
   function smart_<% $field %>_search(what) {
 
-    if ( <% $field %>_search_active )
-      return;
-
     var customer = what.value;
 
     if ( customer == 'searching...' || customer == ''
index cbf90b6..34476bc 100644 (file)
@@ -12,7 +12,7 @@
 %  if ( $opt{'show_month_abbr'} ) {
 %    @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
 %  } else {
-%    @mon = ( ( map "0$_", 1 .. 9 ), 10 .. 12 ), 
+%    @mon = ( 1 .. 12 );
 %  }
 %
 %  my $date = $opt{'selected_date'} || '';
index 2d60fde..9b358e2 100644 (file)
@@ -32,7 +32,7 @@ Example:
 
 % foreach my $state ( keys %states ) { 
 
-  <OPTION VALUE="<% $state |h %>"<% $state eq $opt{'state'} ? ' SELECTED' : '' %>><% $states{$state} || '(n/a)' |h %>
+  <OPTION VALUE="<% $state |h %>"<% $state eq $opt{'state'} ? ' SELECTED' : '' %>><% $states{$state} || '(n/a)' %>
 
 % } 
 
index 1ca586e..52f9fb5 100644 (file)
@@ -33,7 +33,7 @@ my $empty_label =
 my $empty_value = $opt{'empty_value'} || '';
 
 my @terms = ( 'Payable upon receipt',
-              ( map "Net $_", 0, 10, 15, 20, 30, 45, 60, 90 ),
+              ( map "Net $_", 0, 10, 15, 20, 30, 45, 60 ),
             );
 
 my @pre_options = $opt{pre_options} ? @{ $opt{pre_options} } : ();
diff --git a/httemplate/elements/standardize_locations.html b/httemplate/elements/standardize_locations.html
deleted file mode 100644 (file)
index 9f8b71c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<% include('/elements/init_overlib.html') %>
-
-<% include( '/elements/xmlhttp.html',
-              'url'  => $p.'misc/xmlhttp-cust_main-address_standardize.html',
-              'subs' => [ 'address_standardize' ],
-              #'method' => 'POST', #could get too long?
-          )
-%>
-
-<SCRIPT TYPE="text/javascript">
-  <% include('/elements/standardize_locations.js', %options) %>
-</SCRIPT>
-
-<%init>
-
-my (%options) = @_;
-
-</%init>
diff --git a/httemplate/elements/standardize_locations.js b/httemplate/elements/standardize_locations.js
deleted file mode 100644 (file)
index e6a4aa6..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-function standardize_locations() {
-
-  var cf = document.<% $formname %>;
-
-  var state_el      = cf.elements['<% $main_prefix %>state'];
-  var ship_state_el = cf.elements['<% $ship_prefix %>state'];
-
-  var address_info = new Array(
-% if ( $onlyship ) {
-    'onlyship', 1,
-% } else {
-%   if ( $withfirm ) {
-    'company',  cf.elements['<% $main_prefix %>company'].value,
-%   }
-    'address1', cf.elements['<% $main_prefix %>address1'].value,
-    'address2', cf.elements['<% $main_prefix %>address2'].value,
-    'city',     cf.elements['<% $main_prefix %>city'].value,
-    'state',    state_el.options[ state_el.selectedIndex ].value,
-    'zip',      cf.elements['<% $main_prefix %>zip'].value,
-% }
-% if ( $withfirm ) {
-    'ship_company',  cf.elements['<% $ship_prefix %>company'].value,
-% }
-    'ship_address1', cf.elements['<% $ship_prefix %>address1'].value,
-    'ship_address2', cf.elements['<% $ship_prefix %>address2'].value,
-    'ship_city',     cf.elements['<% $ship_prefix %>city'].value,
-    'ship_state',    ship_state_el.options[ ship_state_el.selectedIndex ].value,
-    'ship_zip',      cf.elements['<% $ship_prefix %>zip'].value
-  );
-
-  address_standardize( address_info, update_address );
-
-}
-
-var standardize_address;
-
-function update_address(arg) {
-
-  var argsHash = eval('(' + arg + ')');
-
-  var changed  = argsHash['address_standardized'];
-  var ship_changed = argsHash['ship_address_standardized'];
-  var error = argsHash['error'];
-  var ship_error = argsHash['ship_error'];
-  
-
-  //yay closures
-  standardize_address = function () {
-
-    var cf = document.<% $formname %>;
-    var state_el      = cf.elements['<% $main_prefix %>state'];
-    var ship_state_el = cf.elements['<% $ship_prefix %>state'];
-
-% if ( !$onlyship ) {
-    if ( changed ) {
-%   if ( $withfirm ) {
-      cf.elements['<% $main_prefix %>company'].value  = argsHash['new_company'];
-%   }
-      cf.elements['<% $main_prefix %>address1'].value = argsHash['new_address1'];
-      cf.elements['<% $main_prefix %>address2'].value = argsHash['new_address2'];
-      cf.elements['<% $main_prefix %>city'].value     = argsHash['new_city'];
-      setselect(cf.elements['<% $main_prefix %>state'], argsHash['new_state']);
-      cf.elements['<% $main_prefix %>zip'].value      = argsHash['new_zip'];
-    }
-% }
-
-    if ( ship_changed ) {
-% if ( $withfirm ) {
-      cf.elements['<% $ship_prefix %>company'].value  = argsHash['new_ship_company'];
-% }
-      cf.elements['<% $ship_prefix %>address1'].value = argsHash['new_ship_address1'];
-      cf.elements['<% $ship_prefix %>address2'].value = argsHash['new_ship_address2'];
-      cf.elements['<% $ship_prefix %>city'].value     = argsHash['new_ship_city'];
-      setselect(cf.elements['<% $ship_prefix %>state'], argsHash['new_ship_state']);
-      cf.elements['<% $ship_prefix %>zip'].value      = argsHash['new_ship_zip'];
-    }
-
-    post_standardization();
-
-  }
-
-
-
-  if ( changed || ship_changed ) {
-
-%   if ( $conf->exists('cust_main-auto_standardize_address') ) {
-
-    standardize_address();
-
-%   } else {
-
-    // popup a confirmation popup
-
-    var confirm_change =
-      '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
-      '<TABLE>';
-    
-    if ( changed ) {
-
-      confirm_change = confirm_change + 
-        '<TR><TH>Entered billing address</TH>' +
-          '<TH>Standardized billing address</TH></TR>';
-        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-      
-      if ( argsHash['company'] || argsHash['new_company'] ) {
-        confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['company'] +
-          '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
-      }
-      
-      confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['address1'] +
-          '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['address2'] +
-          '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + '  ' + argsHash['zip'] +
-          '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + '  ' + argsHash['new_zip'] + '</TD></TR>' +
-          '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
-    }
-
-    if ( ship_changed ) {
-
-      confirm_change = confirm_change + 
-        '<TR><TH>Entered service address</TH>' +
-          '<TH>Standardized service address</TH></TR>';
-        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-      
-      if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
-        confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['ship_company'] +
-          '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
-      }
-      
-      confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['ship_address1'] +
-          '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['ship_address2'] +
-          '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + '  ' + argsHash['ship_zip'] +
-          '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + '  ' + argsHash['new_ship_zip'] + '</TD></TR>' +
-        '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
-    }
-
-    var addresses = 'address';
-    var height = 268;
-    if ( changed && ship_changed ) {
-      addresses = 'addresses';
-      height = 396; // #what
-    }
-
-    confirm_change = confirm_change +
-      '<TR><TD>' +
-        '<BUTTON TYPE="button" onClick="post_standardization();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' + 
-      '</TD><TD>' +
-        '<BUTTON TYPE="button" onClick="standardize_address();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' + 
-      '</TD></TR>' +
-      '<TR><TD COLSPAN=2 ALIGN="center">' +
-        '<BUTTON TYPE="button" onClick="document.<% $formname %>.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
-        
-      '</TABLE></CENTER>';
-
-    overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
-
-%   }
-
-  } else {
-
-    post_standardization();
-
-  }
-
-
-}
-
-function post_standardization() {
-
-  var cf = document.<% $formname %>;
-
-% if ( $conf->exists('enable_taxproducts') ) {
-
-  if ( new String(cf.elements['<% $taxpre %>zip'].value).length < 10 )
-  {
-
-    var country_el = cf.elements['<% $taxpre %>country'];
-    var country = country_el.options[ country_el.selectedIndex ].value;
-    var geocode = cf.elements['geocode'].value;
-
-    if ( country == 'CA' || country == 'US' ) {
-
-      var state_el = cf.elements['<% $taxpre %>state'];
-      var state = state_el.options[ state_el.selectedIndex ].value;
-
-      var url = "<% $p %>/misc/choose_tax_location.html" +
-                  "?data_vendor=cch-zip" + 
-                  ";city="     + cf.elements['<% $taxpre %>city'].value +
-                  ";state="    + state + 
-                  ";zip="      + cf.elements['<% $taxpre %>zip'].value +
-                  ";country="  + country +
-                  ";geocode="  + geocode +
-                  ";formname=" + '<% $formname %>' +
-                  ";";
-
-      // popup a chooser
-      OLgetAJAX( url, update_geocode, 300 );
-
-    } else {
-
-      cf.elements['geocode'].value = 'DEFAULT';
-      <% $post_geocode %>;
-
-    }
-
-  } else {
-
-    cf.elements['geocode'].value = '';
-    <% $post_geocode %>;
-
-  }
-
-% } else {
-
-  <% $post_geocode %>;
-
-% }
-
-}
-
-function update_geocode() {
-
-  //yay closures
-  set_geocode = function (what) {
-
-    var cf = document.<% $formname %>;
-
-    //alert(what.options[what.selectedIndex].value);
-    var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
-    cf.elements['<% $taxpre %>city'].value     = argsHash['city'];
-    setselect(cf.elements['<% $taxpre %>state'], argsHash['state']);
-    cf.elements['<% $taxpre %>zip'].value      = argsHash['zip'];
-    cf.elements['geocode'].value  = argsHash['geocode'];
-    <% $post_geocode %>;
-
-  }
-
-  // popup a chooser
-
-  overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
-
-}
-
-function setselect(el, value) {
-
-  for ( var s = 0; s < el.options.length; s++ ) {
-     if ( el.options[s].value == value ) {
-       el.selectedIndex = s;
-     }
-  }
-
-}
-<%init>
-
-my %opt = @_;
-my $conf = new FS::Conf;
-
-my $withfirm = 1;
-
-my $formname =  $opt{form} || 'CustomerForm';
-my $onlyship =  $opt{onlyship} || '';
-my $main_prefix =  $opt{main_prefix} || '';
-my $ship_prefix =  $opt{ship_prefix} || ($onlyship ? '' : 'ship_');
-my $taxpre = $main_prefix;
-$taxpre = $ship_prefix if ( $conf->exists('tax-ship_address') || $onlyship );
-my $post_geocode = $opt{callback} || 'post_geocode();';
-$withfirm = 0 if $opt{no_company};
-
-</%init>
index e68ed4a..e66bdf7 100644 (file)
@@ -84,7 +84,7 @@ my @part_svc = qsearch('part_svc', {}, '', $where);
 
 #my $q_part_pkg = $clone_part_pkg || $part_pkg;
 #my %pkg_svc = map { $_->svcpart => $_ } $q_part_pkg->pkg_svc;
-my %pkg_svc = map { $_->svcpart => $_ } $part_pkg->pkg_svc('disable_linked'=>1);
+my %pkg_svc = map { $_->svcpart => $_ } $part_pkg->pkg_svc;
 
 my @fixups = ();
 my $count = 0;
index b2b6d96..d88f3a8 100644 (file)
@@ -1,4 +1,4 @@
-% if ( ($curuser->access_right('Edit customer tags') && @part_tag) || $is_report ) {
+% if ( $curuser->access_right('Edit customer tags') && @part_tag ) {
 
   <TR>
     <TD ALIGN="right"><% $opt{'label'} || 'Tags' %></TD>
@@ -25,7 +25,6 @@ my $curuser = $FS::CurrentUser::CurrentUser;
 
 my %opt = @_;
 my $cgi = $opt{'cgi'};
-my $is_report = $opt{'is_report'};
 
 my @curr_tagnum = ();
 if ( $cgi->param('error') ) {
index ec10b85..16b7071 100755 (executable)
@@ -2,7 +2,7 @@
 
 <% include('/elements/error.html') %>
 
-<FORM NAME="OrderPkgForm" ACTION="<% $p %>edit/process/change-cust_pkg.html" METHOD=POST>
+<FORM ACTION="<% $p %>edit/process/change-cust_pkg.html" METHOD=POST>
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
 
 <% ntable('#cccccc') %>
 
 </TABLE>
 
-<% include( '/elements/standardize_locations.html',
-            'form'       => "OrderPkgForm",
-            'onlyship'   => 1,
-            'no_company' => 1,
-            'callback'   => 'document.OrderPkgForm.submit();',
-          )
-%>
-
 <BR>
-<INPUT NAME="submitButton" TYPE="button" VALUE="Change package" onClick="this.disabled=true; standardize_locations();">
+<INPUT TYPE="submit" VALUE="Change package">
 
 </FORM>
 </BODY>
diff --git a/httemplate/misc/choose_tax_location.html b/httemplate/misc/choose_tax_location.html
deleted file mode 100644 (file)
index dce04c7..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<FORM NAME="choosegeocodeform">
-<CENTER><BR><B>Choose tax location</B><BR><BR>
-<P>the geocode is:<% $header %></P>
-<P STYLE="<% $style %>"><% $header %></P>
-
-<SELECT NAME='geocodes' ID='geocodes' STYLE="<% $style %>">
-% foreach my $location (@cust_tax_location) {
-%   my %value = ( zip => $zip5,
-%                 map { $_ => $location->$_ }
-%                   qw ( city state geocode )
-%               );
-%   map { $value{$_} = $location{$_} } qw ( city state )
-%     if $location{country} eq 'CA';
-%
-%   my $value = encode_entities(objToJson({ %value })
-%                              );
-%   my $content = '';
-%   $content .= $location->$_. '&nbsp;' x ( $max{$_} - length($location->$_) )
-%     foreach qw( city county state );
-%   $content .=   $location->cityflag eq 'I' ? 'Y' : 'N' ;
-%   my $selected = '' ;
-%   if ($geocode && $location->geocode eq $geocode) {
-%     $selected = 'SELECTED';
-%   }
-  <OPTION VALUE="<% $value %>" STYLE="<% $style %>" <% $selected %>><% $content %>
-% }
-</SELECT><BR><BR>
-
-<TABLE><TR>
-  <TD> <BUTTON TYPE="button" onClick="set_geocode(document.getElementById('geocodes'));"><IMG SRC="<%$p%>images/tick.png" ALT=""> Set location </BUTTON></TD>
-  <TD><BUTTON TYPE="button" onClick="document.<% $formname %>.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission </BUTTON></TD>
-</TR>
-</TABLE>
-
-</CENTER>
-</FORM>
-<%init>
-
-my $conf = new FS::Conf;
-
-my %location = ();
-
-($location{data_vendor}) = $cgi->param('data_vendor') =~ /^([-\w]+)$/;
-($location{city})        = $cgi->param('city')        =~ /^([\w ]+)$/;
-($location{state})       = $cgi->param('state')       =~ /^(\w+)$/;
-($location{zip})         = $cgi->param('zip')         =~ /^([-\w ]+)$/;
-($location{country})     = $cgi->param('country')     =~ /^([\w ]+)$/;
-
-my($geocode)             = $cgi->param('geocode')     =~ /^([\w]+)$/;
-
-my($formname)            = $cgi->param('formname')    =~ /^([\w]*)$/;
-$formname ||= 'CustomerForm';
-
-my($zip5, $zip4) = split('-', $location{zip});
-
-#only support US & CA
-my $hashref = { 'data_vendor' => $location{data_vendor} };
-$hashref->{zip} = $location{country} eq 'CA' ? substr($zip5,0,1) : $zip5,
-
-my @keys = keys(%$hashref);
-my @cust_tax_location = ();
-until ( @cust_tax_location ) {
-  @cust_tax_location = qsearch({ table    => 'cust_tax_location',
-                                 hashref  =>  $hashref,
-                                 order_by =>  'LIMIT 50',
-                              });
-  last unless scalar(@keys);
-  delete $hashref->{ shift @keys };
-} 
-
-my %max = ( city => 4, county => 6, state => 5);
-foreach my $location (@cust_tax_location) {
-  foreach ( qw( city county state ) ) {
-    my $length = length($location->$_);
-    $max{$_} = ($length > $max{$_}) ? $length : $max{$_};
-  }
-}
-foreach ( qw( city county state ) ) {
-  $max{$_} = $location{$_} if $location{$_} > $max{$_};
-  $max{$_}++;
-}
-
-my $header = '&nbsp;&nbsp;';
-$header .= $_. '&nbsp;' x ( $max{lc($_)} - length($_) )
-  foreach qw( City County State );
-$header .=   "In city?";
-
-my $style = "font-family:monospace;";
-
-</%init>
diff --git a/httemplate/misc/cust_main-merge.html b/httemplate/misc/cust_main-merge.html
deleted file mode 100755 (executable)
index 4decbef..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-% if ( $error ) {
-% $cgi->param('error', $error);
-<% $cgi->redirect(popurl(1). "merge_cust.html?". $cgi->query_string ) %>
-% } else {
-<% include('/elements/header-popup.html', "Customer merged") %>
-  <SCRIPT TYPE="text/javascript">
-    window.top.location.href = '<% $p %>view/cust_main.cgi?<% $new_custnum %>';
-%# parent.nd(1) ?
-  </SCRIPT>
-  </BODY>
-</HTML>
-% }
-<%init>
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right('Merge customer');
-
-my $error = '';
-
-$cgi->param('custnum') =~ /^(\d+)$/ or die "illegal custnum";
-my $custnum = $1;
-
-my $new_custnum;
-if ( $cgi->param('new_custnum') =~ /^(\d+)$/ ) {
-  $new_custnum = $1;
-
-  my $cust_main = qsearchs( {
-    'table'     => 'cust_main',
-    'hashref'   => { 'custnum' => $custnum },
-    'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
-  } );
-  die "No customer # $custnum" unless $cust_main;
-
-  $error = $cust_main->merge($new_custnum);
-
-} else {
-  $error = 'Select a customer to merge into';
-}
-
-</%init>
index 200365d..08eedde 100755 (executable)
@@ -1,7 +1,7 @@
 % if ( $error ) {
 %   errorpage($error);
 % } else {
-<% $cgi->redirect($p. "view/svc_domain.cgi?". $domain_record->svcnum. '#dns') %>
+<% $cgi->redirect($p. "view/svc_domain.cgi?". $domain_record->svcnum) %>
 % }
 <%init>
 
index 759c8bf..0ec8bb9 100644 (file)
@@ -29,7 +29,6 @@
 % if ( $cgi->param('action') ) {
 
     <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
-    <INPUT TYPE="hidden" NAME="msgnum" VALUE="<% $cgi->param('msgnum') %>">
 
 %   if ( $msg_template ) {
       <% include('/elements/tr-fixed.html',
diff --git a/httemplate/misc/merge_cust.html b/httemplate/misc/merge_cust.html
deleted file mode 100644 (file)
index ad075be..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<% include('/elements/header-popup.html', 'Merge customer' ) %>
-
-<% include('/elements/error.html') %>
-
-<FORM NAME="cust_merge_popup" ID="cust_merge_popup" ACTION="<% popurl(1) %>cust_main-merge.html" METHOD=POST onSubmit="submit_merge(); return false;">
-
-<SCRIPT TYPE="text/javascript">
-
-var submit_interval_id;
-function submit_merge() {
-  document.getElementById('confirm_merge_cust_button').disabled = 'true';
-  smart_new_custnum_search(document.getElementById('new_custnum_search'));
-  submit_interval_id = setInterval( do_submit_merge, 100);
-}
-
-function do_submit_merge() {
-
-  if ( new_custnum_search_active )
-    return;
-
-  document.getElementById('confirm_merge_cust_button').disabled = '';
-
-  clearInterval(submit_interval_id);
-
-  if ( document.cust_merge_popup.new_custnum.value != '' ) {
-    document.cust_merge_popup.submit();
-  }
-
-}
-
-</SCRIPT>
-
-</SCRIPT>
-
-<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
-
-<TABLE BORDER="0" CELLSPACING="2" STYLE="margin-left:auto; margin-right:auto">
-  <% include('/elements/tr-search-cust_main.html',
-               'label'       => 'Merge into: ',
-               'field'       => 'new_custnum',
-               'find_button' => 1,
-               'curr_value'  => scalar($cgi->param('new_custnum')),
-            )
-  %>
-</TABLE>
-
-<P ALIGN="CENTER">
-%#have merge button start out disabled and enable after you select a target cust
-<INPUT TYPE="submit" NAME="confirm_merge_cust_button" ID="confirm_merge_cust_button" VALUE="Merge customer">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="BUTTON" VALUE="Don't merge" onClick="parent.cClick();"> 
-
-</FORM>
-</BODY>
-</HTML>
-
-<%init>
-
-$cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
-my $custnum = $1;
-
-my $curuser = $FS::CurrentUser::CurrentUser;
-
-die "access denied" unless $curuser->access_right('Merge customer');
-
-my $cust_main = qsearchs( {
-  'table'     => 'cust_main',
-  'hashref'   => { 'custnum' => $custnum },
-  'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
-} );
-die "No customer # $custnum" unless $cust_main;
-
-</%init>
-
index b232deb..8479a75 100644 (file)
@@ -9,14 +9,14 @@
 
   function enable_order_pkg () {
     if ( document.OrderPkgForm.pkgpart.selectedIndex > 0 ) {
-      document.OrderPkgForm.submitButton.disabled = false;
+      document.OrderPkgForm.submit.disabled = false;
       if ( document.OrderPkgForm.pkgpart.options[document.OrderPkgForm.pkgpart.selectedIndex].getAttribute('data-can_discount') == 1 ) {
         document.OrderPkgForm.discountnum.disabled = false;
       } else {
         document.OrderPkgForm.discountnum.disabled = true;
       }
     } else {
-      document.OrderPkgForm.submitButton.disabled = true;
+      document.OrderPkgForm.submit.disabled = true;
       document.OrderPkgForm.discountnum.disabled = true;
     }
   }
           )
 %>
 
+%# false laziness w/edit/quick-charge.html
 <TR>
   <TH ALIGN="right">Start date </TD>
   <TD COLSPAN=6>
-    <% include('/elements/input-date-field.html',{
-                'name'      => 'start_date',
-                'format'    => $date_format,
-                'value'     => $start_date,
-                'noinit'    => 1,
-              }) %>
+    <INPUT TYPE  = "text"
+           NAME  = "start_date"
+           SIZE  = 32
+           ID    = "start_date_text"
+           VALUE = "<% $start_date %>"
+    >
+    <IMG SRC   = "../images/calendar.png"
+         ID    = "start_date_button"
+         STYLE = "cursor: pointer"
+         TITLE = "Select date"
+    >
     <FONT SIZE=-1>(leave blank to start immediately)</FONT>
   </TD>
 </TR>
 
+<SCRIPT TYPE="text/javascript">
+  Calendar.setup({
+    inputField: "start_date_text",
+    ifFormat:   "<% $date_format %>",
+    button:     "start_date_button",
+    align:      "BR"
+  });
+</SCRIPT>
+
 % if ( $cust_main->payby =~ /^(CARD|CHEK)$/ ) {
 %   my $what = lc(FS::payby->shortname($cust_main->payby));
     <TR>
           )
 %>
 
-<TR>
-  <TH ALIGN="right">Contract end date </TD>
-  <TD COLSPAN=6>
-    <% include('/elements/input-date-field.html',{
-                'name'      => 'contract_end',
-                'format'    => $date_format,
-                'value'     => '',
-                'noinit'    => 1,
-                }) %>
-  </TD>
-</TR>
-
 </TABLE>
 
-<% include( '/elements/standardize_locations.html',
-            'form'       => "OrderPkgForm",
-            'onlyship'   => 1,
-            'no_company' => 1,
-            'callback'   => 'document.OrderPkgForm.submit();',
-          )
-%>
-
 <BR>
-<INPUT NAME="submitButton" TYPE="button" VALUE="Order Package" onClick = "this.disabled=true; standardize_locations();" <% $pkgpart ? '' : 'DISABLED' %>>
+<INPUT NAME="submit" TYPE="submit" VALUE="Order Package" <% $pkgpart ? '' : 'DISABLED' %>>
 
 </FORM>
 </BODY>
index 6f2c238..4ab15fd 100755 (executable)
@@ -1,8 +1,6 @@
 %if ( $error ) {
 %  errorpage($error);
-%} elsif ( $pkgnum ) {
-<% $cgi->redirect(popurl(2)."search/cust_pkg_svc.html?svcpart=$svcpart;pkgnum=$pkgnum") %>
-%} else { # $custnum should always exist
+%} else {
 <% $cgi->redirect(popurl(2)."view/cust_main.cgi?$custnum") %>
 %}
 <%init>
@@ -11,28 +9,18 @@ die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Unprovision customer service');
 
 #untaint svcnum
-my @svcnums;
-my ($pkgnum, $svcpart, $custnum);
-if( $cgi->param('svcnum') ) {
-  @svcnums = grep { $_ } map { /^(\d+)$/ && $1 } $cgi->param('svcnum');
-  $pkgnum = $cgi->param('pkgnum');
-  $svcpart = $cgi->param('svcpart');
-  $custnum = $cgi->param('custnum');
-}
-else {
-  @svcnums = map { /^(\d+)$/ && $1 } $cgi->keywords;
-}
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/;
+my $svcnum = $1;
 
-my $error = '';
-foreach my $svcnum (@svcnums) {
+#my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
+#die "Unknown svcnum!" unless $svc_acct;
 
-  my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
-  die "Unknown svcnum!" unless $cust_svc;
+my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+die "Unknown svcnum!" unless $cust_svc;
 
-  $custnum ||= $cust_svc->cust_pkg->custnum;
+my $custnum = $cust_svc->cust_pkg->custnum;
 
-  $error .= $cust_svc->cancel;
-
-}
+my $error = $cust_svc->cancel;
 
 </%init>
index d0627cd..3b9e142 100644 (file)
@@ -28,7 +28,6 @@ if ( $sub eq 'address_standardize' ) {
     } );
 
     foreach my $pre ( '', 'ship_' ) {
-      next unless ($pre || !$arg{onlyship});
 
       my($zip5, $zip4) = split('-',$arg{$pre.'zip'});
 
index 481bea2..615a4bb 100644 (file)
@@ -22,9 +22,7 @@
 % } elsif ( $sub eq 'smart_search' ) {
 %
 %   my $string = $cgi->param('arg');
-%   my @cust_main = smart_search( 'search' => $string,
-%                                 'no_fuzzy_on_exact' => 1, #pref?
-%                               );
+%   my @cust_main = smart_search( 'search' => $string );
 %   my $return = [ map [ $_->custnum, $_->name ], @cust_main ];
 %     
 <% objToJson($return) %>
index 5544ff5..702dc1b 100644 (file)
@@ -147,7 +147,7 @@ foreach my $param ( grep /^termpart\d+status$/, $cgi->param ) {
 }
 
 ###
-# src/dest/charged_party/svcnum
+# src/dest/charged_party
 ###
 
 my $phonenum = qr/^\s*([\d\-\+\ ]+)\s*$/;
@@ -175,32 +175,27 @@ if ( $cgi->param('dcontext') =~ /^\s*(.+)\s*$/ ) {
   push @search, "dcontext = '$dcontext'";
 }
 
-if ( $cgi->param('charged_party') ) {
+if ( $cgi->param('charged_party') =~ $phonenum ) {
+  ( my $charged_party = $1 ) =~ s/$x//g;
+  #$hashref->{'charged_party'} = $charged_party;
+  #push @search, "charged_party = '$charged_party'";
+  #XXX countrycode
 
-  my @cp = map { $_, "1$_" }
-             split(/\s*,\s*/, $cgi->param('charged_party') );
-  
-  my $search = 'charged_party IN ('. join(',', map dbh->quote($_), @cp). ')';
+  my $search = " (    charged_party IN ('$charged_party', '1$charged_party') )";
 
   push @search,  $search;
   push @qsearch, $search;
 }
 
-if ( $cgi->param('charged_party_or_src') ) {
+if ( $cgi->param('charged_party_or_src') =~ $phonenum ) {
+  ( my $charged_party = $1 ) =~ s/$x//g;
+  #$hashref->{'charged_party'} = $charged_party;
+  #push @search, "charged_party = '$charged_party'";
+  #XXX countrycode
 
-  my @cp = map { $_, "1$_" }
-             split(/\s*,\s*/, $cgi->param('charged_party_or_src') );
-  my $in = join(',', map dbh->quote($_), @cp);
+  my $search = " (    charged_party IN ('$charged_party', '1$charged_party')
+                   OR src           IN ('$charged_party', '1$charged_party') )";
 
-  my $search = "( charged_party IN ($in) OR src IN ($in) )";
-
-  push @search,  $search;
-  push @qsearch, $search;
-}
-
-if ( $cgi->param('svcnum') =~ /^([\d, ]+)$/ ) {
-  my $svcnum = $1;
-  my $search = "svcnum IN ($svcnum)";
   push @search,  $search;
   push @qsearch, $search;
 }
index f2a5ccd..98a1da9 100644 (file)
@@ -502,29 +502,26 @@ if ( $cgi->param('nottax') ) {
 } elsif ( $cgi->param('istax') ) {
 
   #false laziness w/report_tax.cgi $taxfromwhere
-  if ( scalar( grep( /locationtaxid/, $cgi->param ) ) ||
-            $cgi->param('iscredit') eq 'rate') {
-
-    $join_pkg .=
-      ' LEFT JOIN cust_bill_pkg_tax_rate_location USING ( billpkgnum ) '.
-      ' LEFT JOIN tax_rate_location USING ( taxratelocationnum ) ';
-
-  } elsif ( $conf->exists('tax-pkg_address') ) {
-
+  if ( $conf->exists('tax-pkg_address') ) {
     $join_pkg .= ' LEFT JOIN cust_bill_pkg_tax_location USING ( billpkgnum )
                    LEFT JOIN cust_location              USING ( locationnum ) ';
 
     #quelle kludge, somewhat false laziness w/report_tax.cgi
     s/cust_pkg\.locationnum/cust_bill_pkg_tax_location.locationnum/g for @where;
+  } elsif ( scalar( grep( /locationtaxid/, $cgi->param ) ) ||
+            $cgi->param('iscredit') eq 'rate') {
+    $join_pkg .=
+      ' LEFT JOIN cust_bill_pkg_tax_rate_location USING ( billpkgnum ) '.
+      ' LEFT JOIN tax_rate_location USING ( taxratelocationnum ) ';
   }
 
   if ( $cgi->param('iscredit') ) {
     $join_pkg .= ' JOIN cust_credit_bill_pkg USING ( billpkgnum';
-    if ( $cgi->param('iscredit') eq 'rate' ) {
-      $join_pkg .= ', billpkgtaxratelocationnum )';
-    } elsif ( $conf->exists('tax-pkg_address') ) {
+    if ( $conf->exists('tax-pkg_address') ) {
       $join_pkg .= ', billpkgtaxlocationnum )';
       push @where, "billpkgtaxratelocationnum IS NULL";
+    } elsif ( $cgi->param('iscredit') eq 'rate' ) {
+      $join_pkg .= ', billpkgtaxratelocationnum )';
     } else {
       $join_pkg .= ' )';
       push @where, "billpkgtaxratelocationnum IS NULL";
index 8fbf636..93f960f 100755 (executable)
 %  if ( $cgi->param('search_cust') ) {
 %    $sortby = \*company_sort;
 %    $orderby = "ORDER BY LOWER(company || ' ' || last || ' ' || first )";
-%    push @cust_main, smart_search( 'search' => $cgi->param('search_cust'),
-%                                   'no_fuzzy_on_exact' => 1, #pref?
-%                                 );
+%    push @cust_main, smart_search( 'search' => $cgi->param('search_cust') );
 %  }
 %
 %  @cust_main = grep { $_->ncancelled_pkgs || ! $_->all_pkgs } @cust_main
index 04ecf89..b6db4e4 100755 (executable)
@@ -44,10 +44,8 @@ my %search_hash = ();
 
 #scalars
 my @scalars = qw (
-  agentnum status address paydate_year paydate_month invoice_terms
-  no_censustract with_geocode custbatch usernum
-  cancelled_pkgs
-  cust_fields flattened_pkgs
+  agentnum status cancelled_pkgs cust_fields flattened_pkgs custbatch usernum
+  no_censustract paydate_year paydate_month invoice_terms
 );
 
 for my $param ( @scalars ) {
@@ -56,7 +54,7 @@ for my $param ( @scalars ) {
 }
 
 #lists
-for my $param (qw( classnum payby tagnum )) {
+for my $param (qw( classnum payby )) {
   $search_hash{$param} = [ $cgi->param($param) ];
 }
 
index 8b73508..f46e08a 100755 (executable)
@@ -19,7 +19,7 @@ my %statusaction = (
   'new'        => 'delete',
   'pending'    => 'complete',
   #'authorized' => '',
-  'captured'   => 'capture',
+  #'captured'   => '',
   #'declined'   => '',
   #wouldn't need to take action on a done state#'done'
 );
index 207e4f6..da4371f 100755 (executable)
@@ -19,7 +19,6 @@
                                      'Adjourn',
                                      'Susp.',
                                      'Expire',
-                                     'Contract end',
                                      'Cancel',
                                      'Reason',
                                      FS::UI::Web::cust_header(
@@ -60,7 +59,7 @@
                     #sub { time2str('%b %d %Y', shift->expire); },
                     #sub { time2str('%b %d %Y', shift->get('cancel')); },
                     ( map { time_or_blank($_) }
-          qw( setup last_bill bill adjourn susp expire contract_end cancel ) ),
+                          qw( setup last_bill bill adjourn susp expire cancel ) ),
 
                     sub { my $self = shift;
                           my $return = '';
@@ -207,7 +206,7 @@ my %disable = (
   ''                => {},
 );
 
-foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end cancel active )) {
+foreach my $field (qw( setup last_bill bill adjourn susp expire cancel active )) {
 
   my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field);
 
diff --git a/httemplate/search/cust_pkg_svc.html b/httemplate/search/cust_pkg_svc.html
deleted file mode 100644 (file)
index 4f27d66..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<% include( 'elements/search.html',
-              'title'       => $part_svc->svc.' services in package #'.$pkgnum,
-             'name'        => 'services',
-              'html_form'   => $html_form,
-             'query'       => $sql_query,
-             'count_query' => $count_query,
-             'redirect'    => $link,
-             'header'      => [ '#',
-                                 'Service',
-                                 '', #checkboxes
-                              ],
-             'fields'      => [ 'svcnum',
-                                 sub {
-                                   ($_[0]->label)[1]
-                                 },
-                                 sub {
-                                   $areboxes = 1;
-                                   '<INPUT TYPE="checkbox" NAME="svcnum" VALUE='.$_[0]->svcnum.'>'
-                                 },
-                              ],
-             'links'       => [ $link,
-                                $link,
-                                 '',
-                              ],
-              'align' => 'rrlc',
-              'color' => [ 
-                           ('')x4,
-                         ],
-              'style' => [ 
-                           ('')x4,
-                         ],
-              'html_foot' => sub { $areboxes ? $html_foot : '' }
-          )
-%>
-<%init>
-
-die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right('List services');
-
-my $pkgnum = $cgi->param('pkgnum');
-$pkgnum =~ /^(\d+)$/ or die "invalid pkgnum: $pkgnum";
-my @extra_sql = ( "cust_svc.pkgnum = $pkgnum" );
-
-my $svcpart = $cgi->param('svcpart');
-$svcpart =~ /^(\d+)$/ or die "invalid svcpart: $svcpart";
-push @extra_sql, "cust_svc.svcpart = $svcpart";
-my $part_svc = qsearchs('part_svc', {svcpart => $svcpart});
-my $svcdb = $part_svc->svcdb;
-
-my $orderby = 'ORDER BY svcnum'; #others?
-
-my $addl_from = " LEFT JOIN part_svc USING (svcpart)
-LEFT JOIN cust_pkg USING (pkgnum)
-LEFT JOIN cust_main USING (custnum)
-INNER JOIN $svcdb USING (svcnum)";
-
-my $search_string;
-if ( length( $cgi->param('search_svc') ) ) {
-
-  $search_string = $cgi->param('search_svc');
-  $search_string =~ s/(^\s+|\s+$)//;
-  push @extra_sql, "FS::$svcdb"->search_sql($search_string);
-
-}
-
-#here is the agent virtualization
-push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql( 
-                   'null_right' => 'View/link unlinked services'
-                 );
-
-my $extra_sql = ' WHERE '. join(' AND ', @extra_sql );
-
-my $sql_query = {
-  'select'     => join(', ',
-                    'cust_svc.*',
-                   'part_svc.svc',
-                  ),
-  'table'      => 'cust_svc',
-  'addl_from'  => $addl_from,
-  'hashref'    => {},
-  'extra_sql'  => "$extra_sql $orderby",
-};
-
-#warn Dumper($sql_query)."\n";
-
-my $count_query = "SELECT COUNT(*) FROM cust_svc $addl_from $extra_sql";
-
-my $link = sub {
-  my $cust_svc = shift;
-  my $url = svc_url(
-    'm'        => $m,
-    'action'   => 'view',
-    'svcdb'    => $svcdb,
-    'query'     => '',
-  );
-  [ $url, 'svcnum' ];
-};
-
-my $html_form = qq!
-<SCRIPT TYPE="text/javascript">
-function areyousure(obj) {
-  return confirm('Permanently delete the selected services?');
-}
-</SCRIPT>
-<FORM METHOD="POST" ACTION="${p}misc/unprovision.cgi" onsubmit="return areyousure()">!; 
-
-my $areboxes = 0;
-
-my $html_foot = qq!
-<BR>
-<INPUT TYPE="submit" NAME="submit" VALUE="Unprovision selected">
-<INPUT TYPE="hidden" NAME="pkgnum" VALUE=$pkgnum>
-<INPUT TYPE="hidden" NAME="svcpart" VALUE=$svcpart>
-</FORM>!;
-
-
-</%init>
index 866606c..a50e4db 100644 (file)
   <TR>
     <TD ALIGN="right">Charged Party #: </TD>
     <TD>
-      <INPUT TYPE="text" NAME="charged_party" VALUE="<% join(',', @charged_party) |h %>">
-    </TD>
-  </TR>
-
-  <TR>
-    <TD ALIGN="right">Charged Party or Source #: </TD>
-    <TD>
-      <INPUT TYPE="text" NAME="charged_party_or_src" VALUE="<% join(',', @charged_party_or_src ) |h %>" >
-    </TD>
-  </TR>
-
-  <TR>
-    <TD ALIGN="right">Freeside service #: </TD>
-    <TD>
-      <INPUT TYPE="text" NAME="svcnum" VALUE="<% join(',', @svcnum ) %>" >
+      <INPUT TYPE="text" NAME="charged_party">
     </TD>
   </TR>
 
@@ -159,72 +145,4 @@ my $names_list = [ map {
                    @fields
                  ];
 
-my @charged_party = ();
-my @charged_party_or_src = ();
-my @svcnum = ();
-if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
-  my $custnum = $1;
-
-  my $cust_main = qsearchs( {
-    'table'     => 'cust_main',
-    'hashref'   => { 'custnum' => $custnum },
-    'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
-  });
-  die "Customer not found!" unless $cust_main;
-
-  #historical?
-  foreach my $cust_pkg ( $cust_main->ncancelled_pkgs ) {
-
-    my @voip_pkgs =
-      grep { $_->plan eq 'voip_cdr' } $cust_pkg->part_pkg->self_and_bill_linked;
-    if ( scalar(@voip_pkgs) > 1 ) { 
-      die "multiple voip_cdr packages bundled\n";
-    } elsif ( !@voip_pkgs ) {
-      next;
-    }
-    my $voip_pkg = @voip_pkgs[0];
-
-    my $cdr_svc_method = $voip_pkg->option('cdr_svc_method')
-                         || 'svc_phone.phonenum';
-
-    my @cust_svc = $cust_pkg->cust_svc; #historical?
-
-    if ( $cdr_svc_method eq 'svc_phone.phonenum' ) {
-
-      my @svc_phone = map $_->svc_x,
-                        grep { $_->part_svc->svcdb eq 'svc_phone' } @cust_svc;
-
-      my @numbers = map {
-                          my $number = $_->phonenum;
-                          $number = $_->countrycode. $number
-                            unless $_->countrycode eq '1';
-                          $number;
-                        }
-                      @svc_phone;
-
-      if ( $voip_pkg->option('disable_src') ) {
-        push @charged_party, @numbers;
-      } else {
-        push @charged_party_or_src, @numbers;
-      }
-
-    } elsif ( $cdr_svc_method eq 'svc_pbx.title' ) {
-      my @svc_pbx = map $_->svc_x,
-                      grep { $_->part_svc->svcdb eq 'svc_pbx' } @cust_svc;
-      push @charged_party, map $_->title, @svc_pbx;
-    } elsif ( $cdr_svc_method eq 'svc_pbx.svcnum' ) {
-      my @cust_svc_pbx = grep { $_->part_svc->svcdb eq 'svc_pbx' } @cust_svc;
-      push @svcnum, map $_->svcnum, @cust_svc_pbx;
-    }
-
-  }
-
-  die "No CDR packages for customer $custnum\n"
-    unless @charged_party || @charged_party_or_src || @svcnum;
-
-  #die "Multiple matching metods for customer $custnum\n"
-  #  if #there's more than one
-
-}
-
 </%init>
index d6be4fb..eb1a662 100755 (executable)
               )
     %>
 
-    <TR>
-      <TD ALIGN="right" VALIGN="center">Address</TD>
-      <TD><INPUT TYPE="text" NAME="address" SIZE=54></TD>
-    </TR>
-
 %   foreach my $field (qw( signupdate )) {
 
       <TR>
 
 %   }
 
-    <% include( '/elements/tr-select-cust_tag.html',
-                 'cgi'          => $cgi,
-                 'is_report'    => 1,
-                  'multiple'     => 1,
-                  'all_selected' => 1,
-              )
-    %>
-
     <% include( '/elements/tr-select-payby.html',
                   'payby_type'   => 'cust',
                   'multiple'     => 1,
         <TD><INPUT TYPE="checkbox" NAME="cancelled_pkgs"></TD>
     </TR>
 
+%   if ( $conf->exists('cust_main-require_censustract') ) {
+
     <TR>
       <TD ALIGN="right" VALIGN="center">Without census tract</TD>
         <TD><INPUT TYPE="checkbox" NAME="no_censustract"></TD>
     </TR>
 
-%   if ( $conf->exists('enable_taxproducts') ) {
-
-      <TR>
-        <TD ALIGN="right" VALIGN="center">With hardcoded tax location</TD>
-          <TD><INPUT TYPE="checkbox" NAME="with_geocode"></TD>
-      </TR>
-
 %   }
 
     <TR>
index 289fec4..58fcf61 100755 (executable)
@@ -89,7 +89,7 @@
 
 %   }
 
-%   foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end cancel )) {
+%   foreach my $field (qw( setup last_bill bill adjourn susp expire cancel )) {
 
       <TR>
         <TD ALIGN="right" VALIGN="center"><% $label{$field} %></TD>
@@ -181,7 +181,6 @@ my %label = (
   'adjourn'   => 'Adjourns',
   'susp'      => 'Suspended',
   'expire'    => 'Expires',
-  'contract_end' => 'Contract ends',
   'cancel'    => 'Cancelled',
 );
 
index c3ddd66..1407d9e 100755 (executable)
@@ -262,13 +262,13 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
   }
 
   $cgi->param('username') =~ /^([\w\-\.\&]+)$/; #untaint username_text
-  my $username = lc($1);
+  my $username = $1;
 
-  push @username_sql, "LOWER(username) LIKE '$username'"
+  push @username_sql, "username ILIKE '$username'"
     if $username_type{'Exact'}
     || $username_type{'Fuzzy'};
 
-  push @username_sql, "LOWER(username) LIKE '\%$username\%'"
+  push @username_sql, "username ILIKE '\%$username\%'"
     if $username_type{'Substring'}
     || $username_type{'All'};
 
index 0928d04..ce8d96a 100755 (executable)
@@ -26,7 +26,7 @@
 
 % if ( $cust_bill->owed > 0
 %      && scalar( grep $payby{$_}, qw(BILL CASH WEST MCRD) )
-%      && $curuser->access_right(['Post payment', 'Post check payment', 'Post cash payment'])
+%      && $curuser->access_right('Post payment')
 %      && ! $conf->exists('pkg-balances')
 %    )
 % {
 
       Post 
 
-%     if ( $payby{'BILL'} && $curuser->access_right(['Post payment', 'Post check payment']) ) { 
+%     if ( $payby{'BILL'} ) { 
           <% $s++ ? ' | ' : '' %>
           <A HREF="<% $p %>edit/cust_pay.cgi?payby=BILL;invnum=<% $invnum %>">check</A>
 %     } 
 
-%     if ( $payby{'CASH'} && $curuser->access_right(['Post payment', 'Post cash payment']) ) { 
+%     if ( $payby{'CASH'} ) { 
           <% $s++ ? ' | ' : '' %>
           <A HREF="<% $p %>edit/cust_pay.cgi?payby=CASH;invnum=<% $invnum %>">cash</A>
 %     } 
 
-%     if ( $payby{'WEST'} && $curuser->access_right(['Post payment']) ) { 
+%     if ( $payby{'WEST'} ) { 
           <% $s++ ? ' | ' : '' %>
           <A HREF="<% $p %>edit/cust_pay.cgi?payby=WEST;invnum=<% $invnum %>">Western Union</A>
 %     } 
 
-%     if ( $payby{'MCRD'} && $curuser->access_right(['Post payment']) ) { 
+%     if ( $payby{'MCRD'} ) { 
           <% $s++ ? ' | ' : '' %>
           <A HREF="<% $p %>edit/cust_pay.cgi?payby=MCRD;invnum=<% $invnum %>">manual credit card</A>
 %     } 
@@ -117,14 +117,13 @@ if ( $query =~ /^((.+)-)?(\d+)$/ ) {
   $notice_name = $cgi->param('notice_name');
 }
 
-my $conf = new FS::Conf;
-
 my %opt = (
-  'unsquelch_cdr' => $conf->exists('voip-cdr_email'),
-  'template'      => $template,
-  'notice_name'   => $notice_name,
+  'template'    => $template,
+  'notice_name' => $notice_name,
 );
 
+my $conf = new FS::Conf;
+
 my @payby =  grep /\w/, $conf->config('payby');
 #@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
 @payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
index 0f9c1e2..b4a6170 100755 (executable)
@@ -64,22 +64,6 @@ function areyousure(href, message) {
 
 % }
 
-% if ( $curuser->access_right('Merge customer') ) {
-
-  <% include( '/elements/popup_link-cust_main.html',
-              { 'action'      => $p. 'misc/merge_cust.html',
-                'label'       => 'Merge&nbsp;this&nbsp;customer',
-                'actionlabel' => 'Merge customer',
-                #'color'       => '#ff0000',
-                'cust_main'   => $cust_main,
-                'width'       => 480,
-                'height'      => 192,
-              }
-            )
-  %> | 
-
-% } 
-
 % if ( $conf->exists('deletecustomers')
 %        && $curuser->access_right('Delete customer')
 %      ) {
index 014ddab..dd19523 100644 (file)
@@ -132,7 +132,7 @@ Billing information
 
 <TR>
   <TD ALIGN="right">Attention</TD>
-  <TD BGCOLOR="#ffffff"><% $cust_main->payname |h %></TD>
+  <TD BGCOLOR="#ffffff"><% $cust_main->payname %></TD>
 </TR>
 % } elsif ( $cust_main->payby eq 'COMP' ) { 
 
index e91af54..e88c02e 100644 (file)
@@ -10,7 +10,7 @@
 <TR>
   <TD ALIGN="right">Contact name</TD>
   <TD COLSPAN=5 BGCOLOR="#ffffff">
-    <% $cust_main->get("${pre}last"). ', '. $cust_main->get("${pre}first") |h %>
+    <% $cust_main->get("${pre}last"). ', '. $cust_main->get("${pre}first") %>
   </TD>
 % if ( $which eq '' && $conf->exists('show_ss') ) { 
     <TD ALIGN="right">SS#</TD>
 </TR>
 <TR>
   <TD ALIGN="right">Company</TD>
-  <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") |h %></TD>
+  <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") %></TD>
 </TR>
 <TR>
   <TD ALIGN="right">Address</TD>
-  <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address1") |h %></TD>
+  <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address1") %></TD>
 </TR>
 
 % if ( $cust_main->get("${pre}address2") ) { 
 
   <TR>
     <TD ALIGN="right"><% $address2_label %></TD>
-    <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address2") |h %></TD>
+    <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address2") %></TD>
   </TR>
 
 % } 
 
 <TR>
   <TD ALIGN="right">City</TD>
-  <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}city") |h %></TD>
+  <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}city") %></TD>
 % if ( $cust_main->get("${pre}county") ) {
     <TD ALIGN="right">County</TD>
-    <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}county") |h %></TD>
+    <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}county") %></TD>
 % }
   <TD ALIGN="right">State</TD>
-  <TD BGCOLOR="#ffffff"><% state_label( $cust_main->get("${pre}state"), $cust_main->get("${pre}country") ) |h %></TD>
+  <TD BGCOLOR="#ffffff"><% state_label( $cust_main->get("${pre}state"), $cust_main->get("${pre}country") ) %></TD>
   <TD ALIGN="right">Zip</TD>
   <TD BGCOLOR="#ffffff"><% $cust_main->get("${pre}zip") %></TD>
 </TR>
index 660d0ef..811ac3c 100755 (executable)
@@ -57,9 +57,7 @@ Current packages
     <TD ALIGN="right">
       <A HREF="<%$p%>search/report_cust_pkg.html?custnum=<% $cust_main->custnum %>">Package reports</A><BR>
       Service reports:
-        <A HREF="<%$p%>search/report_svc_acct.html?custnum=<% $cust_main->custnum %>">accounts</A><BR>
-      Usage reports:
-        <A HREF="<%$p%>search/report_cdr.html?custnum=<% $cust_main->custnum %>">CDRs</A>
+        <A HREF="<%$p%>search/report_svc_acct.html?custnum=<% $cust_main->custnum %>">accounts</A>
     </TD>
   </TR>
 
@@ -163,7 +161,6 @@ my %conf_opt = (
   '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'),
-  'cust_pkg-large_pkg_size'   => $conf->config('cust_pkg-large_pkg_size'),
 );
 
 #subroutines
index 512efcc..6e30922 100644 (file)
@@ -4,40 +4,12 @@
 
   <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
     <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
-    <SCRIPT TYPE="text/javascript">
-function clearhint_search_cust_svc(obj, str) {
-  if (obj.value == str) obj.value = '';
-}
-    </SCRIPT>
 
 %  #foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) {
 %  foreach my $part_svc ( $cust_pkg->part_svc ) {
 
-%    if ( $opt{'cust_pkg-large_pkg_size'} > 0 and
-%         $opt{'cust_pkg-large_pkg_size'} <= $cust_pkg->num_svcs ) {
-%      # summarize
-      <TR>
-        <TD ALIGN="center" VALIGN="top">
-%       my $href="${p}search/cust_pkg_svc.html?svcpart=".$part_svc->svcpart.
-%          ";pkgnum=".$cust_pkg->pkgnum;
-        <A HREF="<% $href %>"><% $part_svc->svc %></A>&nbsp;
-        <A HREF="<% $href %>"><B>(view all <% $cust_pkg->num_svcs %>)</B></A>
-%     my $hint = $hints{$part_svc->svcdb};
-%     if ( $hint ) {
-        <BR>
-        <FORM name="svcpart<%$part_svc->svcpart%>_search" STYLE="display:inline"
-        ACTION="<%$p%>search/cust_pkg_svc.html" METHOD="GET">
-        <INPUT TYPE="hidden" NAME="svcpart" VALUE="<%$part_svc->svcpart%>">
-        <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%$cust_pkg->pkgnum%>">
-        <INPUT TYPE="text" NAME="search_svc"
-        onfocus="clearhint_search_cust_svc(this, '<%$hint%>')" VALUE="<%$hint%>">
-        <INPUT TYPE="submit" VALUE="Search"></FORM>
-%     } #$hint
-        </TD>
-      </TR>
-%    }
-%    else {
-%      foreach my $cust_svc ( @{ $part_svc->cust_pkg_svc } ) {
+%    #foreach my $service (@{$svcpart->{services}}) {
+%    foreach my $cust_svc ( @{ $part_svc->cust_pkg_svc } ) {
 
       <TR>
         <TD ALIGN="right" VALIGN="top"><% FS::UI::Web::svc_link($m, $part_svc, $cust_svc) %></TD>
@@ -93,8 +65,7 @@ function clearhint_search_cust_svc(obj, str) {
 
           </TD>
         </TR>
-%     } #foreach $cust_svc
-%   }
+%   } 
 
 %   if (    ! $cust_pkg->get('cancel')
 %        && $curuser->access_right('Provision customer service') 
@@ -166,13 +137,4 @@ sub svc_unprovision_link {
   qq!', 'Permanently unprovision and delete this service?')">Unprovision</A>!;
 }
 
-my %hints = (
-svc_acct      => '(user or email)',
-svc_domain    => '(domain)',
-svc_broadband => '(ip or mac)',
-svc_forward   => '(email)',
-svc_phone     => '(phone)',
-svc_pbx       => '(phone)',
-);
-
 </%init>
index c05cd5a..a686843 100644 (file)
 
     <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
     <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
-%   if ( $part_pkg->option('suspend_bill') ) {
-      <% pkg_status_row_if( $cust_pkg, 'Next&nbsp;bill', 'bill', %opt, curuser=>$curuser ) %>
-%   }
+%   # pkg_status_row($cust_pkg, 'Next bill', 'bill', %opt)
     <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
-    <% pkg_status_row_if( $cust_pkg, 'Contract ends', 'contract_end', %opt ) %>
 
     <TR>
       <TD COLSPAN=<%$colspan%>>
       <% pkg_status_row_if($cust_pkg, 'Will automatically suspend by', 'autosuspend', %opt) %>
       <% pkg_status_row_if( $cust_pkg, 'Will suspend on', 'adjourn', %opt, curuser=>$curuser ) %>
       <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
-      <% pkg_status_row_if( $cust_pkg, 'Contract ends', 'contract_end', %opt ) %>
 
 %     if ( $part_pkg->freq ) { 
 
index 046899e..b84883a 100644 (file)
@@ -1,7 +1,7 @@
 %# payment links
 
 % my $s = 0;
-% if ( $payby{'BILL'} && $curuser->access_right(['Post payment', 'Post check payment' ]) ) { 
+% if ( $payby{'BILL'} && $curuser->access_right('Post payment') ) { 
   <% $s++ ? ' | ' : '' %>
   <% include('/elements/popup_link-cust_main.html',
                'label'       => 'Enter check payment',
@@ -14,7 +14,7 @@
   %>
 % } 
 
-% if ( $payby{'CASH'} && $curuser->access_right(['Post payment', 'Post cash payment']) ) { 
+% if ( $payby{'CASH'} && $curuser->access_right('Post payment') ) { 
   <% $s++ ? ' | ' : '' %>
   <% include('/elements/popup_link-cust_main.html',
                'label'       => 'Enter cash payment',
@@ -33,7 +33,7 @@
 % } 
 
 % if ( ( $payby{'CARD'} || $payby{'DCRD'} )
-%        && $curuser->access_right(['Process payment', 'Process credit card payment'])
+%        && $curuser->access_right('Process payment')
 %        && ! $cust_main->is_encrypted($cust_main->payinfo)
 %      ) {
   <% $s++ ? ' | ' : '' %>
@@ -41,7 +41,7 @@
 % } 
 
 % if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
-%        && $curuser->access_right(['Process payment', 'Process Echeck payment'])
+%        && $curuser->access_right('Process payment')
 %        && ! $cust_main->is_encrypted($cust_main->payinfo)
 %      ) {
   <% $s++ ? ' | ' : '' %>
@@ -73,7 +73,7 @@
 %# refund links
 
 % $s = 0;
-% if ( $payby{'BILL'} && $curuser->access_right(['Post refund', 'Post check refund']) ) { 
+% if ( $payby{'BILL'} && $curuser->access_right('Post refund') ) { 
   <% $s++ ? ' | ' : '' %>
   <% include('/elements/popup_link-cust_main.html',
                'label'       => 'Enter check refund',
@@ -86,7 +86,7 @@
   %>
 % } 
 
-% if ( $payby{'CASH'} && $curuser->access_right(['Post refund', 'Post cash refund']) ) { 
+% if ( $payby{'CASH'} && $curuser->access_right('Post refund') ) { 
   <% $s++ ? ' | ' : '' %>
   <% include('/elements/popup_link-cust_main.html',
                'label'       => 'Enter cash refund',
@@ -412,16 +412,6 @@ foreach my $cust_pay ($cust_main->cust_pay) {
   };
 }
 
-#pending payments 
-foreach my $cust_pay_pending ($cust_main->cust_pay_pending) {
-  push @history, {
-    'date'    => $cust_pay_pending->_date,
-    'desc'    => include('payment_history/pending_payment.html', $cust_pay_pending, %opt ),
-    'void_payment' => $cust_pay_pending->paid, 
-  };
-}
-
-
 #voided payments
 foreach my $cust_pay_void ($cust_main->cust_pay_void) {
   push @history, {
index e745864..6ec9fdb 100644 (file)
@@ -155,14 +155,11 @@ my $view =
 
 my $refund = '';
 my $refund_days = $opt{'card_refund-days'} || 120;
-my @rights = ('Refund payment');
-push @rights, 'Refund credit card payment' if $payby eq 'CARD';
-push @rights, 'Refund Echeck payment' if $payby eq 'CHEK';
 if (    $cust_pay->closed !~ /^Y/i
      && $cust_pay->payby =~ /^(CARD|CHEK)$/
      && time-$cust_pay->_date < $refund_days*86400
      && $cust_pay->unrefunded > 0
-     && $curuser->access_right(\@rights)
+     && $curuser->access_right('Refund payment')
 ) {
   $refund = qq! (<A HREF="${p}edit/cust_refund.cgi?payby=$1;!.
             qq!paynum=!. $cust_pay->paynum. '"'.
diff --git a/httemplate/view/cust_main/payment_history/pending_payment.html b/httemplate/view/cust_main/payment_history/pending_payment.html
deleted file mode 100644 (file)
index 40805b1..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<b><font size="+1" color="#FF0000">Pending payment </font></b> <% "$info $status ($link)" %>
-<%init>
-
-my( $cust_pay_pending, %opt ) = @_;
-
-my $conf = new FS::Conf;
-
-my $curuser = $FS::CurrentUser::CurrentUser;
-
-my $payby = $cust_pay_pending->payby;
-
-my $payinfo;
-if ( $payby eq 'CARD' ) {
-  $payinfo = $cust_pay_pending->paymask;
-} elsif ( $payby eq 'CHEK' ) {
-  my( $account, $aba ) = split('@', $cust_pay_pending->paymask );
-  $payinfo = "ABA $aba, Acct #$account";
-} else {
-  $payinfo = $cust_pay_pending->payinfo;
-}
-
-my $target = "$payby$payinfo";
-$payby =~ s/^BILL$/Check #/ if $payinfo;
-$payby =~ s/^CHEK$/Electronic check /;
-$payby =~ s/^PREP$/Prepaid card /;
-$payby =~ s/^CARD$/Credit card #/; 
-$payby =~ s/^COMP$/Complimentary by /; 
-$payby =~ s/^CASH$/Cash/;
-$payby =~ s/^WEST$/Western Union/;
-$payby =~ s/^MCRD$/Manual credit card/;
-$payby =~ s/^BILL$//;
-my $info = $payby ? "($payby$payinfo)" : '';
-
-my %statusaction = (
-  'new'        => 'delete',
-  'pending'    => 'complete',
-  'captured'   => 'capture',
-);
-
-my $edit_pending =
-  $FS::CurrentUser::CurrentUser->access_right('Edit customer pending payments');
-
-my $status = "Status: ".$cust_pay_pending->status;
-
-my $action = $statusaction{$cust_pay_pending->status};
-
-my $link = "";
-if ( $action && $edit_pending ) {
-    $link = include('/elements/popup_link.html',
-              'action' => $p. 'edit/cust_pay_pending.html'.
-                            '?paypendingnum='. $cust_pay_pending->paypendingnum.
-                            ";action=$action",
-              'label'  => $action,
-              'color'  => '#ff0000',
-              'width'  => 655,
-              'height' => ( $action eq 'delete' ? 480 : 575 ),
-              'actionlabel' => ucfirst($action). ' pending payment',
-           );
-}
-
-</%init>
index 5d7f60c..be68ff0 100644 (file)
@@ -1,10 +1,6 @@
-<DEL>Payment <% $info %> by <% $cust_pay_void->otaker %></DEL>
+<DEL>Payment <% $info %></DEL>
 <I>voided <% time2str($date_format, $cust_pay_void->void_date) %>
-% my $void_user = $cust_pay_void->void_access_user;
-% if ($void_user) {
-    by <% $void_user->username %></I>
-% }
-<% $unvoid %>
+by <% $cust_pay_void->otaker %></I><% $unvoid %>
 <%init>
 
 my( $cust_pay_void, %opt ) = @_;
index 1408b3d..2f23d9e 100644 (file)
@@ -2,10 +2,7 @@
 
   <% include('/elements/header-popup.html', "$thing Receipt" ) %>
 
-  <div align="center">
-    <A HREF="javascript:self.parent.location = '<% $pr_link %>'">Print</A> | 
-    <A HREF="javascript:self.location = '<% $email_link %>'">Re-email</A>
-  </div><BR>
+  <CENTER><A HREF="javascript:self.parent.location = '<% $pr_link %>'">Print</A></CENTER><BR>
 
 % } elsif ( $link eq 'print' ) { 
 
      )
   %>
   <BR><BR>
-% } elsif ( $link eq 'email' ) {
-%  if ( $email_error ) {
-      <% include('/elements/header-popup.html', "Error re-emailing receipt: $email_error" ) %>
-%  } else {
-      <% include('/elements/header-popup.html', "Re-emailed receipt" ) %>
-%  }
+
 % } else { 
 
   <% include('/elements/header.html', "$thing Receipt", menubar(
@@ -34,7 +26,7 @@
 
 % }
 
-% unless ($link =~ /^(popup|email)$/ ) {
+% unless ($link eq 'popup' ) {
   <% include('/elements/small_custview.html',
                $custnum,
                scalar($conf->config('countrydefault')),
     window.print();
   </SCRIPT>
 
-% } elsif ( $link eq 'email' ) {
-
-    <SCRIPT TYPE="text/javascript">
-      window.top.location.reload();
-    </SCRIPT>
-
 % }
-% if ( $link =~ /^(popup|print|email)$/ ) { 
+
+% if ( $link =~ /^(popup|print)$/ ) { 
     </BODY>
   </HTML>
 % } else {
@@ -162,7 +149,6 @@ my $cust_pay = qsearchs({
 die "$thing #$paynum not found!" unless $cust_pay;
 
 my $pr_link = "${p}view/cust_pay.html?link=print;paynum=$paynum;void=$void";
-my $email_link = "${p}view/cust_pay.html?link=email;paynum=$paynum;void=$void";
 
 my $custnum = $cust_pay->custnum;
 my $display_custnum = $cust_pay->cust_main->display_custnum;
@@ -173,14 +159,4 @@ my $money_char = $conf->config('money_char') || '$';
 
 tie my %payby, 'Tie::IxHash', FS::payby->payby2longname;
 
-my $email_error;
-
-if ( $link eq 'email' ) {
-    my $email_error = $cust_pay->send_receipt(
-       'manual' => 1,
-    );
-
-    warn "can't send payment receipt/statement: $email_error" if $email_error;
-}
-
 </%init>
index 8a352f3..852640e 100644 (file)
          )
 
 </%doc>
-<SCRIPT>
-function areyousure(href) {
-  if (confirm("Permanently delete this <% $label %>?") == true)
-    window.location.href = href;
-}
-</SCRIPT>
-
 % if ( $custnum ) { 
 
   <% include("/elements/header.html","View $label: $value") %>
@@ -43,13 +36,18 @@ function areyousure(href) {
             "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')"
   )) %>
 
+  <SCRIPT>
+  function areyousure(href) {
+      if (confirm("Permanently delete this <% $label %>?") == true)
+          window.location.href = href;
+  }
+  </SCRIPT>
+
 % } 
 
 Service #<B><% $svcnum %></B>
 % my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?';
 | <A HREF="<%$url%><%$svcnum%>">Edit this <% $label %></A>
-| <A HREF="javascript:areyousure('<%$p.'misc/unprovision.cgi?'.$svcnum%>')">
-Unprovision this Service</A>
 <BR>
 
 <% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
diff --git a/httemplate/view/image.cgi b/httemplate/view/image.cgi
deleted file mode 100644 (file)
index 153ec85..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<% $data %>\
-<%init>
-
-#die "access denied"
-#  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
-
-my $conf = new FS::Conf;
-
-my $type;
-if ( $cgi->param('type') eq 'png' ) {
-  $type = 'png';
-} elsif ( $cgi->param('type') eq 'eps' ) {
-  $type = 'eps';
-} else {
-  die "unknown image type ". $cgi->param('type');
-}
-
-my $data;
-if ( $cgi->param('prefname') =~ /^(\w+)$/ ) {
-
-  my $prefname = $1;
-  my $curuser = $FS::CurrentUser::CurrentUser;
-  $data = decode_base64( $curuser->option("$prefname") );
-
-} else {
-  die "no preview_session specified";
-}
-
-http_header('Content-Type' => 'image/png' );
-
-</%init>
index 184286c..82cab06 100644 (file)
@@ -7,30 +7,28 @@
     return confirm("Remove all records and slave from " + document.SlaveForm.recdata.value + "?");
   }
 </SCRIPT>
-<% include('/elements/init_overlib.html') %>
 
-<A NAME="dns"></A>
 <div class="fscontainer">
 <div class="fsbox">
 <div class="fsbox-title">
   <span class="left">DNS Records</span>
 </div>
 
-<% include('/elements/table-grid.html') %>
+% my @records; if ( @records = $svc_domain->domain_record ) { 
+
+  <% include('/elements/table-grid.html') %>
 
 % my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor = $bgcolor2;
+%     my $bgcolor2 = '#ffffff';
+%     my $bgcolor = $bgcolor2;
 
   <tr>
     <th CLASS="grid" BGCOLOR="#cccccc">Zone</th>
     <th CLASS="grid" BGCOLOR="#cccccc">Type</th>
     <th CLASS="grid" BGCOLOR="#cccccc">Data</th>
     <th CLASS="grid" BGCOLOR="#cccccc">TTL</th>
-    <th CLASS="grid" BGCOLOR="#cccccc"></th>
   </tr>
 
-% my @records = $svc_domain->domain_record;
 % foreach my $domain_record ( @records ) {
 %       my $type = $domain_record->rectype eq '_mstr'
 %                    ? "(slave)"
 % unless ( $domain_record->rectype eq 'SOA'
 %          || ! $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice')
 %        ) { 
-%   my $edit_link = include('/elements/popup_link.html',
-%                             'label'  => 'edit',                      
-%                             'action' => $p.'edit/domain_record.html?recnum='.
-%                                         $domain_record->recnum,
-%                             'actionlabel' => 'Edit nameservice record',
-%                             'width'  => 655,
-%                             'height' => 176,
-%                             #'color'  => '#ff0000',
-%                   );
 %   ( my $recdata = $domain_record->recdata ) =~ s/"/\\'\\'/g;
-%   my $delete_url= "javascript:areyousure('${p}misc/delete-domain_record.cgi?".
-%                   $domain_record->recnum. "', 'Delete ".
-%                   $domain_record->reczone. " $type $recdata ?' )";
-      <%$edit_link%>&nbsp;|&nbsp;<A HREF="<%$delete_url%>">delete</A>
+      (<A HREF="<%$p%>edit/domain_record.html?<%$domain_record->recnum%>">edit</A>)
+      (<A HREF="javascript:areyousure('<%$p%>misc/delete-domain_record.cgi?<%$domain_record->recnum%>', 'Delete \'<% $domain_record->reczone %> <% $type %> <% $recdata %>\' ?' )">delete</A>)
 % }
       </td>
     </tr>
 
 % } 
 
-% if ( ! @records ) {
+  </table>
+% } else {
 
   <FORM METHOD="POST" NAME="DefaultForm" ACTION="<%$p%>edit/process/svc_domain-defaultrecords.cgi">
-  <tr>
-    <td class="grid" BGCOLOR="#ffffff" COLSPAN=5>
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
       <INPUT TYPE="submit" VALUE="Add default records">
-    </td>
-  </tr>
   </FORM>
 
 % }
 
 % if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice') ) {
+    <BR>
     <FORM METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
-    <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
-    <tr>
-      <td class="grid" bgcolor="<%$bgcolor%>">
-        <INPUT TYPE="text" NAME="reczone"><BR>
-        <FONT SIZE="-1"><I>Zone</I></FONT>
-      </TD>
-      <TD class="grid" bgcolor="<%$bgcolor%>">
-        <INPUT TYPE="hidden" NAME="recaf" VALUE="IN">
+      <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
+      <TABLE>
+      <TR>
+        <TD ALIGN="right" VALIGN="top">
+          <INPUT TYPE="text" NAME="reczone"><BR>
+          <FONT SIZE="-1"><I>Zone</I></FONT>
+        </TD>
+        <TD ALIGN="right" VALIGN="top">
+          <INPUT TYPE="hidden" NAME="recaf" VALUE="IN"> IN 
+        </TD>
+        <TD ALIGN="right" VALIGN="top">
           <SELECT NAME="rectype">
 %           foreach ( @{ FS::domain_record->rectypes } ) { 
-              <OPTION VALUE="<%$_%>">IN <%$_%></OPTION>
+              <OPTION VALUE="<%$_%>"><%$_%></OPTION>
 %           } 
           </SELECT><BR>
           <FONT SIZE="-1"><I>Type</I></FONT>
-      </TD>
-      <TD class="grid" bgcolor="<%$bgcolor%>">
-        <INPUT TYPE="text" NAME="recdata"><BR>
-        <FONT SIZE="-1"><I>Data</I></FONT>
-      </TD>
-      <TD class="grid" bgcolor="<%$bgcolor%>">
-        <INPUT TYPE="text" NAME="ttl" size="6"><BR>
-        <FONT SIZE="-1"><I>TTL</I></FONT>
-      </TD>
-      <TD class="grid" bgcolor="<%$bgcolor%>" VALIGN="top">
-        <INPUT TYPE="submit" VALUE="Add record">
-      </TD>
-    </TR>
+        </TD>
+        <TD ALIGN="right" VALIGN="top">
+          <INPUT TYPE="text" NAME="recdata"><BR>
+          <FONT SIZE="-1"><I>Data</I></FONT>
+        </TD>
+        <TD ALIGN="right" VALIGN="top">
+          <INPUT TYPE="text" NAME="ttl" size="6"><BR>
+          <FONT SIZE="-1"><I>TTL</I></FONT>
+        </TD>
+        <TD ALIGN="right" VALIGN="top">
+          <INPUT TYPE="submit" VALUE="Add record">
+        </TD>
+      </TR>
+    </TABLE>
     </FORM>
 
     <BR>
       <INPUT TYPE="text" NAME="recdata">
       <INPUT TYPE="submit" VALUE="Slave domain" onClick="return slave_areyousure()">
     </FORM>
-    <BR><BR>
 
 % }
 
-</table>
-
 </div>
 </div>
 <%init>
diff --git a/httemplate/view/svc_pbx.cgi b/httemplate/view/svc_pbx.cgi
deleted file mode 100644 (file)
index 79cafed..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<% include('elements/svc_Common.html',
-             'table'     => 'svc_pbx',
-            'edit_url'  => $p."edit/svc_Common.html?svcdb=svc_pbx;svcnum=",
-             'labels'    => \%labels,
-             'html_foot' => $html_foot,
-          )
-%>
-<%init>
-
-my $fields = FS::svc_pbx->table_info->{'fields'};
-my %labels = map { $_ =>  ( ref($fields->{$_})
-                             ? $fields->{$_}{'label'}
-                             : $fields->{$_}
-                         );
-                 }
-             keys %$fields;
-
-my $html_foot = sub {
-  my $svc_pbx = shift;
-
-  ##
-  # CDR links
-  ##
-
-  tie my %what, 'Tie::IxHash',
-    'pending' => 'NULL',
-    'billed'  => 'done',
-  ;
-
-  #matching as per package def cdr_svc_method
-  my $cust_pkg = $svc_pbx->cust_svc->cust_pkg;
-  return '' unless $cust_pkg;
-
-  my @voip_pkgs =
-    grep { $_->plan eq 'voip_cdr' } $cust_pkg->part_pkg->self_and_bill_linked;
-  if ( scalar(@voip_pkgs) > 1 ) { 
-    warn "multiple voip_cdr packages bundled\n";
-    return '';
-  } elsif ( !@voip_pkgs ) {
-    warn "no voip_cdr packages\n";
-  }
-  my $voip_pkg = @voip_pkgs[0];
-
-  my $cdr_svc_method = $voip_pkg->option('cdr_svc_method')
-                       || 'svc_phone.phonenum';
-  return '' unless $cdr_svc_method =~ /^svc_pbx\.(\w+)$/;
-  my $field = $1;
-
-  my $search;
-  if ( $field eq 'title' ) {
-    $search = 'charged_party='. uri_escape($svc_pbx->title);
-  } elsif ( $field eq 'svcnum' ) {
-    $search = 'svcnum='. $svc_pbx->svcnum;
-  } else {
-    warn "unknown cdr_svc_method svc_pbx.$field";
-    return '';
-  }
-
-  my @links = map {
-    qq(<A HREF="${p}search/cdr.html?cdrbatchnum=__ALL__;$search;freesidestatus=$what{$_}">).
-    "View $_ CDRs</A>";
-  } keys(%what);
-
-  ###
-  # concatenate & return
-  ###
-
-  join(' | ', @links ). '<BR>';
-
-};
-
-</%init>
index 45a6106..d73a5e0 100644 (file)
@@ -5,10 +5,9 @@ config.layout.in
  etc/RT_Config.pm
  etc/RT_SiteConfig.pm
  etc/schema.Pg
- etc/schema.mysql-4.1
 
  lib/RT/Config.pm
-lib/RT/CustomField.pm #CheckMandatoryFields
+lib/RT?CustomField.pm #CheckMandatoryFields
 lib/RT/CustomField_Overlay.pm #customfield date patch
 lib/RT/Interface/Web.pm #customfield date patch
 lib/RT/Interface/Web_Vendor.pm
index 1735702..172e477 100755 (executable)
@@ -386,7 +386,6 @@ CREATE TABLE CustomFields (
   LastUpdatedBy integer NOT NULL DEFAULT 0  ,
   LastUpdated DATETIME NULL  ,
   Disabled int2 NOT NULL DEFAULT 0 ,
-  Required int2 NOT NULL DEFAULT 0 ,
   PRIMARY KEY (id)
 ) TYPE=InnoDB CHARACTER SET utf8;
 
index be5a0d5..f2949ed 100644 (file)
@@ -1855,13 +1855,7 @@ sub OrderByCols {
            );
 
            #if there was a Links.RemoteTarget int, this bs wouldn't be necessary
-           my $custnum_sql = "CAST(SUBSTR($linkalias.Target,31) AS ";
-           if ( RT->Config->Get('DatabaseType') eq 'mysql' ) {
-             $custnum_sql .= 'SIGNED INTEGER)';
-           }
-           else {
-             $custnum_sql .= 'INTEGER)';
-           }
+           my $custnum_sql = "CAST(SUBSTR($linkalias.Target,31) AS INTEGER)";
 
            if ( $subkey eq 'Number' ) {
 
index fc2c49d..d2932d2 100644 (file)
@@ -199,15 +199,6 @@ if ( $ARGS{'Update'} && $id ne 'new' ) {
         push (@results, $msg);
     }
 
-    # Clean up values
-    foreach my $param (grep /^$paramtag-/, keys(%ARGS)) {
-      for ($ARGS{$param}) {
-        s/\r+\n/\n/g;
-        s/^\s+//;
-        s/\s+$//;
-      }
-    }
-
     # Update any existing values
     my $values = $CustomFieldObj->ValuesObj;
     while ( my $value = $values->Next ) {
@@ -215,6 +206,7 @@ if ( $ARGS{'Update'} && $id ne 'new' ) {
             my $param = join("-", $paramtag, $value->Id, $attr);
             next unless exists $ARGS{$param};
             next if ($value->$attr()||'') eq ($ARGS{$param}||'');
+
             my $mutator = "Set$attr";
             my ($id, $msg) = $value->$mutator( $ARGS{$param} );
             push (@results, $msg);
index 9828d7d..aaf8ca8 100644 (file)
@@ -39,10 +39,7 @@ warn "/Elements/AddCustomers called with CustomerString $CustomerString\n"
 
 my @Customers = ();
 if ( $CustomerString ) {
-    @Customers = &RT::URI::freeside::smart_search(
-        'search'            => $CustomerString,
-        'no_fuzzy_on_exact' => 1, #pref?
-    );
+    @Customers = &RT::URI::freeside::smart_search( 'search' => $CustomerString );
 }
 
 my @Services = ();
index 09acdfd..e04c077 100644 (file)
@@ -36,10 +36,7 @@ my $freeside_url = &RT::URI::freeside::FreesideURL();
 
 my @Customers = ();
 if ( $CustomerString ) {
-    @Customers = &RT::URI::freeside::smart_search(
-        'search'            => $CustomerString,
-        'no_fuzzy_on_exact' => 1, #pref?
-    );
+    @Customers = &RT::URI::freeside::smart_search( 'search' => $CustomerString );
 }
 
 my @Services = ();