diff options
Diffstat (limited to 'FS/bin')
| -rw-r--r-- | FS/bin/freeside-ipifony-download | 133 | ||||
| -rwxr-xr-x | FS/bin/freeside-void-payments | 13 | 
2 files changed, 114 insertions, 32 deletions
| diff --git a/FS/bin/freeside-ipifony-download b/FS/bin/freeside-ipifony-download index 64905e193..837cc3329 100644 --- a/FS/bin/freeside-ipifony-download +++ b/FS/bin/freeside-ipifony-download @@ -12,7 +12,18 @@ use FS::Conf;  use Text::CSV;  my %opt; -getopts('va:P:C:T:', \%opt); +getopts('va:P:C:e:', \%opt); + +# Product codes that are subject to flat rate E911 charges.  For these  +# products, the'quantity' field represents the number of lines. +my @E911_CODES = ( 'V-HPBX', 'V-TRUNK' ); + +# Map TAXNONVOICE/TAXVOICE to Freeside taxclass names +my %TAXCLASSES = ( +  'TAXNONVOICE' => 'Other', +  'TAXVOICE'   => 'VoIP', +); +    #$Net::SFTP::Foreign::debug = -1;  sub HELP_MESSAGE { ' @@ -22,7 +33,7 @@ sub HELP_MESSAGE { '          [ -a archivedir ]          [ -P port ]          [ -C category ] -        [ -T taxclass ] +        [ -e pkgpart ]          freesideuser sftpuser@hostname[:path]  ' } @@ -30,12 +41,14 @@ my @fields = (    'custnum',    'date_desc',    'quantity', -  'amount', +  'unit_price',    'classname', +  'taxclass',  );  my $user = shift or die &HELP_MESSAGE; -adminsuidsetup $user; +my $dbh = adminsuidsetup $user; +$FS::UID::AutoCommit = 0;  # for statistics  my $num_charges = 0; @@ -51,6 +64,16 @@ if ( $opt{a} ) {      unless -w $opt{a};  } +my $e911_part_pkg; +if ( $opt{e} ) { +  $e911_part_pkg = FS::part_pkg->by_key($opt{e}) +    or die "E911 pkgpart $opt{e} not found.\n"; + +  if ( $e911_part_pkg->base_recur > 0 or $e911_part_pkg->freq ) { +    die "E911 pkgpart $opt{e} must be a one-time charge.\n"; +  } +} +  my $categorynum = '';  if ( $opt{C} ) {    # find this category (don't auto-create it, it should exist already) @@ -61,8 +84,6 @@ if ( $opt{C} ) {    $categorynum = $category->categorynum;  } -my $taxclass = $opt{T} || ''; -  #my $tmpdir = File::Temp->newdir();  my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere? @@ -88,7 +109,7 @@ my $sftp = Net::SFTP::Foreign->new(    port      => $port,    # for now we don't support passwords. use authorized_keys.    timeout   => 30, -  more      => ($opt{v} ? '-v' : ''), +  #more      => ($opt{v} ? '-v' : ''),  );  die "failed to connect to '$sftpuser\@$host'\n(".$sftp->error.")\n"    if $sftp->error; @@ -100,6 +121,12 @@ if (!@$files) {    print STDERR "No charge files found.\n" if $opt{v};    exit(-1);  } + +my %cust_main; # cache +my %e911_qty; # custnum => sum of E911-subject quantity + +my %is_e911 = map {$_ => 1} @E911_CODES; +  FILE: foreach my $filename (@$files) {    print STDERR "Retrieving $filename\n" if $opt{v};    $sftp->get("$filename", "$tmpdir/$filename"); @@ -133,7 +160,7 @@ FILE: foreach my $filename (@$files) {    open my $fh, "<$tmpdir/$filename";    my $header = <$fh>; -  if ($header !~ /^cust_id/) { +  if ($header !~ /^"cust_id"/) {      warn "warning: $filename has incorrect header row:\n$header\n";      # but try anyway    } @@ -145,7 +172,8 @@ FILE: foreach my $filename (@$files) {        next FILE;      };      @hash{@fields} = $csv->fields(); -    my $cust_main = FS::cust_main->by_key($hash{custnum}); +    my $cust_main =  +      $cust_main{$hash{custnum}} ||= FS::cust_main->by_key($hash{custnum});      if (!$cust_main) {        warn "customer #$hash{custnum} not found\n";        next; @@ -153,13 +181,14 @@ FILE: foreach my $filename (@$files) {      print STDERR "Found customer #$hash{custnum}: ".$cust_main->name."\n"        if $opt{v}; +    my $amount = sprintf('%.2f',$hash{quantity} * $hash{unit_price});      # construct arguments for $cust_main->charge -    my %opt = ( -      amount      => $hash{amount}, +    my %charge_opt = ( +      amount      => $amount,        quantity    => $hash{quantity},        start_date  => $cust_main->next_bill_date,        pkg         => $hash{date_desc}, -      taxclass    => $taxclass, +      taxclass    => $TAXCLASSES{ $hash{taxclass} },      );      if (my $classname = $hash{classname}) {        if (!exists($classnum_of{$classname}) ) { @@ -182,11 +211,11 @@ FILE: foreach my $filename (@$files) {          $classnum_of{$classname} = $pkg_class->classnum;        } -      $opt{classnum} = $classnum_of{$classname}; +      $charge_opt{classnum} = $classnum_of{$classname};      } -    print STDERR "  Charging $hash{amount}\n" +    print STDERR "  Charging $hash{unit_price} * $hash{quantity}\n"        if $opt{v}; -    my $error = $cust_main->charge(\%opt); +    my $error = $cust_main->charge(\%charge_opt);      if ($error) {        warn "Error creating charge: $error" if $error;        $num_errors++; @@ -194,48 +223,94 @@ FILE: foreach my $filename (@$files) {        $num_charges++;        $sum_charges += $hash{amount};      } + +    if ( $opt{e} and $is_e911{$hash{classname}} ) { +      $e911_qty{$hash{custnum}} ||= 0; +      $e911_qty{$hash{custnum}} += $hash{quantity}; +    }    } #while $line    close $fh;  } #FILE +# Order E911 packages +my $num_e911 = 0; +my $num_lines = 0; +foreach my $custnum ( keys (%e911_qty) ) { +  my $cust_main = $cust_main{$custnum}; +  my $quantity = $e911_qty{$custnum}; +  next if $quantity == 0; +  my $cust_pkg = FS::cust_pkg->new({ +      pkgpart     => $opt{e}, +      custnum     => $custnum, +      start_date  => $cust_main->next_bill_date, +      quantity    => $quantity, +  }); +  my $error = $cust_main->order_pkg({ cust_pkg => $cust_pkg }); +  if ( $error ) { +    warn "Error creating e911 charge for customer $custnum: $error\n"; +    $num_errors++; +  } else { +    $num_e911++; +    $num_lines += $quantity; +  } +} + +$dbh->commit; +  if ($opt{v}) {    print STDERR "  Finished!    Processed files: @$files    Created charges: $num_charges    Sum of charges: \$".sprintf('%0.2f', $sum_charges)." +  E911 charges: $num_e911 +  E911 lines: $num_lines    Errors: $num_errors  ";  }  =head1 NAME -freeside-eftca-download - Retrieve payment batch responses from EFT Canada. +freeside-ipifony-download - Download and import invoice items from IPifony.  =head1 SYNOPSIS -  freeside-eftca-download [ -v ] [ -a archivedir ] user +      freeside-ipifony-download  +        [ -v ] +        [ -a archivedir ] +        [ -P port ] +        [ -C category ] +        [ -T taxclass ] +        [ -e pkgpart ] +        freesideuser sftpuser@hostname[:path] -=head1 DESCRIPTION +=head1 REQUIRED PARAMETERS -Command line tool to download returned payment reports from the EFT Canada  -gateway and void the returned payments.  Uses the login and password from  -'batchconfig-eft_canada'. +I<freesideuser>: the Freeside user to run as. --v: Be verbose. +I<sftpuser>: the SFTP user to connect as.  The 'freeside' system user should  +have an authorization key to connect as that user. --a directory: Archive response files in the provided directory. +I<hostname>: the SFTP server. + +=head1 OPTIONAL PARAMETERS + +-v: Be verbose. -user: freeside username +-a I<archivedir>: Save a copy of the downloaded file to I<archivedir>. -=head1 BUGS +-P I<port>: Connect to that TCP port. -You need to manually SFTP to ftp.eftcanada.com from the freeside account  -and accept their key before running this script. +-C I<category>: The name of a package category to use when creating package +classes. -=head1 SEE ALSO +-e I<pkgpart>: The pkgpart (L<FS::part_pkg>) to use for E911 charges.  A  +package of this type will be ordered for each invoice that has E911-subject +line items.  The 'quantity' field on this package will be set to the total  +quantity of those line items. -L<FS::pay_batch> +The E911 package must be a one-time package (flat rate, no frequency, no  +recurring fee) with setup fee equal to the fee per line.  =cut diff --git a/FS/bin/freeside-void-payments b/FS/bin/freeside-void-payments index 8c1f3dbdf..49b74d388 100755 --- a/FS/bin/freeside-void-payments +++ b/FS/bin/freeside-void-payments @@ -90,8 +90,11 @@ my $notfound = 0;  my $canceled = 0;  print "Voiding ".scalar(@auths)." transactions:\n" if $opt{'v'};  foreach my $authnum (@auths) { -  my $paybatch = $gatewaynum . $processor . ':' . $authnum; -  my $cust_pay = qsearchs('cust_pay', { paybatch => $paybatch } ); +  my $cust_pay = qsearchs('cust_pay', { +     gatewaynum     => $gatewaynum, +     processor      => $processor, +     authorization  => $authnum, +  });    my $error;    my $cancel_error;    if($cust_pay) { @@ -103,7 +106,11 @@ foreach my $authnum (@auths) {      }    }    else { -    my $cpv = qsearchs('cust_pay_void', { paybatch => $paybatch }); +    my $cpv = qsearchs('cust_pay_void', { +       gatewaynum     => $gatewaynum, +       processor      => $processor, +       authorization  => $authnum, +    });      if($cpv) {        $error = 'already voided '.time2str('%Y-%m-%d', $cpv->void_date) .           ' by ' . $cpv->otaker; | 
