X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main.pm;h=a8a9ae43b7d293e09c86e3a0f62bbb07fa71034c;hb=3dc6bff7a0a4ceaacd18a7ce6b50cd2b8a2ce498;hp=47a5d9defbfe9c5ffaa63a0a70163b8d7aa9a2c2;hpb=697f745a6e5ac606e625c0edfa7f786526f21f47;p=freeside.git diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 47a5d9def..a8a9ae43b 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -51,6 +51,7 @@ use FS::payment_gateway; use FS::agent_payment_gateway; use FS::banned_pay; use FS::payinfo_Mixin; +use FS::TicketSystem; @ISA = qw( FS::Record FS::payinfo_Mixin ); @@ -349,7 +350,8 @@ sub insert { $error = $self->check_invoicing_list( $invoicing_list ); if ( $error ) { $dbh->rollback if $oldAutoCommit; - return "checking invoicing_list (transaction rolled back): $error"; + #return "checking invoicing_list (transaction rolled back): $error"; + return $error; } $self->invoicing_list( $invoicing_list ); } @@ -1273,6 +1275,21 @@ sub check { ; return $error if $error; + if ( $conf->exists('cust_main-require_phone') + && ! length($self->daytime) && ! length($self->night) + ) { + + my $daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/ + ? 'Day Phone' + : FS::Msgcat::_gettext('daytime'); + my $night_label = FS::Msgcat::_gettext('night') =~ /^(night)?$/ + ? 'Night Phone' + : FS::Msgcat::_gettext('night'); + + return "$daytime_label or $night_label is required" + + } + my @addfields = qw( last first company address1 address2 city county state zip country daytime night fax @@ -1422,10 +1439,11 @@ sub check { $payinfo =~ s/[^\d\@]//g; if ( $conf->exists('echeck-nonus') ) { $payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account@aba'; + $payinfo = "$1\@$2"; } else { $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba'; + $payinfo = "$1\@$2"; } - $payinfo = "$1\@$2"; $self->payinfo($payinfo); $self->paycvv(''); @@ -2415,6 +2433,8 @@ Currently available options are: =item payby - allows for one time override of normal customer billing method +=back + =cut sub collect { @@ -2713,6 +2733,13 @@ sub retry_realtime { my $join = FS::part_event_condition->join_conditions_sql; my $order = FS::part_event_condition->order_conditions_sql; + my $mine = + '( ' + . join ( ' OR ' , map { + "( part_event.eventtable = " . dbh->quote($_) + . " AND tablenum IN( SELECT " . dbdef->table($_)->primary_key . " from $_ where custnum = " . dbh->quote( $self->custnum ) . "))" ; + } FS::part_event->eventtables) + . ') '; #here is the agent virtualization my $agent_virt = " ( part_event.agentnum IS NULL @@ -2736,7 +2763,7 @@ sub retry_realtime { 'addl_from' => "LEFT JOIN part_event USING ( eventpart ) $join", 'hashref' => { 'status' => 'done' }, 'extra_sql' => " AND statustext IS NOT NULL AND statustext != '' ". - " AND $is_realtime_event AND $agent_virt $order" # LIMIT 1" + " AND $mine AND $is_realtime_event AND $agent_virt $order" # LIMIT 1" }); my %seen_invnum = (); @@ -4130,7 +4157,8 @@ is an error, returns the error, otherwise returns false. sub check_invoicing_list { my( $self, $arrayref ) = @_; - foreach my $address ( @{$arrayref} ) { + + foreach my $address ( @$arrayref ) { if ($address eq 'FAX' and $self->getfield('fax') eq '') { return 'Can\'t add FAX invoice destination with a blank FAX number.'; @@ -4145,7 +4173,13 @@ sub check_invoicing_list { : $cust_main_invoice->checkdest ; return $error if $error; + } + + return "Email address required" + if $conf->exists('cust_main-require_invoicing_list_email') + && ! grep { $_ !~ /^([A-Z]+)$/ } @$arrayref; + ''; } @@ -4620,6 +4654,52 @@ sub cust_statuscolor { $statuscolor{$self->cust_status}; } +=item tickets + +Returns an array of hashes representing the customer's RT tickets. + +=cut + +sub tickets { + my $self = shift; + + my $num = $conf->config('cust_main-max_tickets') || 10; + my @tickets = (); + + unless ( $conf->config('ticket_system-custom_priority_field') ) { + + @tickets = @{ FS::TicketSystem->customer_tickets($self->custnum, $num) }; + + } else { + + foreach my $priority ( + $conf->config('ticket_system-custom_priority_field-values'), '' + ) { + last if scalar(@tickets) >= $num; + push @tickets, + @{ FS::TicketSystem->customer_tickets( $self->custnum, + $num - scalar(@tickets), + $priority, + ) + }; + } + } + (@tickets); +} + +# Return services representing svc_accts in customer support packages +sub support_services { + my $self = shift; + my %packages = map { $_ => 1 } $conf->config('support_packages'); + + grep { $_->pkg_svc && $_->pkg_svc->primary_svc eq 'Y' } + grep { $_->part_svc->svcdb eq 'svc_acct' } + map { $_->cust_svc } + grep { exists $packages{ $_->pkgpart } } + $self->ncancelled_pkgs; + +} + =back =head1 CLASS METHODS @@ -5607,7 +5687,9 @@ sub generate_letter { my %letter_data = map { $_ => $self->$_ } $self->fields; $letter_data{payinfo} = $self->mask_payinfo; - my $paydate = $self->paydate; + #my $paydate = $self->paydate || '2037-12'; + my $paydate = $self->paydate =~ /^\S+$/ ? $self->paydate : '2037-12'; + my $payby = $self->payby; my ($payyear,$paymonth,$payday) = split (/-/,$paydate); my $expire_time = timelocal(0,0,0,$payday,--$paymonth,$payyear); @@ -5707,13 +5789,14 @@ sub _agent_plandata { my $part_event_option = qsearchs({ + 'select' => 'part_event_option.*', 'table' => 'part_event_option', 'addl_from' => q{ LEFT JOIN part_event USING ( eventpart ) LEFT JOIN part_event_option AS peo_agentnum ON ( part_event.eventpart = peo_agentnum.eventpart AND peo_agentnum.optionname = 'agentnum' - AND peo_agentnum.optionvalue ~ '(^|,)agentnum(,|$)' + AND peo_agentnum.optionvalue ~ '(^|,)}. $agentnum. q{(,|$)' ) LEFT JOIN part_event_option AS peo_cust_bill_age ON ( part_event.eventpart = peo_cust_bill_age.eventpart @@ -5721,27 +5804,30 @@ sub _agent_plandata { ) }, #'hashref' => { 'optionname' => $option }, - 'hashref' => { 'part_event_option.optionname' => $option }, - 'extra_sql' => " AND event = 'cust_bill_send_agent' ". - " AND peo_agentnum.optionname = 'agentnum' ". - " AND agentnum IS NULL OR agentnum = $agentnum ". - " ORDER BY - CASE WHEN peo_cust_bill_age.optionname != 'cust_bill_age' - THEN -1 - ELSE EXTRACT( EPOCH FROM - REPLACE( peo_cust_bill_age.optionvalue, - 'm', - 'mon' - )::interval - ) - END - , part_event.weight". - " LIMIT 1" + #'hashref' => { 'part_event_option.optionname' => $option }, + 'extra_sql' => + " WHERE part_event_option.optionname = ". dbh->quote($option). + " AND action = 'cust_bill_send_agent' ". + " AND ( disabled IS NULL OR disabled != 'Y' ) ". + " AND peo_agentnum.optionname = 'agentnum' ". + " AND agentnum IS NULL OR agentnum = $agentnum ". + " ORDER BY + CASE WHEN peo_cust_bill_age.optionname != 'cust_bill_age' + THEN -1 + ELSE EXTRACT( EPOCH FROM + REPLACE( peo_cust_bill_age.optionvalue, + 'm', + 'mon' + )::interval + ) + END + , part_event.weight". + " LIMIT 1" }); unless ( $part_event_option ) { return $self->agent->invoice_template || '' - if $option eq '$agent_templatename'; + if $option eq 'agent_templatename'; return ''; } @@ -5749,6 +5835,16 @@ sub _agent_plandata { } +sub queued_bill { + ## actual sub, not a method, designed to be called from the queue. + ## sets up the customer, and calls the bill_and_collect + my (%args) = @_; #, ($time, $invoice_time, $check_freq, $resetup) = @_; + my $cust_main = qsearchs( 'cust_main', { custnum => $args{'custnum'} } ); + $cust_main->bill_and_collect( + %args, + ); +} + =back =head1 BUGS