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 @@
# Employee Advance and Clearing
Odoo addon: hr_expense_advance_clearing
## Installation
```bash
pip install odoo-bringout-oca-hr-expense-hr_expense_advance_clearing
```
## Dependencies
This addon depends on:
- hr_expense
## Manifest Information
- **Name**: Employee Advance and Clearing
- **Version**: 16.0.1.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_advance_clearing`.
## 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_advance_clearing Module - hr_expense_advance_clearing
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_advance_clearing. 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_advance_clearing or install in UI.

View file

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

View file

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

View file

@ -0,0 +1,8 @@
# Wizards
Transient models exposed as UI wizards in hr_expense_advance_clearing.
```mermaid
classDiagram
class AccountPaymentRegister
```

View file

@ -0,0 +1,157 @@
=============================
Employee Advance and Clearing
=============================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e004a029a70a5f80bf9af5ee81bd0f03cb9870e582169ba24919f68ad492037f
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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_advance_clearing
: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_advance_clearing
: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|
Standard Expenses module allow employee to do the expense reimbursement only after the expense has been made.
In other world, employee will need to pay first and reimburse later.
This module, allow company to advance an amount to the employee.
Employee can then use that advance amount to purchase product/service first, then back to company and do the clearing.
There can be 3 scenarios for advance and clearing
* When clearing amount = advance amount, no other operation is required.
* When clearing amount > advance amount, company will pay the extra to employee.
* When clearing amount < advance amount, employee will return the remain to company.
**Table of contents**
.. contents::
:local:
Configuration
=============
This module will create a new product "Employee Advance" automatically.
You will need to setup the Expense Account of this product to your Employee Advance account manually.
* Open Product window and search for "Employee Advance"
* On Accounting tab, select appropriate employee advance account from your chart of account
Note:
* You will need the "Show Full Accounting Features" to see accounting data
* Employee Advance account code, if not already exists, you can create one. Use type = Current Asset and check Allow Reconciliation.
Usage
=====
To use this module, you must configure product "Employee Advance" with account type = Current Asset and check Allow Reconciliation.
After that, you can step following:
**Create an Employee Advance**
#. Go to Expenses > My Expenses > Advances
#. Create sheet and add a line with advance
#. As an option, the user can also set the "Clearing Product". If this is set, on the clear advance step, the clearing product will create a default product line.
#. Set the unit price to advance amount > Save
#. As normal, do Submit to Manager > Approve > Post Journal Entries > Register Payment.
#. As this is Advance, you will see a new field "Amount to clear".
**Clear Advance**
you can do 2 ways,
#. Create clearing from advance document
#. Go to Expenses > My Expenses > Advances
#. Search for the Advance you want to clear, or use filter "Advance (not cleared)" to see all uncleared advance.
#. Open an Advance which is now in paid status with some Amount to be cleared.
#. Click button "Clear Advance", system will create new Expense Report with reference to the previous step Advance.
#. Create name clearing and Save (must save first)
#. Edit > Add or create Expense line(s) as normal.
#. As normal, do Approve > Post Journal Entries
#. Create clearing from new expense
#. Go to Expenses > My Expenses > Expenses
#. Create sheet and reference advance with field "Clear Advance" > Save (must save first)
#. Edit > Add or create Expense line(s) as normal.
#. As normal, do Approve > Post Journal Entries
Note:
* If the total expense amount less than or equal to the advance amount, the status will be set to Paid right after post journal entries.
* If the total expense amount more than the advance amount, Register Payment will pay the extra amount then set state to Paid.
**Return Advance**
#. Go to Expenses > My Expenses > Advances
#. Search for the Advance you want to clear, or use filter "Advance (not cleared)" to see all uncleared advance.
#. Open an Advance which is now in paid status with some Amount to be cleared.
#. Click button "Return Advance" will open Register Payment wizard with Amount to clear.
#. Click button "Create Payment" to return that amount back
#. All returned, Amount to clear is now equal to 0.0
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_advance_clearing%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
~~~~~~~
* Ecosoft
Contributors
~~~~~~~~~~~~
* Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
* Tharathip Chaweewongphan <tharathipc@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.
.. |maintainer-kittiu| image:: https://github.com/kittiu.png?size=40px
:target: https://github.com/kittiu
:alt: kittiu
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-kittiu|
This module is part of the `OCA/hr-expense <https://github.com/OCA/hr-expense/tree/16.0/hr_expense_advance_clearing>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

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

View file

@ -0,0 +1,21 @@
# Copyright 2019 Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Employee Advance and Clearing",
"version": "16.0.1.0.3",
"category": "Human Resources",
"author": "Ecosoft, Odoo Community Association (OCA)",
"license": "AGPL-3",
"website": "https://github.com/OCA/hr-expense",
"depends": ["hr_expense"],
"data": [
"data/advance_product.xml",
"views/account_payment_view.xml",
"views/hr_expense_views.xml",
"views/hr_employee_views.xml",
"views/hr_employee_public_views.xml",
],
"installable": True,
"maintainers": ["kittiu"],
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="product_emp_advance" model="product.product">
<field name="name">Employee Advance</field>
<field name="default_code" />
<field name="type">service</field>
<field name="sale_ok" eval="False" />
<field name="purchase_ok" eval="False" />
<field name="can_be_expensed" eval="False" />
<field name="supplier_taxes_id" eval="False" />
<field name="taxes_id" eval="False" />
</record>
</odoo>

View file

@ -0,0 +1,365 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_advance_clearing
#
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_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"\n"
"Note: pending amount clearing is %(symbol)s%(amount)s"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee__advance_count
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_base__advance_count
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_public__advance_count
msgid "# of Advance"
msgstr "# avansa"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"A remaining advance return of %(amount)s %(symbol)s with the reference "
"%(ref)s related to your expense %(name)s has been made."
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_account_payment__advance_id
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_employee_public_view_form
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_employee_form
msgid "Advance"
msgstr "Avans"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
msgid "Advance (not cleared)"
msgstr "Avans (neočišćen)"
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid "Advance Clearing"
msgstr "Čišćenje avansa"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_residual
msgid "Advance Remaining"
msgstr "Preostali avans"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_employee_base.py:0
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee__advance_sheet_ids
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_base__advance_sheet_ids
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_public__advance_sheet_ids
#, python-format
msgid "Advance Sheet"
msgstr "Izvještaj avansa"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance clearing must not contain any advance expense line"
msgstr "Čišćenje avansa ne smije sadržavati avansnu liniju troška"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance must contain only advance expense line"
msgstr "Avans mora sadržavati samo avansnu liniju troška"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance: %s has no amount to clear"
msgstr "Avans: %s nema iznos za čišćenje"
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_my_hr_advance_sheet
#: model:ir.ui.menu,name:hr_expense_advance_clearing.menu_my_hr_advance_sheet
msgid "Advances"
msgstr "Avansi"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_residual
msgid "Amount to clear"
msgstr "Iznos za čišćenje"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_residual
msgid "Amount to clear of this expense sheet in company currency"
msgstr "Iznos za čišćenje ovog izvještaja troškova u valuti kompanije"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_employee_base
msgid "Basic Employee"
msgstr "Obični zaposlenik"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_id
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Clear Advance"
msgstr "Očisti avans"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
msgid "Clearing"
msgstr "Čišćenje"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_count
msgid "Clearing Count"
msgstr "Broj čišćenja"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__clearing_product_id
msgid "Clearing Product"
msgstr "Proizvod čišćenja"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_sheet_ids
msgid "Clearing Sheet"
msgstr "Izvještaj čišćenja"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Clearing Sheets"
msgstr "Izvještaji čišćenja"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Clearings"
msgstr "Čišćenja"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee__advance_count
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee_base__advance_count
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee_public__advance_count
msgid "Count advance sheet in expense report"
msgstr "Broji izvještaj avansa u izvještaju troškova"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid "Create a new expense report"
msgstr "Kreiraj novi izvještaj o troškovima"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__advance
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance
#: model:product.template,name:hr_expense_advance_clearing.product_emp_advance_product_template
msgid "Employee Advance"
msgstr "Avans radnika"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance product has no payable account"
msgstr "Proizvod avansa radnika nema plativ račun"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, account must be the same payable account"
msgstr "Avans radnika, račun mora biti isti plativ račun"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, all taxes must be removed"
msgstr "Avans radnika, svi porezi moraju biti uklonjeni"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, paid by must be employee"
msgstr "Avans radnika, plaća mora biti radnik"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, selected product is not valid"
msgstr "Avans radnika, odabrani proizvod nije važeći"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_expense
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_search
msgid "Expense"
msgstr "Trošak"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Izvještaj troška"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense__av_line_id
msgid "Expense created from this advance expense line"
msgstr "Trošak kreiran iz ove linije avansnog troška"
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_my_hr_expense_sheet
#: model:ir.ui.menu,name:hr_expense_advance_clearing.menu_my_hr_expense_sheet
msgid "Expenses"
msgstr "Troškovi"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__amount_payable
msgid "Final regiter payment amount even after advance clearing"
msgstr "Finalni iznos registra plaćanja i nakon čišćenja avansa"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_move
msgid "Journal Entry"
msgstr "Žurnal"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_advance_sheet
msgid "No advance report found. Let's create one!"
msgstr "Nije pronađen izvještaj avansa. Kreirajmo jedan!"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_expense_sheet
msgid "No expense report found. Let's create one!"
msgstr "Nisu pronađena izvješće troškova. Kreirajmo jedno!"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_advance_sheet
msgid ""
"Once you have created your advance, submit it to your manager who will "
"validate it."
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid ""
"Once you have created your expense, submit it to your manager who will\n"
" validate it."
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_expense_sheet
msgid ""
"Once you have created your expense, submit it to your manager who will "
"validate it."
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_form
msgid "Optional clearing product is used during clear advance"
msgstr "Opcionalan proizvod čišćenja se koristi tokom čišćenja avansa"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense__clearing_product_id
msgid ""
"Optional: On the clear advance, the clearing product will create default "
"product line."
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__amount_payable
msgid "Payable Amount"
msgstr "Iznos za plaćanje"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_payment
msgid "Payments"
msgstr "Plaćanja"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__av_line_id
msgid "Ref: Advance"
msgstr "Ref: Avans"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_payment_register
msgid "Register Payment"
msgstr "Registracija uplate"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_residual
msgid "Remaining amount to clear the selected advance sheet"
msgstr "Preostali iznos za čišćenje odabranog izvještaja avansa"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_account_payment_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Return Advance"
msgstr "Vrati avans"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_sheet_ids
msgid "Show reference clearing on advance"
msgstr "Prikaži referencu čišćenja na avans"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_id
msgid "Show remaining advance of this employee"
msgstr "Prikaži preostali avans ovog radnika"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/account_move.py:0
#, python-format
msgid ""
"This operation is not allowed as some advance amount was already cleared/returned.\n"
"Please cancel those documents first."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid "You can only register payment for posted journal entries."
msgstr "Možete registrovati plaćanje samo za knjižene stavke dnevnika."
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You can't create payments for entries belonging to different companies."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You can't register a payment because there is nothing left to pay on the "
"selected journal items."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You cannot return advance more than actual remaining "
"(%(symbol)s%(amount)s)%(more_info)s"
msgstr ""

View file

@ -0,0 +1,365 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_advance_clearing
#
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_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"\n"
"Note: pending amount clearing is %(symbol)s%(amount)s"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee__advance_count
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_base__advance_count
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_public__advance_count
msgid "# of Advance"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"A remaining advance return of %(amount)s %(symbol)s with the reference "
"%(ref)s related to your expense %(name)s has been made."
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_account_payment__advance_id
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_employee_public_view_form
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_employee_form
msgid "Advance"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
msgid "Advance (not cleared)"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid "Advance Clearing"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_residual
msgid "Advance Remaining"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_employee_base.py:0
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee__advance_sheet_ids
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_base__advance_sheet_ids
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_public__advance_sheet_ids
#, python-format
msgid "Advance Sheet"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance clearing must not contain any advance expense line"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance must contain only advance expense line"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance: %s has no amount to clear"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_my_hr_advance_sheet
#: model:ir.ui.menu,name:hr_expense_advance_clearing.menu_my_hr_advance_sheet
msgid "Advances"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_residual
msgid "Amount to clear"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_residual
msgid "Amount to clear of this expense sheet in company currency"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_employee_base
msgid "Basic Employee"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_id
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Clear Advance"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
msgid "Clearing"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_count
msgid "Clearing Count"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__clearing_product_id
msgid "Clearing Product"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_sheet_ids
msgid "Clearing Sheet"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Clearing Sheets"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Clearings"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee__advance_count
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee_base__advance_count
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee_public__advance_count
msgid "Count advance sheet in expense report"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid "Create a new expense report"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__advance
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance
#: model:product.template,name:hr_expense_advance_clearing.product_emp_advance_product_template
msgid "Employee Advance"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance product has no payable account"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, account must be the same payable account"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, all taxes must be removed"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, paid by must be employee"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, selected product is not valid"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_expense
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_search
msgid "Expense"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_expense_sheet
msgid "Expense Report"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense__av_line_id
msgid "Expense created from this advance expense line"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_my_hr_expense_sheet
#: model:ir.ui.menu,name:hr_expense_advance_clearing.menu_my_hr_expense_sheet
msgid "Expenses"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__amount_payable
msgid "Final regiter payment amount even after advance clearing"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_advance_sheet
msgid "No advance report found. Let's create one!"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_expense_sheet
msgid "No expense report found. Let's create one!"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_advance_sheet
msgid ""
"Once you have created your advance, submit it to your manager who will "
"validate it."
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid ""
"Once you have created your expense, submit it to your manager who will\n"
" validate it."
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_expense_sheet
msgid ""
"Once you have created your expense, submit it to your manager who will "
"validate it."
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_form
msgid "Optional clearing product is used during clear advance"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense__clearing_product_id
msgid ""
"Optional: On the clear advance, the clearing product will create default "
"product line."
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__amount_payable
msgid "Payable Amount"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_payment
msgid "Payments"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__av_line_id
msgid "Ref: Advance"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_payment_register
msgid "Register Payment"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_residual
msgid "Remaining amount to clear the selected advance sheet"
msgstr ""
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_account_payment_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Return Advance"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_sheet_ids
msgid "Show reference clearing on advance"
msgstr ""
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_id
msgid "Show remaining advance of this employee"
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/account_move.py:0
#, python-format
msgid ""
"This operation is not allowed as some advance amount was already cleared/returned.\n"
"Please cancel those documents first."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid "You can only register payment for posted journal entries."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You can't create payments for entries belonging to different companies."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You can't register a payment because there is nothing left to pay on the "
"selected journal items."
msgstr ""
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You cannot return advance more than actual remaining "
"(%(symbol)s%(amount)s)%(more_info)s"
msgstr ""

View file

@ -0,0 +1,417 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_expense_advance_clearing
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-11-30 15:35+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_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"\n"
"Note: pending amount clearing is %(symbol)s%(amount)s"
msgstr ""
"\n"
"Nota: valore liquidazione in attesa è %(symbol)s%(amount)s"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee__advance_count
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_base__advance_count
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_public__advance_count
msgid "# of Advance"
msgstr "N° di anticipo"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"A remaining advance return of %(amount)s %(symbol)s with the reference "
"%(ref)s related to your expense %(name)s has been made."
msgstr ""
"È stato fatto un residuo reso anticipo di %(amount)s %(symbol)s con "
"riferimento %(ref)s relativo alla sua spesa %(name)s."
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_account_payment__advance_id
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_employee_public_view_form
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_employee_form
msgid "Advance"
msgstr "Anticipo"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
msgid "Advance (not cleared)"
msgstr "Anticipo (non liquidato)"
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid "Advance Clearing"
msgstr "Liquidazione anticipo"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_residual
msgid "Advance Remaining"
msgstr "Residuo anticipo"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_employee_base.py:0
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee__advance_sheet_ids
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_base__advance_sheet_ids
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_employee_public__advance_sheet_ids
#, python-format
msgid "Advance Sheet"
msgstr "Foglio anticipo"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance clearing must not contain any advance expense line"
msgstr ""
"La liquidazione anticipo non deve contenere nessuna riga anticipo spesa"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance must contain only advance expense line"
msgstr "L'anticipo deve contenere solo una riga anticipo spesa"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Advance: %s has no amount to clear"
msgstr "Anticipo: %s non ha un valore da compensare"
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_my_hr_advance_sheet
#: model:ir.ui.menu,name:hr_expense_advance_clearing.menu_my_hr_advance_sheet
msgid "Advances"
msgstr "Anticipi"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_residual
msgid "Amount to clear"
msgstr "Valore da liquidare"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_residual
msgid "Amount to clear of this expense sheet in company currency"
msgstr "Valore da liquidare di questo foglio spese nella valuta dell'azienda"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_employee_base
msgid "Basic Employee"
msgstr "Dipendente base"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_id
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Clear Advance"
msgstr "Liquida anticipo"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_sheet_view_search
msgid "Clearing"
msgstr "Liquidazione"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_count
msgid "Clearing Count"
msgstr "Conteggio liquidazione"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__clearing_product_id
msgid "Clearing Product"
msgstr "Prodotto liquidazione"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_sheet_ids
msgid "Clearing Sheet"
msgstr "Foglio liquidazione"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense_sheet.py:0
#, python-format
msgid "Clearing Sheets"
msgstr "Fogli liquidazioni"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Clearings"
msgstr "Liquidazioni"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee__advance_count
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee_base__advance_count
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_employee_public__advance_count
msgid "Count advance sheet in expense report"
msgstr "Conteggio foglio anticipo nella nota spese"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid "Create a new expense report"
msgstr "Crea una nuova nota spese"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__advance
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__advance
#: model:product.template,name:hr_expense_advance_clearing.product_emp_advance_product_template
msgid "Employee Advance"
msgstr "Anticipo dipendente"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance product has no payable account"
msgstr "Il prodotto anticipo dipendente non ha un conto pagabile"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, account must be the same payable account"
msgstr "Anticipo dipendente, il conto deve essere lo stesso conto pagabile"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, all taxes must be removed"
msgstr "Anticipo dipendente, devono essere rimosse tutte le tasse"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, paid by must be employee"
msgstr "Anticipo dipendente, \"pagato da\" deve essere un dipendente"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/hr_expense.py:0
#, python-format
msgid "Employee advance, selected product is not valid"
msgstr "Anticipo dipendente, il prodotto selezionato non è valido"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_expense
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_search
msgid "Expense"
msgstr "Spesa"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_hr_expense_sheet
msgid "Expense Report"
msgstr "Nota spese"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense__av_line_id
msgid "Expense created from this advance expense line"
msgstr "Spesa creata da questa riga anticipo spesa"
#. module: hr_expense_advance_clearing
#: model:ir.actions.act_window,name:hr_expense_advance_clearing.action_my_hr_expense_sheet
#: model:ir.ui.menu,name:hr_expense_advance_clearing.menu_my_hr_expense_sheet
msgid "Expenses"
msgstr "Spese"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__amount_payable
msgid "Final regiter payment amount even after advance clearing"
msgstr ""
"Registrazione finale importo pagamento anche dopo la liquidazione anticipata"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_move
msgid "Journal Entry"
msgstr "Registrazione contabile"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_advance_sheet
msgid "No advance report found. Let's create one!"
msgstr "Nessuna nota spese trovata. Crearne una!"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_expense_sheet
msgid "No expense report found. Let's create one!"
msgstr "Nessuna nota spese trovata. Crearne una!"
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_advance_sheet
msgid ""
"Once you have created your advance, submit it to your manager who will "
"validate it."
msgstr ""
"Una volta creato l'anticipo, inviarlo al proprio responsabile che lo "
"validerà."
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing
msgid ""
"Once you have created your expense, submit it to your manager who will\n"
" validate it."
msgstr ""
"Una volta calcolata le spesa, inviarla al proprio responsabile che\n"
" la validerà."
#. module: hr_expense_advance_clearing
#: model_terms:ir.actions.act_window,help:hr_expense_advance_clearing.action_my_hr_expense_sheet
msgid ""
"Once you have created your expense, submit it to your manager who will "
"validate it."
msgstr ""
"Una volta creata la spesa, inviarla al proprio responsabile per la "
"validazione."
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.hr_expense_view_form
msgid "Optional clearing product is used during clear advance"
msgstr ""
"Il prodotto liquidazione viene usato nella liquidazione anticipo "
"opzionalmente"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense__clearing_product_id
msgid ""
"Optional: On the clear advance, the clearing product will create default "
"product line."
msgstr ""
"Opzionale: nella liquidazione anticipo, il prodotto liquidazione creerà la "
"riga prodotto predefinito."
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense_sheet__amount_payable
msgid "Payable Amount"
msgstr "Valore pagabile"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_payment
msgid "Payments"
msgstr "Pagamenti"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,field_description:hr_expense_advance_clearing.field_hr_expense__av_line_id
msgid "Ref: Advance"
msgstr "Rif: anticipo"
#. module: hr_expense_advance_clearing
#: model:ir.model,name:hr_expense_advance_clearing.model_account_payment_register
msgid "Register Payment"
msgstr "Registra pagamento"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_residual
msgid "Remaining amount to clear the selected advance sheet"
msgstr "Valore residuo per liquidare il foglio anticipo selezionato"
#. module: hr_expense_advance_clearing
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_account_payment_search
#: model_terms:ir.ui.view,arch_db:hr_expense_advance_clearing.view_hr_expense_sheet_form
msgid "Return Advance"
msgstr "Rimborso anticipo"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__clearing_sheet_ids
msgid "Show reference clearing on advance"
msgstr "Visualizza riferimento liquidazione sull'anticipo"
#. module: hr_expense_advance_clearing
#: model:ir.model.fields,help:hr_expense_advance_clearing.field_hr_expense_sheet__advance_sheet_id
msgid "Show remaining advance of this employee"
msgstr "Visualizza residuo anticipo di questo dipendente"
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/models/account_move.py:0
#, python-format
msgid ""
"This operation is not allowed as some advance amount was already cleared/"
"returned.\n"
"Please cancel those documents first."
msgstr ""
"Questa operazione non è consentita perché una parte del valore anticipato è "
"già stato liquidato/reso.\n"
"Cancellare quella lista documenti."
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid "You can only register payment for posted journal entries."
msgstr ""
"Si possono registrare pagamenti solo per registrazioni contabili assegnate."
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid "You can't create payments for entries belonging to different companies."
msgstr ""
"Non si possono creare pagamenti per entrate appartenenti a diverse aziende."
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You can't register a payment because there is nothing left to pay on the "
"selected journal items."
msgstr ""
"Non si può registrare il pagamento perché non c'è niente da pagare nei "
"movimenti contabili selezionati."
#. module: hr_expense_advance_clearing
#. odoo-python
#: code:addons/hr_expense_advance_clearing/wizard/account_payment_register.py:0
#, python-format
msgid ""
"You cannot return advance more than actual remaining (%(symbol)s"
"%(amount)s)%(more_info)s"
msgstr ""
"Non è possibile restituire un anticipo superiore al rimanente effettivo "
"(%(symbol)s%(amount)s)%(more_info)s"
#, python-format
#~ msgid ""
#~ "\n"
#~ "Note: pending amount clearing is {}{}"
#~ msgstr ""
#~ "\n"
#~ "Nota: il valore da saldare in attesa è {}{}"
#, python-format
#~ msgid ""
#~ "A remaining advance return of {} {} with the reference {} related to your "
#~ "expense {} has been made."
#~ msgstr ""
#~ "È stato eseguito un rimborso anticipo residuo di {} {} con riferimento {} "
#~ "relativo alla sua spesa {}."
#~ msgid "Units"
#~ msgstr "Unità"
#, python-format
#~ msgid "You cannot return advance more than actual remaining ({}{}){}"
#~ msgstr ""
#~ "Non si può rimborsare un anticipo oltre il restante effettivo ({}{}){}"

View file

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

View file

@ -0,0 +1,79 @@
# Copyright 2022 Ecosoft Co., Ltd. (https://ecosoft.co.th)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import _, api, models
from odoo.exceptions import UserError
class AccountMove(models.Model):
_inherit = "account.move"
def _check_hr_advance_move_reconciled(self):
"""Check if the advance move lines already cleard/returned"""
av_moves = self.filtered("line_ids.expense_id.sheet_id.advance")
emp_advance = self.env.ref("hr_expense_advance_clearing.product_emp_advance")
reconciled_av_move_lines = av_moves.mapped("line_ids").filtered(
lambda l: l.product_id == emp_advance and l.matching_number
)
if reconciled_av_move_lines:
raise UserError(
_(
"This operation is not allowed as some advance amount was already "
"cleared/returned.\nPlease cancel those documents first."
)
)
def button_draft(self):
self._check_hr_advance_move_reconciled()
return super().button_draft()
def button_cancel(self):
self._check_hr_advance_move_reconciled()
return super().button_cancel()
def _reverse_moves(self, default_values_list=None, cancel=False):
self._check_hr_advance_move_reconciled()
return super()._reverse_moves(
default_values_list=default_values_list, cancel=cancel
)
@api.depends(
"line_ids.matched_debit_ids.debit_move_id.move_id.payment_id.is_matched",
"line_ids.matched_debit_ids.debit_move_id.move_id.line_ids.amount_residual",
"line_ids.matched_debit_ids.debit_move_id.move_id.line_ids.amount_residual_currency",
"line_ids.matched_credit_ids.credit_move_id.move_id.payment_id.is_matched",
"line_ids.matched_credit_ids.credit_move_id.move_id.line_ids.amount_residual",
"line_ids.matched_credit_ids.credit_move_id.move_id.line_ids.amount_residual_currency",
"line_ids.balance",
"line_ids.currency_id",
"line_ids.amount_currency",
"line_ids.amount_residual",
"line_ids.amount_residual_currency",
"line_ids.payment_id.state",
"line_ids.full_reconcile_id",
"state",
)
def _compute_amount(self):
"""Compute amount residual for advance clearing case."""
res = super()._compute_amount()
for move in self:
total_residual = 0.0
total_residual_currency = 0.0
for line in move.line_ids:
if line.account_type not in ("asset_receivable", "liability_payable"):
continue
# Line residual amount.
clearing = line.expense_id.sheet_id.filtered(
lambda sheet: sheet.advance_sheet_id
)
if clearing:
# Residual amount.
total_residual += line.amount_residual
total_residual_currency += line.amount_residual_currency
# Update amount residual for case clearing
if total_residual and total_residual_currency:
sign = move.direction_sign
move.amount_residual = -sign * total_residual
move.amount_residual_signed = total_residual_currency
return res

View file

@ -0,0 +1,22 @@
# Copyright 2022 Ecosoft Co., Ltd. (https://ecosoft.co.th)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class AccountPayment(models.Model):
_inherit = "account.payment"
advance_id = fields.Many2one(
comodel_name="hr.expense.sheet",
readonly=True,
)
def _synchronize_from_moves(self, changed_fields):
"""skip check when payment is return advance"""
self = (
self.with_context(skip_account_move_synchronization=True)
if self.filtered("advance_id")
else self
)
return super()._synchronize_from_moves(changed_fields)

View file

@ -0,0 +1,33 @@
# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, fields, models
class HrEmployeeBase(models.AbstractModel):
_inherit = "hr.employee.base"
advance_sheet_ids = fields.One2many(
comodel_name="hr.expense.sheet",
inverse_name="employee_id",
domain=[("advance", "=", True)],
readonly=True,
)
advance_count = fields.Integer(
string="# of Advance",
compute="_compute_advance_count",
help="Count advance sheet in expense report",
)
def _compute_advance_count(self):
self.advance_count = len(self.advance_sheet_ids)
def action_open_advance_clearing(self):
self.ensure_one()
return {
"name": _("Advance Sheet"),
"type": "ir.actions.act_window",
"res_model": "hr.expense.sheet",
"view_mode": "tree,form",
"domain": [("id", "in", self.advance_sheet_ids.ids)],
}

View file

@ -0,0 +1,111 @@
# Copyright 2019 Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import Command, _, api, fields, models
from odoo.exceptions import ValidationError
class HrExpense(models.Model):
_inherit = "hr.expense"
advance = fields.Boolean(string="Employee Advance", default=False)
clearing_product_id = fields.Many2one(
comodel_name="product.product",
string="Clearing Product",
tracking=True,
domain="[('can_be_expensed', '=', True),"
"'|', ('company_id', '=', False), ('company_id', '=', company_id)]",
ondelete="restrict",
help="Optional: On the clear advance, the clearing "
"product will create default product line.",
)
av_line_id = fields.Many2one(
comodel_name="hr.expense",
string="Ref: Advance",
ondelete="set null",
help="Expense created from this advance expense line",
)
def _get_product_advance(self):
return self.env.ref("hr_expense_advance_clearing.product_emp_advance", False)
@api.constrains("advance")
def _check_advance(self):
for expense in self.filtered("advance"):
emp_advance = expense._get_product_advance()
if not emp_advance.property_account_expense_id:
raise ValidationError(
_("Employee advance product has no payable account")
)
if expense.product_id != emp_advance:
raise ValidationError(
_("Employee advance, selected product is not valid")
)
if expense.account_id != emp_advance.property_account_expense_id:
raise ValidationError(
_("Employee advance, account must be the same payable account")
)
if expense.tax_ids:
raise ValidationError(_("Employee advance, all taxes must be removed"))
if expense.payment_mode != "own_account":
raise ValidationError(_("Employee advance, paid by must be employee"))
return True
@api.onchange("advance")
def onchange_advance(self):
self.tax_ids = False
if self.advance:
self.product_id = self._get_product_advance()
def _get_move_line_src(self, move_line_name, partner_id):
self.ensure_one()
unit_amount = self.unit_amount or self.total_amount
quantity = self.quantity if self.unit_amount else 1
taxes = self.tax_ids.with_context(round=True).compute_all(
unit_amount, self.currency_id, quantity, self.product_id
)
amount_currency = self.total_amount - self.amount_tax
balance = self.total_amount_company - self.amount_tax_company
ml_src_dict = {
"name": move_line_name,
"quantity": quantity,
"debit": balance if balance > 0 else 0,
"credit": -balance if balance < 0 else 0,
"amount_currency": amount_currency,
"account_id": self.account_id.id,
"product_id": self.product_id.id,
"product_uom_id": self.product_uom_id.id,
"analytic_distribution": self.analytic_distribution,
"expense_id": self.id,
"partner_id": partner_id,
"tax_ids": [Command.set(self.tax_ids.ids)],
"tax_tag_ids": [Command.set(taxes["base_tags"])],
"currency_id": self.currency_id.id,
}
return ml_src_dict
def _get_move_line_dst(
self,
move_line_name,
partner_id,
total_amount,
total_amount_currency,
account_advance,
):
account_date = (
self.date
or self.sheet_id.accounting_date
or fields.Date.context_today(self)
)
ml_dst_dict = {
"name": move_line_name,
"debit": total_amount > 0 and total_amount,
"credit": total_amount < 0 and -total_amount,
"account_id": account_advance.id,
"date_maturity": account_date,
"amount_currency": total_amount_currency,
"currency_id": self.currency_id.id,
"expense_id": self.id,
"partner_id": partner_id,
}
return ml_dst_dict

View file

@ -0,0 +1,324 @@
# Copyright 2019 Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import Command, _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools import float_compare, float_is_zero
from odoo.tools.safe_eval import safe_eval
class HrExpenseSheet(models.Model):
_inherit = "hr.expense.sheet"
advance = fields.Boolean(
string="Employee Advance",
)
advance_sheet_id = fields.Many2one(
comodel_name="hr.expense.sheet",
string="Clear Advance",
domain="[('advance', '=', True), ('employee_id', '=', employee_id),"
" ('clearing_residual', '>', 0.0)]",
readonly=True,
states={
"draft": [("readonly", False)],
"submit": [("readonly", False)],
"approve": [("readonly", False)],
},
help="Show remaining advance of this employee",
)
clearing_sheet_ids = fields.One2many(
comodel_name="hr.expense.sheet",
inverse_name="advance_sheet_id",
string="Clearing Sheet",
readonly=True,
help="Show reference clearing on advance",
)
clearing_count = fields.Integer(
compute="_compute_clearing_count",
)
clearing_residual = fields.Monetary(
string="Amount to clear",
compute="_compute_clearing_residual",
store=True,
help="Amount to clear of this expense sheet in company currency",
)
advance_sheet_residual = fields.Monetary(
string="Advance Remaining",
related="advance_sheet_id.clearing_residual",
store=True,
help="Remaining amount to clear the selected advance sheet",
)
amount_payable = fields.Monetary(
string="Payable Amount",
compute="_compute_amount_payable",
help="Final regiter payment amount even after advance clearing",
)
@api.constrains("advance_sheet_id", "expense_line_ids")
def _check_advance_expense(self):
advance_lines = self.expense_line_ids.filtered("advance")
if self.advance_sheet_id and advance_lines:
raise ValidationError(
_("Advance clearing must not contain any advance expense line")
)
if advance_lines and len(advance_lines) != len(self.expense_line_ids):
raise ValidationError(_("Advance must contain only advance expense line"))
@api.depends("account_move_id.payment_state")
def _compute_payment_state(self):
"""After clear advance.
if amount residual is zero, payment state will change to 'paid'
"""
res = super()._compute_payment_state()
for sheet in self:
if (
sheet.advance_sheet_id
and sheet.account_move_id.state == "posted"
and not sheet.amount_residual
):
sheet.payment_state = "paid"
return res
def _get_product_advance(self):
return self.env.ref("hr_expense_advance_clearing.product_emp_advance", False)
@api.depends("account_move_id.line_ids.amount_residual")
def _compute_clearing_residual(self):
for sheet in self:
emp_advance = sheet._get_product_advance()
residual_company = 0.0
if emp_advance:
property_account_expense_id = emp_advance.with_company(
sheet.company_id
).property_account_expense_id
for line in sheet.sudo().account_move_id.line_ids:
if line.account_id == property_account_expense_id:
residual_company += line.amount_residual
sheet.clearing_residual = residual_company
def _compute_amount_payable(self):
for sheet in self:
rec_lines = sheet.account_move_id.line_ids.filtered(
lambda x: x.credit and x.account_id.reconcile and not x.reconciled
)
sheet.amount_payable = -sum(rec_lines.mapped("amount_residual"))
def _compute_clearing_count(self):
for sheet in self:
sheet.clearing_count = len(sheet.clearing_sheet_ids)
def action_sheet_move_create(self):
res = super().action_sheet_move_create()
for sheet in self:
if not sheet.advance_sheet_id:
continue
amount_residual_bf_reconcile = sheet.advance_sheet_residual
advance_residual = float_compare(
amount_residual_bf_reconcile,
sheet.total_amount,
precision_rounding=sheet.currency_id.rounding,
)
move_lines = (
sheet.account_move_id.line_ids
| sheet.advance_sheet_id.account_move_id.line_ids
)
emp_advance = sheet._get_product_advance()
account_id = emp_advance.property_account_expense_id.id
adv_move_lines = (
self.env["account.move.line"]
.sudo()
.search(
[
("id", "in", move_lines.ids),
("account_id", "=", account_id),
("reconciled", "=", False),
]
)
)
adv_move_lines.reconcile()
# Update state on clearing advance when advance residual > total amount
if advance_residual != -1:
sheet.write(
{
"state": "done",
}
)
# Update amount residual and state when advance residual < total amount
else:
sheet.write(
{
"state": "post",
"payment_state": "not_paid",
"amount_residual": sheet.total_amount
- amount_residual_bf_reconcile,
}
)
return res
def _get_move_line_vals(self):
self.ensure_one()
move_line_vals = []
advance_to_clear = self.advance_sheet_residual
emp_advance = self._get_product_advance()
account_advance = emp_advance.property_account_expense_id
for expense in self.expense_line_ids:
move_line_name = (
expense.employee_id.name + ": " + expense.name.split("\n")[0][:64]
)
total_amount = 0.0
total_amount_currency = 0.0
partner_id = (
expense.employee_id.sudo().address_home_id.commercial_partner_id.id
)
# source move line
move_line_src = expense._get_move_line_src(move_line_name, partner_id)
move_line_values = [move_line_src]
total_amount -= expense.total_amount_company
total_amount_currency -= expense.total_amount
# destination move line
move_line_dst = expense._get_move_line_dst(
move_line_name,
partner_id,
total_amount,
total_amount_currency,
account_advance,
)
# Check clearing > advance, it will split line
credit = move_line_dst["credit"]
# cr payable -> cr advance
remain_payable = 0.0
payable_move_line = []
rounding = expense.currency_id.rounding
if (
float_compare(
credit,
advance_to_clear,
precision_rounding=rounding,
)
== 1
):
remain_payable = credit - advance_to_clear
move_line_dst["credit"] = advance_to_clear
move_line_dst["amount_currency"] = -advance_to_clear
advance_to_clear = 0.0
# extra payable line
payable_move_line = move_line_dst.copy()
payable_move_line["credit"] = remain_payable
payable_move_line["amount_currency"] = -remain_payable
payable_move_line[
"account_id"
] = expense._get_expense_account_destination()
else:
advance_to_clear -= credit
# Add destination first (if credit is not zero)
if not float_is_zero(move_line_dst["credit"], precision_rounding=rounding):
move_line_values.append(move_line_dst)
if payable_move_line:
move_line_values.append(payable_move_line)
move_line_vals.extend(move_line_values)
return move_line_vals
def _prepare_bill_vals(self):
"""create journal entry instead of bills when clearing document"""
self.ensure_one()
res = super()._prepare_bill_vals()
if self.advance_sheet_id and self.payment_mode == "own_account":
if (
self.advance_sheet_residual <= 0.0
): # Advance Sheets with no residual left
raise ValidationError(
_("Advance: %s has no amount to clear") % (self.name)
)
res["move_type"] = "entry"
move_line_vals = self._get_move_line_vals()
res["line_ids"] = [Command.create(x) for x in move_line_vals]
return res
def open_clear_advance(self):
self.ensure_one()
action = self.env.ref(
"hr_expense_advance_clearing.action_hr_expense_sheet_advance_clearing"
)
vals = action.sudo().read()[0]
context1 = vals.get("context", {})
if context1:
context1 = safe_eval(context1)
context1["default_advance_sheet_id"] = self.id
context1["default_employee_id"] = self.employee_id.id
vals["context"] = context1
return vals
def get_domain_advance_sheet_expense_line(self):
return self.advance_sheet_id.expense_line_ids.filtered("clearing_product_id")
def create_clearing_expense_line(self, line):
clear_advance = self._prepare_clear_advance(line)
clearing_line = self.env["hr.expense"].new(clear_advance)
return clearing_line
@api.onchange("advance_sheet_id")
def _onchange_advance_sheet_id(self):
self.expense_line_ids -= self.expense_line_ids.filtered("av_line_id")
self.advance_sheet_id.expense_line_ids.sudo().read() # prefetch
lines = self.get_domain_advance_sheet_expense_line()
for line in lines:
self.expense_line_ids += self.create_clearing_expense_line(line)
def _prepare_clear_advance(self, line):
# Prepare the clearing expense
clear_line_dict = {
"advance": False,
"name": line.clearing_product_id.display_name,
"product_id": line.clearing_product_id.id,
"clearing_product_id": False,
"date": fields.Date.context_today(self),
"account_id": False,
"state": "draft",
"product_uom_id": False,
"av_line_id": line.id,
}
clear_line = self.env["hr.expense"].new(clear_line_dict)
clear_line._compute_account_id() # Set some vals
# Prepare the original advance line
adv_dict = line._convert_to_write(line._cache)
# remove no update columns
_fields = line._fields
del_cols = [k for k in _fields.keys() if _fields[k].type == "one2many"]
del_cols += list(self.env["mail.thread"]._fields.keys())
del_cols += list(self.env["mail.activity.mixin"]._fields.keys())
del_cols += list(clear_line_dict.keys())
del_cols = list(set(del_cols))
adv_dict = {k: v for k, v in adv_dict.items() if k not in del_cols}
# Assign the known value from original advance line
clear_line.update(adv_dict)
clearing_dict = clear_line._convert_to_write(clear_line._cache)
# Convert list of int to [(6, 0, list)]
clearing_dict = {
k: isinstance(v, list)
and all(isinstance(x, int) for x in v)
and [(6, 0, v)]
or v
for k, v in clearing_dict.items()
}
return clearing_dict
def action_open_clearings(self):
self.ensure_one()
return {
"name": _("Clearing Sheets"),
"type": "ir.actions.act_window",
"res_model": "hr.expense.sheet",
"view_mode": "tree,form",
"domain": [("id", "in", self.clearing_sheet_ids.ids)],
}
def action_register_payment(self):
action = super().action_register_payment()
if self.env.context.get("hr_return_advance"):
action["context"].update(
{
"clearing_sheet_ids": self.clearing_sheet_ids.ids,
}
)
return action

View file

@ -0,0 +1,10 @@
This module will create a new product "Employee Advance" automatically.
You will need to setup the Expense Account of this product to your Employee Advance account manually.
* Open Product window and search for "Employee Advance"
* On Accounting tab, select appropriate employee advance account from your chart of account
Note:
* You will need the "Show Full Accounting Features" to see accounting data
* Employee Advance account code, if not already exists, you can create one. Use type = Current Asset and check Allow Reconciliation.

View file

@ -0,0 +1,3 @@
* Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
* Tharathip Chaweewongphan <tharathipc@ecosoft.co.th>
* Saran Lim. <saranl@ecosoft.co.th>

View file

@ -0,0 +1,11 @@
Standard Expenses module allow employee to do the expense reimbursement only after the expense has been made.
In other world, employee will need to pay first and reimburse later.
This module, allow company to advance an amount to the employee.
Employee can then use that advance amount to purchase product/service first, then back to company and do the clearing.
There can be 3 scenarios for advance and clearing
* When clearing amount = advance amount, no other operation is required.
* When clearing amount > advance amount, company will pay the extra to employee.
* When clearing amount < advance amount, employee will return the remain to company.

View file

@ -0,0 +1,43 @@
To use this module, you must configure product "Employee Advance" with account type = Current Asset and check Allow Reconciliation.
After that, you can step following:
**Create an Employee Advance**
#. Go to Expenses > My Expenses > Advances
#. Create sheet and add a line with advance
#. As an option, the user can also set the "Clearing Product". If this is set, on the clear advance step, the clearing product will create a default product line.
#. Set the unit price to advance amount > Save
#. As normal, do Submit to Manager > Approve > Post Journal Entries > Register Payment.
#. As this is Advance, you will see a new field "Amount to clear".
**Clear Advance**
you can do 2 ways,
#. Create clearing from advance document
#. Go to Expenses > My Expenses > Advances
#. Search for the Advance you want to clear, or use filter "Advance (not cleared)" to see all uncleared advance.
#. Open an Advance which is now in paid status with some Amount to be cleared.
#. Click button "Clear Advance", system will create new Expense Report with reference to the previous step Advance.
#. Create name clearing and Save (must save first)
#. Edit > Add or create Expense line(s) as normal.
#. As normal, do Approve > Post Journal Entries
#. Create clearing from new expense
#. Go to Expenses > My Expenses > Expenses
#. Create sheet and reference advance with field "Clear Advance" > Save (must save first)
#. Edit > Add or create Expense line(s) as normal.
#. As normal, do Approve > Post Journal Entries
Note:
* If the total expense amount less than or equal to the advance amount, the status will be set to Paid right after post journal entries.
* If the total expense amount more than the advance amount, Register Payment will pay the extra amount then set state to Paid.
**Return Advance**
#. Go to Expenses > My Expenses > Advances
#. Search for the Advance you want to clear, or use filter "Advance (not cleared)" to see all uncleared advance.
#. Open an Advance which is now in paid status with some Amount to be cleared.
#. Click button "Return Advance" will open Register Payment wizard with Amount to clear.
#. Click button "Create Payment" to return that amount back
#. All returned, Amount to clear is now equal to 0.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,509 @@
<!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>Employee Advance and Clearing</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="employee-advance-and-clearing">
<h1 class="title">Employee Advance and Clearing</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e004a029a70a5f80bf9af5ee81bd0f03cb9870e582169ba24919f68ad492037f
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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_advance_clearing"><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_advance_clearing"><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>Standard Expenses module allow employee to do the expense reimbursement only after the expense has been made.
In other world, employee will need to pay first and reimburse later.</p>
<p>This module, allow company to advance an amount to the employee.
Employee can then use that advance amount to purchase product/service first, then back to company and do the clearing.</p>
<p>There can be 3 scenarios for advance and clearing</p>
<ul class="simple">
<li>When clearing amount = advance amount, no other operation is required.</li>
<li>When clearing amount &gt; advance amount, company will pay the extra to employee.</li>
<li>When clearing amount &lt; advance amount, employee will return the remain to company.</li>
</ul>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</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="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>This module will create a new product “Employee Advance” automatically.
You will need to setup the Expense Account of this product to your Employee Advance account manually.</p>
<ul class="simple">
<li>Open Product window and search for “Employee Advance”</li>
<li>On Accounting tab, select appropriate employee advance account from your chart of account</li>
</ul>
<p>Note:</p>
<ul class="simple">
<li>You will need the “Show Full Accounting Features” to see accounting data</li>
<li>Employee Advance account code, if not already exists, you can create one. Use type = Current Asset and check Allow Reconciliation.</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>To use this module, you must configure product “Employee Advance” with account type = Current Asset and check Allow Reconciliation.
After that, you can step following:</p>
<p><strong>Create an Employee Advance</strong></p>
<ol class="arabic simple">
<li>Go to Expenses &gt; My Expenses &gt; Advances</li>
<li>Create sheet and add a line with advance</li>
<li>As an option, the user can also set the “Clearing Product”. If this is set, on the clear advance step, the clearing product will create a default product line.</li>
<li>Set the unit price to advance amount &gt; Save</li>
<li>As normal, do Submit to Manager &gt; Approve &gt; Post Journal Entries &gt; Register Payment.</li>
<li>As this is Advance, you will see a new field “Amount to clear”.</li>
</ol>
<p><strong>Clear Advance</strong></p>
<p>you can do 2 ways,</p>
<ol class="arabic simple">
<li><dl class="first docutils">
<dt>Create clearing from advance document</dt>
<dd><ol class="first last arabic">
<li>Go to Expenses &gt; My Expenses &gt; Advances</li>
<li>Search for the Advance you want to clear, or use filter “Advance (not cleared)” to see all uncleared advance.</li>
<li>Open an Advance which is now in paid status with some Amount to be cleared.</li>
<li>Click button “Clear Advance”, system will create new Expense Report with reference to the previous step Advance.</li>
<li>Create name clearing and Save (must save first)</li>
<li>Edit &gt; Add or create Expense line(s) as normal.</li>
<li>As normal, do Approve &gt; Post Journal Entries</li>
</ol>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Create clearing from new expense</dt>
<dd><ol class="first last arabic">
<li>Go to Expenses &gt; My Expenses &gt; Expenses</li>
<li>Create sheet and reference advance with field “Clear Advance” &gt; Save (must save first)</li>
<li>Edit &gt; Add or create Expense line(s) as normal.</li>
<li>As normal, do Approve &gt; Post Journal Entries</li>
</ol>
</dd>
</dl>
</li>
</ol>
<p>Note:</p>
<ul class="simple">
<li>If the total expense amount less than or equal to the advance amount, the status will be set to Paid right after post journal entries.</li>
<li>If the total expense amount more than the advance amount, Register Payment will pay the extra amount then set state to Paid.</li>
</ul>
<p><strong>Return Advance</strong></p>
<ol class="arabic simple">
<li>Go to Expenses &gt; My Expenses &gt; Advances</li>
<li>Search for the Advance you want to clear, or use filter “Advance (not cleared)” to see all uncleared advance.</li>
<li>Open an Advance which is now in paid status with some Amount to be cleared.</li>
<li>Click button “Return Advance” will open Register Payment wizard with Amount to clear.</li>
<li>Click button “Create Payment” to return that amount back</li>
<li>All returned, Amount to clear is now equal to 0.0</li>
</ol>
</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_advance_clearing%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>Ecosoft</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Kitti Upariphutthiphong &lt;<a class="reference external" href="mailto:kittiu&#64;ecosoft.co.th">kittiu&#64;ecosoft.co.th</a>&gt;</li>
<li>Tharathip Chaweewongphan &lt;<a class="reference external" href="mailto:tharathipc&#64;ecosoft.co.th">tharathipc&#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>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/kittiu"><img alt="kittiu" src="https://github.com/kittiu.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/hr-expense/tree/16.0/hr_expense_advance_clearing">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,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_hr_expense_advance_clearing

View file

@ -0,0 +1,323 @@
# Copyright 2019 Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
# Copyright 2024 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields
from odoo.exceptions import UserError, ValidationError
from odoo.tests.common import Form, tagged
from odoo.tools import mute_logger
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
@tagged("-at_install", "post_install")
class TestHrExpenseAdvanceClearing(TestExpenseCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
advance_account = cls.company_data["default_account_assets"]
advance_account.reconcile = True
cls.emp_advance = cls.env.ref("hr_expense_advance_clearing.product_emp_advance")
cls.emp_advance.property_account_expense_id = advance_account
cls.product_a.standard_price = 0
# Create advance expense 1,000
cls.advance = cls._create_expense_sheet(
cls,
"Advance 1,000",
cls.expense_employee,
cls.emp_advance,
1000.0,
advance=True,
)
# Create clearing expense 1,000
cls.clearing_equal = cls._create_expense_sheet(
cls, "Buy service 1,000", cls.expense_employee, cls.product_a, 1000.0
)
# Create clearing expense 1,200
cls.clearing_more = cls._create_expense_sheet(
cls, "Buy service 1,200", cls.expense_employee, cls.product_a, 1200.0
)
# Create clearing expense 800
cls.clearing_less = cls._create_expense_sheet(
cls, "Buy service 800", cls.expense_employee, cls.product_a, 800.0
)
def _create_expense(
self,
description,
employee,
product,
amount,
advance=False,
payment_mode="own_account",
):
with Form(
self.env["hr.expense"].with_context(default_advance=advance)
) as expense:
expense.name = description
expense.employee_id = employee
if not advance:
expense.product_id = product
expense.total_amount = amount
expense.payment_mode = payment_mode
expense = expense.save()
expense.tax_ids = False # Test no vat
return expense
def _create_expense_sheet(
self, description, employee, product, amount, advance=False
):
expense = self._create_expense(
self, description, employee, product, amount, advance
)
# Add expense to expense sheet
expense_sheet = self.env["hr.expense.sheet"].create(
{
"name": description,
"employee_id": expense.employee_id.id,
"expense_line_ids": [(6, 0, [expense.id])],
"advance": advance,
}
)
return expense_sheet
def _register_payment(self, move_id, amount, ctx=False, hr_return_advance=False):
if not ctx:
ctx = {
"active_ids": [move_id.id],
"active_id": move_id.id,
"active_model": "account.move",
}
ctx["hr_return_advance"] = hr_return_advance
PaymentWizard = self.env["account.payment.register"]
with Form(PaymentWizard.with_context(**ctx)) as f:
f.journal_id = self.company_data["default_journal_bank"]
f.payment_date = fields.Date.today()
f.amount = amount
payment_wizard = f.save()
payment_wizard.action_create_payments()
def test_0_test_constraints(self):
"""Test some constraints"""
# Advance Sheet can't be clearing at the same time.
with self.assertRaises(ValidationError):
self.advance.advance_sheet_id = self.advance
# Advance Sheet can't change account is not the equal
# Account on Advance Expense's product.
with self.assertRaises(ValidationError):
expense = self._create_expense(
"Advance 1,000",
self.expense_employee,
self.emp_advance,
1.0,
advance=True,
)
expense.account_id = self.company_data["default_account_payable"]
expense._check_advance()
# Advance Sheet should not have > 1 expense lines
with self.assertRaises(ValidationError):
expense = self._create_expense(
"Buy service 1,000", self.expense_employee, self.product_a, 1.0
)
self.advance.write({"expense_line_ids": [(4, expense.id)]})
# Advance Expense's product, must not has tax involved
with self.assertRaises(ValidationError):
self.emp_advance.supplier_taxes_id |= self.company_data[
"default_tax_purchase"
]
expense = self._create_expense(
"Advance 1,000",
self.expense_employee,
self.emp_advance,
1.0,
advance=True,
)
self.emp_advance.supplier_taxes_id = False # Remove tax bf proceed
# Advance Expense, must not paid by company
with self.assertRaises(ValidationError):
expense = self._create_expense(
"Advance 1,000",
self.expense_employee,
self.emp_advance,
1.0,
advance=True,
payment_mode="company_account",
)
# Advance Expense, must be product advance only
with self.assertRaises(ValidationError):
expense = self._create_expense(
"Advance 1,000",
self.expense_employee,
self.emp_advance,
1.0,
advance=True,
)
expense.product_id = self.product_a
expense._check_advance()
# Advance Expense's product must have account configured
with self.assertRaises(ValidationError):
self.emp_advance.property_account_expense_id = False
expense = self._create_expense(
"Advance 1,000",
self.expense_employee,
self.emp_advance,
1.0,
advance=True,
)
@mute_logger("odoo.models.unlink")
def test_1_clear_equal_advance(self):
"""When clear equal advance, all set"""
# ------------------ Advance --------------------------
self.advance.action_submit_sheet()
self.advance.approve_expense_sheets()
self.advance.action_sheet_move_create()
self.assertEqual(self.advance.clearing_residual, 1000.0)
self._register_payment(self.advance.account_move_id, 1000.0)
self.assertEqual(self.advance.state, "done")
# ------------------ Clearing --------------------------
# Clear this with previous advance
vals = self.advance.open_clear_advance() # Test Clear Advance button
ctx = vals.get("context")
self.assertEqual(ctx["default_advance_sheet_id"], self.advance.id)
self.clearing_equal.advance_sheet_id = self.advance
self.assertEqual(self.clearing_equal.advance_sheet_residual, 1000.0)
self.clearing_equal.action_submit_sheet()
self.clearing_equal.approve_expense_sheets()
self.clearing_equal.action_sheet_move_create()
# Equal amount, state change to Paid and advance is cleared
self.assertEqual(self.clearing_equal.state, "done")
self.assertEqual(self.clearing_equal.advance_sheet_residual, 0.0)
# Clear this with previous advance is done
self.clearing_more.advance_sheet_id = self.advance
self.clearing_more.action_submit_sheet()
self.clearing_more.approve_expense_sheets()
with self.assertRaises(ValidationError):
self.clearing_more.action_sheet_move_create()
# There are 2 clearing in advance
self.assertEqual(self.advance.clearing_count, 2)
# Check link clearing in advance must be equal clearing count
clearing_dict = self.advance.action_open_clearings()
self.assertEqual(
len(clearing_dict["domain"][0][2]), self.advance.clearing_count
)
# Check advance from employee
self.assertEqual(self.expense_employee.advance_count, 1)
clearing_document = self.expense_employee.action_open_advance_clearing()
self.assertEqual(
len(clearing_document["domain"][0][2]), self.expense_employee.advance_count
)
# Check back state move in advance after create clearing
with self.assertRaises(UserError):
self.advance.account_move_id.button_draft()
with self.assertRaises(UserError):
self.advance.account_move_id.button_cancel()
with self.assertRaises(UserError):
self.advance.account_move_id._reverse_moves()
@mute_logger("odoo.models.unlink")
def test_2_clear_more_than_advance(self):
"""When clear more than advance, do pay more"""
# ------------------ Advance --------------------------
self.advance.action_submit_sheet()
self.advance.approve_expense_sheets()
self.advance.action_sheet_move_create()
self.assertEqual(self.advance.clearing_residual, 1000.0)
self._register_payment(self.advance.account_move_id, 1000.0)
self.assertEqual(self.advance.state, "done")
# ------------------ Clearing --------------------------
# Clear this with previous advance
self.clearing_more.advance_sheet_id = self.advance
self.assertEqual(self.clearing_more.advance_sheet_residual, 1000.0)
self.clearing_more.action_submit_sheet()
self.clearing_more.approve_expense_sheets()
self.clearing_more.action_sheet_move_create()
# More amount, state not changed to paid, and has to pay 200 more
self.assertEqual(self.clearing_more.state, "post")
self.assertEqual(self.clearing_more.amount_payable, 200.0)
self._register_payment(self.clearing_more.account_move_id, 200.0)
self.assertEqual(self.clearing_more.state, "done")
@mute_logger("odoo.models.unlink")
def test_3_clear_less_than_advance(self):
"""When clear less than advance, do return advance"""
# ------------------ Advance --------------------------
self.advance.action_submit_sheet()
self.advance.approve_expense_sheets()
self.advance.action_sheet_move_create()
# Test return advance register payment with move state draft
with self.assertRaises(UserError):
self.advance.account_move_id.button_draft()
self._register_payment(
self.advance.account_move_id, 200.0, hr_return_advance=True
)
self.assertEqual(self.advance.clearing_residual, 1000.0)
self._register_payment(self.advance.account_move_id, 1000.0)
self.assertEqual(self.advance.state, "done")
# ------------------ Clearing, Return Advance --------------------------
# Clear this with previous advance
self.clearing_less.advance_sheet_id = self.advance
self.assertEqual(self.clearing_less.advance_sheet_residual, 1000.0)
self.clearing_less.action_submit_sheet()
self.clearing_less.approve_expense_sheets()
register_payment = self.advance.with_context(
hr_return_advance=True
).action_register_payment()
# Test return advance register payment without move
with self.assertRaises(UserError):
self._register_payment(
self.env["account.move"], 200.0, hr_return_advance=True
)
# Test return advance over residual
with self.assertRaises(UserError):
self._register_payment(
self.advance.account_move_id,
300.0,
ctx=register_payment["context"],
hr_return_advance=True,
)
self.clearing_less.action_sheet_move_create()
# Less amount, state set to done. Still remain 200 to be returned
self.assertEqual(self.clearing_less.state, "done")
self.assertEqual(self.clearing_less.advance_sheet_residual, 200.0)
# Back to advance and do return advance, clearing residual become 0.0
self._register_payment(
self.advance.account_move_id,
200.0,
ctx=register_payment["context"],
hr_return_advance=True,
)
self.assertEqual(self.advance.clearing_residual, 0.0)
# Check payment of return advance
payment = self.env["account.payment"].search(
[("advance_id", "=", self.advance.id)]
)
self.assertEqual(len(payment), 1)
@mute_logger("odoo.models.unlink")
def test_4_clearing_product_advance(self):
"""When select clearing product on advance"""
# ------------------ Advance --------------------------
self.advance.expense_line_ids.clearing_product_id = self.product_a
self.advance.action_submit_sheet()
self.advance.approve_expense_sheets()
self.advance.action_sheet_move_create()
self.assertEqual(self.advance.clearing_residual, 1000.0)
self._register_payment(self.advance.account_move_id, 1000.0)
self.assertEqual(self.advance.state, "done")
# ------------------ Clearing --------------------------
with Form(self.env["hr.expense.sheet"]) as sheet:
sheet.name = "Test Clearing"
sheet.employee_id = self.expense_employee
ex_sheet = sheet.save()
ex_sheet.advance_sheet_id = self.advance
self.assertEqual(len(ex_sheet.expense_line_ids), 0)
ex_sheet._onchange_advance_sheet_id()
self.assertEqual(len(ex_sheet.expense_line_ids), 1)
reverse_move = self.advance.account_move_id._reverse_moves(
default_values_list=[
{"invoice_date": self.advance.account_move_id.date, "ref": False}
],
cancel=True,
)
self.assertNotEqual(reverse_move, self.advance.account_move_id)

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_account_payment_search" model="ir.ui.view">
<field name="name">account.payment.search</field>
<field name="model">account.payment</field>
<field name="inherit_id" ref="account.view_account_payment_search" />
<field name="arch" type="xml">
<xpath expr="//search/separator[4]" position="before">
<separator />
<filter
string="Return Advance"
name="return_advance_filter"
domain="[('advance_id', '!=', False)]"
/>
</xpath>
</field>
</record>
<record id="view_account_payment_form" model="ir.ui.view">
<field name="name">account.payment.form</field>
<field name="model">account.payment</field>
<field name="inherit_id" ref="account.view_account_payment_form" />
<field name="arch" type="xml">
<xpath expr="//sheet//group[@name='group2']" position="inside">
<field
name="advance_id"
attrs="{'invisible': [('payment_type', '!=', 'inbound')]}"
/>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="hr_employee_public_view_form" model="ir.ui.view">
<field name="name">hr.employee.public.form</field>
<field name="model">hr.employee.public</field>
<field name="inherit_id" ref="hr.hr_employee_public_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button
name="action_open_advance_clearing"
type="object"
icon="fa-bars"
>
<field name="advance_count" string="Advance" widget="statinfo" />
</button>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_employee_form" model="ir.ui.view">
<field name="name">hr.employee.form</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form" />
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button
name="action_open_advance_clearing"
type="object"
icon="fa-bars"
attrs="{'invisible': [('advance_count', '=', 0)]}"
>
<field name="advance_count" string="Advance" widget="statinfo" />
</button>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- New menus Advance and Expense under My Reports -->
<record id="action_my_hr_advance_sheet" model="ir.actions.act_window">
<field name="name">Advances</field>
<field name="res_model">hr.expense.sheet</field>
<field name="view_mode">tree,kanban,form,pivot,graph,activity</field>
<field name="search_view_id" ref="hr_expense.hr_expense_sheet_view_search" />
<field name="domain">[('state', '!=', 'cancel'), ('advance', '=', True)]</field>
<field
name="context"
>{'search_default_my_reports': 1, 'default_advance': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No advance report found. Let's create one!
</p><p>
Once you have created your advance, submit it to your manager who will validate it.
</p>
</field>
</record>
<record id="action_my_hr_expense_sheet" model="ir.actions.act_window">
<field name="name">Expenses</field>
<field name="res_model">hr.expense.sheet</field>
<field name="view_mode">tree,kanban,form,pivot,graph,activity</field>
<field name="search_view_id" ref="hr_expense.hr_expense_sheet_view_search" />
<field
name="domain"
>[('state', '!=', 'cancel'), ('advance', '=', False)]</field>
<field name="context">{'search_default_my_reports': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No expense report found. Let's create one!
</p><p>
Once you have created your expense, submit it to your manager who will validate it.
</p>
</field>
</record>
<menuitem
id="menu_my_hr_advance_sheet"
sequence="1"
parent="hr_expense.menu_hr_expense_sheet_my_reports"
action="action_my_hr_advance_sheet"
name="Advances"
/>
<menuitem
id="menu_my_hr_expense_sheet"
sequence="2"
parent="hr_expense.menu_hr_expense_sheet_my_reports"
action="action_my_hr_expense_sheet"
name="Expenses"
/>
<!-- End new menus -->
<record id="hr_expense_view_search" model="ir.ui.view">
<field name="name">hr.expense.view.search</field>
<field name="model">hr.expense</field>
<field name="inherit_id" ref="hr_expense.hr_expense_view_search" />
<field name="arch" type="xml">
<separator position="after">
<filter
string="Advance"
name="is_advance"
domain="[('advance', '=', True)]"
/>
<filter
string="Expense"
name="is_expense"
domain="[('advance', '=', False)]"
/>
</separator>
</field>
</record>
<record id="hr_expense_sheet_view_search" model="ir.ui.view">
<field name="name">hr.expense.sheet.view.search</field>
<field name="model">hr.expense.sheet</field>
<field name="inherit_id" ref="hr_expense.hr_expense_sheet_view_search" />
<field name="arch" type="xml">
<separator position="after">
<filter
string="Advance"
name="advance_expense"
domain="[('advance', '=', True)]"
/>
<filter
string="Advance (not cleared)"
name="advance_expense_uncleared"
domain="[('advance', '=', True), ('clearing_residual', '>', 0.0)]"
/>
<filter
string="Clearing"
name="advance_clearing"
domain="[('advance_sheet_id', '!=', False)]"
/>
</separator>
</field>
</record>
<record id="action_hr_expense_sheet_advance_clearing" model="ir.actions.act_window">
<field name="name">Advance Clearing</field>
<field name="res_model">hr.expense.sheet</field>
<field name="view_mode">form</field>
<field name="search_view_id" ref="hr_expense_sheet_view_search" />
<field name="domain">
[('employee_id.user_id', '=', uid), ('state', '!=', 'cancel')]
</field>
<field name="context">{'search_default_my_reports': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">Create a new expense report</p>
<p>
Once you have created your expense, submit it to your manager who will
validate it.
</p>
</field>
</record>
<record id="hr_expense_view_form" model="ir.ui.view">
<field name="name">hr.expense.view.form</field>
<field name="model">hr.expense</field>
<field name="inherit_id" ref="hr_expense.hr_expense_view_form" />
<field name="arch" type="xml">
<h1 position="after">
<field
name="advance"
invisible="not context.get('default_advance')"
readonly="1"
force_save="1"
/>
<label for="advance" invisible="not context.get('default_advance')" />
</h1>
<field name="product_id" position="attributes">
<attribute
name="attrs"
>{'readonly': [('advance', '=', True)]}</attribute>
<attribute name="force_save">1</attribute>
</field>
<field name="product_id" position="after">
<field
name="clearing_product_id"
attrs="{'invisible': [('advance', '=', False)]}"
placeholder="Optional clearing product is used during clear advance"
/>
</field>
<field name="analytic_distribution" position="attributes">
<attribute name="attrs">
{'invisible': [('advance', '!=', False)]}
</attribute>
</field>
</field>
</record>
<record id="view_hr_expense_sheet_tree" model="ir.ui.view">
<field name="name">hr.expense.sheet.tree</field>
<field name="model">hr.expense.sheet</field>
<field name="inherit_id" ref="hr_expense.view_hr_expense_sheet_tree" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="advance_sheet_id" optional="show" />
</field>
<field name="total_amount" position="after">
<field name="clearing_residual" optional="show" />
</field>
</field>
</record>
<record id="view_hr_expense_sheet_form" model="ir.ui.view">
<field name="name">hr.expense.sheet.form</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">
<field name="state" position="before">
<button
name="open_clear_advance"
type="object"
string="Clear Advance"
class="oe_highlight"
attrs="{'invisible': ['|', '|', ('advance', '=', False), ('state', '!=', 'done'), ('clearing_residual', '=', 0.0)]}"
/>
<button
name="action_register_payment"
type="object"
string="Return Advance"
attrs="{'invisible': ['|', '|', ('advance', '=', False), ('state', '!=', 'done'), ('clearing_residual', '=', 0.0)]}"
context="{'hr_return_advance': True}"
groups="account.group_account_user"
/>
</field>
<h1 position="after">
<field
name="advance"
attrs="{'invisible': [('advance', '=', False)]}"
readonly="1"
force_save="1"
/>
<label for="advance" attrs="{'invisible': [('advance', '=', False)]}" />
</h1>
<xpath expr="/form/sheet/group/group" position="after">
<group>
<field name="id" invisible="1" />
<field
name="advance_sheet_id"
attrs="{'invisible': [('advance', '=', True)], 'readonly': [('id', '!=', False)]}"
force_save="1"
/>
<field
name="clearing_residual"
attrs="{'invisible': [('advance', '=', False)]}"
/>
<field
name="advance_sheet_residual"
attrs="{'invisible': [('advance_sheet_id', '=', False)]}"
/>
</group>
</xpath>
<xpath
expr="//field[@name='expense_line_ids']/tree/field[@name='name']"
position="after"
>
<field name="employee_id" invisible="1" />
<field name="payment_mode" invisible="1" />
<field name="advance" invisible="1" />
<field name="product_id" invisible="1" />
<field name="product_uom_id" invisible="1" />
<field name="product_uom_category_id" invisible="1" />
<field
name="clearing_product_id"
attrs="{'column_invisible': [('parent.advance', '=', False)]}"
/>
<field name="av_line_id" invisible="1" />
</xpath>
<xpath expr="//field[@name='expense_line_ids']" position="attributes">
<attribute
name="context"
>{'default_advance': advance, 'search_default_is_advance': advance, 'search_default_is_expense': not advance, 'form_view_ref' : 'hr_expense.hr_expense_view_form_without_header', 'default_company_id': company_id, 'default_employee_id': employee_id}</attribute>
<attribute
name="attrs"
>{'readonly': [('id', '=', False), ('advance_sheet_id', '!=', False)]}</attribute>
<attribute name="force_save">True</attribute>
</xpath>
<xpath
expr="//field[@name='expense_line_ids']/tree/field[@name='unit_amount']"
position="attributes"
>
<attribute name="force_save">True</attribute>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<button
name="action_open_clearings"
class="oe_stat_button"
icon="fa-file-text-o"
type="object"
attrs="{'invisible': [('advance', '=', False)]}"
>
<field name="clearing_count" widget="statinfo" string="Clearings" />
</button>
</xpath>
</field>
</record>
</odoo>

View file

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

View file

@ -0,0 +1,158 @@
# Copyright 2020 Ecosoft Co., Ltd (https://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from odoo import _, api, models
from odoo.exceptions import UserError
from odoo.models import BaseModel
from odoo.tools import float_compare
class AccountPaymentRegister(models.TransientModel):
_inherit = "account.payment.register"
def _get_default_advance(self, fields_list):
"""Call default_get from BaseModel"""
defaults = BaseModel.default_get(self, fields_list)
return defaults
def _default_return_advance(self, fields_list):
"""OVERRIDE: lines without check account_internal_type for return advance only"""
res = self._get_default_advance(fields_list)
if "line_ids" in fields_list:
lines = (
self.env["account.move"]
.browse(self._context.get("active_ids", []))
.line_ids
)
# Keep lines having a residual amount to pay.
available_lines = self.env["account.move.line"]
for line in lines:
if line.move_id.state != "posted":
raise UserError(
_("You can only register payment for posted journal entries.")
)
if not line.product_id:
continue
if line.currency_id:
if line.currency_id.is_zero(line.amount_residual_currency):
continue
else:
if line.company_currency_id.is_zero(line.amount_residual):
continue
available_lines |= line
# Check.
if not available_lines:
raise UserError(
_(
"You can't register a payment because "
"there is nothing left to pay on the selected journal items."
)
)
if len(lines.company_id) > 1:
raise UserError(
_(
"You can't create payments for entries belonging "
"to different companies."
)
)
res["line_ids"] = [(6, 0, available_lines.ids)]
return res
@api.model
def default_get(self, fields_list):
if self._context.get("hr_return_advance", False):
return self._default_return_advance(fields_list)
return super().default_get(fields_list)
def _get_product_advance(self):
return self.env.ref("hr_expense_advance_clearing.product_emp_advance", False)
def _validate_over_return(self):
"""Actual remaining = amount to clear - clear pending
and it is not legit to return more than remaining"""
clearings = (
self.env["hr.expense.sheet"]
.browse(self.env.context.get("clearing_sheet_ids", []))
.filtered(lambda l: l.state == "approve")
)
amount_not_clear = sum(clearings.mapped("total_amount"))
actual_remaining = self.source_amount_currency - amount_not_clear
more_info = ""
symbol = self.source_currency_id.symbol
if amount_not_clear:
more_info = _("\nNote: pending amount clearing is %(symbol)s%(amount)s") % {
"symbol": symbol,
"amount": "{:,.2f}".format(amount_not_clear),
}
if float_compare(self.amount, actual_remaining, 2) == 1:
raise UserError(
_(
"You cannot return advance more than actual remaining "
"(%(symbol)s%(amount)s)%(more_info)s"
)
% {
"symbol": symbol,
"amount": "{:,.2f}".format(actual_remaining),
"more_info": more_info,
}
)
def action_create_payments(self):
if self._context.get("hr_return_advance", False):
self._validate_over_return()
self.expense_post_return_advance()
return {"type": "ir.actions.act_window_close"}
return super().action_create_payments()
def expense_post_return_advance(self):
"""This is opposite operation of action_create_payments(),
it return remaining advance from employee back to company
"""
self.ensure_one()
context = dict(self._context or {})
active_ids = context.get("active_ids", [])
move_ids = self.env["account.move"].browse(active_ids)
ctx = self._context.copy()
ctx.update({"skip_account_move_synchronization": True})
expense_sheet = move_ids.line_ids.expense_id.sheet_id
emp_advance = self._get_product_advance()
advance_account = emp_advance.property_account_expense_id
# Create return advance and post it
batches = self._get_batches()
first_batch_result = batches[0]
payment_vals = self._create_payment_vals_from_wizard(first_batch_result)
# Set new payment_type and payment entry to be Dr Bank, Cr Advance
payment_vals["advance_id"] = expense_sheet.id
payment_vals["partner_type"] = "customer"
payment_vals["destination_account_id"] = advance_account.id
payment_vals_list = [payment_vals]
payment = (
self.env["account.payment"].with_context(**ctx).create(payment_vals_list)
)
payment.action_post()
redirect_link = (
f"<a href=# data-oe-model=account.payment data-oe-id={payment.id}>"
f"{payment.name}</a>"
) # Account Payment link
# Log the return advance in the chatter
body = _(
"A remaining advance return of %(amount)s %(symbol)s with the reference "
"%(ref)s related to your expense %(name)s has been made."
) % {
"amount": payment.amount,
"symbol": payment.currency_id.symbol,
"ref": redirect_link,
"name": expense_sheet.name,
}
expense_sheet.message_post(body=body)
# Reconcile the return advance and the advance,
# i.e. lookup on the advance account on move lines
account_move_lines_to_reconcile = self.env["account.move.line"]
for line in payment.move_id.line_ids + expense_sheet.account_move_id.line_ids:
if line.account_id == advance_account and not line.reconciled:
account_move_lines_to_reconcile |= line
res = account_move_lines_to_reconcile.with_context(**ctx).reconcile()
return res

View file

@ -0,0 +1,42 @@
[project]
name = "odoo-bringout-oca-hr-expense-hr_expense_advance_clearing"
version = "16.0.0"
description = "Employee Advance and Clearing - 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_advance_clearing"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]