communigate provisioning phase 2: add svc_domain.trailer -> communigate TrailerText...
[freeside.git] / FS / FS / cust_location.pm
1 package FS::cust_location;
2
3 use strict;
4 use base qw( FS::Record );
5 use Locale::Country;
6 use FS::Record qw( qsearch ); #qsearchs );
7 use FS::prospect_main;
8 use FS::cust_main;
9 use FS::cust_main_county;
10
11 =head1 NAME
12
13 FS::cust_location - Object methods for cust_location records
14
15 =head1 SYNOPSIS
16
17   use FS::cust_location;
18
19   $record = new FS::cust_location \%hash;
20   $record = new FS::cust_location { 'column' => 'value' };
21
22   $error = $record->insert;
23
24   $error = $new_record->replace($old_record);
25
26   $error = $record->delete;
27
28   $error = $record->check;
29
30 =head1 DESCRIPTION
31
32 An FS::cust_location object represents a customer location.  FS::cust_location
33 inherits from FS::Record.  The following fields are currently supported:
34
35 =over 4
36
37 =item locationnum
38
39 primary key
40
41 =item custnum
42
43 custnum
44
45 =item address1
46
47 Address line one (required)
48
49 =item address2
50
51 Address line two (optional)
52
53 =item city
54
55 City
56
57 =item county
58
59 County (optional, see L<FS::cust_main_county>)
60
61 =item state
62
63 State (see L<FS::cust_main_county>)
64
65 =item zip
66
67 Zip
68
69 =item country
70
71 Country (see L<FS::cust_main_county>)
72
73 =item geocode
74
75 Geocode
76
77 =back
78
79 =head1 METHODS
80
81 =over 4
82
83 =item new HASHREF
84
85 Creates a new location.  To add the location to the database, see L<"insert">.
86
87 Note that this stores the hash reference, not a distinct copy of the hash it
88 points to.  You can ask the object for a copy with the I<hash> method.
89
90 =cut
91
92 sub table { 'cust_location'; }
93
94 =item insert
95
96 Adds this record to the database.  If there is an error, returns the error,
97 otherwise returns false.
98
99 =item delete
100
101 Delete this record from the database.
102
103 =item replace OLD_RECORD
104
105 Replaces the OLD_RECORD with this one in the database.  If there is an error,
106 returns the error, otherwise returns false.
107
108 =item check
109
110 Checks all fields to make sure this is a valid location.  If there is
111 an error, returns the error, otherwise returns false.  Called by the insert
112 and replace methods.
113
114 =cut
115
116 #some false laziness w/cust_main, but since it should eventually lose these
117 #fields anyway...
118 sub check {
119   my $self = shift;
120
121   my $error = 
122     $self->ut_numbern('locationnum')
123     || $self->ut_foreign_keyn('prospectnum', 'prospect_main', 'prospectnum')
124     || $self->ut_foreign_keyn('custnum', 'cust_main', 'custnum')
125     || $self->ut_text('address1')
126     || $self->ut_textn('address2')
127     || $self->ut_text('city')
128     || $self->ut_textn('county')
129     || $self->ut_textn('state')
130     || $self->ut_country('country')
131     || $self->ut_zip('zip', $self->country)
132     || $self->ut_alphan('geocode')
133   ;
134   return $error if $error;
135
136   return "No prospect or customer!" unless $self->prospectnum || $self->custnum;
137   return "Prospect and customer!"       if $self->prospectnum && $self->custnum;
138
139   unless ( qsearch('cust_main_county', {
140     'country' => $self->country,
141     'state'   => '',
142    } ) ) {
143     return "Unknown state/county/country: ".
144       $self->state. "/". $self->county. "/". $self->country
145       unless qsearch('cust_main_county',{
146         'state'   => $self->state,
147         'county'  => $self->county,
148         'country' => $self->country,
149       } );
150   }
151
152   $self->SUPER::check;
153 }
154
155 =item country_full
156
157 Returns this locations's full country name
158
159 =cut
160
161 sub country_full {
162   my $self = shift;
163   code2country($self->country);
164 }
165
166 =item location_label [ OPTION => VALUE ... ]
167
168 Returns the label of the service location for this customer.
169
170 Options are
171
172 =over 4
173
174 =item join_string
175
176 used to separate the address elements (defaults to ', ')
177
178 =item escape_function
179
180
181 a callback used for escaping the text of the address elements
182
183 =back
184
185 =cut
186
187 # false laziness with FS::cust_main::location_label
188
189 sub location_label {
190   my $self = shift;
191   my %opt = @_;
192
193   my $separator = $opt{join_string} || ', ';
194   my $escape = $opt{escape_function} || sub{ shift };
195   my $ds = $opt{double_space} || '  ';
196   my $line = '';
197   my $cydefault =
198     $opt{'countrydefault'} || FS::Conf->new->config('countrydefault') || 'US';
199   my $prefix = '';
200
201   my $notfirst = 0;
202   foreach (qw ( address1 address2 ) ) {
203     my $method = "$prefix$_";
204     $line .= ($notfirst ? $separator : ''). &$escape($self->$method)
205       if $self->$method;
206     $notfirst++;
207   }
208   $notfirst = 0;
209   foreach (qw ( city county state zip ) ) {
210     my $method = "$prefix$_";
211     if ( $self->$method ) {
212       $line .= ($notfirst ? ($method eq 'zip' ? $ds : ' ') : $separator);
213       $line .= '(' if $method eq 'county';
214       $line .= &$escape($self->$method);
215       $line .= ')' if $method eq 'county';
216       $notfirst++;
217     }
218     $line .= ',' if $method eq 'county';
219   }
220   $line .= $separator. &$escape(code2country($self->country))
221     if $self->country ne $cydefault;
222
223   $line;
224 }
225
226 =item line
227
228 Synonym for location_label
229
230 =cut
231
232 sub line {
233   my $self = shift;
234   $self->location_label;
235 }
236
237 =item location_hash
238
239 Returns a list of key/value pairs, with the following keys: address1, adddress2,
240 city, county, state, zip, country.
241
242 =cut
243
244 #geocode?  not yet set
245
246 sub location_hash {
247   my $self = shift;
248   map { $_ => $self->$_ } qw( address1 address2 city county state zip country );
249 }
250
251 =back
252
253 =head1 BUGS
254
255 Not yet used for cust_main billing and shipping addresses.
256
257 =head1 SEE ALSO
258
259 L<FS::cust_main_county>, L<FS::cust_pkg>, L<FS::Record>,
260 schema.html from the base documentation.
261
262 =cut
263
264 1;
265