File Coverage

blib/lib/Finance/AMEX/Transaction/GRRCN.pm
Criterion Covered Total %
statement 78 84 92.8
branch 13 24 54.1
condition 2 4 50.0
subroutine 21 21 100.0
pod 6 6 100.0
total 120 139 86.3


line stmt bran cond sub pod time code
1             package Finance::AMEX::Transaction::GRRCN 0.005;
2              
3 9     9   51 use strict;
  9         16  
  9         217  
4 9     9   40 use warnings;
  9         16  
  9         181  
5              
6 9     9   5746 use Text::CSV;
  9         162852  
  9         343  
7 9     9   65 use Carp 'croak';
  9         16  
  9         323  
8              
9 9     9   3361 use Finance::AMEX::Transaction::GRRCN::Header;
  9         22  
  9         223  
10 9     9   3491 use Finance::AMEX::Transaction::GRRCN::Summary;
  9         19  
  9         207  
11 9     9   3405 use Finance::AMEX::Transaction::GRRCN::TaxRecord;
  9         30  
  9         196  
12 9     9   3758 use Finance::AMEX::Transaction::GRRCN::Submission;
  9         29  
  9         198  
13 9     9   3665 use Finance::AMEX::Transaction::GRRCN::Transaction;
  9         23  
  9         198  
14 9     9   3594 use Finance::AMEX::Transaction::GRRCN::TxnPricing;
  9         25  
  9         201  
15 9     9   3690 use Finance::AMEX::Transaction::GRRCN::Chargeback;
  9         24  
  9         196  
16 9     9   3674 use Finance::AMEX::Transaction::GRRCN::Adjustment;
  9         20  
  9         197  
17 9     9   3377 use Finance::AMEX::Transaction::GRRCN::FeeRevenue;
  9         26  
  9         191  
18 9     9   3388 use Finance::AMEX::Transaction::GRRCN::Trailer;
  9         22  
  9         190  
19 9     9   3264 use Finance::AMEX::Transaction::GRRCN::Unknown;
  9         22  
  9         5038  
20              
21             # ABSTRACT: Parse AMEX Global Reconciliation (GRRCN)
22              
23             sub new {
24 8     8 1 27 my ($class, %props) = @_;
25              
26 8         54 my $type_map = {
27             HEADER => 'Finance::AMEX::Transaction::GRRCN::Header',
28             SUMMARY => 'Finance::AMEX::Transaction::GRRCN::Summary',
29             TAXRECORD => 'Finance::AMEX::Transaction::GRRCN::TaxRecord',
30             SUBMISSION => 'Finance::AMEX::Transaction::GRRCN::Submission',
31             TRANSACTN => 'Finance::AMEX::Transaction::GRRCN::Transaction',
32             TXNPRICING => 'Finance::AMEX::Transaction::GRRCN::TxnPricing',
33             CHARGEBACK => 'Finance::AMEX::Transaction::GRRCN::Chargeback',
34             ADJUSTMENT => 'Finance::AMEX::Transaction::GRRCN::Adjustment',
35             FEEREVENUE => 'Finance::AMEX::Transaction::GRRCN::FeeRevenue',
36             TRAILER => 'Finance::AMEX::Transaction::GRRCN::Trailer',
37             };
38              
39 8   50     25 my $file_format = $props{file_format} || 'UNKNOWN';
40 8   50     23 my $file_version = $props{file_version} || 'UNKNOWN';
41              
42 8         24 my $self = bless {
43             _type_map => $type_map,
44             _file_format => $file_format,
45             _file_version => $file_version,
46             }, $class;
47              
48 8         25 return $self;
49             }
50              
51             sub file_format {
52 461     461 1 736 my ($self) = @_;
53 461         1664 return $self->{_file_format};
54             }
55              
56             sub file_version {
57 18     18 1 34 my ($self) = @_;
58 18         46 return $self->{_file_version};
59             }
60              
61             sub detect_file_format {
62 7     7 1 15 my ($self, $line) = @_;
63              
64 7 50       31 if (substr($line, 0, 1) eq '"') {
65 7 50       33 if ($line =~ m{","}xsm) {
    0          
66 7         16 $self->{_file_format} = 'CSV';
67             } elsif ($line =~ m{\"\t\"}xsm) {
68 0         0 $self->{_file_format} = 'TSV';
69             }
70              
71 7         24 return $self->{_file_format};
72             }
73 0         0 $self->{_file_format} = 'FIXED';
74 0         0 return $self->{_file_format};
75             }
76              
77             sub parse_line {
78 112     112 1 226 my ($self, $line) = @_;
79              
80 112 100       335 return if not defined $line;
81              
82 110 100       278 if ($self->file_format eq 'UNKNOWN') {
83 7         18 $self->detect_file_format($line);
84             }
85              
86 110         261 my $type = $self->detect_line_type($line);
87              
88 110 50       1828 if (exists $self->{_type_map}->{$type}) {
89              
90             my $parsed = $self->{_type_map}->{$type}->new(
91             line => $line,
92             file_format => $self->file_format,
93             file_version => $self->{_file_version},
94 110         256 );
95              
96             # We want to set the version when we see the header,
97             # it can change how we parse some of the line types
98 110 100       299 if ($type eq 'HEADER') {
99 8         21 $self->{_file_version} = $parsed->FILE_VERSION_NUMBER;
100             }
101              
102 110         417 return $parsed;
103             }
104              
105 0         0 return Finance::AMEX::Transaction::GRRCN::Unknown->new(line => $line);
106             }
107              
108             sub detect_line_type {
109 110     110 1 261 my ($self, $line) = @_;
110              
111 110 50       246 if ($self->file_format eq 'FIXED') {
112 0         0 return substr($line, 0, 10);
113             }
114              
115 110 50       548 my $csv = Text::CSV->new({
116             binary => 1,
117             quote_char => '"',
118             escape_char => "\\",
119             })
120             or croak 'Cannot use CSV: ' . Text::CSV->error_diag();
121              
122 110         14145 $line =~ s{\s+\z}{}xsm; # csv parser does not like trailing whitespace
123              
124 110 50       304 if ($self->file_format eq 'CSV') {
    0          
125 110         319 $csv->sep_char(',');
126             } elsif ($self->file_format eq 'TSV') {
127 0         0 $csv->sep_char("\t");
128             }
129              
130 110 50       4811 if (my $status = $csv->parse($line)) {
131 110         3867 return ($csv->fields)[0];
132             }
133             }
134              
135             1;
136              
137             __END__