1 package FS::cust_location;
4 use base qw( FS::geocode_Mixin FS::Record );
7 use FS::Record qw( qsearch ); #qsearchs );
11 use FS::cust_main_county;
15 FS::cust_location - Object methods for cust_location records
19 use FS::cust_location;
21 $record = new FS::cust_location \%hash;
22 $record = new FS::cust_location { 'column' => 'value' };
24 $error = $record->insert;
26 $error = $new_record->replace($old_record);
28 $error = $record->delete;
30 $error = $record->check;
34 An FS::cust_location object represents a customer location. FS::cust_location
35 inherits from FS::Record. The following fields are currently supported:
49 Address line one (required)
53 Address line two (optional)
61 County (optional, see L<FS::cust_main_county>)
65 State (see L<FS::cust_main_county>)
73 Country (see L<FS::cust_main_county>)
81 Disabled flag; set to 'Y' to disable the location.
91 Creates a new location. To add the location to the database, see L<"insert">.
93 Note that this stores the hash reference, not a distinct copy of the hash it
94 points to. You can ask the object for a copy with the I<hash> method.
98 sub table { 'cust_location'; }
102 Adds this record to the database. If there is an error, returns the error,
103 otherwise returns false.
107 Delete this record from the database.
109 =item replace OLD_RECORD
111 Replaces the OLD_RECORD with this one in the database. If there is an error,
112 returns the error, otherwise returns false.
116 Checks all fields to make sure this is a valid location. If there is
117 an error, returns the error, otherwise returns false. Called by the insert
122 #some false laziness w/cust_main, but since it should eventually lose these
128 $self->ut_numbern('locationnum')
129 || $self->ut_foreign_keyn('prospectnum', 'prospect_main', 'prospectnum')
130 || $self->ut_foreign_keyn('custnum', 'cust_main', 'custnum')
131 || $self->ut_text('address1')
132 || $self->ut_textn('address2')
133 || $self->ut_text('city')
134 || $self->ut_textn('county')
135 || $self->ut_textn('state')
136 || $self->ut_country('country')
137 || $self->ut_zip('zip', $self->country)
138 || $self->ut_coordn('latitude')
139 || $self->ut_coordn('longitude')
140 || $self->ut_enum('coord_auto', [ '', 'Y' ])
141 || $self->ut_alphan('location_type')
142 || $self->ut_textn('location_number')
143 || $self->ut_enum('location_kind', [ '', 'R', 'B' ] )
144 || $self->ut_alphan('geocode')
146 return $error if $error;
149 unless $self->latitude && $self->longitude;
151 return "No prospect or customer!" unless $self->prospectnum || $self->custnum;
152 return "Prospect and customer!" if $self->prospectnum && $self->custnum;
154 my $conf = new FS::Conf;
155 return 'Location kind is required'
156 if $self->prospectnum
157 && $conf->exists('prospect_main-alt_address_format')
158 && ! $self->location_kind;
160 unless ( qsearch('cust_main_county', {
161 'country' => $self->country,
164 return "Unknown state/county/country: ".
165 $self->state. "/". $self->county. "/". $self->country
166 unless qsearch('cust_main_county',{
167 'state' => $self->state,
168 'county' => $self->county,
169 'country' => $self->country,
178 Returns this locations's full country name
184 code2country($self->country);
189 Synonym for location_label
195 $self->location_label;
198 =item has_ship_address
200 Returns false since cust_location objects do not have a separate shipping
205 sub has_ship_address {
211 Returns a list of key/value pairs, with the following keys: address1, address2,
212 city, county, state, zip, country, geocode, location_type, location_number,
217 =item move_to HASHREF
219 Takes a hashref with one or more cust_location fields. Creates a duplicate
220 of the existing location with all fields set to the values in the hashref.
221 Moves all packages that use the existing location to the new one, then sets
222 the "disabled" flag on the old location. Returns nothing on success, an
223 error message on error.
231 local $SIG{HUP} = 'IGNORE';
232 local $SIG{INT} = 'IGNORE';
233 local $SIG{QUIT} = 'IGNORE';
234 local $SIG{TERM} = 'IGNORE';
235 local $SIG{TSTP} = 'IGNORE';
236 local $SIG{PIPE} = 'IGNORE';
238 my $oldAutoCommit = $FS::UID::AutoCommit;
239 local $FS::UID::AutoCommit = 0;
243 my $new = FS::cust_location->new({
245 'custnum' => $old->custnum,
246 'prospectnum' => $old->prospectnum,
249 $error = $new->insert;
251 $dbh->rollback if $oldAutoCommit;
252 return "Error creating location: $error";
255 my @pkgs = qsearch('cust_pkg', {
256 'locationnum' => $old->locationnum,
259 foreach my $cust_pkg (@pkgs) {
260 $error = $cust_pkg->change(
261 'locationnum' => $new->locationnum,
264 if ( $error and not ref($error) ) {
265 $dbh->rollback if $oldAutoCommit;
266 return "Error moving pkgnum ".$cust_pkg->pkgnum.": $error";
271 $error = $old->replace;
273 $dbh->rollback if $oldAutoCommit;
274 return "Error disabling old location: $error";
277 $dbh->commit if $oldAutoCommit;
283 Attempts to parse data for location_type and location_number from address1
291 return '' if $self->get('location_type')
292 || $self->get('location_number');
295 if ( 1 ) { #ikano, switch on via config
296 { no warnings 'void';
297 eval { 'use FS::part_export::ikano;' };
300 %parse = FS::part_export::ikano->location_types_parse;
305 foreach my $from ('address1', 'address2') {
306 foreach my $parse ( keys %parse ) {
307 my $value = $self->get($from);
308 if ( $value =~ s/(^|\W+)$parse\W+(\w+)\W*$//i ) {
309 $self->set('location_type', $parse{$parse});
310 $self->set('location_number', $2);
311 $self->set($from, $value);
317 #nothing matched, no changes
318 $self->get('address2')
319 ? "Can't parse unit type and number from address2"
325 Moves data from location_type and location_number to the end of address1.
332 #false laziness w/geocode_Mixin.pm::line
333 my $lt = $self->get('location_type');
337 if ( 1 ) { #ikano, switch on via config
338 { no warnings 'void';
339 eval { 'use FS::part_export::ikano;' };
342 %location_type = FS::part_export::ikano->location_types;
344 %location_type = (); #?
347 $self->address1( $self->address1. ' '. $location_type{$lt} || $lt );
348 $self->location_type('');
351 if ( length($self->location_number) ) {
352 $self->address1( $self->address1. ' '. $self->location_number );
353 $self->location_number('');
363 Not yet used for cust_main billing and shipping addresses.
367 L<FS::cust_main_county>, L<FS::cust_pkg>, L<FS::Record>,
368 schema.html from the base documentation.