From c92a3b0291a6df757344476658d5d36ef167cc77 Mon Sep 17 00:00:00 2001 From: "admin.suherdy" Date: Thu, 20 Nov 2025 08:49:19 +0700 Subject: [PATCH] fix some bug regarding the groups in xml view --- README.md | 84 ++--- __manifest__.py | 50 +-- __pycache__/__init__.cpython-310.pyc | Bin 0 -> 234 bytes models/__init__.py | 2 +- models/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 282 bytes .../purchase_order.cpython-310.pyc | Bin 0 -> 4518 bytes .../purchase_order.cpython-312.pyc | Bin 6829 -> 6917 bytes models/__pycache__/stock_move.cpython-310.pyc | Bin 0 -> 2918 bytes models/purchase_order.py | 343 +++++++++--------- models/stock_move.py | 206 +++++------ views/purchase_order_views.xml | 114 +++--- views/stock_move_link_views.xml | 88 ++--- views/stock_move_views.xml | 84 +++-- 13 files changed, 485 insertions(+), 486 deletions(-) create mode 100644 __pycache__/__init__.cpython-310.pyc create mode 100644 models/__pycache__/__init__.cpython-310.pyc create mode 100644 models/__pycache__/purchase_order.cpython-310.pyc create mode 100644 models/__pycache__/stock_move.cpython-310.pyc diff --git a/README.md b/README.md index 6babc6c..0e0cb25 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,43 @@ -# Subcontracting Inventory Move First - -## Overview -This module extends the standard Odoo subcontracting workflow to allow creating inventory moves first and then linking them to purchase orders, rather than the standard flow where purchase orders create inventory moves. - -## Features -- Create "Resupply Subcontract" inventory moves directly in the inventory module -- Link these moves to purchase orders after creation -- Smart button on purchase orders to view linked inventory moves -- Maintain data consistency between moves and purchase orders -- Update source document field in inventory moves and related stock pickings to show purchase order number -- Proper handling of purchase order cancellation to unlink moves - -## Usage - -### Creating Subcontracting Inventory Moves First -1. Navigate to Inventory > Operations > Transfers -2. Create a new transfer with operation type "Resupply Subcontractor" -3. The inventory move will be created without being linked to a purchase order initially - -### Linking to Purchase Orders -1. Go to the purchase order you want to link -2. Click the "Link Subcontracting Moves" button -3. Select the appropriate inventory moves from the list -4. Click the "Link to Purchase Order" button at the top of the list view to confirm linking -5. The moves will be linked to the purchase order and source document fields updated - -### Viewing Linked Moves -1. On any purchase order form, the smart button "Subcontracting Moves" will show the count of linked moves -2. Click the button to view and manage all linked inventory moves - -## Technical Details -- The module adds a `purchase_order_id` field to `stock.move` to track links to purchase orders -- The module adds a `subcontracting_move_ids` field to `purchase.order` to track linked moves -- Business logic ensures data consistency when linking/unlinking moves and orders -- When linking moves to purchase orders, the source document field is updated to show the purchase order number -- When linking moves to purchase orders, the source document field in related stock pickings is also updated -- Proper handling of purchase order cancellation to unlink moves without errors - -## Compatibility -- Compatible with Odoo 18.0 -- Works alongside standard subcontracting workflow +# Subcontracting Inventory Move First + +## Overview +This module extends the standard Odoo subcontracting workflow to allow creating inventory moves first and then linking them to purchase orders, rather than the standard flow where purchase orders create inventory moves. + +## Features +- Create "Resupply Subcontract" inventory moves directly in the inventory module +- Link these moves to purchase orders after creation +- Smart button on purchase orders to view linked inventory moves +- Maintain data consistency between moves and purchase orders +- Update source document field in inventory moves and related stock pickings to show purchase order number +- Proper handling of purchase order cancellation to unlink moves + +## Usage + +### Creating Subcontracting Inventory Moves First +1. Navigate to Inventory > Operations > Transfers +2. Create a new transfer with operation type "Resupply Subcontractor" +3. The inventory move will be created without being linked to a purchase order initially + +### Linking to Purchase Orders +1. Go to the purchase order you want to link +2. Click the "Link Subcontracting Moves" button +3. Select the appropriate inventory moves from the list +4. Click the "Link to Purchase Order" button at the top of the list view to confirm linking +5. The moves will be linked to the purchase order and source document fields updated + +### Viewing Linked Moves +1. On any purchase order form, the smart button "Subcontracting Moves" will show the count of linked moves +2. Click the button to view and manage all linked inventory moves + +## Technical Details +- The module adds a `purchase_order_id` field to `stock.move` to track links to purchase orders +- The module adds a `subcontracting_move_ids` field to `purchase.order` to track linked moves +- Business logic ensures data consistency when linking/unlinking moves and orders +- When linking moves to purchase orders, the source document field is updated to show the purchase order number +- When linking moves to purchase orders, the source document field in related stock pickings is also updated +- Proper handling of purchase order cancellation to unlink moves without errors + +## Compatibility +- Compatible with Odoo 18.0 +- Works alongside standard subcontracting workflow - Depends on: mrp_subcontracting, purchase, stock, mrp_subcontracting_purchase \ No newline at end of file diff --git a/__manifest__.py b/__manifest__.py index 2a154d8..aec2fa9 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,26 +1,26 @@ -{ - 'name': 'Subcontracting Inventory Move First', - 'version': '18.0.1.0.0', - 'category': 'Manufacturing/Manufacturing', - 'summary': 'Allow creating inventory moves first and then linking to purchase orders in subcontracting', - 'author' : "Suherdy Yacob", - 'description': """ - This module extends the standard subcontracting workflow to allow creating - inventory moves first and then linking them to purchase orders, - rather than the standard flow where purchase orders create inventory moves. - """, - 'depends': [ - 'mrp_subcontracting', - 'purchase', - 'stock', - 'mrp_subcontracting_purchase', - ], - 'data': [ - 'views/stock_move_views.xml', - 'views/stock_move_link_views.xml', - 'views/purchase_order_views.xml', - ], - 'installable': True, - 'auto_install': False, - 'license': 'LGPL-3', +{ + 'name': 'Subcontracting Inventory Move First', + 'version': '18.0.1.0.0', + 'category': 'Manufacturing/Manufacturing', + 'summary': 'Allow creating inventory moves first and then linking to purchase orders in subcontracting', + 'author' : "Suherdy Yacob", + 'description': """ + This module extends the standard subcontracting workflow to allow creating + inventory moves first and then linking them to purchase orders, + rather than the standard flow where purchase orders create inventory moves. + """, + 'depends': [ + 'mrp_subcontracting', + 'purchase', + 'stock', + 'mrp_subcontracting_purchase', + ], + 'data': [ + 'views/stock_move_views.xml', + 'views/stock_move_link_views.xml', + 'views/purchase_order_views.xml', + ], + 'installable': True, + 'auto_install': False, + 'license': 'LGPL-3', } \ No newline at end of file diff --git a/__pycache__/__init__.cpython-310.pyc b/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f38fbf1bd72b156aa5013e74b0de5045e5aafa0 GIT binary patch literal 234 zcmYjLF$w}P5KK-H5d;fAam@ug3lU!+f}Kr>+2{o>SxIt2T7To0t`cnY3s&w~Ij}R# zz$}B)>4Xtpw?{oEefH)b1(^+9oDl&7-Y~}xoHHo)tQ@>K#U<}X4#6~WTNWJ)edo@? zkmN@nFKTo~#I`m8a+Q_Fp literal 0 HcmV?d00001 diff --git a/models/__init__.py b/models/__init__.py index a215966..0e9dd86 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,2 +1,2 @@ -from . import stock_move +from . import stock_move from . import purchase_order \ No newline at end of file diff --git a/models/__pycache__/__init__.cpython-310.pyc b/models/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c71dc7f4fe1c96c5165f91d9ac88d884f51534dd GIT binary patch literal 282 zcmYjLy-EZz5KeYakmF8#0AFC64K{Lx$UT7wcGrYlk~6_gW|<@hX?+`CX)D3X#s{!+ zV&%Ym^L_IV+wGc>eZPIUJBpu8{I`z8o;=+U7-smy0zYuxct^ZDbj15-HmtrlwG4b& zrwsa41~^+%S93w_RI(D#SbQA%g<;!@J;6J}i^d!L6yYFPk&3fu>R6SA<36Za#ZklP zjd-frLDXQZ00VHl6S~l`pp1c-Xz-{ZW>h-+_#%Bg+n53C-z)OuF=Y{GcuGQ2)n_Tk Uxh|LYlq{2dX#b}b!G>M)Un>w!fdBvi literal 0 HcmV?d00001 diff --git a/models/__pycache__/purchase_order.cpython-310.pyc b/models/__pycache__/purchase_order.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06fe505cd46ed4833c31b7e808128a80594bb380 GIT binary patch literal 4518 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 aZ^ldn>{GYb{%5(hZc@ld>D0^iW&1yU`q)GO literal 0 HcmV?d00001 diff --git a/models/__pycache__/purchase_order.cpython-312.pyc b/models/__pycache__/purchase_order.cpython-312.pyc index bd5947c13798446902403f62a8e81d9576705be8..b8c14c5f736671d5548c32ad71f2741b657dd9f6 100644 GIT binary patch delta 899 zcmY+C?@Lor7{|}O+r7J+PUqC^?uXuM{@f_kN)1t{{8c7INC}yYwcVOFf1OP+xkG~r z1*5G~y3q?K1P-F4?8SVOe?V_GM7`{7^r|-Re=5&g^Io$K|=_beiJKPmZANRq0KRLvhH7oc3BOU zKB<9Bqtk{-GnZikQxg(|O?V#})$H&@Ms;5bq76f-BOmfa)K0to0hfO`5X`XS&?~_J zB!(F^(P0TL(KkZ_n~w`oM3$oZxjkGS&x0cl7|juLq&%+ODRM5bM=Y=l(dqcZJzL}A zwS}(md8Nj=?pyPv>aXn7TutRy{$zon_N&kw?orI;(aFec{KktprP7&bTx*STidePI zt#Ju^T5R4I+tXru(zhe_L>YxITg{8*rK&F^tGDa62J2E)9lLy|ViDs-F>8GCwV<4G zBr4XNQH>&0uFk|}68UMNXi`%Gv^u4&An%T6K7-;Kl zGNv#0C{C1j(KP$+7Q|>RZ!v0w8>4K zBfc5^-Kk)3e9Yx>k9j1&Lv>=FrDOr*N#~Zkk;IGC8}yX_+-e*h_ey@32TJas#Lb;GaJf8wcOZc2ewWKZ!G1JpDWlfWbIT+1K4VKWwnN&)m=0BdwI7h` fr~y@52dFU=vf4`T(Nt}?d!;YZ_Y063+A#Dlg;nyK delta 801 zcmZ8fOH30%7@pa-+ZHIabW2}Lx4fjp2oxwO#wf(n7TOEO7oygNR4Bi4tQpF&YRLP9F8(!8Q$P)04({uK@!`X9~f@@9^#a{rmmj%0+5uPo`qI1(> zgdAiG$WG}brCv(ygj&jwfjkP*+rjZD;%HepJ%>ieg3)kb3WdT5^O|-k{eSq3rtSV` zQtT~&q5?EDzqPH}(nnp{`u?;+*kOT5Na~Z8chao!*u%=-EU0MsY3_*0^IFrgJ$^i; zd44J{97)Y2@5a1&-n!yVdQ+D(d`FJ&$?!d!wk&@-)}QB$318fouIpNx%yoM*-JZ17 zyTuLUb^P*B{E{za$AP@1DHTjcVxGKNSaBwuDSyUn&zYSWvvX6QHTT6_dCrg+j1Q)* zooiQf4tK`kP79tb&Rf&~zO%>ywI!{n-59A}g3yP5Xm!w!ceN+r5bomI;GK;Sr)EqS z$(Ob;1?A|}h#zozO z;l<%?MkljuO8{F{q}5IT>16>TNHBsf{BRvXVaS+l$2%3Tz!8vm7e>0~_J#p^|wWaUP+D=HJt*x1P^RY8;e((2wyK;86O5pd)=-18i zA|bzF=lIWs&P^!#5>%XU8k2;!X~NnpaoP?gKM>Bib3nKwSkK*e+9mEjB+b$*SWlXc z@w$8vANcLMwO9Bm*mKW_ zOWO0`?`czcn90uLyK-9$sv6B!0`}{AKUba2P>YsST&UM8ccS#M;Ef04;l_O&9{5^h zjWmzr!MD>H`#>Wu)@QPjZAQAG^YxBQGZl8SDBWm8>9$BSsdgK98seoh1rx@XDc~hC zVcbm-_Xp?Rd9H5Ul6jh$i$O;w{X7#vaa=I*IjH;9tSv>0vzBWK{rx5TPwJ@X2Wd9Tm4-%1E-&cqLGb0TcqxrL2F8i*8f5H zE%*=y+|$DM2#g^akwZeE?NPPJ0X!r&_IeEI{la@lfZ7G!f#AFXb54&zjjKwqs`|p| zIvX^iuzm*DH*15N-vO0m+5m=aM`8zPCMKkt#J5pUv8!Zar>CG;)~PZ$H&}^O3rPtW zVjJv4DVICO?Mjs>gamk#D+O$Add5w|1elra_Jyh7semE}QweRY*m!70+;~~2Hbgd9 zxuryyi4%Ea7P;t#d7O=T3TzPte;iZoE6H>41a_I3*jw4|Q74y4(^IS9n>vLRMo*n7 zT!kDHPcn5Ddf;zWq&in3kg&bwC5yN^k1OXUJHuuH?5-~06I9JZV+mPQOStyK0-wNM z_?^VYEv;1g%%hAkihr=E_nKA4J(zJ}%>R?UVP)_4!Q~^4{pbFVZg(&vC%+OHsL(j3 zKZhzK`#`559fEp3XM2v#*vg(ebbCxKLG9?Jt?E{F=m2%t;L81Np;W{Ll4mnac`O<- zSB)Z}PHI&*mOD*mN{N7onyPIezcSf$O-bi{q0C$`z5-|*q*`L?kq(Y!qy@iOD$xBH z99Ew|Wyu00Pz%s`NlhgPI&r9V5FCN8K7+YyP;?EddB=Bal)3Dw%LZqT06cO0Tlt6} zO~JYW9n43}!UJ+hLDa~Qo+f*2$kcL1GidkO$g%lK)p4yFxEG~C?0zRVe`9DoCzhk`V`MXKAHLi#NxrGW20rx9Sft?ObrqNN}OjwUz!;S zvZIP|bs6_UF;|#2>Px78gktYmcYW$Qb?UlM*x>a0{O#a{CO`BGMauFVzY#cae4D7R z0WbLeI73Fz=kyE)5&}13hjtF$Ru>=#oSvhu4xJ%nA)cp>!3Q%IDNr{3 z3Z=D>ysB|Tx^295C3mzio_G@JOcyM;3ag9*>x~!o`y%D)BOEDNKWy;ES!KNKFwTWG z(+`(IT5WEb*|CJbJ5b-imTf3{87kjdratxAJd_$;rR-^q4d#x*WlwIhN4J{`#t#B~ zAq0V`2Cy~HW3+2Qu$71Lc*X~*0E$GJ!pIu`ZkX - - - - purchase.order.form.inherit.subcontracting.inventory.move.first - purchase.order - - - - - - - - - - - - - - - - - - - - - - Subcontracting Inventory Moves - ir.actions.act_window - stock.move - list,form - [('location_dest_id.name', '=', 'Subcontracting Location')] - {'search_default_location_dest_id_name': 'Subcontracting Location'} - - - - - + + + + + purchase.order.form.inherit.subcontracting.inventory.move.first + purchase.order + + + + + + + + + + + + + + + + + + + + + + Subcontracting Inventory Moves + ir.actions.act_window + stock.move + list,form + [('location_dest_id.name', '=', 'Subcontracting Location')] + {'search_default_location_dest_id_name': 'Subcontracting Location'} + + + + + \ No newline at end of file diff --git a/views/stock_move_link_views.xml b/views/stock_move_link_views.xml index 5d36764..b6ac513 100644 --- a/views/stock_move_link_views.xml +++ b/views/stock_move_link_views.xml @@ -1,45 +1,45 @@ - - - - - Link to Purchase Order - - - code - -if records: - # Get the active purchase order from context - po_id = env.context.get('default_purchase_order_id') or env.context.get('active_id') - if po_id: - po = env['purchase.order'].browse(po_id) - for record in records: - po.link_selected_subcontracting_move(record.id) -# Close the wizard window -action = {'type': 'ir.actions.act_window_close'} - - - - - - stock.move.link.subcontracting.tree - stock.move - - -
-
- - - - - - - -
-
-
+ + + + + Link to Purchase Order + + + code + +if records: + # Get the active purchase order from context + po_id = env.context.get('default_purchase_order_id') or env.context.get('active_id') + if po_id: + po = env['purchase.order'].browse(po_id) + for record in records: + po.link_selected_subcontracting_move(record.id) +# Close the wizard window +action = {'type': 'ir.actions.act_window_close'} + + + + + + stock.move.link.subcontracting.tree + stock.move + + +
+
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/views/stock_move_views.xml b/views/stock_move_views.xml index 33d7d7a..02f2af8 100644 --- a/views/stock_move_views.xml +++ b/views/stock_move_views.xml @@ -1,43 +1,41 @@ - - - - - stock.move.form.inherit.subcontracting.inventory.move.first - stock.move - - - - - - - - - - - - - - stock.move.tree.inherit.subcontracting.inventory.move.first - stock.move - - - - - - - - - - - View Linked Purchase Order - - - code - action = record.action_view_linked_purchase_order() - - + + + + + stock.move.form.inherit.subcontracting.inventory.move.first + stock.move + + + + + + + + + + + + + + stock.move.tree.inherit.subcontracting.inventory.move.first + stock.move + + + + + + + + + + + View Linked Purchase Order + + + code + action = record.action_view_linked_purchase_order() + +