kludge to clone customer packages you otherwise couldn't see, RT#4854
[freeside.git] / httemplate / edit / part_pkg.cgi
index 3968c89..f404699 100755 (executable)
@@ -1,17 +1,28 @@
 <% include( 'elements/edit.html',
-              'post_url'    => popurl(1).'process/part_pkg.cgi',
-              'name'        => "Package definition",
-              'table'       => 'part_pkg',
-              #'viewall_dir' => 'browse',
-              'viewall_url' => $p.'browse/part_pkg.cgi',
-              'html_init'   => include('/elements/init_overlib.html').
-                               $freq_changed,
-              'html_bottom' => $html_bottom,
-              'new_hashref_callback' => $new_hashref_callback,
-              'new_object_callback'  => $new_object_callback,
-              'new_callback'         => $new_callback,
-              'edit_callback'        => $edit_callback,
-              'error_callback'       => $error_callback,
+              'post_url'              => popurl(1).'process/part_pkg.cgi',
+              'name'                  => "Package definition",
+              'table'                 => 'part_pkg',
+
+              'agent_virt'            => 1,
+              'agent_null_right'      => $edit_global,
+              'agent_clone_extra_sql' => $agent_clone_extra_sql,
+              #'viewall_dir'           => 'browse',
+              'viewall_url'           => $p.'browse/part_pkg.cgi',
+              'html_init'             => include('/elements/init_overlib.html').
+                                         $javascript,
+              'html_bottom'           => $html_bottom,
+              'body_etc'              =>
+                'onLoad="agent_changed(document.edit_topform.agentnum)"',
+
+              'begin_callback'        => $begin_callback,
+              'end_callback'          => $end_callback,
+              'new_hashref_callback'  => $new_hashref_callback,
+              'new_object_callback'   => $new_object_callback,
+              'new_callback'          => $new_callback,
+              'clone_callback'        => $clone_callback,
+              'edit_callback'         => $edit_callback,
+              'error_callback'        => $error_callback,
+              'field_callback'        => $field_callback,
 
               'labels' => { 
                             'pkgpart'          => 'Package Definition',
@@ -28,7 +39,7 @@
                             'disabled'         => 'Disable new orders',
                             'pay_weight'       => 'Payment weight',
                             'credit_weight'    => 'Credit weight',
-                            'agentnum'         => '',
+                            'agentnum'         => 'Agent',
                             'setup_fee'        => 'Setup fee',
                             'recur_fee'        => 'Recurring fee',
                             'bill_dst_pkgpart' => 'Include line item(s) from package',
 
                             { type => 'columnstart' },
                             
-                              {field=>'pkg',      type=>'text', size=>40 }, #32
+                              { field     => 'pkg',
+                                type      => 'text',
+                                size      => 40, #32
+                                maxlength => 50,
+                              },
                               {field=>'comment',  type=>'text', size=>40 }, #32
+                              { field         => 'agentnum',
+                                type          => 'select-agent',
+                                disable_empty => ! $acl_edit_global,
+                                empty_label   => '(global)',
+                                onchange      => 'agent_changed',
+                              },
                               {field=>'classnum', type=>'select-pkg_class' },
-                              {field=>'disabled', type=>'checkbox', value=>'Y'},
+                              {field=>'disabled', type=>$disabled_type, value=>'Y'},
 
                               { type  => 'tablebreak-tr-title',
                                 value => 'Pricing', #better name?
                                            },
                                 layer_fields => \%taxproduct_fields,
                                 layer_values_callback => $taxproduct_values,
+                                layers_only  =>   !$taxproducts,
+                                cell_style   => ( !$taxproducts
+                                                  ? 'display:none'
+                                                  : ''
+                                                ),
                               },
 
                               { type  => 'tablebreak-tr-title',
 
                             { type => 'columnnext' },
 
-                              { field=>'agent_type',
-                                type => 'select-agent_types',
+                              { field    => 'agent_type',
+                                type     => 'select-agent_types',
+                                disabled => ! $acl_edit_global,
                                 curr_value_callback => sub {
                                   my($cgi, $object, $field) = @_;
                                   #in the other callbacks..?  hmm.
 
 my $curuser = $FS::CurrentUser::CurrentUser;
 
-die "access denied"
-  unless $curuser->access_right('Edit package definitions')
-      || $curuser->access_right('Edit global package definitions')
-      || ( $cgi->param('pkgnum') && $curuser->access_right('Customize customer package') );
+my $edit_global = 'Edit global package definitions';
+my $acl_edit        = $curuser->access_right('Edit package definitions');
+my $acl_edit_global = $curuser->access_right($edit_global);
+
+my $acl_edit_either = $acl_edit || $acl_edit_global;
+
+my $begin_callback = sub {
+  my( $cgi, $fields, $opt ) = @_;
+  die "access denied"
+    unless $acl_edit_either
+        || ( $cgi->param('pkgnum')
+             && $curuser->access_right('Customize customer package')
+           );
+};
+
+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
+  "   OR ( part_pkg.disabled = 'Y' AND part_pkg.comment LIKE '(CUSTOM)%' ) ".
+  ' ) ';
+
+my $conf = new FS::Conf;
+my $taxproducts = $conf->exists('enable_taxproducts');
 
 #XXX
 # - tr-part_pkg_freq: month_increments_only (from price plans)
@@ -181,43 +229,28 @@ die "access denied"
 my @agent_type = ();
 my %tax_override = ();
 
-my $clone_part_pkg = '';
-
 my %taxproductnums = map { ($_->classnum => 1) }
                      qsearch('usage_class', { 'disabled' => '' });
-
-if ( $cgi->param('error') ) {  # oh well
-  foreach ($cgi->param) {
-    /^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
-  }
-} elsif ( my $pkgpart = $cgi->keywords || $cgi->param('pkgpart') ) {
-  $pkgpart =~ /^(\d+)$/ or die "illegal pkgpart";
-  my $part_pkg = qsearchs( 'part_pkg', { pkgpart => $pkgpart } );
-  die "no part_pkg for pkgpart $pkgpart" unless $pkgpart;
-  foreach ($part_pkg->options) {
-    /^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
-  }
-  foreach ($part_pkg->part_pkg_taxoverride) {
-    $taxproductnums{$_->usage_class} = 1
-      if $_->usage_class;
-  }
-} else {
-  # do nothing
-}
 my @taxproductnums = ( qw( setup recur ), sort (keys %taxproductnums) );
 
 my %options = ();
 my $recur_disabled = 1;
+
 my $error_callback = sub {
   my($cgi, $object, $fields, $opt ) = @_;
+
   (@agent_type) = $cgi->param('agent_type');
+
+  $opt->{action} = 'Custom' if $cgi->param('pkgnum');
+
+  $recur_disabled = $cgi->param('freq') ? 0 : 1;
+
+  foreach ($cgi->param) {
+    /^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
+  }
   $tax_override{''} = $cgi->param('tax_override');
   $tax_override{$_} = $cgi->param('tax_override_$_')
     foreach(grep { /^tax_override_(\w+)$/ } $cgi->param);
-  $opt->{action} = 'Custom' if $cgi->param('clone');
-  $clone_part_pkg= qsearchs('part_pkg', { 'pkgpart' => $cgi->param('clone') } );
-
-  $recur_disabled = $cgi->param('freq') ? 0 : 1;
 
   #some false laziness w/process
   $cgi->param('plan') =~ /^(\w+)$/ or die 'unparsable plan';
@@ -243,20 +276,9 @@ my $new_hashref_callback = sub { { 'plan' => 'flat' }; };
 my $new_object_callback = sub {
   my( $cgi, $hashref, $fields, $opt ) = @_;
 
-  my $part_pkg = '';
-  if ( $cgi->param('clone') ) {
-    $opt->{action} = 'Custom';
-    $clone_part_pkg = qsearchs('part_pkg', { pkgpart=>$cgi->param('clone') } );
-    $part_pkg = $clone_part_pkg->clone;
-    $part_pkg->disabled('Y');
-    %options = $clone_part_pkg->options;
-    $part_pkg->set($_ => $options{$_})
-      foreach (qw( setup_fee recur_fee ));
-  } else {
-    $part_pkg = FS::part_pkg->new( $hashref );
-    $part_pkg->set($_ => '0')
-      foreach (qw( setup_fee recur_fee ));
-  }
+  my $part_pkg = FS::part_pkg->new( $hashref );
+  $part_pkg->set($_ => '0')
+    foreach (qw( setup_fee recur_fee ));
 
   $part_pkg;
 
@@ -268,19 +290,14 @@ my $edit_callback = sub {
   $recur_disabled = $object->freq ? 0 : 1;
 
   (@agent_type) = map {$_->typenum} qsearch('type_pkgs',{'pkgpart'=>$1});
-  $tax_override{$_} =
-    join (",", map {$_->taxclassnum}
-               qsearch( 'part_pkg_taxoverride', { 'pkgpart' => $object->pkgpart,
-                                                  'usage_class' => $_,
-                                                }
-                      )
-         )
-    foreach ( '', @taxproductnums );
-
-#    join (",", map {$_->taxclassnum}
-#               $part_pkg->part_pkg_taxrate( 'cch', $conf->config('defaultloc')
-#         );
-#      unless $tax_override;
+
+  foreach ($object->options) {
+    /^usage_taxproductnum_(\d+)$/ && ($taxproductnums{$1} = 1);
+  }
+  foreach ($object->part_pkg_taxoverride) {
+    $taxproductnums{$_->usage_class} = 1
+      if $_->usage_class;
+  }
 
   %options = $object->options;
 
@@ -300,6 +317,33 @@ my $new_callback = sub {
 
 };
 
+my $clone_callback = sub {
+  my( $cgi, $object, $fields, $opt ) = @_;
+
+  if ( $cgi->param('pkgnum') ) {
+
+    my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cgi->param('pkgnum') } );
+    $object->agentnum( $cust_pkg->cust_main->agentnum );
+
+    $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\) /;
+
+    $object->disabled('Y');
+
+  }
+
+  %options = $object->options;
+
+  $object->set($_ => $options{$_})
+    foreach (qw( setup_fee recur_fee ));
+
+  $recur_disabled = $object->freq ? 0 : 1;
+};
+
 my $m2_error_callback_maker = sub {
   my $link_type = shift; #yay closures
   return sub {
@@ -317,7 +361,7 @@ my $m2_error_callback_maker = sub {
   };
 };
 
-my $freq_changed = <<'END';
+my $javascript = <<'END';
   <SCRIPT TYPE="text/javascript">
 
     function freq_changed(what) {
@@ -333,6 +377,22 @@ my $freq_changed = <<'END';
 
     }
 
+    function agent_changed(what) {
+
+      var agentnum = what.options[what.selectedIndex].value;
+
+      if ( agentnum == 0 ) {
+        what.form.agent_type.disabled = false;
+        //what.form.agent_type.style.backgroundColor = '#ffffff';
+        what.form.agent_type.style.visibility = '';
+      } else {
+        what.form.agent_type.disabled = true;
+        //what.form.agent_type.style.backgroundColor = '#dddddd';
+        what.form.agent_type.style.visibility = 'hidden';
+      }
+
+    }
+
   </SCRIPT>
 END
 
@@ -473,11 +533,18 @@ my $html_bottom = sub {
     layer_callback => $layer_callback,
   );
 
-  include('/elements/selectlayers.html', %selectlayers, 'layers_only'=>1 ).
-  '<SCRIPT TYPE="text/javascript">'.
-    include('/elements/selectlayers.html', %selectlayers, 'js_only'=>1 ).
-    "taxproduct_selectchanged(document.getElementById('taxproduct_select'));".
-  '</SCRIPT>';
+  my $return =
+    include('/elements/selectlayers.html', %selectlayers, 'layers_only'=>1 ).
+    '<SCRIPT TYPE="text/javascript">'.
+      include('/elements/selectlayers.html', %selectlayers, 'js_only'=>1 );
+
+  $return .=
+    "taxproduct_selectchanged(document.getElementById('taxproduct_select'));\n"
+      if $taxproducts;
+
+  $return .= '</SCRIPT>';
+
+  $return;
 
 };
 
@@ -486,21 +553,42 @@ my %usage_class = map { ($_->classnum => $_->classname) }
 $usage_class{setup} = 'Setup';
 $usage_class{recur} = 'Recurring';
 
-my %taxproduct_fields = map { $_ => [ "taxproductnum_$_", 
-                                      { type  => 'select-taxproduct',
-                                        #label => "$usage_class{$_} tax product",
-                                      },
-                                      "tax_override_$_", 
-                                      { type  => 'select-taxoverride' }
-                                    ]
-                            }
-                         @taxproductnums;
-$taxproduct_fields{'(default)'} =
-  [ 'taxproductnum', { type => 'select-taxproduct',
-                       #label => 'Default tax product',
-                     },
-    'tax_override',  { type => 'select-taxoverride' },
-  ];
+my %taxproduct_fields = ();
+my $end_callback = sub {
+  my( $cgi, $object, $fields, $opt ) = @_;
+
+  @taxproductnums = ( qw( setup recur ), sort (keys %taxproductnums) );
+
+  if ( $object->pkgpart ) {
+    foreach my $usage_class ( '', @taxproductnums ) {
+      $tax_override{$usage_class} =
+        join (",", map $_->taxclassnum,
+                       qsearch( 'part_pkg_taxoverride', {
+                                  'pkgpart'     => $object->pkgpart,
+                                  'usage_class' => $usage_class,
+                              })
+             );
+    }
+  }
+
+  %taxproduct_fields =
+    map { $_ => [ "taxproductnum_$_", 
+                  { type  => 'select-taxproduct',
+                    #label => "$usage_class{$_} tax product",
+                  },
+                  "tax_override_$_", 
+                  { type  => 'select-taxoverride' }
+                ]
+        }
+        @taxproductnums;
+
+  $taxproduct_fields{'(default)'} =
+    [ 'taxproductnum', { type => 'select-taxproduct',
+                         #label => 'Default tax product',
+                       },
+      'tax_override',  { type => 'select-taxoverride' },
+    ];
+};
 
 my $taxproduct_values = sub {
   my ($cgi, $object, $flags) = @_;
@@ -529,4 +617,21 @@ my $taxproduct_values = sub {
   
 };
 
+my $field_callback = sub {
+  my ($cgi, $object, $fieldref) = @_;
+
+  my $field = $fieldref->{field};
+  if ($field eq 'taxproductnums') {
+    $fieldref->{value} = join(',', @taxproductnums);
+  } elsif ($field eq 'taxproduct_select') {
+    $fieldref->{options} = [ '(default)', @taxproductnums ];
+    $fieldref->{labels}  = { ( '(default)' => '(default)' ),
+                             map {( $_ => ($usage_class{$_} || $_) )}
+                               @taxproductnums
+                           };
+    $fieldref->{layer_fields} = \%taxproduct_fields;
+    $fieldref->{layer_values_callback} = $taxproduct_values;
+  }
+};
+
 </%init>