In some countries it is required to have a register of the hours that an employee worked. For example a law was approved in Spain that forces all companies to have the attendance registry of his employees. This can not be achieved with the current timesheet module because timesheet is only about tracking the time spent in some works but the attendance means having the time when the employee started to work and the hours when the employee finished to work.
Proposal
Add a new module named company_attendance which will add the following model:
Attendance
Employee
Datetime
Type: In/Out
When creating a record the In/Out value will be set based on the last value of the employee, allowing the user to see it’s current status but it will allowed to change it an no consistency check will be implemented.
Each user will be only allowed to access it’s own attendances. If the user is part of a especial group it will be allowed to see the attendances of all employees.
This information should be used to report for each employee the hours worked. The Attendance Report model will contain the following fields:
Employee:
Date:
Start Time: The minimun time of this day
End Time: The maximum time of this day
Worked Duration: The duration that this employee worked on this day
All this information will be computed using a table_query.
If the timesheet module is activated, the report will contain an additional Timesheet Duration field to sum up the timesheet duration of the current day for the employee.
A process should be added to close the attendance until a date. This process will ensure that all the attendance lines have the valid alternance. Once this process is executed the attendance records until this date will be readonly.
With such design it is complex and expensive to ensure no overlapping (see check_dates on FiscalYear).
This sounds to be too simple. There are holidays, employee leaves, sick days etc.
Also in some case extra hours are counting from a datetime (e.g. after ) Some times there different factors depending on the time (e.g. after x1.5, after x2).
Some workers have shift in their planning like working 1 week, rest 1 week. Or they have shift of 8 hours.
I’am going to start an upgrade of our workload planning module set. Attendance is one part of this. So we can use a upstream module for attendance.
Our module set will also add:
attendance planning based on worktime models (early stage, late layer a.s.o)
recording of absenteeism (illness f.e.)
workload planning (showing available work hours of employees compared to planned workload)
reports based on cost centers
a mobile client
to track attendance
show planned work of the day to each employee
record time spent on specific works (timesheet)
This module set is already running for worktime planning in a service station and a production company. So we have a real life use case and already a request to pimp up the functions and logic …
We have (and working on) this already - but I think there should be a simple attendance tracker as base. You talk more about planning and evaluation than tracking.
I agree that first we should have a simple attendance and we can add more features latter. So I removed the extra hours part so we can discuss it latter.
I do not think we have any other option to check overlapping. Do you have any simpler design in mind?
I can tell you from experience: There will be the need of manually fixing some lines because real people is involved. We have a warning if employee starts a new line and an old one isn’t closed. As you know - at end of working day everybody have a hurry
And overlapping should be prevented client side because with a open line you can’t start a new one.
That’s why I want to have a wizard to be used for the employeee. So the employee executes the wizard and they can see the current state, so they can enter the end date from previous day if requested. This wizard can be customized to introduce as much warngins and information as you want. See:
I’ll throw a wrench at the problem:
I think there should be a “type” field for each attendance record/line.
Because there are different type of “attendance” and they are payed differently: like offsite work vs normal hours.
At work here the “punch clock” can take a “reason number” from the employee for this purpose.
Don’t know if this is useful in the base module, or a separate one.
ok - I see - read it and forget it while writing
One thing I saw looking at my module:
I have a related model timetracking.break - so I track come and go one time a “working day” and
and related breaks with a start and end. It eases the creation of reports and evaluation. With lot of partitions it is mostly impossible to base other statistic stuff on the tracked lines.
Possibly. Depends a lot on the company. In my case this information is tracked on timesheet.lines because attandance is tracking start, end and breaks in general. We track additional ‘kinds’ starting tasks via timesheet.lines. So you can relate the overall time spent to productivity recorded on works. The Boss loves this feature
Yes, it could be a table with: Employee, DateTime, action (in/out).
Of course there will be no consistency check that in is followed by out but inconsistency could be ignored.
This can work only by locking the table against concurrent creation. I do not think it is good for performance.
Should not this be cross-referenced with the timesheet? Or with a configuration which define depending on the date/time what kind it is.
I think this will integrate well with electronic/analog “punch clock”.
They record the direction (if it’s clock in/out) and the date/time.
Many modern punch clock machine can acquire a number that the worker can input to state the reason of entry/exit. This is very convenient for the worker (no computer needed for data entry).
I have an idea, what about create another module: Access audit.
This will create a log from different machine (manual, access gate, punch clock …). This will be defined as:
Party: The party that use the gate
gate: many2one to a list of machine names (this will use by other module for filter events)
timestamp: the datetime of the event
direction: (in/out)
Then the Attendance module can filter the Access audit record by gate, and generate a line with the reason of entering/exit.
Having an audit of all the access can pave the way to other module (access control for example) without duplicating the same model.
For Spain is a requirement to be able to compute the start time, end time, and the total duration of the day, which is more complex with your module. But I think we can use a Window function to compute the duration between two rows.
Ok so with your model instead of using the wizard we can propose the in/out based on the previous value and then let the user confirm it.
I’ve had a look at the module and I’ve seen a lot of Functionality that I do not see that is specified on this blueprint. Is there any functionality that we are missing on this blueprint?
Do not understand what this is needed. From what I understand all the information registered by the devices can be stored on the attendance model.
What are this codes used for?
This is something that we should probably think about. IUC what you define is a closing date to avoid updating the attendance values prior to this day. Am I right? Could you elaborate a little bit more what are the requirements and what you implemented?
Devices normally stores a code for employee (for party in fact). If you have fully integrated Tryton with devices the attendance model is ok due to Tryton creates the employees on devices and you can use the party code/party id/employee id or wathever you want. But if not you will receive an employee code and you need to identify the employee on Tryton.
To identify the in/out action. Additionally you can specify a special code for special actions (normally at output) like described @wifasoi. We preferred to define different codes like devices do.
This is exactly the requirement: avoid updating the attendance values prior to the closed period date.
After a government audit the attendances should be blocked.
Indeed after checking the code I see part of this functionality is missing. . I’ve fixed it.