From 69dae009ffb44e928ada8b44a43acb56d3e14290 Mon Sep 17 00:00:00 2001 From: "david.beal@akretion.com" Date: Fri, 24 Apr 2015 12:52:37 +0200 Subject: [PATCH 01/23] module product_profile_exemple --- product_profile_example/README.rst | 52 ++++++++ product_profile_example/__init__.py | 22 ++++ product_profile_example/__openerp__.py | 43 +++++++ product_profile_example/product.profile.csv | 20 +++ .../product_product_data.xml | 24 ++++ product_profile_example/profile.py | 46 +++++++ .../static/description/akretion.png | Bin 0 -> 9649 bytes .../static/description/field.png | Bin 0 -> 60208 bytes .../static/description/icon.png | Bin 0 -> 3655 bytes .../static/description/index.html | 117 ++++++++++++++++++ .../static/description/list.png | Bin 0 -> 21858 bytes 11 files changed, 324 insertions(+) create mode 100644 product_profile_example/README.rst create mode 100644 product_profile_example/__init__.py create mode 100644 product_profile_example/__openerp__.py create mode 100644 product_profile_example/product.profile.csv create mode 100644 product_profile_example/product_product_data.xml create mode 100644 product_profile_example/profile.py create mode 100644 product_profile_example/static/description/akretion.png create mode 100644 product_profile_example/static/description/field.png create mode 100644 product_profile_example/static/description/icon.png create mode 100644 product_profile_example/static/description/index.html create mode 100644 product_profile_example/static/description/list.png diff --git a/product_profile_example/README.rst b/product_profile_example/README.rst new file mode 100644 index 00000000000..c874bc1724a --- /dev/null +++ b/product_profile_example/README.rst @@ -0,0 +1,52 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +Product Profile Example +======================= + +This module is a use case of **Product Profile Example** module. + +See its description. + + + +Configuration +============= + +Optionnaly: + +* Settings > Configuration > General Settings: check 'Display Profile fields' and apply + (only if you want display hidden fields) + + + +Usage +===== + +Create or modify a product template or a product variant. Assign a value to the profile field. +Then, all fields which depend on this profile will be set to the right value at once. + + + +Credits +======= + +Contributors +------------ + +* David BEAL + +Maintainer +---------- + +.. image:: http://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/product_profile_example/__init__.py b/product_profile_example/__init__.py new file mode 100644 index 00000000000..0993b5c4a3d --- /dev/null +++ b/product_profile_example/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: David BEAL +# Copyright 2015 Akretion +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import profile diff --git a/product_profile_example/__openerp__.py b/product_profile_example/__openerp__.py new file mode 100644 index 00000000000..494c24e1901 --- /dev/null +++ b/product_profile_example/__openerp__.py @@ -0,0 +1,43 @@ +# coding: utf-8 +############################################################################## +# +# Author: David BEAL +# Copyright 2015 Akretion +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Product Profile Example', + 'summary': 'Product Profile Use Case', + 'version': '0.2', + 'author': 'Akretion', + 'maintainer': 'Akretion', + 'category': 'product', + 'description': 'see Product Profile module', + 'depends': [ + 'product_profile', + 'purchase', + 'point_of_sale', + 'mrp', + ], + 'website': 'http://www.akretion.com/', + 'data': [ + 'product.profile.csv', + 'product_product_data.xml', + ], + 'installable': True, + 'license': 'AGPL-3', +} diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv new file mode 100644 index 00000000000..96bd952d7ec --- /dev/null +++ b/product_profile_example/product.profile.csv @@ -0,0 +1,20 @@ +"id","name","description","type","sale_ok","purchase_ok","available_in_pos","route_ids/id" +"own","My Own Type Saleable","- My own type +- Saleable product +- Not purchasable","product",1,0,1,"purchase.route_warehouse0_buy" +"consu_prof","Consumable","- Consumable","consu",1,0,0,"purchase.route_warehouse0_buy" +"pos_pu_prof","POS & purchase","- Product in POS +- Product purchasable","product",1,1,1,"purchase.route_warehouse0_buy" +"manuf_prof","Manufacturing TO","- Manufacturing Product +- Make to order product +- Not purchaseable +- Display on POS","product",1,0,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto" +"any_prof","Weird profile","- Purchasable +- Display on POS +- Not Saleable","product",0,1,1, +"complete_prof","Complete profile","- Stockable product +- Saleable +- Purchasable +- Available in POS +- MTO +- Manufacturable","product",1,1,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy" diff --git a/product_profile_example/product_product_data.xml b/product_profile_example/product_product_data.xml new file mode 100644 index 00000000000..019009cc9d6 --- /dev/null +++ b/product_profile_example/product_product_data.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/product_profile_example/profile.py b/product_profile_example/profile.py new file mode 100644 index 00000000000..eac47fba847 --- /dev/null +++ b/product_profile_example/profile.py @@ -0,0 +1,46 @@ +# coding: utf-8 +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014 Akretion (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +from openerp import models, fields + + +class ProductProfile(models.Model): + _inherit = 'product.profile' + + def _get_types(self): + return [('product', 'Stockable Product'), + ('consu', 'Consumable'), + ('service', 'Service')] + + sale_ok = fields.Boolean( + string='Can be Sold', + help="Specify if the product can be selected in a sales order line.") + purchase_ok = fields.Boolean( + string='Can be Purchased') + available_in_pos = fields.Boolean() + route_ids = fields.Many2many( + 'stock.location.route', + string='Routes', + domain="[('product_selectable', '=', True)]", + help="Depending on the modules installed, this will allow " + "you to define the route of the product: " + "whether it will be bought, manufactured, MTO/MTS,...") diff --git a/product_profile_example/static/description/akretion.png b/product_profile_example/static/description/akretion.png new file mode 100644 index 0000000000000000000000000000000000000000..c56d4cde0d6337175c0237ea534ada21b9cd4dbd GIT binary patch literal 9649 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 literal 0 HcmV?d00001 diff --git a/product_profile_example/static/description/field.png b/product_profile_example/static/description/field.png new file mode 100644 index 0000000000000000000000000000000000000000..f34129424be0c265cecad6002a38de810cd07e61 GIT binary patch literal 60208 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�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 literal 0 HcmV?d00001 diff --git a/product_profile_example/static/description/icon.png b/product_profile_example/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8b3dc5563dcf86a77af97366b723c902e070b5 GIT binary patch literal 3655 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 QB_ENtx{g}8igozE0D`>^ga7~l literal 0 HcmV?d00001 diff --git a/product_profile_example/static/description/index.html b/product_profile_example/static/description/index.html new file mode 100644 index 00000000000..b28ae1b142d --- /dev/null +++ b/product_profile_example/static/description/index.html @@ -0,0 +1,117 @@ + +
+
+

Example of Profile field Module

+

This module install demo data for Product Profile Module

+
+

+1/ Configure your complex products in one click with this field +

+

+2/ Explanation help end users to know the implication of their settings +

+
+
+ +
+
+
+ + +
+
+

Configuration scenario

+

Define your own settings

+
+ +
+
+

+Define your own settings rules +
+
+ +Use Case: products configuration becomes harder for end users: too many fields to take care of in the form +

+
+
+
+ + +
+
+

Complex product form

+

Product profile example module

+
+

+ +
+
+
+
+
+ +Particularly useful for complex form + +

+
+
+ +
+
+
+ + +
+
+

+

+
+ +
+
+

+
+
+
+
+
+ +Explanation customisable for end users benefit + +

+
+
+
+ + +
+
+

+

+
+

+
+
+
+
+
+ +Clean interface of all fields which depends of this profile + +

+
+
+ +
+
+
+ + +
+
+ + + +
+
diff --git a/product_profile_example/static/description/list.png b/product_profile_example/static/description/list.png new file mode 100644 index 0000000000000000000000000000000000000000..e756361c6fa60058c0ec34d518bb4ce0336653e5 GIT binary patch literal 21858 zcmagGWl&r}w>3OS65I){!8N!`aCg_>4#8cLAi>=og1Zb8WN>$P4estT-{d~`R^40m zR(<`0nd#|sPIu4l-g~XRns5~*X;dUaBme+_Dk~$Q1^~dS001yp2(Zu^@Ppq0^aajU zOjZK{0bylJc@z4Pz)e!eP2I`T&C|ri0$}Cn zXn19vta<9-ND~1rJV!KneK1upaa1D6xlh2<^NUzq8P=Q`z18$I#rKP5Cu=&`w+#d9 zrqPC&I7PC_>(vhF=dnMpc{558e9q4wbM`;AHZ(N!c{^EJdD4N6&=DwtCo5vA&tS=e zF~nG5-wQ%tK7OYT*6<|25JSjk2xI=Q8W?@A15Htcq49AgMa8kf!AV;nf3^}v@DU4+ zSm|&b6Jz4gj!QH2&XJLkRaFjr;q+Bn&)ssNDw>0%qbTU;c<^1&vb>yOp&M#qP3X&t z;d2{aK!*T3;QaXbczAfIrKR=u_QuW4T}0C#6lP=^9M|f3PD4dCTcy9y-`|gMgddtu z7g11p#6kjnAf^}s#Se1)ZX+cnB|pEm+}zxf604!!#iDQ{t>8Gjg=%Nwg;Lc|Az~EC za?uU~C|(G<2;!X_jn`f|sYB-T^YiGWf+`hrs6^bH@}pYvn3z5uo@c9D-s>YH^7$%* z=Ir4TKc>(qkj)9Nsjv`7>H`7-;^X7h%4SzqRye8O3*M;7$^R>Mv!(HB<2$rc2GO!| zjGNzq9+x+$Xf_Asogbi&gifI1Oeig3s4-YrSQzBE=HlU@Ri@Ezo}^b*-LFP@gM&a} zHIZ|Baq-QgQK{8^%QnKubl+&9j}VEpkJi#vEwEAG1F%VP-tXPA!<$(5JUuJvwj>o}#Z|@O;NUo4ZBES1ov3F5P*G8tTUc<} z&JIpZ)ph4D^bZiIm1*EeT3PJ}2M7Q70n5n9C=Pr5g)u3vet&x?kOoKJa(4%J_O>b> zOe7$e^ZM(dmxQClLHWn>r;l&TppVxtVWS#-6mcgNM0-rHv<%uwJh?#ogt_8aVUYy5 z_CziJg?TBwcI$2)$j2ba4bT{+Io?Qg2|dKvReAuzOBL|8glUOH2f` z#cF+aF?VzP`BlJvhvJ5Pi}&pAbOo?^a*~ytEQ#Rk;xarjfetOm$cZDn$_a>)swh1& zR9HPD-ZnNiauz0I_N1TXeOHx{rVCl^U$+`GL07qaf~q)ulNRUYShLz4fvyLW`R6Q1 zJiavrNNC@c`I;|9HL4M=^iXXp77I2AG`1do6%2nIkZU7{+OLO)2h*5^UFR}5C4pP$ zv~hZF4GD=Isn?c~Ozfa+wbfI(N=si?m&;*!c5G~HZ4GQQQw+63!e|->h9g9de7fNa z!B`7jU*G4bD3tATwH8j)WNz%Mq4Ei_jWz!Y1CFyzOr@KR{qAz|+BPq7}*LkN4Oq{u@(h2ngQyXby{R zH&O~}EOpNJc56<(lW0cMNkX{_Y;JnxkXPHC?1ex*-f4NU^1m4PTbJ#d>)mWl#4lg_ z@Z8Z@9xlJ3Jt!L8IuL~qAyNhZYDtn0tl4nqreqPXtvV%Iw(I>hew%~?2#OticGCP;KXwG^J>d+E;EaK zO-BItMkykQ$&`(SL+3EPUvS3S>cFSaMvo!cmXpvdjd7n~b6fin-qbpUO|8dE82~ta zbr4|{c~z;R#Mswe_b$}K|(;zhzbM6R%daUEhP(L22nPrrUpD+k278_5l>mH ziU6NL*+c#QlZ_NSNY=|L!`TsE!^(_c}R!L9Y0I5*qhYGYA|x$4#Ezv?+v2I zzGfNj@F9X?YhG@yqvLI1aqv2xOU}7-V&oXf<*2RMw^`1OZsrmqbt&Js$tB8A1!F`c zG>5?RB86L_=SC}x&mjL0X63s&*>aT?q&uy`7py}7n-i0epl%?bARzpT{#Q^D5I!@x zxw$c=ujB716lP;estQgp;vj7&u)~pJy75y;=(d|1+EM6 z*jA&&JL$f*+iz5Wi-YH}r)&Wa$0zqcWXN&uKHFPVIe)PsOJ3Y~qSMyBtVEDEyHlRm zW1J1ut?k7?s=Y1{1|Z11A?$h5l%jj8M)H~RG#h# z?xfT|v?Lh~@4Fy`w=v}1*S>vk0su&}!#dVR^uMT5i)B-YyFWCYdV0rkrT_6;i@-ge zpE$Eej`RDv-9Zp6FYHT+1`rH|wEJK0kpu=nGCqlR6@j%IF6DWWX%dIr_(>>&>uhGr zT=OD@@2=|BRzUVk?azz5IzV{9Rd;MoTVkKK=NC+|}A z;biC@U8Ht+e5`*&(-Vry$h8auppYn;A&{;V<;(qu?f7!{HfSopYD_k(LLsK=X$@A* zjXB}52Z+}ixQ3#$1I8)Uc-GQN(-{*HDa zQvTR=4w)g4g9C)-zk^4h_-(CgVly|TjSc85_wJal#+hhv_f^a?C5abb(uZUHC258w z@dd-WE(sH9Vi$wb_5FN2LP5TU1df+cu<0{9JzK6Hml`TSjm>nT#hM%^mlg)_tNlTA z4OlIP1c>`{SfR^S)uY$s<*>D3hMP2a-KL|rrOF2#bA3Yt2{ADOjBeHDnG>g1QrZKZ z^aPzl_Uh_s^K%KBp^_5V=YVRi(Cm}1-|hSS)L;z;sF5L{qbtkHbF`(zrKDIoIGmoJ zv&L(f27@nG7zqdn(9qEO^`62R;F{HcT7n1K?psndb|P&(n=``_E(Bq|WEzSBI{SOR zn)Tp(BhC=(%4#0Yl(07xnwSAhfUtns!$LWhtN617A_+##D)zQ|2R ziX&~FjvHXtXYQchs>e=evuAEKlMQ|9=9U&IDJdTxpNN9N&nUI?EI9!zu?svWli69k zZq!`6!|}-6uPZ(>6*Z*@`LxnAjfI6~Iyz~WeXgFKo@8WXWg2>As^3Gc2b@<6rDKog zDy$5Qmh*6XB8rV2(@4sh^q_ItgexV5$(Q2(o}iKo2#`` z#d&={uD8y5+y#u>AI}vDq!5(Mec70Amh0#{e>Mp*;0vX%nVy~&6cmgy#$s3OT;@5N zB~c=2O^H;#!tg0m!J$qZf`x<2<^QmKuZ4w$b#iiogVcwOqDMhF;0%pvOJ)vlePXsH zRGF%nC5OOzUN8Vp_mwk&$6(5%4<8_ciO2w823LLZ;xms2Y|!X-W^AwZuQa?m&zYhD z)^Sy=kSu5|5#ITJWC6|D4TNQnKwHl@><>)P(==q9%2|}N?l~~yZfJlk5GZtZxtc@C znzGdHOB%Lm9G;q5Cj*vaBhjJ(8qgwT3Jn|#hR1#6(-`go}9Gtb%POF z&$(KgwooT(0L0}cM5AXgL>JJBh;%&PpWAT~e!-A)_}hRM-GV~OotG@|mLWRmf?sH8 zWMrhE5EUC6d${b@E%=|6<%+fD*f?vLOn1$5?bw}J)n<8M!1 zJtDEMS#ejF9uCu@_g2(~-;=y9U3?SvzSlPM%uLO6KId*CwLcB;wYw}nH^LI6y6 zn*1bU05l?fU<~p*?JMf2A{2Dg(BD@RUcM4U`_ARCmK=sr>v(0^!O!C%*w*s!^Bz)7 zJ*KFn4ObiR>4U(KVJ4`egPEVw<{a-6`VueQO*)?*APydQ5Bx#93d3&VLs!WZbzXMv~86de^fdm z`Fr@Air?r=g|>7cc;jP~lPPKeU6A35jjQn4%I|7sWUObOs<6P>g|S*83`(__Q`!k) z{FCC}L3LHw(}Bw+LL^a3$h|c7S1(SXAe+r{Q{H&sB?8nqN|b$C>LhTAZl61rh85rM zs6Nas`eBwIV8~p)m#7V8IwRw1W8svTs4-K)cMHSnGONh-hZruVC;1EzZ=nCl~wt2;! z5-tT;Leq=$t;gMaelqsxrC6Y%>ml9CsfN-<1Y`7k_-dWOJ+D=4r|8N}oKUCHkBW-D zMi}|Dir%FX5Nd)_1Phpf{H7aD%cQ8gEKAV+9zByt7-8Zkjd6TXB83nh9xkh(V82+K z-`XlL9u^k&j=dL6+=2+Y(ct3lZf|d&of)wgd3P2@;ENYLzQ?gBtslz?BS`%zTR6<5 zysbC$qPRc^mt%ugERLm+N_4L?f0naAk!E3SV5%o(=17g+WG-BkLwz&r;^K0)4rYuf zsHmtYEG$e;PCl$CM#$I3r;w2Q!lL`1f45G+ffOC8TZI5 zAm!IiaRdr;%vyPDir_fO&X50EMFzp3|JNrL#eWDIikG3tn(4psG)yZe6tU{U+iy_> zW7H!ocK_%4kg)%CH@Wla%B|Nd-drx|qlQftAw3xT3ME_Bs__%}`%%}SW;@V}Zi01Y z7Nrn|A|h8_`|zB%wtS+CedM)1Hmm81a5ipCi0Je26MiCt-hogCBlzLrp|Oz@Y{VMz zH*$$yafUs8bZ!plak|X;`Y=S2oRMMs5Q#yF(7koJZLzduL`sTcC{A{MS%8m=M|*$k z@Vp(1((`Yu`5EE+k0Ho->?qs^_@Q+`ASxPKyZ5!Fnp#3wSQrJWou8u>O1WCJl$wet zxU|X20y9HPPuFJ7R{T3m?hZw;N_0|A&Uk&L1_KwoAOJ&h3g0bi2*v$R9n7bQf;zH# zFLv@D2%GC~W1h<^7!AankUrw(6dH`-i=gq^HpjIVD3S2Z)05|=ceV`|gWb)3+9LK7g#-?K7bkqu94xdU=eLi?(|)UUy6Vpys3;+v zNgtm%FvUvy*`ta|Y%(ws@ZJ_!wcSIvGAv0FP~Lh-!WP&K^MUVXgZ~% ziGmdLwx`u@l97`jy}=5~0`)eUzdkMfU0jR$dg2=<5(wZHy0@)rGSET>|0e}axmPJw z)A3}@4akK1mG-Mp8atz?++bU+$5c$%?LdI=w6q*Ut9P@^TXsiabMegaZL#tu3OF^i zD+@YI2Ih9f%Yc!Az~qx@rZ>!FH4geB`9#4lsWe63KxEIdr$!V=R*VVmtgdTWi>EwZ zN?rwp+?EA5&ICuPt-E?-$W6b$A6}%?6FyUZ5<9>Z zSB)~v&Wiy%%*;zA5g)?!R8H{bikrKJa?@qxu%6!IxA^H&czvU)oQDNmygN4SQ>eO&2KQoFiqG z^cgAdV@gSgvp*lJNcnM39jCYXqc7<3{qe0;l!8|r@l9G?E1aLVGrMo_FMf_Wrb<1$ zxmOZ-adtcshr;lVx%2ITN%DS@=r@;0zoQTHcS`FWiqndElpeWSOqV}jTue(;+EC@b z3p4-ie!Rem9vn0z3<08jWBJo|p0KKo>(9ZO=fp~uZaw|uH(g3TeNdx*vyrfeR(v`L zJxo3;>v&=J({|$c+NIY_^m}sp)ahfcyHdQ=i%o^!(_D?&g1fo?h-GqNai1%)R?urm z|1c6^PHTw4brwdlEzOq$k{u!gQ2%nTPuw6K&CF&Lg%Ao)<5JulbYx}GKx7pJ;%UB`@G|BoB7W8B^nILP{vI5ow1qsN9q<%7>SQY_DFq|GM+kkqygF4QZFg`z&1Q^|!6=_?q2inBk{Q7>%T=*z(*= z{FTSgjY~CavxyTy_ocExjGmIU5wruY(wwR!EWSFORC;kZz@K~DTT297;MU*-*XYePC-wFAzXpK#mcLKfRO1>VGZACczbI z@>`9*=QDL~#uTT6p9uIQNSciaHO|j*e-D5DM2GHD6)Q-sJ4rhV%P=Ffy{}%vcar3Qcs!)G$saY@+wu#x$NGkWbDiQB9GX8iCs9p-C9XZ{PEiE zwUS@W3?nt|Rl3pp{+%?X8;&@_gbk-)jjC}w%af|tkSyc{^sHa&AOUXVo$rboEZ^M?z69DiJ)}oE``%OSd}rX5v3aNyjmY^;*nVBC zEGs|w5vBw31EXB{2l+SR0cYZgYbaQ%yRQTp&K70g0@TG22ApkyEqQsOh6d0mH6Wl}s*s*< z;78eXE9VG-ChO7d@{ItZh+jDof6LS!4{j4y0(PeNSEHRvjr<%0QRwQb(sH%fT_fQ* zhWzQ5e{ayc?u%Trv$DMBk+y2eSfkvQ<8jyau&i?*xUgg4^&G(SbXR%n>8Zd@6Z5be zk+MB$VhKJlN3fEP)RF$;*ZgI&s>SM;zk}pWMk_j+IdcoU_OQL39yW4D1bV#(s zoEi1xlX0@?nXaqI0(1>hk>m)d-BeOe-180EJkyD5t+&+EHz?;>XiERWu11 zlxGkZ6lRhdyhB(F{$SwZLJ1@kO}7wmMyM&mkGzFrcmC|ySY;iZMeMVREOvYj`uXmk z1uSD%#wFN|dRtSU3IyhS?zgw-+qX08{qP1k7Hb*Aiw+a`D8f`cjDR>xa`%V zxi+X5jKNUWJ+C|j>}R+^ybg>|!@VQ<=zq}Btt4;uY7?cXT&Mo2XVzyIRj=&xCQMM? zf~${^xfPy%ImaVH2Hh2L$;cR&VU2dh$Ovc2=sm`0S_rl{eEEfGQbzwxNyOId=aB5I zf_y}s@jXj<6t;6jbQp?YBX6b=!sYj&O>2n~tl~aq^4kQsI5>1T5d*ty8w3=g+Lt;0 z%9wWh-BQ!uy?in$ni zKaZxdnI$A7uyb&@E6>?@98MRNtN;yIJfTd4t1Cw|j)s9j))uSygiU~0_iYHWI_0O3 zj3?fRWI4MJA9!*Eb+-;4f_nm>z=?u^n|uBuwT{BZ`tR)Gx?sv$H!dZGsJ&YGsv5h7-lida^~+3@rb6k{iDyf(w>x$U;|FzG2un15svzT`bun zEd#q?o^xV36VbmmtI#$H*w{}uWIFT9dnQ%)CodHYu%vik=cfhf`fQ(o+nL%Yc5*(e z_Uu1b-_NDxg`G^I)p_$u`uiLnz3#fA{vt1J5(FwZRhH&p<(GGskY)+F%A0Nl$~vqO zxf64@7@Iw_+qDdTo>iLf33zTQv7;wABF*9dMgdY9FdEB}eWX|AqQ52}?P1@wFIHQ! z24*nODaYT42jGqEQoF3veU?*(Hjss%u-$5HP|vv={7BoW>DQOFLQ9cE(W z=^M2d>eRzRmX8Y1YxEoLUE2DW1?)E$<4=Xm7sVRCR*GMDopXJdTzlO1d5~QBDBgdQ zn)~LlTzStD4S8*t=k~kFo#_y+Jb6yBJx}pnfAtxfAP%48=OMXxOFJ`?Q`rXJxR`*A zd_4_nVP)2DadSrneC-3xb7KjArx{9c??1)t62%6W9GWY=Wp5A){AvD~=Hh%@erk1A z6nQ6nx?Dq?4*QK@!Lw$~@5LiRPqjjIfTD22dXH)S(d_R8p5Zfi>uRHGWT?@qWJ+C% zb6~@WwNt(6B8RH0q1I-#C1!8B_?7Lcd+AB$?eb(_8Atw2}y(M6=bt+tg6SgF3-v+H&^O!Ms00&)@#Vq z`pa|L$>GJ!_z%WpVc>))&EL)GWIR%#Rgu7_Ul94ytC@T%sWK)2VCv!c%qnfe z%2UA{xk1ZzCq#=_Tmx6f@- ze96M!baA<%1O(j=Dwil{@UG$oT@gJmHHMR+R-wmbW)M0bh>^~Hdr13IgHHOKg1%$K zPg+>fa#fIuxs9>940ofNiVb{JT}bF`mQ=@k59lnrpS3v$^LRf2v$`wjPQL6FhHR)X;QzBR@YtF0=f&#rO;}a5?|YgaV!9>v~USj={}6nlCN@zzm|eESaw| zOhi_*3%}saUX@aUo8$!8IWQNAPD}&HkLq1`$>ZgP34y;qTiCj^<9~f4Le=G*r>Cl% zpC`fOF+Hd4|1MrKsb|j(2ucJM!UKqp_@?4AQr>>`_#PHfmp9A-T*~^}#Jqk(1p_h% z867N+#(vHMbYOn4P`RunOi*SfGqPy2r?;mm9&~-e0SsP`>Ew=kpaVAFNu8I%MxMTg zF*t6O0f_!J*gzx~uIg0zuFI#x28c4~0{o(+04%B+%?+b?q3Ek3*A&1{{AxlZ;O{)% zW=@?20G6KxnuvYB@_fCE^M@ z2X1}T0U=j>de@_T-Uz<_xC5`cRif6FFTEd>rvNoecE8c@Kt>kP0JYxRG{JBFU{7nA z&?U(e$d`*p>JRKkP5wfaDbrH#^FWuj$J;(W=lRqlya1brs^<$E2H5lOI?;ede5{+qd1^^Z%w|?jsqr~l z^UJ{xI?}Wy<@D2LNo@feCKT)dfcMXKIB}AY(gv$-gBEu;SQ*qhP*|#!4j3n@`2%O-SO8 z)>~ua3!y791^-fNr{O{LOb*}Wg|6-@mLeN-^h zA4C6_btJJGeqx(YrZnNR&b`92@v(JcoL^+s;s?pvmZ^IUJuHeEh8OMi@LtKP7ADC5 z$;jdNBUdS{zEI`8_G0n=O z{adVALicJTDp6SrIbXg=2RUf{ToAL}-Z!w3=i~I@Y*O$`o56ntLNQjamdwlYMfGYR zt}dH7J|F0Q|I0`_PPT&hx7*`J5uWQO52r=9O{s{O_`wtZRx}c>&%OE6-*sKDOTtGq zIQ9c~v`q-&i#qj3ur!V}=hyWFFEb|-W|ak~0lt+}FW1vahUZrAv< zCh^=?QrL8-f2wO=TWR_0)~j4Os_uTc%I5o_)#Eg*%-&wES}0&A*EgOAmIy>A;z@bL zJLLvbvLCLYXVm$LZ$Fh)&>V7>dYw7n6q+R<&<^phTLb0Zf2+Q@f~JUw?$=Tq6B}Lh zp*gp8y_CGCn)+F@O&-_h)&^0xAqdNZM;{W|hH~bLM%RgYOIQhdPQ!5&Obynspr&m2 zCHNVg&d%YwcHYnsj_KEp(UO=XfRsp1uFz9Sz;M@e))UYZ`?& z#*pM8R!bS;TTnXs>X6TN6cA|9AGq?-fuCf6ewFZ@{$Y3pi_26J$rs~^Gjr+qHe}=R|li%l4W~a819EEh4Sd)=w$>0Bi$s;7!61wK3@dZL6 z?<5ViDGtH;qU%XC(EQlTri@JFrqtWpcZxCnA$kCd$H251x0643bwi3Q&}A#jBJ3yz z{`9ArbGGH%VgZXmIIqi#lv1XW$C1Fm8Na9RjADY-VC>F@0rqPj0@i6&+MsAJ8N*ZY<)Vd;1zV?Szd1%cdkXSY9$x*YE0n#6;oa$K4 z)3BAp#p6#q{#YE(c{$jo%z~6pea+6=U-gcoA4Mb(qOd`af69-X$`FgbjdZ zLS~1RH1?0)#TV?dhg3CovoThh&6sSwzn2dO69w$ghtCBvCpO{>Jf41BX2ioL>q>d# zu>oLkapq?A$Wm83_=b3|$OXaQm4YlFV<#Spq{Puxuglib?~%^64PTnSRiJHf*A~-X z_&CgWvn1_Itz+pT1_7rl(4Cm&RZg{abN_5#$NSO&DCLM>Tm3$>Nl1ntsx-2`{$$*m zp6B>^f)CJ#IFjJHLX#QM?*0yPpKukwWP5da=0?=9EiX@uR zoSmXKL)f(SH6dp{2$9wD})XgwbAl zK$!?e_`0gih9ik7rkZs4<8K*4$$Y97%4ImC<_*5$aHqy>kQshcr9&>v;0aE+wANWm zN+oW1-q^3mKgm@5&AKC5nZdO@9=Xa>;bQAx$k^M}giMtTg6NcoT*o--%v}w{*j8mB zR4YUt1|fdlaVydP=-?Grb(T8I;Nmi&f^a~sL9B+i4aoEb_0Mp>;8>)k&iFji?SkRM zz6ZDRLzY08Qn|lCpvjZHBq+n>!%A(|C| zUV#;)mHtL#JS>Y0uc1R8Nz*0zK~I^3cjvRLcbOUWh$KARZ?T$WvE#dodShX+=ndMn z)b-^*C^SloyP%un>_deDJyCSlq|IRqYkxHkf#y%6?SbHVO`jMgokqX@*0y@BuPZS* zAW=QgzFkhoXtv;bbG6e9%@+@J`W39cyso~5%eP@;9))bKdST&yUv>@4;^J9c+L#kR zv%y-IrqyPD*Aho34aG7j{LSC59A%?YkVO51g#AxL&n2A>GcmqS@kywv5{P(N7o)_Y zsSZ^^iXA*MHpr_R#`&^dWhm)C=}FTr@ZS;+oAatbozCP){^&msg#eZte(~b`2Z9;8 zhJ5}Py#604!GCEI{zq+)htQ>(@gJY{A5FpkaaR8g%)29zym&d^L!BIu!L|Q-KjhnE zx=s2cF^rVs@qu|sr|u2(F`7Ra9Jet2#|xwUVgLYyaVTvG=KI(d>P;8Vlg{>UH6;k*uz-|Fldy|T+8qw8QzkX5;6PIgH4 zX+~vv?v^UHlsxQ6TDB)Gu)=>}anXFRR}*CXU==tKJ>R3sBiVa&49J!~*$%+pZL;c~bEb*jsCrhekOyA2Ft^%LWe%OKMW&kB(J zTD?ivAAY=jhz~Dr&or{e9`$4&*_t~|NX6L|Oi<(9g~;1F@Hnv5)5-Yr>e1p4>QtBV zV(H&|#8;75Nx)%O6K|{5{_zj51g!sR zoxE0dMq(x)ubmIlGw0rsD=_(!TDPPl!=<#R?YxDT@P|iNl?YECFsr{!{%e7;$rlpYLWaP5S+@9NKgp zfme~V0Uc}@!q?N~6DbBUBOeXBr4)!Z^0USwk<8NNI^g}LyEYc2%`KQ-O}0lTo?SnD zgw#EIG<7a>`}n`~eu>t61icwGxhbNaLdoCX(39d9h(F5u^xD=`I=A7?$=r*(Nm0TKQnZXWtmS; zy$gA`a<1jIKSb>0riSH?22S)ma+l6rL& z$OTxF5rb_PfFam$fV`X2rOM6Tjv+w=8@#)|=R1cj6*s`stlfQSzag9k4UGKRQhv1J zs(ZC_+ASCv-Q8dqNcT6d!~awCLSIg-t2NP)jNMtToYVbf8!pjaTMp35S7NE5BXt${ z3Dsb@Ir8p&)VRZ9Y=7*$Ce8Qr*?Lp+2Yab;U6A+o`HVhwO{Q<>Vr*B7yMGB$hvkbe z8KlK@MP#4ydR5;O!R2d^vXJlQ_l?H6l_n=+j;b@@DQ!Zu2>Q*`UbBz_yYlGIG;GX6 zZjY{IMLSDSjPdnK4t)FQ7;~F?(TzO0>p7RR#;4~=#N60#9iTms|3BTT{c`QM#@GDj zifS5TUE%ZK=MRyP)t0vv?mD{^NGdV_U~p9S&e*g99MPh|ZoB;l|~G0sZ}X^iFZ zBcB{V)b;+G+hEj2$7wkN593yHni=v(sd&wBy!J`kv2a`4PpPzMZl1 zzN&J6lsLC4EH`|pxO3+g!`}g#dU5@pA`6rkIc*M%IWbg|_&>CBo7uV&$$7zJf$m;c z=0K@O=jo{zi{U%gAQ+Ax_SQ&89t5-YD=i6ORgrua0XVbBUf(o@9%g$w{5v>e;3{Ym z1H3kj9qW(iZIcr~y@B10G^6z;l?pjPv@a8tp*b?c%Ni5f!yB0 zKlM4~7o88L`|Po;oy#v{kSiExbp<3;tTX^1YKa<)4yjYHFob;% z5Z!sF`ge+5#nW;lnh7R2E7La?@4?e{W{Kx`aI5uQ@BtPY((~&?JC&z9o)+LNVWQ4Lw=8YrFG!5M~=)*c!`I>_{Z<2yK&wkvWmaB-)6V)nFj?| zGRWT13+|NjPH^cI*(E2?wz)fGmXs?XP24riQXKG=<}(Wd;&=|$IX(MTH)Yy@3kJGPm7G^jeJ@wtC{xeW z!F#Ppm?aYQt*~&2@85iI4f2;dj3>ND-ASod`8lh9*c|L$&7? z!3BwtAZSmR(EYME(sL5)UhDg1px=#$>G$7``{>1h7Yqn_7dv}X#;%FWYOIW%z<>o{8h_l^H^jPKP z*P#-g^#^|sq7^*^QL2j&7Ag(9FiWQzkl&JG#FD{>y&lmt45~_nYAVRsjEpX-az3`=L}K;CiKF+TF9d zO5C6cmEX3uE4RiNnzPFjPDMcxfrZvyUUJ~wsn*gWCz?%peI0%C-9vn!y}f+~(B81G z532YL&WUAj<=oyjU1>bmux*43f~La?&(^Ez)u5ok^(JCeDqNjZxDa|SO8rbjl_5D= zPhI8R?iVO58O5?H?3I0xQ{UqdOex!}FvF!0g-UtzXvU;uU6cda3Ll8QszDDqwx&p@Bo;x>Gz zSP_YbZPb9*XS}7~qa{t;wIkg(uS=t!sjegPzx=#Ymmcfoo3Zien}hNzqJ`u7#loB9 z#>9@=xM5>1M<5tIeEF_V+ZEjhjGoaNR_HtW1XdKXdHB0=M?b*2I62LIepP?ys_pGh z^2hE{vqM??1)oZB@qTSKFvOBNrsmsl&tat1yU%q3?GLt(K#}$g-Xpi2A&QS&yIa_F z|IH-BKp~Zm#b}szgJmISCY+O%L^YX`_k(HD{{T`b(lSlvCo>w$jIM{yNbn|fI%N2M zYBAVuX(j=nnbe>RZlagve5s-ST14x|G~dbsHyq%T@JMhpKxq$gJmUWdJfIzV*>-n zeyX+e=)Rj7JUp)<6!DgxZrIaBojC{l{KJPv{+!}xP6o9ibp^FQX9mI37rtpwbvv2E zhK~VAnrQ#r;b|slIiaA)bUoXUCUHX1I{VM6Jz=w2aSif_-pf{~>C6-}q2FV}0QNFa zZrz5RYb{tQ1|WeK=rv`f-CdaYZlf#Lpa1vwGnY&6hh<%%#pbVFF_{F!i|}o1{(Es! zTBdu~X#wcCKcQ#K9np-1|#hd<3{K!1N}mc?3|p6;o;u)S(|2cG}L zg?+{G+y87Q(CY1p*-qFgAh2)sXOV}O?HOqdTKeTP$k2QtWkO)A1GWW~i>o_ar1*q77?3W-^wlwijNSXuB3AiNFqLFq!eL^A76|&o^2_$9tq+?cn+v zlz-xWBLb+YLC;hs{q{Jg7a#W*4D@U`&wvGdL)=T8$PO&EQ=^;1vz0 zwHpAyS^M{Y0Z4sNlo7=al2woVyl5(fjB>B`9@DQq_}?d$zR*QbT8tK}`#td|N`%Zz z!3gF|R`1NZF#)Jm<;W&dL^&~!I~at4Ijf$tZFAu6iC5plo9VI<4e@}NHu1Y+wY?+X zmcx4$%#&#e1YNXw@WPJC@T+`GF;bC&@Ip&dph= z#qk`u?c*c#MGtOn#m%YQT!wAlh_>kyJ)pl=jTB>`7h%g^F($a~%hB1S*4rm+2YiYh zVWd6()<-E5um2k3yZ`6;ivP=naP#xGw2TD(BQ*FJ80EFsEJUHJt(@57pEjZ%;r~b( z{+nyrl6)ull7kH0kU%qxrR2vGRVi7lE_-xT*iucfuyE-%TI8r?O@%DasB` zjBx2wCl4Qa%{$E(fHfE@=mM20#;1sAQYn25ztB{<#7*-$zk^Yozn7mBk{ut z$q8W?r{>aPl7a8bpom(!=GX0yyZcJLFE4F=GebB8A(6nw0x8m5Z`bn-5=bbmr7a!N zdCKcL(fW|Ss*q~JPFD8o?k!K?>*q=QmF5o>Rt`50<{rwl#d;CJIWX&bACXyw81@N_ z)J**{@3Q5hJphycUn|!c4QJb}Ct4zrM50B1Lv$veBnX3e)gXu--AfG7dmkl;PL${+ z3_&Jih+%X|5Jc~75X=x|3c?tSe3SP(>pSawYn^reoIm%E{p@|;>v`6__TJC6_q7#2 z1Xw?rGTue3aX;x->xS7pgcvhj@39_XlOM0e`c<8G>As)2PY!GIY_RNFIj|~Y5BQ2q!^DXU{q%Y>c zcmS+pkJAY19QaQPz|lowoR``k1^Y%{0AL~u!(54WYWq2Mg>bc!CXH*kq+X3 zd{p|eGhe(bni;eTv&dzjj1e}{B_7=N^qCb{oAO*@Xc{X5g-9vT)4Uo!uZG2|_qTQi zEH7k9yVBfCZxR$vdqJn(-`Tzu&o;~An_zqpy}sh+At^B~Tw>eiyIINF(Nk+Xs4TeR zxh@PR7QNkmiOT8yqMOe2jp-2;#}3Z$GabkmS2}(|}9<(5NWcjVIv27b`;+oO!_78rb=kFRpOqXq^|6V)euu&5bl>N;- zT<56_6%2J)t<;M9PaK;{4zbU>xo+8v`42oCC>)rhYrTjh)xQ(<-uDN49_%kfk1$5U z(ZuQy?@5%hr`w=v%?hKFo6OZ3A?UMHg*4eiOZs_fR)Y27E6f4ioFzgpKl3I(WHlJQ zlyR7s%X){;UQ{-Oh)f=B%2ae|nr-Ohf^G(($(>SP^VdHOn zxo(8l`D||7{kCnWNrJGGeg0)GZ^`cLMqI<|;3LQqW#K(G4FB9kU4XTRck$T#We}?A ze3%lzao$oq%%Z$GQkLbq!j8YG3P@_ArLo?%n*@JI^}DhI`q|;bizRthY)56N9mPCv z6m?x6El!%|%H%@bJEwoubv#5I+_I%G9O8d?mHKT`>x3+qZg2PhDo!y?cK96A4O&}T zBwI{U-P#AgEas!H_yaKo!~Ql>*Sy_1XAK){E&J^zt(R1CTrMBy@AT*ImH~rA__W8@ z(Lm6Q=NVYbm9MXQTNXl@3|efdw#UTk>&`-?11tNhxqfmz67Er02k%JMS$T3GLh<526Rwi+4_BJ#IcH)xCtYA@TeVB3CPXkf~PQn}IlNST3$g zs8)}{GOJ&jR}NNEXusdt;J2))=9*7>ok%f;M0j_daQDA1FaV(9 z1a{T2@i{rhN6^OSG+^<(iwi+`bD4i-Obz!g>MhKJo>x@8X_URKJTpE}=}ILsQaj}$ zotlVK^erR-#1^s=5#a9&H%62_IqHGlrSkEpULE|K$w%eqI7KLOQA@g^Z@xcQq6+@a z+xs72`|oUv%Kodfuo#%OVW93`{mn4;yBp*09saMHv9}A;-v`Pxi{-sv7NjPACPr*1VuJFfp{BAH06^z40!1qF6^8zfQGZT15icQt-}N|t>^GKw zYej38Y<#^7?L0OgtYb=`$xtAZct8*n2@!Tc^G{ftnU`|tePKO`fa;}c${1VY$%l!kU+&T=AXLE4O&8<| z(KkI-x{XI95O19QKhVnJK*7XQwRj_q3!z)(a|ccjGT3-6WI&38u0OvGhh5v%X1coT zBl1^-w`)n>SY?-&bxE zAxvA7%Hp$HA5+EuxUdbPu7`0`8{FErnhfvDAv`c-nH~A#Wl|ByJfS}d`5pnew2;5I&nbSf>Gm_1+hp*22;$xT> z!>+r)qSIy=c#@daoV&;k3Z~vWoh+mM>W1FfWmf_j|oKZ65Np_^B_seL+JmQoujTydU<^P8`z7N*>MpAcl zKo`vPKsc72VIf6qthH)@odIh)K zv;h4>{#;dFF9CCII{zJOn7G*eij{vMj56Q7l8*jp_Zlf8BNOr ?fJj`ZJHq`Wyd z1d(==IPaeA91rVQW}-ya61>BYXNni097j?MTt4d9P1UUL)hR3`*fDt)9;TJTdWRxx zDyFXcLGC=>%TrsV8ieno0%0&lTz|tB> zCoSK{U0*PD{P@mWGqb#V<{6_x2%6FONR67feDYR#-Xq+m$nF9kHzt_iTAy?!{G`U{ zE^zyL$gw~kE6)>?gD_O05! z6zrs;o}GUhI|mcdo|2bd`Ej9kA1Ws*&1-#H>EYiG+6Mri@5s=rlR7NY0 z-8fwAZT#`*OG87M{$XWS?%_oQ!Shpj!jj0&+AAZP?Q7%pc*5jTRC&S+XOjmU{*Kynp-2o(taNCJ73{{jcK%yR81&P5^A#( z5PZ@C-#@BJ&e|-jB%Sxq>{;SndxR?>qpLA=F#V!hGd`D04Raf9rh$kGZ#(=%wA!Ur z(d)=3e~Kzq8HD5f#Z+6b9q#zr|7zR^%J3Ub5fflZ;bdrTv`9-C`pZuijS%)yNniGl zqWfv6(!~<^VVl$lg1`1AoPQTA5SGW@bo9wXY}~JyTVc3CA0vLvTV_T(o@&nj-x%>@xW#ye1mUvu}}obT}SO@QhS z4pPiA-n3VRXS?8{jz&X;fmV&jdHQ{f-PvLK^=@C11Xz=qHQ?zvCP{8();(`tf^*UN3K3#)T^x%nKk*q!H!KTdQ=?JR`aP5lDU4(<8jkU(4rg7lE{qCSVVOYdaSl5R}raLw1*7s$9Z zIcAZ|`PQEsx0lqyPl$Fxz5;jKes-<1rO_%;iEqf4PZf89+MXR2C{8O228IR3eOOi* zWGs^a5)1}m zsx9y~?Z;eBE$!!#I+&B)Zoha~Q@qNy49rt-D`|z}At$`b%`5PrM>wPo8(tGDOV>dK#g)}H8{`7s8^!GQXAz-jN~ zG;Uj|s?u^?O-w45v%TYt+EET)MUy;!whc*CgT^@AmQ$Rjf?U7Xw@9}!Xfl!fY^=iG zIvzDN=Rm?(Jqsx0j>~vZ3>e7cZkA(xaBs;omD5LOloeUYR|-_rmyM7?|bc`)LwC%H!um7BkH7rkbHMLz1hxy zT`h&wIhmH_f!bN!Gu}JK>({9BF{R=cDtb3u^0?g4WruHLDYITXD`+_Nfrk;O+tIDy z(+f1Ut@th0#a`REn@<0~Y)&}&v?iGhCjZ_+i&nRw0KfXzD=H)hk6(y&e(r94cI*{k zMPO&o%ZCLYvr~U91}lz&g0Wa9j=M#$_wP+wrl-(fK9A?$b!kf%rHPV-zM186FZV6{ zg*0;HEFh7*G491K6iI6m$Qv<&{3(M+8CJgKR6%h(!a z`Z*5($ZE%h1`nHi8t+wXNys$$F4P8J1B_)pP*ZB(5JS~a2UNm&z`=kqFmi~hXXKg1 z-0==JHD`uwxpo2I*EmHLKK1mAGv7)R{w=oGW&x Date: Tue, 19 May 2015 17:25:28 +0200 Subject: [PATCH 02/23] take care of repeated fields in xml for profile --- product_profile_example/__openerp__.py | 4 +++- product_profile_example/product.profile.csv | 2 +- .../{product_product_data.xml => product_product_demo.xml} | 0 3 files changed, 4 insertions(+), 2 deletions(-) rename product_profile_example/{product_product_data.xml => product_product_demo.xml} (100%) diff --git a/product_profile_example/__openerp__.py b/product_profile_example/__openerp__.py index 494c24e1901..85dc242773c 100644 --- a/product_profile_example/__openerp__.py +++ b/product_profile_example/__openerp__.py @@ -36,7 +36,9 @@ 'website': 'http://www.akretion.com/', 'data': [ 'product.profile.csv', - 'product_product_data.xml', + ], + 'demo': [ + 'product_product_demo.xml', ], 'installable': True, 'license': 'AGPL-3', diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv index 96bd952d7ec..855038fcbc9 100644 --- a/product_profile_example/product.profile.csv +++ b/product_profile_example/product.profile.csv @@ -1,4 +1,4 @@ -"id","name","description","type","sale_ok","purchase_ok","available_in_pos","route_ids/id" +"id","name","explanation","type","sale_ok","purchase_ok","available_in_pos","route_ids/id" "own","My Own Type Saleable","- My own type - Saleable product - Not purchasable","product",1,0,1,"purchase.route_warehouse0_buy" diff --git a/product_profile_example/product_product_data.xml b/product_profile_example/product_product_demo.xml similarity index 100% rename from product_profile_example/product_product_data.xml rename to product_profile_example/product_product_demo.xml From 1f40fcf2e0d494f31695d4a2ed8a8f02d8f96533 Mon Sep 17 00:00:00 2001 From: David Beal Date: Mon, 22 Jun 2015 17:17:46 +0200 Subject: [PATCH 03/23] dynamically create search filters --- product_profile_example/__init__.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/product_profile_example/__init__.py b/product_profile_example/__init__.py index 0993b5c4a3d..7d966012f81 100644 --- a/product_profile_example/__init__.py +++ b/product_profile_example/__init__.py @@ -1,22 +1,2 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Author: David BEAL -# Copyright 2015 Akretion -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## from . import profile From 98325e57c0e883fe3c9e284185aeefcbb1106328 Mon Sep 17 00:00:00 2001 From: David Beal Date: Mon, 16 Nov 2015 19:36:33 +0100 Subject: [PATCH 04/23] doc + complete product_profile_example --- product_profile_example/README.rst | 3 +++ product_profile_example/__openerp__.py | 6 +++--- product_profile_example/product.profile.csv | 24 ++++++++++----------- product_profile_example/profile.py | 3 +++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/product_profile_example/README.rst b/product_profile_example/README.rst index c874bc1724a..06de4835065 100644 --- a/product_profile_example/README.rst +++ b/product_profile_example/README.rst @@ -26,7 +26,10 @@ Usage Create or modify a product template or a product variant. Assign a value to the profile field. Then, all fields which depend on this profile will be set to the right value at once. +Bug Tracker +=========== +See 'Bug tracker' in the README.rst of Product Profile module Credits ======= diff --git a/product_profile_example/__openerp__.py b/product_profile_example/__openerp__.py index 85dc242773c..e3ed29accbf 100644 --- a/product_profile_example/__openerp__.py +++ b/product_profile_example/__openerp__.py @@ -22,11 +22,11 @@ { 'name': 'Product Profile Example', 'summary': 'Product Profile Use Case', - 'version': '0.2', - 'author': 'Akretion', + 'version': '0.3', + 'author': 'Akretion, Odoo Community Association (OCA)', 'maintainer': 'Akretion', 'category': 'product', - 'description': 'see Product Profile module', + 'description': 'See Product Profile module', 'depends': [ 'product_profile', 'purchase', diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv index 855038fcbc9..c2aca309b96 100644 --- a/product_profile_example/product.profile.csv +++ b/product_profile_example/product.profile.csv @@ -1,20 +1,20 @@ -"id","name","explanation","type","sale_ok","purchase_ok","available_in_pos","route_ids/id" -"own","My Own Type Saleable","- My own type +id,name,explanation,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,route_ids/id +own,My Own Type Saleable,"- My own type - Saleable product -- Not purchasable","product",1,0,1,"purchase.route_warehouse0_buy" -"consu_prof","Consumable","- Consumable","consu",1,0,0,"purchase.route_warehouse0_buy" -"pos_pu_prof","POS & purchase","- Product in POS -- Product purchasable","product",1,1,1,"purchase.route_warehouse0_buy" -"manuf_prof","Manufacturing TO","- Manufacturing Product +- Not purchasable",product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy +consu_prof,Consumable,- Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy +pos_pu_prof,POS & purchase,"- Product in POS +- Product purchasable",product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy +manuf_prof,Manufacturing TO,"- Manufacturing Product - Make to order product - Not purchaseable -- Display on POS","product",1,0,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto" -"any_prof","Weird profile","- Purchasable +- Display on POS",product,1,0,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto" +any_prof,Weird profile,"- Purchasable - Display on POS -- Not Saleable","product",0,1,1, -"complete_prof","Complete profile","- Stockable product +- Not Saleable",product,0,1,product.product_category_all,1, +complete_prof,Complete profile,"- Stockable product - Saleable - Purchasable - Available in POS - MTO -- Manufacturable","product",1,1,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy" +- Manufacturable",product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy" diff --git a/product_profile_example/profile.py b/product_profile_example/profile.py index eac47fba847..b3ad57350fe 100644 --- a/product_profile_example/profile.py +++ b/product_profile_example/profile.py @@ -44,3 +44,6 @@ def _get_types(self): help="Depending on the modules installed, this will allow " "you to define the route of the product: " "whether it will be bought, manufactured, MTO/MTS,...") + profile_default_categ_id = fields.Many2one( + 'product.category', + string='Default category') From 916dc0178358b61ab9b23bd5978b4fd62d4d043f Mon Sep 17 00:00:00 2001 From: David Beal Date: Fri, 20 Nov 2015 11:29:27 +0100 Subject: [PATCH 05/23] OCA remarks --- product_profile_example/__init__.py | 1 - product_profile_example/__openerp__.py | 24 +++--------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/product_profile_example/__init__.py b/product_profile_example/__init__.py index 7d966012f81..8123cce2378 100644 --- a/product_profile_example/__init__.py +++ b/product_profile_example/__init__.py @@ -1,2 +1 @@ - from . import profile diff --git a/product_profile_example/__openerp__.py b/product_profile_example/__openerp__.py index e3ed29accbf..09d5e25b1ab 100644 --- a/product_profile_example/__openerp__.py +++ b/product_profile_example/__openerp__.py @@ -1,30 +1,12 @@ # coding: utf-8 -############################################################################## -# -# Author: David BEAL -# Copyright 2015 Akretion -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2015 David BEAL @ Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { 'name': 'Product Profile Example', 'summary': 'Product Profile Use Case', - 'version': '0.3', + 'version': '8.0.1.0.0', 'author': 'Akretion, Odoo Community Association (OCA)', - 'maintainer': 'Akretion', 'category': 'product', 'description': 'See Product Profile module', 'depends': [ From 1f928bd5b1dc0476e7bd9807fab9a6d596e745e2 Mon Sep 17 00:00:00 2001 From: David Beal Date: Tue, 16 Feb 2016 10:13:46 +0100 Subject: [PATCH 06/23] =?UTF-8?q?=C2=A0m2o=20field=20use=20in=20product=5F?= =?UTF-8?q?profile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- product_profile_example/product.profile.csv | 14 +++++++------- product_profile_example/profile.py | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv index c2aca309b96..bfd32982222 100644 --- a/product_profile_example/product.profile.csv +++ b/product_profile_example/product.profile.csv @@ -1,20 +1,20 @@ -id,name,explanation,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,route_ids/id +id,name,explanation,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,route_ids/id,product_manager/id own,My Own Type Saleable,"- My own type - Saleable product -- Not purchasable",product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy -consu_prof,Consumable,- Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy +- Not purchasable",product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,base.user_root +consu_prof,Consumable,- Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy, pos_pu_prof,POS & purchase,"- Product in POS -- Product purchasable",product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy +- Product purchasable",product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy, manuf_prof,Manufacturing TO,"- Manufacturing Product - Make to order product - Not purchaseable -- Display on POS",product,1,0,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto" +- Display on POS",product,1,0,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto",base.user_root any_prof,Weird profile,"- Purchasable - Display on POS -- Not Saleable",product,0,1,product.product_category_all,1, +- Not Saleable",product,0,1,product.product_category_all,1,,base.user_root complete_prof,Complete profile,"- Stockable product - Saleable - Purchasable - Available in POS - MTO -- Manufacturable",product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy" +- Manufacturable",product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy", diff --git a/product_profile_example/profile.py b/product_profile_example/profile.py index b3ad57350fe..3f2495643c8 100644 --- a/product_profile_example/profile.py +++ b/product_profile_example/profile.py @@ -47,3 +47,6 @@ def _get_types(self): profile_default_categ_id = fields.Many2one( 'product.category', string='Default category') + product_manager = fields.Many2one( + 'res.users', + string='Product Manager') From afae909151861631a1f65a7d61e164430a822e94 Mon Sep 17 00:00:00 2001 From: David Beal Date: Fri, 18 Mar 2016 16:18:37 +0100 Subject: [PATCH 07/23] make behavior homogeneous between onchange and import data on profile_default_ fields --- product_profile_example/__openerp__.py | 2 +- product_profile_example/product.profile.csv | 2 +- product_profile_example/profile.py | 23 +++------------------ 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/product_profile_example/__openerp__.py b/product_profile_example/__openerp__.py index 09d5e25b1ab..a9043068cda 100644 --- a/product_profile_example/__openerp__.py +++ b/product_profile_example/__openerp__.py @@ -5,7 +5,7 @@ { 'name': 'Product Profile Example', 'summary': 'Product Profile Use Case', - 'version': '8.0.1.0.0', + 'version': '8.0.1.0.1', 'author': 'Akretion, Odoo Community Association (OCA)', 'category': 'product', 'description': 'See Product Profile module', diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv index bfd32982222..a68a5dbd39b 100644 --- a/product_profile_example/product.profile.csv +++ b/product_profile_example/product.profile.csv @@ -1,4 +1,4 @@ -id,name,explanation,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,route_ids/id,product_manager/id +id,name,explanation,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,profile_default_route_ids/id,product_manager/id own,My Own Type Saleable,"- My own type - Saleable product - Not purchasable",product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,base.user_root diff --git a/product_profile_example/profile.py b/product_profile_example/profile.py index 3f2495643c8..6bcd354b811 100644 --- a/product_profile_example/profile.py +++ b/product_profile_example/profile.py @@ -1,23 +1,6 @@ # coding: utf-8 -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2014 Akretion (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2015 David BEAL @ Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields @@ -37,7 +20,7 @@ def _get_types(self): purchase_ok = fields.Boolean( string='Can be Purchased') available_in_pos = fields.Boolean() - route_ids = fields.Many2many( + profile_default_route_ids = fields.Many2many( 'stock.location.route', string='Routes', domain="[('product_selectable', '=', True)]", From 2543edf20b2d97fe9072075ed7a26739d6deaf39 Mon Sep 17 00:00:00 2001 From: David Beal Date: Sun, 20 Mar 2016 12:26:20 +0100 Subject: [PATCH 08/23] add test unit to product profile --- product_profile_example/product.profile.csv | 24 ++++---- product_profile_example/tests/__init__.py | 1 + product_profile_example/tests/test_profile.py | 60 +++++++++++++++++++ 3 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 product_profile_example/tests/__init__.py create mode 100644 product_profile_example/tests/test_profile.py diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv index a68a5dbd39b..9af03cab9e8 100644 --- a/product_profile_example/product.profile.csv +++ b/product_profile_example/product.profile.csv @@ -1,20 +1,20 @@ -id,name,explanation,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,profile_default_route_ids/id,product_manager/id -own,My Own Type Saleable,"- My own type +id,name,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,profile_default_route_ids/id,product_manager/id,explanation +own,My Own Type Saleable,product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,base.user_root,"- My own type - Saleable product -- Not purchasable",product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,base.user_root -consu_prof,Consumable,- Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy, -pos_pu_prof,POS & purchase,"- Product in POS -- Product purchasable",product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy, -manuf_prof,Manufacturing TO,"- Manufacturing Product +- Not purchasable" +consu_prof,Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy,,- Consumable +pos_pu_prof,POS & purchase,product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy,,"- Product in POS +- Product purchasable" +manuf_prof,Manufacturing TO,product,1,0,product.product_category_8,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto",base.user_root,"- Manufacturing Product - Make to order product - Not purchaseable -- Display on POS",product,1,0,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto",base.user_root -any_prof,Weird profile,"- Purchasable +- Display on POS" +any_prof,Weird profile,product,0,1,product.product_category_all,1,,base.user_root,"- Purchasable - Display on POS -- Not Saleable",product,0,1,product.product_category_all,1,,base.user_root -complete_prof,Complete profile,"- Stockable product +- Not Saleable" +complete_prof,Complete profile,product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy",,"- Stockable product - Saleable - Purchasable - Available in POS - MTO -- Manufacturable",product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy", +- Manufacturable" diff --git a/product_profile_example/tests/__init__.py b/product_profile_example/tests/__init__.py new file mode 100644 index 00000000000..19eed982853 --- /dev/null +++ b/product_profile_example/tests/__init__.py @@ -0,0 +1 @@ +from . import test_profile diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py new file mode 100644 index 00000000000..6c98691929d --- /dev/null +++ b/product_profile_example/tests/test_profile.py @@ -0,0 +1,60 @@ +# coding: utf-8 +# © 2016 David BEAL @ Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp.tests.common import TransactionCase + + +class TestProductProfile(TransactionCase): + def test_check_hard_disc_product(self): + # check route_ids + real_routes = [x.id for x in self.hard_disc_prd.route_ids] + theoritical_routes = [ + self.env.ref('mrp.route_warehouse0_manufacture').id, + self.env.ref('stock.route_warehouse0_mto').id, + ] + real_routes.sort() + theoritical_routes.sort() + self.assertEqual(real_routes, theoritical_routes) + # check categ_id + theoritical_categ_id = self.env.ref('product.product_category_8') + self.assertEqual(self.hard_disc_prd.categ_id.id, + theoritical_categ_id.id) + + def test_create_product(self): + name = 'only name is specified' + vals = {'profile_id': self.my_own_profile.id, + 'name': name} + new_product = self.prd_m.create(vals) + new_product._onchange_from_profile() + count_prd = self.prd_m.search([('name', '=', name)]) + self.assertEqual(len(count_prd), 1) + + def test_write_template(self): + vals = {'profile_id': self.my_own_profile.id} + self.analysis_tmpl.write(vals) + self.assertEqual(self.analysis_tmpl.profile_id, self.my_own_profile) + + def test_write_product(self): + vals = {'profile_id': self.my_own_profile.id} + self.analysis_prd.write(vals) + self.assertEqual(self.analysis_prd.profile_id, self.my_own_profile) + + def test_product_tmpl_fields_view_get(self): + view_id = self.env.ref('product.product_template_search_view').id + res = self.hard_disc_prd.fields_view_get( + view_id=view_id, view_type='search') + self.assertTrue('string="My Own Type Saleable"' in res['arch'], + 'string="My Own Type Saleable" must be in ' + 'fields_view_get() output') + + def setUp(self): + super(TestProductProfile, self).setUp() + self.prd_m = self.env['product.product'] + # product 'HDD SH-2' in demo data + self.hard_disc_prd = self.env.ref('product.product_product_18') + self.my_own_profile = self.env.ref('product_profile_example.own') + self.analysis_tmpl = self.env.ref( + 'point_of_sale.partner_product_11_product_template') + self.analysis_prd = self.env.ref( + 'point_of_sale.partner_product_11') From ee8befad115d38baa97a599bf8c3ffe29a444aba Mon Sep 17 00:00:00 2001 From: David Beal Date: Fri, 25 Mar 2016 16:26:42 +0100 Subject: [PATCH 09/23] ensure updated profile impact products --- product_profile_example/tests/test_profile.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index 6c98691929d..967a2a9a070 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -48,12 +48,22 @@ def test_product_tmpl_fields_view_get(self): 'string="My Own Type Saleable" must be in ' 'fields_view_get() output') + def test_impact_write_profile_model(self): + """If profile is updated, products must be written too + on profile depends fields""" + self.manufacturing_prof.write({'type': 'consu'}) + product = self.env['product.product'].search( + [('profile_id', '=', self.manufacturing_prof.id)])[0] + self.assertEqual(product.type, 'consu') + def setUp(self): super(TestProductProfile, self).setUp() self.prd_m = self.env['product.product'] # product 'HDD SH-2' in demo data self.hard_disc_prd = self.env.ref('product.product_product_18') self.my_own_profile = self.env.ref('product_profile_example.own') + self.manufacturing_prof = self.env.ref( + 'product_profile_example.manuf_prof') self.analysis_tmpl = self.env.ref( 'point_of_sale.partner_product_11_product_template') self.analysis_prd = self.env.ref( From c8d868e02b07eda784ed71b62bd7df9c878b9fae Mon Sep 17 00:00:00 2001 From: David Beal Date: Mon, 6 Jun 2016 12:50:55 +0200 Subject: [PATCH 10/23] profile when default in vals --- product_profile_example/tests/test_profile.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index 967a2a9a070..aa9c22a4536 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -56,6 +56,17 @@ def test_impact_write_profile_model(self): [('profile_id', '=', self.manufacturing_prof.id)])[0] self.assertEqual(product.type, 'consu') + def test_default_behavior(self): + """Check if field prefixed with default_profile + have a default behavior on field values""" + categ = self.env.ref('product.product_category_3') + consu_profile = self.env.ref('product_profile_example.consu_prof') + vals = {'profile_id': consu_profile.id, + 'categ_id': categ.id, + 'name': "Product with modified category"} + new_product = self.prd_m.create(vals) + self.assertEqual(new_product.categ_id, categ) + def setUp(self): super(TestProductProfile, self).setUp() self.prd_m = self.env['product.product'] From af1962f7ae880ab83bfa6165a53abc83296af860 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Tue, 29 Nov 2016 09:26:01 -0500 Subject: [PATCH 11/23] OCA Transbot updated translations from Transifex --- product_profile_example/i18n/sl.po | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 product_profile_example/i18n/sl.po diff --git a/product_profile_example/i18n/sl.po b/product_profile_example/i18n/sl.po new file mode 100644 index 00000000000..2bd3b72c053 --- /dev/null +++ b/product_profile_example/i18n/sl.po @@ -0,0 +1,63 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_profile_example +# +# Translators: +# Matjaž Mozetič , 2016 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-11-03 10:07+0000\n" +"PO-Revision-Date: 2016-11-03 10:07+0000\n" +"Last-Translator: Matjaž Mozetič , 2016\n" +"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: product_profile_example +#: field:product.profile,available_in_pos:0 +msgid "Available in pos" +msgstr "Na voljo v POS" + +#. module: product_profile_example +#: field:product.profile,purchase_ok:0 +msgid "Can be Purchased" +msgstr "Lahko se nabavi" + +#. module: product_profile_example +#: field:product.profile,sale_ok:0 +msgid "Can be Sold" +msgstr "Lahko se proda" + +#. module: product_profile_example +#: field:product.profile,profile_default_categ_id:0 +msgid "Default category" +msgstr "Privzeta kategorija" + +#. module: product_profile_example +#: help:product.profile,profile_default_route_ids:0 +msgid "" +"Depending on the modules installed, this will allow you to define the route " +"of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "" +"Glede na nameščene module omogoča določitev proge proizvoda: kupljen, " +"proizveden, po naročilu..." + +#. module: product_profile_example +#: field:product.profile,product_manager:0 +msgid "Product Manager" +msgstr "Upravitelj proizvoda" + +#. module: product_profile_example +#: field:product.profile,profile_default_route_ids:0 +msgid "Routes" +msgstr "Proge" + +#. module: product_profile_example +#: help:product.profile,sale_ok:0 +msgid "Specify if the product can be selected in a sales order line." +msgstr "Določa, če se proizvod lahko izbere v postavki prodajnega naloga." From 0a00aeb6215057759d9cfc3c59bd1fd4b3ccb96e Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Fri, 3 Mar 2017 23:34:53 -0500 Subject: [PATCH 12/23] OCA Transbot updated translations from Transifex --- product_profile_example/i18n/de.po | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 product_profile_example/i18n/de.po diff --git a/product_profile_example/i18n/de.po b/product_profile_example/i18n/de.po new file mode 100644 index 00000000000..3e2135e4ce6 --- /dev/null +++ b/product_profile_example/i18n/de.po @@ -0,0 +1,64 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_profile_example +# +# Translators: +# Rudolf Schnapka , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-01 13:35+0000\n" +"PO-Revision-Date: 2017-03-01 13:35+0000\n" +"Last-Translator: Rudolf Schnapka , 2017\n" +"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: product_profile_example +#: field:product.profile,available_in_pos:0 +msgid "Available in pos" +msgstr "Verfügbar in POS/Kasse" + +#. module: product_profile_example +#: field:product.profile,purchase_ok:0 +msgid "Can be Purchased" +msgstr "Kann eingekauft werden" + +#. module: product_profile_example +#: field:product.profile,sale_ok:0 +msgid "Can be Sold" +msgstr "Kann verkauft werden" + +#. module: product_profile_example +#: field:product.profile,profile_default_categ_id:0 +msgid "Default category" +msgstr "Vorgabe-Kategorie" + +#. module: product_profile_example +#: help:product.profile,profile_default_route_ids:0 +msgid "" +"Depending on the modules installed, this will allow you to define the route " +"of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "" +"Abhängig von installierten Modulen, wird Ihnen hiermit die Festlegung des " +"Routings für das Produkt ermöglicht: Ob es erworben oder hergestellt wird, " +"Auftrags-/Lagerbeschaffung, ..." + +#. module: product_profile_example +#: field:product.profile,product_manager:0 +msgid "Product Manager" +msgstr "Produkt-Manager" + +#. module: product_profile_example +#: field:product.profile,profile_default_route_ids:0 +msgid "Routes" +msgstr "Routen" + +#. module: product_profile_example +#: help:product.profile,sale_ok:0 +msgid "Specify if the product can be selected in a sales order line." +msgstr "" From ff762573797645b1e4c687b4dacde7dd3eaf4561 Mon Sep 17 00:00:00 2001 From: MonsieurB Date: Fri, 31 Mar 2017 10:25:52 +0200 Subject: [PATCH 13/23] mig V10 --- product_profile_example/README.rst | 5 ++-- product_profile_example/__init__.py | 4 +++ .../{__openerp__.py => __manifest__.py} | 2 +- product_profile_example/product.profile.csv | 14 ++++----- .../product_product_demo.xml | 30 +++++++++---------- product_profile_example/profile.py | 11 ++----- product_profile_example/tests/__init__.py | 4 +++ product_profile_example/tests/test_profile.py | 15 ++++++---- 8 files changed, 44 insertions(+), 41 deletions(-) rename product_profile_example/{__openerp__.py => __manifest__.py} (95%) diff --git a/product_profile_example/README.rst b/product_profile_example/README.rst index 06de4835065..2c862f3ce24 100644 --- a/product_profile_example/README.rst +++ b/product_profile_example/README.rst @@ -1,6 +1,7 @@ .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg :alt: License: AGPL-3 +======================= Product Profile Example ======================= @@ -15,8 +16,8 @@ Configuration Optionnaly: -* Settings > Configuration > General Settings: check 'Display Profile fields' and apply - (only if you want display hidden fields) +* Settings > Configuration > General Settings: check 'Display fields in Profile' and apply + (only if you want display hidden fields set by profile git ) diff --git a/product_profile_example/__init__.py b/product_profile_example/__init__.py index 8123cce2378..b1170fe3f80 100644 --- a/product_profile_example/__init__.py +++ b/product_profile_example/__init__.py @@ -1 +1,5 @@ +# coding: utf-8 +# © 2015 David BEAL @ Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from . import profile diff --git a/product_profile_example/__openerp__.py b/product_profile_example/__manifest__.py similarity index 95% rename from product_profile_example/__openerp__.py rename to product_profile_example/__manifest__.py index a9043068cda..b4cadf3492c 100644 --- a/product_profile_example/__openerp__.py +++ b/product_profile_example/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Product Profile Example', 'summary': 'Product Profile Use Case', - 'version': '8.0.1.0.1', + 'version': '10.0.1.0.1', 'author': 'Akretion, Odoo Community Association (OCA)', 'category': 'product', 'description': 'See Product Profile module', diff --git a/product_profile_example/product.profile.csv b/product_profile_example/product.profile.csv index 9af03cab9e8..0a7c0330c08 100644 --- a/product_profile_example/product.profile.csv +++ b/product_profile_example/product.profile.csv @@ -1,18 +1,18 @@ -id,name,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,profile_default_route_ids/id,product_manager/id,explanation -own,My Own Type Saleable,product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,base.user_root,"- My own type +id,name,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,profile_default_route_ids/id,explanation +own,My Own Type Saleable,product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,"- My own type - Saleable product - Not purchasable" -consu_prof,Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy,,- Consumable -pos_pu_prof,POS & purchase,product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy,,"- Product in POS +consu_prof,Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy,"- Consumable" +pos_pu_prof,POS & purchase,product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy,"- Product in POS - Product purchasable" -manuf_prof,Manufacturing TO,product,1,0,product.product_category_8,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto",base.user_root,"- Manufacturing Product +manuf_prof,Manufacturing TO,product,1,0,product.product_category_5,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto","- Manufacturing Product - Make to order product - Not purchaseable - Display on POS" -any_prof,Weird profile,product,0,1,product.product_category_all,1,,base.user_root,"- Purchasable +any_prof,Weird profile,product,0,1,product.product_category_all,1,,"- Purchasable - Display on POS - Not Saleable" -complete_prof,Complete profile,product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy",,"- Stockable product +complete_prof,Complete profile,product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy","- Stockable product - Saleable - Purchasable - Available in POS diff --git a/product_profile_example/product_product_demo.xml b/product_profile_example/product_product_demo.xml index 019009cc9d6..5fe546c52ce 100644 --- a/product_profile_example/product_product_demo.xml +++ b/product_profile_example/product_product_demo.xml @@ -1,24 +1,22 @@ - - + - - - + + + - - - + + + - - - + + + - - - + + + - - + diff --git a/product_profile_example/profile.py b/product_profile_example/profile.py index 6bcd354b811..61bcb2e7d28 100644 --- a/product_profile_example/profile.py +++ b/product_profile_example/profile.py @@ -2,17 +2,13 @@ # © 2015 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from openerp import models, fields +from odoo import models, fields class ProductProfile(models.Model): _inherit = 'product.profile' - def _get_types(self): - return [('product', 'Stockable Product'), - ('consu', 'Consumable'), - ('service', 'Service')] + type = fields.Selection(selection_add=[('product', 'Stockable Product')]) sale_ok = fields.Boolean( string='Can be Sold', @@ -30,6 +26,3 @@ def _get_types(self): profile_default_categ_id = fields.Many2one( 'product.category', string='Default category') - product_manager = fields.Many2one( - 'res.users', - string='Product Manager') diff --git a/product_profile_example/tests/__init__.py b/product_profile_example/tests/__init__.py index 19eed982853..a9e8b12e870 100644 --- a/product_profile_example/tests/__init__.py +++ b/product_profile_example/tests/__init__.py @@ -1 +1,5 @@ +# coding: utf-8 +# © 2015 David BEAL @ Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from . import test_profile diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index aa9c22a4536..733ace85f9d 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -2,10 +2,11 @@ # © 2016 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp.tests.common import TransactionCase +from odoo.tests.common import TransactionCase class TestProductProfile(TransactionCase): + def test_check_hard_disc_product(self): # check route_ids real_routes = [x.id for x in self.hard_disc_prd.route_ids] @@ -17,7 +18,7 @@ def test_check_hard_disc_product(self): theoritical_routes.sort() self.assertEqual(real_routes, theoritical_routes) # check categ_id - theoritical_categ_id = self.env.ref('product.product_category_8') + theoritical_categ_id = self.theoritical_categ_id self.assertEqual(self.hard_disc_prd.categ_id.id, theoritical_categ_id.id) @@ -59,7 +60,7 @@ def test_impact_write_profile_model(self): def test_default_behavior(self): """Check if field prefixed with default_profile have a default behavior on field values""" - categ = self.env.ref('product.product_category_3') + categ = self.categ consu_profile = self.env.ref('product_profile_example.consu_prof') vals = {'profile_id': consu_profile.id, 'categ_id': categ.id, @@ -71,11 +72,13 @@ def setUp(self): super(TestProductProfile, self).setUp() self.prd_m = self.env['product.product'] # product 'HDD SH-2' in demo data - self.hard_disc_prd = self.env.ref('product.product_product_18') + self.hard_disc_prd = self.env.ref('product.product_product_17') self.my_own_profile = self.env.ref('product_profile_example.own') self.manufacturing_prof = self.env.ref( 'product_profile_example.manuf_prof') self.analysis_tmpl = self.env.ref( - 'point_of_sale.partner_product_11_product_template') + 'point_of_sale.partner_product_7_product_template') self.analysis_prd = self.env.ref( - 'point_of_sale.partner_product_11') + 'point_of_sale.partner_product_7') + self.theoritical_categ_id = self.env.ref('product.product_category_5') + self.categ = self.env.ref('product.product_category_3') From 8a2112d2473eb8dfea3e257bdb9bab8ec7147fbb Mon Sep 17 00:00:00 2001 From: MonsieurB Date: Thu, 4 May 2017 18:11:15 +0200 Subject: [PATCH 14/23] code reviews --- product_profile_example/tests/test_profile.py | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index 733ace85f9d..bf926676135 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -7,6 +7,21 @@ class TestProductProfile(TransactionCase): + def setUp(self): + super(TestProductProfile, self).setUp() + self.prd_m = self.env['product.product'] + # product 'HDD SH-2' in demo data + self.hard_disc_prd = self.env.ref('product.product_product_17') + self.my_own_profile = self.env.ref('product_profile_example.own') + self.manufacturing_prof = self.env.ref( + 'product_profile_example.manuf_prof') + self.analysis_tmpl = self.env.ref( + 'point_of_sale.partner_product_7_product_template') + self.analysis_prd = self.env.ref( + 'point_of_sale.partner_product_7') + self.theoritical_categ_id = self.env.ref('product.product_category_5') + self.categ = self.env.ref('product.product_category_3') + def test_check_hard_disc_product(self): # check route_ids real_routes = [x.id for x in self.hard_disc_prd.route_ids] @@ -68,17 +83,3 @@ def test_default_behavior(self): new_product = self.prd_m.create(vals) self.assertEqual(new_product.categ_id, categ) - def setUp(self): - super(TestProductProfile, self).setUp() - self.prd_m = self.env['product.product'] - # product 'HDD SH-2' in demo data - self.hard_disc_prd = self.env.ref('product.product_product_17') - self.my_own_profile = self.env.ref('product_profile_example.own') - self.manufacturing_prof = self.env.ref( - 'product_profile_example.manuf_prof') - self.analysis_tmpl = self.env.ref( - 'point_of_sale.partner_product_7_product_template') - self.analysis_prd = self.env.ref( - 'point_of_sale.partner_product_7') - self.theoritical_categ_id = self.env.ref('product.product_category_5') - self.categ = self.env.ref('product.product_category_3') From 1a3be4100ae5bc61925a1ca3d2c9e26804c2e666 Mon Sep 17 00:00:00 2001 From: MonsieurB Date: Fri, 12 May 2017 10:40:30 +0200 Subject: [PATCH 15/23] code review --- product_profile_example/__manifest__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/product_profile_example/__manifest__.py b/product_profile_example/__manifest__.py index b4cadf3492c..0f6dbbc6b87 100644 --- a/product_profile_example/__manifest__.py +++ b/product_profile_example/__manifest__.py @@ -8,7 +8,6 @@ 'version': '10.0.1.0.1', 'author': 'Akretion, Odoo Community Association (OCA)', 'category': 'product', - 'description': 'See Product Profile module', 'depends': [ 'product_profile', 'purchase', From e3512b1820162a92968974aa60b30ad2cb898148 Mon Sep 17 00:00:00 2001 From: Mourad Date: Mon, 11 Dec 2017 16:17:20 +0100 Subject: [PATCH 16/23] [FIX] pylint --- product_profile_example/tests/test_profile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index bf926676135..d3a3a58ad1b 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -82,4 +82,3 @@ def test_default_behavior(self): 'name': "Product with modified category"} new_product = self.prd_m.create(vals) self.assertEqual(new_product.categ_id, categ) - From 5fed1138673dabd2854200b14ced71046e62b516 Mon Sep 17 00:00:00 2001 From: David Beal Date: Fri, 26 Jan 2018 16:48:20 +0100 Subject: [PATCH 17/23] FIX profile example, move csv to demo --- product_profile_example/__manifest__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/product_profile_example/__manifest__.py b/product_profile_example/__manifest__.py index 0f6dbbc6b87..8bf3d470562 100644 --- a/product_profile_example/__manifest__.py +++ b/product_profile_example/__manifest__.py @@ -15,10 +15,8 @@ 'mrp', ], 'website': 'http://www.akretion.com/', - 'data': [ - 'product.profile.csv', - ], 'demo': [ + 'product.profile.csv', 'product_product_demo.xml', ], 'installable': True, From 722a29ec501c673870e0ef551b1da65ca25c17b1 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 27 Jan 2018 09:40:49 +0100 Subject: [PATCH 18/23] OCA Transbot updated translations from Transifex --- product_profile_example/i18n/de.po | 34 +++++++++++++++--------------- product_profile_example/i18n/sl.po | 34 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/product_profile_example/i18n/de.po b/product_profile_example/i18n/de.po index 3e2135e4ce6..a8679934f4f 100644 --- a/product_profile_example/i18n/de.po +++ b/product_profile_example/i18n/de.po @@ -3,14 +3,14 @@ # * product_profile_example # # Translators: -# Rudolf Schnapka , 2017 +# OCA Transbot , 2018 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-03-01 13:35+0000\n" -"PO-Revision-Date: 2017-03-01 13:35+0000\n" -"Last-Translator: Rudolf Schnapka , 2017\n" +"POT-Creation-Date: 2018-01-27 03:49+0000\n" +"PO-Revision-Date: 2018-01-27 03:49+0000\n" +"Last-Translator: OCA Transbot , 2018\n" "Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,27 +19,27 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: product_profile_example -#: field:product.profile,available_in_pos:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos msgid "Available in pos" msgstr "Verfügbar in POS/Kasse" #. module: product_profile_example -#: field:product.profile,purchase_ok:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_purchase_ok msgid "Can be Purchased" msgstr "Kann eingekauft werden" #. module: product_profile_example -#: field:product.profile,sale_ok:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_sale_ok msgid "Can be Sold" msgstr "Kann verkauft werden" #. module: product_profile_example -#: field:product.profile,profile_default_categ_id:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_categ_id msgid "Default category" msgstr "Vorgabe-Kategorie" #. module: product_profile_example -#: help:product.profile,profile_default_route_ids:0 +#: model:ir.model.fields,help:product_profile_example.field_product_profile_profile_default_route_ids msgid "" "Depending on the modules installed, this will allow you to define the route " "of the product: whether it will be bought, manufactured, MTO/MTS,..." @@ -49,16 +49,16 @@ msgstr "" "Auftrags-/Lagerbeschaffung, ..." #. module: product_profile_example -#: field:product.profile,product_manager:0 -msgid "Product Manager" -msgstr "Produkt-Manager" - -#. module: product_profile_example -#: field:product.profile,profile_default_route_ids:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids msgid "Routes" msgstr "Routen" #. module: product_profile_example -#: help:product.profile,sale_ok:0 +#: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok msgid "Specify if the product can be selected in a sales order line." msgstr "" + +#. module: product_profile_example +#: model:ir.model,name:product_profile_example.model_product_profile +msgid "product.profile" +msgstr "" diff --git a/product_profile_example/i18n/sl.po b/product_profile_example/i18n/sl.po index 2bd3b72c053..01f14a9ac26 100644 --- a/product_profile_example/i18n/sl.po +++ b/product_profile_example/i18n/sl.po @@ -3,14 +3,14 @@ # * product_profile_example # # Translators: -# Matjaž Mozetič , 2016 +# OCA Transbot , 2018 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-11-03 10:07+0000\n" -"PO-Revision-Date: 2016-11-03 10:07+0000\n" -"Last-Translator: Matjaž Mozetič , 2016\n" +"POT-Creation-Date: 2018-01-27 03:49+0000\n" +"PO-Revision-Date: 2018-01-27 03:49+0000\n" +"Last-Translator: OCA Transbot , 2018\n" "Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,27 +19,27 @@ msgstr "" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" #. module: product_profile_example -#: field:product.profile,available_in_pos:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos msgid "Available in pos" msgstr "Na voljo v POS" #. module: product_profile_example -#: field:product.profile,purchase_ok:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_purchase_ok msgid "Can be Purchased" msgstr "Lahko se nabavi" #. module: product_profile_example -#: field:product.profile,sale_ok:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_sale_ok msgid "Can be Sold" msgstr "Lahko se proda" #. module: product_profile_example -#: field:product.profile,profile_default_categ_id:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_categ_id msgid "Default category" msgstr "Privzeta kategorija" #. module: product_profile_example -#: help:product.profile,profile_default_route_ids:0 +#: model:ir.model.fields,help:product_profile_example.field_product_profile_profile_default_route_ids msgid "" "Depending on the modules installed, this will allow you to define the route " "of the product: whether it will be bought, manufactured, MTO/MTS,..." @@ -48,16 +48,16 @@ msgstr "" "proizveden, po naročilu..." #. module: product_profile_example -#: field:product.profile,product_manager:0 -msgid "Product Manager" -msgstr "Upravitelj proizvoda" - -#. module: product_profile_example -#: field:product.profile,profile_default_route_ids:0 +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids msgid "Routes" msgstr "Proge" #. module: product_profile_example -#: help:product.profile,sale_ok:0 +#: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok msgid "Specify if the product can be selected in a sales order line." msgstr "Določa, če se proizvod lahko izbere v postavki prodajnega naloga." + +#. module: product_profile_example +#: model:ir.model,name:product_profile_example.model_product_profile +msgid "product.profile" +msgstr "" From 43cf2be1e4e7a5915868a1c334b53522c222c0ec Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 3 Mar 2018 10:22:24 +0100 Subject: [PATCH 19/23] OCA Transbot updated translations from Transifex --- product_profile_example/i18n/de.po | 11 +++-- product_profile_example/i18n/es.po | 61 +++++++++++++++++++++++++++ product_profile_example/i18n/fr.po | 66 ++++++++++++++++++++++++++++++ product_profile_example/i18n/hr.po | 63 ++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 product_profile_example/i18n/es.po create mode 100644 product_profile_example/i18n/fr.po create mode 100644 product_profile_example/i18n/hr.po diff --git a/product_profile_example/i18n/de.po b/product_profile_example/i18n/de.po index a8679934f4f..5531beef033 100644 --- a/product_profile_example/i18n/de.po +++ b/product_profile_example/i18n/de.po @@ -4,13 +4,14 @@ # # Translators: # OCA Transbot , 2018 +# Rudolf Schnapka , 2018 msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-01-27 03:49+0000\n" -"PO-Revision-Date: 2018-01-27 03:49+0000\n" -"Last-Translator: OCA Transbot , 2018\n" +"POT-Creation-Date: 2018-01-29 08:49+0000\n" +"PO-Revision-Date: 2018-01-29 08:49+0000\n" +"Last-Translator: Rudolf Schnapka , 2018\n" "Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -57,8 +58,10 @@ msgstr "Routen" #: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok msgid "Specify if the product can be selected in a sales order line." msgstr "" +"Geben Sie an, ob das Produkt in einer Verkaufsauftragsposition ausgewählt " +"werden darf." #. module: product_profile_example #: model:ir.model,name:product_profile_example.model_product_profile msgid "product.profile" -msgstr "" +msgstr "product.profile" diff --git a/product_profile_example/i18n/es.po b/product_profile_example/i18n/es.po new file mode 100644 index 00000000000..8aa832fdc10 --- /dev/null +++ b/product_profile_example/i18n/es.po @@ -0,0 +1,61 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_profile_example +# +# Translators: +# enjolras , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-29 08:49+0000\n" +"PO-Revision-Date: 2018-01-29 08:49+0000\n" +"Last-Translator: enjolras , 2018\n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos +msgid "Available in pos" +msgstr "Disponible en TPV" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_purchase_ok +msgid "Can be Purchased" +msgstr "Se puede comprar" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_sale_ok +msgid "Can be Sold" +msgstr "Se puede vender" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_categ_id +msgid "Default category" +msgstr "Categoría predeterminada" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_profile_default_route_ids +msgid "" +"Depending on the modules installed, this will allow you to define the route " +"of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids +msgid "Routes" +msgstr "Rutas" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok +msgid "Specify if the product can be selected in a sales order line." +msgstr "" + +#. module: product_profile_example +#: model:ir.model,name:product_profile_example.model_product_profile +msgid "product.profile" +msgstr "product.profile" diff --git a/product_profile_example/i18n/fr.po b/product_profile_example/i18n/fr.po new file mode 100644 index 00000000000..95a047d2a96 --- /dev/null +++ b/product_profile_example/i18n/fr.po @@ -0,0 +1,66 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_profile_example +# +# Translators: +# Quentin THEURET , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-29 08:49+0000\n" +"PO-Revision-Date: 2018-01-29 08:49+0000\n" +"Last-Translator: Quentin THEURET , 2018\n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos +msgid "Available in pos" +msgstr "Disponible dans le PdV" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_purchase_ok +msgid "Can be Purchased" +msgstr "Peut être acheté" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_sale_ok +msgid "Can be Sold" +msgstr "Peut être vendu" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_categ_id +msgid "Default category" +msgstr "Catégorie par défaut" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_profile_default_route_ids +msgid "" +"Depending on the modules installed, this will allow you to define the route " +"of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "" +"En fonction des modules installés, ceci va vous autoriser à définir la route" +" du produit : si il peut être acheté, fabriqué, approvisionné à la commande," +" approvisionné sur stock,..." + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids +msgid "Routes" +msgstr "Routes" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok +msgid "Specify if the product can be selected in a sales order line." +msgstr "" +"Détermine si le produit peut être sélectionné dans les lignes de commandes " +"de vente." + +#. module: product_profile_example +#: model:ir.model,name:product_profile_example.model_product_profile +msgid "product.profile" +msgstr "product.profile" diff --git a/product_profile_example/i18n/hr.po b/product_profile_example/i18n/hr.po new file mode 100644 index 00000000000..c10b5e97998 --- /dev/null +++ b/product_profile_example/i18n/hr.po @@ -0,0 +1,63 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_profile_example +# +# Translators: +# Bole , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-29 08:49+0000\n" +"PO-Revision-Date: 2018-01-29 08:49+0000\n" +"Last-Translator: Bole , 2018\n" +"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos +msgid "Available in pos" +msgstr "Dostupno u POS-u" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_purchase_ok +msgid "Can be Purchased" +msgstr "Može se nabaviti" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_sale_ok +msgid "Can be Sold" +msgstr "Može se prodavati" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_categ_id +msgid "Default category" +msgstr "Zadana kategorija" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_profile_default_route_ids +msgid "" +"Depending on the modules installed, this will allow you to define the route " +"of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "" +"Ovisno o instaliranim modulima, ovo će vam omogućiti da definirate rute na " +"proizvodu: može li se kupiti, proizvoesti, MTO/MTS..." + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids +msgid "Routes" +msgstr "Rute" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok +msgid "Specify if the product can be selected in a sales order line." +msgstr "Označava može li se proizvod odabrati u stavkama ponuda" + +#. module: product_profile_example +#: model:ir.model,name:product_profile_example.model_product_profile +msgid "product.profile" +msgstr "product.profile" From 36fa52ff62c9bb90a2bee398a1ad3ec365204ba5 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Sat, 23 Jun 2018 18:32:08 +0000 Subject: [PATCH 20/23] [UPD] Update product_profile_example.pot --- product_profile_example/i18n/de.po | 4 +- product_profile_example/i18n/es.po | 4 +- product_profile_example/i18n/fr.po | 10 ++-- product_profile_example/i18n/hr.po | 7 ++- .../i18n/product_profile_example.pot | 55 +++++++++++++++++++ product_profile_example/i18n/sl.po | 7 ++- 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 product_profile_example/i18n/product_profile_example.pot diff --git a/product_profile_example/i18n/de.po b/product_profile_example/i18n/de.po index 5531beef033..875960657df 100644 --- a/product_profile_example/i18n/de.po +++ b/product_profile_example/i18n/de.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * product_profile_example -# +# # Translators: # OCA Transbot , 2018 # Rudolf Schnapka , 2018 @@ -13,10 +13,10 @@ msgstr "" "PO-Revision-Date: 2018-01-29 08:49+0000\n" "Last-Translator: Rudolf Schnapka , 2018\n" "Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: product_profile_example diff --git a/product_profile_example/i18n/es.po b/product_profile_example/i18n/es.po index 8aa832fdc10..c529be91903 100644 --- a/product_profile_example/i18n/es.po +++ b/product_profile_example/i18n/es.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * product_profile_example -# +# # Translators: # enjolras , 2018 msgid "" @@ -12,10 +12,10 @@ msgstr "" "PO-Revision-Date: 2018-01-29 08:49+0000\n" "Last-Translator: enjolras , 2018\n" "Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: product_profile_example diff --git a/product_profile_example/i18n/fr.po b/product_profile_example/i18n/fr.po index 95a047d2a96..b52fba6d7a5 100644 --- a/product_profile_example/i18n/fr.po +++ b/product_profile_example/i18n/fr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * product_profile_example -# +# # Translators: # Quentin THEURET , 2018 msgid "" @@ -12,10 +12,10 @@ msgstr "" "PO-Revision-Date: 2018-01-29 08:49+0000\n" "Last-Translator: Quentin THEURET , 2018\n" "Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. module: product_profile_example @@ -44,9 +44,9 @@ msgid "" "Depending on the modules installed, this will allow you to define the route " "of the product: whether it will be bought, manufactured, MTO/MTS,..." msgstr "" -"En fonction des modules installés, ceci va vous autoriser à définir la route" -" du produit : si il peut être acheté, fabriqué, approvisionné à la commande," -" approvisionné sur stock,..." +"En fonction des modules installés, ceci va vous autoriser à définir la route " +"du produit : si il peut être acheté, fabriqué, approvisionné à la commande, " +"approvisionné sur stock,..." #. module: product_profile_example #: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids diff --git a/product_profile_example/i18n/hr.po b/product_profile_example/i18n/hr.po index c10b5e97998..a52c51c265e 100644 --- a/product_profile_example/i18n/hr.po +++ b/product_profile_example/i18n/hr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * product_profile_example -# +# # Translators: # Bole , 2018 msgid "" @@ -12,11 +12,12 @@ msgstr "" "PO-Revision-Date: 2018-01-29 08:49+0000\n" "Last-Translator: Bole , 2018\n" "Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" +"Language: hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: hr\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #. module: product_profile_example #: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos diff --git a/product_profile_example/i18n/product_profile_example.pot b/product_profile_example/i18n/product_profile_example.pot new file mode 100644 index 00000000000..c22397377de --- /dev/null +++ b/product_profile_example/i18n/product_profile_example.pot @@ -0,0 +1,55 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_profile_example +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.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: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos +msgid "Available in pos" +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_purchase_ok +msgid "Can be Purchased" +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_sale_ok +msgid "Can be Sold" +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_categ_id +msgid "Default category" +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_profile_default_route_ids +msgid "Depending on the modules installed, this will allow you to define the route of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids +msgid "Routes" +msgstr "" + +#. module: product_profile_example +#: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok +msgid "Specify if the product can be selected in a sales order line." +msgstr "" + +#. module: product_profile_example +#: model:ir.model,name:product_profile_example.model_product_profile +msgid "product.profile" +msgstr "" + diff --git a/product_profile_example/i18n/sl.po b/product_profile_example/i18n/sl.po index 01f14a9ac26..b88cf779992 100644 --- a/product_profile_example/i18n/sl.po +++ b/product_profile_example/i18n/sl.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * product_profile_example -# +# # Translators: # OCA Transbot , 2018 msgid "" @@ -12,11 +12,12 @@ msgstr "" "PO-Revision-Date: 2018-01-27 03:49+0000\n" "Last-Translator: OCA Transbot , 2018\n" "Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: sl\n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" #. module: product_profile_example #: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos From 5a843055d088b523acc581a65cb2a68a206a3d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marta=20V=C3=A1zquez=20Rodr=C3=ADguez?= Date: Fri, 8 Feb 2019 11:11:28 +0000 Subject: [PATCH 21/23] Translated using Weblate (Spanish) Currently translated at 100.0% (8 of 8 strings) Translation: product-attribute-10.0/product-attribute-10.0-product_profile_example Translate-URL: https://translation.odoo-community.org/projects/product-attribute-10-0/product-attribute-10-0-product_profile_example/es/ --- product_profile_example/i18n/es.po | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/product_profile_example/i18n/es.po b/product_profile_example/i18n/es.po index c529be91903..4abd80a3bd0 100644 --- a/product_profile_example/i18n/es.po +++ b/product_profile_example/i18n/es.po @@ -9,14 +9,15 @@ msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-01-29 08:49+0000\n" -"PO-Revision-Date: 2018-01-29 08:49+0000\n" -"Last-Translator: enjolras , 2018\n" +"PO-Revision-Date: 2019-02-08 13:50+0000\n" +"Last-Translator: Marta Vázquez Rodríguez \n" "Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.4\n" #. module: product_profile_example #: model:ir.model.fields,field_description:product_profile_example.field_product_profile_available_in_pos @@ -44,6 +45,8 @@ msgid "" "Depending on the modules installed, this will allow you to define the route " "of the product: whether it will be bought, manufactured, MTO/MTS,..." msgstr "" +"Dependiendo de los módulos instalados, esto le permitirá definir la ruta del " +"producto: si se va comprar, manufacturado, MTO, MTS,..." #. module: product_profile_example #: model:ir.model.fields,field_description:product_profile_example.field_product_profile_profile_default_route_ids @@ -54,6 +57,8 @@ msgstr "Rutas" #: model:ir.model.fields,help:product_profile_example.field_product_profile_sale_ok msgid "Specify if the product can be selected in a sales order line." msgstr "" +"Especifica si el producto puede ser seleccionado en la línea del pedido de " +"venta." #. module: product_profile_example #: model:ir.model,name:product_profile_example.model_product_profile From b16d227f86e35f7d0bfb1694ad459459f65f2798 Mon Sep 17 00:00:00 2001 From: Kevin Khao Date: Tue, 11 Feb 2020 11:30:47 +0100 Subject: [PATCH 22/23] [IMP] product_profile_example: black, structure change --- product_profile_example/__init__.py | 3 +- product_profile_example/__manifest__.py | 29 +++----- .../{ => demo}/product.profile.csv | 0 .../{ => demo}/product_product_demo.xml | 0 product_profile_example/models/__init__.py | 4 + .../{ => models}/profile.py | 26 +++---- product_profile_example/tests/__init__.py | 1 - product_profile_example/tests/test_profile.py | 73 ++++++++++--------- 8 files changed, 67 insertions(+), 69 deletions(-) rename product_profile_example/{ => demo}/product.profile.csv (100%) rename product_profile_example/{ => demo}/product_product_demo.xml (100%) create mode 100644 product_profile_example/models/__init__.py rename product_profile_example/{ => models}/profile.py (52%) diff --git a/product_profile_example/__init__.py b/product_profile_example/__init__.py index b1170fe3f80..19d563ef687 100644 --- a/product_profile_example/__init__.py +++ b/product_profile_example/__init__.py @@ -1,5 +1,4 @@ -# coding: utf-8 # © 2015 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import profile +from . import models diff --git a/product_profile_example/__manifest__.py b/product_profile_example/__manifest__.py index 8bf3d470562..576ce054781 100644 --- a/product_profile_example/__manifest__.py +++ b/product_profile_example/__manifest__.py @@ -1,24 +1,15 @@ -# coding: utf-8 # © 2015 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'Product Profile Example', - 'summary': 'Product Profile Use Case', - 'version': '10.0.1.0.1', - 'author': 'Akretion, Odoo Community Association (OCA)', - 'category': 'product', - 'depends': [ - 'product_profile', - 'purchase', - 'point_of_sale', - 'mrp', - ], - 'website': 'http://www.akretion.com/', - 'demo': [ - 'product.profile.csv', - 'product_product_demo.xml', - ], - 'installable': True, - 'license': 'AGPL-3', + "name": "Product Profile Example", + "summary": "Product Profile Use Case", + "version": "10.0.1.0.1", + "author": "Akretion, Odoo Community Association (OCA)", + "category": "product", + "depends": ["product_profile", "purchase", "point_of_sale", "mrp",], + "website": "http://www.akretion.com/", + "demo": ["demo/product.profile.csv", "demo/product_product_demo.xml",], + "installable": True, + "license": "AGPL-3", } diff --git a/product_profile_example/product.profile.csv b/product_profile_example/demo/product.profile.csv similarity index 100% rename from product_profile_example/product.profile.csv rename to product_profile_example/demo/product.profile.csv diff --git a/product_profile_example/product_product_demo.xml b/product_profile_example/demo/product_product_demo.xml similarity index 100% rename from product_profile_example/product_product_demo.xml rename to product_profile_example/demo/product_product_demo.xml diff --git a/product_profile_example/models/__init__.py b/product_profile_example/models/__init__.py new file mode 100644 index 00000000000..37f3cd0267b --- /dev/null +++ b/product_profile_example/models/__init__.py @@ -0,0 +1,4 @@ +# © 2015 David BEAL @ Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import profile diff --git a/product_profile_example/profile.py b/product_profile_example/models/profile.py similarity index 52% rename from product_profile_example/profile.py rename to product_profile_example/models/profile.py index 61bcb2e7d28..e735e59b369 100644 --- a/product_profile_example/profile.py +++ b/product_profile_example/models/profile.py @@ -1,4 +1,3 @@ -# coding: utf-8 # © 2015 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -6,23 +5,24 @@ class ProductProfile(models.Model): - _inherit = 'product.profile' + _inherit = "product.profile" - type = fields.Selection(selection_add=[('product', 'Stockable Product')]) + type = fields.Selection(selection_add=[("product", "Stockable Product")]) sale_ok = fields.Boolean( - string='Can be Sold', - help="Specify if the product can be selected in a sales order line.") - purchase_ok = fields.Boolean( - string='Can be Purchased') + string="Can be Sold", + help="Specify if the product can be selected in a sales order line.", + ) + purchase_ok = fields.Boolean(string="Can be Purchased") available_in_pos = fields.Boolean() profile_default_route_ids = fields.Many2many( - 'stock.location.route', - string='Routes', + "stock.location.route", + string="Routes", domain="[('product_selectable', '=', True)]", help="Depending on the modules installed, this will allow " - "you to define the route of the product: " - "whether it will be bought, manufactured, MTO/MTS,...") + "you to define the route of the product: " + "whether it will be bought, manufactured, MTO/MTS,...", + ) profile_default_categ_id = fields.Many2one( - 'product.category', - string='Default category') + "product.category", string="Default category" + ) diff --git a/product_profile_example/tests/__init__.py b/product_profile_example/tests/__init__.py index a9e8b12e870..58755a2967b 100644 --- a/product_profile_example/tests/__init__.py +++ b/product_profile_example/tests/__init__.py @@ -1,4 +1,3 @@ -# coding: utf-8 # © 2015 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index d3a3a58ad1b..6983a568930 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -1,4 +1,3 @@ -# coding: utf-8 # © 2016 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -6,79 +5,85 @@ class TestProductProfile(TransactionCase): - def setUp(self): super(TestProductProfile, self).setUp() - self.prd_m = self.env['product.product'] + self.prd_m = self.env["product.product"] # product 'HDD SH-2' in demo data - self.hard_disc_prd = self.env.ref('product.product_product_17') - self.my_own_profile = self.env.ref('product_profile_example.own') + self.hard_disc_prd = self.env.ref("product.product_product_17") + self.my_own_profile = self.env.ref("product_profile_example.own") self.manufacturing_prof = self.env.ref( - 'product_profile_example.manuf_prof') + "product_profile_example.manuf_prof" + ) self.analysis_tmpl = self.env.ref( - 'point_of_sale.partner_product_7_product_template') - self.analysis_prd = self.env.ref( - 'point_of_sale.partner_product_7') - self.theoritical_categ_id = self.env.ref('product.product_category_5') - self.categ = self.env.ref('product.product_category_3') + "point_of_sale.partner_product_7_product_template" + ) + self.analysis_prd = self.env.ref("point_of_sale.partner_product_7") + self.theoritical_categ_id = self.env.ref("product.product_category_5") + self.categ = self.env.ref("product.product_category_3") def test_check_hard_disc_product(self): # check route_ids real_routes = [x.id for x in self.hard_disc_prd.route_ids] theoritical_routes = [ - self.env.ref('mrp.route_warehouse0_manufacture').id, - self.env.ref('stock.route_warehouse0_mto').id, + self.env.ref("mrp.route_warehouse0_manufacture").id, + self.env.ref("stock.route_warehouse0_mto").id, ] real_routes.sort() theoritical_routes.sort() self.assertEqual(real_routes, theoritical_routes) # check categ_id theoritical_categ_id = self.theoritical_categ_id - self.assertEqual(self.hard_disc_prd.categ_id.id, - theoritical_categ_id.id) + self.assertEqual( + self.hard_disc_prd.categ_id.id, theoritical_categ_id.id + ) def test_create_product(self): - name = 'only name is specified' - vals = {'profile_id': self.my_own_profile.id, - 'name': name} + name = "only name is specified" + vals = {"profile_id": self.my_own_profile.id, "name": name} new_product = self.prd_m.create(vals) new_product._onchange_from_profile() - count_prd = self.prd_m.search([('name', '=', name)]) + count_prd = self.prd_m.search([("name", "=", name)]) self.assertEqual(len(count_prd), 1) def test_write_template(self): - vals = {'profile_id': self.my_own_profile.id} + vals = {"profile_id": self.my_own_profile.id} self.analysis_tmpl.write(vals) self.assertEqual(self.analysis_tmpl.profile_id, self.my_own_profile) def test_write_product(self): - vals = {'profile_id': self.my_own_profile.id} + vals = {"profile_id": self.my_own_profile.id} self.analysis_prd.write(vals) self.assertEqual(self.analysis_prd.profile_id, self.my_own_profile) def test_product_tmpl_fields_view_get(self): - view_id = self.env.ref('product.product_template_search_view').id + view_id = self.env.ref("product.product_template_search_view").id res = self.hard_disc_prd.fields_view_get( - view_id=view_id, view_type='search') - self.assertTrue('string="My Own Type Saleable"' in res['arch'], - 'string="My Own Type Saleable" must be in ' - 'fields_view_get() output') + view_id=view_id, view_type="search" + ) + self.assertTrue( + 'string="My Own Type Saleable"' in res["arch"], + 'string="My Own Type Saleable" must be in ' + "fields_view_get() output", + ) def test_impact_write_profile_model(self): """If profile is updated, products must be written too on profile depends fields""" - self.manufacturing_prof.write({'type': 'consu'}) - product = self.env['product.product'].search( - [('profile_id', '=', self.manufacturing_prof.id)])[0] - self.assertEqual(product.type, 'consu') + self.manufacturing_prof.write({"type": "consu"}) + product = self.env["product.product"].search( + [("profile_id", "=", self.manufacturing_prof.id)] + )[0] + self.assertEqual(product.type, "consu") def test_default_behavior(self): """Check if field prefixed with default_profile have a default behavior on field values""" categ = self.categ - consu_profile = self.env.ref('product_profile_example.consu_prof') - vals = {'profile_id': consu_profile.id, - 'categ_id': categ.id, - 'name': "Product with modified category"} + consu_profile = self.env.ref("product_profile_example.consu_prof") + vals = { + "profile_id": consu_profile.id, + "categ_id": categ.id, + "name": "Product with modified category", + } new_product = self.prd_m.create(vals) self.assertEqual(new_product.categ_id, categ) From c6364f3273a35df9dbf92f51f72b0f5de810f2e6 Mon Sep 17 00:00:00 2001 From: Kevin Khao Date: Tue, 11 Feb 2020 11:31:35 +0100 Subject: [PATCH 23/23] [MIG][12.0] product_profile_example: Migration to 12.0 --- product_profile_example/README.rst | 3 +- product_profile_example/__manifest__.py | 10 +- .../demo/product.profile.csv | 20 -- .../demo/product_product.xml | 12 + .../demo/product_product_demo.xml | 22 -- .../demo/product_profile.xml | 57 +++++ product_profile_example/models/__init__.py | 2 +- .../models/{profile.py => product_profile.py} | 2 +- .../static/description/icon.png | Bin 3655 -> 9455 bytes .../description/product_profile_icon.png | Bin 0 -> 3655 bytes product_profile_example/tests/test_profile.py | 220 ++++++++++++++---- 11 files changed, 251 insertions(+), 97 deletions(-) delete mode 100644 product_profile_example/demo/product.profile.csv create mode 100644 product_profile_example/demo/product_product.xml delete mode 100644 product_profile_example/demo/product_product_demo.xml create mode 100644 product_profile_example/demo/product_profile.xml rename product_profile_example/models/{profile.py => product_profile.py} (93%) create mode 100644 product_profile_example/static/description/product_profile_icon.png diff --git a/product_profile_example/README.rst b/product_profile_example/README.rst index 2c862f3ce24..9d8803627ef 100644 --- a/product_profile_example/README.rst +++ b/product_profile_example/README.rst @@ -14,7 +14,7 @@ See its description. Configuration ============= -Optionnaly: +Optionally: * Settings > Configuration > General Settings: check 'Display fields in Profile' and apply (only if you want display hidden fields set by profile git ) @@ -39,6 +39,7 @@ Contributors ------------ * David BEAL +* Kevin KHAO Maintainer ---------- diff --git a/product_profile_example/__manifest__.py b/product_profile_example/__manifest__.py index 576ce054781..0197f5acbd3 100644 --- a/product_profile_example/__manifest__.py +++ b/product_profile_example/__manifest__.py @@ -2,14 +2,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { + "license": "AGPL-3", "name": "Product Profile Example", "summary": "Product Profile Use Case", - "version": "10.0.1.0.1", + "version": "12.0.1.0.0", "author": "Akretion, Odoo Community Association (OCA)", "category": "product", - "depends": ["product_profile", "purchase", "point_of_sale", "mrp",], - "website": "http://www.akretion.com/", - "demo": ["demo/product.profile.csv", "demo/product_product_demo.xml",], + "depends": ["product_profile", "purchase_stock", "point_of_sale", "mrp"], + "website": "https://github.com/OCA/product-attribute", + "demo": ["demo/product_profile.xml", "demo/product_product.xml"], "installable": True, - "license": "AGPL-3", } diff --git a/product_profile_example/demo/product.profile.csv b/product_profile_example/demo/product.profile.csv deleted file mode 100644 index 0a7c0330c08..00000000000 --- a/product_profile_example/demo/product.profile.csv +++ /dev/null @@ -1,20 +0,0 @@ -id,name,type,sale_ok,purchase_ok,profile_default_categ_id/id,available_in_pos,profile_default_route_ids/id,explanation -own,My Own Type Saleable,product,1,0,product.product_category_all,1,purchase.route_warehouse0_buy,"- My own type -- Saleable product -- Not purchasable" -consu_prof,Consumable,consu,1,0,product.product_category_all,0,purchase.route_warehouse0_buy,"- Consumable" -pos_pu_prof,POS & purchase,product,1,1,product.product_category_all,1,purchase.route_warehouse0_buy,"- Product in POS -- Product purchasable" -manuf_prof,Manufacturing TO,product,1,0,product.product_category_5,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto","- Manufacturing Product -- Make to order product -- Not purchaseable -- Display on POS" -any_prof,Weird profile,product,0,1,product.product_category_all,1,,"- Purchasable -- Display on POS -- Not Saleable" -complete_prof,Complete profile,product,1,1,product.product_category_all,1,"mrp.route_warehouse0_manufacture,stock.route_warehouse0_mto,purchase.route_warehouse0_buy","- Stockable product -- Saleable -- Purchasable -- Available in POS -- MTO -- Manufacturable" diff --git a/product_profile_example/demo/product_product.xml b/product_profile_example/demo/product_product.xml new file mode 100644 index 00000000000..ee5f9098183 --- /dev/null +++ b/product_profile_example/demo/product_product.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/product_profile_example/demo/product_product_demo.xml b/product_profile_example/demo/product_product_demo.xml deleted file mode 100644 index 5fe546c52ce..00000000000 --- a/product_profile_example/demo/product_product_demo.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/product_profile_example/demo/product_profile.xml b/product_profile_example/demo/product_profile.xml new file mode 100644 index 00000000000..8921582698f --- /dev/null +++ b/product_profile_example/demo/product_profile.xml @@ -0,0 +1,57 @@ + + + + + My Own Type Saleable + product + True + False + + True + + - My own type +- Saleable product +- Not purchasable + + + + Complete Profile + product + True + True + + True + + - Stockable product +- Saleable +- Purchasable +- Available in POS +- MTO +- Manufacturable + + + + Manufacturing TO + product + True + False + + True + + - Manufacturing Product +- Make to order product +- Display on POS + + + + Consumable + consu + True + False + + False + Consumable + + + + diff --git a/product_profile_example/models/__init__.py b/product_profile_example/models/__init__.py index 37f3cd0267b..e923f538423 100644 --- a/product_profile_example/models/__init__.py +++ b/product_profile_example/models/__init__.py @@ -1,4 +1,4 @@ # © 2015 David BEAL @ Akretion # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from . import profile +from . import product_profile diff --git a/product_profile_example/models/profile.py b/product_profile_example/models/product_profile.py similarity index 93% rename from product_profile_example/models/profile.py rename to product_profile_example/models/product_profile.py index e735e59b369..c303565dd35 100644 --- a/product_profile_example/models/profile.py +++ b/product_profile_example/models/product_profile.py @@ -24,5 +24,5 @@ class ProductProfile(models.Model): "whether it will be bought, manufactured, MTO/MTS,...", ) profile_default_categ_id = fields.Many2one( - "product.category", string="Default category" + "product.category", string="Default category", required=True ) diff --git a/product_profile_example/static/description/icon.png b/product_profile_example/static/description/icon.png index 7c8b3dc5563dcf86a77af97366b723c902e070b5..3a0328b516c4980e8e44cdb63fd945757ddd132d 100644 GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 3655 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 QB_ENtx{g}8igozE0D`>^ga7~l diff --git a/product_profile_example/static/description/product_profile_icon.png b/product_profile_example/static/description/product_profile_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8b3dc5563dcf86a77af97366b723c902e070b5 GIT binary patch literal 3655 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 QB_ENtx{g}8igozE0D`>^ga7~l literal 0 HcmV?d00001 diff --git a/product_profile_example/tests/test_profile.py b/product_profile_example/tests/test_profile.py index 6983a568930..d4f28fe9bfd 100644 --- a/product_profile_example/tests/test_profile.py +++ b/product_profile_example/tests/test_profile.py @@ -7,23 +7,57 @@ class TestProductProfile(TransactionCase): def setUp(self): super(TestProductProfile, self).setUp() + self._setup_obj_data() + self._setup_profile_data() + + def _setup_obj_data(self): + self.tmpl_m = self.env["product.template"] self.prd_m = self.env["product.product"] - # product 'HDD SH-2' in demo data - self.hard_disc_prd = self.env.ref("product.product_product_17") - self.my_own_profile = self.env.ref("product_profile_example.own") - self.manufacturing_prof = self.env.ref( - "product_profile_example.manuf_prof" - ) + # misc + self.desk_combination_prd = self.env.ref("product.product_product_3") self.analysis_tmpl = self.env.ref( - "point_of_sale.partner_product_7_product_template" + "product.expense_hotel_product_template" ) - self.analysis_prd = self.env.ref("point_of_sale.partner_product_7") + self.analysis_prd = self.env.ref("product.expense_hotel") self.theoritical_categ_id = self.env.ref("product.product_category_5") self.categ = self.env.ref("product.product_category_3") - def test_check_hard_disc_product(self): + def _setup_profile_data(self): + self.profile_own = self.env.ref("product_profile_example.profile_own") + self.profile_own_nondefaults = { + "type": "product", + "sale_ok": True, + "purchase_ok": False, + "available_in_pos": True, + } + self.profile_own_defaults = { + "categ_id": self.env.ref("product.product_category_all"), + "route_ids": self.env.ref("purchase_stock.route_warehouse0_buy"), + } + self.profile_complete = self.env.ref( + "product_profile_example.profile_complete" + ) + self.profile_complete_nondefaults = { + "type": "product", + "sale_ok": True, + "purchase_ok": True, + "available_in_pos": True, + } + self.profile_complete_defaults = { + "categ_id": self.env.ref("product.product_category_all"), + "route_ids": [ + self.env.ref("mrp.route_warehouse0_manufacture") + + self.env.ref("stock.route_warehouse0_mto") + + self.env.ref("purchase_stock.route_warehouse0_buy") + ], + } + self.profile_manuf = self.env.ref( + "product_profile_example.profile_manuf" + ) + + def test_check_desk_combination_product(self): # check route_ids - real_routes = [x.id for x in self.hard_disc_prd.route_ids] + real_routes = [x.id for x in self.desk_combination_prd.route_ids] theoritical_routes = [ self.env.ref("mrp.route_warehouse0_manufacture").id, self.env.ref("stock.route_warehouse0_mto").id, @@ -34,56 +68,148 @@ def test_check_hard_disc_product(self): # check categ_id theoritical_categ_id = self.theoritical_categ_id self.assertEqual( - self.hard_disc_prd.categ_id.id, theoritical_categ_id.id + self.desk_combination_prd.categ_id.id, theoritical_categ_id.id ) - def test_create_product(self): - name = "only name is specified" - vals = {"profile_id": self.my_own_profile.id, "name": name} - new_product = self.prd_m.create(vals) - new_product._onchange_from_profile() - count_prd = self.prd_m.search([("name", "=", name)]) + def test_on_create_template_with_profile(self): + """Creating a product with a profile applies all the profile's values""" + name = "template with 'own' profile" + vals = {"profile_id": self.profile_own.id, "name": name} + new_tmpl = self.tmpl_m.create(vals) + count_tmpl = self.tmpl_m.search([("name", "=", name)]).ids + self.assertEqual(len(count_tmpl), 1) + # test all values from profile are applied + for key in self.profile_own_nondefaults: + self.assertEqual( + self.profile_own_nondefaults[key], getattr(new_tmpl, key) + ) + for key in self.profile_own_defaults: + self.assertEqual( + self.profile_own_defaults[key], getattr(new_tmpl, key) + ) + + def test_on_create_product_with_profile(self): + """Creating a product with a profile applies all the profile's values""" + name = "product with 'own' profile" + vals = {"profile_id": self.profile_own.id, "name": name} + new_prd = self.prd_m.create(vals) + count_prd = self.prd_m.search([("name", "=", name)]).ids self.assertEqual(len(count_prd), 1) + # test all values from profile are applied + for key in self.profile_own_nondefaults: + self.assertEqual( + self.profile_own_nondefaults[key], getattr(new_prd, key) + ) + for key in self.profile_own_defaults: + self.assertEqual( + self.profile_own_defaults[key], getattr(new_prd, key) + ) + + def test_on_set_tmpl_profile(self): + """Test that setting a profile impacts: + - nondefaults in every case + - defaults only if there was no profile previously""" + + # set profile to "own" + vals = {"profile_id": self.profile_own.id} + self.analysis_tmpl.write(vals) + self.assertEqual(self.analysis_tmpl.profile_id, self.profile_own) + for key in self.profile_own_nondefaults: + self.assertEqual( + self.profile_own_nondefaults[key], + getattr(self.analysis_tmpl, key), + ) + for key in self.profile_own_defaults: + self.assertEqual( + self.profile_own_defaults[key], + getattr(self.analysis_tmpl, key), + ) + + # get vals on the template + defaults_keys = self.profile_own_defaults.keys() + defaults_tmpl_vals = { + key: self.analysis_tmpl[key] for key in defaults_keys + } - def test_write_template(self): - vals = {"profile_id": self.my_own_profile.id} + # set profile to "complete_prof" + vals = {"profile_id": self.profile_complete.id} self.analysis_tmpl.write(vals) - self.assertEqual(self.analysis_tmpl.profile_id, self.my_own_profile) + self.assertEqual(self.analysis_tmpl.profile_id, self.profile_complete) + for key in self.profile_complete_nondefaults: + self.assertEqual( + self.profile_complete_nondefaults[key], + getattr(self.analysis_tmpl, key), + ) + for key in self.profile_own_defaults: + self.assertEqual( + defaults_tmpl_vals[key], getattr(self.analysis_tmpl, key) + ) - def test_write_product(self): - vals = {"profile_id": self.my_own_profile.id} + def test_on_set_prd_profile(self): + """Test that setting a profile impacts: + - nondefaults in every case + - defaults only if there was no profile previously""" + + # set profile to "own" + vals = {"profile_id": self.profile_own.id} + self.analysis_prd.write(vals) + self.assertEqual(self.analysis_prd.profile_id, self.profile_own) + for key in self.profile_own_nondefaults: + self.assertEqual( + self.profile_own_nondefaults[key], + getattr(self.analysis_prd, key), + ) + for key in self.profile_own_defaults: + self.assertEqual( + self.profile_own_defaults[key], getattr(self.analysis_prd, key) + ) + + # get vals on the products + defaults_keys = self.profile_own_defaults.keys() + defaults_prd_vals = { + key: self.analysis_tmpl[key] for key in defaults_keys + } + + # set profile to "complete_prof" + vals = {"profile_id": self.profile_own.id} self.analysis_prd.write(vals) - self.assertEqual(self.analysis_prd.profile_id, self.my_own_profile) + self.assertEqual(self.analysis_prd.profile_id, self.profile_own) + for key in self.profile_complete_nondefaults: + self.assertEqual( + self.profile_own_nondefaults[key], + getattr(self.analysis_prd, key), + ) + for key in self.profile_complete_defaults: + self.assertEqual( + defaults_prd_vals[key], getattr(self.analysis_prd, key) + ) + + def test_on_write_profile_nondefaults(self): + """Writing on non-default profile fields should propagate + changes on products""" + product = self.env["product.product"].search( + [("profile_id", "=", self.profile_manuf.id)] + )[0] + self.profile_manuf.write({"purchase_ok": False}) + self.assertEqual(product.purchase_ok, False) + + def test_on_write_profile_defaults(self): + """Writing on default profile fields should not propagate + changes on products""" + product = self.env["product.product"].search( + [("profile_id", "=", self.profile_manuf.id)] + )[0] + self.profile_manuf.write({"profile_default_categ_id": self.categ.id}) + self.assertNotEqual(product.categ_id, self.categ) def test_product_tmpl_fields_view_get(self): + # test search filters loaded view_id = self.env.ref("product.product_template_search_view").id - res = self.hard_disc_prd.fields_view_get( + res = self.desk_combination_prd.fields_view_get( view_id=view_id, view_type="search" ) self.assertTrue( - 'string="My Own Type Saleable"' in res["arch"], + b'string="My Own Type Saleable"' in res["arch"], 'string="My Own Type Saleable" must be in ' "fields_view_get() output", ) - - def test_impact_write_profile_model(self): - """If profile is updated, products must be written too - on profile depends fields""" - self.manufacturing_prof.write({"type": "consu"}) - product = self.env["product.product"].search( - [("profile_id", "=", self.manufacturing_prof.id)] - )[0] - self.assertEqual(product.type, "consu") - - def test_default_behavior(self): - """Check if field prefixed with default_profile - have a default behavior on field values""" - categ = self.categ - consu_profile = self.env.ref("product_profile_example.consu_prof") - vals = { - "profile_id": consu_profile.id, - "categ_id": categ.id, - "name": "Product with modified category", - } - new_product = self.prd_m.create(vals) - self.assertEqual(new_product.categ_id, categ)