autoload methods returning foreign records, RT#13971
[freeside.git] / FS / FS / discount.pm
1 package FS::discount;
2 use base qw( FS::Record );
3
4 use strict;
5
6 =head1 NAME
7
8 FS::discount - Object methods for discount records
9
10 =head1 SYNOPSIS
11
12   use FS::discount;
13
14   $record = new FS::discount \%hash;
15   $record = new FS::discount { 'column' => 'value' };
16
17   $error = $record->insert;
18
19   $error = $new_record->replace($old_record);
20
21   $error = $record->delete;
22
23   $error = $record->check;
24
25 =head1 DESCRIPTION
26
27 An FS::discount object represents a discount definition.  FS::discount inherits
28 from FS::Record.  The following fields are currently supported:
29
30 =over 4
31
32 =item discountnum
33
34 primary key
35
36 =item name
37
38 name
39
40 =item amount
41
42 amount
43
44 =item percent
45
46 percent
47
48 =item months
49
50 months
51
52 =item disabled
53
54 disabled
55
56 =item setup - apply discount to setup fee (not just to recurring fee)
57
58 If the discount is based on a percentage, then the % will be applied to the
59 setup and recurring portions. 
60
61 =back
62
63 =head1 METHODS
64
65 =over 4
66
67 =item new HASHREF
68
69 Creates a new discount.  To add the discount to the database, see L<"insert">.
70
71 Note that this stores the hash reference, not a distinct copy of the hash it
72 points to.  You can ask the object for a copy with the I<hash> method.
73
74 =cut
75
76 # the new method can be inherited from FS::Record, if a table method is defined
77
78 sub table { 'discount'; }
79
80 =item insert
81
82 Adds this record to the database.  If there is an error, returns the error,
83 otherwise returns false.
84
85 =cut
86
87 # the insert method can be inherited from FS::Record
88
89 =item delete
90
91 Delete this record from the database.
92
93 =cut
94
95 # the delete method can be inherited from FS::Record
96
97 =item replace OLD_RECORD
98
99 Replaces the OLD_RECORD with this one in the database.  If there is an error,
100 returns the error, otherwise returns false.
101
102 =cut
103
104 # the replace method can be inherited from FS::Record
105
106 =item check
107
108 Checks all fields to make sure this is a valid discount.  If there is
109 an error, returns the error, otherwise returns false.  Called by the insert
110 and replace methods.
111
112 =cut
113
114 # the check method should currently be supplied - FS::Record contains some
115 # data checking routines
116
117 sub check {
118   my $self = shift;
119
120   if ( $self->_type eq 'Select discount type' ) {
121     return 'Please select a discount type';
122   } elsif ( $self->_type eq 'Amount' ) {
123     $self->percent('0');
124     return 'Amount must be greater than 0' unless $self->amount > 0;
125   } elsif ( $self->_type eq 'Percentage' ) {
126     $self->amount('0.00');
127     return 'Percentage must be greater than 0' unless $self->percent > 0;
128   }
129
130   my $error = 
131     $self->ut_numbern('discountnum')
132     || $self->ut_foreign_keyn('classnum', 'discount_class', 'classnum')
133     || $self->ut_textn('name')
134     || $self->ut_money('amount')
135     || $self->ut_float('percent') #actually decimal, but this will do
136     || $self->ut_floatn('months') #actually decimal, but this will do
137     || $self->ut_enum('disabled', [ '', 'Y' ])
138     || $self->ut_enum('setup', [ '', 'Y' ])
139     #|| $self->ut_enum('linked', [ '', 'Y' ])
140   ;
141   return $error if $error;
142
143 #causes "months must be integers greater than 1" errors when you go back and
144 # try to edit an existing discount (because the months format as NN.000)
145 #not worth whatever reason it came in with "prepayment discounts rt#5318" for
146 #  #discourage non-integer months for package discounts
147 #  if ($self->discountnum) {
148 #    my $sql =
149 #      "SELECT count(*) FROM part_pkg_discount WHERE part_pkg_discount.discountnum = ".
150 #      $self->discountnum;
151 #
152 #    my $count = $self->scalar_sql($sql); 
153 #    return "months must be integers greater than 1"
154 #      if ( $count && ($self->ut_number('months') || $self->months < 2) );
155 #  }
156     
157   $self->SUPER::check;
158 }
159
160 =item description_short
161
162 =item description
163
164 Returns a text description incorporating the amount, percent and months fields.
165
166 description_short omits term information
167
168 =cut
169
170 sub description_short {
171   my $self = shift;
172
173   my $conf = new FS::Conf;
174   my $money_char = $conf->config('money_char') || '$';  
175
176   my $desc = $self->name ? $self->name.': ' : '';
177   $desc .= $money_char. sprintf('%.2f/month ', $self->amount)
178     if $self->amount > 0;
179
180   ( my $percent = $self->percent ) =~ s/\.0+$//;
181   $percent =~ s/(\.\d*[1-9])0+$/$1/;
182   $desc .= $percent. '% '
183     if $self->percent > 0;
184
185   $desc;
186 }
187
188 sub description {
189   my $self = shift;
190   my $desc = $self->description_short;
191
192   ( my $months = $self->months ) =~ s/\.0+$//;
193   $months =~ s/(\.\d*[1-9])0+$/$1/;
194   $desc .= " for $months months" if $months;
195
196   $desc .= ', applies to setup' if $self->setup;
197
198   $desc;
199 }
200
201 sub classname {
202   my $self = shift;
203   my $discount_class = $self->discount_class;
204   $discount_class ? $discount_class->classname : '(none)';
205 }
206
207 =back
208
209 =head1 BUGS
210
211 =head1 SEE ALSO
212
213 L<FS::cust_pkg_discount>, L<FS::Record>, schema.html from the base documentation.
214
215 =cut
216
217 1;
218