File Coverage

blib/lib/Business/NAB/Australian/DirectEntry/Report.pm
Criterion Covered Total %
statement 87 87 100.0
branch 5 6 83.3
condition 6 9 66.6
subroutine 13 13 100.0
pod 4 4 100.0
total 115 119 96.6


line stmt bran cond sub pod time code
1             package Business::NAB::Australian::DirectEntry::Report;
2             $Business::NAB::Australian::DirectEntry::Report::VERSION = '0.03';
3             =head1 NAME
4              
5             Business::NAB::Australian::DirectEntry::Report
6              
7             =head1 SYNOPSIS
8              
9             use Business::NAB::Australian::DirectEntry::Report;
10              
11             # parse;
12             my $Report = Business::NAB::Australian::DirectEntry::Report
13             ->new_from_file( $file_path );
14              
15             foreach my $Credit (
16             grep { $_->is_credit } $Report->payment_record->@*
17             ) {
18             ...
19             }
20              
21             # build
22             my $Report = Business::NAB::Australian::DirectEntry::Report->new;
23              
24             $Report->add_header_record(
25             .. # Business::NAB:: ... HeaderRecord object
26             );
27              
28             $Report->add_payment_record(
29             .. # Business::NAB:: ... PaymentRecord object
30             ) for ( @payments );
31              
32             $Report->to_file(
33             $file_path,
34             $separator, # defaults to "\r\n"
35             );
36              
37             =head1 DESCRIPTION
38              
39             Class for building/parsing a Australian Direct Entry Reports file
40              
41             =cut
42              
43 1     1   1331949 use strict;
  1         2  
  1         46  
44 1     1   6 use warnings;
  1         2  
  1         75  
45 1     1   6 use feature qw/ signatures /;
  1         3  
  1         216  
46 1     1   611 use autodie qw/ :all /;
  1         21570  
  1         5  
47 1     1   25928 use Carp qw/ croak /;
  1         3  
  1         87  
48              
49 1     1   805 use Moose;
  1         584268  
  1         10  
50             with 'Business::NAB::Role::AttributeContainer';
51             extends 'Business::NAB::FileContainer';
52              
53 1     1   8459 use Moose::Util::TypeConstraints;
  1         2  
  1         8  
54 1     1   2475 no warnings qw/ experimental::signatures /;
  1         2  
  1         82  
55              
56 1     1   11 use List::Util qw/ sum0 /;
  1         3  
  1         1205  
57              
58             # we have long namespaces and use them multiple times so have
59             # normalised them out into the $parent and @subclasses below
60             my $parent = 'Business::NAB::Australian::DirectEntry::Report';
61              
62             my @subclasses = (
63             qw/
64             HeaderRecord
65             PaymentRecord
66             ValueSummary
67             FailedRecord
68             FailedSummary
69             TrailerRecord
70             DisclaimerRecord
71             /
72             );
73              
74             =head1 ATTRIBUTES
75              
76             All attributes are ArrayRef[Obj] where Obj are of the Business::NAB::Australian::DirectEntry::Report::* namespace:
77              
78             HeaderRecord
79             PaymentRecord
80             ValueSummary
81             FailedRecord
82             FailedSummary
83             TrailerRecord
84             DisclaimerRecord
85              
86             Convenience methods are available for trivial addition of new elements
87             to the arrays:
88              
89             $Report->add_header_record( $HeaderRecord );
90             $Report->add_payment_record( $PaymentRecord );
91             $Report->add_value_summary( $ValueSummary );
92             $Report->add_failed_record( $FailedRecord );
93             $Report->add_failed_summary( $FailedSummary );
94             $Report->add_trailer_record( $TrailerRecord );
95             $Report->add_disclaimer_record( $DisclaimerRecord );
96              
97             =over
98              
99             =item header_record (ArrayRef[Obj])
100              
101             =item payment_record (ArrayRef[Obj])
102              
103             =item value_summary (ArrayRef[Obj])
104              
105             =item failed_record (ArrayRef[Obj])
106              
107             =item failed_summary (ArrayRef[Obj])
108              
109             =item trailer_record (ArrayRef[Obj])
110              
111             =item disclaimer_record (ArrayRef[Obj])
112              
113             =back
114              
115             =cut
116              
117             __PACKAGE__->load_attributes( $parent, @subclasses );
118              
119             =head1 METHODS
120              
121             =head2 new_from_file
122              
123             Returns a new instance of the class with attributes populated from
124             the result of parsing the passed file
125              
126             my $Payments = Business::NAB::Australian::DirectEntry::Report
127             ->new_from_file( $file_path );
128              
129             =cut
130              
131 1     1 1 3061 sub new_from_file ( $class, $file ) {
  1         4  
  1         2  
  1         3  
132              
133 1         16 my %sub_class_map = (
134             '00' => 'HeaderRecord',
135             '53' => 'PaymentRecord',
136             '54' => 'ValueSummary',
137             '57' => 'PaymentRecord',
138             '58' => 'ValueSummary',
139             '61' => 'FailedRecord',
140             '62' => 'FailedSummary',
141             '99' => 'TrailerRecord',
142             '100' => 'DisclaimerRecord',
143             );
144              
145 1         67 my $self = $class->new;
146              
147 1         14 return $self->SUPER::new_from_file(
148             $parent, $file, \%sub_class_map, ','
149             );
150             }
151              
152             =head2 to_file
153              
154             Writes the file content to the passed file path:
155              
156             $Report->to_file(
157             $file_path,
158             $separator, # defaults to "\r\n"
159             );
160              
161             =cut
162              
163             sub to_file (
164 3         8 $self,
165 3         9 $file,
166 3         50 $sep = "\r\n",
167 3     3 1 15701 ) {
  3         8  
168 3         22 open( my $fh, '>', $file );
169              
170 3         3047 print $fh $self->header_record->[ 0 ]->to_record . $sep;
171              
172 3         13 my $class = "Business::NAB::Australian::DirectEntry::Report::ValueSummary";
173 3         6 my @records;
174              
175 3         12 foreach my $type ( qw/ credit debit / ) {
176              
177 6         36 my $check = "is_${type}";
178 6         35 my @payments = grep { $_->$check } $self->payment_record->@*;
  18         185  
179 6         72 print $fh $_->to_record . $sep foreach ( @payments );
180              
181 6         37 my ( $ValueSummary ) = grep { $_->$check } $self->value_summary->@*;
  8         79  
182              
183             $ValueSummary //= $class->new(
184             record_type => $type eq 'credit' ? '54' : '58',
185             sub_trancode => 'UVD',
186             number_of_items => scalar( @payments ),
187 6 100 66     45 total_of_items => sum0 map { $_->amount } @payments,
  3         194  
188             );
189              
190 6         35 print $fh $ValueSummary->to_record . $sep;
191              
192 6         160 push( @records, @payments );
193             }
194              
195 3         10 $class = "Business::NAB::Australian::DirectEntry::Report::FailedSummary";
196              
197 3 50       21 if ( my @failed = $self->failed_record->@* ) {
198              
199 3         56 print $fh $_->to_record . $sep foreach ( @failed );
200              
201 3         42 my ( $FailedSummary ) = $self->failed_summary->@*;
202              
203             $FailedSummary //= $class->new(
204             sub_trancode => 'UXS',
205             number_of_items => scalar( @failed ),
206             failed_item_treatment_option => 1,
207             text => 'Failed items will be returned as individual '
208             . 'items to your trace account.',
209 3   66     35 total_of_items => sum0 map { $_->amount } @failed,
  1         70  
210             );
211              
212 3         28 print $fh $FailedSummary->to_record . $sep;
213              
214 3         78 push( @records, @failed );
215             }
216              
217 3 100       23 if ( my ( $TrailerRecord ) = $self->trailer_record->@* ) {
218 2         34 print $fh $TrailerRecord->to_record . $sep;
219             } else {
220              
221 1         12 my $credit_total = sum0 map { $_->amount } grep { $_->is_credit }
  3         224  
  4         36  
222             @records;
223              
224 1         4 my $debit_total = sum0 map { $_->amount } grep { $_->is_debit }
  1         65  
  4         31  
225             @records;
226              
227 1         3 $class = "Business::NAB::Australian::DirectEntry::Report::TrailerRecord";
228 1         71 $TrailerRecord = $class->new(
229             net_file_total => $credit_total - $debit_total,
230             credit_file_total => $credit_total,
231             debit_file_total => $debit_total,
232             total_number_of_records => scalar( @records ),
233             );
234              
235 1         7 print $fh $TrailerRecord->to_record . $sep;
236             }
237              
238 3         12 $class = "Business::NAB::Australian::DirectEntry::Report::DisclaimerRecord";
239 3         22 my ( $DisclaimerRecord ) = $self->disclaimer_record->@*;
240 3   66     193 $DisclaimerRecord //= $class->new(
241             text => "(c) 2012 National Australia Bank Limit ABN 12 004 044 937",
242             );
243              
244 3         23 print $fh $DisclaimerRecord->to_record . $sep;
245              
246 3         22 close( $fh );
247              
248 3         2373 return;
249             }
250              
251             =head2 original_filename
252              
253             An alias for the header_record C<import_file_name>
254              
255             =cut
256              
257 1     1 1 4 sub original_filename ( $self ) {
  1         2  
  1         4  
258 1         8 $self->header_record->[ 0 ]->import_file_name;
259             }
260              
261             =head2 status
262              
263             Hardcoded to "PROCESSED" - as per NAB's documentation that states
264             "This report assists with confirming the processing of your payment
265             file..."
266              
267             =cut
268              
269 1     1 1 1225 sub status ( $self ) { 'PROCESSED' }
  1         3  
  1         3  
  1         5  
270              
271             =head1 SEE ALSO
272              
273             L<Business::NAB::Australian::DirectEntry::Report::PaymentRecord>
274              
275             L<Business::NAB::Australian::DirectEntry::Report::ValueSummary>
276              
277             L<Business::NAB::Australian::DirectEntry::Report::FailedRecord>
278              
279             L<Business::NAB::Australian::DirectEntry::Report::FailedSummary>
280              
281             =cut
282              
283             __PACKAGE__->meta->make_immutable;