multiple payment options, RT#23741
[freeside.git] / FS / FS / payby.pm
1 package FS::payby;
2
3 use strict;
4 use vars qw(%hash %payby2bop);
5 use Tie::IxHash;
6 use Business::CreditCard;
7
8 =head1 NAME
9
10 FS::payby - Object methods for payment type records
11
12 =head1 SYNOPSIS
13
14   use FS::payby;
15
16   #for now...
17
18   my @payby = FS::payby->payby;
19
20   my $bool = FS::payby->can_payby('cust_main', 'CARD');
21
22   tie my %payby, 'Tie::IxHash', FS::payby->payby2longname
23
24   my @cust_payby = FS::payby->cust_payby;
25
26   tie my %payby, 'Tie::IxHash', FS::payby->cust_payby2longname
27
28 =head1 DESCRIPTION
29
30 Payment types.
31
32 =head1 METHODS
33
34 =over 4 
35
36 =item
37
38 =cut
39
40 # paybys can be any/all of:
41 # - a customer saved payment type (cust_payby.payby)
42 # - a payment or refund type (cust_pay.payby, cust_pay_batch.payby, cust_refund.payby)
43
44 tie %hash, 'Tie::IxHash',
45   'CARD' => {
46     tinyname  => 'card',
47     shortname => 'Credit card',
48     longname  => 'Credit card (automatic)',
49     realtime  => 1,
50   },
51   'DCRD' => {
52     tinyname  => 'card',
53     shortname => 'Credit card',
54     longname  => 'Credit card (on-demand)',
55     cust_pay  => 'CARD', #this is a customer type only, payments are CARD...
56     realtime  => 1,
57   },
58   'CHEK' => {
59     tinyname  => 'check',
60     shortname => 'Electronic check',
61     longname  => 'Electronic check (automatic)',
62     realtime  => 1,
63   },
64   'DCHK' => {
65     tinyname  => 'check',
66     shortname => 'Electronic check',
67     longname  => 'Electronic check (on-demand)',
68     cust_pay  => 'CHEK', #this is a customer type only, payments are CHEK...
69     realtime  => 1,
70   },
71   'PPAL' => {
72     tinyname  => 'PayPal',
73     shortname => 'PayPal',
74     longname  => 'PayPal',
75     cust_main => '', #not yet a customer type, but could be once we can do
76                      # invoice presentment via paypal
77   },
78   'PREP' => {
79     tinyname  => 'prepaid card',
80     shortname => 'Prepaid card',
81     longname  => 'Prepaid card',
82     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
83   },
84   'CASH' => {
85     tinyname  => 'cash',
86     shortname => 'Cash', # initial payment, then billing
87     longname  => 'Cash',
88     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
89   },
90   'WEST' => {
91     tinyname  => 'western union',
92     shortname => 'Western Union', # initial payment, then billing
93     longname  => 'Western Union',
94     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
95   },
96   'MCRD' => { #not the same as DCRD
97     tinyname  => 'card',
98     shortname => 'Manual credit card', # initial payment, then billing
99     longname  => 'Manual credit card', 
100     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
101   },
102   'MCHK' => { #not the same as DCHK
103     tinyname  => 'card',
104     shortname => 'Manual electronic check', # initial payment, then billing
105     longname  => 'Manual electronic check', 
106     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
107   },
108   'APPL' => {
109     tinyname  => 'apple store',
110     shortname => 'Apple Store',
111     longname  => 'Apple Store',
112     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
113   },
114   'ANRD' => {
115     tinyname  => 'android market',
116     shortname => 'Android Market',
117     longname  => 'Android Market',
118     cust_main => 'BILL', #this is a payment type only, customers go to BILL...
119   },
120   'EDI' => {
121     tinyname  => 'EDI',
122     shortname => 'Electronic Debit (EDI)',
123     longname  => 'Electronic Debit (EDI)',
124     cust_main => '', #not a customer type
125   },
126   'WIRE' => {
127     tinyname  => 'Wire',
128     shortname => 'Wire transfer',
129     longname  => 'Wire transfer',
130     cust_main => '', #not a customer type
131   },
132   'CBAK' => {
133     tinyname  => 'chargeback',
134     shortname => 'Chargeback',
135     longname  => 'Chargeback',
136     cust_main => '', # not a customer type
137   },
138 ;
139
140 sub payby {
141   keys %hash;
142 }
143
144 sub can_payby {
145   my( $self, $table, $payby ) = @_;
146
147   #return "Illegal payby" unless $hash{$payby};
148   return 0 unless $hash{$payby};
149
150   $table = 'cust_pay' if $table =~ /^cust_(pay_pending|pay_batch|pay_void|refund)$/;
151   return 0 if exists( $hash{$payby}->{$table} );
152
153   return 1;
154 }
155
156 sub realtime {  # can use realtime payment facilities
157   my( $self, $payby ) = @_;
158
159   return 0 unless $hash{$payby};
160   return 0 unless exists( $hash{$payby}->{realtime} );
161
162   return $hash{$payby}->{realtime};
163 }
164
165 sub payby2shortname {
166   my $self = shift;
167   map { $_ => $hash{$_}->{shortname} } $self->payby;
168 }
169
170 sub payby2longname {
171   my $self = shift;
172   map { $_ => $hash{$_}->{longname} } $self->payby;
173 }
174
175 sub shortname {
176   my( $self, $payby ) = @_;
177   $hash{$payby}->{shortname};
178 }
179
180 sub payname {
181   my( $self, $payby ) = @_;
182   #$hash{$payby}->{payname} || $hash{$payby}->{shortname};
183   exists($hash{$payby}->{payname})
184     ? $hash{$payby}->{payname}
185     : $hash{$payby}->{shortname};
186 }
187
188 sub longname {
189   my( $self, $payby ) = @_;
190   $hash{$payby}->{longname};
191 }
192
193 %payby2bop = (
194   'CARD' => 'CC',
195   'CHEK' => 'ECHECK',
196   'MCRD' => 'CC', #?  but doesn't MCRD mean _offline_ card?  i think it got
197                   # overloaded for third-party card payments -- but no one is
198                   # doing those other than paypal now
199   'PPAL' => 'PAYPAL',
200 );
201
202 sub payby2bop {
203   my( $self, $payby ) = @_;
204   $payby2bop{ $self->payby2payment($payby) };
205 }
206
207 sub payby2payment {
208   my( $self, $payby ) = @_;
209   $hash{$payby}{'cust_pay'} || $payby;
210 }
211
212 sub cust_payby {
213   my $self = shift;
214   grep { ! exists $hash{$_}->{cust_main} } $self->payby;
215 }
216
217 sub cust_payby2shortname {
218   my $self = shift;
219   map { $_ => $hash{$_}->{shortname} } $self->cust_payby;
220 }
221
222 sub cust_payby2longname {
223   my $self = shift;
224   map { $_ => $hash{$_}->{longname} } $self->cust_payby;
225 }
226
227 =back
228
229 =head1 BUGS
230
231 This should eventually be an actual database table, and all tables that
232 currently have a char payby field should have a foreign key into here instead.
233
234 =head1 SEE ALSO
235
236 =cut
237
238 1;
239