source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/DataRequest.pm @ 1002

Last change on this file since 1002 was 1002, checked in by nanardon, 12 years ago
  • fix attributes object return in some, simplify code
  • Property svn:keywords set to Id Rev
File size: 11.6 KB
Line 
1package LATMOS::Accounts::Bases::Sql::DataRequest;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use LATMOS::Accounts::Utils;
8use LATMOS::Accounts::Log;
9
10our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
11
12=head1 NAME
13
14    LATMOS::Accounts::Bases::Sql::DataRequest
15
16=head1 DESCRIPTION
17
18Object to handle request forms in Link::Accounts system
19
20=cut
21
22=head1 FUNCTIONS
23
24=head2 new($accreq, $id)
25
26Instanciate a C<LATMOS::Accounts::Bases::Sql::DataRequest> object over an
27existing form definition (C<$accreq>).
28
29C<$id> is an optional DataRequest id to fetch an aready stored set of data.
30
31=cut
32
33sub new {
34    my ($class, $accreq, $id) = @_;
35
36    bless {
37        id => $id,
38        accreq => $accreq,
39    }, $class
40}
41
42sub ar_id { $_[0]->{id} }
43
44=head2 otype
45
46=cut
47
48sub otype { $_[0]->accreq->get_attributes('oType') }
49
50=head2 attributes
51
52=cut
53
54sub attributes {
55    $_[0]->accreq->get_attributes('attributes')
56}
57
58sub attribute_info {
59    my ($self, $attr) = @_;
60    $self->accreq->attr_info($attr);
61}
62
63sub oobject {
64    my ($self) = @_;
65    if (my $name = $self->object_name) {
66        return $self->base->get_object($self->otype, $name);
67    } else {
68        return undef;
69    }
70}
71
72sub set_ptr_object {
73    my ($self, $ptr) = @_;
74
75    if (ref $ptr) {
76        $self->{_object_name} = $ptr->id;
77    } else {
78        $self->{_object_name} = $ptr;
79    }
80}
81
82sub is_for_new_object {
83    my ($self) = @_;
84
85    $self->accreq->get_attributes('requireObject') ? 0 : 1;
86}
87
88# Fetch informations and cache it
89sub _infos {
90    my ($self) = @_;
91
92    return $self->{_infos} if ($self->{_infos});
93
94    my $sth = $self->accreq->db->prepare(q{
95        select *, now() >= apply as due
96        from request where id = ?
97    });
98
99    $sth->execute($self->ar_id);
100
101    return $self->{_infos} = $sth->fetchrow_hashref;
102}
103
104sub object_name {
105    my ($self) = @_;
106
107    return $self->{_object_name} if ($self->{_object_name});
108
109    return ($self->_infos || {})->{object};
110}
111
112sub user {
113    my ($self) = @_;
114
115    return ($self->_infos || {})->{user};
116}
117
118sub o_user {
119    my ($self) = @_;
120
121    my $user = ($self->_infos || {})->{user};
122    return $self->base->get_object('user', $user);
123}
124
125sub apply {
126    my ($self) = @_;
127
128    return ($self->_infos || {})->{apply};
129}
130
131sub due {
132    my ($self) = @_;
133
134    return ($self->_infos || {})->{due};
135}
136
137sub objrev {
138    my ($self) = @_;
139
140    return ($self->_infos || {})->{objrev};
141}
142
143sub register {
144    my ($self, $options, %param) = @_;
145
146    my $user = $options->{user};
147    my $apply = $options->{apply};
148    my $auto = $options->{auto};
149
150    my $rev;
151
152    if (!$self->is_for_new_object()) {
153        if ($self->oobject) {
154            $rev = $self->oobject->get_attributes('rev');
155        } else {
156            la_log(LA_ERR, "An object type %s is required", $self->otype);
157            return;
158        }
159    }
160
161    my $sth_req = $self->base->db->prepare(q{
162        INSERT into request (name, object, "user", apply, automated, objrev)
163        values (?,?,?,?,?,?)
164        });
165    $apply ||= scalar(localtime);
166    $sth_req->execute($self->accreq->id, $self->object_name, $user, $apply,
167        $auto ? 1 : 0, $rev) or return;
168
169    my $newid = $self->base->db->last_insert_id(
170        undef,undef,undef,undef,
171        { sequence => 'request_id_seq'}
172    ) or do {
173        la_log(LA_ERR, "Cannot get new request id");
174        $self->base->db->rollback;
175        return;
176    };
177
178    my $sth_attr = $self->base->db->prepare(q{
179        insert into request_attributes (reqid, attribute, value)
180        values (?,?,?)
181    });
182
183    my $attr_count = 0;
184    foreach ($self->attributes) {
185        if (exists($param{$_})) {
186            if ($self->oobject) {
187                if (join('|', $self->oobject->get_attributes($_) || '')
188                    eq
189                    join('|', ref $param{$_} ? @{ $param{$_} } : $param{$_})) {
190                    # No diff
191                    next;
192                }
193            }
194            if (!$param{$_}) {
195                $attr_count += $sth_attr->execute($newid, $_, undef)
196                    if ($self->oobject);
197            } elsif(ref $param{$_}) {
198                foreach my $v (@{$param{$_}}) {
199                    $attr_count += $sth_attr->execute($newid, $_, $v);
200                }
201            } else {
202                $attr_count += $sth_attr->execute($newid, $_, $param{$_});
203            }
204        }
205    }
206
207    if ($attr_count) {
208        $self->{id} = $newid;
209        $self->base->db->commit;
210        $self->notify;
211        # flush cache
212        $self->{_infos} = undef;
213        return 1;
214    } else {
215        la_log(LA_ERR, "Nothing to store into the request");
216        $self->base->db->rollback;
217        return;
218    }
219}
220
221sub notify {
222    my ($self) = @_;
223
224    if (!$self->accreq->get_attributes('notifyMail')) {
225        return;
226    }
227
228    require LATMOS::Accounts::Mail;
229
230    my $submiter = $self->user
231        ? $self->base->get_object('user', $self->user)
232        : undef;
233
234    my %mail = (
235        to => $self->accreq->get_attributes('notifyMail'),
236        cc => ($submiter
237            ? $submiter->get_attributes('mail')
238            : ''),
239        Subject => sprintf('New request: %s',
240            $self->accreq->get_attributes('description')),
241        'X-LATMOS-Reason' => 'User request',
242    );
243
244    my $text = '';
245
246    if ($submiter) {
247        $text.= "\n";
248        $text .= "Request from " . $submiter->get_attributes('displayName');
249        $text .= "\n";
250    }
251
252    if (my $obj = $self->oobject) {
253        $text .= "For object " . $self->otype . ' ';
254        $text .= $obj->id;
255        if (my $dpn = $obj->get_attributes('displayName')) {
256            $text .= " ($dpn)"; 
257        }
258        $text .= "\n\n";
259    }
260
261    my %vals = $self->get_values;
262    foreach my $attr ($self->attributes) {
263        if (exists($vals{$attr})) {
264            foreach (ref $vals{$attr} ? @{ $vals{$attr} } : $vals{$attr}) {
265                $text .= "$attr: $_\n";
266            }
267        }
268    }
269
270    $text .= "\n\n";
271    $text .= "To apply: " . $self->apply;
272
273    my $lamail = LATMOS::Accounts::Mail->new(
274        $self->base->la,
275        \$text,
276    );
277
278
279    if ($lamail->process(
280        {}, # no variables
281        \%mail,
282        )) {
283        la_log(LA_NOTICE, "Request mail sent to %s", $mail{to});
284    }
285}
286
287sub get_values {
288    my ($self) = @_;
289
290    my $sth_f = $self->base->db->prepare(q{
291        select attribute, value from request_attributes where reqid = ?
292            order by attribute
293    });
294
295    my %values;
296    $sth_f->execute($self->ar_id);
297    while (my $res = $sth_f->fetchrow_hashref) {
298        my $attr = $res->{attribute};
299        if (exists($values{$attr})) {
300            if (!ref($values{$attr})) {
301                if (my $v = $values{$attr}) {
302                    $values{$attr} = [ grep { $_ } ($v, $res->{value}) ];
303                } else {
304                    $values{$attr} = $res->{value};
305                }
306            } elsif ($res->{value}) {
307                push(@{$values{$attr}}, $res->{value});
308            }
309        } else {
310            $values{$attr} = $res->{value};
311        }
312    }
313
314    %values
315}
316
317sub _register_applied {
318    my ($self, $comment) = @_;
319
320    my $sth = $self->base->db->prepare(q{
321        update request set done=now(), applied = true,
322        reason = ? where id = ?
323    });
324    $sth->execute($comment, $self->ar_id);
325}
326
327sub register_discard {
328    my ($self, $comment) = @_;
329
330    my $sth = $self->base->db->prepare(q{
331        update request set done=now(), applied = false,
332        reason = ? where id = ?
333    });
334    $sth->execute($comment, $self->ar_id);
335}
336
337sub _prepare_attrs {
338    my ($self, %attrs) = @_;
339
340    my %newvalues = $self->get_values;
341    foreach (keys %attrs) {
342        $newvalues{$_} = $attrs{$_};
343    }
344    foreach (keys %newvalues) {
345        if (!$self->base->attribute($self->otype, $_)) {
346            delete($newvalues{$_});
347        }
348    }
349
350    return %newvalues;
351}
352
353sub unset_auto {
354    my ($self) = @_;
355
356    my $sth = $self->accreq->db->prepare(q{
357        update request  set automated = false where id = ?
358    });
359    return $sth->execute($self->ar_id);
360}
361
362sub auto_apply_to_object {
363    my ($self, $comment) = @_;
364
365    if (!$self->is_for_new_object) {
366        if (my $obj = $self->oobject) {
367            if ($obj->get_attributes('rev') != $self->objrev) {
368                $self->base->log(LA_WARN,
369                    'Object %s has been modified, set request as non
370                    automated');
371
372                $self->unset_auto;
373                return 1; # The automatic action "succeed"
374            }
375        } else {
376            $self->base->log('Cannot apply to non existing object %s',
377                $self->object_name);
378            return;
379        }
380    }
381    $self->apply_to_object($comment);
382}
383
384sub apply_to_object {
385    my ($self, $comment, %attrs) = @_;
386
387    my %newvalues = $self->_prepare_attrs(%attrs);
388
389    if ($self->is_for_new_object) {
390        if ($self->base->create_object(
391            $self->otype,
392            $attrs{_name},
393            %attrs
394        )) {
395            $self->_register_applied($comment);
396            return 1;
397        } else {
398            $self->base->log(
399                LA_ERR,
400                'Error applying DataRequest id=%d to create object %s/%s: %s',
401                $self->ar_id,
402                $self->otype,
403                $attrs{_name},
404                $self->base->db->errstr,
405            );
406            return;
407        }
408    } else {
409        my $obj = $self->oobject or return;
410
411        if (defined($obj->set_c_fields(%newvalues)) &&
412            $self->_register_applied($comment)) {
413            $self->base->log(
414                LA_INFO,
415                'DataRequest id=%d applied to object %s/%s',
416                $self->ar_id,
417                $self->otype,
418                $obj->id,
419            );
420            return 1;
421        } else {
422            $self->base->log(
423                LA_ERR,
424                'Error applying DataRequest id=%d to object %s/%s: %s',
425                $self->ar_id,
426                $self->otype,
427                $obj->id,
428                $self->base->db->errstr,
429            );
430            $self->base->rollback;
431            return;
432        }
433    }
434}
435
436=head2 FUNCTION TO HANDLE OBJECT
437
438The following functions are provided to use a
439C<Datarequest> with the same way a C<LATMOS::Accounts::Base::Object>.
440
441See L<LATMOS::Accounts::Base::Object> documentation.
442
443=cut
444
445=head2 id
446
447=cut
448
449sub id { $_[0]->object_name }
450
451=head2 base
452
453=cut
454
455sub base { $_[0]->accreq->base }
456
457=head2 accreq
458
459=cut
460
461sub accreq { $_[0]->{accreq} }
462
463=head2 type
464
465=cut
466
467sub type { $_[0]->otype }
468
469=head2 get_attributes
470
471=cut
472
473sub get_attributes {
474    my ($self, @args) = @_;
475    if ($self->ar_id) {
476        # TODO not fetching all values each time
477        my %values = $self->get_values;
478        return $values{$args[0]};
479    } elsif (my $obj = $self->oobject) {
480        return $obj->get_attributes(@args);
481    } else {
482        return;
483    }
484}
485
486=head2 attribute
487
488=cut
489
490sub attribute {
491    my ($self, $attrname) = @_;
492
493    my $attr = $self->_attribute($attrname);
494
495    $attr->{_noacl} = 1;
496
497    $attr
498}
499
500sub _attribute {
501    my ($self, $attrname) = @_;
502
503    if (my $info = $self->attribute_info($attrname)) {
504        return $self->base->attribute($self->otype, $info);
505    } else {
506        my $obj = $self->oobject;
507        my $oo =  $obj
508            ? $obj->attribute($attrname)
509            : $self->base->attribute($self->otype, $attrname);
510        return $oo || $self->base->attribute($self->otype, { name => $attrname });
511    }
512}
513
5141;
515
516__END__
517
518=head1 SEE ALSO
519
520=head1 AUTHOR
521
522Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
523
524=head1 COPYRIGHT AND LICENSE
525
526Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS
527
528This library is free software; you can redistribute it and/or modify
529it under the same terms as Perl itself, either Perl version 5.10.0 or,
530at your option, any later version of Perl 5 you may have available.
531
532=cut
Note: See TracBrowser for help on using the repository browser.