Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Wed, 9 Oct 2013 06:04:11 +0000 (23:04 -0700)
committerIvan Kohler <ivan@freeside.biz>
Wed, 9 Oct 2013 06:04:11 +0000 (23:04 -0700)
60 files changed:
FS/FS/Mason.pm
FS/FS/Record.pm
FS/FS/Schema.pm
FS/FS/cable_provider.pm [new file with mode: 0644]
FS/FS/cust_main.pm
FS/FS/cust_pkg.pm
FS/FS/part_event/Condition/pkg_age_Common.pm
FS/FS/part_export/domain_shellcommands.pm
FS/FS/part_export/shellcommands_withdomain.pm
FS/FS/payby.pm
FS/FS/svc_cable.pm
FS/MANIFEST
FS/t/cable_provider.t [new file with mode: 0644]
bin/test-event [changed mode: 0644->0755]
httemplate/browse/cable_provider.html [new file with mode: 0644]
httemplate/docs/about.html
httemplate/edit/cable_provider.html [new file with mode: 0644]
httemplate/edit/cust_main-contacts.html
httemplate/edit/cust_payby.html [new file with mode: 0644]
httemplate/edit/elements/edit.html
httemplate/edit/process/cable_provider.html [new file with mode: 0644]
httemplate/edit/process/cust_payby.html [new file with mode: 0644]
httemplate/elements/menu.html
httemplate/elements/select-cable_provider.html [new file with mode: 0644]
httemplate/elements/tr-select-cable_provider.html [new file with mode: 0644]
httemplate/elements/tr-select-month_year.html [new file with mode: 0644]
httemplate/view/cust_main.cgi
ng_selfservice/.freeside.class.php.swp [deleted file]
ng_selfservice/.index.php.swp [deleted file]
ng_selfservice/.logout.php.swp [deleted file]
ng_selfservice/.main.php.swp [deleted file]
ng_selfservice/.password.php.swp [deleted file]
ng_selfservice/.payment.php.swp [deleted file]
ng_selfservice/.payment_ach.php.swp [deleted file]
ng_selfservice/.payment_cc.php.swp [deleted file]
ng_selfservice/.payment_paypal.php.swp [deleted file]
ng_selfservice/.payment_webpay.php.swp [deleted file]
ng_selfservice/.personal.php.swp [deleted file]
ng_selfservice/.process_login.php.swp [deleted file]
ng_selfservice/.process_ticket_create.php.swp [deleted file]
ng_selfservice/.services.php.swp [deleted file]
ng_selfservice/.services_new.php.swp [deleted file]
ng_selfservice/.ticket.php.swp [deleted file]
ng_selfservice/.ticket_create.php.swp [deleted file]
ng_selfservice/.tickets.php.swp [deleted file]
ng_selfservice/.tickets_resolved.php.swp [deleted file]
ng_selfservice/.usage.php.swp [deleted file]
ng_selfservice/.usage_cdr.php.swp [deleted file]
ng_selfservice/.usage_data.php.swp [deleted file]
ng_selfservice/elements/.card.php.swp [deleted file]
ng_selfservice/elements/.check.php.swp [deleted file]
ng_selfservice/elements/.error.php.swp [deleted file]
ng_selfservice/elements/.header.php.swp [deleted file]
ng_selfservice/elements/.menu.php.swp [deleted file]
ng_selfservice/elements/.menu_footer.php.swp [deleted file]
ng_selfservice/elements/.session.php.swp [deleted file]
ng_selfservice/elements/.ticketlist.php.swp [deleted file]
ng_selfservice/js/.menu.js.swp [deleted file]
rt/lib/RT/Interface/Web.pm
rt/share/html/Ticket/Update.html

index f1fc5cb..1215ca4 100644 (file)
@@ -355,6 +355,7 @@ if ( -e $addl_handler_use_file ) {
   use FS::cable_model;
   use FS::invoice_mode;
   use FS::invoice_conf;
+  use FS::cable_provider;
   # Sammath Naur
 
   if ( $FS::Mason::addl_handler_use ) {
index fd03524..71eddc1 100644 (file)
@@ -3038,13 +3038,8 @@ Checks to see if the string is encrypted and returns true or false (1/0) to indi
 
 sub is_encrypted {
   my ($self, $value) = @_;
-  # Possible Bug - Some work may be required here....
-
-  if ($value =~ /^M/ && length($value) > 80) {
-    return 1;
-  } else {
-    return 0;
-  }
+  # could be more precise about it, but this will do for now
+  $value =~ /^M/ && length($value) > 80;
 }
 
 =item decrypt($value)
index 5ea24e4..e44b74e 100644 (file)
@@ -4272,6 +4272,8 @@ sub tables_hashref {
     'svc_cable' => {
       'columns' => [
         'svcnum',        'int',     '',      '', '', '', 
+        'providernum',   'int', 'NULL',      '', '', '',
+        # XXX "Circuit ID/Order number"
         'modelnum',      'int', 'NULL',      '', '', '',
         'serialnum', 'varchar', 'NULL', $char_d, '', '',
         'mac_addr',  'varchar', 'NULL',      12, '', '', 
@@ -4292,6 +4294,17 @@ sub tables_hashref {
       'index'  => [],
     },
 
+    'cable_provider' => {
+      'columns' => [
+        'providernum', 'serial',     '',      '', '', '',
+        'provider',   'varchar',     '', $char_d, '', '',
+        'disabled',      'char', 'NULL',       1, '', '', 
+      ],
+      'primary_key' => 'providernum',
+      'unique' => [ [ 'provider' ], ],
+      'index'  => [],
+    },
+
     'vend_main' => {
       'columns' => [
         'vendnum',   'serial',     '',      '', '', '',
diff --git a/FS/FS/cable_provider.pm b/FS/FS/cable_provider.pm
new file mode 100644 (file)
index 0000000..e988192
--- /dev/null
@@ -0,0 +1,112 @@
+package FS::cable_provider;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::cable_provider - Object methods for cable_provider records
+
+=head1 SYNOPSIS
+
+  use FS::cable_provider;
+
+  $record = new FS::cable_provider \%hash;
+  $record = new FS::cable_provider { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cable_provider object represents a cable service provider.
+FS::cable_provider inherits from FS::Record.  The following fields are
+currently supported:
+
+=over 4
+
+=item providernum
+
+primary key
+
+=item provider
+
+provider
+
+=item disabled
+
+disabled
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new provider.  To add the provider to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'cable_provider'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid provider.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('providernum')
+    || $self->ut_text('provider')
+    || $self->ut_enum('disabled', [ '', 'Y' ] )
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
index e393125..a9a4cb0 100644 (file)
@@ -2097,6 +2097,21 @@ sub cust_contact {
   qsearch('contact', { 'custnum' => $self->custnum } );
 }
 
+=item cust_payby
+
+Returns all payment methods (see L<FS::cust_payby>) for this customer.
+
+=cut
+
+sub cust_payby {
+  my $self = shift;
+  qsearch({
+    'table'    => 'cust_payby',
+    'hashref'  => { 'custnum' => $self->custnum },
+    'order_by' => 'ORDER BY weight ASC',
+  });
+}
+
 =item unsuspend
 
 Unsuspends all unflagged suspended packages (see L</unflagged_suspended_pkgs>
@@ -5140,7 +5155,6 @@ sub _upgrade_data { #class method
       die $error if $error;
 
       $cust_main->setfield($_, '') foreach @payfields;
-      #$DEBUG = 2;
       $error = $cust_main->replace;
       die $error if $error;
 
index 19ef1f3..0cb1b50 100644 (file)
@@ -2613,14 +2613,30 @@ sub part_pkg_currency_option {
 
 =item cust_svc [ OPTION => VALUE ... ] (current usage)
 
+=item cust_svc_unsorted [ OPTION => VALUE ... ] 
+
 Returns the services for this package, as FS::cust_svc objects (see
 L<FS::cust_svc>).  Available options are svcpart and svcdb.  If either is
 spcififed, returns only the matching services.
 
+As an optimization, use the cust_svc_unsorted version if you are not displaying
+the results.
+
 =cut
 
 sub cust_svc {
   my $self = shift;
+  cluck "cust_pkg->cust_svc called" if $DEBUG > 2;
+  $self->_sort_cust_svc( $self->cust_svc_unsorted_arrayref );
+}
+
+sub cust_svc_unsorted {
+  my $self = shift;
+  @{ $self->cust_svc_unsorted_arrayref };
+}
+
+sub cust_svc_unsorted_arrayref {
+  my $self = shift;
 
   return () unless $self->num_cust_svc(@_);
 
@@ -2645,13 +2661,7 @@ sub cust_svc {
     $search{extra_sql} = ' AND svcdb = '. dbh->quote( $opt{'svcdb'} );
   }
 
-  cluck "cust_pkg->cust_svc called" if $DEBUG > 2;
-
-  #if ( $self->{'_svcnum'} ) {
-  #  values %{ $self->{'_svcnum'}->cache };
-  #} else {
-    $self->_sort_cust_svc( [ qsearch(\%search) ] );
-  #}
+  [ qsearch(\%search) ];
 
 }
 
index 726b01d..33e49b8 100644 (file)
@@ -49,7 +49,7 @@ sub condition {
 }
 
 sub pkg_age_age {
-  my( $self, $cust_pkg, %opt );
+  my( $self, $cust_pkg, %opt ) = @_;
   $self->option_age_from('age', $opt{'time'} );
 }
 
index 582e292..8e85d71 100644 (file)
@@ -49,8 +49,7 @@ The following variables are available for interpolation (prefixed with <code>new
   <LI><code>$uid</code> - of catchall account
   <LI><code>$gid</code> - of catchall account
   <LI><code>$dir</code> - home directory of catchall account
-  <LI>All other fields in
-    <a href="../docs/schema.html#svc_domain">svc_domain</a> are also available.
+  <LI>All other fields in <b>svc_domain</b> are also available.
 </UL>
 END
 );
index 1b59589..29715b7 100644 (file)
@@ -141,7 +141,32 @@ The following variables are available for interpolation (prefixed with
   <LI><code>$shell</code>
   <LI><code>$quota</code>
   <LI><code>@radius_groups</code>
-  <LI>All other fields in <a href="../docs/schema.html#svc_acct">svc_acct</a> are also available.
+  <LI><code>$reasonnum (when suspending)</code>
+  <LI><code>$reasontext (when suspending)</code>
+  <LI><code>$reasontypenum (when suspending)</code>
+  <LI><code>$reasontypetext (when suspending)</code>
+  <LI><code>$pkgnum</code>
+  <LI><code>$custnum</code>
+  <LI>All other fields in <b>svc_acct</b> are also available.
+  <LI>The following fields from <b>cust_main</b> are also available (except during replace): company, address1, address2, city, state, zip, county, daytime, night, fax, otaker, agent_custid, locale.  When used on the command line (rather than STDIN), they will be quoted for the shell already (do not add additional quotes).
+</UL>
+For the package changed command only, the following fields are also available:
+<UL>
+  <LI>$old_pkgnum and $new_pkgnum
+  <LI>$old_pkgpart and $new_pkgpart
+  <LI>$old_agent_pkgid and $new_agent_pkgid
+  <LI>$old_order_date and $new_order_date
+  <LI>$old_start_date and $new_start_date
+  <LI>$old_setup and $new_setup
+  <LI>$old_bill and $new_bill
+  <LI>$old_last_bill and $new_last_bill
+  <LI>$old_susp and $new_susp
+  <LI>$old_adjourn and $new_adjourn
+  <LI>$old_resume and $new_resume
+  <LI>$old_cancel and $new_cancel
+  <LI>$old_unancel and $new_unancel
+  <LI>$old_expire and $new_expire
+  <LI>$old_contract_end and $new_contract_end
 </UL>
 END
 );
index e223a05..b33f8f3 100644 (file)
@@ -70,12 +70,12 @@ tie %hash, 'Tie::IxHash',
     cust_pay  => 'CHEK', #this is a customer type only, payments are CHEK...
     realtime  => 1,
   },
-  'LECB' => {
-    tinyname  => 'phone bill',
-    shortname => 'Phone bill billing',
-    longname  => 'Phone bill billing',
-    realtime  => 1,
-  },
+  #'LECB' => {
+  #  tinyname  => 'phone bill',
+  #  shortname => 'Phone bill billing',
+  #  longname  => 'Phone bill billing',
+  #  realtime  => 1,
+  #},
   'BILL' => {
     tinyname  => 'billing',
     shortname => 'Billing',
index 1980c0e..596f699 100644 (file)
@@ -4,6 +4,7 @@ use base qw( FS::svc_Common ); #qw( FS::device_Common FS::svc_Common );
 use strict;
 use Tie::IxHash;
 use FS::Record qw( qsearchs ); # qw( qsearch qsearchs );
+use FS::cable_provider;
 use FS::cable_model;
 
 =head1 NAME
@@ -72,24 +73,35 @@ sub search_sql {
 sub table_info {
 
   tie my %fields, 'Tie::IxHash',
-    'svcnum'     => 'Service',
-    'modelnum'   => { label             => 'Model',
-                      type              => 'select-cable_model',
-                      disable_inventory => 1,
-                      disable_select    => 1,
-                      value_callback    => sub {
-                                             my $svc = shift;
-                                             $svc->cable_model->model_name;
-                                           },
-                    },
-    'serialnum'  => 'Serial number',
-    'mac_addr'   => { label          => 'MAC address',
-                      type           => 'input-mac_addr',
-                      value_callback => sub {
-                                          my $svc = shift;
-                                          join(':', $svc->mac_addr =~ /../g);
-                                        },
-                    },
+    'svcnum'      => 'Service',
+    'providernum' => { label             => 'Provider',
+                       type              => 'select-cable_provider',
+                       disable_inventory => 1,
+                       disable_select    => 1,
+                       value_callback    => sub {
+                                              my $svc = shift;
+                                              my $p = $svc->cable_provider;
+                                              $p ? $p->provider : '';
+                                            },
+                     },
+    #XXX "Circuit ID/Order number"
+    'modelnum'    => { label             => 'Model',
+                       type              => 'select-cable_model',
+                       disable_inventory => 1,
+                       disable_select    => 1,
+                       value_callback    => sub {
+                                              my $svc = shift;
+                                              $svc->cable_model->model_name;
+                                            },
+                     },
+    'serialnum'   => 'Serial number',
+    'mac_addr'    => { label          => 'MAC address',
+                       type           => 'input-mac_addr',
+                       value_callback => sub {
+                                           my $svc = shift;
+                                           join(':', $svc->mac_addr =~ /../g);
+                                         },
+                     },
   ;
 
   {
@@ -130,6 +142,7 @@ sub check {
 
   my $error = 
        $self->ut_numbern('svcnum')
+    || $self->ut_foreign_key('providernum', 'cable_provider', 'providernum')
     || $self->ut_foreign_key('modelnum', 'cable_model', 'modelnum')
     || $self->ut_alpha('serialnum')
     || $self->ut_mac_addr('mac_addr')
@@ -139,6 +152,17 @@ sub check {
   $self->SUPER::check;
 }
 
+=item cable_provider
+
+Returns the cable_provider object for this record.
+
+=cut
+
+sub cable_provider {
+  my $self = shift;
+  qsearchs('cable_provider', { 'providernum'=>$self->providernum } );
+}
+
 =item cable_model
 
 Returns the cable_model object for this record.
index 339965e..5dbe754 100644 (file)
@@ -724,3 +724,5 @@ FS/invoice_mode.pm
 t/invoice_mode.t
 FS/invoice_conf.pm
 t/invoice_conf.t
+FS/cable_provider.pm
+t/cable_provider.t
diff --git a/FS/t/cable_provider.t b/FS/t/cable_provider.t
new file mode 100644 (file)
index 0000000..c794379
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cable_provider;
+$loaded=1;
+print "ok 1\n";
old mode 100644 (file)
new mode 100755 (executable)
index d3a9f11..73c9d31
@@ -34,7 +34,10 @@ print "\n";
 
 my @conditions = $part_event->part_event_condition;
 foreach my $condition ( @conditions ) {
-  my $sat = $condition->condition( $object, 'cust_event' => $cust_event );
+  my $sat = $condition->condition( $object,
+                                   'cust_event' => $cust_event,
+                                   'time' => time,
+                                 );
 
   my $sql = $condition->condition_sql();
   
diff --git a/httemplate/browse/cable_provider.html b/httemplate/browse/cable_provider.html
new file mode 100644 (file)
index 0000000..0d34498
--- /dev/null
@@ -0,0 +1,32 @@
+<& elements/browse.html,
+     'title'              => 'Cable providers',
+     'html_init'          => $html_init,
+     'name'               => 'providers',
+     'disableable'        => 1,
+     'disabled_statuspos' => 1,
+     'query'              => { 'table'     => 'cable_provider',
+                               'hashref'   => {},
+                               'order_by' => 'ORDER BY provider',
+                             },
+     'count_query'        => $count_query,
+     'header'             => $header,
+     'fields'             => $fields,
+     'links'              => $links,
+&>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+  qq!<A HREF="${p}edit/cable_provider.html"><I>Add a provider</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM cable_provider';
+
+my $link = [ $p.'edit/cable_provider.html?', 'providernum' ];
+
+my $header = [ 'Provider' ];
+my $fields = [ 'provider' ];
+my $links  = [ $link ];
+
+</%init>
index c2ba4e4..80d9488 100644 (file)
@@ -56,7 +56,7 @@ GNU <b>Affero</b> General Public License.<BR>
 
 % unless ( $agentnum ) {
   <CENTER>
-  <FONT SIZE="-3">"I can't figure out ... if it's an end or the beginning" - R. Hunter</FONT>
+  <FONT SIZE="-3">"" - R. Hunter</FONT>
   </CENTER>
 % }
 
diff --git a/httemplate/edit/cable_provider.html b/httemplate/edit/cable_provider.html
new file mode 100644 (file)
index 0000000..9a911cc
--- /dev/null
@@ -0,0 +1,20 @@
+<& elements/edit.html,
+     'name_singular' => 'Provider',
+     'table'         => 'cable_provider',
+     'fields'        => [
+                          'provider',
+                          { field=>'disabled', type=>'checkbox', value=>'Y', },
+                        ],
+     'labels'        => {
+                          'providernum' => 'Provider',
+                          'provider'    => 'Provider',
+                          'disabled'    => 'Disabled',
+                        },
+     'viewall_dir'   => 'browse',
+&>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
index bae58bd..cd83a29 100644 (file)
@@ -1,8 +1,9 @@
-<% include('elements/edit.html',
+<& elements/edit.html,
      'name_singular'   => 'customer contacts', #yes, we're editing all of them
      'table'           => 'cust_main',
-     'post_url'       => popurl(1). 'process/cust_main-contacts.html',
-     'labels'          => { 'custnum'     => ' ', #XXX supress this line entirely, its being redundant
+     'post_url'        => popurl(1). 'process/cust_main-contacts.html',
+     'no_pkey_display' => 1,
+     'labels'          => {
                             'contactnum'  => 'Contact',
                             #'locationnum' => '&nbsp;',
                           },
      #'edit_callback'   => $edit_callback,
      #'error_callback'  => $error_callback,
      'agent_virt'      => 1,
-     'menubar'          => [], #remove "view all" link
+     'menubar'         => [], #remove "view all" link
 
      #XXX it would be nice if this could instead be after the error but before
      # the table
-     'html_init'        => include('/elements/small_custview.html',
-                                     $custnum,
-                                     $conf->config('countrydefault') || 'US',
-                                     1, #no balance
-                                  ),
-   )
-%>
+     'html_init'       => include('/elements/small_custview.html',
+                                    $custnum,
+                                    $conf->config('countrydefault') || 'US',
+                                    1, #no balance
+                                 ).
+                          '<BR>',
+&>
 <%init>
 
 my $curuser = $FS::CurrentUser::CurrentUser;
diff --git a/httemplate/edit/cust_payby.html b/httemplate/edit/cust_payby.html
new file mode 100644 (file)
index 0000000..67eb40a
--- /dev/null
@@ -0,0 +1,184 @@
+%# #based on / some false laziness w/ cust_main-contacts.html
+<& elements/edit.html,
+     'name_singular'   => 'payment methods', #"customer payment methods" ?
+     'table'           => 'cust_main',
+     'post_url'        => popurl(1). 'process/cust_payby.html',
+     'no_pkey_display' => 1,
+     'labels'          => {
+                            'custpaybynum'  => ' ', #'Payment method',
+                            #'locationnum' => '&nbsp;',
+                          },
+     'fields'          => [
+       { field                 => 'custpaybynum',
+         type                  => 'selectlayers',
+         options               => [ '',
+                                    grep { ! /^(DCRD|DCHK)$/ }
+                                      FS::payby->cust_payby
+                                  ],
+         labels                => { '' => 'Select payment method',
+                                    FS::payby->payby2shortname
+                                  },
+         layer_fields          => \%payby_fields,
+         layer_values_callback => $payby_layer_values,
+         m2m_method            => 'cust_payby',
+         m2m_dstcol            => 'custpaybynum',   
+         m2_label              => ' ', #'Payment method',
+         m2_error_callback     => $m2_error_callback,
+       },
+     ],
+     #'new_callback'    => $new_callback,
+     #'edit_callback'   => $edit_callback,
+     #'error_callback'  => $error_callback,
+     'agent_virt'      => 1,
+     'menubar'         => [], #remove "view all" link
+
+     #XXX it would be nice if this could instead be after the error but before
+     # the table
+     'html_init'       => include('/elements/small_custview.html',
+                                    $custnum,
+                                    $conf->config('countrydefault') || 'US',
+                                    1, #no balance
+                                 ).
+                          '<BR>',
+&>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $conf = new FS::Conf;
+
+my $custnum;
+if ( $cgi->param('error') ) {
+  $custnum = scalar($cgi->param('custnum'));
+
+  die "access denied"
+    unless $curuser->access_right(($custnum ? 'Edit' : 'New'). ' customer'); #payment methods?
+
+} elsif ( $cgi->keywords ) { #editing
+  $custnum = ($cgi->keywords)[0];
+
+  die "access denied"
+    unless $curuser->access_right('Edit customer');
+
+} else { #new customer
+
+  #this doesn't really work here, we're an edit only
+  die "guru meditation #53";
+
+  die "access denied"
+    unless $curuser->access_right('New customer');
+
+}
+
+
+#XXX
+my %payby_fields = (
+  'CARD' => [ 'CARD_payinfo' => mt('Card number'),
+              'CARD_exp'     => {
+                                  label => 'Expiration',
+                                  type  => 'select-month_year',
+                                  #XXX prefix?
+                                },
+              'CARD_paycvv'  => 'CVV2', #XXX help popup
+              'CARD_payname' => mt('Exact name on card'),
+              'CARD_payauto' => { label => mt('Charge future payments to this credit card automatically'),
+                                  type  => 'checkbox',
+                                },
+            ],
+  'CHEK' => [ 'CHEK_payinfo1'  => mt('Account number'),
+              'CHEK_paytype'   => { label => 'Type',
+                                    #XXX select values
+                                    #@FS::cust_main::paytypes #??
+                                  },
+              'CHEK_payinfo2'  => mt('ABA/Routing number'), #XXX help popup
+              'CHEK_exp_month' => { type  => 'hidden',
+                                    value => 12,
+                                  },
+              'CHEK_exp_year'  => { type  => 'hidden',
+                                    value => 2037,
+                                  },
+              'CHEK_payname'   => mt('Bank name'),
+              #'CHEK_paystate'  => { label => $paystate_label,
+              #                      type  => 'select-state',
+              #                    },
+              'CHEK_payauto' => { label => mt('Charge future payments to this electronic check automatically'),
+                                  type  => 'checkbox',
+                                },
+            ],
+  #'LECB'
+  'BILL' => [ 'BILL_payinfo' => mt('P.O.'),
+              'BILL_exp_month' => { type  => 'hidden',
+                                    value => 12,
+                                  },
+              'BILL_exp_year'  => { type  => 'hidden',
+                                    value => 2037,
+                                  },
+              'BILL_payname'   => mt('Attention'),
+            ],
+  'COMP' => [
+              'COMP_payinfo' => mt('Approved by'),
+            ],
+
+);
+
+#XXX
+my $payby_layer_values = sub {
+  my ( $cgi, $cust_payby, $switches ) = @_;
+  +{
+#     #map { $_ => { $part_event_condition->options } }
+#     #    keys %condition_fields
+#     map { my $conditionname = $_;
+#           my %opts = $switches->{'mode'} eq 'error'
+#                      ? %{ $cgi_conditions{$conditionname} || {} }
+#                      : $part_event_condition->options;
+#           %opts = (
+#             map { ( "$conditionname.$_" => $opts{$_} ); }
+#                 keys %opts
+#           );
+#           ( $conditionname => \%opts );
+#         }
+#         keys %condition_fields
+  };
+};
+
+
+#my $new_callback = sub {
+#  my( $cgi, $cust_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $edit_callback = sub {
+# my( $cgi, $cust_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $error_callback = sub {
+#  my( $cgi, $cust_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+my $m2_error_callback = sub {
+  my($cgi, $object) = @_;
+
+  #XXX
+
+  #process_o2m fields in process/cust_main-contacts.html
+  my @fields = qw( first last title comment );
+  my @gfields = ( '', map "_$_", @fields );
+
+  map {
+        if ( /^contactnum(\d+)$/ ) {
+          my $num = $1;
+          if ( grep $cgi->param("contactnum$num$_"), @gfields ) {
+            my $x = new FS::contact {
+              'contactnum' => scalar($cgi->param("contactnum$num")),
+              map { $_ => scalar($cgi->param("contactnum${num}_$_")) } @fields,
+            };
+            $x;
+          } else {
+            ();
+          }
+        } else {
+          ();
+        }
+      }
+      $cgi->param;
+};
+
+</%init>
index 051788c..6c96532 100644 (file)
@@ -116,6 +116,9 @@ Example:
     # display of primary key, no submit button, no html_foot, no footer)
     'embed' => $object, #need to pass the object
 
+    #don't show the primary key label and value
+    'no_pkey_display' => 1,
+
     ###
     # HTML callbacks
     ###
@@ -236,13 +239,17 @@ Example:
   <INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $table %>">
   <INPUT TYPE="hidden" NAME="<% $pkey %>" VALUE="<% $clone ? '' : $object->$pkey() %>">
 
-  <FONT SIZE="+1"><B>
-  <% ( $opt{labels} && exists $opt{labels}->{$pkey} )
-        ? $opt{labels}->{$pkey}
-        : $pkey
-  %>
-  </B></FONT>
-  #<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
+%   unless ( $opt{'no_pkey_display'} ) {
+
+      <FONT SIZE="+1"><B>
+      <% ( $opt{labels} && exists $opt{labels}->{$pkey} )
+            ? $opt{labels}->{$pkey}
+            : $pkey
+      %>
+      </B></FONT>
+      #<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
+
+%   }
 
 % }
 
diff --git a/httemplate/edit/process/cable_provider.html b/httemplate/edit/process/cable_provider.html
new file mode 100644 (file)
index 0000000..ecffaf6
--- /dev/null
@@ -0,0 +1,10 @@
+<& elements/process.html,
+     'table'       => 'cable_provider',
+     'viewall_dir' => 'browse',
+&>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/cust_payby.html b/httemplate/edit/process/cust_payby.html
new file mode 100644 (file)
index 0000000..a999e4d
--- /dev/null
@@ -0,0 +1,19 @@
+<% include('elements/process.html',
+     'table'          => 'cust_main',
+     'error_redirect' => popurl(3). 'edit/cust_payby.html?',
+     'agent_virt'     => 1,
+     'skip_process'   => 1, #we don't want to make any changes to cust_main
+     'process_o2m' => {
+       'table'  => 'cust_payby',
+       'fields' => \@payby_fields,
+     },
+     'redirect' => popurl(3). 'view/cust_main.cgi?',
+   )
+%>
+<%init>
+
+#XXX
+my @payby_fields = qw();
+}
+
+</%init>
index c8fe5f2..8cb9675 100644 (file)
@@ -521,6 +521,7 @@ tie my %config_radius, 'Tie::IxHash',
 ;
 
 tie my %config_cable, 'Tie::IxHash',
+  'Cable providers' => [ $fsurl.'browse/cable_provider.html', '' ],
   'Cable modem models' => [ $fsurl.'browse/cable_model.html', '' ],
 ;
 
diff --git a/httemplate/elements/select-cable_provider.html b/httemplate/elements/select-cable_provider.html
new file mode 100644 (file)
index 0000000..9530b78
--- /dev/null
@@ -0,0 +1,7 @@
+<% include( '/elements/select-table.html',
+    'table'            => 'cable_provider',
+    'name_col'         => 'provider',
+    'empty_label'      => 'Select provider',
+    @_,
+   )
+%>
diff --git a/httemplate/elements/tr-select-cable_provider.html b/httemplate/elements/tr-select-cable_provider.html
new file mode 100644 (file)
index 0000000..abb8564
--- /dev/null
@@ -0,0 +1,12 @@
+% #if ( scalar(@domains) < 2 ) {
+% #} else {
+  <TR>
+    <TD ALIGN="right"><% $opt{'label'} || 'Provider' %></TD>
+    <TD>
+      <% include( '/elements/select-cable_provider.html', %opt) %>
+    </TD>
+   </TR>
+% #}
+<%init>
+  my %opt = @_;
+</%init>
diff --git a/httemplate/elements/tr-select-month_year.html b/httemplate/elements/tr-select-month_year.html
new file mode 100644 (file)
index 0000000..b1943bd
--- /dev/null
@@ -0,0 +1,22 @@
+% unless ( $opt{'js_only'} ) {
+
+    <% include('tr-td-label.html', %opt ) %>
+
+      <TD <% $colspan %> <% $style %>>
+% }
+
+    <% include('select-month_year.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+      </TD>
+    </TR>
+% }
+<%init>
+
+my %opt = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $colspan = $opt{'colspan'} ? 'COLSPAN="'.$opt{'colspan'}.'"' : '';
+
+</%init>
index 430c50c..3919881 100755 (executable)
@@ -147,7 +147,6 @@ function areyousure(href, message) {
 % if ( $br ) {
   <BR><BR>
 % }
-</%doc>
 
 %my $signupurl = $conf->config('signupurl');
 %if ( $signupurl ) {
diff --git a/ng_selfservice/.freeside.class.php.swp b/ng_selfservice/.freeside.class.php.swp
deleted file mode 100644 (file)
index 5c39524..0000000
Binary files a/ng_selfservice/.freeside.class.php.swp and /dev/null differ
diff --git a/ng_selfservice/.index.php.swp b/ng_selfservice/.index.php.swp
deleted file mode 100644 (file)
index 50c9cfb..0000000
Binary files a/ng_selfservice/.index.php.swp and /dev/null differ
diff --git a/ng_selfservice/.logout.php.swp b/ng_selfservice/.logout.php.swp
deleted file mode 100644 (file)
index ec27faa..0000000
Binary files a/ng_selfservice/.logout.php.swp and /dev/null differ
diff --git a/ng_selfservice/.main.php.swp b/ng_selfservice/.main.php.swp
deleted file mode 100644 (file)
index cc55626..0000000
Binary files a/ng_selfservice/.main.php.swp and /dev/null differ
diff --git a/ng_selfservice/.password.php.swp b/ng_selfservice/.password.php.swp
deleted file mode 100644 (file)
index e1e968f..0000000
Binary files a/ng_selfservice/.password.php.swp and /dev/null differ
diff --git a/ng_selfservice/.payment.php.swp b/ng_selfservice/.payment.php.swp
deleted file mode 100644 (file)
index 2b705a3..0000000
Binary files a/ng_selfservice/.payment.php.swp and /dev/null differ
diff --git a/ng_selfservice/.payment_ach.php.swp b/ng_selfservice/.payment_ach.php.swp
deleted file mode 100644 (file)
index 1a87a2d..0000000
Binary files a/ng_selfservice/.payment_ach.php.swp and /dev/null differ
diff --git a/ng_selfservice/.payment_cc.php.swp b/ng_selfservice/.payment_cc.php.swp
deleted file mode 100644 (file)
index 369d104..0000000
Binary files a/ng_selfservice/.payment_cc.php.swp and /dev/null differ
diff --git a/ng_selfservice/.payment_paypal.php.swp b/ng_selfservice/.payment_paypal.php.swp
deleted file mode 100644 (file)
index 3abff2f..0000000
Binary files a/ng_selfservice/.payment_paypal.php.swp and /dev/null differ
diff --git a/ng_selfservice/.payment_webpay.php.swp b/ng_selfservice/.payment_webpay.php.swp
deleted file mode 100644 (file)
index 6ef3df9..0000000
Binary files a/ng_selfservice/.payment_webpay.php.swp and /dev/null differ
diff --git a/ng_selfservice/.personal.php.swp b/ng_selfservice/.personal.php.swp
deleted file mode 100644 (file)
index f5e8c23..0000000
Binary files a/ng_selfservice/.personal.php.swp and /dev/null differ
diff --git a/ng_selfservice/.process_login.php.swp b/ng_selfservice/.process_login.php.swp
deleted file mode 100644 (file)
index c530f11..0000000
Binary files a/ng_selfservice/.process_login.php.swp and /dev/null differ
diff --git a/ng_selfservice/.process_ticket_create.php.swp b/ng_selfservice/.process_ticket_create.php.swp
deleted file mode 100644 (file)
index c286792..0000000
Binary files a/ng_selfservice/.process_ticket_create.php.swp and /dev/null differ
diff --git a/ng_selfservice/.services.php.swp b/ng_selfservice/.services.php.swp
deleted file mode 100644 (file)
index e063e40..0000000
Binary files a/ng_selfservice/.services.php.swp and /dev/null differ
diff --git a/ng_selfservice/.services_new.php.swp b/ng_selfservice/.services_new.php.swp
deleted file mode 100644 (file)
index 8d0c657..0000000
Binary files a/ng_selfservice/.services_new.php.swp and /dev/null differ
diff --git a/ng_selfservice/.ticket.php.swp b/ng_selfservice/.ticket.php.swp
deleted file mode 100644 (file)
index e9b2503..0000000
Binary files a/ng_selfservice/.ticket.php.swp and /dev/null differ
diff --git a/ng_selfservice/.ticket_create.php.swp b/ng_selfservice/.ticket_create.php.swp
deleted file mode 100644 (file)
index 65b00fe..0000000
Binary files a/ng_selfservice/.ticket_create.php.swp and /dev/null differ
diff --git a/ng_selfservice/.tickets.php.swp b/ng_selfservice/.tickets.php.swp
deleted file mode 100644 (file)
index 7b4d67b..0000000
Binary files a/ng_selfservice/.tickets.php.swp and /dev/null differ
diff --git a/ng_selfservice/.tickets_resolved.php.swp b/ng_selfservice/.tickets_resolved.php.swp
deleted file mode 100644 (file)
index 1b3c634..0000000
Binary files a/ng_selfservice/.tickets_resolved.php.swp and /dev/null differ
diff --git a/ng_selfservice/.usage.php.swp b/ng_selfservice/.usage.php.swp
deleted file mode 100644 (file)
index 61fd4fa..0000000
Binary files a/ng_selfservice/.usage.php.swp and /dev/null differ
diff --git a/ng_selfservice/.usage_cdr.php.swp b/ng_selfservice/.usage_cdr.php.swp
deleted file mode 100644 (file)
index 83c270a..0000000
Binary files a/ng_selfservice/.usage_cdr.php.swp and /dev/null differ
diff --git a/ng_selfservice/.usage_data.php.swp b/ng_selfservice/.usage_data.php.swp
deleted file mode 100644 (file)
index e5a9272..0000000
Binary files a/ng_selfservice/.usage_data.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.card.php.swp b/ng_selfservice/elements/.card.php.swp
deleted file mode 100644 (file)
index 15d30ce..0000000
Binary files a/ng_selfservice/elements/.card.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.check.php.swp b/ng_selfservice/elements/.check.php.swp
deleted file mode 100644 (file)
index fe08303..0000000
Binary files a/ng_selfservice/elements/.check.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.error.php.swp b/ng_selfservice/elements/.error.php.swp
deleted file mode 100644 (file)
index 1a6eb28..0000000
Binary files a/ng_selfservice/elements/.error.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.header.php.swp b/ng_selfservice/elements/.header.php.swp
deleted file mode 100644 (file)
index 2371770..0000000
Binary files a/ng_selfservice/elements/.header.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.menu.php.swp b/ng_selfservice/elements/.menu.php.swp
deleted file mode 100644 (file)
index 0c29ff9..0000000
Binary files a/ng_selfservice/elements/.menu.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.menu_footer.php.swp b/ng_selfservice/elements/.menu_footer.php.swp
deleted file mode 100644 (file)
index 4bd2b30..0000000
Binary files a/ng_selfservice/elements/.menu_footer.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.session.php.swp b/ng_selfservice/elements/.session.php.swp
deleted file mode 100644 (file)
index ddd0137..0000000
Binary files a/ng_selfservice/elements/.session.php.swp and /dev/null differ
diff --git a/ng_selfservice/elements/.ticketlist.php.swp b/ng_selfservice/elements/.ticketlist.php.swp
deleted file mode 100644 (file)
index db3d0fe..0000000
Binary files a/ng_selfservice/elements/.ticketlist.php.swp and /dev/null differ
diff --git a/ng_selfservice/js/.menu.js.swp b/ng_selfservice/js/.menu.js.swp
deleted file mode 100644 (file)
index 8df94a9..0000000
Binary files a/ng_selfservice/js/.menu.js.swp and /dev/null differ
index 4a6bfda..2dc16e3 100644 (file)
@@ -2070,7 +2070,6 @@ sub _ProcessUpdateMessageRecipients {
     if (grep $_ eq 'Requestor' || $_ eq 'Requestors', @{ $args{ARGSRef}->{'SkipNotification'} || [] }) {
         push @txn_squelch, map $_->address, Email::Address->parse( $message_args->{Requestor} );
         push @txn_squelch, $args{TicketObj}->Requestors->MemberEmailAddresses;
-
     }
 
     push @txn_squelch, @{$args{ARGSRef}{SquelchMailTo}} if $args{ARGSRef}{SquelchMailTo};
@@ -2092,6 +2091,39 @@ sub _ProcessUpdateMessageRecipients {
     }
 }
 
+sub ProcessAttachments {
+    my %args = (
+        ARGSRef => {},
+        @_
+    );
+
+    my $ARGSRef = $args{ARGSRef} || {};
+    # deal with deleting uploaded attachments
+    foreach my $key ( keys %$ARGSRef ) {
+        if ( $key =~ m/^DeleteAttach-(.+)$/ ) {
+            delete $session{'Attachments'}{$1};
+        }
+        $session{'Attachments'} = { %{ $session{'Attachments'} || {} } };
+    }
+
+    # store the uploaded attachment in session
+    if ( defined $ARGSRef->{'Attach'} && length $ARGSRef->{'Attach'} )
+    {    # attachment?
+        my $attachment = MakeMIMEEntity( AttachmentFieldName => 'Attach' );
+
+        my $file_path = Encode::decode_utf8("$ARGSRef->{'Attach'}");
+        $session{'Attachments'} =
+          { %{ $session{'Attachments'} || {} }, $file_path => $attachment, };
+    }
+
+    # delete temporary storage entry to make WebUI clean
+    unless ( keys %{ $session{'Attachments'} } and $ARGSRef->{'UpdateAttach'} )
+    {
+        delete $session{'Attachments'};
+    }
+}
+
+
 =head2 MakeMIMEEntity PARAMHASH
 
 Takes a paramhash Subject, Body and AttachmentFieldName.
@@ -2174,37 +2206,6 @@ sub MakeMIMEEntity {
 
 }
 
-sub ProcessAttachments {
-    my %args = (
-        ARGSRef => {},
-        @_
-    );
-
-    my $ARGSRef = $args{ARGSRef} || {};
-    # deal with deleting uploaded attachments
-    foreach my $key ( keys %$ARGSRef ) {
-        if ( $key =~ m/^DeleteAttach-(.+)$/ ) {
-            delete $session{'Attachments'}{$1};
-        }
-        $session{'Attachments'} = { %{ $session{'Attachments'} || {} } };
-    }
-
-    # store the uploaded attachment in session
-    if ( defined $ARGSRef->{'Attach'} && length $ARGSRef->{'Attach'} )
-    {    # attachment?
-        my $attachment = MakeMIMEEntity( AttachmentFieldName => 'Attach' );
-
-        my $file_path = Encode::decode_utf8("$ARGSRef->{'Attach'}");
-        $session{'Attachments'} =
-          { %{ $session{'Attachments'} || {} }, $file_path => $attachment, };
-    }
-
-    # delete temporary storage entry to make WebUI clean
-    unless ( keys %{ $session{'Attachments'} } and $ARGSRef->{'UpdateAttach'} )
-    {
-        delete $session{'Attachments'};
-    }
-}
 
 
 =head2 ParseDateToISO
index 26a37e8..8a3d8e3 100755 (executable)
@@ -290,6 +290,7 @@ if ( $ARGS{'SubmitTicket'} ) {
 
     my %squelched = ProcessTransactionSquelching( \%ARGS );
     $ARGS{'SquelchMailTo'} = [keys %squelched] if keys %squelched;
+warn @{ $ARGS{'SquelchMailTo'} } if $ARGS{'SquelchMailTo'};
 
     my $CFs = $TicketObj->TransactionCustomFields;
     my $ValidCFs = $m->comp(
@@ -311,6 +312,7 @@ if ( $ARGS{'SubmitTicket'} ) {
     );
     $checks_failure = 1 unless $status;
 }
+warn @{ $ARGS{'SquelchMailTo'} } if $ARGS{'SquelchMailTo'};
 
 # check email addresses for RT's
 {