supplemental packages, #20689
[freeside.git] / FS / FS / part_pkg_link.pm
1 package FS::part_pkg_link;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record qw( qsearchs );
6 use FS::part_pkg;
7
8 @ISA = qw(FS::Record);
9
10 =head1 NAME
11
12 FS::part_pkg_link - Object methods for part_pkg_link records
13
14 =head1 SYNOPSIS
15
16   use FS::part_pkg_link;
17
18   $record = new FS::part_pkg_link \%hash;
19   $record = new FS::part_pkg_link { 'column' => 'value' };
20
21   $error = $record->insert;
22
23   $error = $new_record->replace($old_record);
24
25   $error = $record->delete;
26
27   $error = $record->check;
28
29 =head1 DESCRIPTION
30
31 An FS::part_pkg_link object represents an link from one package definition to
32 another.  FS::part_pkg_link inherits from FS::Record.  The following fields are
33 currently supported:
34
35 =over 4
36
37 =item pkglinknum
38
39 primary key
40
41 =item src_pkgpart
42
43 Source package (see L<FS::part_pkg>)
44
45 =item dst_pkgpart
46
47 Destination package (see L<FS::part_pkg>)
48
49 =item link_type
50
51 Link type - currently, "bill" (source package bills a line item from target
52 package), or "svc" (source package includes services from target package), 
53 or "supp" (ordering source package creates a target package).
54
55 =item hidden
56
57 Flag indicating that this subpackage should be felt, but not seen as an invoice
58 line item when set to 'Y'.  Not allowed for "supp" links.
59
60 =back
61
62 =head1 METHODS
63
64 =over 4
65
66 =item new HASHREF
67
68 Creates a new link.  To add the link to the database, see L<"insert">.
69
70 Note that this stores the hash reference, not a distinct copy of the hash it
71 points to.  You can ask the object for a copy with the I<hash> method.
72
73 =cut
74
75 # the new method can be inherited from FS::Record, if a table method is defined
76
77 sub table { 'part_pkg_link'; }
78
79 =item insert
80
81 Adds this record to the database.  If there is an error, returns the error,
82 otherwise returns false.
83
84 =cut
85
86 # the insert method can be inherited from FS::Record
87
88 =item delete
89
90 Delete this record from the database.
91
92 =cut
93
94 # the delete method can be inherited from FS::Record
95
96 =item replace OLD_RECORD
97
98 Replaces the OLD_RECORD with this one in the database.  If there is an error,
99 returns the error, otherwise returns false.
100
101 =cut
102
103 # the replace method can be inherited from FS::Record
104
105 =item check
106
107 Checks all fields to make sure this is a valid link.  If there is
108 an error, returns the error, otherwise returns false.  Called by the insert
109 and replace methods.
110
111 =cut
112
113 # the check method should currently be supplied - FS::Record contains some
114 # data checking routines
115
116 sub check {
117   my $self = shift;
118
119   my $error = 
120     $self->ut_numbern('pkglinknum')
121     || $self->ut_foreign_key('src_pkgpart', 'part_pkg', 'pkgpart')
122     || $self->ut_foreign_key('dst_pkgpart', 'part_pkg', 'pkgpart')
123     || $self->ut_enum('link_type', [ 'bill', 'svc', 'supp' ] )
124     || $self->ut_enum('hidden', [ '', 'Y' ] )
125   ;
126   return $error if $error;
127
128   if ( $self->link_type eq 'supp' ) {
129     # some sanity checking
130     my $src_pkg = $self->src_pkg;
131     my $dst_pkg = $self->dst_pkg;
132     if ( $src_pkg->freq eq '0' and $dst_pkg->freq ne '0' ) {
133       return "One-time charges can't have supplemental packages."
134     } elsif ( $dst_pkg->freq ne '0' ) {
135       my $ratio = $dst_pkg->freq / $src_pkg->freq;
136       if ($ratio != int($ratio)) {
137         return "Supplemental package period (pkgpart ".$dst_pkg->pkgpart.
138                ") must be an integer multiple of main package period.";
139       }
140     }
141   }
142
143   $self->SUPER::check;
144 }
145
146 =item src_pkg
147
148 Returns the source part_pkg object (see L<FS::part_pkg>).
149
150 =cut
151
152 sub src_pkg {
153   my $self = shift;
154   qsearchs('part_pkg', { 'pkgpart' => $self->src_pkgpart } );
155 }
156
157 =item dst_pkg
158
159 Returns the source part_pkg object (see L<FS::part_pkg>).
160
161 =cut
162
163 sub dst_pkg {
164   my $self = shift;
165   qsearchs('part_pkg', { 'pkgpart' => $self->dst_pkgpart } );
166 }
167
168 =back
169
170 =head1 BUGS
171
172 =head1 SEE ALSO
173
174 L<FS::Record>, schema.html from the base documentation.
175
176 =cut
177
178 1;
179