svc_hardware uniqueness checks, RT#81534
[freeside.git] / FS / FS / cust_pkg_reason_fee.pm
1 package FS::cust_pkg_reason_fee;
2
3 use strict;
4 use base qw( FS::Record FS::FeeOrigin_Mixin );
5 use FS::Record qw( qsearch qsearchs );
6
7 =head1 NAME
8
9 FS::cust_pkg_reason_fee - Object methods for cust_pkg_reason_fee records
10
11 =head1 SYNOPSIS
12
13   use FS::cust_pkg_reason_fee;
14
15   $record = new FS::cust_pkg_reason_fee \%hash;
16   $record = new FS::cust_pkg_reason_fee { 'column' => 'value' };
17
18   $error = $record->insert;
19
20   $error = $new_record->replace($old_record);
21
22   $error = $record->delete;
23
24   $error = $record->check;
25
26 =head1 DESCRIPTION
27
28 An FS::cust_pkg_reason_fee object links a package status change that charged
29 a fee (an L<FS::cust_pkg_reason> object) to the resulting invoice line item.
30 FS::cust_pkg_reason_fee inherits from FS::Record and FS::FeeOrigin_Mixin.  
31 The following fields are currently supported:
32
33 =over 4
34
35 =item pkgreasonfeenum - primary key
36
37 =item pkgreasonnum - key of the cust_pkg_reason object that triggered the fee.
38
39 =item billpkgnum - key of the cust_bill_pkg record representing the fee on an
40 invoice. This can be NULL if the fee is scheduled but hasn't been billed yet.
41
42 =item feepart - key of the fee definition (L<FS::part_fee>).
43
44 =item nextbill - 'Y' if the fee should be charged on the customer's next bill,
45 rather than causing a bill to be produced immediately.
46
47 =back
48
49 =head1 METHODS
50
51 =over 4
52
53 =item new HASHREF
54
55 Creates a new record.  To add the record to the database, see L<"insert">.
56
57 =cut
58
59 sub table { 'cust_pkg_reason_fee'; }
60
61 =item insert
62
63 Adds this record to the database.  If there is an error, returns the error,
64 otherwise returns false.
65
66 =item delete
67
68 Delete this record from the database.
69
70 =item replace OLD_RECORD
71
72 Replaces the OLD_RECORD with this one in the database.  If there is an error,
73 returns the error, otherwise returns false.
74
75 =item check
76
77 Checks all fields to make sure this is a valid example.  If there is
78 an error, returns the error, otherwise returns false.  Called by the insert
79 and replace methods.
80
81 =cut
82
83 sub check {
84   my $self = shift;
85
86   my $error = 
87     $self->ut_numbern('pkgreasonfeenum')
88     || $self->ut_foreign_key('pkgreasonnum', 'cust_pkg_reason', 'num')
89     || $self->ut_foreign_keyn('billpkgnum', 'cust_bill_pkg', 'billpkgnum')
90     || $self->ut_foreign_key('feepart', 'part_fee', 'feepart')
91     || $self->ut_flag('nextbill')
92   ;
93   return $error if $error;
94
95   $self->SUPER::check;
96 }
97
98 =back
99
100 =head1 CLASS METHODS
101
102 =over 4
103
104 =item _by_cust CUSTNUM[, PARAMS]
105
106 See L<FS::FeeOrigin_Mixin/by_cust>.
107
108 =cut
109
110 sub _by_cust {
111   my $class = shift;
112   my $custnum = shift or return;
113   my %params = @_;
114   $custnum =~ /^\d+$/ or die "bad custnum $custnum";
115     
116   my $where = ($params{hashref} && keys (%{ $params{hashref} }))
117               ? 'AND'
118               : 'WHERE';
119   qsearch({
120     table     => 'cust_pkg_reason_fee',
121     addl_from => 'JOIN cust_pkg_reason ON (cust_pkg_reason_fee.pkgreasonnum = cust_pkg_reason.num) ' .
122                  'JOIN cust_pkg USING (pkgnum) ',
123     extra_sql => "$where cust_pkg.custnum = $custnum",
124     %params
125   });
126 }
127
128 =back
129
130 =head1 METHODS
131
132 =over 4
133
134 =item cust_pkg
135
136 Returns the package that triggered the fee.
137
138 =cut
139
140 sub cust_pkg {
141   my $self = shift;
142   $self->cust_pkg_reason->cust_pkg;
143 }
144
145 =head1 SEE ALSO
146
147 L<FS::FeeOrigin_Mixin>, L<FS::cust_pkg_reason>, L<part_fee>
148
149 =cut
150
151 1;
152