package Business::BatchPayment::Item;

use strict;
use Moose;
use Moose::Util::TypeConstraints;
use MooseX::UndefTolerant;
use DateTime;

=head1 NAME

Business::BatchPayment::Item

=head1 DESCRIPTION

A Business::BatchPayment::Item represents a single payment request or 
reply (approval or rejection).  When submitting a batch, the merchant 
system constructs B::BP::Item objects for each attempted payment in 
the batch.  Results downloaded from the gateway are returned as a 
list of Items with the 'approved' field set to a true or false value. 

=head1 REQUIRED ATTRIBUTES

=over 4

=item action

"payment" or "credit".  Most processors support only "payment".
"payment" is defined as "money transfer FROM the account identified in the 
Item TO the account identified by the Processor object's login settings."
"credit" is the other direction.

=cut

enum 'Action' => qw(payment credit);
coerce 'Action', from 'Str', via { lc $_ };
has action => (
  is  => 'rw',
  isa => 'Action',
  default => 'payment',
  required => 1,
  coerce => 1,
);

=item payment_type

"CC" or "ECHECK".  Most processors will only support one or the other, 
and if set on the Processor object, this is not required.

=cut

# are we okay with these names?
enum 'PaymentType' => qw( CC ECHECK );
has payment_type => ( is  => 'rw', isa => 'PaymentType' );

=item amount

the amount, as a decimal number.  Required only in request
items.

=cut

# perhaps we should apply roles that distinguish request and reply items?
# they have different required fields.
has amount => (
  is  => 'rw',
  isa => 'Num',
);

=item tid

transaction identifier.  Requests must provide this.  It's a token of 
some kind to be passed to the gateway and used to identify the reply.  
For now it's required to be an integer.  An invoice number would be 
a good choice.

=cut

has tid => ( is  => 'rw', isa => 'Int' );

=back

=head1 OPTIONAL ATTRIBUTES

=head2 Customer Information

=over 4

=item customer_id

A customer number or other identifier, for the merchant's use.

=item first_name

First name.

=item last_name

Last name.

=item company

Company name.

=item address, address2, city, state, country, zip

Billing address fields.  Credit card processors may use these (especially
zip) for authentication.

=cut

has [ qw(
  customer_id
  first_name
  last_name
  company
  address
  address2
  city
  state
  country
  zip
) ] => ( is => 'rw', isa => 'Str', default => '' );

=back

=head2 Transaction Information

=over 4

=item process_date

The date requested for processing.

=item invoice_number

An invoice number, for your use.

=cut

class_type 'DateTime';
coerce 'DateTime', from 'Int', via { DateTime->from_epoch($_) };
has process_date    => ( is => 'rw', isa => 'DateTime', coerce => 1 );

has invoice_number  => ( is => 'rw', isa => 'Str' );

=back

=head2 Bank Transfer / ACH / EFT

=over 4

=item account_number

Bank account number.

=item routing_code

Bank's routing code.

=item account_type

Can be 'personal checking', 'personal savings', 'business checking', 
or 'business savings'.

=cut

enum 'Account_Type' => [
  'personal checking',
  'personal savings',
  'business checking',
  'business savings',
];
coerce 'Account_Type', from 'Str', via { lc $_ };

has account_number  => ( is => 'rw', isa => 'Str' );
has routing_code    => ( is => 'rw', isa => 'Str' );
has account_type    => ( is => 'rw', isa => 'Account_Type', coerce => 1 );

=back

=head2 Credit Card

=over 4

=item card_number

Credit card number.

=item expiration

Credit card expiration, MMYY format.

=cut

has card_number     => ( is => 'rw', isa => 'Str' );
has expiration      => ( is => 'rw', isa => 'Str' );

=back

=head2 Tokenized Payment

=over 4

=item pay_by_token

If your gateway supports it, this may be 
provided instead of card_number/account_number.  See also 
C<assigned_token> below.

=cut

has pay_by_token    => ( is => 'rw', isa => 'Str' );

=back

=head1 REPLY ATTRIBUTES

=over 4

=item approved 

Boolean field for whether the item was approved.  This 
will always be set on replies.

=item payment_date 

The date the payment was processed, as a DateTime
object.

=item order_number 

The transaction identifier returned by the gateway
(not to be confused with 'tid', which is a transaction identifier assigned
by the merchant system).  This is usually the identifier for performing 
other operations on the transaction, like voiding or refunding it.

=item authorization

The authorization code, probably only meaningful for credit cards.  
Should be undef (or not present) if the transaction wasn't approved.

=item check_number

The check number, probably only meaningful if this transaction was
processed from a paper check.

=item assigned_token

In tokenized systems which store the customer's account number or 
credit card for future transactions, this is the token assigned to 
identify that account.  Pass it as 'pay_by_token' to use that payment 
account again.

=item error_message

The message returned by the gateway.  This may contain a value even 
if the payment was successful (use C<approved> to determine that.)

=back

=cut

has approved        => ( is => 'rw', isa => 'Maybe[Bool]' );

has payment_date    => ( is => 'rw', isa => 'DateTime' );

has [qw( 
  authorization
  error_message
  order_number
  assigned_token
)] => ( is => 'rw', isa => 'Str');

has check_number => ( is => 'rw', isa => 'Int' );

__PACKAGE__->meta->make_immutable;

1;
