From da55c0a4e1ceca424ff8db717f8cb9106a53722a Mon Sep 17 00:00:00 2001 From: Mohammad Tomaraei Date: Wed, 9 Feb 2022 14:45:47 +0100 Subject: [PATCH 1/3] added a per-project record mapping interface on top of sync.link --- sync_record_mapping/__init__.py | 2 + sync_record_mapping/__manifest__.py | 24 +++++ sync_record_mapping/models/__init__.py | 2 + sync_record_mapping/models/sync_link.py | 42 +++++++++ sync_record_mapping/models/sync_project.py | 47 ++++++++++ .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 7992 bytes sync_record_mapping/static/src/js/debug.js | 35 ++++++++ sync_record_mapping/views/assets.xml | 10 +++ sync_record_mapping/views/debug.xml | 15 ++++ .../views/sync_project_views.xml | 58 ++++++++++++ sync_record_mapping/wizard/__init__.py | 1 + .../wizard/sync_record_mapping_wizard.py | 52 +++++++++++ .../wizard/sync_record_mapping_wizard.xml | 84 ++++++++++++++++++ 14 files changed, 375 insertions(+) create mode 100644 sync_record_mapping/__init__.py create mode 100644 sync_record_mapping/__manifest__.py create mode 100644 sync_record_mapping/models/__init__.py create mode 100644 sync_record_mapping/models/sync_link.py create mode 100644 sync_record_mapping/models/sync_project.py create mode 100644 sync_record_mapping/security/ir.model.access.csv create mode 100644 sync_record_mapping/static/description/icon.png create mode 100644 sync_record_mapping/static/src/js/debug.js create mode 100644 sync_record_mapping/views/assets.xml create mode 100644 sync_record_mapping/views/debug.xml create mode 100644 sync_record_mapping/views/sync_project_views.xml create mode 100644 sync_record_mapping/wizard/__init__.py create mode 100644 sync_record_mapping/wizard/sync_record_mapping_wizard.py create mode 100644 sync_record_mapping/wizard/sync_record_mapping_wizard.xml diff --git a/sync_record_mapping/__init__.py b/sync_record_mapping/__init__.py new file mode 100644 index 00000000..9b429614 --- /dev/null +++ b/sync_record_mapping/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/sync_record_mapping/__manifest__.py b/sync_record_mapping/__manifest__.py new file mode 100644 index 00000000..9946398e --- /dev/null +++ b/sync_record_mapping/__manifest__.py @@ -0,0 +1,24 @@ +# Remember to bump the module version every time you make a change! + +{ + "name": "Record Mapping for Sync Studio", + "summary": "Adds a more intuitive interface for managing manual record mappings between Odoo and external systems.", + "version": "14.0.1.0.0", + "category": "Extra Tools", + "author": "Butopea, " "Mohammad Tomaraei", + "website": "https://butopea.com", + "license": "AGPL-3", + "depends": ["base", "sync"], + "qweb": [ + "views/debug.xml" + ], + "data": [ + "security/ir.model.access.csv", + "views/sync_project_views.xml", + "views/assets.xml", + "wizard/sync_record_mapping_wizard.xml" + ], + "installable": True, + "application": False, + "auto_install": False, +} diff --git a/sync_record_mapping/models/__init__.py b/sync_record_mapping/models/__init__.py new file mode 100644 index 00000000..25dfa735 --- /dev/null +++ b/sync_record_mapping/models/__init__.py @@ -0,0 +1,2 @@ +from . import sync_project +from . import sync_link diff --git a/sync_record_mapping/models/sync_link.py b/sync_record_mapping/models/sync_link.py new file mode 100644 index 00000000..2c3425bc --- /dev/null +++ b/sync_record_mapping/models/sync_link.py @@ -0,0 +1,42 @@ +from odoo import api, fields, models + +RECORD_MAPPING_LINK_PREFIX = 'record_mappings_sync_project_' + + +class SyncLink(models.Model): + _inherit = "sync.link" + + sync_project_id = fields.Many2one( + 'sync.project', + compute='_compute_sync_project_id', + inverse='_inverse_sync_project_id' + ) + + @api.depends('relation') + def _compute_sync_project_id(self): + """ Matches the sync project record based on the relation field """ + for record in self: + if not record.relation or not record.relation.startswith(RECORD_MAPPING_LINK_PREFIX): + record.sync_project_id = False + continue + sync_project_id = self.env['sync.project'].search( + [ + ('id', '=', int(record.relation[len(RECORD_MAPPING_LINK_PREFIX):])), + ('active', 'in', [True, False]) + ], + limit=1 + ) + if sync_project_id: + record.sync_project_id = sync_project_id + else: + record.sync_project_id = False + + @api.onchange('sync_project_id') + def _onchange_sync_project_id(self): + """ Sets the relation field value when the user chooses a sync project via the dropdown """ + if self.sync_project_id: + self.relation = "%s%s" % (RECORD_MAPPING_LINK_PREFIX, self.sync_project_id.id) + + def _inverse_sync_project_id(self): + """ Nothing to do in this case, but it's required for the field to work """ + return diff --git a/sync_record_mapping/models/sync_project.py b/sync_record_mapping/models/sync_project.py new file mode 100644 index 00000000..0c6b7337 --- /dev/null +++ b/sync_record_mapping/models/sync_project.py @@ -0,0 +1,47 @@ +from odoo import api, fields, models + + +class SyncProject(models.Model): + _inherit = "sync.project" + + def _compute_record_mapping_relation(self): + """ The relation is a computed unique string to allow assigning links to a particular project """ + for record in self: + record.record_mapping_relation = "record_mappings_sync_project_%s" % record.id + + @staticmethod + def record_mapping_domain(relation): + return [ + '&', + ('system2', '=', '__odoo__'), + ('relation', '=', relation) + ] + + record_mapping_relation = fields.Char(compute=_compute_record_mapping_relation, copy=False) + + def _compute_record_mapping_ids(self): + for project in self: + record_mapping_ids = self.env['sync.link'].search( + self.record_mapping_domain(project.record_mapping_relation) + ) + if record_mapping_ids: + project.record_mapping_ids = [(6, 0, record_mapping_ids.ids)] + else: + project.record_mapping_ids = False + + def _inverse_record_mapping_ids(self): + """ Detects changes in record mappings to delete the records """ + for project in self: + record_mapping_ids = self.env['sync.link'].search( + self.record_mapping_domain(project.record_mapping_relation) + ) + record_mapping_ids_to_delete = record_mapping_ids - project.record_mapping_ids + if record_mapping_ids_to_delete: + record_mapping_ids_to_delete.unlink() + + record_mapping_ids = fields.Many2many( + 'sync.link', + compute='_compute_record_mapping_ids', + inverse='_inverse_record_mapping_ids', + copy=False + ) \ No newline at end of file diff --git a/sync_record_mapping/security/ir.model.access.csv b/sync_record_mapping/security/ir.model.access.csv new file mode 100644 index 00000000..f8114db5 --- /dev/null +++ b/sync_record_mapping/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_sync_record_mapping_wizard_user,sync.record.mapping.wizard user,model_sync_record_mapping_wizard,sync.sync_group_user,1,1,1,1 +access_sync_record_mapping_wizard_dev,sync.record.mapping.wizard dev,model_sync_record_mapping_wizard,sync.sync_group_dev,1,1,1,1 \ No newline at end of file diff --git a/sync_record_mapping/static/description/icon.png b/sync_record_mapping/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad931db70f5c87176934888ae6e5464586e47ee GIT binary patch literal 7992 zcmYj$cRZE<`~P(g$IKqtD>ET`q#P@|D0@U^*%IDKoFpTAm+X*DAv2DYm5`MgA~Hfq z9HZae=l9R|kNdtK_v75JabDMTJ+J5Ux}prPXi-tHQ2+pyj<&`%ZiBx=ve-I3|C} zaF^@xwBL5DX^s+!%kZ=x8P6ZrtBw{E95+~hWv5Qdq(N(Ru6z1fHTD z80kd(&k6f&Y`$eQ`<301c{9BIXz5US)AkO{pZ(y5pFsnMCo5OQ8yA!G{_o9rhp-+x zy}v{G+HB2Oai@$?vFfLyV)2Z{0eAl;iTk$>PYtX1>&s()5_(cjUmQ(o40y5<@wBJ2 zv;R_+W#QG~?;?P|2v`&_LT)`NlmOZBV5u4yX+fb;1(b)6h?0Vu%RYnFe3 z(Iv;K;&T`4(x%GWTjBsI5nwo(lc=Y}-}78aP*+0Xki#QUW@_ZU@)YCAn*P7B%EY+s zLw<+$hvc0;{g<>}mYJkA4rrzK1psIgL7_vE^~g$X?byZa0N=gFB<)P0CLP}&b%5oC z+*^?QK2H9tqQcklu8HMUnYwPN0FP%*t&||l0xA731-?)HcRRIaAYJ2~#IEjb@d{+0 zB=9{q{ny4kcdSj;gH~B_n>US=8sd;^PK5n(J!$A?N-h34%y@QUIgX(QS2@uCa(QRx z)(1AAzQ>w+Muo+T^Z4t2Ma{t5PU0vpavv%+UKIYgzwK7v?cb@J(s#(qxSl}a&PCoA^ z1x9u-{MN}Pk;CD!kDu7_e#$eyiRCxppS=tzH@XVGUD7IS?avFp9zZ#@)c3bHmR8`-B9nP`G-)5fel2vzy_`%i%0H?siVE^J#C{@;DlA^H#p; zmZ~=jVa8x1q_=kf9}Rdq$jNtPCq|-Dh;?$n2S809xUlv^y?lY ztSUr=$OL1+TJxVv-`Te7uywuT>7OXxHBCm}LX;fz+hFeaNlq6k_vC*4e=I?)Sj?1+A;aW67 zFwsAYI6ca4yNG6(a;1n##fu6`e)|-OECU@>8$LU zuZHetG~PEpH)c|dgSAfYmg_)cg-wSX6}2Nx6{Q^`F_eth6JC|kkV7fpJ_BA1@u+B` z;v~J};@{7Xi<|Z`pWE!V3p7&m2T(6%+mcB(j51m5q{b41$ph->DkAuT9E*cL#bM_L zE&HT{C(5lcTvgRwe~Zl&*}F|!O0dnE`89~6k#7))Ie!Wb6tZ9_{`+N0dF#k@d3NB- z;J^QAB#gi0F;!>eNeW@GzqWJk=VBQj@^^8MzMTdvJsQ3r&W62EaX(%9o2~9_*aJzP zrxz(em<;*>Y;)s;kWX)4ePo4rv` zpx^%IYwlfP-23W838l*RANBw*ON?M;^;c0{eB8sN5aGk4QonTq-tOP_sQ@4Rs2T$% zIvpi}E)i_bNbn%1pMKxy!0i6&#j4*icQ;mr`2(0WxC9T{WCqeoTU;hi;ZdJG27_O* zLqZ+~AKymtVc`X_PpHLzX^uC7Z?4yfj@5kY^>dd*<6^d$Vh)#>1lP^9tx$%3{>87v zVT%$B5ePuTqRnPyj;7SV2t5>g&)N4tr9g3-tDNY%ig2>UpElj#ru!B}CyNm(q)n@h(HToykChW|1E?%SYA z%&2JMC+;@PBCg?xobm&dq=Ia zJs1~dqM~kmYlJKBYq8BcBw1o9akrJdP~d#!Wuun(>{qKsrRaKZ=`{DHb7VjxjBsB5J0hm3{$B&nqieu2__Ls5%g8%w+*;S zEFb*YbOXt9w@}s2Vi#0yQR(fz7yBd`i-9{v;R!?wu@kQrVr`RRo=v0&Qp0#OU>j$R zak7J|VE z1Yb(N#)p*kKL2tH28$)rTi0G%{%ou5yTT`G-To{h_Zg4Rc^pu)Qe~q5Etdi?f0B3Zb0xns@3F{*oYq^9gtn%CNnXxR?Q@&? z-L$qrSg-`f`ew3pi#gl{ykCsy)2T}xyRIJw zy7Z+^{``sRWQh?~SlcD*5Q^$34|&-(Z1I;45~6`8-tiJm*uk1v`wy-2{X0#sN8fd| za-q%D{>}#fg8QD+*R!_N zmm5PJ3KWY%Uc^ZRU~=9ygi7~Ql>~;sH2N}LY>s+~d5#v&dSY^T;|Ck>DJZy_m-k*ZikwcF7-2Sx_FQOA3LIN$bN%)24pvT{W?xPno$o4HO1vp1{i3{S z!0&=UD+(NMTDJ>DY%rBu29=7#&6B$wu_t{ZDWWXUZNGdmctUIChr$9oV9)k4WlBZr z>TqgbB-yXyB5ZtVUaQKxLF7h(8_KI7DMbXyHp zbEW#|pjXCzvftxxm)XCPKqU_t9z#?*f&E6$ia}lLbhNHkFoi!o zxMp5YE>my2RN6xm=0fzm;?v9mfBo040pS+t%#|q4w!ym{g zB+Qf&P_!`pl6iP0Had3HGVY@6&>$CRt3oaTmGt`1@bvj;Rc0+ByYTL66t(Qp^W}sC zV#C$@=Idx+d|}=GB7maIsB039HKb*a^ue6g5-+R>#+B>7yhtTRAHnXKYu*0z`+K1|I1}FW>kr%4Nn%9z zNnq~wz`YV(Hs^f`(B_A^?iq1H$Wp){sR9RXJLC|}*QE=)wEhym<#CCgL1Kf?(uh>(tBHz5i9VAq21ic}h>Si~#$muRvEt-2#*J%QFf%j0uix^6I z7yC7yZK_z%>&_~dqVe*XRcq{>f#v1{Uo{&-Q>jj3J9`Ma`ED`u;MH?6D6I1pFIU{yt1CovkMv$! z9sJB?@yTrBs>Y@>IDL_S*vrN$rc4AZD4=}D7`W+@Mx#+qLLxTNH>1@MDh4=7g#>{+ z%E@PM7R;{@UsbpJM)nBvi_JV?B3(^9TagM(xR+8kXtN8{LomiFR1)02Ct zx3g~7B!egCEA0Y*vZZzZa*zI|#YRBE<479SKY+_?SjeKlt9O;GL4%FDgS!$hI(9-_ zdFPmVp0<<8I#p;Zq;k$~&k%3fpBHk#q$Jy0&G<{CLE!EBf&`r8d`(fnjivI_Fo0gfDy_W8S`;P)9PT z8-u{5I9eP-@Xhj3L5BM)I>3YTj_Fj=ufV5SEPbpHzj#BY_iG0KuN)$XGDRmeAZ)hr z#ej}p9TkX)rW01uyCca}{&KuGMZ8R;c5Weh>8gj44%&cjUmkGNXQA7Mx&Q6_4`0<1 zC0O*!&zRXP9vDNa5=F_M^V&8_*fq!lh*HO>r)^kEBi!djatc3EOB^W0E~ubDiWVFJ zMrW^>P)$(ae~J^*0xqmcuX|9+J8aCl@ZR9%*xYQ=9aR_gIMukTnX$fgc4C;dl@q+n z=%K#lj6(kLy|@H1So9zLyR%nMaEv)4+>0!mDjT2>_i(P3ingWnez6O#bF7-dwy>M} z!9L;H{2Bl!qMVs<_Y$q&g?d;=XeOGZ2l>=$qZ;NbL#RL@`c>EmRoYQrL?ji|`|S(N z+I*_{-bNSujG=IYUKc?zPilh`LW}hoOwzKUb?Kkb2Bq7p-hDBsa90rD;NuG^%fAy2^xk2*0Fyo{GKhL#Xv~ z!c@mVZ-i22VorBaBGZ!$r)zG+A515?f;nMOKTZ}FcZ+VcO-D~g`Cw+xxpM357CEQ# zwA-$7x$YZ_jClQRTYcSQdT8mCVTFQ;NCKo$>qyOr81XeVjWFxf7=*|V$g$R0cCJ5n z%*^xCHvz}J!tD0c$VSqthXq9r*iRtZDn+A~)edgL%Fm2Q@DGxa4v=!N?h52@+MwC+rbdub7z%QoE4Nkf_!M z?%i&hrUUJcyVQlvSxMQE{jAeL1jUonmhok@Y7|&R09^teBvf4=;4<#VJ|>QT*sb+1 zwWO_(xnhEo#2ZmCgTh%o?awQlzN+0Xkq|>ygYyI^FD}(M#S4vyl5efGZjpmOo_?b= zWuK$o^qrXa!SCU`KYvU5dGc2+D+OXysIES+Pfzr=+#8` zHsMBxcy9FiDd=Yo-gK6~`1y^0bBU&Z$|_jqt6#v4h`zs@B-y5)wpyo?CIlc5NiX^M zV!Vztr|iqs?uN*dsJ$Y}irXBwg%BBxn`qof>|ZPY%GX>A@8gwPh$0(CMd5r|i%)@R zERSEn7Fw&X%XB4u(DzjIt?0Te^`C&1g!AjJ@udcQ)ajLds9K60{ajOqXT)BlrYb%4 zDx&hlP(%ce$>7{Eb@Z9TE~Wa!T~qF+jW&mucSo+Cqtnf&v4b+t{eT<-W%>@(yuoN?h`{M=G;ElbYvrJSF2w1lMIi zSa&BkR3hk)qaO_d3xDh?iCtwA|CDj9gxpc#eR~Sl|NlG_XZD`#S)qmvk)qUhq$tIl zuMzWM(O@(0^big62W?a&_w9YG2lroLAQAM)ZN0oFFmBQ$MQSKR5*jV``V)6@%*4*q z5n_l``$9%9j)-*Xhdlha+l`*G$>Ak*j83~n+$-K{!I<-i(AyNGmMw|DUN&Ewv=m7*< zkO9{_H;QizcT-@9YYaj|$9JBxsV<*MAIvx;@xaW{2x;$KpzT4Zg4tI8z>rh^(9SW< z6C?vG=r0dSFTA1DFiY>XWO~<1&(fFOIYOq?IvSy>RA2+j{M!4=sl3IG9WRgIHEz;YHXFa_5I+=i1Ki9Wbp;WC4~Oja%Ge(oemRVGXy)=x0sM zT33i~QWUmb5j=b?@0hbs4hiuhbPSR@-zp|&+k%MxlzXu>lV9f(RO!okwfge|2GkOc z`f0xyRnAond{q6}->ZQ^s=RLiOI_r9Ys5IN!}IrzrYN^{hW;o7a3=D~p3047CsRV$ zU5mmS=&LX%_l_x(2KIw}FAFwtB6d~>oU;D1;osXFRV&7pEswpBDDApS{g#~`e~M3$ z8|M6Au9Om}>iT4w>w0BqNZ<)=rCpux4+%~NfwBsx?9cXDpPL`I0#>|KqwgvQw{q4z z_p3Cq>36c`wT~$^(jv+2y((=w_QUvYw9%SCkMu3<$ zOMTN{Nz6ci)pu9?)y8<%yOGTR9yj8d9Mzo~myF)Ck^QrsU#wW#KbhC2HpdIoy%;0Q zI0dv7ZF;`?*HO4;GWG7Dq*o_f1R0wXj00u;-Kg~N#5hIIi1TdM&vZ+Dd_Q0s;u*{@ z?=UadA6iORs}#nmN@#v;`{U-2^<*egJn7PxqZbQ5p8q|8X{3Ym>>#Xhms)HiP?v4; zXMz5%Kfpe~0b*HAUlDN@K=X0x7BLu zPi^xi=*-o{#$k!P3rOqY9wIEN-PnExk!~jE`@4K^LqQ_qMfHcA%!y)awK7r5>;NQy z4+T6LexM*&Bf!@>GFWWa6VBUeo^!ZHS7{fGv?pejhc#-c=ZDl+Q-t55z`d&>^!i16&3yYf zgkC*&uG=D8W7jI3T>mJ8z_iYXhR^_AUwsX|Y4O{|dZFXQ|EmowkRFSle3|@}aE#_t zD9aI*BS>z#Z#&T=;!^*n__4<6`eG9_+#rECJEe$hZniUWbSz>gS+OBhV2bofkcjHrdTXD$6u%0zZ1@)XH%}%aRyYC^5h2WKW5Z_{zi>?& z=1w8s#kkbsDlDBvp&hlZw`MARh^*?1NZRhzjU*~GDD5ip&8Rkn>RsMoernVlwrtcj zg~m_HuJ5!zJXbG{6G1A?5tjM^cl%;&0`(EN`vkcAh%pwOj1TZ}O8h0rv?41z3 z7`#ZIajW^co$lhP;)>=S4)03<{~%1X;lJ1263=^g{Jh~D)$%IA zeKGCO(=Hm(U_mhF;xaHQ5C)(Exh(S(;>4hwkfna6Ax=-;=TXqRMm1!(0zb}TWnHl; zEYYQQkQU5|fsxm`9ivjC9AQr7nC`wrLHA}Wzs_yEu>GNeqqiNc8??ks>v zDkPPh2^~{-<58~XKQcZWMws2CeKTI-d&?1TnN|#M^y;t+!Av=5=v%eI#r~^dwpCI) zb53qe3XmdY$NdX{pCrT0araKv)=d{$7LdQ*+SZ7Q7a+o2SUla?G`9O!7*Q})C?KsM zp6lMGvcB$;Q={iU#`rLV6(Xz9xZ#iQ6u;P>aGMM(w6a1%4Dc|4x7garXW6WI6=E1V zi%QtwY?lq#Yiu+o%IK%?1UwRFCyk6|WWZrw9qUFl-_l9>f7{APmsvLdFA<`oiz5>o Se + + Manage Record Mappings + + + + diff --git a/sync_record_mapping/views/sync_project_views.xml b/sync_record_mapping/views/sync_project_views.xml new file mode 100644 index 00000000..615eb071 --- /dev/null +++ b/sync_record_mapping/views/sync_project_views.xml @@ -0,0 +1,58 @@ + + + + sync.project.form.inherit.record.mapping + sync.project + + + + +

+ + You can create record mappings once you save the form. + +

+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+
+
+
+
+
+
diff --git a/sync_record_mapping/wizard/__init__.py b/sync_record_mapping/wizard/__init__.py new file mode 100644 index 00000000..b0c91b8a --- /dev/null +++ b/sync_record_mapping/wizard/__init__.py @@ -0,0 +1 @@ +from . import sync_record_mapping_wizard diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.py b/sync_record_mapping/wizard/sync_record_mapping_wizard.py new file mode 100644 index 00000000..0781fb54 --- /dev/null +++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.py @@ -0,0 +1,52 @@ +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +class SyncRecordMappingWizard(models.TransientModel): + _name = 'sync.record.mapping.wizard' + + res_model = fields.Char('Odoo Model') + res_id = fields.Many2oneReference('Related Document ID', model_field='res_model') + + @staticmethod + def record_mapping_domain(res_id, res_model): + return [ + '&', + '&', + ('system2', '=', '__odoo__'), + ('ref2', '=', str(res_id)), + ('model', '=', res_model) + ] + + @api.depends('res_model', 'res_id') + def _compute_record_mapping_ids(self): + self.ensure_one() + if not self.res_model or not self.res_id: + raise UserError(_('Invalid model or record.')) + record_mapping_ids = self.env['sync.link'].search( + self.record_mapping_domain(self.res_id, self.res_model) + ) + if record_mapping_ids: + self.record_mapping_ids = [(6, 0, record_mapping_ids.ids)] + else: + self.record_mapping_ids = False + + def _inverse_record_mapping_ids(self): + """ Detects changes in record mappings to delete the records """ + self.ensure_one() + record_mapping_ids = self.env['sync.link'].search( + self.record_mapping_domain(self.res_id, self.res_model) + ) + record_mapping_ids_to_delete = record_mapping_ids - self.record_mapping_ids + if record_mapping_ids_to_delete: + record_mapping_ids_to_delete.unlink() + + record_mapping_ids = fields.Many2many( + 'sync.link', + compute='_compute_record_mapping_ids', + inverse='_inverse_record_mapping_ids', + store=True + ) + + def action_done(self): + return {} diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.xml b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml new file mode 100644 index 00000000..ea39b41a --- /dev/null +++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml @@ -0,0 +1,84 @@ + + + + sync.record.mapping.wizard.form + sync.record.mapping.wizard + form + +
+ + + + + + +
+
+ +
+
+ + sync.record.mapping.ids.tree + sync.link + primary + + + + + + + + + + + + + + + sync.record.mapping.ids.form + sync.link + primary + +
+ + + + + + + + + + +
+
+
+
From 9c96304d841d68ff65a454656dd745543f5aa832 Mon Sep 17 00:00:00 2001 From: Mohammad Tomaraei Date: Wed, 9 Feb 2022 16:39:43 +0100 Subject: [PATCH 2/3] removed sync_project_id restriction on links for more compatibility --- sync_record_mapping/__init__.py | 1 - sync_record_mapping/__manifest__.py | 1 - sync_record_mapping/models/__init__.py | 2 - sync_record_mapping/models/sync_link.py | 42 -------------- sync_record_mapping/models/sync_project.py | 47 --------------- .../views/sync_project_views.xml | 58 ------------------- .../wizard/sync_record_mapping_wizard.py | 6 +- .../wizard/sync_record_mapping_wizard.xml | 24 ++------ 8 files changed, 8 insertions(+), 173 deletions(-) delete mode 100644 sync_record_mapping/models/__init__.py delete mode 100644 sync_record_mapping/models/sync_link.py delete mode 100644 sync_record_mapping/models/sync_project.py delete mode 100644 sync_record_mapping/views/sync_project_views.xml diff --git a/sync_record_mapping/__init__.py b/sync_record_mapping/__init__.py index 9b429614..40272379 100644 --- a/sync_record_mapping/__init__.py +++ b/sync_record_mapping/__init__.py @@ -1,2 +1 @@ -from . import models from . import wizard diff --git a/sync_record_mapping/__manifest__.py b/sync_record_mapping/__manifest__.py index 9946398e..72cdef93 100644 --- a/sync_record_mapping/__manifest__.py +++ b/sync_record_mapping/__manifest__.py @@ -14,7 +14,6 @@ ], "data": [ "security/ir.model.access.csv", - "views/sync_project_views.xml", "views/assets.xml", "wizard/sync_record_mapping_wizard.xml" ], diff --git a/sync_record_mapping/models/__init__.py b/sync_record_mapping/models/__init__.py deleted file mode 100644 index 25dfa735..00000000 --- a/sync_record_mapping/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import sync_project -from . import sync_link diff --git a/sync_record_mapping/models/sync_link.py b/sync_record_mapping/models/sync_link.py deleted file mode 100644 index 2c3425bc..00000000 --- a/sync_record_mapping/models/sync_link.py +++ /dev/null @@ -1,42 +0,0 @@ -from odoo import api, fields, models - -RECORD_MAPPING_LINK_PREFIX = 'record_mappings_sync_project_' - - -class SyncLink(models.Model): - _inherit = "sync.link" - - sync_project_id = fields.Many2one( - 'sync.project', - compute='_compute_sync_project_id', - inverse='_inverse_sync_project_id' - ) - - @api.depends('relation') - def _compute_sync_project_id(self): - """ Matches the sync project record based on the relation field """ - for record in self: - if not record.relation or not record.relation.startswith(RECORD_MAPPING_LINK_PREFIX): - record.sync_project_id = False - continue - sync_project_id = self.env['sync.project'].search( - [ - ('id', '=', int(record.relation[len(RECORD_MAPPING_LINK_PREFIX):])), - ('active', 'in', [True, False]) - ], - limit=1 - ) - if sync_project_id: - record.sync_project_id = sync_project_id - else: - record.sync_project_id = False - - @api.onchange('sync_project_id') - def _onchange_sync_project_id(self): - """ Sets the relation field value when the user chooses a sync project via the dropdown """ - if self.sync_project_id: - self.relation = "%s%s" % (RECORD_MAPPING_LINK_PREFIX, self.sync_project_id.id) - - def _inverse_sync_project_id(self): - """ Nothing to do in this case, but it's required for the field to work """ - return diff --git a/sync_record_mapping/models/sync_project.py b/sync_record_mapping/models/sync_project.py deleted file mode 100644 index 0c6b7337..00000000 --- a/sync_record_mapping/models/sync_project.py +++ /dev/null @@ -1,47 +0,0 @@ -from odoo import api, fields, models - - -class SyncProject(models.Model): - _inherit = "sync.project" - - def _compute_record_mapping_relation(self): - """ The relation is a computed unique string to allow assigning links to a particular project """ - for record in self: - record.record_mapping_relation = "record_mappings_sync_project_%s" % record.id - - @staticmethod - def record_mapping_domain(relation): - return [ - '&', - ('system2', '=', '__odoo__'), - ('relation', '=', relation) - ] - - record_mapping_relation = fields.Char(compute=_compute_record_mapping_relation, copy=False) - - def _compute_record_mapping_ids(self): - for project in self: - record_mapping_ids = self.env['sync.link'].search( - self.record_mapping_domain(project.record_mapping_relation) - ) - if record_mapping_ids: - project.record_mapping_ids = [(6, 0, record_mapping_ids.ids)] - else: - project.record_mapping_ids = False - - def _inverse_record_mapping_ids(self): - """ Detects changes in record mappings to delete the records """ - for project in self: - record_mapping_ids = self.env['sync.link'].search( - self.record_mapping_domain(project.record_mapping_relation) - ) - record_mapping_ids_to_delete = record_mapping_ids - project.record_mapping_ids - if record_mapping_ids_to_delete: - record_mapping_ids_to_delete.unlink() - - record_mapping_ids = fields.Many2many( - 'sync.link', - compute='_compute_record_mapping_ids', - inverse='_inverse_record_mapping_ids', - copy=False - ) \ No newline at end of file diff --git a/sync_record_mapping/views/sync_project_views.xml b/sync_record_mapping/views/sync_project_views.xml deleted file mode 100644 index 615eb071..00000000 --- a/sync_record_mapping/views/sync_project_views.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - sync.project.form.inherit.record.mapping - sync.project - - - - -

- - You can create record mappings once you save the form. - -

- - - - - - - - - - - - -
- - - - - - - - - - - - - - -
-
-
-
-
-
-
diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.py b/sync_record_mapping/wizard/sync_record_mapping_wizard.py index 0781fb54..e77fb9e3 100644 --- a/sync_record_mapping/wizard/sync_record_mapping_wizard.py +++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.py @@ -37,6 +37,7 @@ def _inverse_record_mapping_ids(self): record_mapping_ids = self.env['sync.link'].search( self.record_mapping_domain(self.res_id, self.res_model) ) + # TODO: Could this possibly cause a race condition? record_mapping_ids_to_delete = record_mapping_ids - self.record_mapping_ids if record_mapping_ids_to_delete: record_mapping_ids_to_delete.unlink() @@ -46,7 +47,4 @@ def _inverse_record_mapping_ids(self): compute='_compute_record_mapping_ids', inverse='_inverse_record_mapping_ids', store=True - ) - - def action_done(self): - return {} + ) \ No newline at end of file diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.xml b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml index ea39b41a..f6aae9f3 100644 --- a/sync_record_mapping/wizard/sync_record_mapping_wizard.xml +++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml @@ -17,6 +17,7 @@ domain="[ '&', '&', + ('system1', '=', '__external__'), ('system2', '=', '__odoo__'), ('ref2', '=', str(res_id)), ('model', '=', res_model), @@ -24,16 +25,13 @@ context="{ 'tree_view_ref':'sync_record_mapping.view_record_mapping_ids_tree', 'form_view_ref':'sync_record_mapping.view_record_mapping_ids_form', + 'default_system1': '__external__', 'default_system2': '__odoo__', 'default_model': res_model, 'default_ref2': res_id }" /> -
-
@@ -43,13 +41,8 @@ primary - - - + + @@ -65,13 +58,8 @@
- - - + + From bbd53326143e0b66b0237421909233c9b9e103f7 Mon Sep 17 00:00:00 2001 From: Mohammad Tomaraei Date: Wed, 9 Feb 2022 16:55:07 +0100 Subject: [PATCH 3/3] removed the Create button from the wizard --- sync_record_mapping/wizard/sync_record_mapping_wizard.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.xml b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml index f6aae9f3..1c5f4aeb 100644 --- a/sync_record_mapping/wizard/sync_record_mapping_wizard.xml +++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml @@ -5,7 +5,7 @@ sync.record.mapping.wizard form - +