'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', '', '', '',
active, inactive, suspended, one-time charge, inactive, cancel (or cancelled)
+=item custom
+
+ boolean selects custom packages
+
=item classnum
=item pkgpart
#eslaf
###
+ # parse custom
+ ###
+
+ push @where, "part_pkg.custom = 'Y'" if $params->{custom};
+
+ ###
# parse part_pkg
###
=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
=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
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 ); # ?
}
|| $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')
'';
}
-=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
}
+ # 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
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>.
[
{
#'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,
},
'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,
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';
</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>
'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,
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
);
#}
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);
% join("\n", map {
% '<OPTION VALUE="'. $_->pkgpart. '"'.
% ( $selected{$_->pkgpart} ? ' SELECTED' : '' ).
-% '>'. $_->pkg. ' - '. $_->comment
+% '>'. $_->pkg_comment
% } qsearch('part_pkg', { 'disabled' => '' } ) ).
% '</SELECT>';
%}
sub { shift->param('pkgnum') },
},
+ { field=>'custom', type=>'hidden' },
+
{ type => 'columnstart' },
{ field => 'pkg',
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;
$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');
% 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>
% }
'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'))
<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') {
<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>
<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>
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>
%# 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 ) {
$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);
}
sub {
map {
qq!<A HREF="${p}edit/part_pkg.cgi?!. $_->pkgpart. '">'.
- $_->pkg. ' - '. $_->comment.
+ $_->pkg_comment(nopkgpart => 1).
'</A><BR>'
} $_[0]->part_pkg
},
% }
+ <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>
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>
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;