From a13e7af0f68ce06221a5899a81105bba454b2177 Mon Sep 17 00:00:00 2001 From: "admin.suherdy" Date: Wed, 17 Dec 2025 15:50:16 +0700 Subject: [PATCH] first commit --- __init__.py | 1 + __manifest__.py | 18 ++++++ __pycache__/__init__.cpython-312.pyc | Bin 0 -> 225 bytes models/__init__.py | 2 + models/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 275 bytes models/__pycache__/sale_order.cpython-312.pyc | Bin 0 -> 586 bytes .../sale_order_line.cpython-312.pyc | Bin 0 -> 3334 bytes models/sale_order.py | 6 ++ models/sale_order_line.py | 58 ++++++++++++++++++ 9 files changed, 85 insertions(+) create mode 100644 __init__.py create mode 100644 __manifest__.py create mode 100644 __pycache__/__init__.cpython-312.pyc create mode 100644 models/__init__.py create mode 100644 models/__pycache__/__init__.cpython-312.pyc create mode 100644 models/__pycache__/sale_order.cpython-312.pyc create mode 100644 models/__pycache__/sale_order_line.cpython-312.pyc create mode 100644 models/sale_order.py create mode 100644 models/sale_order_line.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..7bfdaf9 --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,18 @@ +{ + 'name': 'Sale Order Tracking', + 'version': '18.0.1.0.0', + 'category': 'Sales', + 'summary': 'Track changes in Sale Orders and Lines', + 'description': """ + This module tracks: + 1. Customer changes in Sale Order. + 2. Product and Quantity changes in Sale Order Lines. + 3. Addition and Removal of Sale Order Lines. + """, + 'author': 'Antigravity', + 'depends': ['sale_management'], + 'data': [], + 'installable': True, + 'application': False, + 'license': 'LGPL-3', +} diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a295ffa22545f5947ee71d8c7bcab519f1c2714d GIT binary patch literal 225 zcmXwzF=_)b5Jfe+V2r`wB00o167F1t5PX1;Iz@!65nhp%#z?z`PLea^EV+S;G_KqQ zw%aPRVE<;`|M2vjq%O_qQI`^EGJU4%nXZWiD;8#4P1)G0y$2->m literal 0 HcmV?d00001 diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..2d7ee6c --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,2 @@ +from . import sale_order +from . import sale_order_line diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b51a98621175ecab20a4f14c9f566af474d0b511 GIT binary patch literal 275 zcmYk0F-`+95JhKpBLP7XEk!uMHfyB{1ws)AK-6h0V_U2h+Y{Nlg-?<*a29S52^uQ8 zNa<2BD}i8&KmU!s^yh6hn*z_mJ-8+B&k=s7`Z32jn;jT1=po=5ar71YYF#0ex|w_- zM;hEuv+`C_GBzUTWQCIz9R(}$(Ai{4Ta>2fRZv?MTTQJq z;;HlF*B@|`&X~Ue10qWq literal 0 HcmV?d00001 diff --git a/models/__pycache__/sale_order.cpython-312.pyc b/models/__pycache__/sale_order.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5deb88f474b4e32b46695db3a6b46bbb0dd16508 GIT binary patch literal 586 zcmYjOJx{|h5IrYp2vzwK5+E^@fu&0V48VX8VgVuXA;FZzGO?k7#4b)cgb5^8B$)aa zK=4mk8Bi9GnAngC3lnzI3Ot%fErgoO@>bFKIw0NFiY%PnboL#=%iufb}T51lH5KDSwxfIuOFaCfbOEI zc7TD8DEJ0NzG(onP710237`Z#nh&U~`L-UE5AKtQ?Mlkzc{Nec6&fEjQ0}CX1g9ZC z-f0Zv4#u3s4CB0tu@cpeG_GNM)+SN!#K9qNG8v}QQX_I_oA7KwaF$nFM5dfc9MXH} z>hV9vUQ@)(OWKM+GdClFI9!WKi*Pp(Zb-eoENu!NsONiv3NgRz1??miF`-oO#M4r7 zAr<#!dZkzYj@(uzwbez?b|sT4T*1r8^u^}e*v!pDr+!<%n|&VhF1O@JzjH^~V(Fn$ zbIQk5w)IDpw+-uR(LJirkF!$xu`0(^s@+YdRQNOzLa$K&vP?90V|Qw|wQo?cVEzKL C=#UKn literal 0 HcmV?d00001 diff --git a/models/__pycache__/sale_order_line.cpython-312.pyc b/models/__pycache__/sale_order_line.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a4992b878cacd7d17fdb909b9038ba87bb843f6 GIT binary patch literal 3334 zcmbVPO>7&-6`t82{)v=m{nAw`Gpa0_azfg&9a)NMIF1^pwyMUm;{y?Sz2dH9QY2U2 zU0Nowgay<)EsjR(95pmfW)Fe1+<6urdlfM_|!MM6eTfC z4;_HBGxKKNdo%OCZyx{b^LY@I;l#N_yBnduk9#!ApJtgRH^HHQM7RaMm!}Tc-xPAfX?z1*Wl`WXtzg zXv~+)j;9zcU15+$k#m{Id&zkOc|j0`k>E>b@W>@KHxe{)_zP?@(~^)2yG&Ne&Wp0_ z1ihvsE{nV>nl9_`xP)MO=4DC9##Pex3JGOC#pk#TpBBxQ9Z6P7b2rtT=}n7@!q1A_ zyrigMhsh{nYQ}Wm;!_HjN+_zylFLv`hI~vqt<0Kkj*F*wMd3JwoN17h#h0n*4Jj=~ zmFx{s7IKjsAD5=jrulh36NyWagb;l%r{0h>;BOq zTWLS|95L=w#j#3D+iwfME^Gw)N>^67$6WdFTgKtH^uBXnhra16U$|ymxTgP{)4A(< zC%;Tr{Ov2gk9=kSfZ-o_O6&fCZ~Z4X-JogHgZv#u?-m$D`$CpnjTN#<2+#-kLkQXg zDgb~4YL+U{YBfj!I2eEfFwy8Sv;&@r_p5QOj%2w_HJh^G1iqfGr6LIU%92!4MZ&zBIrfwHEYh4bA|eZiMdbLWs5O8&&%av}x2W1Tbp-A!`T0TEQXUd-xWTuQuL8 z!KuLvYo<$cY0kMJgygdVtGSZop6kkOtWX#U4uG6fbN=rckC=iRZ2Id|KsVX;{V~n` zrEBNp!2(5mhP^E|KI4K1yrwL#o3tj)L%fFBD+00D;HDaR3VZNqP1a64pP)yM|KHoC zbs!KH2&8F3Cfk);p^Ddn3_2tjPrz@hAF2oVBErDy8k&MIC}0iWgNytfUctac9tP#m zALs=f#uHzV_kxNXGx3bc5LQr#9ss=jBlx~_kIsr2@%FrYCf~mwjSF%@6(gf5DGrOy zL~8RoVVTka)r)@+h^{q9A6_cnTpnA>8O_n}6cWt8YCeF&)b2L&2j8>#EEvDRXJ$nq zC}o0#34j%u2?-t#Ciwc9pbYGf@*S75d`3;Ex!U9zNep-fYT< z3tW|N%_cHj?Z^R384(i-b`lXZWD-jX@h5m4D79MbgOj#F4j*a%fbJXhosZF2@_ZA+8 z)>>YzboZ7{t`0pOGP;j0yEYxDJy<$vw1q0RmF0_--ht0Yjo#DH>gp}ct#uu*1c$#m zS{|7+Mkd!rKG3gzpbt;!Q@lQ%E>Gu;>HKpNy+5Ni5xQf4rtv$Zcj!FzkcNGH>igJN z4h$NB!LMjNF!(GmO3WVqoLOsot=TUsr<&I@y4Wn>au?Mef{c`{{A)n+O!@|>eF+2PpXlXZ^6o8*!|`aE*baSw2NFG3dFtL2=*wiIrmvcL#l=*LG(y z_h8%VA)^Ea_H*DGwfA~P9)>aEm_me`G{*R^sLw!s+sqI?vHZ@;_($XaM$oht{})6_ B?fC!z literal 0 HcmV?d00001 diff --git a/models/sale_order.py b/models/sale_order.py new file mode 100644 index 0000000..c341263 --- /dev/null +++ b/models/sale_order.py @@ -0,0 +1,6 @@ +from odoo import models, fields + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + partner_id = fields.Many2one(tracking=True) diff --git a/models/sale_order_line.py b/models/sale_order_line.py new file mode 100644 index 0000000..3716867 --- /dev/null +++ b/models/sale_order_line.py @@ -0,0 +1,58 @@ +from odoo import models, fields, api + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + @api.model_create_multi + def create(self, vals_list): + lines = super(SaleOrderLine, self).create(vals_list) + for line in lines: + if line.order_id: + # Log creation + msg = f"Line added: {line.product_id.display_name} (Qty: {line.product_uom_qty})" + line.order_id.message_post(body=msg) + return lines + + def write(self, vals): + # Capture old values for tracking + changes = {} + track_fields = ['product_id', 'product_uom_qty'] + + # Only track if relevant fields are being modified + if any(f in vals for f in track_fields): + for line in self: + changes[line.id] = { + 'product_id': line.product_id, + 'product_uom_qty': line.product_uom_qty, + } + + result = super(SaleOrderLine, self).write(vals) + + for line in self: + if line.id in changes: + old_data = changes[line.id] + + # Track Product Change + if 'product_id' in vals: + new_product = line.product_id + old_product = old_data['product_id'] + if old_product != new_product: + msg = f"Product changed on line: {old_product.display_name or 'None'} -> {new_product.display_name or 'None'}" + line.order_id.message_post(body=msg) + + # Track Quantity Change + if 'product_uom_qty' in vals: + new_qty = line.product_uom_qty + old_qty = old_data['product_uom_qty'] + if old_qty != new_qty: + msg = f"Quantity changed for {line.product_id.display_name}: {old_qty} -> {new_qty}" + line.order_id.message_post(body=msg) + + return result + + def unlink(self): + for line in self: + if line.order_id and line.product_id: + msg = f"Line removed: {line.product_id.display_name} (Qty: {line.product_uom_qty})" + line.order_id.message_post(body=msg) + return super(SaleOrderLine, self).unlink()