show credit balance on invoices, #11564
[freeside.git] / FS / FS / cust_bill_pkg_tax_location.pm
1 package FS::cust_bill_pkg_tax_location;
2
3 use strict;
4 use base qw( FS::Record );
5 use FS::Record qw( qsearch qsearchs );
6 use FS::cust_bill_pkg;
7 use FS::cust_pkg;
8 use FS::cust_location;
9 use FS::cust_bill_pay_pkg;
10 use FS::cust_credit_bill_pkg;
11 use FS::cust_main_county;
12
13 =head1 NAME
14
15 FS::cust_bill_pkg_tax_location - Object methods for cust_bill_pkg_tax_location records
16
17 =head1 SYNOPSIS
18
19   use FS::cust_bill_pkg_tax_location;
20
21   $record = new FS::cust_bill_pkg_tax_location \%hash;
22   $record = new FS::cust_bill_pkg_tax_location { 'column' => 'value' };
23
24   $error = $record->insert;
25
26   $error = $new_record->replace($old_record);
27
28   $error = $record->delete;
29
30   $error = $record->check;
31
32 =head1 DESCRIPTION
33
34 An FS::cust_bill_pkg_tax_location object represents an record of taxation
35 based on package location.  FS::cust_bill_pkg_tax_location inherits from
36 FS::Record.  The following fields are currently supported:
37
38 =over 4
39
40 =item billpkgtaxlocationnum
41
42 billpkgtaxlocationnum
43
44 =item billpkgnum
45
46 billpkgnum
47
48 =item taxnum
49
50 taxnum
51
52 =item taxtype
53
54 taxtype
55
56 =item pkgnum
57
58 pkgnum
59
60 =item locationnum
61
62 locationnum
63
64 =item amount
65
66 amount
67
68
69 =back
70
71 =head1 METHODS
72
73 =over 4
74
75 =item new HASHREF
76
77 Creates a new record.  To add the record to the database, see L<"insert">.
78
79 Note that this stores the hash reference, not a distinct copy of the hash it
80 points to.  You can ask the object for a copy with the I<hash> method.
81
82 =cut
83
84 sub table { 'cust_bill_pkg_tax_location'; }
85
86 =item insert
87
88 Adds this record to the database.  If there is an error, returns the error,
89 otherwise returns false.
90
91 =item delete
92
93 Delete this record from the database.
94
95 =item replace OLD_RECORD
96
97 Replaces the OLD_RECORD with this one in the database.  If there is an error,
98 returns the error, otherwise returns false.
99
100 =item check
101
102 Checks all fields to make sure this is a valid record.  If there is
103 an error, returns the error, otherwise returns false.  Called by the insert
104 and replace methods.
105
106 =cut
107
108 # the check method should currently be supplied - FS::Record contains some
109 # data checking routines
110
111 sub check {
112   my $self = shift;
113
114   my $error = 
115     $self->ut_numbern('billpkgtaxlocationnum')
116     || $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum' )
117     || $self->ut_number('taxnum') #cust_bill_pkg/tax_rate key, based on taxtype
118     || $self->ut_enum('taxtype', [ qw( FS::cust_main_county FS::tax_rate ) ] )
119     || $self->ut_foreign_key('pkgnum', 'cust_pkg', 'pkgnum' )
120     || $self->ut_foreign_key('locationnum', 'cust_location', 'locationnum' )
121     || $self->ut_money('amount')
122   ;
123   return $error if $error;
124
125   $self->SUPER::check;
126 }
127
128 =item cust_bill_pkg
129
130 Returns the associated cust_bill_pkg object
131
132 =cut
133
134 sub cust_bill_pkg {
135   my $self = shift;
136   qsearchs( 'cust_bill_pkg', { 'billpkgnum' => $self->billpkgnum }  );
137 }
138
139 =item cust_location
140
141 Returns the associated cust_location object
142
143 =cut
144
145 sub cust_location {
146   my $self = shift;
147   qsearchs( 'cust_location', { 'locationnum' => $self->locationnum }  );
148 }
149
150 =item desc
151
152 Returns a description for this tax line item constituent.  Currently this
153 is the desc of the associated line item followed by the state/county/city
154 for the location in parentheses.
155
156 =cut
157
158 sub desc {
159   my $self = shift;
160   my $cust_location = $self->cust_location;
161   my $location = join('/', grep { $_ }                 # leave in?
162                            map { $cust_location->$_ }
163                            qw( state county city )     # country?
164   );
165   my $cust_bill_pkg_desc = $self->billpkgnum
166                          ? $self->cust_bill_pkg->desc
167                          : $self->cust_bill_pkg_desc;
168   "$cust_bill_pkg_desc ($location)";
169 }
170
171 =item owed
172
173 Returns the amount owed (still outstanding) on this tax line item which is
174 the amount of this record minus all payment applications and credit
175 applications.
176
177 =cut
178
179 sub owed {
180   my $self = shift;
181   my $balance = $self->amount;
182   $balance -= $_->amount foreach ( $self->cust_bill_pay_pkg('setup') );
183   $balance -= $_->amount foreach ( $self->cust_credit_bill_pkg('setup') );
184   $balance = sprintf( '%.2f', $balance );
185   $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp
186   $balance;
187 }
188
189 sub cust_bill_pay_pkg {
190   my $self = shift;
191   qsearch( 'cust_bill_pay_pkg',
192            { map { $_ => $self->$_ } qw( billpkgtaxlocationnum billpkgnum ) }
193          );
194 }
195
196 sub cust_credit_bill_pkg {
197   my $self = shift;
198   qsearch( 'cust_credit_bill_pkg',
199            { map { $_ => $self->$_ } qw( billpkgtaxlocationnum billpkgnum ) }
200          );
201 }
202
203 sub cust_main_county {
204   my $self = shift;
205   my $result;
206   if ( $self->taxtype eq 'FS::cust_main_county' ) {
207     $result = qsearchs( 'cust_main_county', { 'taxnum' => $self->taxnum } );
208   }
209 }
210
211 =back
212
213 =head1 BUGS
214
215 The presense of FS::cust_main_county::delete makes the cust_main_county method
216 unreliable
217
218 =head1 SEE ALSO
219
220 L<FS::Record>, schema.html from the base documentation.
221
222 =cut
223
224 1;
225