From 327334658253ca4014a1cd964be072963a22d750 Mon Sep 17 00:00:00 2001 From: Darshan Patel Date: Mon, 18 Jan 2016 14:37:44 +0530 Subject: [PATCH 1/3] Added stock_account OU module Added Test Cases. Improved code for test cases Migrated Valuation method of quants. Migrated Valuation method _account_entry_move of quants. Completed test cases and modified valuation method --- stock_account_operating_unit/README.rst | 93 ++++ stock_account_operating_unit/__init__.py | 2 + stock_account_operating_unit/__manifest__.py | 19 + stock_account_operating_unit/i18n/es.po | 38 ++ .../i18n/stock_account_operating_unit.pot | 33 ++ .../model/__init__.py | 2 + .../model/stock_move.py | 124 +++++ .../readme/CONFIGURATION.rst | 11 + .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 4 + stock_account_operating_unit/readme/USAGE.rst | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 443 ++++++++++++++++++ .../tests/__init__.py | 2 + .../test_stock_account_operating_unit.py | 369 +++++++++++++++ 15 files changed, 1146 insertions(+) create mode 100644 stock_account_operating_unit/README.rst create mode 100644 stock_account_operating_unit/__init__.py create mode 100644 stock_account_operating_unit/__manifest__.py create mode 100644 stock_account_operating_unit/i18n/es.po create mode 100644 stock_account_operating_unit/i18n/stock_account_operating_unit.pot create mode 100644 stock_account_operating_unit/model/__init__.py create mode 100644 stock_account_operating_unit/model/stock_move.py create mode 100644 stock_account_operating_unit/readme/CONFIGURATION.rst create mode 100644 stock_account_operating_unit/readme/CONTRIBUTORS.rst create mode 100644 stock_account_operating_unit/readme/DESCRIPTION.rst create mode 100644 stock_account_operating_unit/readme/USAGE.rst create mode 100644 stock_account_operating_unit/static/description/icon.png create mode 100644 stock_account_operating_unit/static/description/index.html create mode 100644 stock_account_operating_unit/tests/__init__.py create mode 100644 stock_account_operating_unit/tests/test_stock_account_operating_unit.py diff --git a/stock_account_operating_unit/README.rst b/stock_account_operating_unit/README.rst new file mode 100644 index 0000000000..f45d6365fb --- /dev/null +++ b/stock_account_operating_unit/README.rst @@ -0,0 +1,93 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +======================================= +Stock account moves with Operating Unit +======================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:872054dcf798ba84e28378c2656a5fc15a5ae4347137521a870e9e464a3d80ac + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Foperating--unit-lightgray.png?logo=github + :target: https://github.com/OCA/operating-unit/tree/15.0/stock_account_operating_unit + :alt: OCA/operating-unit +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/operating-unit-15-0/operating-unit-15-0-stock_account_operating_unit + :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/operating-unit&target_branch=15.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module introduces the following features: + +- Creates account move lines when stock moves are posted between internal + locations within the same company, but different OU’s. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Create stock moves between internal locations within the same company, but +different OU’s. The journal entries are created and they are self-balanced +within the OU when the journal entries are posted + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ForgeFlow +* Serpent Consulting Services Pvt. Ltd. + +Contributors +~~~~~~~~~~~~ + +* ForgeFlow, S.L. +* Serpent Consulting Services Pvt. Ltd. +* Jarsa Sistemas + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/operating-unit `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_account_operating_unit/__init__.py b/stock_account_operating_unit/__init__.py new file mode 100644 index 0000000000..50170638d0 --- /dev/null +++ b/stock_account_operating_unit/__init__.py @@ -0,0 +1,2 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from . import model diff --git a/stock_account_operating_unit/__manifest__.py b/stock_account_operating_unit/__manifest__.py new file mode 100644 index 0000000000..5dc24ae4d6 --- /dev/null +++ b/stock_account_operating_unit/__manifest__.py @@ -0,0 +1,19 @@ +# © 2019 ForgeFlow, S.L. +# - Jordi Ballester Alomar +# © 2019 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Stock account moves with Operating Unit", + "summary": "Create journal entries in moves between internal locations " + "with different operating units.", + "version": "15.0.1.0.0", + "category": "Generic Modules/Sales & Purchases", + "author": "ForgeFlow, " + "Serpent Consulting Services Pvt. Ltd.," + "Odoo Community Association (OCA)", + "license": "LGPL-3", + "website": "https://github.com/OCA/operating-unit", + "depends": ["stock_operating_unit", "account_operating_unit", "stock_account"], + "installable": True, +} diff --git a/stock_account_operating_unit/i18n/es.po b/stock_account_operating_unit/i18n/es.po new file mode 100644 index 0000000000..19e497b745 --- /dev/null +++ b/stock_account_operating_unit/i18n/es.po @@ -0,0 +1,38 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_account_operating_unit +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-03-14 11:17+0000\n" +"Last-Translator: Javier Colmenero \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: stock_account_operating_unit +#: code:addons/stock_account_operating_unit/model/stock_move.py:0 +#, python-format +msgid "%s - OU Move" +msgstr "%s - movimiento unidad operacional" + +#. module: stock_account_operating_unit +#: model:ir.model,name:stock_account_operating_unit.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de stock" + +#. module: stock_account_operating_unit +#: code:addons/stock_account_operating_unit/model/stock_move.py:0 +#, python-format +msgid "" +"You cannot create stock moves involving separate source and destination " +"accounts related to different operating units." +msgstr "" +"No puedes crear movimientos de stock, involucrando distintos orígines y " +"destinos asociados a unidades operacionales diferentes." diff --git a/stock_account_operating_unit/i18n/stock_account_operating_unit.pot b/stock_account_operating_unit/i18n/stock_account_operating_unit.pot new file mode 100644 index 0000000000..ed4538c694 --- /dev/null +++ b/stock_account_operating_unit/i18n/stock_account_operating_unit.pot @@ -0,0 +1,33 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_account_operating_unit +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.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: stock_account_operating_unit +#: code:addons/stock_account_operating_unit/model/stock_move.py:0 +#, python-format +msgid "%s - OU Move" +msgstr "" + +#. module: stock_account_operating_unit +#: model:ir.model,name:stock_account_operating_unit.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: stock_account_operating_unit +#: code:addons/stock_account_operating_unit/model/stock_move.py:0 +#, python-format +msgid "" +"You cannot create stock moves involving separate source and destination " +"accounts related to different operating units." +msgstr "" diff --git a/stock_account_operating_unit/model/__init__.py b/stock_account_operating_unit/model/__init__.py new file mode 100644 index 0000000000..6ac287cbfc --- /dev/null +++ b/stock_account_operating_unit/model/__init__.py @@ -0,0 +1,2 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from . import stock_move diff --git a/stock_account_operating_unit/model/stock_move.py b/stock_account_operating_unit/model/stock_move.py new file mode 100644 index 0000000000..5163037bcb --- /dev/null +++ b/stock_account_operating_unit/model/stock_move.py @@ -0,0 +1,124 @@ +# © 2019 ForgeFlow, S.L. +# - Jordi Ballester Alomar +# © 2019 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo import _, exceptions, models + + +class StockMove(models.Model): + _inherit = "stock.move" + + def _generate_valuation_lines_data( + self, + partner_id, + qty, + debit_value, + credit_value, + debit_account_id, + credit_account_id, + description, + ): + res = super(StockMove, self)._generate_valuation_lines_data( + partner_id, + qty, + debit_value, + credit_value, + debit_account_id, + credit_account_id, + description, + ) + if res: + debit_line_vals = res.get("debit_line_vals") + credit_line_vals = res.get("credit_line_vals") + price_diff_line_vals = res.get("price_diff_line_vals", {}) + + if ( + self.operating_unit_id + and self.operating_unit_dest_id + and self.operating_unit_id != self.operating_unit_dest_id + and debit_line_vals["account_id"] != credit_line_vals["account_id"] + ): + raise exceptions.UserError( + _( + "You cannot create stock moves involving separate source" + " and destination accounts related to different " + "operating units." + ) + ) + + if not self.operating_unit_dest_id and not self.operating_unit_id: + ou_id = ( + self.picking_id.picking_type_id.warehouse_id.operating_unit_id.id + ) + else: + ou_id = False + + debit_line_vals["operating_unit_id"] = ( + ou_id or self.operating_unit_dest_id.id or self.operating_unit_id.id + ) + credit_line_vals["operating_unit_id"] = ( + ou_id or self.operating_unit_id.id or self.operating_unit_dest_id.id + ) + rslt = { + "credit_line_vals": credit_line_vals, + "debit_line_vals": debit_line_vals, + } + if price_diff_line_vals: + price_diff_line_vals["operating_unit_id"] = ( + ou_id or self.operating_unit_id.id or self.operating_unit_dest_id.id + ) + rslt["price_diff_line_vals"] = price_diff_line_vals + return rslt + return res + + def _action_done(self, cancel_backorder=False): + """ + Generate accounting moves if the product being moved is subject + to real_time valuation tracking, + and the source or destination location are + a transit location or is outside of the company or the source or + destination locations belong to different operating units. + """ + res = super(StockMove, self)._action_done(cancel_backorder) + for move in self: + + if move.product_id.valuation == "real_time": + # Inter-operating unit moves do not accept to + # from/to non-internal location + if ( + move.location_id.company_id + and move.location_id.company_id == move.location_dest_id.company_id + and move.operating_unit_id != move.operating_unit_dest_id + ): + ( + journal_id, + acc_src, + acc_dest, + acc_valuation, + ) = move._get_accounting_data_for_valuation() + + move_lines = move._prepare_account_move_line( + move.product_qty, + move.product_id.standard_price, + acc_valuation, + acc_valuation, + _("%s - OU Move") % move.product_id.display_name, + ) + am = ( + self.env["account.move"] + .with_context( + company_id=move.company_id.id, + ) + .create( + { + "journal_id": journal_id, + "line_ids": move_lines, + "company_id": move.company_id.id, + "ref": move.picking_id and move.picking_id.name, + "stock_move_id": move.id, + } + ) + .with_company(move.location_id.company_id.id) + ) + am.action_post() + return res diff --git a/stock_account_operating_unit/readme/CONFIGURATION.rst b/stock_account_operating_unit/readme/CONFIGURATION.rst new file mode 100644 index 0000000000..a4a154d498 --- /dev/null +++ b/stock_account_operating_unit/readme/CONFIGURATION.rst @@ -0,0 +1,11 @@ +If your company is required to generate a balanced balance sheet by +operating unit you can specify at company level that operating units should +be self-balanced, and then indicate a self-balancing clearing account. + +#. Create an account for "Inter-OU Clearing" of type Regular. +#. Go to *Settings / Companies / Configuration* and: + + * Set the "Operating Units are self-balanced" checkbox. + * Set the "Inter-OU Clearing" account in "Inter-operating unit clearing + account" field. +#. Assign Operating Unit in Accounts. diff --git a/stock_account_operating_unit/readme/CONTRIBUTORS.rst b/stock_account_operating_unit/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..6b63c1ca0f --- /dev/null +++ b/stock_account_operating_unit/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* ForgeFlow, S.L. +* Serpent Consulting Services Pvt. Ltd. +* Jarsa Sistemas diff --git a/stock_account_operating_unit/readme/DESCRIPTION.rst b/stock_account_operating_unit/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..2e9ddaf403 --- /dev/null +++ b/stock_account_operating_unit/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This module introduces the following features: + +- Creates account move lines when stock moves are posted between internal + locations within the same company, but different OU’s. diff --git a/stock_account_operating_unit/readme/USAGE.rst b/stock_account_operating_unit/readme/USAGE.rst new file mode 100644 index 0000000000..419dbd3b53 --- /dev/null +++ b/stock_account_operating_unit/readme/USAGE.rst @@ -0,0 +1,3 @@ +Create stock moves between internal locations within the same company, but +different OU’s. The journal entries are created and they are self-balanced +within the OU when the journal entries are posted diff --git a/stock_account_operating_unit/static/description/icon.png b/stock_account_operating_unit/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/stock_account_operating_unit/static/description/index.html b/stock_account_operating_unit/static/description/index.html new file mode 100644 index 0000000000..bcd61a5c59 --- /dev/null +++ b/stock_account_operating_unit/static/description/index.html @@ -0,0 +1,443 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Stock account moves with Operating Unit

+ +

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runboat

+

This module introduces the following features:

+
    +
  • Creates account move lines when stock moves are posted between internal +locations within the same company, but different OU’s.
  • +
+

Table of contents

+ +
+

Usage

+

Create stock moves between internal locations within the same company, but +different OU’s. The journal entries are created and they are self-balanced +within the OU when the journal entries are posted

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
  • Serpent Consulting Services Pvt. Ltd.
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/operating-unit project on GitHub.

+

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

+
+
+
+
+ + diff --git a/stock_account_operating_unit/tests/__init__.py b/stock_account_operating_unit/tests/__init__.py new file mode 100644 index 0000000000..604c5f9c2e --- /dev/null +++ b/stock_account_operating_unit/tests/__init__.py @@ -0,0 +1,2 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from . import test_stock_account_operating_unit diff --git a/stock_account_operating_unit/tests/test_stock_account_operating_unit.py b/stock_account_operating_unit/tests/test_stock_account_operating_unit.py new file mode 100644 index 0000000000..13a0cd68d8 --- /dev/null +++ b/stock_account_operating_unit/tests/test_stock_account_operating_unit.py @@ -0,0 +1,369 @@ +# © 2019 ForgeFlow, S.L. +# - Jordi Ballester Alomar +# © 2019 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo.tests import Form + +from odoo.addons.stock.tests.common import TestStockCommon + + +class TestStockAccountOperatingUnit(TestStockCommon): + def setUp(self): + super(TestStockAccountOperatingUnit, self).setUp() + self.res_groups = self.env["res.groups"] + self.res_users_model = self.env["res.users"] + self.aml_model = self.env["account.move.line"] + self.account_model = self.env["account.account"] + self.product_model = self.env["product.product"] + self.product_cteg_model = self.env["product.category"] + self.acc_type_model = self.env["account.account.type"] + self.operating_unit_model = self.env["operating.unit"] + self.company_model = self.env["res.company"] + self.move_model = self.env["stock.move"] + self.picking_model = self.env["stock.picking"] + + # Company + self.company = self.env.ref("base.main_company") + self.group_stock_manager = self.env.ref("stock.group_stock_manager") + self.grp_acc_user = self.env.ref("account.group_account_invoice") + self.grp_stock_user = self.env.ref("stock.group_stock_user") + # Main Operating Unit + self.ou1 = self.env.ref("operating_unit.main_operating_unit") + # B2B Operating Unit + self.b2b = self.env.ref("operating_unit.b2b_operating_unit") + # B2C Operating Unit + self.b2c = self.env.ref("operating_unit.b2c_operating_unit") + # Partner + self.partner1 = self.env.ref("base.res_partner_1") + self.stock_location_stock = self.env.ref("stock.stock_location_stock") + self.supplier_location = self.env.ref("stock.stock_location_suppliers") + + # Create user1 + self.user1 = self._create_user( + "stock_account_user_1", + [self.grp_stock_user, self.grp_acc_user, self.group_stock_manager], + self.company, + [self.ou1, self.b2c], + ) + # Create user2 + self.user2 = self._create_user( + "stock_account_user_2", + [self.grp_stock_user, self.grp_acc_user, self.group_stock_manager], + self.company, + [self.b2c], + ) + # Create account for Goods Received Not Invoiced + name = "Goods Received Not Invoiced" + code = "grni" + acc_type = self.env.ref("account.data_account_type_equity") + self.account_grni = self._create_account(acc_type, name, code, self.company) + # Create account for Cost of Goods Sold + name = "Cost of Goods Sold" + code = "cogs" + acc_type = self.env.ref("account.data_account_type_expenses") + self.account_cogs_id = self._create_account(acc_type, name, code, self.company) + # Create account for Inventory + name = "Inventory" + code = "inventory" + acc_type = self.env.ref("account.data_account_type_fixed_assets") + self.account_inventory = self._create_account( + acc_type, name, code, self.company + ) + # Create account for Inter-OU Clearing + name = "Inter-OU Clearing" + code = "inter_ou" + acc_type = self.env.ref("account.data_account_type_equity") + self.account_inter_ou_clearing = self._create_account( + acc_type, name, code, self.company + ) + # Update company data + self.company.write( + { + "inter_ou_clearing_account_id": self.account_inter_ou_clearing.id, + "ou_is_self_balanced": True, + } + ) + + # Create Product + self.product = self._create_product() + # Create incoming stock picking type + self.incoming_id = self.env.ref("stock.warehouse0").in_type_id + # Create incoming and internal stock picking types + b2c_wh = self.env.ref("stock_operating_unit.stock_warehouse_b2c") + b2c_wh.lot_stock_id.write({"operating_unit_id": self.b2c.id}) + self.location_b2c_id = b2c_wh.lot_stock_id + self.b2c_type_in_id = b2c_wh.in_type_id + self.b2c_type_int_id = b2c_wh.int_type_id + + def _create_user(self, login, groups, company, operating_units): + """Create a user.""" + group_ids = [group.id for group in groups] + user = self.res_users_model.create( + { + "name": "Test Stock Account User", + "login": login, + "password": "demo", + "email": "example@yourcompany.com", + "company_id": company.id, + "company_ids": [(4, company.id)], + "operating_unit_ids": [(4, ou.id) for ou in operating_units], + "groups_id": [(6, 0, group_ids)], + } + ) + return user + + def _create_account(self, acc_type, name, code, company): + """Create an account.""" + account = self.account_model.create( + { + "name": name, + "code": code, + "user_type_id": acc_type.id, + "company_id": company.id, + } + ) + return account + + def _create_product(self): + """Create a Product with inventory valuation set to auto.""" + product_cteg = self.product_cteg_model.create( + { + "name": "test_product_ctg", + "property_valuation": "real_time", + "property_stock_valuation_account_id": self.account_inventory.id, + "property_stock_account_input_categ_id": self.account_grni.id, + "property_stock_account_output_categ_id": self.account_cogs_id, + } + ) + product = self.product_model.create( + { + "name": "test_product", + "categ_id": product_cteg.id, + "type": "product", + "list_price": 1.0, + "standard_price": 1.0, + } + ) + return product + + def _create_picking(self, user, ou_id, picking_type, src_loc_id, dest_loc_id): + """Create a Picking.""" + picking = self.picking_model.with_user(user.id).create( + { + "picking_type_id": picking_type.id, + "location_id": src_loc_id.id, + "location_dest_id": dest_loc_id.id, + "operating_unit_id": ou_id.id, + } + ) + self.move_model.with_user(user.id).create( + { + "name": "a move", + "product_id": self.product.id, + "product_uom_qty": 1.0, + "product_uom": 1, + "picking_id": picking.id, + "location_id": src_loc_id.id, + "location_dest_id": dest_loc_id.id, + } + ) + return picking + + def _confirm_receive(self, user_id, picking): + """ + Checks the stock availability, validates and process the stock picking. + """ + picking.action_confirm() + picking.action_assign() + res = picking.with_user(user_id).button_validate() + wiz = Form( + self.env[res["res_model"]].with_context(**res["context"]), + view=self.env.ref("stock.view_immediate_transfer"), + ).save() + wiz.process() + + def _check_account_balance( + self, account_id, operating_unit=None, expected_balance=0.0 + ): + """ + Check the balance of the account based on different operating units. + """ + domain = [("account_id", "=", account_id)] + if operating_unit: + domain.extend([("operating_unit_id", "=", operating_unit.id)]) + + balance = self._get_balance(domain) + if operating_unit: + self.assertEqual( + balance, + expected_balance, + "Balance is not %s for Operating Unit %s." + % (str(expected_balance), operating_unit.name), + ) + else: + self.assertEqual( + balance, + expected_balance, + "Balance is not %s for all Operating Units." % str(expected_balance), + ) + + def _get_balance(self, domain): + """ + Call read_group method and return the balance of particular account. + """ + aml_rec = self.aml_model.read_group( + domain, ["debit", "credit", "account_id"], ["account_id"] + ) + if aml_rec: + return aml_rec[0].get("debit", 0.0) - aml_rec[0].get("credit", 0.0) + else: + return 0.0 + + def test_pickings(self): + """Test account balances during receiving stock into the main + operating unit, then into b2c operating unit, and then transfer stock + from main ou to b2c.""" + # Create Incoming Shipment 1 + self.picking = self._create_picking( + self.user1, + self.ou1, + self.incoming_id, + self.supplier_location, + self.stock_location_stock, + ) + # Receive it + self._confirm_receive(self.user1.id, self.picking) + # GL account ‘Inventory’ has balance 1 irrespective of the OU + expected_balance = 1.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=None, + expected_balance=expected_balance, + ) + # GL account ‘Inventory’ has balance 1 on OU main_operating_unit + expected_balance = 1.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=self.ou1, + expected_balance=expected_balance, + ) + # GL account ‘Inventory’ has balance 0 on OU B2C + expected_balance = 0.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=self.b2c, + expected_balance=expected_balance, + ) + # GL account ‘Goods Received Not Invoiced’ has balance - 1 + # irrespective of the OU + expected_balance = -1.0 + self._check_account_balance( + self.account_grni.id, operating_unit=None, expected_balance=expected_balance + ) + # GL account ‘Goods Received Not Invoiced’ has balance -1 on Main OU + expected_balance = -1.0 + self._check_account_balance( + self.account_grni.id, + operating_unit=self.ou1, + expected_balance=expected_balance, + ) + # GL account ‘Goods Received Not Invoiced’ has balance 0 on OU b2c + expected_balance = 0.0 + self._check_account_balance( + self.account_grni.id, + operating_unit=self.b2c, + expected_balance=expected_balance, + ) + + # Create Incoming Shipment 2 + self.picking = self._create_picking( + self.user2, + self.b2c, + self.b2c_type_in_id, + self.supplier_location, + self.location_b2c_id, + ) + + # Receive it + self._confirm_receive(self.user2.id, self.picking) + + # GL account ‘Inventory’ has balance 2 irrespective of the OU + expected_balance = 2.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=None, + expected_balance=expected_balance, + ) + # GL account ‘Inventory’ has balance 1 on OU main_operating_unit + expected_balance = 1.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=self.ou1, + expected_balance=expected_balance, + ) + # GL account ‘Inventory’ has balance 1 on OU b2c + expected_balance = 1.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=self.b2c, + expected_balance=expected_balance, + ) + # GL account ‘Goods Received Not Invoiced’ has balance - 2 + # irrespective of the OU + expected_balance = -2.0 + self._check_account_balance( + self.account_grni.id, operating_unit=None, expected_balance=expected_balance + ) + # GL account ‘Goods Received Not Invoiced’ has balance -1 on Main OU + expected_balance = -1.0 + self._check_account_balance( + self.account_grni.id, + operating_unit=self.ou1, + expected_balance=expected_balance, + ) + # GL account ‘Goods Received Not Invoiced’ has balance 0 on OU b2c + expected_balance = -1.0 + self._check_account_balance( + self.account_grni.id, + operating_unit=self.b2c, + expected_balance=expected_balance, + ) + + # Create Internal Transfer + self.picking = self._create_picking( + self.user1, + self.b2c, + self.b2c_type_int_id, + self.stock_location_stock, + self.location_b2c_id, + ) + # Receive it + self._confirm_receive(self.user1.id, self.picking) + # GL account ‘Inventory’ has balance 2 irrespective of the OU + expected_balance = 2.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=None, + expected_balance=expected_balance, + ) + # GL account ‘Inventory’ has balance 0 on OU main_operating_unit + expected_balance = 0.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=self.ou1, + expected_balance=expected_balance, + ) + # GL account ‘Inventory’ has balance 2 on OU b2c + expected_balance = 2.0 + self._check_account_balance( + self.account_inventory.id, + operating_unit=self.b2c, + expected_balance=expected_balance, + ) + # GL account ‘Inter-OU clearing’ has balance 0 irrespective of the OU + expected_balance = 0.0 + self._check_account_balance( + self.account_inter_ou_clearing.id, + operating_unit=None, + expected_balance=expected_balance, + ) From b8ae489efa28b228fe8357de4791a275343a9491 Mon Sep 17 00:00:00 2001 From: Manfred Nelvin H Date: Fri, 22 May 2026 21:52:12 +0530 Subject: [PATCH 2/3] [IMP] pre-commit fixes --- stock_account_operating_unit/README.rst | 38 ++++++++---------- .../readme/CONTRIBUTORS.md | 3 ++ .../readme/CONTRIBUTORS.rst | 3 -- .../{DESCRIPTION.rst => DESCRIPTION.md} | 4 +- stock_account_operating_unit/readme/USAGE.md | 3 ++ stock_account_operating_unit/readme/USAGE.rst | 3 -- .../static/description/index.html | 40 ++++++++----------- 7 files changed, 42 insertions(+), 52 deletions(-) create mode 100644 stock_account_operating_unit/readme/CONTRIBUTORS.md delete mode 100644 stock_account_operating_unit/readme/CONTRIBUTORS.rst rename stock_account_operating_unit/readme/{DESCRIPTION.rst => DESCRIPTION.md} (61%) create mode 100644 stock_account_operating_unit/readme/USAGE.md delete mode 100644 stock_account_operating_unit/readme/USAGE.rst diff --git a/stock_account_operating_unit/README.rst b/stock_account_operating_unit/README.rst index f45d6365fb..17cfb8eab2 100644 --- a/stock_account_operating_unit/README.rst +++ b/stock_account_operating_unit/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ======================================= Stock account moves with Operating Unit ======================================= @@ -17,25 +13,25 @@ Stock account moves with Operating Unit .. |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/license-LGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Foperating--unit-lightgray.png?logo=github - :target: https://github.com/OCA/operating-unit/tree/15.0/stock_account_operating_unit + :target: https://github.com/OCA/operating-unit/tree/18.0/stock_account_operating_unit :alt: OCA/operating-unit .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/operating-unit-15-0/operating-unit-15-0-stock_account_operating_unit + :target: https://translation.odoo-community.org/projects/operating-unit-18-0/operating-unit-18-0-stock_account_operating_unit :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/operating-unit&target_branch=15.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/operating-unit&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| This module introduces the following features: -- Creates account move lines when stock moves are posted between internal - locations within the same company, but different OU’s. +- Creates account move lines when stock moves are posted between + internal locations within the same company, but different OU’s. **Table of contents** @@ -45,9 +41,9 @@ This module introduces the following features: Usage ===== -Create stock moves between internal locations within the same company, but -different OU’s. The journal entries are created and they are self-balanced -within the OU when the journal entries are posted +Create stock moves between internal locations within the same company, +but different OU’s. The journal entries are created and they are +self-balanced within the OU when the journal entries are posted Bug Tracker =========== @@ -55,7 +51,7 @@ Bug Tracker Bugs are tracked on `GitHub 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -63,20 +59,20 @@ Credits ======= Authors -~~~~~~~ +------- * ForgeFlow * Serpent Consulting Services Pvt. Ltd. Contributors -~~~~~~~~~~~~ +------------ -* ForgeFlow, S.L. -* Serpent Consulting Services Pvt. Ltd. -* Jarsa Sistemas +- ForgeFlow, S.L. +- Serpent Consulting Services Pvt. Ltd. +- Jarsa Sistemas Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -88,6 +84,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/operating-unit `_ project on GitHub. +This module is part of the `OCA/operating-unit `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_account_operating_unit/readme/CONTRIBUTORS.md b/stock_account_operating_unit/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..c040b275a0 --- /dev/null +++ b/stock_account_operating_unit/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- ForgeFlow, S.L. \ +- Serpent Consulting Services Pvt. Ltd. \ +- Jarsa Sistemas \ diff --git a/stock_account_operating_unit/readme/CONTRIBUTORS.rst b/stock_account_operating_unit/readme/CONTRIBUTORS.rst deleted file mode 100644 index 6b63c1ca0f..0000000000 --- a/stock_account_operating_unit/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1,3 +0,0 @@ -* ForgeFlow, S.L. -* Serpent Consulting Services Pvt. Ltd. -* Jarsa Sistemas diff --git a/stock_account_operating_unit/readme/DESCRIPTION.rst b/stock_account_operating_unit/readme/DESCRIPTION.md similarity index 61% rename from stock_account_operating_unit/readme/DESCRIPTION.rst rename to stock_account_operating_unit/readme/DESCRIPTION.md index 2e9ddaf403..f6ae3b2eb1 100644 --- a/stock_account_operating_unit/readme/DESCRIPTION.rst +++ b/stock_account_operating_unit/readme/DESCRIPTION.md @@ -1,4 +1,4 @@ This module introduces the following features: -- Creates account move lines when stock moves are posted between internal - locations within the same company, but different OU’s. +- Creates account move lines when stock moves are posted between + internal locations within the same company, but different OU’s. diff --git a/stock_account_operating_unit/readme/USAGE.md b/stock_account_operating_unit/readme/USAGE.md new file mode 100644 index 0000000000..32fec63b86 --- /dev/null +++ b/stock_account_operating_unit/readme/USAGE.md @@ -0,0 +1,3 @@ +Create stock moves between internal locations within the same company, +but different OU’s. The journal entries are created and they are +self-balanced within the OU when the journal entries are posted diff --git a/stock_account_operating_unit/readme/USAGE.rst b/stock_account_operating_unit/readme/USAGE.rst deleted file mode 100644 index 419dbd3b53..0000000000 --- a/stock_account_operating_unit/readme/USAGE.rst +++ /dev/null @@ -1,3 +0,0 @@ -Create stock moves between internal locations within the same company, but -different OU’s. The journal entries are created and they are self-balanced -within the OU when the journal entries are posted diff --git a/stock_account_operating_unit/static/description/index.html b/stock_account_operating_unit/static/description/index.html index bcd61a5c59..001dab9bda 100644 --- a/stock_account_operating_unit/static/description/index.html +++ b/stock_account_operating_unit/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Stock account moves with Operating Unit -
+
+

Stock account moves with Operating Unit

- - -Odoo Community Association - -
-

Stock account moves with Operating Unit

-

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runboat

This module introduces the following features:

    -
  • Creates account move lines when stock moves are posted between internal -locations within the same company, but different OU’s.
  • +
  • Creates account move lines when stock moves are posted between +internal locations within the same company, but different OU’s.

Table of contents

@@ -394,30 +389,30 @@

Stock account moves with Operating Unit

-

Usage

-

Create stock moves between internal locations within the same company, but -different OU’s. The journal entries are created and they are self-balanced -within the OU when the journal entries are posted

+

Usage

+

Create stock moves between internal locations within the same company, +but different OU’s. The journal entries are created and they are +self-balanced within the OU when the journal entries are posted

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub 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.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Serpent Consulting Services Pvt. Ltd.
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -433,11 +428,10 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/operating-unit project on GitHub.

+

This module is part of the OCA/operating-unit project on GitHub.

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

-
From 3d1235945e35af6a14dc67860b41c6efff3c7e8d Mon Sep 17 00:00:00 2001 From: Manfred Nelvin H Date: Fri, 22 May 2026 21:53:46 +0530 Subject: [PATCH 3/3] [18.0][MIG] stock_account_operating_unit --- stock_account_operating_unit/__init__.py | 2 +- stock_account_operating_unit/__manifest__.py | 2 +- .../{model => models}/__init__.py | 0 .../{model => models}/stock_move.py | 8 +- stock_account_operating_unit/pyproject.toml | 3 + .../test_stock_account_operating_unit.py | 309 ++++++++++++++++-- 6 files changed, 286 insertions(+), 38 deletions(-) rename stock_account_operating_unit/{model => models}/__init__.py (100%) rename stock_account_operating_unit/{model => models}/stock_move.py (96%) create mode 100644 stock_account_operating_unit/pyproject.toml diff --git a/stock_account_operating_unit/__init__.py b/stock_account_operating_unit/__init__.py index 50170638d0..133f68732d 100644 --- a/stock_account_operating_unit/__init__.py +++ b/stock_account_operating_unit/__init__.py @@ -1,2 +1,2 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). -from . import model +from . import models diff --git a/stock_account_operating_unit/__manifest__.py b/stock_account_operating_unit/__manifest__.py index 5dc24ae4d6..1f87df293c 100644 --- a/stock_account_operating_unit/__manifest__.py +++ b/stock_account_operating_unit/__manifest__.py @@ -7,7 +7,7 @@ "name": "Stock account moves with Operating Unit", "summary": "Create journal entries in moves between internal locations " "with different operating units.", - "version": "15.0.1.0.0", + "version": "18.0.1.0.0", "category": "Generic Modules/Sales & Purchases", "author": "ForgeFlow, " "Serpent Consulting Services Pvt. Ltd.," diff --git a/stock_account_operating_unit/model/__init__.py b/stock_account_operating_unit/models/__init__.py similarity index 100% rename from stock_account_operating_unit/model/__init__.py rename to stock_account_operating_unit/models/__init__.py diff --git a/stock_account_operating_unit/model/stock_move.py b/stock_account_operating_unit/models/stock_move.py similarity index 96% rename from stock_account_operating_unit/model/stock_move.py rename to stock_account_operating_unit/models/stock_move.py index 5163037bcb..b58101764e 100644 --- a/stock_account_operating_unit/model/stock_move.py +++ b/stock_account_operating_unit/models/stock_move.py @@ -16,15 +16,17 @@ def _generate_valuation_lines_data( credit_value, debit_account_id, credit_account_id, + svl_id, description, ): - res = super(StockMove, self)._generate_valuation_lines_data( + res = super()._generate_valuation_lines_data( partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, + svl_id, description, ) if res: @@ -79,9 +81,8 @@ def _action_done(self, cancel_backorder=False): a transit location or is outside of the company or the source or destination locations belong to different operating units. """ - res = super(StockMove, self)._action_done(cancel_backorder) + res = super()._action_done(cancel_backorder) for move in self: - if move.product_id.valuation == "real_time": # Inter-operating unit moves do not accept to # from/to non-internal location @@ -102,6 +103,7 @@ def _action_done(self, cancel_backorder=False): move.product_id.standard_price, acc_valuation, acc_valuation, + False, _("%s - OU Move") % move.product_id.display_name, ) am = ( diff --git a/stock_account_operating_unit/pyproject.toml b/stock_account_operating_unit/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/stock_account_operating_unit/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/stock_account_operating_unit/tests/test_stock_account_operating_unit.py b/stock_account_operating_unit/tests/test_stock_account_operating_unit.py index 13a0cd68d8..07898c4905 100644 --- a/stock_account_operating_unit/tests/test_stock_account_operating_unit.py +++ b/stock_account_operating_unit/tests/test_stock_account_operating_unit.py @@ -2,6 +2,9 @@ # - Jordi Ballester Alomar # © 2019 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from unittest.mock import patch + +from odoo.exceptions import UserError from odoo.tests import Form from odoo.addons.stock.tests.common import TestStockCommon @@ -9,14 +12,13 @@ class TestStockAccountOperatingUnit(TestStockCommon): def setUp(self): - super(TestStockAccountOperatingUnit, self).setUp() + super().setUp() self.res_groups = self.env["res.groups"] self.res_users_model = self.env["res.users"] self.aml_model = self.env["account.move.line"] self.account_model = self.env["account.account"] self.product_model = self.env["product.product"] self.product_cteg_model = self.env["product.category"] - self.acc_type_model = self.env["account.account.type"] self.operating_unit_model = self.env["operating.unit"] self.company_model = self.env["res.company"] self.move_model = self.env["stock.move"] @@ -25,7 +27,7 @@ def setUp(self): # Company self.company = self.env.ref("base.main_company") self.group_stock_manager = self.env.ref("stock.group_stock_manager") - self.grp_acc_user = self.env.ref("account.group_account_invoice") + self.grp_acc_user = self.env.ref("account.group_account_user") self.grp_stock_user = self.env.ref("stock.group_stock_user") # Main Operating Unit self.ou1 = self.env.ref("operating_unit.main_operating_unit") @@ -45,6 +47,7 @@ def setUp(self): self.company, [self.ou1, self.b2c], ) + # Create user2 self.user2 = self._create_user( "stock_account_user_2", @@ -52,29 +55,26 @@ def setUp(self): self.company, [self.b2c], ) + # Create account for Goods Received Not Invoiced name = "Goods Received Not Invoiced" code = "grni" - acc_type = self.env.ref("account.data_account_type_equity") - self.account_grni = self._create_account(acc_type, name, code, self.company) + self.account_grni = self._create_account("equity", name, code, self.company) # Create account for Cost of Goods Sold name = "Cost of Goods Sold" code = "cogs" - acc_type = self.env.ref("account.data_account_type_expenses") - self.account_cogs_id = self._create_account(acc_type, name, code, self.company) + self.account_cogs_id = self._create_account("expense", name, code, self.company) # Create account for Inventory name = "Inventory" code = "inventory" - acc_type = self.env.ref("account.data_account_type_fixed_assets") self.account_inventory = self._create_account( - acc_type, name, code, self.company + "asset_current", name, code, self.company ) # Create account for Inter-OU Clearing name = "Inter-OU Clearing" - code = "inter_ou" - acc_type = self.env.ref("account.data_account_type_equity") + code = "INTEROU" self.account_inter_ou_clearing = self._create_account( - acc_type, name, code, self.company + "equity", name, code, self.company ) # Update company data self.company.write( @@ -114,12 +114,11 @@ def _create_user(self, login, groups, company, operating_units): def _create_account(self, acc_type, name, code, company): """Create an account.""" - account = self.account_model.create( + account = self.account_model.with_company(company).create( { "name": name, "code": code, - "user_type_id": acc_type.id, - "company_id": company.id, + "account_type": acc_type, } ) return account @@ -130,16 +129,18 @@ def _create_product(self): { "name": "test_product_ctg", "property_valuation": "real_time", + "property_cost_method": "standard", "property_stock_valuation_account_id": self.account_inventory.id, "property_stock_account_input_categ_id": self.account_grni.id, - "property_stock_account_output_categ_id": self.account_cogs_id, + "property_stock_account_output_categ_id": self.account_cogs_id.id, } ) product = self.product_model.create( { "name": "test_product", "categ_id": product_cteg.id, - "type": "product", + "type": "consu", + "is_storable": True, "list_price": 1.0, "standard_price": 1.0, } @@ -161,7 +162,7 @@ def _create_picking(self, user, ou_id, picking_type, src_loc_id, dest_loc_id): "name": "a move", "product_id": self.product.id, "product_uom_qty": 1.0, - "product_uom": 1, + "product_uom": self.product.uom_id.id, "picking_id": picking.id, "location_id": src_loc_id.id, "location_dest_id": dest_loc_id.id, @@ -171,16 +172,26 @@ def _create_picking(self, user, ou_id, picking_type, src_loc_id, dest_loc_id): def _confirm_receive(self, user_id, picking): """ - Checks the stock availability, validates and process the stock picking. + Checks the stock availability,validates and process the stock picking. """ picking.action_confirm() picking.action_assign() + for move in picking.move_ids: + if not move.quantity: + move.quantity = move.product_uom_qty res = picking.with_user(user_id).button_validate() - wiz = Form( - self.env[res["res_model"]].with_context(**res["context"]), - view=self.env.ref("stock.view_immediate_transfer"), - ).save() - wiz.process() + if isinstance(res, dict): + view_id = res.get("view_id") or (res.get("views") or [(False, False)])[0][0] + view = self.env["ir.ui.view"].browse(view_id) if view_id else False + form = Form( + self.env[res["res_model"]].with_context(**res.get("context", {})), + view=view if view else None, + ) + wiz = form.save() + if hasattr(wiz, "process_cancel_backorder"): + wiz.process_cancel_backorder() + else: + wiz.process() def _check_account_balance( self, account_id, operating_unit=None, expected_balance=0.0 @@ -197,14 +208,14 @@ def _check_account_balance( self.assertEqual( balance, expected_balance, - "Balance is not %s for Operating Unit %s." - % (str(expected_balance), operating_unit.name), + f"Balance is not {expected_balance} " + f"for Operating Unit {operating_unit.name}.", ) else: self.assertEqual( balance, expected_balance, - "Balance is not %s for all Operating Units." % str(expected_balance), + f"Balance is not {expected_balance} " "for all Operating Units.", ) def _get_balance(self, domain): @@ -212,7 +223,9 @@ def _get_balance(self, domain): Call read_group method and return the balance of particular account. """ aml_rec = self.aml_model.read_group( - domain, ["debit", "credit", "account_id"], ["account_id"] + domain, + ["debit", "credit", "account_id"], + ["account_id"], ) if aml_rec: return aml_rec[0].get("debit", 0.0) - aml_rec[0].get("credit", 0.0) @@ -254,12 +267,15 @@ def test_pickings(self): operating_unit=self.b2c, expected_balance=expected_balance, ) - # GL account ‘Goods Received Not Invoiced’ has balance - 1 + # GL account ‘Goods Received Not Invoiced’ has balance -1 # irrespective of the OU expected_balance = -1.0 self._check_account_balance( - self.account_grni.id, operating_unit=None, expected_balance=expected_balance + self.account_grni.id, + operating_unit=None, + expected_balance=expected_balance, ) + # GL account ‘Goods Received Not Invoiced’ has balance -1 on Main OU expected_balance = -1.0 self._check_account_balance( @@ -308,11 +324,14 @@ def test_pickings(self): operating_unit=self.b2c, expected_balance=expected_balance, ) - # GL account ‘Goods Received Not Invoiced’ has balance - 2 + + # GL account ‘Goods Received Not Invoiced’ has balance -2 # irrespective of the OU expected_balance = -2.0 self._check_account_balance( - self.account_grni.id, operating_unit=None, expected_balance=expected_balance + self.account_grni.id, + operating_unit=None, + expected_balance=expected_balance, ) # GL account ‘Goods Received Not Invoiced’ has balance -1 on Main OU expected_balance = -1.0 @@ -321,7 +340,7 @@ def test_pickings(self): operating_unit=self.ou1, expected_balance=expected_balance, ) - # GL account ‘Goods Received Not Invoiced’ has balance 0 on OU b2c + # GL account ‘Goods Received Not Invoiced’ has balance -1 on OU b2c expected_balance = -1.0 self._check_account_balance( self.account_grni.id, @@ -367,3 +386,227 @@ def test_pickings(self): operating_unit=None, expected_balance=expected_balance, ) + + def test_confirm_receive_processes_backorder_wizard_action(self): + picking = self._create_picking( + self.user1, + self.ou1, + self.incoming_id, + self.supplier_location, + self.stock_location_stock, + ) + picking.action_confirm() + picking.action_assign() + picking.move_ids.quantity = 0.5 + self._confirm_receive(self.user1.id, picking) + self.assertEqual(picking.state, "done") + + def test_generate_valuation_lines_data_inter_ou_account_mismatch_raises(self): + b2c_wh = self.env.ref("stock_operating_unit.stock_warehouse_b2c") + src_location = self.env["stock.location"].create( + { + "name": "OU1 Stock Location", + "usage": "internal", + "company_id": self.company.id, + "operating_unit_id": self.ou1.id, + } + ) + dest_location = self.env["stock.location"].create( + { + "name": "B2C Stock Location", + "usage": "internal", + "company_id": self.company.id, + "operating_unit_id": self.b2c.id, + } + ) + picking = self.picking_model.create( + { + "picking_type_id": b2c_wh.int_type_id.id, + "location_id": src_location.id, + "location_dest_id": dest_location.id, + } + ) + move = self.move_model.create( + { + "name": "a move", + "product_id": self.product.id, + "product_uom_qty": 1.0, + "product_uom": self.product.uom_id.id, + "picking_id": picking.id, + "location_id": src_location.id, + "location_dest_id": dest_location.id, + } + ) + + mocked_res = { + "debit_line_vals": {"account_id": self.account_inventory.id}, + "credit_line_vals": {"account_id": self.account_grni.id}, + } + with patch( + "odoo.addons.stock_account.models.stock_move.StockMove._generate_valuation_lines_data", + return_value=mocked_res, + ): + with self.assertRaises(UserError): + move._generate_valuation_lines_data( + partner_id=False, + qty=1.0, + debit_value=1.0, + credit_value=1.0, + debit_account_id=self.account_inventory.id, + credit_account_id=self.account_grni.id, + svl_id=False, + description="Test", + ) + + def test_generate_valuation_lines_data_uses_warehouse_ou_when_move_has_no_ou(self): + b2c_wh = self.env.ref("stock_operating_unit.stock_warehouse_b2c") + internal_location = self.env["stock.location"].create( + { + "name": "No OU Stock Location", + "usage": "internal", + "company_id": self.company.id, + } + ) + picking = self.picking_model.create( + { + "picking_type_id": b2c_wh.in_type_id.id, + "location_id": self.supplier_location.id, + "location_dest_id": internal_location.id, + } + ) + move = self.move_model.create( + { + "name": "a move", + "product_id": self.product.id, + "product_uom_qty": 1.0, + "product_uom": self.product.uom_id.id, + "picking_id": picking.id, + "location_id": self.supplier_location.id, + "location_dest_id": internal_location.id, + } + ) + + mocked_res = { + "debit_line_vals": {"account_id": self.account_inventory.id}, + "credit_line_vals": {"account_id": self.account_inventory.id}, + } + with patch( + "odoo.addons.stock_account.models.stock_move.StockMove._generate_valuation_lines_data", + return_value=mocked_res, + ): + rslt = move._generate_valuation_lines_data( + partner_id=False, + qty=1.0, + debit_value=1.0, + credit_value=1.0, + debit_account_id=self.account_inventory.id, + credit_account_id=self.account_inventory.id, + svl_id=False, + description="Test", + ) + self.assertEqual( + rslt["debit_line_vals"]["operating_unit_id"], + b2c_wh.operating_unit_id.id, + ) + self.assertEqual( + rslt["credit_line_vals"]["operating_unit_id"], + b2c_wh.operating_unit_id.id, + ) + + def test_generate_valuation_lines_data_sets_price_diff_operating_unit(self): + b2c_wh = self.env.ref("stock_operating_unit.stock_warehouse_b2c") + src_location = self.env["stock.location"].create( + { + "name": "OU1 Stock Location (Price Diff)", + "usage": "internal", + "company_id": self.company.id, + "operating_unit_id": self.ou1.id, + } + ) + dest_location = self.env["stock.location"].create( + { + "name": "B2C Stock Location (Price Diff)", + "usage": "internal", + "company_id": self.company.id, + "operating_unit_id": self.b2c.id, + } + ) + picking = self.picking_model.create( + { + "picking_type_id": b2c_wh.int_type_id.id, + "location_id": src_location.id, + "location_dest_id": dest_location.id, + } + ) + move = self.move_model.create( + { + "name": "a move", + "product_id": self.product.id, + "product_uom_qty": 1.0, + "product_uom": self.product.uom_id.id, + "picking_id": picking.id, + "location_id": src_location.id, + "location_dest_id": dest_location.id, + } + ) + + mocked_res = { + "debit_line_vals": {"account_id": self.account_inventory.id}, + "credit_line_vals": {"account_id": self.account_inventory.id}, + "price_diff_line_vals": {"account_id": self.account_grni.id}, + } + with patch( + "odoo.addons.stock_account.models.stock_move.StockMove._generate_valuation_lines_data", + return_value=mocked_res, + ): + rslt = move._generate_valuation_lines_data( + partner_id=False, + qty=1.0, + debit_value=2.0, + credit_value=1.0, + debit_account_id=self.account_inventory.id, + credit_account_id=self.account_inventory.id, + svl_id=False, + description="Test", + ) + self.assertEqual( + rslt["price_diff_line_vals"]["operating_unit_id"], + self.ou1.id, + ) + + def test_generate_valuation_lines_data_passthrough_when_parent_returns_falsy(self): + b2c_wh = self.env.ref("stock_operating_unit.stock_warehouse_b2c") + picking = self.picking_model.create( + { + "picking_type_id": b2c_wh.in_type_id.id, + "location_id": self.supplier_location.id, + "location_dest_id": self.stock_location_stock.id, + } + ) + move = self.move_model.create( + { + "name": "a move", + "product_id": self.product.id, + "product_uom_qty": 1.0, + "product_uom": self.product.uom_id.id, + "picking_id": picking.id, + "location_id": self.supplier_location.id, + "location_dest_id": self.stock_location_stock.id, + } + ) + + with patch( + "odoo.addons.stock_account.models.stock_move.StockMove._generate_valuation_lines_data", + return_value=False, + ): + rslt = move._generate_valuation_lines_data( + partner_id=False, + qty=1.0, + debit_value=1.0, + credit_value=1.0, + debit_account_id=self.account_inventory.id, + credit_account_id=self.account_inventory.id, + svl_id=False, + description="Test", + ) + self.assertFalse(rslt)