From 6aaab6438c9756a30e1fc8dbdfe627553aa69c6e Mon Sep 17 00:00:00 2001
From: Sudhir Arya
Date: Thu, 31 Dec 2015 19:24:48 +0530
Subject: [PATCH 01/26] Added Purchase Operating Unit module.
---
purchase_operating_unit/README.rst | 64 +++++++++++++
purchase_operating_unit/__init__.py | 5 +
purchase_operating_unit/__openerp__.py | 27 ++++++
.../demo/purchase_order_demo.xml | 34 +++++++
purchase_operating_unit/models/__init__.py | 8 ++
purchase_operating_unit/models/invoice.py | 21 +++++
purchase_operating_unit/models/procurement.py | 34 +++++++
purchase_operating_unit/models/purchase.py | 75 +++++++++++++++
.../security/purchase_security.xml | 28 ++++++
.../static/description/icon.png | Bin 0 -> 9455 bytes
purchase_operating_unit/tests/__init__.py | 7 ++
.../tests/test_po_security.py | 43 +++++++++
.../tests/test_purchase_operating_unit.py | 89 ++++++++++++++++++
.../views/purchase_order_line_view.xml | 43 +++++++++
.../views/purchase_order_view.xml | 52 ++++++++++
15 files changed, 530 insertions(+)
create mode 100644 purchase_operating_unit/README.rst
create mode 100644 purchase_operating_unit/__init__.py
create mode 100644 purchase_operating_unit/__openerp__.py
create mode 100644 purchase_operating_unit/demo/purchase_order_demo.xml
create mode 100644 purchase_operating_unit/models/__init__.py
create mode 100644 purchase_operating_unit/models/invoice.py
create mode 100644 purchase_operating_unit/models/procurement.py
create mode 100644 purchase_operating_unit/models/purchase.py
create mode 100644 purchase_operating_unit/security/purchase_security.xml
create mode 100644 purchase_operating_unit/static/description/icon.png
create mode 100644 purchase_operating_unit/tests/__init__.py
create mode 100644 purchase_operating_unit/tests/test_po_security.py
create mode 100644 purchase_operating_unit/tests/test_purchase_operating_unit.py
create mode 100644 purchase_operating_unit/views/purchase_order_line_view.xml
create mode 100644 purchase_operating_unit/views/purchase_order_view.xml
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
new file mode 100644
index 0000000000..b034157cff
--- /dev/null
+++ b/purchase_operating_unit/README.rst
@@ -0,0 +1,64 @@
+.. image:: https://img.shields.io/badge/license-AGPLv3-blue.svg
+ :target: https://www.gnu.org/licenses/lgpl.html
+ :alt: License: LGPL-3
+
+===============================
+Purchase with Operating Units
+===============================
+
+This module introduces the following features:
+- It introduces the operating unit to the purchase order.
+- The operating unit is copied to the invoice.
+- The operating unit is copied to the stock picking.
+- It implements user's security rules.
+
+
+Configuration
+=============
+
+
+Usage
+=====
+
+.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
+ :alt: Try me on Runbot
+ :target: https://runbot.odoo-community.org/runbot/213/7.0
+
+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 smashing it by providing a detailed and welcomed feedback.
+
+
+Credits
+=======
+
+Images
+------
+
+* Odoo Community Association: `Icon `_.
+
+Contributors
+------------
+
+* Jordi Ballester Alomar
+* Aaron Henriquez
+* Sudhir Arya
+
+Maintainer
+----------
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: http://odoo-community.org
+
+This module is maintained by the OCA.
+
+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.
+
+To contribute to this module, please visit http://odoo-community.org.
diff --git a/purchase_operating_unit/__init__.py b/purchase_operating_unit/__init__.py
new file mode 100644
index 0000000000..cf1a072540
--- /dev/null
+++ b/purchase_operating_unit/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+# © 2016 Eficent Business and IT Consulting Services S.L.
+# © 2016 Serpent Consulting Services Pvt. Ltd.
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import models
diff --git a/purchase_operating_unit/__openerp__.py b/purchase_operating_unit/__openerp__.py
new file mode 100644
index 0000000000..980fd08585
--- /dev/null
+++ b/purchase_operating_unit/__openerp__.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+{
+ "name": "Operating Unit in Purchase Orders",
+ "summary": "An operating unit (OU) is an organizational entity part of a\
+ company",
+ "version": "9.0.1.0.0",
+ "author": "Eficent, Serpent Consulting Services Pvt. Ltd.,"
+ "Odoo Community Association (OCA)",
+ "website": "http://www.eficent.com",
+ "category": "Purchase Management",
+ "depends": ["purchase", "procurement_operating_unit"],
+ "license": "LGPL-3",
+ "data": [
+ "security/purchase_security.xml",
+ "views/purchase_order_view.xml",
+ "views/purchase_order_line_view.xml",
+ ],
+ "demo": [
+ "demo/purchase_order_demo.xml",
+ ],
+ "installable": True,
+}
diff --git a/purchase_operating_unit/demo/purchase_order_demo.xml b/purchase_operating_unit/demo/purchase_order_demo.xml
new file mode 100644
index 0000000000..fc427bfe36
--- /dev/null
+++ b/purchase_operating_unit/demo/purchase_order_demo.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/purchase_operating_unit/models/__init__.py b/purchase_operating_unit/models/__init__.py
new file mode 100644
index 0000000000..eeebb4267f
--- /dev/null
+++ b/purchase_operating_unit/models/__init__.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import purchase
+from . import procurement
+from . import invoice
diff --git a/purchase_operating_unit/models/invoice.py b/purchase_operating_unit/models/invoice.py
new file mode 100644
index 0000000000..eff0a4266c
--- /dev/null
+++ b/purchase_operating_unit/models/invoice.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from openerp import api, models
+
+
+class AccountInvoice(models.Model):
+ _inherit = 'account.invoice'
+
+ # Load all unsold PO lines
+ @api.onchange('purchase_id')
+ def purchase_order_change(self):
+ """
+ Override to add Operating Unit from Purchase Order to Invoice.
+ """
+ if self.purchase_id and self.purchase_id.operating_unit_id:
+ # Assign OU from PO to Invoice
+ self.operating_unit_id = self.purchase_id.operating_unit_id.id
+ return super(AccountInvoice, self).purchase_order_change()
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
new file mode 100644
index 0000000000..709a529e53
--- /dev/null
+++ b/purchase_operating_unit/models/procurement.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from openerp import api, models
+from openerp.tools.translate import _
+from openerp.exceptions import UserError
+
+
+class ProcurementOrder(models.Model):
+ _inherit = 'procurement.order'
+
+ @api.one
+ @api.constrains('operating_unit_id', 'purchase_line_id')
+ def _check_purchase_order_operating_unit(self, cr, uid, ids, context=None):
+ purchase = self.purchase_line_id.purchase_id
+ if purchase and\
+ self.purchase.operating_unit_id !=\
+ self.location_id.operating_unit_id:
+ raise UserError(_('Configuration error!\nThe Quotation / Purchase\
+ Order and the Procurement Order must belong to the\
+ same Operating Unit.'))
+
+ @api.multi
+ def _prepare_purchase_order(self, partner):
+ res = super(ProcurementOrder, self)._prepare_purchase_order(partner)
+ operating_unit = self.location_id.operating_unit_id
+ if operating_unit:
+ res.update({
+ 'operating_unit_id': operating_unit.id,
+ 'requesting_operating_unit_id': operating_unit.id
+ })
+ return res
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase.py
new file mode 100644
index 0000000000..65562264ff
--- /dev/null
+++ b/purchase_operating_unit/models/purchase.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from openerp.tools.translate import _
+from openerp import api, fields, models
+from openerp.exceptions import UserError
+
+
+class PurchaseOrder(models.Model):
+ _inherit = 'purchase.order'
+
+ operating_unit_id = fields.Many2one('operating.unit', 'Operating Unit',
+ default=lambda self:
+ self.env['res.users'].
+ operating_unit_default_get(self._uid))
+ requesting_operating_unit_id =\
+ fields.Many2one('operating.unit', 'Requesting Operating Unit',
+ default=lambda self:
+ self.env['res.users'].
+ operating_unit_default_get(self._uid))
+
+# @api.one
+# @api.constrains('operating_unit_id', 'picking_type_id')
+# def _check_warehouse_operating_unit(self):
+# picking_type = self.picking_type_id
+# if picking_type:
+# if picking_type.warehouse_id and\
+# picking_type.warehouse_id.operating_unit_id\
+# and self.operating_unit_id and\
+# picking_type.warehouse_id.operating_unit_id !=\
+# self.operating_unit_id:
+# raise UserError(_('Configuration error!\nThe\
+# Quotation / Purchase Order and the Warehouse of picking type\
+# must belong to the same Operating Unit.'))
+
+ @api.one
+ @api.constrains('operating_unit_id', 'requesting_operating_unit_id',
+ 'company_id')
+ def _check_company_operating_unit(self):
+ if self.company_id and self.operating_unit_id and\
+ self.company_id != self.operating_unit_id.company_id:
+ raise UserError(_('Configuration error!\nThe Company in the\
+ Purchase Order and in the Operating Unit must be the same.'))
+
+ @api.onchange('requesting_operating_unit_id', 'operating_unit_id')
+ def onchange_operating_unit_id(self):
+ pick_type = self.env['stock.picking.type']
+ location_obj = self.env['stock.location']
+ if not self.requesting_operating_unit_id or not self.operating_unit_id:
+ return {}
+ request_locations =\
+ location_obj.search([('operating_unit_id', '=',
+ self.requesting_operating_unit_id.id)])
+ picking_types =\
+ pick_type.search([('default_location_dest_id', 'in',
+ request_locations.ids)], limit=1)
+ if picking_types:
+ self.picking_type_id = picking_types.id
+
+ @api.model
+ def _prepare_picking(self):
+ res = super(PurchaseOrder, self)._prepare_picking()
+ res['operating_unit_id'] = self.operating_unit_id and\
+ self.operating_unit_id.id
+ return res
+
+
+class PurchaseOrderLine(models.Model):
+ _inherit = 'purchase.order.line'
+
+ operating_unit_id = fields.Many2one('operating.unit',
+ related='order_id.operating_unit_id',
+ string='Operating Unit', readonly=True)
diff --git a/purchase_operating_unit/security/purchase_security.xml b/purchase_operating_unit/security/purchase_security.xml
new file mode 100644
index 0000000000..14cdd36be4
--- /dev/null
+++ b/purchase_operating_unit/security/purchase_security.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
+ PO's from allowed operating units
+
+
+
+
+
+
+
+
+
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
+ PO lines from allowed operating units
+
+
+
+
+
+
+
+
+
diff --git a/purchase_operating_unit/static/description/icon.png b/purchase_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)`y_~Hnd9AUX7h-H?jVuU|}My+C=TjH(jKz
zqMVr0re3S$H@t{zI95qa)+Crz*5Zj}Ao%4Z><+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
z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp
zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zls4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6#
z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f#
zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC
zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv!
zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG
z-wfS
zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9
z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE#
z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz
zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t
z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN
zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q
ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k
zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG
z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff
z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1
zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO
zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$
zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV(
z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb
zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4
z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{
zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx}
z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov
zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22
zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq
zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t<
z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k
z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp
z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{}
zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/purchase_operating_unit/tests/__init__.py b/purchase_operating_unit/tests/__init__.py
new file mode 100644
index 0000000000..cb1343a28e
--- /dev/null
+++ b/purchase_operating_unit/tests/__init__.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import test_purchase_operating_unit
+from . import test_po_security
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
new file mode 100644
index 0000000000..104acaa1bf
--- /dev/null
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from openerp.addons.purchase_operating_unit.tests import\
+ test_purchase_order as test_po
+
+
+class TestPoSecurity(test_po.TestPurchaseOrder):
+
+ def test_po_ou_security(self):
+ """Test Security of Purchase Operating Unit"""
+ # User 2 is only assigned to Operating Unit 2, and cannot list
+ # purchase orders from Operating Unit 1.
+ po_ids =\
+ self.PurchaseOrder.sudo(self.user2_id).\
+ search([('operating_unit_id', '=', self.ou1.id)]).ids
+ self.assertEqual(po_ids, [])
+ # User 2 cannot list the picking that was created from PO 1
+ picking_ids =\
+ self.StockPikcing.sudo(self.user2_id).\
+ search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
+ self.assertEqual(picking_ids, [])
+ # User 2 cannot list the invoice that was created from PO 2
+ invoice_ids = self.AccountInvoice.sudo(self.user2_id).\
+ search([('purchase_id', '=', self.purchase1.id)]).ids
+ self.assertEqual(invoice_ids, [])
+ # User 1 is assigned to Operating Unit 1, and can list
+ # the purchase order 1 from Operating Unit 1.
+ po_ids =\
+ self.PurchaseOrder.sudo(self.user1_id).\
+ search([('operating_unit_id', '=', self.ou1.id)]).ids
+ self.assertNotEqual(po_ids, [])
+ # User 1 can list the picking that was created from PO 1
+ picking_ids =\
+ self.StockPikcing.sudo(self.user1_id).\
+ search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
+ self.assertNotEqual(picking_ids, [])
+ # User 1 can list the invoice that was created from PO 2
+ invoice_ids = self.AccountInvoice.sudo(self.user1_id).\
+ search([('purchase_id', '=', self.purchase1.id)]).ids
+ self.assertNotEqual(invoice_ids, [])
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
new file mode 100644
index 0000000000..d992ad0204
--- /dev/null
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+# © 2015 Eficent Business and IT Consulting Services S.L.
+# - Jordi Ballester Alomar
+# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+import time
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
+from openerp.addons.purchase.tests import test_purchase_order
+
+
+class TestPurchaseOperatingUnit(test_purchase_order.TestPurchaseOrder):
+
+ def setUp(self):
+ super(TestPurchaseOperatingUnit, self).setUp()
+ self.ResUsers = self.env['res.users']
+ self.StockMove = self.env['stock.move']
+ self.StockPikcing = self.env['stock.picking']
+ # company
+ self.company1 = self.env.ref('base.main_company')
+ self.company2 = self.env.ref('stock.res_company_1')
+ # groups
+ self.group_purchase_user = self.env.ref('purchase.group_purchase_user')
+ self.group_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')
+ # Partner
+ self.partner1 = self.env.ref('base.res_partner_1')
+ # Products
+ self.product1 = self.env.ref('product.product_product_7')
+ self.product2 = self.env.ref('product.product_product_9')
+ self.product3 = self.env.ref('product.product_product_11')
+ # Create users
+ self.user1_id = self._create_user('user_1',
+ [self.group_purchase_user,
+ self.group_stock_user],
+ self.company1,
+ [self.ou1])
+ self.user2_id = self._create_user('user_2',
+ [self.group_purchase_user,
+ self.group_stock_user],
+ self.company2,
+ [self.b2b])
+ self.purchase1 = self._create_purchase(
+ self.user1_id, [(self.product1, 1000),
+ (self.product2, 500),
+ (self.product3, 800)])
+ self.purchase1.sudo(self.user1_id).button_confirm()
+
+ def _create_user(self, login, groups, company, operating_units):
+ """ Create a user."""
+ group_ids = [group.id for group in groups]
+ user =\
+ self.ResUsers.with_context({'no_reset_password': True}).\
+ create({
+ 'name': 'Chicago Purchase User',
+ 'login': login,
+ 'password': 'demo',
+ 'email': 'chicago@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.id
+
+ def _create_purchase(self, user_id, line_products):
+ """ Create a purchase order.
+ ``line_products`` is a list of tuple [(product, qty)]
+ """
+ lines = []
+ for product, qty in line_products:
+ line_values = {
+ 'name': product.name,
+ 'product_id': product.id,
+ 'product_qty': qty,
+ 'product_uom': product.uom_id.id,
+ 'price_unit': 50,
+ 'date_planned': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ }
+ lines.append((0, 0, line_values))
+ return self.PurchaseOrder.sudo(user_id).create({
+ 'operating_unit_id': self.ou1.id,
+ 'requesting_operating_unit_id': self.ou1.id,
+ 'partner_id': self.partner1.id,
+ 'order_line': lines,
+ 'company_id': self.company1.id,
+ })
diff --git a/purchase_operating_unit/views/purchase_order_line_view.xml b/purchase_operating_unit/views/purchase_order_line_view.xml
new file mode 100644
index 0000000000..283a8d9bc5
--- /dev/null
+++ b/purchase_operating_unit/views/purchase_order_line_view.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+ purchase_order_line_tree
+ purchase.order.line
+
+
+
+
+
+
+
+
+
+ purchase_order_line_form
+ purchase.order.line
+
+
+
+
+
+
+
+
+
+ purchase_order_line_search
+ purchase.order.line
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
new file mode 100644
index 0000000000..cb3d7d9e4b
--- /dev/null
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+ purchase_order_tree
+ purchase.order
+
+
+
+
+
+
+
+
+
+ purchase_order_form
+ purchase.order
+
+
+
+
+
+
+
+
+
+ {'operating_unit_id': operating_unit_id}
+
+
+
+
+
+
+
+
+ view_purchase_order_filter
+ purchase.order
+
+
+
+
+
+
+
+
+
+
+
+
+
From eda9ceae86716d65564d23033155de6aa040850e Mon Sep 17 00:00:00 2001
From: Sudhir Arya
Date: Sat, 2 Jan 2016 15:10:14 +0530
Subject: [PATCH 02/26] Improved the unit test case for Purchase OU.
---
purchase_operating_unit/tests/test_po_security.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 104acaa1bf..b1449e711c 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -4,10 +4,10 @@
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from openerp.addons.purchase_operating_unit.tests import\
- test_purchase_order as test_po
+ test_purchase_operating_unit as test_po_ou
-class TestPoSecurity(test_po.TestPurchaseOrder):
+class TestPoSecurity(test_po_ou.TestPurchaseOperatingUnit):
def test_po_ou_security(self):
"""Test Security of Purchase Operating Unit"""
From c65ca8d574815a5219c12facaf1add2423086668 Mon Sep 17 00:00:00 2001
From: Sudhir Arya
Date: Fri, 8 Jan 2016 11:19:47 +0530
Subject: [PATCH 03/26] Improved the code of unit test cases and of constraint.
---
purchase_operating_unit/models/procurement.py | 2 +-
purchase_operating_unit/tests/test_po_security.py | 4 ++--
purchase_operating_unit/tests/test_purchase_operating_unit.py | 3 +--
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
index 709a529e53..7cd036d19e 100644
--- a/purchase_operating_unit/models/procurement.py
+++ b/purchase_operating_unit/models/procurement.py
@@ -12,7 +12,7 @@ class ProcurementOrder(models.Model):
_inherit = 'procurement.order'
@api.one
- @api.constrains('operating_unit_id', 'purchase_line_id')
+ @api.constrains('purchase_line_id')
def _check_purchase_order_operating_unit(self, cr, uid, ids, context=None):
purchase = self.purchase_line_id.purchase_id
if purchase and\
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index b1449e711c..293f7b2b8c 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -19,7 +19,7 @@ def test_po_ou_security(self):
self.assertEqual(po_ids, [])
# User 2 cannot list the picking that was created from PO 1
picking_ids =\
- self.StockPikcing.sudo(self.user2_id).\
+ self.StockPicking.sudo(self.user2_id).\
search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
self.assertEqual(picking_ids, [])
# User 2 cannot list the invoice that was created from PO 2
@@ -34,7 +34,7 @@ def test_po_ou_security(self):
self.assertNotEqual(po_ids, [])
# User 1 can list the picking that was created from PO 1
picking_ids =\
- self.StockPikcing.sudo(self.user1_id).\
+ self.StockPicking.sudo(self.user1_id).\
search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
self.assertNotEqual(picking_ids, [])
# User 1 can list the invoice that was created from PO 2
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index d992ad0204..b352e5d863 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -13,8 +13,7 @@ class TestPurchaseOperatingUnit(test_purchase_order.TestPurchaseOrder):
def setUp(self):
super(TestPurchaseOperatingUnit, self).setUp()
self.ResUsers = self.env['res.users']
- self.StockMove = self.env['stock.move']
- self.StockPikcing = self.env['stock.picking']
+ self.StockPicking = self.env['stock.picking']
# company
self.company1 = self.env.ref('base.main_company')
self.company2 = self.env.ref('stock.res_company_1')
From aca74a6ca7cb9df203d6e69f05ba9b80e89880e5 Mon Sep 17 00:00:00 2001
From: Sudhir Arya
Date: Mon, 22 Feb 2016 15:47:06 +0530
Subject: [PATCH 04/26] Migrated the module with test cases.
---
purchase_operating_unit/README.rst | 2 +-
purchase_operating_unit/__openerp__.py | 3 +-
purchase_operating_unit/models/procurement.py | 6 +-
purchase_operating_unit/models/purchase.py | 111 ++++++++++++------
.../tests/test_po_security.py | 4 +-
.../tests/test_purchase_operating_unit.py | 23 +++-
6 files changed, 107 insertions(+), 42 deletions(-)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index b034157cff..a738cb85da 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -22,7 +22,7 @@ Usage
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
- :target: https://runbot.odoo-community.org/runbot/213/7.0
+ :target: https://runbot.odoo-community.org/runbot/213/9.0
Bug Tracker
===========
diff --git a/purchase_operating_unit/__openerp__.py b/purchase_operating_unit/__openerp__.py
index 980fd08585..3384aaf801 100644
--- a/purchase_operating_unit/__openerp__.py
+++ b/purchase_operating_unit/__openerp__.py
@@ -9,7 +9,8 @@
"summary": "An operating unit (OU) is an organizational entity part of a\
company",
"version": "9.0.1.0.0",
- "author": "Eficent, Serpent Consulting Services Pvt. Ltd.,"
+ "author": "Eficent Business and IT Consulting Services S.L., "
+ "Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
"website": "http://www.eficent.com",
"category": "Purchase Management",
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
index 7cd036d19e..bd98de86bc 100644
--- a/purchase_operating_unit/models/procurement.py
+++ b/purchase_operating_unit/models/procurement.py
@@ -13,10 +13,10 @@ class ProcurementOrder(models.Model):
@api.one
@api.constrains('purchase_line_id')
- def _check_purchase_order_operating_unit(self, cr, uid, ids, context=None):
+ def _check_purchase_order_operating_unit(self):
purchase = self.purchase_line_id.purchase_id
- if purchase and\
- self.purchase.operating_unit_id !=\
+ if purchase and \
+ purchase.operating_unit_id !=\
self.location_id.operating_unit_id:
raise UserError(_('Configuration error!\nThe Quotation / Purchase\
Order and the Procurement Order must belong to the\
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase.py
index 65562264ff..9d142b31b9 100644
--- a/purchase_operating_unit/models/purchase.py
+++ b/purchase_operating_unit/models/purchase.py
@@ -3,14 +3,26 @@
# - Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp.tools.translate import _
-from openerp import api, fields, models
-from openerp.exceptions import UserError
+from openerp import _, api, exceptions, fields, models
+from openerp.exceptions import Warning
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
+ @api.model
+ def _default_picking_type(self):
+ res = super(PurchaseOrder, self)._default_picking_type()
+ type_obj = self.env['stock.picking.type']
+ operating_unit = self.env['res.users'].operating_unit_default_get(
+ self._uid)
+ types = type_obj.search([('code', '=', 'incoming'),
+ ('warehouse_id.operating_unit_id', '=',
+ operating_unit.id)])
+ if types:
+ res = types[:1].id
+ return res
+
operating_unit_id = fields.Many2one('operating.unit', 'Operating Unit',
default=lambda self:
self.env['res.users'].
@@ -21,19 +33,29 @@ class PurchaseOrder(models.Model):
self.env['res.users'].
operating_unit_default_get(self._uid))
-# @api.one
-# @api.constrains('operating_unit_id', 'picking_type_id')
-# def _check_warehouse_operating_unit(self):
-# picking_type = self.picking_type_id
-# if picking_type:
-# if picking_type.warehouse_id and\
-# picking_type.warehouse_id.operating_unit_id\
-# and self.operating_unit_id and\
-# picking_type.warehouse_id.operating_unit_id !=\
-# self.operating_unit_id:
-# raise UserError(_('Configuration error!\nThe\
-# Quotation / Purchase Order and the Warehouse of picking type\
-# must belong to the same Operating Unit.'))
+ picking_type_id = fields.Many2one('stock.picking.type', 'Deliver To',
+ help="This will determine picking type "
+ "of incoming shipment",
+ required=True,
+ states={'confirmed':
+ [('readonly', True)],
+ 'approved': [('readonly', True)],
+ 'done': [('readonly', True)]},
+ default=_default_picking_type)
+
+ @api.one
+ @api.constrains('operating_unit_id', 'picking_type_id')
+ def _check_warehouse_operating_unit(self):
+ picking_type = self.picking_type_id
+ if picking_type:
+ if picking_type.warehouse_id and\
+ picking_type.warehouse_id.operating_unit_id\
+ and self.operating_unit_id and\
+ picking_type.warehouse_id.operating_unit_id !=\
+ self.operating_unit_id:
+ raise Warning(_('Configuration error!\nThe\
+ Quotation / Purchase Order and the Warehouse of picking type\
+ must belong to the same Operating Unit.'))
@api.one
@api.constrains('operating_unit_id', 'requesting_operating_unit_id',
@@ -41,30 +63,39 @@ class PurchaseOrder(models.Model):
def _check_company_operating_unit(self):
if self.company_id and self.operating_unit_id and\
self.company_id != self.operating_unit_id.company_id:
- raise UserError(_('Configuration error!\nThe Company in the\
+ raise Warning(_('Configuration error!\nThe Company in the\
Purchase Order and in the Operating Unit must be the same.'))
- @api.onchange('requesting_operating_unit_id', 'operating_unit_id')
- def onchange_operating_unit_id(self):
- pick_type = self.env['stock.picking.type']
- location_obj = self.env['stock.location']
- if not self.requesting_operating_unit_id or not self.operating_unit_id:
- return {}
- request_locations =\
- location_obj.search([('operating_unit_id', '=',
- self.requesting_operating_unit_id.id)])
- picking_types =\
- pick_type.search([('default_location_dest_id', 'in',
- request_locations.ids)], limit=1)
- if picking_types:
- self.picking_type_id = picking_types.id
+ @api.onchange('operating_unit_id')
+ def _onchange_operating_unit_id(self):
+ type_obj = self.env['stock.picking.type']
+ if self.operating_unit_id:
+ types = type_obj.search([('code', '=', 'incoming'),
+ ('warehouse_id.operating_unit_id', '=',
+ self.operating_unit_id.id)])
+ if types:
+ self.picking_type_id = types[:1]
+ else:
+ raise exceptions.Warning(_("No Warehouse found with the "
+ "Operating Unit indicated in the "
+ "Purchase Order!"))
@api.model
def _prepare_picking(self):
- res = super(PurchaseOrder, self)._prepare_picking()
- res['operating_unit_id'] = self.operating_unit_id and\
+ picking_vals = super(PurchaseOrder, self)._prepare_picking()
+ picking_vals['operating_unit_id'] = self.operating_unit_id and\
self.operating_unit_id.id
- return res
+ return picking_vals
+
+ @api.one
+ @api.constrains('invoice_ids')
+ def _check_invoice_ou(self):
+ for po in self:
+ for invoice in po.invoice_ids:
+ if invoice.operating_unit_id != po.operating_unit_id:
+ raise Warning(_('The operating unit of the purchase order '
+ 'must be the same as in the '
+ 'associated invoices.'))
class PurchaseOrderLine(models.Model):
@@ -73,3 +104,15 @@ class PurchaseOrderLine(models.Model):
operating_unit_id = fields.Many2one('operating.unit',
related='order_id.operating_unit_id',
string='Operating Unit', readonly=True)
+
+ @api.one
+ @api.constrains('invoice_lines')
+ def _check_invoice_ou(self):
+ for line in self:
+ for inv_line in line.invoice_lines:
+ if inv_line.invoice_id and \
+ inv_line.invoice_id.operating_unit_id != \
+ line.operating_unit_id:
+ raise Warning(_('The operating unit of the purchase order '
+ 'must be the same as in the '
+ 'associated invoices.'))
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 293f7b2b8c..0ca2888caa 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -22,7 +22,7 @@ def test_po_ou_security(self):
self.StockPicking.sudo(self.user2_id).\
search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
self.assertEqual(picking_ids, [])
- # User 2 cannot list the invoice that was created from PO 2
+ # User 2 cannot list the invoice that was created from PO 1
invoice_ids = self.AccountInvoice.sudo(self.user2_id).\
search([('purchase_id', '=', self.purchase1.id)]).ids
self.assertEqual(invoice_ids, [])
@@ -37,7 +37,7 @@ def test_po_ou_security(self):
self.StockPicking.sudo(self.user1_id).\
search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
self.assertNotEqual(picking_ids, [])
- # User 1 can list the invoice that was created from PO 2
+# # User 1 can list the invoice that was created from PO 2
invoice_ids = self.AccountInvoice.sudo(self.user1_id).\
search([('purchase_id', '=', self.purchase1.id)]).ids
self.assertNotEqual(invoice_ids, [])
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index b352e5d863..1952908e7b 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -30,6 +30,8 @@ def setUp(self):
self.product1 = self.env.ref('product.product_product_7')
self.product2 = self.env.ref('product.product_product_9')
self.product3 = self.env.ref('product.product_product_11')
+ # Account
+ self.account = self.env.ref('l10n_generic_coa.conf_a_pay')
# Create users
self.user1_id = self._create_user('user_1',
[self.group_purchase_user,
@@ -46,6 +48,7 @@ def setUp(self):
(self.product2, 500),
(self.product3, 800)])
self.purchase1.sudo(self.user1_id).button_confirm()
+ self._create_invoice(self.purchase1, self.partner1, self.account)
def _create_user(self, login, groups, company, operating_units):
""" Create a user."""
@@ -79,10 +82,28 @@ def _create_purchase(self, user_id, line_products):
'date_planned': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}
lines.append((0, 0, line_values))
- return self.PurchaseOrder.sudo(user_id).create({
+ purchase = self.PurchaseOrder.sudo(user_id).create({
'operating_unit_id': self.ou1.id,
'requesting_operating_unit_id': self.ou1.id,
'partner_id': self.partner1.id,
'order_line': lines,
'company_id': self.company1.id,
})
+ return purchase
+
+ def _create_invoice(self, purchase, partner, account):
+ """ Create a vendor invoice for the purchase order."""
+ invoice_vals = {
+ 'purchase_id': purchase.id,
+ 'partner_id': partner.id,
+ 'account_id': account.id,
+ 'type': 'in_invoice',
+ }
+ purchase_context = {
+ 'active_id': purchase.id,
+ 'active_ids': purchase.ids,
+ 'active_model': 'purchase.order',
+ }
+ self.env['account.invoice'].with_context(purchase_context).\
+ create(invoice_vals)
+ return True
From dae053c3b3bc999c8c28326cc9d98c26113de60b Mon Sep 17 00:00:00 2001
From: jbeficent
Date: Thu, 6 Oct 2016 10:31:48 +0200
Subject: [PATCH 05/26] create PO from procurement
---
purchase_operating_unit/README.rst | 5 -
purchase_operating_unit/__openerp__.py | 8 +-
.../demo/purchase_order_demo.xml | 48 ++++---
purchase_operating_unit/models/procurement.py | 21 +--
purchase_operating_unit/models/purchase.py | 123 ++++++++++--------
.../security/purchase_security.xml | 46 ++++---
.../views/purchase_order_line_view.xml | 68 +++++-----
.../views/purchase_order_view.xml | 78 ++++++-----
8 files changed, 197 insertions(+), 200 deletions(-)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index a738cb85da..cf6cc99ff7 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -12,11 +12,6 @@ This module introduces the following features:
- The operating unit is copied to the stock picking.
- It implements user's security rules.
-
-Configuration
-=============
-
-
Usage
=====
diff --git a/purchase_operating_unit/__openerp__.py b/purchase_operating_unit/__openerp__.py
index 3384aaf801..3c3f7ff812 100644
--- a/purchase_operating_unit/__openerp__.py
+++ b/purchase_operating_unit/__openerp__.py
@@ -1,15 +1,15 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
{
"name": "Operating Unit in Purchase Orders",
- "summary": "An operating unit (OU) is an organizational entity part of a\
- company",
+ "summary": "An operating unit (OU) is an organizational entity part of a "
+ "company",
"version": "9.0.1.0.0",
- "author": "Eficent Business and IT Consulting Services S.L., "
+ "author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
"website": "http://www.eficent.com",
diff --git a/purchase_operating_unit/demo/purchase_order_demo.xml b/purchase_operating_unit/demo/purchase_order_demo.xml
index fc427bfe36..1db5f80a9f 100644
--- a/purchase_operating_unit/demo/purchase_order_demo.xml
+++ b/purchase_operating_unit/demo/purchase_order_demo.xml
@@ -1,34 +1,32 @@
-
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
index bd98de86bc..038657ddcd 100644
--- a/purchase_operating_unit/models/procurement.py
+++ b/purchase_operating_unit/models/procurement.py
@@ -3,9 +3,8 @@
# - Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp import api, models
-from openerp.tools.translate import _
-from openerp.exceptions import UserError
+from openerp import _, api, models
+from openerp.exceptions import ValidationError
class ProcurementOrder(models.Model):
@@ -14,13 +13,15 @@ class ProcurementOrder(models.Model):
@api.one
@api.constrains('purchase_line_id')
def _check_purchase_order_operating_unit(self):
- purchase = self.purchase_line_id.purchase_id
- if purchase and \
- purchase.operating_unit_id !=\
- self.location_id.operating_unit_id:
- raise UserError(_('Configuration error!\nThe Quotation / Purchase\
- Order and the Procurement Order must belong to the\
- same Operating Unit.'))
+ purchase = self.purchase_line_id.order_id
+ location = self.location_id
+ if (purchase and
+ purchase.operating_unit_id != location.operating_unit_id):
+ raise ValidationError(
+ _('Configuration error\nThe Quotation / Purchase Order and '
+ 'the Procurement Order must belong to the same '
+ 'Operating Unit.')
+ )
@api.multi
def _prepare_purchase_order(self, partner):
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase.py
index 9d142b31b9..69949fe142 100644
--- a/purchase_operating_unit/models/purchase.py
+++ b/purchase_operating_unit/models/purchase.py
@@ -3,8 +3,8 @@
# - Jordi Ballester Alomar
# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp import _, api, exceptions, fields, models
-from openerp.exceptions import Warning
+from openerp import _, api, fields, models
+from openerp.exceptions import ValidationError, UserError
class PurchaseOrder(models.Model):
@@ -15,7 +15,8 @@ def _default_picking_type(self):
res = super(PurchaseOrder, self)._default_picking_type()
type_obj = self.env['stock.picking.type']
operating_unit = self.env['res.users'].operating_unit_default_get(
- self._uid)
+ self.env.uid
+ )
types = type_obj.search([('code', '=', 'incoming'),
('warehouse_id.operating_unit_id', '=',
operating_unit.id)])
@@ -23,48 +24,57 @@ def _default_picking_type(self):
res = types[:1].id
return res
- operating_unit_id = fields.Many2one('operating.unit', 'Operating Unit',
- default=lambda self:
- self.env['res.users'].
- operating_unit_default_get(self._uid))
- requesting_operating_unit_id =\
- fields.Many2one('operating.unit', 'Requesting Operating Unit',
- default=lambda self:
- self.env['res.users'].
- operating_unit_default_get(self._uid))
+ operating_unit_id = fields.Many2one(
+ comodel_name='operating.unit',
+ string='Operating Unit',
+ default=lambda self: (self.env['res.users'].
+ operating_unit_default_get(self.env.uid))
+ )
+ requesting_operating_unit_id = fields.Many2one(
+ comodel_name='operating.unit',
+ string='Requesting Operating Unit',
+ default=lambda self: (self.env['res.users'].
+ operating_unit_default_get(self.env.uid))
+ )
- picking_type_id = fields.Many2one('stock.picking.type', 'Deliver To',
- help="This will determine picking type "
- "of incoming shipment",
- required=True,
- states={'confirmed':
- [('readonly', True)],
- 'approved': [('readonly', True)],
- 'done': [('readonly', True)]},
- default=_default_picking_type)
+ picking_type_id = fields.Many2one(
+ comodel_name='stock.picking.type',
+ string='Deliver To',
+ help="This will determine picking type of incoming shipment",
+ required=True,
+ states={'confirmed': [('readonly', True)],
+ 'approved': [('readonly', True)],
+ 'done': [('readonly', True)]},
+ default=lambda self: self._default_picking_type(),
+ )
- @api.one
@api.constrains('operating_unit_id', 'picking_type_id')
def _check_warehouse_operating_unit(self):
- picking_type = self.picking_type_id
- if picking_type:
- if picking_type.warehouse_id and\
- picking_type.warehouse_id.operating_unit_id\
- and self.operating_unit_id and\
- picking_type.warehouse_id.operating_unit_id !=\
- self.operating_unit_id:
- raise Warning(_('Configuration error!\nThe\
- Quotation / Purchase Order and the Warehouse of picking type\
- must belong to the same Operating Unit.'))
+ for record in self:
+ picking_type = record.picking_type_id
+ if not record.picking_type_id:
+ continue
+ warehouse = picking_type.warehouse_id
+ if (picking_type.warehouse_id and
+ picking_type.warehouse_id.operating_unit_id and
+ record.operating_unit_id and
+ warehouse.operating_unit_id != record.operating_unit_id):
+ raise ValidationError(
+ _('Configuration error\nThe Quotation / Purchase Order '
+ 'and the Warehouse of picking type must belong to the '
+ 'same Operating Unit.')
+ )
- @api.one
@api.constrains('operating_unit_id', 'requesting_operating_unit_id',
'company_id')
def _check_company_operating_unit(self):
- if self.company_id and self.operating_unit_id and\
- self.company_id != self.operating_unit_id.company_id:
- raise Warning(_('Configuration error!\nThe Company in the\
- Purchase Order and in the Operating Unit must be the same.'))
+ for record in self:
+ if (record.company_id and record.operating_unit_id and
+ record.company_id != record.operating_unit_id.company_id):
+ raise ValidationError(
+ _('Configuration error\nThe Company in the Purchase Order '
+ 'and in the Operating Unit must be the same.')
+ )
@api.onchange('operating_unit_id')
def _onchange_operating_unit_id(self):
@@ -76,43 +86,42 @@ def _onchange_operating_unit_id(self):
if types:
self.picking_type_id = types[:1]
else:
- raise exceptions.Warning(_("No Warehouse found with the "
- "Operating Unit indicated in the "
- "Purchase Order!"))
+ raise UserError(
+ _("No Warehouse found with the Operating Unit indicated "
+ "in the Purchase Order")
+ )
@api.model
def _prepare_picking(self):
picking_vals = super(PurchaseOrder, self)._prepare_picking()
- picking_vals['operating_unit_id'] = self.operating_unit_id and\
- self.operating_unit_id.id
+ picking_vals['operating_unit_id'] = self.operating_unit_id.id
return picking_vals
- @api.one
- @api.constrains('invoice_ids')
+ @api.constrains('invoice_ids', 'operating_unit_id')
def _check_invoice_ou(self):
for po in self:
for invoice in po.invoice_ids:
if invoice.operating_unit_id != po.operating_unit_id:
- raise Warning(_('The operating unit of the purchase order '
- 'must be the same as in the '
- 'associated invoices.'))
+ raise ValidationError(
+ _('The operating unit of the purchase order must '
+ 'be the same as in the associated invoices.')
+ )
class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
- operating_unit_id = fields.Many2one('operating.unit',
- related='order_id.operating_unit_id',
+ operating_unit_id = fields.Many2one(related='order_id.operating_unit_id',
string='Operating Unit', readonly=True)
- @api.one
- @api.constrains('invoice_lines')
+ @api.constrains('operating_unit_id', 'invoice_lines')
def _check_invoice_ou(self):
for line in self:
for inv_line in line.invoice_lines:
- if inv_line.invoice_id and \
- inv_line.invoice_id.operating_unit_id != \
- line.operating_unit_id:
- raise Warning(_('The operating unit of the purchase order '
- 'must be the same as in the '
- 'associated invoices.'))
+ invoice_operating_unit = inv_line.invoice_id.operating_unit_id
+ if (inv_line.invoice_id and
+ invoice_operating_unit != line.operating_unit_id):
+ raise ValidationError(
+ _('The operating unit of the purchase order must '
+ 'be the same as in the associated invoices.')
+ )
diff --git a/purchase_operating_unit/security/purchase_security.xml b/purchase_operating_unit/security/purchase_security.xml
index 14cdd36be4..f5ed96aaee 100644
--- a/purchase_operating_unit/security/purchase_security.xml
+++ b/purchase_operating_unit/security/purchase_security.xml
@@ -1,28 +1,26 @@
-
-
+
-
-
- ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
- PO's from allowed operating units
-
-
-
-
-
-
+
+
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
+ PO's from allowed operating units
+
+
+
+
+
+
-
-
- ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
- PO lines from allowed operating units
-
-
-
-
-
-
+
+
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
+ PO lines from allowed operating units
+
+
+
+
+
+
-
-
+
diff --git a/purchase_operating_unit/views/purchase_order_line_view.xml b/purchase_operating_unit/views/purchase_order_line_view.xml
index 283a8d9bc5..b0734875dc 100644
--- a/purchase_operating_unit/views/purchase_order_line_view.xml
+++ b/purchase_operating_unit/views/purchase_order_line_view.xml
@@ -1,43 +1,41 @@
-
-
+
-
- purchase_order_line_tree
- purchase.order.line
-
-
-
-
-
+
+ purchase_order_line_tree
+ purchase.order.line
+
+
+
+
-
+
+
-
- purchase_order_line_form
- purchase.order.line
-
-
-
-
-
+
+ purchase_order_line_form
+ purchase.order.line
+
+
+
+
-
+
+
-
- purchase_order_line_search
- purchase.order.line
-
-
-
-
-
-
-
-
+
+ purchase_order_line_search
+ purchase.order.line
+
+
+
+
+
+
+
-
+
+
-
-
+
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index cb3d7d9e4b..ee1f25e290 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -1,52 +1,50 @@
-
-
+
-
- purchase_order_tree
- purchase.order
-
-
-
-
-
+
+ purchase_order_tree
+ purchase.order
+
+
+
+
-
+
+
-
- purchase_order_form
- purchase.order
-
-
-
-
+
+ purchase_order_form
+ purchase.order
+
+
+
+
-
+
-
-
- {'operating_unit_id': operating_unit_id}
-
+
+
+ {'operating_unit_id': operating_unit_id}
+
-
-
+
+
-
- view_purchase_order_filter
- purchase.order
-
-
-
-
-
-
-
-
+
+ view_purchase_order_filter
+ purchase.order
+
+
+
+
+
+
+
-
+
+
-
-
+
From efd3bcc28ca15ce032dfec63d19e7e58b6f49d4d Mon Sep 17 00:00:00 2001
From: ahenriquez
Date: Tue, 31 Jan 2017 10:02:04 +0100
Subject: [PATCH 06/26] [MIG] purchase_operating_unit: Migrated to 10.0
---
purchase_operating_unit/README.rst | 5 +----
.../{__openerp__.py => __manifest__.py} | 4 ++--
purchase_operating_unit/models/__init__.py | 4 ++--
purchase_operating_unit/models/invoice.py | 17 ++++++++++++++---
purchase_operating_unit/models/procurement.py | 8 ++++----
purchase_operating_unit/models/purchase.py | 18 ++++--------------
purchase_operating_unit/tests/__init__.py | 4 ++--
.../tests/test_po_security.py | 6 +++---
.../tests/test_purchase_operating_unit.py | 8 ++++----
.../views/purchase_order_view.xml | 5 -----
10 files changed, 36 insertions(+), 43 deletions(-)
rename purchase_operating_unit/{__openerp__.py => __manifest__.py} (90%)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index cf6cc99ff7..e68b754012 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -12,12 +12,9 @@ This module introduces the following features:
- The operating unit is copied to the stock picking.
- It implements user's security rules.
-Usage
-=====
-
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
- :target: https://runbot.odoo-community.org/runbot/213/9.0
+ :target: https://runbot.odoo-community.org/runbot/213/10.0
Bug Tracker
===========
diff --git a/purchase_operating_unit/__openerp__.py b/purchase_operating_unit/__manifest__.py
similarity index 90%
rename from purchase_operating_unit/__openerp__.py
rename to purchase_operating_unit/__manifest__.py
index 3c3f7ff812..11a2f72dc8 100644
--- a/purchase_operating_unit/__openerp__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -1,14 +1,14 @@
# -*- coding: utf-8 -*-
# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
{
"name": "Operating Unit in Purchase Orders",
"summary": "An operating unit (OU) is an organizational entity part of a "
"company",
- "version": "9.0.1.0.0",
+ "version": "10.0.1.0.0",
"author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
diff --git a/purchase_operating_unit/models/__init__.py b/purchase_operating_unit/models/__init__.py
index eeebb4267f..df20d9dbe3 100644
--- a/purchase_operating_unit/models/__init__.py
+++ b/purchase_operating_unit/models/__init__.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import purchase
from . import procurement
diff --git a/purchase_operating_unit/models/invoice.py b/purchase_operating_unit/models/invoice.py
index eff0a4266c..3505850814 100644
--- a/purchase_operating_unit/models/invoice.py
+++ b/purchase_operating_unit/models/invoice.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp import api, models
+from odoo import api, models
class AccountInvoice(models.Model):
@@ -19,3 +19,14 @@ def purchase_order_change(self):
# Assign OU from PO to Invoice
self.operating_unit_id = self.purchase_id.operating_unit_id.id
return super(AccountInvoice, self).purchase_order_change()
+
+ @api.onchange('operating_unit_id')
+ def _onchange_allowed_purchase_ids(self):
+ '''
+ Show only the purchase orders that have the same operating unit
+ '''
+ result = super(AccountInvoice, self)._onchange_allowed_purchase_ids()
+
+ result['domain']['purchase_id'] += [('operating_unit_id', '=',
+ self.operating_unit_id.id)]
+ return result
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
index 038657ddcd..b6874bbb76 100644
--- a/purchase_operating_unit/models/procurement.py
+++ b/purchase_operating_unit/models/procurement.py
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp import _, api, models
-from openerp.exceptions import ValidationError
+from odoo import _, api, models
+from odoo.exceptions import ValidationError
class ProcurementOrder(models.Model):
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase.py
index 69949fe142..ba556dece5 100644
--- a/purchase_operating_unit/models/purchase.py
+++ b/purchase_operating_unit/models/purchase.py
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp import _, api, fields, models
-from openerp.exceptions import ValidationError, UserError
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError, UserError
class PurchaseOrder(models.Model):
@@ -97,16 +97,6 @@ def _prepare_picking(self):
picking_vals['operating_unit_id'] = self.operating_unit_id.id
return picking_vals
- @api.constrains('invoice_ids', 'operating_unit_id')
- def _check_invoice_ou(self):
- for po in self:
- for invoice in po.invoice_ids:
- if invoice.operating_unit_id != po.operating_unit_id:
- raise ValidationError(
- _('The operating unit of the purchase order must '
- 'be the same as in the associated invoices.')
- )
-
class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
diff --git a/purchase_operating_unit/tests/__init__.py b/purchase_operating_unit/tests/__init__.py
index cb1343a28e..de41426d68 100644
--- a/purchase_operating_unit/tests/__init__.py
+++ b/purchase_operating_unit/tests/__init__.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import test_purchase_operating_unit
from . import test_po_security
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 0ca2888caa..bd54d6a171 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from openerp.addons.purchase_operating_unit.tests import\
+from odoo.addons.purchase_operating_unit.tests import\
test_purchase_operating_unit as test_po_ou
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 1952908e7b..63e4198f54 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
-# © 2015 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
-# © 2015 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
import time
-from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
-from openerp.addons.purchase.tests import test_purchase_order
+from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
+from odoo.addons.purchase.tests import test_purchase_order
class TestPurchaseOperatingUnit(test_purchase_order.TestPurchaseOrder):
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index ee1f25e290..a1f9b73e2b 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -19,17 +19,12 @@
-
-
{'operating_unit_id': operating_unit_id}
-
-
-
From ffe89fb465cd22bcdc1d775fbf6462874a44bd28 Mon Sep 17 00:00:00 2001
From: Darshan Patel
Date: Tue, 4 Jul 2017 14:48:56 +0530
Subject: [PATCH 07/26] [FIX] readonly on OU
---
purchase_operating_unit/__manifest__.py | 2 +-
purchase_operating_unit/models/purchase.py | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 11a2f72dc8..5b060356e8 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -8,7 +8,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "An operating unit (OU) is an organizational entity part of a "
"company",
- "version": "10.0.1.0.0",
+ "version": "10.0.1.1.0",
"author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase.py
index ba556dece5..3e9fc4042d 100644
--- a/purchase_operating_unit/models/purchase.py
+++ b/purchase_operating_unit/models/purchase.py
@@ -24,15 +24,24 @@ def _default_picking_type(self):
res = types[:1].id
return res
+ READONLY_STATES = {
+ 'purchase': [('readonly', True)],
+ 'done': [('readonly', True)],
+ 'cancel': [('readonly', True)],
+ }
+
operating_unit_id = fields.Many2one(
comodel_name='operating.unit',
string='Operating Unit',
+ states=READONLY_STATES,
default=lambda self: (self.env['res.users'].
operating_unit_default_get(self.env.uid))
)
+
requesting_operating_unit_id = fields.Many2one(
comodel_name='operating.unit',
string='Requesting Operating Unit',
+ states=READONLY_STATES,
default=lambda self: (self.env['res.users'].
operating_unit_default_get(self.env.uid))
)
From d660ae0d9bc68f0419fb208a8f836f02d3b98ed0 Mon Sep 17 00:00:00 2001
From: aheficent
Date: Wed, 22 Nov 2017 18:20:45 +0100
Subject: [PATCH 08/26] [FIX] when the procurement location is not internal the
PO may belong to an OU
---
purchase_operating_unit/__manifest__.py | 2 +-
purchase_operating_unit/models/procurement.py | 25 +++++++++++--------
purchase_operating_unit/models/purchase.py | 2 +-
3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 5b060356e8..e7ac4dc1b2 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -8,7 +8,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "An operating unit (OU) is an organizational entity part of a "
"company",
- "version": "10.0.1.1.0",
+ "version": "10.0.1.1.1",
"author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
index b6874bbb76..2cd8e730d8 100644
--- a/purchase_operating_unit/models/procurement.py
+++ b/purchase_operating_unit/models/procurement.py
@@ -10,18 +10,21 @@
class ProcurementOrder(models.Model):
_inherit = 'procurement.order'
- @api.one
- @api.constrains('purchase_line_id')
+ @api.multi
+ @api.constrains('purchase_line_id', 'location_id')
def _check_purchase_order_operating_unit(self):
- purchase = self.purchase_line_id.order_id
- location = self.location_id
- if (purchase and
- purchase.operating_unit_id != location.operating_unit_id):
- raise ValidationError(
- _('Configuration error\nThe Quotation / Purchase Order and '
- 'the Procurement Order must belong to the same '
- 'Operating Unit.')
- )
+ for proc in self:
+ if not proc.purchase_line_id:
+ continue
+ ou = proc.location_id.operating_unit_id
+ order_ou = proc.purchase_line_id.operating_unit_id
+ if (ou != order_ou and
+ proc.location_id.usage not in ('supplier', 'customer')):
+ raise ValidationError(
+ _('Configuration error. The Quotation / Purchase Order '
+ 'and the Procurement Order must belong to the same '
+ 'Operating Unit.')
+ )
@api.multi
def _prepare_purchase_order(self, partner):
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase.py
index 3e9fc4042d..b7f9a01933 100644
--- a/purchase_operating_unit/models/purchase.py
+++ b/purchase_operating_unit/models/purchase.py
@@ -113,7 +113,7 @@ class PurchaseOrderLine(models.Model):
operating_unit_id = fields.Many2one(related='order_id.operating_unit_id',
string='Operating Unit', readonly=True)
- @api.constrains('operating_unit_id', 'invoice_lines')
+ @api.constrains('order_id.operating_unit_id', 'invoice_lines')
def _check_invoice_ou(self):
for line in self:
for inv_line in line.invoice_lines:
From 5b2e88fd1edbab3dd666dab3a3d06bf53698f855 Mon Sep 17 00:00:00 2001
From: aaron
Date: Mon, 11 Jun 2018 12:02:48 +0200
Subject: [PATCH 09/26] [FIX]PYLINT mainly
---
purchase_operating_unit/tests/test_po_security.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index bd54d6a171..89d0da8ea9 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -4,7 +4,7 @@
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo.addons.purchase_operating_unit.tests import\
- test_purchase_operating_unit as test_po_ou
+ test_purchase_operating_unit as test_po_ou # noqa
class TestPoSecurity(test_po_ou.TestPurchaseOperatingUnit):
From aeb13efdf2c260e974c71f32a723e3af590962b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Be=C3=B1at=20Jimenez?=
Date: Tue, 18 Dec 2018 10:11:05 +0100
Subject: [PATCH 10/26] [MIG] purchase_operating_unit: Migration to v12.0
---
purchase_operating_unit/README.rst | 90 +++-
purchase_operating_unit/__init__.py | 3 -
purchase_operating_unit/__manifest__.py | 11 +-
.../demo/purchase_order_demo.xml | 4 +
.../i18n/purchase_operating_unit.pot | 82 ++++
purchase_operating_unit/models/__init__.py | 9 +-
.../models/{invoice.py => account_invoice.py} | 17 +-
purchase_operating_unit/models/procurement.py | 38 --
.../models/{purchase.py => purchase_order.py} | 22 +-
.../readme/CONTRIBUTORS.rst | 3 +
.../readme/DESCRIPTION.rst | 6 +
purchase_operating_unit/readme/ROADMAP.rst | 3 +
purchase_operating_unit/readme/USAGE.rst | 6 +
.../security/purchase_security.xml | 8 +-
.../static/description/index.html | 447 ++++++++++++++++++
purchase_operating_unit/tests/__init__.py | 4 -
.../tests/test_po_security.py | 4 +-
.../tests/test_purchase_operating_unit.py | 7 +-
.../views/purchase_order_line_view.xml | 21 +-
.../views/purchase_order_view.xml | 25 +-
20 files changed, 685 insertions(+), 125 deletions(-)
create mode 100644 purchase_operating_unit/i18n/purchase_operating_unit.pot
rename purchase_operating_unit/models/{invoice.py => account_invoice.py} (66%)
delete mode 100644 purchase_operating_unit/models/procurement.py
rename purchase_operating_unit/models/{purchase.py => purchase_order.py} (81%)
create mode 100644 purchase_operating_unit/readme/CONTRIBUTORS.rst
create mode 100644 purchase_operating_unit/readme/DESCRIPTION.rst
create mode 100644 purchase_operating_unit/readme/ROADMAP.rst
create mode 100644 purchase_operating_unit/readme/USAGE.rst
create mode 100644 purchase_operating_unit/static/description/index.html
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index e68b754012..53cc27fdbd 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -1,56 +1,98 @@
-.. image:: https://img.shields.io/badge/license-AGPLv3-blue.svg
- :target: https://www.gnu.org/licenses/lgpl.html
- :alt: License: LGPL-3
-
-===============================
-Purchase with Operating Units
-===============================
+=================================
+Operating Unit in Purchase Orders
+=================================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |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-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/12.0/purchase_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-12-0/operating-unit-12-0-purchase_operating_unit
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/213/12.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
This module introduces the following features:
+
- It introduces the operating unit to the purchase order.
- The operating unit is copied to the invoice.
- The operating unit is copied to the stock picking.
- It implements user's security rules.
-.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
- :alt: Try me on Runbot
- :target: https://runbot.odoo-community.org/runbot/213/10.0
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+#. Create a PO: the Default Operating Unit is assigned to the PO. If you want,
+ you can change to another Operating Unit.
+#. Validate the PO: the Operating Unit is propagated to the Pickings and
+ Invoices.
+#. From the invoice, it is not possible to change the Operating Unit, it has to
+ be the same as the one of the PO.
+
+Known issues / Roadmap
+======================
+
+Procurement Orders were removed. Procurement Operating Unit module is
+deprecated. Stock Operating Unit ensures consistency between the operating unit
+from different models.
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 smashing it by providing a detailed and welcomed feedback.
+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 smashing it by providing a detailed and welcomed
+`feedback `_.
+Do not contact contributors directly about support or help with technical issues.
Credits
=======
-Images
-------
+Authors
+~~~~~~~
-* Odoo Community Association: `Icon `_.
+* Eficent
+* Serpent Consulting Services Pvt. Ltd.
Contributors
-------------
+~~~~~~~~~~~~
* Jordi Ballester Alomar
* Aaron Henriquez
* Sudhir Arya
-Maintainer
-----------
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
- :target: http://odoo-community.org
-
-This module is maintained by the OCA.
+ :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.
-To contribute to this module, please visit http://odoo-community.org.
+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/purchase_operating_unit/__init__.py b/purchase_operating_unit/__init__.py
index cf1a072540..133f68732d 100644
--- a/purchase_operating_unit/__init__.py
+++ b/purchase_operating_unit/__init__.py
@@ -1,5 +1,2 @@
-# -*- coding: utf-8 -*-
-# © 2016 Eficent Business and IT Consulting Services S.L.
-# © 2016 Serpent Consulting Services Pvt. Ltd.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import models
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index e7ac4dc1b2..0327137673 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
@@ -6,15 +5,15 @@
{
"name": "Operating Unit in Purchase Orders",
- "summary": "An operating unit (OU) is an organizational entity part of a "
- "company",
- "version": "10.0.1.1.1",
+ "summary": "Adds the concecpt of operating unit (OU) in purchase order "
+ "management",
+ "version": "12.0.1.0.0",
"author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
- "website": "http://www.eficent.com",
+ "website": "https://github.com/OCA/operating-unit",
"category": "Purchase Management",
- "depends": ["purchase", "procurement_operating_unit"],
+ "depends": ["stock_operating_unit", "purchase_stock"],
"license": "LGPL-3",
"data": [
"security/purchase_security.xml",
diff --git a/purchase_operating_unit/demo/purchase_order_demo.xml b/purchase_operating_unit/demo/purchase_order_demo.xml
index 1db5f80a9f..7071a0fba2 100644
--- a/purchase_operating_unit/demo/purchase_order_demo.xml
+++ b/purchase_operating_unit/demo/purchase_order_demo.xml
@@ -1,4 +1,8 @@
+
+
+
+
diff --git a/purchase_operating_unit/i18n/purchase_operating_unit.pot b/purchase_operating_unit/i18n/purchase_operating_unit.pot
new file mode 100644
index 0000000000..1f1bb85df3
--- /dev/null
+++ b/purchase_operating_unit/i18n/purchase_operating_unit.pot
@@ -0,0 +1,82 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * purchase_operating_unit
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.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: purchase_operating_unit
+#: code:addons/purchase_operating_unit/models/purchase_order.py:82
+#, python-format
+msgid "Configuration error. The Company in the Purchase Order and in the Operating Unit must be the same."
+msgstr ""
+
+#. module: purchase_operating_unit
+#: code:addons/purchase_operating_unit/models/purchase_order.py:71
+#, python-format
+msgid "Configuration error. The Quotation / Purchase Order and the Warehouse of picking type must belong to the same Operating Unit."
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__picking_type_id
+msgid "Deliver To"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model,name:purchase_operating_unit.model_account_invoice
+msgid "Invoice"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model,name:purchase_operating_unit.model_account_invoice_line
+msgid "Invoice Line"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: code:addons/purchase_operating_unit/models/purchase_order.py:97
+#, python-format
+msgid "No Warehouse found with the Operating Unit indicated in the Purchase Order"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__operating_unit_id
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line__operating_unit_id
+#: model_terms:ir.ui.view,arch_db:purchase_operating_unit.purchase_order_line_search
+#: model_terms:ir.ui.view,arch_db:purchase_operating_unit.view_purchase_order_filter
+msgid "Operating Unit"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model,name:purchase_operating_unit.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model,name:purchase_operating_unit.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__requesting_operating_unit_id
+msgid "Requesting Operating Unit"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: code:addons/purchase_operating_unit/models/account_invoice.py:43
+#, python-format
+msgid "The operating unit of the purchase order must be the same as in the associated invoices."
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model.fields,help:purchase_operating_unit.field_purchase_order__picking_type_id
+msgid "This will determine picking type of incoming shipment"
+msgstr ""
+
diff --git a/purchase_operating_unit/models/__init__.py b/purchase_operating_unit/models/__init__.py
index df20d9dbe3..14eb8bcd10 100644
--- a/purchase_operating_unit/models/__init__.py
+++ b/purchase_operating_unit/models/__init__.py
@@ -1,8 +1,3 @@
-# -*- coding: utf-8 -*-
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
-# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from . import purchase
-from . import procurement
-from . import invoice
+from . import purchase_order
+from . import account_invoice
diff --git a/purchase_operating_unit/models/invoice.py b/purchase_operating_unit/models/account_invoice.py
similarity index 66%
rename from purchase_operating_unit/models/invoice.py
rename to purchase_operating_unit/models/account_invoice.py
index 3505850814..93e559ec79 100644
--- a/purchase_operating_unit/models/invoice.py
+++ b/purchase_operating_unit/models/account_invoice.py
@@ -1,9 +1,8 @@
-# -*- coding: utf-8 -*-
# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from odoo import api, models
+from odoo import _, api, exceptions, models
class AccountInvoice(models.Model):
@@ -30,3 +29,17 @@ def _onchange_allowed_purchase_ids(self):
result['domain']['purchase_id'] += [('operating_unit_id', '=',
self.operating_unit_id.id)]
return result
+
+
+class AccountInvoiceLines(models.Model):
+ _inherit = 'account.invoice.line'
+
+ @api.constrains('operating_unit_id', 'purchase_line_id')
+ def _check_invoice_ou(self):
+ for line in self:
+ if (line.purchase_line_id and line.operating_unit_id !=
+ line.purchase_line_id.operating_unit_id):
+ raise exceptions.ValidationError(
+ _('The operating unit of the purchase order must '
+ 'be the same as in the associated invoices.')
+ )
diff --git a/purchase_operating_unit/models/procurement.py b/purchase_operating_unit/models/procurement.py
deleted file mode 100644
index 2cd8e730d8..0000000000
--- a/purchase_operating_unit/models/procurement.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
-# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
-# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from odoo import _, api, models
-from odoo.exceptions import ValidationError
-
-
-class ProcurementOrder(models.Model):
- _inherit = 'procurement.order'
-
- @api.multi
- @api.constrains('purchase_line_id', 'location_id')
- def _check_purchase_order_operating_unit(self):
- for proc in self:
- if not proc.purchase_line_id:
- continue
- ou = proc.location_id.operating_unit_id
- order_ou = proc.purchase_line_id.operating_unit_id
- if (ou != order_ou and
- proc.location_id.usage not in ('supplier', 'customer')):
- raise ValidationError(
- _('Configuration error. The Quotation / Purchase Order '
- 'and the Procurement Order must belong to the same '
- 'Operating Unit.')
- )
-
- @api.multi
- def _prepare_purchase_order(self, partner):
- res = super(ProcurementOrder, self)._prepare_purchase_order(partner)
- operating_unit = self.location_id.operating_unit_id
- if operating_unit:
- res.update({
- 'operating_unit_id': operating_unit.id,
- 'requesting_operating_unit_id': operating_unit.id
- })
- return res
diff --git a/purchase_operating_unit/models/purchase.py b/purchase_operating_unit/models/purchase_order.py
similarity index 81%
rename from purchase_operating_unit/models/purchase.py
rename to purchase_operating_unit/models/purchase_order.py
index b7f9a01933..4149c7921f 100644
--- a/purchase_operating_unit/models/purchase.py
+++ b/purchase_operating_unit/models/purchase_order.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
@@ -69,19 +68,18 @@ def _check_warehouse_operating_unit(self):
record.operating_unit_id and
warehouse.operating_unit_id != record.operating_unit_id):
raise ValidationError(
- _('Configuration error\nThe Quotation / Purchase Order '
+ _('Configuration error. The Quotation / Purchase Order '
'and the Warehouse of picking type must belong to the '
'same Operating Unit.')
)
- @api.constrains('operating_unit_id', 'requesting_operating_unit_id',
- 'company_id')
+ @api.constrains('operating_unit_id', 'company_id')
def _check_company_operating_unit(self):
for record in self:
if (record.company_id and record.operating_unit_id and
record.company_id != record.operating_unit_id.company_id):
raise ValidationError(
- _('Configuration error\nThe Company in the Purchase Order '
+ _('Configuration error. The Company in the Purchase Order '
'and in the Operating Unit must be the same.')
)
@@ -111,16 +109,4 @@ class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
operating_unit_id = fields.Many2one(related='order_id.operating_unit_id',
- string='Operating Unit', readonly=True)
-
- @api.constrains('order_id.operating_unit_id', 'invoice_lines')
- def _check_invoice_ou(self):
- for line in self:
- for inv_line in line.invoice_lines:
- invoice_operating_unit = inv_line.invoice_id.operating_unit_id
- if (inv_line.invoice_id and
- invoice_operating_unit != line.operating_unit_id):
- raise ValidationError(
- _('The operating unit of the purchase order must '
- 'be the same as in the associated invoices.')
- )
+ string='Operating Unit')
diff --git a/purchase_operating_unit/readme/CONTRIBUTORS.rst b/purchase_operating_unit/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000000..4244f4e535
--- /dev/null
+++ b/purchase_operating_unit/readme/CONTRIBUTORS.rst
@@ -0,0 +1,3 @@
+* Jordi Ballester Alomar
+* Aaron Henriquez
+* Sudhir Arya
diff --git a/purchase_operating_unit/readme/DESCRIPTION.rst b/purchase_operating_unit/readme/DESCRIPTION.rst
new file mode 100644
index 0000000000..ace6b56436
--- /dev/null
+++ b/purchase_operating_unit/readme/DESCRIPTION.rst
@@ -0,0 +1,6 @@
+This module introduces the following features:
+
+- It introduces the operating unit to the purchase order.
+- The operating unit is copied to the invoice.
+- The operating unit is copied to the stock picking.
+- It implements user's security rules.
diff --git a/purchase_operating_unit/readme/ROADMAP.rst b/purchase_operating_unit/readme/ROADMAP.rst
new file mode 100644
index 0000000000..e066763c22
--- /dev/null
+++ b/purchase_operating_unit/readme/ROADMAP.rst
@@ -0,0 +1,3 @@
+Procurement Orders were removed. Procurement Operating Unit module is
+deprecated. Stock Operating Unit ensures consistency between the operating unit
+from different models.
diff --git a/purchase_operating_unit/readme/USAGE.rst b/purchase_operating_unit/readme/USAGE.rst
new file mode 100644
index 0000000000..0f2c129360
--- /dev/null
+++ b/purchase_operating_unit/readme/USAGE.rst
@@ -0,0 +1,6 @@
+#. Create a PO: the Default Operating Unit is assigned to the PO. If you want,
+ you can change to another Operating Unit.
+#. Validate the PO: the Operating Unit is propagated to the Pickings and
+ Invoices.
+#. From the invoice, it is not possible to change the Operating Unit, it has to
+ be the same as the one of the PO.
diff --git a/purchase_operating_unit/security/purchase_security.xml b/purchase_operating_unit/security/purchase_security.xml
index f5ed96aaee..b6727e68b9 100644
--- a/purchase_operating_unit/security/purchase_security.xml
+++ b/purchase_operating_unit/security/purchase_security.xml
@@ -1,9 +1,13 @@
+
+
+
+
- ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in', user.operating_unit_ids.ids)]
PO's from allowed operating units
@@ -14,7 +18,7 @@
- ['|',('operating_unit_id','=',False),('operating_unit_id','in',[g.id for g in user.operating_unit_ids])]
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in', user.operating_unit_ids.ids)]
PO lines from allowed operating units
diff --git a/purchase_operating_unit/static/description/index.html b/purchase_operating_unit/static/description/index.html
new file mode 100644
index 0000000000..7457d289d2
--- /dev/null
+++ b/purchase_operating_unit/static/description/index.html
@@ -0,0 +1,447 @@
+
+
+
+
+
+
+Operating Unit in Purchase Orders
+
+
+
+
+
Operating Unit in Purchase Orders
+
+
+

+
This module introduces the following features:
+
+- It introduces the operating unit to the purchase order.
+- The operating unit is copied to the invoice.
+- The operating unit is copied to the stock picking.
+- It implements user’s security rules.
+
+
Table of contents
+
+
+
+
+- Create a PO: the Default Operating Unit is assigned to the PO. If you want,
+you can change to another Operating Unit.
+- Validate the PO: the Operating Unit is propagated to the Pickings and
+Invoices.
+- From the invoice, it is not possible to change the Operating Unit, it has to
+be the same as the one of the PO.
+
+
+
+
+
Procurement Orders were removed. Procurement Operating Unit module is
+deprecated. Stock Operating Unit ensures consistency between the operating unit
+from different models.
+
+
+
+
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 smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+- Eficent
+- Serpent Consulting Services Pvt. Ltd.
+
+
+
+
+
+
This module is maintained by the OCA.
+

+
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/purchase_operating_unit/tests/__init__.py b/purchase_operating_unit/tests/__init__.py
index de41426d68..9c86acd517 100644
--- a/purchase_operating_unit/tests/__init__.py
+++ b/purchase_operating_unit/tests/__init__.py
@@ -1,7 +1,3 @@
-# -*- coding: utf-8 -*-
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
-# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import test_purchase_operating_unit
from . import test_po_security
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 89d0da8ea9..04387f73a3 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -1,10 +1,8 @@
-# -*- coding: utf-8 -*-
# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from odoo.addons.purchase_operating_unit.tests import\
- test_purchase_operating_unit as test_po_ou # noqa
+from . import test_purchase_operating_unit as test_po_ou # noqa
class TestPoSecurity(test_po_ou.TestPurchaseOperatingUnit):
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 63e4198f54..561a51ebd7 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -1,19 +1,20 @@
-# -*- coding: utf-8 -*-
# © 2015-17 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
import time
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
-from odoo.addons.purchase.tests import test_purchase_order
+from odoo.tests import common
-class TestPurchaseOperatingUnit(test_purchase_order.TestPurchaseOrder):
+class TestPurchaseOperatingUnit(common.TransactionCase):
def setUp(self):
super(TestPurchaseOperatingUnit, self).setUp()
self.ResUsers = self.env['res.users']
self.StockPicking = self.env['stock.picking']
+ self.PurchaseOrder = self.env['purchase.order']
+ self.AccountInvoice = self.env['account.invoice']
# company
self.company1 = self.env.ref('base.main_company')
self.company2 = self.env.ref('stock.res_company_1')
diff --git a/purchase_operating_unit/views/purchase_order_line_view.xml b/purchase_operating_unit/views/purchase_order_line_view.xml
index b0734875dc..11dd70fd42 100644
--- a/purchase_operating_unit/views/purchase_order_line_view.xml
+++ b/purchase_operating_unit/views/purchase_order_line_view.xml
@@ -7,7 +7,9 @@
-
+
@@ -18,7 +20,9 @@
-
+
@@ -28,12 +32,15 @@
purchase.order.line
-
-
-
+
+
+
-
+
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index a1f9b73e2b..92362e6717 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -7,7 +7,9 @@
-
+
@@ -18,13 +20,16 @@
-
-
+
+
-
+
{'operating_unit_id': operating_unit_id}
-
+
@@ -34,10 +39,14 @@
-
+
-
+
From 78c8444061fc5e114654548aee31784e10377591 Mon Sep 17 00:00:00 2001
From: BT-nstuder
Date: Tue, 7 Jan 2020 10:49:27 +0100
Subject: [PATCH 11/26] [IMP] purchase_operating_unit: black, isort, prettier
---
purchase_operating_unit/__manifest__.py | 10 +-
.../demo/purchase_order_demo.xml | 24 ++--
.../models/account_invoice.py | 31 +++--
.../models/purchase_order.py | 116 +++++++++-------
.../security/purchase_security.xml | 37 ++---
.../tests/test_po_security.py | 49 ++++---
.../tests/test_purchase_operating_unit.py | 131 +++++++++---------
.../views/purchase_order_line_view.xml | 39 +++---
.../views/purchase_order_view.xml | 50 ++++---
9 files changed, 266 insertions(+), 221 deletions(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 0327137673..aa8c1da7d5 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -6,11 +6,11 @@
{
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
- "management",
+ "management",
"version": "12.0.1.0.0",
"author": "Eficent, "
- "Serpent Consulting Services Pvt. Ltd.,"
- "Odoo Community Association (OCA)",
+ "Serpent Consulting Services Pvt. Ltd.,"
+ "Odoo Community Association (OCA)",
"website": "https://github.com/OCA/operating-unit",
"category": "Purchase Management",
"depends": ["stock_operating_unit", "purchase_stock"],
@@ -20,8 +20,6 @@
"views/purchase_order_view.xml",
"views/purchase_order_line_view.xml",
],
- "demo": [
- "demo/purchase_order_demo.xml",
- ],
+ "demo": ["demo/purchase_order_demo.xml"],
"installable": True,
}
diff --git a/purchase_operating_unit/demo/purchase_order_demo.xml b/purchase_operating_unit/demo/purchase_order_demo.xml
index 7071a0fba2..46b3fdb4a0 100644
--- a/purchase_operating_unit/demo/purchase_order_demo.xml
+++ b/purchase_operating_unit/demo/purchase_order_demo.xml
@@ -1,36 +1,28 @@
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
diff --git a/purchase_operating_unit/models/account_invoice.py b/purchase_operating_unit/models/account_invoice.py
index 93e559ec79..267c79f60c 100644
--- a/purchase_operating_unit/models/account_invoice.py
+++ b/purchase_operating_unit/models/account_invoice.py
@@ -6,10 +6,10 @@
class AccountInvoice(models.Model):
- _inherit = 'account.invoice'
+ _inherit = "account.invoice"
# Load all unsold PO lines
- @api.onchange('purchase_id')
+ @api.onchange("purchase_id")
def purchase_order_change(self):
"""
Override to add Operating Unit from Purchase Order to Invoice.
@@ -19,27 +19,32 @@ def purchase_order_change(self):
self.operating_unit_id = self.purchase_id.operating_unit_id.id
return super(AccountInvoice, self).purchase_order_change()
- @api.onchange('operating_unit_id')
+ @api.onchange("operating_unit_id")
def _onchange_allowed_purchase_ids(self):
- '''
+ """
Show only the purchase orders that have the same operating unit
- '''
+ """
result = super(AccountInvoice, self)._onchange_allowed_purchase_ids()
- result['domain']['purchase_id'] += [('operating_unit_id', '=',
- self.operating_unit_id.id)]
+ result["domain"]["purchase_id"] += [
+ ("operating_unit_id", "=", self.operating_unit_id.id)
+ ]
return result
class AccountInvoiceLines(models.Model):
- _inherit = 'account.invoice.line'
+ _inherit = "account.invoice.line"
- @api.constrains('operating_unit_id', 'purchase_line_id')
+ @api.constrains("operating_unit_id", "purchase_line_id")
def _check_invoice_ou(self):
for line in self:
- if (line.purchase_line_id and line.operating_unit_id !=
- line.purchase_line_id.operating_unit_id):
+ if (
+ line.purchase_line_id
+ and line.operating_unit_id != line.purchase_line_id.operating_unit_id
+ ):
raise exceptions.ValidationError(
- _('The operating unit of the purchase order must '
- 'be the same as in the associated invoices.')
+ _(
+ "The operating unit of the purchase order must "
+ "be the same as in the associated invoices."
+ )
)
diff --git a/purchase_operating_unit/models/purchase_order.py b/purchase_operating_unit/models/purchase_order.py
index 4149c7921f..70dd184a43 100644
--- a/purchase_operating_unit/models/purchase_order.py
+++ b/purchase_operating_unit/models/purchase_order.py
@@ -3,110 +3,130 @@
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo import _, api, fields, models
-from odoo.exceptions import ValidationError, UserError
+from odoo.exceptions import UserError, ValidationError
class PurchaseOrder(models.Model):
- _inherit = 'purchase.order'
+ _inherit = "purchase.order"
@api.model
def _default_picking_type(self):
res = super(PurchaseOrder, self)._default_picking_type()
- type_obj = self.env['stock.picking.type']
- operating_unit = self.env['res.users'].operating_unit_default_get(
- self.env.uid
+ type_obj = self.env["stock.picking.type"]
+ operating_unit = self.env["res.users"].operating_unit_default_get(self.env.uid)
+ types = type_obj.search(
+ [
+ ("code", "=", "incoming"),
+ ("warehouse_id.operating_unit_id", "=", operating_unit.id),
+ ]
)
- types = type_obj.search([('code', '=', 'incoming'),
- ('warehouse_id.operating_unit_id', '=',
- operating_unit.id)])
if types:
res = types[:1].id
return res
READONLY_STATES = {
- 'purchase': [('readonly', True)],
- 'done': [('readonly', True)],
- 'cancel': [('readonly', True)],
+ "purchase": [("readonly", True)],
+ "done": [("readonly", True)],
+ "cancel": [("readonly", True)],
}
operating_unit_id = fields.Many2one(
- comodel_name='operating.unit',
- string='Operating Unit',
+ comodel_name="operating.unit",
+ string="Operating Unit",
states=READONLY_STATES,
- default=lambda self: (self.env['res.users'].
- operating_unit_default_get(self.env.uid))
+ default=lambda self: (
+ self.env["res.users"].operating_unit_default_get(self.env.uid)
+ ),
)
requesting_operating_unit_id = fields.Many2one(
- comodel_name='operating.unit',
- string='Requesting Operating Unit',
+ comodel_name="operating.unit",
+ string="Requesting Operating Unit",
states=READONLY_STATES,
- default=lambda self: (self.env['res.users'].
- operating_unit_default_get(self.env.uid))
+ default=lambda self: (
+ self.env["res.users"].operating_unit_default_get(self.env.uid)
+ ),
)
picking_type_id = fields.Many2one(
- comodel_name='stock.picking.type',
- string='Deliver To',
+ comodel_name="stock.picking.type",
+ string="Deliver To",
help="This will determine picking type of incoming shipment",
required=True,
- states={'confirmed': [('readonly', True)],
- 'approved': [('readonly', True)],
- 'done': [('readonly', True)]},
+ states={
+ "confirmed": [("readonly", True)],
+ "approved": [("readonly", True)],
+ "done": [("readonly", True)],
+ },
default=lambda self: self._default_picking_type(),
)
- @api.constrains('operating_unit_id', 'picking_type_id')
+ @api.constrains("operating_unit_id", "picking_type_id")
def _check_warehouse_operating_unit(self):
for record in self:
picking_type = record.picking_type_id
if not record.picking_type_id:
continue
warehouse = picking_type.warehouse_id
- if (picking_type.warehouse_id and
- picking_type.warehouse_id.operating_unit_id and
- record.operating_unit_id and
- warehouse.operating_unit_id != record.operating_unit_id):
+ if (
+ picking_type.warehouse_id
+ and picking_type.warehouse_id.operating_unit_id
+ and record.operating_unit_id
+ and warehouse.operating_unit_id != record.operating_unit_id
+ ):
raise ValidationError(
- _('Configuration error. The Quotation / Purchase Order '
- 'and the Warehouse of picking type must belong to the '
- 'same Operating Unit.')
+ _(
+ "Configuration error. The Quotation / Purchase Order "
+ "and the Warehouse of picking type must belong to the "
+ "same Operating Unit."
+ )
)
- @api.constrains('operating_unit_id', 'company_id')
+ @api.constrains("operating_unit_id", "company_id")
def _check_company_operating_unit(self):
for record in self:
- if (record.company_id and record.operating_unit_id and
- record.company_id != record.operating_unit_id.company_id):
+ if (
+ record.company_id
+ and record.operating_unit_id
+ and record.company_id != record.operating_unit_id.company_id
+ ):
raise ValidationError(
- _('Configuration error. The Company in the Purchase Order '
- 'and in the Operating Unit must be the same.')
+ _(
+ "Configuration error. The Company in the Purchase Order "
+ "and in the Operating Unit must be the same."
+ )
)
- @api.onchange('operating_unit_id')
+ @api.onchange("operating_unit_id")
def _onchange_operating_unit_id(self):
- type_obj = self.env['stock.picking.type']
+ type_obj = self.env["stock.picking.type"]
if self.operating_unit_id:
- types = type_obj.search([('code', '=', 'incoming'),
- ('warehouse_id.operating_unit_id', '=',
- self.operating_unit_id.id)])
+ types = type_obj.search(
+ [
+ ("code", "=", "incoming"),
+ ("warehouse_id.operating_unit_id", "=", self.operating_unit_id.id),
+ ]
+ )
if types:
self.picking_type_id = types[:1]
else:
raise UserError(
- _("No Warehouse found with the Operating Unit indicated "
- "in the Purchase Order")
+ _(
+ "No Warehouse found with the Operating Unit indicated "
+ "in the Purchase Order"
+ )
)
@api.model
def _prepare_picking(self):
picking_vals = super(PurchaseOrder, self)._prepare_picking()
- picking_vals['operating_unit_id'] = self.operating_unit_id.id
+ picking_vals["operating_unit_id"] = self.operating_unit_id.id
return picking_vals
class PurchaseOrderLine(models.Model):
- _inherit = 'purchase.order.line'
+ _inherit = "purchase.order.line"
- operating_unit_id = fields.Many2one(related='order_id.operating_unit_id',
- string='Operating Unit')
+ operating_unit_id = fields.Many2one(
+ related="order_id.operating_unit_id", string="Operating Unit"
+ )
diff --git a/purchase_operating_unit/security/purchase_security.xml b/purchase_operating_unit/security/purchase_security.xml
index b6727e68b9..5c6d8791ce 100644
--- a/purchase_operating_unit/security/purchase_security.xml
+++ b/purchase_operating_unit/security/purchase_security.xml
@@ -1,30 +1,31 @@
-
+
-
-
- ['|',('operating_unit_id','=',False),('operating_unit_id','in', user.operating_unit_ids.ids)]
+
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in', user.operating_unit_ids.ids)]
PO's from allowed operating units
-
-
-
-
-
+
+
+
+
+
-
-
- ['|',('operating_unit_id','=',False),('operating_unit_id','in', user.operating_unit_ids.ids)]
+
+ ['|',('operating_unit_id','=',False),('operating_unit_id','in', user.operating_unit_ids.ids)]
PO lines from allowed operating units
-
-
-
-
-
+
+
+
+
+
-
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 04387f73a3..2b5fcc6cdd 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -6,36 +6,49 @@
class TestPoSecurity(test_po_ou.TestPurchaseOperatingUnit):
-
def test_po_ou_security(self):
"""Test Security of Purchase Operating Unit"""
# User 2 is only assigned to Operating Unit 2, and cannot list
# purchase orders from Operating Unit 1.
- po_ids =\
- self.PurchaseOrder.sudo(self.user2_id).\
- search([('operating_unit_id', '=', self.ou1.id)]).ids
+ po_ids = (
+ self.PurchaseOrder.sudo(self.user2_id)
+ .search([("operating_unit_id", "=", self.ou1.id)])
+ .ids
+ )
self.assertEqual(po_ids, [])
# User 2 cannot list the picking that was created from PO 1
- picking_ids =\
- self.StockPicking.sudo(self.user2_id).\
- search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
+ picking_ids = (
+ self.StockPicking.sudo(self.user2_id)
+ .search([("id", "in", self.purchase1.picking_ids.ids)])
+ .ids
+ )
self.assertEqual(picking_ids, [])
# User 2 cannot list the invoice that was created from PO 1
- invoice_ids = self.AccountInvoice.sudo(self.user2_id).\
- search([('purchase_id', '=', self.purchase1.id)]).ids
+ invoice_ids = (
+ self.AccountInvoice.sudo(self.user2_id)
+ .search([("purchase_id", "=", self.purchase1.id)])
+ .ids
+ )
self.assertEqual(invoice_ids, [])
# User 1 is assigned to Operating Unit 1, and can list
# the purchase order 1 from Operating Unit 1.
- po_ids =\
- self.PurchaseOrder.sudo(self.user1_id).\
- search([('operating_unit_id', '=', self.ou1.id)]).ids
+ po_ids = (
+ self.PurchaseOrder.sudo(self.user1_id)
+ .search([("operating_unit_id", "=", self.ou1.id)])
+ .ids
+ )
self.assertNotEqual(po_ids, [])
# User 1 can list the picking that was created from PO 1
- picking_ids =\
- self.StockPicking.sudo(self.user1_id).\
- search([('id', 'in', self.purchase1.picking_ids.ids)]).ids
+ picking_ids = (
+ self.StockPicking.sudo(self.user1_id)
+ .search([("id", "in", self.purchase1.picking_ids.ids)])
+ .ids
+ )
self.assertNotEqual(picking_ids, [])
-# # User 1 can list the invoice that was created from PO 2
- invoice_ids = self.AccountInvoice.sudo(self.user1_id).\
- search([('purchase_id', '=', self.purchase1.id)]).ids
+ # # User 1 can list the invoice that was created from PO 2
+ invoice_ids = (
+ self.AccountInvoice.sudo(self.user1_id)
+ .search([("purchase_id", "=", self.purchase1.id)])
+ .ids
+ )
self.assertNotEqual(invoice_ids, [])
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 561a51ebd7..ef6ab00912 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -3,69 +3,71 @@
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
import time
-from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
+
from odoo.tests import common
+from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class TestPurchaseOperatingUnit(common.TransactionCase):
-
def setUp(self):
super(TestPurchaseOperatingUnit, self).setUp()
- self.ResUsers = self.env['res.users']
- self.StockPicking = self.env['stock.picking']
- self.PurchaseOrder = self.env['purchase.order']
- self.AccountInvoice = self.env['account.invoice']
+ self.ResUsers = self.env["res.users"]
+ self.StockPicking = self.env["stock.picking"]
+ self.PurchaseOrder = self.env["purchase.order"]
+ self.AccountInvoice = self.env["account.invoice"]
# company
- self.company1 = self.env.ref('base.main_company')
- self.company2 = self.env.ref('stock.res_company_1')
+ self.company1 = self.env.ref("base.main_company")
+ self.company2 = self.env.ref("stock.res_company_1")
# groups
- self.group_purchase_user = self.env.ref('purchase.group_purchase_user')
- self.group_stock_user = self.env.ref('stock.group_stock_user')
+ self.group_purchase_user = self.env.ref("purchase.group_purchase_user")
+ self.group_stock_user = self.env.ref("stock.group_stock_user")
# Main Operating Unit
- self.ou1 = self.env.ref('operating_unit.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')
+ self.b2b = self.env.ref("operating_unit.b2b_operating_unit")
# Partner
- self.partner1 = self.env.ref('base.res_partner_1')
+ self.partner1 = self.env.ref("base.res_partner_1")
# Products
- self.product1 = self.env.ref('product.product_product_7')
- self.product2 = self.env.ref('product.product_product_9')
- self.product3 = self.env.ref('product.product_product_11')
+ self.product1 = self.env.ref("product.product_product_7")
+ self.product2 = self.env.ref("product.product_product_9")
+ self.product3 = self.env.ref("product.product_product_11")
# Account
- self.account = self.env.ref('l10n_generic_coa.conf_a_pay')
+ self.account = self.env.ref("l10n_generic_coa.conf_a_pay")
# Create users
- self.user1_id = self._create_user('user_1',
- [self.group_purchase_user,
- self.group_stock_user],
- self.company1,
- [self.ou1])
- self.user2_id = self._create_user('user_2',
- [self.group_purchase_user,
- self.group_stock_user],
- self.company2,
- [self.b2b])
+ self.user1_id = self._create_user(
+ "user_1",
+ [self.group_purchase_user, self.group_stock_user],
+ self.company1,
+ [self.ou1],
+ )
+ self.user2_id = self._create_user(
+ "user_2",
+ [self.group_purchase_user, self.group_stock_user],
+ self.company2,
+ [self.b2b],
+ )
self.purchase1 = self._create_purchase(
- self.user1_id, [(self.product1, 1000),
- (self.product2, 500),
- (self.product3, 800)])
+ self.user1_id,
+ [(self.product1, 1000), (self.product2, 500), (self.product3, 800)],
+ )
self.purchase1.sudo(self.user1_id).button_confirm()
self._create_invoice(self.purchase1, self.partner1, self.account)
def _create_user(self, login, groups, company, operating_units):
""" Create a user."""
group_ids = [group.id for group in groups]
- user =\
- self.ResUsers.with_context({'no_reset_password': True}).\
- create({
- 'name': 'Chicago Purchase User',
- 'login': login,
- 'password': 'demo',
- 'email': 'chicago@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)]
- })
+ user = self.ResUsers.with_context({"no_reset_password": True}).create(
+ {
+ "name": "Chicago Purchase User",
+ "login": login,
+ "password": "demo",
+ "email": "chicago@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.id
def _create_purchase(self, user_id, line_products):
@@ -75,36 +77,37 @@ def _create_purchase(self, user_id, line_products):
lines = []
for product, qty in line_products:
line_values = {
- 'name': product.name,
- 'product_id': product.id,
- 'product_qty': qty,
- 'product_uom': product.uom_id.id,
- 'price_unit': 50,
- 'date_planned': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ "name": product.name,
+ "product_id": product.id,
+ "product_qty": qty,
+ "product_uom": product.uom_id.id,
+ "price_unit": 50,
+ "date_planned": time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}
lines.append((0, 0, line_values))
- purchase = self.PurchaseOrder.sudo(user_id).create({
- 'operating_unit_id': self.ou1.id,
- 'requesting_operating_unit_id': self.ou1.id,
- 'partner_id': self.partner1.id,
- 'order_line': lines,
- 'company_id': self.company1.id,
- })
+ purchase = self.PurchaseOrder.sudo(user_id).create(
+ {
+ "operating_unit_id": self.ou1.id,
+ "requesting_operating_unit_id": self.ou1.id,
+ "partner_id": self.partner1.id,
+ "order_line": lines,
+ "company_id": self.company1.id,
+ }
+ )
return purchase
def _create_invoice(self, purchase, partner, account):
""" Create a vendor invoice for the purchase order."""
invoice_vals = {
- 'purchase_id': purchase.id,
- 'partner_id': partner.id,
- 'account_id': account.id,
- 'type': 'in_invoice',
+ "purchase_id": purchase.id,
+ "partner_id": partner.id,
+ "account_id": account.id,
+ "type": "in_invoice",
}
purchase_context = {
- 'active_id': purchase.id,
- 'active_ids': purchase.ids,
- 'active_model': 'purchase.order',
+ "active_id": purchase.id,
+ "active_ids": purchase.ids,
+ "active_model": "purchase.order",
}
- self.env['account.invoice'].with_context(purchase_context).\
- create(invoice_vals)
+ self.env["account.invoice"].with_context(purchase_context).create(invoice_vals)
return True
diff --git a/purchase_operating_unit/views/purchase_order_line_view.xml b/purchase_operating_unit/views/purchase_order_line_view.xml
index 11dd70fd42..b4661f9d2e 100644
--- a/purchase_operating_unit/views/purchase_order_line_view.xml
+++ b/purchase_operating_unit/views/purchase_order_line_view.xml
@@ -1,48 +1,53 @@
-
+
-
purchase_order_line_tree
purchase.order.line
-
+
-
purchase_order_line_form
purchase.order.line
-
+
-
purchase_order_line_search
purchase.order.line
-
+
-
+
-
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index 92362e6717..1f32543460 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -1,54 +1,62 @@
-
+
-
purchase_order_tree
purchase.order
-
+
-
purchase_order_form
purchase.order
-
-
+
+
- {'operating_unit_id': operating_unit_id}
+ {'operating_unit_id': operating_unit_id}
-
view_purchase_order_filter
purchase.order
-
+
-
+
-
From ad413f19f791f52ddf3f34900c8ae68a6355b9bf Mon Sep 17 00:00:00 2001
From: BT-nstuder
Date: Wed, 8 Jan 2020 08:01:51 +0100
Subject: [PATCH 12/26] [MIG] purchase_operating_unit: Migration to 13.0
---
purchase_operating_unit/README.rst | 11 ++---
purchase_operating_unit/__manifest__.py | 2 +-
.../i18n/purchase_operating_unit.pot | 40 +++++++++++--------
.../models/account_invoice.py | 34 ++++++++--------
.../models/purchase_order.py | 6 +--
.../readme/CONTRIBUTORS.rst | 1 +
.../static/description/index.html | 7 ++--
.../tests/test_po_security.py | 18 ++++-----
.../tests/test_purchase_operating_unit.py | 18 +++++----
9 files changed, 73 insertions(+), 64 deletions(-)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index 53cc27fdbd..621ff8d321 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -14,13 +14,13 @@ Operating Unit in Purchase Orders
: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/12.0/purchase_operating_unit
+ :target: https://github.com/OCA/operating-unit/tree/13.0/purchase_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-12-0/operating-unit-12-0-purchase_operating_unit
+ :target: https://translation.odoo-community.org/projects/operating-unit-13-0/operating-unit-13-0-purchase_operating_unit
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/213/12.0
+ :target: https://runbot.odoo-community.org/runbot/213/13.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -60,7 +60,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 smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -79,6 +79,7 @@ Contributors
* Jordi Ballester Alomar
* Aaron Henriquez
* Sudhir Arya
+* Nicola Studer
Maintainers
~~~~~~~~~~~
@@ -93,6 +94,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/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index aa8c1da7d5..8f1be2e99f 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,7 +7,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "12.0.1.0.0",
+ "version": "13.0.1.0.0",
"author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
diff --git a/purchase_operating_unit/i18n/purchase_operating_unit.pot b/purchase_operating_unit/i18n/purchase_operating_unit.pot
index 1f1bb85df3..801a2787d9 100644
--- a/purchase_operating_unit/i18n/purchase_operating_unit.pot
+++ b/purchase_operating_unit/i18n/purchase_operating_unit.pot
@@ -1,12 +1,12 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
-# * purchase_operating_unit
+# * purchase_operating_unit
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 12.0\n"
+"Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: <>\n"
+"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -14,15 +14,19 @@ msgstr ""
"Plural-Forms: \n"
#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/purchase_order.py:82
+#: code:addons/purchase_operating_unit/models/purchase_order.py:0
#, python-format
-msgid "Configuration error. The Company in the Purchase Order and in the Operating Unit must be the same."
+msgid ""
+"Configuration error. The Company in the Purchase Order and in the Operating "
+"Unit must be the same."
msgstr ""
#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/purchase_order.py:71
+#: code:addons/purchase_operating_unit/models/purchase_order.py:0
#, python-format
-msgid "Configuration error. The Quotation / Purchase Order and the Warehouse of picking type must belong to the same Operating Unit."
+msgid ""
+"Configuration error. The Quotation / Purchase Order and the Warehouse of "
+"picking type must belong to the same Operating Unit."
msgstr ""
#. module: purchase_operating_unit
@@ -31,19 +35,20 @@ msgid "Deliver To"
msgstr ""
#. module: purchase_operating_unit
-#: model:ir.model,name:purchase_operating_unit.model_account_invoice
-msgid "Invoice"
+#: model:ir.model,name:purchase_operating_unit.model_account_move
+msgid "Journal Entries"
msgstr ""
#. module: purchase_operating_unit
-#: model:ir.model,name:purchase_operating_unit.model_account_invoice_line
-msgid "Invoice Line"
+#: model:ir.model,name:purchase_operating_unit.model_account_move_line
+msgid "Journal Item"
msgstr ""
#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/purchase_order.py:97
+#: code:addons/purchase_operating_unit/models/purchase_order.py:0
#, python-format
-msgid "No Warehouse found with the Operating Unit indicated in the Purchase Order"
+msgid ""
+"No Warehouse found with the Operating Unit indicated in the Purchase Order"
msgstr ""
#. module: purchase_operating_unit
@@ -70,13 +75,14 @@ msgid "Requesting Operating Unit"
msgstr ""
#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/account_invoice.py:43
+#: code:addons/purchase_operating_unit/models/account_invoice.py:0
#, python-format
-msgid "The operating unit of the purchase order must be the same as in the associated invoices."
+msgid ""
+"The operating unit of the purchase order must be the same as in the "
+"associated invoices."
msgstr ""
#. module: purchase_operating_unit
#: model:ir.model.fields,help:purchase_operating_unit.field_purchase_order__picking_type_id
-msgid "This will determine picking type of incoming shipment"
+msgid "This will determine operation type of incoming shipment"
msgstr ""
-
diff --git a/purchase_operating_unit/models/account_invoice.py b/purchase_operating_unit/models/account_invoice.py
index 267c79f60c..c3bea48b5b 100644
--- a/purchase_operating_unit/models/account_invoice.py
+++ b/purchase_operating_unit/models/account_invoice.py
@@ -5,35 +5,37 @@
from odoo import _, api, exceptions, models
-class AccountInvoice(models.Model):
- _inherit = "account.invoice"
+class AccountMove(models.Model):
+ _inherit = "account.move"
# Load all unsold PO lines
- @api.onchange("purchase_id")
- def purchase_order_change(self):
+ @api.onchange("purchase_vendor_bill_id", "purchase_id")
+ def _onchange_purchase_auto_complete(self):
"""
Override to add Operating Unit from Purchase Order to Invoice.
"""
- if self.purchase_id and self.purchase_id.operating_unit_id:
+ purchase_id = self.purchase_id
+ if self.purchase_vendor_bill_id.purchase_order_id:
+ purchase_id = self.purchase_vendor_bill_id.purchase_order_id
+ if purchase_id and purchase_id.operating_unit_id:
# Assign OU from PO to Invoice
- self.operating_unit_id = self.purchase_id.operating_unit_id.id
- return super(AccountInvoice, self).purchase_order_change()
+ self.operating_unit_id = purchase_id.operating_unit_id.id
+ return super()._onchange_purchase_auto_complete()
@api.onchange("operating_unit_id")
- def _onchange_allowed_purchase_ids(self):
+ def _onchange_operating_unit_id(self):
"""
Show only the purchase orders that have the same operating unit
"""
- result = super(AccountInvoice, self)._onchange_allowed_purchase_ids()
+ return {
+ "domain": {
+ "purchase_id": [("operating_unit_id", "=", self.operating_unit_id.id)]
+ }
+ }
- result["domain"]["purchase_id"] += [
- ("operating_unit_id", "=", self.operating_unit_id.id)
- ]
- return result
-
-class AccountInvoiceLines(models.Model):
- _inherit = "account.invoice.line"
+class AccountMoveLine(models.Model):
+ _inherit = "account.move.line"
@api.constrains("operating_unit_id", "purchase_line_id")
def _check_invoice_ou(self):
diff --git a/purchase_operating_unit/models/purchase_order.py b/purchase_operating_unit/models/purchase_order.py
index 70dd184a43..cf259d8323 100644
--- a/purchase_operating_unit/models/purchase_order.py
+++ b/purchase_operating_unit/models/purchase_order.py
@@ -49,16 +49,12 @@ def _default_picking_type(self):
)
picking_type_id = fields.Many2one(
- comodel_name="stock.picking.type",
- string="Deliver To",
- help="This will determine picking type of incoming shipment",
- required=True,
states={
"confirmed": [("readonly", True)],
"approved": [("readonly", True)],
"done": [("readonly", True)],
},
- default=lambda self: self._default_picking_type(),
+ default=_default_picking_type,
)
@api.constrains("operating_unit_id", "picking_type_id")
diff --git a/purchase_operating_unit/readme/CONTRIBUTORS.rst b/purchase_operating_unit/readme/CONTRIBUTORS.rst
index 4244f4e535..d5625161d4 100644
--- a/purchase_operating_unit/readme/CONTRIBUTORS.rst
+++ b/purchase_operating_unit/readme/CONTRIBUTORS.rst
@@ -1,3 +1,4 @@
* Jordi Ballester Alomar
* Aaron Henriquez
* Sudhir Arya
+* Nicola Studer
diff --git a/purchase_operating_unit/static/description/index.html b/purchase_operating_unit/static/description/index.html
index 7457d289d2..928586103d 100644
--- a/purchase_operating_unit/static/description/index.html
+++ b/purchase_operating_unit/static/description/index.html
@@ -367,7 +367,7 @@ Operating Unit in Purchase Orders
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

This module introduces the following features:
- It introduces the operating unit to the purchase order.
@@ -411,7 +411,7 @@
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 smashing it by providing a detailed and welcomed
-feedback.
+feedback.
Do not contact contributors directly about support or help with technical issues.
@@ -438,7 +439,7 @@
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/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 2b5fcc6cdd..48119c4167 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -11,44 +11,44 @@ def test_po_ou_security(self):
# User 2 is only assigned to Operating Unit 2, and cannot list
# purchase orders from Operating Unit 1.
po_ids = (
- self.PurchaseOrder.sudo(self.user2_id)
+ self.PurchaseOrder.with_user(self.user2_id)
.search([("operating_unit_id", "=", self.ou1.id)])
.ids
)
self.assertEqual(po_ids, [])
# User 2 cannot list the picking that was created from PO 1
picking_ids = (
- self.StockPicking.sudo(self.user2_id)
+ self.StockPicking.with_user(self.user2_id)
.search([("id", "in", self.purchase1.picking_ids.ids)])
.ids
)
self.assertEqual(picking_ids, [])
# User 2 cannot list the invoice that was created from PO 1
invoice_ids = (
- self.AccountInvoice.sudo(self.user2_id)
- .search([("purchase_id", "=", self.purchase1.id)])
+ self.AccountInvoice.with_user(self.user2_id)
+ .search([("id", "=", self.invoice.id)])
.ids
)
self.assertEqual(invoice_ids, [])
# User 1 is assigned to Operating Unit 1, and can list
# the purchase order 1 from Operating Unit 1.
po_ids = (
- self.PurchaseOrder.sudo(self.user1_id)
+ self.PurchaseOrder.with_user(self.user1_id)
.search([("operating_unit_id", "=", self.ou1.id)])
.ids
)
self.assertNotEqual(po_ids, [])
# User 1 can list the picking that was created from PO 1
picking_ids = (
- self.StockPicking.sudo(self.user1_id)
+ self.StockPicking.with_user(self.user1_id)
.search([("id", "in", self.purchase1.picking_ids.ids)])
.ids
)
self.assertNotEqual(picking_ids, [])
- # # User 1 can list the invoice that was created from PO 2
+ # User 1 can list the invoice that was created from PO 2
invoice_ids = (
- self.AccountInvoice.sudo(self.user1_id)
- .search([("purchase_id", "=", self.purchase1.id)])
+ self.AccountInvoice.with_user(self.user1_id)
+ .search([("id", "=", self.invoice.id)])
.ids
)
self.assertNotEqual(invoice_ids, [])
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index ef6ab00912..327e659711 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -14,7 +14,7 @@ def setUp(self):
self.ResUsers = self.env["res.users"]
self.StockPicking = self.env["stock.picking"]
self.PurchaseOrder = self.env["purchase.order"]
- self.AccountInvoice = self.env["account.invoice"]
+ self.AccountInvoice = self.env["account.move"]
# company
self.company1 = self.env.ref("base.main_company")
self.company2 = self.env.ref("stock.res_company_1")
@@ -32,7 +32,7 @@ def setUp(self):
self.product2 = self.env.ref("product.product_product_9")
self.product3 = self.env.ref("product.product_product_11")
# Account
- self.account = self.env.ref("l10n_generic_coa.conf_a_pay")
+ self.account = self.env.ref("l10n_generic_coa.payable")
# Create users
self.user1_id = self._create_user(
"user_1",
@@ -50,8 +50,8 @@ def setUp(self):
self.user1_id,
[(self.product1, 1000), (self.product2, 500), (self.product3, 800)],
)
- self.purchase1.sudo(self.user1_id).button_confirm()
- self._create_invoice(self.purchase1, self.partner1, self.account)
+ self.purchase1.with_user(self.user1_id).button_confirm()
+ self.invoice = self._create_invoice(self.purchase1, self.partner1, self.account)
def _create_user(self, login, groups, company, operating_units):
""" Create a user."""
@@ -85,7 +85,7 @@ def _create_purchase(self, user_id, line_products):
"date_planned": time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}
lines.append((0, 0, line_values))
- purchase = self.PurchaseOrder.sudo(user_id).create(
+ purchase = self.PurchaseOrder.with_user(user_id).create(
{
"operating_unit_id": self.ou1.id,
"requesting_operating_unit_id": self.ou1.id,
@@ -101,7 +101,7 @@ def _create_invoice(self, purchase, partner, account):
invoice_vals = {
"purchase_id": purchase.id,
"partner_id": partner.id,
- "account_id": account.id,
+ # "account_id": account.id,
"type": "in_invoice",
}
purchase_context = {
@@ -109,5 +109,7 @@ def _create_invoice(self, purchase, partner, account):
"active_ids": purchase.ids,
"active_model": "purchase.order",
}
- self.env["account.invoice"].with_context(purchase_context).create(invoice_vals)
- return True
+ res = (
+ self.env["account.move"].with_context(purchase_context).create(invoice_vals)
+ )
+ return res
From 6c4bfa7f82c215ecf7bcdc8b1a55daccc8c94a16 Mon Sep 17 00:00:00 2001
From: Nikul Chaudhary
Date: Thu, 1 Oct 2020 08:28:19 +0530
Subject: [PATCH 13/26] [FIX] Fixed Issue #291
---
purchase_operating_unit/README.rst | 1 +
purchase_operating_unit/readme/CONTRIBUTORS.rst | 1 +
purchase_operating_unit/static/description/index.html | 1 +
.../tests/test_purchase_operating_unit.py | 6 +++++-
4 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index 621ff8d321..a4e49acdff 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -80,6 +80,7 @@ Contributors
* Aaron Henriquez
* Sudhir Arya
* Nicola Studer
+* Nikul Chaudhary
Maintainers
~~~~~~~~~~~
diff --git a/purchase_operating_unit/readme/CONTRIBUTORS.rst b/purchase_operating_unit/readme/CONTRIBUTORS.rst
index d5625161d4..5ddf7e513a 100644
--- a/purchase_operating_unit/readme/CONTRIBUTORS.rst
+++ b/purchase_operating_unit/readme/CONTRIBUTORS.rst
@@ -2,3 +2,4 @@
* Aaron Henriquez
* Sudhir Arya
* Nicola Studer
+* Nikul Chaudhary
diff --git a/purchase_operating_unit/static/description/index.html b/purchase_operating_unit/static/description/index.html
index 928586103d..75f811a48f 100644
--- a/purchase_operating_unit/static/description/index.html
+++ b/purchase_operating_unit/static/description/index.html
@@ -430,6 +430,7 @@
Aaron Henriquez <aheficent@eficent.com>
Sudhir Arya <sudhir.arya@serpentcs.com>
Nicola Studer <nicola.studer@braintec-group.com>
+Nikul Chaudhary <nikul.chaudhary.serpentcs@gmail.com>
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 327e659711..21ed118299 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -15,6 +15,7 @@ def setUp(self):
self.StockPicking = self.env["stock.picking"]
self.PurchaseOrder = self.env["purchase.order"]
self.AccountInvoice = self.env["account.move"]
+ self.AccountAccount = self.env["account.account"]
# company
self.company1 = self.env.ref("base.main_company")
self.company2 = self.env.ref("stock.res_company_1")
@@ -32,7 +33,10 @@ def setUp(self):
self.product2 = self.env.ref("product.product_product_9")
self.product3 = self.env.ref("product.product_product_11")
# Account
- self.account = self.env.ref("l10n_generic_coa.payable")
+ payable_acc_type = self.env.ref("account.data_account_type_payable").id
+ self.account = self.AccountAccount.search(
+ [("user_type_id", "=", payable_acc_type)], limit=1
+ )
# Create users
self.user1_id = self._create_user(
"user_1",
From 7900bd501feae54502de9aabc575d091bdce0df1 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Thu, 1 Oct 2020 05:57:57 +0000
Subject: [PATCH 14/26] purchase_operating_unit 13.0.1.0.1
---
purchase_operating_unit/__manifest__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 8f1be2e99f..868fa66226 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,7 +7,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "13.0.1.0.0",
+ "version": "13.0.1.0.1",
"author": "Eficent, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
From 775c82ffc0659c4e500e7b897e0ae90d5beffed1 Mon Sep 17 00:00:00 2001
From: mreficent
Date: Mon, 5 Oct 2020 10:42:21 +0200
Subject: [PATCH 15/26] [UPD] Eficent -> ForgeFlow
---
purchase_operating_unit/__manifest__.py | 4 ++--
purchase_operating_unit/demo/purchase_order_demo.xml | 2 +-
purchase_operating_unit/models/account_invoice.py | 2 +-
purchase_operating_unit/models/purchase_order.py | 2 +-
purchase_operating_unit/readme/CONTRIBUTORS.rst | 4 ++--
purchase_operating_unit/security/purchase_security.xml | 2 +-
purchase_operating_unit/tests/test_po_security.py | 2 +-
purchase_operating_unit/tests/test_purchase_operating_unit.py | 2 +-
8 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 868fa66226..0e58f9c819 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -1,4 +1,4 @@
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
@@ -8,7 +8,7 @@
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
"version": "13.0.1.0.1",
- "author": "Eficent, "
+ "author": "ForgeFlow, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
"website": "https://github.com/OCA/operating-unit",
diff --git a/purchase_operating_unit/demo/purchase_order_demo.xml b/purchase_operating_unit/demo/purchase_order_demo.xml
index 46b3fdb4a0..87604a6780 100644
--- a/purchase_operating_unit/demo/purchase_order_demo.xml
+++ b/purchase_operating_unit/demo/purchase_order_demo.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/purchase_operating_unit/models/account_invoice.py b/purchase_operating_unit/models/account_invoice.py
index c3bea48b5b..52c944534b 100644
--- a/purchase_operating_unit/models/account_invoice.py
+++ b/purchase_operating_unit/models/account_invoice.py
@@ -1,4 +1,4 @@
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
diff --git a/purchase_operating_unit/models/purchase_order.py b/purchase_operating_unit/models/purchase_order.py
index cf259d8323..ed7f17384c 100644
--- a/purchase_operating_unit/models/purchase_order.py
+++ b/purchase_operating_unit/models/purchase_order.py
@@ -1,4 +1,4 @@
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
diff --git a/purchase_operating_unit/readme/CONTRIBUTORS.rst b/purchase_operating_unit/readme/CONTRIBUTORS.rst
index 5ddf7e513a..f609b53bbb 100644
--- a/purchase_operating_unit/readme/CONTRIBUTORS.rst
+++ b/purchase_operating_unit/readme/CONTRIBUTORS.rst
@@ -1,5 +1,5 @@
-* Jordi Ballester Alomar
-* Aaron Henriquez
+* Jordi Ballester Alomar
+* Aaron Henriquez
* Sudhir Arya
* Nicola Studer
* Nikul Chaudhary
diff --git a/purchase_operating_unit/security/purchase_security.xml b/purchase_operating_unit/security/purchase_security.xml
index 5c6d8791ce..7db8d37e2e 100644
--- a/purchase_operating_unit/security/purchase_security.xml
+++ b/purchase_operating_unit/security/purchase_security.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index 48119c4167..a4cf8c28b3 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -1,4 +1,4 @@
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 21ed118299..6f45c32e8b 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -1,4 +1,4 @@
-# © 2015-17 Eficent Business and IT Consulting Services S.L.
+# © 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
From 5481655bc549fc17911663e90c440b6afba2af90 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Mon, 5 Oct 2020 09:37:30 +0000
Subject: [PATCH 16/26] [UPD] README.rst
---
purchase_operating_unit/README.rst | 6 +++---
purchase_operating_unit/static/description/index.html | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index a4e49acdff..53166f3e2b 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -70,14 +70,14 @@ Credits
Authors
~~~~~~~
-* Eficent
+* ForgeFlow
* Serpent Consulting Services Pvt. Ltd.
Contributors
~~~~~~~~~~~~
-* Jordi Ballester Alomar
-* Aaron Henriquez
+* Jordi Ballester Alomar
+* Aaron Henriquez
* Sudhir Arya
* Nicola Studer
* Nikul Chaudhary
diff --git a/purchase_operating_unit/static/description/index.html b/purchase_operating_unit/static/description/index.html
index 75f811a48f..c9f9ec9be7 100644
--- a/purchase_operating_unit/static/description/index.html
+++ b/purchase_operating_unit/static/description/index.html
@@ -419,15 +419,15 @@
-- Eficent
+- ForgeFlow
- Serpent Consulting Services Pvt. Ltd.
-- Jordi Ballester Alomar <jordi.ballester@eficent.com>
-- Aaron Henriquez <aheficent@eficent.com>
+- Jordi Ballester Alomar <jordi.ballester@forgeflow.com>
+- Aaron Henriquez <ahforgeflow@forgeflow.com>
- Sudhir Arya <sudhir.arya@serpentcs.com>
- Nicola Studer <nicola.studer@braintec-group.com>
- Nikul Chaudhary <nikul.chaudhary.serpentcs@gmail.com>
From cf5033bcfe548b2fa78ce746a71e1d64937a8c4e Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Fri, 4 Dec 2020 13:37:33 +0700
Subject: [PATCH 17/26] [IMP] : black, isort, prettier
---
purchase_operating_unit/tests/test_purchase_operating_unit.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 6f45c32e8b..9068e73977 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -75,7 +75,7 @@ def _create_user(self, login, groups, company, operating_units):
return user.id
def _create_purchase(self, user_id, line_products):
- """ Create a purchase order.
+ """Create a purchase order.
``line_products`` is a list of tuple [(product, qty)]
"""
lines = []
From e7a167a7bfd7fb82524aa0c15c481af6989df1e7 Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Fri, 4 Dec 2020 13:39:43 +0700
Subject: [PATCH 18/26] [14.0][MIG] purchase_operating_unit
---
purchase_operating_unit/README.rst | 11 ++++----
purchase_operating_unit/__manifest__.py | 2 +-
.../i18n/purchase_operating_unit.pot | 28 +++++++++++++++++--
.../readme/CONTRIBUTORS.rst | 1 +
.../static/description/index.html | 7 +++--
.../tests/test_purchase_operating_unit.py | 2 +-
6 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index 53166f3e2b..48a6aea0f1 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -14,13 +14,13 @@ Operating Unit in Purchase Orders
: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/13.0/purchase_operating_unit
+ :target: https://github.com/OCA/operating-unit/tree/14.0/purchase_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-13-0/operating-unit-13-0-purchase_operating_unit
+ :target: https://translation.odoo-community.org/projects/operating-unit-14-0/operating-unit-14-0-purchase_operating_unit
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/213/13.0
+ :target: https://runbot.odoo-community.org/runbot/213/14.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -60,7 +60,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 smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -81,6 +81,7 @@ Contributors
* Sudhir Arya
* Nicola Studer
* Nikul Chaudhary
+* Kitti U.
Maintainers
~~~~~~~~~~~
@@ -95,6 +96,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/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 0e58f9c819..c78a75bf8d 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,7 +7,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "13.0.1.0.1",
+ "version": "14.0.1.0.0",
"author": "ForgeFlow, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
diff --git a/purchase_operating_unit/i18n/purchase_operating_unit.pot b/purchase_operating_unit/i18n/purchase_operating_unit.pot
index 801a2787d9..7ce760c8a5 100644
--- a/purchase_operating_unit/i18n/purchase_operating_unit.pot
+++ b/purchase_operating_unit/i18n/purchase_operating_unit.pot
@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 13.0\n"
+"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -34,9 +34,25 @@ msgstr ""
msgid "Deliver To"
msgstr ""
+#. module: purchase_operating_unit
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move__display_name
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move_line__display_name
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__display_name
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: purchase_operating_unit
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move__id
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move_line__id
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__id
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line__id
+msgid "ID"
+msgstr ""
+
#. module: purchase_operating_unit
#: model:ir.model,name:purchase_operating_unit.model_account_move
-msgid "Journal Entries"
+msgid "Journal Entry"
msgstr ""
#. module: purchase_operating_unit
@@ -44,6 +60,14 @@ msgstr ""
msgid "Journal Item"
msgstr ""
+#. module: purchase_operating_unit
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move____last_update
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move_line____last_update
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order____last_update
+#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line____last_update
+msgid "Last Modified on"
+msgstr ""
+
#. module: purchase_operating_unit
#: code:addons/purchase_operating_unit/models/purchase_order.py:0
#, python-format
diff --git a/purchase_operating_unit/readme/CONTRIBUTORS.rst b/purchase_operating_unit/readme/CONTRIBUTORS.rst
index f609b53bbb..c690766eb4 100644
--- a/purchase_operating_unit/readme/CONTRIBUTORS.rst
+++ b/purchase_operating_unit/readme/CONTRIBUTORS.rst
@@ -3,3 +3,4 @@
* Sudhir Arya
* Nicola Studer
* Nikul Chaudhary
+* Kitti U.
diff --git a/purchase_operating_unit/static/description/index.html b/purchase_operating_unit/static/description/index.html
index c9f9ec9be7..a62e19ecc6 100644
--- a/purchase_operating_unit/static/description/index.html
+++ b/purchase_operating_unit/static/description/index.html
@@ -367,7 +367,7 @@ Operating Unit in Purchase Orders
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

This module introduces the following features:
- It introduces the operating unit to the purchase order.
@@ -411,7 +411,7 @@
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 smashing it by providing a detailed and welcomed
-feedback.
+feedback.
Do not contact contributors directly about support or help with technical issues.
@@ -440,7 +441,7 @@
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/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 9068e73977..f4354e6a24 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -106,7 +106,7 @@ def _create_invoice(self, purchase, partner, account):
"purchase_id": purchase.id,
"partner_id": partner.id,
# "account_id": account.id,
- "type": "in_invoice",
+ "move_type": "in_invoice",
}
purchase_context = {
"active_id": purchase.id,
From 43d95489846e0d176799a6be808c4af37ea2716e Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Wed, 16 Jun 2021 00:46:27 +0700
Subject: [PATCH 19/26] [14.0][FIX] purchase_operating_unit, add OU when create
invoice
---
purchase_operating_unit/models/purchase_order.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/purchase_operating_unit/models/purchase_order.py b/purchase_operating_unit/models/purchase_order.py
index ed7f17384c..7d686a9ab1 100644
--- a/purchase_operating_unit/models/purchase_order.py
+++ b/purchase_operating_unit/models/purchase_order.py
@@ -119,6 +119,11 @@ def _prepare_picking(self):
picking_vals["operating_unit_id"] = self.operating_unit_id.id
return picking_vals
+ def _prepare_invoice(self):
+ invoice_vals = super()._prepare_invoice()
+ invoice_vals["operating_unit_id"] = self.operating_unit_id.id
+ return invoice_vals
+
class PurchaseOrderLine(models.Model):
_inherit = "purchase.order.line"
From db743612c24ec4bc4ebda3fffd287c944b94a854 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Tue, 3 Aug 2021 06:23:36 +0000
Subject: [PATCH 20/26] purchase_operating_unit 14.0.1.0.1
---
purchase_operating_unit/__manifest__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index c78a75bf8d..3675ad68cc 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,7 +7,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "14.0.1.0.0",
+ "version": "14.0.1.0.1",
"author": "ForgeFlow, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
From d70916889aa0ffd4c883f8ebf7693d70b5ee4a55 Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Tue, 19 Oct 2021 16:53:37 +0700
Subject: [PATCH 21/26] [14.0][FIX] purchase_operating_unit
---
purchase_operating_unit/views/purchase_order_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index 1f32543460..7c2613be05 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -34,7 +34,7 @@
{'operating_unit_id': operating_unit_id}
+ >{'default_state': 'draft', 'operating_unit_id': operating_unit_id}
From ee4dbac94743e6b81c2dc01e2299fdb95e1bc2ac Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Tue, 19 Oct 2021 10:17:06 +0000
Subject: [PATCH 22/26] purchase_operating_unit 14.0.1.0.2
---
purchase_operating_unit/__manifest__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 3675ad68cc..30c91b8984 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,7 +7,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "14.0.1.0.1",
+ "version": "14.0.1.0.2",
"author": "ForgeFlow, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
From f41178409c82e387c2c82a5b6f58b511c5cc55e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesu=CC=81s=20Alan=20Ramos=20Rodri=CC=81guez?=
Date: Thu, 13 Jan 2022 13:54:08 -0600
Subject: [PATCH 23/26] [IMP] purchase_operating_unit: black, isort, prettier
---
purchase_operating_unit/tests/test_purchase_operating_unit.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index f4354e6a24..514336e699 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -58,7 +58,7 @@ def setUp(self):
self.invoice = self._create_invoice(self.purchase1, self.partner1, self.account)
def _create_user(self, login, groups, company, operating_units):
- """ Create a user."""
+ """Create a user."""
group_ids = [group.id for group in groups]
user = self.ResUsers.with_context({"no_reset_password": True}).create(
{
@@ -101,7 +101,7 @@ def _create_purchase(self, user_id, line_products):
return purchase
def _create_invoice(self, purchase, partner, account):
- """ Create a vendor invoice for the purchase order."""
+ """Create a vendor invoice for the purchase order."""
invoice_vals = {
"purchase_id": purchase.id,
"partner_id": partner.id,
From 3b97d662f97ca7346ff56d097e562c3591828864 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesu=CC=81s=20Alan=20Ramos=20Rodri=CC=81guez?=
Date: Thu, 13 Jan 2022 13:50:54 -0600
Subject: [PATCH 24/26] [MIG] purchase_operating_unit: Migration to 15.0
---
purchase_operating_unit/README.rst | 22 ++----
purchase_operating_unit/__manifest__.py | 4 +-
.../demo/purchase_order_demo.xml | 4 +-
.../i18n/purchase_operating_unit.pot | 53 +------------
purchase_operating_unit/models/__init__.py | 2 +-
.../{account_invoice.py => account_move.py} | 9 ++-
.../models/purchase_order.py | 77 +------------------
.../readme/CONTRIBUTORS.rst | 1 +
.../readme/DESCRIPTION.rst | 1 -
purchase_operating_unit/readme/ROADMAP.rst | 3 -
purchase_operating_unit/readme/USAGE.rst | 3 +-
.../security/purchase_security.xml | 4 +-
.../static/description/index.html | 38 ++++-----
.../tests/test_po_security.py | 18 +----
.../tests/test_purchase_operating_unit.py | 56 ++++++++++----
.../views/purchase_order_line_view.xml | 3 -
.../views/purchase_order_view.xml | 3 -
17 files changed, 83 insertions(+), 218 deletions(-)
rename purchase_operating_unit/models/{account_invoice.py => account_move.py} (88%)
delete mode 100644 purchase_operating_unit/readme/ROADMAP.rst
diff --git a/purchase_operating_unit/README.rst b/purchase_operating_unit/README.rst
index 48a6aea0f1..b693a9deaa 100644
--- a/purchase_operating_unit/README.rst
+++ b/purchase_operating_unit/README.rst
@@ -14,13 +14,13 @@ Operating Unit in Purchase Orders
: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/14.0/purchase_operating_unit
+ :target: https://github.com/OCA/operating-unit/tree/15.0/purchase_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-14-0/operating-unit-14-0-purchase_operating_unit
+ :target: https://translation.odoo-community.org/projects/operating-unit-15-0/operating-unit-15-0-purchase_operating_unit
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/213/14.0
+ :target: https://runbot.odoo-community.org/runbot/213/15.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -29,7 +29,6 @@ This module introduces the following features:
- It introduces the operating unit to the purchase order.
- The operating unit is copied to the invoice.
-- The operating unit is copied to the stock picking.
- It implements user's security rules.
**Table of contents**
@@ -42,25 +41,17 @@ Usage
#. Create a PO: the Default Operating Unit is assigned to the PO. If you want,
you can change to another Operating Unit.
-#. Validate the PO: the Operating Unit is propagated to the Pickings and
- Invoices.
+#. Validate the PO: the Operating Unit is propagated to the Invoices.
#. From the invoice, it is not possible to change the Operating Unit, it has to
be the same as the one of the PO.
-Known issues / Roadmap
-======================
-
-Procurement Orders were removed. Procurement Operating Unit module is
-deprecated. Stock Operating Unit ensures consistency between the operating unit
-from different models.
-
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 smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -82,6 +73,7 @@ Contributors
* Nicola Studer
* Nikul Chaudhary
* Kitti U.
+* Alan Ramos
Maintainers
~~~~~~~~~~~
@@ -96,6 +88,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/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 30c91b8984..2bfcaa471b 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,13 +7,13 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "14.0.1.0.2",
+ "version": "15.0.1.0.0",
"author": "ForgeFlow, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
"website": "https://github.com/OCA/operating-unit",
"category": "Purchase Management",
- "depends": ["stock_operating_unit", "purchase_stock"],
+ "depends": ["purchase", "account_operating_unit"],
"license": "LGPL-3",
"data": [
"security/purchase_security.xml",
diff --git a/purchase_operating_unit/demo/purchase_order_demo.xml b/purchase_operating_unit/demo/purchase_order_demo.xml
index 87604a6780..af80cc9aac 100644
--- a/purchase_operating_unit/demo/purchase_order_demo.xml
+++ b/purchase_operating_unit/demo/purchase_order_demo.xml
@@ -1,7 +1,7 @@
-
+
-
+
diff --git a/purchase_operating_unit/i18n/purchase_operating_unit.pot b/purchase_operating_unit/i18n/purchase_operating_unit.pot
index 7ce760c8a5..54c0e4539a 100644
--- a/purchase_operating_unit/i18n/purchase_operating_unit.pot
+++ b/purchase_operating_unit/i18n/purchase_operating_unit.pot
@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 14.0\n"
+"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -21,35 +21,6 @@ msgid ""
"Unit must be the same."
msgstr ""
-#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/purchase_order.py:0
-#, python-format
-msgid ""
-"Configuration error. The Quotation / Purchase Order and the Warehouse of "
-"picking type must belong to the same Operating Unit."
-msgstr ""
-
-#. module: purchase_operating_unit
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__picking_type_id
-msgid "Deliver To"
-msgstr ""
-
-#. module: purchase_operating_unit
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move__display_name
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move_line__display_name
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__display_name
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line__display_name
-msgid "Display Name"
-msgstr ""
-
-#. module: purchase_operating_unit
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move__id
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move_line__id
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__id
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line__id
-msgid "ID"
-msgstr ""
-
#. module: purchase_operating_unit
#: model:ir.model,name:purchase_operating_unit.model_account_move
msgid "Journal Entry"
@@ -60,21 +31,6 @@ msgstr ""
msgid "Journal Item"
msgstr ""
-#. module: purchase_operating_unit
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move____last_update
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_account_move_line____last_update
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order____last_update
-#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line____last_update
-msgid "Last Modified on"
-msgstr ""
-
-#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/purchase_order.py:0
-#, python-format
-msgid ""
-"No Warehouse found with the Operating Unit indicated in the Purchase Order"
-msgstr ""
-
#. module: purchase_operating_unit
#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order__operating_unit_id
#: model:ir.model.fields,field_description:purchase_operating_unit.field_purchase_order_line__operating_unit_id
@@ -99,14 +55,9 @@ msgid "Requesting Operating Unit"
msgstr ""
#. module: purchase_operating_unit
-#: code:addons/purchase_operating_unit/models/account_invoice.py:0
+#: code:addons/purchase_operating_unit/models/account_move.py:0
#, python-format
msgid ""
"The operating unit of the purchase order must be the same as in the "
"associated invoices."
msgstr ""
-
-#. module: purchase_operating_unit
-#: model:ir.model.fields,help:purchase_operating_unit.field_purchase_order__picking_type_id
-msgid "This will determine operation type of incoming shipment"
-msgstr ""
diff --git a/purchase_operating_unit/models/__init__.py b/purchase_operating_unit/models/__init__.py
index 14eb8bcd10..105a10e6f7 100644
--- a/purchase_operating_unit/models/__init__.py
+++ b/purchase_operating_unit/models/__init__.py
@@ -1,3 +1,3 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import purchase_order
-from . import account_invoice
+from . import account_move
diff --git a/purchase_operating_unit/models/account_invoice.py b/purchase_operating_unit/models/account_move.py
similarity index 88%
rename from purchase_operating_unit/models/account_invoice.py
rename to purchase_operating_unit/models/account_move.py
index 52c944534b..821be7e559 100644
--- a/purchase_operating_unit/models/account_invoice.py
+++ b/purchase_operating_unit/models/account_move.py
@@ -1,8 +1,9 @@
-# © 2015-17 ForgeFlow S.L.
+# Copyright 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# Copyright 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
-from odoo import _, api, exceptions, models
+from odoo import _, api, models
+from odoo.exceptions import ValidationError
class AccountMove(models.Model):
@@ -44,7 +45,7 @@ def _check_invoice_ou(self):
line.purchase_line_id
and line.operating_unit_id != line.purchase_line_id.operating_unit_id
):
- raise exceptions.ValidationError(
+ raise ValidationError(
_(
"The operating unit of the purchase order must "
"be the same as in the associated invoices."
diff --git a/purchase_operating_unit/models/purchase_order.py b/purchase_operating_unit/models/purchase_order.py
index 7d686a9ab1..07810dfe0a 100644
--- a/purchase_operating_unit/models/purchase_order.py
+++ b/purchase_operating_unit/models/purchase_order.py
@@ -1,29 +1,14 @@
-# © 2015-17 ForgeFlow S.L.
+# Copyright 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# Copyright 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo import _, api, fields, models
-from odoo.exceptions import UserError, ValidationError
+from odoo.exceptions import ValidationError
class PurchaseOrder(models.Model):
_inherit = "purchase.order"
- @api.model
- def _default_picking_type(self):
- res = super(PurchaseOrder, self)._default_picking_type()
- type_obj = self.env["stock.picking.type"]
- operating_unit = self.env["res.users"].operating_unit_default_get(self.env.uid)
- types = type_obj.search(
- [
- ("code", "=", "incoming"),
- ("warehouse_id.operating_unit_id", "=", operating_unit.id),
- ]
- )
- if types:
- res = types[:1].id
- return res
-
READONLY_STATES = {
"purchase": [("readonly", True)],
"done": [("readonly", True)],
@@ -48,36 +33,6 @@ def _default_picking_type(self):
),
)
- picking_type_id = fields.Many2one(
- states={
- "confirmed": [("readonly", True)],
- "approved": [("readonly", True)],
- "done": [("readonly", True)],
- },
- default=_default_picking_type,
- )
-
- @api.constrains("operating_unit_id", "picking_type_id")
- def _check_warehouse_operating_unit(self):
- for record in self:
- picking_type = record.picking_type_id
- if not record.picking_type_id:
- continue
- warehouse = picking_type.warehouse_id
- if (
- picking_type.warehouse_id
- and picking_type.warehouse_id.operating_unit_id
- and record.operating_unit_id
- and warehouse.operating_unit_id != record.operating_unit_id
- ):
- raise ValidationError(
- _(
- "Configuration error. The Quotation / Purchase Order "
- "and the Warehouse of picking type must belong to the "
- "same Operating Unit."
- )
- )
-
@api.constrains("operating_unit_id", "company_id")
def _check_company_operating_unit(self):
for record in self:
@@ -93,32 +48,6 @@ def _check_company_operating_unit(self):
)
)
- @api.onchange("operating_unit_id")
- def _onchange_operating_unit_id(self):
- type_obj = self.env["stock.picking.type"]
- if self.operating_unit_id:
- types = type_obj.search(
- [
- ("code", "=", "incoming"),
- ("warehouse_id.operating_unit_id", "=", self.operating_unit_id.id),
- ]
- )
- if types:
- self.picking_type_id = types[:1]
- else:
- raise UserError(
- _(
- "No Warehouse found with the Operating Unit indicated "
- "in the Purchase Order"
- )
- )
-
- @api.model
- def _prepare_picking(self):
- picking_vals = super(PurchaseOrder, self)._prepare_picking()
- picking_vals["operating_unit_id"] = self.operating_unit_id.id
- return picking_vals
-
def _prepare_invoice(self):
invoice_vals = super()._prepare_invoice()
invoice_vals["operating_unit_id"] = self.operating_unit_id.id
diff --git a/purchase_operating_unit/readme/CONTRIBUTORS.rst b/purchase_operating_unit/readme/CONTRIBUTORS.rst
index c690766eb4..9f02e3f0b7 100644
--- a/purchase_operating_unit/readme/CONTRIBUTORS.rst
+++ b/purchase_operating_unit/readme/CONTRIBUTORS.rst
@@ -4,3 +4,4 @@
* Nicola Studer
* Nikul Chaudhary
* Kitti U.
+* Alan Ramos
diff --git a/purchase_operating_unit/readme/DESCRIPTION.rst b/purchase_operating_unit/readme/DESCRIPTION.rst
index ace6b56436..10d7911fa2 100644
--- a/purchase_operating_unit/readme/DESCRIPTION.rst
+++ b/purchase_operating_unit/readme/DESCRIPTION.rst
@@ -2,5 +2,4 @@ This module introduces the following features:
- It introduces the operating unit to the purchase order.
- The operating unit is copied to the invoice.
-- The operating unit is copied to the stock picking.
- It implements user's security rules.
diff --git a/purchase_operating_unit/readme/ROADMAP.rst b/purchase_operating_unit/readme/ROADMAP.rst
deleted file mode 100644
index e066763c22..0000000000
--- a/purchase_operating_unit/readme/ROADMAP.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Procurement Orders were removed. Procurement Operating Unit module is
-deprecated. Stock Operating Unit ensures consistency between the operating unit
-from different models.
diff --git a/purchase_operating_unit/readme/USAGE.rst b/purchase_operating_unit/readme/USAGE.rst
index 0f2c129360..fb2deacb52 100644
--- a/purchase_operating_unit/readme/USAGE.rst
+++ b/purchase_operating_unit/readme/USAGE.rst
@@ -1,6 +1,5 @@
#. Create a PO: the Default Operating Unit is assigned to the PO. If you want,
you can change to another Operating Unit.
-#. Validate the PO: the Operating Unit is propagated to the Pickings and
- Invoices.
+#. Validate the PO: the Operating Unit is propagated to the Invoices.
#. From the invoice, it is not possible to change the Operating Unit, it has to
be the same as the one of the PO.
diff --git a/purchase_operating_unit/security/purchase_security.xml b/purchase_operating_unit/security/purchase_security.xml
index 7db8d37e2e..970d195ac3 100644
--- a/purchase_operating_unit/security/purchase_security.xml
+++ b/purchase_operating_unit/security/purchase_security.xml
@@ -1,7 +1,7 @@
-
+
-
+
diff --git a/purchase_operating_unit/static/description/index.html b/purchase_operating_unit/static/description/index.html
index a62e19ecc6..a9b0660348 100644
--- a/purchase_operating_unit/static/description/index.html
+++ b/purchase_operating_unit/static/description/index.html
@@ -367,24 +367,22 @@ Operating Unit in Purchase Orders
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

This module introduces the following features:
- It introduces the operating unit to the purchase order.
- The operating unit is copied to the invoice.
-- The operating unit is copied to the stock picking.
- It implements user’s security rules.
Table of contents
- Usage
-- Known issues / Roadmap
-- Bug Tracker
-- Credits
@@ -394,37 +392,30 @@
- Create a PO: the Default Operating Unit is assigned to the PO. If you want,
you can change to another Operating Unit.
-- Validate the PO: the Operating Unit is propagated to the Pickings and
-Invoices.
+- Validate the PO: the Operating Unit is propagated to the Invoices.
- From the invoice, it is not possible to change the Operating Unit, it has to
be the same as the one of the PO.
-
-
-
Procurement Orders were removed. Procurement Operating Unit module is
-deprecated. Stock Operating Unit ensures consistency between the operating unit
-from different models.
-
-
+
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 smashing it by providing a detailed and welcomed
-feedback.
+
feedback.
Do not contact contributors directly about support or help with technical issues.
-
+
-
+
- ForgeFlow
- Serpent Consulting Services Pvt. Ltd.
-
+
This module is maintained by the OCA.
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/purchase_operating_unit/tests/test_po_security.py b/purchase_operating_unit/tests/test_po_security.py
index a4cf8c28b3..ae0a82f5e8 100644
--- a/purchase_operating_unit/tests/test_po_security.py
+++ b/purchase_operating_unit/tests/test_po_security.py
@@ -1,6 +1,6 @@
-# © 2015-17 ForgeFlow S.L.
+# Copyright 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# Copyright 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import test_purchase_operating_unit as test_po_ou # noqa
@@ -16,13 +16,6 @@ def test_po_ou_security(self):
.ids
)
self.assertEqual(po_ids, [])
- # User 2 cannot list the picking that was created from PO 1
- picking_ids = (
- self.StockPicking.with_user(self.user2_id)
- .search([("id", "in", self.purchase1.picking_ids.ids)])
- .ids
- )
- self.assertEqual(picking_ids, [])
# User 2 cannot list the invoice that was created from PO 1
invoice_ids = (
self.AccountInvoice.with_user(self.user2_id)
@@ -38,13 +31,6 @@ def test_po_ou_security(self):
.ids
)
self.assertNotEqual(po_ids, [])
- # User 1 can list the picking that was created from PO 1
- picking_ids = (
- self.StockPicking.with_user(self.user1_id)
- .search([("id", "in", self.purchase1.picking_ids.ids)])
- .ids
- )
- self.assertNotEqual(picking_ids, [])
# User 1 can list the invoice that was created from PO 2
invoice_ids = (
self.AccountInvoice.with_user(self.user1_id)
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 514336e699..3cb596fd8e 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -1,27 +1,25 @@
-# © 2015-17 ForgeFlow S.L.
+# Copyright 2015-17 ForgeFlow S.L.
# - Jordi Ballester Alomar
-# © 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
+# Copyright 2015-17 Serpent Consulting Services Pvt. Ltd. - Sudhir Arya
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
import time
-from odoo.tests import common
+from odoo.exceptions import ValidationError
+from odoo.tests import Form, common
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class TestPurchaseOperatingUnit(common.TransactionCase):
def setUp(self):
- super(TestPurchaseOperatingUnit, self).setUp()
+ super().setUp()
self.ResUsers = self.env["res.users"]
- self.StockPicking = self.env["stock.picking"]
self.PurchaseOrder = self.env["purchase.order"]
self.AccountInvoice = self.env["account.move"]
self.AccountAccount = self.env["account.account"]
# company
- self.company1 = self.env.ref("base.main_company")
- self.company2 = self.env.ref("stock.res_company_1")
+ self.company = self.env.ref("base.main_company")
# groups
self.group_purchase_user = self.env.ref("purchase.group_purchase_user")
- self.group_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
@@ -40,14 +38,14 @@ def setUp(self):
# Create users
self.user1_id = self._create_user(
"user_1",
- [self.group_purchase_user, self.group_stock_user],
- self.company1,
+ [self.group_purchase_user],
+ self.company,
[self.ou1],
)
self.user2_id = self._create_user(
"user_2",
- [self.group_purchase_user, self.group_stock_user],
- self.company2,
+ [self.group_purchase_user],
+ self.company,
[self.b2b],
)
self.purchase1 = self._create_purchase(
@@ -60,7 +58,7 @@ def setUp(self):
def _create_user(self, login, groups, company, operating_units):
"""Create a user."""
group_ids = [group.id for group in groups]
- user = self.ResUsers.with_context({"no_reset_password": True}).create(
+ user = self.ResUsers.with_context(**{"no_reset_password": True}).create(
{
"name": "Chicago Purchase User",
"login": login,
@@ -95,7 +93,7 @@ def _create_purchase(self, user_id, line_products):
"requesting_operating_unit_id": self.ou1.id,
"partner_id": self.partner1.id,
"order_line": lines,
- "company_id": self.company1.id,
+ "company_id": self.company.id,
}
)
return purchase
@@ -105,7 +103,6 @@ def _create_invoice(self, purchase, partner, account):
invoice_vals = {
"purchase_id": purchase.id,
"partner_id": partner.id,
- # "account_id": account.id,
"move_type": "in_invoice",
}
purchase_context = {
@@ -114,6 +111,33 @@ def _create_invoice(self, purchase, partner, account):
"active_model": "purchase.order",
}
res = (
- self.env["account.move"].with_context(purchase_context).create(invoice_vals)
+ self.env["account.move"]
+ .with_context(**purchase_context)
+ .create(invoice_vals)
)
return res
+
+ def test_01_purchase_operating_unit(self):
+ self.purchase1.button_cancel()
+ self.purchase1.button_draft()
+ # Check change operating unit in purchase
+ with self.assertRaises(ValidationError):
+ self.b2b.company_id = False
+ with Form(self.purchase1) as po:
+ po.operating_unit_id = self.b2b
+ self.purchase1.with_user(self.user1_id).button_confirm()
+ # Create Vendor Bill
+ f = Form(self.env["account.move"].with_context(default_move_type="in_invoice"))
+ f.partner_id = self.purchase1.partner_id
+ f.purchase_id = self.purchase1
+ invoice = f.save()
+ self.assertEqual(invoice.operating_unit_id, self.purchase1.operating_unit_id)
+ self.assertEqual(
+ invoice.invoice_line_ids[0].operating_unit_id,
+ invoice.invoice_line_ids[0].purchase_line_id.operating_unit_id,
+ )
+ # Check change operating unit in invoice line != purchase line,
+ # it should error.
+ with self.assertRaises(ValidationError):
+ with Form(invoice.invoice_line_ids[0]) as line:
+ line.operating_unit_id = self.b2b
diff --git a/purchase_operating_unit/views/purchase_order_line_view.xml b/purchase_operating_unit/views/purchase_order_line_view.xml
index b4661f9d2e..32c4b0b2d3 100644
--- a/purchase_operating_unit/views/purchase_order_line_view.xml
+++ b/purchase_operating_unit/views/purchase_order_line_view.xml
@@ -8,7 +8,6 @@
@@ -22,7 +21,6 @@
@@ -44,7 +42,6 @@
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index 7c2613be05..13c2b00da5 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -8,7 +8,6 @@
@@ -22,12 +21,10 @@
From 73e065219fa48844605095dcbdd7ad483dbf3f07 Mon Sep 17 00:00:00 2001
From: bt-aleonard
Date: Thu, 11 May 2023 15:52:54 +0200
Subject: [PATCH 25/26] [IMP] purchase_operating_unit: pre-commit stuff
---
.../odoo/addons/purchase_operating_unit | 1 +
setup/purchase_operating_unit/setup.py | 6 ++++++
2 files changed, 7 insertions(+)
create mode 120000 setup/purchase_operating_unit/odoo/addons/purchase_operating_unit
create mode 100644 setup/purchase_operating_unit/setup.py
diff --git a/setup/purchase_operating_unit/odoo/addons/purchase_operating_unit b/setup/purchase_operating_unit/odoo/addons/purchase_operating_unit
new file mode 120000
index 0000000000..4695973c4e
--- /dev/null
+++ b/setup/purchase_operating_unit/odoo/addons/purchase_operating_unit
@@ -0,0 +1 @@
+../../../../purchase_operating_unit
\ No newline at end of file
diff --git a/setup/purchase_operating_unit/setup.py b/setup/purchase_operating_unit/setup.py
new file mode 100644
index 0000000000..28c57bb640
--- /dev/null
+++ b/setup/purchase_operating_unit/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)
From c7310c7fd254d60901bd7a8c2395ae403ebad825 Mon Sep 17 00:00:00 2001
From: bt-aleonard
Date: Thu, 11 May 2023 15:54:30 +0200
Subject: [PATCH 26/26] [MIG] purchase_operating_unit: Migration to 16.0
---
purchase_operating_unit/__manifest__.py | 2 +-
.../tests/test_purchase_operating_unit.py | 127 +++++++++++-------
.../views/purchase_order_view.xml | 4 +
3 files changed, 81 insertions(+), 52 deletions(-)
diff --git a/purchase_operating_unit/__manifest__.py b/purchase_operating_unit/__manifest__.py
index 2bfcaa471b..a63030d8dc 100644
--- a/purchase_operating_unit/__manifest__.py
+++ b/purchase_operating_unit/__manifest__.py
@@ -7,7 +7,7 @@
"name": "Operating Unit in Purchase Orders",
"summary": "Adds the concecpt of operating unit (OU) in purchase order "
"management",
- "version": "15.0.1.0.0",
+ "version": "16.0.1.0.0",
"author": "ForgeFlow, "
"Serpent Consulting Services Pvt. Ltd.,"
"Odoo Community Association (OCA)",
diff --git a/purchase_operating_unit/tests/test_purchase_operating_unit.py b/purchase_operating_unit/tests/test_purchase_operating_unit.py
index 3cb596fd8e..291b75f17f 100644
--- a/purchase_operating_unit/tests/test_purchase_operating_unit.py
+++ b/purchase_operating_unit/tests/test_purchase_operating_unit.py
@@ -4,61 +4,71 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
import time
-from odoo.exceptions import ValidationError
+from odoo.exceptions import AccessError, ValidationError
from odoo.tests import Form, common
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class TestPurchaseOperatingUnit(common.TransactionCase):
- def setUp(self):
- super().setUp()
- self.ResUsers = self.env["res.users"]
- self.PurchaseOrder = self.env["purchase.order"]
- self.AccountInvoice = self.env["account.move"]
- self.AccountAccount = self.env["account.account"]
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.ResUsers = cls.env["res.users"]
+ cls.PurchaseOrder = cls.env["purchase.order"]
+ cls.AccountInvoice = cls.env["account.move"]
+ cls.AccountAccount = cls.env["account.account"]
# company
- self.company = self.env.ref("base.main_company")
+ cls.company = cls.env.ref("base.main_company")
# groups
- self.group_purchase_user = self.env.ref("purchase.group_purchase_user")
+ cls.group_purchase_user = cls.env.ref("purchase.group_purchase_user")
+ cls.group_operating_unit = cls.env.ref(
+ "operating_unit.group_multi_operating_unit"
+ )
# Main Operating Unit
- self.ou1 = self.env.ref("operating_unit.main_operating_unit")
+ cls.ou1 = cls.env.ref("operating_unit.main_operating_unit")
# B2B Operating Unit
- self.b2b = self.env.ref("operating_unit.b2b_operating_unit")
+ cls.b2b = cls.env.ref("operating_unit.b2b_operating_unit")
# Partner
- self.partner1 = self.env.ref("base.res_partner_1")
+ cls.partner1 = cls.env.ref("base.res_partner_1")
# Products
- self.product1 = self.env.ref("product.product_product_7")
- self.product2 = self.env.ref("product.product_product_9")
- self.product3 = self.env.ref("product.product_product_11")
+ cls.product1 = cls.env.ref("product.product_product_7")
+ cls.product2 = cls.env.ref("product.product_product_9")
+ cls.product3 = cls.env.ref("product.product_product_11")
# Account
- payable_acc_type = self.env.ref("account.data_account_type_payable").id
- self.account = self.AccountAccount.search(
- [("user_type_id", "=", payable_acc_type)], limit=1
+ # payable_acc_type = cls.env.ref("account.data_account_type_payable").id
+ cls.account = cls.AccountAccount.search(
+ [("account_type", "=", "liability_payable")], limit=1
)
# Create users
- self.user1_id = self._create_user(
+ cls.user1_id = cls._create_user(
"user_1",
- [self.group_purchase_user],
- self.company,
- [self.ou1],
+ [cls.group_purchase_user, cls.group_operating_unit],
+ cls.company,
+ [cls.ou1],
)
- self.user2_id = self._create_user(
+ cls.user2_id = cls._create_user(
"user_2",
- [self.group_purchase_user],
- self.company,
- [self.b2b],
+ [cls.group_purchase_user],
+ cls.company,
+ [cls.b2b],
)
- self.purchase1 = self._create_purchase(
- self.user1_id,
- [(self.product1, 1000), (self.product2, 500), (self.product3, 800)],
+ cls.purchase1 = cls._create_purchase(
+ cls.user1_id,
+ [(cls.product1, 1000), (cls.product2, 500), (cls.product3, 800)],
)
- self.purchase1.with_user(self.user1_id).button_confirm()
- self.invoice = self._create_invoice(self.purchase1, self.partner1, self.account)
+ cls.purchase1.with_user(cls.user1_id).button_confirm()
+ cls.purchase1.order_line[0].qty_received = cls.purchase1.order_line[
+ 0
+ ].product_qty
+ cls.purchase1.with_user(cls.user1_id).action_create_invoice()
+ # cls.invoice = cls._create_invoice(cls.purchase1, cls.partner1, cls.account)
+ cls.invoice = cls.purchase1.invoice_ids[0]
- def _create_user(self, login, groups, company, operating_units):
+ @classmethod
+ def _create_user(cls, login, groups, company, operating_units):
"""Create a user."""
group_ids = [group.id for group in groups]
- user = self.ResUsers.with_context(**{"no_reset_password": True}).create(
+ user = cls.ResUsers.with_context(**{"no_reset_password": True}).create(
{
"name": "Chicago Purchase User",
"login": login,
@@ -72,7 +82,8 @@ def _create_user(self, login, groups, company, operating_units):
)
return user.id
- def _create_purchase(self, user_id, line_products):
+ @classmethod
+ def _create_purchase(cls, user_id, line_products):
"""Create a purchase order.
``line_products`` is a list of tuple [(product, qty)]
"""
@@ -87,18 +98,19 @@ def _create_purchase(self, user_id, line_products):
"date_planned": time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}
lines.append((0, 0, line_values))
- purchase = self.PurchaseOrder.with_user(user_id).create(
+ purchase = cls.PurchaseOrder.with_user(user_id).create(
{
- "operating_unit_id": self.ou1.id,
- "requesting_operating_unit_id": self.ou1.id,
- "partner_id": self.partner1.id,
+ "operating_unit_id": cls.ou1.id,
+ "requesting_operating_unit_id": cls.ou1.id,
+ "partner_id": cls.partner1.id,
"order_line": lines,
- "company_id": self.company.id,
+ "company_id": cls.company.id,
}
)
return purchase
- def _create_invoice(self, purchase, partner, account):
+ @classmethod
+ def _create_invoice(cls, purchase, partner, account):
"""Create a vendor invoice for the purchase order."""
invoice_vals = {
"purchase_id": purchase.id,
@@ -111,7 +123,7 @@ def _create_invoice(self, purchase, partner, account):
"active_model": "purchase.order",
}
res = (
- self.env["account.move"]
+ cls.env["account.move"]
.with_context(**purchase_context)
.create(invoice_vals)
)
@@ -123,21 +135,34 @@ def test_01_purchase_operating_unit(self):
# Check change operating unit in purchase
with self.assertRaises(ValidationError):
self.b2b.company_id = False
- with Form(self.purchase1) as po:
+ # The user_1 is used here so he's able to see the field operating_unit
+ with Form(self.purchase1.with_user(self.user1_id)) as po:
po.operating_unit_id = self.b2b
+ # This has been changed to follow the standard flow of creating a
+ # purchase order and then billing
self.purchase1.with_user(self.user1_id).button_confirm()
+ # self.purchase1.order_line[0].qty_received = self.purchase1.order_line[0].product_qty
+ # self.purchase1.with_user(self.user1_id).action_create_invoice()
# Create Vendor Bill
- f = Form(self.env["account.move"].with_context(default_move_type="in_invoice"))
- f.partner_id = self.purchase1.partner_id
- f.purchase_id = self.purchase1
- invoice = f.save()
- self.assertEqual(invoice.operating_unit_id, self.purchase1.operating_unit_id)
+ # The user_1 is used here so he's able to see the field purchase_id
+ # f = Form(self.env["account.move"].with_context(
+ # default_move_type="in_invoice").with_user(self.user1_id))
+ # f.partner_id = self.purchase1.partner_id
+ # f.purchase_id = self.purchase1
+ # invoice = f.save()
+
self.assertEqual(
- invoice.invoice_line_ids[0].operating_unit_id,
- invoice.invoice_line_ids[0].purchase_line_id.operating_unit_id,
+ self.purchase1.invoice_ids[0].operating_unit_id,
+ self.purchase1.operating_unit_id,
+ )
+ self.assertEqual(
+ self.purchase1.invoice_ids[0].invoice_line_ids[0].operating_unit_id,
+ self.purchase1.invoice_ids[0]
+ .invoice_line_ids[0]
+ .purchase_line_id.operating_unit_id,
)
# Check change operating unit in invoice line != purchase line,
# it should error.
- with self.assertRaises(ValidationError):
- with Form(invoice.invoice_line_ids[0]) as line:
+ with self.assertRaises(AccessError):
+ with Form(self.purchase1.invoice_ids[0].invoice_line_ids[0]) as line:
line.operating_unit_id = self.b2b
diff --git a/purchase_operating_unit/views/purchase_order_view.xml b/purchase_operating_unit/views/purchase_order_view.xml
index 13c2b00da5..8228a67d05 100644
--- a/purchase_operating_unit/views/purchase_order_view.xml
+++ b/purchase_operating_unit/views/purchase_order_view.xml
@@ -27,6 +27,10 @@
name="operating_unit_id"
groups="operating_unit.group_multi_operating_unit"
/>
+
+
+
+