File Coverage

blib/lib/Finance/AMEX/Transaction/GRRCN.pm
Criterion Covered Total %
statement 72 78 92.3
branch 13 24 54.1
condition 2 4 50.0
subroutine 19 19 100.0
pod 2 5 40.0
total 108 130 83.0


line stmt bran cond sub pod time code
1             package Finance::AMEX::Transaction::GRRCN;
2             $Finance::AMEX::Transaction::GRRCN::VERSION = '0.004';
3 8     8   56 use strict;
  8         17  
  8         239  
4 8     8   46 use warnings;
  8         17  
  8         201  
5              
6 8     8   6226 use Text::CSV;
  8         226800  
  8         403  
7              
8 8     8   6527 use Finance::AMEX::Transaction::GRRCN::Header;
  8         33  
  8         270  
9 8     8   5396 use Finance::AMEX::Transaction::GRRCN::Summary;
  8         28  
  8         214  
10 8     8   5257 use Finance::AMEX::Transaction::GRRCN::TaxRecord;
  8         25  
  8         231  
11 8     8   5027 use Finance::AMEX::Transaction::GRRCN::Submission;
  8         26  
  8         221  
12 8     8   4452 use Finance::AMEX::Transaction::GRRCN::Transaction;
  8         47  
  8         274  
13 8     8   4277 use Finance::AMEX::Transaction::GRRCN::TxnPricing;
  8         26  
  8         241  
14 8     8   4667 use Finance::AMEX::Transaction::GRRCN::Chargeback;
  8         27  
  8         223  
15 8     8   4085 use Finance::AMEX::Transaction::GRRCN::Adjustment;
  8         68  
  8         240  
16 8     8   3920 use Finance::AMEX::Transaction::GRRCN::FeeRevenue;
  8         25  
  8         218  
17 8     8   3767 use Finance::AMEX::Transaction::GRRCN::Trailer;
  8         24  
  8         226  
18 8     8   3641 use Finance::AMEX::Transaction::GRRCN::Unknown;
  8         25  
  8         5183  
19              
20             # ABSTRACT: Parse AMEX Global Reconciliation (GRRCN)
21              
22             sub new {
23 2     2 1 9 my ($class, %props) = @_;
24              
25 2         19 my $type_map = {
26             HEADER => 'Finance::AMEX::Transaction::GRRCN::Header',
27             SUMMARY => 'Finance::AMEX::Transaction::GRRCN::Summary',
28             TAXRECORD => 'Finance::AMEX::Transaction::GRRCN::TaxRecord',
29             SUBMISSION => 'Finance::AMEX::Transaction::GRRCN::Submission',
30             TRANSACTN => 'Finance::AMEX::Transaction::GRRCN::Transaction',
31             TXNPRICING => 'Finance::AMEX::Transaction::GRRCN::TxnPricing',
32             CHARGEBACK => 'Finance::AMEX::Transaction::GRRCN::Chargeback',
33             ADJUSTMENT => 'Finance::AMEX::Transaction::GRRCN::Adjustment',
34             FEEREVENUE => 'Finance::AMEX::Transaction::GRRCN::FeeRevenue',
35             TRAILER => 'Finance::AMEX::Transaction::GRRCN::Trailer',
36             };
37              
38 2   50     12 my $file_format = $props{format} || 'UNKNOWN';
39              
40             my $self = bless {
41             _type_map => $type_map,
42             _file_format => $file_format,
43 2   50     16 _version => $props{version} || 1.01,
44             }, $class;
45              
46 2         7 return $self;
47             }
48              
49             sub file_format {
50 416     416 0 819 my ($self) = @_;
51 416         1974 return $self->{_file_format};
52             }
53              
54             sub detect_file_format {
55 2     2 0 7 my ($self, $line) = @_;
56              
57 2 50       13 if (substr($line, 0, 1) eq '"') {
58 2 50       13 if ($line =~ m{","}) {
    0          
59 2         7 $self->{_file_format} = 'CSV';
60             } elsif ($line =~ m{\"\t\"}) {
61 0         0 $self->{_file_format} = 'TSV';
62             }
63              
64 2         6 return $self->{_file_format};
65             }
66 0         0 $self->{_file_format} = 'FIXED';
67 0         0 return $self->{_file_format};
68             }
69              
70             sub parse_line {
71 106     106 1 319 my ($self, $line) = @_;
72              
73 106 100       404 return if not defined $line;
74              
75 104 100       430 if ($self->file_format eq 'UNKNOWN') {
76 2         8 $self->detect_file_format($line);
77             }
78              
79 104         431 my $type = $self->detect_line_type($line);
80              
81 104 50       2331 if (exists $self->{_type_map}->{$type}) {
82              
83             my $parsed = $self->{_type_map}->{$type}->new(
84             line => $line,
85             file_format => $self->file_format,
86             version => $self->{_version},
87 104         429 );
88              
89 104 100       425 if ($type eq 'HEADER') {
90 2         12 $self->{_version} = $parsed->FILE_VERSION_NUMBER;
91             }
92              
93 104         442 return $parsed;
94             }
95              
96 0         0 return Finance::AMEX::Transaction::GRRCN::Unknown->new(line => $line);
97             }
98              
99             sub detect_line_type {
100 104     104 0 310 my ($self, $line) = @_;
101              
102 104 50       272 if ($self->file_format eq 'FIXED') {
103 0         0 return substr($line, 0, 10);
104             }
105              
106 104 50       736 my $csv = Text::CSV->new ({
107             binary => 1,
108             quote_char => '"',
109             escape_char => "\\",
110             }) or die "Cannot use CSV: ".Text::CSV->error_diag ();
111 104         17043 $line =~ s{\s+\z}{}; # csv parser does not like trailing whitespace
112              
113 104 50       398 if ($self->file_format eq 'CSV') {
    0          
114 104         478 $csv->sep_char(',');
115             } elsif ($self->file_format eq 'TSV') {
116 0         0 $csv->sep_char("\t");
117             }
118              
119 104 50       6007 if (my $status = $csv->parse($line)) {
120 104         4402 return ($csv->fields)[0];
121             }
122             }
123              
124             1;
125              
126             __END__