RT# 83450 - fixed rateplan export
[freeside.git] / FS / FS / pay_batch / td_eft1464.pm
1 package FS::pay_batch::td_eft1464;
2
3 use strict;
4 use vars qw(@ISA %import_info %export_info $name);
5 use Date::Format 'time2str';
6 use FS::Conf;
7 use FS::Record qw(qsearch);
8
9 =head1 NAME
10
11 td_eft1464 - TD Commercial Banking EFT1464 format
12
13 =head1 CONFIGURATION
14
15 The Freeside option 'batchconfig-td_eft1464' must be set 
16 with the following values on separate lines:
17
18 =over 4
19
20 =item Originator ID
21
22 =item TD Datacenter Location
23
24 00400 - Vancouver
25 00410 - Montreal
26 00420 - Toronto
27 00430 - Halifax
28 00470 - Winnipeg
29 00490 - Calgary
30
31 =item Short Name
32
33 =item Long Name
34
35 =item Returned Payment Branch (5 digits)
36
37 =item Returned Payment Account
38
39 =item Transaction Type Code - defaults to "437" (Internet access)
40
41 =back
42
43 =cut
44
45 my $conf;
46 my %opt;
47 my $i;
48
49 $name = 'td_eft1464';
50 # TD Bank EFT 1464 Byte format
51 # https://www.payments.ca/sites/default/files/standard-005.pdf
52
53 %import_info = ( filetype => 'NONE' ); 
54 # just to suppress warning; importing this format is a fatal error
55
56 %export_info = (
57   delimiter => '',
58   init => sub {
59     $conf = shift;
60     @opt{
61       'origid',
62       'datacenter',
63       'shortname',
64       'longname',
65       'retbranch',
66       'retacct',
67       'cpacode',
68     } = $conf->config("batchconfig-td_eft1464");
69     $opt{'origid'} = sprintf('%-10.10s', $opt{'origid'});
70     $opt{'shortname'} = sprintf('%-15.15s', $opt{'shortname'});
71     $opt{'longname'} = sprintf('%-30.30s', $opt{'longname'});
72     $opt{'retbranch'} = '0004'.sprintf('%5.5s',$opt{'retbranch'});
73     $opt{'retacct'} = sprintf('%-11.11s', $opt{'retacct'}). ' ';
74     $i = 1;
75   },
76   header => sub { 
77     my $pay_batch = shift;
78     my @cust_pay_batch = @{(shift)};
79     my $time = $pay_batch->download || time;
80     my $now = sprintf("%03u%03u", 
81       (localtime(time))[5] % 100,#year since 1900
82       (localtime(time))[7]+1);#day of year
83
84     # Request settlement the next day
85     my $duedate = time+86400;
86     $opt{'due'} = sprintf("%03u%03u",
87       (localtime($duedate))[5] % 100,
88       (localtime($duedate))[7]+1);
89
90     $opt{'fcn'} = 
91       sprintf('%04u', ($pay_batch->batchnum % 9999)+1), # file creation number
92     join('',
93       'A', #record type
94       sprintf('%09u', 1), #record number
95       $opt{'origid'},
96       $opt{'fcn'},
97       $now,
98       $opt{'datacenter'},
99       ' ' x 1429, #filler
100     );
101   },
102   row => sub {
103     my ($cust_pay_batch, $pay_batch) = @_;
104     my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
105     if ( $aba =~ /^(\d+)\.(\d+)$/ ) {  #branch.route
106       $aba = $2.$1; #routebranch
107     }
108     $i++;
109     # The 1464 byte format supports up to 5 payments per line,
110     # but we're only going to send 1.
111
112     ## set to D for debit by default, then override to what cust_pay_batch has as payments may not have paycode.
113     my $debitorcredit = 'D';
114     $debitorcredit = $cust_pay_batch->paycode unless !$cust_pay_batch->paycode;
115
116     my $control = join('',
117       $debitorcredit,       # D for 'debit' or C for Credit
118       sprintf("%09u", $i),  #record number
119       $opt{'origid'},
120       $opt{'fcn'},
121     );
122     my $payment = join('',
123       $opt{'cpacode'} || 437, # CPA code, defaults to "Internet access"
124       sprintf('%010.0f', $cust_pay_batch->amount*100),
125       $opt{'due'}, #due date...? XXX
126       sprintf('%09u', $aba),
127       sprintf('%-12.12s', $account),
128       '0' x 22,
129       '0' x 3,
130       $opt{'shortname'},
131       sprintf('%-30.30s', 
132         join(' ',
133           $cust_pay_batch->first, $cust_pay_batch->last)
134       ),
135       $opt{'longname'},
136       $opt{'origid'},
137       sprintf('%-19.19s', $cust_pay_batch->paybatchnum), # originator reference num
138       $opt{'retbranch'},
139       $opt{'retacct'}, 
140       ' ' x 15,
141       ' ' x 22,
142       ' ' x 2,
143       '0' x 11,
144     );
145     return sprintf('%-1464s',$control . $payment) ;
146   },
147   footer => sub {
148     my ($pay_batch, $batchcount, $batchtotal) = @_;
149     my $totaldebittxns = $pay_batch->type eq "DEBIT" ? $batchtotal*100 : 0;
150     my $countdebittxns = $pay_batch->type eq "DEBIT" ? $batchcount : 0;
151     my $totalcredittxns = $pay_batch->type eq "CREDIT" ? $batchtotal*100 : 0;
152     my $countcredittxns = $pay_batch->type eq "CREDIT" ? $batchcount : 0;
153     join('',
154       'Z',
155       sprintf('%09u', $batchcount + 2),
156       $opt{'origid'}, 
157       $opt{'fcn'},
158       sprintf('%014.0f', $totaldebittxns), # total of debit txns
159       sprintf('%08u', $countdebittxns), # number of debit txns
160       sprintf('%014.0f', $totalcredittxns), # total of debit txns
161       sprintf('%08u', $countcredittxns), # number of debit txns
162       ' ' x 1396,
163     )
164   },
165 );
166
167 ## this format can handle credit transactions
168 sub can_handle_credits {
169   1;
170 }
171
172 sub _upgrade_gateway {
173   my $conf = FS::Conf->new;
174   my @batchconfig = $conf->config('batchconfig-td_eft1464');
175   my %options;
176   @options{ qw(originator datacentre short_name long_name return_branch 
177                return_account cpa_code) } = @batchconfig;
178   ( 'TD_EFT', %options );
179 }
180
181 1;
182