RT# 83450 - fixed rateplan export
[freeside.git] / FS / FS / cust_main_invoice.pm
1 package FS::cust_main_invoice;
2 use base qw( FS::Record );
3
4 use strict;
5 use FS::Record qw( qsearchs dbh );
6 use FS::Conf;
7 use FS::svc_acct;
8 use FS::Msgcat qw(gettext);
9
10 =head1 NAME
11
12 FS::cust_main_invoice - Object methods for cust_main_invoice records
13
14 =head1 ANNOUNCEMENT
15
16 This is deprecated in version 4. Instead, contacts with the "invoice_dest"
17 attribute should be used.
18
19 =head1 SYNOPSIS
20
21   use FS::cust_main_invoice;
22
23   $record = new FS::cust_main_invoice \%hash;
24   $record = new FS::cust_main_invoice { 'column' => 'value' };
25
26   $error = $record->insert;
27
28   $error = $new_record->replace($old_record);
29
30   $error = $record->delete;
31
32   $error = $record->check;
33
34   $email_address = $record->address;
35
36 =head1 DESCRIPTION
37
38 An FS::cust_main_invoice object represents an invoice destination.  FS::cust_main_invoice inherits from
39 FS::Record.  The following fields are currently supported:
40
41 =over 4
42
43 =item destnum - primary key
44
45 =item custnum - customer (see L<FS::cust_main>)
46
47 =item dest - Invoice destination: If numeric, a svcnum (see L<FS::svc_acct>), if string, a literal email address, `POST' to enable mailing (the default if no cust_main_invoice records exist), or `FAX' to enable faxing via a HylaFAX server.
48
49 =back
50
51 =head1 METHODS
52
53 =over 4
54
55 =item new HASHREF
56
57 Creates a new invoice destination.  To add the invoice destination to the database, see L<"insert">.
58
59 Note that this stores the hash reference, not a distinct copy of the hash it
60 points to.  You can ask the object for a copy with the I<hash> method.
61
62 =cut
63
64 sub table { 'cust_main_invoice'; }
65
66 =item insert
67
68 Adds this record to the database.  If there is an error, returns the error,
69 otherwise returns false.
70
71 =item delete
72
73 Delete this record from the database.
74
75 =item replace OLD_RECORD
76
77 Replaces the OLD_RECORD with this one in the database.  If there is an error,
78 returns the error, otherwise returns false.
79
80 =cut
81
82 sub replace {
83   my ( $new, $old ) = ( shift, shift );
84
85   return "Can't change custnum!" unless $old->custnum == $new->custnum;
86
87   $new->SUPER::replace($old);
88 }
89
90
91 =item check
92
93 Checks all fields to make sure this is a valid invoice destination.  If there is
94 an error, returns the error, otherwise returns false.  Called by the insert
95 and replace methods.
96
97 =cut
98
99 sub check {
100   my $self = shift;
101
102   my $error = $self->ut_numbern('destnum')
103            || $self->ut_number('custnum')
104            || $self->checkdest;
105   ;
106   return $error if $error;
107
108   $self->SUPER::check;
109 }
110
111 =item checkdest
112
113 Checks the dest field only.
114
115 #If it finds that the account ends in the
116 #same domain configured as the B<domain> configuration file, it will change the
117 #invoice destination from an email address to a service number (see
118 #L<FS::svc_acct>).
119
120 =cut
121
122 sub checkdest { 
123   my $self = shift;
124
125   my $error = $self->ut_text('dest');
126   return $error if $error;
127
128   my $conf = new FS::Conf;
129
130   if ( $self->dest =~ /^(POST|FAX)$/ ) {
131     #contemplate our navel
132   } elsif ( $self->dest =~ /^(\d+)$/ ) {
133     return "Unknown local account (specified by svcnum: ". $self->dest. ")"
134       unless qsearchs( 'svc_acct', { 'svcnum' => $self->dest } );
135   } elsif ( $conf->exists('emailinvoice-apostrophe')
136               ? $self->dest =~ /^\s*([\w\.\-\&\+\']+)\@(([\w\.\-]+\.)+\w+)\s*$/
137               : $self->dest =~ /^\s*([\w\.\-\&\+]+)\@(([\w\.\-]+\.)+\w+)\s*$/ ){
138     my($user, $domain) = ($1, $2);
139     $self->dest("$1\@$2");
140   } else {
141     return gettext("illegal_email_invoice_address"). ': '. $self->dest;
142   }
143
144   ''; #no error
145 }
146
147 =item address
148
149 Returns the literal email address for this record (or `POST' or `FAX').
150
151 =cut
152
153 sub address {
154   my $self = shift;
155   if ( $self->dest =~ /^(\d+)$/ ) {
156     my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $1 } )
157       or return undef;
158     $svc_acct->email;
159   } else {
160     $self->dest;
161   }
162 }
163
164 =item cust_main
165
166 Returns the parent customer object (see L<FS::cust_main>).
167
168 =back
169
170 =cut
171
172 sub _upgrade_schema {
173   my ($class, %opts) = @_;
174
175   # delete records where custnum points to a nonexistent customer
176   my $sql = 'DELETE FROM cust_main_invoice
177     WHERE NOT EXISTS (
178       SELECT 1 FROM cust_main WHERE cust_main.custnum = cust_main_invoice.custnum
179     )';
180   my $sth = dbh->prepare($sql) or die dbh->errstr;
181   $sth->execute or die $sth->errstr;
182
183   '';
184 }
185
186 =head1 BUGS
187
188 =head1 SEE ALSO
189
190 L<FS::Record>, L<FS::cust_main>
191
192 =cut
193
194 1;
195