2 use base qw( FS::Template_Mixin FS::cust_main_Mixin FS::otaker_Mixin FS::Record );
5 use FS::Record qw( qsearch qsearchs );
13 FS::quotation - Object methods for quotation records
19 $record = new FS::quotation \%hash;
20 $record = new FS::quotation { 'column' => 'value' };
22 $error = $record->insert;
24 $error = $new_record->replace($old_record);
26 $error = $record->delete;
28 $error = $record->check;
32 An FS::quotation object represents a quotation. FS::quotation inherits from
33 FS::Record. The following fields are currently supported:
70 Creates a new quotation. To add the quotation to the database, see L<"insert">.
72 Note that this stores the hash reference, not a distinct copy of the hash it
73 points to. You can ask the object for a copy with the I<hash> method.
77 sub table { 'quotation'; }
78 sub notice_name { 'Quotation'; }
79 sub template_conf { 'quotation_'; }
83 Adds this record to the database. If there is an error, returns the error,
84 otherwise returns false.
88 Delete this record from the database.
90 =item replace OLD_RECORD
92 Replaces the OLD_RECORD with this one in the database. If there is an error,
93 returns the error, otherwise returns false.
97 Checks all fields to make sure this is a valid quotation. If there is
98 an error, returns the error, otherwise returns false. Called by the insert
107 $self->ut_numbern('quotationnum')
108 || $self->ut_foreign_keyn('prospectnum', 'prospect_main', 'prospectnum' )
109 || $self->ut_foreign_keyn('custnum', 'cust_main', 'custnum' )
110 || $self->ut_numbern('_date')
111 || $self->ut_enum('disabled', [ '', 'Y' ])
112 || $self->ut_numbern('usernum')
114 return $error if $error;
116 $self->_date(time) unless $self->_date;
118 $self->usernum($FS::CurrentUser::CurrentUser->usernum) unless $self->usernum;
129 qsearchs('prospect_main', { 'prospectnum' => $self->prospectnum } );
138 qsearchs('cust_main', { 'custnum' => $self->custnum } );
145 sub cust_bill_pkg { #actually quotation_pkg objects
147 qsearch('quotation_pkg', { quotationnum=>$self->quotationnum });
156 $self->_total('setup');
159 =item total_recur [ FREQ ]
165 #=item total_recur [ FREQ ]
166 #my $freq = @_ ? shift : '';
167 $self->_total('recur');
171 my( $self, $method ) = @_;
174 $total += $_->$method() for $self->cust_bill_pkg;
175 sprintf('%.2f', $total);
179 #prevent things from falsely showing up as taxes, at least until we support
180 # quoting tax amounts..
185 shift->cust_bill_pkg;
189 my( $self, $total_items ) = @_;
191 if ( $self->total_setup > 0 ) {
192 push @$total_items, {
193 'total_item' => $self->mt( $self->total_recur > 0 ? 'Total Setup' : 'Total' ),
194 'total_amount' => $self->total_setup,
198 #could/should add up the different recurring frequencies on lines of their own
199 # but this will cover the 95% cases for now
200 if ( $self->total_recur > 0 ) {
201 push @$total_items, {
202 'total_item' => $self->mt('Total Recurring'),
203 'total_amount' => $self->total_recur,
209 =item enable_previous
213 sub enable_previous { 0 }
222 =item search_sql_where HASHREF
224 Class method which returns an SQL WHERE fragment to search for parameters
225 specified in HASHREF. Valid parameters are
231 List reference of start date, end date, as UNIX timestamps.
241 List reference of charged limits (exclusive).
245 List reference of charged limits (exclusive).
249 flag, return open invoices only
253 flag, return net invoices only
261 Note: validates all passed-in data; i.e. safe to use with unchecked CGI params.
265 sub search_sql_where {
266 my($class, $param) = @_;
268 # warn "$me search_sql_where called with params: \n".
269 # join("\n", map { " $_: ". $param->{$_} } keys %$param ). "\n";
275 if ( $param->{'agentnum'} =~ /^(\d+)$/ ) {
276 push @search, "( prospect_main.agentnum = $1 OR cust_main.agentnum = $1 )";
280 # if ( $param->{'refnum'} =~ /^(\d+)$/ ) {
281 # push @search, "cust_main.refnum = $1";
285 if ( $param->{'prospectnum'} =~ /^(\d+)$/ ) {
286 push @search, "quotation.prospectnum = $1";
290 if ( $param->{'custnum'} =~ /^(\d+)$/ ) {
291 push @search, "cust_bill.custnum = $1";
295 if ( $param->{_date} ) {
296 my($beginning, $ending) = @{$param->{_date}};
298 push @search, "quotation._date >= $beginning",
299 "quotation._date < $ending";
303 if ( $param->{'quotationnum_min'} =~ /^(\d+)$/ ) {
304 push @search, "quotation.quotationnum >= $1";
306 if ( $param->{'quotationnum_max'} =~ /^(\d+)$/ ) {
307 push @search, "quotation.quotationnum <= $1";
311 # if ( $param->{charged} ) {
312 # my @charged = ref($param->{charged})
313 # ? @{ $param->{charged} }
314 # : ($param->{charged});
316 # push @search, map { s/^charged/cust_bill.charged/; $_; }
320 my $owed_sql = FS::cust_bill->owed_sql;
323 push @search, "quotation._date < ". (time-86400*$param->{'days'})
326 #agent virtualization
327 my $curuser = $FS::CurrentUser::CurrentUser;
328 #false laziness w/search/quotation.html
329 push @search,' ( '. $curuser->agentnums_sql( table=>'prospect_main' ).
330 ' OR '. $curuser->agentnums_sql( table=>'cust_main' ).
333 join(' AND ', @search );
343 L<FS::Record>, schema.html from the base documentation.