webgui/lib/WebGUI/Asset/Wobject/StockData.pm
Colin Kuskie f5347b1314 WebGUI/Operation/Help.pm, refactor _getHelpName
All other files, make sure that either assetName, macroName or topicName is defined
in the i18n file.  Make sure that all Assets have assetName defined in their
definition sub.
2005-12-10 23:33:25 +00:00

476 lines
13 KiB
Perl

package WebGUI::Asset::Wobject::StockData;
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2005 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use strict;
use WebGUI::ErrorHandler;
use WebGUI::Icon;
use WebGUI::International;
use WebGUI::Privilege;
use WebGUI::Session;
use WebGUI::SQL;
use WebGUI::URL;
use WebGUI::Utility;
use WebGUI::Asset::Wobject;
use Finance::Quote;
our @ISA = qw(WebGUI::Asset::Wobject);
#-------------------------------------------------------------------
=head2 _appendStockVars ( hash, data, symbol )
Appends stock variables for the symbol passed in to the hash passed in
=head3 hash
hash to append stock variables to
=head3 data
hash reference in the format passed by the fetch method from Finance::Quote
=head3 symbol
stock symbol to append variables for
=cut
sub _appendStockVars {
my $self = shift;
my $hash = $_[0];
my $data = $_[1];
my $symbol = $_[2];
$hash->{'stocks.symbol'} = _na($symbol);
$hash->{'stocks.name'} = _na($data->{$symbol,"name"});
$hash->{'stocks.last'} = _na($data->{$symbol,"last"});
$hash->{'stocks.high'} = _na($data->{$symbol,"high"});
$hash->{'stocks.low'} = _na($data->{$symbol,"low"});
$hash->{'stocks.date'} = _na($data->{$symbol,"date"});
$hash->{'stocks.time'} = _na($data->{$symbol,"time"});
$hash->{'stocks.net'} = _na($data->{$symbol,"net"});
$hash->{'stocks.net.isDown'} = $hash->{'stocks.net'} < 0;
$hash->{'stocks.net.isUp'} = $hash->{'stocks.net'} > 0;
$hash->{'stocks.net.noChange'} = $hash->{'stocks.net'} == 0;
$hash->{'stocks.net.icon'} = "nc.gif";
if($hash->{'stocks.net.isDown'}) {
$hash->{'stocks.net.icon'} = "down.gif";
} elsif($hash->{'stocks.net.isUp'}) {
$hash->{'stocks.net.icon'} = "up.gif";
}
$hash->{'stocks.p_change'} = _na($data->{$symbol,"p_change"});
$hash->{'stocks.volume'} = _na($data->{$symbol,"volume"});
$hash->{'stocks.volume.millions'} = _na(WebGUI::Utility::round(($hash->{'stocks.volume'}/1000000),2));
$hash->{'stocks.avg_vol'} = _na($data->{$symbol,"avg_vol"});
$hash->{'stocks.bid'} = _na($data->{$symbol,"bid"});
$hash->{'stocks.ask'} = _na(WebGUI::Utility::commify($data->{$symbol,"ask"}));
$hash->{'stocks.close'} = _na($data->{$symbol,"close"});
$hash->{'stocks.open'} = _na($data->{$symbol,"open"});
$hash->{'stocks.day_range'} = _na($data->{$symbol,"day_range"});
$hash->{'stocks.year_range'} = _na($data->{$symbol,"year_range"});
my ($yrLo,$yrHi) = split("-",$hash->{'stocks.year_range'});
$hash->{'stocks.year_high'} = _na($self->_trim($yrHi));
$hash->{'stocks.year_low'} = _na($self->_trim($yrLo));
$hash->{'stocks.eps'} = _na($data->{$symbol,"eps"});
$hash->{'stocks.pe'} = _na($data->{$symbol,"pe"});
$hash->{'stocks.div_date'} = _na($data->{$symbol,"div_date"});
$hash->{'stocks.div'} = _na($data->{$symbol,"div"});
$hash->{'stocks.div_yield'} = _na($data->{$symbol,"div_yield"});
$hash->{'stocks.cap'} = _na(lc($data->{$symbol,"cap"}));
$hash->{'stocks.ex_div'} = _na($data->{$symbol,"ex_div"});
$hash->{'stocks.nav'} = _na($data->{$symbol,"nav"});
$hash->{'stocks.yield'} = _na($data->{$symbol,"yield"});
$hash->{'stocks.exchange'} = _na($data->{$symbol,"exchange"});
$hash->{'stocks.success'} = _na($data->{$symbol,"success"});
$hash->{'stocks.errormsg'} = _na($data->{$symbol,"errormsg"});
$hash->{'stocks.method'} = _na($data->{$symbol,"method"});
}
#-------------------------------------------------------------------
=head2 _na( string )
If string passed in is empty, returns N/A
=head3 string
a string
=cut
sub _na {
my $str = $_[0];
unless($str) {
$str = "N/A";
}
return $str;
}
#-------------------------------------------------------------------
=head2 _appendZero( intger )
Appends a zero to an integer if it is 0-9
=head3 integer
an integer
=cut
sub _appendZero {
my $self = shift;
my $num = $_[0];
if (length($num) == 1) {
$num = "0".$num;
}
return $num;
}
#-------------------------------------------------------------------
=head2 _clearStockEditSession ( )
Clears the session variables from session used by the stock list edit form
=cut
sub _clearStockEditSession {
my $self = shift;
$session{form}{symbol} = "";
$session{form}{stockId} = "";
}
#-------------------------------------------------------------------
=head2 _convertToEpoch (date,time)
Converts the date and time returned by Finance::Quote to an epoch
=head3 date
date format returned by Finance::Quote
=head3 time
time format returned by Finance::Quote
=cut
sub _convertToEpoch {
my $self = shift;
my $date = $_[0];
my $time = $_[1];
my ($month,$day,$year) = split("/",$date);
$month = $self->_appendZero($month);
$day = $self->_appendZero($day);
my $tfixed = substr($time,0,-2);
my ($hour,$minute) = split(":",$tfixed);
if($time =~ m/pm/i) {
$hour += 12;
}
$hour = $self->_appendZero($hour);
$minute = $self->_appendZero($minute);
return WebGUI::DateTime::humanToEpoch("$year-$month-$day $hour:$minute:00");
}
#-------------------------------------------------------------------
=head2 _getStocks ( stocks )
Private method which retrieves stock information from the Finance::Quote package
=head3 stocks
list of stock symbols to find passed in as an array reference. stock symbols should all be uppercase
=cut
sub _getStocks {
my $self = shift;
my $stocks = $_[0];
#Create a new Finance::Quote object
my $q = Finance::Quote->new;
#Disable failover if specified
unless ($self->getValue("failover")) {
$q->failover(0);
}
#Fetch the stock information and return the results
return $q->fetch($self->getValue("source"),@{$stocks});
}
#-------------------------------------------------------------------
=head2 _getStockSources ( )
Private method which retrieves the list of available stock sources from Finance::Quote package
and returns the results as a hash reference for the selectList Form API
=cut
sub _getStockSources {
my $self = shift;
#Instantiate Finance::Quote
my $q = Finance::Quote->new;
#Retrieve array of available sources and sort them
my @srcs = sort $q->sources;
#Create a hash reference with the name referencing itself
my %sources;
#Tie to IxHash to preserve alphabetical order
tie %sources, "Tie::IxHash";
foreach my $src (@srcs) {
$sources{$src} = $src;
}
return \%sources;
}
#-------------------------------------------------------------------
=head2 _submenu
renders the admin console view
=cut
sub _submenu {
my $self = shift;
my $workarea = shift;
my $title = shift;
my $help = shift;
my $ac = WebGUI::AdminConsole->new("editstocks");
$ac->setHelp($help) if ($help);
$ac->setIcon($self->getIcon);
return $ac->render($workarea, $title);
}
#-------------------------------------------------------------------
=head2 _trim (str)
Trims whitespace form front and end of a string
=head3 str
a string to trim
=cut
sub _trim {
my $self = shift;
my $str = $_[0];
$str =~ s/^\s//;
$str =~ s/\s$//;
return $str;
}
#-------------------------------------------------------------------
=head2 definition
defines wobject properties for Stock Data instances
=cut
sub definition {
my $class = shift;
my $definition = shift;
my $properties = {
templateId =>{
fieldType=>"template",
defaultValue=>'StockDataTMPL000000001'
},
displayTemplateId=>{
fieldType=>"template",
defaultValue=>'StockDataTMPL000000002'
},
defaultStocks=>{
fieldType=>"textarea",
defaultValue=>"DELL\nMSFT\nORCL\nSUNW\nYHOO"
},
source=>{
fieldType=>"selectList",
defaultValue=>"usa"
},
failover=>{
fieldType=>"checkbox",
defaultValue=>undef
}
};
push(@{$definition}, {
tableName=>'StockData',
className=>'WebGUI::Asset::Wobject::StockData',
icon=>'stockData.gif',
assetName=>WebGUI::International::get("assetName","Asset_StockData"),
properties=>$properties
});
return $class->SUPER::definition($definition);
}
#-------------------------------------------------------------------
=head2 getEditForm
returns the tabform object that will be used in generating the edit page for Stock Lists
=cut
sub getEditForm {
my $self = shift;
my $tabform = $self->SUPER::getEditForm();
$tabform->getTab("display")->template(
-value=>$self->get("templateId"),
-label=>WebGUI::International::get("template_label","Asset_StockData"),
-namespace=>"StockData"
);
$tabform->getTab("display")->template(
-value=>$self->get("displayTemplateId"),
-label=>WebGUI::International::get("display_template_label","Asset_StockData"),
-namespace=>"StockData/Display"
);
$tabform->getTab("properties")->textarea(
-name => "defaultStocks",
-label=> WebGUI::International::get("default_stock_label","Asset_StockData"),
-value=> $self->getValue("defaultStocks")
);
$tabform->getTab("properties")->selectList(
-name => "source",
-label=> WebGUI::International::get("stock_source","Asset_StockData"),
-options=>$self->_getStockSources(),
-value=> [$self->getValue("source")],
-hoverHelp=>WebGUI::International::get("stock_source_description","Asset_StockData")
);
$tabform->getTab("properties")->yesNo(
-name=> "failover",
-label=> WebGUI::International::get("failover_label","Asset_StockData"),
-value=>$self->getValue("failover"),
-hoverHelp=> WebGUI::International::get("failover_description","Asset_StockData")
);
return $tabform;
}
#-------------------------------------------------------------------
=head2 purge ( )
removes collateral data associated with a StockData when the system
purges it's data.
=cut
sub purge {
my $self = shift;
return $self->SUPER::purge;
}
#-------------------------------------------------------------------
=head2 view ( )
method called by the www_view method. Returns a processed template
to be displayed within the page style
=cut
sub view {
my $self = shift;
my $var = {};
#Set some template variables
$var->{'extrasFolder'} = $session{config}{extrasURL}."/wobject/StockData";
$var->{'editUrl'} = $self->getUrl("func=editStocks");
$var->{'isVisitor'} = $session{user}{userId} eq 1;
$var->{'stock.display.url'} = $self->getUrl("func=displayStock&symbol=");
#Build list of stocks as an array
my $defaults = $self->getValue("defaultStocks");
#replace any windows newlines
$defaults =~ s/\r//;
my @array = split("\n",$defaults);
#trim default stocks of whitespace
for (my $i = 0; $i < scalar(@array); $i++) {
$array[$i] = $self->_trim($array[$i]);
}
my $data = $self->_getStocks(\@array);
my @stocks = ();
foreach my $symbol (@array) {
my $hash = {};
#Append Template Variables for stock symbol
$self->_appendStockVars($hash,$data,$symbol);
#Create last update date formats
unless ($var->{'lastUpdate.default'}) {
my $luEpoch = $self->_convertToEpoch($hash->{'stocks.date'},$hash->{'stocks.time'});
$var->{'lastUpdate.intl'} = WebGUI::DateTime::epochToHuman($luEpoch,"%y-%m-%d %j:%n");
$var->{'lastUpdate.us'} = WebGUI::DateTime::epochToHuman($luEpoch,"%m/%d/%y %h:%n %p");
$var->{'lastUpdate.default'} = WebGUI::DateTime::epochToHuman($luEpoch,"%C %d %H:%n %P");
}
push (@stocks, $hash);
}
$var->{'stocks.loop'} = \@stocks;
return $self->processTemplate($var, $self->get("templateId"));
}
#-------------------------------------------------------------------
=head2 www_displayStock ( )
Web facing method which allows users to view details about their stocks
=cut
sub www_displayStock {
my $self = shift;
my $var = {};
return WebGUI::Privilege::noAccess() unless $self->canView();
$var->{'extrasFolder'} = $session{config}{extrasURL}."/wobject/StockData";
my $symbol = $session{form}{symbol};
my $data = $self->_getStocks([$symbol]);
#Append Template Variables for stock symbol
$self->_appendStockVars($var,$data,$symbol);
#Configure last update dates
my $luEpoch = $self->_convertToEpoch($var->{'stocks.date'},$var->{'stocks.time'});
$var->{'lastUpdate.intl'} = WebGUI::DateTime::epochToHuman($luEpoch,"%y-%m-%d");
$var->{'lastUpdate.us'} = WebGUI::DateTime::epochToHuman($luEpoch,"%m/%d/%y");
$session{setting}{showDebug} = 0;
return $self->processTemplate($var, $self->get("displayTemplateId"));
}
#-------------------------------------------------------------------
#=head2 www_edit ( )
#Web facing method which is the default edit page
#=cut
#sub www_edit {
# my $self = shift;
# return WebGUI::Privilege::insufficient() unless $self->canEdit;
# $self->getAdminConsole->setHelp("stock list add/edit","Asset_StockData");
# return $self->getAdminConsole->render($self->getEditForm->print,
# WebGUI::International::get("edit_title","Asset_StockData"));
#}
#-------------------------------------------------------------------
=head2 www_view ( )
Overwrite www_view method and call the superclass object, passing in a 1 to disable cache
=cut
sub www_view {
my $self = shift;
$self->SUPER::www_view(1);
}
1;