|
1 |
package SL::BackgroundJob::UpdateExchangerates;
|
|
2 |
|
|
3 |
use strict;
|
|
4 |
use utf8;
|
|
5 |
|
|
6 |
use parent qw(SL::BackgroundJob::Base);
|
|
7 |
|
|
8 |
use SL::DB::Exchangerate;
|
|
9 |
use SL::DB::Currency;
|
|
10 |
|
|
11 |
use Rose::Object::MakeMethods::Generic (
|
|
12 |
scalar => [ qw(worker) ],
|
|
13 |
);
|
|
14 |
|
|
15 |
|
|
16 |
sub create_job {
|
|
17 |
my $self_or_class = shift;
|
|
18 |
|
|
19 |
my $package = ref($self_or_class) || $self_or_class;
|
|
20 |
$package =~ s/SL::BackgroundJob:://;
|
|
21 |
|
|
22 |
my $cron_spec = ('35 4 * * *'); # every day at 4:35 am
|
|
23 |
|
|
24 |
my $data = <<DATA;
|
|
25 |
module: FromYahoo
|
|
26 |
options:
|
|
27 |
translate:
|
|
28 |
£: GBP
|
|
29 |
DATA
|
|
30 |
|
|
31 |
my %params = (cron_spec => $cron_spec,
|
|
32 |
type => 'interval',
|
|
33 |
active => 1,
|
|
34 |
package_name => $package,
|
|
35 |
data => $data);
|
|
36 |
|
|
37 |
my $job = SL::DB::Manager::BackgroundJob->find_by(package_name => $params{package_name});
|
|
38 |
if (!$job) {
|
|
39 |
$job = SL::DB::BackgroundJob->new(%params)->update_next_run_at;
|
|
40 |
} else {
|
|
41 |
$job->assign_attributes(%params)->update_next_run_at;
|
|
42 |
}
|
|
43 |
|
|
44 |
return $job;
|
|
45 |
}
|
|
46 |
|
|
47 |
sub run {
|
|
48 |
my ($self, $db_obj) = @_;
|
|
49 |
|
|
50 |
my $params = $db_obj->data_as_hash;
|
|
51 |
|
|
52 |
return $::locale->text('Parameter module must be given.') if !$params->{module};
|
|
53 |
|
|
54 |
# instanciate worker for given module
|
|
55 |
my $error;
|
|
56 |
eval {
|
|
57 |
my $worker_class = 'SL::BackgroundJob::UpdateExchangerates::' . $params->{module};
|
|
58 |
eval "require $worker_class";
|
|
59 |
$self->worker($worker_class->new(options => $params->{options}));
|
|
60 |
1;
|
|
61 |
} or do {
|
|
62 |
$error = $::locale->text('Could not load class #1 (#2): "#3"', $params->{module}, 'SL/BackgroundJob/UpdateExchangerates', $@);
|
|
63 |
};
|
|
64 |
return $error if $error;
|
|
65 |
|
|
66 |
my $default_currency = SL::DB::Currency->new(id => $::instance_conf->get_currency_id)->load;
|
|
67 |
my $transdate = DateTime->today_local;
|
|
68 |
my @rates_to_update;
|
|
69 |
|
|
70 |
# collect currencies that should be updated
|
|
71 |
foreach my $currency (@{SL::DB::Manager::Currency->get_all_sorted}) {
|
|
72 |
next if $currency->id == $default_currency->id;
|
|
73 |
|
|
74 |
my $exrate = SL::DB::Manager::Exchangerate->find_by(transdate => $transdate, currency_id => $currency->id);
|
|
75 |
|
|
76 |
if (!$exrate) {
|
|
77 |
push @rates_to_update, {from => $default_currency,
|
|
78 |
to => $currency,
|
|
79 |
dir => 'buy'};
|
|
80 |
push @rates_to_update, {from => $default_currency,
|
|
81 |
to => $currency,
|
|
82 |
dir => 'sell'};
|
|
83 |
next;
|
|
84 |
}
|
|
85 |
|
|
86 |
if (!$exrate->buy) {
|
|
87 |
push @rates_to_update, {from => $default_currency,
|
|
88 |
to => $currency,
|
|
89 |
dir => 'buy'};
|
|
90 |
}
|
|
91 |
if (!$exrate->sell) {
|
|
92 |
push @rates_to_update, {from => $default_currency,
|
|
93 |
to => $currency,
|
|
94 |
dir => 'sell'};
|
|
95 |
}
|
|
96 |
}
|
|
97 |
|
|
98 |
return "updated: 0" if scalar @rates_to_update == 0;
|
|
99 |
|
|
100 |
# update rates
|
|
101 |
$self->worker->update_rates(\@rates_to_update);
|
|
102 |
|
|
103 |
# save rates
|
|
104 |
my @updated;
|
|
105 |
foreach my $rate (@rates_to_update) {
|
|
106 |
my $exrate = SL::DB::Manager::Exchangerate->find_by_or_create(transdate => $transdate, currency_id => $rate->{to}->id);
|
|
107 |
|
|
108 |
next if !$exrate; # should not happen
|
|
109 |
|
|
110 |
if ($rate->{rate}) {
|
|
111 |
$exrate->transdate($transdate) if !$exrate->transdate;
|
|
112 |
$exrate->currency($rate->{to}) if !$exrate->currency;
|
|
113 |
|
|
114 |
my $method = $rate->{dir};
|
|
115 |
if (!$exrate->$method) {
|
|
116 |
$exrate->$method($rate->{rate});
|
|
117 |
$exrate->save;
|
|
118 |
push @updated, $rate->{to}->name . " ($method: " . $rate->{rate} . ")";
|
|
119 |
}
|
|
120 |
}
|
|
121 |
}
|
|
122 |
|
|
123 |
return "updated: " . scalar @updated . ': ' . join ', ', @updated;
|
|
124 |
}
|
|
125 |
|
|
126 |
|
|
127 |
1;
|
|
128 |
|
|
129 |
|
|
130 |
__END__
|
|
131 |
|
|
132 |
=encoding utf8
|
|
133 |
|
|
134 |
=head1 NAME
|
|
135 |
|
|
136 |
SL::BackgroundJob::UpdateExchangerates - Background job for updating the
|
|
137 |
exchange rates for currencies
|
|
138 |
|
|
139 |
=head1 SYNOPSIS
|
|
140 |
|
|
141 |
This background job can update all exchange rates for currencies if the rates
|
|
142 |
are not already present for the current date.
|
|
143 |
A worker module must be given as data to the job (see documentation at
|
|
144 |
SL::BackgroundJob::UpdateExchangerates::Base and
|
|
145 |
SL::BackgroundJob::UpdateExchangerates::* as examples).
|
|
146 |
The worker will be used to get the actual rates from some kind of service.
|
|
147 |
Options to the worker can be given as data to the background job:
|
|
148 |
|
|
149 |
module: FromOpenexchangerates
|
|
150 |
options:
|
|
151 |
api_id: 1234565789
|
|
152 |
translate:
|
|
153 |
£: GBP
|
|
154 |
|
|
155 |
=head1 Todo
|
|
156 |
|
|
157 |
Better error handling / error notification
|
|
158 |
|
|
159 |
=head1 AUTHOR
|
|
160 |
|
|
161 |
Bernd Bleßmann E<lt>bernd@kivitendo-premium.deE<gt>
|
|
162 |
|
|
163 |
=cut
|
|
164 |
|
Backkground: UpdateExchangerates - Wechselkurs von Openexchangerates