From baf2c9867bbffbe45524ff94f39c7e9364daf248 Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Wed, 25 Apr 2018 18:03:25 +0200 Subject: [PATCH] [ADD] stock_request_kanban --- stock_request_kanban/README.rst | 83 +++++++++ stock_request_kanban/__init__.py | 5 + stock_request_kanban/__manifest__.py | 28 +++ .../data/stock_request_sequence_data.xml | 14 ++ stock_request_kanban/models/__init__.py | 5 + stock_request_kanban/models/stock_request.py | 10 ++ .../models/stock_request_kanban.py | 19 ++ .../report/report_paper_format.xml | 15 ++ .../report/stock_request_kanban_templates.xml | 75 ++++++++ .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 5760 bytes stock_request_kanban/tests/__init__.py | 1 + stock_request_kanban/tests/test_kanban.py | 166 ++++++++++++++++++ .../views/stock_request_kanban_views.xml | 146 +++++++++++++++ .../views/stock_request_order_views.xml | 21 +++ stock_request_kanban/wizard/__init__.py | 6 + .../wizard/wizard_stock_request_kanban.py | 14 ++ .../wizard_stock_request_kanban_abstract.py | 90 ++++++++++ .../wizard_stock_request_kanban_views.xml | 56 ++++++ .../wizard_stock_request_order_kanban.py | 53 ++++++ ...izard_stock_request_order_kanban_views.xml | 31 ++++ 21 files changed, 841 insertions(+) create mode 100644 stock_request_kanban/README.rst create mode 100644 stock_request_kanban/__init__.py create mode 100644 stock_request_kanban/__manifest__.py create mode 100644 stock_request_kanban/data/stock_request_sequence_data.xml create mode 100644 stock_request_kanban/models/__init__.py create mode 100644 stock_request_kanban/models/stock_request.py create mode 100644 stock_request_kanban/models/stock_request_kanban.py create mode 100644 stock_request_kanban/report/report_paper_format.xml create mode 100644 stock_request_kanban/report/stock_request_kanban_templates.xml create mode 100644 stock_request_kanban/security/ir.model.access.csv create mode 100644 stock_request_kanban/static/description/icon.png create mode 100644 stock_request_kanban/tests/__init__.py create mode 100644 stock_request_kanban/tests/test_kanban.py create mode 100644 stock_request_kanban/views/stock_request_kanban_views.xml create mode 100644 stock_request_kanban/views/stock_request_order_views.xml create mode 100644 stock_request_kanban/wizard/__init__.py create mode 100644 stock_request_kanban/wizard/wizard_stock_request_kanban.py create mode 100644 stock_request_kanban/wizard/wizard_stock_request_kanban_abstract.py create mode 100644 stock_request_kanban/wizard/wizard_stock_request_kanban_views.xml create mode 100644 stock_request_kanban/wizard/wizard_stock_request_order_kanban.py create mode 100644 stock_request_kanban/wizard/wizard_stock_request_order_kanban_views.xml diff --git a/stock_request_kanban/README.rst b/stock_request_kanban/README.rst new file mode 100644 index 000000000..b998d251f --- /dev/null +++ b/stock_request_kanban/README.rst @@ -0,0 +1,83 @@ +.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg + :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +==================== +Stock Request Kanban +==================== + +On most companies there is products that must be purchased often but cannot be +stored as a usual product because no consumption moves are made. +Usually, they are stored as consumables or putaway rules are defined. +In both cases, reordering rules cannot be used. +This module allows to use stock request as reordering rules for this kind of +products. + +It is created following the concept of lean kanban cards. + +Usage +===== + +Creation +-------- +* Go to 'Stock Requests / Stock Requests Kanban' and create a new Kanban. +* Indicate a product, quantity and location. +* Press 'Save'. +* Print the kanban and put it in the storage of the product + +Request kanban +-------------- + +This should be used if you want to create the kanban when the card is consumed. + +* Once the product is consumed, take the card +* Go to 'Stock Requests / Order Kanban Card' +* Scan the card +* The stock request is created + +Request kanban batch +-------------------- + +This should be used when you will store the cards and create request orders +for kanbans later. + +* Once the product is consumed, take the card and store it +* Create a store request order +* Press the scan button +* Scan all the pending kanban cards + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/153/11.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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Enric Tobella + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://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 https://odoo-community.org. diff --git a/stock_request_kanban/__init__.py b/stock_request_kanban/__init__.py new file mode 100644 index 000000000..22ba14540 --- /dev/null +++ b/stock_request_kanban/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2018 Creu Blanca +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from . import models +from . import wizard diff --git a/stock_request_kanban/__manifest__.py b/stock_request_kanban/__manifest__.py new file mode 100644 index 000000000..ccb4333a6 --- /dev/null +++ b/stock_request_kanban/__manifest__.py @@ -0,0 +1,28 @@ +# Copyright 2018 Creu Blanca +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + 'name': 'Stock Request kanban', + 'version': '11.0.1.0.0', + 'category': 'Reporting', + 'website': 'https://github.com/eficent/cb-addons', + 'author': 'Creu Blanca, Eficent, Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'summary': 'Adds a stock request order, and takes stock requests as lines', + 'depends': [ + 'stock_request', + 'barcodes', + ], + 'data': [ + 'data/stock_request_sequence_data.xml', + 'report/report_paper_format.xml', + 'wizard/wizard_stock_request_kanban_views.xml', + 'wizard/wizard_stock_request_order_kanban_views.xml', + 'views/stock_request_order_views.xml', + 'views/stock_request_kanban_views.xml', + 'report/stock_request_kanban_templates.xml', + 'security/ir.model.access.csv', + ], + 'installable': True, + 'application': False, +} diff --git a/stock_request_kanban/data/stock_request_sequence_data.xml b/stock_request_kanban/data/stock_request_sequence_data.xml new file mode 100644 index 000000000..33931ab67 --- /dev/null +++ b/stock_request_kanban/data/stock_request_sequence_data.xml @@ -0,0 +1,14 @@ + + + + + + Stock Request Kanban + stock.request.kanban + KB + 5 + + + + + diff --git a/stock_request_kanban/models/__init__.py b/stock_request_kanban/models/__init__.py new file mode 100644 index 000000000..66d035730 --- /dev/null +++ b/stock_request_kanban/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2018 Creu Blanca +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from . import stock_request +from . import stock_request_kanban diff --git a/stock_request_kanban/models/stock_request.py b/stock_request_kanban/models/stock_request.py new file mode 100644 index 000000000..664b71afe --- /dev/null +++ b/stock_request_kanban/models/stock_request.py @@ -0,0 +1,10 @@ +# Copyright 2018 Creu Blanca +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import models, fields + + +class StockRequest(models.Model): + _inherit = 'stock.request' + + kanban_id = fields.Many2one('stock.request.kanban', readonly=True) diff --git a/stock_request_kanban/models/stock_request_kanban.py b/stock_request_kanban/models/stock_request_kanban.py new file mode 100644 index 000000000..b91378e2c --- /dev/null +++ b/stock_request_kanban/models/stock_request_kanban.py @@ -0,0 +1,19 @@ +# Copyright 2018 Creu Blanca +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, models, fields + + +class StockRequestKanban(models.Model): + _name = 'stock.request.kanban' + _description = 'Stock Request Kanban' + _inherit = 'stock.request.abstract' + + active = fields.Boolean(default=True) + + @api.model + def create(self, vals): + if vals.get('name', '/') == '/': + vals['name'] = self.env['ir.sequence'].next_by_code( + 'stock.request.kanban') + return super().create(vals) diff --git a/stock_request_kanban/report/report_paper_format.xml b/stock_request_kanban/report/report_paper_format.xml new file mode 100644 index 000000000..4296a6412 --- /dev/null +++ b/stock_request_kanban/report/report_paper_format.xml @@ -0,0 +1,15 @@ + + + + Kanban format + A4 + Portrait + 0.0 + 0.0 + 0.0 + 0.0 + 0 + 72 + + + \ No newline at end of file diff --git a/stock_request_kanban/report/stock_request_kanban_templates.xml b/stock_request_kanban/report/stock_request_kanban_templates.xml new file mode 100644 index 000000000..2bcff8ff6 --- /dev/null +++ b/stock_request_kanban/report/stock_request_kanban_templates.xml @@ -0,0 +1,75 @@ + + + + + + + + + diff --git a/stock_request_kanban/security/ir.model.access.csv b/stock_request_kanban/security/ir.model.access.csv new file mode 100644 index 000000000..2b0a2da15 --- /dev/null +++ b/stock_request_kanban/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_stock_request_kanban_user,stock request kanban user,model_stock_request_kanban,stock_request.group_stock_request_user,1,1,1, +access_stock_request_kanban_manager,stock request kanban manager,model_stock_request_kanban,stock_request.group_stock_request_manager,1,1,1,1 diff --git a/stock_request_kanban/static/description/icon.png b/stock_request_kanban/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..dc706ff5d0d8eeb02bdc4c3486060e9a81ecd48b GIT binary patch literal 5760 zcmcgwE`kGKfLEXGk4;CxnJhYIWuv3I%*_@^n?HafJ8%GMgLz8{|`XCf3aJ^X7FFav(;2n z0X+O?ACVPl{}=*KbyFVzfQaHhU;%RSX#bJ;z8c!9_^Uu5J~948#_-#J6qB=|iLbJU zo125X@4prRQ1*7P@pZ6gg*p4aW>wSB*0UFKzy|=R)-_ZV4Fl%(^I^W`llgs+3#62G ziO?65Zwo|{cy=GO2g!wT$vcxfxs$sGxa}j>qiSW^z-=-JE*ss9+j?*mHR}Mk>zq3| z4wh{^R_soA*U#_f4zn4Pa`cVc9!toZzFazum)UhGuDBPwb}Y_Ixi{#;;IKPOqB4Zi zA7vut4s2}z$^V@vRN`rNL_U_xd3;c@@kam%Y!O=YTwbVTMQ`{@vQHh@K zg2OKDu7iRbA0OFtmsguzZgfMGp_Tcaj~R0O57%fQAttdAEYJ7kf1&OmEyn-VrFr5P zi@{GQS2{GoU_v~RSQV@>6~=UbkkV^xEmgVGe&rdA{n80SUqHbREVX>PLDuJfbHH>O z8`MaU74LQbbzhd~sqxd)oU4Qq=G+Nk%^QFL*@gTmE82_jA#z-21t0G&1?&89hD1qg zCMySE0L-_rpx}cuJ<<|!U2JzVk9}go*dso);G{FxwRM&d)V_RJQCg}(VGZrQ7rgmN z8Tw~o7QS29VR>XSZ2`-d#4;dR)qCxW-Cu_c*~fv0Cxg6EeR&{?j|glokjo_r9~($1 z{1+-0lw|Slf&dF~lcdiYLlD@kM5b&=Nz1zM(GWQN&Q7te0hr`>M7vz+*AQt8b!^pC zImoH&#+k7Y8OPBW2RG4m9S33%SD5L{6~QwSeWez9yKm~h7J|ad_q7`uS&BP6!UG-v z;EiNoSAdqyiiDsXss|VV#^3=dX~e3(=d}1Z`k*y-<8Teof zF7LM=mxJgdra$#Y62HkwlS;#diF20cevV8S+hlEmyuf_#HM6M&7%=(gOQ00{;?6|Y z4blv%93~CW;=E>n0YlM#b<|VkC}kV;U0FaBJ{G5aWV?M-Yb!mP;Z0WHxl-g{`3pIu z>u-@|BD`WU$@VL$f`B!GywZL28gHMGJ{ztH77J`46n}%O%&uU5Zg!+5^p4jp_;GXQ z08FrQ!AXJ`VMvShc*9|1C|fqup+eBk(E`UPJw5Oc(~@bqf`QyR5B>2Mjiyh%PIHc( zoHp-jq_GlNTfk=t2ya>rmF>XO8_&mJD}LjE?#9S7208Fp+&sl(QR_qX(fMbqDjts9 z&0>oxzi4(i<|sI}s2Z!pZe|Zil@zG4Pf$aDCMTj1*{z=s}zUd0|*i@xGxEPP4 z+_i$Ie3>#A*$E7OmD92n3-KnfqYMyKZXV5PNraYfZxfD9P}xrGGLR|hy)^BTYCqG4 z;&h3`WIG~d8_Z@V`cwcTrPSTucd#mjXH$GY zWzT>K#ihI6FT{+0*$#T@^2K?DqeRSKqe22*`fJKl?!b0W8FMWslZuG_ArC@=47sNM zcQU`NYCE~GqSc5W-|pG?ceI6|3`(F~RgX$W8_Jnv^_*h|BDG|1uae$i@ZU>&OwMv7 z-pE;wATQyTf#Gn=#}G#yx~HE#&tRbuHoGemR>6B`dY&Aop?$L7S2 zeX;qCblE!VH9a>T9u$17|Kb{jbZzm#8BS_X0HGSK9yN2mnU){;-Xx{le1tW`&XQo% zSn}l|WH{|`hp5Z0;{ie**Yhd12D!FF_Bj+K9xh8{k=uA7l{<4$A?Vw8oeU)#|$0q4z5AVpw5IDLIciGr&q1W_XeZ7oE1}xV95XOtxLWWI7bHW>p~jnJ(FA zR@unuWjeESsN-m!%%-%w#bO`VLcM|H6E}Fe=7^d64yMB_L}9n^mDG>vu!dPT`n{P; z(s^n@=JP#&@vd_w?UF3O24Ps=q2$DMpP+9~TT0?v@X*2snr1O`aI_(Lw=gJt^r*#6 ztz3!C)1Kb!DJ!Kubf{{e--To~hpf-*b%HP1l@9_@Wa9rvMmqaMt(&C)PHd_!ZyvFI zB3x1wL3iRfp=YI=-NfruT&$B?@YS94B6j<5ue_;)g(rX0j>b|vF>$0YuKouz{SHG6 zMoN&0JPsEb5;7BKuecs^zU^m6zG9I1)n@*?n=g~=V2Kv4g&Wg?&-8^F`~VXaOToIk z--K+=%~(ciNKZ=f-tO%UCqIM2zTXHwQC(t1Vib7EFZne=8H%DAJ)|Vo;51Py5##`n z)ER+00iuI-QAImvNskxls&2y_dEDwhS9Sz+eHzgj(mCF_CV7PHL|@b2?_0IUEpPp4 zRs^?ucGJlC<(Z=fJ>1qWI&KSplnYVCQRr3xO-jDpn6;l$xp(Y;#}eaAXpN)!DF;*{pJD#u^70FAEO*>69klKW zmF6pK-bi@Y)kh{I-A1d(DeBKDyZ%6bf_v)WYOzqMmI)voskRO|pf#l5 zaN*pCG~Z6zA*oZ?meq~_xCW1Q97;ztdnh-8gqn&U0??1*W;iC z{#}|JDRR4cH%AafuJ(y7&dLOL5Gs9Q^@L3t*^_@({=)M)6u9abU0Uqw&&A*21upAV z6tLN7(9((KcsJ|ys_CF2OwCE>62Em$)TkFD<}$Invvh&Vcl!6WQ~bi^zKOKfWhMFV{1s8nK};Cd}bnVIp;dQ54WU@y2n;bY%u_y;>+dTzqk z9SLFWw}I0_C8c%Vo>MF(A&A6M_zQ^yVmo&6{z-IC`VROsX-Cm*8N1jdbsjfXeT3);4}Si_o(3G6fGPsChBULXk~^RPtx+Z z0bK5%!qpqBG7UbE_iIkpxN?j;GIF7->YY`l^*YVrZOV&T8iDK8V`D7kWq~ZYmdonR zvT|RKLP8-GLuTSd7e;Q6)UC%Nn+rzlCZE1%(Ji!^uXoMCI`yF3x zq@^R=R%RFymL9;qaZPOM4^|am;+V{1pCT&?(0LTM6oDa+I#7OTSYWbE)TIn*^*GHP z`mJ${gmjCxtPV=qnD$jzO{@F%YVeRtk7Et2K*3XilW*7=*@>8d_kEKT!` zsjIx@-_%o3Jwx(QS+M@2Us$P&UQ%I9 zI}DJY)R9o#id$2{8)>VXISS9uCv(@_k7FN3t2dXmVvH02Z`Z zk2Yl>+sM={Rh{SfNRyf`1TPQQfC-&)yN(ZW-2KYbw-J;`Q-t zyDh>~l`GZek&lR9(tDy06<`xh;Ocg&qdIN7Fe2}#z#~*DI-n4c&#DVxwmj^|PK@V# z$GLVI(_OlDrHOjHcmsgl_rX5#f^*HWvm8QQo$UxH)MVUU^dce@p-+MMw$*otp~@^z z4;cwih20ibsy{iHYLkq~Q7HoU3J@ND?EUHlBs?YMS-kb6@L^%=lOP?0F=TI>C-8pT zFOWNKy)5$q%>(heTF(J^_>tXz#GepdoU<-hip6s7D_6fHaB~?Df!i*n$?A=6`VYN} zs}?QWsyg#}qPw86R_Q76Ec;1v6V7JmJr0k;gz>X_bb4X)hf%Ar5X-`?>JFsLl|pzE z`!hE?d2aTJr|HgxO4h))4QY-SMDum{vlT?$S%n}(@bKg`8r46*9bVC|yq`*!RUQp;6iQnqR0iqt#5J7P z?p_J9N^g=7_~7=77c##ITynJN{_%A% zOIzp(x4(a{R{3g=e4hkaiecXN7soB^h%3K@N6{tt70J|k(9IC57d#SIxV)z3+KZ8R zx6BX}W9m0UYeMxhx3v^pkNdxYYem4U=jCMUysqtk&KbFHY=2;^M#%{-(vrbafhFFF zawtk%`OuxrpSao7_L~grR|onv zuFVyq`XVH6KQWcT!lY^zuQ>09>9mtAh}kFAMc1E3mhziUuud(FF1J50-nF&S)|O;t zKPs0IWbN{2I&w!+zSbNsWZ&Exr!#@|wNH{!=2eH0t-@eNNV z0OiTlHp^n6)tl!MFRzI3H1hdMWe(KRD&FQ@eVhNod#iBv;nIIE0%5l9NdssWv@!ip zop{_U_q!A9WO|;3qhTL}Q_0KisB`ADON`btyo|3jUFbYL*-Yw}6_B}F|KVXmi`Q{~ zXf-xA8^}Hm;3OngWodoriX8d!HERJoGaczS_@-`8bL-^V?Ttn$$+(N><_2yNs|$}t zY;eHI>KQ^FnLSIBr*bxMhRcAiLx;$uJF2B}zQUJY`2GAOWlp=WX0i)Vr1#;cILEdfw&zY5SFJ?8e>q`d4B2c+QTc$p z$(cp^(708*l``hmEWpK7r^ag9$&`-%)-XF<(eVR=Vn@x*G+J*^QEjcxOZE5_;W|s7 zTX!^g_E(ONh6b1J`i5O^dIweVaP5r=9cJ>~NHU@9#1W%M|F#+49&clUAHon}utP$w z(fjxD#rW)!MjbHurL(O+Y7*!YFlr;Ymi)}li^QkBHg7hwKy;J6zj3#~{w{4dk#9%% zeTd;pL%mm~aS=wfw?!+Y|sI2jxb60tP z`I^X{c0Hykw6-(&RhpT;ld2YxdQ~Wwe*e~jG05i0-8mqUGV3`v)Yv_=lhXZ_G&s$j zsD=Er@r>N1vnU>yKa ze3{1kR$rG)?B749QYwVg1Ie~>;dAB$5vxq^C@3g+al&Lo(pR&3T6OY}`13mEk6Jj} zwsaLc3x9hk*?S?Yk<&F7c#M4s!X6wvie; z6oVV$4Vu($`o4twomtmA7YulxZ}VUEUu|jA6a2d;z)qzJ3PSl$p)aOqI-P2+PrcZ3 zBy!Ly5gUyrp53OD!&SDs9+upbZzgj84ptuR75~a>_|4lJx%b&CrUtB{7+piGs~YYg zRiL>z>l4daNNA8gZGPtr4~6VbYbz}r@?P&rM{uHLyF??y+fX2oFEhB zNG&Sb%tTy-gd$0}ED4!OfKa|D zuA@gttv8=+UfGdMWQ=@-+mPJTm6asQ6wx!P4lX&K!(hof2P~Wsh5?R-<10@pnp;!p zs3zevUWN}|_U^GsZ1sHkwHjyKFEEtj%#7$$T3}&Z1$ MsOqSERkDu!AL4u3zW@LL literal 0 HcmV?d00001 diff --git a/stock_request_kanban/tests/__init__.py b/stock_request_kanban/tests/__init__.py new file mode 100644 index 000000000..6370893a8 --- /dev/null +++ b/stock_request_kanban/tests/__init__.py @@ -0,0 +1 @@ +from . import test_kanban diff --git a/stock_request_kanban/tests/test_kanban.py b/stock_request_kanban/tests/test_kanban.py new file mode 100644 index 000000000..38f8b2df6 --- /dev/null +++ b/stock_request_kanban/tests/test_kanban.py @@ -0,0 +1,166 @@ +# Copyright 2017 Creu Blanca +# Copyright 2017 Eficent Business and IT Consulting Services, S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo.tests.common import TransactionCase +from odoo.exceptions import ValidationError +from reportlab.graphics.barcode import getCodes + + +class TestKanban(TransactionCase): + + def setUp(self): + super().setUp() + self.main_company = self.env.ref('base.main_company') + self.warehouse = self.env.ref('stock.warehouse0') + self.categ_unit = self.env.ref('product.product_uom_categ_unit') + + # common data + self.company_2 = self.env['res.company'].create({ + 'name': 'Comp2', + }) + self.wh2 = self.env['stock.warehouse'].search( + [('company_id', '=', self.company_2.id)], limit=1) + + self.ressuply_loc = self.env['stock.location'].create({ + 'name': 'Ressuply', + 'location_id': self.warehouse.view_location_id.id, + }) + self.route = self.env['stock.location.route'].create({ + 'name': 'Transfer', + 'product_categ_selectable': False, + 'product_selectable': True, + 'company_id': self.main_company.id, + 'sequence': 10, + }) + self.product = self.env['product.product'].create({ + 'name': 'Product', + 'route_ids': [(4, self.route.id)], + 'company_id': False, + }) + self.uom_dozen = self.env['product.uom'].create({ + 'name': 'Test-DozenA', + 'category_id': self.categ_unit.id, + 'factor_inv': 12, + 'uom_type': 'bigger', + 'rounding': 0.001}) + + self.env['procurement.rule'].create({ + 'name': 'Transfer', + 'route_id': self.route.id, + 'location_src_id': self.ressuply_loc.id, + 'location_id': self.warehouse.lot_stock_id.id, + 'action': 'move', + 'picking_type_id': self.warehouse.int_type_id.id, + 'procure_method': 'make_to_stock', + 'warehouse_id': self.warehouse.id, + 'company_id': self.main_company.id, + 'propagate': 'False', + }) + + def test_onchanges(self): + kanban = self.env['stock.request.kanban'].new({}) + kanban.product_id = self.product + kanban.onchange_product_id() + kanban.company_id = self.main_company + kanban.onchange_company_id() + self.assertTrue(kanban.warehouse_id) + kanban.warehouse_id = self.wh2 + kanban.onchange_warehouse_id() + self.assertEqual(kanban.company_id, self.company_2) + kanban.location_id = self.warehouse.view_location_id + kanban.onchange_location_id() + self.assertEqual(kanban.company_id, self.main_company) + self.assertEqual(kanban.warehouse_id, self.warehouse) + + def test_create(self): + kanban = self.env['stock.request.kanban'].new({}) + kanban.product_id = self.product + kanban.onchange_product_id() + kanban.product_uom_qty = 1 + kanban = kanban.create(kanban._convert_to_write(kanban._cache)) + self.assertTrue(kanban.company_id) + self.assertEqual(kanban.route_ids, self.route) + + def test_order_barcodes(self): + kanban_1 = self.env['stock.request.kanban'].create({ + 'product_id': self.product.id, + 'product_uom_id': self.product.uom_id.id, + 'product_uom_qty': 1, + }) + kanban_2 = self.env['stock.request.kanban'].create({ + 'product_id': self.product.id, + 'product_uom_id': self.product.uom_id.id, + 'product_uom_qty': 1, + }) + kanban_3 = self.env['stock.request.kanban'].create({ + 'product_id': self.product.id, + 'product_uom_id': self.product.uom_id.id, + 'product_uom_qty': 1, + 'company_id': self.company_2.id, + 'warehouse_id': self.wh2.id, + 'location_id': self.wh2.lot_stock_id.id, + }) + order = self.env['stock.request.order'].create({ + 'company_id': self.main_company.id, + 'warehouse_id': self.warehouse.id, + 'location_id': self.warehouse.lot_stock_id.id, + }) + wizard = self.env['wizard.stock.request.order.kanban'].with_context( + default_order_id=order.id + ).create({}) + with self.assertRaises(ValidationError): + wizard.on_barcode_scanned(kanban_1.name) + self.pass_code(wizard, kanban_1.name) + self.assertEqual(wizard.status_state, 0) + self.assertTrue(order.stock_request_ids.filtered( + lambda r: r.kanban_id == kanban_1 + )) + self.pass_code(wizard, kanban_2.name) + self.assertTrue(order.stock_request_ids.filtered( + lambda r: r.kanban_id == kanban_2 + )) + self.assertEqual(wizard.status_state, 0) + self.pass_code(wizard, kanban_1.name) + self.assertEqual(wizard.status_state, 1) + self.pass_code(wizard, kanban_2.name+kanban_1.name) + self.assertEqual(wizard.status_state, 1) + with self.assertRaises(ValidationError): + self.pass_code(wizard, kanban_3.name) + + def test_barcodes(self): + kanban_1 = self.env['stock.request.kanban'].create({ + 'product_id': self.product.id, + 'product_uom_id': self.product.uom_id.id, + 'product_uom_qty': 1, + }) + kanban_2 = self.env['stock.request.kanban'].create({ + 'product_id': self.product.id, + 'product_uom_id': self.product.uom_id.id, + 'product_uom_qty': 1, + }) + wizard = self.env['wizard.stock.request.kanban'].with_context( + ).create({}) + with self.assertRaises(ValidationError): + wizard.on_barcode_scanned(kanban_1.name) + self.assertFalse(self.env['stock.request'].search( + [('kanban_id', '=', kanban_1.id)]) + ) + self.pass_code(wizard, kanban_1.name) + self.assertEqual(wizard.status_state, 0) + self.assertTrue(self.env['stock.request'].search( + [('kanban_id', '=', kanban_1.id)]) + ) + self.assertFalse(self.env['stock.request'].search( + [('kanban_id', '=', kanban_2.id)]) + ) + self.pass_code(wizard, kanban_2.name) + self.assertTrue(self.env['stock.request'].search( + [('kanban_id', '=', kanban_2.id)]) + ) + + def pass_code(self, wizard, code): + bcc = getCodes()[wizard.get_barcode_format()](value=code) + bcc.validate() + bcc.encode() + wizard.on_barcode_scanned(bcc.encoded[1:-1]) diff --git a/stock_request_kanban/views/stock_request_kanban_views.xml b/stock_request_kanban/views/stock_request_kanban_views.xml new file mode 100644 index 000000000..1f3474a8a --- /dev/null +++ b/stock_request_kanban/views/stock_request_kanban_views.xml @@ -0,0 +1,146 @@ + + + + + + stock.request.kanban.tree + stock.request.kanban + + + + + + + + + + + + + + + + + stock.request.kanban.search + stock.request.kanban + + + + + + + + + + + + + + + + + + stock.request.kanban.form + stock.request.kanban + +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + stock.request.kanban.kanban + stock.request.kanban + + + + + + + + + + + +
+ +
+ +
+
+ +
+
    +
  • +
  • +
  • +
  • +
+
+
+ + + + + + + + + Stock Request Kanbans + stock.request.kanban + ir.actions.act_window + form + kanban,tree,form + +

+ Click to add a Stock Request Kanban. +

+
+
+ + + + diff --git a/stock_request_kanban/views/stock_request_order_views.xml b/stock_request_kanban/views/stock_request_order_views.xml new file mode 100644 index 000000000..d830b6c75 --- /dev/null +++ b/stock_request_kanban/views/stock_request_order_views.xml @@ -0,0 +1,21 @@ + + + + + stock.request.order.form + stock.request.order + + + +