File Coverage

blib/lib/Business/TW/TSIB/VirtualAccount.pm
Criterion Covered Total %
statement 24 67 35.8
branch 1 14 7.1
condition 0 6 0.0
subroutine 4 9 44.4
pod 3 3 100.0
total 32 99 32.3


line stmt bran cond sub pod time code
1             package Business::TW::TSIB::VirtualAccount;
2              
3 3     3   85917 use warnings;
  3         7  
  3         104  
4 3     3   18 use strict;
  3         5  
  3         103  
5 3     3   2004 use Business::TW::TSIB::VirtualAccount::Entry;
  3         11  
  3         27  
6              
7             =head1 NAME
8              
9             Business::TW::TSIB::VirtualAccount - Module for Taishin Bank Virtual Account Management
10              
11             =head1 VERSION
12              
13             Version 0.03
14              
15             =cut
16              
17             our $VERSION = '0.04';
18              
19             =head1 SYNOPSIS
20              
21             use Business::TW::TSIB::VirtualAccount;
22             my $va = Business::TW::TSIB::VirtualAccount->new({ corp_code => '95678' });
23             my $acc = $va->generate( { due => DateTime->new( year => 2007, month => 4, day => 2 )
24             amount => 3900,
25             ar_id => '2089' } );
26             # $acc should be '95286092208929'
27             # total 14 columns
28            
29             my $entries = Business::TW::TSIB::VirtualAccount->parse_summary($fh);
30              
31             # entries is arrayref of Business::TW::TSIB::VirtualAccount::Entry objects,
32             # which has the following accessors:
33              
34             * response_code
35             * account
36             * date
37             * seqno
38             * flag
39             * time
40             * txn_type
41             * amount
42             * postive
43             * entry_type
44             * virtual_account
45             * id
46             * from_bank
47             * comment
48             * preserved
49             * status
50              
51             =head1 DESCRIPTION
52              
53             This module provides utility functions for the virtual account service
54             by TSIB (Taishin International Bank, Taiwan).
55              
56             =head1 METHODS
57              
58             =head2 new( { corp_code => $corp_code} )
59              
60             Initialize the virtual account context with C provided by
61             TSIB.
62              
63             =cut
64              
65             sub new {
66 0     0 1 0 my $class = shift;
67 0         0 my $args = shift;
68 0         0 my $self = {};
69 0 0       0 die("No Given Corperation Code")
70             if ( !exists( $args->{corp_code} ) );
71              
72 0 0       0 die("Coperation code needs 5 columns")
73             if ( length( "$args->{corp_code}" ) != 5 );
74              
75 0         0 $self->{corp_code} = $args->{corp_code};
76 0         0 return bless $self, $class;
77             }
78              
79             =head2 $va->generate( $args )
80              
81             Generate a virtual account with the given arguments. $args is a hash ref and must contain:
82              
83             =over
84              
85             =item due
86              
87             A L object for due day of the payment
88              
89             =item amount
90              
91             The expected amount of the transaction.
92              
93             =item ar_id
94              
95             The arbitary account receivable identifier.
96              
97             =back
98              
99             =cut
100              
101             sub generate {
102 0     0 1 0 my $self = shift;
103 0         0 my $args = shift;
104              
105 0 0       0 map { die("No Given $_") if ( !exists( $args->{$_} ) ) }
  0         0  
106             qw/due amount ar_id/;
107              
108 0 0       0 die("ar_id needs 4 columns") if ( length("$args->{ar_id}") != 4 ) ;
109              
110             # generate account
111             #
112             # format:
113             # | corp_code ( 5 ) | date_code ( 4 ) | ar_id ( 4 ) | checksum ( 1 ) |
114             #
115             # total 14 columns
116              
117 0         0 my $account
118             = $self->{corp_code}
119             . $self->_gen_datecode($args)
120             . $args->{ar_id}; # 13 columns
121            
122 0 0       0 die('Error: Column lenght of account don\'t correspond to 13')
123             if ( length($account) != 13 );
124              
125 0         0 return $self->_gen_checksum( $account, $args ); # 14 columns , checksum appended
126             }
127              
128             sub _gen_datecode {
129 0     0   0 my $self = shift;
130 0         0 my $args = shift;
131 0         0 return sprintf( "%d%03d",
132             ( $args->{due}->year - 1 ) % 10,
133             $args->{due}->day_of_year );
134             }
135              
136             sub _get_amountcode {
137 0     0   0 my $self = shift;
138 0         0 my $args = shift;
139 0         0 my @as = reverse split( //, "$args->{amount}" );
140 0         0 my $amount_code = 0;
141 0   0     0 map {
      0        
142 0         0 $amount_code += ( ( $as[$_] || 0 ) + ( $as[ 6 - $_ ] || 0 ) ) * ( 5 - $_ )
143             } ( 0, 1, 2 );
144 0   0     0 $amount_code += ( $as[3] || 0 ) * 2;
145 0         0 return $amount_code;
146             }
147              
148             sub _gen_checksum {
149 0     0   0 my $self = shift;
150 0         0 my $account = shift;
151 0         0 my $args = shift;
152              
153             # gen amount code
154 0         0 my $amount_code = $self->_get_amountcode( $args );
155              
156             # gen checksum
157 0         0 my @c = split( //, $account );
158 0         0 my @c_odd = @c[ 0, 2, 4, 6, 8, 10, 12 ];
159 0         0 my @c_even = @c[ 1, 3, 5, 7, 9, 11 ];
160 0         0 my ( $sum_odd, $sum_even ) = ( 0, 0 );
161 0         0 map { $sum_odd += $_; } @c_odd;
  0         0  
162 0         0 map { $sum_even += $_; } @c_even;
  0         0  
163 0         0 my $checksum = $sum_odd * 3 + $sum_even + $amount_code ;
164 0         0 $checksum %= 10; # mod
165 0         0 $checksum = 10 - $checksum; # 10's complement
166 0 0       0 $checksum = 0 if ( $checksum == 10 );
167 0         0 return $account . $checksum;
168              
169             }
170              
171             =head2 $self->parse_summary($fh)
172              
173             =cut
174              
175             sub parse_summary {
176 1     1 1 2283 my $self = shift;
177 1         3 my $fh = shift;
178              
179             # format:
180             #
181             # 4 # response code
182             # 14 # account
183             # 8 # date
184             # 6 # sequence number (seqno)
185             # 1 # flag
186             # 6 # time
187             # 4 # transaction type
188             # 12 # amount
189             # 1 # postive
190             # 1 # entry type
191             # 16 # virtual account
192             # 10 # ID Card
193             # 3 # from bank
194             # 20 # comment
195             # 18 # preserve
196             # 1 # status
197              
198 1         2 my @entries;
199 1         14 while (<$fh>) {
200 10         25 chomp;
201 10 50       31 next unless length $_;
202              
203 10         18 my %cols;
204              
205             @cols{
206 10         181 qw/
207             response_code
208             account
209             date
210             seqno
211             flag
212             time
213             txn_type
214             amount
215             postive
216             entry_type
217             virtual_account
218             id
219             from_bank
220             comment
221             preserved
222             status/
223             }
224             = (
225             m/
226             (.{4}) # response code
227             (.{14}) # account
228             (.{8}) # date
229             (.{6}) # seqno
230             (.{1}) # flag
231             (.{6}) # time
232             (.{4}) # transaction type
233             (.{12}) # amount
234             (.{1}) # postive
235             (.{1}) # entry type
236             (.{16}) # virtual account
237             (.{10}) # ID Card
238             (.{3}) # from_bank
239             (.{20}) # comment
240             (.{18}) # preserve
241             (.{1}) # status
242             /x
243             );
244              
245             # trim
246 10         58 map { $cols{$_} =~ s/\s*$//g; $cols{$_} =~ s/^\s*//g; } keys %cols;
  160         717  
  160         572  
247 10         37 $cols{amount} /= 10;
248 10         42 my $entry = Business::TW::TSIB::VirtualAccount::Entry->new( \%cols );
249 10         595 push @entries, $entry;
250             }
251 1         6 return \@entries;
252             }
253              
254             =head1 AUTHOR
255              
256             Chia-liang Kao, C<< >> ,
257             You-An Lin, C<< >>
258              
259             =head1 BUGS
260              
261             Please report any bugs or feature requests to
262             C, or through the web interface at
263             L.
264             I will be notified, and then you'll automatically be notified of progress on
265             your bug as I make changes.
266              
267             =head1 SUPPORT
268              
269             You can find documentation for this module with the perldoc command.
270              
271             perldoc Business::TW::TSIB::VirtualAccount
272              
273             You can also look for information at:
274              
275             =over 4
276              
277             =item * AnnoCPAN: Annotated CPAN documentation
278              
279             L
280              
281             =item * CPAN Ratings
282              
283             L
284              
285             =item * RT: CPAN's request tracker
286              
287             L
288              
289             =item * Search CPAN
290              
291             L
292              
293             =back
294              
295             =head1 ACKNOWLEDGEMENTS
296              
297             =head1 COPYRIGHT & LICENSE
298              
299             Copyright 2007 AIINK co., ltd, all rights reserved.
300              
301             This program is free software; you can redistribute it and/or modify it
302             under the same terms as Perl itself.
303              
304             =cut
305              
306              
307              
308              
309              
310             1; # End of Business::TW::TSIB::VirtualAccount