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<+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+Zl&#s4&}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

+ + +

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

+

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

+
    +
  1. Create a PO: the Default Operating Unit is assigned to the PO. If you want, +you can change to another Operating Unit.
  2. +
  3. Validate the PO: the Operating Unit is propagated to the Pickings and +Invoices.
  4. +
  5. From the invoice, it is not possible to change the Operating Unit, it has to +be the same as the one of the PO.
  6. +
+
+
+

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.

+

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

+
+
+

Credits

+
+

Authors

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

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

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

+

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

+
+
+
+ + diff --git a/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. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

This module introduces the following features:

@@ -438,7 +439,7 @@

Maintainers

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

-

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

+

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

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

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 @@

Contributors

  • 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 @@

    Credits

    Authors

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

    Contributors

      -
    • 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. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

      +

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

      This module introduces the following features:

      • It introduces the operating unit to the purchase order.
      • @@ -411,7 +411,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.

    @@ -431,6 +431,7 @@

    Contributors

  • Sudhir Arya <sudhir.arya@serpentcs.com>
  • Nicola Studer <nicola.studer@braintec-group.com>
  • Nikul Chaudhary <nikul.chaudhary.serpentcs@gmail.com>
  • +
  • Kitti U. <kittiu@ecosoft.co.th>
  • @@ -440,7 +441,7 @@

    Maintainers

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

    -

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

    +

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

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

    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. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

    +

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

    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

    -
    -

    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

    +

    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.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • ForgeFlow
    • Serpent Consulting Services Pvt. Ltd.
    -

    Contributors

    +

    Contributors

    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association

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

    -

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

    +

    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" /> + + + +