File Coverage

blib/lib/WWW/Myki/Card.pm
Criterion Covered Total %
statement 18 64 28.1
branch 0 12 0.0
condition 0 3 0.0
subroutine 6 11 54.5
pod 2 3 66.6
total 26 93 27.9


line stmt bran cond sub pod time code
1             package WWW::Myki::Card;
2              
3 1     1   6 use strict;
  1         2  
  1         34  
4 1     1   6 use warnings;
  1         1  
  1         28  
5              
6 1     1   1474 use HTML::TreeBuilder;
  1         70138  
  1         36  
7 1     1   104 use Scalar::Util qw(weaken);
  1         2  
  1         121  
8 1     1   6 use Carp qw(croak);
  1         1  
  1         115  
9              
10             our $VERSION = '0.02';
11             our @MATTR = qw(id _link holder money pass);
12             our @ATTR = qw(id _link holder money pass type expiry status money_top_up
13             money_total active_pass inactive_pass last_transaction);
14              
15             foreach my $attr ( @ATTR ) {
16             {
17 1     1   5 no strict 'refs';
  1         2  
  1         1349  
18             *{ __PACKAGE__ .'::'. $attr } = sub {
19 0     0     my( $self, $val ) = @_;
20 0 0         $self->{$attr} = $val if defined $val;
21 0           return $self->{$attr}
22             }
23             }
24             }
25              
26             sub new {
27 0     0 0   my( $class, %args ) = @_;
28 0           my $self = {};
29 0           bless $self, $class;
30 0 0         $args{_mech} ? weaken( $self->{_mech} = $args{_mech} ) : croak "Mandatory attribute _mech not supplied";
31              
32 0           foreach my $attr ( @MATTR ) {
33 0 0         $args{$attr} ? $self->{$attr} = $args{$attr} : croak "Mandatory attribute $attr not present";
34             }
35              
36 0           $self->_get_card_details;
37 0           return $self
38             }
39              
40             sub refresh {
41 0     0 1   my $self = shift;
42 0           $self->_get_card_details
43             }
44              
45             sub _get_card_details {
46 0     0     my $self = shift;
47 0           my $r = $self->{_mech}->get( $self->{_link} );
48 0           my $t = HTML::TreeBuilder->new_from_content( $r->content );
49 0           $t = $t->look_down( id => 'ctl00_uxContentPlaceHolder_uxCardDetailsPnl' );
50 0           my @r = $t->look_down ( _tag => 'td' );
51 0           $self->type ( $r[3]->as_text );
52 0           $self->expiry ( $r[5]->as_text );
53 0           $self->status ( $r[7]->as_text );
54 0           $self->money_top_up ( $r[11]->as_text );
55 0           $self->money_total ( $r[13]->as_text );
56 0           $self->active_pass ( $r[15]->as_text );
57 0           $self->inactive_pass ( $r[17]->as_text );
58 0           $self->last_transaction ( $r[19]->as_text );
59             }
60              
61             sub transactions {
62 0     0 1   my( $self, $refresh ) = shift;
63 0 0 0       return @{ $self->{transactions} } if ( $self->{transactions} and not $refresh );
  0            
64 0           undef $self->{transactions};
65 0           $self->{_mech}->get( $self->{_link} );
66 0           $self->{_mech}->follow_link( text => 'My transactions' );
67 0           $self->{_mech}->form_name( 'aspnetForm' );
68 0           $self->{_mech}->select( 'ctl00$uxContentPlaceHolder$uxCardList', $self->id );
69 0           my $r = $self->{_mech}->click_button( name => 'ctl00$uxContentPlaceHolder$uxSelectNewCard' );
70 0           my $t = HTML::TreeBuilder->new_from_content( $r->content );
71 0           ( $self->{total_transactions} )
72             = ( $t->look_down( id => 'ctl00_uxContentPlaceHolder_uxTotalRecords' )->as_text =~ /of\s(\d*)\s/ );
73 0           $t = $t->look_down( id => 'ctl00_uxContentPlaceHolder_uxMykiTxnHistory' );
74              
75 0           for ( $t->look_down( _tag => 'tr' ) ) {
76 0 0         my @cols = map { $_->as_text } $_->look_down( _tag => 'td' ) or next;
  0            
77 0 0         return () if ( $cols[0] =~ /.*no record found.*/i );
78              
79 0           push @{ $self->{transactions} },
  0            
80             WWW::Myki::Transaction->new(
81             date => $cols[0],
82             time => $cols[1],
83             type => $cols[2],
84             service => $cols[3],
85             zone => $cols[4],
86             desc => $cols[5],
87             credit => $cols[6],
88             debit => $cols[7],
89             balance => $cols[8]
90             )
91             }
92              
93 0           return @{ $self->{transactions} }
  0            
94             }
95              
96             =head1 NAME
97              
98             WWW::Myki::Card - Class for operations with a Myki card
99              
100             =head1 VERSION 0.01
101              
102             =head1 SYNOPSIS
103              
104             # Print my Myki card money balance
105             my $balance = $card->money;
106              
107             # What time did I stumble home last night?
108             print $card->last_transaction;
109              
110             # Yeesh, really? How?
111             print $card->service;
112              
113             # Ooooohh, now I remember.
114            
115             =head1 DESCRIPTION
116              
117             L is a class providing account and card management and querying functionality
118             for registered Myki users.
119              
120             Please note that you're are not meant to call the constructor yourself, instead a WWW::Myki::Card
121             object will be created automatically for you by calls to methods in a L object like
122             B.
123              
124             =head1 METHODS
125              
126             =head2 id
127              
128             Returns the card ID number.
129              
130             =head2 holder
131              
132             Returns the name of the registered card holder.
133              
134             =head2 money
135              
136             Returns the balance of Myki money on the card.
137              
138             =head2 pass
139              
140             Returns the balance of the active Myki pass (if any) on the card.
141              
142             =head2 type
143              
144             Returns the card type.
145              
146             =head2 expiry
147              
148             Returns the card expiry date in the format DD Mon YYYY, where Mon is the abbreviated month name.
149              
150             =head2 status
151              
152             Returns the card status.
153              
154             =head2 money_top_up
155              
156             Returns the value of any Myki money top up in progress - this is money that has been added by a top up,
157             but may not yet have been credited to the card.
158              
159             =head2 money_total
160              
161             Returns the total of the balance of Myki money and the balance of Myki money top in progress on the card.
162              
163             =head2 active_pass
164              
165             Returns the balance of the current active Myki pass (if any) on the card.
166              
167             =head2 inactive_pass
168              
169             Returns the balance of the current inactive Myki pass (if any) on the card.
170              
171             =head2 last_transaction
172              
173             Returns the last transaction time and date for the card in the format; DD Mon YYYY HH:MM:SS AM/PM,
174             where Mon is the abbreviated month name.
175              
176             =head2 transactions
177              
178             foreach my $trip ( $card->transactions ) {
179             printf( "%10s %8s %-10s %-20s\n", $trip->date, $trip->time, $trip->service, $trip->desc )
180             }
181              
182             # Prints a formatted list of the last 15 transactions for this card - e.g.
183             #
184             # 29/05/2012 17:28:38 Bus Surburbia,Route SUB16out_new
185             # 29/05/2012 08:08:12 Bus Metro,Route MET16in_new
186              
187             Returns an array of L objects representing the last 15 transactions for the card, or
188             an empty array if there are no recorded transactions.
189              
190             See L for more information on transactions. Transaction data is cached on the initial
191             invocation to increase the performance of subsequent calls and reduce unnecessary communication with the Myki
192             portal. This is probably what you want, but if you really do want to force transaction data to be refreshed
193             then you can call the method with the argument B set to a true value. e.g.
194              
195             $card->transactions( refresh => 1 );
196              
197             Please note that this will incur a performance penalty.
198              
199             =head2 refresh
200              
201             When a WWW::Myki::Card object is created, the card data is cached to improve the performance of subsequent
202             method calls and reduce unessecary network communication. This is probably what you want, however if you
203             do want to force the object to update its cached data for any reason, then you can call B. Note
204             that doing so will incur a performance penalty.
205              
206             =head1 AUTHOR
207              
208             Luke Poskitt, C<< >>
209              
210             =head1 BUGS
211              
212             Please report any bugs or feature requests to C, or through the web interface
213             at L. I will be notified, and then you'll
214             automatically be notified of progress on your bug as I make changes.
215              
216             =head1 SUPPORT
217              
218             You can find documentation for this module with the perldoc command.
219              
220             perldoc WWW::Myki::Card
221              
222             You can also look for information at:
223              
224             =over 4
225              
226             =item * RT: CPAN's request tracker
227              
228             L
229              
230             =item * AnnoCPAN: Annotated CPAN documentation
231              
232             L
233              
234             =item * CPAN Ratings
235              
236             L
237              
238             =item * Search CPAN
239              
240             L
241              
242             =back
243              
244             =head1 LICENSE AND COPYRIGHT
245              
246             Copyright 2012 Luke Poskitt.
247              
248             This program is free software; you can redistribute it and/or modify it
249             under the terms of either: the GNU General Public License as published
250             by the Free Software Foundation; or the Artistic License.
251              
252             See http://dev.perl.org/licenses/ for more information.
253              
254             =head1 SEE ALSO
255              
256             L, L
257              
258             =cut
259              
260             1;