File Coverage

blib/lib/Business/Westpac/PaymentsPlus/Australian/Payment/Import/File.pm
Criterion Covered Total %
statement 52 52 100.0
branch 6 6 100.0
condition 2 2 100.0
subroutine 16 16 100.0
pod 1 2 50.0
total 77 78 98.7


line stmt bran cond sub pod time code
1             package Business::Westpac::PaymentsPlus::Australian::Payment::Import::File;
2              
3             =head1 NAME
4              
5             Business::Westpac::PaymentsPlus::Australian::Payment::Import::File
6              
7             =head1 SYNOPSIS
8              
9             my $ImportFile = Business::Westpac::PaymentsPlus::Australian::Payment::Import::File->new(
10             customer_code => 'TESTPAYER',
11             customer_name => 'TESTPAYER',
12             customer_file_reference => 'TESTFILE001',
13             scheduled_date => '26082016',
14             );
15              
16             $ImportFile->add_eft_record(
17             eft => \%eft_details,
18             remittance => \%remittance_details,
19             invoices => [
20             \%invoice_details,
21             \%second_invoice_details,
22             ]
23             );
24              
25             $ImportFile->add_osko_record( ... );
26             $ImportFile->add_cheque_record( ... );
27             $ImportFile->add_bpay_record( ... );
28             $ImportFile->add_realtime_record( ... );
29             $ImportFile->add_remittance_only_record( ... );
30             $ImportFile->add_overseas_telegraphic_transfer_record( ... );
31              
32              
33             =head1 DESCRIPTION
34              
35             This class implements the format as defined by Westpac at https://paymentsplus.westpac.com.au/docs/file-formats/australian-payment-import-csv
36              
37             This class follows the structure and validation rules in the spec,
38             and delegates most of this to the subclasses (SEE ALSO below)
39              
40             =cut
41              
42 1     1   462368 use feature qw/ signatures /;
  1         3  
  1         142  
43              
44 1     1   884 use Moose;
  1         612942  
  1         6  
45             with 'Business::Westpac::Role::CSV';
46 1     1   7829 no warnings qw/ experimental::signatures /;
  1         2  
  1         42  
47              
48 1     1   4 use Carp qw/ croak /;
  1         2  
  1         59  
49 1     1   842 use Module::Load;
  1         1569  
  1         6  
50              
51 1         1582 use Business::Westpac::Types qw/
52             add_max_string_attribute
53 1     1   673 /;
  1         9  
54              
55             # we have long namespaces and use them multiple times so have
56             # normalised them out into the $parent and @subclasses below
57             my $parent = 'Business::Westpac::PaymentsPlus::Australian::Payment::Import';
58              
59             my @subclasses = ( qw/
60             FileHeader
61             Invoice
62             Payment::BPAY
63             Payment::Cheque
64             Payment::EFT
65             Payment::OTT
66             Payment::Osko
67             Payment::RealTime
68             Payment::RemittanceOnly
69             Remittance
70             Trailer
71             / );
72              
73             load $parent . "::$_" for @subclasses;
74              
75             has 'records' => (
76             traits => [ 'Array' ],
77             is => 'rw',
78             isa => "ArrayRef[ " .
79             join( " | ",map { "${parent}::$_" } @subclasses ) . "
80             ]",
81             default => sub { [] },
82             handles => {
83             _add_record => 'push',
84             },
85             );
86              
87             has 'count' => (
88             traits => [ 'Number' ],
89             is => 'rw',
90             isa => 'Num',
91             default => sub { 0 },
92             handles => {
93             _add_payment => 'add'
94             },
95             );
96              
97             has 'amount' => (
98             traits => [ 'Number' ],
99             is => 'rw',
100             isa => 'Num',
101             default => sub { 0 },
102             handles => {
103             _add_amount => 'add'
104             },
105             );
106              
107             foreach my $str_attr (
108             'CustomerCode[10]',
109             'CustomerName[40]',
110             'CustomerFileReference[20]',
111             ) {
112             __PACKAGE__->add_max_string_attribute(
113             $str_attr,
114             is => 'ro',
115             required => 1,
116             );
117             }
118              
119             has 'scheduled_date' => (
120             is => 'ro',
121             isa => 'WestpacDate',
122             required => 1,
123             coerce => 1,
124             handles => {
125             scheduled_csv_date => [ strftime => '%d%m%C%y' ],
126             },
127             );
128              
129             has 'currency' => (
130             is => 'ro',
131             isa => 'Str',
132             required => 0,
133             default => sub { 'AUD' },
134             );
135              
136             has 'version' => (
137             is => 'ro',
138             isa => 'Str',
139             required => 0,
140             default => sub { '6' },
141             );
142              
143 1     1 0 4 sub record_type { 'H' }
144              
145             =head1 METHODS
146              
147             =head2 to_csv
148              
149             Return an array of CSV lines for output
150              
151             my @csv = $self->to_csv;
152              
153             The returned lines will contain the entire file structure ready for
154             output, including the header and trailers.
155              
156             =cut
157              
158 1     1 1 3 sub to_csv ( $self ) {
  1         3  
  1         2  
159              
160             # header line
161 1         11 my @csv = $self->attributes_to_csv( qw/
162             record_type
163             customer_code
164             customer_name
165             customer_file_reference
166             scheduled_csv_date
167             currency
168             version
169             / );
170              
171             # payment records
172             push( @csv,$_->to_csv )
173 1         90 foreach $self->records->@*;
174              
175             # trailer line
176 1         77 push(
177             @csv,
178             $self->values_to_csv(
179             'T',$self->count,$self->amount
180             )
181             );
182              
183 1         52 return @csv;
184             }
185              
186             =head2 add_eft_record (E)
187              
188             =head2 add_osko_record (O)
189              
190             =head2 add_realtime_record (RT)
191              
192             =head2 add_overseas_telegraphic_transfer_record (OTT)
193              
194             =head2 add_bpay_record (B)
195              
196             =head2 add_cheque_record (C)
197              
198             =head2 add_remittance_only_record (RO)
199              
200             Add payment records to the file, optionally adding remittance and invoice
201             records. As per the Westpac spec some record types require remittance
202             and others have them as an option:
203              
204             Type Remittance Invoice
205              
206             E 0..1 0..n
207             O 0..1 0..n
208             RT 0..1 0..n
209             OTT 0..1 0..n
210             B 0..1 0..n
211             C 1 0..n
212             RO 1 0..n
213              
214             Each method expects a hash with the attributes to populate the objects
215             that will be instantiated, with the key names being those used for the
216             method name C<add_${key_name}_record>, for example:
217              
218             $ImportFile->add_eft_record(
219              
220             # refer to Business::Westpac::PaymentsPlus::Australian::Payment::Import::Payment::EFT
221             eft => {
222             payer_payment_reference => 'REF00001',
223             payment_amount => '36.04',
224             recipient_reference => 'REF00001',
225             account_number => '000002',
226             account_name => 'Payee 02',
227             bsb_number => '062-000',
228             funding_bsb_number => '032-000',
229             funding_account_number => '000007',
230             remitter_name => 'Remitter Name',
231             },
232              
233             # optional (in most cases) remittance and invoice lines
234             # refer to Business::Westpac::PaymentsPlus::Australian::Payment::Import::Invoice
235             # and Business::Westpac::PaymentsPlus::Australian::Payment::Import::Remittance
236             remittance => { ... },
237             invoices => [ { ... },{ ... }, ... ],
238             );
239              
240             =cut
241              
242             foreach my $payment_type (
243             [ qw/ EFT eft / ],
244             [ qw/ Osko osko / ],
245             [ qw/ RealTime realtime / ],
246             [ qw/ OTT overseas_telegraphic_transfer / ],
247             [ qw/ BPAY bpay / ],
248             [ qw/ Cheque cheque 1 / ],
249             [ qw/ RemittanceOnly remittance_only 1 / ],
250             ) {
251             my ( $class,$key_name,$requires_remit ) = $payment_type->@*;
252             my $sub = "add_${key_name}_record";
253              
254 11         28 __PACKAGE__->meta->add_method(
255 11     11   115929 $sub => sub ( $self,%records ) {
  11     11   38  
  11     11   23  
        11      
        11      
        11      
        11      
256              
257 11 100       38 if ( $requires_remit ) {
258 5 100       62 $records{remittance} || croak(
259             "$class records must have a remittance"
260             );
261             }
262              
263             return $self->_add_payment_object_to_records(
264 9         40 $class,$records{$key_name},\%records
265             );
266             },
267             );
268             }
269              
270             sub _add_payment_object_to_records (
271 9         17 $self,
272 9         19 $subclass,
273 9         17 $attributes,
274 9         17 $records = {},
275 9     9   66 ) {
  9         16  
276 9         22 my $parent = 'Business::Westpac::PaymentsPlus::Australian::Payment::Import';
277 9         25 my $class = "${parent}::Payment::${subclass}";
278              
279 9         824 $self->_add_record(
280             my $Record = $class->new( $attributes->%* )
281             );
282              
283 8         647 $self->_add_payment( 1 );
284 8         605 $self->_add_amount( $Record->payment_amount );
285              
286 8 100       31 if ( $records->{remittance} ) {
287 5         14 my $class = "${parent}::Remittance";
288             $self->_add_record(
289             $class->new( $records->{remittance}->%* )
290 5         436 );
291             }
292              
293 8   100     27 foreach my $invoice ( @{ $records->{invoices} // [] } ) {
  8         54  
294 3         9 my $class = "${parent}::Invoice";
295 3         234 $self->_add_record(
296             $class->new( $invoice->%* )
297             );
298             }
299              
300 8         44 return $Record;
301             }
302              
303             __PACKAGE__->meta->make_immutable;
304              
305             =head1 SEE ALSO
306              
307             Business::Westpac::PaymentsPlus::Australian::Payment::Import...
308              
309             =over 4
310              
311             ::FileHeader
312              
313             ::Invoice
314              
315             ::Payment
316              
317             ::Payment::Cheque
318              
319             ::Payment::EFT
320              
321             ::Payment::Okso
322              
323             ::Payment::OTT
324              
325             ::Payment::RealTime
326              
327             ::Remittance
328              
329             ::Remittance::Only
330              
331             L<Business::Westpac::Types>
332              
333             =back
334              
335             =cut