5cddb91cf5043c31c149e73e6693beaf282b95c9
[freeside.git] / FS / FS / svc_Common.pm
1 package FS::svc_Common;
2
3 use strict;
4 use vars qw( @ISA $noexport_hack );
5 use FS::Record qw( qsearchs fields dbh );
6 use FS::cust_svc;
7 use FS::part_svc;
8
9 @ISA = qw( FS::Record );
10
11 =head1 NAME
12
13 FS::svc_Common - Object method for all svc_ records
14
15 =head1 SYNOPSIS
16
17 use FS::svc_Common;
18
19 @ISA = qw( FS::svc_Common );
20
21 =head1 DESCRIPTION
22
23 FS::svc_Common is intended as a base class for table-specific classes to
24 inherit from, i.e. FS::svc_acct.  FS::svc_Common inherits from FS::Record.
25
26 =head1 METHODS
27
28 =over 4
29
30 =item insert
31
32 Adds this record to the database.  If there is an error, returns the error,
33 otherwise returns false.
34
35 The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be 
36 defined.  An FS::cust_svc record will be created and inserted.
37
38 =cut
39
40 sub insert {
41   my $self = shift;
42   my $error;
43
44   local $SIG{HUP} = 'IGNORE';
45   local $SIG{INT} = 'IGNORE';
46   local $SIG{QUIT} = 'IGNORE';
47   local $SIG{TERM} = 'IGNORE';
48   local $SIG{TSTP} = 'IGNORE';
49   local $SIG{PIPE} = 'IGNORE';
50
51   my $oldAutoCommit = $FS::UID::AutoCommit;
52   local $FS::UID::AutoCommit = 0;
53   my $dbh = dbh;
54
55   $error = $self->check;
56   return $error if $error;
57
58   my $svcnum = $self->svcnum;
59   my $cust_svc;
60   unless ( $svcnum ) {
61     $cust_svc = new FS::cust_svc ( {
62       #hua?# 'svcnum'  => $svcnum,
63       'pkgnum'  => $self->pkgnum,
64       'svcpart' => $self->svcpart,
65     } );
66     $error = $cust_svc->insert;
67     if ( $error ) {
68       $dbh->rollback if $oldAutoCommit;
69       return $error;
70     }
71     $svcnum = $self->svcnum($cust_svc->svcnum);
72   } else {
73     $cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
74     unless ( $cust_svc ) {
75       $dbh->rollback if $oldAutoCommit;
76       return "no cust_svc record found for svcnum ". $self->svcnum;
77     }
78     $self->pkgnum($cust_svc->pkgnum);
79     $self->svcpart($cust_svc->svcpart);
80   }
81
82   $error = $self->SUPER::insert;
83   if ( $error ) {
84     $dbh->rollback if $oldAutoCommit;
85     return $error;
86   }
87
88   #new-style exports!
89   unless ( $noexport_hack ) {
90     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
91       my $error = $part_export->export_insert($self);
92       if ( $error ) {
93         $dbh->rollback if $oldAutoCommit;
94         return "exporting to ". $part_export->exporttype.
95                " (transaction rolled back): $error";
96       }
97     }
98   }
99
100   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
101
102   '';
103 }
104
105 =item delete
106
107 Deletes this account from the database.  If there is an error, returns the
108 error, otherwise returns false.
109
110 The corresponding FS::cust_svc record will be deleted as well.
111
112 =cut
113
114 sub delete {
115   my $self = shift;
116   my $error;
117
118   local $SIG{HUP} = 'IGNORE';
119   local $SIG{INT} = 'IGNORE';
120   local $SIG{QUIT} = 'IGNORE';
121   local $SIG{TERM} = 'IGNORE';
122   local $SIG{TSTP} = 'IGNORE';
123   local $SIG{PIPE} = 'IGNORE';
124
125   my $svcnum = $self->svcnum;
126
127   my $oldAutoCommit = $FS::UID::AutoCommit;
128   local $FS::UID::AutoCommit = 0;
129   my $dbh = dbh;
130
131   $error = $self->SUPER::delete;
132   return $error if $error;
133
134   #new-style exports!
135   unless ( $noexport_hack ) {
136     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
137       my $error = $part_export->export_delete($self);
138       if ( $error ) {
139         $dbh->rollback if $oldAutoCommit;
140         return "exporting to ". $part_export->exporttype.
141                " (transaction rolled back): $error";
142       }
143     }
144   }
145
146   return $error if $error;
147
148   my $cust_svc = $self->cust_svc;
149   $error = $cust_svc->delete;
150   return $error if $error;
151
152   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
153
154   '';
155 }
156
157 =item replace OLD_RECORD
158
159 Replaces OLD_RECORD with this one.  If there is an error, returns the error,
160 otherwise returns false.
161
162 =cut
163
164 sub replace {
165   my ($new, $old) = (shift, shift);
166   my $error;
167
168   local $SIG{HUP} = 'IGNORE';
169   local $SIG{INT} = 'IGNORE';
170   local $SIG{QUIT} = 'IGNORE';
171   local $SIG{TERM} = 'IGNORE';
172   local $SIG{TSTP} = 'IGNORE';
173   local $SIG{PIPE} = 'IGNORE';
174
175   my $oldAutoCommit = $FS::UID::AutoCommit;
176   local $FS::UID::AutoCommit = 0;
177   my $dbh = dbh;
178
179   my $error = $new->SUPER::replace($old);
180   if ($error) {
181     $dbh->rollback if $oldAutoCommit;
182     return $error;
183   }
184
185   #new-style exports!
186   unless ( $noexport_hack ) {
187     foreach my $part_export ( $new->cust_svc->part_svc->part_export ) {
188       my $error = $part_export->export_replace($new,$old);
189       if ( $error ) {
190         $dbh->rollback if $oldAutoCommit;
191         return "exporting to ". $part_export->exporttype.
192                " (transaction rolled back): $error";
193       }
194     }
195   }
196
197   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
198   '';
199 }
200
201
202 =item setfixed
203
204 Sets any fixed fields for this service (see L<FS::part_svc>).  If there is an
205 error, returns the error, otherwise returns the FS::part_svc object (use ref()
206 to test the return).  Usually called by the check method.
207
208 =cut
209
210 sub setfixed {
211   my $self = shift;
212   $self->setx('F');
213 }
214
215 =item setdefault
216
217 Sets all fields to their defaults (see L<FS::part_svc>), overriding their
218 current values.  If there is an error, returns the error, otherwise returns
219 the FS::part_svc object (use ref() to test the return).
220
221 =cut
222
223 sub setdefault {
224   my $self = shift;
225   $self->setx('D');
226 }
227
228 sub setx {
229   my $self = shift;
230   my $x = shift;
231
232   my $error;
233
234   $error =
235     $self->ut_numbern('svcnum')
236   ;
237   return $error if $error;
238
239   #get part_svc
240   my $svcpart;
241   if ( $self->svcnum ) {
242     my $cust_svc = $self->cust_svc;
243     return "Unknown svcnum" unless $cust_svc; 
244     $svcpart = $cust_svc->svcpart;
245   } else {
246     $svcpart = $self->getfield('svcpart');
247   }
248   my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
249   return "Unkonwn svcpart" unless $part_svc;
250
251   #set default/fixed/whatever fields from part_svc
252   my $table = $self->table;
253   foreach my $field ( grep { $_ ne 'svcnum' } fields($table) ) {
254     my $part_svc_column = $part_svc->part_svc_column($field);
255     if ( $part_svc_column->columnflag eq $x ) {
256       $self->setfield( $field, $part_svc_column->columnvalue );
257     }
258   }
259
260  $part_svc;
261
262 }
263
264 =item cust_svc
265
266 Returns the cust_svc record associated with this svc_ record, as a FS::cust_svc
267 object (see L<FS::cust_svc>).
268
269 =cut
270
271 sub cust_svc {
272   my $self = shift;
273   qsearchs('cust_svc', { 'svcnum' => $self->svcnum } );
274 }
275
276 =item suspend
277
278 =item unsuspend
279
280 =item cancel
281
282 Stubs - return false (no error) so derived classes don't need to define these
283 methods.  Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
284
285 =cut
286
287 sub suspend { ''; }
288 sub unsuspend { ''; }
289 sub cancel { ''; }
290
291 =back
292
293 =head1 VERSION
294
295 $Id: svc_Common.pm,v 1.9 2002-05-31 00:18:56 khoff Exp $
296
297 =head1 BUGS
298
299 The setfixed method return value.
300
301 =head1 SEE ALSO
302
303 L<FS::Record>, L<FS::cust_svc>, L<FS::part_svc>, L<FS::cust_pkg>, schema.html
304 from the base documentation.
305
306 =cut
307
308 1;
309