Initial commit: OCA Mrp packages (117 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:05 +02:00
commit 277e84fd7a
4403 changed files with 395154 additions and 0 deletions

View file

@ -0,0 +1,47 @@
# Dates planning in sales order lines
Odoo addon: sale_timesheet_timeline
## Installation
```bash
pip install odoo-bringout-oca-timesheet-sale_timesheet_timeline
```
## Dependencies
This addon depends on:
- sale_timesheet
- project_timeline
## Manifest Information
- **Name**: Dates planning in sales order lines
- **Version**: 16.0.1.0.0
- **Category**: Services/Project
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/timesheet](https://github.com/OCA/timesheet) branch 16.0, addon `sale_timesheet_timeline`.
## 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
- Reports: doc/REPORTS.md
- Security: doc/SECURITY.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 Sale_timesheet_timeline Module - sale_timesheet_timeline
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 sale_timesheet_timeline. 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,6 @@
# Dependencies
This addon depends on:
- [sale_timesheet](../../odoo-bringout-oca-ocb-sale_timesheet)
- [project_timeline](../../odoo-bringout-oca-project-project_timeline)

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 sale_timesheet_timeline or install in UI.

View file

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

View file

@ -0,0 +1,13 @@
# Models
Detected core models and extensions in sale_timesheet_timeline.
```mermaid
classDiagram
class sale_order
class sale_order_line
```
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: sale_timesheet_timeline. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon sale_timesheet_timeline
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,8 @@
# Security
This module does not define custom security rules or access controls beyond Odoo defaults.
Default Odoo security applies:
- Base user access through standard groups
- Model access inherited from dependencies
- No custom row-level security rules

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 sale_timesheet_timeline
```

View file

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

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-timesheet-sale_timesheet_timeline"
version = "16.0.0"
description = "Dates planning in sales order lines - Odoo addon"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-timesheet-sale_timesheet>=16.0.0",
"odoo-bringout-oca-timesheet-project_timeline>=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 = ["sale_timesheet_timeline"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]

View file

@ -0,0 +1,101 @@
===================================
Dates planning in sales order lines
===================================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8f9fea88f3275fcbe5a535f86aaff7a8ef2f645719f47dd5bbd4c6523269b371
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/licence-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%2Ftimesheet-lightgray.png?logo=github
:target: https://github.com/OCA/timesheet/tree/16.0/sale_timesheet_timeline
:alt: OCA/timesheet
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/timesheet-16-0/timesheet-16-0-sale_timesheet_timeline
: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/timesheet&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows to plan in advance the start/end dates and assignees for the sales
order lines that are services, and they are transferred to the created task (if any)
when confirming the order.
It includes a timeline view for pre-viewing and managing the planning.
In addition, this planning is shown in the order portal view.
**Table of contents**
.. contents::
:local:
Usage
=====
#. Go to Sales > Orders > Quotations
#. Create a new record.
#. Add a line with a product of type "Service".
#. A new smart-button "Planning" will appear.
#. On optional fields, you will find 3 fields for setting manually the planning data:
"Task Start", "Task End" and "Task Assignees".
#. You can also click on the "Planning" button and plan the dates visually in the
timeline view.
Known issues / Roadmap
======================
- Timeline visualization in portal.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/timesheet/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/timesheet/issues/new?body=module:%20sale_timesheet_timeline%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
~~~~~~~
* Tecnativa
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
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/timesheet <https://github.com/OCA/timesheet/tree/16.0/sale_timesheet_timeline>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models

View file

@ -0,0 +1,15 @@
# Copyright 2024 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Dates planning in sales order lines",
"version": "16.0.1.0.0",
"category": "Services/Project",
"website": "https://github.com/OCA/timesheet",
"author": "Tecnativa, Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"application": False,
"depends": ["sale_timesheet", "project_timeline"],
"data": ["views/sale_order_views.xml", "views/sale_portal_templates.xml"],
}

View file

@ -0,0 +1,84 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_timeline
#
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: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_order_form
msgid "<span class=\"o_stat_text\">Planning</span>"
msgstr "<span class=\"o_stat_text\">Planiranje</span>"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order__any_service_line
msgid "Any Service Line"
msgstr "Bilo koja linija usluge"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Assignees"
msgstr "Odgovoran"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "End"
msgstr "Kraj"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Planning"
msgstr "Planiranje"
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order
msgid "Sales Order"
msgstr "Prodajni nalog"
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order_line
msgid "Sales Order Line"
msgstr "Stavka prodajne narudžbe"
#. module: sale_timesheet_timeline
#: model:ir.actions.act_window,name:sale_timesheet_timeline.action_sale_order_line_timeline
msgid "Sales Tasks Planning"
msgstr "Planiranje zadataka prodaje"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Start"
msgstr "Započni"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Task"
msgstr "Zadatak"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_user_ids
msgid "Task Assignees"
msgstr "Dodijeljeni zadatka"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_end
msgid "Task End"
msgstr "Završetak zadatka"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_start
msgid "Task Start"
msgstr "Početak zadatka"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_sale_order_line_timeline
msgid "User"
msgstr "Korisnik"

View file

@ -0,0 +1,88 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_timeline
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-21 07:09+0000\n"
"PO-Revision-Date: 2024-08-21 09:11+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"X-Generator: Poedit 3.0.1\n"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_order_form
msgid "<span class=\"o_stat_text\">Planning</span>"
msgstr "<span class=\"o_stat_text\">Planificación</span>"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order__any_service_line
msgid "Any Service Line"
msgstr "Cualquier línea de servicio"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Assignees"
msgstr "Asignados"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "End"
msgstr "Fin"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Planning"
msgstr "Planificación"
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order
msgid "Sales Order"
msgstr "Pedido de venta"
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order_line
msgid "Sales Order Line"
msgstr "Línea de pedido de venta"
#. module: sale_timesheet_timeline
#: model:ir.actions.act_window,name:sale_timesheet_timeline.action_sale_order_line_timeline
msgid "Sales Tasks Planning"
msgstr "Planificación de tareas de ventas"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Start"
msgstr "Inicio"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Task"
msgstr "Tarea"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_user_ids
msgid "Task Assignees"
msgstr "Asignados a la tarea"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_end
msgid "Task End"
msgstr "Fin de tarea"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_start
msgid "Task Start"
msgstr "Comienzo de tarea"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_sale_order_line_timeline
msgid "User"
msgstr "Usuario"

View file

@ -0,0 +1,87 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_timeline
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-10-14 09:06+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 5.6.2\n"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_order_form
msgid "<span class=\"o_stat_text\">Planning</span>"
msgstr "<span class=\"o_stat_text\">Pianificazione</span>"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order__any_service_line
msgid "Any Service Line"
msgstr "Ogni riga servizio"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Assignees"
msgstr "Assegnatari"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "End"
msgstr "Fine"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Planning"
msgstr "Pianificazione"
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order
msgid "Sales Order"
msgstr "Ordine di vendita"
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order_line
msgid "Sales Order Line"
msgstr "Riga ordine di vendita"
#. module: sale_timesheet_timeline
#: model:ir.actions.act_window,name:sale_timesheet_timeline.action_sale_order_line_timeline
msgid "Sales Tasks Planning"
msgstr "Pianificazione attività vendite"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Start"
msgstr "Avvio"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Task"
msgstr "Attività"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_user_ids
msgid "Task Assignees"
msgstr "Assegnatario attività"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_end
msgid "Task End"
msgstr "Fine attività"
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_start
msgid "Task Start"
msgstr "Inizio attività"
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_sale_order_line_timeline
msgid "User"
msgstr "Utente"

View file

@ -0,0 +1,84 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_timeline
#
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: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_order_form
msgid "<span class=\"o_stat_text\">Planning</span>"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order__any_service_line
msgid "Any Service Line"
msgstr ""
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Assignees"
msgstr ""
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "End"
msgstr ""
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Planning"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.model,name:sale_timesheet_timeline.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.actions.act_window,name:sale_timesheet_timeline.action_sale_order_line_timeline
msgid "Sales Tasks Planning"
msgstr ""
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Start"
msgstr ""
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.sale_order_portal_content
msgid "Task"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_user_ids
msgid "Task Assignees"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_end
msgid "Task End"
msgstr ""
#. module: sale_timesheet_timeline
#: model:ir.model.fields,field_description:sale_timesheet_timeline.field_sale_order_line__task_date_start
msgid "Task Start"
msgstr ""
#. module: sale_timesheet_timeline
#: model_terms:ir.ui.view,arch_db:sale_timesheet_timeline.view_sale_order_line_timeline
msgid "User"
msgstr ""

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import sale_order

View file

@ -0,0 +1,42 @@
# Copyright 2024 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import Command, fields, models
class SaleOrder(models.Model):
_inherit = "sale.order"
any_service_line = fields.Boolean(compute="_compute_any_service_line")
def _compute_any_service_line(self):
for record in self:
record.any_service_line = any(
[x.product_type == "service" for x in record.order_line]
)
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
task_date_start = fields.Datetime("Task Start")
task_date_end = fields.Datetime("Task End")
task_user_ids = fields.Many2many(
comodel_name="res.users",
string="Task Assignees",
copy=True,
context={"active_test": False},
domain="[('share', '=', False), ('active', '=', True)]",
)
def _timesheet_create_task_prepare_values(self, project):
# Transfer dates and assignees from sales order line
res = super()._timesheet_create_task_prepare_values(project)
if self.task_date_start:
res["planned_date_start"] = self.task_date_start
if self.task_date_end:
res["planned_date_end"] = self.task_date_end
res["date_deadline"] = self.task_date_end
if self.task_user_ids:
res["user_ids"] = [Command.link(x.id) for x in self.task_user_ids]
return res

View file

@ -0,0 +1,3 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza

View file

@ -0,0 +1,7 @@
This module allows to plan in advance the start/end dates and assignees for the sales
order lines that are services, and they are transferred to the created task (if any)
when confirming the order.
It includes a timeline view for pre-viewing and managing the planning.
In addition, this planning is shown in the order portal view.

View file

@ -0,0 +1 @@
- Timeline visualization in portal.

View file

@ -0,0 +1,8 @@
#. Go to Sales > Orders > Quotations
#. Create a new record.
#. Add a line with a product of type "Service".
#. A new smart-button "Planning" will appear.
#. On optional fields, you will find 3 fields for setting manually the planning data:
"Task Start", "Task End" and "Task Assignees".
#. You can also click on the "Planning" button and plan the dates visually in the
timeline view.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,454 @@
<!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>Dates planning in sales order lines</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" id="dates-planning-in-sales-order-lines">
<h1 class="title">Dates planning in sales order lines</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8f9fea88f3275fcbe5a535f86aaff7a8ef2f645719f47dd5bbd4c6523269b371
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/timesheet/tree/16.0/sale_timesheet_timeline"><img alt="OCA/timesheet" src="https://img.shields.io/badge/github-OCA%2Ftimesheet-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/timesheet-16-0/timesheet-16-0-sale_timesheet_timeline"><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/timesheet&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 allows to plan in advance the start/end dates and assignees for the sales
order lines that are services, and they are transferred to the created task (if any)
when confirming the order.</p>
<p>It includes a timeline view for pre-viewing and managing the planning.</p>
<p>In addition, this planning is shown in the order portal view.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<ol class="arabic simple">
<li>Go to Sales &gt; Orders &gt; Quotations</li>
<li>Create a new record.</li>
<li>Add a line with a product of type “Service”.</li>
<li>A new smart-button “Planning” will appear.</li>
<li>On optional fields, you will find 3 fields for setting manually the planning data:
“Task Start”, “Task End” and “Task Assignees”.</li>
<li>You can also click on the “Planning” button and plan the dates visually in the
timeline view.</li>
</ol>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Timeline visualization in portal.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/timesheet/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/timesheet/issues/new?body=module:%20sale_timesheet_timeline%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">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul>
<li><p class="first"><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:</p>
<blockquote>
<ul class="simple">
<li>Pedro M. Baeza</li>
</ul>
</blockquote>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<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/timesheet/tree/16.0/sale_timesheet_timeline">OCA/timesheet</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>
</body>
</html>

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import test_sale_timesheet_timeline

View file

@ -0,0 +1,50 @@
# Copyright 2024 Tecnativa - Pedro M. Baeza
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from odoo import fields
from odoo.tests import Form, new_test_user
from odoo.addons.base.tests.common import BaseCommon
class TestSaleTimesheetTimeline(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner = cls.env["res.partner"].create({"name": "Test partner"})
cls.user = new_test_user(cls.env, login="test_user_st_timeline")
cls.project = cls.env["project.project"].create(
{"name": "Test project", "allow_billable": True}
)
cls.product_task = cls.env["product.product"].create(
{
"name": "Test task product",
"detailed_type": "service",
"service_tracking": "task_global_project",
"service_policy": "ordered_prepaid",
"project_id": cls.project.id,
"uom_id": cls.env.ref("uom.product_uom_hour").id,
"uom_po_id": cls.env.ref("uom.product_uom_hour").id,
}
)
order_form = Form(cls.env["sale.order"])
order_form.partner_id = cls.partner
with order_form.order_line.new() as line_form:
line_form.product_id = cls.product_task
line_form.product_uom_qty = 10
line_form.name = "This is a long description\nwith line feed"
line_form.task_date_start = "2024-08-01 00:00:00"
line_form.task_date_end = "2024-08-05 12:00:00"
line_form.task_user_ids.add(cls.user)
cls.order = order_form.save()
def test_task_creation(self):
self.order.action_confirm()
task = self.project.task_ids
self.assertEqual(
task.planned_date_start, fields.Datetime.from_string("2024-08-01 00:00:00")
)
self.assertEqual(
task.planned_date_end, fields.Datetime.from_string("2024-08-05 12:00:00")
)
self.assertEqual(task.date_deadline, fields.Date.from_string("2024-08-05"))
self.assertEqual(task.user_ids, self.user)

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2024 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<record id="view_sale_order_line_timeline" model="ir.ui.view">
<field name="model">sale.order.line</field>
<field name="type">timeline</field>
<field name="arch" type="xml">
<timeline
date_start="task_date_start"
date_stop="task_date_end"
default_group_by="task_user_ids"
event_open_popup="true"
colors="white: task_user_ids == ''"
>
<field name="name" />
<field name="task_user_ids" />
<field name="product_uom_qty" />
<templates>
<t t-name="timeline-item">
<div class="o_project_timeline_item">
<t t-foreach="record.task_user_ids" t-as="user">
<img
t-if="record.task_user_ids"
t-attf-src="/web/image/res.users/#{user}/avatar_128/16x16"
t-att-title="record.user"
width="16"
height="16"
class="mr8"
alt="User"
/>
</t>
<span name="name">
<t t-esc="record.name.split('\n')[0]" />
</span>
<small
name="planned_hours"
class="text-info ml4"
t-if="record.product_uom_qty"
>
<t
t-esc="field_utils.format.float_time(record.product_uom_qty)"
/>
</small>
</div>
</t>
</templates>
</timeline>
</field>
</record>
<record id="action_sale_order_line_timeline" model="ir.actions.act_window">
<field name="name">Sales Tasks Planning</field>
<field name="res_model">sale.order.line</field>
<field name="view_mode">timeline</field>
<field
name="domain"
>[('order_id', '=', active_id), ('product_type', '=', 'service')]</field>
</record>
<!-- Put this one after the action definition -->
<record id="view_order_form" model="ir.ui.view">
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='order_line']/tree" position="inside">
<field
name="task_date_start"
optional="hide"
attrs="{'invisible': [('product_type', '!=', 'service')], 'readonly': [('state', 'not in', ('draft', 'sent'))]}"
/>
<field
name="task_date_end"
optional="hide"
attrs="{'invisible': [('product_type', '!=', 'service')], 'readonly': [('state', 'not in', ('draft', 'sent'))]}"
/>
<field
name="task_user_ids"
optional="hide"
widget="many2many_avatar_user"
attrs="{'invisible': [('product_type', '!=', 'service')], 'readonly': [('state', 'not in', ('draft', 'sent'))]}"
/>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<field name="any_service_line" invisible="1" />
<button
name="%(action_sale_order_line_timeline)d"
type="action"
class="oe_stat_button"
icon="fa-tasks"
attrs="{'invisible': [('any_service_line', '=', False)]}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Planning</span>
</div>
</button>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,72 @@
<odoo>
<template
id="sale_order_portal_content"
inherit_id="sale.sale_order_portal_content"
>
<xpath expr="//div[@id='total']" position="after">
<t
t-set="show_timeline"
t-value="lines_to_report.filtered(lambda x: x.task_date_start or x.task_date_end or x.task_user_ids)"
/>
<div t-if="show_timeline" id="timeline">
<h3>Planning</h3>
<table class="table table-sm" id="sales_order_planning_table">
<thead class="bg-100">
<tr>
<th class="text-start" id="product_name_header">Task</th>
<th class="text-center">Start</th>
<th class="text-center">End</th>
<th class="text-end">Assignees</th>
</tr>
</thead>
<tbody class="sale_tbody">
<t
t-set="sorted_lines"
t-value="sorted(lines_to_report, key=lambda l: (l.task_date_start is False and l.task_date_end is False, l.task_date_start is not False, l.task_date_start or l.task_date_end))"
/>
<t t-foreach="sorted_lines" t-as="line">
<t
t-set="show_line"
t-value="line.task_date_start or line.task_date_end or line.task_user_ids"
/>
<tr
t-if="show_line"
t-att-class="'bg-200 fw-bold o_line_section' if line.display_type == 'line_section' else 'fst-italic o_line_note' if line.display_type == 'line_note' else ''"
>
<t t-if="not line.display_type">
<t t-set="name" t-value="line.name.split('\n')" />
<td id="name">
<span
t-esc="name[0] + ' ' + name[1] if len(name) > 1 else name[0]"
/>
</td>
<td class="text-center">
<div id="date_start">
<span
t-field="line.task_date_start"
t-options='{"widget": "date"}'
/>
</div>
</td>
<td class="text-center">
<div id="date_end">
<span
t-field="line.task_date_end"
t-options='{"widget": "date"}'
/>
</div>
</td>
<td class="text-end">
<div id="user_ids">
<span t-field="line.task_user_ids" />
</div>
</td>
</t>
</tr>
</t>
</tbody>
</table>
</div>
</xpath>
</template>
</odoo>