Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,46 @@
# Maintenance Timesheets
Odoo addon: maintenance_timesheet
## Installation
```bash
pip install odoo-bringout-oca-maintenance-maintenance_timesheet
```
## Dependencies
This addon depends on:
- base_maintenance
- maintenance_project
- hr_timesheet
## Manifest Information
- **Name**: Maintenance Timesheets
- **Version**: 16.0.2.1.0
- **Category**: Human Resources
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/maintenance](https://github.com/OCA/maintenance) branch 16.0, addon `maintenance_timesheet`.
## License
This package maintains the original AGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Maintenance_timesheet Module - maintenance_timesheet
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for maintenance_timesheet. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,3 @@
# Controllers
This module does not define custom HTTP controllers.

View file

@ -0,0 +1,7 @@
# Dependencies
This addon depends on:
- [base_maintenance](../../odoo-bringout-oca-maintenance-base_maintenance)
- [maintenance_project](../../odoo-bringout-oca-maintenance-maintenance_project)
- [hr_timesheet](../../odoo-bringout-oca-ocb-hr_timesheet)

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon maintenance_timesheet or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-maintenance-maintenance_timesheet"
# or
uv pip install odoo-bringout-oca-maintenance-maintenance_timesheet"
```

View file

@ -0,0 +1,14 @@
# Models
Detected core models and extensions in maintenance_timesheet.
```mermaid
classDiagram
class account_analytic_line
class maintenance_equipment
class maintenance_request
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: maintenance_timesheet. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon maintenance_timesheet
- License: LGPL-3

View file

@ -0,0 +1,22 @@
# Reports
Report definitions and templates in maintenance_timesheet.
```mermaid
classDiagram
```
## Available Reports
No named reports found in XML files.
## Report Files
- **maintenance_request_report.xml** (XML template/definition)
## Notes
- Named reports above are accessible through Odoo's reporting menu
- Python files define report logic and data processing
- XML files contain report templates, definitions, and formatting
- Reports are integrated with Odoo's printing and email systems

View file

@ -0,0 +1,65 @@
# Security
Access control and security definitions in maintenance_timesheet.
## Access Control Lists (ACLs)
Model access permissions defined in:
- **[bosnian_translations.json](../bosnian_translations.json)**
- 1767 model access rules
- **[bosnian_translations_output.json](../bosnian_translations_output.json)**
- 414 model access rules
- **[CHANGELOG.md](../CHANGELOG.md)**
- 132 model access rules
- **[doc](../doc)**
- **[docker](../docker)**
- **[input](../input)**
- **[nix](../nix)**
- **[odoo.conf](../odoo.conf)**
- 58 model access rules
- **[odoo_packages_bez_l10n.txt](../odoo_packages_bez_l10n.txt)**
- 1947 model access rules
- **[odoo_packages_bringout.txt](../odoo_packages_bringout.txt)**
- 1947 model access rules
- **[odoo_packages.txt](../odoo_packages.txt)**
- 2085 model access rules
- **[output](../output)**
- **[packages](../packages)**
- **[PACKAGES.md](../PACKAGES.md)**
- 298 model access rules
- **[README.md](../README.md)**
- 338 model access rules
- **[scripts](../scripts)**
- **[temp](../temp)**
- **[TRANSLATION_BS_SUMMARY.md](../TRANSLATION_BS_SUMMARY.md)**
- 225 model access rules
## Record Rules
Row-level security rules defined in:
## Security Groups & Configuration
Security groups and permissions defined in:
- **[maintenance_timesheet_security.xml](../maintenance_timesheet/security/maintenance_timesheet_security.xml)**
```mermaid
graph TB
subgraph "Security Layers"
A[Users] --> B[Groups]
B --> C[Access Control Lists]
C --> D[Models]
B --> E[Record Rules]
E --> F[Individual Records]
end
```
Security files overview:
- **[maintenance_timesheet_security.xml](../maintenance_timesheet/security/maintenance_timesheet_security.xml)**
- Security groups, categories, and XML-based rules
Notes
- Access Control Lists define which groups can access which models
- Record Rules provide row-level security (filter records by user/group)
- Security groups organize users and define permission sets
- All security is enforced at the ORM level by Odoo

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon maintenance_timesheet
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,82 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
======================
Maintenance Timesheets
======================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:6e3c051cdab2b2b121c7ede1bc83c4f83179f60e4506daf330a965ef56b938bc
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmaintenance-lightgray.png?logo=github
:target: https://github.com/OCA/maintenance/tree/16.0/maintenance_timesheet
:alt: OCA/maintenance
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/maintenance-16-0/maintenance-16-0-maintenance_timesheet
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/maintenance&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module adds timesheets to a request.
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/maintenance/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/maintenance/issues/new?body=module:%20maintenance_timesheet%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Solvos
Contributors
~~~~~~~~~~~~
* David Alonso <david.alonso@solvos.es>
* Luisa Miguéns <luisa.miguens@solvos.es>
* Christian Ramos <c.ramos@binhex.es>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/maintenance <https://github.com/OCA/maintenance/tree/16.0/maintenance_timesheet>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1 @@
from . import models

View file

@ -0,0 +1,20 @@
# © 2020 Solvos Consultoría Informática (<http://www.solvos.es>)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
{
"name": "Maintenance Timesheets",
"summary": "Adds timesheets to maintenance requests",
"author": "Odoo Community Association (OCA), Solvos",
"license": "AGPL-3",
"version": "16.0.2.1.0",
"category": "Human Resources",
"website": "https://github.com/OCA/maintenance",
"depends": ["base_maintenance", "maintenance_project", "hr_timesheet"],
"data": [
"security/maintenance_timesheet_security.xml",
"views/hr_timesheet_views.xml",
"views/maintenance_request_views.xml",
"report/maintenance_request_report.xml",
],
"demo": ["data/demo_maintenance_timesheet.xml"],
"installable": True,
}

View file

@ -0,0 +1,45 @@
<odoo noupdate="1">
<record id="hr_timesheet.group_hr_timesheet_user" model="res.groups">
<field name="users" eval="[(4, ref('base.user_demo')),]" />
</record>
<record id="request_1" model="maintenance.request">
<field name="name">Corrective #1 for Generic Monitor</field>
<field name="equipment_id" ref="maintenance_project.equipment_1" />
<field
name="schedule_date"
eval="(DateTime.now() + relativedelta(days=-1)).strftime('%Y-%m-%d')"
/>
<field name="user_id" ref="base.user_admin" />
<field name="project_id" ref="maintenance_project.project_project_1" />
<field name="task_id" ref="maintenance_project.project_task_12" />
<field name="maintenance_type">corrective</field>
</record>
<record id="timesheet_11" model="account.analytic.line">
<field
name="date"
eval="(DateTime.now() + relativedelta(days=-1)).strftime('%Y-%m-%d')"
/>
<field name="name">Request tasks done</field>
<field name="maintenance_request_id" ref="maintenance_timesheet.request_1" />
<field name="user_id" ref='base.user_admin' />
<field name="project_id" ref="maintenance_project.project_project_1" />
<field name="task_id" ref="maintenance_project.project_task_12" />
<field name="unit_amount" eval="2.0" />
</record>
<record id="maintenance.m_request_8" model="maintenance.request">
<field name="project_id" ref="maintenance_project.project_project_1" />
<field name="task_id" ref="maintenance_project.project_task_11" />
</record>
<record id="timesheet_21" model="account.analytic.line">
<field
name="date"
eval="(DateTime.now() + relativedelta(days=-1)).strftime('%Y-%m-%d')"
/>
<field name="name">Touchpad repaired</field>
<field name="maintenance_request_id" ref="maintenance.m_request_8" />
<field name="user_id" ref='base.user_demo' />
<field name="project_id" ref="maintenance_project.project_project_1" />
<field name="task_id" ref="maintenance_project.project_task_11" />
<field name="unit_amount" eval="3" />
</record>
</odoo>

View file

@ -0,0 +1,133 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * maintenance_timesheet
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_kanban
msgid "<span class=\"o_label\">Hours</span>"
msgstr "<span class=\"o_label\">Sati</span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_form
msgid ""
"<span class=\"o_stat_text\">\n"
" Hours\n"
" </span>"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<span id=\"timesheet_information_title\">Timesheet Entries</span>"
msgstr "<span id=\"timesheet_information_title\">Unosi radnih sati</span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Timesheet Total Hours:</strong>"
msgstr "<strong>Ukupno sati radnog lista:</strong>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Total</strong>"
msgstr "<strong>Ukupno</strong>"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_account_analytic_line
msgid "Analytic Line"
msgstr "Analitička stavka"
#. module: maintenance_timesheet
#. odoo-python
#: code:addons/maintenance_timesheet/models/hr_timesheet.py:0
#, python-format
msgid ""
"Cannot save or delete a timesheet for a maintenance request already done"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Date"
msgstr "Datum"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Description"
msgstr "Opis"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Duration (Hour(s))"
msgstr "Trajanje (sati)"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_equipment
msgid "Maintenance Equipment"
msgstr "Oprema za održavanje"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_account_analytic_line__maintenance_request_id
msgid "Maintenance Request"
msgstr "Zahtjev za održavanje"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__planned_hours
msgid "Planned Hours"
msgstr "Planirani sati"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__progress
msgid "Progress"
msgstr "Napredak"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Project -"
msgstr "Projekat -"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__remaining_hours
msgid "Remaining Hours"
msgstr "Preostali sati"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_timesheet_line_search
msgid "Request"
msgstr "Zahtjev"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Responsible"
msgstr "Odgovoran"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Task"
msgstr "Zadatak"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Time"
msgstr "Vrijeme"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_total_hours
msgid "Timesheet Total Hours"
msgstr "Ukupno sati radnog lista"
#. module: maintenance_timesheet
#: model:ir.actions.act_window,name:maintenance_timesheet.timesheet_action_from_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_ids
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Timesheets"
msgstr "Šihtarice"

View file

@ -0,0 +1,155 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * maintenance_timesheet
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-10-04 08:28+0000\n"
"PO-Revision-Date: 2023-09-07 16:37+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_kanban
msgid "<span class=\"o_label\">Hours</span>"
msgstr "<span class=\"o_label\">horas</span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_form
msgid ""
"<span class=\"o_stat_text\">\n"
" Hours\n"
" </span>"
msgstr ""
"<span class=\"o_stat_text\">\n"
" Horas\n"
" </span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<span id=\"timesheet_information_title\">Timesheet Entries</span>"
msgstr ""
"<span id=\"timesheet_information_title\">Entradas en la hoja de horas</span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Timesheet Total Hours:</strong>"
msgstr "<strong>Horas totales de la hoja de horas:</strong>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Total</strong>"
msgstr "<strong>Total</strong>"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_account_analytic_line
msgid "Analytic Line"
msgstr "Cuenta analítica"
#. module: maintenance_timesheet
#. odoo-python
#: code:addons/maintenance_timesheet/models/hr_timesheet.py:0
#, python-format
msgid ""
"Cannot save or delete a timesheet for a maintenance request already done"
msgstr ""
"No se puede editar o borrar un parte de trabajo de una petición de "
"mantenimiento ya finalizada"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Date"
msgstr "fecha"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Description"
msgstr "descripción"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Duration (Hour(s))"
msgstr "Duración (Hora(s))"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_equipment
msgid "Maintenance Equipment"
msgstr "Equipo"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_account_analytic_line__maintenance_request_id
msgid "Maintenance Request"
msgstr "Petición de mantenimiento"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__planned_hours
msgid "Planned Hours"
msgstr "Horas planificadas"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__progress
msgid "Progress"
msgstr "progreso"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Project -"
msgstr "proyecto-"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__remaining_hours
msgid "Remaining Hours"
msgstr "Horas restantes"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_timesheet_line_search
msgid "Request"
msgstr "Petición"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Responsible"
msgstr "Responsable"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Task"
msgstr "Tarea"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Time"
msgstr "Tiempo"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_total_hours
msgid "Timesheet Total Hours"
msgstr "Horas totales en partes de trabajo"
#. module: maintenance_timesheet
#: model:ir.actions.act_window,name:maintenance_timesheet.timesheet_action_from_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_ids
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Timesheets"
msgstr "Partes de trabajo"
#~ msgid "<span class=\"o_label\" >Hours</span>"
#~ msgstr "<span class=\"o_label\" >horas</span>"
#~ msgid "Display Name"
#~ msgstr "nombre para mostrar"
#~ msgid "ID"
#~ msgstr "ID(identificador)"
#~ msgid "Last Modified on"
#~ msgstr "modificado por última vez el"

View file

@ -0,0 +1,154 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * maintenance_timesheet
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-03-14 15:36+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_kanban
msgid "<span class=\"o_label\">Hours</span>"
msgstr "<span class=\"o_label\">Ore</span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_form
msgid ""
"<span class=\"o_stat_text\">\n"
" Hours\n"
" </span>"
msgstr ""
"<span class=\"o_stat_text\">\n"
" Ore\n"
" </span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<span id=\"timesheet_information_title\">Timesheet Entries</span>"
msgstr ""
"<span id=\"timesheet_information_title\">Registrazioni foglio presenze</span>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Timesheet Total Hours:</strong>"
msgstr "<strong>Ore totali foglio presenze:</strong>"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Total</strong>"
msgstr "<strong>Totale</strong>"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_account_analytic_line
msgid "Analytic Line"
msgstr "Riga analitica"
#. module: maintenance_timesheet
#. odoo-python
#: code:addons/maintenance_timesheet/models/hr_timesheet.py:0
#, python-format
msgid ""
"Cannot save or delete a timesheet for a maintenance request already done"
msgstr ""
"Non si può salvare o cancellare un foglio presenze per una richiesta di "
"manutenzione già eseguita"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Date"
msgstr "Data"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Description"
msgstr "Descrizione"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Duration (Hour(s))"
msgstr "Durata (ora(e))"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_equipment
msgid "Maintenance Equipment"
msgstr "Attrezzatura manutenzione"
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_account_analytic_line__maintenance_request_id
msgid "Maintenance Request"
msgstr "Richiesta manutenzione"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__planned_hours
msgid "Planned Hours"
msgstr "Ore pianificate"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__progress
msgid "Progress"
msgstr "Avanzamento"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Project -"
msgstr "Progetto -"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__remaining_hours
msgid "Remaining Hours"
msgstr "Ore residue"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_timesheet_line_search
msgid "Request"
msgstr "Richiesta"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Responsible"
msgstr "Responsabile"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Task"
msgstr "Lavoro"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Time"
msgstr "Orario"
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_total_hours
msgid "Timesheet Total Hours"
msgstr "Ore totali foglio presenze"
#. module: maintenance_timesheet
#: model:ir.actions.act_window,name:maintenance_timesheet.timesheet_action_from_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_ids
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Timesheets"
msgstr "Fogli ore"
#~ msgid "<span class=\"o_label\" style=\"padding-left: 5px;\">Hours</span>"
#~ msgstr "<span class=\"o_label\" style=\"padding-left: 5px;\">Ore</span>"
#~ msgid "Display Name"
#~ msgstr "Nome visualizzato"
#~ msgid "ID"
#~ msgstr "ID"
#~ msgid "Last Modified on"
#~ msgstr "Ultima modifica il"

View file

@ -0,0 +1,133 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * maintenance_timesheet
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_kanban
msgid "<span class=\"o_label\">Hours</span>"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_equipment_request_view_form
msgid ""
"<span class=\"o_stat_text\">\n"
" Hours\n"
" </span>"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<span id=\"timesheet_information_title\">Timesheet Entries</span>"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Timesheet Total Hours:</strong>"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "<strong>Total</strong>"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_account_analytic_line
msgid "Analytic Line"
msgstr ""
#. module: maintenance_timesheet
#. odoo-python
#: code:addons/maintenance_timesheet/models/hr_timesheet.py:0
#, python-format
msgid ""
"Cannot save or delete a timesheet for a maintenance request already done"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Date"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Description"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Duration (Hour(s))"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_equipment
msgid "Maintenance Equipment"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model,name:maintenance_timesheet.model_maintenance_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_account_analytic_line__maintenance_request_id
msgid "Maintenance Request"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__planned_hours
msgid "Planned Hours"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__progress
msgid "Progress"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Project -"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__remaining_hours
msgid "Remaining Hours"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.hr_timesheet_line_search
msgid "Request"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Responsible"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Task"
msgstr ""
#. module: maintenance_timesheet
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.report_maintenance_request_document
msgid "Time"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_total_hours
msgid "Timesheet Total Hours"
msgstr ""
#. module: maintenance_timesheet
#: model:ir.actions.act_window,name:maintenance_timesheet.timesheet_action_from_request
#: model:ir.model.fields,field_description:maintenance_timesheet.field_maintenance_request__timesheet_ids
#: model_terms:ir.ui.view,arch_db:maintenance_timesheet.equipment_request_view_form
msgid "Timesheets"
msgstr ""

View file

@ -0,0 +1,10 @@
<?xml version='1.0' encoding='utf-8' ?>
<odoo>
<record id="hr_timesheet_rule_request_user" model="ir.rule">
<field name="domain_force">[
('maintenance_request_id.message_partner_ids', 'in', [user.partner_id.id]),
('maintenance_request_id.user_id.id', '=', user.id)
]
</field>
</record>
</odoo>

View file

@ -0,0 +1,10 @@
# Copyright 2025 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
openupgrade.load_data(
env.cr, "maintenance_timesheet", "migrations/16.0.2.1.0/noupdate_changes.xml"
)

View file

@ -0,0 +1,3 @@
from . import hr_timesheet
from . import maintenance_equipment
from . import maintenance_request

View file

@ -0,0 +1,57 @@
# © 2019 Solvos Consultoría Informática (<http://www.solvos.es>)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class AccountAnalyticLine(models.Model):
_inherit = "account.analytic.line"
maintenance_request_id = fields.Many2one(comodel_name="maintenance.request")
@api.onchange("maintenance_request_id")
def onchange_maintenance_request_id(self):
if self.maintenance_request_id and not self.project_id:
self.project_id = self.maintenance_request_id.project_id
self.task_id = self.maintenance_request_id.task_id
@api.model_create_multi
def create(self, vals_list):
maintenance_request_ids = [
vals.get("maintenance_request_id")
for vals in vals_list
if vals.get("maintenance_request_id")
]
self._check_request_done(maintenance_request_ids)
return super().create(vals_list)
def write(self, values):
current_request = self.maintenance_request_id
new_request_id = values.get("maintenance_request_id", False)
if current_request:
self._check_request_done(current_request.id)
if new_request_id:
self._check_request_done(new_request_id)
return super().write(values)
def unlink(self):
self._check_request_done(
self.filtered(lambda x: x.maintenance_request_id).maintenance_request_id.ids
)
return super().unlink()
def _check_request_done(self, request_id: int | list[int]):
"""
Editing a timesheet related to a finished request is forbidden.
"""
request_ids = [request_id] if isinstance(request_id, int) else request_id
if any(
self.env["maintenance.request"].browse(request_ids).stage_id.mapped("done")
):
raise ValidationError(
_(
"Cannot save or delete a timesheet for "
"a maintenance request already done"
)
)

View file

@ -0,0 +1,13 @@
# Copyright 2019 Solvos Consultoría Informática (<http://www.solvos.es>)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo import models
class MaintenanceEquipment(models.Model):
_inherit = "maintenance.equipment"
def _prepare_project_from_equipment_values(self):
data = super()._prepare_project_from_equipment_values()
data["allow_timesheets"] = True
return data

View file

@ -0,0 +1,82 @@
# © 2019 Solvos Consultoría Informática (<http://www.solvos.es>)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo import api, fields, models
class MaintenanceRequest(models.Model):
_inherit = "maintenance.request"
timesheet_ids = fields.One2many(
string="Timesheets",
comodel_name="account.analytic.line",
inverse_name="maintenance_request_id",
)
timesheet_total_hours = fields.Float(
compute="_compute_timesheet_total_hours", readonly=True, store=True
)
planned_hours = fields.Float(tracking=True)
progress = fields.Float(
compute="_compute_progress_hours",
group_operator="avg",
store=True,
)
remaining_hours = fields.Float(
compute="_compute_progress_hours",
readonly=True,
store=True,
)
@api.depends("planned_hours", "timesheet_total_hours")
def _compute_progress_hours(self):
for item in self:
item.progress = 0.0
if item.planned_hours > 0.0:
if item.timesheet_total_hours > item.planned_hours:
item.progress = 100
else:
item.progress = round(
100.0 * item.timesheet_total_hours / item.planned_hours, 2
)
item.remaining_hours = item.planned_hours - item.timesheet_total_hours
def _add_followers(self):
"""
Members of maintenance team are included as followers to automatically
grant request visibility and timesheet permissions for this request
"""
res = super()._add_followers()
for request in self:
partner_ids = request.maintenance_team_id.member_ids.mapped(
"partner_id"
).ids
request.message_subscribe(partner_ids=partner_ids)
return res
@api.depends("timesheet_ids.unit_amount")
def _compute_timesheet_total_hours(self):
for request in self:
request.timesheet_total_hours = sum(
request.timesheet_ids.mapped("unit_amount")
)
def action_view_timesheet_ids(self):
"""
Access to the current timesheets for this maintenance request
The view will be restricted to the current request and only HR managers
could create timesheets for every employee
"""
self.ensure_one()
action = self.env["ir.actions.act_window"]._for_xml_id(
"maintenance_timesheet.timesheet_action_from_request"
)
action["domain"] = [("maintenance_request_id", "=", self.id)]
action["context"] = {
"default_project_id": self.project_id.id,
"default_task_id": self.task_id.id,
"default_maintenance_request_id": self.id,
"readonly_employee_id": not self.env.user.has_group(
"hr_timesheet.group_timesheet_manager"
),
}
return action

View file

@ -0,0 +1,3 @@
* David Alonso <david.alonso@solvos.es>
* Luisa Miguéns <luisa.miguens@solvos.es>
* Christian Ramos <c.ramos@binhex.es>

View file

@ -0,0 +1 @@
This module adds timesheets to a request.

View file

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template
id="report_maintenance_request_document"
inherit_id="maintenance_project.report_maintenance_request_document"
>
<xpath expr="//div[@id='project_informations']" position="inside">
<div
groups="hr_timesheet.group_hr_timesheet_user"
class="col-auto mw-100 mb-2"
>
<strong>Timesheet Total Hours:</strong>
<p
class="m-0"
t-field="doc.timesheet_total_hours"
t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}"
/>
</div>
</xpath>
<xpath expr="//div[@id='description']" position="after">
<div
id="timesheet_information"
t-if="doc.timesheet_ids"
groups="hr_timesheet.group_hr_timesheet_user"
class="col-auto mw-100 mb-2"
>
<h5>
<span id="timesheet_information_title">Timesheet Entries</span>
</h5>
<div id="timesheet_information_detail" class="row">
<div class="col-md-12">
<table class="table table-condensed">
<thead>
<tr>
<th>Date</th>
<th>Responsible</th>
<th>Description</th>
<th t-if="show_task"><t
t-if="show_project"
>Project - </t>Task</th>
<th class="text-right">Time</th>
</tr>
</thead>
<tbody>
<t t-foreach="doc.timesheet_ids" t-as="l">
<tr>
<td>
<span t-field="l.date" />
</td>
<td>
<span t-field="l.user_id.partner_id.name" />
</td>
<td>
<span
t-field="l.name"
t-options="{'widget': 'text'}"
/>
</td>
<td t-if="show_task or show_project">
<t t-if="show_project">
<span t-field="l.project_id.name" />
</t>
<t t-if="show_project and l.task_id"> - </t>
<t t-if="l.task_id">
<span t-field="l.task_id.name" />
</t>
</td>
<td class="text-right">
<span
t-field="l.unit_amount"
t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}"
/>
</td>
</tr>
</t>
<tr>
<td />
<td />
<td t-if="show_task" />
<td class="text-right">
<strong>Total</strong>
</td>
<td class="text-right">
<strong
t-esc="sum(doc.timesheet_ids.mapped('unit_amount'))"
t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}"
/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</xpath>
</template>
</odoo>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="hr_timesheet_rule_request_user" model="ir.rule">
<field
name="name"
>Users are allowed to access timesheets related to a followed request</field>
<field name="model_id" ref="model_account_analytic_line" />
<field name="domain_force">[
('maintenance_request_id.message_partner_ids', 'in', [user.partner_id.id]),
('maintenance_request_id.user_id.id', '=', user.id)
]
</field>
<field
name="groups"
eval="[(4, ref('hr_timesheet.group_hr_timesheet_user'))]"
/>
</record>
<record id="hr_timesheet_rule_request_manager" model="ir.rule">
<field
name="name"
>Managers are allowed to access timesheets related to any request</field>
<field name="model_id" ref="model_account_analytic_line" />
<field name="domain_force">
[('maintenance_request_id', '!=', False)]
</field>
<field name="groups" eval="[(4, ref('maintenance.group_equipment_manager'))]" />
</record>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,431 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="maintenance-timesheets">
<h1>Maintenance Timesheets</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:6e3c051cdab2b2b121c7ede1bc83c4f83179f60e4506daf330a965ef56b938bc
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/maintenance/tree/16.0/maintenance_timesheet"><img alt="OCA/maintenance" src="https://img.shields.io/badge/github-OCA%2Fmaintenance-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/maintenance-16-0/maintenance-16-0-maintenance_timesheet"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/maintenance&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module adds timesheets to a request.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/maintenance/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/maintenance/issues/new?body=module:%20maintenance_timesheet%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-2">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-3">Authors</a></h3>
<ul class="simple">
<li>Solvos</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-4">Contributors</a></h3>
<ul class="simple">
<li>David Alonso &lt;<a class="reference external" href="mailto:david.alonso&#64;solvos.es">david.alonso&#64;solvos.es</a>&gt;</li>
<li>Luisa Miguéns &lt;<a class="reference external" href="mailto:luisa.miguens&#64;solvos.es">luisa.miguens&#64;solvos.es</a>&gt;</li>
<li>Christian Ramos &lt;<a class="reference external" href="mailto:c.ramos&#64;binhex.es">c.ramos&#64;binhex.es</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h3>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/maintenance/tree/16.0/maintenance_timesheet">OCA/maintenance</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
from . import test_maintenance_timesheet

View file

@ -0,0 +1,107 @@
# Copyright 2019 Solvos Consultoría Informática (<http://www.solvos.es>)
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo import fields
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
class TestMaintenanceTimesheet(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.stage_undone = cls.env.ref("maintenance.stage_0")
cls.stage_done = cls.env.ref("maintenance.stage_4")
cls.request_demo1 = cls.env.ref("maintenance_timesheet.request_1")
cls.request2 = cls.env["maintenance.request"].create(
{
"name": "Corrective #2 for Generic Monitor",
"equipment_id": cls.env.ref("maintenance_project.equipment_1").id,
"user_id": cls.env.ref("base.user_admin").id,
"schedule_date": fields.Date.today(),
"stage_id": cls.stage_undone.id,
"maintenance_type": "corrective",
}
)
cls.timesheet21_data = {
"name": "Some tasks done",
"project_id": cls.request2.project_id.id,
"user_id": cls.env.ref("base.user_admin").id,
"date": fields.Date.today(),
"unit_amount": 1.5,
}
cls.request2.timesheet_ids = [(0, 0, cls.timesheet21_data)]
def test_request_timesheets(self):
self.assertEqual(self.request_demo1.timesheet_total_hours, 2)
self.assertEqual(
self.request2.timesheet_total_hours, self.timesheet21_data["unit_amount"]
)
def test_onchange_maintenance_request_id(self):
ts1 = self.env["account.analytic.line"].new(
{
"date": fields.Date.today(),
"name": "Timesheet without initial equipment",
"user_id": self.env.ref("base.user_admin").id,
}
)
self.assertFalse(ts1.project_id)
ts1.maintenance_request_id = self.request2
ts1.onchange_maintenance_request_id()
self.assertEqual(ts1.project_id, self.request2.project_id)
def test_check_request_done(self):
self.request2.stage_id = self.stage_done
with self.assertRaises(ValidationError):
self.request2.timesheet_ids = [
(
0,
0,
{
"name": "Attempt to create a task for a done request",
"project_id": self.request2.project_id.id,
"user_id": self.env.ref("base.user_admin").id,
"date": fields.Date.today(),
"unit_amount": 2,
},
)
]
with self.assertRaises(ValidationError):
self.env["account.analytic.line"].create(
{
"name": "Attepting to create a task 2",
"project_id": self.request2.project_id.id,
"user_id": self.env.ref("base.user_admin").id,
"maintenance_request_id": self.request2.id,
"date": fields.Date.today(),
"unit_amount": 1,
}
)
with self.assertRaises(ValidationError):
# Attempt to modify a timesheet related a done request
for timesheet in self.request2.timesheet_ids:
timesheet.unit_amount += 1
with self.assertRaises(ValidationError):
# Attempt to delete a timesheet related a done request
self.request2.timesheet_ids.unlink()
self.request2.stage_id = self.stage_undone
# Deleting timesheets is enabled again
self.request2.timesheet_ids.unlink()
def test_action_view_timesheet_ids(self):
act1 = self.request2.action_view_timesheet_ids()
self.assertEqual(act1["domain"][0][2], self.request2.id)
self.assertEqual(
act1["context"]["default_project_id"], self.request2.project_id.id
)
self.assertFalse(act1["context"]["default_task_id"])
self.assertFalse(act1["context"]["readonly_employee_id"])
def test_prepare_project_from_equipment_values(self):
equipment = self.env["maintenance.equipment"].create({"name": "Test equipment"})
equipment.action_create_project()
self.assertTrue(equipment.project_id.allow_timesheets)

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="hr_timesheet_line_search" model="ir.ui.view">
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_search" />
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<field name="maintenance_request_id" />
</xpath>
<xpath expr="//filter[@name='groupby_employee']" position="before">
<filter
string="Request"
name="groupby_request"
domain="[]"
context="{'group_by':'maintenance_request_id'}"
/>
</xpath>
</field>
</record>
<record id="hr_timesheet_line_tree" model="ir.ui.view">
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_tree" />
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<field
name="maintenance_request_id"
invisible="context.get('default_maintenance_request_id', False)"
/>
</xpath>
</field>
</record>
<record id="timesheet_view_tree_user" model="ir.ui.view">
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.timesheet_view_tree_user" />
<field name="arch" type="xml">
<xpath expr="//field[@name='employee_id']" position="attributes">
<attribute
name="readonly"
>context.get('readonly_employee_id', False)</attribute>
</xpath>
</field>
</record>
<record id="hr_timesheet_line_form" model="ir.ui.view">
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form" />
<field name="arch" type="xml">
<field name="project_id" position="before">
<field name="maintenance_request_id" />
</field>
</field>
</record>
</odoo>

View file

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="timesheet_action_from_request" model="ir.actions.act_window">
<field name="name">Timesheets</field>
<field name="res_model">account.analytic.line</field>
<field name="search_view_id" ref="hr_timesheet_line_search" />
<field
name="domain"
>[('project_id', '!=', False), ('maintenance_request_id', '!=', False)]</field>
</record>
<record
id="timesheet_action_view_from_request_list"
model="ir.actions.act_window.view"
>
<field name="sequence" eval="5" />
<field name="view_mode">tree</field>
<field name="view_id" ref="hr_timesheet.timesheet_view_tree_user" />
<field name="act_window_id" ref="timesheet_action_from_request" />
</record>
<record
id="timesheet_action_view_from_request_form"
model="ir.actions.act_window.view"
>
<field name="sequence" eval="10" />
<field name="view_mode">form</field>
<field name="view_id" ref="hr_timesheet_line_form" />
<field name="act_window_id" ref="timesheet_action_from_request" />
</record>
<!-- maintenance.request: view inheritance -->
<record id="hr_equipment_request_view_tree" model="ir.ui.view">
<field name="model">maintenance.request</field>
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_tree" />
<field name="arch" type="xml">
<field name="stage_id" position="after">
<field
name="timesheet_total_hours"
groups="maintenance.group_equipment_manager"
widget="timesheet_uom"
/>
</field>
</field>
</record>
<record id="hr_equipment_request_view_kanban" model="ir.ui.view">
<field name="model">maintenance.request</field>
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_kanban" />
<field name="arch" type="xml">
<xpath expr="//field[@name='activity_state']" position="after">
<field
name="timesheet_total_hours"
groups="hr_timesheet.group_hr_timesheet_user"
/>
</xpath>
<xpath expr="//div[hasclass('oe_kanban_bottom_left')]" position="inside">
<a
class="o_project_kanban_box"
name="action_view_timesheet_ids"
type="object"
groups="hr_timesheet.group_hr_timesheet_user"
>
<div>
<span class="o_value">
<field
name="timesheet_total_hours"
class="oe_inline"
widget="timesheet_uom"
/>
<!-- t t-esc="record.timesheet_total_hours.value"/-->
</span>
<span class="o_label">Hours</span>
</div>
</a>
</xpath>
</field>
</record>
<record id="hr_equipment_request_view_form" model="ir.ui.view">
<field name="model">maintenance.request</field>
<field name="inherit_id" ref="base_maintenance.equipment_request_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button
class="oe_stat_button"
type="object"
name="action_view_timesheet_ids"
icon="fa-calendar"
groups="hr_timesheet.group_hr_timesheet_user"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field
name="timesheet_total_hours"
widget="timesheet_uom"
/>
</span>
<span class="o_stat_text">
Hours
</span>
</div>
</button>
</xpath>
</field>
</record>
<record id="equipment_request_view_form" model="ir.ui.view">
<field name="model">maintenance.request</field>
<field name="inherit_id" ref="base_maintenance.equipment_request_view_form" />
<field name="arch" type="xml">
<page name="description_page" position="after">
<page
string="Timesheets"
name="timesheets"
attrs="{'invisible':[('project_id', '=', False)]}"
groups="hr_timesheet.group_hr_timesheet_user"
>
<group>
<group>
<field name="planned_hours" widget="float_time" />
</group>
<group>
<field name="progress" widget="progressbar" />
</group>
</group>
<field
name="timesheet_ids"
context="{'default_project_id': project_id, 'default_task_id': task_id}"
>
<tree editable="bottom" delete="true">
<field name="company_id" invisible="1" />
<field name="project_id" invisible="1" />
<field name="task_id" invisible="1" />
<field name="date" widget="date" />
<field name="user_id" required="1" />
<field name="name" />
<field
name="unit_amount"
string="Duration (Hour(s))"
widget="float_time"
/>
</tree>
<form>
<group>
<field name="date" />
<field name="user_id" />
<field name="name" />
<field
name="unit_amount"
string="Duration (Hour(s))"
widget="float_time"
/>
</group>
</form>
</field>
<group class="oe_subtotal_footer oe_right">
<field name="timesheet_total_hours" widget="float_time" />
<field name="remaining_hours" widget="float_time" />
</group>
</page>
</page>
</field>
</record>
</odoo>

View file

@ -0,0 +1,44 @@
[project]
name = "odoo-bringout-oca-maintenance-maintenance_timesheet"
version = "16.0.0"
description = "Maintenance Timesheets - Adds timesheets to maintenance requests"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-maintenance-base_maintenance>=16.0.0",
"odoo-bringout-oca-maintenance-maintenance_project>=16.0.0",
"odoo-bringout-oca-ocb-hr_timesheet>=16.0.0",
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["maintenance_timesheet"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]