Permalink
Browse files

Merge branch '10.0' into 10.0-project_timelog-port

  • Loading branch information...
GabbasovDinar committed Jul 11, 2018
2 parents d7ecb91 + 674fe75 commit a7ab8080e01917f46f242a2f85432e095d7094d4
Showing with 2,884 additions and 22 deletions.
  1. +45 −0 base_attendance/README.rst
  2. +4 −0 base_attendance/__init__.py
  3. +41 −0 base_attendance/__manifest__.py
  4. +4 −0 base_attendance/doc/changelog.rst
  5. +63 −0 base_attendance/doc/index.rst
  6. +6 −0 base_attendance/models/__init__.py
  7. +112 −0 base_attendance/models/res_attendance.py
  8. +16 −0 base_attendance/models/res_config.py
  9. +135 −0 base_attendance/models/res_partner.py
  10. +49 −0 base_attendance/report/res_partner_badge.xml
  11. +5 −0 base_attendance/security/ir.model.access.csv
  12. +58 −0 base_attendance/security/res_attendance_security.xml
  13. BIN base_attendance/static/description/icon.png
  14. +90 −0 base_attendance/static/description/index.html
  15. BIN base_attendance/static/description/kiosk-mode.png
  16. BIN base_attendance/static/description/menu.png
  17. +165 −0 base_attendance/static/src/js/greeting_message.js
  18. +122 −0 base_attendance/static/src/js/kiosk_confirm.js
  19. +80 −0 base_attendance/static/src/js/kiosk_mode.js
  20. +56 −0 base_attendance/static/src/js/presence_widgets.js
  21. +28 −0 base_attendance/static/src/js/res_partner_kanban_view_handler.js
  22. +41 −0 base_attendance/static/src/js/test_kiosk_tour.js
  23. +216 −0 base_attendance/static/src/less/hr_attendance.less
  24. +109 −0 base_attendance/static/src/xml/attendance.xml
  25. +6 −0 base_attendance/tests/__init__.py
  26. +67 −0 base_attendance/tests/test_hr_attendance_constraints.py
  27. +22 −0 base_attendance/tests/test_hr_attendance_process.py
  28. +18 −0 base_attendance/tests/test_kiosk_tour.py
  29. +236 −0 base_attendance/views/res_attendance_view.xml
  30. +33 −0 base_attendance/views/res_config_view.xml
  31. +17 −0 base_attendance/views/web_asset_backend_template.xml
  32. +1 −1 ir_attachment_s3/__manifest__.py
  33. +5 −0 ir_attachment_s3/doc/changelog.rst
  34. +11 −7 ir_attachment_s3/models/ir_attachment.py
  35. +1 −1 ir_attachment_url/__manifest__.py
  36. +5 −0 ir_attachment_url/doc/changelog.rst
  37. +1 −1 ir_attachment_url/models/ir_attachment.py
  38. +3 −3 ir_config_parameter_multi_company/README.rst
  39. +4 −3 ir_config_parameter_multi_company/__manifest__.py
  40. +6 −0 ir_config_parameter_multi_company/doc/changelog.rst
  41. +22 −1 ir_config_parameter_multi_company/doc/index.rst
  42. +1 −1 ir_config_parameter_multi_company/models/ir_config_parameter.py
  43. +4 −4 ir_config_parameter_multi_company/static/description/index.html
  44. +1 −0 ir_config_parameter_multi_company/tests/test_base.py
  45. +57 −0 web_website/README.rst
  46. +2 −0 web_website/__init__.py
  47. +49 −0 web_website/__manifest__.py
  48. +12 −0 web_website/demo/assets_demo.xml
  49. +11 −0 web_website/demo/res_users_demo.xml
  50. +4 −0 web_website/doc/changelog.rst
  51. +54 −0 web_website/doc/index.rst
  52. +7 −0 web_website/models/__init__.py
  53. +26 −0 web_website/models/ir_http.py
  54. +110 −0 web_website/models/ir_property.py
  55. +14 −0 web_website/models/res_config.py
  56. +60 −0 web_website/models/res_users.py
  57. +16 −0 web_website/models/test_website_dependent.py
  58. +3 −0 web_website/security/ir.model.access.csv
  59. +9 −0 web_website/security/security.xml
  60. BIN web_website/static/description/icon.png
  61. +59 −0 web_website/static/description/index.html
  62. +63 −0 web_website/static/src/js/switch_website_menu.js
  63. +33 −0 web_website/static/src/js/tour.js
  64. +15 −0 web_website/static/src/xml/qweb.xml
  65. +3 −0 web_website/tests/__init__.py
  66. +36 −0 web_website/tests/test_ui.py
  67. +234 −0 web_website/tests/test_website_dependent.py
  68. +12 −0 web_website/views/assets.xml
  69. +39 −0 web_website/views/ir_property_views.xml
  70. +23 −0 web_website/views/res_config_views.xml
  71. +24 −0 web_website/views/res_users_views.xml
View
@@ -0,0 +1,45 @@
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: https://www.gnu.org/licenses/lgpl
:alt: License: LGPL-3
=====================
Partner Attendances
=====================
Process partners attendance.
The module is copy-pasted from hr_attendance and modified to work with res.partners records.
Credits
=======
Contributors
------------
* `Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>`__
Sponsors
--------
* `IT-Projects LLC <https://it-projects.info>`__
Maintainers
-----------
* `IT-Projects LLC <https://it-projects.info>`__
To get a guaranteed support you are kindly requested to purchase the module at `odoo apps store <https://apps.odoo.com/apps/modules/10.0/base_attendance/>`__.
Thank you for understanding!
`IT-Projects Team <https://www.it-projects.info/team>`__
Further information
===================
Demo: http://runbot.it-projects.info/demo/misc-addons/10.0
HTML Description: https://apps.odoo.com/apps/modules/10.0/base_attendance/
Usage instructions: `<doc/index.rst>`_
Changelog: `<doc/changelog.rst>`_
Tested on Odoo 10.0 7a63d471edec45a106fef5f783aeb7eaf43447f6
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import models
@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
"name": """Partner Attendances""",
"summary": """Manage partner attendances""",
"category": "Extra Tools",
# "live_test_url": "",
"images": [],
"version": "10.0.1.0.0",
"application": False,
"author": "IT-Projects LLC, Kolushov Alexandr",
"support": "apps@it-projects.info",
"website": "https://it-projects.info/team/KolushovAlexandr",
"license": "LGPL-3",
"price": 60.00,
"currency": "EUR",
"depends": [
'report',
'barcodes'
],
"external_dependencies": {"python": [], "bin": []},
'data': [
'security/res_attendance_security.xml',
'security/ir.model.access.csv',
'views/web_asset_backend_template.xml',
'views/res_attendance_view.xml',
'report/res_partner_badge.xml',
'views/res_config_view.xml',
],
'demo': [
],
'qweb': [
"static/src/xml/attendance.xml",
],
'installable': True,
'auto_install': False,
}
@@ -0,0 +1,4 @@
`1.0.0`
-------
- Init version
@@ -0,0 +1,63 @@
=====================
Partner Attendances
=====================
Configuration
=============
Access rights
-------------
In order to set access rights for users
* Open menu ``[[ Settings ]] >> Users``
* Click on required user
* Click ``Edit`` and set field **Attendance**:
* ``Read-Only`` may see only *Attendances* menu
* ``Manual Attendance`` may create and update partner attendances, but not delete
* ``Officer`` may also delete partners attendances, has access to *Partners*, *Reports* menus and *Kiosk Mode*
* ``Manager`` like Officer, but also has access to *Configuration* menu
Barcode
-------
* If you want to use barcodes install module ``Point of sale``, or add barcode field to the partner form manually
Usage
=====
Attendances
-----------
To create *Attendances*
* Open menu ``[[ Partner Attendances ]] >> Attendances``
* Click ``Create``
* Choose a partner in **Partner**
* Specify the **Check In** field
* Field **Check Out** is not required, it may be specified later
* Click ``Save``
Kiosk Mode
----------
*Attendances* records creating is also possible via *Kiosk Mode*
* Open menu ``[[ Partner Attendances ]] >> Kiosk Mode``
* Click ``Select Partner``
* Click on a partner
* Click the blue icon to check in/ check out a partner
* Click ``ok``
Also it is possible to use barcodes to check partners attendance
* Open menu ``[[ Partner Attendances ]] >> Kiosk Mode``
* Scan a partner's barcode to check him in or out, it depends on the actual partner's presence
Installation
============
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ this module in a usual way
@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import res_attendance
from . import res_partner
from . import res_config
@@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from datetime import datetime
from odoo import models, fields, api, exceptions, _
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class HrAttendance(models.Model):
_name = "res.partner.attendance"
_description = "Attendance"
_order = "check_in desc"
def _default_partner(self):
return self.env['res.partner'].search([('user_id', '=', self.env.uid)], limit=1)
partner_id = fields.Many2one('res.partner', string="Partner", default=_default_partner, required=True, ondelete='cascade', index=True)
check_in = fields.Datetime(string="Check In", default=fields.Datetime.now, required=True)
check_out = fields.Datetime(string="Check Out")
worked_hours = fields.Float(string='Worked Hours', compute='_compute_worked_hours', store=True, readonly=True)
@api.multi
def name_get(self):
result = []
for attendance in self:
if not attendance.check_out:
result.append((attendance.id, _("%(partner_name)s from %(check_in)s") % {
'partner_name': attendance.partner_id.name,
'check_in': fields.Datetime.to_string(fields.Datetime.context_timestamp(attendance, fields.Datetime.from_string(attendance.check_in))),
}))
else:
int_worked_hours = int(attendance.worked_hours)
worked_time = "%02dh:%02dm" % (int_worked_hours, (attendance.worked_hours - int_worked_hours) * 60)
result.append((attendance.id, _("%(worked_time)s by %(partner_name)s from %(check_in)s to %(check_out)s") % {
'worked_time': worked_time,
'partner_name': attendance.partner_id.name,
'check_in': fields.Datetime.to_string(fields.Datetime.context_timestamp(attendance, fields.Datetime.from_string(attendance.check_in))),
'check_out': fields.Datetime.to_string(fields.Datetime.context_timestamp(attendance, fields.Datetime.from_string(attendance.check_out))),
}))
return result
@api.depends('check_in', 'check_out')
def _compute_worked_hours(self):
for attendance in self:
if attendance.check_out:
delta = datetime.strptime(attendance.check_out, DEFAULT_SERVER_DATETIME_FORMAT) - datetime.strptime(
attendance.check_in, DEFAULT_SERVER_DATETIME_FORMAT)
attendance.worked_hours = delta.total_seconds() / 3600.0
@api.constrains('check_in', 'check_out')
def _check_validity_check_in_check_out(self):
""" verifies if check_in is earlier than check_out. """
for attendance in self:
if attendance.check_in and attendance.check_out:
if attendance.check_out < attendance.check_in:
raise exceptions.ValidationError(_('"Check Out" time cannot be earlier than "Check In" time.'))
@api.constrains('check_in', 'check_out', 'partner_id')
def _check_validity(self):
""" Verifies the validity of the attendance record compared to the others from the same partner.
For the same partner we must have :
* maximum 1 "open" attendance record (without check_out)
* no overlapping time slices with previous partner records
"""
for attendance in self:
# we take the latest attendance before our check_in time and check it doesn't overlap with ours
last_attendance_before_check_in = self.env['res.partner.attendance'].search([
('partner_id', '=', attendance.partner_id.id),
('check_in', '<=', attendance.check_in),
('id', '!=', attendance.id),
], order='check_in desc', limit=1)
if last_attendance_before_check_in and last_attendance_before_check_in.check_out and last_attendance_before_check_in.check_out > attendance.check_in:
raise exceptions.ValidationError(_("Cannot create new attendance record for %(partner_name)s, the partner was already checked in on %(datetime)s") % {
'partner_name': attendance.partner_id.name,
'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(attendance.check_in))),
})
if not attendance.check_out:
# if our attendance is "open" (no check_out), we verify there is no other "open" attendance
no_check_out_attendances = self.env['res.partner.attendance'].search([
('partner_id', '=', attendance.partner_id.id),
('check_out', '=', False),
('id', '!=', attendance.id),
])
if no_check_out_attendances:
raise exceptions.ValidationError(_("Cannot create new attendance record for %(partner_name)s, the partner hasn't checked out since %(datetime)s") % {
'partner_name': attendance.partner_id.name,
'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(no_check_out_attendances.check_in))),
})
else:
# we verify that the latest attendance with check_in time before our check_out time
# is the same as the one before our check_in time computed before, otherwise it overlaps
last_attendance_before_check_out = self.env['res.partner.attendance'].search([
('partner_id', '=', attendance.partner_id.id),
('check_in', '<', attendance.check_out),
('id', '!=', attendance.id),
], order='check_in desc', limit=1)
if last_attendance_before_check_out and last_attendance_before_check_in != last_attendance_before_check_out:
raise exceptions.ValidationError(_("Cannot create new attendance record for %(partner_name)s, the partner was already checked in on %(datetime)s") % {
'partner_name': attendance.partner.name,
'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(last_attendance_before_check_out.check_in))),
})
@api.multi
def copy(self):
# super here is called by the reason of LINT error:
# [W8106(method-required-super), HrAttendance.copy] Missing `super` call in "copy" method.
super(HrAttendance, self).copy()
raise exceptions.UserError(_('You cannot duplicate an attendance.'))
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2004-2015 Odoo S.A.
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import fields, models
class BaseConfigSettings(models.TransientModel):
_inherit = 'base.config.settings'
group_attendance_use_pin = fields.Selection([(0, 'Partners do not need to enter their PIN to check in manually in the "Kiosk Mode".'),
(1, 'Partners must enter their PIN to check in manually in the "Kiosk Mode".')],
string='Partner PIN',
help='Enable or disable partner PIN identification at check in',
implied_group="base_attendance.group_hr_attendance_use_pin")
Oops, something went wrong.

0 comments on commit a7ab808

Please sign in to comment.