use vars qw( $import $DEBUG $conf $label_prefix );
use Data::Dumper;
use Date::Format qw( time2str );
-use Locale::Country;
use FS::UID qw( dbh driver_name );
use FS::Record qw( qsearch qsearchs );
use FS::Conf;
=item city
-City
+City (if cust_main-no_city_in_address config is set when inserting, this will be forced blank)
=item county
Tax district code (optional)
+=item incorporated
+
+Incorporated city flag: set to 'Y' if the address is in the legal borders
+of an incorporated city.
+
=item disabled
Disabled flag; set to 'Y' to disable the location.
my @essential = (qw(custnum address1 address2 city county state zip country
location_number location_type location_kind disabled));
+ if ($conf->exists('cust_main-no_city_in_address')) {
+ warn "Warning: passed city to find_or_insert when cust_main-no_city_in_address is configured, ignoring it"
+ if $self->get('city');
+ $self->set('city','');
+ }
+
# I don't think this is necessary
#if ( !$self->coord_auto and $self->latitude and $self->longitude ) {
# push @essential, qw(latitude longitude);
sub insert {
my $self = shift;
+ if ($conf->exists('cust_main-no_city_in_address')) {
+ warn "Warning: passed city to insert when cust_main-no_city_in_address is configured, ignoring it"
+ if $self->get('city');
+ $self->set('city','');
+ }
+
if ( $self->censustract ) {
$self->set('censusyear' => $conf->config('census_year') || 2012);
}
# cust_location exports
#my $export_args = $options{'export_args'} || [];
- my @part_export =
- map qsearch( 'part_export', {exportnum=>$_} ),
- $conf->config('cust_location-exports'); #, $agentnum
-
- foreach my $part_export ( @part_export ) {
- my $error = $part_export->export_insert($self); #, @$export_args);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "exporting to ". $part_export->exporttype.
- " (transaction rolled back): $error";
+ # don't export custnum_pending cases, let follow-up replace handle that
+ if ($self->custnum || $self->prospectnum) {
+ my @part_export =
+ map qsearch( 'part_export', {exportnum=>$_} ),
+ $conf->config('cust_location-exports'); #, $agentnum
+
+ foreach my $part_export ( @part_export ) {
+ my $error = $part_export->export_insert($self); #, @$export_args);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "exporting to ". $part_export->exporttype.
+ " (transaction rolled back): $error";
+ }
}
}
-
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
}
my $self = shift;
my $old = shift;
$old ||= $self->replace_old;
- # the following fields are immutable
- foreach (qw(address1 address2 city state zip country)) {
- if ( $self->$_ ne $old->$_ ) {
- return "can't change cust_location field $_";
+
+ warn "Warning: passed city to replace when cust_main-no_city_in_address is configured"
+ if $conf->exists('cust_main-no_city_in_address') && $self->get('city');
+
+ # the following fields are immutable if this is a customer location. if
+ # it's a prospect location, then there are no active packages, no billing
+ # history, no taxes, and in general no reason to keep the old location
+ # around.
+ if ( $self->custnum ) {
+ foreach (qw(address1 address2 city state zip country)) {
+ if ( $self->$_ ne $old->$_ ) {
+ return "can't change cust_location field $_";
+ }
}
}
# cust_location exports
#my $export_args = $options{'export_args'} || [];
- my @part_export =
- map qsearch( 'part_export', {exportnum=>$_} ),
- $conf->config('cust_location-exports'); #, $agentnum
-
- foreach my $part_export ( @part_export ) {
- my $error = $part_export->export_replace($self, $old); #, @$export_args);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "exporting to ". $part_export->exporttype.
- " (transaction rolled back): $error";
+ # don't export custnum_pending cases, let follow-up replace handle that
+ if ($self->custnum || $self->prospectnum) {
+ my @part_export =
+ map qsearch( 'part_export', {exportnum=>$_} ),
+ $conf->config('cust_location-exports'); #, $agentnum
+
+ foreach my $part_export ( @part_export ) {
+ my $error = $part_export->export_replace($self, $old); #, @$export_args);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "exporting to ". $part_export->exporttype.
+ " (transaction rolled back): $error";
+ }
}
}
-
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
}
$self->ut_numbern('locationnum')
|| $self->ut_foreign_keyn('prospectnum', 'prospect_main', 'prospectnum')
|| $self->ut_foreign_keyn('custnum', 'cust_main', 'custnum')
+ || $self->ut_textn('locationname')
|| $self->ut_text('address1')
|| $self->ut_textn('address2')
- || $self->ut_text('city')
+ || ($conf->exists('cust_main-no_city_in_address')
+ ? $self->ut_textn('city')
+ : $self->ut_text('city'))
|| $self->ut_textn('county')
|| $self->ut_textn('state')
|| $self->ut_country('country')
|| $self->ut_alphan('geocode')
|| $self->ut_alphan('district')
|| $self->ut_numbern('censusyear')
+ || $self->ut_flag('incorporated')
;
return $error if $error;
if ( $self->censustract ne '' ) {
$self->censustract("$1.$2");
}
- if ( $conf->exists('cust_main-require_address2') and
- !$self->ship_address2 =~ /\S/ ) {
- return "Unit # is required";
- }
+ #yikes... this is ancient, pre-dates cust_location and will be harder to
+ # implement now... how do we know this location is a service location from
+ # here and not a billing? we can't just check locationnums, we might be new :/
+ return "Unit # is required"
+ if $conf->exists('cust_main-require_address2')
+ && ! $self->address2 =~ /\S/;
# tricky...we have to allow for the customer to not be inserted yet
return "No prospect or customer!" unless $self->prospectnum
=item country_full
-Returns this locations's full country name
+Returns this location's full country name
=cut
-sub country_full {
- my $self = shift;
- code2country($self->country);
-}
+#moved to geocode_Mixin.pm
=item line
my $self = shift;
my $locationnum = $self->locationnum;
- return '' if FS::cust_main->count('bill_locationnum = '.$locationnum)
- or FS::cust_main->count('ship_locationnum = '.$locationnum)
+ return '' if FS::cust_main->count('bill_locationnum = '.$locationnum.' OR
+ ship_locationnum = '.$locationnum)
or FS::contact->count( 'locationnum = '.$locationnum)
or FS::cust_pkg->count('cancel IS NULL AND
locationnum = '.$locationnum)
=item location_label
-Returns the label of the location object, with an optional site ID
-string (based on the cust_location-label_prefix config option).
+Returns the label of the location object.
+
+Options:
+
+=over 4
+
+=item cust_main
+
+Customer object (see L<FS::cust_main>)
+
+=item prospect_main
+
+Prospect object (see L<FS::prospect_main>)
+
+=item join_string
+
+String used to join location elements
+
+=item no_prefix
+
+Don't label the default service location as "Default service location".
+May become the default at some point.
+
+=back
=cut
sub location_label {
my( $self, %opt ) = @_;
+ my $prefix = $self->label_prefix(%opt);
+ $prefix .= ($opt{join_string} || ': ') if $prefix;
+ $prefix = '' if $opt{'no_prefix'};
+
+ $prefix . $self->SUPER::location_label(%opt);
+}
+
+=item label_prefix
+
+Returns the optional site ID string (based on the cust_location-label_prefix
+config option), "Default service location", or the empty string.
+
+Options:
+
+=over 4
+
+=item cust_main
+
+Customer object (see L<FS::cust_main>)
+
+=item prospect_main
+
+Prospect object (see L<FS::prospect_main>)
+
+=back
+
+=cut
+
+sub label_prefix {
+ my( $self, %opt ) = @_;
+
my $cust_or_prospect = $opt{cust_main} || $opt{prospect_main};
unless ( $cust_or_prospect ) {
if ( $self->custnum ) {
($agent =~ /^(..)/),
sprintf('%05d', $self->locationnum)
) );
- }
- elsif ( ( $opt{'cust_main'} || $self->custnum )
+
+ } elsif ( $label_prefix eq '_location' && $self->locationname ) {
+ $prefix = $self->locationname;
+
+ } elsif ( ( $opt{'cust_main'} || $self->custnum )
&& $self->locationnum == $cust_or_prospect->ship_locationnum ) {
$prefix = 'Default service location';
}
- $prefix .= ($opt{join_string} || ': ') if $prefix;
- $prefix . $self->SUPER::location_label(%opt);
+ $prefix;
}
-=item county_state_county
+=item county_state_country
Returns a string consisting of just the county, state and country.
=back
-=head1 CLASS METHODS
-
-=item in_county_sql OPTIONS
-
-Returns an SQL expression to test membership in a cust_main_county
-geographic area. By default, this requires district, city, county,
-state, and country to match exactly. Pass "ornull => 1" to allow
-partial matches where some fields are NULL in the cust_main_county
-record but not in the location.
-
-Pass "param => 1" to receive a parameterized expression (rather than
-one that requires a join to cust_main_county) and a list of parameter
-names in order.
-
-=cut
-
-sub in_county_sql {
- # replaces FS::cust_pkg::location_sql
- my ($class, %opt) = @_;
- my $ornull = $opt{ornull} ? ' OR ? IS NULL' : '';
- my $x = $ornull ? 3 : 2;
- my @fields = (('district') x 3,
- ('city') x 3,
- ('county') x $x,
- ('state') x $x,
- 'country');
-
- my $text = (driver_name =~ /^mysql/i) ? 'char' : 'text';
-
- my @where = (
- "cust_location.district = ? OR ? = '' OR CAST(? AS $text) IS NULL",
- "cust_location.city = ? OR ? = '' OR CAST(? AS $text) IS NULL",
- "cust_location.county = ? OR (? = '' AND cust_location.county IS NULL) $ornull",
- "cust_location.state = ? OR (? = '' AND cust_location.state IS NULL ) $ornull",
- "cust_location.country = ?"
- );
- my $sql = join(' AND ', map "($_)\n", @where);
- if ( $opt{param} ) {
- return $sql, @fields;
- }
- else {
- # do the substitution here
- foreach (@fields) {
- $sql =~ s/\?/cust_main_county.$_/;
- $sql =~ s/cust_main_county.$_ = ''/cust_main_county.$_ IS NULL/;
- }
- return $sql;
- }
-}
-
-=back
-
=head2 SUBROUTINES
=over 4