further work on agents editing own packages: fix fallout on package customization...
authorivan <ivan>
Mon, 9 Feb 2009 01:49:28 +0000 (01:49 +0000)
committerivan <ivan>
Mon, 9 Feb 2009 01:49:28 +0000 (01:49 +0000)
FS/FS/access_user.pm
FS/FS/part_pkg.pm
httemplate/browse/access_group.html
httemplate/browse/part_pkg.cgi
httemplate/edit/elements/edit.html
httemplate/edit/part_pkg.cgi
httemplate/elements/select-part_pkg.html

index e5c5ed1..63ae30d 100644 (file)
@@ -425,11 +425,7 @@ sub access_right {
     $self->{_ACLcache} = {};
   }
 
-  my $has_right = ' ( '. join(' OR ',
-                                      map { 'rightname = '. dbh->quote($_) }
-                                          @$rightname
-                             ).
-                  ' ) ';
+  my $has_right = ' rightname IN ('. join(',', map '?', @$rightname ). ') ';
 
   my $sth = dbh->prepare("
     SELECT groupnum FROM access_usergroup
@@ -441,7 +437,7 @@ sub access_right {
         AND $has_right
       LIMIT 1
   ") or die dbh->errstr;
-  $sth->execute($self->usernum) or die $sth->errstr;
+  $sth->execute($self->usernum, @$rightname) or die $sth->errstr;
   my $row = $sth->fetchrow_arrayref;
 
   #$row ? $row->[0] : '';
index e53d7b8..3308ead 100644 (file)
@@ -1100,10 +1100,48 @@ sub calc_remain { 0; }
 sub calc_cancel { 0; }
 sub calc_units  { 0; }
 
+=item format OPTION DATA
+
+Returns data formatted according to the function 'format' described
+in the plan info.  Returns DATA if no such function exists.
+
+=cut
+
+sub format {
+  my ($self, $option, $data) = (shift, shift, shift);
+  if (exists($plans{$self->plan}->{fields}->{$option}{format})) {
+    &{$plans{$self->plan}->{fields}->{$option}{format}}($data);
+  }else{
+    $data;
+  }
+}
+
+=item parse OPTION DATA
+
+Returns data parsed according to the function 'parse' described
+in the plan info.  Returns DATA if no such function exists.
+
+=cut
+
+sub parse {
+  my ($self, $option, $data) = (shift, shift, shift);
+  if (exists($plans{$self->plan}->{fields}->{$option}{parse})) {
+    &{$plans{$self->plan}->{fields}->{$option}{parse}}($data);
+  }else{
+    $data;
+  }
+}
+
 =back
 
 =cut
 
+=head1 CLASS METHODS
+
+=over 4
+
+=cut
+
 # _upgrade_data
 #
 # Used by FS::Upgrade to migrate to a new database.
@@ -1170,6 +1208,37 @@ sub _upgrade_data { # class method
 
 }
 
+=item curuser_pkgs_sql
+
+Returns an SQL fragment for searching for packages the current user can
+use, either via part_pkg.agentnum directly, or via agent type (see
+L<FS::type_pkgs>).
+
+=cut
+
+sub curuser_pkgs_sql {
+  #my($class) = shift;
+
+  my $agentnums = join(',', $FS::CurrentUser::CurrentUser->agentnums);
+
+  "
+    (
+      agentnum IS NOT NULL
+      OR
+      0 < ( SELECT COUNT(*)
+              FROM type_pkgs
+                LEFT JOIN agent_type USING ( typenum )
+                LEFT JOIN agent AS typeagent USING ( typenum )
+              WHERE type_pkgs.pkgpart = part_pkg.pkgpart
+                AND typeagent.agentnum IN ($agentnums)
+          )
+    )
+  ";
+
+}
+
+=back
+
 =head1 SUBROUTINES
 
 =over 4
@@ -1217,38 +1286,6 @@ sub plan_info {
   \%plans;
 }
 
-=item format OPTION DATA
-
-Returns data formatted according to the function 'format' described
-in the plan info.  Returns DATA if no such function exists.
-
-=cut
-
-sub format {
-  my ($self, $option, $data) = (shift, shift, shift);
-  if (exists($plans{$self->plan}->{fields}->{$option}{format})) {
-    &{$plans{$self->plan}->{fields}->{$option}{format}}($data);
-  }else{
-    $data;
-  }
-}
-
-=item parse OPTION DATA
-
-Returns data parsed according to the function 'parse' described
-in the plan info.  Returns DATA if no such function exists.
-
-=cut
-
-sub parse {
-  my ($self, $option, $data) = (shift, shift, shift);
-  if (exists($plans{$self->plan}->{fields}->{$option}{parse})) {
-    &{$plans{$self->plan}->{fields}->{$option}{parse}}($data);
-  }else{
-    $data;
-  }
-}
-
 
 =back
 
index cecf3d6..aa9097f 100644 (file)
@@ -81,9 +81,7 @@ my $rights_sub = sub {
     '<TR><TH BGCOLOR="#dcdcdc">'. $_. '</TH></TR>'.
     '<TR><TD>'.
 
-     join('<BR>', grep { warn "$access_group->access_right($_): ".
-                              $access_group->access_right($_). "\n";
-                         $access_group->access_right($_); }
+     join('<BR>', grep { $access_group->access_right($_); }
                    map { ref($_) ? $_->{'rightname'} : $_; }
                        @{ $rights{$_} }
          ).
index cdaa2c9..1fed614 100755 (executable)
@@ -46,25 +46,11 @@ if ( $cgi->param('active') ) {
 
 my $extra_sql = '';
 
-#false laziness w/elements/select-part_pkg.html
-my $agentnums = join(',', $curuser->agentnums);
-
 unless ( $acl_edit_global ) {
-  $extra_sql .= "
-    WHERE (
-      agentnum IS NOT NULL OR 0 < (
-        SELECT COUNT(*)
-          FROM type_pkgs
-            LEFT JOIN agent_type USING ( typenum )
-            LEFT JOIN agent AS typeagent USING ( typenum )
-          WHERE type_pkgs.pkgpart = part_pkg.pkgpart
-            AND typeagent.agentnum IN ($agentnums)
-      )
-    )
-  ";
+  $extra_sql .= ' WHERE '.  FS::part_pkg->curuser_pkgs_sql;
 }
-#eofalse
 
+my $agentnums = join(',', $curuser->agentnums);
 my $count_cust_pkg = "
   SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum )
     WHERE cust_pkg.pkgpart = part_pkg.pkgpart
@@ -97,7 +83,12 @@ my $html_init;
     One or more service definitions are grouped together into a package 
     definition and given pricing information.  Customers purchase packages
     rather than purchase services directly.<BR><BR>
+    <FORM METHOD="POST" ACTION="${p}edit/part_pkg.cgi">
     <A HREF="${p}edit/part_pkg.cgi"><I>Add a new package definition</I></A>
+    or
+    !.include('/elements/select-part_pkg.html', 'element_name' => 'clone' ). qq!
+    <INPUT TYPE="submit" VALUE="Clone existing package">
+    </FORM>
     <BR><BR>
   !;
 #}
index 76fcd38..d18a37d 100644 (file)
@@ -91,8 +91,12 @@ Example:
     'menubar'     => '', #menubar arrayref
 
     #agent virtualization
-    'agent_virt'       => 1,
-    'agent_null_right' => 'Access Right Name',
+    'agent_virt'            => 1,
+    'agent_null_right'      => 'Access Right Name',
+    'agent_clone_extra_sql' => '', #if provided, this overrides the extra_sql
+                                   #implementing agent virt, for clone
+                                   #operations.  i.e. pass "1=1" to allow
+                                   #cloning anything
 
     'viewall_dir' => '', #'search' or 'browse', defaults to 'search'
 
@@ -106,6 +110,8 @@ Example:
     # HTML callbacks
     ###
 
+    'body_etc' => '', # Additional BODY attributes, i.e. onLoad=""
+
     'html_init'   => '', #after the header/menubar
 
     #string or coderef of additional HTML to add before </TABLE>
@@ -172,7 +178,8 @@ Example:
 
 <% include('/elements/header'. ( $opt{popup} ? '-popup' : '' ). '.html',
               $title,
-              include( '/elements/menubar.html', @menubar )
+              include( '/elements/menubar.html', @menubar ),
+              $opt{'body_etc'},
            )
 %>
 
@@ -620,6 +627,9 @@ if ( $cgi->param('error') ) {
 
   $clone = $1;
 
+  $qsearch{'extra_sql'} = ' AND '. $opt{'agent_clone_extra_sql'}
+    if $opt{'agent_clone_extra_sql'};
+
   $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $clone } });
 
   &{$opt{'clone_callback'}}($cgi, $object, $fields, \%opt )
index 3efc26c..5a9bb10 100755 (executable)
@@ -1,25 +1,28 @@
 <% include( 'elements/edit.html',
-              'post_url'         => popurl(1).'process/part_pkg.cgi',
-              'name'             => "Package definition",
-              'table'            => 'part_pkg',
-
-              'agent_virt'       => 1,
-              'agent_null_right' => $edit_global,
-
-              #'viewall_dir'      => 'browse',
-              'viewall_url'      => $p.'browse/part_pkg.cgi',
-              'html_init'        => include('/elements/init_overlib.html').
-                                    $freq_changed,
-              'html_bottom'      => $html_bottom,
-
-              '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,
+              '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' => FS::part_pkg->curuser_pkgs_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,
 
               'labels' => { 
                             'pkgpart'          => 'Package Definition',
@@ -65,6 +68,7 @@
                                 type          => 'select-agent',
                                 disable_empty => ! $acl_edit_global,
                                 empty_label   => '(global)',
+                                onchange      => 'agent_changed',
                               },
                               {field=>'classnum', type=>'select-pkg_class' },
                               {field=>'disabled', type=>$disabled_type, value=>'Y'},
@@ -230,7 +234,7 @@ my $error_callback = sub {
 
   (@agent_type) = $cgi->param('agent_type');
 
-  $opt->{action} = 'Custom' if $cgi->param('clone');
+  $opt->{action} = 'Custom' if $cgi->param('pkgnum');
 
   $recur_disabled = $cgi->param('freq') ? 0 : 1;
 
@@ -309,14 +313,21 @@ my $new_callback = sub {
 my $clone_callback = sub {
   my( $cgi, $object, $fields, $opt ) = @_;
 
-  $opt->{action} = 'Custom';
+  if ( $cgi->param('pkgnum') ) {
 
-  #my $part_pkg = $clone_part_pkg->clone;
-  #this is all clone did anyway
-  $object->comment( '(CUSTOM) '. $object->comment )
-    unless $object->comment =~ /^\(CUSTOM\) /;
+    my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cgi->param('pkgnum') } );
+    $object->agentnum( $cust_pkg->cust_main->agentnum );
 
-  $object->disabled('Y');
+    $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;
 
@@ -343,7 +354,7 @@ my $m2_error_callback_maker = sub {
   };
 };
 
-my $freq_changed = <<'END';
+my $javascript = <<'END';
   <SCRIPT TYPE="text/javascript">
 
     function freq_changed(what) {
@@ -359,6 +370,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
 
index cd6d24c..52b1cca 100644 (file)
@@ -33,20 +33,6 @@ my( %opt ) = @_;
 $opt{'records'} = delete $opt{'part_pkg'}
   if $opt{'part_pkg'};
 
-#false laziness w/browse/part_pkg.cgi
-my $agentnums = join(',', $FS::CurrentUser::CurrentUser->agentnums);
-
-$opt{'extra_sql'} .=
-  " AND ( agentnum IS NOT NULL
-          OR 0 < ( SELECT COUNT(*)
-                     FROM type_pkgs
-                       LEFT JOIN agent_type USING ( typenum )
-                       LEFT JOIN agent AS typeagent USING ( typenum )
-                     WHERE type_pkgs.pkgpart = part_pkg.pkgpart
-                       AND typeagent.agentnum IN ($agentnums)
-                 )
-        )
-  ";
-#eofalse
+$opt{'extra_sql'} .= ' AND '. FS::part_pkg->curuser_pkgs_sql;
 
 </%init>