stray closing /TABLE in the no-ticket case
[freeside.git] / FS / FS / FeeOrigin_Mixin.pm
1 package FS::FeeOrigin_Mixin;
2
3 use strict;
4 use base qw( FS::Record );
5 use FS::Record qw( qsearch qsearchs );
6 use FS::part_fee;
7 use FS::cust_bill_pkg;
8
9 # is there a nicer idiom for this?
10 our @subclasses = qw( FS::cust_event_fee FS::cust_pkg_reason_fee );
11 use FS::cust_event_fee;
12 use FS::cust_pkg_reason_fee;
13
14 =head1 NAME
15
16 FS::FeeOrigin_Mixin - Common interface for fee origin records
17
18 =head1 SYNOPSIS
19
20   use FS::cust_event_fee;
21
22   $record = new FS::cust_event_fee \%hash;
23   $record = new FS::cust_event_fee { 'column' => 'value' };
24
25   $error = $record->insert;
26
27   $error = $new_record->replace($old_record);
28
29   $error = $record->delete;
30
31   $error = $record->check;
32
33 =head1 DESCRIPTION
34
35 An FS::FeeOrigin_Mixin object associates the timestamped event that triggered 
36 a fee (which may be a billing event, or something else like a package
37 suspension) to the resulting invoice line item (L<FS::cust_bill_pkg> object).
38 The following fields are required:
39
40 =over 4
41
42 =item billpkgnum - key of the cust_bill_pkg record representing the fee 
43 on an invoice.  This is a unique column but can be NULL to indicate a fee that
44 hasn't been billed yet.  In that case it will be billed the next time billing
45 runs for the customer.
46
47 =item feepart - key of the fee definition (L<FS::part_fee>).
48
49 =item nextbill - 'Y' if the fee should be charged on the customer's next bill,
50 rather than causing a bill to be produced immediately.
51
52 =back
53
54 =head1 CLASS METHODS
55
56 =over 4
57
58 =item by_cust CUSTNUM[, PARAMS]
59
60 Finds all cust_event_fee records belonging to the customer CUSTNUM.
61
62 PARAMS can be additional params to pass to qsearch; this really only works
63 for 'hashref' and 'order_by'.
64
65 =cut
66
67 # invoke for all subclasses, and return the results as a flat list
68
69 sub by_cust {
70   my $class = shift;
71   my @args = @_;
72   return map { $_->_by_cust(@args) } @subclasses;
73 }
74
75 =back
76
77 =head1 INTERFACE
78
79 =over 4
80
81 =item _by_cust CUSTNUM[, PARAMS]
82
83 The L</by_cust> search method. Each subclass must implement this.
84
85 =item cust_bill
86
87 If the fee origin generates a fee based on past invoices (for example, an
88 invoice event that charges late fees), this method should return the
89 L<FS::cust_bill> object that will be the basis for the fee. If this returns
90 nothing, then then fee will be based on the rest of the invoice where it
91 appears.
92
93 =item cust_pkg
94
95 If the fee origin generates a fee limited in scope to one package (for
96 example, a package reconnection fee event), this method should return the
97 L<FS::cust_pkg> object the fee applies to. If it's a percentage fee, this
98 determines which charges it's a percentage of; otherwise it just affects the
99 fee description appearing on the invoice.
100
101 Currently not tested in combination with L</cust_bill>; be careful.
102
103 =cut
104
105 # stubs
106
107 sub _by_cust { my $class = shift; die "'$class' must provide _by_cust method" }
108
109 sub cust_bill { '' }
110
111 sub cust_pkg { '' }
112
113 # still necessary in 4.x; can't FK the billpkgnum because of voids
114 sub cust_bill_pkg {
115   my $self = shift;
116   $self->billpkgnum ? FS::cust_bill_pkg->by_key($self->billpkgnum) : '';
117 }
118
119 =head1 BUGS
120
121 =head1 SEE ALSO
122
123 L<FS::cust_event_fee>, L<FS::cust_pkg_reason_fee>, L<FS::cust_bill_pkg>, 
124 L<FS::part_fee>
125
126 =cut
127
128 1;
129