RT# 83341 - added ability to sort by name in advanced customer reports
[freeside.git] / FS / FS / svc_circuit.pm
1 package FS::svc_circuit;
2
3 use strict;
4 use base qw(
5   FS::svc_IP_Mixin
6   FS::MAC_Mixin
7   FS::svc_Common
8 );
9 use FS::Record qw( dbh qsearch qsearchs );
10 use FS::circuit_provider;
11 use FS::circuit_type;
12 use FS::circuit_termination;
13
14 =head1 NAME
15
16 FS::svc_circuit - Object methods for svc_circuit records
17
18 =head1 SYNOPSIS
19
20   use FS::svc_circuit;
21
22   $record = new FS::svc_circuit \%hash;
23   $record = new FS::svc_circuit { 'column' => 'value' };
24
25   $error = $record->insert;
26
27   $error = $new_record->replace($old_record);
28
29   $error = $record->delete;
30
31   $error = $record->check;
32
33 =head1 DESCRIPTION
34
35 An FS::svc_circuit object represents a telecom circuit service (other than 
36 an analog phone line, which is svc_phone, or a DSL Internet connection, 
37 which is svc_dsl).  FS::svc_circuit inherits from FS::svc_IP_Mixin,
38 FS::MAC_Mixin, and FS::svc_Common.  The following fields are currently
39 supported:
40
41 =over 4
42
43 =item svcnum
44
45 primary key; see also L<FS::cust_svc>
46
47 =item typenum
48
49 circuit type (such as DS1, DS1-PRI, DS3, OC3, etc.); foreign
50 key to L<FS::circuit_type>.
51
52 =item providernum
53
54 circuit provider (telco); foreign key to 
55 L<FS::circuit_provider>.
56
57 =item termnum
58
59 circuit termination type; foreign key to 
60 L<FS::circuit_termination>
61
62 =item circuit_id
63
64 provider circuit ID string defined by the provider
65
66 =item desired_due_date
67
68 the requested date for completion of the circuit
69 order
70
71 =item due_date
72
73 the provider's committed date for completion of the circuit
74 order
75
76 =item vendor_order_id
77
78 the provider's order number
79
80 =item vendor_qual_id
81
82 the qualification number, if a qualification was 
83 performed
84
85 =item vendor_order_type
86
87 =item vendor_order_status
88
89 the order status: ACCEPTED, PENDING, COMPLETED,
90 etc.
91
92 =item endpoint_ip_addr
93
94 the IP address of the endpoint equipment, if any. 
95 This will be validated as an IP address but not assigned from managed address
96 space or checked for uniqueness.
97
98 =item endpoint_mac_addr
99
100 the MAC address of the endpoint.
101
102 =item internal_circuit_id
103
104 internal circuit ID string
105
106 =back
107
108 =head1 METHODS
109
110 =over 4
111
112 =item new HASHREF
113
114 Creates a new circuit service.  To add the record to the database, see 
115 L<"insert">.
116
117 =cut
118
119 sub table { 'svc_circuit'; }
120
121 sub table_info {
122   my %dis = ( disable_default => 1, disable_fixed => 1,
123               disabled_inventory => 1, disable_select => 1 );
124
125   tie my %fields, 'Tie::IxHash', (
126     'svcnum'              => 'Service',
127     'providernum'         => {
128                               label         => 'Provider',
129                               type          => 'select',
130                               select_table  => 'circuit_provider',
131                               select_key    => 'providernum',
132                               select_label  => 'provider',
133                               disable_inventory => 1,
134                              },
135     'typenum'             => {
136                               label         => 'Circuit type',
137                               type          => 'select',
138                               select_table  => 'circuit_type',
139                               select_key    => 'typenum',
140                               select_label  => 'typename',
141                               disable_inventory => 1,
142                              },
143     'termnum'             => {
144                               label         => 'Termination type',
145                               type          => 'select',
146                               select_table  => 'circuit_termination',
147                               select_key    => 'termnum',
148                               select_label  => 'termination',
149                               disable_inventory => 1,
150                              },
151     'circuit_id'          => { label => 'Provider Circuit ID', %dis },
152     'desired_due_date'    => { label => 'Desired due date',
153                              %dis
154                              },
155     'due_date'            => { label => 'Due date',
156                              %dis
157                              },
158     'vendor_order_id'     => { label => 'Vendor order ID', %dis },
159     'vendor_qual_id'      => { label => 'Vendor qualification ID', %dis },
160     'vendor_order_type'   => {
161                               label => 'Vendor order type',
162                               disable_inventory => 1
163                              }, # should be a select?
164     'vendor_order_status' => {
165                               label => 'Vendor order status',
166                               disable_inventory => 1
167                              }, # should also be a select?
168     'endpoint_ip_addr'    => {
169                               label => 'Endpoint IP address',
170                              },
171     'endpoint_mac_addr'   => {
172                               label => 'Endpoint MAC address',
173                               type => 'input-mac_addr',
174                               disable_inventory => 1,
175                              },
176     'internal_circuit_id' => { label => 'Internal Circuit ID', %dis },
177   );
178   return {
179     'name'              => 'Circuit',
180     'name_plural'       => 'Circuits',
181     'longname_plural'   => 'Voice and data circuit services',
182     'display_weight'    => 72,
183     'cancel_weight'     => 85, # after svc_phone
184     'fields'            => \%fields,
185   };
186 }
187
188 =item insert
189
190 Adds this record to the database.  If there is an error, returns the error,
191 otherwise returns false.
192
193 =item delete
194
195 Delete this record from the database.
196
197 =item replace OLD_RECORD
198
199 Replaces the OLD_RECORD with this one in the database.  If there is an error,
200 returns the error, otherwise returns false.
201
202 =item check
203
204 Checks all fields to make sure this is a valid service.  If there is
205 an error, returns the error, otherwise returns false.  Called by the insert
206 and replace methods.
207
208 =cut
209
210 sub check {
211   my $self = shift;
212
213   my $mac_addr = uc($self->get('endpoint_mac_addr'));
214   $mac_addr =~ s/[\W_]//g;
215   $self->set('endpoint_mac_addr', $mac_addr);
216
217   my $error = 
218     $self->ut_numbern('svcnum')
219     || $self->ut_number('typenum')
220     || $self->ut_number('providernum')
221     || $self->ut_text('circuit_id')
222     || $self->ut_numbern('desired_due_date')
223     || $self->ut_numbern('due_date')
224     || $self->ut_textn('vendor_order_id')
225     || $self->ut_textn('vendor_qual_id')
226     || $self->ut_textn('vendor_order_type')
227     || $self->ut_textn('vendor_order_status')
228     || $self->ut_ipn('endpoint_ip_addr')
229     || $self->ut_textn('endpoint_mac_addr')
230     || $self->ut_textn('internal_circuit_id')
231   ;
232
233   # no canonical values yet for vendor_order_status or _type
234
235   return $error if $error;
236
237   $self->SUPER::check;
238 }
239
240 =item label
241
242 Returns the circuit ID.
243
244 =cut
245
246 sub label {
247   my $self = shift;
248   $self->get('circuit_id');
249 }
250
251 sub search_sql {
252   my ($class, $string) = @_;
253   my @where = ();
254   push @where, 'LOWER(svc_circuit.circuit_id) = LOWER(' . dbh->quote($string) . ')';
255   push @where, 'LOWER(circuit_provider.provider) = LOWER(' . dbh->quote($string) . ')';
256   push @where, 'LOWER(circuit_type.typename) = LOWER(' . dbh->quote($string) . ')';
257   '(' . join(' OR ', @where) . ')';
258 }
259
260 sub search_sql_addl_from {
261   'LEFT JOIN circuit_provider USING ( providernum ) '.
262   'LEFT JOIN circuit_type USING ( typenum )';
263 }
264
265 sub _upgrade_data {
266
267   require FS::Misc::FixIPFormat;
268   FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
269       'svc_circuit', 'svcnum', 'endpoint_ip_addr',
270   );
271
272   '';
273
274 }
275
276 =back
277
278 =head1 SEE ALSO
279
280 L<FS::Record>
281
282 =cut
283
284 1;