File Coverage

blib/lib/Business/NAB/BPAY/Remittance/File/TrailerRecord.pm
Criterion Covered Total %
statement 42 42 100.0
branch 4 4 100.0
condition 3 3 100.0
subroutine 11 11 100.0
pod 2 2 100.0
total 62 62 100.0


line stmt bran cond sub pod time code
1             package Business::NAB::BPAY::Remittance::File::TrailerRecord;
2             $Business::NAB::BPAY::Remittance::File::TrailerRecord::VERSION = '0.03';
3             =head1 NAME
4              
5             Business::NAB::BPAY::Remittance::File::TrailerRecord
6              
7             =head1 SYNOPSIS
8              
9             use Business::NAB::BPAY::Remittance::File::TrailerRecord;
10              
11             # parse
12             my $Trailer = Business::NAB::BPAY::Remittance::File::TrailerRecord
13             ->new_from_record( $line );
14              
15             # create
16             my $Trailer = Business::NAB::BPAY::Remittance::File::TrailerRecord->new(
17             biller_code => ...
18             number_of_payments => ...
19             amount_of_payments => ...
20             number_of_error_corrections => ...
21             amount_of_error_corrections => ...
22             number_of_reversals => ...
23             amount_of_reversals => ...
24             settlement_amount => ...
25             );
26              
27             my $line = $Trailer->to_record;
28              
29             =head1 DESCRIPTION
30              
31             Class for trailer record in the "BPAY Remittance File"
32              
33             =cut;
34              
35 2     2   1198947 use strict;
  2         5  
  2         91  
36 2     2   12 use warnings;
  2         3  
  2         154  
37 2     2   15 use feature qw/ signatures /;
  2         4  
  2         329  
38              
39 2     2   17 use Carp qw/ croak /;
  2         6  
  2         203  
40 2     2   754 use Moose;
  2         606849  
  2         19  
41 2         212 use Business::NAB::Types qw/
42             add_max_string_attribute
43 2     2   21242 /;
  2         9  
44              
45 2     2   20 no warnings qw/ experimental::signatures /;
  2         7  
  2         1831  
46              
47             =head1 ATTRIBUTES
48              
49             =over
50              
51             =item biller_code (Str, max length 10)
52              
53             =item number_of_payments (NAB::Type::BRFInt)
54              
55             =item amount_of_payments (NAB::Type::BRFInt)
56              
57             =item number_of_error_corrections (NAB::Type::BRFInt)
58              
59             =item amount_of_error_corrections (NAB::Type::BRFInt)
60              
61             =item number_of_reversals (NAB::Type::BRFInt)
62              
63             =item amount_of_reversals (NAB::Type::BRFInt)
64              
65             =item settlement_amount (NAB::Type::BRFInt)
66              
67             =back
68              
69             =cut
70              
71             foreach my $str_attr (
72             'biller_code[10]',
73             ) {
74             __PACKAGE__->add_max_string_attribute(
75             $str_attr,
76             is => 'ro',
77             required => 1,
78             );
79             }
80              
81             foreach my $attr (
82             qw/
83             number_of_payments
84             amount_of_payments
85             number_of_error_corrections
86             amount_of_error_corrections
87             number_of_reversals
88             amount_of_reversals
89             settlement_amount
90             /
91             ) {
92             has $attr => (
93             is => 'ro',
94             isa => 'NAB::Type::BRFInt',
95             required => 1,
96             coerce => 1,
97             trigger => sub {
98             my ( $self, $value, $old_value ) = @_;
99             $self->{ $attr } = int( $value );
100             },
101             );
102             }
103              
104             sub _pack_template {
105 7     7   54 return "A2 A10 A9 A15 A9 A15 A9 A15 A15";
106             }
107              
108             =head1 METHODS
109              
110             =head2 new_from_record
111              
112             Returns a new instance of the class with attributes populated from
113             the result of parsing the passed line:
114              
115             my $Trailer = Business::NAB::BPAY::Remittance::File::TrailerRecord
116             ->new_from_record( $line );
117              
118             =cut
119              
120 3     3 1 24590 sub new_from_record ( $class, $line ) {
  3         9  
  3         8  
  3         8  
121              
122             # undef being "this space intentionally left blank"
123             my (
124 3         15 $record_type,
125             $biller_code,
126             $total_payments,
127             $amount_payments,
128             $total_error,
129             $amount_error,
130             $total_reversals,
131             $amount_reversals,
132             $settlement_amount,
133             ) = unpack( $class->_pack_template(), $line );
134              
135 3 100       17 if ( $record_type ne '99' ) {
136 1         22 croak( "unsupported record type ($record_type)" );
137             }
138              
139 2         140 return $class->new(
140             biller_code => $biller_code,
141             number_of_payments => $total_payments,
142             amount_of_payments => $amount_payments,
143             number_of_error_corrections => $total_error,
144             amount_of_error_corrections => $amount_error,
145             number_of_reversals => $total_reversals,
146             amount_of_reversals => $amount_reversals,
147             settlement_amount => $settlement_amount,
148             );
149             }
150              
151             =head2 to_record
152              
153             Returns a string constructed from the object's attributes, representing
154             the record for use in a batch file:
155              
156             my $line = $Trailer->to_record;
157              
158             =cut
159              
160 4     4 1 11 sub to_record ( $self ) {
  4         11  
  4         9  
161              
162 4         37 my $record = pack(
163             $self->_pack_template(),
164             "99",
165             $self->biller_code,
166             sprintf( "%09s", $self->_brf_int( $self->number_of_payments ) ),
167             sprintf( "%015s", $self->_brf_int( $self->amount_of_payments ) ),
168             sprintf( "%09s", $self->_brf_int( $self->number_of_error_corrections ) ),
169             sprintf( "%015s", $self->_brf_int( $self->amount_of_error_corrections ) ),
170             sprintf( "%09s", $self->_brf_int( $self->number_of_reversals ) ),
171             sprintf( "%015s", $self->_brf_int( $self->amount_of_reversals ) ),
172             sprintf( "%015s", $self->_brf_int( $self->settlement_amount ) ),
173             );
174              
175 4         90 return $record;
176             }
177              
178             sub _brf_int {
179 28     28   68 my ( $self, $str ) = @_;
180              
181             # trailer record amounts in BPAY Remittance Files use the last
182             # character to represent:
183             # - the last digit
184             # - the sign
185             #
186             # it's a little odd, but i guess they've historically had to squeeze
187             # amounts into the 15 available spaces (which are minor units, so 13,
188             # which still feels like a lot, but whatever). this is the *only*
189             # NAB file type that does this, so it might actually be a BPAY thing
190             #
191             # see also: NAB::Type::BRFInt in Business::NAB::Types which will coerce
192             # NAB's value to an actual signed integer
193 28         70 my $last_char = chop( $str );
194              
195 28 100 100     127 if ( $str && $str < 0 ) {
196 1         4 $str *= -1;
197 1         3 $last_char =~ tr/0-9$/}J-R/;
198             } else {
199 27         74 $last_char =~ tr/0-9$/{A-I/;
200             }
201              
202 28         1651 return $str . $last_char;
203             }
204              
205             =head1 SEE ALSO
206              
207             L<Business::NAB::Types>
208              
209             =cut
210              
211             __PACKAGE__->meta->make_immutable;