Metadata-Version: 2.1
Name: odoo-addon-l10n_ro_stock_account
Version: 19.0.1.4.0.1
Requires-Dist: odoo-addon-l10n_ro_stock==19.0.*
Requires-Dist: odoo==19.0.*
Summary: Romania - Stock Accounting
Home-page: https://github.com/OCA/l10n-romania
License: AGPL-3
Author: NextERP Romania,Dorin Hongu,Forest and Biomass Romania,Odoo Community Association (OCA)
Author-email: support@odoo-community.org
Classifier: Programming Language :: Python
Classifier: Framework :: Odoo
Classifier: Framework :: Odoo :: 19.0
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Classifier: Development Status :: 6 - Mature
Description-Content-Type: text/x-rst

.. image:: https://odoo-community.org/readme-banner-image
   :target: https://odoo-community.org/get-involved?utm_source=readme
   :alt: Odoo Community Association

==========================
Romania - Stock Accounting
==========================

.. 
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   !! This file is generated by oca-gen-addon-readme !!
   !! changes will be overwritten.                   !!
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   !! source digest: sha256:a44d806e6eeb20e5a64ee46ddded0c33a10e8d0fed0d5be1364e54bf338712a6
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
    :target: https://odoo-community.org/page/development-status
    :alt: Mature
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
    :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
    :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--romania-lightgray.png?logo=github
    :target: https://github.com/OCA/l10n-romania/tree/19.0/l10n_ro_stock_account
    :alt: OCA/l10n-romania
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
    :target: https://translation.odoo-community.org/projects/l10n-romania-19-0/l10n-romania-19-0-l10n_ro_stock_account
    :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/l10n-romania&target_branch=19.0
    :alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module provides Romanian-specific stock accounting features that
align with Romanian accounting standards and regulations. Below are the
configuration options available.

Overview
--------

The module extends Odoo's standard stock accounting to meet Romanian
accounting requirements, providing:

- Location-specific accounting configurations
- Romanian-specific stock valuation accounts
- Product category stock account customization
- Warehouse fiscal position management
- Specialized accounts for stock operations
- Per-location FIFO valuation (vs. Odoo's default company-wide FIFO)
- Automatic negative stock compensation for FIFO products

Per-location FIFO
-----------------

For products with ``cost_method=fifo``, the module values outgoing moves
against the FIFO stack of the **source location** rather than the
company-wide stack. Each outgoing move is automatically split into one
``stock.move`` per FIFO layer (e.g. an outgoing of 4 units from a
location with ``IN 2@10`` + ``IN 3@8`` produces a ``2x10`` move + a
``2x8`` move).

Internal transfers (``internal → internal`` or via transit) are treated
as both ``is_in`` and ``is_out`` on the same move:

- they consume from the FIFO stack of the source location,
- they enter the FIFO stack of the destination location with the value
  pulled from the source,
- they generate an accounting entry through the location's valuation
  account (or the company-level transfer account if locations share an
  account).

Controlled by ``res.company.fifo_per_location`` (defaults to ``True``
for Romanian companies, computed from ``country_id``, editable per
company).

Negative stock compensation
---------------------------

When a FIFO outgoing move happens before the corresponding incoming move
(i.e. the location FIFO stack is empty), the outgoing value falls back
to the product's ``standard_price``. The pending quantity is tracked on
the outgoing move via ``fifo_neg_pending_qty`` /
``fifo_neg_origin_value``.

When the next matching incoming move is posted, the module:

1. allocates the new incoming value across pending outgoing moves
   (FIFO);
2. updates ``stock.move.value`` on the outgoing moves to reflect the
   real purchase price;
3. emits an ``account.move`` correction that debits the variation/COGS
   account and credits the stock valuation account for the delta;
4. links that correction back to the originating IN move via
   ``account.move.fifo_neg_origin_move_id`` for traceability.

Compensation is idempotent — if ``_set_value`` is re-invoked on the same
IN move (e.g. when the supplier invoice is posted), the existing
compensation is detected and not duplicated.

Controlled by ``res.company.fifo_location_negative_compensation``
(defaults to ``True`` for Romanian companies, editable per company).

Performance notes
-----------------

- Partial composite index on
  ``stock_move(product_id, location_dest_id, date DESC, id DESC) WHERE state='done' AND is_in=true``
  powers the FIFO stack lookup with index-only scans on large histories.
- Partial index on ``stock_move(...) WHERE fifo_neg_pending_qty > 0``
  keeps the compensation search constant-time even with millions of
  historical moves.
- A request-scoped cache (``context['fifo_stack_cache']``) reuses the
  same ``_run_fifo_get_stack`` result across batched lookups in
  ``product._compute_value`` and ``stock.quant._compute_value`` — large
  Inventory Valuation reports drop from O(N) queries to O(distinct
  (product, location)) queries.

**Table of contents**

.. contents::
   :local:

Changelog
=========

19.0.1.3.0
----------

- Value an internal transfer at the cost the source warehouse actually
  holds for the product, instead of the product's global average. Both
  legs of the transfer entry are built from a single
  ``stock.move.value``, so they can never diverge on this series - what
  was wrong is the amount itself: a transfer between two warehouses took
  out of the source warehouse the average computed over *all*
  warehouses. When that average was higher than what the source
  warehouse held, the warehouse was left with value and no quantity to
  carry it (and the other way round when it was lower), which is what
  the storage sheet shows per warehouse. The accounting stayed balanced
  throughout, only the per-warehouse valuation was off.
- The new ``_l10n_ro_get_source_account_unit_cost`` rebuilds that cost
  from the done moves in and out of the locations sharing the source
  valuation account. It is plugged into ``_get_value_from_std_price``,
  the last step of the standard valuation chain, so a value coming from
  a bill, a quotation, a return or a landed cost keeps priority exactly
  as before; only the fallback to the product's global cost is replaced.
  FIFO and lot valued products are left alone - there the cost already
  comes from the layers or from the lot - and so are source locations
  without a valuation account of their own, where there is no
  per-warehouse cost to follow.
- Same defect as the one fixed on 18.0 by
  ``_l10n_ro_get_source_account_unit_cost`` in 18.0.1.29.0, but with a
  different mechanism: on this series the valuation layer is gone and
  the value lives on the move.

19.0.1.1.1
----------

- Fix silent over-delivery in ``stock_move._split_for_fifo_assignment``:
  it walked the per-location FIFO stack for
  ``product_uom_qty``/``product_qty`` - the *ordered* demand - instead
  of ``quantity``, the amount actually being shipped on this transfer.
  Reducing ``quantity`` below the ordered demand so the remainder
  backorders is the normal Odoo workflow (core's own
  ``_create_backorder`` compares ``quantity`` against
  ``product_uom_qty`` for exactly this); ``product_uom_qty`` is supposed
  to stay at the full order. Consuming/valuing FIFO layers against the
  full order instead of the actual shipped quantity meant that whenever
  satisfying the (wrongly inflated) target required more than one price
  layer, the split created an extra ``stock.move`` for the difference
  and shipped it too - delivering the full original demand regardless of
  what was actually picked, with no backorder. When a single layer
  happened to cover the full order the bug was silent (wrong valuation,
  same visible outcome). The split now walks the stack for ``quantity``
  (what's actually shipping), matching what core already uses for its
  own backorder decision; a consistency check raises a clear error
  instead of silently completing the transfer if the amount accounted
  for by the split still doesn't match.

19.0.1.0.0
----------

- Recognise the exchange rate difference on the 408 pivot (*Furnizori -
  facturi nesosite*) when a reception on notice
  (``picking.l10n_ro_notice``) comes from a purchase order in a foreign
  currency. Until now the 408 leg of the notice entry was booked in
  company currency only, so the order currency was lost and nothing
  could compute the rate delta: it stayed as a silent balance on 408, a
  manual reconciliation could not clear it, and the stock ledger drifted
  away from the stock account by that same delta.
- The 408 leg now keeps the order currency, since the estimated
  liability is a monetary item, while the stock leg stays in company
  currency at the reception rate. When the invoice is posted, the rate
  delta on the quantity already received is booked as
  ``Dr 408 / Cr 765`` (favourable) or ``Cr 408 / Dr 665`` (unfavourable)
  - per OMFP 1802/2014 the function of account 408 lists exactly these
  differences as "recorded when the invoice is received". The lines are
  ``cogs`` lines on the bill, so the invoice total is untouched, they
  stay out of the e-invoice and they are removed when the bill is reset
  to draft.
- Account 408 therefore does **not** need to be reconcilable: the pivot
  closes by document, not by matching amounts. No reconciliation is
  attempted.
- ``_get_value_from_bill`` keeps the reception rate for the quantity
  received on notice, so inventory is no longer revalued for exchange
  rate movements (IAS 21 / OMFP 1802: a non-monetary asset is not
  retranslated) and the stock ledger agrees with the stock account. Only
  the quantity invoiced beyond the reception - a genuine price
  difference, whose liability arises at the invoice date - is taken at
  the invoice rate.

19.0.0.26.1
-----------

- Expose the ``stock.move.l10n_ro_move_type`` selection as the module
  level ``MOVE_TYPE`` constant, so other modules can reuse it instead of
  duplicating the list. Up to 18.0 the same list was available as
  ``VALUED_TYPE`` on ``stock.valuation.layer``. No functional change.

19.0.0.25.1
-----------

- Fix ``IndexError: list index out of range`` in
  ``stock_move._l10n_ro_process_fifo_split`` when validating an outgoing
  move. An incoming move with nothing left to consume (its valued
  quantity is zero, for instance a reception corrected to 0 after
  validation) still entered the per-location FIFO stack; ``_split``
  returns no values for a quantity that is zero at the UoM rounding, so
  indexing its result crashed the transfer. Such moves no longer enter
  the stack, zero-quantity slices are skipped by the outgoing split, and
  the quantities are compared with the UoM rounding instead of raw
  floats.

19.0.0.19.1
-----------

- Fix
  ``TypeError: '<' not supported between instances of 'bool' and 'str'``
  in ``stock_move._compute_account`` when sorting the account move
  lines. A journal item without an account (or whose account has no
  code) returns ``False`` for ``account_id.code``, which cannot be
  compared against the string codes of the other lines. The sort key now
  falls back to an empty string, and the subsequent ``code[0]`` check
  guards against an empty/falsy code.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/l10n-romania/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/l10n-romania/issues/new?body=module:%20l10n_ro_stock_account%0Aversion:%2019.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
-------

* NextERP Romania
* Dorin Hongu
* Forest and Biomass Romania

Contributors
------------

- `NextERP Romania <https://www.nexterp.ro>`__:

  - Fekete Mihai <feketemihai@nexterp.ro>
  - Alexandru Teodor <teodoralexandru@nexterp.ro>

- `Terrabit <https://www.terrabit.ro>`__:

  - Dorin Hongu <dhongu@gmail.com>

Do not contact contributors directly about support or help with
technical issues.

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-dhongu| image:: https://github.com/dhongu.png?size=40px
    :target: https://github.com/dhongu
    :alt: dhongu
.. |maintainer-feketemihai| image:: https://github.com/feketemihai.png?size=40px
    :target: https://github.com/feketemihai
    :alt: feketemihai

Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-dhongu| |maintainer-feketemihai| 

This module is part of the `OCA/l10n-romania <https://github.com/OCA/l10n-romania/tree/19.0/l10n_ro_stock_account>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
