Initial commit: OCA Technical packages (595 packages)

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

View file

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

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Hr_expense_invoice Module - hr_expense_invoice
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 hr_expense_invoice. 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:
- [hr_expense](../../odoo-bringout-oca-ocb-hr_expense)

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

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-hr-expense-hr_expense_invoice"
# or
uv pip install odoo-bringout-oca-hr-expense-hr_expense_invoice"
```

View file

@ -0,0 +1,15 @@
# Models
Detected core models and extensions in hr_expense_invoice.
```mermaid
classDiagram
class account_move
class account_move_line
class hr_expense
class hr_expense_sheet
```
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: hr_expense_invoice. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon hr_expense_invoice
- 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 hr_expense_invoice
```

View file

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

View file

@ -0,0 +1,117 @@
================================
Supplier invoices on HR expenses
================================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8fc733402c14a85ff1cc83cdcbb61bbd05755df61c13a34391bf929a9a1727a3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fhr--expense-lightgray.png?logo=github
:target: https://github.com/OCA/hr-expense/tree/16.0/hr_expense_invoice
:alt: OCA/hr-expense
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/hr-expense-16-0/hr-expense-16-0-hr_expense_invoice
: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/hr-expense&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module should be used when a supplier invoice is paid by an employee. It
allows to set a supplier invoice for each expense line, adding the
corresponding journal items to transfer the debt to the employee.
There are 2 ways to reference expense to invoice.
1. On expense, directly select one invoice.
2. On expense report, use button "Create Vendor Bill" to create one invoice
for multiple expenses.
**Table of contents**
.. contents::
:local:
Usage
=====
**Reference one invoice to an expense**
* Create an expense sheet.
* Add an expense line to sheet with an invoice_id selected or create one new.
* Process expense sheet.
* On paying expense sheet, you are reconciling supplier invoice too.
**Create one invoice to multiple expenses**
* Create an expense sheet with one or multiple expense lines
* After approved, click button "Create Vendor Bill"
* Select multiple expense to create an invoice, and process it.
* New invoice will be create and link to the selected expense lines.
* Validate newly create invoice.
* On paying expense sheet, you are reconciling supplier invoice(s) too.
Known issues / Roadmap
======================
* Multiple payment terms for a supplier invoice are not handled correctly.
* Partial reconcile supplier invoices are also not correctly handled.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/hr-expense/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/hr-expense/issues/new?body=module:%20hr_expense_invoice%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
* Vicent Cubells
* Víctor Martínez
* Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
* Rattapong Chokmasermkul <rattapongc@ecosoft.co.th>
* Saran Lim. <saranl@ecosoft.co.th>
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/hr-expense <https://github.com/OCA/hr-expense/tree/16.0/hr_expense_invoice>`_ 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 (http://www.gnu.org/licenses/agpl).
from . import models

View file

@ -0,0 +1,18 @@
# Copyright 2015-2021 Tecnativa - Pedro M. Baeza
# Copyright 2017 Tecnativa - Vicent Cubells
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Supplier invoices on HR expenses",
"version": "16.0.2.0.3",
"category": "Human Resources",
"author": "Tecnativa, Odoo Community Association (OCA)",
"license": "AGPL-3",
"website": "https://github.com/OCA/hr-expense",
"depends": ["hr_expense"],
"data": [
"views/account_move_views.xml",
"views/hr_expense_views.xml",
],
"installable": True,
}

View file

@ -0,0 +1,121 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
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: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr "<span>Trošak</span>"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr "Kreiraj račun dobavljača"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Trošak"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Izvještaj troškova"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
msgid "Expenses"
msgstr "Trošak"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr "Račun"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr "Račun"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr "Žurnal"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr "Stavka žurnala"
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr "Status izvještaja"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr "Trošak izvornog računa"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr "Stavka transfera"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr "Ulazni račun"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr "Status računa dobavljača mora biti Knjižen"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,129 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
# Translators:
# Lukáš Spurný <lukasspurny8@gmail.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-23 03:45+0000\n"
"PO-Revision-Date: 2018-02-23 03:45+0000\n"
"Last-Translator: Lukáš Spurný <lukasspurny8@gmail.com>, 2018\n"
"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/"
"teams/23907/cs_CZ/)\n"
"Language: cs_CZ\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Výdaje"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Zpráva o výdajích"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
#, fuzzy
msgid "Expenses"
msgstr "Výdaje"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
#, fuzzy
msgid "Invoice Count"
msgstr "Faktura"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, fuzzy, python-format
msgid "Invoices"
msgstr "Faktura"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,127 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-07-12 14: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: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, fuzzy
msgid "Create Vendor Bill"
msgstr "Lieferantenrechnung"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Spesen"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Spesen-Bericht"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
#, fuzzy
msgid "Expenses"
msgstr "Spesen"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
#, fuzzy
msgid "Invoice Count"
msgstr "Rechnung"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, fuzzy, python-format
msgid "Invoices"
msgstr "Rechnung"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr "Lieferantenrechnung"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,140 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-27 16:34+0000\n"
"PO-Revision-Date: 2023-10-29 23:38+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr "Crear Factura de Vendedor"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Gasto"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Informe de gastos"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
msgid "Expenses"
msgstr "Gastos"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr "Conteo de Factura"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr "Facturas"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr "Entrada Diaria"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr "Estado de la hoja"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr "Factura de Proveedor"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
"El importe de la factura del proveedor no coincide.\n"
"Asegúrese de que el importe de la factura del proveedor coincide con el "
"importe de sus líneas de gasto"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr "Debe publicarse el estado de la factura del proveedor"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""
"No puede modificar el importe total, ya que hay un gasto vinculado a esta "
"factura."
#~ msgid "Expense Report State"
#~ msgstr "Estado del Informe de Gastos"
#~ msgid "Register Payment"
#~ msgstr "Registrar Pago"
#, python-format
#~ msgid "Register payment on expense's invoice is not allowed"
#~ msgstr "No se permite registrar el pago en la factura del gasto"

View file

@ -0,0 +1,129 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
# Translators:
# guillaume bauer <guillaume.bauer@syentys.com>, 2017
# Alexandre Fayolle <alexandre.fayolle@camptocamp.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-23 03:45+0000\n"
"PO-Revision-Date: 2018-02-23 03:45+0000\n"
"Last-Translator: Alexandre Fayolle <alexandre.fayolle@camptocamp.com>, 2018\n"
"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\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"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Note de frais"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Rapport de dépenses"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
#, fuzzy
msgid "Expenses"
msgstr "Note de frais"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
#, fuzzy
msgid "Invoice Count"
msgstr "Facture"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, fuzzy, python-format
msgid "Invoices"
msgstr "Facture"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,129 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
# Translators:
# Bole <bole@dajmi5.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-23 03:45+0000\n"
"PO-Revision-Date: 2018-02-23 03:45+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>, 2017\n"
"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Trošak"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Izvještaj troškova"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
#, fuzzy
msgid "Expenses"
msgstr "Trošak"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
#, fuzzy
msgid "Invoice Count"
msgstr "Račun"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, fuzzy, python-format
msgid "Invoices"
msgstr "Račun"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,121 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
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: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
msgid "Expenses"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,141 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-05-30 13:38+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr "<span>Spesa</span>"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr "Crea una fattura fornitore"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Spesa"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Nota spese"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
msgid "Expenses"
msgstr "Spese"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr "Numero fatture"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr "Fatture"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr "Registrazione contabile"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr "Movimento contabile"
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
"Riferimento alla spesa con una fattura collegata che ha generato questa "
"registrazione contabile del trasferimento"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr "Stato prospetto"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr "Fattura spesa origine"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr "Movimento di trasferimento"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr "Fattura fornitore"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
"Differenza fattura fornitore!\n"
"Assicurarsi che il valore nel conto del fornitore sia pari al valore delle "
"righe di spesa"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr "Lo stato del conto fornitore deve essere Inviato"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""
"Non si può cambiare il valore totale, perché c'è una spesa collegata a "
"questa fattura."
#~ msgid "Expense Report State"
#~ msgstr "Stato nota spese"
#~ msgid "Register Payment"
#~ msgstr "Registra pagamento"
#, python-format
#~ msgid "Register payment on expense's invoice is not allowed"
#~ msgstr "Non è consentito registrare il pagamento sulla fattura delle spese"

View file

@ -0,0 +1,128 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
# Translators:
# Peter Hageman <hageman.p@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-11-28 01:43+0000\n"
"PO-Revision-Date: 2017-11-28 01:43+0000\n"
"Last-Translator: Peter Hageman <hageman.p@gmail.com>, 2017\n"
"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/"
"teams/23907/nl_NL/)\n"
"Language: nl_NL\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"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr ""
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Onkostennota"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
#, fuzzy
msgid "Expenses"
msgstr "Onkostennota"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr ""
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr ""
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""

View file

@ -0,0 +1,130 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-15 18:19+0000\n"
"Last-Translator: Peter Romão <peterromao@yahoo.co.uk>\n"
"Language-Team: none\n"
"Language: pt\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: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr "<span>Despesa</span>"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr "Criar Fatura de Fornecedor"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Despesa"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Relatório de Despesas"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
msgid "Expenses"
msgstr "Despesas"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr "Número de Faturas"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr "Faturas"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr "Lançamento de Diário"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr "Item de Diário"
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
"Referência à despesa com fatura vinculada que gerou este lançamento em diário"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr "Estado da folha"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr "Fatura de Despesa de Origem"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr "Movimento de Transferência"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr "Fatura de Fornecedor"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
"Divergência no valor da fatura\n"
"Por favor, assegure-se de que o valor nas faturas de fornecedor são iguais "
"às suas linhas de despesa"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr "O estado da fatura de fornecedor tem de ser Publicado"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""
"Não pode alterar o valor total dado que já existe uma despesa vinculada a "
"esta fatura."

View file

@ -0,0 +1,130 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_invoice
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-10 15:25+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: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.view_move_form
msgid "<span>Expense</span>"
msgstr "<span>Masraf</span>"
#. module: hr_expense_invoice
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
msgid "Create Vendor Bill"
msgstr "Tedarikçi Faturası Oluşturun"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense
msgid "Expense"
msgstr "Masraf"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Masraf Formu"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__expense_ids
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__expense_ids
msgid "Expenses"
msgstr "Masraflar"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense_sheet__invoice_count
msgid "Invoice Count"
msgstr "Fatura Sayısı"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#: model_terms:ir.ui.view,arch_db:hr_expense_invoice.hr_expense_sheet_form_view_inherit_sale_expense
#, python-format
msgid "Invoices"
msgstr "Faturalar"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move
msgid "Journal Entry"
msgstr "Yevmiye Kaydı"
#. module: hr_expense_invoice
#: model:ir.model,name:hr_expense_invoice.model_account_move_line
msgid "Journal Item"
msgstr "Yevmiye Kalemi"
#. module: hr_expense_invoice
#: model:ir.model.fields,help:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,help:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid ""
"Reference to the expense with a linked invoice that generated thistransfer "
"journal entry"
msgstr ""
"Bu transfer yevmiye kaydını oluşturan bağlantılı faturaya sahip gidere "
"referans"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__sheet_id_state
msgid "Sheet state"
msgstr "Çizelge Durumu"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_bank_statement_line__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_move__source_invoice_expense_id
#: model:ir.model.fields,field_description:hr_expense_invoice.field_account_payment__source_invoice_expense_id
msgid "Source Invoice Expense"
msgstr "Kaynak Fatura Masrafı"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__transfer_move_ids
msgid "Transfer Move"
msgstr "Transfer Hareketi"
#. module: hr_expense_invoice
#: model:ir.model.fields,field_description:hr_expense_invoice.field_hr_expense__invoice_id
msgid "Vendor Bill"
msgstr "Tedarikçi Faturası"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid ""
"Vendor bill amount mismatch!\n"
"Please make sure amount in vendor bills equal to amount of its expense lines"
msgstr ""
"Tedarikçi faturası tutarı uyuşmuyor!\n"
"Lütfen tedarikçi faturalarındaki tutarın, masraf kalemlerindeki tutara eşit "
"olduğundan emin olun"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/hr_expense.py:0
#: code:addons/hr_expense_invoice/models/hr_expense_sheet.py:0
#, python-format
msgid "Vendor bill state must be Posted"
msgstr "Tedarikçi faturası durumu Gönderilmiş olmalıdır"
#. module: hr_expense_invoice
#. odoo-python
#: code:addons/hr_expense_invoice/models/account_move.py:0
#, python-format
msgid ""
"You can't change the total amount, as there's an expense linked to this "
"invoice."
msgstr ""
"Bu faturaya bağlı bir masraf olduğundan toplam tutarı değiştiremezsiniz."

View file

@ -0,0 +1,5 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import hr_expense
from . import hr_expense_sheet
from . import account_move

View file

@ -0,0 +1,77 @@
# Copyright 2019 Ecosoft <saranl@ecosoft.co.th>
# Copyright 2021 Tecnativa - Víctor Martínez
# Copyright 2024 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools import float_compare
class AccountMove(models.Model):
_inherit = "account.move"
expense_ids = fields.One2many(
comodel_name="hr.expense", inverse_name="invoice_id", string="Expenses"
)
source_invoice_expense_id = fields.Many2one(
comodel_name="hr.expense",
help="Reference to the expense with a linked invoice that generated this"
"transfer journal entry",
)
def write(self, vals):
# Check if the amount of the invoice linked to an invoice is different
# Done here in the write instead of a Python constraint as the computed field
# amount_total is not yet updated on that moment
res = super().write(vals)
# Only need to check expenses amount when the invoice amount changes
if not ("amount_total" in vals or "tax_totals" in vals):
return res
DecimalPrecision = self.env["decimal.precision"]
precision = DecimalPrecision.precision_get("Product Price")
for move in self.filtered("expense_ids"):
expense_amount = sum(move.expense_ids.mapped("total_amount"))
if float_compare(expense_amount, move.amount_total, precision) != 0:
raise ValidationError(
_(
"You can't change the total amount, as there's an expense "
"linked to this invoice."
)
)
return res
def action_view_expense(self):
self.ensure_one()
return {
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "hr.expense",
"res_id": self.expense_ids[:1].id,
}
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
@api.constrains("account_id", "display_type")
def _check_payable_receivable(self):
_self = self.filtered("expense_id")
return super(AccountMoveLine, (self - _self))._check_payable_receivable()
def reconcile(self):
"""Mark expenses paid by employee having invoice when reconciling them."""
expenses = self.move_id.source_invoice_expense_id
not_paid_expenses = expenses.filtered(lambda x: x.state != "done")
res = super().reconcile()
not_paid_expense_sheets = not_paid_expenses.sheet_id.filtered(
lambda x: x.state != "done"
)
paid_expenses = not_paid_expenses.filtered(
lambda expense: expense.currency_id.is_zero(expense.amount_residual)
)
paid_expenses.write({"state": "done"})
paid_sheets = not_paid_expense_sheets.filtered(
lambda x: all(expense.state == "done" for expense in x.expense_line_ids)
)
paid_sheets.set_to_paid()
return res

View file

@ -0,0 +1,210 @@
# Copyright 2017 Tecnativa - Vicent Cubells
# Copyright 2020 Tecnativa - David Vidal
# Copyright 2021 Tecnativa - Víctor Martínez
# Copyright 2015-2024 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import Command, _, api, fields, models
from odoo.exceptions import UserError
class HrExpense(models.Model):
_inherit = "hr.expense"
sheet_id_state = fields.Selection(related="sheet_id.state", string="Sheet state")
invoice_id = fields.Many2one(
comodel_name="account.move",
string="Vendor Bill",
domain=[
("move_type", "=", "in_invoice"),
("state", "=", "posted"),
("payment_state", "=", "not_paid"),
("expense_ids", "=", False),
],
copy=False,
)
transfer_move_ids = fields.One2many(
comodel_name="account.move",
inverse_name="source_invoice_expense_id",
)
def _prepare_invoice_values(self):
invoice_lines = [
(
0,
0,
{
"product_id": self.product_id.id,
"name": self.name,
"price_unit": self.untaxed_amount,
"quantity": self.quantity,
"account_id": self.account_id.id,
"analytic_distribution": self.analytic_distribution,
"tax_ids": [(6, 0, self.tax_ids.ids)],
},
)
]
return {
"name": "/",
"ref": self.reference,
"move_type": "in_invoice",
"invoice_date": self.date,
"invoice_line_ids": invoice_lines,
}
def action_move_create(self):
"""Don't let super to create any move:
- Paid by company: there's already the invoice.
- Paid by employee: we create here a journal entry transferring the AP
balance from the invoice partner to the employee.
"""
expenses_with_invoice = self.filtered("invoice_id")
res = super(HrExpense, self - expenses_with_invoice).action_move_create()
# Create AP transfer entry for expenses paid by employees
for expense in expenses_with_invoice:
if expense.payment_mode == "own_account":
move = self.env["account.move"].create(
expense._prepare_own_account_transfer_move_vals()
)
move.action_post()
# reconcile with the invoice
ap_lines = expense.invoice_id.line_ids.filtered(
lambda x: x.display_type == "payment_term"
)
transfer_line = move.line_ids.filtered(
lambda x: x.partner_id == self.invoice_id.partner_id
)
(ap_lines + transfer_line).reconcile()
return res
def _prepare_own_account_transfer_move_vals(self):
self.ensure_one()
self = self.with_company(self.company_id)
# TODO: Allow to select a specific journal
journal = self.env["account.journal"].search(
[
("company_id", "=", self.company_id.id),
("type", "=", "general"),
],
limit=1,
)
employee_partner = self.employee_id.sudo().address_home_id.commercial_partner_id
invoice_partner = self.invoice_id.partner_id
ap_lines = self.invoice_id.line_ids.filtered(
lambda x: x.display_type == "payment_term"
)
amount_invoice = sum(ap_lines.mapped("credit"))
return {
"journal_id": journal.id,
"move_type": "entry",
"name": "/",
"date": self.date,
"ref": self.name,
"source_invoice_expense_id": self.id,
"line_ids": [
Command.create(
{
"account_id": ap_lines.account_id[:1].id,
"partner_id": invoice_partner.id,
"debit": amount_invoice,
}
),
Command.create(
{
"account_id": employee_partner.property_account_payable_id.id,
"partner_id": employee_partner.id,
"credit": amount_invoice,
}
),
],
}
def action_expense_create_invoice(self):
invoice = self.env["account.move"].create(self._prepare_invoice_values())
attachments = self.env["ir.attachment"].search(
[("res_model", "=", self._name), ("res_id", "in", self.ids)]
)
for attachment in attachments:
attachment.copy({"res_model": invoice._name, "res_id": invoice.id})
# Normalize data in the expense for avoiding mismatchings. Examples: the tax
# reported is not correct, there's more than one concept, etc...
self.write(
{
"invoice_id": invoice.id,
"quantity": 1,
"tax_ids": False,
"unit_amount": invoice.amount_total,
}
)
return True
@api.constrains("invoice_id")
def _check_invoice_id(self):
for expense in self: # Only non binding expense
if (
not expense.sheet_id
and expense.invoice_id
and expense.invoice_id.state != "posted"
):
raise UserError(_("Vendor bill state must be Posted"))
@api.onchange("invoice_id")
def _onchange_invoice_id(self):
"""Assure quantity is 1 if an invoice is set for having proper totals, and
the rest of the fields that are not computed writable, avoiding to ud
"""
if self.invoice_id:
self.quantity = 1
self.reference = self.invoice_id.name
self.date = self.invoice_id.date
if self.invoice_id.company_id != self.company_id:
# for avoiding to trigger dependent computes
self.company_id = self.invoice_id.company_id.id
# tax_ids put as dependency for assuring this is computed after setting tax_ids
@api.depends("invoice_id", "tax_ids")
def _compute_unit_amount(self):
with_invoice = self.filtered("invoice_id")
for record in with_invoice:
record.unit_amount = record.invoice_id.amount_total
return super(HrExpense, self - with_invoice)._compute_unit_amount()
# tax_ids put as dependency for assuring this is computed after setting tax_ids
@api.depends("invoice_id", "tax_ids")
def _compute_amount(self):
with_invoice = self.filtered("invoice_id")
for record in with_invoice:
record.total_amount = record.invoice_id.amount_total
return super(HrExpense, self - with_invoice)._compute_amount()
@api.depends("invoice_id")
def _compute_currency_id(self):
with_invoice = self.filtered("invoice_id")
for record in with_invoice:
record.currency_id = record.invoice_id.currency_id.id
return super(HrExpense, self - with_invoice)._compute_currency_id()
@api.depends("invoice_id")
def _compute_tax_ids(self):
with_invoice = self.filtered("invoice_id")
for record in with_invoice:
record.tax_ids = [(5,)]
return super(HrExpense, self - with_invoice)._compute_tax_ids()
@api.depends(
"transfer_move_ids.line_ids.amount_residual",
"transfer_move_ids.line_ids.amount_residual_currency",
)
def _compute_amount_residual(self):
"""Compute the amount residual for expenses paid by employee with invoices."""
applicable_expenses = self.filtered(lambda x: x.transfer_move_ids)
for rec in applicable_expenses:
if not rec.currency_id or rec.currency_id == rec.company_currency_id:
residual_field = "amount_residual"
else:
residual_field = "amount_residual_currency"
payment_term_lines = rec.transfer_move_ids.sudo().line_ids.filtered(
lambda x: x.account_type in ("asset_receivable", "liability_payable")
)
rec.amount_residual = -sum(payment_term_lines.mapped(residual_field))
return super(HrExpense, self - applicable_expenses)._compute_amount_residual()

View file

@ -0,0 +1,114 @@
# Copyright 2017 Tecnativa - Vicent Cubells
# Copyright 2015-2024 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools import float_compare
class HrExpenseSheet(models.Model):
_inherit = "hr.expense.sheet"
invoice_count = fields.Integer(compute="_compute_invoice_count")
def action_sheet_move_create(self):
"""Perform extra checks and set proper state and payment state according linked
invoices.
"""
self._validate_expense_invoice()
res = super().action_sheet_move_create()
# The payment state is set in a fixed way in super, but it depends on the
# payment state of the invoices when there are some of them linked
self.filtered(
lambda x: x.expense_line_ids.invoice_id
and x.payment_mode == "company_account"
)._compute_payment_state()
return res
def set_to_paid(self):
"""Don't mark sheet as paid when reconciling invoices."""
if self.env.context.get("use_hr_expense_invoice"):
return True
return super().set_to_paid()
def _compute_invoice_count(self):
Invoice = self.env["account.move"]
can_read = Invoice.check_access_rights("read", raise_exception=False)
for sheet in self:
sheet.invoice_count = (
can_read and len(sheet.expense_line_ids.mapped("invoice_id")) or 0
)
@api.depends(
"expense_line_ids.invoice_id.payment_state",
"expense_line_ids.amount_residual",
)
def _compute_payment_state(self):
"""Determine the payment status for lines with expense invoices linked"""
invoice_sheets = self.filtered(lambda x: x.expense_line_ids.invoice_id)
invoice_sheets.payment_state = "not_paid"
for sheet in invoice_sheets:
lines = sheet.expense_line_ids
lines_with_invoices = len(lines.filtered("invoice_id"))
if sheet.payment_mode == "company_account":
lines_with_paid_invoices = len(
lines.filtered(lambda x: x.invoice_id.payment_state == "paid")
)
lines_with_partial_invoices = len(
lines.filtered(lambda x: x.invoice_id.payment_state == "partial")
)
else:
lines_with_paid_invoices = len(
lines.filtered(
lambda x: x.transfer_move_ids and x.amount_residual == 0
)
)
lines_with_partial_invoices = 0 # TODO: Consider partial reconciliation
if lines_with_invoices == lines_with_paid_invoices:
sheet.payment_state = "paid"
elif lines_with_paid_invoices or lines_with_partial_invoices:
sheet.payment_state = "partial"
return super(HrExpenseSheet, self - invoice_sheets)._compute_payment_state()
def _validate_expense_invoice(self):
"""Check several criteria that needs to be met for creating the move."""
expense_lines = self.mapped("expense_line_ids").filtered("invoice_id")
DecimalPrecision = self.env["decimal.precision"]
precision = DecimalPrecision.precision_get("Product Price")
invoices = expense_lines.mapped("invoice_id")
if not invoices:
return
# All invoices must confirmed
if any(invoices.filtered(lambda i: i.state != "posted")):
raise UserError(_("Vendor bill state must be Posted"))
expense_amount = sum(expense_lines.mapped("total_amount"))
invoice_amount = sum(invoices.mapped("amount_total"))
# Expense amount must equal invoice amount
if float_compare(expense_amount, invoice_amount, precision) != 0:
raise UserError(
_(
"Vendor bill amount mismatch!\nPlease make sure amount in "
"vendor bills equal to amount of its expense lines"
)
)
def action_view_invoices(self):
self.ensure_one()
action = {
"name": _("Invoices"),
"type": "ir.actions.act_window",
"res_model": "account.move",
"target": "current",
}
invoice_ids = self.expense_line_ids.mapped("invoice_id").ids
view = self.env.ref("account.view_move_form")
if len(invoice_ids) == 1:
invoice = invoice_ids[0]
action["res_id"] = invoice
action["view_mode"] = "form"
action["views"] = [(view.id, "form")]
else:
action["view_mode"] = "tree,form"
action["domain"] = [("id", "in", invoice_ids)]
return action

View file

@ -0,0 +1,9 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Vicent Cubells
* Víctor Martínez
* Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
* Rattapong Chokmasermkul <rattapongc@ecosoft.co.th>
* Saran Lim. <saranl@ecosoft.co.th>

View file

@ -0,0 +1,9 @@
This module should be used when a supplier invoice is paid by an employee. It
allows to set a supplier invoice for each expense line, adding the
corresponding journal items to transfer the debt to the employee.
There are 2 ways to reference expense to invoice.
1. On expense, directly select one invoice.
2. On expense report, use button "Create Vendor Bill" to create one invoice
for multiple expenses.

View file

@ -0,0 +1,2 @@
* Multiple payment terms for a supplier invoice are not handled correctly.
* Partial reconcile supplier invoices are also not correctly handled.

View file

@ -0,0 +1,15 @@
**Reference one invoice to an expense**
* Create an expense sheet.
* Add an expense line to sheet with an invoice_id selected or create one new.
* Process expense sheet.
* On paying expense sheet, you are reconciling supplier invoice too.
**Create one invoice to multiple expenses**
* Create an expense sheet with one or multiple expense lines
* After approved, click button "Create Vendor Bill"
* Select multiple expense to create an invoice, and process it.
* New invoice will be create and link to the selected expense lines.
* Validate newly create invoice.
* On paying expense sheet, you are reconciling supplier invoice(s) too.

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,467 @@
<!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>Supplier invoices on HR expenses</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="supplier-invoices-on-hr-expenses">
<h1 class="title">Supplier invoices on HR expenses</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8fc733402c14a85ff1cc83cdcbb61bbd05755df61c13a34391bf929a9a1727a3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/hr-expense/tree/16.0/hr_expense_invoice"><img alt="OCA/hr-expense" src="https://img.shields.io/badge/github-OCA%2Fhr--expense-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/hr-expense-16-0/hr-expense-16-0-hr_expense_invoice"><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/hr-expense&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 should be used when a supplier invoice is paid by an employee. It
allows to set a supplier invoice for each expense line, adding the
corresponding journal items to transfer the debt to the employee.</p>
<p>There are 2 ways to reference expense to invoice.</p>
<ol class="arabic simple">
<li>On expense, directly select one invoice.</li>
<li>On expense report, use button “Create Vendor Bill” to create one invoice
for multiple expenses.</li>
</ol>
<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>
<p><strong>Reference one invoice to an expense</strong></p>
<ul class="simple">
<li>Create an expense sheet.</li>
<li>Add an expense line to sheet with an invoice_id selected or create one new.</li>
<li>Process expense sheet.</li>
<li>On paying expense sheet, you are reconciling supplier invoice too.</li>
</ul>
<p><strong>Create one invoice to multiple expenses</strong></p>
<ul class="simple">
<li>Create an expense sheet with one or multiple expense lines</li>
<li>After approved, click button “Create Vendor Bill”</li>
<li>Select multiple expense to create an invoice, and process it.</li>
<li>New invoice will be create and link to the selected expense lines.</li>
<li>Validate newly create invoice.</li>
<li>On paying expense sheet, you are reconciling supplier invoice(s) too.</li>
</ul>
</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>Multiple payment terms for a supplier invoice are not handled correctly.</li>
<li>Partial reconcile supplier invoices are also not correctly handled.</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/hr-expense/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/hr-expense/issues/new?body=module:%20hr_expense_invoice%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 class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
<li>Vicent Cubells</li>
<li>Víctor Martínez</li>
</ul>
</li>
<li>Kitti Upariphutthiphong &lt;<a class="reference external" href="mailto:kittiu&#64;ecosoft.co.th">kittiu&#64;ecosoft.co.th</a>&gt;</li>
<li>Rattapong Chokmasermkul &lt;<a class="reference external" href="mailto:rattapongc&#64;ecosoft.co.th">rattapongc&#64;ecosoft.co.th</a>&gt;</li>
<li>Saran Lim. &lt;<a class="reference external" href="mailto:saranl&#64;ecosoft.co.th">saranl&#64;ecosoft.co.th</a>&gt;</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/hr-expense/tree/16.0/hr_expense_invoice">OCA/hr-expense</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 @@
from . import test_hr_expense_invoice

View file

@ -0,0 +1,245 @@
# Copyright 2017 Tecnativa - Vicent Cubells
# Copyright 2021 Tecnativa - Pedro M. Baeza
# Copyright 2021-2023 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import base64
from odoo import fields
from odoo.exceptions import UserError, ValidationError
from odoo.tests import tagged
from odoo.tests.common import Form
from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
@tagged("post_install", "-at_install")
class TestHrExpenseInvoice(TestExpenseCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT))
cls.account_payment_register = cls.env["account.payment.register"]
cls.payment_obj = cls.env["account.payment"]
cls.cash_journal = cls.company_data["default_journal_cash"]
cls.company_data["company"].account_sale_tax_id = False
cls.company_data["company"].account_purchase_tax_id = False
cls.product_a.supplier_taxes_id = False
cls.invoice = cls.init_invoice(
"in_invoice",
products=[cls.product_a],
)
cls.invoice.invoice_line_ids.price_unit = 100
cls.invoice2 = cls.invoice.copy(
{
"invoice_date": fields.Date.today(),
}
)
cls.expense = cls.env["hr.expense"].create(
{
"name": "Expense test",
"employee_id": cls.expense_employee.id,
"product_id": cls.product_a.id,
"unit_amount": 50.00,
}
)
cls._create_attachment(cls, cls.expense._name, cls.expense.id)
cls.expense2 = cls.expense.copy()
cls._create_attachment(cls, cls.expense2._name, cls.expense2.id)
cls.expense3 = cls.expense.copy()
cls._create_attachment(cls, cls.expense3._name, cls.expense3.id)
def _invoice_register_payment(self, invoice):
res = invoice.action_register_payment()
payment_form = Form(self.env[res["res_model"]].with_context(**res["context"]))
payment_form.journal_id = self.cash_journal
return payment_form.save()
def _register_payment(self, sheet):
res = sheet.action_register_payment()
register_payment_form = Form(
self.env[res["res_model"]].with_context(**res["context"])
)
register_payment_form.journal_id = self.cash_journal
register = register_payment_form.save()
res2 = register.action_create_payments()
payment = self.env[res2["res_model"]].browse(res2["res_id"])
self.assertEqual(len(payment), 1)
self.assertEqual(sheet.payment_state, "paid")
def _create_attachment(self, res_model, res_id):
return self.env["ir.attachment"].create(
{
"name": "Test attachment %s (%s)" % (res_id, res_model),
"res_model": res_model,
"res_id": res_id,
"datas": base64.b64encode(b"\xff data"),
}
)
def _action_submit_expenses(self, expenses):
res = expenses.action_submit_expenses()
sheet_form = Form(self.env[res["res_model"]].with_context(**res["context"]))
return sheet_form.save()
def test_0_hr_tests_misc(self):
self.assertEqual(self.expense.attachment_number, 1)
self.assertEqual(self.expense2.attachment_number, 1)
self.assertEqual(self.expense3.attachment_number, 1)
def test_0_hr_test_no_invoice(self):
# We add an expense
sheet = self._action_submit_expenses(self.expense)
self.assertIn(self.expense, sheet.expense_line_ids)
self.assertAlmostEqual(self.expense.total_amount, 50.0)
# We approve sheet, no invoice
sheet.approve_expense_sheets()
self.assertEqual(sheet.state, "approve")
self.assertFalse(sheet.account_move_id)
# We post journal entries
sheet.action_sheet_move_create()
self.assertEqual(sheet.state, "post")
self.assertTrue(sheet.account_move_id)
# We make payment on expense sheet
self._register_payment(sheet)
def test_1_hr_test_invoice(self):
# We add an expense
self.expense.unit_amount = 100
sheet = self._action_submit_expenses(self.expense)
self.assertIn(self.expense, sheet.expense_line_ids)
# We add invoice to expense
self.invoice.action_post() # residual = 100
with Form(self.expense) as f:
f.invoice_id = self.invoice
# We approve sheet
sheet.approve_expense_sheets()
self.assertEqual(sheet.state, "approve")
self.assertFalse(sheet.account_move_id)
self.assertEqual(self.invoice.state, "posted")
# Test state not posted
self.invoice.button_draft()
with self.assertRaises(UserError):
sheet.action_sheet_move_create()
self.invoice.action_post()
# We post journal entries
sheet.action_sheet_move_create()
self.assertEqual(sheet.state, "post")
self.assertEqual(self.invoice.payment_state, "paid")
self.assertEqual(sheet.payment_state, "not_paid")
self.assertEqual(self.expense.amount_residual, 100)
self.assertTrue(self.expense.transfer_move_ids)
# Pay the transferred amount (through a hack using reversal)
reverse_move = self.expense.transfer_move_ids._reverse_moves(
default_values_list=[{"source_invoice_expense_id": False}] # , cancel=True
)
reverse_move.action_post()
emp_line = self.expense.transfer_move_ids.line_ids.filtered(
lambda x: x.credit > 0
)
emp_line_reversed = reverse_move.line_ids.filtered(lambda x: x.debit > 0)
(emp_line + emp_line_reversed).reconcile()
self.assertEqual(self.expense.amount_residual, 0)
self.assertEqual(sheet.payment_state, "paid")
self.assertEqual(sheet.state, "done")
# Unreconcile the payment
reverse_move.button_draft()
self.assertEqual(self.expense.amount_residual, 100)
self.assertEqual(sheet.payment_state, "not_paid")
def test_1_hr_test_invoice_paid_by_company(self):
# We add an expense
self.expense.unit_amount = 100
self.expense.payment_mode = "company_account"
sheet = self._action_submit_expenses(self.expense)
self.assertIn(self.expense, sheet.expense_line_ids)
# We add invoice to expense
self.invoice.action_post() # residual = 100.0
self.expense.invoice_id = self.invoice
# We approve sheet
sheet.approve_expense_sheets()
self.assertEqual(sheet.state, "approve")
self.assertFalse(sheet.account_move_id)
self.assertEqual(self.invoice.state, "posted")
# We post journal entries
sheet.action_sheet_move_create()
self.assertEqual(sheet.state, "done")
self.assertEqual(self.invoice.payment_state, "not_paid")
# Click on View Invoice button link to the correct invoice
res = sheet.action_view_invoices()
self.assertEqual(res["view_mode"], "form")
def test_2_hr_test_multi_invoices(self):
# We add 2 expenses
self.expense.unit_amount = 100
self.expense2.unit_amount = 100
expenses = self.expense + self.expense2
sheet = self._action_submit_expenses(expenses)
self.assertIn(self.expense, sheet.expense_line_ids)
self.assertIn(self.expense2, sheet.expense_line_ids)
# We add invoices to expenses
self.invoice.action_post()
self.invoice2.action_post()
self.expense.invoice_id = self.invoice.id
self.expense2.invoice_id = self.invoice2.id
self.assertAlmostEqual(self.expense.total_amount, 100)
self.assertAlmostEqual(self.expense2.total_amount, 100)
# We approve sheet
sheet.approve_expense_sheets()
self.assertEqual(sheet.state, "approve")
self.assertFalse(sheet.account_move_id)
self.assertEqual(self.invoice.state, "posted")
# We post journal entries
sheet.action_sheet_move_create()
self.assertEqual(sheet.state, "post")
self.assertEqual(self.invoice.payment_state, "paid")
self.assertEqual(self.invoice2.payment_state, "paid")
def test_3_hr_test_expense_create_invoice(self):
# We add 2 expenses
expenses = self.expense + self.expense2
sheet = self._action_submit_expenses(expenses)
self.assertIn(self.expense, sheet.expense_line_ids)
self.assertIn(self.expense2, sheet.expense_line_ids)
self.expense.action_expense_create_invoice()
self.assertTrue(self.expense.invoice_id)
self.assertAlmostEqual(self.expense.invoice_id.message_attachment_count, 1)
self.assertEqual(sheet.invoice_count, 1)
sheet.invalidate_recordset()
self.expense2.action_expense_create_invoice()
self.assertTrue(self.expense2.invoice_id)
self.assertAlmostEqual(self.expense2.invoice_id.message_attachment_count, 1)
self.assertEqual(sheet.invoice_count, 2)
# Only change invoice not assigned to expense yet
with self.assertRaises(ValidationError):
self.expense.invoice_id.amount_total = 60
# Force to change
invoice = self.expense2.invoice_id
self.expense2.invoice_id = False
invoice.amount_total = 50
self.assertEqual(self.expense2.total_amount, 50)
# Set invoice_id again to expense2
self.expense2.invoice_id = invoice
# Validate invoices
self.expense.invoice_id.partner_id = self.partner_a
self.expense.invoice_id.action_post()
self.expense2.invoice_id.partner_id = self.partner_a
self.expense2.invoice_id.action_post()
# We approve sheet
sheet.approve_expense_sheets()
# We post journal entries
sheet.action_sheet_move_create()
def test_4_hr_expense_constraint(self):
# Only invoice with status open is allowed
with self.assertRaises(UserError):
self.expense.write({"invoice_id": self.invoice.id})
sheet = self._action_submit_expenses(self.expense)
self.expense.invoice_id = self.invoice
self.invoice.action_post()
self.expense.total_amount = 80
# Amount must equal, expense vs invoice
with self.assertRaises(UserError):
sheet._validate_expense_invoice()
self.expense.total_amount = 100.0
sheet._validate_expense_invoice()

View file

@ -0,0 +1,22 @@
<odoo>
<record id="view_move_form" model="ir.ui.view">
<field name="name">account.move.form - Add expense smart-button</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form" />
<field name="arch" type="xml">
<div class="oe_button_box" position="inside">
<field name="expense_ids" invisible="1" />
<button
class="oe_stat_button"
icon="fa-file-text-o"
name="action_view_expense"
groups="account.group_account_invoice"
type="object"
attrs="{'invisible': [('expense_ids', '=', [])]}"
>
<span>Expense</span>
</button>
</div>
</field>
</record>
</odoo>

View file

@ -0,0 +1,156 @@
<odoo>
<record id="hr_expense_view_form" model="ir.ui.view">
<field name="name">hr.expense.form</field>
<field name="model">hr.expense</field>
<field name="inherit_id" ref="hr_expense.hr_expense_view_form" />
<field name="arch" type="xml">
<field name="unit_amount" position="attributes">
<attribute name="force_save">1</attribute>
</field>
<label for="quantity" position="attributes">
<attribute
name="attrs"
>{'invisible': [('invoice_id', '!=', False)]}</attribute>
</label>
<xpath
expr='//field[@name="quantity"]/parent::div/parent::div'
position="attributes"
>
<attribute
name="attrs"
>{'invisible': [('invoice_id', '!=', False)]}</attribute>
</xpath>
<label for="tax_ids" position="attributes">
<attribute
name="attrs"
>{'invisible': [('invoice_id', '!=', False)]}</attribute>
</label>
<xpath
expr='//field[@name="tax_ids"]/parent::div/parent::div'
position="attributes"
>
<attribute
name="attrs"
>{'invisible': [('invoice_id', '!=', False)]}</attribute>
</xpath>
<!-- Force saved to be sure they are stored when selecting the vendor bill in any state -->
<field name="quantity" position="attributes">
<attribute name="force_save">1</attribute>
</field>
<field name="reference" position="attributes">
<attribute name="force_save">1</attribute>
</field>
<field name="date" position="attributes">
<attribute name="force_save">1</attribute>
</field>
<field name="total_amount" position="attributes">
<attribute name="force_save">1</attribute>
<attribute
name="attrs"
>{'readonly': [('invoice_id', '!=', False)]}</attribute>
</field>
<xpath
expr="//field[@name='total_amount']/../field[@name='currency_id']"
position="attributes"
>
<attribute
name="attrs"
>{'readonly': [('invoice_id', '!=', False)]}</attribute>
</xpath>
<field name="reference" position="attributes">
<attribute name="force_save">1</attribute>
<attribute
name="attrs"
>{'readonly': ['|', ('is_ref_editable', '=', False), ('invoice_id', '!=', False)], 'invisible': [('product_has_cost', '=', True)]}</attribute>
</field>
<field name="date" position="attributes">
<attribute name="force_save">1</attribute>
<attribute
name="attrs"
>{'readonly': ['|', ('sheet_is_editable', '=', False), ('invoice_id', '!=', False)]}</attribute>
</field>
<field name="account_id" position="attributes">
<attribute
name="attrs"
>{'readonly': ['|', ('is_editable', '=', False), ('sheet_is_editable', '=', False)], 'invisible': [('invoice_id', '!=', False)]}</attribute>
</field>
<xpath
expr="//field[@name='analytic_distribution']/../field[@name='company_id']"
position="attributes"
>
<attribute
name="attrs"
>{'readonly': [('invoice_id', '!=', False)]}</attribute>
</xpath>
<xpath expr='//field[@name="product_id"]/parent::div' position="after">
<!-- Added double, one as invisible and w/o group, for those without the permission -->
<field name="invoice_id" invisible="1" />
<field
name="invoice_id"
groups="account.group_account_readonly"
context="{'default_type': 'in_invoice',
'type': 'in_invoice',
'journal_type': 'purchase',
'default_ref': reference,
'default_invoice_date': date,
'default_line_ids': [{'product_id': product_id,
'name': name,
'price_unit': unit_amount,
'quantity': quantity,
'date': date,
'account_id': account_id,
'tax_ids': tax_ids, }], }"
/>
</xpath>
<field name="tax_ids" position="attributes">
<attribute
name="attrs"
>{'invisible': [('invoice_id', '!=', False)]}</attribute>
</field>
</field>
</record>
<record id="hr_expense_sheet_form_view_inherit_sale_expense" model="ir.ui.view">
<field name="name">hr.expense.sheet.form.inherit.sale.expense</field>
<field name="model">hr.expense.sheet</field>
<field name="inherit_id" ref="hr_expense.view_hr_expense_sheet_form" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='expense_line_ids']/tree/field[@name='name']"
position="after"
>
<field name="invoice_id" groups="account.group_account_invoice" />
<field name="quantity" invisible="1" />
</xpath>
<xpath
expr="//field[@name='expense_line_ids']/tree/field[@name='total_amount']"
position="after"
>
<field name="sheet_id_state" invisible="1" />
<button
name="action_expense_create_invoice"
groups="account.group_account_invoice"
string="Create Vendor Bill"
type="object"
attrs="{'invisible': ['|', ('invoice_id', '!=', False),('sheet_id_state', 'not in', ('draft','approve'))]}"
/>
</xpath>
<div class="oe_button_box" position="inside">
<button
class="oe_stat_button"
icon="fa-book"
name="action_view_invoices"
groups="account.group_account_invoice"
type="object"
attrs="{'invisible': [('invoice_count', '=', 0)]}"
>
<field
name="invoice_count"
groups="account.group_account_invoice"
widget="statinfo"
string="Invoices"
/>
</button>
</div>
</field>
</record>
</odoo>

View file

@ -0,0 +1,42 @@
[project]
name = "odoo-bringout-oca-hr-expense-hr_expense_invoice"
version = "16.0.0"
description = "Supplier invoices on HR expenses - Odoo addon"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-hr_expense>=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 = ["hr_expense_invoice"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]