]> wagnertech.de Git - mfinanz.git/blob - SL/BackgroundJob/UpdateExchangerates.pm
date error in mapping
[mfinanz.git] / SL / BackgroundJob / UpdateExchangerates.pm
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