From 14d7fe93445d40a8ae24cfd81e30d595ea2004d6 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 9 May 2003 01:18:02 +0000 Subject: Net::SSH and Net::SCP are in ports --- install/freebsd/ports | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/freebsd/ports b/install/freebsd/ports index 329f084d6..385d6b598 100644 --- a/install/freebsd/ports +++ b/install/freebsd/ports @@ -30,9 +30,9 @@ databases/p5-DBD-Pg #databases/p5-DBD-mysql databases/p5-DBIx-DataSource #database/p5-DBIx-DBSchema - #net/p5-Net-SSH +net/p5-Net-SSH textproc/p5-String-ShellQuote - #net/p5-Net-SCP +net/p5-Net-SCP www/p5-Apache-ASP www/p5-HTML-Mason devel/p5-Tie-IxHash -- cgit v1.2.1 From 1a6e8ccb610247daf9f475358471cfeed44f4e65 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 9 May 2003 06:03:53 +0000 Subject: updated freebsd install --- fs_selfservice/DEPLOY | 6 +++--- install/freebsd/INSTALL | 18 +++++++++++++++--- install/freebsd/ports | 8 ++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/fs_selfservice/DEPLOY b/fs_selfservice/DEPLOY index 7c68e78ec..7ab3b2a7a 100755 --- a/fs_selfservice/DEPLOY +++ b/fs_selfservice/DEPLOY @@ -9,7 +9,7 @@ cd .. kill `cat /var/run/freeside-selfservice-server.ivan.pid`; sleep 3 ./freeside-selfservice-server ivan localhost -cp /home/ivan/freeside_current/fs_selfservice/FS-SelfService/cgi/* /var/www/MyAccount +cp /home/ivan/freeside/fs_selfservice/FS-SelfService/cgi/* /var/www/MyAccount chown freeside /var/www/MyAccount/selfservice.cgi -chmod 4755 /var/www/MyAccount/selfservice.cgi -ln -s /var/www/MyAccount/selfservice.cgi /var/www/MyAccount/index.cgi +chmod 755 /var/www/MyAccount/selfservice.cgi +ln -s /var/www/MyAccount/selfservice.cgi /var/www/MyAccount/index.cgi || true diff --git a/install/freebsd/INSTALL b/install/freebsd/INSTALL index 4840ac2be..f42699c14 100755 --- a/install/freebsd/INSTALL +++ b/install/freebsd/INSTALL @@ -1,9 +1,21 @@ #!/bin/sh +cd /usr/ports/sysutils/portupgrade +make install + +pkgdb -u + +portinstall -PR cvsup-without-gui + +cp /usr/share/examples/cvsup/ports-supfile /root +perl -pi -e 's/CHANGE_THIS/cvsup1/;' /root/ports-supfile +cvsup /root/ports-supfile + for port in `grep -v '^ *#' ports`; do - cd /usr/ports/$port - make install || exit + #cd /usr/ports/$port + #make install || exit + portinstall -P -R $port || exit done -perl -MCPAN -e"install DBIx::DBSchema HTML::Widgets::SelectLayers Time::Duration" +perl -MCPAN -e"install Net::SSH DBIx::DBSchema HTML::Widgets::SelectLayers Time::Duration Business::CreditCard" diff --git a/install/freebsd/ports b/install/freebsd/ports index 385d6b598..3f0d40773 100644 --- a/install/freebsd/ports +++ b/install/freebsd/ports @@ -12,11 +12,11 @@ security/p5-MD5 net/p5-URI www/p5-HTML-Tagset www/p5-HTML-Parser -www/p5-Net +net/p5-Net misc/p5-Locale-Codes net/p5-Net-Whois www/p5-libwww -misc/p5-Business-CreditCard + #misc/p5-Business-CreditCard devel/p5-Data-ShowTable mail/p5-Mail-Tools devel/p5-TimeDate @@ -30,11 +30,11 @@ databases/p5-DBD-Pg #databases/p5-DBD-mysql databases/p5-DBIx-DataSource #database/p5-DBIx-DBSchema -net/p5-Net-SSH + #net/p5-Net-SSH textproc/p5-String-ShellQuote net/p5-Net-SCP www/p5-Apache-ASP -www/p5-HTML-Mason + #www/p5-HTML-Mason devel/p5-Tie-IxHash #devel/p5-Time-Duration #www/p5-HTML-Widgets-SelectLayers -- cgit v1.2.1 From 51df5a9bad917d04e58c2686831a1481f45b667e Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 9 May 2003 06:14:55 +0000 Subject: freebsd install --- install/freebsd/INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/freebsd/INSTALL b/install/freebsd/INSTALL index f42699c14..28a453ab3 100755 --- a/install/freebsd/INSTALL +++ b/install/freebsd/INSTALL @@ -17,5 +17,5 @@ for port in `grep -v '^ *#' ports`; do portinstall -P -R $port || exit done -perl -MCPAN -e"install Net::SSH DBIx::DBSchema HTML::Widgets::SelectLayers Time::Duration Business::CreditCard" +for a in Net::SSH DBIx::DBSchema HTML::Widgets::SelectLayers Time::Duration Business::CreditCard; do perl -MCPAN -e"install $a"; done -- cgit v1.2.1 From 116b7654a443c2d471834264bed034b123008407 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 9 May 2003 07:05:07 +0000 Subject: little bit more fbsd install automation --- install/freebsd/INSTALL | 23 +++++++++++++++++++++-- install/freebsd/ports | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/install/freebsd/INSTALL b/install/freebsd/INSTALL index 28a453ab3..53fc613d1 100755 --- a/install/freebsd/INSTALL +++ b/install/freebsd/INSTALL @@ -1,7 +1,8 @@ #!/bin/sh -cd /usr/ports/sysutils/portupgrade -make install +( cd /usr/ports/sysutils/portupgrade + make install +) pkgdb -u @@ -19,3 +20,21 @@ done for a in Net::SSH DBIx::DBSchema HTML::Widgets::SelectLayers Time::Duration Business::CreditCard; do perl -MCPAN -e"install $a"; done +su -l pgsql -c initdb + +/usr/local/etc/rc.d/010.pgsql.sh start + +pw user add freeside -m + +su -l pgsql -c 'createuser -P freeside' + +su -l freeside -c 'createdb freeside' + +#? +cd ../.. +make install-perl-modules +make create-config +make deploy + +#edit apache config, etc. + diff --git a/install/freebsd/ports b/install/freebsd/ports index 3f0d40773..8381e5a04 100644 --- a/install/freebsd/ports +++ b/install/freebsd/ports @@ -2,6 +2,7 @@ shells/zsh misc/screen ftp/lftp www/mod_perl +www/apache13-modssl net/rsync databases/postgresql7 misc/p5-Array-PrintCols -- cgit v1.2.1 From 71af70d04218beec79b4351b2ca721a07a33460f Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 9 May 2003 07:17:54 +0000 Subject: mod_ssl before mod_perl so mod_perl picks up EAPI --- install/freebsd/ports | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/freebsd/ports b/install/freebsd/ports index 8381e5a04..1e04a424d 100644 --- a/install/freebsd/ports +++ b/install/freebsd/ports @@ -1,8 +1,8 @@ shells/zsh misc/screen ftp/lftp -www/mod_perl www/apache13-modssl +www/mod_perl net/rsync databases/postgresql7 misc/p5-Array-PrintCols -- cgit v1.2.1 From d60478318bc9c3d94703d1845c0b40504c51a8cb Mon Sep 17 00:00:00 2001 From: khoff Date: Fri, 9 May 2003 19:30:57 +0000 Subject: Cleaned-up package view code and added CSS tags. --- httemplate/view/cust_main.cgi | 354 ++++++++++++++++++++++++++---------------- 1 file changed, 224 insertions(+), 130 deletions(-) diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index cea8d6321..d392f8a39 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -15,6 +15,16 @@ print header("Customer View", menubar( 'Main Menu' => popurl(2) )); +print < +.package TH { font-size: medium } +.package TR { font-size: smaller } +.package .datehdr TH { font-size: smaller } +.package .pkgnum { font-size: medium } +.package .provision { font-size: larger; color: red; font-weight: bold } + +END + die "No customer specified (bad URL)!" unless $cgi->keywords; my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array $query =~ /^(\d+)$/; @@ -357,149 +367,81 @@ print qq!
Packages !, qq!( Order and cancel packages (preserves services) )!, ; -#display packages +#begin display packages #get package info -my @packages; -if ( $conf->exists('hidecancelledpackages') ) { - @packages = sort { $a->pkgnum <=> $b->pkgnum } ($cust_main->ncancelled_pkgs); -} else { - @packages = sort { $a->pkgnum <=> $b->pkgnum } ($cust_main->all_pkgs); -} - -if ( @packages ) { - #formatting - my $colspan = $packages[0]->dbdef_table->column('last_bill') ? 6 : 5; - - print &table(), "\n", - qq!Package!, - qq!DatesServices\n!, - qq!Setup!; - - print qq!Last bill! - if $packages[0]->dbdef_table->column('last_bill'); - - print qq!Next bill!, - qq!Susp.!, - qq!Expire!, - qq!Cancel!, - qq!\n!; -} - -my $n1 = ''; -foreach my $package (@packages) { - my $pkgnum = $package->pkgnum; - my $pkg = $package->part_pkg->pkg; - my $comment = $package->part_pkg->comment; - my $pkgview = popurl(2). "view/cust_pkg.cgi?$pkgnum"; +my $packages = get_packages($cust_main); - #my @cust_svc = qsearch( 'cust_svc', { 'pkgnum' => $pkgnum } ); - #my $rowspan = scalar(@cust_svc) || 1; - my @cust_svc = (); +if ( @$packages ) { +%> + + + + + + + + + + + + + + +<% +foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { my $rowspan = 0; - my %pkg_svc = (); - unless ( $package->getfield('cancel') ) { - foreach my $pkg_svc ( - grep { $_->quantity } - qsearch('pkg_svc',{'pkgpart'=> $package->pkgpart }) - ) { - $rowspan += ( $pkg_svc{$pkg_svc->svcpart} = $pkg_svc->quantity ); - } + + if ($pkg->{cancel}) { + $rowspan = 0; } else { - #@cust_svc = qsearch( 'cust_svc', { 'pkgnum' => $pkgnum } ); - @cust_svc = (); - $rowspan = scalar(@cust_svc) || 1; - } - $rowspan ||= 1; - - my $button_cgi = new CGI; - $button_cgi->param('clone', $package->part_pkg->pkgpart); - $button_cgi->param('pkgnum', $package->pkgnum); - my $button_url = popurl(2). "edit/part_pkg.cgi?". $button_cgi->query_string; - - #print $n1, qq!!, - print $n1, qq!!, - qq!'; - - my @fields = qw( setup ); - push @fields, qw( last_bill ) if $package->dbdef_table->column('last_bill'); - push @fields, qw( bill susp expire cancel); - - for ( @fields ) { - print "', - ; +%> + + + + +<% + foreach (qw(setup last_bill next_bill susp expire cancel)) { + print qq! \n!; } - my $n2 = ''; - #false laziness with view/cust_pkg.cgi, but i'm trying to make that go away so - #foreach my $cust_svc ( @cust_svc ) { - foreach my $svcpart ( sort { $a<=>$b } keys %pkg_svc ) { - my $svc = qsearchs('part_svc',{'svcpart'=>$svcpart})->getfield('svc'); - $svc =~ s/ / /g; - my(@cust_svc)=qsearch('cust_svc',{'pkgnum'=>$pkgnum, - 'svcpart'=>$svcpart, - }); - for my $enum ( 1 .. $pkg_svc{$svcpart} ) { - my $cust_svc; - if ( $cust_svc = shift @cust_svc ) { - my($label, $value, $svcdb) = $cust_svc->label; - my($svcnum) = $cust_svc->svcnum; - my($sview) = popurl(2). "view"; - print $n2,qq!!, - qq!!; - } else { - print $n2, qq!'; - } - $n2=""; + if ($rowspan == 0) { print qq!\n!; next; } + + my $cnt = 0; + foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) { + foreach my $service (@{$svcpart->{services}}) { + print '' if ($cnt > 0); +%> + + + +<% + $cnt++; + } + if ($svcpart->{count} < $svcpart->{quantity}) { + print qq!\n! if ($cnt > 0); + print qq! \n\n!; } } +} +print '
PackageDatesServices
SetupLast billNext billSusp.ExpireCancel
$pkgnum$pkgnum!, - #qq!$pkg - $comment!, - qq!$pkg - $comment ( Details )!; - # | !; - - #false laziness with view/cust_pkg.cgi, but i'm trying to make that go away so - unless ( $package->getfield('cancel') ) { - - print qq! ( !. - 'Change package )'; - - print ' ( '; - if ( $package->getfield('susp') ) { - print qq!Unsuspend!; - } else { - print qq!Suspend!; + foreach my $svcpart (@{$pkg->{svcparts}}) { + $rowspan += $svcpart->{count}; + $rowspan++ if ($svcpart->{count} < $svcpart->{quantity}); } - print ' | Cancel'; - - print ' ) '; + } - print ' ( Edit dates | '; - - print qq!Customize )!; - - } - print '", ( $package->getfield($_) - ? time2str("%D
%l:%M:%S%P %z", - $package->getfield($_) ) - : ' ' - ), '
CLASS="pkgnum"><%=$pkg->{pkgnum}%>> + <%=$pkg->{pkg}%> - <%=$pkg->{comment}%> ( <%=pkg_details_link($pkg)%> )
+<% unless ($pkg->{cancel}) { %> + ( <%=pkg_change_link($pkg)%> ) + ( <%=($pkg->{susp}) ? pkg_unsuspend_link($pkg) : pkg_suspend_link($pkg)%> | <%=pkg_cancel_link($pkg)%> ) + ( <%=pkg_dates_link($pkg)%> | <%=pkg_customize_link($pkg)%> ) +<% } %> +
! . pkg_datestr($pkg,$_) . qq!$label$value
Unprovision )
!. - qq!Provision $svc!; - - print qq!
!. - qq!Link to legacy $svc! - if $conf->exists('legacy_link'); - - print '
<%=svc_link($svcpart,$service)%><%=svc_label_link($svcpart,$service)%>
( <%=svc_unprovision_link($service)%> )
!.svc_provision_link($pkg,$svcpart).qq!
' +} - $n1=""; -} -print ""; - -#formatting -print ""; +#end display packages print <'; sub keyfield_numerically { (split(/\t/,$a))[0] <=> (split(/\t/,$b))[0]; } %> + +<% + + +sub get_packages { + +my $cust_main = shift or return undef; + +my @packages = (); + +foreach my $cust_pkg (($conf->exists('hidecancelledpackages') ? ($cust_main->ncancelled_pkgs) + : ($cust_main->all_pkgs))) { + + my $part_pkg = $cust_pkg->part_pkg; + + my %pkg = (); + $pkg{pkgnum} = $cust_pkg->pkgnum; + $pkg{pkg} = $part_pkg->pkg; + $pkg{pkgpart} = $part_pkg->pkgpart; + $pkg{comment} = $part_pkg->getfield('comment'); + $pkg{setup} = $cust_pkg->getfield('setup'); + $pkg{last_bill} = $cust_pkg->getfield('last_bill'); + $pkg{next_bill} = $cust_pkg->getfield('bill'); + $pkg{susp} = $cust_pkg->getfield('susp'); + $pkg{expire} = $cust_pkg->getfield('expire'); + $pkg{cancel} = $cust_pkg->getfield('cancel'); + + $pkg{svcparts} = []; + + foreach my $pkg_svc (qsearch('pkg_svc', { 'pkgpart' => $part_pkg->pkgpart })) { + + next if ($pkg_svc->quantity == 0); + + my $part_svc = qsearchs('part_svc', { 'svcpart' => $pkg_svc->svcpart }); + + my $svcpart = {}; + $svcpart->{svcpart} = $part_svc->svcpart; + $svcpart->{svc} = $part_svc->svc; + $svcpart->{svcdb} = $part_svc->svcdb; + $svcpart->{quantity} = $pkg_svc->quantity; + $svcpart->{count} = 0; + + $svcpart->{services} = []; + + foreach my $cust_svc (qsearch('cust_svc', { 'pkgnum' => $cust_pkg->pkgnum, + 'svcpart' => $part_svc->svcpart } )) { + + my $svc = {}; + $svc->{svcnum} = $cust_svc->svcnum; + $svc->{label} = ($cust_svc->label)[1]; + + push @{$svcpart->{services}}, $svc; + + $svcpart->{count}++; + + } + + push @{$pkg{svcparts}}, $svcpart; + + } + + push @packages, \%pkg; + +} + +return \@packages; + +} + +sub svc_link { + + my ($svcpart, $svc) = (shift,shift) or return ''; + return qq!$svcpart->{svc}!; + +} + +sub svc_label_link { + + my ($svcpart, $svc) = (shift,shift) or return ''; + return qq!$svc->{label}!; + +} + +sub svc_provision_link { + my ($pkg, $svcpart) = (shift,shift) or return ''; + return qq!! . + qq!Provision $svcpart->{svc} (! . ($svcpart->{quantity} - $svcpart->{count}) . qq!)!; +} + +sub svc_unprovision_link { + my $svc = shift or return ''; + return qq!Unprovision!; +} + +# This should be generalized to use config options to determine order. +sub pkgsort_pkgnum_cancel { + if ($a->{cancel} and $b->{cancel}) { + return ($a->{pkgnum} <=> $b->{pkgnum}); + } elsif ($a->{cancel} or $b->{cancel}) { + return (-1) if ($b->{cancel}); + return (1) if ($a->{cancel}); + return (0); + } else { + return($a->{pkgnum} <=> $b->{pkgnum}); + } +} + +sub pkg_datestr { + my ($pkg,$field) = (shift,shift) or return ''; + return $pkg->{$field} ? time2str('%D
%l:%M:%S%P %z', + $pkg->{$field}) + : ' '; +} + +sub pkg_details_link { + my $pkg = shift or return ''; + return qq!Details!; +} + +sub pkg_change_link { + my $pkg = shift or return ''; + return qq!Change package!; +} + +sub pkg_suspend_link { + my $pkg = shift or return ''; + return qq!Suspend!; +} + +sub pkg_unsuspend_link { + my $pkg = shift or return ''; + return qq!Unsuspend!; +} + +sub pkg_cancel_link { + my $pkg = shift or return ''; + return qq!Cancel!; +} + +sub pkg_dates_link { + my $pkg = shift or return ''; + return qq!Edit dates!; +} + +sub pkg_customize_link { + my $pkg = shift or return ''; + return qq!Customize!; +} + +%> + -- cgit v1.2.1 From 59b2ab6633c0fe401cfe3b74f5cd4e8883a6fc22 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 10 May 2003 05:40:53 +0000 Subject: - substitute '0' for existing blank setup/recur fees - use timelocal_nocheck instead of timelocal for proper wraparound --- FS/FS/cust_main.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index cefc7648f..608c5e3cb 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -4,7 +4,7 @@ use strict; use vars qw( @ISA $conf $Debug $import ); use Safe; use Carp; -use Time::Local; +use Time::Local qw(timelocal_nocheck); use Date::Format; #use Date::Manip; use Business::CreditCard; @@ -994,6 +994,7 @@ sub bill { ": $setup_prog"; }; $setup_prog = $1; + $setup_prog = '0' if $setup_prog =~ /^\s*$/; #my $cpt = new Safe; ##$cpt->permit(); #what is necessary? @@ -1023,6 +1024,7 @@ sub bill { ": $recur_prog"; }; $recur_prog = $1; + $recur_prog = '0' if $recur_prog =~ /^\s*$/; # shared with $recur_prog $sdate = $cust_pkg->bill || $cust_pkg->setup || $time; @@ -1052,7 +1054,7 @@ sub bill { $mon += $part_pkg->freq; until ( $mon < 12 ) { $mon -= 12; $year++; } $cust_pkg->setfield('bill', - timelocal($sec,$min,$hour,$mday,$mon,$year)); + timelocal_nocheck($sec,$min,$hour,$mday,$mon,$year)); $cust_pkg_mod_flag = 1; } -- cgit v1.2.1 From aa8f46a06edce17b919486a62d9e208c1954355a Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 10 May 2003 05:41:20 +0000 Subject: fix bug in last_bill method which prevented last_bill dates from being set --- FS/FS/cust_pkg.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 4eea2c087..bd3d1f503 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -477,8 +477,8 @@ Useful for billing metered services. sub last_bill { my $self = shift; - if ( $self->dbdef_table->column('manual_flag') ) { - return $self->setfield('last_bill', $_[1]) if @_; + if ( $self->dbdef_table->column('last_bill') ) { + return $self->setfield('last_bill', $_[0]) if @_; return $self->getfield('last_bill') if $self->getfield('last_bill'); } my $cust_bill_pkg = qsearchs('cust_bill_pkg', { 'pkgnum' => $self->pkgnum, -- cgit v1.2.1 From 75500e2f75a32b3735999eaf5edde3e871911226 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 10 May 2003 06:45:45 +0000 Subject: first pass at new package list UI --- httemplate/view/cust_main.cgi | 137 ++++++++++++++++++++++++++++++++++++------ httemplate/view/cust_pkg.cgi | 2 +- 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index d392f8a39..e820143aa 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -19,7 +19,6 @@ print < .package TH { font-size: medium } .package TR { font-size: smaller } -.package .datehdr TH { font-size: smaller } .package .pkgnum { font-size: medium } .package .provision { font-size: larger; color: red; font-weight: bold } @@ -377,17 +376,9 @@ if ( @$packages ) { %> - - - - - - - - - - - + + + <% foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { @@ -410,15 +401,119 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { <%=$pkg->{pkg}%> - <%=$pkg->{comment}%> ( <%=pkg_details_link($pkg)%> )
<% unless ($pkg->{cancel}) { %> ( <%=pkg_change_link($pkg)%> ) - ( <%=($pkg->{susp}) ? pkg_unsuspend_link($pkg) : pkg_suspend_link($pkg)%> | <%=pkg_cancel_link($pkg)%> ) ( <%=pkg_dates_link($pkg)%> | <%=pkg_customize_link($pkg)%> ) <% } %> <% - foreach (qw(setup last_bill next_bill susp expire cancel)) { - print qq! \n!; + #foreach (qw(setup last_bill next_bill susp expire cancel)) { + # print qq! \n!; + #} + print "'; + unless ( $pkg->{setup} ) { + print ''; + } else { + print "'; + print "' + if $pkg->{'last_bill'}; + print "' + if $pkg->{'susp'}; + } + + } else { + + if ( $pkg->{susp} ) { #status: suspended + print ''; + unless ( $pkg->{setup} ) { + print ''; + } else { + print "'; + } + print "' + if $pkg->{'last_bill'}; + # next bill ?? + print "' + if $pkg->{'expire'}; + print ''; + + } else { #status: active + + unless ( $pkg->{setup} ) { #not setup + + print ''; + print ''; + } + + } else { #setup + + unless ( $pkg->{freq} ) { + print "". + ''; + } else { + print ''. + ''; + } + + } + + print "' + if $pkg->{'last_bill'}; + print "' + if $pkg->{'next_bill'}; + print "' + if $pkg->{'expire'}; + if ( $pkg->{freq} ) { + print ''; + } + + } + + } + + print "
PackageDatesServices
SetupLast billNext billSusp.ExpireCancelPackageStatusServices
! . pkg_datestr($pkg,$_) . qq!! . pkg_datestr($pkg,$_) . qq!". &itable(''); + + #move + my %freq = ( + 1 => 'monthly', + 2 => 'bi-monthly', + 3 => 'quarterly', + 6 => 'semi-annually', + 12 => 'annually', + 24 => 'bi-annually', + 36 => 'tri-annually', + ); + + sub freq { + my $freq = shift; + exists $freq{$freq} ? $freq{$freq} : "every $freq months"; } + #eomove + + if ( $pkg->{cancel} ) { #status: cancelled + + print '
Cancelled '. + pkg_datestr($pkg,'cancel'). '
Never billed
Setup ". + pkg_datestr($pkg, 'setup'). '
Last bill ". + pkg_datestr($pkg, 'last_bill'). '
Suspended ". + pkg_datestr($pkg, 'susp'). '
Suspended '. + pkg_datestr($pkg,'susp'). '
Never billed
Setup ". + pkg_datestr($pkg, 'setup'). '
Last bill ". + pkg_datestr($pkg, 'last_bill'). '
Expires ". + pkg_datestr($pkg, 'expire'). '
( '. pkg_unsuspend_link($pkg). + ' | '. pkg_cancel_link($pkg). ' )
Not yet billed ('; + unless ( $pkg->{freq} ) { + print 'one-time charge)
( '. pkg_cancel_link($pkg). + ' )'; + } else { + print 'billed '. freq($pkg->{freq}). ')
One-time charge
Billed '. + pkg_datestr($pkg,'setup'). '
Active, '. + 'billed '. freq($pkg->{freq}). '
Setup '. + pkg_datestr($pkg, 'setup'). '
Last bill ". + pkg_datestr($pkg, 'last_bill'). '
Next bill ". + pkg_datestr($pkg, 'next_bill'). '
Expires ". + pkg_datestr($pkg, 'expire'). '
( '. pkg_suspend_link($pkg). + ' | '. pkg_cancel_link($pkg). ' )
\n"; + if ($rowspan == 0) { print qq!\n!; next; } my $cnt = 0; @@ -687,6 +782,7 @@ foreach my $cust_pkg (($conf->exists('hidecancelledpackages') ? ($cust_main->nca $pkg{pkg} = $part_pkg->pkg; $pkg{pkgpart} = $part_pkg->pkgpart; $pkg{comment} = $part_pkg->getfield('comment'); + $pkg{freq} = $part_pkg->freq; $pkg{setup} = $cust_pkg->getfield('setup'); $pkg{last_bill} = $cust_pkg->getfield('last_bill'); $pkg{next_bill} = $cust_pkg->getfield('bill'); @@ -776,10 +872,13 @@ sub pkgsort_pkgnum_cancel { } sub pkg_datestr { - my ($pkg,$field) = (shift,shift) or return ''; - return $pkg->{$field} ? time2str('%D
%l:%M:%S%P %z', - $pkg->{$field}) - : ' '; + my($pkg, $field) = @_ or return ''; + return ' ' unless $pkg->{$field}; + my $format = $conf->exists('pkg_showtimes') + ? '%D %l:%M:%S%P %z' + : '%b %o, %Y'; + ( my $strip = time2str($format, $pkg->{$field}) ) =~ s/ (\d)/$1/g; + $strip; } sub pkg_details_link { diff --git a/httemplate/view/cust_pkg.cgi b/httemplate/view/cust_pkg.cgi index c3880114c..5f0e6bffc 100755 --- a/httemplate/view/cust_pkg.cgi +++ b/httemplate/view/cust_pkg.cgi @@ -71,7 +71,7 @@ print &ntable("#cccccc"), '', &ntable("#cccccc",2), ( $setup ? time2str("%D",$setup) : "(Not setup)" ), ''; print 'Last bill date', - ( $cust_pkg->last_bill ? time2str("%D",$cust_pkg->last_bill) : " " ), + ( $cust_pkg->get('last_bill') ? time2str("%D",$cust_pkg->get('last_bill')) : " " ), '' if $cust_pkg->dbdef_table->column('last_bill'); -- cgit v1.2.1 From 24426a8b0d8e42dd5d00115cd84bd5d786fc58c3 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 11 May 2003 22:25:08 +0000 Subject: handler.pl updates from Richard Siddall --- htetc/handler.pl | 2 +- htetc/handler.pl-1.0x | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htetc/handler.pl b/htetc/handler.pl index 9f2a483c2..481d5a2d9 100644 --- a/htetc/handler.pl +++ b/htetc/handler.pl @@ -38,7 +38,7 @@ use strict; my $ah = new HTML::Mason::ApacheHandler ( #interp => $interp, #auto_send_headers => 0, - comp_root=>'/var/www/masonside', + comp_root=>'/var/www/freeside', data_dir=>'/usr/local/etc/freeside/masondata', #out_mode=>'stream', ); diff --git a/htetc/handler.pl-1.0x b/htetc/handler.pl-1.0x index 768ebffec..8840b0816 100644 --- a/htetc/handler.pl-1.0x +++ b/htetc/handler.pl-1.0x @@ -30,8 +30,8 @@ use strict; # my $parser = new HTML::Mason::Parser; my $interp = new HTML::Mason::Interp (parser=>$parser, - comp_root=>'/var/www/masondocs', - data_dir=>'/home/ivan/freeside_current/masondata', + comp_root=>'/var/www/freeside', + data_dir=>'/usr/local/etc/freeside/masondata', out_mode=>'stream', ); my $ah = new HTML::Mason::ApacheHandler ( interp => $interp, -- cgit v1.2.1 From 42a4396bcfe9d7b9748ff5fac7f1fffa32a25d47 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 11 May 2003 22:34:05 +0000 Subject: red here is too confusing --- CREDITS | 3 +++ httemplate/view/cust_main.cgi | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CREDITS b/CREDITS index ec8134969..0b4e2d9c9 100644 --- a/CREDITS +++ b/CREDITS @@ -110,5 +110,8 @@ other fixes. Charles A Beasley contributed quota editing for the Infostreet export. +Richard Siddall sent in Mason fixes and other +things I'm probably forgetting. + Everything else is my (Ivan Kohler ) fault. diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index e820143aa..af2babcba 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -20,7 +20,7 @@ print < END -- cgit v1.2.1 From bace32bf9341c78d1a068b302dbba031c79c128d Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 11 May 2003 22:53:49 +0000 Subject: patch from Richard Siddall for strict vars --- httemplate/search/cust_pkg.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi index 3cc520fa8..538edf3f1 100755 --- a/httemplate/search/cust_pkg.cgi +++ b/httemplate/search/cust_pkg.cgi @@ -93,7 +93,7 @@ if ( $cgi->param('magic') && $cgi->param('magic') eq 'bill' ) { AND cust_svc.svcpart = pkg_svc.svcpart AND cust_pkg.pkgpart = pkg_svc.pkgpart GROUP BY cust_svc.pkgnum,cust_svc.svcpart"; - $sth = dbh->prepare($query) or die dbh->errstr. " preparing $query"; + my $sth = dbh->prepare($query) or die dbh->errstr. " preparing $query"; $sth->execute or die "Error executing \"$query\": ". $sth->errstr; -- cgit v1.2.1 From 38480ba7cb708bbe1bf78482d570425c121f2386 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 11 May 2003 22:55:07 +0000 Subject: mail forward search not yet implemented --- httemplate/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httemplate/index.html b/httemplate/index.html index d13649b07..e5bd11806 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -114,7 +114,7 @@ Auditing pre-Freeside services with no customer record Packages -- cgit v1.2.1 From 4454c0bae42714d3dc215572a15a0ad0960b20fe Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 May 2003 07:33:47 +0000 Subject: fix service links --- httemplate/view/cust_main.cgi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index af2babcba..3934a3dcb 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -430,8 +430,8 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { if ( $pkg->{cancel} ) { #status: cancelled - print 'Cancelled '. - pkg_datestr($pkg,'cancel'). ''; + print 'Cancelled '. + ''. pkg_datestr($pkg,'cancel'). ''; unless ( $pkg->{setup} ) { print 'Never billed'; } else { @@ -448,8 +448,8 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { } else { if ( $pkg->{susp} ) { #status: suspended - print 'Suspended '. - pkg_datestr($pkg,'susp'). ''; + print 'Suspended '. + ''. pkg_datestr($pkg,'susp'). ''; unless ( $pkg->{setup} ) { print 'Never billed'; } else { @@ -486,8 +486,8 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { 'Billed '. pkg_datestr($pkg,'setup'). ''; } else { - print 'Active, '. - 'billed '. freq($pkg->{freq}). ''. + print 'Active'. + ', billed '. freq($pkg->{freq}). ''. 'Setup '. pkg_datestr($pkg, 'setup'). ''; } @@ -835,14 +835,14 @@ return \@packages; sub svc_link { my ($svcpart, $svc) = (shift,shift) or return ''; - return qq!$svcpart->{svc}!; + return qq!$svcpart->{svc}!; } sub svc_label_link { my ($svcpart, $svc) = (shift,shift) or return ''; - return qq!$svc->{label}!; + return qq!$svc->{label}!; } -- cgit v1.2.1 From 6a961cb36a8f9606a168331fd5c3625c3bbec9c2 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 May 2003 07:34:15 +0000 Subject: setbuf call doesn't appear to be working... --- fs_selfservice/FS-SelfService/freeside-selfservice-clientd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs_selfservice/FS-SelfService/freeside-selfservice-clientd b/fs_selfservice/FS-SelfService/freeside-selfservice-clientd index 0c25c3407..f13dd42d7 100644 --- a/fs_selfservice/FS-SelfService/freeside-selfservice-clientd +++ b/fs_selfservice/FS-SelfService/freeside-selfservice-clientd @@ -14,7 +14,7 @@ use IO::Handle qw(_IONBF); use IO::Select; use IO::File; -STDOUT->setbuf(''); +#STDOUT->setbuf(''); use vars qw( $Debug ); $Debug = 3; #2 will turn on child logging, 3 will log packet contents, -- cgit v1.2.1 From 9033414f18177eb733d1a227d2be1c15d244f766 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 13 May 2003 03:22:35 +0000 Subject: - self-service updates: cleanup and beginnings of "make a payment" - fix pod masking FS::svc_acct::cust_svc --- FS/FS/svc_acct.pm | 2 ++ fs_selfservice/FS-SelfService/cgi/login.html | 15 ++++++++++++--- fs_selfservice/FS-SelfService/cgi/myaccount.html | 13 ++++++++----- fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 8 ++++++-- fs_selfservice/FS-SelfService/cgi/view_invoice.html | 4 ++-- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index e0c4662b2..8f2861bfd 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -922,6 +922,8 @@ sub svc_domain { Returns the FS::cust_svc record for this account (see L). +=cut + sub cust_svc { my $self = shift; qsearchs( 'cust_svc', { 'svcnum' => $self->svcnum } ); diff --git a/fs_selfservice/FS-SelfService/cgi/login.html b/fs_selfservice/FS-SelfService/cgi/login.html index dfbd0137a..112cc34ea 100644 --- a/fs_selfservice/FS-SelfService/cgi/login.html +++ b/fs_selfservice/FS-SelfService/cgi/login.html @@ -6,16 +6,25 @@ - + - + - +
Username + + +
Domain + + +
Password + + +


diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html index f8a916eea..d8bfe0cb1 100644 --- a/fs_selfservice/FS-SelfService/cgi/myaccount.html +++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html @@ -3,20 +3,23 @@ <%= $url = "$selfurl?session=$session_id;action="; ''; %> @@ -23,7 +23,7 @@
MyAccount
-SomethingElse
+
Hello <%= $name %>!

-Your customer number is <%= $custnum %>

Your contact information
<%= $small_custview %> -Your outstanding balance is $<%= $balance %>

+
+<%= if ( $balance ) { + $OUT .= qq! Make a $balance payment!; +} %> +

<%= if ( @open_invoices ) { $OUT .= ''. '
Open Invoices'; - my $link = qq!myaccount!; my $col1 = "ffffff"; my $col2 = "dddddd"; my $col = $col1; @@ -40,7 +43,7 @@ Your outstanding balance is $<%= $balance %>


-small text +powered by freeside diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index eae373931..9b8bdc100 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -53,7 +53,7 @@ if ( $cgi->param('session') eq 'login' ) { $session_id = $cgi->param('session'); -$cgi->param('action') =~ /^(myaccount|view_invoice)$/ +$cgi->param('action') =~ /^(myaccount|view_invoice|make_payment)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -88,6 +88,10 @@ sub view_invoice { } +sub make_payment { + +} + #-- sub do_template { @@ -95,7 +99,7 @@ sub do_template { my $fill_in = shift; $cgi->delete_all(); - $fill_in->{'self_url'} = $cgi->self_url; + $fill_in->{'selfurl'} = $cgi->self_url; my $template = new Text::Template( TYPE => 'FILE', SOURCE => "$template_dir/$name.html", diff --git a/fs_selfservice/FS-SelfService/cgi/view_invoice.html b/fs_selfservice/FS-SelfService/cgi/view_invoice.html index 33388de99..d2b012b5d 100644 --- a/fs_selfservice/FS-SelfService/cgi/view_invoice.html +++ b/fs_selfservice/FS-SelfService/cgi/view_invoice.html @@ -3,7 +3,7 @@ <%= $url = "$selfurl?session=$session_id;action="; ''; %>
MyAccount
-SomethingElse
+
<-- back to MyAccount

@@ -14,7 +14,7 @@

-small text +powered by freeside -- cgit v1.2.1 From 6e2a0edcc8659e18af767a2d5305b450092b3542 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 13 May 2003 05:47:25 +0000 Subject: missing pod =cut at end --- FS/FS/addr_block.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm index af4e5fb79..c5ddca7d0 100755 --- a/FS/FS/addr_block.pm +++ b/FS/FS/addr_block.pm @@ -324,5 +324,7 @@ To be implemented. Minimum block size should be a config option. It's hardcoded at /30 right now because that's the smallest block that makes any sense at all. +=cut + 1; -- cgit v1.2.1 From d1fe599b5646d693c99908b0288a76744103b5a2 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 13 May 2003 06:01:53 +0000 Subject: - document missing fields in cust_bill_event --- FS/FS/cust_bill_event.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FS/FS/cust_bill_event.pm b/FS/FS/cust_bill_event.pm index 44e4d4797..c97734780 100644 --- a/FS/FS/cust_bill_event.pm +++ b/FS/FS/cust_bill_event.pm @@ -44,6 +44,10 @@ currently supported: =item _date - specified as a UNIX timestamp; see L. Also see L and L for conversion functions. +=item status - event status: B or B + +=item statustext - additional status detail (i.e. error message) + =back =head1 METHODS -- cgit v1.2.1 From ac15b7153b154f5bb951f0ce62731f8216ff9fc4 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 14 May 2003 16:51:43 +0000 Subject: display recurring custom line items on invoices as well as one-shot ones --- FS/FS/cust_bill.pm | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 76c0752ab..a0634d918 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -983,13 +983,20 @@ sub print_text { push @buf, map { [ " $_", '' ] } $cust_bill_pkg->details; - } else { #pkgnum tax + } else { #pkgnum tax or one-shot line item my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc') ? ( $cust_bill_pkg->itemdesc || 'Tax' ) : 'Tax'; - push @buf, [ $itemdesc, - $money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ] - if $cust_bill_pkg->setup != 0; + if ( $cust_bill_pkg->setup != 0 ) { + push @buf, [ $itemdesc, + $money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ]; + } + if ( $cust_bill_pkg->recur != 0 ) { + push @buf, [ "$itemdesc (". time2str("%x", $cust_bill_pkg->sdate). " - " + . time2str("%x", $cust_bill_pkg->edate). ")", + $money_char. sprintf("%10.2f", $cust_bill_pkg->recur) + ]; + } } } -- cgit v1.2.1 From d1d57ae4fa0f2a30b36a70c656aa2672744f75a3 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 18 May 2003 06:20:21 +0000 Subject: self-service: make payment UI done --- FS/FS/ClientAPI/MyAccount.pm | 37 +++++++++++++++++++++++ fs_selfservice/FS-SelfService/SelfService.pm | 1 + fs_selfservice/FS-SelfService/cgi/login.html | 4 +-- fs_selfservice/FS-SelfService/cgi/myaccount.html | 7 ++--- fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 5 +-- 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 9983b5d26..80c7330e8 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -19,6 +19,7 @@ FS::ClientAPI->register_handlers( 'MyAccount/customer_info' => \&customer_info, 'MyAccount/invoice' => \&invoice, 'MyAccount/cancel' => \&cancel, + 'MyAccount/payment_info' => \&payment_info, ); #store in db? @@ -112,6 +113,42 @@ sub customer_info { } +sub payment_info { + my $p = shift; + my $session = $cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my %return; + + my $custnum = $session->{'custnum'}; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + $return{balance} = $cust_main->balance; + + $return{payname} = $cust_main->payname + || $cust_main->first. ' '. $cust_main->get('last'); + + $return{$_} = $cust_main->get($_) for qw(address1 address2 city state zip); + + if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) { + #$return{card_type} = + $return{payinfo} = $cust_main->payinfo; + #exp date (month, year) + + #CARD vd DCRD remembering + } + + #list all states & counties + + return { 'error' => '', + %return, + }; + +}; + + sub invoice { my $p = shift; my $session = $cache->get($p->{'session_id'}) diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm index 4d68d614a..c561dabdb 100644 --- a/fs_selfservice/FS-SelfService/SelfService.pm +++ b/fs_selfservice/FS-SelfService/SelfService.pm @@ -23,6 +23,7 @@ $socket = "/usr/local/freeside/selfservice_socket"; 'customer_info' => 'MyAccount/customer_info', 'invoice' => 'MyAccount/invoice', 'cancel' => 'MyAccount/cancel', + 'payment_info' => 'MyAccount/payment_info', ); @EXPORT_OK = keys %autoload; diff --git a/fs_selfservice/FS-SelfService/cgi/login.html b/fs_selfservice/FS-SelfService/cgi/login.html index 112cc34ea..ca6251eb1 100644 --- a/fs_selfservice/FS-SelfService/cgi/login.html +++ b/fs_selfservice/FS-SelfService/cgi/login.html @@ -8,7 +8,7 @@
Username - +
Password - +
diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html index d8bfe0cb1..f1a63870a 100644 --- a/fs_selfservice/FS-SelfService/cgi/myaccount.html +++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html @@ -9,12 +9,9 @@ Hello <%= $name %>!

Your contact information
<%= $small_custview %>
-<%= if ( $balance ) { - $OUT .= qq! Make a $balance payment!; +<%= if ( $balance > 0 ) { + $OUT .= qq! Make a payment

!; } %> -

- <%= if ( @open_invoices ) { $OUT .= ''. diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 9b8bdc100..7b392bcf4 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -6,7 +6,7 @@ use subs qw(do_template); use CGI; use CGI::Carp qw(fatalsToBrowser); use Text::Template; -use FS::SelfService qw(login customer_info invoice); +use FS::SelfService qw(login customer_info invoice payment_info); $template_dir = '.'; @@ -68,6 +68,7 @@ if ( $result->{error} eq "Can't resume session" ) { #ick #warn $result->{'open_invoices'}; #warn scalar(@{$result->{'open_invoices'}}); +warn "processing template $action\n"; do_template($action, { 'session_id' => $session_id, %{$result} @@ -89,7 +90,7 @@ sub view_invoice { } sub make_payment { - + payment_info( 'session_id' => $session_id ); } #-- -- cgit v1.2.1 From 416dc3b6df09133c4130445008919408f04586c3 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 18 May 2003 08:08:12 +0000 Subject: more self-service make payment UI work --- FS/FS/ClientAPI/MyAccount.pm | 36 ++++++++++++++++++++++++++++++------ fs_selfservice/DEPLOY | 6 ++---- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 80c7330e8..c722c9d5f 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -4,14 +4,16 @@ use strict; use vars qw($cache); use Digest::MD5 qw(md5_hex); use Date::Format; +use Business::CreditCard; use Cache::SharedMemoryCache; #store in db? use FS::CGI qw(small_custview); #doh use FS::Conf; -use FS::Record qw(qsearchs); +use FS::Record qw(qsearch qsearchs); use FS::svc_acct; use FS::svc_domain; use FS::cust_main; use FS::cust_bill; +use FS::cust_main_county; use FS::ClientAPI; #hmm FS::ClientAPI->register_handlers( @@ -132,15 +134,38 @@ sub payment_info { $return{$_} = $cust_main->get($_) for qw(address1 address2 city state zip); + $return{payby} = $cust_main->payby; + if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) { - #$return{card_type} = + $return{card_type} = cardtype($cust_main->payinfo); $return{payinfo} = $cust_main->payinfo; - #exp date (month, year) - #CARD vd DCRD remembering + if ( $cust_main->paydate =~ /^(\d{4})-(\d{2})-\d{2}$/ ) { #Pg date format + @return{'month', 'year'} = ( $2, $1 ); + } elsif ( $cust_main->paydate =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) { + @return{'month', 'year'} = ( $1, $3 ); + } + } - #list all states & counties + #list all counties/states/countries + $return{'cust_main_county'} = + [ map { $_->hashref } qsearch('cust_main_county', {}) ], + + #shortcut for one-country folks + my $conf = new FS::Conf; + my %states = map { $_->state => 1 } + qsearch('cust_main_county', { + 'country' => $conf->config('defaultcountry') || 'US' + } ); + $return{'states'} = [ sort { $a cmp $b } keys %states ]; + + $return{card_types} = { + 'VISA' => 'VISA card', + 'MasterCard' => 'MasterCard', + 'Discover' => 'Discover card', + 'American Express' => 'American Express card', + }; return { 'error' => '', %return, @@ -148,7 +173,6 @@ sub payment_info { }; - sub invoice { my $p = shift; my $session = $cache->get($p->{'session_id'}) diff --git a/fs_selfservice/DEPLOY b/fs_selfservice/DEPLOY index 7ab3b2a7a..4aef4cfa4 100755 --- a/fs_selfservice/DEPLOY +++ b/fs_selfservice/DEPLOY @@ -1,14 +1,12 @@ #!/bin/sh +kill `cat /var/run/freeside-selfservice-server.fs_selfservice.pid` + ( cd ..; make deploy; cd fs_selfservice ) cd FS-SelfService perl Makefile.PL && make && make install -cd .. -kill `cat /var/run/freeside-selfservice-server.ivan.pid`; sleep 3 -./freeside-selfservice-server ivan localhost - cp /home/ivan/freeside/fs_selfservice/FS-SelfService/cgi/* /var/www/MyAccount chown freeside /var/www/MyAccount/selfservice.cgi chmod 755 /var/www/MyAccount/selfservice.cgi -- cgit v1.2.1 From 2c88b03550a72438bbd75ec7461d2c26fc797efc Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 18 May 2003 08:09:41 +0000 Subject: forgot this file --- .../FS-SelfService/cgi/make_payment.html | 118 +++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 fs_selfservice/FS-SelfService/cgi/make_payment.html diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html new file mode 100644 index 000000000..d469bddb6 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -0,0 +1,118 @@ +MyAccount +MyAccount

+<%= $url = "$selfurl?session=$session_id;action="; ''; %> +
+MyAccount
+ +
+Make a payment

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Amount Due +
+ $<%=sprintf("%.2f",$balance)%> +
+
Payment amount +
+ $"> +
+
Card type + +
Card number + + + + + + + + +
+ Exp. + + / + +
+
Exact name on card
Card billing address + +
Address line 2 + +
City + + + + + + + + +
+ + State + + Zip + +
+
+ + Remember this information +
+ NAME="CARD"> + Charge future payments to this card automatically +
+ +
+
+
+powered by freeside + + -- cgit v1.2.1 From 667a729f660ad4f871acd5eb3173303396543eeb Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 18 May 2003 11:44:37 +0000 Subject: interface for making payments all done --- FS/FS/ClientAPI/MyAccount.pm | 8 +++++--- fs_selfservice/FS-SelfService/cgi/make_payment.html | 14 ++++++++------ fs_selfservice/FS-SelfService/cgi/myaccount.html | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index c722c9d5f..c750ada46 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -107,7 +107,6 @@ sub customer_info { } - return { 'error' => '', 'custnum' => $custnum, %return, @@ -130,14 +129,14 @@ sub payment_info { $return{balance} = $cust_main->balance; $return{payname} = $cust_main->payname - || $cust_main->first. ' '. $cust_main->get('last'); + || ( $cust_main->first. ' '. $cust_main->get('last') ); $return{$_} = $cust_main->get($_) for qw(address1 address2 city state zip); $return{payby} = $cust_main->payby; if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) { - $return{card_type} = cardtype($cust_main->payinfo); + warn $return{card_type} = cardtype($cust_main->payinfo); $return{payinfo} = $cust_main->payinfo; if ( $cust_main->paydate =~ /^(\d{4})-(\d{2})-\d{2}$/ ) { #Pg date format @@ -167,6 +166,9 @@ sub payment_info { 'American Express' => 'American Express card', }; + my $_date = time; + $return{paybatch} = 'webui-MyAccount-$_date-$$-". rand() * 2**32 + return { 'error' => '', %return, }; diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html index d469bddb6..ce1db6865 100644 --- a/fs_selfservice/FS-SelfService/cgi/make_payment.html +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -6,7 +6,7 @@ Make a payment

-
+ @@ -29,8 +29,8 @@ - +
Card type @@ -63,7 +63,7 @@
Exact name on card
Card billing address @@ -85,7 +85,7 @@ State @@ -109,7 +109,9 @@
- +
+ +

diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html index f1a63870a..f48fdedea 100644 --- a/fs_selfservice/FS-SelfService/cgi/myaccount.html +++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html @@ -7,7 +7,7 @@ Hello <%= $name %>!

-Your contact information
<%= $small_custview %> +<%= $small_custview %>
<%= if ( $balance > 0 ) { $OUT .= qq! Make a payment

!; -- cgit v1.2.1 From f0afbc011e7b909a2e6ac54039c975710e76f341 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 19 May 2003 00:15:20 +0000 Subject: processing payments... --- .../FS-SelfService/cgi/make_payment.html | 4 +- fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 73 +++++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html index ce1db6865..6adc0bde0 100644 --- a/fs_selfservice/FS-SelfService/cgi/make_payment.html +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -99,12 +99,12 @@ - + Remember this information - NAME="CARD"> + NAME="auto" VALUE="1"> Charge future payments to this card automatically diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 7b392bcf4..2ce2c8b6c 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -53,7 +53,8 @@ if ( $cgi->param('session') eq 'login' ) { $session_id = $cgi->param('session'); -$cgi->param('action') =~ /^(myaccount|view_invoice|make_payment)$/ +$cgi->param('action') =~ + /^(myaccount|view_invoice|make_payment|process_payment)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -93,6 +94,76 @@ sub make_payment { payment_info( 'session_id' => $session_id ); } +sub process_payment { + + $cgi->param('amount') =~ /^\s*(\d+(\.\d{2})?)\s*$/ + or die "illegal amount"; #!!! + my $amount = $1; + + my $payinfo = $cgi->param('payinfo'); + $payinfo =~ s/\D//g; + $payinfo =~ /^(\d{13,16})$/ + #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo; + or die "illegal card"; #!!! + $payinfo = $1; + validate($payinfo) + #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo; + or die "invalid card"; #!!! + cardtype($payinfo) eq $cgi->param('card_type') + #or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type'); + or die "not a ". $cgi->param('card_type'); + + $cgi->param('month') =~ /^(\d{2})$/ or die "illegal month"; + my $month = $1; + $cgi->param('year') =~ /^(\d{4})$/ or die "illegal year"; + my $year = $1; + + $cgi->param('payname') =~ /^(.{0,80})$/ or die "illegal payname"; + my $payname = $1; + + $cgi->param('address1') =~ /^(.{0,80})$/ or die "illegal address1"; + my $address1 = $1; + + $cgi->param('address2') =~ /^(.{0,80})$/ or die "illegal address2"; + my $address2 = $1; + + $cgi->param('city') =~ /^(.{0,80})$/ or die "illegal city"; + my $city = $1; + + $cgi->param('state') =~ /^(.{2})$/ or die "illegal state"; + my $state = $1; + + $cgi->param('zip') =~ /^(.{0,10})$/ or die "illegal zip"; + my $zip = $1; + + my $save = 0; + $save = 1 if $cgi->param('save'); + + my $auto = 0; + $auto = 1 if $cgi->param('auto'); + + $cgi->param('paybatch') =~ /^([\w\-\.]+)$/ or die "illegal paybatch"; + my $patbatch = $1; + + process_payment( + 'session_id' => $session_id, + 'amount' => $amount, + 'payinfo' => $payinfo, + 'month' => $month, + 'year' => $year, + 'payname' => $payname, + 'address1' => $address1, + 'address2' => $address2, + 'city' => $city, + 'state' => $state, + 'zip' => $zip, + 'save' => $save, + 'auto' => $auto, + 'paybatch' => $paybatch, + ); + +} + #-- sub do_template { -- cgit v1.2.1 From fd9138f66cf7f3ab9557e0beebb4e2657a59e34c Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 19 May 2003 12:00:45 +0000 Subject: maintenance: - add FS::Misc with send_email subroutine, remove all duplicate code from various modules - move the realtime_bop from cust_bill to cust_main & change usage slightly. invnum is no longer required. FS::cust_bill::realtime_bop remains as a wrapper. self-service: - fix some syntax errors, make payment UI (step one) really should be working now --- FS/FS/ClientAPI/MyAccount.pm | 16 ++- FS/FS/Misc.pm | 95 ++++++++++++++ FS/FS/cust_bill.pm | 298 +++---------------------------------------- FS/FS/cust_main.pm | 216 +++++++++++++++++++++++++++++++ FS/FS/cust_pay.pm | 50 +++----- FS/FS/cust_pkg.pm | 49 ++----- FS/FS/svc_acct.pm | 32 ++--- FS/FS/svc_domain.pm | 6 +- FS/MANIFEST | 2 + FS/t/Misc.t | 5 + 10 files changed, 394 insertions(+), 375 deletions(-) create mode 100644 FS/FS/Misc.pm create mode 100644 FS/t/Misc.t diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index c750ada46..a64cfb5d7 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -167,7 +167,7 @@ sub payment_info { }; my $_date = time; - $return{paybatch} = 'webui-MyAccount-$_date-$$-". rand() * 2**32 + $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32; return { 'error' => '', %return, @@ -175,6 +175,20 @@ sub payment_info { }; +sub make_payment{ + my $p = shift; + + my $session = $cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my %return; + + my $custnum = $session->{'custnum'}; + + + +} + sub invoice { my $p = shift; my $session = $cache->get($p->{'session_id'}) diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm new file mode 100644 index 000000000..56dc72e36 --- /dev/null +++ b/FS/FS/Misc.pm @@ -0,0 +1,95 @@ +package FS::Misc; + +use strict; +use vars qw ( @ISA @EXPORT_OK ); +use Exporter; + +@ISA = qw( Exporter ); +@EXPORT_OK = qw( send_email ); + +=head1 NAME + +FS::Misc - Miscellaneous subroutines + +=head1 SYNOPSIS + + use FS::Misc qw(send_email); + + send_email(); + +=head1 DESCRIPTION + +Miscellaneous subroutines. This module contains miscellaneous subroutines +called from multiple other modules. These are not OO or necessarily related, +but are collected here to elimiate code duplication. + +=head1 SUBROUTINES + +=over 4 + +=item send_email OPTION => VALUE ... + +Options: + +I - (required) + +I - (required) comma-separated scalar or arrayref of recipients + +I - (required) + +I - (optional) MIME type + +I - (required) arrayref of body text lines + +=cut + +use vars qw( $conf ); +use Date::Format; +use Mail::Header; +use Mail::Internet 1.44; +use FS::UID; + +FS::UID->install_callback( sub { + $conf = new FS::Conf; +} ); + +sub send_email { + my(%options) = shift; + + $ENV{MAILADDRESS} = $options{'from'}; + my $to = ref($options{to}) ? join(', ', @{ $options{to} } ) : $options{to}; + my @header = ( + 'From: '. $options{'from'}, + 'To: '. $to, + 'Sender: '. $options{'from'}, + 'Reply-To: '. $options{'from'}, + 'Date: '. time2str("%a, %d %b %Y %X %z", time), + 'Subject: '. $options{'subject'}, + ); + push @header, 'Content-Type: '. $options{'content-type'} + if exists($options{'content-type'}); + my $header = new Mail::Header ( \@header ); + + my $message = new Mail::Internet ( + 'Header' => $header, + 'Body' => $options{'body'}, + ); + + my $smtpmachine = $conf->config('smtpmachine'); + $!=0; + $message->smtpsend( 'Host' => $smtpmachine ) + or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) + or return "can't send email to $to via server $smtpmachine with SMTP: $!"; +} + +=head1 BUGS + +This package exists. + +=head1 SEE ALSO + +L, L, L, the base documentation. + +=cut + +1; diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index a0634d918..a22f44b24 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -2,18 +2,12 @@ package FS::cust_bill; use strict; use vars qw( @ISA $conf $money_char ); -use vars qw( $lpr $invoice_from $smtpmachine ); -use vars qw( $xaction $E_NoErr ); -use vars qw( $bop_processor $bop_login $bop_password $bop_action @bop_options ); -use vars qw( $ach_processor $ach_login $ach_password $ach_action @ach_options ); use vars qw( $invoice_lines @buf ); #yuck -use vars qw( $quiet ); use Date::Format; -use Mail::Internet 1.44; -use Mail::Header; use Text::Template; use FS::UID qw( datasrc ); use FS::Record qw( qsearch qsearchs ); +use FS::Misc qw( send_email ); use FS::cust_main; use FS::cust_bill_pkg; use FS::cust_credit; @@ -26,46 +20,10 @@ use FS::cust_bill_event; @ISA = qw( FS::Record ); #ask FS::UID to run this stuff for us later -$FS::UID::callback{'FS::cust_bill'} = sub { - +FS::UID->install_callback( sub { $conf = new FS::Conf; - $money_char = $conf->config('money_char') || '$'; - - $lpr = $conf->config('lpr'); - $invoice_from = $conf->config('invoice_from'); - $smtpmachine = $conf->config('smtpmachine'); - - ( $bop_processor,$bop_login, $bop_password, $bop_action ) = ( '', '', '', ''); - @bop_options = (); - ( $ach_processor,$ach_login, $ach_password, $ach_action ) = ( '', '', '', ''); - @ach_options = (); - - if ( $conf->exists('business-onlinepayment') ) { - ( $bop_processor, - $bop_login, - $bop_password, - $bop_action, - @bop_options - ) = $conf->config('business-onlinepayment'); - $bop_action ||= 'normal authorization'; - ( $ach_processor, $ach_login, $ach_password, $ach_action, @ach_options ) = - ( $bop_processor, $bop_login, $bop_password, $bop_action, @bop_options ); - eval "use Business::OnlinePayment"; - } - - if ( $conf->exists('business-onlinepayment-ach') ) { - ( $ach_processor, - $ach_login, - $ach_password, - $ach_action, - @ach_options - ) = $conf->config('business-onlinepayment-ach'); - $ach_action ||= 'normal authorization'; - eval "use Business::OnlinePayment"; - } - -}; +} ); =head1 NAME @@ -373,33 +331,20 @@ sub send { if ( grep { $_ ne 'POST' } @invoicing_list or !@invoicing_list ) { #email #better to notify this person than silence - @invoicing_list = ($invoice_from) unless @invoicing_list; - - #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card - #$ENV{SMTPHOSTS} = $smtpmachine; - $ENV{MAILADDRESS} = $invoice_from; - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: Invoice", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ @print_text ], #( date) + @invoicing_list = ($conf->config('invoice_from')) unless @invoicing_list; + + my $error = send_email( + 'from' => $conf->config('invoice_from'), + 'to' => [ grep { $_ ne 'POST' } @invoicing_list ], + 'subject' => 'Invoice', + 'body' => \@print_text, ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or return "(customer # ". $self->custnum. ") can't send invoice email". - " to ". join(', ', grep { $_ ne 'POST' } @invoicing_list ). - " via server $smtpmachine with SMTP: $!"; + return "can't send invoice: $error" if $error; } if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal + my $lpr = $conf->config('lpr'); open(LPR, "|$lpr") or return "Can't open pipe to $lpr: $!"; print LPR @print_text; @@ -610,15 +555,7 @@ for supported processors. sub realtime_card { my $self = shift; - $self->realtime_bop( - 'CC', - $bop_processor, - $bop_login, - $bop_password, - $bop_action, - \@bop_options, - @_ - ); + $self->realtime_bop( 'CC', @_ ); } =item realtime_ach @@ -632,15 +569,7 @@ for supported processors. sub realtime_ach { my $self = shift; - $self->realtime_bop( - 'ECHECK', - $ach_processor, - $ach_login, - $ach_password, - $ach_action, - \@ach_options, - @_ - ); + $self->realtime_bop( 'ECHECK', @_ ); } =item realtime_lec @@ -654,53 +583,15 @@ for supported processors. sub realtime_lec { my $self = shift; - $self->realtime_bop( - 'LEC', - $bop_processor, - $bop_login, - $bop_password, - $bop_action, - \@bop_options, - @_ - ); + $self->realtime_bop( 'LEC', @_ ); } sub realtime_bop { - my( $self, $method, $processor, $login, $password, $action, $options ) = @_; - - #trim an extraneous blank line - pop @$options if scalar(@$options) % 2 && $options->[-1] =~ /^\s*$/; + my( $self, $method ) = @_; my $cust_main = $self->cust_main; my $amount = $self->owed; - my $address = $cust_main->address1; - $address .= ", ". $cust_main->address2 if $cust_main->address2; - - my($payname, $payfirst, $paylast); - if ( $cust_main->payname && $method ne 'ECHECK' ) { - $payname = $cust_main->payname; - $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ - or do { - #$dbh->rollback if $oldAutoCommit; - return "Illegal payname $payname"; - }; - ($payfirst, $paylast) = ($1, $2); - } else { - $payfirst = $cust_main->getfield('first'); - $paylast = $cust_main->getfield('last'); - $payname = "$payfirst $paylast"; - } - - my @invoicing_list = grep { $_ ne 'POST' } $cust_main->invoicing_list; - if ( $conf->exists('emailinvoiceauto') - || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) { - push @invoicing_list, $cust_main->all_emails; - } - my $email = $invoicing_list[0]; - - my( $action1, $action2 ) = split(/\s*\,\s*/, $action ); - my $description = 'Internet Services'; if ( $conf->exists('business-onlinepayment-description') ) { my $dtempl = $conf->config('business-onlinepayment-description'); @@ -714,163 +605,12 @@ sub realtime_bop { grep { $_->pkgnum } $self->cust_bill_pkg ); $description = eval qq("$dtempl"); - } - my %content; - if ( $method eq 'CC' ) { - $content{card_number} = $cust_main->payinfo; - $cust_main->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; - $content{expiration} = "$2/$1"; - } elsif ( $method eq 'ECHECK' ) { - my($account_number,$routing_code) = $cust_main->payinfo; - ( $content{account_number}, $content{routing_code} ) = - split('@', $cust_main->payinfo); - $content{bank_name} = $cust_main->payname; - } elsif ( $method eq 'LEC' ) { - $content{phone} = $cust_main->payinfo; - } - - my $transaction = - new Business::OnlinePayment( $processor, @$options ); - $transaction->content( - 'type' => $method, - 'login' => $login, - 'password' => $password, - 'action' => $action1, - 'description' => $description, - 'amount' => $amount, - 'invoice_number' => $self->invnum, - 'customer_id' => $self->custnum, - 'last_name' => $paylast, - 'first_name' => $payfirst, - 'name' => $payname, - 'address' => $address, - 'city' => $cust_main->city, - 'state' => $cust_main->state, - 'zip' => $cust_main->zip, - 'country' => $cust_main->country, - 'referer' => 'http://cleanwhisker.420.am/', - 'email' => $email, - 'phone' => $cust_main->daytime || $cust_main->night, - %content, #after + $cust_main->realtime_bop($method, $amount, + 'description' => $description, + 'invnum' => $self->invnum, ); - $transaction->submit(); - - if ( $transaction->is_success() && $action2 ) { - my $auth = $transaction->authorization; - my $ordernum = $transaction->can('order_number') - ? $transaction->order_number - : ''; - - #warn "********* $auth ***********\n"; - #warn "********* $ordernum ***********\n"; - my $capture = - new Business::OnlinePayment( $processor, @$options ); - - my %capture = ( - %content, - type => $method, - action => $action2, - login => $login, - password => $password, - order_number => $ordernum, - amount => $amount, - authorization => $auth, - description => $description, - ); - - foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code - transaction_sequence_num local_transaction_date - local_transaction_time AVS_result_code )) { - $capture{$field} = $transaction->$field() if $transaction->can($field); - } - - $capture->content( %capture ); - - $capture->submit(); - - unless ( $capture->is_success ) { - my $e = "Authorization sucessful but capture failed, invnum #". - $self->invnum. ': '. $capture->result_code. - ": ". $capture->error_message; - warn $e; - return $e; - } - - } - - if ( $transaction->is_success() ) { - - my %method2payby = ( - 'CC' => 'CARD', - 'ECHECK' => 'CHEK', - 'LEC' => 'LECB', - ); - - my $cust_pay = new FS::cust_pay ( { - 'invnum' => $self->invnum, - 'paid' => $amount, - '_date' => '', - 'payby' => $method2payby{$method}, - 'payinfo' => $cust_main->payinfo, - 'paybatch' => "$processor:". $transaction->authorization, - } ); - my $error = $cust_pay->insert; - if ( $error ) { - # gah, even with transactions. - my $e = 'WARNING: Card/ACH debited but database not updated - '. - 'error applying payment, invnum #' . $self->invnum. - " ($processor): $error"; - warn $e; - return $e; - } else { - return ''; - } - #} elsif ( $options{'report_badcard'} ) { - } else { - - my $perror = "$processor error, invnum #". $self->invnum. ': '. - $transaction->result_code. ": ". $transaction->error_message; - - if ( !$quiet && $conf->exists('emaildecline') - && grep { $_ ne 'POST' } $cust_main->invoicing_list - ) { - my @templ = $conf->config('declinetemplate'); - my $template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", @templ ], - ) or return "($perror) can't create template: $Text::Template::ERROR"; - $template->compile() - or return "($perror) can't compile template: $Text::Template::ERROR"; - - my $templ_hash = { error => $transaction->error_message }; - - #false laziness w/FS::cust_pay::delete & fs_signup_server && ::send - $ENV{MAILADDRESS} = $invoice_from; - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: Your payment could not be processed", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ $template->fill_in(HASH => $templ_hash) ], - ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or return "($perror) (customer # ". $self->custnum. - ") can't send card decline email to ". - join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ). - " via server $smtpmachine with SMTP: $!"; - } - - return $perror; - } } diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 608c5e3cb..b162622a4 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -10,6 +10,7 @@ use Date::Format; use Business::CreditCard; use FS::UID qw( getotaker dbh ); use FS::Record qw( qsearchs qsearch dbdef ); +use FS::Misc qw( send_email ); use FS::cust_pkg; use FS::cust_bill; use FS::cust_bill_pkg; @@ -1408,6 +1409,221 @@ sub collect { } +=item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ] + + +Runs a realtime credit card, ACH (electronic check) or phone bill transaction +via a Business::OnlinePayment realtime gateway. See +L for supported gateways. + +Available methods are: I, I and I + +Available options are: I, I, I + +I is a free-text field passed to the gateway. It defaults to +"Internet services". + +If an I is specified, this payment (if sucessful) is applied to the +specified invoice. If you don't specify an I you might want to +call the B method. + +I can be set true to surpress email decline notices. + +(moved from cust_bill) (probably should get realtime_{card,ach,lec} here too) + +=cut + +sub realtime_bop { + my( $self, $method, $amount, %options ) = @_; + $options{'description'} ||= 'Internet services'; + + #pre-requisites + die "Real-time processing not enabled\n" + unless $conf->exists('business-onlinepayment'); + eval "use Business::OnlinePayment"; + die $@ if $@; + + #load up config + my $bop_config = 'business-onlinepayment'; + $bop_config .= '-ach' + if $method eq 'ECHECK' && $conf->exists($bop_config. '-ach'); + my ( $processor, $login, $password, $action, @bop_options ) = + $conf->config($bop_config); + $action ||= 'normal authorization'; + pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/; + + #massage data + + my $address = $self->address1; + $address .= ", ". $self->address2 if $self->address2; + + my($payname, $payfirst, $paylast); + if ( $self->payname && $method ne 'ECHECK' ) { + $payname = $self->payname; + $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ + or return "Illegal payname $payname"; + ($payfirst, $paylast) = ($1, $2); + } else { + $payfirst = $self->getfield('first'); + $paylast = $self->getfield('last'); + $payname = "$payfirst $paylast"; + } + + my @invoicing_list = grep { $_ ne 'POST' } $self->invoicing_list; + if ( $conf->exists('emailinvoiceauto') + || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) { + push @invoicing_list, $self->all_emails; + } + my $email = $invoicing_list[0]; + + my %content; + if ( $method eq 'CC' ) { + $content{card_number} = $self->payinfo; + $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; + $content{expiration} = "$2/$1"; + } elsif ( $method eq 'ECHECK' ) { + my($account_number,$routing_code) = $self->payinfo; + ( $content{account_number}, $content{routing_code} ) = + split('@', $self->payinfo); + $content{bank_name} = $self->payname; + } elsif ( $method eq 'LEC' ) { + $content{phone} = $self->payinfo; + } + + #transaction(s) + + my( $action1, $action2 ) = split(/\s*\,\s*/, $action ); + + my $transaction = + new Business::OnlinePayment( $processor, @bop_options ); + $transaction->content( + 'type' => $method, + 'login' => $login, + 'password' => $password, + 'action' => $action1, + 'description' => $options{'description'}, + 'amount' => $amount, + 'invoice_number' => $options{'invnum'}, + 'customer_id' => $self->custnum, + 'last_name' => $paylast, + 'first_name' => $payfirst, + 'name' => $payname, + 'address' => $address, + 'city' => $self->city, + 'state' => $self->state, + 'zip' => $self->zip, + 'country' => $self->country, + 'referer' => 'http://cleanwhisker.420.am/', + 'email' => $email, + 'phone' => $self->daytime || $self->night, + %content, #after + ); + $transaction->submit(); + + if ( $transaction->is_success() && $action2 ) { + my $auth = $transaction->authorization; + my $ordernum = $transaction->can('order_number') + ? $transaction->order_number + : ''; + + my $capture = + new Business::OnlinePayment( $processor, @bop_options ); + + my %capture = ( + %content, + type => $method, + action => $action2, + login => $login, + password => $password, + order_number => $ordernum, + amount => $amount, + authorization => $auth, + description => $options{'description'}, + ); + + foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code + transaction_sequence_num local_transaction_date + local_transaction_time AVS_result_code )) { + $capture{$field} = $transaction->$field() if $transaction->can($field); + } + + $capture->content( %capture ); + + $capture->submit(); + + unless ( $capture->is_success ) { + my $e = "Authorization sucessful but capture failed, custnum #". + $self->custnum. ': '. $capture->result_code. + ": ". $capture->error_message; + warn $e; + return $e; + } + + } + + #result handling + if ( $transaction->is_success() ) { + + my %method2payby = ( + 'CC' => 'CARD', + 'ECHECK' => 'CHEK', + 'LEC' => 'LECB', + ); + + my $cust_pay = new FS::cust_pay ( { + 'invnum' => $self->invnum, #!!!!!!!! + 'paid' => $amount, + '_date' => '', + 'payby' => $method2payby{$method}, + 'payinfo' => $self->payinfo, + 'paybatch' => "$processor:". $transaction->authorization, + } ); + my $error = $cust_pay->insert; + if ( $error ) { + # gah, even with transactions. + my $e = 'WARNING: Card/ACH debited but database not updated - '. + 'error applying payment, invnum #' . $self->invnum. + " ($processor): $error"; + warn $e; + return $e; + } else { + return ''; + } + + } else { + + my $perror = "$processor error: ". $transaction->error_message; + + if ( !$options{'quiet'} && $conf->exists('emaildecline') + && grep { $_ ne 'POST' } $self->invoicing_list + ) { + my @templ = $conf->config('declinetemplate'); + my $template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", @templ ], + ) or return "($perror) can't create template: $Text::Template::ERROR"; + $template->compile() + or return "($perror) can't compile template: $Text::Template::ERROR"; + + my $templ_hash = { error => $transaction->error_message }; + + my $error = send_email( + 'from' => $conf->config('invoice_from'), + 'to' => [ grep { $_ ne 'POST' } $self->invoicing_list ], + 'subject' => 'Your payment could not be processed', + 'body' => [ $template->fill_in(HASH => $templ_hash) ], + ); + + $perror .= " (also received error sending decline notification: $error)" + if $error; + + } + + return $perror; + } + +} + =item total_owed Returns the total owed for this customer on all invoices diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 79cf82755..55f2fc4a3 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -1,13 +1,12 @@ package FS::cust_pay; use strict; -use vars qw( @ISA $conf $unsuspendauto $smtpmachine $invoice_from ); +use vars qw( @ISA $conf $unsuspendauto ); use Date::Format; -use Mail::Header; -use Mail::Internet 1.44; use Business::CreditCard; use FS::UID qw( dbh ); use FS::Record qw( dbh qsearch qsearchs dbh ); +use FS::Misc qw(send_email); use FS::cust_bill; use FS::cust_bill_pay; use FS::cust_main; @@ -15,14 +14,10 @@ use FS::cust_main; @ISA = qw( FS::Record ); #ask FS::UID to run this stuff for us later -$FS::UID::callback{'FS::cust_pay'} = sub { - +FS::UID->install_callback( sub { $conf = new FS::Conf; $unsuspendauto = $conf->exists('unsuspendauto'); - $smtpmachine = $conf->config('smtpmachine'); - $invoice_from = $conf->config('invoice_from'); - -}; +} ); =head1 NAME @@ -265,19 +260,12 @@ sub delete { if ( $conf->config('deletepayments') ne '' ) { my $cust_main = qsearchs('cust_main',{ 'custnum' => $self->custnum }); - #false laziness w/FS::cust_bill::send & fs_signup_server - $ENV{MAILADDRESS} = $invoice_from; #??? well as good as any - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". $conf->config('deletepayments'), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: FREESIDE NOTIFICATION: Payment deleted", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ + + my $error = send_email( + 'from' => $conf->config('invoice_from'), #??? well as good as any + 'to' => $conf->config('deletepayments'), + 'subject' => 'FREESIDE NOTIFICATION: Payment deleted', + 'body' => [ "This is an automatic message from your Freeside installation\n", "informing you that the following payment has been deleted:\n", "\n", @@ -291,16 +279,12 @@ sub delete { 'paybatch: '. $self->paybatch. "\n", ], ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or do { - $dbh->rollback if $oldAutoCommit; - return "(customer # ". $self->custnum. - ") can't send payment deletion email to ". - $conf->config('deletepayments'). - " via server $smtpmachine with SMTP: $!"; - }; + + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't send payment deletion notification: $error"; + } + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -406,7 +390,7 @@ sub unapplied { =head1 VERSION -$Id: cust_pay.pm,v 1.23 2002-11-19 09:51:58 ivan Exp $ +$Id: cust_pay.pm,v 1.24 2003-05-19 12:00:44 ivan Exp $ =head1 BUGS diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index bd3d1f503..9ab269503 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -5,6 +5,7 @@ use vars qw(@ISA $disable_agentcheck); use vars qw( $quiet ); use FS::UID qw( getotaker dbh ); use FS::Record qw( qsearch qsearchs ); +use FS::Misc qw( send_email ); use FS::cust_svc; use FS::part_pkg; use FS::cust_main; @@ -20,12 +21,8 @@ use FS::svc_domain; use FS::svc_www; use FS::svc_forward; -# need all this for sending cancel emails in sub cancel - +# for sending cancel emails in sub cancel use FS::Conf; -use Date::Format; -use Mail::Internet 1.44; -use Mail::Header; @ISA = qw( FS::Record ); @@ -304,38 +301,16 @@ sub cancel { $dbh->commit or die $dbh->errstr if $oldAutoCommit; my $conf = new FS::Conf; - - if ( !$quiet && $conf->exists('emailcancel') - && grep { $_ ne 'POST' } $self->cust_main->invoicing_list) { - - my @invoicing_list = $self->cust_main->invoicing_list; - - my $invoice_from = $conf->config('invoice_from'); - my @print_text = map "$_\n", $conf->config('cancelmessage'); - my $subject = $conf->config('cancelsubject'); - my $smtpmachine = $conf->config('smtpmachine'); - - if ( grep { $_ ne 'POST' } @invoicing_list ) { #email invoice - #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card - #$ENV{SMTPHOSTS} = $smtpmachine; - $ENV{MAILADDRESS} = $invoice_from; - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: $subject", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ @print_text ], - ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ); - #should this return an error? - } + my @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list; + if ( !$quiet && $conf->exists('emailcancel') && @invoicing_list ) { + my $conf = new FS::Conf; + my $error = send_email( + 'from' => $conf->config('invoice_from'), + 'to' => \@invoicing_list, + 'subject' => $conf->config('cancelsubject'), + 'body' => [ map "$_\n", $conf->config('cancelmessage') ], + ); + #should this do something on errors? } ''; #no errors diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 8f2861bfd..497e59c94 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -1024,36 +1024,28 @@ sub radius_groups { =item send_email +This is the FS::svc_acct job-queue-able version. It still uses +FS::Misc::send_email under-the-hood. + =cut sub send_email { my %opt = @_; - use Date::Format; - use Mail::Internet 1.44; - use Mail::Header; + eval "use FS::Misc qw(send_email)"; + die $@ if $@; $opt{mimetype} ||= 'text/plain'; $opt{mimetype} .= '; charset="iso-8859-1"' unless $opt{mimetype} =~ /charset/; - $ENV{MAILADDRESS} = $opt{from}; - my $header = new Mail::Header ( [ - "From: $opt{from}", - "To: $opt{to}", - "Sender: $opt{from}", - "Reply-To: $opt{from}", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: $opt{subject}", - "Content-Type: $opt{mimetype}", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ map "$_\n", split("\n", $opt{body}) ], + my $error = send_email( + 'from' => $opt{from}, + 'to' => $opt{to}, + 'subject' => $opt{subject}, + 'content-type' => $opt{mimetype}, + 'body' => [ map "$_\n", split("\n", $opt{body}) ], ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or die "can't send email to $opt{to} via $smtpmachine with SMTP: $!"; + die $error if $error; } =item check_and_rebuild_fuzzyfiles diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm index 81edc337e..2e8866a56 100644 --- a/FS/FS/svc_domain.pm +++ b/FS/FS/svc_domain.pm @@ -1,13 +1,11 @@ package FS::svc_domain; use strict; -use vars qw( @ISA $whois_hack $conf $smtpmachine +use vars qw( @ISA $whois_hack $conf @defaultrecords $soadefaultttl $soaemail $soaexpire $soamachine $soarefresh $soaretry ); use Carp; -use Mail::Internet 1.44; -use Mail::Header; use Date::Format; use Net::Whois 1.0; use FS::Record qw(fields qsearch qsearchs dbh); @@ -26,8 +24,6 @@ use FS::queue; $FS::UID::callback{'FS::domain'} = sub { $conf = new FS::Conf; - $smtpmachine = $conf->config('smtpmachine'); - @defaultrecords = $conf->config('defaultrecords'); $soadefaultttl = $conf->config('soadefaultttl'); $soaemail = $conf->config('soaemail'); diff --git a/FS/MANIFEST b/FS/MANIFEST index 6397cc411..272b5b731 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -36,6 +36,7 @@ FS/ClientAPI/passwd.pm FS/ClientAPI/MyAccount.pm FS/Conf.pm FS/ConfItem.pm +FS/Misc.pm FS/Record.pm FS/SearchCache.pm FS/UI/Base.pm @@ -125,6 +126,7 @@ t/InitHandler.t t/ClientAPI.t t/Conf.t t/ConfItem.t +t/Misc.t t/Record.t t/UID.t t/Msgcat.t diff --git a/FS/t/Misc.t b/FS/t/Misc.t new file mode 100644 index 000000000..cc7751ab6 --- /dev/null +++ b/FS/t/Misc.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::Misc; +$loaded=1; +print "ok 1\n"; -- cgit v1.2.1 From a1295d0682aa81a408abe06fcaa7c14440f6a2e2 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 19 May 2003 13:38:41 +0000 Subject: first crack at payment processing with self-service (step two of the process) --- FS/FS/ClientAPI/MyAccount.pm | 23 ++++++++++++++++++++++ FS/FS/cust_main.pm | 13 ++++++++++-- .../FS-SelfService/cgi/make_payment.html | 4 ++-- .../FS-SelfService/cgi/process_payment.html | 18 +++++++++++++++++ fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 4 +++- 5 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 fs_selfservice/FS-SelfService/cgi/process_payment.html diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index a64cfb5d7..2ce55a8e7 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -185,7 +185,30 @@ sub make_payment{ my $custnum = $session->{'custnum'}; + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + if ( $p->{'save'} ) { + my $new = new FS::cust_main { $cust_main->hash }; + $new->set( $_ => $p->{$_} ) + foreach qw( payname address1 address2 city state zip payinfo ); + $new->set( 'paydate' => $p->{'month'}. '-'. $p->{'year'} ); + $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); + my $error = $new->replace($cust_main); + return { 'error' => $error } if $error; + $cust_main = $new; + } + + my $error = $cust_main->realtime_bop( 'CC', $p->{'amount'}, quiet=>1, + 'paydate' => $p->{'month'}. '-'. $p->{'year'}, + map { $_ => $p->{$_} } + qw( payname address1 address2 city state zip payinfo ) + ); + return { 'error' => $error } if $error; + + $cust_main->apply_payments; + return { 'error' => '' }; } diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index b162622a4..09c56474c 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -1411,7 +1411,6 @@ sub collect { =item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ] - Runs a realtime credit card, ACH (electronic check) or phone bill transaction via a Business::OnlinePayment realtime gateway. See L for supported gateways. @@ -1420,6 +1419,10 @@ Available methods are: I, I and I Available options are: I, I, I +The additional options I, I, I, I, I, +I, I and I are also available. Any of these options, +if set, will override the value from the customer record. + I is a free-text field passed to the gateway. It defaults to "Internet services". @@ -1443,6 +1446,11 @@ sub realtime_bop { eval "use Business::OnlinePayment"; die $@ if $@; + #overrides + $self->set( $_ => $options{$_} ) + foreach grep { exists($options{$_}) } + qw( payname address1 address2 city state zip payinfo paydate ); + #load up config my $bop_config = 'business-onlinepayment'; $bop_config .= '-ach' @@ -1571,7 +1579,8 @@ sub realtime_bop { ); my $cust_pay = new FS::cust_pay ( { - 'invnum' => $self->invnum, #!!!!!!!! + 'custnum' => $self->custnum, + 'invnum' => $options{'invnum'}, 'paid' => $amount, '_date' => '', 'payby' => $method2payby{$method}, diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html index 6adc0bde0..fdb411b11 100644 --- a/fs_selfservice/FS-SelfService/cgi/make_payment.html +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -31,7 +31,7 @@ @@ -104,7 +104,7 @@ - NAME="auto" VALUE="1"> + NAME="auto" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.save.checked=true; }"> Charge future payments to this card automatically diff --git a/fs_selfservice/FS-SelfService/cgi/process_payment.html b/fs_selfservice/FS-SelfService/cgi/process_payment.html new file mode 100644 index 000000000..e4946dc8f --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/process_payment.html @@ -0,0 +1,18 @@ +MyAccount +MyAccount

+<%= $url = "$selfurl?session=$session_id;action="; ''; %> +
+MyAccount
+ +
+Payment results

+<%= if ( $error ) { + $OUT .= qq!Error processing your payment: $error +
+
+powered by freeside + + diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 2ce2c8b6c..d43df4041 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -96,6 +96,8 @@ sub make_payment { sub process_payment { + use Business::CreditCard; + $cgi->param('amount') =~ /^\s*(\d+(\.\d{2})?)\s*$/ or die "illegal amount"; #!!! my $amount = $1; @@ -143,7 +145,7 @@ sub process_payment { $auto = 1 if $cgi->param('auto'); $cgi->param('paybatch') =~ /^([\w\-\.]+)$/ or die "illegal paybatch"; - my $patbatch = $1; + my $paybatch = $1; process_payment( 'session_id' => $session_id, -- cgit v1.2.1 From e2a51e422dbd070a4571f229f8e5c6929950d137 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 19 May 2003 13:54:55 +0000 Subject: fix up some bugs in processing payments via self-service... appears to be working so far --- FS/FS/ClientAPI/MyAccount.pm | 13 +++++++------ fs_selfservice/FS-SelfService/SelfService.pm | 17 +++++++++-------- fs_selfservice/FS-SelfService/cgi/make_payment.html | 4 ++-- fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 7 ++++--- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 2ce55a8e7..6e9bf23a9 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -17,11 +17,12 @@ use FS::cust_main_county; use FS::ClientAPI; #hmm FS::ClientAPI->register_handlers( - 'MyAccount/login' => \&login, - 'MyAccount/customer_info' => \&customer_info, - 'MyAccount/invoice' => \&invoice, - 'MyAccount/cancel' => \&cancel, - 'MyAccount/payment_info' => \&payment_info, + 'MyAccount/login' => \&login, + 'MyAccount/customer_info' => \&customer_info, + 'MyAccount/invoice' => \&invoice, + 'MyAccount/cancel' => \&cancel, + 'MyAccount/payment_info' => \&payment_info, + 'MyAccount/process_payment' => \&process_payment, ); #store in db? @@ -175,7 +176,7 @@ sub payment_info { }; -sub make_payment{ +sub process_payment { my $p = shift; my $session = $cache->get($p->{'session_id'}) diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm index c561dabdb..5849b28d1 100644 --- a/fs_selfservice/FS-SelfService/SelfService.pm +++ b/fs_selfservice/FS-SelfService/SelfService.pm @@ -16,14 +16,15 @@ $VERSION = '0.03'; $socket = "/usr/local/freeside/selfservice_socket"; %autoload = ( - 'passwd' => 'passwd/passwd', - 'chfn' => 'passwd/passwd', - 'chsh' => 'passwd/passwd', - 'login' => 'MyAccount/login', - 'customer_info' => 'MyAccount/customer_info', - 'invoice' => 'MyAccount/invoice', - 'cancel' => 'MyAccount/cancel', - 'payment_info' => 'MyAccount/payment_info', + 'passwd' => 'passwd/passwd', + 'chfn' => 'passwd/passwd', + 'chsh' => 'passwd/passwd', + 'login' => 'MyAccount/login', + 'customer_info' => 'MyAccount/customer_info', + 'invoice' => 'MyAccount/invoice', + 'cancel' => 'MyAccount/cancel', + 'payment_info' => 'MyAccount/payment_info', + 'process_payment' => 'MyAccount/process_payment', ); @EXPORT_OK = keys %autoload; diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html index fdb411b11..1d860f08a 100644 --- a/fs_selfservice/FS-SelfService/cgi/make_payment.html +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -8,7 +8,7 @@ Make a payment

- + @@ -110,7 +110,7 @@
Amount Due

- +
diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index d43df4041..456d2dde2 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -6,7 +6,8 @@ use subs qw(do_template); use CGI; use CGI::Carp qw(fatalsToBrowser); use Text::Template; -use FS::SelfService qw(login customer_info invoice payment_info); +use FS::SelfService qw( login customer_info invoice payment_info + process_payment ); $template_dir = '.'; @@ -54,7 +55,7 @@ if ( $cgi->param('session') eq 'login' ) { $session_id = $cgi->param('session'); $cgi->param('action') =~ - /^(myaccount|view_invoice|make_payment|process_payment)$/ + /^(myaccount|view_invoice|make_payment|do_payment)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -94,7 +95,7 @@ sub make_payment { payment_info( 'session_id' => $session_id ); } -sub process_payment { +sub do_payment { use Business::CreditCard; -- cgit v1.2.1 From e354694764fb1442b6bc74a63189f094c51f1a89 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 20 May 2003 05:43:47 +0000 Subject: working self-service self-payments! --- FS/FS/ClientAPI/MyAccount.pm | 4 ++-- FS/FS/cust_main.pm | 20 +++++++++++++++----- fs_selfservice/FS-SelfService/cgi/make_payment.html | 2 +- .../FS-SelfService/cgi/payment_results.html | 18 ++++++++++++++++++ .../FS-SelfService/cgi/process_payment.html | 18 ------------------ fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 4 ++-- 6 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 fs_selfservice/FS-SelfService/cgi/payment_results.html delete mode 100644 fs_selfservice/FS-SelfService/cgi/process_payment.html diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 6e9bf23a9..e12e93b12 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -193,7 +193,7 @@ sub process_payment { my $new = new FS::cust_main { $cust_main->hash }; $new->set( $_ => $p->{$_} ) foreach qw( payname address1 address2 city state zip payinfo ); - $new->set( 'paydate' => $p->{'month'}. '-'. $p->{'year'} ); + $new->set( 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01' ); $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); my $error = $new->replace($cust_main); return { 'error' => $error } if $error; @@ -201,7 +201,7 @@ sub process_payment { } my $error = $cust_main->realtime_bop( 'CC', $p->{'amount'}, quiet=>1, - 'paydate' => $p->{'month'}. '-'. $p->{'year'}, + 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01', map { $_ => $p->{$_} } qw( payname address1 address2 city state zip payinfo ) ); diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 09c56474c..7e2ff388e 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -33,7 +33,7 @@ use FS::Msgcat qw(gettext); @ISA = qw( FS::Record ); -$Debug = 0; +$Debug = 1; #$Debug = 1; $import = 0; @@ -761,10 +761,15 @@ sub check { unless $self->payby =~ /^(BILL|PREPAY|CHEK|LECB)$/; $self->paydate(''); } else { - $self->paydate =~ /^(\d{1,2})[\/\-](\d{2}(\d{2})?)$/ - or return "Illegal expiration date: ". $self->paydate; - my $y = length($2) == 4 ? $2 : "20$2"; - $self->paydate("$y-$1-01"); + my( $m, $y ); + if ( $self->paydate =~ /^(\d{1,2})[\/\-](\d{2}(\d{2})?)$/ ) { + ( $m, $y ) = ( $1, length($2) == 4 ? $2 : "20$2" ); + } elsif ( $self->paydate =~ /^(20)?(\d{2})[\/\-](\d{2})[\/\-]\d+$/ ) { + ( $m, $y ) = ( $3, "20$2" ); + } else { + return "Illegal expiration date: ". $self->paydate; + } + $self->paydate("$y-$m-01"); my($nowm,$nowy)=(localtime(time))[4,5]; $nowm++; $nowy+=1900; return gettext('expired_card') if !$import && ( $y<$nowy || ( $y==$nowy && $1<$nowm ) ); @@ -1438,6 +1443,11 @@ I can be set true to surpress email decline notices. sub realtime_bop { my( $self, $method, $amount, %options ) = @_; + if ( $Debug ) { + warn "$self $method $amount\n"; + warn " $_ => $options{$_}\n" foreach keys %options; + } + $options{'description'} ||= 'Internet services'; #pre-requisites diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html index 1d860f08a..a1cda6d49 100644 --- a/fs_selfservice/FS-SelfService/cgi/make_payment.html +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -8,7 +8,7 @@ Make a payment

- + diff --git a/fs_selfservice/FS-SelfService/cgi/payment_results.html b/fs_selfservice/FS-SelfService/cgi/payment_results.html new file mode 100644 index 000000000..92c8cf51b --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/payment_results.html @@ -0,0 +1,18 @@ +MyAccount +MyAccount

+<%= $url = "$selfurl?session=$session_id;action="; ''; %> +
Amount Due
+MyAccount
+ +
+Payment results

+<%= if ( $error ) { + $OUT .= qq!Error processing your payment: $error!; +} else { + $OUT .= 'Your payment was processed sucessfully. Thank you.'; +} %> +
+
+powered by freeside + + diff --git a/fs_selfservice/FS-SelfService/cgi/process_payment.html b/fs_selfservice/FS-SelfService/cgi/process_payment.html deleted file mode 100644 index e4946dc8f..000000000 --- a/fs_selfservice/FS-SelfService/cgi/process_payment.html +++ /dev/null @@ -1,18 +0,0 @@ -MyAccount -MyAccount

-<%= $url = "$selfurl?session=$session_id;action="; ''; %> -
-MyAccount
- -
-Payment results

-<%= if ( $error ) { - $OUT .= qq!Error processing your payment: $error -
-
-powered by freeside - - diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 456d2dde2..6d6716ddc 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -55,7 +55,7 @@ if ( $cgi->param('session') eq 'login' ) { $session_id = $cgi->param('session'); $cgi->param('action') =~ - /^(myaccount|view_invoice|make_payment|do_payment)$/ + /^(myaccount|view_invoice|make_payment|payment_results)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -95,7 +95,7 @@ sub make_payment { payment_info( 'session_id' => $session_id ); } -sub do_payment { +sub payment_results { use Business::CreditCard; -- cgit v1.2.1 From e58e375c39f08c28239ecc173cc3fbf3f5ca5b92 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 30 May 2003 08:45:33 +0000 Subject: doc --- httemplate/docs/ssh.html | 1 + 1 file changed, 1 insertion(+) diff --git a/httemplate/docs/ssh.html b/httemplate/docs/ssh.html index 9716f1e86..d2c501e35 100755 --- a/httemplate/docs/ssh.html +++ b/httemplate/docs/ssh.html @@ -9,6 +9,7 @@
  • Append the newly-created identity.pub file to ~root/.ssh/authorized_keys (or the appopriate ~username/.ssh/authorized_keys) on the remote machine(s).
  • Some new SSH v2 implementation accept v2 style keys only. Use the -t option to ssh-keygen, and append the created id_dsa.pub or id_rsa.pub to ~root/.ssh/authorized_keys2 (or the appopriate ~username/.ssh/authorized_keys) on the remote machine(s).
  • You may need to set PermitRootLogin without-password (meaning with keys only) in your sshd_config file on the remote machine(s). +
  • You may want to set ForwardX11 = no in ~root/.ssh/config to prevent spurious errors if your distribution turns on X11 forwarding by default. -- cgit v1.2.1 From 0ef12cb47ee609b04f54fb52e448c73ed3869ec1 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 30 May 2003 09:22:53 +0000 Subject: sqlradius exports include "op" field --- FS/FS/part_export/sqlradius.pm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/FS/FS/part_export/sqlradius.pm b/FS/FS/part_export/sqlradius.pm index ccf9a7687..60450ee63 100644 --- a/FS/FS/part_export/sqlradius.pm +++ b/FS/FS/part_export/sqlradius.pm @@ -187,11 +187,15 @@ sub sqlradius_insert { #subroutine, not method } else { my $i_sth = $dbh->prepare( - "INSERT INTO rad$table ( UserName, Attribute, Value ) ". - "VALUES ( ?, ?, ? )" + "INSERT INTO rad$table ( UserName, Attribute, op, Value ) ". + "VALUES ( ?, ?, ?, ? )" ) or die $dbh->errstr; - $i_sth->execute( $username, $attribute, $attributes{$attribute} ) - or die $i_sth->errstr; + $i_sth->execute( + $username, + $attribute, + ( $attribute =~ /Password/i ? '==' : ':=' ), + $attributes{$attribute}, + ) or die $i_sth->errstr; } -- cgit v1.2.1 From 10435c0296ed4239e451503c60aa3412e58ef517 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 30 May 2003 09:40:54 +0000 Subject: force inclusion of httemplate/docs/man hierarchy --- httemplate/docs/man/FS/part_export/.cvs_is_on_crack | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 httemplate/docs/man/FS/part_export/.cvs_is_on_crack diff --git a/httemplate/docs/man/FS/part_export/.cvs_is_on_crack b/httemplate/docs/man/FS/part_export/.cvs_is_on_crack new file mode 100644 index 000000000..e69de29bb -- cgit v1.2.1 From 745aca307ef43c0c9bd5d8ee78464f624acb7b3f Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 2 Jun 2003 12:22:44 +0000 Subject: add last_bill field to manpage --- FS/FS/cust_pkg.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 9ab269503..9f20603bd 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -100,6 +100,8 @@ inherits from FS::Record. The following fields are currently supported: =item bill - date (next bill date) +=item last_bill - last bill date + =item susp - date =item expire - date -- cgit v1.2.1 From 4896baa43b4891f43810f618cec51156aabbf7ec Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 2 Jun 2003 14:51:30 +0000 Subject: UI nit --- httemplate/view/cust_main.cgi | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 3934a3dcb..3a0605635 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -20,7 +20,7 @@ print < END @@ -430,7 +430,7 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { if ( $pkg->{cancel} ) { #status: cancelled - print 'Cancelled '. + print 'Cancelled '. ''. pkg_datestr($pkg,'cancel'). ''; unless ( $pkg->{setup} ) { print 'Never billed'; @@ -848,9 +848,12 @@ sub svc_label_link { sub svc_provision_link { my ($pkg, $svcpart) = (shift,shift) or return ''; + ( my $svc_nbsp = $svcpart->{svc} ) =~ s/\s+/ /g; return qq!! . - qq!Provision $svcpart->{svc} (! . ($svcpart->{quantity} - $svcpart->{count}) . qq!)!; + "Provision $svc_nbsp (". + ($svcpart->{quantity} - $svcpart->{count}). + ')'; } sub svc_unprovision_link { -- cgit v1.2.1 From b5e03a09e99ede045b0e3be87085c628d422e3ea Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 3 Jun 2003 05:49:16 +0000 Subject: router.svcnum nullability fix --- FS/bin/freeside-setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index 518a2ad42..a1fab5fa0 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -1031,7 +1031,7 @@ sub tables_hash_hack { 'columns' => [ 'routernum', 'serial', '', '', 'routername', 'varchar', '', $char_d, - 'svcnum', 'int', '0', '', + 'svcnum', 'int', 'NULL', '', ], 'primary_key' => 'routernum', 'unique' => [], -- cgit v1.2.1 From a60b96753d5c615914fa766b2b0fe8bd2f86c337 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 3 Jun 2003 06:09:52 +0000 Subject: use serial for primary keys in new tables too --- FS/bin/freeside-setup | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index a1fab5fa0..d2a98dd0c 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -1031,7 +1031,7 @@ sub tables_hash_hack { 'columns' => [ 'routernum', 'serial', '', '', 'routername', 'varchar', '', $char_d, - 'svcnum', 'int', 'NULL', '', + 'svcnum', 'int', '0', '', ], 'primary_key' => 'routernum', 'unique' => [], @@ -1074,7 +1074,7 @@ sub tables_hash_hack { 'addr_block' => { 'columns' => [ - 'blocknum', 'int', '', '', + 'blocknum', 'serial', '', '', 'routernum', 'int', '', '', 'ip_gateway', 'varchar', '', 15, 'ip_netmask', 'int', '', '', @@ -1086,7 +1086,7 @@ sub tables_hash_hack { 'part_sb_field' => { 'columns' => [ - 'sbfieldpart', 'int', '', '', + 'sbfieldpart', 'serial', '', '', 'svcpart', 'int', '', '', 'name', 'varchar', '', $char_d, 'length', 'int', '', '', -- cgit v1.2.1 From dcf30bca55c04f22b752deab57a70ee710f2fd32 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 3 Jun 2003 06:10:07 +0000 Subject: slightly better upgrade docs --- httemplate/docs/upgrade10.html | 107 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index 6c4fe0c37..ce1eed416 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -1,5 +1,5 @@
    -this is very incomplete
    +this is incomplete
     
     install NetAddr::IP and Chart
     
    @@ -12,6 +12,111 @@ CREATE TABLE cust_bill_pkg_detail (
     );
     CREATE INDEX cust_bill_pkg_detail1 ON cust_bill_pkg_detail ( pkgnum, invnum );
     
    +CREATE TABLE router (
    +  routernum serial,
    +  routername varchar(80),
    +  svcnum int,
    +  PRIMARY KEY (routernum)
    +);
    +
    +CREATE TABLE part_svc_router (
    +  svcpart int NOT NULL,
    +  routernum int NOT NULL
    +);
    +
    +CREATE TABLE part_router_field (
    +  routerfieldpart serial,
    +  name varchar(80),
    +  length int NOT NULL,
    +  check_block text,
    +  list_source text,
    +  PRIMARY KEY (routerfieldpart)
    +);
    +
    +CREATE TABLE router_field (
    +  routerfieldpart int NOT NULL,
    +  routernum int NOT NULL,
    +  value varchar(128)
    +);
    +CREATE UNIQUE INDEX router_field1 ON router_field ( routerfieldpart, routernum );
    +
    +CREATE TABLE addr_block (
    +  blocknum serial,
    +  routernum int NOT NULL,
    +  ip_gateway varchar(15) NOT NULL,
    +  ip_netmask int NOT NULL,
    +  PRIMARY KEY (blocknum)
    +);
    +CREATE UNIQUE INDEX addr_block1 ON addr_block ( blocknum, routernum );
    +
    +CREATE TABLE part_sb_field (
    +  sbfieldpart serial,
    +  svcpart int NOT NULL,
    +  name varchar(80) NOT NULL,
    +  length int NOT NULL,
    +  check_block text NULL,
    +  list_source text NULL,
    +  PRIMARY key (sbfieldpart)
    +);
    +CREATE UNIQUE INDEX part_sb_field1 ON part_sb_field ( sbfieldpart, svcpart );
    +
    +CREATE TABLE sb_field (
    +  sbfieldpart int NOT NULL,
    +  svcnum int NOT NULL,
    +  value varchar(128)
    +)
    +CREATE UNIQUE INDEX sb_field1 ON sb_field ( sbfieldpart, svcnum );
    +
    +CREATE TABLE svc_broadband (
    +  svcnum int NOT NULL,
    +  blocknum int NOT NULL,
    +  speed_up int NOT NULL,
    +  speed_down int NOT NULL,
    +  ip_addr varchar(15),
    +  PRIMARY KEY (svcnum)
    +
    +DELETE INDEX cust_bill_pkg1;
    +
    +ALTER TABLE cust_bill_pkg ADD itemdesc varchar(80) NULL;
    +ALTER TABLE h_cust_bill_pkg ADD itemdesc varchar(80) NULL;
    +ALTER TABLE cust_main_county ADD taxname varchar(80) NULL;
    +ALTER TABLE h_cust_main_county ADD taxname varchar(80) NULL;
    +ALTER TABLE cust_pkg ADD last_bill int NULL;
    +ALTER TABLE h_cust_pkg ADD last_bill int NULL;
    +
    +DROP TABLE svc_acct_sm
    +DROP TABLE h_svc_acct_sm
    +
    +dump database, edit:
    +- cust_main: increase otaker from 8 to 32
    +- cust_main: change ss from char(11) to varchar(11)
    +- cust_credit: increase otaker from 8 to 32
    +- cust_pkg: increase otaker from 8 to 32
    +- cust_refund: increase otaker from 8 to 32
    +- domain_record: increase reczone from 80 to 255
    +- domain_record: change rectype from char to varchar
    +- domain_record: increase recdata from 80 to 255
    +then reload
    +
     create all of the new broadband tables
     
    +optionally:
    +
    +  CREATE INDEX cust_main6 ON cust_main ( daytime );
    +  CREATE INDEX cust_main7 ON cust_main ( night );
    +  CREATE INDEX cust_main8 ON cust_main ( fax );
    +  CREATE INDEX cust_main9 ON cust_main ( ship_daytime );
    +  CREATE INDEX cust_main10 ON cust_main ( ship_night );
    +  CREATE INDEX cust_main11 ON cust_main ( ship_fax );
    +
    +  serial columns
    +
    +mandatory again:
    +
    +dbdef-create username
    +create-history-tables username cust_bill_pkg_detail router part_svc_router part_router_field router_field addr_block part_sb_field sb_field svc_broadband
    +dbdef-create username
    +
    +
    +
     
    -- cgit v1.2.1 From a618738fb37939ef95ac70e8b90fe298450c215b Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 3 Jun 2003 07:54:57 +0000 Subject: upgrade docs --- httemplate/docs/upgrade10.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index ce1eed416..1035510db 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -1,7 +1,9 @@
     this is incomplete
     
    -install NetAddr::IP and Chart
    +install DBIx::DBSchema 0.21
    +
    +install NetAddr::IP and Chart::Base
     
     CREATE TABLE cust_bill_pkg_detail (
       detailnum serial,
    @@ -64,7 +66,7 @@ CREATE TABLE sb_field (
       sbfieldpart int NOT NULL,
       svcnum int NOT NULL,
       value varchar(128)
    -)
    +);
     CREATE UNIQUE INDEX sb_field1 ON sb_field ( sbfieldpart, svcnum );
     
     CREATE TABLE svc_broadband (
    @@ -74,6 +76,7 @@ CREATE TABLE svc_broadband (
       speed_down int NOT NULL,
       ip_addr varchar(15),
       PRIMARY KEY (svcnum)
    +);
     
     DELETE INDEX cust_bill_pkg1;
     
    @@ -84,9 +87,6 @@ ALTER TABLE h_cust_main_county ADD taxname varchar(80) NULL;
     ALTER TABLE cust_pkg ADD last_bill int NULL;
     ALTER TABLE h_cust_pkg ADD last_bill int NULL;
     
    -DROP TABLE svc_acct_sm
    -DROP TABLE h_svc_acct_sm
    -
     dump database, edit:
     - cust_main: increase otaker from 8 to 32
     - cust_main: change ss from char(11) to varchar(11)
    @@ -98,8 +98,6 @@ dump database, edit:
     - domain_record: increase recdata from 80 to 255
     then reload
     
    -create all of the new broadband tables
    -
     optionally:
     
       CREATE INDEX cust_main6 ON cust_main ( daytime );
    -- 
    cgit v1.2.1
    
    
    From 306bbf9006e7867ec50342d6f931ab25eee01b2d Mon Sep 17 00:00:00 2001
    From: ivan 
    Date: Tue, 3 Jun 2003 09:34:09 +0000
    Subject: removing (very) deprecated import
    
    ---
     bin/svc_acct_sm.import | 262 -------------------------------------------------
     1 file changed, 262 deletions(-)
     delete mode 100755 bin/svc_acct_sm.import
    
    diff --git a/bin/svc_acct_sm.import b/bin/svc_acct_sm.import
    deleted file mode 100755
    index b668405f5..000000000
    --- a/bin/svc_acct_sm.import
    +++ /dev/null
    @@ -1,262 +0,0 @@
    -#!/usr/bin/perl -Tw
    -#
    -# $Id: svc_acct_sm.import,v 1.10 2001-08-21 02:43:18 ivan Exp $
    -
    -use strict;
    -use vars qw(%d_part_svc %m_part_svc);
    -use Term::Query qw(query);
    -use Net::SCP qw(iscp);
    -use FS::UID qw(adminsuidsetup datasrc);
    -use FS::Record qw(qsearch qsearchs);
    -use FS::svc_acct_sm;
    -use FS::svc_domain;
    -use FS::svc_acct;
    -use FS::part_svc;
    -
    -my $user = shift or die &usage;
    -adminsuidsetup $user;
    -
    -my($spooldir)="/usr/local/etc/freeside/export.". datasrc;
    -
    -my(%mta) = (
    -  1 => "qmail",
    -  2 => "sendmail",
    -);
    -
    -###
    -
    -%d_part_svc =
    -  map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_domain'});
    -%m_part_svc =
    -  map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_acct_sm'});
    -
    -die "No services with svcdb svc_domain!\n" unless %d_part_svc;
    -die "No services with svcdb svc_svc_acct_sm!\n" unless %m_part_svc;
    -
    -print "\n\n", 
    -      ( join "\n", map "$_: ".$d_part_svc{$_}->svc, sort keys %d_part_svc ),
    -      "\n\n";
    -$^W=0; #Term::Query isn't -w-safe
    -my $domain_svcpart = 
    -  query "Enter part number for domains: ", 'irk', [ keys %d_part_svc ];
    -$^W=1;
    -
    -print "\n\n", 
    -      ( join "\n", map "$_: ".$m_part_svc{$_}->svc, sort keys %m_part_svc ),
    -      "\n\n";
    -$^W=0; #Term::Query isn't -w-safe
    -my $mailalias_svcpart = 
    -  query "Enter part number for mail aliases: ", 'irk', [ keys %m_part_svc ];
    -$^W=1;
    -
    -print "\n\n", <) {
    -  next if /^(#|$)/;
    -  next if $mta{$mta} eq 'sendmail' && /^\s*$/; #blank lines
    -  /^\.?([\w\-\.]+)$/
    -    #or do { warn "Strange rcpthosts/sendmail.cw line: $_"; next; };
    -    or die "Strange rcpthosts/sendmail.cw line: $_";
    -  my $domain = $1;
    -  my($svc_domain);
    -  unless ( $svc_domain = qsearchs('svc_domain', {'domain'=>$domain} ) ) {
    -    $svc_domain = new FS::svc_domain ({
    -      'domain'  => $domain,
    -      'svcpart' => $domain_svcpart,
    -      'action'  => 'N',
    -    });
    -    my $error = $svc_domain->insert;
    -    #warn $error if $error;
    -    die $error if $error;
    -  }
    -  $svcnum{$domain}=$svc_domain->svcnum;
    -}
    -close RCPTHOSTS; 
    -
    -#these two loops have enough similar parts they should probably be merged
    -if ( $mta{$mta} eq "qmail" ) {
    -
    -  open(VD_FIX,">$spooldir/virtualdomains.FIX");
    -  print VD_FIX "#!/usr/bin/perl\n";
    -
    -  open(VIRTUALDOMAINS,"<$spooldir/virtualdomains.import")
    -    or die "Can't open $spooldir/virtualdomains.import: $!";
    -  while () {
    -    next if /^#/;
    -    /^\.?([\w\-\.]+):(\w+)(\-([\w\-\.]+))?$/
    -      #or do { warn "Strange virtualdomains line: $_"; next; };
    -      or die "Strange virtualdomains line: $_";
    -    my($domain,$username,$dash_ext,$extension)=($1,$2,$3,$4);
    -    $dash_ext ||= '';
    -    $extension ||= '';
    -    my($svc_acct)=qsearchs('svc_acct',{'username'=>$username});
    -    unless ( $svc_acct ) {
    -      #warn "Unknown user $username in virtualdomains; skipping\n";
    -      #die "Unknown user $username in virtualdomains; skipping\n";
    -      next;
    -    }
    -    if ( $domain ne $extension ) {
    -      #warn "virtualdomains line $domain:$username$dash_ext changed to $domain:$username-$domain\n";
    -      my($dir)=$svc_acct->dir;
    -      my($qdomain)=$domain;
    -      $qdomain =~ s/\./:/g; #see manpage for 'dot-qmail': EXTENSION ADDRESSES
    -      #example to move .qmail files for virtual domains to their new location 
    -      #dry run
    -      #issh("root\@$shellmachine",'perl -e \'foreach $a (<'. $dir. '/.qmail'. $dash_ext. '-*>) { $old=$a; $a =~ s/\\.qmail'. $dash_ext. '\\-/\\.qmail\\-'. $qdomain. '\\-/; print " $old -> $a\n"; }\'');
    -      #the real thing
    -      #issh("root\@$shellmachine",'perl -e \'foreach $a (<'. $dir. '/.qmail'. $dash_ext. '-*>) { $old=$a; $a =~ s/\\.qmail'. $dash_ext. '\\-/\\.qmail\\-'. $qdomain. '\\-/; rename $old, $a; }\'');
    -      print VD_FIX <) {
    -  \$old = \$file;
    -  \$file =~ s/\.qmail$dash_ext\-/\.qmail\-$qdomain\-/;
    -  rename \$old, \$file;
    -}
    -END
    -    }
    -
    -    unless ( exists $svcnum{$domain} ) {
    -      my($svc_domain) = new FS::svc_domain ({
    -        'domain'  => $domain,
    -        'svcpart' => $domain_svcpart,
    -        'action'  => 'N',
    -      });
    -      my $error = $svc_domain->insert;
    -      #warn $error if $error;
    -      die $error if $error;
    -      $svcnum{$domain}=$svc_domain->svcnum;
    -    }
    -
    -    my($svc_acct_sm)=new FS::svc_acct_sm ({
    -      'domsvc'  => $svcnum{$domain},
    -      'domuid'  => $svc_acct->uid,
    -      'domuser' => '*',
    -      'svcpart' => $mailalias_svcpart,
    -    });
    -    my($error)='';
    -    $error=$svc_acct_sm->insert;
    -    #warn $error if $error;
    -    die $error, ", domain $domain" if $error;
    -  }
    -  close VIRTUALDOMAINS;
    -  close VD_FIX;
    -
    -} elsif ( $mta{$mta} eq "sendmail" ) {
    -
    -  open(VIRTUSERTABLE,"<$spooldir/virtusertable.import")
    -    or die "Can't open $spooldir/virtusertable.import: $!";
    -  while () {
    -    next if /^#/; #comments?
    -    next if /^\s*$/; #blank lines
    -    /^([\w\-\.]+)?\@([\w\-\.]+)\t+([\w\-\.]+)$/
    -      #or do { warn "Strange virtusertable line: $_"; next; };
    -      or die "Strange virtusertable line: $_";
    -    my($domuser,$domain,$username)=($1,$2,$3);
    -    my($svc_acct)=qsearchs('svc_acct',{'username'=>$username});
    -    unless ( $svc_acct ) {
    -      #warn "Unknown user $username in virtusertable";
    -      die "Unknown user $username in virtusertable";
    -      next;
    -    }
    -    my($svc_acct_sm)=new FS::svc_acct_sm ({
    -      'domsvc'  => $svcnum{$domain},
    -      'domuid'  => $svc_acct->uid,
    -      'domuser' => $domuser || '*',
    -      'svcpart' => $mailalias_svcpart,
    -    });
    -    my($error)='';
    -    $error=$svc_acct_sm->insert;
    -    #warn $error if $error;
    -    die $error if $error;
    -  }
    -  close VIRTUSERTABLE;
    -
    -} else {
    -  die "Unknown MTA!\n";
    -}
    -
    -#open(RECIPIENTMAP,"<$spooldir/recipientmap.import");
    -#close RECIPIENTMAP;
    -
    -print "\n\n", <
    Date: Tue, 3 Jun 2003 12:40:59 +0000
    Subject: 1.5.0pre2 (too late, hehe)
    
    ---
     Makefile | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/Makefile b/Makefile
    index 433563e36..eb762e157 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -58,8 +58,8 @@ SELFSERVICE_MACHINE = localhost
     #not changable yet
     FREESIDE_CONF = /usr/local/etc/freeside
     
    -VERSION=1.5.0pre1
    -TAG=freeside_1_5_0pre1
    +VERSION=1.5.0pre2
    +TAG=freeside_1_5_0pre2
     
     help:
     	@echo "supported targets: aspdocs masondocs alldocs docs install-docs"
    -- 
    cgit v1.2.1
    
    
    From 978b435880e71f6a4765525ea9797b7dc65bd625 Mon Sep 17 00:00:00 2001
    From: ivan 
    Date: Tue, 3 Jun 2003 12:41:50 +0000
    Subject: minor update to cp export - eliminate redundant "host" parameter
    
    ---
     FS/FS/part_export.pm    | 1 -
     FS/FS/part_export/cp.pm | 2 +-
     2 files changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
    index 9a1b9d864..06fab6ad1 100644
    --- a/FS/FS/part_export.pm
    +++ b/FS/FS/part_export.pm
    @@ -692,7 +692,6 @@ tie my %cyrus_options, 'Tie::IxHash',
     ;
     
     tie my %cp_options, 'Tie::IxHash',
    -  'host'      => { label=>'Hostname' },
       'port'      => { label=>'Port number' },
       'username'  => { label=>'Username' },
       'password'  => { label=>'Password' },
    diff --git a/FS/FS/part_export/cp.pm b/FS/FS/part_export/cp.pm
    index d998c1d95..c37dc3b98 100644
    --- a/FS/FS/part_export/cp.pm
    +++ b/FS/FS/part_export/cp.pm
    @@ -42,7 +42,7 @@ sub cp_queue {
         'job'    => 'FS::part_export::cp::cp_command',
       };
       $queue->insert(
    -    $self->option('host'),
    +    $self->machine,
         $self->option('port'),
         $self->option('username'),
         $self->option('password'),
    -- 
    cgit v1.2.1
    
    
    From 43b604bc300b40f8fad5191b805952dd543251f7 Mon Sep 17 00:00:00 2001
    From: ivan 
    Date: Tue, 3 Jun 2003 13:53:28 +0000
    Subject: fix provision links
    
    ---
     httemplate/view/cust_main.cgi | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
    index 3a0605635..4fe60fe79 100755
    --- a/httemplate/view/cust_main.cgi
    +++ b/httemplate/view/cust_main.cgi
    @@ -849,7 +849,7 @@ sub svc_label_link {
     sub svc_provision_link {
       my ($pkg, $svcpart) = (shift,shift) or return '';
       ( my $svc_nbsp = $svcpart->{svc} ) =~ s/\s+/ /g;
    -  return qq!! .
              "Provision $svc_nbsp (".
              ($svcpart->{quantity} - $svcpart->{count}).
    -- 
    cgit v1.2.1
    
    
    From 4bf86e5f7f44e77159564804d09e0938a8edc905 Mon Sep 17 00:00:00 2001
    From: ivan 
    Date: Wed, 4 Jun 2003 12:44:57 +0000
    Subject: fix last bill label
    
    ---
     httemplate/search/cust_pkg.cgi | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi
    index 538edf3f1..12179eaca 100755
    --- a/httemplate/search/cust_pkg.cgi
    +++ b/httemplate/search/cust_pkg.cgi
    @@ -196,7 +196,7 @@ if ( scalar(@cust_pkg) == 1 ) {
             Setup
     END
     
    -  print 'Next
    bill
    ' + print 'Last
    bill
    ' if defined dbdef->table('cust_pkg')->column('last_bill'); print < Date: Wed, 4 Jun 2003 16:14:38 +0000 Subject: allow empty slipip's --- FS/FS/svc_acct.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 497e59c94..282ef5aab 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -783,12 +783,14 @@ sub check { $recref->{quota} = $1; unless ( $part_svc->part_svc_column('slipip')->columnflag eq 'F' ) { - unless ( $recref->{slipip} eq '0e0' ) { + if ( $recref->{slipip} eq '' ) { + $recref->{slipip} = ''; + } elsif ( $recref->{slipip} eq '0e0' ) { + $recref->{slipip} = '0e0'; + } else { $recref->{slipip} =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/ or return "Illegal slipip: ". $self->slipip; $recref->{slipip} = $1; - } else { - $recref->{slipip} = '0e0'; } } -- cgit v1.2.1 From 9bb4c3a8b4cc5313049ad043d2798e37ee210ae6 Mon Sep 17 00:00:00 2001 From: khoff Date: Thu, 5 Jun 2003 00:22:48 +0000 Subject: order/cancel packages rewritten --- FS/FS/cust_pkg.pm | 231 +++++++++++++++++++++++------------------------------- 1 file changed, 96 insertions(+), 135 deletions(-) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 9f20603bd..a423c5518 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -605,6 +605,61 @@ sub attribute_since_sqlradacct { } +=item transfer DEST_PKGNUM + +Transfers as many services as possible from this package to another package. +The destination package must already exist. Services are moved only if +the destination allows services with the correct I (not svcdb). +Any services that can't be moved remain in the original package. + +Returns an error, if there is one; otherwise, returns the number of services +that couldn't be moved. + +=cut + +sub transfer { + my ($self, $dest_pkgnum) = @_; + + my $remaining = 0; + my $dest; + my %target; + my $pkg_svc; + + if (ref ($dest_pkgnum) eq 'FS::cust_pkg') { + $dest = $dest_pkgnum; + $dest_pkgnum = $dest->pkgnum; + } else { + $dest = qsearchs('cust_pkg', { pkgnum => $dest_pkgnum }); + } + + return ('Package does not exist: '.$dest_pkgnum) unless $dest; + + foreach $pkg_svc (qsearch('pkg_svc', { pkgpart => $dest->pkgpart })) { + $target{$pkg_svc->svcpart} = $pkg_svc->quantity; + } + + my $cust_svc; + + foreach $cust_svc ($dest->cust_svc) { + $target{$cust_svc->svcpart}--; + } + + foreach $cust_svc ($self->cust_svc) { + if($target{$cust_svc->svcpart} > 0) { + $target{$cust_svc->svcpart}--; + my $new = new FS::cust_svc { + svcnum => $cust_svc->svcnum, + svcpart => $cust_svc->svcpart, + pkgnum => $dest_pkgnum }; + my $error = $new->replace($cust_svc); + return $error if $error; + } else { + $remaining++ + } + } + return $remaining; +} + =back =head1 SUBROUTINES @@ -631,156 +686,62 @@ newly-created cust_pkg objects. =cut sub order { - my($custnum, $pkgparts, $remove_pkgnums, $return_cust_pkg) = @_; - $remove_pkgnums = [] unless defined($remove_pkgnums); + # Rewritten to make use of the transfer() method, and in general + # to not suck so badly. + + my ($custnum, $pkgparts, $remove_pkgnum, $return_cust_pkg) = @_; + + # Transactionize this whole mess my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; - # generate %part_pkg - # $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart - # - my($cust_main)=qsearchs('cust_main',{'custnum'=>$custnum}); - my($agent)=qsearchs('agent',{'agentnum'=> $cust_main->agentnum }); - my %part_pkg = %{ $agent->pkgpart_hashref }; - - my(%svcnum); - # generate %svcnum - # for those packages being removed: - #@{ $svcnum{$svcpart} } goes from a svcpart to a list of FS::cust_svc objects - my($pkgnum); - foreach $pkgnum ( @{$remove_pkgnums} ) { - foreach my $cust_svc (qsearch('cust_svc',{'pkgnum'=>$pkgnum})) { - push @{ $svcnum{$cust_svc->getfield('svcpart')} }, $cust_svc; - } - } - - my @cust_svc; - #generate @cust_svc - # for those packages the customer is purchasing: - # @{$pkgparts} is a list of said packages, by pkgpart - # @cust_svc is a corresponding list of lists of FS::Record objects - foreach my $pkgpart ( @{$pkgparts} ) { - unless ( $part_pkg{$pkgpart} ) { + my $error; + my $cust_main = qsearchs('cust_main', { custnum => $custnum }); + return "Customer not found: $custnum" unless $cust_main; + + # Create the new packages. + my $cust_pkg; + foreach (@$pkgparts) { + $cust_pkg = new FS::cust_pkg { custnum => $custnum, + pkgpart => $_ }; + $error = $cust_pkg->insert; + if ($error) { $dbh->rollback if $oldAutoCommit; - return "Customer not permitted to purchase pkgpart $pkgpart!"; + return $error; } - push @cust_svc, [ - map { - ( $svcnum{$_} && @{ $svcnum{$_} } ) ? shift @{ $svcnum{$_} } : (); - } map { $_->svcpart } - qsearch('pkg_svc', { pkgpart => $pkgpart, - quantity => { op=>'>', value=>'0', } } ) - ]; + push @$return_cust_pkg, $cust_pkg; } - - #special-case until this can be handled better - # move services to new svcparts - even if the svcparts don't match (svcdb - # needs to...) - # looks like they're moved in no particular order, ewwwwwwww - # and looks like just one of each svcpart can be moved... o well - - #start with still-leftover services - #foreach my $svcpart ( grep { scalar(@{ $svcnum{$_} }) } keys %svcnum ) { - foreach my $svcpart ( keys %svcnum ) { - next unless @{ $svcnum{$svcpart} }; - - my $svcdb = $svcnum{$svcpart}->[0]->part_svc->svcdb; - - #find an empty place to put one - my $i = 0; - foreach my $pkgpart ( @{$pkgparts} ) { - my @pkg_svc = - qsearch('pkg_svc', { pkgpart => $pkgpart, - quantity => { op=>'>', value=>'0', } } ); - #my @pkg_svc = - # grep { $_->quantity > 0 } qsearch('pkg_svc', { pkgpart=>$pkgpart } ); - if ( ! @{$cust_svc[$i]} #find an empty place to put them with - && grep { $svcdb eq $_->part_svc->svcdb } #with appropriate svcdb - @pkg_svc - ) { - my $new_svcpart = - ( grep { $svcdb eq $_->part_svc->svcdb } @pkg_svc )[0]->svcpart; - my $cust_svc = shift @{$svcnum{$svcpart}}; - $cust_svc->svcpart($new_svcpart); - #warn "changing from $svcpart to $new_svcpart!!!\n"; - $cust_svc[$i] = [ $cust_svc ]; + # $return_cust_pkg now contains refs to all of the newly + # created packages. + + # Transfer services and cancel old packages. + foreach my $old_pkgnum (@$remove_pkgnum) { + my $old_pkg = qsearchs ('cust_pkg', { pkgnum => $old_pkgnum }); + foreach my $new_pkg (@$return_cust_pkg) { + $error = $old_pkg->transfer($new_pkg); + if ($error and $error == 0) { + # $old_pkg->transfer failed. + $dbh->rollback if $oldAutoCommit; + return $error; } - $i++; } - - } - - #check for leftover services - foreach (keys %svcnum) { - next unless @{ $svcnum{$_} }; - $dbh->rollback if $oldAutoCommit; - return "Leftover services, svcpart $_: svcnum ". - join(', ', map { $_->svcnum } @{ $svcnum{$_} } ); - } - - #no leftover services, let's make changes. - - local $SIG{HUP} = 'IGNORE'; - local $SIG{INT} = 'IGNORE'; - local $SIG{QUIT} = 'IGNORE'; - local $SIG{TERM} = 'IGNORE'; - local $SIG{TSTP} = 'IGNORE'; - local $SIG{PIPE} = 'IGNORE'; - - #first cancel old packages - foreach my $pkgnum ( @{$remove_pkgnums} ) { - my($old) = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); - unless ( $old ) { + if ($error > 0) { + # Transfers were successful, but we went through all of the + # new packages and still had services left on the old package. + # We can't cancel the package under the circumstances, so abort. $dbh->rollback if $oldAutoCommit; - return "Package $pkgnum not found to remove!"; + return "Unable to transfer all services from package ".$old_pkg->pkgnum; } - my(%hash) = $old->hash; - $hash{'cancel'}=time; - my($new) = new FS::cust_pkg ( \%hash ); - my($error)=$new->replace($old); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "Couldn't update package $pkgnum: $error"; + $error = $old_pkg->cancel; + if ($error) { + $dbh->rollback; + return $error; } } - - #now add new packages, changing cust_svc records if necessary - my $pkgpart; - while ($pkgpart=shift @{$pkgparts} ) { - - my $new = new FS::cust_pkg { - 'custnum' => $custnum, - 'pkgpart' => $pkgpart, - }; - my $error = $new->insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "Couldn't insert new cust_pkg record: $error"; - } - push @{$return_cust_pkg}, $new if $return_cust_pkg; - my $pkgnum = $new->pkgnum; - - foreach my $cust_svc ( @{ shift @cust_svc } ) { - my(%hash) = $cust_svc->hash; - $hash{'pkgnum'}=$pkgnum; - my $new = new FS::cust_svc ( \%hash ); - - #avoid Record diffing missing changed svcpart field from above. - my $old = qsearchs('cust_svc', { 'svcnum' => $cust_svc->svcnum } ); - - my $error = $new->replace($old); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "Couldn't link old service to new package: $error"; - } - } - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - - ''; #no errors + ''; } =back -- cgit v1.2.1 From d2a32e633b46e7e248c593c5de6fc598de2b32cb Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 6 Jun 2003 04:42:04 +0000 Subject: database profiling bs i should just switch to mason --- htetc/global.asa | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htetc/global.asa b/htetc/global.asa index 5fd89957f..555364223 100644 --- a/htetc/global.asa +++ b/htetc/global.asa @@ -126,7 +126,9 @@ sub Script_OnFlush { } } -if ( defined(@DBIx::Profile::ISA) && DBIx::Profile::db->can('sprintProfile') ) { +#if ( defined(@DBIx::Profile::ISA) && DBIx::Profile::db->can('sprintProfile') ) { +#if ( defined(@DBIx::Profile::ISA) && UNIVERSAL::can('DBIx::Profile::db', 'sprintProfile') ) { +if ( defined(@DBIx::Profile::ISA) ) { #warn "enabling profiling redirects"; *CGI::redirect = sub { -- cgit v1.2.1 From fc970220d488dfbcf2f7a4b1c7ae6b7618af1ecc Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 6 Jun 2003 10:49:59 +0000 Subject: add suspend/unsuspend capability to CP export --- FS/FS/part_export/cp.pm | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/FS/FS/part_export/cp.pm b/FS/FS/part_export/cp.pm index c37dc3b98..ee5f54285 100644 --- a/FS/FS/part_export/cp.pm +++ b/FS/FS/part_export/cp.pm @@ -10,10 +10,10 @@ sub rebless { shift; } sub _export_insert { my( $self, $svc_acct ) = (shift, shift); $self->cp_queue( $svc_acct->svcnum, 'create_mailbox', - Mailbox => $svc_acct->username, - Password => $svc_acct->_password, - Workgroup => $self->option('workgroup'), - Domain => $svc_acct->domain, + 'Mailbox' => $svc_acct->username, + 'Password' => $svc_acct->_password, + 'Workgroup' => $self->option('workgroup'), + 'Domain' => $svc_acct->domain, ); } @@ -30,8 +30,30 @@ sub _export_replace { sub _export_delete { my( $self, $svc_acct ) = (shift, shift); $self->cp_queue( $svc_acct->svcnum, 'delete_mailbox', - Mailbox => $svc_acct->username, - Domain => $svc_acct->domain, + 'Mailbox' => $svc_acct->username, + 'Domain' => $svc_acct->domain, + ); +} + +sub _export_suspend { + my( $self, $svc_acct ) = (shift, shift); + $self->cp_queue( $svc_acct->svcnum, 'set_mailbox_status', + 'Mailbox' => $svc_acct->username, + 'Domain' => $svc_acct->domain, + 'OTHER' => 'T', + 'OTHER_SUSPEND' => 'T', + ); +} + +sub _export_unsuspend { + my( $self, $svc_acct ) = (shift, shift); + $self->cp_queue( $svc_acct->svcnum, 'set_mailbox_status', + 'Mailbox' => $svc_acct->username, + 'Domain' => $svc_acct->domain, + 'PAYMENT' => 'F', + 'OTHER' => 'F', + 'OTHER_SUSPEND' => 'F', + 'OTHER_BOUNCE' => 'F', ); } -- cgit v1.2.1 From d5da3d1db2e73288cb15b8dbd6e3c34d54eb0faa Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 7 Jun 2003 01:42:52 +0000 Subject: require Time::Local 1.04 on perls before 5.6 --- FS/FS/cust_main.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 7e2ff388e..923de00c4 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -4,6 +4,7 @@ use strict; use vars qw( @ISA $conf $Debug $import ); use Safe; use Carp; +BEGIN { eval "use Time::Local 1.05;" if $] < 5.006; }; use Time::Local qw(timelocal_nocheck); use Date::Format; #use Date::Manip; -- cgit v1.2.1 From 82b6a3add627d151f749bc26d170e6bb4b80d526 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 7 Jun 2003 01:47:23 +0000 Subject: give a better error message regarding Time::Local on old perls. really. --- FS/FS/cust_main.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 923de00c4..0176c7723 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -4,8 +4,10 @@ use strict; use vars qw( @ISA $conf $Debug $import ); use Safe; use Carp; -BEGIN { eval "use Time::Local 1.05;" if $] < 5.006; }; -use Time::Local qw(timelocal_nocheck); +BEGIN { + eval "use Time::Local 1.05;" if $] < 5.006; + eval "use Time::Local qw(timelocal_nocheck);"; +} use Date::Format; #use Date::Manip; use Business::CreditCard; -- cgit v1.2.1 From 9533cf0292866372f32a80e61ea590f20005bf74 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 7 Jun 2003 01:57:33 +0000 Subject: really, really give a better error message when used under 5.005 now. really. --- FS/FS/cust_main.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 0176c7723..079583a9a 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -5,7 +5,9 @@ use vars qw( @ISA $conf $Debug $import ); use Safe; use Carp; BEGIN { - eval "use Time::Local 1.05;" if $] < 5.006; + eval "use Time::Local;"; + die "Time::Local version 1.05 with Perl versions before 5.6" + if $] < 5.006 && !defined($Time::Local::VERSION); eval "use Time::Local qw(timelocal_nocheck);"; } use Date::Format; -- cgit v1.2.1 From 6c0c9e76ef87a5600496debb2c0a53332b5ac5f5 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 7 Jun 2003 01:58:45 +0000 Subject: and fix the error message --- FS/FS/cust_main.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 079583a9a..533c630f2 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -6,7 +6,7 @@ use Safe; use Carp; BEGIN { eval "use Time::Local;"; - die "Time::Local version 1.05 with Perl versions before 5.6" + die "Time::Local version 1.05 required with Perl versions before 5.6" if $] < 5.006 && !defined($Time::Local::VERSION); eval "use Time::Local qw(timelocal_nocheck);"; } -- cgit v1.2.1 From 9bdd5507fab070864ecc3ebacd1f8c7f8a0b9b3c Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 9 Jun 2003 00:59:21 +0000 Subject: documentation update from "Jesse D. Guardiani" , thanks --- httemplate/docs/install.html | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html index 533decb7b..54614ccb3 100644 --- a/httemplate/docs/install.html +++ b/httemplate/docs/install.html @@ -144,9 +144,14 @@ PerlSetVar Debug 2
    • Run make masondocs -
    • Copy masondocs/ to your web server's document space. -
    • Copy htetc/handler.pl to an appropriate directory (use htetc/handler.pl-1.0x for Mason versions before 1.10). -
    • Edit handler.pl and set an appropriate data_dir, such as /usr/local/etc/freeside/masondata +
    • Copy masondocs/ to your web server's document space. (For example: /usr/local/apache/htdocs/freeside-mason) +
    • Copy htetc/handler.pl to /usr/local/etc/freeside (use htetc/handler.pl-1.0x for Mason versions before 1.10). +
    • Edit handler.pl and: +
        +
      • set an appropriate comp_root, such as /usr/local/apache/htdocs/freeside-mason +
      • set an appropriate data_dir, such as /usr/local/etc/freeside/masondata +
      +
    • Configure Apache to use the handler.pl file and to execute .cgi files using HTML::Mason. For example:
       PerlModule HTML::Mason
      -- 
      cgit v1.2.1
      
      
      From 19270ddc47dead26e94d01a78dd4a5e8313ffdac Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Mon, 9 Jun 2003 11:11:21 +0000
      Subject: add "$ignore_quantity" bypass
      
      ---
       FS/FS/cust_svc.pm | 6 ++++--
       1 file changed, 4 insertions(+), 2 deletions(-)
      
      diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm
      index 8ac806519..c0cb6f4e9 100644
      --- a/FS/FS/cust_svc.pm
      +++ b/FS/FS/cust_svc.pm
      @@ -1,7 +1,7 @@
       package FS::cust_svc;
       
       use strict;
      -use vars qw( @ISA );
      +use vars qw( @ISA $ignore_quantity );
       use Carp qw( cluck );
       use FS::Record qw( qsearch qsearchs dbh );
       use FS::cust_pkg;
      @@ -17,6 +17,8 @@ use FS::part_export;
       
       @ISA = qw( FS::Record );
       
      +$ignore_quantity = 0;
      +
       sub _cache {
         my $self = shift;
         my ( $hashref, $cache ) = @_;
      @@ -229,7 +231,7 @@ sub check {
           });
           return "Already ". scalar(@cust_svc). " ". $part_svc->svc.
                  " services for pkgnum ". $self->pkgnum
      -      if scalar(@cust_svc) >= $quantity;
      +      if scalar(@cust_svc) >= $quantity && (!$ignore_quantity || !$quantity);
         }
       
         ''; #no error
      -- 
      cgit v1.2.1
      
      
      From f012a5c9f502bc480414686b44c41df0b27c8b2f Mon Sep 17 00:00:00 2001
      From: khoff 
      Date: Wed, 11 Jun 2003 19:13:43 +0000
      Subject: We're passing a list here, not one argument.
      
      ---
       FS/FS/Misc.pm | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm
      index 56dc72e36..1f951595a 100644
      --- a/FS/FS/Misc.pm
      +++ b/FS/FS/Misc.pm
      @@ -54,7 +54,7 @@ FS::UID->install_callback( sub {
       } );
       
       sub send_email {
      -  my(%options) = shift;
      +  my(%options) = @_;
       
         $ENV{MAILADDRESS} = $options{'from'};
         my $to = ref($options{to}) ? join(', ', @{ $options{to} } ) : $options{to};
      -- 
      cgit v1.2.1
      
      
      From 0bdae1eced79650fd64c66cdf2107a8f2d0b9067 Mon Sep 17 00:00:00 2001
      From: khoff 
      Date: Wed, 11 Jun 2003 20:27:18 +0000
      Subject: In scalar context, smtpsend returns the number of addresses that the
       message was successfully delivered to.  I'm assuming 'Debug' causes Net::SMTP
       to warn the debug output, not return it.
      
      ---
       FS/FS/Misc.pm | 13 ++++++++++---
       1 file changed, 10 insertions(+), 3 deletions(-)
      
      diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm
      index 1f951595a..efad2dfd6 100644
      --- a/FS/FS/Misc.pm
      +++ b/FS/FS/Misc.pm
      @@ -77,9 +77,16 @@ sub send_email {
       
         my $smtpmachine = $conf->config('smtpmachine');
         $!=0;
      -  $message->smtpsend( 'Host' => $smtpmachine )
      -    or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
      -      or return "can't send email to $to via server $smtpmachine with SMTP: $!";
      +
      +  my $rv = $message->smtpsend( 'Host' => $smtpmachine )
      +    or $message->smtpsend( Host => $smtpmachine, Debug => 1 );
      +
      +  if ($rv) { #smtpsend returns a list of addresses, not true/false
      +    return '';
      +  } else {
      +    return "can't send email to $to via server $smtpmachine with SMTP: $!";
      +  }  
      +
       }
       
       =head1 BUGS
      -- 
      cgit v1.2.1
      
      
      From 1e40dbcd2cc56ab3a0c548dab5a75b5ff1360b69 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 12:43:27 +0000
      Subject: sqlradius doc update; don't need to allow null OP columns
      
      ---
       FS/FS/part_export.pm | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
      index 06fab6ad1..4e3326442 100644
      --- a/FS/FS/part_export.pm
      +++ b/FS/FS/part_export.pm
      @@ -890,7 +890,7 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
             'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS)',
             'options' => \%sqlradius_options,
             'nodomain' => 'Y',
      -      'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for FreeRADIUS or ICRADIUS.  An existing RADIUS database will be updated in realtime, but you can use freeside-sqlradius-reset to delete the entire RADIUS database and repopulate the tables from the Freeside database.  See the DBI documentation and the documentation for your DBD for the exact syntax of a DBI data source.  If using FreeRADIUS 0.5 or above, make sure your op fields are set to allow NULL values.',
      +      'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for FreeRADIUS or ICRADIUS.  An existing RADIUS database will be updated in realtime, but you can use freeside-sqlradius-reset to delete the entire RADIUS database and repopulate the tables from the Freeside database.  See the DBI documentation and the documentation for your DBD for the exact syntax of a DBI data source.',
           },
       
           'sqlmail' => {
      -- 
      cgit v1.2.1
      
      
      From faea8c040128dcace598fb224cf9f7e9a2e256c9 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 12:57:44 +0000
      Subject: _default_ default now sets GECOS like the OS-defaults
      
      ---
       FS/FS/part_export.pm | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
      index 4e3326442..9330a925d 100644
      --- a/FS/FS/part_export.pm
      +++ b/FS/FS/part_export.pm
      @@ -548,7 +548,7 @@ tie my %shellcommands_options, 'Tie::IxHash',
         #'machine' => { label=>'Remote machine' },
         'user' => { label=>'Remote username', default=>'root' },
         'useradd' => { label=>'Insert command',
      -                 default=>'useradd -d $dir -m -s $shell -u $uid -p $crypt_password $username'
      +                 default=>'useradd -c $finger -d $dir -m -s $shell -u $uid -p $crypt_password $username'
                       #default=>'cp -pr /etc/skel $dir; chown -R $uid.$gid $dir'
                      },
         'useradd_stdin' => { label=>'Insert command STDIN',
      @@ -564,7 +564,7 @@ tie my %shellcommands_options, 'Tie::IxHash',
                              default=>'',
                            },
         'usermod' => { label=>'Modify command',
      -                 default=>'usermod -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username',
      +                 default=>'usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username',
                       #default=>'[ -d $old_dir ] && mv $old_dir $new_dir || ( '.
                        #  'chmod u+t $old_dir; mkdir $new_dir; cd $old_dir; '.
                        #  'find . -depth -print | cpio -pdm $new_dir; '.
      -- 
      cgit v1.2.1
      
      
      From b77d5769face5c38dd34c37e98a8fce47c4e15de Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:32:15 +0000
      Subject: adding fix-sequences
      
      ---
       bin/fix-sequences | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
       1 file changed, 55 insertions(+)
       create mode 100755 bin/fix-sequences
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      new file mode 100755
      index 000000000..f193e21d4
      --- /dev/null
      +++ b/bin/fix-sequences
      @@ -0,0 +1,55 @@
      +#!/usr/bin/perl -Tw
      +
      +use strict;
      +use DBI;
      +use DBIx::DBSchema 0.21;
      +use DBIx::DBSchema::Table;
      +use DBIx::DBSchema::Column;
      +use DBIx::DBSchema::ColGroup::Unique;
      +use DBIx::DBSchema::ColGroup::Index;
      +use FS::UID qw(adminsuidsetup);
      +use FS::Record qw(dbdef);
      +
      +my $user = shift or die &usage;
      +my $dbh = adminsuidsetup $user;
      +
      +my $schema = dbdef();
      +
      +#false laziness w/fs-setup
      +my @tables = scalar(@ARGV)
      +               ? @ARGV
      +               : grep { ! /^h_/ } $schema->tables;
      +foreach my $table ( @tables ) {
      +  my $tableobj = $schema->table($table)
      +    or die "unknown table $table (did you run dbdef-create?)\n";
      +
      +  my $primary_key = $tableobj->primary_key;
      +  next unless $primary_key;
      +
      +  my $col = $tableobj->column($primary_key);
      +
      +  next unless uc($col->type) eq 'SERIAL'
      +              || ( driver_name eq 'Pg'
      +                     && defined($col->default)
      +                     && $col->default =~ /^nextval\(/i
      +                 )
      +              || ( driver_name eq 'mysql'
      +                     && defined($col->local)
      +                     && $col->local =~ /AUTO_INCREMENT/i
      +                 );
      +
      +  warn "fixing sequence for $table\n";
      +
      +  $dbh->do( "SELECT setval( '${table}_${primary_key}_seq',
      +                            ( SELECT max($primary_key) FROM $table ) );" )
      +    or die $dbh->errstr;
      +
      +}
      +
      +$dbh->commit or die $dbh->errstr;
      +$dbh->disconnect or die $dbh->errstr;
      +
      +sub usage {
      +  die "Usage:\n  create-history-tables user [ table table ... ] \n";
      +}
      +
      -- 
      cgit v1.2.1
      
      
      From 232897b9389df4dca4773873e6e5d638ac5e8c4b Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:35:42 +0000
      Subject: moo
      
      ---
       bin/fix-sequences | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      index f193e21d4..be240226f 100755
      --- a/bin/fix-sequences
      +++ b/bin/fix-sequences
      @@ -7,7 +7,7 @@ use DBIx::DBSchema::Table;
       use DBIx::DBSchema::Column;
       use DBIx::DBSchema::ColGroup::Unique;
       use DBIx::DBSchema::ColGroup::Index;
      -use FS::UID qw(adminsuidsetup);
      +use FS::UID qw(adminsuidsetup driver_name);
       use FS::Record qw(dbdef);
       
       my $user = shift or die &usage;
      @@ -50,6 +50,6 @@ $dbh->commit or die $dbh->errstr;
       $dbh->disconnect or die $dbh->errstr;
       
       sub usage {
      -  die "Usage:\n  create-history-tables user [ table table ... ] \n";
      +  die "Usage:\n  fix-sequences user [ table table ... ] \n";
       }
       
      -- 
      cgit v1.2.1
      
      
      From 1957a30d2616acadba23324b764eb03ba008b590 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:43:13 +0000
      Subject: update for long table names; use sequence name directly instead of
       guessing
      
      ---
       bin/fix-sequences | 11 ++++++++++-
       1 file changed, 10 insertions(+), 1 deletion(-)
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      index be240226f..55639d962 100755
      --- a/bin/fix-sequences
      +++ b/bin/fix-sequences
      @@ -28,6 +28,7 @@ foreach my $table ( @tables ) {
       
         my $col = $tableobj->column($primary_key);
       
      +
         next unless uc($col->type) eq 'SERIAL'
                     || ( driver_name eq 'Pg'
                            && defined($col->default)
      @@ -38,9 +39,17 @@ foreach my $table ( @tables ) {
                            && $col->local =~ /AUTO_INCREMENT/i
                        );
       
      +  my $seq = "${table}_${primary_key}_seq";
      +  if ( driver_name eq 'Pg'
      +       && defined($col->default) 
      +       && $col->default =~ /^nextval\('"(\w+_seq)"'::text\)$/
      +     ) {
      +    $seq = $1;
      +  }
      +
         warn "fixing sequence for $table\n";
       
      -  $dbh->do( "SELECT setval( '${table}_${primary_key}_seq',
      +  $dbh->do( "SELECT setval( '$seq',
                                   ( SELECT max($primary_key) FROM $table ) );" )
           or die $dbh->errstr;
       
      -- 
      cgit v1.2.1
      
      
      From cbf32a25fcfc38632d1262ad8261e679e1c9b7c5 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:47:51 +0000
      Subject: debugging
      
      ---
       bin/fix-sequences | 13 ++++++++-----
       1 file changed, 8 insertions(+), 5 deletions(-)
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      index 55639d962..d5349ee74 100755
      --- a/bin/fix-sequences
      +++ b/bin/fix-sequences
      @@ -42,16 +42,19 @@ foreach my $table ( @tables ) {
         my $seq = "${table}_${primary_key}_seq";
         if ( driver_name eq 'Pg'
              && defined($col->default) 
      -       && $col->default =~ /^nextval\('"(\w+_seq)"'::text\)$/
      +       && $col->default =~ /^nextval\('"(public\.)?(\w+_seq)"'::text\)$/
            ) {
      -    $seq = $1;
      +    $seq = $2;
         }
       
         warn "fixing sequence for $table\n";
       
      -  $dbh->do( "SELECT setval( '$seq',
      -                            ( SELECT max($primary_key) FROM $table ) );" )
      -    or die $dbh->errstr;
      +
      +  my $sql = "SELECT setval( '$seq',
      +                            ( SELECT max($primary_key) FROM $table ) );" );
      +
      +  warn $col->default. " $seq\n$sql\n";
      +  $dbh->do( $sql ) or die $dbh->errstr;
       
       }
       
      -- 
      cgit v1.2.1
      
      
      From 6dca9c84fb27d3c01d94b993c56ea66f25d94fb2 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:49:02 +0000
      Subject: arg
      
      ---
       bin/fix-sequences | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      index d5349ee74..70b6df601 100755
      --- a/bin/fix-sequences
      +++ b/bin/fix-sequences
      @@ -51,7 +51,7 @@ foreach my $table ( @tables ) {
       
       
         my $sql = "SELECT setval( '$seq',
      -                            ( SELECT max($primary_key) FROM $table ) );" );
      +                            ( SELECT max($primary_key) FROM $table ) );";
       
         warn $col->default. " $seq\n$sql\n";
         $dbh->do( $sql ) or die $dbh->errstr;
      -- 
      cgit v1.2.1
      
      
      From 982fa001e4f9fdc6c544b43d7c21143facc8823d Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:50:17 +0000
      Subject: "doc"
      
      ---
       bin/fix-sequences | 2 ++
       1 file changed, 2 insertions(+)
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      index 70b6df601..1ef7bd654 100755
      --- a/bin/fix-sequences
      +++ b/bin/fix-sequences
      @@ -1,5 +1,7 @@
       #!/usr/bin/perl -Tw
       
      +# run dbdef-create first!
      +
       use strict;
       use DBI;
       use DBIx::DBSchema 0.21;
      -- 
      cgit v1.2.1
      
      
      From d7fa80b06b82168ed78e888835197e09b29491dd Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:50:59 +0000
      Subject: remove overly-verbose debugging for now
      
      ---
       bin/fix-sequences | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/bin/fix-sequences b/bin/fix-sequences
      index 1ef7bd654..2ff89d3e5 100755
      --- a/bin/fix-sequences
      +++ b/bin/fix-sequences
      @@ -55,7 +55,7 @@ foreach my $table ( @tables ) {
         my $sql = "SELECT setval( '$seq',
                                   ( SELECT max($primary_key) FROM $table ) );";
       
      -  warn $col->default. " $seq\n$sql\n";
      +  #warn $col->default. " $seq\n$sql\n";
         $dbh->do( $sql ) or die $dbh->errstr;
       
       }
      -- 
      cgit v1.2.1
      
      
      From f0e07588b2eef04bf5a8cbf0b77c6bde27e02321 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 13:57:08 +0000
      Subject: better error handling for re-imports
      
      ---
       bin/passwd.import | 10 ++++++++--
       1 file changed, 8 insertions(+), 2 deletions(-)
      
      diff --git a/bin/passwd.import b/bin/passwd.import
      index fbf27370f..304499e34 100755
      --- a/bin/passwd.import
      +++ b/bin/passwd.import
      @@ -1,5 +1,5 @@
       #!/usr/bin/perl -Tw
      -# $Id: passwd.import,v 1.5 2002-06-21 09:57:05 ivan Exp $
      +# $Id: passwd.import,v 1.6 2003-06-12 13:57:08 ivan Exp $
       
       use strict;
       use vars qw(%part_svc);
      @@ -104,7 +104,13 @@ while () {
         });
         my($error);
         $error=$svc_acct->insert;
      -  die $error if $error;
      +  if ( $error ) {
      +    if ( $error =~ /duplicate/i ) {
      +      warn "$username: $error";
      +    } else {
      +      die "$username: $error";
      +    }
      +  }
       
       }
       
      -- 
      cgit v1.2.1
      
      
      From 1b7aca1fcbc4731099cd27d81e47200395abd316 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 14:06:06 +0000
      Subject: tyop
      
      ---
       bin/passwd.import | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/bin/passwd.import b/bin/passwd.import
      index 304499e34..a56be3aaa 100755
      --- a/bin/passwd.import
      +++ b/bin/passwd.import
      @@ -1,5 +1,5 @@
       #!/usr/bin/perl -Tw
      -# $Id: passwd.import,v 1.6 2003-06-12 13:57:08 ivan Exp $
      +# $Id: passwd.import,v 1.7 2003-06-12 14:06:06 ivan Exp $
       
       use strict;
       use vars qw(%part_svc);
      @@ -14,7 +14,7 @@ use FS::part_svc;
       my $user = shift or die &usage;
       adminsuidsetup $user;
       
      -push @FS::svc_acct::shells, qw(/bin/sync /sbin/shuddown /bin/halt); #others?
      +push @FS::svc_acct::shells, qw(/bin/sync /sbin/shutdown /bin/halt); #others?
       
       my($spooldir)="/usr/local/etc/freeside/export.". datasrc;
       
      -- 
      cgit v1.2.1
      
      
      From ce6df8eaa7ba3ba864cc58b2a51ab6b603e68dc1 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Thu, 12 Jun 2003 14:08:00 +0000
      Subject: /bin/halt and /sbin/halt
      
      ---
       bin/passwd.import | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/bin/passwd.import b/bin/passwd.import
      index a56be3aaa..093f8bafd 100755
      --- a/bin/passwd.import
      +++ b/bin/passwd.import
      @@ -1,5 +1,5 @@
       #!/usr/bin/perl -Tw
      -# $Id: passwd.import,v 1.7 2003-06-12 14:06:06 ivan Exp $
      +# $Id: passwd.import,v 1.8 2003-06-12 14:08:00 ivan Exp $
       
       use strict;
       use vars qw(%part_svc);
      @@ -14,7 +14,7 @@ use FS::part_svc;
       my $user = shift or die &usage;
       adminsuidsetup $user;
       
      -push @FS::svc_acct::shells, qw(/bin/sync /sbin/shutdown /bin/halt); #others?
      +push @FS::svc_acct::shells, qw(/bin/sync /sbin/shutdown /bin/halt /sbin/halt); #others?
       
       my($spooldir)="/usr/local/etc/freeside/export.". datasrc;
       
      -- 
      cgit v1.2.1
      
      
      From 2c2f1122f76c0aec0861bf3d9c7fb9dff109c346 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Fri, 13 Jun 2003 08:11:24 +0000
      Subject: add vpopmail presets to shellcommands_withdomain export
      
      ---
       FS/FS/part_export.pm               | 10 ++++++++--
       FS/FS/part_export/shellcommands.pm | 11 +++++++++++
       2 files changed, 19 insertions(+), 2 deletions(-)
      
      diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
      index 9330a925d..300e88821 100644
      --- a/FS/FS/part_export.pm
      +++ b/FS/FS/part_export.pm
      @@ -576,6 +576,9 @@ tie my %shellcommands_options, 'Tie::IxHash',
                              type =>'textarea',
                              default=>'',
                            },
      +  'usermod_pwonly' => { label=>'Disallow username changes',
      +                        type =>'checkbox',
      +                      },
         'suspend' => { label=>'Suspension command',
                        default=>'',
                      },
      @@ -613,6 +616,9 @@ tie my %shellcommands_withdomain_options, 'Tie::IxHash',
                              type =>'textarea',
                              #default=>"$_password\n$_password\n",
                            },
      +  'usermod_pwonly' => { label=>'Disallow username changes',
      +                        type =>'checkbox',
      +                      },
         'suspend' => { label=>'Suspension command',
                        default=>'',
                      },
      @@ -875,9 +881,9 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
           },
       
           'shellcommands_withdomain' => {
      -      'desc' => 'Real-time export via remote SSH.',
      +      'desc' => 'Real-time export via remote SSH (vpopmail, etc.).',
             'options' => \%shellcommands_withdomain_options,
      -      'notes' => 'Run remote commands via SSH.  username@domain (rather than just usernames) are considered unique (also see shellcommands).  You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains.  You will need to setup SSH for unattended operation.

      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', + 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', }, 'ldap' => { diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm index f592a838a..b1f9b0d68 100644 --- a/FS/FS/part_export/shellcommands.pm +++ b/FS/FS/part_export/shellcommands.pm @@ -81,6 +81,17 @@ sub _export_replace { $new_crypt_password = ''; #surpress "used only once" warnings $new_crypt_password = crypt( $new->_password, $saltset[int(rand(64))].$saltset[int(rand(64))]); + if ( $self->option('usermod_pwonly') ) { + my $error = ''; + if ( $old_username ne $new_username ) { + $error ||= "can't change username"; + } + if ( $old_domain ne $new_domain ) { + $error ||= "can't change domain"; + } + return $error. ' ('. $self->exporttype. ' to '. $self->machine. ')' + if $error; + } $self->shellcommands_queue( $new->svcnum, user => $self->option('user')||'root', host => $self->machine, -- cgit v1.2.1 From d8d7c720d27047d4cde950e741f80fc2e77eb7a6 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 13 Jun 2003 08:23:21 +0000 Subject: full path to vpopmail commands --- FS/FS/part_export.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index 300e88821..ad77ec8c2 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -883,7 +883,7 @@ tie my %forward_shellcommands_options, 'Tie::IxHash', 'shellcommands_withdomain' => { 'desc' => 'Real-time export via remote SSH (vpopmail, etc.).', 'options' => \%shellcommands_withdomain_options, - 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', + 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', }, 'ldap' => { -- cgit v1.2.1 From 4a02b0fa8b35533d8d938941cbb5ca89903132c0 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 13 Jun 2003 08:38:58 +0000 Subject: pass vpopmail passwords on command-line (unfortunately) --- FS/FS/part_export.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index ad77ec8c2..5cdce1608 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -883,7 +883,7 @@ tie my %forward_shellcommands_options, 'Tie::IxHash', 'shellcommands_withdomain' => { 'desc' => 'Real-time export via remote SSH (vpopmail, etc.).', 'options' => \%shellcommands_withdomain_options, - 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', + 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', }, 'ldap' => { -- cgit v1.2.1 From 499b8660e2aa5632fc14e8fcfa6631800ade1e35 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 13 Jun 2003 08:44:52 +0000 Subject: correct stickiness for checkbox options on export edit --- httemplate/edit/part_export.cgi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi index 4defbc86f..0590549f5 100644 --- a/httemplate/edit/part_export.cgi +++ b/httemplate/edit/part_export.cgi @@ -72,7 +72,9 @@ my $widget = new HTML::Widgets::SelectLayers( } elsif ( $type eq 'text' ) { $html .= qq!!; } elsif ( $type eq 'checkbox' ) { - $html .= qq!!; + $html .= qq! Date: Fri, 13 Jun 2003 08:46:19 +0000 Subject: missing semi --- httemplate/edit/part_export.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi index 0590549f5..24d646b8b 100644 --- a/httemplate/edit/part_export.cgi +++ b/httemplate/edit/part_export.cgi @@ -72,7 +72,7 @@ my $widget = new HTML::Widgets::SelectLayers( } elsif ( $type eq 'text' ) { $html .= qq!!; } elsif ( $type eq 'checkbox' ) { - $html .= qq! Date: Fri, 13 Jun 2003 09:12:29 +0000 Subject: proper command escape for vpopmail export --- FS/FS/part_export.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index 5cdce1608..f1a0b1a2e 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -883,7 +883,7 @@ tie my %forward_shellcommands_options, 'Tie::IxHash', 'shellcommands_withdomain' => { 'desc' => 'Real-time export via remote SSH (vpopmail, etc.).', 'options' => \%shellcommands_withdomain_options, - 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', + 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to setup SSH for unattended operation.

      Use these buttons for some useful presets:
      The following variables are available for interpolation (prefixed with new_ or old_ for replace operations):
      • $username
      • $domain
      • $_password
      • $quoted_password - unencrypted password quoted for the shell
      • $crypt_password - encrypted password
      • $uid
      • $gid
      • $finger - GECOS, already quoted for the shell (do not add additional quotes)
      • $dir - home directory
      • $shell
      • $quota
      • All other fields in svc_acct are also available.
      ', }, 'ldap' => { -- cgit v1.2.1 From 92b6d3bef27fdcfb22cb67f2c62173cfda246684 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 13 Jun 2003 15:19:02 +0000 Subject: $new_quoted_password vs. $quoted_new__password --- FS/FS/part_export/shellcommands.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm index b1f9b0d68..edc944009 100644 --- a/FS/FS/part_export/shellcommands.pm +++ b/FS/FS/part_export/shellcommands.pm @@ -75,7 +75,8 @@ sub _export_replace { ${"new_$_"} = $new->getfield($_) foreach $new->fields; } $new_finger = shell_quote $new_finger; - $quoted_new__password = shell_quote $new__password; + $quoted_new__password = shell_quote $new__password; #old, wrong? + $new_quoted_password = shell_quote $new__password; #new, better? $old_domain = $old->domain; $new_domain = $new->domain; $new_crypt_password = ''; #surpress "used only once" warnings -- cgit v1.2.1 From be0c6c490ff51286e521e838ceafb1cf7ec2aa5a Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 14 Jun 2003 01:01:12 +0000 Subject: \n\n between virtualhost entries --- bin/apache.export | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/apache.export b/bin/apache.export index 908313606..f0a6beefc 100755 --- a/bin/apache.export +++ b/bin/apache.export @@ -39,7 +39,7 @@ foreach my $export ( @exports ) { use vars qw($zone $username); $zone = $svc_www->domain_record->zone; $username = $svc_www->svc_acct->username; - print HTTPD_CONF eval(qq("$template")); + print HTTPD_CONF eval(qq("$template")). "\n\n"; } my $user = $export->option('user'); -- cgit v1.2.1 From 9e6413e476a3516a08710efa5ff4d5949c1aa88c Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 14 Jun 2003 02:02:55 +0000 Subject: add index on cust_bill._date --- FS/bin/freeside-setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index d2a98dd0c..734744efe 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -373,7 +373,7 @@ sub tables_hash_hack { ], 'primary_key' => 'invnum', 'unique' => [], - 'index' => [ ['custnum'] ], + 'index' => [ ['custnum'], ['_date'] ], }, 'cust_bill_event' => { -- cgit v1.2.1 From d01e41ec4ca900fb0b782c6d97f549a505f3a719 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 14 Jun 2003 02:04:12 +0000 Subject: cust_bill2 index --- httemplate/docs/upgrade9.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/httemplate/docs/upgrade9.html b/httemplate/docs/upgrade9.html index c6afe2b0f..24d1cce42 100644 --- a/httemplate/docs/upgrade9.html +++ b/httemplate/docs/upgrade9.html @@ -15,10 +15,11 @@ INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 18, 'daytime', 'en_US', 'Day Phone' ); INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 19, 'night', 'en_US', 'Night Phone' );
      -
    • Optionally, apply the following changes to your database (performance improvement for large numbers of services or packages): +
    • Optionally, apply the following changes to your database (performance improvements):
       CREATE INDEX part_pkg1 ON part_pkg ( disabled );
       CREATE INDEX part_svc1 ON part_svc ( disabled );
      +CREATE INDEX cust_bill2 ON cust_bill ( _date );
       
    • If you want to use ACH (electronic checks), you will need to make changes to your database. The easiest way to make these changes is to dump your database (with pg_dump), change the payinfo field in the cust_pay, cust_refund, h_cust_pay and h_cust_refund tables from varchar(16) to varchar(80), reload the database from the dump, and run dbdef-create
    • Restart Apache and freeside-queued. -- cgit v1.2.1 From eef1e8261ea49fe7c531598cbfca064ad3447a5e Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 22 Jun 2003 09:04:55 +0000 Subject: skip history tables that exist already; easier to re-run now --- bin/create-history-tables | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/create-history-tables b/bin/create-history-tables index 33eb0e5a3..8d419d287 100755 --- a/bin/create-history-tables +++ b/bin/create-history-tables @@ -20,6 +20,7 @@ my @tables = scalar(@ARGV) ? @ARGV : grep { ! /^h_/ } $schema->tables; foreach my $table ( @tables ) { + next if grep { /^h_$table/ } $schema->tables; warn "creating history table for $table\n"; my $tableobj = $schema->table($table) or die "unknown table $table (did you run dbdef-create?)\n"; -- cgit v1.2.1 From 8f4fddbaa123a4baee6fb1df4d2abf857f22a04c Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 22 Jun 2003 09:11:11 +0000 Subject: skip pg_ tables also (ewww, showing up in reverse-engineered schema) --- bin/create-history-tables | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/create-history-tables b/bin/create-history-tables index 8d419d287..39248bf3f 100755 --- a/bin/create-history-tables +++ b/bin/create-history-tables @@ -18,7 +18,7 @@ my $schema = dbdef(); #false laziness w/fs-setup my @tables = scalar(@ARGV) ? @ARGV - : grep { ! /^h_/ } $schema->tables; + : grep { ! /^(h|pg)_/ } $schema->tables; foreach my $table ( @tables ) { next if grep { /^h_$table/ } $schema->tables; warn "creating history table for $table\n"; -- cgit v1.2.1 From 3464d4c767130711e724fbd96e391e03fa3a1796 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 22 Jun 2003 14:21:57 +0000 Subject: fix the credit card retry on change or manual "retry_card" to ONCE per invoice --- FS/FS/cust_main.pm | 166 ++++++++++++++++++++++++++++++----------------- httemplate/misc/bill.cgi | 3 +- 2 files changed, 108 insertions(+), 61 deletions(-) diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 533c630f2..b45540095 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -306,24 +306,12 @@ sub insert { } } - #false laziness with sub replace - my $queue = new FS::queue { 'job' => 'FS::cust_main::append_fuzzyfiles' }; - $error = $queue->insert($self->getfield('last'), $self->company); + $error = $self->queue_fuzzyfiles_update; if ( $error ) { $dbh->rollback if $oldAutoCommit; - return "queueing job (transaction rolled back): $error"; + return "updating fuzzy search cache: $error"; } - if ( defined $self->dbdef_table->column('ship_last') && $self->ship_last ) { - $queue = new FS::queue { 'job' => 'FS::cust_main::append_fuzzyfiles' }; - $error = $queue->insert($self->getfield('last'), $self->company); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "queueing job (transaction rolled back): $error"; - } - } - #eslaf - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -525,34 +513,47 @@ sub replace { if ( $self->payby =~ /^(CARD|CHEK|LECB)$/ && grep { $self->get($_) ne $old->get($_) } qw(payinfo paydate payname) ) { - # card/check info has changed, want to retry realtime_card invoice events - #false laziness w/collect - foreach my $cust_bill_event ( - grep { - #$_->part_bill_event->plan eq 'realtime-card' - $_->part_bill_event->eventcode =~ - /^\$cust_bill\->realtime_(card|ach|lec)\(\);$/ - && $_->status eq 'done' - && $_->statustext - } - map { $_->cust_bill_event } - grep { $_->cust_bill_event } - $self->open_cust_bill - - ) { - my $error = $cust_bill_event->retry; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "error scheduling invoice events for retry: $error"; - } + # card/check/lec info has changed, want to retry realtime_ invoice events + my $error = $self->retry_realtime; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; } - #eslaf + } + $error = $self->queue_fuzzyfiles_update; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "updating fuzzy search cache: $error"; } - #false laziness with sub insert + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + +=item queue_fuzzyfiles_update + +Used by insert & replace to update the fuzzy search cache + +=cut + +sub queue_fuzzyfiles_update { + my $self = shift; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + my $queue = new FS::queue { 'job' => 'FS::cust_main::append_fuzzyfiles' }; - $error = $queue->insert($self->getfield('last'), $self->company); + my $error = $queue->insert($self->getfield('last'), $self->company); if ( $error ) { $dbh->rollback if $oldAutoCommit; return "queueing job (transaction rolled back): $error"; @@ -560,13 +561,12 @@ sub replace { if ( defined $self->dbdef_table->column('ship_last') && $self->ship_last ) { $queue = new FS::queue { 'job' => 'FS::cust_main::append_fuzzyfiles' }; - $error = $queue->insert($self->getfield('last'), $self->company); + $error = $queue->insert($self->getfield('ship_last'), $self->ship_company); if ( $error ) { $dbh->rollback if $oldAutoCommit; return "queueing job (transaction rolled back): $error"; } } - #eslaf $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -1276,7 +1276,10 @@ invoice_time - Use this time when deciding when to print invoices and late notices on those invoices. The default is now. It is specified as a UNIX timestamp; see L). Also see L and L for conversion functions. -retry_card - Retry cards even when not scheduled by invoice events. +retry - Retry card/echeck/LEC transactions even when not scheduled by invoice +events. + +retry_card - Deprecated alias for 'retry' batch_card - This option is deprecated. See the invoice events web interface to control whether cards are batched or run against a realtime gateway. @@ -1310,26 +1313,16 @@ sub collect { return ''; } - if ( exists($options{'retry_card'}) && $options{'retry_card'} ) { - #false laziness w/replace - foreach my $cust_bill_event ( - grep { - #$_->part_bill_event->plan eq 'realtime-card' - $_->part_bill_event->eventcode eq '$cust_bill->realtime_card();' - && $_->status eq 'done' - && $_->statustext - } - map { $_->cust_bill_event } - grep { $_->cust_bill_event } - $self->open_cust_bill - ) { - my $error = $cust_bill_event->retry; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "error scheduling invoice events for retry: $error"; - } + if ( exists($options{'retry_card'}) ) { + carp 'retry_card option passed to collect is deprecated; use retry'; + $options{'retry'} ||= $options{'retry_card'}; + } + if ( exists($options{'retry'}) && $options{'retry'} ) { + my $error = $self->retry_realtime; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; } - #eslaf } foreach my $cust_bill ( $self->cust_bill ) { @@ -1419,6 +1412,60 @@ sub collect { } +=item retry_realtime + +Schedules realtime credit card / electronic check / LEC billing events for +for retry. Useful if card information has changed or manual retry is desired. +The 'collect' method must be called to actually retry the transaction. + +Implementation details: For each of this customer's open invoices, changes +the status of the first "done" (with statustext error) realtime processing +event to "failed". + +=cut + +sub retry_realtime { + my $self = shift; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + foreach my $cust_bill ( + grep { $_->cust_bill_event } + $self->open_cust_bill + ) { + my @cust_bill_event = + sort { $a->part_bill_event->seconds <=> $b->part_bill_event->seconds } + grep { + #$_->part_bill_event->plan eq 'realtime-card' + $_->part_bill_event->eventcode =~ + /\$cust_bill\->realtime_(card|ach|lec)$/ + && $_->status eq 'done' + && $_->statustext + } + $_->cust_bill_event; + next unless @cust_bill_event; + my $error = $cust_bill_event[0]->retry; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error scheduling invoice event for retry: $error"; + } + + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + =item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ] Runs a realtime credit card, ACH (electronic check) or phone bill transaction @@ -2506,4 +2553,3 @@ L, L, schema.html from the base documentation. 1; - diff --git a/httemplate/misc/bill.cgi b/httemplate/misc/bill.cgi index f048e5559..44d85b880 100755 --- a/httemplate/misc/bill.cgi +++ b/httemplate/misc/bill.cgi @@ -21,7 +21,8 @@ unless ( $error ) { #'batch_card'=> 'yes', #'batch_card'=> 'no', #'report_badcard'=> 'yes', - 'retry_card' => 'yes', + #'retry_card' => 'yes', + 'retry' => 'yes', ); } #&eidiot($error) if $error; -- cgit v1.2.1 From 4383c98b73d549da1773934614ea791802753323 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 24 Jun 2003 14:12:31 +0000 Subject: explicitly use the necessary modules --- FS/FS/part_export/forward_shellcommands.pm | 2 ++ FS/FS/part_export/sqlmail.pm | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/FS/FS/part_export/forward_shellcommands.pm b/FS/FS/part_export/forward_shellcommands.pm index 43d558a69..a53628a19 100644 --- a/FS/FS/part_export/forward_shellcommands.pm +++ b/FS/FS/part_export/forward_shellcommands.pm @@ -2,7 +2,9 @@ package FS::part_export::forward_shellcommands; use strict; use vars qw(@ISA); +use FS::Record qw(qsearchs); use FS::part_export; +use FS::svc_acct; @ISA = qw(FS::part_export); diff --git a/FS/FS/part_export/sqlmail.pm b/FS/FS/part_export/sqlmail.pm index 64f72df07..8ccad3c7e 100644 --- a/FS/FS/part_export/sqlmail.pm +++ b/FS/FS/part_export/sqlmail.pm @@ -1,9 +1,10 @@ package FS::part_export::sqlmail; use vars qw(@ISA); +use Digest::MD5 qw(md5_hex); use FS::Record qw(qsearchs); use FS::part_export; -use Digest::MD5 qw(md5_hex); +use FS::svc_domain; @ISA = qw(FS::part_export); -- cgit v1.2.1 From 268594d99867ba0db820884ac47b652deb02e265 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 24 Jun 2003 15:34:45 +0000 Subject: display full POP numbers in signup server - patch from "Stephen Bechard" --- fs_signup/FS-SignupClient/cgi/signup.cgi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs_signup/FS-SignupClient/cgi/signup.cgi b/fs_signup/FS-SignupClient/cgi/signup.cgi index e384aaf8e..de142a1c4 100755 --- a/fs_signup/FS-SignupClient/cgi/signup.cgi +++ b/fs_signup/FS-SignupClient/cgi/signup.cgi @@ -1,6 +1,6 @@ #!/usr/bin/perl -Tw # -# $Id: signup.cgi,v 1.36 2003-04-21 20:53:57 ivan Exp $ +# $Id: signup.cgi,v 1.37 2003-06-24 15:34:45 ivan Exp $ use strict; use vars qw( @payby $cgi $locales $packages $pops $init_data $error @@ -382,7 +382,7 @@ sub popselector { return '' unless @$pops; return $pops->[0]{city}. ', '. $pops->[0]{state}. - ' ('. $pops->[0]{ac}. ')/'. $pops->[0]{exch}. + ' ('. $pops->[0]{ac}. ')/'. $pops->[0]{exch}. '-'. $pops->[0]{loc}. '' if scalar(@$pops) == 1; @@ -435,7 +435,7 @@ END foreach my $pop ( @{$pop{$state}->{$popac}}) { my $o_popnum = $pop->{popnum}; my $poptext = $pop->{city}. ', '. $pop->{state}. - ' ('. $pop->{ac}. ')/'. $pop->{exch}; + ' ('. $pop->{ac}. ')/'. $pop->{exch}. '-'. $pop->{loc}; $text .= "opt(what.form.popnum, \"$o_popnum\", \"$poptext\");\n"; if ($popnum == $o_popnum) { @@ -467,7 +467,7 @@ END $text .= qq!