source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Employment.pm @ 2363

Last change on this file since 2363 was 2363, checked in by nanardon, 4 years ago

Add 'reference' to next and previous employment attributes

File size: 13.2 KB
Line 
1package LATMOS::Accounts::Bases::Sql::Employment;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Sql::objects);
8use LATMOS::Accounts::Log;
9use LATMOS::Accounts::I18N;
10use Date::Parse;
11use DateTime;
12use Date::Calc;
13
14our $VERSION = (q$Rev: 594 $ =~ /^Rev: (\d+) /)[0];
15
16=head1 NAME
17
18LATMOS::Accounts::Bases::Sql::Address - Physical office Adress Support
19
20=head1 DESCRIPTION
21
22C<Address> objects allow to store user's several office addresses.
23
24Notice most of other bases (Ldap, ...) support only one address.
25
26=cut
27
28sub stringify {
29    my ($self) = @_;
30
31    my $user = $self->base->get_object('user', $self->_get_c_field('user'))
32        or return $self->id;
33
34    return join(', ', grep { $_ }
35        (
36            $user,
37            $self->get_c_field('firstday'),
38        )
39    );
40}
41
42sub _object_table { 'employment' }
43
44sub _key_field { 'name' }
45
46sub _has_extended_attributes { 1 }
47
48sub _get_attr_schema {
49    my ($class, $base) = @_;
50
51    my $attrs = {
52        name =>         { inline => 1, },
53        exported =>     { inline => 1, },
54        user =>         { inline => 1,
55            reference => 'user',
56            label => l('User'),
57        },
58        description => {
59            label => l('Description'),
60        },
61        firstday => {
62            inline => 1,
63            formtype => 'DATE',
64            monitored => 1,
65            label => l('Contract start'),
66        },
67        lastday => {
68            inline => 1,
69            formtype => 'DATE',
70            monitored => 1,
71            label => l('Contract end'),
72        },
73        length => {
74            ro => 1,
75            managed => 1,
76            get => sub {
77                my ($self) = @_;
78                my $lastday = $self->object->get_attributes('lastday') || DateTime->now->ymd('-');
79                my $firstday = $self->object->get_attributes('firstday');
80
81                my @fd = split('-', $firstday);
82                my @ld = split('-', $lastday);
83
84                return Date::Calc::Delta_Days(@fd, @ld) +1;
85            },
86            label => l('Length'),
87        },
88        lengthText => {
89            ro => 1,
90            managed => 1,
91            get => sub {
92                my ($self) = @_;
93                my $lastday = $self->object->get_attributes('lastday')|| DateTime->now->ymd('-');
94                {
95                    my $dtlast = DateTime->from_epoch(epoch => str2time($lastday));
96                    $dtlast->add(days => 1);
97                    $lastday = $dtlast->ymd('-');
98                }
99                my $firstday = $self->object->get_attributes('firstday');
100
101                return if ($firstday gt $lastday);
102
103                my @fd = split('-', $firstday) or return;
104                my @ld = split('-', $lastday)  or return;
105
106                my ($Dy,$Dm,$Dd) = Date::Calc::N_Delta_YMD(@fd, @ld);
107                return join(', ',
108                    ($Dy ? l('%d years', $Dy)  : ()),
109                    ($Dm ? l('%d months', $Dm) : ()),
110                    ($Dd ? l('%d days', $Dd)   : ()),
111                );
112            },
113            label => l('Length'),
114        },
115        'state' => {
116            managed => 1,
117            ro => 1,
118            get => sub {
119                my ($self) = @_;
120                my $now = DateTime->now;
121                if ($now->epoch < str2time($self->object->get_attributes('firstday'))) {
122                    return 1;
123                } elsif ( my $end = $self->object->get_attributes('lastday') ) {
124                    my $eend = str2time($end) + 86400;
125                    if ($now->epoch > $eend) {
126                        return -1;
127                    } else {
128                        return 0;
129                    }
130                } else {
131                    return 0;
132                }
133            },
134            label => l('State'),
135        },
136        contratType => {
137            reference => 'group',
138            can_values => sub {
139                $base->search_objects('group', 'sutype=contrattype')
140            },
141            monitored => 1,
142            label => l('Type of contract'),
143        },
144        managerContact => {
145            delayed => 1,
146            can_values => sub {
147                my %uniq = map { $_ => 1 } grep { $_ }
148                ($_[1] ? $_[1]->get_attributes('managerContact') : ()),
149                $base->search_objects('user', 'active=*');
150                sort keys %uniq;
151            },
152            reference => 'user',
153            label => l('Direct manager'),
154        },
155        department => {
156            reference => 'group',
157            can_values => sub {
158                $base->search_objects('group', 'sutype=dpmt')
159            },
160            monitored => 1,
161            label => l('Department'),
162        },
163        company => {
164            label => l('Company'),
165        },
166        employer => {
167            label => l('Employer'),
168        },
169        endcircuit    => {
170            formtype => 'DATE',
171            monitored => 1,
172            label => l('End of entrance circuit'),
173        },
174        hosted => {
175            formtype => 'CHECKBOX',
176            label => l('Hosted'),
177        },
178        assigned => {
179            formtype => 'CHECKBOX',
180            label => l('Assigned'),
181        },
182        requestId => {
183            label => l('Request id')
184        },
185        previous => {
186            ro => 1,
187            managed => 1,
188            reference => 'employment',
189            get => sub {
190                my ($self) = @_;
191                my $find = $self->object->base->db->prepare_cached(q{
192                    SELECT name from employment where "user" = ?
193                        and (lastday is not null and lastday < ?)
194                        order by lastday desc
195                });
196                $find->execute(
197                    $self->object->get_field('user'),
198                    $self->object->get_field('firstday')
199                );
200                my $res = $find->fetchrow_hashref;
201                $find->finish;
202                return $res->{name};
203            },
204            label => l('Previous'),
205        },
206        'next' => {
207            ro => 1,
208            managed => 1,
209            reference => 'employment',
210            get => sub {
211                my ($self) = @_;
212                my $find = $self->object->base->db->prepare_cached(q{
213                    SELECT name from employment where "user" = ?
214                        and firstday > ?
215                        order by firstday asc
216                });
217                $find->execute(
218                    $self->object->get_field('user'),
219                    $self->object->get_field('lastday')
220                );
221                my $res = $find->fetchrow_hashref;
222                $find->finish;
223                return $res->{name};
224            },
225            label => l('Next'),
226        },
227        minFirstDay => {
228            ro => 1,
229            hidden => 1,
230            managed => 1,
231            formtype => 'DATE',
232            get => sub {
233                my ($attr) = @_;
234                my $self = $attr->object;
235
236                my $find = $self->base->db->prepare_cached(q{
237                    SELECT max(lastday) as lastday FROM employment where "user" = ?
238                        and lastday is not NULL and lastday < ?
239                    });
240
241                my $first = $self->get_field('firstday');
242
243                $find->execute(
244                    $self->get_field('user'),
245                    $first
246                );
247                my $res = $find->fetchrow_hashref;
248                $find->finish;
249
250                if ($res && $res->{lastday}) {
251                    my $dt = DateTime->from_epoch( epoch => str2time($res->{lastday}));
252                    $dt->set_time_zone( DateTime::TimeZone->new( name => 'local' ) );
253                    $dt->add(days => 1);
254                    if ($first eq $dt->ymd('-')) {
255                        return $first;
256                    } else {
257                        return $dt->ymd('-');
258                    }
259                } else {
260                    return;
261                }
262            },
263            label => l('Minimal first day'),
264        },
265        maxLastDay => {
266            ro => 1,
267            hidden => 1,
268            managed => 1,
269            formtype => 'DATE',
270            get => sub {
271                my ($attr) = @_;
272                my $self = $attr->object;
273
274                my $find = $self->base->db->prepare_cached(q{
275                    SELECT min(firstday) as firstday FROM employment where "user" = ?
276                        and firstday > ?
277                    });
278
279                my $last = $self->get_field('lastday') or do {
280                    # This contract is last then...
281                    return;
282                };
283
284                $find->execute(
285                    $self->get_field('user'),
286                    $last
287                );
288                my $res = $find->fetchrow_hashref;
289                $find->finish;
290
291                if ($res && $res->{firstday}) {
292                    my $dt = DateTime->from_epoch( epoch => str2time($res->{firstday}));
293                    $dt->set_time_zone( DateTime::TimeZone->new( name => 'local' ) );
294                    $dt->subtract(days => 1);
295                    if ($last eq $dt->ymd('-')) {
296                        return $last;
297                    } else {
298                        return $dt->ymd('-');
299                    }
300                } else {
301                    return;
302                }
303            },
304            label => l('Maximal last day'),
305        },
306    };
307
308    if (! $base->config("allow_pasted_employment")) {
309    # Completed contract are RO, we allow to still set lastday
310        foreach (qw(endcircuit firstday contratType department managerContact company employer)) {
311            $attrs->{$_}{ro} = sub {
312                my ($self) = $_[0];
313                $self or return 0;
314                my $st = $self->get_attributes('state') || '0';
315                return $st < 0 ? 1 : 0;
316            };
317        }
318    }
319    $class->SUPER::_get_attr_schema($base, $attrs);
320}
321
322sub ParentObject {
323    my ($self) = @_;
324
325    return $self->base->get_object('user', $self->_get_attributes('user'));
326}
327
328sub _create {
329    my ($class, $base, $id, %data) = @_;
330    $data{user} or return;
331    my $user = $base->get_object('user', $data{user});
332    $user or return;
333    my $res = $class->SUPER::_create($base, $id, %data);
334    $user->applyCurrentEmployment;
335    $res;
336}
337
338sub _delete {
339    my ($class, $base, $id) = @_;
340
341    my $obj = $base->get_object($class->type, $id)
342        or return;
343
344    my $user = $obj->_get_attributes('user');
345
346    my $res = $class->SUPER::_delete($base, $id);
347    if ($res) {
348        my $ouser = $base->get_object('user', $user);
349        $ouser->StoreEmployementSummary;
350        $ouser->applyCurrentEmployment;
351    }
352
353    $res
354}
355
356sub _set_c_fields {
357    my ($self, %data) = @_;
358
359    my $res = $self->SUPER::_set_c_fields(%data);
360
361    if ($res) {
362        my $user = $self->base->get_object('user', $self->get_attributes('user')) or do {
363            $self->base->log(LA_ERR, "Cannot fetch user %s to apply employment", $self->get_attributes('user'));
364            return;
365        };
366
367        $user->StoreEmployementSummary;
368        $user->applyCurrentEmployment;
369    }
370
371    return $res;
372}
373
374sub checkValues {
375    my ($class, $base, $obj, %changes) = @_;
376
377    my $user = $changes{user} || $obj->get_attributes('user');
378    my $id = ref $obj ? $obj->id : $obj;
379
380    my $firstday = exists($changes{firstday}) 
381        ? $changes{firstday} : 
382            ref $obj ? $obj->get_attributes('firstday') : undef;
383    my $lastday  = exists($changes{lastday})
384        ?  $changes{lastday} :
385            ref $obj ? $obj->get_attributes('lastday') : undef;
386
387    if ($lastday) {
388        my $sth = $base->db->prepare_cached(q{
389            select name, firstday, lastday from employment where "user" = ? and name != ?
390                and
391            (
392            (firstday <= ? and (lastday is NULL or lastday >= ?))
393                or
394            ((lastday is NOT NULL and lastday <= ?) and firstday >= ?)
395            )
396        });
397        $sth->execute($user, $id, $lastday, $firstday, $lastday, $firstday);
398        my $res = $sth->fetchrow_hashref;
399        $sth->finish;
400
401        if ($res) {
402            $base->log(LA_ERR, "The change will overlap contrat %s (%s - %s)", $res->{name}, $res->{firstday}, $res->{lastday} || '');
403            return;
404        }
405    } elsif (!$firstday) {
406        $base->log(LA_ERR, "No firstday given");
407        return;
408    } else {
409        my $sth = $base->db->prepare_cached(q{
410            select * from employment where "user" = ? and name != ?
411            and (lastday is NULL OR lastday >= ?)
412            limit 1
413        });
414        $sth->execute($user, $id, $firstday);
415        my $res = $sth->fetchrow_hashref;
416        if ($res && $res->{name}) {
417            if ($id ne $res->{name}) {
418                $base->log(LA_ERR, "Another contract has no ending (%s)", $res->{name} || '');
419                return;
420            }
421        }
422    }
423
424    return 1;
425}
426
4271;
428
429__END__
430
431=head1 SEE ALSO
432
433L<LATMOS::Accounts::Bases::Sql>
434
435=head1 AUTHOR
436
437Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
438
439=head1 COPYRIGHT AND LICENSE
440
441Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS
442
443This library is free software; you can redistribute it and/or modify
444it under the same terms as Perl itself, either Perl version 5.10.0 or,
445at your option, any later version of Perl 5 you may have available.
446
447
448=cut
Note: See TracBrowser for help on using the repository browser.