summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan <ivan>2006-06-18 12:54:49 +0000
committerivan <ivan>2006-06-18 12:54:49 +0000
commitc738a3c4923774b64960aa87fa58bd0751487edb (patch)
treee037c5c2e1211dd16c8024f16c9ce4d1fe589efb
parentaaad08cae3a0d46d012de5b78360101cda836c30 (diff)
ACLs: finish group edit (agents + rights) & browse
-rw-r--r--FS/FS/AccessRight.pm139
-rw-r--r--FS/FS/access_group.pm57
-rw-r--r--FS/FS/access_groupagent.pm24
-rw-r--r--FS/FS/m2name_Common.pm95
-rw-r--r--FS/FS/part_pkg.pm53
-rw-r--r--FS/MANIFEST3
-rw-r--r--htetc/handler.pl4
-rw-r--r--httemplate/browse/access_group.html45
-rw-r--r--httemplate/browse/access_user.html2
-rw-r--r--httemplate/edit/access_group.html36
-rw-r--r--httemplate/edit/elements/edit.html21
-rwxr-xr-xhttemplate/edit/part_pkg.cgi2
-rw-r--r--httemplate/edit/process/access_group.html10
-rw-r--r--httemplate/edit/process/elements/process.html15
-rw-r--r--httemplate/elements/checkboxes-table-name.html85
-rw-r--r--httemplate/elements/checkboxes-table.html28
16 files changed, 520 insertions, 99 deletions
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index 01d63e3..5229e1e 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -1,7 +1,7 @@
package FS::AccessRight;
use strict;
-user vars qw(@rights %rights);
+use vars qw(@rights); # %rights);
use Tie::IxHash;
=head1 NAME
@@ -19,59 +19,94 @@ assigned to users and/or groups.
=cut
+#@rights = (
+# 'Reports' => [
+# '_desc' => 'Access to high-level reporting',
+# ],
+# 'Configuration' => [
+# '_desc' => 'Access to configuration',
+#
+# 'Settings' => {},
+#
+# 'agent' => [
+# '_desc' => 'Master access to reseller configuration',
+# 'agent_type' => {},
+# 'agent' => {},
+# ],
+#
+# 'export_svc_pkg' => [
+# '_desc' => 'Access to export, service and package configuration',
+# 'part_export' => {},
+# 'part_svc' => {},
+# 'part_pkg' => {},
+# 'pkg_class' => {},
+# ],
+#
+# 'billing' => [
+# '_desc' => 'Access to billing configuration',
+# 'payment_gateway' => {},
+# 'part_bill_event' => {},
+# 'prepay_credit' => {},
+# 'rate' => {},
+# 'cust_main_county' => {},
+# ],
+#
+# 'dialup' => [
+# '_desc' => 'Access to dialup configuraiton',
+# 'svc_acct_pop' => {},
+# ],
+#
+# 'broadband' => [
+# '_desc' => 'Access to broadband configuration',
+# 'router' => {},
+# 'addr_block' => {},
+# ],
+#
+# 'misc' => [
+# 'part_referral' => {},
+# 'part_virtual_field' => {},
+# 'msgcat' => {},
+# 'inventory_class' => {},
+# ],
+#
+# },
+#
+#);
+#
+##turn it into a more hash-like structure, but ordered via IxHash
+
+#well, this is what we have for now. could be ordered better, could be lots of
+# things better, but this ACL system does 99% of what folks need and the UI
+# isn't *that* bad
@rights = (
- 'Reports' => [
- '_desc' => 'Access to high-level reporting',
- ],
- 'Configuration' => [
- '_desc' => 'Access to configuration',
-
- 'Settings' => {},
-
- 'agent' => [
- '_desc' => 'Master access to reseller configuration',
- 'agent_type' => {},
- 'agent' => {},
- ],
-
- 'export_svc_pkg' => [
- '_desc' => 'Access to export, service and package configuration',
- 'part_export' => {},
- 'part_svc' => {},
- 'part_pkg' => {},
- 'pkg_class' => {},
- ],
-
- 'billing' => [
- '_desc' => 'Access to billing configuration',
- 'payment_gateway' => {},
- 'part_bill_event' => {},
- 'prepay_credit' => {},
- 'rate' => {},
- 'cust_main_county' => {},
- ],
-
- 'dialup' => [
- '_desc' => 'Access to dialup configuraiton',
- 'svc_acct_pop' => {},
- ],
-
- 'broadband' => [
- '_desc' => 'Access to broadband configuration',
- 'router' => {},
- 'addr_block' => {},
- ],
-
- 'misc' => [
- 'part_referral' => {},
- 'part_virtual_field' => {},
- 'msgcat' => {},
- 'inventory_class' => {},
- ],
-
- },
+ 'New customer',
+ 'View customer',
+ #'View Customer | View tickets',
+ 'Edit customer',
+ 'Cancel customer',
+ 'Delete customer',
+
+ 'Order customer package',
+ 'Change customer package',
+ 'Edit customer package dates',
+ 'Customize customer package',
+ 'Suspend customer package',
+ 'Unsuspend customer package',
+ 'Cancel customer package immediately',
+ 'Cancel customer package later',
+
+ 'Provision service',
+ 'Unprovision service',
+ #legacy link stuff
+
+ 'Post payment',
+ 'Process payment',
+ 'Post credit',
+ #more financial stuff
);
-#turn it into a more hash-like structure, but ordered via IxHash
+sub rights {
+ @rights;
+}
diff --git a/FS/FS/access_group.pm b/FS/FS/access_group.pm
index 9d870e5..2519040 100644
--- a/FS/FS/access_group.pm
+++ b/FS/FS/access_group.pm
@@ -3,8 +3,11 @@ package FS::access_group;
use strict;
use vars qw( @ISA );
use FS::Record qw( qsearch qsearchs );
+use FS::m2name_Common;
+use FS::access_groupagent;
+use FS::access_right;
-@ISA = qw(FS::Record);
+@ISA = qw(FS::m2m_Common FS::m2name_Common FS::Record);
=head1 NAME
@@ -27,15 +30,14 @@ FS::access_group - Object methods for access_group records
=head1 DESCRIPTION
-An FS::access_group object represents an example. FS::access_group inherits from
+An FS::access_group object represents an access group. FS::access_group inherits from
FS::Record. The following fields are currently supported:
=over 4
=item groupnum - primary key
-=item groupname -
-
+=item groupname - Access group name
=back
@@ -45,7 +47,7 @@ FS::Record. The following fields are currently supported:
=item new HASHREF
-Creates a new example. To add the example to the database, see L<"insert">.
+Creates a new access group. To add the access group 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.
@@ -84,7 +86,7 @@ returns the error, otherwise returns false.
=item check
-Checks all fields to make sure this is a valid example. If there is
+Checks all fields to make sure this is a valid access group. If there is
an error, returns the error, otherwise returns false. Called by the insert
and replace methods.
@@ -105,12 +107,51 @@ sub check {
$self->SUPER::check;
}
+=item access_groupagent
+
+Returns all associated FS::access_groupagent records.
+
+=cut
+
+sub access_groupagent {
+ my $self = shift;
+ qsearch('access_groupagent', { 'groupnum' => $self->groupnum } );
+}
+
+=item access_rights
+
+Returns all associated FS::access_right records.
+
+=cut
+
+sub access_rights {
+ my $self = shift;
+ qsearch('access_right', { 'righttype' => 'FS::access_group',
+ 'rightobjnum' => $self->groupnum
+ }
+ );
+}
+
+=item access_right RIGHTNAME
+
+Returns the specified FS::access_right record. Can be used as a boolean, to
+test if this group has the given RIGHTNAME.
+
+=cut
+
+sub access_right {
+ my( $self, $name ) = shift;
+ qsearchs('access_right', { 'righttype' => 'FS::access_group',
+ 'rightobjnum' => $self->groupnum,
+ 'rightname' => $name,
+ }
+ );
+}
+
=back
=head1 BUGS
-The author forgot to customize this manpage.
-
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
diff --git a/FS/FS/access_groupagent.pm b/FS/FS/access_groupagent.pm
index 6b5def1..3de8fee 100644
--- a/FS/FS/access_groupagent.pm
+++ b/FS/FS/access_groupagent.pm
@@ -3,6 +3,7 @@ package FS::access_groupagent;
use strict;
use vars qw( @ISA );
use FS::Record qw( qsearch qsearchs );
+use FS::agent;
@ISA = qw(FS::Record);
@@ -27,7 +28,7 @@ FS::access_groupagent - Object methods for access_groupagent records
=head1 DESCRIPTION
-An FS::access_groupagent object represents an example. FS::access_groupagent inherits from
+An FS::access_groupagent object represents an group reseller virtualization. FS::access_groupagent inherits from
FS::Record. The following fields are currently supported:
=over 4
@@ -47,7 +48,7 @@ FS::Record. The following fields are currently supported:
=item new HASHREF
-Creates a new example. To add the example to the database, see L<"insert">.
+Creates a new group reseller virtualization. To add the record 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.
@@ -86,7 +87,7 @@ returns the error, otherwise returns false.
=item check
-Checks all fields to make sure this is a valid example. If there is
+Checks all fields to make sure this is a valid group reseller virtualization. If there is
an error, returns the error, otherwise returns false. Called by the insert
and replace methods.
@@ -100,20 +101,29 @@ sub check {
my $error =
$self->ut_numbern('groupagentnum')
- || $self->ut_number('groupnum')
- || $self->ut_number('agentnum')
+ || $self->ut_foreign_key('groupnum', 'access_group', 'groupnum')
+ || $self->ut_foreign_key('agentnum', 'agent', 'agentnum')
;
return $error if $error;
$self->SUPER::check;
}
+=item agent
+
+Returns the associated FS::agent object.
+
+=cut
+
+sub agent {
+ my $self = shift;
+ qsearchs('agent', { 'agentnum' => $self->agentnum } );
+}
+
=back
=head1 BUGS
-The author forgot to customize this manpage.
-
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
diff --git a/FS/FS/m2name_Common.pm b/FS/FS/m2name_Common.pm
new file mode 100644
index 0000000..7c9637e
--- /dev/null
+++ b/FS/FS/m2name_Common.pm
@@ -0,0 +1,95 @@
+package FS::m2name_Common;
+
+use strict;
+use vars qw( @ISA $DEBUG );
+use FS::Schema qw( dbdef );
+use FS::Record qw( qsearch qsearchs ); #dbh );
+
+@ISA = qw( FS::Record );
+
+$DEBUG = 0;
+
+=head1 NAME
+
+FS::m2name_Common - Base class for tables with a related table listing names
+
+=head1 SYNOPSIS
+
+use FS::m2name_Common;
+
+@ISA = qw( FS::m2name_Common );
+
+=head1 DESCRIPTION
+
+FS::m2name_Common is intended as a base class for classes which have a
+related table that lists names.
+
+=head1 METHODS
+
+=over 4
+
+=item process_m2name
+
+=cut
+
+sub process_m2name {
+ my( $self, %opt ) = @_;
+
+ my $self_pkey = $self->dbdef_table->primary_key;
+ my $link_sourcekey = $opt{'num_col'} || $self_pkey;
+
+ my $link_table = $self->_load_table($opt{'link_table'});
+
+ my $link_static = $opt{'link_static'} || {};
+
+ foreach my $name ( @{ $opt{'names_list'} } ) {
+
+ my $obj = qsearchs( $link_table, {
+ $link_sourcekey => $self->$self_pkey(),
+ $opt{'name_col'} => $name,
+ %$link_static,
+ });
+
+ if ( $obj && ! $opt{'params'}->{"$link_table.$name"} ) {
+
+ my $d_obj = $obj; #need to save $obj for below.
+ my $error = $d_obj->delete;
+ die "error deleting $d_obj for $link_table.$name: $error" if $error;
+
+ } elsif ( $opt{'params'}->{"$link_table.$name"} && ! $obj ) {
+
+ #ok to clobber it now (but bad form nonetheless?)
+ #$obj = new "FS::$link_table" ( {
+ $obj = "FS::$link_table"->new( {
+ $link_sourcekey => $self->$self_pkey(),
+ $opt{'name_col'} => $name,
+ %$link_static,
+ });
+ my $error = $obj->insert;
+ die "error inserting $obj for $link_table.$name: $error" if $error;
+ }
+
+ }
+
+ '';
+}
+
+sub _load_table {
+ my( $self, $table ) = @_;
+ eval "use FS::$table";
+ die $@ if $@;
+ $table;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm
index 05dc599..de4d047 100644
--- a/FS/FS/part_pkg.pm
+++ b/FS/FS/part_pkg.pm
@@ -1,7 +1,7 @@
package FS::part_pkg;
use strict;
-use vars qw( @ISA %freq %plans $DEBUG );
+use vars qw( @ISA %plans $DEBUG );
use Carp qw(carp cluck confess);
use Tie::IxHash;
use FS::Conf;
@@ -571,6 +571,32 @@ sub is_free {
}
}
+
+sub freqs_href {
+ #method, class method or sub? #my $self = shift;
+
+ tie my %freq, 'Tie::IxHash',
+ '0' => '(no recurring fee)',
+ '1h' => 'hourly',
+ '1d' => 'daily',
+ '1w' => 'weekly',
+ '2w' => 'biweekly (every 2 weeks)',
+ '1' => 'monthly',
+ '2' => 'bimonthly (every 2 months)',
+ '3' => 'quarterly (every 3 months)',
+ '6' => 'semiannually (every 6 months)',
+ '12' => 'annually',
+ '24' => 'biannually (every 2 years)',
+ '36' => 'triannually (every 3 years)',
+ '48' => '(every 4 years)',
+ '60' => '(every 5 years)',
+ '120' => '(every 10 years)',
+ ;
+
+ \%freq;
+
+}
+
=item freq_pretty
Returns an english representation of the I<freq> field, such as "monthly",
@@ -578,29 +604,14 @@ Returns an english representation of the I<freq> field, such as "monthly",
=cut
-tie %freq, 'Tie::IxHash',
- '0' => '(no recurring fee)',
- '1h' => 'hourly',
- '1d' => 'daily',
- '1w' => 'weekly',
- '2w' => 'biweekly (every 2 weeks)',
- '1' => 'monthly',
- '2' => 'bimonthly (every 2 months)',
- '3' => 'quarterly (every 3 months)',
- '6' => 'semiannually (every 6 months)',
- '12' => 'annually',
- '24' => 'biannually (every 2 years)',
- '36' => 'triannually (every 3 years)',
- '48' => '(every 4 years)',
- '60' => '(every 5 years)',
- '120' => '(every 10 years)',
-;
-
sub freq_pretty {
my $self = shift;
my $freq = $self->freq;
- if ( exists($freq{$freq}) ) {
- $freq{$freq};
+
+ my $freqs_href = $self->freqs_href;
+
+ if ( exists($freqs_href->{$freq}) ) {
+ $freqs_href->{$freq};
} else {
my $interval = 'month';
if ( $freq =~ /^(\d+)([hdw])$/ ) {
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 9e3285d..098fe4a 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -342,3 +342,6 @@ t/access_right.t
FS/m2m_Common.pm
FS/pay_batch.pm
t/pay_batch.t
+FS/ConfDefaults.pm
+t/ConfDefaults.t
+FS/m2name_Common.pm
diff --git a/htetc/handler.pl b/htetc/handler.pl
index d400a55..1dfa137 100644
--- a/htetc/handler.pl
+++ b/htetc/handler.pl
@@ -182,6 +182,10 @@ sub handler
use FS::pkg_class;
use FS::access_user;
use FS::access_group;
+ use FS::access_usergroup;
+ use FS::access_groupagent;
+ use FS::access_right;
+ use FS::AccessRight;
if ( %%%RT_ENABLED%%% ) {
eval '
diff --git a/httemplate/browse/access_group.html b/httemplate/browse/access_group.html
index 6ba89ea..9ebb2b8 100644
--- a/httemplate/browse/access_group.html
+++ b/httemplate/browse/access_group.html
@@ -4,6 +4,45 @@ my $html_init =
"Internal access groups control access to the back-office interface.<BR><BR>".
qq!<A HREF="${p}edit/access_group.html"><I>Add an internal access group</I></A><BR><BR>!;
+#false laziness w/access_user.html & agent_type.cgi
+my $agents_sub = sub {
+ my $access_group = shift;
+
+ [ map {
+ my $access_groupagent = $_;
+ my $agent = $access_groupagent->agent;
+ [
+ {
+ 'data' => $agent->agent,
+ 'align' => 'left',
+ 'link' => $p. 'edit/agent.cgi?'. $agent->agentnum,
+ },
+ ];
+ }
+ grep { $_->agent } #?
+ $access_group->access_groupagent,
+
+ ];
+
+};
+
+my $rights_sub = sub {
+ my $access_group = shift;
+
+ [ map { my $access_right = $_;
+ [
+ {
+ 'data' => $access_right->rightname,
+ 'align' => 'left',
+ },
+ ];
+ }
+ $access_group->access_rights,
+
+ ];
+
+};
+
my $count_query = 'SELECT COUNT(*) FROM access_group';
my $link = [ $p.'edit/access_group.html?', 'groupnum' ];
@@ -22,12 +61,18 @@ my $link = [ $p.'edit/access_group.html?', 'groupnum' ];
'count_query' => $count_query,
'header' => [ '#',
'Group name',
+ 'Agents',
+ 'Rights',
],
'fields' => [ 'groupnum',
'groupname',
+ $agents_sub,
+ $rights_sub,
],
'links' => [ $link,
$link,
+ '',
+ '',
],
)
%>
diff --git a/httemplate/browse/access_user.html b/httemplate/browse/access_user.html
index 38d5430..be11bf8 100644
--- a/httemplate/browse/access_user.html
+++ b/httemplate/browse/access_user.html
@@ -4,7 +4,7 @@ my $html_init =
"Internal users have access to the back-office interface. Typically, this is your employees and contractors, but in a VISP setup, you can also add accounts for your reseller's employees. It is <B>highly recommended</B> to add a <B>separate account for each person</B> rather than using role accounts.<BR><BR>".
qq!<A HREF="${p}edit/access_user.html"><I>Add an internal user</I></A><BR><BR>!;
-#false laziness w/agent_type.cgi
+#false laziness w/access_group.html & agent_type.cgi
my $groups_sub = sub {
my $access_user = shift;
diff --git a/httemplate/edit/access_group.html b/httemplate/edit/access_group.html
index 11b8df7..d7f7667 100644
--- a/httemplate/edit/access_group.html
+++ b/httemplate/edit/access_group.html
@@ -5,6 +5,42 @@
'groupnum' => 'Group number',
'groupname' => 'Group name',
},
+
'viewall_dir' => 'browse',
+
+ 'html_bottom' =>
+ sub {
+ my $access_group = shift;
+
+ "<BR>Group virtualized to customers of agents:<BR>".
+ ntable("#cccccc",2).
+ '<TR><TD>'.
+ include( '/elements/checkboxes-table.html',
+ 'source_obj' => $access_group,
+ 'link_table' => 'access_groupagent',
+ 'target_table' => 'agent',
+ 'name_col' => 'agent',
+ 'target_link' => $p.'edit/agent.cgi?',
+ 'disable-able' => 1,
+ ).
+ '</TR></TD></TABLE>'.
+
+ "<BR>Group rights:<BR>".
+ ntable("#cccccc",2).
+ '<TR><TD>'.
+ include( '/elements/checkboxes-table-name.html',
+ 'source_obj' => $access_group,
+ 'link_table' => 'access_right',
+ 'link_static' => { 'righttype' =>
+ 'FS::access_group',
+ },
+ 'num_col' => 'rightobjnum',
+ 'name_col' => 'rightname',
+ 'names_list' => [ FS::AccessRight->rights() ],
+ ).
+ '</TR></TD></TABLE>'
+
+ ;
+ },
)
%>
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index 120c03a..94bf6ee 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -16,6 +16,18 @@
#
# 'menubar' => '', #menubar arrayref
#
+ # #run when re-displaying with an error
+ # 'error_callback' => sub { my $cgi, $object = @_; },
+ #
+ # #run when editing
+ # 'edit_callback' => sub { my $cgi, $object = @_; },
+ #
+ # #run when adding
+ # 'new_callback' => sub { my $cgi, $object = @_; },
+ #
+ # #broken'html_table_bottom' => '', #string or listref of additinal HTML to
+ # #add before </TABLE>
+ #
# 'viewall_dir' => '', #'search' or 'browse', defaults to 'search'
#
# 'html_bottom' => '', #string
@@ -43,16 +55,25 @@
map { $_ => scalar($cgi->param($_)) } fields($table)
});
+ &{$opt{'error_callback'}}($cgi, $object)
+ if $opt{'error_callback'};
+
} elsif ( $cgi->keywords ) { #editing
my( $query ) = $cgi->keywords;
$query =~ /^(\d+)$/;
$object = qsearchs( $table, { $pkey => $1 } );
+ &{$opt{'edit_callback'}}($cgi, $object)
+ if $opt{'edit_callback'};
+
} else { #adding
$object = $class->new( {} );
+ &{$opt{'new_callback'}}($cgi, $object)
+ if $opt{'new_callback'};
+
}
my $action = $object->$pkey() ? 'Edit' : 'Add';
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index 462d516..b085d226 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -237,7 +237,7 @@ if ( dbdef->table('pkg_svc')->column('primary_svc') ) {
push @form_radio, 'pkg_svc_primary';
}
-tie my %freq, 'Tie::IxHash', %FS::part_pkg::freq;
+tie my %freq, 'Tie::IxHash', %{FS::part_pkg->freqs_href()};
if ( $part_pkg->dbdef_table->column('freq')->type =~ /(int)/i ) {
delete $freq{$_} foreach grep { ! /^\d+$/ } keys %freq;
}
diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html
index e8c6d07..9bb9d1d 100644
--- a/httemplate/edit/process/access_group.html
+++ b/httemplate/edit/process/access_group.html
@@ -1,5 +1,15 @@
<%= include( 'elements/process.html',
'table' => 'access_group',
'viewall_dir' => 'browse',
+ 'process_m2m' => { 'link_table' => 'access_groupagent',
+ 'target_table' => 'agent',
+ },
+ 'process_m2name' => {
+ 'link_table' => 'access_right',
+ 'link_static' => { 'righttype' => 'FS::access_group', },
+ 'num_col' => 'rightobjnum',
+ 'name_col' => 'rightname',
+ 'names_list' => [ FS::AccessRight->rights() ],
+ },
)
%>
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 59ad35e..a6e3b50 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -16,7 +16,14 @@
# 'viewall_dir' => '', #'search' or 'browse', defaults to 'search'
# 'process_m2m' => { 'link_table' => 'link_table_name',
# 'target_table' => 'target_table_name',
- # }.
+ # },
+ # 'process_m2name' => { 'link_table' => 'link_table_name',
+ # 'link_static' => { 'column' => 'value' },
+ # 'num_col' => 'column', #if column name is different in
+ # #link_table than source_table
+ # 'name_col' => 'name_column',
+ # 'names_list' => [ 'list', 'names' ],
+ # },
my(%opt) = @_;
@@ -52,6 +59,12 @@
);
}
+ if ( !$error && $opt{'process_m2name'} ) {
+ $error = $new->process_m2name( %{ $opt{'process_m2name'} },
+ 'params' => scalar($cgi->Vars),
+ );
+ }
+
if ( $error ) {
$cgi->param('error', $error);
print $cgi->redirect(popurl(2). "$table.html?". $cgi->query_string );
diff --git a/httemplate/elements/checkboxes-table-name.html b/httemplate/elements/checkboxes-table-name.html
new file mode 100644
index 0000000..8e9dd29
--- /dev/null
+++ b/httemplate/elements/checkboxes-table-name.html
@@ -0,0 +1,85 @@
+<%
+
+ ##
+ # required
+ ##
+ # 'link_table' => 'table_name',
+ #
+ # 'name_col' => 'name_column',
+ # #or
+ # 'name_callback' => sub { },
+ #
+ # 'names_list' => [ 'value', 'other value' ],
+ #
+ ##
+ # recommended (required?)
+ ##
+ # 'source_obj' => $obj,
+ # #or?
+ # #'source_table' => 'table_name',
+ # #'sourcenum' => '4', #current value of primary key in source_table
+ # # # (none is okay, just pass it if you have it)
+ ##
+ # optional
+ ##
+ # 'num_col' => 'col_name' #if column name is different in link_table than
+ # #source_table
+ # 'link_static' => { 'column' => 'value' },
+
+ my( %opt ) = @_;
+
+ my( $source_pkey, $sourcenum, $source_obj );
+ if ( $opt{'source_obj'} ) {
+
+ $source_obj = $opt{'source_obj'};
+ #$source_table = $source_obj->dbdef_table->table;
+ $source_pkey = $source_obj->dbdef_table->primary_key;
+ $sourcenum = $source_obj->$source_pkey();
+
+ } else {
+
+ #$source_obj?
+ $source_pkey = $opt{'source_table'}
+ ? dbdef->table($opt{'source_table'})->primary_key
+ : '';
+ $sourcenum = $opt{'sourcenum'};
+ }
+
+ $source_pkey = $opt{'num_col'} || $source_pkey;
+
+ my $link_static = $opt{'link_static'} || {};
+
+%>
+
+<% foreach my $name ( @{ $opt{'names_list'} } ) {
+
+ my $checked;
+ if ( $cgi->param('error') ) {
+
+ $checked = $cgi->param($opt{'link_table'}. ".$name" )
+ ? 'CHECKED'
+ : '';
+
+ } else {
+
+ $checked =
+ qsearchs( $opt{'link_table'}, {
+ $source_pkey => $sourcenum,
+ $opt{'name_col'} => $name,
+ %$link_static,
+ } )
+ ? 'CHECKED'
+ : ''
+
+ }
+
+%>
+
+ <INPUT TYPE="checkbox" NAME="<%= $opt{'link_table'}. ".$name" %>" <%= $checked %> VALUE="ON">
+
+ <%= $name %>
+
+ <BR>
+
+<% } %>
+
diff --git a/httemplate/elements/checkboxes-table.html b/httemplate/elements/checkboxes-table.html
index d26ebef..16376fa 100644
--- a/httemplate/elements/checkboxes-table.html
+++ b/httemplate/elements/checkboxes-table.html
@@ -68,16 +68,28 @@
) {
my $targetnum = $target_obj->$target_pkey();
+
+ my $checked;
+ if ( $cgi->param('error') ) {
+
+ $checked = $cgi->param($target_pkey.$targetnum)
+ ? 'CHECKED'
+ : '';
+
+ } else {
+
+ $checked = qsearchs( $opt{'link_table'}, {
+ $source_pkey => $sourcenum,
+ $target_pkey => $targetnum,
+ } )
+ ? 'CHECKED'
+ : ''
+
+ }
+
%>
- <INPUT TYPE="checkbox" NAME="<%= $target_pkey. $targetnum %>" <%=
- qsearchs( $opt{'link_table'}, {
- $source_pkey => $sourcenum,
- $target_pkey => $targetnum,
- })
- ? 'CHECKED '
- : ''
- %> VALUE="ON">
+ <INPUT TYPE="checkbox" NAME="<%= $target_pkey. $targetnum %>" <%= $checked %> VALUE="ON">
<% if ( $opt{'target_link'} ) { %>