5 use FS::Record qw( qsearch dbh );
11 @ISA = qw( FS::Record );
15 FS::part_pkg - Object methods for part_pkg objects
21 $record = new FS::part_pkg \%hash
22 $record = new FS::part_pkg { 'column' => 'value' };
24 $custom_record = $template_record->clone;
26 $error = $record->insert;
28 $error = $new_record->replace($old_record);
30 $error = $record->delete;
32 $error = $record->check;
34 @pkg_svc = $record->pkg_svc;
36 $svcnum = $record->svcpart;
37 $svcnum = $record->svcpart( 'svc_acct' );
41 An FS::part_pkg object represents a billing item definition. FS::part_pkg
42 inherits from FS::Record. The following fields are currently supported:
46 =item pkgpart - primary key (assigned automatically for new billing item definitions)
48 =item pkg - Text name of this billing item definition (customer-viewable)
50 =item comment - Text name of this billing item definition (non-customer-viewable)
52 =item setup - Setup fee expression
54 =item freq - Frequency of recurring fee
56 =item recur - Recurring fee expression
58 =item setuptax - Setup fee tax exempt flag, empty or `Y'
60 =item recurtax - Recurring fee tax exempt flag, empty or `Y'
62 =item plan - Price plan
64 =item plandata - Price plan data
66 =item disabled - Disabled flag, empty or `Y'
70 setup and recur are evaluated as Safe perl expressions. You can use numbers
71 just as you would normally. More advanced semantics are not yet defined.
79 Creates a new billing item definition. To add the billing item definition to
80 the database, see L<"insert">.
84 sub table { 'part_pkg'; }
88 An alternate constructor. Creates a new billing item definition by duplicating
89 an existing definition. A new pkgpart is assigned and `(CUSTOM) ' is prepended
90 to the comment field. To add the billing item definition to the database, see
97 my $class = ref($self);
98 my %hash = $self->hash;
99 $hash{'pkgpart'} = '';
100 $hash{'comment'} = "(CUSTOM) ". $hash{'comment'}
101 unless $hash{'comment'} =~ /^\(CUSTOM\) /;
102 #new FS::part_pkg ( \%hash ); # ?
103 new $class ( \%hash ); # ?
108 Adds this billing item definition to the database. If there is an error,
109 returns the error, otherwise returns false.
116 local $SIG{HUP} = 'IGNORE';
117 local $SIG{INT} = 'IGNORE';
118 local $SIG{QUIT} = 'IGNORE';
119 local $SIG{TERM} = 'IGNORE';
120 local $SIG{TSTP} = 'IGNORE';
121 local $SIG{PIPE} = 'IGNORE';
123 my $oldAutoCommit = $FS::UID::AutoCommit;
124 local $FS::UID::AutoCommit = 0;
127 my $error = $self->SUPER::insert;
129 $dbh->rollback if $oldAutoCommit;
133 my $conf = new FS::Conf;
135 if ( $conf->exists('agent_defaultpkg') ) {
136 foreach my $agent_type ( qsearch('agent_type', {} ) ) {
137 my $type_pkgs = new FS::type_pkgs({
138 'typenum' => $agent_type->typenum,
139 'pkgpart' => $self->pkgpart,
141 my $error = $type_pkgs->insert;
143 $dbh->rollback if $oldAutoCommit;
149 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
156 Currently unimplemented.
161 return "Can't (yet?) delete package definitions.";
162 # check & make sure the pkgpart isn't in cust_pkg or type_pkgs?
165 =item replace OLD_RECORD
167 Replaces OLD_RECORD with this one in the database. If there is an error,
168 returns the error, otherwise returns false.
172 Checks all fields to make sure this is a valid billing item definition. If
173 there is an error, returns the error, otherwise returns false. Called by the
174 insert and replace methods.
181 my $conf = new FS::Conf;
182 if ( $conf->exists('safe-part_pkg') ) {
184 my $error = $self->ut_anything('setup')
185 || $self->ut_anything('recur');
186 return $error if $error;
188 my $s = $self->setup;
190 $s =~ /^\s*\d*\.?\d*\s*$/ or do {
192 return "illegal setup: $s";
195 my $r = $self->recur;
197 $r =~ /^\s*\d*\.?\d*\s*$/
199 or $r =~ /^my \$mnow = \$sdate; my \(\$sec,\$min,\$hour,\$mday,\$mon,\$year\) = \(localtime\(\$sdate\) \)\[0,1,2,3,4,5\]; my \$mstart = timelocal\(0,0,0,1,\$mon,\$year\); my \$mend = timelocal\(0,0,0,1, \$mon == 11 \? 0 : \$mon\+1, \$year\+\(\$mon==11\)\); \$sdate = \$mstart; \( \$part_pkg->freq \- 1 \) \* \d*\.?\d* \/ \$part_pkg\-\>freq \+ \d*\.?\d* \/ \$part_pkg\-\>freq \* \(\$mend\-\$mnow\) \/ \(\$mend\-\$mstart\) ;\s*$/
201 or $r =~ /^my \$mnow = \$sdate; my \(\$sec,\$min,\$hour,\$mday,\$mon,\$year\) = \(localtime\(\$sdate\) \)\[0,1,2,3,4,5\]; \$sdate = timelocal\(0,0,0,1,\$mon,\$year\); \s*\d*\.?\d*\s*;\s*$/
203 or $r =~ /^my \$error = \$cust_pkg\->cust_main\->credit\( \s*\d*\.?\d*\s* \* scalar\(\$cust_pkg\->cust_main\->referral_cust_main_ncancelled\(\s*\d+\s*\)\), "commission" \); die \$error if \$error; \s*\d*\.?\d*\s*;\s*$/
205 or $r =~ /^my \$error = \$cust_pkg\->cust_main\->credit\( \s*\d*\.?\d*\s* \* scalar\(\$cust_pkg\->cust_main->referral_cust_pkg\(\s*\d+\s*\)\), "commission" \); die \$error if \$error; \s*\d*\.?\d*\s*;\s*$/
207 or $r =~ /^my \$error = \$cust_pkg\->cust_main\->credit\( \s*\d*\.?\d*\s* \* scalar\( grep \{ my \$pkgpart = \$_\->pkgpart; grep \{ \$_ == \$pkgpart \} \(\s*(\s*\d+,\s*)*\s*\) \} \$cust_pkg\->cust_main->referral_cust_pkg\(\s*\d+\s*\)\), "commission" \); die \$error if \$error; \s*\d*\.?\d*\s*;\s*$/
209 or $r =~ /^my \$hours = \$cust_pkg\->seconds_since\(\$cust_pkg\->bill \|\| 0\) \/ 3600 \- \s*\d*\.?\d*\s*; \$hours = 0 if \$hours < 0; \s*\d*\.?\d*\s* \+ \s*\d*\.?\d*\s* \* \$hours;\s*$/
211 or $r =~ /^my \$min = \$cust_pkg\->seconds_since\(\$cust_pkg\->bill \|\| 0\) \/ 60 \- \s*\d*\.?\d*\s*; \$min = 0 if \$min < 0; \s*\d*\.?\d*\s* \+ \s*\d*\.?\d*\s* \* \$min;\s*$/
215 return "illegal recur: $r";
220 $self->ut_numbern('pkgpart')
221 || $self->ut_text('pkg')
222 || $self->ut_text('comment')
223 || $self->ut_anything('setup')
224 || $self->ut_number('freq')
225 || $self->ut_anything('recur')
226 || $self->ut_alphan('plan')
227 || $self->ut_anything('plandata')
228 || $self->ut_enum('setuptax', [ '', 'Y' ] )
229 || $self->ut_enum('recurtax', [ '', 'Y' ] )
230 || $self->ut_enum('disabled', [ '', 'Y' ] )
236 Returns all FS::pkg_svc objects (see L<FS::pkg_svc>) for this package
237 definition (with non-zero quantity).
243 grep { $_->quantity } qsearch( 'pkg_svc', { 'pkgpart' => $self->pkgpart } );
246 =item svcpart [ SVCDB ]
248 Returns the svcpart of a single service definition (see L<FS::part_svc>)
249 associated with this billing item definition (see L<FS::pkg_svc>). Returns
250 false if there not exactly one service definition with quantity 1, or if
251 SVCDB is specified and does not match the svcdb of the service definition,
258 my @pkg_svc = $self->pkg_svc;
259 return '' if scalar(@pkg_svc) != 1
260 || $pkg_svc[0]->quantity != 1
261 || ( $svcdb && $pkg_svc[0]->part_svc->svcdb ne $svcdb );
262 $pkg_svc[0]->svcpart;
269 $Id: part_pkg.pm,v 1.9 2002-03-24 17:42:58 ivan Exp $
273 The delete method is unimplemented.
275 setup and recur semantics are not yet defined (and are implemented in
276 FS::cust_bill. hmm.).
280 L<FS::Record>, L<FS::cust_pkg>, L<FS::type_pkgs>, L<FS::pkg_svc>, L<Safe>.
281 schema.html from the base documentation.