separate reason classes for voiding different transaction types, #38532
[freeside.git] / FS / FS / reason_type.pm
1 package FS::reason_type;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record qw( qsearch qsearchs );
6
7 @ISA = qw(FS::Record);
8
9 tie our %class_name, Tie::IxHash, (  
10   'C' => 'cancel',
11   'R' => 'credit',
12   'S' => 'suspend',
13   'F' => 'refund',
14   'X' => 'void credit',
15   'I' => 'void invoice',
16   'P' => 'void payment',
17 );
18
19 our %class_purpose = (  
20   'C' => 'explain why a customer package was cancelled',
21   'R' => 'explain why a customer was credited',
22   'S' => 'explain why a customer package was suspended',
23   'F' => 'explain why a customer was refunded',
24   'X' => 'explain why a credit was voided',
25   'I' => 'explain why an invoice was voided',
26   'P' => 'explain why a payment was voided',
27 );
28
29 our %class_add_access_right = (
30   'C' => 'Add on-the-fly cancel reason',
31   'R' => 'Add on-the-fly credit reason',
32   'S' => 'Add on-the-fly suspend reason',
33   'F' => 'Add on-the-fly refund reason',
34   'X' => 'Add on-the-fly void reason',
35   'I' => 'Add on-the-fly void reason',
36   'P' => 'Add on-the-fly void reason',
37 );
38
39 =head1 NAME
40
41 FS::reason_type - Object methods for reason_type records
42
43 =head1 SYNOPSIS
44
45   use FS::reason_type;
46
47   $record = new FS::reason_type \%hash;
48   $record = new FS::reason_type { 'column' => 'value' };
49
50   $error = $record->insert;
51
52   $error = $new_record->replace($old_record);
53
54   $error = $record->delete;
55
56   $error = $record->check;
57
58 =head1 DESCRIPTION
59
60 An FS::reason_type object represents a grouping of reasons.  FS::reason_type
61 inherits from FS::Record.  The following fields are currently supported:
62
63 =over 4
64
65 =item typenum - primary key
66
67 =item class - one of the keys of %class_name
68
69 =item type - name of the type of reason
70
71
72 =back
73
74 =head1 METHODS
75
76 =over 4
77
78 =item new HASHREF
79
80 Creates a new reason_type.  To add the example to the database, see L<"insert">.
81
82 Note that this stores the hash reference, not a distinct copy of the hash it
83 points to.  You can ask the object for a copy with the I<hash> method.
84
85 =cut
86
87 sub table { 'reason_type'; }
88
89 =item insert
90
91 Adds this record to the database.  If there is an error, returns the error,
92 otherwise returns false.
93
94 =cut
95
96 =item delete
97
98 Delete this record from the database.
99
100 =cut
101
102 =item replace OLD_RECORD
103
104 Replaces the OLD_RECORD with this one in the database.  If there is an error,
105 returns the error, otherwise returns false.
106
107 =cut
108
109 =item check
110
111 Checks all fields to make sure this is a valid reason_type.  If there is
112 an error, returns the error, otherwise returns false.  Called by the insert
113 and replace methods.
114
115 =cut
116
117 sub check {
118   my $self = shift;
119
120   my $error = 
121     $self->ut_numbern('typenum')
122     || $self->ut_enum('class', [ keys %class_name ] )
123     || $self->ut_text('type')
124   ;
125   return $error if $error;
126
127   $self->SUPER::check;
128 }
129
130 =item reasons
131
132 Returns a list of all reasons associated with this type.
133
134 =cut
135
136 sub reasons {
137   qsearch( 'reason', { 'reason_type' => shift->typenum } );
138 }
139
140 =item enabled_reasons
141
142 Returns a list of enabled reasons associated with this type.
143
144 =cut
145
146 sub enabled_reasons {
147   qsearch( 'reason', { 'reason_type' => shift->typenum,
148                        'enabled'     => '',
149                      } );
150 }
151
152 # Used by FS::Setup to initialize a new database.
153 sub _populate_initial_data {  # class method
154   my ($self, %opts) = @_;
155
156   my $conf = new FS::Conf;
157
158   foreach ( keys %class_name ) {
159     my $object  = $self->new( {'class' => $_,
160                                'type' => ucfirst($class_name{$_}). ' Reason',
161                             } );
162     my $error   = $object->insert();
163     die "error inserting $self into database: $error\n"
164       if $error;
165   }
166
167   my $object = qsearchs('reason_type', { 'class' => 'R' });
168   die "can't find credit reason type just inserted!\n"
169     unless $object;
170
171   foreach ( keys %FS::cust_credit::reasontype_map ) {
172 #   my $object  = $self->new( {'class' => 'R',
173 #                              'type' => $FS::cust_credit::reasontype_map{$_},
174 #                           } );
175 #   my $error   = $object->insert();
176 #   die "error inserting $self into database: $error\n"
177 #     if $error;
178     $conf->set($_, $object->typenum);
179   }
180
181   '';
182
183 }
184
185 # Used by FS::Upgrade to migrate to a new database.
186 sub _upgrade_data {  # class method
187   my ($self, %opts) = @_;
188
189   foreach ( keys %class_name ) {
190     unless (scalar(qsearch('reason_type', { 'class' => $_ }))) {
191       my $object  = $self->new( {'class' => $_,
192                                  'type' => ucfirst($class_name{$_}),
193                               } );
194       my $error   = $object->insert();
195       die "error inserting $self into database: $error\n"
196         if $error;
197     }
198   }
199
200   '';
201
202 }
203
204 =back
205
206 =head1 BUGS
207
208 Here be termintes.  Don't use on wooden computers.
209
210 =head1 SEE ALSO
211
212 L<FS::Record>, schema.html from the base documentation.
213
214 =cut
215
216 1;
217