package LATMOS::Accounts::Bases::Sql::Employment; use 5.010000; use strict; use warnings; use base qw(LATMOS::Accounts::Bases::Sql::objects); use LATMOS::Accounts::Log; use LATMOS::Accounts::I18N; use Date::Parse; use DateTime; use Date::Calc; our $VERSION = (q$Rev: 594 $ =~ /^Rev: (\d+) /)[0]; =head1 NAME LATMOS::Accounts::Bases::Sql::Address - Physical office Adress Support =head1 DESCRIPTION C
objects allow to store user's several office addresses. Notice most of other bases (Ldap, ...) support only one address. =cut sub stringify { my ($self) = @_; my $user = $self->base->get_object('user', $self->_get_c_field('user')) or return $self->id; return join(', ', grep { $_ } ( $user, $self->get_c_field('firstday'), ) ); } sub _object_table { 'employment' } sub _key_field { 'name' } sub _has_extended_attributes { 1 } sub _get_attr_schema { my ($class, $base) = @_; my $attrs = { name => { inline => 1, }, exported => { inline => 1, }, user => { inline => 1, reference => 'user', label => l('User'), }, description => { label => l('Description'), }, firstday => { inline => 1, formtype => 'DATE', monitored => 1, label => l('Contract start'), }, lastday => { inline => 1, formtype => 'DATE', monitored => 1, label => l('Contract end'), }, length => { ro => 1, managed => 1, get => sub { my ($self) = @_; my $lastday = $self->object->get_attributes('lastday') || DateTime->now->ymd('-'); my $firstday = $self->object->get_attributes('firstday'); my @fd = split('-', $firstday); my @ld = split('-', $lastday); return Date::Calc::Delta_Days(@fd, @ld) +1; }, label => l('Length'), }, lengthText => { ro => 1, managed => 1, get => sub { my ($self) = @_; my $lastday = $self->object->get_attributes('lastday')|| DateTime->now->ymd('-'); { my $dtlast = DateTime->from_epoch(epoch => str2time($lastday)); $dtlast->add(days => 1); $lastday = $dtlast->ymd('-'); } my $firstday = $self->object->get_attributes('firstday'); return if ($firstday gt $lastday); my @fd = split('-', $firstday) or return; my @ld = split('-', $lastday) or return; my ($Dy,$Dm,$Dd) = Date::Calc::N_Delta_YMD(@fd, @ld); return join(', ', ($Dy ? l('%d years', $Dy) : ()), ($Dm ? l('%d months', $Dm) : ()), ($Dd ? l('%d days', $Dd) : ()), ); }, label => l('Length'), }, 'state' => { managed => 1, ro => 1, get => sub { my ($self) = @_; my $now = DateTime->now; if ($now->epoch < str2time($self->object->get_attributes('firstday'))) { return 1; } elsif ( my $end = $self->object->get_attributes('lastday') ) { my $eend = str2time($end) + 86400; if ($now->epoch > $eend) { return -1; } else { return 0; } } else { return 0; } }, label => l('State'), }, contratType => { reference => 'group', can_values => sub { $base->search_objects('group', 'sutype=contrattype') }, monitored => 1, label => l('Type of contract'), }, managerContact => { delayed => 1, can_values => sub { my %uniq = map { $_ => 1 } grep { $_ } ($_[1] ? $_[1]->get_attributes('managerContact') : ()), $base->search_objects('user', 'active=*'); sort keys %uniq; }, reference => 'user', label => l('Direct manager'), }, department => { reference => 'group', can_values => sub { $base->search_objects('group', 'sutype=dpmt') }, monitored => 1, label => l('Department'), }, company => { label => l('Company'), }, employer => { label => l('Employer'), }, endcircuit => { formtype => 'DATE', monitored => 1, label => l('End of entrance circuit'), }, hosted => { formtype => 'CHECKBOX', label => l('Hosted'), }, previous => { ro => 1, managed => 1, get => sub { my ($self) = @_; my $find = $self->object->base->db->prepare_cached(q{ SELECT name from employment where "user" = ? and (lastday is not null and lastday < ?) order by lastday desc }); $find->execute( $self->object->get_field('user'), $self->object->get_field('firstday') ); my $res = $find->fetchrow_hashref; $find->finish; return $res->{name}; }, label => l('Previous'), }, next => { ro => 1, managed => 1, get => sub { my ($self) = @_; my $find = $self->object->base->db->prepare_cached(q{ SELECT name from employment where "user" = ? and firstday > ? order by firstday asc }); $find->execute( $self->object->get_field('user'), $self->object->get_field('lastday') ); my $res = $find->fetchrow_hashref; $find->finish; return $res->{name}; }, label => l('Next'), }, minFirstDay => { ro => 1, hidden => 1, managed => 1, formtype => 'DATE', get => sub { my ($attr) = @_; my $self = $attr->object; my $find = $self->base->db->prepare_cached(q{ SELECT max(lastday) as lastday FROM employment where "user" = ? and lastday is not NULL and lastday < ? }); my $first = $self->get_field('firstday'); $find->execute( $self->get_field('user'), $first ); my $res = $find->fetchrow_hashref; $find->finish; if ($res && $res->{lastday}) { my $dt = DateTime->from_epoch( epoch => str2time($res->{lastday})); $dt->set_time_zone( DateTime::TimeZone->new( name => 'local' ) ); $dt->add(days => 1); if ($first eq $dt->ymd('-')) { return $first; } else { return $dt->ymd('-'); } } else { return; } }, label => l('Minimal first day'), }, maxLastDay => { ro => 1, hidden => 1, managed => 1, formtype => 'DATE', get => sub { my ($attr) = @_; my $self = $attr->object; my $find = $self->base->db->prepare_cached(q{ SELECT min(firstday) as firstday FROM employment where "user" = ? and firstday > ? }); my $last = $self->get_field('lastday') or do { # This contract is last then... return; }; $find->execute( $self->get_field('user'), $last ); my $res = $find->fetchrow_hashref; $find->finish; if ($res && $res->{firstday}) { my $dt = DateTime->from_epoch( epoch => str2time($res->{firstday})); $dt->set_time_zone( DateTime::TimeZone->new( name => 'local' ) ); $dt->subtract(days => 1); if ($last eq $dt->ymd('-')) { return $last; } else { return $dt->ymd('-'); } } else { return; } }, label => l('Maximal last day'), }, }; if (! $base->config("allow_pasted_employment")) { # Completed contract are RO, we allow to still set lastday foreach (qw(endcircuit firstday contratType department managerContact company employer)) { $attrs->{$_}{ro} = sub { my ($self) = $_[0]; $self or return 0; my $st = $self->get_attributes('state') || '0'; return $st < 0 ? 1 : 0; }; } } $class->SUPER::_get_attr_schema($base, $attrs); } sub _create { my ($class, $base, $id, %data) = @_; $data{user} or return; my $user = $base->get_object('user', $data{user}); $user or return; my $res = $class->SUPER::_create($base, $id, %data); $user->applyCurrentEmployment; $res; } sub _delete { my ($class, $base, $id) = @_; my $obj = $base->get_object($class->type, $id) or return; my $user = $obj->_get_attributes('user'); my $res = $class->SUPER::_delete($base, $id); if ($res) { my $ouser = $base->get_object('user', $user); $ouser->applyCurrentEmployment; } $res } sub set_fields { my ($self, %data) = @_; my $res = $self->SUPER::set_fields(%data); my $user = $self->base->get_object('user', $self->get_attributes('user')) or do { $self->base->log(LA_ERR, "Cannot fetch user %s to apply employment", $self->get_attributes('user')); return; }; $user->applyCurrentEmployment; return $res; } sub checkValues { my ($class, $base, $obj, %changes) = @_; my $user = $changes{user} || $obj->get_attributes('user'); my $id = ref $obj ? $obj->id : $obj; my $firstday = exists($changes{firstday}) ? $changes{firstday} : $obj->get_attributes('firstday'); my $lastday = exists($changes{lastday}) ? $changes{lastday} : $obj->get_attributes('lastday'); if ($lastday) { my $sth = $base->db->prepare_cached(q{ select name, firstday, lastday from employment where "user" = ? and name != ? and ( (firstday <= ? and (lastday is NULL or lastday >= ?)) or ((lastday is NOT NULL and lastday <= ?) and firstday >= ?) ) }); $sth->execute($user, $id, $lastday, $firstday, $lastday, $firstday); my $res = $sth->fetchrow_hashref; $sth->finish; if ($res) { $base->log(LA_ERR, "The change will overlap contrat %s (%s - %s)", $res->{name}, $res->{firstday}, $res->{lastday} || ''); return; } } else { my $sth = $base->db->prepare_cached(q{ select * from employment where "user" = ? and name != ? and (lastday is NULL OR lastday >= ?) limit 1 }); $sth->execute($user, $id, $firstday); my $res = $sth->fetchrow_hashref; if ($res && $res->{name}) { if ($id ne $res->{name}) { $base->log(LA_ERR, "Another contract has no ending (%s)", $res->{name} || ''); return; } } } return 1; } 1; __END__ =head1 SEE ALSO L =head1 AUTHOR Olivier Thauvin, Eolivier.thauvin@latmos.ipsl.frE =head1 COPYRIGHT AND LICENSE Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available. =cut