}
-=item print ARRAYREF
+=item do_print ARRAYREF
Sends the lines in ARRAYREF to the printer.
'tagname', 'varchar', '', $char_d, '', '',
'tagdesc', 'varchar', 'NULL', $char_d, '', '',
'tagcolor', 'varchar', 'NULL', 6, '', '',
+ 'by_default', 'char', 'NULL', 1, '', '',
'disabled', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'tagnum',
$cust_pkg->h_labels_short($self->_date, undef, 'I')
unless $cust_bill_pkg->pkgpart_override; #don't redisplay services
- if ( $cust_pkg->locationnum != $cust_main->ship_locationnum ) {
+ if ( ! $cust_pkg->locationnum or
+ $cust_pkg->locationnum != $cust_main->ship_locationnum ) {
my $loc = $cust_pkg->location_label;
$loc = substr($loc, 0, $maxlength). '...'
if $format eq 'latex' && length($loc) > $maxlength;
my $seconds_left = $part_pkg->option_cacheable('use_duration')
? $self->duration
: $self->billsec;
- # charge for the first (conn_sec) seconds
- my $seconds = min($seconds_left, $rate_detail->conn_sec);
- $seconds_left -= $seconds;
- $weektime += $seconds;
- my $charge = $rate_detail->conn_charge;
+
+ #no, do this later so it respects (group) included minutes
+ # # charge for the first (conn_sec) seconds
+ # my $seconds = min($seconds_left, $rate_detail->conn_sec);
+ # $seconds_left -= $seconds;
+ # $weektime += $seconds;
+ # my $charge = $rate_detail->conn_charge;
+ my $seconds = 0;
+ my $charge = 0;
+ my $connection_charged = 0;
my $etime;
while($seconds_left) {
$seconds += $charge_sec;
+
my $region_group = ($part_pkg->option_cacheable('min_included') || 0) > 0;
${$opt{region_group_included_min}} -= $minutes
)
)
{
+
+ #NOW do connection charges here... right?
+ #my $conn_seconds = min($seconds_left, $rate_detail->conn_sec);
+ my $conn_seconds = 0;
+ unless ( $connection_charged++ ) { #only one connection charge
+ $conn_seconds = min($charge_sec, $rate_detail->conn_sec);
+ $seconds_left -= $conn_seconds;
+ $weektime += $conn_seconds;
+ $charge += $rate_detail->conn_charge;
+ }
+
#should preserve (display?) this
- my $charge_min = 0 - $included_min->{$regionnum}{$ratetimenum};
+ my $charge_min = 0 - $included_min->{$regionnum}{$ratetimenum} - ( $conn_seconds / 60 );
$included_min->{$regionnum}{$ratetimenum} = 0;
- $charge += ($rate_detail->min_charge * $charge_min); #still not rounded
+ $charge += ($rate_detail->min_charge * $charge_min) if $charge_min > 0; #still not rounded
} elsif ( ${$opt{region_group_included_min}} > 0
&& $region_group
--- /dev/null
+package FS::cdr::qwest;
+
+use strict;
+use vars qw(@ISA %info);
+use FS::cdr qw(_cdr_date_parser_maker);
+
+@ISA = qw(FS::cdr);
+
+my %disposition = (
+ 0 => 'ANSWERED', #normal completed call
+ 1 => 'ANSWERED', #"treated call"
+ 2 => 'NO ANSWER', #abandoned call
+ 3 => 'ERROR', #abnormal call
+ 4 => 'ERROR', #signaling system error
+ 5 => 'ANSWERED', #forced disconnect
+ 6 => 'ANSWERED', #off-net route advance
+ 7 => 'NO ANSWER', #test call
+ 8 => 'NO ANSWER', #recorded promotion
+ 9 => 'ERROR', #TCAP DCP response time-out
+ 12=> 'ANSWERED', #abnormal release
+ 13=> 'ERROR', #"completed answer CDR"(?)
+ 15=> 'ERROR', #"COS failure"(?)
+);
+
+my $startdate = _cdr_date_parser_maker('startdate');
+my $enddate = _cdr_date_parser_maker('enddate');
+
+%info = (
+ 'name' => 'Qwest (Standard Daily)',
+ 'weight' => 400,
+ 'type' => 'fixedlength',
+ 'fixedlength_format' => [qw(
+ billing_cycle_id:6:1:6
+ discn_dt:8:7:14
+ anstype:6:15:20
+ pindigs:4:21:24
+ origtime:6:25:30
+ discn_time:6:31:36
+ time_chng:1:37:37
+ ani:15:38:52
+ infodig:2:53:54
+ calldur:11:55:65
+ univacc:10:66:75
+ compcode:6:76:81
+ dialedno:15:82:96
+ calledno:15:97:111
+ predig:1:112:112
+ seqnum:11:113:123
+ orig_dt:8:124:131
+ finsid:6:132:137
+ trtmtcd:6:138:143
+ anisuff:6:144:149
+ origgrp:6:150:155
+ origmem:6:156:161
+ termgrp:6:162:167
+ termmem:6:168:173
+ fintkgrp:6:174:179
+ billnum:24:180:203
+ acctcd:12:204:215
+ swid:6:216:221
+ orig_bill_file_id:11:222:232
+ orig_trunk_group_name:12:233:244
+ orig_trunk_time_bias_ind:6:245:250
+ term_trunk_group_name:12:251:262
+ final_trunk_group_name:12:263:274
+ orig_trunk_usage_ind:6:275:280
+ orig_pricing_npa:3:281:283
+ orig_pricing_nxx:3:284:286
+ term_pricing_npa:3:287:289
+ term_pricing_nxx:3:290:292
+ prcmp_id:6:293:298
+ component_group_cd:2:299:300
+ component_group_val:24:301:324
+ intra_lata_ind:1:325:325
+ carrsel:1:326:326
+ cic:6:327:332
+ origlrn:10:333:342
+ portedno:10:343:352
+ lnpcheck:1:353:353
+ )],
+ 'import_fields' => [
+ '', # billing_cycle_id
+ sub { # discn_dt
+ # hold onto this, combine it with discn_time later
+ # YYYYMMDD
+ my ($cdr, $data, $conf, $param) = @_;
+ $param->{'discn_dt'} = $data;
+ '';
+ },
+ '', # anstype
+ '', # pindigs
+ sub { # orig_time
+ # and this
+ # hhmmss
+ my ($cdr, $data, $conf, $param) = @_;
+ $param->{'orig_time'} = $data;
+ '';
+ },
+ sub { # discn_time
+ my ($cdr, $data, $conf, $param) = @_;
+ $data = $param->{'discn_dt'} . $data; #YYYYMMDDhhmmss
+ $enddate->($cdr, $data);
+ },
+ '', # time_chng
+ 'src', # ani (originating number)
+ '', # infodig
+ 'billsec', # calldur
+ '', # univacc
+ sub { # compcode
+ my ($cdr, $data) = @_;
+ my $compcode = sprintf('%d', $data);
+ $cdr->disposition($disposition{$compcode});
+ # only those that map to ANSWERED are billable, but that should be
+ # set in rating options, not enforced here
+ '';
+ },
+ 'dst', # dialedno
+ '', # calledno (physical terminating number)
+ '', # predig (0/1/011 prefix)
+ '', # seqnum
+ sub { # orig_dt
+ # backward from the discn_ fields
+ my ($cdr, $data, $conf, $param) = @_;
+ $data .= $param->{'orig_time'};
+ $startdate->($cdr, $data);
+ },
+ '', # finsid
+ '', # trtmtcd
+ '', # anisuff
+ 'channel', # origgrp (orig. trunk group)
+ '', # origmem (belongs in channel?)
+ 'dstchannel', # termgrp (term. trunk group)
+ '', # termmem (same?)
+ '', # fintkgrp
+ 'charged_party', # billnum (empty for "normal" calls)
+ '', # acctcd
+ '', # swid
+ '', # orig_bill_file_id
+ '', # orig_trunk_group_name
+ '', # orig_trunk_time_bias_ind
+ '', # term_trunk_group_name
+ '', # final_trunk_group_name
+ '', # orig_trunk_usage_ind
+ '', # orig_pricing_npa
+ '', # orig_pricing_nxx
+ '', # term_pricing_npa
+ '', # term_pricing_nxx
+ '', # prcmp_id
+ '', # component_group_cd
+ '', # component_group_val
+ '', # intra_lata_ind (or should we use this?)
+ '', # carrsel
+ '', # cic
+ '', # origlrn
+ '', # portedno
+ '', # lnpcheck
+ ],
+
+);
+
+1;
package FS::cust_bill_ApplicationCommon;
use strict;
-use vars qw( @ISA $DEBUG $me $skip_apply_to_lineitems_hack );
+use vars qw( @ISA $DEBUG $me $skip_apply_to_lineitems_hack $date_format );
use List::Util qw(min);
+use Date::Format;
use FS::Schema qw( dbdef );
+use FS::UID;
use FS::Record qw( qsearch qsearchs dbh );
use FS::cust_pkg;
use FS::cust_svc;
$skip_apply_to_lineitems_hack = 0;
+FS::UID->install_callback( sub {
+ my $conf = new FS::Conf;
+ $date_format = $conf->config('date_format') || '%x'; #/YY
+} );
+
=head1 NAME
FS::cust_bill_ApplicationCommon - Base class for bill application classes
sub applied_to_invoice {
my $self = shift;
- 'applied to '. $self->cust_bill->invnum_date_pretty;
+ my $string = 'applied to '. $self->cust_bill->invnum_date_pretty;
+
+ #show application date if over 24 hours after (or before) payment/credit date
+ $string .= ' on '. $self->_date_pretty
+ if abs( $self->_date - $self->_app_source_object->_date ) > 86400;
+
+ $string;
+}
+
+=item _app_source_object
+
+=cut
+
+sub _app_source_object {
+ my $self = shift;
+ my $source_table = $self->_app_source_table;
+ $self->$source_table();
+}
+
+=item _date_pretty
+
+Returns a string with the application date, for example: "3/20/2008"
+
+=cut
+
+sub _date_pretty {
+ my $self = shift;
+ time2str($date_format, $self->_date);
}
=item lineitem_breakdown_table
use HTML::Entities qw( decode_entities encode_entities ) ;
use HTML::FormatText;
use HTML::TreeBuilder;
+
+use File::Temp;
+use IPC::Run qw(run);
use vars qw( $DEBUG $conf );
FS::UID->install_callback( sub { $conf = new FS::Conf; } );
sub prepare {
my( $self, %opt ) = @_;
- my $cust_main = $opt{'cust_main'};
- my $object = $opt{'object'};
+ my $cust_main = $opt{'cust_main'} or die 'cust_main required';
+ my $object = $opt{'object'} or die 'object required';
# localization
my $locale = $cust_main->locale || '';
send_email(generate_email($self->prepare(@_)));
}
+=item render OPTION => VALUE ...
+
+Fills in the template and renders it to a PDF document. Returns the
+name of the PDF file.
+
+Options are as for 'prepare', but 'from' and 'to' are meaningless.
+
+=cut
+
+# will also have options to set paper size, margins, etc.
+
+sub render {
+ my $self = shift;
+ eval "use PDF::WebKit";
+ die $@ if $@;
+ my %opt = @_;
+ my %hash = $self->prepare(%opt);
+ my $html = $hash{'html_body'};
+
+ my $tmp = 'msg'.$self->msgnum.'-'.time2str('%Y%m%d', time).'-XXXXXXXX';
+ my $dir = "$FS::UID::cache_dir/cache.$FS::UID::datasrc";
+
+ # Graphics/stylesheets should probably go in /var/www on the Freeside
+ # machine.
+ my $kit = PDF::WebKit->new(\$html); #%options
+ # hack to use our wrapper script
+ $kit->configure(sub { shift->wkhtmltopdf('freeside-wkhtmltopdf') });
+ my $fh = File::Temp->new(
+ TEMPLATE => $tmp,
+ DIR => $dir,
+ UNLINK => 0,
+ SUFFIX => '.pdf'
+ );
+
+ print $fh $kit->to_pdf;
+ close $fh;
+ return $fh->filename;
+}
+
+=item print OPTIONS
+
+Render a PDF and send it to the printer. OPTIONS are as for 'render'.
+
+=cut
+
+sub print {
+ my $file = render(@_);
+ my @lpr = $conf->config('lpr');
+ run ([@lpr, '-r'], '<', $file)
+ or die "lpr error:\n$?\n";
+}
+
+
# helper sub for package dates
my $ymd = sub { $_[0] ? time2str('%Y-%m-%d', $_[0]) : '' };
+# helper sub for money amounts
+my $money = sub { ($conf->money_char || '$') . sprintf('%.2f', $_[0] || 0) };
+
# helper sub for usage-related messages
my $usage_warning = sub {
my $svc = shift;
signupdate dundate
packages recurdates
),
+ [ invoicing_email => sub { shift->invoicing_list_emailonly_scalar } ],
#compatibility: obsolete ship_ fields - use the non-ship versions
map (
{ my $field = $_;
labels_short
),
[ pkg => sub { shift->part_pkg->pkg } ],
+ [ pkg_category => sub { shift->part_pkg->categoryname } ],
+ [ pkg_class => sub { shift->part_pkg->classname } ],
[ cancel => sub { shift->getfield('cancel') } ], # grrr...
[ start_ymd => sub { $ymd->(shift->getfield('start_date')) } ],
[ setup_ymd => sub { $ymd->(shift->getfield('setup')) } ],
[ susp_ymd => sub { $ymd->(shift->getfield('susp')) } ],
[ expire_ymd => sub { $ymd->(shift->getfield('expire')) } ],
[ cancel_ymd => sub { $ymd->(shift->getfield('cancel')) } ],
+
+ # not necessarily correct for non-flat packages
+ [ setup_fee => sub { shift->part_pkg->option('setup_fee') } ],
+ [ recur_fee => sub { shift->part_pkg->option('recur_fee') } ],
+
+ [ freq_pretty => sub { shift->part_pkg->freq_pretty } ],
+
],
'cust_bill' => [qw(
invnum
--- /dev/null
+package FS::part_event::Action::letter;
+
+use strict;
+use base qw( FS::part_event::Action );
+use FS::Record qw( qsearchs );
+use FS::msg_template;
+
+sub description { 'Print a form letter to the customer' }
+
+#sub eventtable_hashref {
+# { 'cust_main' => 1,
+# 'cust_bill' => 1,
+# 'cust_pkg' => 1,
+# };
+#}
+
+sub option_fields {
+ (
+ 'msgnum' => { 'label' => 'Template',
+ 'type' => 'select-table',
+ 'table' => 'msg_template',
+ 'name_col' => 'msgname',
+ 'disable_empty' => 1,
+ },
+ );
+}
+
+sub default_weight { 56; } #?
+
+sub do_action {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ my $msgnum = $self->option('msgnum');
+
+ my $msg_template = qsearchs('msg_template', { 'msgnum' => $msgnum } )
+ or die "Template $msgnum not found";
+
+ $msg_template->print(
+ 'cust_main' => $cust_main,
+ 'object' => $object,
+ );
+
+}
+
+1;
#use Data::Dumper;
use Tie::IxHash;
use Frontier::Client; #to avoid adding a dependency on RPC::XML just now
+use Frontier::RPC2;
#use FS::Record qw( qsearch qsearchs );
use FS::Schema qw( dbdef );
if ( $fields{$value} ) {
my $type = dbdef->table('svc_acct')->column($value)->type;
if ( $type =~ /^(int|serial)/i ) {
- return Frontier::Client->new->int( $svc_acct->$value() );
+ return Frontier::RPC2::Integer->new( $svc_acct->$value() );
} elsif ( $value =~ /^last_log/ ) {
- return Frontier::Client->new->date_time( $svc_acct->$value() ); #conversion?
+ return Frontier::RPC2::DateTime::ISO8601->new( $svc_acct->$value() ); #conversion?
} else {
- return Frontier::Client->new->string( $svc_acct->$value() );
+ return Frontier::RPC2::String->new( $svc_acct->$value() );
}
} elsif ( $value eq 'domain' ) {
- return Frontier::Client->new->string( $svc_acct->domain );
+ return Frontier::RPC2::String->new( $svc_acct->domain );
} elsif ( $value eq 'crypt_password' ) {
- return Frontier::Client->new->string( $svc_acct->crypt_password( $self->option('crypt') ) );
+ return Frontier::RPC2::String->new( $svc_acct->crypt_password( $self->option('crypt') ) );
} elsif ( $value eq 'ldap_password' ) {
- return Frontier::Client->new->string( $svc_acct->ldap_password($self->option('crypt') ) );
+ return Frontier::RPC2::String->new( $svc_acct->ldap_password($self->option('crypt') ) );
} elsif ( $value eq 'radius_groups' ) {
my @radius_groups = $svc_acct->radius_groups;
#XXX
'username' => { label=>'Database username' },
'password' => { label=>'Database password' },
'manager' => { label=>'Manager name' },
- 'groupid' => { label=>'Group ID', default=>'1' },
- 'service_prefix' => { label=>'Service name prefix' },
- 'nasnames' => { label=>'NAS IDs/addresses' },
+ 'template_name' => { label=>'Template service name' },
+ 'service_prefix' => { label=>'Service name prefix' },
'debug' => { label=>'Enable debugging', type=>'checkbox' },
;
sub export_part_svc {
my ($self, $part_svc, $dbh) = @_;
+ # if $dbh exists, use the existing transaction
+ # otherwise create our own and commit when finished
+ my $commit = 0;
+ if (!$dbh) {
+ $dbh = $self->connect;
+ $commit = 1;
+ }
+
my $name = $self->option('service_prefix').$part_svc->svc;
my %params = (
'enableservice' => 1,
'nextsrvid' => -1,
'dailynextsrvid' => -1,
+ # force price-related fields to zero
+ 'unitprice' => 0,
+ 'unitpriceadd' => 0,
+ 'unitpricetax' => 0,
+ 'unitpriceaddtax' => 0,
);
my @fixed_groups;
# use speed settings from fixed usergroups configured on this part_svc
if ( my $psc = $part_svc->part_svc_column('usergroup') ) {
- if ( $psc->columnflag eq 'F' ) {
- # each part_svc really should only have one fixed group with non-null
- # speed settings, but go by priority order for consistency
- @fixed_groups =
- sort { $a->priority <=> $b->priority }
- grep { $_ }
- map { FS::radius_group->by_key($_) }
- split(/\s*,\s*/, $psc->columnvalue);
- }
+ # each part_svc really should only have one fixed group with non-null
+ # speed settings, but go by priority order for consistency
+ @fixed_groups =
+ sort { $a->priority <=> $b->priority }
+ grep { $_ }
+ map { FS::radius_group->by_key($_) }
+ split(/\s*,\s*/, $psc->columnvalue);
} # otherwise there are no fixed groups, so leave speed empty
foreach (qw(down up)) {
$sth->execute($name) or die $dbh->errstr;
if ( $sth->rows > 1 ) {
die "Multiple services with name '$name' found in Radius Manager.\n";
- } elsif ( $sth->rows == 1 ) {
- my $row = $sth->fetchrow_arrayref;
- my $srvid = $row->[0];
- warn "rm_services: updating srvid#$srvid\n" if $DEBUG;
- $sth = $dbh->prepare(
- 'UPDATE rm_services SET '.join(', ', map {"$_ = ?"} keys %params) .
- ' WHERE srvid = ?'
- );
- $sth->execute(values(%params), $srvid) or die $dbh->errstr;
- return $srvid;
- } else { # $sth->rows == 0
- # create a new one
- # but first... get the next available srvid
+
+ } elsif ( $sth->rows == 0 ) {
+ # leave this blank to disable creating new service defs
+ my $template_name = $self->option('template_name');
+
+ die "Can't create a new service profile--no template service specified.\n"
+ unless $template_name;
+
+ warn "rm_services: fetching template '$template_name'\n" if $DEBUG;
+ $sth = $dbh->prepare('SELECT * FROM rm_services WHERE srvname = ? LIMIT 1');
+ $sth->execute($template_name);
+ die "Can't create a new service profile--template service ".
+ "'$template_name' not found.\n" unless $sth->rows == 1;
+ my $template = $sth->fetchrow_hashref;
+ %params = (%$template, %params);
+
+ # get the next available srvid
$sth = $dbh->prepare('SELECT MAX(srvid) FROM rm_services');
$sth->execute or die $dbh->errstr;
- my $srvid = 1; # just in case you somehow have nothing in your database
+ my $srvid;
if ( $sth->rows ) {
$srvid = $sth->fetchrow_arrayref->[0] + 1;
}
$params{'srvid'} = $srvid;
- # NOW create a new one
+
+ # create a new one based on the template
warn "rm_services: inserting '$name' as srvid#$srvid\n" if $DEBUG;
$sth = $dbh->prepare(
'INSERT INTO rm_services ('.join(', ', keys %params).
') VALUES ('.join(', ', map {'?'} keys %params).')'
);
$sth->execute(values(%params)) or die $dbh->errstr;
- # also link it to our manager name
+ # also link it to all the managers allowed on the template service
warn "rm_services: linking to manager\n" if $DEBUG;
$sth = $dbh->prepare(
- 'INSERT INTO rm_allowedmanagers (srvid, managername) VALUES (?, ?)'
+ 'INSERT INTO rm_allowedmanagers (srvid, managername) '.
+ 'SELECT ?, managername FROM rm_allowedmanagers WHERE srvid = ?'
);
- $sth->execute($srvid, $self->option('manager')) or die $dbh->errstr;
- # and allow it on our NAS
+ $sth->execute($srvid, $template->{srvid}) or die $dbh->errstr;
+ # and the same for NASes
+ warn "rm_services: linking to nas\n" if $DEBUG;
$sth = $dbh->prepare(
- 'INSERT INTO rm_allowednases (srvid, nasid) VALUES (?, ?)'
+ 'INSERT INTO rm_allowednases (srvid, nasid) '.
+ 'SELECT ?, nasid FROM rm_allowednases WHERE srvid = ?'
);
- foreach my $nasid ($self->nas_ids($dbh)) {
- warn "rm_services: linking to nasid#$nasid\n" if $DEBUG;
- $sth->execute($srvid, $nasid) or die $dbh->errstr;
- }
- return $srvid;
- }
-}
+ $sth->execute($srvid, $template->{srvid}) or die $dbh->errstr;
-=item nas_ids DBH
+ $dbh->commit if $commit;
+ return $srvid;
-Convert the 'nasnames option into a list of real NAS ids.
+ } else { # $sth->rows == 1, it already exists
-=cut
-
-sub nas_ids {
- my $self = shift;
- my $dbh = shift;
+ my $row = $sth->fetchrow_arrayref;
+ my $srvid = $row->[0];
+ warn "rm_services: updating srvid#$srvid\n" if $DEBUG;
+ $sth = $dbh->prepare(
+ 'UPDATE rm_services SET '.join(', ', map {"$_ = ?"} keys %params) .
+ ' WHERE srvid = ?'
+ );
+ $sth->execute(values(%params), $srvid) or die $dbh->errstr;
- my @nasnames = split(/\s*,\s*/, $self->option('nasnames'));
- return unless @nasnames;
- # pass these through unchanged
- my @ids = grep { /^\d+$/ } @nasnames;
- @nasnames = grep { not /^\d+$/ } @nasnames;
- if ( @nasnames ) {
- my $in_nasnames = join(',', map {$dbh->quote($_)} @nasnames);
+ $dbh->commit if $commit;
+ return $srvid;
- my $sth = $dbh->prepare("SELECT id FROM nas WHERE nasname IN ($in_nasnames)");
- $sth->execute or die $dbh->errstr;
- my $rows = $sth->fetchall_arrayref;
- push @ids, $_->[0] foreach @$rows;
}
-
- return @ids;
}
1;
=over 4
-=item tagnum
+=item tagnum - primary key
-primary key
+=item tagname - tag name
-=item tagname
+=item tagdesc - description (can be longer than name)
-tagname
+=item tagcolor - HTML-style color to display this tag
-=item tagdesc
-
-tagdesc
-
-=item tagcolor
-
-tagcolor
+=item by_default - 'Y' to enable this tag on new customers
+=item disabled
=back
|| $self->ut_text('tagname')
|| $self->ut_textn('tagdesc')
|| $self->ut_textn('tagcolor')
+ || $self->ut_enum('by_default', [ '', 'Y' ] )
|| $self->ut_enum('disabled', [ '', 'Y' ] )
;
return $error if $error;
=back
+=head1 CLASS METHODS
+
+=over 4
+
+=item default_tags
+
+Returns the tagnums of all tags that have 'by_default' enabled.
+
+=cut
+
+sub default_tags {
+ my $class = shift;
+ map { $_->tagnum } qsearch('part_tag', { disabled => '', by_default => 'Y' });
+}
+
=head1 BUGS
=head1 SEE ALSO
--- /dev/null
+#!/bin/sh
+
+if [ $DISPLAY ] ; then
+ wkhtmltopdf $@
+else
+ xvfb-run -- wkhtmltopdf $@
+fi
<% include( 'elements/class_Common.html',
- 'name' => 'Contact Type',
+ 'name_singular' => 'Contact Type',
'table' => 'contact_class',
'nocat' => 1,
'addl_labels' => { 'classnum' => 'Type number',
<% include( 'elements/class_Common.html',
- 'name' => 'Customer Class',
+ 'name_singular' => 'Customer Class',
'table' => 'cust_class',
'addl_fields' => \@addl_fields,
'addl_labels' => { 'tax' => 'Tax Exempt' },
$stateid = '';
$payinfo = '';
+ $cgi->param('tagnum', FS::part_tag->default_tags);
+
if ( $cgi->param('qualnum') =~ /^(\d+)$/ ) {
my $qualnum = $1;
my $qual = qsearchs('qual', { 'qualnum' => $qualnum } )
<% include( 'elements/class_Common.html',
- 'name' => 'Customer Note Class',
+ 'name_singular' => 'Customer Note Class',
'table' => 'cust_note_class',
'nocat' => 1,
)
<% include( 'elements/edit.html',
- 'name' => 'Hardware Class',
+ 'name_singular' => 'Hardware Class',
'table' => 'hardware_class',
'labels' => {
'classnum' => 'Class number',
<% include( 'elements/edit.html',
- 'name' => 'Inventory Class',
+ 'name_singular' => 'Inventory Class',
'table' => 'inventory_class',
'labels' => {
'classnum' => 'Class number',
<% include( 'elements/class_Common.html',
- 'name' => 'Service class',
+ 'name_singular' => 'Service class',
'table' => 'part_svc_class',
'nocat' => 1,
)
{ field=>'tagname', type=>'text', size=>10 },
{ field=>'disabled', type=>'checkbox', value=>'Y' },
{ field=>'tagdesc', type=>'text', size=>60 },
+ { field=>'by_default', type=>'checkbox', value=>'Y' },
$tagcolor,
],
'labels' => { 'tagnum' => 'Tag #',
'tagname' => 'Tag',
'tagdesc' => 'Message',
'tagcolor' => 'Highlight Color',
+ 'by_default' => 'On by default',
'disabled' => 'Disabled',
},
'viewall_dir' => 'browse',
<% include( 'elements/class_Common.html',
- 'name' => 'Package Class',
+ 'name_singular' => 'Package Class',
'table' => 'pkg_class',
%opt,
)
# no validation of these; they can contain just about anything
$content{'subject'} = $cgi->param('subject') || '';
$content{'body'} = $cgi->param('body') || '';
+ $object->subject('');
+ $object->body('');
return %content;
}
my $is_report = $opt{'is_report'};
my @curr_tagnum = ();
-if ( $cgi && $cgi->param('error') ) {
+if ( $cgi && $cgi->param('tagnum') ) {
@curr_tagnum = $cgi->param('tagnum');
} elsif ( $opt{'custnum'} ) {
@curr_tagnum = map $_->tagnum,