I guess you need to download the new version. my file is completely different than yours. your version is 2011 mine is 2014.
-- diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/company_view.xml /media/GRMCPRXFRER/hr_attendance_analysis/company_view.xml --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/company_view.xml 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/company_view.xml 2014-05-28 04:23:20.000000000 +0200 @@ -5,11 +5,11 @@ <field name="inherit_id" ref="base.view_company_form"/> <field name="name">view.company.form</field> <field name="model">res.company</field> + <field name="type">form</field> <field name="arch" type="xml"> <page string="Configuration" position="inside"> - <group name="attendance_analysis_grp" string="Attendance analysis"> - <field name="working_time_precision" widget="float_time"/> - </group> + <field name="working_time_precision" widget="float_time"/> + <newline/> </page> </field> </record> diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_attendance.py /media/GRMCPRXFRER/hr_attendance_analysis/hr_attendance.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_attendance.py 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/hr_attendance.py 2014-05-28 04:23:08.000000000 +0200 @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # +# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>) # Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published @@ -13,7 +12,7 @@ # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. @@ -21,29 +20,29 @@ ############################################################################## from __future__ import division -from openerp.osv import fields, orm -from openerp.tools.translate import _ +from osv import fields, osv +from tools.translate import _ import time from datetime import * import math -from openerp.tools import float_compare import pytz -class res_company(orm.Model): +class res_company(osv.osv): _inherit = 'res.company' _columns = { - 'working_time_precision': fields.float('Working time precision', help='The precision used to analyse working times over working schedule (hh:mm)', required=True) + 'working_time_precision': fields.float('Working time precision', help='The precision used to analyse working times over working schedule', required=True) } _defaults = { - 'working_time_precision': 1.0 / 60 # hours + 'working_time_precision': 0.016666667 } +res_company() -class hr_attendance(orm.Model): +class hr_attendance(osv.osv): # ref: https://bugs.launchpad.net/openobject-client/+bug/887612 # test: 0.9853 - 0.0085 @@ -65,31 +64,19 @@ if hours / 24 > 0: days += hours / 24 hours = hours % 24 - return datetime(1900, 1, int(days), hours, minutes) + return datetime(1900, 1, days, hours, minutes) def float_to_timedelta(self, float_val): str_time = self.float_time_convert(float_val) - return timedelta(0, int(str_time.split(':')[0]) * 60.0*60.0 - + int(str_time.split(':')[1]) * 60.0) - - def total_seconds(self, td): - return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 + return timedelta(0, int(str_time.split(':')[0]) * 60.0*60.0 + int(str_time.split(':')[1]) * 60.0) - def time_difference(self, float_start_time, float_end_time): - if float_compare( - float_end_time, float_start_time, precision_rounding=0.0000001 - ) == -1: - # that means a difference smaller than 0.36 milliseconds - raise orm.except_orm( - _('Error'), - _('End time %s < start time %s') % ( - str(float_end_time), str(float_start_time) - ) - ) - delta = self.float_to_datetime( - float_end_time) - self.float_to_datetime( - float_start_time) - return self.total_seconds(delta) / 60.0 / 60.0 + def time_difference(self, float_start_time, float_end_time, precision=(1.0/60)): + if float_end_time < float_start_time: + if float_start_time - float_end_time > precision: + raise osv.except_osv(_('Error'), _('End time %s < start time %s') + % (str(float_end_time),str(float_start_time))) + delta = self.float_to_datetime(float_end_time) - self.float_to_datetime(float_start_time) + return delta.total_seconds() / 60.0 / 60.0 def time_sum(self, float_first_time, float_second_time): str_first_time = self.float_time_convert(float_first_time) @@ -98,7 +85,7 @@ str_second_time = self.float_time_convert(float_second_time) second_timedelta = timedelta(0, int(str_second_time.split(':')[0]) * 60.0*60.0 + int(str_second_time.split(':')[1]) * 60.0) - return self.total_seconds(first_timedelta + second_timedelta) / 60.0 / 60.0 + return (first_timedelta + second_timedelta).total_seconds() / 60.0 / 60.0 def _split_long_attendances(self, start_datetime, duration): # start_datetime: datetime, duration: hours @@ -106,20 +93,18 @@ res = [] if duration > 24: res.append((start_datetime, 24)) - res.extend(self._split_long_attendances( - start_datetime + timedelta(1), duration - 24)) + res.extend(self._split_long_attendances(start_datetime + timedelta(1), duration - 24)) else: res.append((start_datetime, duration)) return res - def _split_no_recursive_attendance(self, start_datetime, duration, precision=0.25): + def _split_norecurse_attendance(self, start_datetime, duration, precision=025): # start_datetime: datetime, duration: hours, precision: hours # returns [(datetime, hours)] res = [] while (duration > precision): res.append((start_datetime, precision)) - start_datetime += timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, - minutes=0, hours=precision) + start_datetime += timedelta(0,0,0,0,0,precision) duration -= precision if duration > precision / 2.0: res.append((start_datetime, precision)) @@ -136,9 +121,7 @@ res.append((start_datetime, precision)) return res - def get_reference_calendar(self, cr, uid, employee_id, date=None, context=None): - if date is None: - date = fields.date.context_today(self, cr, uid, context=context) + def get_active_contracts(self, cr, uid, employee_id, date=datetime.now().strftime('%Y-%m-%d')): contract_pool = self.pool.get('hr.contract') active_contract_ids= contract_pool.search(cr, uid, [ '&', @@ -150,38 +133,33 @@ ('date_end', '>=', date), ('date_end', '=', False), '&', - '&', - ('trial_date_start', '!=', False), + '|', + ('trial_date_start', '=', False), ('trial_date_start', '<=', date), - '&', - ('trial_date_end', '!=', False), + '|', + ('trial_date_end', '=', False), ('trial_date_end', '>=', date), - ], context=context) + ]) if len(active_contract_ids) > 1: - employee = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context) - raise orm.except_orm(_('Error'), _( - 'Too many active contracts for employee %s' - ) % employee.name) - if active_contract_ids: - contract = contract_pool.browse(cr, uid, active_contract_ids[0], context=context) - return contract.working_hours + raise osv.except_osv(_('Error'), _('Too many active contracts for employee %s') % attendance.employee_id.name) return active_contract_ids def _ceil_rounding(self, rounding, datetime): - minutes = (datetime.minute / 60.0 - + datetime.second / 60.0 / 60.0) + minutes = datetime.minute / 60.0 \ + + datetime.second / 60.0 / 60.0 return math.ceil(minutes * rounding) / rounding def _floor_rounding(self, rounding, datetime): - minutes = (datetime.minute / 60.0 - + datetime.second / 60.0 / 60.0) + minutes = datetime.minute / 60.0 \ + + datetime.second / 60.0 / 60.0 return math.floor(minutes * rounding) / rounding def _get_attendance_duration(self, cr, uid, ids, field_name, arg, context=None): res = {} + contract_pool = self.pool.get('hr.contract') resource_pool = self.pool.get('resource.resource') attendance_pool = self.pool.get('resource.calendar.attendance') - precision = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.working_time_precision + precision = self.pool.get('res.users').browse(cr, uid, uid).company_id.working_time_precision # 2012.10.16 LF FIX : Get timezone from context active_tz = pytz.timezone(context.get("tz","UTC") if context else "UTC") str_now = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S') @@ -189,167 +167,145 @@ duration = 0.0 outside_calendar_duration = 0.0 inside_calendar_duration = 0.0 - attendance = self.browse(cr, uid, attendance_id, context=context) + attendance = self.browse(cr, uid, attendance_id) res[attendance.id] = {} # 2012.10.16 LF FIX : Attendance in context timezone - attendance_start = datetime.strptime( - attendance.name, '%Y-%m-%d %H:%M:%S' - ).replace(tzinfo=pytz.utc).astimezone(active_tz) + attendance_start = datetime.strptime(attendance.name, '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.utc).astimezone(active_tz) next_attendance_date = str_now next_attendance_ids = False # should we compute for sign out too? if attendance.action == 'sign_in': next_attendance_ids = self.search(cr, uid, [ ('employee_id', '=', attendance.employee_id.id), - ('name', '>', attendance.name)], order='name', context=context) + ('name', '>', attendance.name)], order='name') if next_attendance_ids: - next_attendance = self.browse(cr, uid, next_attendance_ids[0], context=context) + next_attendance = self.browse(cr, uid, next_attendance_ids[0]) if next_attendance.action == 'sign_in': # 2012.10.16 LF FIX : Attendance in context timezone - raise orm.except_orm(_('Error'), _( - 'Incongruent data: sign-in %s is followed by another sign-in' - ) % attendance_start) + raise osv.except_osv(_('Error'), _('Incongruent data: sign-in %s is followed by another sign-in') % attendance_start) next_attendance_date = next_attendance.name - # 2012.10.16 LF FIX : Attendance in context timezone - attendance_stop = datetime.strptime( - next_attendance_date, '%Y-%m-%d %H:%M:%S' - ).replace(tzinfo=pytz.utc).astimezone(active_tz) - duration_delta = attendance_stop - attendance_start - duration = self.total_seconds(duration_delta) / 60.0 / 60.0 - duration = round(duration / precision) * precision + # 2012.10.16 LF FIX : Attendance in context timezone + attendance_stop = datetime.strptime(next_attendance_date, '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.utc).astimezone(active_tz) + duration_delta = attendance_stop - attendance_start + duration = duration_delta.total_seconds() / 60.0 / 60.0 + duration = round(duration / precision) * precision res[attendance.id]['duration'] = duration res[attendance.id]['end_datetime'] = next_attendance_date - # If calendar is not specified: working days = 24/7 + # If contract is not specified: working days = 24/7 res[attendance.id]['inside_calendar_duration'] = duration res[attendance.id]['outside_calendar_duration'] = 0.0 - reference_calendar = self.get_reference_calendar( - cr, uid, attendance.employee_id.id, date=str_now[:10], context=context) + if next_attendance_ids: + active_contract_ids = self.get_active_contracts(cr, uid, attendance.employee_id.id, date=str_now[:10]) - if reference_calendar and next_attendance_ids: - if reference_calendar: - # TODO applicare prima arrotondamento o tolleranza? - if reference_calendar.attendance_rounding: - float_attendance_rounding = float(reference_calendar.attendance_rounding) - rounded_start_hour = self._ceil_rounding( - float_attendance_rounding, attendance_start) - rounded_stop_hour = self._floor_rounding( - float_attendance_rounding, attendance_stop) - - if abs(1- rounded_start_hour) < 0.01: # if shift == 1 hour - attendance_start = datetime(attendance_start.year, attendance_start.month, - attendance_start.day, attendance_start.hour + 1) - else: - attendance_start = datetime(attendance_start.year, attendance_start.month, - attendance_start.day, attendance_start.hour, int(round(rounded_start_hour * 60.0))) + if active_contract_ids: + contract = contract_pool.browse(cr, uid, active_contract_ids[0]) + if contract.working_hours: + # TODO applicare prima arrotondamento o tolleranza? + if contract.working_hours.attendance_rounding: + float_attendance_rounding = float(contract.working_hours.attendance_rounding) + rounded_start_hour = self._ceil_rounding(float_attendance_rounding, attendance_start) + rounded_stop_hour = self._floor_rounding(float_attendance_rounding, attendance_stop) - attendance_stop = datetime(attendance_stop.year, attendance_stop.month, - attendance_stop.day, attendance_stop.hour, - int(round(rounded_stop_hour * 60.0))) - - # again - duration_delta = attendance_stop - attendance_start - duration = self.total_seconds(duration_delta) / 60.0 / 60.0 - duration = round(duration / precision) * precision - res[attendance.id]['duration'] = duration - - res[attendance.id]['inside_calendar_duration'] = 0.0 - res[attendance.id]['outside_calendar_duration'] = 0.0 - calendar_id = reference_calendar.id - intervals_within = 0 - - # split attendance in intervals = precision - # 2012.10.16 LF FIX : no recursion in split attendance - splitted_attendances = self._split_no_recursive_attendance( - attendance_start, duration, precision) - counter = 0 - for atomic_attendance in splitted_attendances: - counter += 1 - centered_attendance = atomic_attendance[0] + timedelta( - 0,0,0,0,0, atomic_attendance[1] / 2.0) - centered_attendance_hour = ( - centered_attendance.hour + centered_attendance.minute / 60.0 - + centered_attendance.second / 60.0 / 60.0 - ) - # check if centered_attendance is within a working schedule - # 2012.10.16 LF FIX : weekday must be single character not int - weekday_char = str(unichr(centered_attendance.weekday() + 48)) - matched_schedule_ids = attendance_pool.search(cr, uid, [ - '&', - '|', - ('date_from', '=', False), - ('date_from','<=',centered_attendance.date()), - '|', - ('dayofweek', '=', False), - ('dayofweek','=',weekday_char), - ('calendar_id','=',calendar_id), - ('hour_to','>=',centered_attendance_hour), - ('hour_from','<=',centered_attendance_hour), - ], context=context) - if len(matched_schedule_ids) > 1: - raise orm.except_orm(_('Error'), - _('Wrongly configured working schedule with id %s') % str(calendar_id)) - if matched_schedule_ids: - intervals_within += 1 - # sign in tolerance - if intervals_within == 1: - calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0], context=context) - attendance_start_hour = ( - attendance_start.hour + attendance_start.minute / 60.0 - + attendance_start.second / 60.0 / 60.0 - ) - if attendance_start_hour >= ( - calendar_attendance.hour_from and - (attendance_start_hour - (calendar_attendance.hour_from + - calendar_attendance.tolerance_to)) < 0.01 - ): # handling float roundings (<=) - additional_intervals = round( - (attendance_start_hour - calendar_attendance.hour_from) / precision) - intervals_within += additional_intervals - res[attendance.id]['duration'] = self.time_sum( - res[attendance.id]['duration'], additional_intervals * precision) - # sign out tolerance - if len(splitted_attendances) == counter: - attendance_stop_hour = ( - attendance_stop.hour + attendance_stop.minute / 60.0 - + attendance_stop.second / 60.0 / 60.0 - ) - calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0], context=context) - if attendance_stop_hour <= ( - calendar_attendance.hour_to and - (attendance_stop_hour - (calendar_attendance.hour_to - - calendar_attendance.tolerance_from)) > -0.01 - ): # handling float roundings (>=) - additional_intervals = round( - (calendar_attendance.hour_to - attendance_stop_hour) / precision) - intervals_within += additional_intervals - res[attendance.id]['duration'] = self.time_sum( - res[attendance.id]['duration'], additional_intervals * precision) - - res[attendance.id]['inside_calendar_duration'] = intervals_within * precision - # make difference using time in order to avoid rounding errors - # inside_calendar_duration can't be > duration - res[attendance.id]['outside_calendar_duration'] = self.time_difference( - res[attendance.id]['inside_calendar_duration'], - res[attendance.id]['duration']) - - if reference_calendar.overtime_rounding: - if res[attendance.id]['outside_calendar_duration']: - overtime = res[attendance.id]['outside_calendar_duration'] - if reference_calendar.overtime_rounding_tolerance: - overtime = self.time_sum(overtime, - reference_calendar.overtime_rounding_tolerance) - float_overtime_rounding = float(reference_calendar.overtime_rounding) - res[attendance.id]['outside_calendar_duration'] = math.floor( - overtime * float_overtime_rounding) / float_overtime_rounding - + if abs(1- rounded_start_hour) < 0.01: # if shift == 1 hour + attendance_start = datetime(attendance_start.year, attendance_start.month, + attendance_start.day, attendance_start.hour + 1) + else: + attendance_start = datetime(attendance_start.year, attendance_start.month, + attendance_start.day, attendance_start.hour, int(round(rounded_start_hour * 60.0))) + + attendance_stop = datetime(attendance_stop.year, attendance_stop.month, + attendance_stop.day, attendance_stop.hour, int(round(rounded_stop_hour * 60.0))) + + # again + duration_delta = attendance_stop - attendance_start + duration = duration_delta.total_seconds() / 60.0 / 60.0 + duration = round(duration / precision) * precision + res[attendance.id]['duration'] = duration + + res[attendance.id]['inside_calendar_duration'] = 0.0 + res[attendance.id]['outside_calendar_duration'] = 0.0 + calendar_id = contract.working_hours.id + intervals_within = 0 + + # split attendance in intervals = precision + # 2012.10.16 LF FIX : no recursion in split attendance + splitted_attendances = self._split_norecurse_attendance(attendance_start, duration, precision) + counter = 0 + for atomic_attendance in splitted_attendances: + counter += 1 + centered_attendance = atomic_attendance[0] + timedelta(0,0,0,0,0, atomic_attendance[1] / 2.0) + centered_attendance_hour = centered_attendance.hour + centered_attendance.minute / 60.0 \ + + centered_attendance.second / 60.0 / 60.0 + # check if centered_attendance is within a working schedule + # 2012.10.16 LF FIX : weekday must be single character not int + weekday_char = str(unichr(centered_attendance.weekday() + 48)) + matched_schedule_ids = attendance_pool.search(cr, uid, [ + '&', + '|', + ('date_from', '=', False), + ('date_from','<=',centered_attendance.date()), + '|', + ('dayofweek', '=', False), + ('dayofweek','=',weekday_char), + ('calendar_id','=',calendar_id), + ('hour_to','>=',centered_attendance_hour), + ('hour_from','<=',centered_attendance_hour), + ]) + if len(matched_schedule_ids) > 1: + raise osv.except_osv(_('Error'), + _('Wrongly configured working schedule with id %s') % str(calendar_id)) + if matched_schedule_ids: + intervals_within += 1 + # sign in tolerance + if intervals_within == 1: + calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0]) + attendance_start_hour = attendance_start.hour + attendance_start.minute / 60.0 \ + + attendance_start.second / 60.0 / 60.0 + if attendance_start_hour >= calendar_attendance.hour_from and \ + (attendance_start_hour - (calendar_attendance.hour_from + + calendar_attendance.tolerance_to)) < 0.01: # handling float roundings (<=) + additional_intervals = round( + (attendance_start_hour - calendar_attendance.hour_from) / precision) + intervals_within += additional_intervals + res[attendance.id]['duration'] = self.time_sum( + res[attendance.id]['duration'], additional_intervals * precision) + # sign out tolerance + if len(splitted_attendances) == counter: + attendance_stop_hour = attendance_stop.hour + attendance_stop.minute / 60.0 \ + + attendance_stop.second / 60.0 / 60.0 + calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0]) + if attendance_stop_hour <= calendar_attendance.hour_to and \ + (attendance_stop_hour - (calendar_attendance.hour_to - + calendar_attendance.tolerance_from)) > -0.01: # handling float roundings (>=) + additional_intervals = round( + (calendar_attendance.hour_to - attendance_stop_hour) / precision) + intervals_within += additional_intervals + res[attendance.id]['duration'] = self.time_sum( + res[attendance.id]['duration'], additional_intervals * precision) + + res[attendance.id]['inside_calendar_duration'] = intervals_within * precision + # make difference using time in order to avoid rounding errors + # inside_calendar_duration can't be > duration + res[attendance.id]['outside_calendar_duration'] = self.time_difference( + res[attendance.id]['inside_calendar_duration'], res[attendance.id]['duration'], precision=precision) + + if contract.working_hours.overtime_rounding: + if res[attendance.id]['outside_calendar_duration']: + overtime = res[attendance.id]['outside_calendar_duration'] + if contract.working_hours.overtime_rounding_tolerance: + overtime = self.time_sum(overtime, + contract.working_hours.overtime_rounding_tolerance) + float_overtime_rounding = float(contract.working_hours.overtime_rounding) + res[attendance.id]['outside_calendar_duration'] = math.floor( + overtime * float_overtime_rounding) / float_overtime_rounding return res def _get_by_contracts(self, cr, uid, ids, context=None): attendance_ids = [] attendance_pool = self.pool.get('hr.attendance') for contract in self.pool.get('hr.contract').browse(cr, uid, ids, context=context): - att_ids = attendance_pool.search(cr, uid, [('employee_id', '=', contract.employee_id.id)], context=context) + att_ids = attendance_pool.search(cr, uid, [('employee_id', '=', contract.employee_id.id)]) for att_id in att_ids: if att_id not in attendance_ids: attendance_ids.append(att_id) @@ -360,7 +316,7 @@ attendance_pool = self.pool.get('hr.attendance') contract_pool = self.pool.get('hr.contract') for calendar in self.pool.get('resource.calendar').browse(cr, uid, ids, context=context): - contract_ids = contract_pool.search(cr, uid, [('working_hours', '=', calendar.id)], context=context) + contract_ids = contract_pool.search(cr, uid, [('working_hours', '=', calendar.id)]) att_ids = attendance_pool._get_by_contracts(cr, uid, contract_ids, context=None) for att_id in att_ids: if att_id not in attendance_ids: @@ -387,31 +343,46 @@ ('employee_id', '=', attendance.employee_id.id), ('name', '<', attendance.name), ('action', '=', 'sign_in'), - ], order='name', context=context) + ], order='name') if previous_attendance_ids and previous_attendance_ids[len(previous_attendance_ids) - 1] not in attendance_ids: attendance_ids.append(previous_attendance_ids[len(previous_attendance_ids) - 1]) return attendance_ids _inherit = "hr.attendance" - _store_rules = { - 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20), - 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20), - 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20), - 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20), - } - _columns = { 'duration': fields.function(_get_attendance_duration, method=True, multi='duration', string="Attendance duration", - store=_store_rules), + store={ + 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20), + 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20), + 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20), + 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20), + } + ), 'end_datetime': fields.function(_get_attendance_duration, method=True, multi='duration', type="datetime", string="End date time", - store=_store_rules), + store={ + 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20), + 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20), + 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20), + 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20), + }), 'outside_calendar_duration': fields.function(_get_attendance_duration, method=True, multi='duration', string="Overtime", - store=_store_rules), + store={ + 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20), + 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20), + 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20), + 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20), + }), 'inside_calendar_duration': fields.function(_get_attendance_duration, method=True, multi='duration', string="Duration within working schedule", - store=_store_rules), + store={ + 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20), + 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20), + 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20), + 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20), + }), } +hr_attendance() Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_attendance.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/hr_attendance.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_attendance_view.xml /media/GRMCPRXFRER/hr_attendance_analysis/hr_attendance_view.xml --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_attendance_view.xml 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/hr_attendance_view.xml 2014-05-28 04:23:06.000000000 +0200 @@ -6,6 +6,7 @@ <field name="name">hr.attendance.form</field> <field name="model">hr.attendance</field> <field name="inherit_id" ref="hr_attendance.view_attendance_form"></field> + <field name="type">form</field> <field name="arch" type="xml"> <field name="action_desc" position="after"> <field name="duration" widget="float_time"/> @@ -18,6 +19,7 @@ <record id="view_attendance_analysis" model="ir.ui.view"> <field name="name">hr.attendance.analysis</field> <field name="model">hr.attendance</field> + <field name="type">tree</field> <field name="priority" eval="17"/> <field name="arch" type="xml"> <tree string="Employee attendances analysis"> @@ -35,6 +37,7 @@ <record model="ir.ui.view" id="view_hr_attendance_filter"> <field name="name">view_hr_attendance_filter</field> <field name="model">hr.attendance</field> + <field name="type">search</field> <field name="arch" type="xml"> <search string="Hr Attendance Search"> <filter icon="terp-go-today" string="Today" name="today" domain="[('name::date','=',current_date)]" /> @@ -55,6 +58,7 @@ <record model="ir.ui.view" id="view_hr_attendance_calendar"> <field name="name">view_hr_attendance.calendar</field> <field name="model">hr.attendance</field> + <field name="type">calendar</field> <field name="arch" type="xml"> <calendar string="Calendar View" date_start="name" date_stop="end_datetime" color="employee_id"> <field name="duration" /> diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_contract.py /media/GRMCPRXFRER/hr_attendance_analysis/hr_contract.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_contract.py 2014-05-30 01:07:03.115142290 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/hr_contract.py 1970-01-01 02:00:00.000000000 +0200 @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Authors: Stéphane Bidoul & Laetitia Gangloff -# Copyright (c) 2013 Acsone SA/NV (http://www.acsone.eu) -# All Rights Reserved -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsibility of assessing all potential -# consequences resulting from its eventual inadequacies and bugs. -# End users who are looking for a ready-to-use solution with commercial -# guarantees and support are strongly advised to contact a Free Software -# Service Company. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -############################################################################## -import datetime - -from openerp.osv import fields, orm - - -class hr_contract(orm.Model): - _inherit = 'hr.contract' - - def copy(self, cr, uid, id, defaults, context=None): - """ - When duplicate a contract set the start date to the last end date + 1 day. - If the last end date is False, do nothing - """ - contract = self.browse(cr, uid, id, context=context) - end_date_contract_id = self.search(cr, uid, [('employee_id', '=', contract.employee_id.id), ], limit=1, order='date_end desc', context=context) - last_end_date = False - if end_date_contract_id: - contract = self.browse(cr, uid, end_date_contract_id, context=context) - last_end_date = contract[0].date_end - - if last_end_date: - defaults['date_start'] = datetime.datetime.strftime(datetime.datetime.strptime(last_end_date, "%Y-%m-%d") + datetime.timedelta(days=1), "%Y-%m-%d") - defaults['date_end'] = False - defaults['trial_date_start'] = False - defaults['trial_date_end'] = False - return super(hr_contract, self).copy(cr, uid, id, defaults, context=context) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/hr_contract.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/hr_contract.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/i18n/it.po /media/GRMCPRXFRER/hr_attendance_analysis/i18n/it.po --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/i18n/it.po 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/i18n/it.po 2014-05-28 04:26:18.000000000 +0200 @@ -6,22 +6,20 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0.3\n" "Report-Msgid-Bugs-To: [hidden email]\n" -"POT-Creation-Date: 2011-12-23 10:03+0000\n" -"PO-Revision-Date: 2013-09-22 17:18+0000\n" -"Last-Translator: Lorenzo Battistini - Agile BG " -"<[hidden email]>\n" +"POT-Creation-Date: 2011-12-23 10:04+0000\n" +"PO-Revision-Date: 2011-12-23 11:18+0100\n" +"Last-Translator: Lorenzo Battistini <[hidden email]>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-05-22 06:43+0000\n" -"X-Generator: Launchpad (build 17017)\n" +"Plural-Forms: \n" #. module: hr_attendance_analysis #: code:addons/hr_attendance_analysis/hr_attendance.py:123 #, python-format -msgid "Incongruent data" -msgstr "" +msgid "Incongruent data: sign-in %s is followed by another sign-in" +msgstr "Dati incongruenti: l'entrata %s è seguita da un'altra entrata" #. module: hr_attendance_analysis #: code:addons/hr_attendance_analysis/hr_attendance.py:87 @@ -36,9 +34,7 @@ #. module: hr_attendance_analysis #: help:res.company,working_time_precision:0 msgid "The precision used to analyse working times over working schedule" -msgstr "" -"La precisione utilizzata per analizzare le ore lavorative rispetto al " -"calendario di lavoro" +msgstr "La precisione utilizzata per analizzare le ore lavorative rispetto al calendario di lavoro" #. module: hr_attendance_analysis #: view:hr.attendance:0 @@ -115,13 +111,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar,attendance_rounding:0 -msgid "" -"For instance, using rounding = 15 minutes, every sign in will be rounded to " -"the following quarter hour and every sign out to the previous quarter hour" -msgstr "" -"Per esempio, utilizzando un arrotondamento = 15 minuti, ogni entrata verrà " -"arrotondata al quarto d'ora successivo ed ogni uscita al quarto d'ora " -"precedente" +msgid "For instance, using rounding = 15 minutes, every sign in will be rounded to the following quarter hour and every sign out to the previous quarter hour" +msgstr "Per esempio, utilizzando un arrotondamento = 15 minuti, ogni entrata verrà arrotondata al quarto d'ora successivo ed ogni uscita al quarto d'ora precedente" #. module: hr_attendance_analysis #: report:addons/hr_attendance_analysis/report/calendar_report.mako:80 @@ -130,12 +121,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar.attendance,tolerance_to:0 -msgid "" -"Sign in done in the interval \"Work from + Tolerance to\" will be considered " -"done at \"Work from\"" -msgstr "" -"Le entrate effettuate nell'intervallo \"Lavoro da + Tolleranza a\" saranno " -"considerate come fatte in \"Lavoro da\"" +msgid "Sign in done in the interval \"Work from + Tolerance to\" will be considered done at \"Work from\"" +msgstr "Le entrate effettuate nell'intervallo \"Lavoro da + Tolleranza a\" saranno considerate come fatte in \"Lavoro da\"" #. module: hr_attendance_analysis #: field:resource.calendar.attendance,tolerance_from:0 @@ -205,13 +192,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar,overtime_rounding:0 -msgid "" -"Setting rounding = 30 minutes, an overtime of 29 minutes will be considered " -"as 0 minutes, 31 minutes as 30 minutes, 61 minutes as 1 hour and so on" -msgstr "" -"Impostando un arrotondamento = 30 minuti, uno straordinario di 29 minuti " -"sarà considerato come 0 minuti, 31 minuti come 30 minuti, 61 minuti come " -"un'ora e così via" +msgid "Setting rounding = 30 minutes, an overtime of 29 minutes will be considered as 0 minutes, 31 minutes as 30 minutes, 61 minutes as 1 hour and so on" +msgstr "Impostando un arrotondamento = 30 minuti, uno straordinario di 29 minuti sarà considerato come 0 minuti, 31 minuti come 30 minuti, 61 minuti come un'ora e così via" #. module: hr_attendance_analysis #: field:resource.calendar,attendance_rounding:0 @@ -228,9 +210,7 @@ #. module: hr_attendance_analysis #: constraint:hr.attendance:0 msgid "Error: Sign in (resp. Sign out) must follow Sign out (resp. Sign in)" -msgstr "" -"Errore: una operazione di Entrata (Uscita) deve essere seguito da una Uscita " -"(Entrata)" +msgstr "Errore: una operazione di Entrata (Uscita) deve essere seguito da una Uscita (Entrata)" #. module: hr_attendance_analysis #: view:res.company:0 @@ -265,14 +245,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar,leave_rounding:0 -msgid "" -"On the contrary of overtime rounding, using rounding = 15 minutes, a leave " -"of 1 minute will be considered as 15 minutes, 16 minutes as 30 minutes and " -"so on" -msgstr "" -"Al contrario dell'arrotondamento straordinari, utilizzando un arrotondamento " -"= 15 minuti, un'assenza di 1 minuto verrà considerata come di 15 minuti, 16 " -"minuti come 30 minuti e così via" +msgid "On the contrary of overtime rounding, using rounding = 15 minutes, a leave of 1 minute will be considered as 15 minutes, 16 minutes as 30 minutes and so on" +msgstr "Al contrario dell'arrotondamento straordinari, utilizzando un arrotondamento = 15 minuti, un'assenza di 1 minuto verrà considerata come di 15 minuti, 16 minuti come 30 minuti e così via" #. module: hr_attendance_analysis #: model:ir.actions.report.xml,name:hr_attendance_analysis.attendance_analysis_report_id @@ -379,7 +353,7 @@ #. module: hr_attendance_analysis #: report:addons/hr_attendance_analysis/report/calendar_report.mako:10 msgid "Employee: " -msgstr "Dipendente: " +msgstr "Dipendente:" #. module: hr_attendance_analysis #: selection:resource.calendar,attendance_rounding:0 @@ -435,17 +409,13 @@ msgid "" "\n" "Dynamic reports based on employee's attendances and contract's calendar.\n" -"Among other things, it lets you see the amount of working hours outside and " -"inside the contract's working schedule (overtime).\n" -"It also provides a daily based report, showing the detailed and total hours " -"compared to calendar hours.\n" +"Among other things, it lets you see the amount of working hours outside and inside the contract's working schedule (overtime).\n" +"It also provides a daily based report, showing the detailed and total hours compared to calendar hours.\n" msgstr "" "\n" "Dynamic reports based on employee's attendances and contract's calendar.\n" -"Among other things, it lets you see the amount of working hours outside and " -"inside the contract's working schedule (overtime).\n" -"It also provides a daily based report, showing the detailed and total hours " -"compared to calendar hours.\n" +"Among other things, it lets you see the amount of working hours outside and inside the contract's working schedule (overtime).\n" +"It also provides a daily based report, showing the detailed and total hours compared to calendar hours.\n" #. module: hr_attendance_analysis #: selection:resource.calendar,attendance_rounding:0 @@ -480,12 +450,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar.attendance,tolerance_from:0 -msgid "" -"Sign out done in the interval \"Work to - Tolerance from\" will be " -"considered done at \"Work to\"" -msgstr "" -"Le uscite effettuate nell'intervallo \"Lavoro a - Tolleranza da\" saranno " -"considerate come fatte in \"Lavoro a\"" +msgid "Sign out done in the interval \"Work to - Tolerance from\" will be considered done at \"Work to\"" +msgstr "Le uscite effettuate nell'intervallo \"Lavoro a - Tolleranza da\" saranno considerate come fatte in \"Lavoro a\"" #. module: hr_attendance_analysis #: report:addons/hr_attendance_analysis/report/calendar_report.mako:21 @@ -571,12 +537,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar.overtime.type,limit:0 -msgid "" -"Limit, in hours, of overtime that can be imputed to this type of overtime in " -"a day. The surplus is imputed to the subsequent type" -msgstr "" -"Limite, in ore, dello straordinario che può essere attribuito a questo tipo " -"di straordinario in un giorno. L'eccedenza è attribuita al tipo successivo." +msgid "Limit, in hours, of overtime that can be imputed to this type of overtime in a day. The surplus is imputed to the subsequent type" +msgstr "Limite, in ore, dello straordinario che può essere attribuito a questo tipo di straordinario in un giorno. L'eccedenza è attribuita al tipo successivo." #. module: hr_attendance_analysis #: report:addons/hr_attendance_analysis/report/calendar_report.mako:26 @@ -585,14 +547,8 @@ #. module: hr_attendance_analysis #: help:resource.calendar,overtime_rounding_tolerance:0 -msgid "" -"Overtime can be rounded using a tolerance. Using tolerance = 3 minutes and " -"rounding = 15 minutes, if employee does overtime of 12 minutes, it will be " -"considered as 15 minutes." -msgstr "" -"Lo straordinario può essere arrotondato usando una tolleranza. Con una " -"tolleranza = 3 minuti e arrotondamento = 15 minuti, se il dipendente fa uno " -"straordinario di 12 minuti, sarà considerato come 15 minuti." +msgid "Overtime can be rounded using a tolerance. Using tolerance = 3 minutes and rounding = 15 minutes, if employee does overtime of 12 minutes, it will be considered as 15 minutes." +msgstr "Lo straordinario può essere arrotondato usando una tolleranza. Con una tolleranza = 3 minuti e arrotondamento = 15 minuti, se il dipendente fa uno straordinario di 12 minuti, sarà considerato come 15 minuti." #. module: hr_attendance_analysis #: field:resource.calendar.overtime.type,sequence:0 @@ -609,3 +565,4 @@ #, python-format msgid "Saturday" msgstr "Sabato" + diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/__init__.py /media/GRMCPRXFRER/hr_attendance_analysis/__init__.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/__init__.py 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/__init__.py 2014-05-28 04:23:26.000000000 +0200 @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # +# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>) # Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published @@ -13,14 +12,13 @@ # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## import hr_attendance -import hr_contract import report import wizard import resource Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/__init__.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/__init__.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/__openerp__.py /media/GRMCPRXFRER/hr_attendance_analysis/__openerp__.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/__openerp__.py 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/__openerp__.py 2014-05-28 04:23:26.000000000 +0200 @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # +# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>) # Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published @@ -13,7 +12,7 @@ # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. @@ -23,7 +22,6 @@ 'name': "HR - Attendance Analysis", 'version': '0.1', 'category': 'Generic Modules/Human Resources', - 'summary': "Dynamic reports based on employee's attendances and contract's calendar", 'description': """ Dynamic reports based on employee's attendances and contract's calendar. Among other things, it lets you see the amount of working hours outside and inside the contract's working schedule (overtime). @@ -32,12 +30,17 @@ - Tolerance for sign-in and sign-out - Attendances and overtimes roundings - Diffrent types of overtime, according to the overtime amount + +This module requires python 2.7 or later +---------------------------------------- + """, 'author': 'Agile Business Group', 'website': 'http://www.agilebg.com', 'license': 'AGPL-3', "depends" : ['hr_attendance', 'hr_contract', 'hr_holidays', 'report_webkit'], - "data" : [ + "init_xml" : [], + "update_xml" : [ 'company_view.xml', 'hr_attendance_view.xml', 'reports.xml', @@ -45,7 +48,7 @@ 'resource_view.xml', 'security/ir.model.access.csv', ], - "demo" : [], + "demo_xml" : [], "active": False, "installable": True } diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/report/calendar_report.mako /media/GRMCPRXFRER/hr_attendance_analysis/report/calendar_report.mako --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/report/calendar_report.mako 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/report/calendar_report.mako 2014-05-28 04:25:40.000000000 +0200 @@ -1,4 +1,3 @@ -## -*- coding: utf-8 -*- <html> <head> <style type="text/css"> diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/report/calendar_report.py /media/GRMCPRXFRER/hr_attendance_analysis/report/calendar_report.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/report/calendar_report.py 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/report/calendar_report.py 2014-05-28 04:25:38.000000000 +0200 @@ -28,18 +28,23 @@ class Parser(report_sxw.rml_parse): def _get_day_of_week(self, day): - WEEKDAYS = { - 0: _('Monday'), - 1: _('Tuesday'), - 2: _('Wednesday'), - 3: _('Thursday'), - 4: _('Friday'), - 5: _('Saturday'), - 6: _('Sunday'), - } dayofweek='' weekday = datetime.strptime(day,'%Y-%m-%d').weekday() - return WEEKDAYS[weekday] + if weekday == 0: + dayofweek = _('Monday') + elif weekday == 1: + dayofweek = _('Tuesday') + elif weekday == 2: + dayofweek = _('Wednesday') + elif weekday == 3: + dayofweek = _('Thursday') + elif weekday == 4: + dayofweek = _('Friday') + elif weekday == 5: + dayofweek = _('Saturday') + elif weekday == 6: + dayofweek = _('Sunday') + return dayofweek def _get_month_name(self, day): str_month='' Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/report/calendar_report.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/report/calendar_report.pyc differ Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/report/__init__.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/report/__init__.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/resource.py /media/GRMCPRXFRER/hr_attendance_analysis/resource.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/resource.py 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/resource.py 2014-05-28 04:23:00.000000000 +0200 @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # +# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>) # Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published @@ -13,16 +12,16 @@ # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## -from openerp.osv import fields, orm +from osv import fields, osv -class resource_calendar_attendance(orm.Model): +class resource_calendar_attendance(osv.osv): _inherit = "resource.calendar.attendance" _columns = { 'tolerance_from': fields.float('Tolerance from', size=8, @@ -31,8 +30,9 @@ help='Sign in done in the interval "Work from + Tolerance to" will be considered done at "Work from"'), } +resource_calendar_attendance() -class resource_calendar(orm.Model): +class resource_calendar(osv.osv): _inherit = "resource.calendar" _columns = { 'attendance_rounding': fields.selection([ @@ -88,8 +88,9 @@ help='On the contrary of overtime rounding, using rounding = 15 minutes, a leave of 1 minute will be considered as 15 minutes, 16 minutes as 30 minutes and so on'), 'overtime_type_ids': fields.one2many('resource.calendar.overtime.type', 'calendar_id', 'Overtime types'), } +resource_calendar() -class resource_calendar_overtime_range(orm.Model): +class resource_calendar_overtime_range(osv.osv): _name = 'resource.calendar.overtime.type' _description = 'Overtime type' _order = 'sequence' @@ -100,3 +101,4 @@ 'limit': fields.float('Limit', size=8, help='Limit, in hours, of overtime that can be imputed to this type of overtime in a day. The surplus is imputed to the subsequent type') } +resource_calendar_overtime_range() Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/resource.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/resource.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/resource_view.xml /media/GRMCPRXFRER/hr_attendance_analysis/resource_view.xml --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/resource_view.xml 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/resource_view.xml 2014-05-28 04:22:38.000000000 +0200 @@ -5,6 +5,7 @@ <record id="view_resource_calendar_attendance_form" model="ir.ui.view"> <field name="name">resource.calendar.attendance.form</field> <field name="model">resource.calendar.attendance</field> + <field name="type">form</field> <field name="inherit_id" ref="resource.view_resource_calendar_attendance_form"></field> <field name="arch" type="xml"> <field name="hour_from" position="after"> @@ -18,17 +19,16 @@ <record id="resource_calendar_form" model="ir.ui.view"> <field name="name">resource.calendar.form</field> <field name="model">resource.calendar</field> + <field name="type">form</field> <field name="inherit_id" ref="resource.resource_calendar_form"></field> <field name="arch" type="xml"> <field name="attendance_ids" position="after"> <notebook colspan="4"> <page string="Roundings"> - <group colspan="4"> - <field name="attendance_rounding"/> - <field name="leave_rounding"/> - <field name="overtime_rounding"/> - <field name="overtime_rounding_tolerance" widget="float_time"/> - </group> + <field name="attendance_rounding"/> + <field name="leave_rounding"/> + <field name="overtime_rounding"/> + <field name="overtime_rounding_tolerance" widget="float_time"/> </page> <page string="Overtime types"> <field name="overtime_type_ids" colspan="4" nolabel="1"> diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/__init__.py /media/GRMCPRXFRER/hr_attendance_analysis/wizard/__init__.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/__init__.py 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/wizard/__init__.py 2014-05-28 04:24:32.000000000 +0200 @@ -1,21 +1,18 @@ -# -*- coding: utf-8 -*- ############################################################################## # -# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) +# Copyright (C) 2011 OpenERP Italian Community (<http://www.openerp-italia.org>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU General Public License for more details. # -# You should have received a copy of the GNU Affero General Public License +# You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/__init__.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/wizard/__init__.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.py /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.py --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.py 2014-05-30 02:13:49.425473465 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.py 2014-05-28 04:24:32.000000000 +0200 @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # +# Copyright (C) 2011 Agile Business Group sagl (<http://www.agilebg.com>) # Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published @@ -13,20 +12,20 @@ # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## -from openerp.osv import fields, orm -from openerp.tools.translate import _ +from osv import fields,osv +from tools.translate import _ from datetime import * import math import calendar -class wizard_calendar_report(orm.TransientModel): +class wizard_calendar_report(osv.osv_memory): _columns = { 'month': fields.selection([ @@ -55,7 +54,7 @@ 'year': lambda * a: datetime.now().year, 'from_date': lambda * a: (datetime.now()-timedelta(30)).strftime('%Y-%m-%d'), 'to_date': lambda * a: datetime.now().strftime('%Y-%m-%d'), - 'employee_ids': lambda s, cr, uid, c: s.pool.get('hr.employee').search(cr, uid, [], context=None), + 'employee_ids': lambda s, cr, uid, c: s.pool.get('hr.employee').search(cr, uid, []), } _name = "attendance_analysis.wizard.calendar_report" @@ -74,15 +73,16 @@ if context is None: context = {} attendance_pool = self.pool.get('hr.attendance') + contract_pool = self.pool.get('hr.contract') holidays_pool = self.pool.get('hr.holidays') days_by_employee = {} - form = self.read(cr, uid, ids, context=context)[0] + form = self.read(cr, uid, ids)[0] from_date = datetime.strptime(form['from_date'], '%Y-%m-%d') to_date = datetime.strptime(form['to_date'], '%Y-%m-%d') if from_date > to_date: - raise orm.except_orm(_('Error'), _('From date must be < to date')) + raise osv.except_osv(_('Error'), _('From date must be < to date')) employee_ids=form['employee_ids'] delta = to_date - from_date max_number_of_attendances_per_day = 0 @@ -96,7 +96,7 @@ current_total_attendances = 0.0 current_total_overtime = 0.0 current_total_leaves = 0.0 - current_total_due = 24.0 # If calendar is not specified: working days = 24/7 + current_total_due = 24.0 # If contract is not specified: working days = 24/7 current_total_inside_calendar = 0.0 str_current_date = current_date.strftime('%Y-%m-%d') days_by_employee[employee_id][str_current_date] = { @@ -110,8 +110,7 @@ 'signout_4': '', } current_date_beginning = datetime.combine(current_date, time()) - str_current_date_beginning = current_date_beginning.strftime( - '%Y-%m-%d %H:%M:%S') + str_current_date_beginning = current_date_beginning.strftime('%Y-%m-%d %H:%M:%S') current_date_end = datetime.combine(current_date, time())+ timedelta(1) str_current_date_end = current_date_end.strftime('%Y-%m-%d %H:%M:%S') @@ -120,21 +119,20 @@ ('name','>=',str_current_date_beginning), ('name','<=',str_current_date_end), ('action','=','sign_in'), - ], context=context) + ]) # computing attendance totals - for attendance in attendance_pool.browse(cr, uid, attendance_ids, context=context): - current_total_attendances = attendance_pool.time_sum( - current_total_attendances,attendance.duration) + for attendance in attendance_pool.browse(cr, uid, attendance_ids): + current_total_attendances = attendance_pool.time_sum(current_total_attendances, + attendance.duration) current_total_overtime = attendance_pool.time_sum(current_total_overtime, attendance.outside_calendar_duration) - current_total_inside_calendar = attendance_pool.time_sum( - current_total_inside_calendar, + current_total_inside_calendar = attendance_pool.time_sum(current_total_inside_calendar, attendance.inside_calendar_duration) #printing up to 4 attendances if len(attendance_ids) < 5: count = 1 - for attendance in sorted(attendance_pool.browse(cr, uid, attendance_ids, context=context), + for attendance in sorted(attendance_pool.browse(cr, uid, attendance_ids), key=lambda x: x['name']): days_by_employee[employee_id][str_current_date][ 'signin_'+str(count)] = attendance.name[11:16] @@ -144,35 +142,26 @@ if len(attendance_ids) > max_number_of_attendances_per_day: max_number_of_attendances_per_day = len(attendance_ids) - days_by_employee[employee_id][str_current_date][ - 'attendances' - ] = current_total_attendances - days_by_employee[employee_id][str_current_date][ - 'overtime' - ] = current_total_overtime + days_by_employee[employee_id][str_current_date]['attendances'] = current_total_attendances + days_by_employee[employee_id][str_current_date]['overtime'] = current_total_overtime - reference_calendar = attendance_pool.get_reference_calendar( - cr, uid, int(employee_id), date=str_current_date, context=context) + active_contract_ids = attendance_pool.get_active_contracts( + cr, uid, int(employee_id), date=str_current_date) # computing due total - if reference_calendar: - if reference_calendar.attendance_ids: + if active_contract_ids: + contract = contract_pool.browse(cr, uid, active_contract_ids[0]) + if contract.working_hours and contract.working_hours.attendance_ids: current_total_due = 0.0 - for calendar_attendance in reference_calendar.attendance_ids: - if (( - not calendar_attendance.dayofweek - or int(calendar_attendance.dayofweek) == current_date.weekday() - ) - and ( - not calendar_attendance.date_from or - datetime.strptime(calendar_attendance.date_from,'%Y-%m-%d') - <= current_date - )): + for calendar_attendance in contract.working_hours.attendance_ids: + if (not calendar_attendance.dayofweek + or int(calendar_attendance.dayofweek) == current_date.weekday()) \ + and (not calendar_attendance.date_from or + datetime.strptime(calendar_attendance.date_from,'%Y-%m-%d') <= current_date): calendar_attendance_duration = attendance_pool.time_difference( calendar_attendance.hour_from, calendar_attendance.hour_to) if calendar_attendance_duration < 0: - raise orm.except_orm(_('Error'), - _("%s: 'Work to' is < 'Work from'") - % calendar_attendance.name) + raise osv.except_osv(_('Error'), + _("%s: 'Work to' is < 'Work from'") % calendar_attendance.name) current_total_due = attendance_pool.time_sum(current_total_due, calendar_attendance_duration) @@ -198,8 +187,8 @@ ('date_to', '>', str_current_date_end), ('state', '=', 'validate'), ('employee_id', '=', int(employee_id)), - ], context=context) - for holiday in holidays_pool.browse(cr, uid, holidays_ids, context=context): + ]) + for holiday in holidays_pool.browse(cr, uid, holidays_ids): date_from = datetime.strptime(holiday.date_from, '%Y-%m-%d %H:%M:%S') date_to = datetime.strptime(holiday.date_to, '%Y-%m-%d %H:%M:%S') # if beginned before today @@ -208,35 +197,27 @@ # if ends after today if date_to > current_date_end: date_to = current_date_end - current_total_leaves = attendance_pool.time_sum( - current_total_leaves, + current_total_leaves = attendance_pool.time_sum(current_total_leaves, (date_to - date_from).total_seconds() / 60.0 / 60.0) days_by_employee[employee_id][str_current_date]['leaves'] = current_total_leaves - if current_total_leaves > days_by_employee[employee_id][ - str_current_date]['due']: - days_by_employee[employee_id][str_current_date][ - 'leaves' - ] = days_by_employee[employee_id][str_current_date]['due'] - due_minus_leaves = attendance_pool.time_difference( - current_total_leaves, current_total_due) + if current_total_leaves > days_by_employee[employee_id][str_current_date]['due']: + days_by_employee[employee_id][str_current_date]['leaves'] = \ + days_by_employee[employee_id][str_current_date]['due'] + due_minus_leaves = attendance_pool.time_difference(current_total_leaves, current_total_due) if due_minus_leaves < current_total_inside_calendar: days_by_employee[employee_id][str_current_date]['negative'] = 0.0 else: - days_by_employee[employee_id][str_current_date][ - 'negative' - ] = attendance_pool.time_difference( - current_total_inside_calendar, due_minus_leaves) - - if reference_calendar: - if reference_calendar.leave_rounding: - float_rounding = float(reference_calendar.leave_rounding) - days_by_employee[employee_id][str_current_date][ - 'negative' - ] = math.floor( + days_by_employee[employee_id][str_current_date]['negative'] = \ + attendance_pool.time_difference(current_total_inside_calendar, due_minus_leaves) + + if active_contract_ids: + contract = contract_pool.browse(cr, uid, active_contract_ids[0]) + if contract.working_hours and contract.working_hours.leave_rounding: + float_rounding = float(contract.working_hours.leave_rounding) + days_by_employee[employee_id][str_current_date]['negative'] = math.floor( days_by_employee[employee_id][str_current_date]['negative'] * - float_rounding - ) / float_rounding + float_rounding) / float_rounding day_count += 1 @@ -269,83 +250,53 @@ days_by_employee[employee_id][str_date]['due']) # computing overtime types - reference_calendar = attendance_pool.get_reference_calendar( - cr, uid, int(employee_id), date=str_date, context=context) - if reference_calendar: - if reference_calendar.overtime_type_ids: - sorted_types = sorted( - reference_calendar.overtime_type_ids, - key=lambda k: k.sequence) - current_overtime = days_by_employee[employee_id][ - str_date]['overtime'] + active_contract_ids = attendance_pool.get_active_contracts( + cr, uid, int(employee_id), date=str_date) + if active_contract_ids: + contract = contract_pool.browse(cr, uid, active_contract_ids[0]) + if contract.working_hours and contract.working_hours.overtime_type_ids: + sorted_types = sorted(contract.working_hours.overtime_type_ids, key=lambda k: k.sequence) + current_overtime = days_by_employee[employee_id][str_date]['overtime'] for overtime_type in sorted_types: - if not totals_by_employee[employee_id]['total_types'].get( - overtime_type.name, False): - totals_by_employee[employee_id]['total_types'][ - overtime_type.name] = 0.0 + if not totals_by_employee[employee_id]['total_types'].get(overtime_type.name, False): + totals_by_employee[employee_id]['total_types'][overtime_type.name] = 0.0 if current_overtime: if current_overtime <= overtime_type.limit or not overtime_type.limit: totals_by_employee[employee_id]['total_types'][ - overtime_type.name] = attendance_pool.time_sum( - totals_by_employee[employee_id] - ['total_types'][overtime_type.name], - current_overtime) + overtime_type.name] = attendance_pool.time_sum(totals_by_employee[ + employee_id]['total_types'][overtime_type.name], current_overtime) current_overtime = 0.0 else: totals_by_employee[employee_id]['total_types'][ - overtime_type.name] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_types'] - [overtime_type.name], overtime_type.limit) + overtime_type.name] = attendance_pool.time_sum(totals_by_employee[ + employee_id]['total_types'][overtime_type.name], overtime_type.limit) current_overtime = attendance_pool.time_difference(overtime_type.limit, current_overtime) - days_by_employee[employee_id][str_date][ - 'attendances' - ] = attendance_pool.float_time_convert( + days_by_employee[employee_id][str_date]['attendances'] = attendance_pool.float_time_convert( days_by_employee[employee_id][str_date]['attendances']) - days_by_employee[employee_id][str_date][ - 'overtime' - ] = attendance_pool.float_time_convert( + days_by_employee[employee_id][str_date]['overtime'] = attendance_pool.float_time_convert( days_by_employee[employee_id][str_date]['overtime']) - days_by_employee[employee_id][str_date][ - 'negative' - ] = attendance_pool.float_time_convert( + days_by_employee[employee_id][str_date]['negative'] = attendance_pool.float_time_convert( days_by_employee[employee_id][str_date]['negative']) - days_by_employee[employee_id][str_date][ - 'leaves' - ] = attendance_pool.float_time_convert( + days_by_employee[employee_id][str_date]['leaves'] = attendance_pool.float_time_convert( days_by_employee[employee_id][str_date]['leaves']) - days_by_employee[employee_id][str_date][ - 'due' - ] = attendance_pool.float_time_convert( + days_by_employee[employee_id][str_date]['due'] = attendance_pool.float_time_convert( days_by_employee[employee_id][str_date]['due']) - totals_by_employee[employee_id][ - 'total_attendances' - ] = attendance_pool.float_time_convert( + totals_by_employee[employee_id]['total_attendances'] = attendance_pool.float_time_convert( totals_by_employee[employee_id]['total_attendances']) - totals_by_employee[employee_id][ - 'total_overtime' - ] = attendance_pool.float_time_convert( + totals_by_employee[employee_id]['total_overtime'] = attendance_pool.float_time_convert( totals_by_employee[employee_id]['total_overtime']) - totals_by_employee[employee_id][ - 'total_negative' - ] = attendance_pool.float_time_convert( + totals_by_employee[employee_id]['total_negative'] = attendance_pool.float_time_convert( totals_by_employee[employee_id]['total_negative']) - totals_by_employee[employee_id][ - 'total_leaves' - ] = attendance_pool.float_time_convert( + totals_by_employee[employee_id]['total_leaves'] = attendance_pool.float_time_convert( totals_by_employee[employee_id]['total_leaves']) - totals_by_employee[employee_id][ - 'total_due' - ] = attendance_pool.float_time_convert( + totals_by_employee[employee_id]['total_due'] = attendance_pool.float_time_convert( totals_by_employee[employee_id]['total_due']) for overtime_type in totals_by_employee[employee_id]['total_types']: - totals_by_employee[employee_id]['total_types'][ - overtime_type - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_types'][overtime_type]) + totals_by_employee[employee_id]['total_types'][overtime_type] = attendance_pool.float_time_convert(totals_by_employee[employee_id]['total_types'][overtime_type]) datas = {'ids': employee_ids} datas['model'] = 'hr.employee' @@ -360,3 +311,4 @@ 'datas': datas, } +wizard_calendar_report() diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.py~ /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.py~ --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.py~ 2014-05-30 01:07:03.123146291 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.py~ 1970-01-01 02:00:00.000000000 +0200 @@ -1,362 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2011 Domsense srl (<http://www.domsense.com>) -# Copyright (C) 2011-2013 Agile Business Group sagl -# (<http://www.agilebg.com>) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -############################################################################## - -from openerp.osv import fields, orm -from openerp.tools.translate import _ -from datetime import * -import math -import calendar - -class wizard_calendar_report(orm.TransientModel): - - _columns = { - 'month': fields.selection([ - ('1', 'January'), - ('2', 'February'), - ('3', 'March'), - ('4', 'April'), - ('5', 'May'), - ('6', 'June'), - ('7', 'July'), - ('8', 'August'), - ('9', 'September'), - ('10', 'October'), - ('11', 'November'), - ('12', 'December'), - ], 'Month'), - 'year': fields.integer('Year'), - 'from_date': fields.date('From date', required=True), - 'to_date': fields.date('To date', required=True), - 'employee_ids': fields.many2many('hr.employee', 'calendar_report_employee_rel', 'employee_id', 'report_id', - required=True), - } - - _defaults = { - 'month': lambda * a: str(datetime.now().month), - 'year': lambda * a: datetime.now().year, - 'from_date': lambda * a: (datetime.now()-timedelta(30)).strftime('%Y-%m-%d'), - 'to_date': lambda * a: datetime.now().strftime('%Y-%m-%d'), - 'employee_ids': lambda s, cr, uid, c: s.pool.get('hr.employee').search(cr, uid, [], context=None), - } - - _name = "attendance_analysis.wizard.calendar_report" - - def on_change_month(self, cr, uid, id, str_month, year): - res = {} - if year and str_month: - month = int(str_month) - day = calendar.monthrange(year, month)[1] - to_date = date(year, month, day).strftime('%Y-%m-%d') - res= {'value':{'to_date': to_date, 'from_date': date(year, month, 1).strftime('%Y-%m-%d')}} - return res - - - def print_calendar(self, cr, uid, ids, context=None): - if context is None: - context = {} - attendance_pool = self.pool.get('hr.attendance') - holidays_pool = self.pool.get('hr.holidays') - - days_by_employee = {} - - form = self.read(cr, uid, ids, context=context)[0] - from_date = datetime.strptime(form['from_date'], '%Y-%m-%d') - to_date = datetime.strptime(form['to_date'], '%Y-%m-%d') - if from_date > to_date: - raise orm.except_orm(_('Error'), _('From date must be < to date')) - employee_ids=form['employee_ids'] - delta = to_date - from_date - max_number_of_attendances_per_day = 0 - - for employee_id in employee_ids: - employee_id = str(employee_id) - days_by_employee[employee_id] = {} - day_count=0 - while day_count <= delta.days: - current_date = from_date + timedelta(day_count) - current_total_attendances = 0.0 - current_total_overtime = 0.0 - current_total_leaves = 0.0 - current_total_due = 24.0 # If calendar is not specified: working days = 24/7 - current_total_inside_calendar = 0.0 - str_current_date = current_date.strftime('%Y-%m-%d') - days_by_employee[employee_id][str_current_date] = { - 'signin_1': '', - 'signout_1': '', - 'signin_2': '', - 'signout_2': '', - 'signin_3': '', - 'signout_3': '', - 'signin_4': '', - 'signout_4': '', - } - current_date_beginning = datetime.combine(current_date, time()) - str_current_date_beginning = current_date_beginning.strftime( - '%Y-%m-%d %H:%M:%S') - current_date_end = datetime.combine(current_date, time())+ timedelta(1) - str_current_date_end = current_date_end.strftime('%Y-%m-%d %H:%M:%S') - - attendance_ids = attendance_pool.search(cr, uid, [ - ('employee_id','=',int(employee_id)), - ('name','>=',str_current_date_beginning), - ('name','<=',str_current_date_end), - ('action','=','sign_in'), - ], context=context) - # computing attendance totals - for attendance in attendance_pool.browse(cr, uid, attendance_ids, context=context): - current_total_attendances = attendance_pool.time_sum( - current_total_attendances,attendance.duration) - current_total_overtime = attendance_pool.time_sum(current_total_overtime, - attendance.outside_calendar_duration) - current_total_inside_calendar = attendance_pool.time_sum( - current_total_inside_calendar, - attendance.inside_calendar_duration) - - #printing up to 4 attendances - if len(attendance_ids) < 5: - count = 1 - for attendance in sorted(attendance_pool.browse(cr, uid, attendance_ids, context=context), - key=lambda x: x['name']): - days_by_employee[employee_id][str_current_date][ - 'signin_'+str(count)] = attendance.name[11:16] - days_by_employee[employee_id][str_current_date][ - 'signout_'+str(count)] = attendance.end_datetime[11:16] - count += 1 - if len(attendance_ids) > max_number_of_attendances_per_day: - max_number_of_attendances_per_day = len(attendance_ids) - - days_by_employee[employee_id][str_current_date][ - 'attendances' - ] = current_total_attendances - days_by_employee[employee_id][str_current_date][ - 'overtime' - ] = current_total_overtime - - reference_calendar = attendance_pool.get_reference_calendar( - cr, uid, int(employee_id), date=str_current_date, context=context) - # computing due total - if reference_calendar: - if reference_calendar.attendance_ids: - current_total_due = 0.0 - for calendar_attendance in reference.attendance_ids: - if (( - not calendar_attendance.dayofweek - or int(calendar_attendance.dayofweek) == current_date.weekday() - ) - and ( - not calendar_attendance.date_from or - datetime.strptime(calendar_attendance.date_from,'%Y-%m-%d') - <= current_date - )): - calendar_attendance_duration = attendance_pool.time_difference( - calendar_attendance.hour_from, calendar_attendance.hour_to) - if calendar_attendance_duration < 0: - raise orm.except_orm(_('Error'), - _("%s: 'Work to' is < 'Work from'") - % calendar_attendance.name) - current_total_due = attendance_pool.time_sum(current_total_due, - calendar_attendance_duration) - - days_by_employee[employee_id][str_current_date]['due'] = current_total_due - - # computing leaves - holidays_ids = holidays_pool.search(cr, uid, [ - '&', - '&', - '|', - # leave begins today - '&', - ('date_from', '>=', str_current_date_beginning), - ('date_from', '<=', str_current_date_end), - '|', - # leave ends today - '&', - ('date_to', '<=', str_current_date_end), - ('date_to', '>=', str_current_date_beginning), - # leave is ongoing - '&', - ('date_from', '<', str_current_date_beginning), - ('date_to', '>', str_current_date_end), - ('state', '=', 'validate'), - ('employee_id', '=', int(employee_id)), - ], context=context) - for holiday in holidays_pool.browse(cr, uid, holidays_ids, context=context): - date_from = datetime.strptime(holiday.date_from, '%Y-%m-%d %H:%M:%S') - date_to = datetime.strptime(holiday.date_to, '%Y-%m-%d %H:%M:%S') - # if beginned before today - if date_from < current_date_beginning: - date_from = current_date_beginning - # if ends after today - if date_to > current_date_end: - date_to = current_date_end - current_total_leaves = attendance_pool.time_sum( - current_total_leaves, - (date_to - date_from).total_seconds() / 60.0 / 60.0) - - days_by_employee[employee_id][str_current_date]['leaves'] = current_total_leaves - if current_total_leaves > days_by_employee[employee_id][ - str_current_date]['due']: - days_by_employee[employee_id][str_current_date][ - 'leaves' - ] = days_by_employee[employee_id][str_current_date]['due'] - due_minus_leaves = attendance_pool.time_difference( - current_total_leaves, current_total_due) - if due_minus_leaves < current_total_inside_calendar: - days_by_employee[employee_id][str_current_date]['negative'] = 0.0 - else: - days_by_employee[employee_id][str_current_date][ - 'negative' - ] = attendance_pool.time_difference( - current_total_inside_calendar, due_minus_leaves) - - if reference_calendar: - if reference_calendar.leave_rounding: - float_rounding = float(reference_calendar.leave_rounding) - days_by_employee[employee_id][str_current_date][ - 'negative' - ] = math.floor( - days_by_employee[employee_id][str_current_date]['negative'] * - float_rounding - ) / float_rounding - - day_count += 1 - - totals_by_employee = {} - for employee_id in days_by_employee: - totals_by_employee[employee_id] = { - 'total_attendances': 0.0, - 'total_overtime': 0.0, - 'total_negative': 0.0, - 'total_leaves': 0.0, - 'total_due': 0.0, - 'total_types': {}, - } - - for str_date in days_by_employee[employee_id]: - totals_by_employee[employee_id]['total_attendances'] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_attendances'], - days_by_employee[employee_id][str_date]['attendances']) - totals_by_employee[employee_id]['total_overtime'] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_overtime'], - days_by_employee[employee_id][str_date]['overtime']) - totals_by_employee[employee_id]['total_negative'] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_negative'], - days_by_employee[employee_id][str_date]['negative']) - totals_by_employee[employee_id]['total_leaves'] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_leaves'], - days_by_employee[employee_id][str_date]['leaves']) - totals_by_employee[employee_id]['total_due'] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_due'], - days_by_employee[employee_id][str_date]['due']) - - # computing overtime types - reference_calendar = attendance_pool.get_reference_calendar( - cr, uid, int(employee_id), date=str_date, context=context) - if reference_calendar: - if reference_calendar.overtime_type_ids: - sorted_types = sorted( - reference_calendar.overtime_type_ids, - key=lambda k: k.sequence) - current_overtime = days_by_employee[employee_id][ - str_date]['overtime'] - for overtime_type in sorted_types: - if not totals_by_employee[employee_id]['total_types'].get( - overtime_type.name, False): - totals_by_employee[employee_id]['total_types'][ - overtime_type.name] = 0.0 - if current_overtime: - if current_overtime <= overtime_type.limit or not overtime_type.limit: - totals_by_employee[employee_id]['total_types'][ - overtime_type.name] = attendance_pool.time_sum( - totals_by_employee[employee_id] - ['total_types'][overtime_type.name], - current_overtime) - current_overtime = 0.0 - else: - totals_by_employee[employee_id]['total_types'][ - overtime_type.name] = attendance_pool.time_sum( - totals_by_employee[employee_id]['total_types'] - [overtime_type.name], overtime_type.limit) - current_overtime = attendance_pool.time_difference(overtime_type.limit, - current_overtime) - - days_by_employee[employee_id][str_date][ - 'attendances' - ] = attendance_pool.float_time_convert( - days_by_employee[employee_id][str_date]['attendances']) - days_by_employee[employee_id][str_date][ - 'overtime' - ] = attendance_pool.float_time_convert( - days_by_employee[employee_id][str_date]['overtime']) - days_by_employee[employee_id][str_date][ - 'negative' - ] = attendance_pool.float_time_convert( - days_by_employee[employee_id][str_date]['negative']) - days_by_employee[employee_id][str_date][ - 'leaves' - ] = attendance_pool.float_time_convert( - days_by_employee[employee_id][str_date]['leaves']) - days_by_employee[employee_id][str_date][ - 'due' - ] = attendance_pool.float_time_convert( - days_by_employee[employee_id][str_date]['due']) - - totals_by_employee[employee_id][ - 'total_attendances' - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_attendances']) - totals_by_employee[employee_id][ - 'total_overtime' - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_overtime']) - totals_by_employee[employee_id][ - 'total_negative' - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_negative']) - totals_by_employee[employee_id][ - 'total_leaves' - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_leaves']) - totals_by_employee[employee_id][ - 'total_due' - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_due']) - - for overtime_type in totals_by_employee[employee_id]['total_types']: - totals_by_employee[employee_id]['total_types'][ - overtime_type - ] = attendance_pool.float_time_convert( - totals_by_employee[employee_id]['total_types'][overtime_type]) - - datas = {'ids': employee_ids} - datas['model'] = 'hr.employee' - datas['form'] = {} - datas['form']['days_by_employee'] = days_by_employee - datas['form']['totals_by_employee'] = totals_by_employee - datas['form']['max_number_of_attendances_per_day'] = max_number_of_attendances_per_day - - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'attendance_analysis.calendar_report', - 'datas': datas, - } - Binary files /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.pyc and /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.pyc differ diff -urN /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.xml /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.xml --- /opt/openerp/openerp-7.0-20131119-002500/openerp/addons/hr_attendance_analysis/wizard/print_calendar_report.xml 2014-05-30 01:07:03.119144292 +0200 +++ /media/GRMCPRXFRER/hr_attendance_analysis/wizard/print_calendar_report.xml 2014-05-28 04:24:28.000000000 +0200 @@ -5,6 +5,7 @@ <record id="wizard_calendar_report" model="ir.ui.view"> <field name="name">Attendances Analysis Calendar</field> <field name="model">attendance_analysis.wizard.calendar_report</field> + <field name="type">form</field> <field name="arch" type="xml"> <form string="Attendances Analysis Calendar"> <group colspan="4" height="400"> ----------------------------------------------------------------------------------------------- Regards,
From: [hidden email] To: [hidden email] Subject: RE: wrong file Date: Sun, 1 Jun 2014 02:33:47 +0200 fe geded?! From: [hidden email] To: [hidden email] Subject: RE: wrong file Date: Sat, 31 May 2014 01:14:50 +0000 hi you sent me the wrong file hr_attendance.py is not valid. would you send it again ----------------------------------------------------------------------------------------------- Regards,
تلقيت هذه الرسالة لأنك مشترك في مجموعة "مجتمع أوبن إي آر بي العربي: النقاشات العامة" في مجموعات Google. لإلغاء الاشتراك في هذه المجموعة وإيقاف تلقي رسائل الإلكترونية منها، أرسل رسالة إلكترونية إلى [hidden email]. للمزيد من الخيارات، انتقل إلى https://groups.google.com/d/optout. OOs.diff (141K) Download Attachment |
Free forum by Nabble | Edit this page |