eliminate some false laziness in FS::Misc::send_email vs. msg_template/email.pm send_...
[freeside.git] / FS / FS / acct_rt_transaction.pm
1 package FS::acct_rt_transaction;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record qw( qsearch qsearchs dbh );
6
7 @ISA = qw(FS::Record);
8
9 =head1 NAME
10
11 FS::acct_rt_transaction - Object methods for acct_rt_transaction records
12
13 =head1 SYNOPSIS
14
15   use FS::acct_rt_transaction;
16
17   $record = new FS::acct_rt_transaction \%hash;
18   $record = new FS::acct_rt_transaction { 'column' => 'value' };
19
20   $error = $record->insert;
21
22   $error = $new_record->replace($old_record);
23
24   $error = $record->delete;
25
26   $error = $record->check;
27
28 =head1 DESCRIPTION
29
30 An FS::acct_rt_transaction object represents an application of time
31 from a rt transaction to a svc_acct.  FS::acct_rt_transaction inherits from
32 FS::Record.  The following fields are currently supported:
33
34 =over 4
35
36 =item svcrtid
37
38 Primary key
39
40 =item svcnum
41
42 The svcnum of the svc_acct to which the time applies
43
44 =item transaction_id
45
46 The id of the rt transtaction from which the time applies
47
48 =item seconds
49
50 The amount of time applied from tickets
51
52 =item support
53
54 The amount of time applied to support services
55
56 =back
57
58 =head1 METHODS
59
60 =over 4
61
62 =item new HASHREF
63
64 Creates a new acct_rt_transaction.  To add the example to the database, see L<"insert">.
65
66 Note that this stores the hash reference, not a distinct copy of the hash it
67 points to.  You can ask the object for a copy with the I<hash> method.
68
69 =cut
70
71 sub table { 'acct_rt_transaction'; }
72
73 =item insert
74
75 Adds this record to the database.  If there is an error, returns the error,
76 otherwise returns false.
77
78 =cut
79
80 sub insert {
81   my( $self, %options ) = @_;
82   
83   local $SIG{HUP} = 'IGNORE';
84   local $SIG{INT} = 'IGNORE';
85   local $SIG{QUIT} = 'IGNORE';
86   local $SIG{TERM} = 'IGNORE';
87   local $SIG{TSTP} = 'IGNORE';
88   local $SIG{PIPE} = 'IGNORE';
89
90   my $oldAutoCommit = $FS::UID::AutoCommit;
91   local $FS::UID::AutoCommit = 0;
92   my $dbh = dbh;
93
94   my $error = $self->SUPER::insert($options{options} ? %{$options{options}} : ());
95   if ( $error ) {
96     $dbh->rollback if $oldAutoCommit;
97     return $error;
98   }
99
100   my $svc_acct = qsearchs('svc_acct', {'svcnum' => $self->svcnum});
101   unless ($svc_acct) {
102     $dbh->rollback if $oldAutoCommit;
103     return "Can't find svc_acct " . $self->svcnum;
104   }
105
106   $error = $svc_acct->decrement_seconds($self->support);
107   if ( $error ) {
108     $dbh->rollback if $oldAutoCommit;
109     return "Error incrementing service seconds: $error";
110   }
111   
112   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
113   '';
114
115 }
116
117
118 =item delete
119
120 Delete this record from the database.
121
122 =cut
123
124 sub delete { 
125   my $self = shift;
126
127   local $SIG{HUP} = 'IGNORE';
128   local $SIG{INT} = 'IGNORE';
129   local $SIG{QUIT} = 'IGNORE';
130   local $SIG{TERM} = 'IGNORE';
131   local $SIG{TSTP} = 'IGNORE';
132   local $SIG{PIPE} = 'IGNORE';
133
134   my $oldAutoCommit = $FS::UID::AutoCommit;
135   local $FS::UID::AutoCommit = 0;
136   my $dbh = dbh;
137
138   my $error = $self->SUPER::delete;
139   if ( $error ) {
140     $dbh->rollback if $oldAutoCommit;
141     return $error;
142   }
143
144   my $svc_acct = qsearchs('svc_acct', {'svcnum' => $self->svcnum});
145   unless ($svc_acct) {
146     $dbh->rollback if $oldAutoCommit;
147     return "Can't find svc_acct " . $self->svcnum;
148   }
149
150   $error = $svc_acct->increment_seconds($self->support);
151   if ( $error ) {
152     $dbh->rollback if $oldAutoCommit;
153     return "Error incrementing service seconds: $error";
154   }
155   
156   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
157   '';
158
159 }
160
161 =item replace OLD_RECORD
162
163 Replaces the OLD_RECORD with this one in the database.  If there is an error,
164 returns the error, otherwise returns false.
165
166 =cut
167
168 =item check
169
170 Checks all fields to make sure this is a valid acct_rt_transaction.  If there is
171 an error, returns the error, otherwise returns false.  Called by the insert
172 and replace methods.
173
174 =cut
175
176 sub check {
177   my $self = shift;
178
179   my ($selfref) = $self->hashref;
180
181   my $error = 
182     $self->ut_numbern('svcrtid')
183     || $self->ut_numbern('svcnum')
184     || $self->ut_number('transaction_id')
185     || $self->ut_numbern('_date')
186     || $self->ut_snumber('seconds')
187     || $self->ut_snumber('support')
188   ;
189   return $error if $error;
190
191   $self->_date(time) unless $self->_date;
192
193   if ($selfref->{custnum}) {
194     my $conf = new FS::Conf;
195     my %packages = map { $_ => 1 } $conf->config('support_packages');
196     my $cust_main = qsearchs('cust_main',{ 'custnum' => $selfref->{custnum} } );
197     return "Invalid custnum: " . $selfref->{custnum} unless $cust_main;
198
199     my (@svcs) = map { $_->svcnum } $cust_main->support_services;
200     return "svcnum ". $self->svcnum. " invalid for custnum ".$selfref->{custnum}
201       unless (!$self->svcnum || scalar(grep { $_ == $self->svcnum } @svcs));
202
203     $self->svcnum($svcs[0]) unless $self->svcnum;
204     return "Can't find support service for custnum ".$selfref->{custnum}
205       unless $self->svcnum;
206   }
207
208   $self->SUPER::check;
209 }
210
211 =item creator
212
213 Returns the creator of the RT transaction associated with this object.
214
215 =cut
216
217 sub creator {
218   my $self = shift;
219   FS::TicketSystem->transaction_creator($self->transaction_id);
220 }
221
222 =item ticketid
223
224 Returns the number of the RT ticket associated with this object.
225
226 =cut
227
228 sub ticketid {
229   my $self = shift;
230   FS::TicketSystem->transaction_ticketid($self->transaction_id);
231 }
232
233 =item subject
234
235 Returns the subject of the RT ticket associated with this object.
236
237 =cut
238
239 sub subject {
240   my $self = shift;
241   FS::TicketSystem->transaction_subject($self->transaction_id);
242 }
243
244 =item status
245
246 Returns the status of the RT ticket associated with this object.
247
248 =cut
249
250 sub status {
251   my $self = shift;
252   FS::TicketSystem->transaction_status($self->transaction_id);
253 }
254
255 =item batch_insert SVC_ACCT_RT_TRANSACTION_OBJECT, ...
256
257 Class method which inserts multiple time applications.  Takes a list of
258 FS::acct_rt_transaction objects.  If there is an error inserting any
259 application, the entire transaction is rolled back, i.e. all time is applied
260 or none is.
261
262 For example:
263
264   my $errors = FS::acct_rt_transaction->batch_insert(@transactions);
265   if ( $error ) {
266     #success; all payments were inserted
267   } else {
268     #failure; no payments were inserted.
269   }
270
271 =cut
272
273 sub batch_insert {
274   my $self = shift; #class method
275
276   local $SIG{HUP} = 'IGNORE';
277   local $SIG{INT} = 'IGNORE';
278   local $SIG{QUIT} = 'IGNORE';
279   local $SIG{TERM} = 'IGNORE';
280   local $SIG{TSTP} = 'IGNORE';
281   local $SIG{PIPE} = 'IGNORE';
282
283   my $oldAutoCommit = $FS::UID::AutoCommit;
284   local $FS::UID::AutoCommit = 0;
285   my $dbh = dbh;
286
287   my $error;
288   foreach (@_) {
289     $error = $_->insert;
290     last if $error;
291   }
292
293   if ( $error ) {
294     $dbh->rollback if $oldAutoCommit;
295   } else {
296     $dbh->commit or die $dbh->errstr if $oldAutoCommit;
297   }
298
299   $error;
300
301 }
302
303 =back
304
305 =head1 BUGS
306
307 Possibly the delete method or others.
308
309 =head1 SEE ALSO
310
311 L<FS::Record>, schema.html from the base documentation.
312
313 =cut
314
315 1;
316