File Coverage

blib/lib/Finance/StockAccount/Import/OptionsXpress.pm
Criterion Covered Total %
statement 57 59 96.6
branch 21 28 75.0
condition 3 3 100.0
subroutine 6 6 100.0
pod 0 4 0.0
total 87 100 87.0


line stmt bran cond sub pod time code
1             package Finance::StockAccount::Import::OptionsXpress;
2              
3             our $VERSION = '0.01';
4              
5 3     3   23035 use Time::Moment;
  3         5800  
  3         73  
6 3     3   921 use parent 'Finance::StockAccount::Import';
  3         469  
  3         11  
7              
8             #### Expected Fields, tab separated:
9             # Symbol, Description, Action, Quantity, Price, Commission, Reg Fees, Date, TransactionID, Order Number, Transaction Type ID, Total Cost
10             # 0 1 2 3 4 5 6 7 8 9 10 11
11             my @pattern = qw(symbol 0 action 2 quantity 3 price 4 commission 5 regulatoryFees 6 date 7 totalCost 11);
12             my $numFields = 12;
13              
14             sub new {
15 8     8 0 6128 my ($class, $file, $tzoffset) = @_;
16 8         43 my $self = $class->SUPER::new($file, $tzoffset);
17 8         30 $self->{pattern} = \@pattern;
18 8         11 $self->{headers} = undef;
19 8         15 $self->init();
20 8         32 return $self;
21             }
22              
23             sub init {
24 8     8 0 9 my $self = shift;
25 8         11 my $file = $self->{file};
26 8 50       306 open my $fh, '<', $file or die "Failed to open $file: $!.\n";
27 8         15 $self->{fh} = $fh;
28              
29 8         120 my $hline = <$fh>;
30 8         15 chomp($hline);
31 8         48 my @headers = split(', ', $hline);
32 8 50       25 scalar(@headers) == $numFields or die "Unexpected number of headers. Header line:\n$hline\n";
33 8         13 $self->{headers} = \@headers;
34 8         12 my $blankLine = <$fh>;
35 8 50       28 $blankLine =~ /\w/ and warn "Expected blank line after header line. May have inadvertantly skipped first transaction...\n";
36 8         16 return 1;
37             }
38              
39             sub getTm {
40 239     239 0 249 my ($self, $dateString) = @_;
41 239 50       1041 if ($dateString =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{2}):(\d{2})\s+(\wM)$/i) {
42 239         731 my ($month, $day, $year, $hour, $minute, $second, $pm) = ($1, $2, $3, $4, $5, $6, $7);
43 239 100 100     782 if ($pm =~ /^PM$/i and $hour < 12) {
44 74         66 $hour += 12;
45             }
46 239         1733 return Time::Moment->new(
47             year => $year,
48             month => $month,
49             day => $day,
50             hour => $hour,
51             minute => $minute,
52             second => $second,
53             offset => $self->{tzoffset},
54             );
55             }
56             else {
57 0         0 warn "Did not recognize date time format:\n$dateString\n";
58 0         0 return undef;
59             }
60             }
61              
62             sub nextAt {
63 246     246 0 494 my $self = shift;
64 246         252 my $fh = $self->{fh};
65 246         221 my $pattern = $self->{pattern};
66 246 100       674 if (my $line = <$fh>) {
67 239         245 chomp($line);
68 239         1257 my @row = split(',', $line);
69              
70 239         316 my $hash = {};
71 239         187 my $action;
72 239         514 for (my $x=0; $x
73 1912         1870 my $index = $pattern->[$x+1];
74 1912 50       2736 if (exists($row[$index])) {
75 1912         1549 my $key = $pattern->[$x];
76 1912 100       3332 if ($key eq 'action') {
    100          
    100          
77 239         448 $action = $row[$index];
78             }
79             elsif ($key eq 'date') {
80 239         408 $hash->{tm} = $self->getTm($row[$index]);
81             }
82             elsif ($key eq 'totalCost') {
83 239         480 next();
84             }
85             else {
86 1195         962 my $value = $row[$index];
87 1195 100       2754 if ($key =~ /^(?:price|quantity|commission|regulatoryFees)$/) {
88 956         990 $value += 0;
89             }
90 1195         3078 $hash->{$key} = $row[$index];
91             }
92             }
93             }
94 239         607 my $at = Finance::StockAccount::AccountTransaction->new($hash);
95 239 100       448 if ($action eq 'Sell') {
    50          
96 96         182 $at->sell(1);
97             }
98             elsif ($action eq 'Buy') {
99 143         285 $at->buy(1);
100             }
101 239         1140 return $at;
102             }
103             else {
104 7 50       76 close($fh) or die "Failed to close file descriptor: $!.\n";
105 7         26 return 0;
106             }
107             }
108              
109              
110              
111             1;
112