Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 8557458b

Von Jan Büren vor fast 2 Jahren hinzugefügt

  • ID 8557458b0d59aa6bc85a78489a18d5cde48128fc
  • Vorgänger 04ff751a
  • Nachfolger 9b04d6e3

Backkground: UpdateExchangerates - Wechselkurs von Openexchangerates

Unterschiede anzeigen:

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

  
SL/BackgroundJob/UpdateExchangerates/FromOpenexchangerates.pm
1
package SL::BackgroundJob::UpdateExchangerates::FromOpenexchangerates;
2

  
3
use strict;
4
use utf8;
5

  
6
use parent qw(SL::BackgroundJob::UpdateExchangerates::Base);
7

  
8
use LWP::Simple;
9
use SL::JSON;
10

  
11

  
12
sub update_rates {
13
  my ($self, $rates) = @_;
14

  
15
  return if !$self->options->{api_id};
16

  
17
  # 'https://openexchangerates.org/api/latest.json?app_id=xxx&base=EUR';
18
  # setting base does not work for me, so get for default base USD and calculate ...
19
  my $url;
20
  $url .= 'https://openexchangerates.org/api/latest.json?app_id=';
21
  $url .= $self->options->{api_id};
22

  
23
  my $result = get($url);
24
  return if !$result;
25
  my $result_h = decode_json($result);
26

  
27
  foreach my $rate (@$rates) {
28
    my $base_rate = $result_h->{rates}->{ $self->translate_currency_name($rate->{from}->name) };
29
    next if !$base_rate;
30

  
31
    my $target_rate = $result_h->{rates}->{ $self->translate_currency_name($rate->{to}->name) };
32
    next if !$target_rate;
33

  
34
    my $exrate = $base_rate/$target_rate;
35

  
36
    # buy and sell are the same, so do not differenciate
37
    $rate->{rate} = $exrate;
38
  }
39
}
40

  
41

  
42
1;
43

  
44

  
45
#module: FromOpenexchangerates
46
#options:
47
#  api_id: ce3e48c3f3a54c4d968530a08bb87734
SL/BackgroundJob/UpdateExchangerates/SimpleTest.pm
1
package SL::BackgroundJob::UpdateExchangerates::SimpleTest;
2

  
3
use strict;
4
use utf8;
5

  
6
use parent qw(SL::BackgroundJob::UpdateExchangerates::Base);
7

  
8

  
9
sub update_rates {
10
  my ($self, $rates) = @_;
11

  
12
  foreach my $rate (@$rates) {
13
    my $from = $self->translate_currency_name($rate->{from}->name);
14
    my $to   = $self->translate_currency_name($rate->{to}->name);
15
    if ( $from eq 'EUR' && $to eq 'USD') {
16
      $rate->{rate} = 0.9205 if $rate->{dir} eq 'buy';
17
      $rate->{rate} = 0.9202 if $rate->{dir} eq 'sell';
18
    }
19
  }
20
}
21

  
22
1;

Auch abrufbar als: Unified diff