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,46 @@
# Sales Timesheet: exclude Timesheet Line from Sale Order
Odoo addon: sale_timesheet_line_exclude
## Installation
```bash
pip install odoo-bringout-oca-timesheet-sale_timesheet_line_exclude
```
## Dependencies
This addon depends on:
- sale_timesheet
## Manifest Information
- **Name**: Sales Timesheet: exclude Timesheet Line from Sale Order
- **Version**: 16.0.1.2.0
- **Category**: Sales
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/timesheet](https://github.com/OCA/timesheet) branch 16.0, addon `sale_timesheet_line_exclude`.
## 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_line_exclude Module - sale_timesheet_line_exclude
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_line_exclude. 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,5 @@
# Dependencies
This addon depends on:
- [sale_timesheet](../../odoo-bringout-oca-ocb-sale_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 sale_timesheet_line_exclude or install in UI.

View file

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

View file

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

View file

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

View file

@ -0,0 +1,74 @@
# Security
Access control and security definitions in sale_timesheet_line_exclude.
## Access Control Lists (ACLs)
Model access permissions defined in:
- **[all_odoo_addons_repos.txt](../all_odoo_addons_repos.txt)**
- 318 model access rules
- **[bosnian_translations.json](../bosnian_translations.json)**
- 50 model access rules
- **[bosnian_translations_output.json](../bosnian_translations_output.json)**
- 444 model access rules
- **[CHANGELOG.md](../CHANGELOG.md)**
- 132 model access rules
- **[delete_all_odoo_addons.sh](../delete_all_odoo_addons.sh)**
- 50 model access rules
- **[delete_odoo_addons.sh](../delete_odoo_addons.sh)**
- 44 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)**
- 146 model access rules
- **[verify_deletions.sh](../verify_deletions.sh)**
- 55 model access rules
## Record Rules
Row-level security rules defined in:
## Security Groups & Configuration
Security groups and permissions defined in:
- **[exclude_from_sale_order.xml](../sale_timesheet_line_exclude/security/exclude_from_sale_order.xml)**
- 1 security groups defined
```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:
- **[exclude_from_sale_order.xml](../sale_timesheet_line_exclude/security/exclude_from_sale_order.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 sale_timesheet_line_exclude
```

View file

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

View file

@ -0,0 +1,42 @@
[project]
name = "odoo-bringout-oca-timesheet-sale_timesheet_line_exclude"
version = "16.0.0"
description = "Sales Timesheet: exclude Timesheet Line from Sale Order - Exclude Timesheet Line from Sale Order"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-timesheet-sale_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 = ["sale_timesheet_line_exclude"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]

View file

@ -0,0 +1,101 @@
=======================================================
Sales Timesheet: exclude Timesheet Line from Sale Order
=======================================================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:33935b7fce5969b56315a8597b08297bf4f2764ca4b973f077e64ebd2c35e90c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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_line_exclude
: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_line_exclude
: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|
Allows to exclude specific *Timesheet* line from Sale Order.
This feature proves itself useful for *By Task* billing approach, when
a specific timesheet entry tracked towards a billable task needs to be
excluded from the Sale Order.
This functionality is not available in Odoo, reported in `odoo/odoo#31043 <https://github.com/odoo/odoo/pull/31043>`_.
**Table of contents**
.. contents::
:local:
Usage
=====
To exclude a specific timesheet entry from invoicing:
# Go to *Timesheets > Timesheet > All Timesheets*
# On the Timesheet list view, check *Non-billable* for specific timesheet entries
or:
# Go to *Project > All Tasks*, ans open a specific Task form
# On the Task form, *Timesheets* tab, check *Non-billable* for specific timesheet entries
To have access to this *Non-billable* field, the user must be added to the
*Exclude timesheets from sale order* security group.
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_line_exclude%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
~~~~~~~
* CorporateHub
Contributors
~~~~~~~~~~~~
* `CorporateHub <https://corporatehub.eu/>`__
* Alexey Pelykh <alexey.pelykh@corphub.eu>
* Freni Patel <fpatel@opensourceintegrators.com>
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_line_exclude>`_ 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,21 @@
# Copyright 2018-2019 Brainbean Apps (https://brainbeanapps.com)
# Copyright 2020 CorporateHub (https://corporatehub.eu)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Sales Timesheet: exclude Timesheet Line from Sale Order",
"version": "16.0.1.2.0",
"category": "Sales",
"website": "https://github.com/OCA/timesheet",
"author": "CorporateHub, " "Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"application": False,
"summary": "Exclude Timesheet Line from Sale Order",
"depends": ["sale_timesheet"],
"data": [
"security/exclude_from_sale_order.xml",
"views/account_analytic_line.xml",
"views/project_task.xml",
],
}

View file

@ -0,0 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
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_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Analitička stavka"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr "Označavanjem ovog bi se isključio ovaj unos evidencije radnog vremena iz prodajnog naloga"
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr "Isključi evidencije radnog vremena iz prodajnog naloga"
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "Isključeno iz prodajnog naloga"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr "Daje pristup polju Ne-naplativo na evidencijama radnog vremena."
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "Nenaplatno"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""

View file

@ -0,0 +1,60 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-07-12 13:43+0000\n"
"Last-Translator: Maria Sparenberg <maria.sparenberg@gmx.net>\n"
"Language-Team: none\n"
"Language: de\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 3.7.1\n"
#. module: sale_timesheet_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Kostenstellenbuchung"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
"Wenn der Haken gesetzt ist, wird diese Zeiterfassung für die Abrechnung über "
"einen Verkaufsauftrag ausgeschlossen."
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "von Abrechnung ausgeschlossen"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "von Abrechnung ausschließen"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""
"Es ist nicht erlaubt, Zeiterfassungen zu verändern, die bereits abgerechnet "
"sind."

View file

@ -0,0 +1,59 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2020-05-18 20:19+0000\n"
"Last-Translator: Josep M <jmyepes@mac.com>\n"
"Language-Team: none\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 3.10\n"
#. module: sale_timesheet_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Línea analítica"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
"Marcando esto excluirá esta entrada del Parte de horas del pedido de venta"
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "Excluido del pedido de venta"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "Excluir del pedido de venta"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""
"No puede modificar los Partes de horas de forma que afecte las facturas ya "
"que estos Partes de horas ya se facturaron."

View file

@ -0,0 +1,61 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2022-10-05 15:29+0000\n"
"Last-Translator: Vincent Hatakeyama <vincent+github@hatakeyama.fr>\n"
"Language-Team: none\n"
"Language: fr\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.3.2\n"
#. module: sale_timesheet_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Ligne analytique"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
"Cocher cette case exclut cette entrée de feuille de temps de la commande "
"client"
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "Exclue de la commande client"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "Non facturable"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""
"Vous ne pouvez pas modifier les feuilles de temps d'une manière qui "
"affecterait les factures puisque ces feuilles de temps étaient déjà "
"facturées."

View file

@ -0,0 +1,60 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-10-10 10: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_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Riga analitica"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
"Con questa selezione la registrazione nel foglio ore verrà esclusa "
"dall'ordine di vendita"
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr "Escludi fogli ore dagli ordini di vendita"
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "Esclusa dall'ordine di vendita"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr "Consenti accesso ai campi non fatturabili nei fogli ore."
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "Non fatturabile"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""
"Non è possibile modificare i fogli ore in modo tale da influire sulle "
"fatture poiché questi fogli ore sono già stati fatturati."

View file

@ -0,0 +1,60 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-13 17:06+0000\n"
"Last-Translator: Rodrigo Sottomaior Macedo "
"<sottomaiormacedotec@sottomaiormacedo.tech>\n"
"Language-Team: none\n"
"Language: pt_BR\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_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Linha Analítica"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
"Marcar isto excluiria esta entrada da planilha de horas do pedido de venda"
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr "Excluir planilhas de horas do pedido de venda"
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "Excluído do pedido de venda"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr "Dá acesso ao campo Não Faturável em planilhas de horas."
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "Não faturável"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""
"Você não pode modificar planilhas de horas de uma forma que afete as "
"faturas, uma vez que essas planilhas de horas já foram faturadas."

View file

@ -0,0 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
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_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr ""
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr ""
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""

View file

@ -0,0 +1,59 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_timesheet_line_exclude
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-06-12 17:26+0000\n"
"Last-Translator: Betül Öğmen <betulo@eska.biz>\n"
"Language-Team: none\n"
"Language: tr\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.10.4\n"
#. module: sale_timesheet_line_exclude
#: model:ir.model,name:sale_timesheet_line_exclude.model_account_analytic_line
msgid "Analytic Line"
msgstr "Analitik Satırı"
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,help:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Checking this would exclude this timesheet entry from Sale Order"
msgstr ""
"Bunu işaretlemek, bu zaman çizelgesi girişini Satış Emrinden hariç tutacaktır"
#. module: sale_timesheet_line_exclude
#: model:res.groups,name:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Exclude timesheets from sale order"
msgstr "Zaman çizelgelerini satış siparişinden hariç tut"
#. module: sale_timesheet_line_exclude
#: model_terms:ir.ui.view,arch_db:sale_timesheet_line_exclude.account_analytic_line_search
msgid "Excluded From Sale Order"
msgstr "Satış Siparişinden Hariç Tutulan"
#. module: sale_timesheet_line_exclude
#: model:res.groups,comment:sale_timesheet_line_exclude.group_exclude_from_sale_order
msgid "Gives access to the Non-Billable field on timesheets."
msgstr "Zaman çizelgelerindeki Faturalandırılamayan alana erişim sağlar."
#. module: sale_timesheet_line_exclude
#: model:ir.model.fields,field_description:sale_timesheet_line_exclude.field_account_analytic_line__exclude_from_sale_order
msgid "Non-billable"
msgstr "Faturalanamaz"
#. module: sale_timesheet_line_exclude
#. odoo-python
#: code:addons/sale_timesheet_line_exclude/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can not modify timesheets in a way that would affect invoices since "
"these timesheets were already invoiced."
msgstr ""
"Faturaları etkileyecek şekilde zaman çizelgelerini değiştiremezsiniz, çünkü "
"bu zaman çizelgeleri zaten faturalandırılmıştır."

View file

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

View file

@ -0,0 +1,53 @@
# Copyright 2018-2019 Brainbean Apps
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class AccountAnalyticLine(models.Model):
_inherit = "account.analytic.line"
exclude_from_sale_order = fields.Boolean(
string="Non-billable",
help="Checking this would exclude this timesheet entry from Sale Order",
groups="sale_timesheet_line_exclude.group_exclude_from_sale_order",
copy=False,
)
@api.constrains("exclude_from_sale_order")
def _constrains_exclude_from_sale_order(self):
for line in self:
if (
line.timesheet_invoice_id
and line.so_line.product_id.invoice_policy == "delivery"
):
raise ValidationError(
_(
"You can not modify timesheets in a way that would affect "
"invoices since these timesheets were already invoiced."
)
)
@api.depends("exclude_from_sale_order")
def _compute_timesheet_invoice_type(self):
res = super()._compute_timesheet_invoice_type()
for line in self:
if line.exclude_from_sale_order:
line.timesheet_invoice_type = "non_billable"
return res
@api.depends("exclude_from_sale_order")
def _compute_so_line(self):
return super()._compute_so_line()
def _timesheet_determine_sale_line(self):
self.ensure_one()
if self.exclude_from_sale_order:
return False
return super()._timesheet_determine_sale_line()
def _timesheet_postprocess(self, values):
if "exclude_from_sale_order" in values:
self._compute_so_line()
return super()._timesheet_postprocess(values)

View file

@ -0,0 +1,4 @@
* `CorporateHub <https://corporatehub.eu/>`__
* Alexey Pelykh <alexey.pelykh@corphub.eu>
* Freni Patel <fpatel@opensourceintegrators.com>

View file

@ -0,0 +1,7 @@
Allows to exclude specific *Timesheet* line from Sale Order.
This feature proves itself useful for *By Task* billing approach, when
a specific timesheet entry tracked towards a billable task needs to be
excluded from the Sale Order.
This functionality is not available in Odoo, reported in `odoo/odoo#31043 <https://github.com/odoo/odoo/pull/31043>`_.

View file

@ -0,0 +1,12 @@
To exclude a specific timesheet entry from invoicing:
# Go to *Timesheets > Timesheet > All Timesheets*
# On the Timesheet list view, check *Non-billable* for specific timesheet entries
or:
# Go to *Project > All Tasks*, ans open a specific Task form
# On the Task form, *Timesheets* tab, check *Non-billable* for specific timesheet entries
To have access to this *Non-billable* field, the user must be added to the
*Exclude timesheets from sale order* security group.

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright ACSONE SA/NV (https://acsone.eu)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="group_exclude_from_sale_order" model="res.groups">
<field name="name">Exclude timesheets from sale order</field>
<field name="category_id" ref="base.module_category_hidden" />
<field
name="comment"
>Gives access to the Non-Billable field on timesheets.</field>
<field
name="users"
eval="[Command.link(ref('base.user_root')), Command.link(ref('base.user_admin'))]"
/>
</record>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,445 @@
<!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>Sales Timesheet: exclude Timesheet Line from Sale Order</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="sales-timesheet-exclude-timesheet-line-from-sale-order">
<h1 class="title">Sales Timesheet: exclude Timesheet Line from Sale Order</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:33935b7fce5969b56315a8597b08297bf4f2764ca4b973f077e64ebd2c35e90c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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_line_exclude"><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_line_exclude"><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>Allows to exclude specific <em>Timesheet</em> line from Sale Order.</p>
<p>This feature proves itself useful for <em>By Task</em> billing approach, when
a specific timesheet entry tracked towards a billable task needs to be
excluded from the Sale Order.</p>
<p>This functionality is not available in Odoo, reported in <a class="reference external" href="https://github.com/odoo/odoo/pull/31043">odoo/odoo#31043</a>.</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="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>To exclude a specific timesheet entry from invoicing:</p>
<blockquote>
# Go to <em>Timesheets &gt; Timesheet &gt; All Timesheets</em>
# On the Timesheet list view, check <em>Non-billable</em> for specific timesheet entries</blockquote>
<p>or:</p>
<blockquote>
# Go to <em>Project &gt; All Tasks</em>, ans open a specific Task form
# On the Task form, <em>Timesheets</em> tab, check <em>Non-billable</em> for specific timesheet entries</blockquote>
<p>To have access to this <em>Non-billable</em> field, the user must be added to the
<em>Exclude timesheets from sale order</em> security group.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">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_line_exclude%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-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>CorporateHub</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://corporatehub.eu/">CorporateHub</a><ul>
<li>Alexey Pelykh &lt;<a class="reference external" href="mailto:alexey.pelykh&#64;corphub.eu">alexey.pelykh&#64;corphub.eu</a>&gt;</li>
<li>Freni Patel &lt;<a class="reference external" href="mailto:fpatel&#64;opensourceintegrators.com">fpatel&#64;opensourceintegrators.com</a>&gt;</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">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_line_exclude">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,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import test_sale_timesheet_line_exclude

View file

@ -0,0 +1,342 @@
# Copyright 2018-2019 Brainbean Apps (https://brainbeanapps.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.exceptions import ValidationError
from odoo.tests import common
class TestSaleTimesheetLineExclude(common.TransactionCase):
def setUp(self):
super().setUp()
self.uom_hour = self.env.ref("uom.product_uom_hour")
self.Partner = self.env["res.partner"]
self.SudoPartner = self.Partner.sudo()
self.Employee = self.env["hr.employee"]
self.SudoEmployee = self.Employee.sudo()
self.AccountAccount = self.env["account.account"]
self.AccountAccountPlan = self.env["account.analytic.plan"]
self.SudoAccountAccount = self.AccountAccount.sudo()
self.Project = self.env["project.project"]
self.SudoProject = self.Project.sudo()
self.ProjectTask = self.env["project.task"]
self.SudoProjectTask = self.ProjectTask.sudo()
self.AccountAnalyticLine = self.env["account.analytic.line"]
self.SudoAccountAnalyticLine = self.AccountAnalyticLine.sudo()
self.ProductProduct = self.env["product.product"]
self.SudoProductProduct = self.ProductProduct.sudo()
self.SaleOrder = self.env["sale.order"]
self.SudoSaleOrder = self.SaleOrder.sudo()
self.SaleOrderLine = self.env["sale.order.line"]
self.SudoSaleOrderLine = self.SaleOrderLine.sudo()
self.ProjectCreateSaleOrder = self.env["project.create.sale.order"]
self.analytic_plan = self.AccountAccountPlan.create(
{
"name": "Plan Test",
"company_id": False,
}
)
self.analytic_account_sale = self.env["account.analytic.account"].create(
{
"name": "Project for selling timesheet - AA",
"code": "AA-20300",
"company_id": self.env.company.id,
"plan_id": self.analytic_plan.id,
}
)
self.account = self.SudoAccountAccount.create(
{
"code": "TEST1",
"name": "Sales #1",
"reconcile": True,
"account_type": "expense_direct_cost",
}
)
self.project = self.SudoProject.create(
{
"name": "Project #1",
"allow_timesheets": True,
"analytic_account_id": self.analytic_account_sale.id,
"allow_billable": True,
}
)
self.product = self.SudoProductProduct.create(
{
"name": "Service #1",
"standard_price": 30,
"list_price": 90,
"type": "service",
"invoice_policy": "delivery",
"uom_id": self.uom_hour.id,
"uom_po_id": self.uom_hour.id,
"default_code": "CODE-1",
"service_type": "timesheet",
"service_tracking": "task_global_project",
"project_id": self.project.id,
"taxes_id": False,
"property_account_income_id": self.account.id,
}
)
self.employee = self.SudoEmployee.create(
{"name": "Employee #1", "hourly_cost": 42}
)
self.account_payable = self.SudoAccountAccount.create(
{
"code": "AP4",
"name": "Payable #1",
"account_type": "liability_payable",
"reconcile": True,
}
)
self.account_receivable = self.SudoAccountAccount.create(
{
"code": "AR1",
"name": "Receivable #1",
"account_type": "asset_receivable",
"reconcile": True,
}
)
self.partner = self.SudoPartner.create(
{
"name": "Partner #1",
"email": "partner1@localhost",
"property_account_payable_id": self.account_payable.id,
"property_account_receivable_id": self.account_receivable.id,
}
)
self.sale_order = self.SudoSaleOrder.create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
}
)
self.sale_order_line = self.SudoSaleOrderLine.create(
{
"order_id": self.sale_order.id,
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 2,
"product_uom": self.uom_hour.id,
"price_unit": self.product.list_price,
}
)
self.sale_order.action_confirm()
self.task = self.SudoProjectTask.search(
[("sale_line_id", "=", self.sale_order_line.id)]
)
def test_create_without_exclude_from_sale_order(self):
timesheet = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertEqual(timesheet.timesheet_invoice_type, "billable_time")
self.assertEqual(self.sale_order_line.qty_delivered, 1)
self.assertEqual(self.sale_order_line.qty_to_invoice, 1)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
def test_create_with_exclude_from_sale_order(self):
timesheet = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"exclude_from_sale_order": True,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertEqual(timesheet.timesheet_invoice_type, "non_billable")
self.assertEqual(self.sale_order_line.qty_delivered, 0)
self.assertEqual(self.sale_order_line.qty_to_invoice, 0)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
def test_write_exclude_from_sale_order(self):
timesheet = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"exclude_from_sale_order": False,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertTrue(timesheet.so_line)
timesheet.write({"exclude_from_sale_order": True})
self.assertFalse(timesheet.so_line)
self.assertEqual(timesheet.timesheet_invoice_type, "non_billable")
self.assertEqual(self.sale_order_line.qty_delivered, 0)
self.assertEqual(self.sale_order_line.qty_to_invoice, 0)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
def test_write_remove_exclude_from_sale_order(self):
timesheet = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"exclude_from_sale_order": True,
"account_id": self.project.analytic_account_id.id,
}
)
timesheet.write({"exclude_from_sale_order": False})
self.assertTrue(timesheet.so_line)
self.assertEqual(timesheet.timesheet_invoice_type, "billable_time")
self.assertEqual(self.sale_order_line.qty_delivered, 1)
self.assertEqual(self.sale_order_line.qty_to_invoice, 1)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
def test_create_invoice(self):
timesheet1 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"account_id": self.project.analytic_account_id.id,
}
)
timesheet2 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"exclude_from_sale_order": True,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertEqual(timesheet1.timesheet_invoice_type, "billable_time")
self.assertEqual(timesheet2.timesheet_invoice_type, "non_billable")
self.assertEqual(self.sale_order_line.qty_delivered, 1)
self.assertEqual(self.sale_order_line.qty_to_invoice, 1)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
self.sale_order._create_invoices()
self.assertTrue(timesheet1.timesheet_invoice_id)
self.assertEqual(self.sale_order_line.qty_delivered, 1)
self.assertEqual(self.sale_order_line.qty_to_invoice, 0)
self.assertEqual(self.sale_order_line.qty_invoiced, 1)
def test_write_invoiced(self):
timesheet1 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"account_id": self.project.analytic_account_id.id,
}
)
timesheet2 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"exclude_from_sale_order": True,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertEqual(timesheet1.timesheet_invoice_type, "billable_time")
self.assertEqual(timesheet2.timesheet_invoice_type, "non_billable")
self.assertEqual(self.sale_order_line.qty_delivered, 1)
self.assertEqual(self.sale_order_line.qty_to_invoice, 1)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
self.sale_order._create_invoices()
self.assertTrue(timesheet1.timesheet_invoice_id)
self.assertEqual(self.sale_order_line.qty_delivered, 1)
self.assertEqual(self.sale_order_line.qty_to_invoice, 0)
self.assertEqual(self.sale_order_line.qty_invoiced, 1)
with self.assertRaises(ValidationError):
timesheet1.write({"exclude_from_sale_order": True})
def test_1(self):
timesheet1 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-1",
"unit_amount": 1,
"employee_id": self.employee.id,
"account_id": self.project.analytic_account_id.id,
}
)
timesheet2 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-2",
"unit_amount": 1,
"employee_id": self.employee.id,
"exclude_from_sale_order": False,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertEqual(timesheet1.timesheet_invoice_type, "billable_time")
self.assertEqual(timesheet2.timesheet_invoice_type, "billable_time")
self.assertEqual(self.sale_order_line.qty_delivered, 2)
self.assertEqual(self.sale_order_line.qty_to_invoice, 2)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
timesheet3 = self.SudoAccountAnalyticLine.create(
{
"project_id": self.task.project_id.id,
"task_id": self.task.id,
"name": "Entry #1-3",
"unit_amount": 1,
"employee_id": self.employee.id,
"account_id": self.project.analytic_account_id.id,
}
)
self.assertEqual(timesheet3.timesheet_invoice_type, "billable_time")
self.assertTrue(timesheet3.so_line)
self.assertEqual(self.sale_order_line.qty_delivered, 3)
self.assertEqual(self.sale_order_line.qty_to_invoice, 3)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
self.assertEqual(timesheet1.timesheet_invoice_type, "billable_time")
self.assertTrue(timesheet1.so_line)
timesheet2.write({"exclude_from_sale_order": True})
self.assertEqual(timesheet2.timesheet_invoice_type, "non_billable")
self.assertFalse(timesheet2.so_line)
self.assertEqual(self.sale_order_line.qty_delivered, 2)
self.assertEqual(self.sale_order_line.qty_to_invoice, 2)
self.assertEqual(self.sale_order_line.qty_invoiced, 0)
self.assertFalse(timesheet1.timesheet_invoice_id)
self.sale_order._create_invoices()
self.assertTrue(timesheet1.timesheet_invoice_id)
self.assertEqual(self.sale_order_line.qty_delivered, 2)
self.assertEqual(self.sale_order_line.qty_to_invoice, 0)
self.assertEqual(self.sale_order_line.qty_invoiced, 2)
with self.assertRaises(ValidationError):
timesheet1.write({"exclude_from_sale_order": True})

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--
Copyright 2018-2019 Brainbean Apps
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-->
<record id="hr_timesheet_line_tree" model="ir.ui.view">
<field name="name">account.analytic.line.tree</field>
<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='task_id']" position="after">
<field name="exclude_from_sale_order" optional="show" />
</xpath>
</field>
</record>
<record id="account_analytic_line_search" model="ir.ui.view">
<field name="name">account.analytic.line.search</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="sale_timesheet.timesheet_view_search" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="exclude_from_sale_order" />
</field>
<filter name="non_billable" position="after">
<filter
name="excluded_from_sale_order"
string="Excluded From Sale Order"
domain="[('exclude_from_sale_order', '=', True)]"
/>
</filter>
</field>
</record>
</odoo>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--
Copyright 2018-2019 Brainbean Apps (https://brainbeanapps.com)
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-->
<record id="project_task_view_form_inherit_sale_timesheet" model="ir.ui.view">
<field name="name">project.task.form.inherit.timesheet</field>
<field name="model">project.task</field>
<field
name="inherit_id"
ref="sale_timesheet.project_task_view_form_inherit_sale_timesheet"
/>
<field name="arch" type="xml">
<xpath
expr="//field[@name='timesheet_ids']/tree/field[@name='so_line']"
position="before"
>
<field name="exclude_from_sale_order" />
</xpath>
</field>
</record>
</odoo>