dde682bc963fdf615dbe2d12373927c84916eb4c
[freeside.git] / FS / FS / svc_cable.pm
1 package FS::svc_cable;
2 use base qw( FS::svc_MAC_Mixin
3              FS::svc_Common
4            ); #FS::device_Common
5
6 use strict;
7 use Tie::IxHash;
8 use FS::Record qw( qsearchs ); # qw( qsearch qsearchs );
9 use FS::cable_provider;
10 use FS::cable_model;
11
12 =head1 NAME
13
14 FS::svc_cable - Object methods for svc_cable records
15
16 =head1 SYNOPSIS
17
18   use FS::svc_cable;
19
20   $record = new FS::svc_cable \%hash;
21   $record = new FS::svc_cable { 'column' => 'value' };
22
23   $error = $record->insert;
24
25   $error = $new_record->replace($old_record);
26
27   $error = $record->delete;
28
29   $error = $record->check;
30
31 =head1 DESCRIPTION
32
33 An FS::svc_cable object represents a cable subscriber.  FS::svc_cable inherits
34 from FS::Record.  The following fields are currently supported:
35
36 =over 4
37
38 =item svcnum
39
40 primary key
41
42 =back
43
44 =head1 METHODS
45
46 =over 4
47
48 =item new HASHREF
49
50 Creates a new record.  To add the record to the database, see L<"insert">.
51
52 Note that this stores the hash reference, not a distinct copy of the hash it
53 points to.  You can ask the object for a copy with the I<hash> method.
54
55 =cut
56
57 sub table { 'svc_cable'; }
58
59 sub table_dupcheck_fields { ( 'serialnum', 'mac_addr' ); }
60
61 sub search_sql {
62   my( $class, $string ) = @_;
63   if ( $string =~ /^([A-F0-9]{12})$/i ) {
64     $class->search_sql_field('mac_addr', uc($string));
65   } elsif ( $string =~ /^(([A-F0-9]{2}:){5}([A-F0-9]{2}))$/i ) {
66     $string =~ s/://g;
67     $class->search_sql_field('mac_addr', uc($string) );
68   } elsif ( $string =~ /^(\w+)$/ ) {
69     $class->search_sql_field('serialnum', $1);
70   } else {
71     '1 = 0'; #false
72   }
73 }
74
75 sub table_info {
76
77   tie my %fields, 'Tie::IxHash',
78     'svcnum'      => 'Service',
79     'providernum' => { label             => 'Provider',
80                        type              => 'select-cable_provider',
81                        disable_inventory => 1,
82                        disable_select    => 1,
83                        value_callback    => sub {
84                                               my $svc = shift;
85                                               my $p = $svc->cable_provider;
86                                               $p ? $p->provider : '';
87                                             },
88                      },
89     'ordernum'    => 'Order number', #XXX "Circuit ID/Order number"
90     'modelnum'    => { label             => 'Model',
91                        type              => 'select-cable_model',
92                        disable_inventory => 1,
93                        disable_select    => 1,
94                        value_callback    => sub {
95                                               my $svc = shift;
96                                               $svc->cable_model->model_name;
97                                             },
98                      },
99     'serialnum'   => 'Serial number',
100     'mac_addr'    => { label          => 'MAC address',
101                        type           => 'input-mac_addr',
102                        value_callback => sub {
103                                            my $svc = shift;
104                                            $svc->mac_addr_formatted('U',':');
105                                          },
106                      },
107   ;
108
109   {
110     'name'            => 'Cable Subscriber',
111     #'name_plural'     => '', #optional,
112     #'longname_plural' => '', #optional
113     'fields'          => \%fields,
114     'sorts'           => [ 'svcnum', 'serialnum', 'mac_addr', ],
115     'display_weight'  => 54,
116     'cancel_weight'   => 70, #?  no deps, so
117   };
118 }
119
120 =item label
121
122 Returns the MAC address and serial number.
123
124 =cut
125
126 sub label {
127   my $self = shift;
128   my $part_svc = $self->cust_svc->part_svc;
129   my @label = ();
130   push @label, 'MAC:'. $self->mac_addr_pretty
131     if $self->mac_addr;
132   if ( $self->serialnum ) {
133     my $serialnum_label = $part_svc->part_svc_column('serialnum');
134     push @label,
135       ($serialnum_label && $serialnum_label->columnlabel || 'Serial#').
136       $self->serialnum;
137   }
138   return join(', ', @label);
139 }
140
141 =item insert
142
143 Adds this record to the database.  If there is an error, returns the error,
144 otherwise returns false.
145
146 =item delete
147
148 Delete this record from the database.
149
150 =item replace OLD_RECORD
151
152 Replaces the OLD_RECORD with this one in the database.  If there is an error,
153 returns the error, otherwise returns false.
154
155 =item check
156
157 Checks all fields to make sure this is a valid record.  If there is
158 an error, returns the error, otherwise returns false.  Called by the insert
159 and replace methods.
160
161 =cut
162
163 sub check {
164   my $self = shift;
165
166   my $error = 
167        $self->ut_numbern('svcnum')
168     || $self->ut_foreign_keyn('providernum', 'cable_provider', 'providernum')
169     || $self->ut_alphan('ordernum')
170     || $self->ut_foreign_key('modelnum', 'cable_model', 'modelnum')
171     || $self->ut_alphan('serialnum')
172     || $self->ut_mac_addrn('mac_addr')
173   ;
174   return $error if $error;
175
176   $self->SUPER::check;
177 }
178
179 sub _check_duplicate {
180   my $self = shift;
181
182   # Not reliable checks because the table isn't locked, but that's why we have
183   # unique indices.  These are just to give friendlier error messages.
184
185   if ( $self->mac_addr ) {
186     my @dup_mac;
187     @dup_mac = $self->find_duplicates('global', 'mac_addr');
188     if ( @dup_mac ) {
189       return "MAC address in use (svcnum ".$dup_mac[0]->svcnum.")";
190     }
191   }
192
193   if ( $self->serialnum ) {
194     my @dup_serial;
195     @dup_serial = $self->find_duplicates('global', 'serialnum');
196     if ( @dup_serial ) {
197       return "Serial number in use (svcnum ".$dup_serial[0]->svcnum.")";
198     }
199   }
200
201   '';
202 }
203
204 =item cable_provider
205
206 Returns the cable_provider object for this record.
207
208 =cut
209
210 sub cable_provider {
211   my $self = shift;
212   qsearchs('cable_provider', { 'providernum'=>$self->providernum } );
213 }
214
215 =item cable_model
216
217 Returns the cable_model object for this record.
218
219 =cut
220
221 sub cable_model {
222   my $self = shift;
223   qsearchs('cable_model', { 'modelnum'=>$self->modelnum } );
224 }
225
226 =back
227
228 =head1 BUGS
229
230 =head1 SEE ALSO
231
232 L<FS::Record>, schema.html from the base documentation.
233
234 =cut
235
236 1;
237