ceb2a01280f1dd05dd2fe5f47da2d2abe806007f
[freeside.git] / FS / FS / part_pkg.pm
1 package FS::part_pkg;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record qw( qsearch );
6 use FS::pkg_svc;
7
8 @ISA = qw( FS::Record );
9
10 =head1 NAME
11
12 FS::part_pkg - Object methods for part_pkg objects
13
14 =head1 SYNOPSIS
15
16   use FS::part_pkg;
17
18   $record = new FS::part_pkg \%hash
19   $record = new FS::part_pkg { 'column' => 'value' };
20
21   $custom_record = $template_record->clone;
22
23   $error = $record->insert;
24
25   $error = $new_record->replace($old_record);
26
27   $error = $record->delete;
28
29   $error = $record->check;
30
31   @pkg_svc = $record->pkg_svc;
32
33   $svcnum = $record->svcpart;
34   $svcnum = $record->svcpart( 'svc_acct' );
35
36 =head1 DESCRIPTION
37
38 An FS::part_pkg object represents a billing item definition.  FS::part_pkg
39 inherits from FS::Record.  The following fields are currently supported:
40
41 =over 4
42
43 =item pkgpart - primary key (assigned automatically for new billing item definitions)
44
45 =item pkg - Text name of this billing item definition (customer-viewable)
46
47 =item comment - Text name of this billing item definition (non-customer-viewable)
48
49 =item setup - Setup fee expression
50
51 =item freq - Frequency of recurring fee
52
53 =item recur - Recurring fee expression
54
55 =item setuptax - Setup fee tax exempt flag, empty or `Y'
56
57 =item recurtax - Recurring fee tax exempt flag, empty or `Y'
58
59 =item plan - Price plan
60
61 =item plandata - Price plan data
62
63 =back
64
65 setup and recur are evaluated as Safe perl expressions.  You can use numbers
66 just as you would normally.  More advanced semantics are not yet defined.
67
68 =head1 METHODS
69
70 =over 4 
71
72 =item new HASHREF
73
74 Creates a new billing item definition.  To add the billing item definition to
75 the database, see L<"insert">.
76
77 =cut
78
79 sub table { 'part_pkg'; }
80
81 =item clone
82
83 An alternate constructor.  Creates a new billing item definition by duplicating
84 an existing definition.  A new pkgpart is assigned and `(CUSTOM) ' is prepended
85 to the comment field.  To add the billing item definition to the database, see
86 L<"insert">.
87
88 =cut
89
90 sub clone {
91   my $self = shift;
92   my $class = ref($self);
93   my %hash = $self->hash;
94   $hash{'pkgpart'} = '';
95   $hash{'comment'} = "(CUSTOM) ". $hash{'comment'}
96     unless $hash{'comment'} =~ /^\(CUSTOM\) /;
97   #new FS::part_pkg ( \%hash ); # ?
98   new $class ( \%hash ); # ?
99 }
100
101 =item insert
102
103 Adds this billing item definition to the database.  If there is an error,
104 returns the error, otherwise returns false.
105
106 =item delete
107
108 Currently unimplemented.
109
110 =cut
111
112 sub delete {
113   return "Can't (yet?) delete package definitions.";
114 # check & make sure the pkgpart isn't in cust_pkg or type_pkgs?
115 }
116
117 =item replace OLD_RECORD
118
119 Replaces OLD_RECORD with this one in the database.  If there is an error,
120 returns the error, otherwise returns false.
121
122 =item check
123
124 Checks all fields to make sure this is a valid billing item definition.  If
125 there is an error, returns the error, otherwise returns false.  Called by the
126 insert and replace methods.
127
128 =cut
129
130 sub check {
131   my $self = shift;
132
133   my $error = $self->ut_numbern('pkgpart')
134     || $self->ut_text('pkg')
135     || $self->ut_text('comment')
136     || $self->ut_anything('setup')
137     || $self->ut_number('freq')
138     || $self->ut_anything('recur')
139     || $self->ut_alphan('plan')
140     || $self->ut_anything('plandata')
141   ;
142   return $error if $error;
143
144   $self->setuptax =~ /^(Y?)$/ or return "Illegal setuptax: ". $self->setuptax;
145   $self->setuptax($1);
146
147   $self->recurtax =~ /^(Y?)$/ or return "Illegal recrutax: ". $self->recurtax;
148   $self->recurtax($1);
149
150   '';
151 }
152
153 =item pkg_svc
154
155 Returns all FS::pkg_svc objects (see L<FS::pkg_svc>) for this package
156 definition (with non-zero quantity).
157
158 =cut
159
160 sub pkg_svc {
161   my $self = shift;
162   grep { $_->quantity } qsearch( 'pkg_svc', { 'pkgpart' => $self->pkgpart } );
163 }
164
165 =item svcpart [ SVCDB ]
166
167 Returns the svcpart of a single service definition (see L<FS::part_svc>)
168 associated with this billing item definition (see L<FS::pkg_svc>).  Returns
169 false if there not exactly one service definition with quantity 1, or if 
170 SVCDB is specified and does not match the svcdb of the service definition, 
171
172 =cut
173
174 sub svcpart {
175   my $self = shift;
176   my $svcdb = shift;
177   my @pkg_svc = $self->pkg_svc;
178   return '' if scalar(@pkg_svc) != 1
179                || $pkg_svc[0]->quantity != 1
180                || ( $svcdb && $pkg_svc[0]->part_svc->svcdb ne $svcdb );
181   $pkg_svc[0]->svcpart;
182 }
183
184 =back
185
186 =head1 VERSION
187
188 $Id: part_pkg.pm,v 1.4 2001-10-20 12:17:59 ivan Exp $
189
190 =head1 BUGS
191
192 The delete method is unimplemented.
193
194 setup and recur semantics are not yet defined (and are implemented in
195 FS::cust_bill.  hmm.).
196
197 =head1 SEE ALSO
198
199 L<FS::Record>, L<FS::cust_pkg>, L<FS::type_pkgs>, L<FS::pkg_svc>, L<Safe>.
200 schema.html from the base documentation.
201
202 =cut
203
204 1;
205