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_alphan('location_type')
139 || $self->ut_textn('location_number')
140 || $self->ut_enum('location_kind', [ '', 'R', 'B' ] )
141 || $self->ut_alphan('geocode')
143 return $error if $error;
145 return "No prospect or customer!" unless $self->prospectnum || $self->custnum;
146 return "Prospect and customer!" if $self->prospectnum && $self->custnum;
148 my $conf = new FS::Conf;
149 return 'Location kind is required'
150 if $self->prospectnum
151 && $conf->exists('prospect_main-alt_address_format')
152 && ! $self->location_kind;
154 unless ( qsearch('cust_main_county', {
155 'country' => $self->country,
158 return "Unknown state/county/country: ".
159 $self->state. "/". $self->county. "/". $self->country
160 unless qsearch('cust_main_county',{
161 'state' => $self->state,
162 'county' => $self->county,
163 'country' => $self->country,
172 Returns this locations's full country name
178 code2country($self->country);
183 Synonym for location_label
189 $self->location_label;
192 =item has_ship_address
194 Returns false since cust_location objects do not have a separate shipping
199 sub has_ship_address {
205 Returns a list of key/value pairs, with the following keys: address1, address2,
206 city, county, state, zip, country, geocode, location_type, location_number,
211 =item move_to HASHREF
213 Takes a hashref with one or more cust_location fields. Creates a duplicate
214 of the existing location with all fields set to the values in the hashref.
215 Moves all packages that use the existing location to the new one, then sets
216 the "disabled" flag on the old location. Returns nothing on success, an
217 error message on error.
225 local $SIG{HUP} = 'IGNORE';
226 local $SIG{INT} = 'IGNORE';
227 local $SIG{QUIT} = 'IGNORE';
228 local $SIG{TERM} = 'IGNORE';
229 local $SIG{TSTP} = 'IGNORE';
230 local $SIG{PIPE} = 'IGNORE';
232 my $oldAutoCommit = $FS::UID::AutoCommit;
233 local $FS::UID::AutoCommit = 0;
237 my $new = FS::cust_location->new({
239 'custnum' => $old->custnum,
240 'prospectnum' => $old->prospectnum,
243 $error = $new->insert;
245 $dbh->rollback if $oldAutoCommit;
246 return "Error creating location: $error";
249 my @pkgs = qsearch('cust_pkg', {
250 'locationnum' => $old->locationnum,
253 foreach my $cust_pkg (@pkgs) {
254 $error = $cust_pkg->change(
255 'locationnum' => $new->locationnum,
258 if ( $error and not ref($error) ) {
259 $dbh->rollback if $oldAutoCommit;
260 return "Error moving pkgnum ".$cust_pkg->pkgnum.": $error";
265 $error = $old->replace;
267 $dbh->rollback if $oldAutoCommit;
268 return "Error disabling old location: $error";
271 $dbh->commit if $oldAutoCommit;
277 Attempts to parse data for location_type and location_number from address1
285 return '' if $self->get('location_type')
286 || $self->get('location_number');
289 if ( 1 ) { #ikano, switch on via config
290 { no warnings 'void';
291 eval { 'use FS::part_export::ikano;' };
294 %parse = FS::part_export::ikano->location_types_parse;
299 foreach my $from ('address1', 'address2') {
300 foreach my $parse ( keys %parse ) {
301 my $value = $self->get($from);
302 if ( $value =~ s/(^|\W+)$parse\W+(\w+)\W*$//i ) {
303 $self->set('location_type', $parse{$parse});
304 $self->set('location_number', $2);
305 $self->set($from, $value);
311 #nothing matched, no changes
312 $self->get('address2')
313 ? "Can't parse unit type and number from address2"
319 Moves data from location_type and location_number to the end of address1.
326 #false laziness w/geocode_Mixin.pm::line
327 my $lt = $self->get('location_type');
331 if ( 1 ) { #ikano, switch on via config
332 { no warnings 'void';
333 eval { 'use FS::part_export::ikano;' };
336 %location_type = FS::part_export::ikano->location_types;
338 %location_type = (); #?
341 $self->address1( $self->address1. ' '. $location_type{$lt} || $lt );
342 $self->location_type('');
345 if ( length($self->location_number) ) {
346 $self->address1( $self->address1. ' '. $self->location_number );
347 $self->location_number('');
357 Not yet used for cust_main billing and shipping addresses.
361 L<FS::cust_main_county>, L<FS::cust_pkg>, L<FS::Record>,
362 schema.html from the base documentation.