CUSTOM packages/actual flag for custom packages #3988
authorjeff <jeff>
Sun, 21 Jun 2009 15:21:32 +0000 (15:21 +0000)
committerjeff <jeff>
Sun, 21 Jun 2009 15:21:32 +0000 (15:21 +0000)
23 files changed:
FS/FS/Schema.pm
FS/FS/cust_pkg.pm
FS/FS/part_pkg.pm
httemplate/browse/agent_type.cgi
httemplate/browse/part_pkg.cgi
httemplate/edit/REAL_cust_pkg.cgi
httemplate/edit/agent_type.cgi
httemplate/edit/cust_main/first_pkg/select-part_pkg.html
httemplate/edit/cust_pkg.cgi
httemplate/edit/part_bill_event.cgi
httemplate/edit/part_pkg.cgi
httemplate/edit/reg_code.cgi
httemplate/misc/bulk_change_pkg.cgi
httemplate/misc/cancel_pkg.html
httemplate/misc/cust_main-import.cgi
httemplate/misc/delay_susp_pkg.html
httemplate/misc/meta-import.cgi
httemplate/search/cust_main.cgi
httemplate/search/cust_pkg.cgi
httemplate/search/reg_code.html
httemplate/search/report_cust_pkg.html
httemplate/view/cust_main/packages/package.html
httemplate/view/cust_main/packages/status.html

index d264fd0..69a96a9 100644 (file)
@@ -1191,6 +1191,7 @@ sub tables_hashref {
         'plan',          'varchar', 'NULL', $char_d, '', '', 
         'plandata',      'text', 'NULL', '', '', '', 
         'disabled',      'char', 'NULL', 1, '', '', 
+        'custom',        'char', 'NULL', 1, '', '', 
         'taxclass',      'varchar', 'NULL', $char_d, '', '', 
         'classnum',      'int',     'NULL', '', '', '', 
         'taxproductnum', 'int',     'NULL', '', '', '', 
index 0e5f3b7..a510c52 100644 (file)
@@ -2193,6 +2193,10 @@ active, inactive, suspended, cancel (or cancelled)
 
 active, inactive, suspended, one-time charge, inactive, cancel (or cancelled)
 
+=item custom
+
+ boolean selects custom packages
+
 =item classnum
 
 =item pkgpart
@@ -2321,6 +2325,12 @@ sub search_sql {
   #eslaf
 
   ###
+  # parse custom
+  ###
+
+  push @where,  "part_pkg.custom = 'Y'" if $params->{custom};
+
+  ###
   # parse part_pkg
   ###
 
index fe56c62..0562a6d 100644 (file)
@@ -85,6 +85,8 @@ inherits from FS::Record.  The following fields are currently supported:
 
 =item disabled - Disabled flag, empty or `Y'
 
+=item custom - Custom flag, empty or `Y'
+
 =item setup_cost - for cost tracking
 
 =item recur_cost - for cost tracking
@@ -113,9 +115,8 @@ sub table { 'part_pkg'; }
 =item clone
 
 An alternate constructor.  Creates a new package definition by duplicating
-an existing definition.  A new pkgpart is assigned and `(CUSTOM) ' is prepended
-to the comment field.  To add the package definition to the database, see
-L<"insert">.
+an existing definition.  A new pkgpart is assigned and the custom flag is
+set to Y.  To add the package definition to the database, see L<"insert">.
 
 =cut
 
@@ -124,8 +125,7 @@ sub clone {
   my $class = ref($self);
   my %hash = $self->hash;
   $hash{'pkgpart'} = '';
-  $hash{'comment'} = "(CUSTOM) ". $hash{'comment'}
-    unless $hash{'comment'} =~ /^\(CUSTOM\) /;
+  $hash{'custom'} = 'Y';
   #new FS::part_pkg ( \%hash ); # ?
   new $class ( \%hash ); # ?
 }
@@ -452,6 +452,7 @@ sub check {
     || $self->ut_enum('recurtax', [ '', 'Y' ] )
     || $self->ut_textn('taxclass')
     || $self->ut_enum('disabled', [ '', 'Y' ] )
+    || $self->ut_enum('custom', [ '', 'Y' ] )
     #|| $self->ut_moneyn('setup_cost')
     #|| $self->ut_moneyn('recur_cost')
     || $self->ut_floatn('setup_cost')
@@ -488,20 +489,30 @@ sub check {
   '';
 }
 
-=item pkg_comment
+=item pkg_comment [ OPTION => VALUE... ]
 
 Returns an (internal) string representing this package.  Currently,
 "pkgpart: pkg - comment", is returned.  "pkg - comment" may be returned in the
-future, omitting pkgpart.
+future, omitting pkgpart.  The comment will have '(CUSTOM) ' prepended if
+custom is Y.
+
+If the option nopkgpart is true then the "pkgpart: ' is omitted.
 
 =cut
 
 sub pkg_comment {
   my $self = shift;
+  my %opt = @_;
 
   #$self->pkg. ' - '. $self->comment;
   #$self->pkg. ' ('. $self->comment. ')';
-  $self->pkgpart. ': '. $self->pkg. ' - '. $self->comment;
+  my $pre = $opt{nopkgpart} ? '' : $self->pkgpart. ': ';
+  $pre. $self->pkg. ' - '. $self->custom_comment;
+}
+
+sub custom_comment {
+  my $self = shift;
+  ( $self->custom ? '(CUSTOM) ' : '' ). $self->comment;
 }
 
 =item pkg_class
@@ -1257,6 +1268,33 @@ sub _upgrade_data { # class method
 
   }
 
+  # now upgrade to the explicit custom flag
+
+  @part_pkg = qsearch({
+    'table'     => 'part_pkg',
+    'hashref'   => { disabled => 'Y', custom => '' },
+    'extra_sql' => "AND comment LIKE '(CUSTOM) %'",
+  });
+
+  foreach my $part_pkg (@part_pkg) {
+    my $new = new FS::part_pkg { $part_pkg->hash };
+    $new->custom('Y');
+    my $comment = $part_pkg->comment;
+    $comment =~ s/^\(CUSTOM\) //;
+    $new->comment($comment);
+
+    my $pkg_svc = { map { $_->svcpart => $_->quantity } $part_pkg->pkg_svc };
+    my $primary = $part_pkg->svcpart;
+    my $options = { $part_pkg->options };
+
+    my $error = $new->replace( $part_pkg,
+                               'pkg_svc'     => $pkg_svc,
+                               'primary_svc' => $primary,
+                               'options'     => $options,
+                             );
+    die $error if $error;
+  }
+
 }
 
 =item curuser_pkgs_sql
@@ -1379,6 +1417,8 @@ plandata should go
 
 part_pkg_taxrate is Pg specific
 
+replace should be smarter about managing the related tables (options, pkg_svc)
+
 =head1 SEE ALSO
 
 L<FS::Record>, L<FS::cust_pkg>, L<FS::type_pkgs>, L<FS::pkg_svc>, L<Safe>.
index d64ff18..f07a651 100755 (executable)
@@ -44,7 +44,9 @@ my $agent_type = shift;
          [
            {
              #'data'  => $part_pkg->pkg. ' - '. $part_pkg->comment,
-             'data'  => $type_pkgs->pkg. ' - '. $type_pkgs->comment,
+             'data'  => $type_pkgs->pkg. ' - '.
+                        ( $type_pkgs->custom ? '(CUSTOM) ' : '' ).
+                        $type_pkgs->comment,
              'align' => 'left',
              'link'  => $p. 'edit/part_pkg.cgi?'. $type_pkgs->pkgpart,
            },
index 8c961b8..c6cbb81 100755 (executable)
@@ -4,11 +4,11 @@
                  'html_posttotal'        => $html_posttotal,
                  'name'                  => 'package definitions',
                  'disableable'           => 1,
-                 'disabled_statuspos'    => 3,
+                 'disabled_statuspos'    => 4,
                  'agent_virt'            => 1,
                  'agent_null_right'      => [ $edit, $edit_global ],
                  'agent_null_right_link' => $edit_global,
-                 'agent_pos'             => 5,
+                 'agent_pos'             => 6,
                  'query'                 => { 'select'    => $select,
                                               'table'     => 'part_pkg',
                                               'hashref'   => \%hash,
@@ -164,10 +164,12 @@ $cgi->param('recurring', $cgi->param('recurring') ^ 1 ); #put it back
 
 my $link = [ $p.'edit/part_pkg.cgi?', 'pkgpart' ];
 
-my @header = ( '#', 'Package', 'Comment' );
-my @fields = ( 'pkgpart', 'pkg', 'comment' );
-my $align = 'rll';
-my @links = ( $link, $link, '' );
+my @header = ( '#', 'Package', 'Comment', 'Custom' );
+my @fields = ( 'pkgpart', 'pkg', 'comment',
+               sub{ '<B><FONT COLOR="#0000CC">'.$_[0]->custom.'</FONT></B>' }
+             );
+my $align = 'rllc';
+my @links = ( $link, $link, '', '' );
 
 unless ( 0 ) { #already showing only one class or something?
   push @header, 'Class';
index b2c89c3..a707aca 100755 (executable)
   </TR>
 
   <TR>
+    <TD ALIGN="right">Custom</TD>
+    <TD BGCOLOR="#ffffff"><% $part_pkg->custom %></TD>
+  </TR>
+
+  <TR>
     <TD ALIGN="right">Comment</TD>
     <TD BGCOLOR="#ffffff"><% $part_pkg->comment %></TD>
   </TR>
index abf4bf8..8a6fbc2 100755 (executable)
@@ -20,7 +20,7 @@ Select which packages agents of this type may sell to customers<BR>
               'source_obj'    => $agent_type,
               'link_table'    => 'type_pkgs',
               'target_table'  => 'part_pkg',
-              'name_callback' => sub { $_[0]->pkg. ' - '. $_[0]->comment; },
+              'name_callback' => sub { $_[0]->pkg_comment(nopkgpart => 1); },
               'target_link'   => $p.'edit/part_pkg.cgi?',
               'disable-able'  => 1,
 
index 1b62035..d2d862b 100644 (file)
@@ -141,9 +141,7 @@ foreach my $part_pkg ( @part_pkg ) {
 
 my @options = ( '', map $pkgpart_svcpart{ $_->pkgpart }, @part_pkg );
 my %labels = ( '' => '(none)',
-               map { $pkgpart_svcpart{ $_->pkgpart }
-                       => $_->pkg. " - ". $_->comment
-                   }
+               map { $pkgpart_svcpart{ $_->pkgpart } => $_->pkg_comment }
                    @part_pkg
              );
 
index f927e10..dd1ed33 100755 (executable)
@@ -128,10 +128,10 @@ my %all_comment = ();
 #}
 foreach (qsearch('part_pkg', {} )) {
   $all_pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
-  $all_comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+  $all_comment{ $_ -> getfield('pkgpart') } = $_->custom_comment;
   next if $_->disabled;
   $pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg');
-  $comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment');
+  $comment{ $_ -> getfield('pkgpart') } = $_->custom_comment;
 }
 
 my($custnum, %remove_pkg);
index 3b51141..ffd642b 100755 (executable)
@@ -78,7 +78,7 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
 %  join("\n", map {
 %    '<OPTION VALUE="'. $_->pkgpart. '"'.
 %    ( $selected{$_->pkgpart} ? ' SELECTED' : '' ).
-%    '>'. $_->pkg. ' - '. $_->comment
+%    '>'. $_->pkg_comment
 %  } qsearch('part_pkg', { 'disabled' => '' } ) ).
 %  '</SELECT>';
 %}
index 6391db9..0934f50 100755 (executable)
@@ -58,6 +58,8 @@
                                 sub { shift->param('pkgnum') },
                             },
 
+                            { field=>'custom',  type=>'hidden' },
+
                             { type => 'columnstart' },
                             
                               { field     => 'pkg',
@@ -217,10 +219,7 @@ my $disabled_type = $acl_edit_either ? 'checkbox' : 'hidden';
 
 my $agent_clone_extra_sql = 
   ' ( '. FS::part_pkg->curuser_pkgs_sql.
-  #kludge to clone custom customer packages you otherwise couldn't see
-  #really need a proper "CUSTOM" flag that's distinct from disabled
-  #"   OR ( part_pkg.disabled = 'Y' AND part_pkg.comment LIKE '(CUSTOM)%' ) ".
-  "   OR ( part_pkg.disabled = 'Y' ) ".
+  "   OR ( part_pkg.custom = 'Y' ) ".
   ' ) ';
 
 my $conf = new FS::Conf;
@@ -339,9 +338,8 @@ my $clone_callback = sub {
     $opt->{action} = 'Custom';
 
     #my $part_pkg = $clone_part_pkg->clone;
-    #this is all clone did anyway
-    $object->comment( '(CUSTOM) '. $object->comment )
-      unless $object->comment =~ /^\(CUSTOM\) /;
+    #this is all clone does anyway
+    $object->custom('Y');
 
     $object->disabled('Y');
 
index e57ac09..76790ab 100644 (file)
@@ -18,7 +18,7 @@ registration codes for <B><% $agent->agent %></B> allowing the following package
 %   my $pkgpart = $part_pkg->pkgpart;
 
     <INPUT TYPE="checkbox" NAME="pkgpart<% $pkgpart %>" <% $cgi->param("pkgpart$pkgpart") ? 'CHECKED' : '' %>>
-    <% $part_pkg->pkg %> - <% $part_pkg->comment %>
+    <% $part_pkg->pkg_comment %>
     <BR>
 
 % } 
index 9334985..3bb6775 100755 (executable)
                      'table'          => 'part_pkg',
                      'name_col'       => 'pkg',
                      'empty_label'    => 'Select package',
-                     'label_callback' => sub { $_[0]->pkgpart. ': '.
-                                               $_[0]->pkg.     ' - '.
-                                               $_[0]->comment;
-                                             },
+                     'label_callback' => sub { $_[0]->pkg_comment },
                      'element_name'   => 'new_pkgpart',
                      'curr_value'     => ( $cgi->param('error')
                                            ? scalar($cgi->param('new_pkgpart'))
index e0e5fd1..1228eb1 100755 (executable)
@@ -17,7 +17,7 @@
 
 
 <BR><BR>
-<% ucfirst($method) . " $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% ucfirst($method) . $part_pkg->pkg_comment %>
 <% ntable("#cccccc", 2) %>
 
 % if ($method eq 'expire' || $method eq 'adjourn') {
index b822c5d..9c1f984 100644 (file)
@@ -56,7 +56,7 @@ Import a file containing customer records.
     <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION>
 % foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) { 
 
-       <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION>
+       <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg_comment %></OPTION>
 % } 
 
     </SELECT>
index 1158a35..d4a6da1 100755 (executable)
@@ -12,7 +12,7 @@
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
 
 <BR><BR>
-<% "Delay automatic suspension of $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% "Delay automatic suspension of " .$part_pkg->pkg_comment %>
 <% ntable("#cccccc", 2) %>
 
 <TR>
index 5b3470c..8c158bd 100644 (file)
@@ -46,7 +46,7 @@ Import data from a DBI data source<BR><BR>
     First package: <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION>
 % foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) { 
 
-     <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION>
+     <OPTION VALUE="<% $part_pkg->pkgpart %>"><% $part_pkg->pkg_comment %></OPTION>
 % } 
 
 </SELECT><BR><BR>
index 658069b..e65dc71 100755 (executable)
 %#      my $part_pkg = qsearchs( 'part_pkg', { pkgpart => $_->pkgpart } );
 %      my $part_pkg = $_->part_pkg;
 %
-%      my $pkg = $part_pkg->pkg;
-%      my $comment = $part_pkg->comment;
+%      my $pkg_comment = $part_pkg->pkg_comment(nopkgpart => 1);
 %      my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
 %                   ? ''
 %                   : ';show=packages';
 %      #my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } );
 %      my $rowspan = scalar(@cust_svc) || 1;
 %
-%      print $n1, qq!<TD CLASS="grid" BGCOLOR="$bgcolor"  ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg - $comment</FONT></A></TD>!;
+%      print $n1, qq!<TD CLASS="grid" BGCOLOR="$bgcolor"  ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg_comment</FONT></A></TD>!;
 %
 %      my($n2)='';
 %      foreach my $cust_svc ( @cust_svc ) {
index 2a70280..13d0c7a 100755 (executable)
@@ -161,7 +161,7 @@ my $money_char = $conf->config('money_char') || '$';
   
   $search_hash{'query'} = $cgi->keywords;
   
-  for my $param (qw(agentnum magic status classnum pkgpart)) {
+  for my $param (qw(agentnum magic status classnum pkgpart custom)) {
     $search_hash{$param} = $cgi->param($param)
       if $cgi->param($param);
   }
index f65b00d..f7d6d20 100644 (file)
@@ -13,7 +13,7 @@
                    sub {
                      map { 
                        qq!<A HREF="${p}edit/part_pkg.cgi?!. $_->pkgpart. '">'.
-                       $_->pkg. ' - '. $_->comment.
+                       $_->pkg_comment(nopkgpart => 1).
                        '</A><BR>'
                      } $_[0]->part_pkg
                    },
index b5d2d8b..3840663 100755 (executable)
 
 %   }
     
+    <SCRIPT TYPE="text/javascript">
+  
+      function custom_changed(what) {
+
+        if ( what.checked  ) {
+
+          what.form.pkgpart.disabled = true;
+          what.form.pkgpart.style.backgroundColor = '#dddddd';
+
+        } else {
+
+          what.form.pkgpart.disabled = false;
+          what.form.pkgpart.style.backgroundColor = '#ffffff';
+
+        }
+
+      }
+
+    </SCRIPT>
+
+    <% include( '/elements/tr-checkbox.html',
+                'label' => 'Custom packages',
+                'field' => 'custom',
+                'value' => 1,
+                'onchange' => 'custom_changed(this);',
+              )
+    %> 
+
     <% include( '/elements/tr-selectmultiple-part_pkg.html' ) %> 
 
     <TR>
index 5edbb4d..280a016 100644 (file)
@@ -6,7 +6,7 @@
            ID  ="cust_pkg<% $cust_pkg->pkgnum %>"
         ><% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B></A>
         - 
-        <% $part_pkg->comment |h %>
+        <% $part_pkg->custom_comment |h %>
       </TD>
     </TR>
 
index af407b0..141ed15 100644 (file)
@@ -244,7 +244,7 @@ sub pkg_status_row_changed {
   if ( $old ) {
     my $part_pkg = $old->part_pkg;
     my $label = 'Changed from '. $cust_pkg->change_pkgnum. ': '.
-                $part_pkg->pkg. ' - '. $part_pkg->comment;
+                $part_pkg->pkg_comment(nopartpkg => 1);
     $html .= pkg_status_row_colspan( $label, '', size=>'-1', align=>'right' );
   }
   $html;