[freeside-commits] branch FREESIDE_4_BRANCH updated. 43033e3456e278ff6076db539cc1ef4bf83293eb

Mark Wells mark at 420.am
Fri Jul 22 09:57:35 PDT 2016


The branch, FREESIDE_4_BRANCH has been updated
       via  43033e3456e278ff6076db539cc1ef4bf83293eb (commit)
       via  963f05981025f647b8f9f924e668ae02f8671c58 (commit)
       via  de94cc4c6e81d762f22e4abb619452d4f13eb944 (commit)
      from  78a1f87b26cad0687ed176ab0a6e0028f0b80e5c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 43033e3456e278ff6076db539cc1ef4bf83293eb
Author: Mark Wells <mark at freeside.biz>
Date:   Fri Jul 22 09:43:30 2016 -0700

    in 4.x, fall back to pattern-matching the card number if paycardtype is not set, #71291

diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
index 03aaedd..5ff5d2a 100755
--- a/httemplate/search/elements/cust_pay_or_refund.html
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -74,6 +74,7 @@ my %cardtype_of = (
   'Amex'      => q['American Express card'],
   'Discover'  => q['Discover card'],
   'Maestro'   => q['Switch', 'Solo', 'Laser'],
+  'Tokenized' => q['Tokenized'],
 );  
 </%shared>
 <%init>
@@ -196,11 +197,23 @@ push @fields, 'payby_payinfo_pretty',
 push @link_onclicks, $sub_receipt, '';
 push @sort_fields, 'paysort', $amount_field;
 
+# 4.x, to remain functional while the upgrade is running...
+my $sub_guess_cardtype = sub {
+  my $row = shift;
+  $row->paycardtype || (
+    ($row->payby eq 'CARD'  && $row->paymask !~ /N\/A/)
+    ? cardtype($row->paymask)
+    : ''
+  )
+};
+
 if ($opt{'show_card_type'}) {
   push @header, emt('Card Type');
   $align .= 'r';
   push @links, '';
-  push @fields, 'paycardtype';
+  push @fields, $sub_guess_cardtype;
+  # worst case, paycardtype isn't filled in yet and sorting by that column
+  # does nothing.
   push @sort_fields, 'paycardtype';
 }
 
@@ -326,20 +339,153 @@ if ( $cgi->param('magic') ) {
 
         if ( $subtype ) {
 
-          if ( $subtype eq 'Tokenized' ) {
-
-            $payby_search .= " AND substring($table.payinfo from 1 for 2 ) = '99' ";
-            # XXX should store the cardtype as 'Tokenized' in this case?
-
-          } else {
+          my $in_cardtype = $cardtype_of{$subtype}
+            or die "unknown card type $subtype";
+          # will complete this phrase after alt_search
+          $payby_search .= " AND ( $table.paycardtype IN($in_cardtype)";
+
+          # 4.x transitional, to avoid breaking things while we upgrade
+          my $similar_to = dbh->{Driver}->{Name} =~ /^mysql/i
+                             ? 'REGEXP' #doesn't behave exactly the same, but
+                                        #should work for our patterns
+                             : 'SIMILAR TO';
+
+          my $alt_search;
+          if ( $subtype eq 'VisaMC' ) {
+
+            #avoid posix regexes for portability
+            $alt_search =
+              # Visa
+              " ( (     substring($table.payinfo from 1 for 1) = '4'     ".
+              #   is not Switch
+              "     AND substring($table.payinfo from 1 for 4) != '4936' ".
+              "     AND substring($table.payinfo from 1 for 6)           ".
+              "         NOT $similar_to '49030[2-9]'                        ".
+              "     AND substring($table.payinfo from 1 for 6)           ".
+              "         NOT $similar_to '49033[5-9]'                        ".
+              "     AND substring($table.payinfo from 1 for 6)           ".
+              "         NOT $similar_to '49110[1-2]'                        ".
+              "     AND substring($table.payinfo from 1 for 6)           ".
+              "         NOT $similar_to '49117[4-9]'                        ".
+              "     AND substring($table.payinfo from 1 for 6)           ".
+              "         NOT $similar_to '49118[1-2]'                        ".
+              "   )".
+              # MasterCard
+              "   OR substring($table.payinfo from 1 for 2) = '51' ".
+              "   OR substring($table.payinfo from 1 for 2) = '52' ".
+              "   OR substring($table.payinfo from 1 for 2) = '53' ".
+              "   OR substring($table.payinfo from 1 for 2) = '54' ".
+              "   OR substring($table.payinfo from 1 for 2) = '54' ".
+              "   OR substring($table.payinfo from 1 for 2) = '55' ".
+              "   OR substring($table.payinfo from 1 for 4) $similar_to '222[1-9]' ".
+              "   OR substring($table.payinfo from 1 for 3) $similar_to '22[3-9]' ".
+              "   OR substring($table.payinfo from 1 for 2) $similar_to '2[3-6]' ".
+              "   OR substring($table.payinfo from 1 for 3) $similar_to '27[0-1]' ".
+              "   OR substring($table.payinfo from 1 for 4) = '2720' ".
+              "   OR substring($table.payinfo from 1 for 3) = '2[2-7]x' ".
+              " ) ";
+
+          } elsif ( $subtype eq 'Amex' ) {
+
+            $alt_search =
+              " (    substring($table.payinfo from 1 for 2 ) = '34' ".
+              "   OR substring($table.payinfo from 1 for 2 ) = '37' ".
+              " ) ";
+
+          } elsif ( $subtype eq 'Discover' ) {
+
+            my $country = $conf->config('countrydefault') || 'US';
+
+            $alt_search =
+              " (    substring($table.payinfo from 1 for 4 ) = '6011'  ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '60x'   ".
+              "   OR substring($table.payinfo from 1 for 2 ) = '65'    ".
+
+              # diner's 300-305 / 3095
+              "   OR substring($table.payinfo from 1 for 3 ) = '300'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '301'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '302'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '303'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '304'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '305'   ".
+              "   OR substring($table.payinfo from 1 for 4 ) = '3095'  ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '30x'   ".
+
+              # diner's 36, 38, 39
+              "   OR substring($table.payinfo from 1 for 2 ) = '36'    ".
+              "   OR substring($table.payinfo from 1 for 2 ) = '38'    ".
+              "   OR substring($table.payinfo from 1 for 2 ) = '39'    ".
+
+              "   OR substring($table.payinfo from 1 for 3 ) = '644'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '645'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '646'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '647'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '648'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '649'   ".
+              "   OR substring($table.payinfo from 1 for 3 ) = '64x'   ".
+
+              # JCB cards in the 3528-3589 range identified as Discover inside US & territories (NOT Canada)
+              ( $country =~ /^(US|PR|VI|MP|PW|GU)$/
+               ?" OR substring($table.payinfo from 1 for 4 ) = '3528'  ".
+                " OR substring($table.payinfo from 1 for 4 ) = '3529'  ".
+                " OR substring($table.payinfo from 1 for 3 ) = '353'   ".
+                " OR substring($table.payinfo from 1 for 3 ) = '354'   ".
+                " OR substring($table.payinfo from 1 for 3 ) = '355'   ".
+                " OR substring($table.payinfo from 1 for 3 ) = '356'   ".
+                " OR substring($table.payinfo from 1 for 3 ) = '357'   ".
+                " OR substring($table.payinfo from 1 for 3 ) = '358'   ".
+                " OR substring($table.payinfo from 1 for 3 ) = '35x'   "
+               :""
+              ).
+
+              #China Union Pay processed as Discover in US, Mexico and Caribbean
+              ( $country =~ /^(US|MX|AI|AG|AW|BS|BB|BM|BQ|VG|KY|CW|DM|DO|GD|GP|JM|MQ|MS|BL|KN|LC|VC|MF|SX|TT|TC)$/
+               ?" OR substring($table.payinfo from 1 for 3 ) $similar_to '62[24-68x]'   "
+               :""
+              ).
+
+              " ) ";
+
+          } elsif ( $subtype eq 'Maestro' ) {
+
+            $alt_search =
+              " (    substring($table.payinfo from 1 for 2 ) = '63'     ".
+              "   OR substring($table.payinfo from 1 for 2 ) = '67'     ".
+              "   OR substring($table.payinfo from 1 for 6 ) = '564182' ".
+              "   OR substring($table.payinfo from 1 for 4 ) = '4936'   ".
+              "   OR substring($table.payinfo from 1 for 6 )            ".
+              "      $similar_to '49030[2-9]'                             ".
+              "   OR substring($table.payinfo from 1 for 6 )            ".
+              "      $similar_to '49033[5-9]'                             ".
+              "   OR substring($table.payinfo from 1 for 6 )            ".
+              "      $similar_to '49110[1-2]'                             ".
+              "   OR substring($table.payinfo from 1 for 6 )            ".
+              "      $similar_to '49117[4-9]'                             ".
+              "   OR substring($table.payinfo from 1 for 6 )            ".
+              "      $similar_to '49118[1-2]'                             ".
+              " ) ";
+
+          } elsif ( $subtype eq 'Tokenized' ) {
+
+              $alt_search = " substring($table.payinfo from 1 for 2 ) = '99' ";
+
+          } else { # shouldn't happen if there's a $subtype
+
+            $alt_search = 'TRUE';
+ 
+          }
 
-            my $in_cardtype = $cardtype_of{$subtype}
-              or die "unknown card type $subtype";
-            $payby_search .= " AND $table.paycardtype IN($in_cardtype)";
+          # alt_search is already paren'd if it contains OR.
+          # now make sure it works if they're encrypted.
+          my $masksearch = $alt_search;
+          $masksearch =~ s/$table.payinfo/$table.paymask/g;
+          $alt_search = "( ($table.paymask IS NOT NULL AND $masksearch)
+                          OR $alt_search )";
 
-          }
+          # close paren here
+          $payby_search .= " OR ( $table.paycardtype IS NULL AND $alt_search ) )";
 
-        }
+        } # if $subtype
 
         push @all_payby_search, $payby_search;
 
@@ -499,8 +645,6 @@ if ( $cgi->param('magic') ) {
     'addl_from' => $addl_from,
   };
 
-warn Dumper \$sql_query;
-
 } else {
 
   #hmm... is this still used?

commit 963f05981025f647b8f9f924e668ae02f8671c58
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Jul 21 19:57:31 2016 -0700

    set card types in a queued job to avoid excessive upgrade time, #71291

diff --git a/FS/FS/payinfo_Mixin.pm b/FS/FS/payinfo_Mixin.pm
index 4f26e8c..5f7ce35 100644
--- a/FS/FS/payinfo_Mixin.pm
+++ b/FS/FS/payinfo_Mixin.pm
@@ -420,15 +420,30 @@ sub paydate_epoch_sql {
 Find all records with a credit card payment type and no paycardtype, and
 replace them in order to set their paycardtype.
 
+This method actually just starts a queue job.
+
 =cut
 
 sub upgrade_set_cardtype {
   my $class = shift;
+  my $table = $class->table or die "upgrade_set_cardtype needs a table";
+
+  if ( ! FS::upgrade_journal->is_done("${table}__set_cardtype") ) {
+    my $job = FS::queue->new({ job => 'FS::payinfo_Mixin::process_set_cardtype' });
+    my $error = $job->insert($table);
+    die $error if $error;
+    FS::upgrade_journal->set_done("${table}__set_cardtype");
+  }
+}
+
+sub process_set_cardtype {
+  my $table = shift;
+
   # assign cardtypes to CARD/DCRDs that need them; check_payinfo_cardtype
   # will do this. ignore any problems with the cards.
   local $ignore_masked_payinfo = 1;
   my $search = FS::Cursor->new({
-    table     => $class->table,
+    table     => $table,
     extra_sql => q[ WHERE payby IN('CARD','DCRD') AND paycardtype IS NULL ],
   });
   while (my $record = $search->fetch) {

commit de94cc4c6e81d762f22e4abb619452d4f13eb944
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Jul 21 15:05:50 2016 -0700

    demand Business::CreditCard 0.36 in package specs

diff --git a/debian/control b/debian/control
index 24ddea3..4de8fee 100644
--- a/debian/control
+++ b/debian/control
@@ -28,7 +28,7 @@ Description: Billing and trouble ticketing for service providers
 Package: freeside-lib
 Architecture: all
 Depends: aspell-en,gnupg,ghostscript,gsfonts,gzip,latex-xcolor,
- libbusiness-creditcard-perl,libcache-cache-perl,
+ libbusiness-creditcard-perl (>= 0.36),libcache-cache-perl,
  libcache-simple-timedexpiry-perl,libchart-perl,libclass-container-perl,
  libclass-data-inheritable-perl,libclass-returnvalue-perl,libcolor-scheme-perl,
  libcompress-zlib-perl,libconvert-binhex-perl,libcrypt-passwdmd5-perl,

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/payinfo_Mixin.pm                             |   17 +-
 debian/control                                     |    2 +-
 httemplate/search/elements/cust_pay_or_refund.html |  172 ++++++++++++++++++--
 3 files changed, 175 insertions(+), 16 deletions(-)




More information about the freeside-commits mailing list