Merge lp:~openerp-dev/openobject-addons/trunk-osv_memory_crm_profiling-uco into lp:openobject-addons
- trunk-osv_memory_crm_profiling-uco
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 5961 |
Proposed branch: | lp:~openerp-dev/openobject-addons/trunk-osv_memory_crm_profiling-uco |
Merge into: | lp:openobject-addons |
Diff against target: |
362 lines (+160/-102) 7 files modified
crm_profiling/__openerp__.py (+1/-1) crm_profiling/crm_profiling.py (+5/-35) crm_profiling/crm_profiling_view.xml (+1/-8) crm_profiling/crm_profiling_wizard.xml (+0/-5) crm_profiling/test/test_crm_profiling.yml (+2/-10) crm_profiling/wizard/open_questionnaire.py (+65/-43) crm_profiling/wizard/open_questionnaire_view.xml (+86/-0) |
To merge this branch: | bzr merge lp:~openerp-dev/openobject-addons/trunk-osv_memory_crm_profiling-uco |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Raphael Collet (OpenERP) (community) | Approve | ||
Ujjvala Collins (community) | Needs Resubmitting | ||
Olivier Dony (Odoo) | Needs Fixing | ||
Mustufa Rangwala (Open ERP) (community) | Approve | ||
Vo Minh Thu | Pending | ||
Review via email: mp+74942@code.launchpad.net |
Commit message
Description of the change
[IMP] crm_profiling:
-------
* Converted Open Questionnaire wizard to osv_memory.
* Removed unused file: crm_profiling/
Mustufa Rangwala (Open ERP) (mra-tinyerp) wrote : | # |
Raphael Collet (OpenERP) (rco-openerp) wrote : | # |
I will merge it, but it is unusable for a non-technical person. There is no way to open a given questionnaire, except defining a low-level action in XML...
Olivier Dony (Odoo) (odo-openerp) wrote : | # |
I have reverted this merge, it was unacceptable.
1) Runbot tests were failing after the merge, so it was not tested properly
2) The code of the crm profiling wizard alters the _columns of the wizard object dynamically, which must never happen! This has global effects on the osv objects, which means that the behavior will be unpredictable when several people use the wizards, and it also makes memory leaks, etc.
When you need dynamic views for wizard you have 2 options usually:
- generate dynamic "virtual" fields in field_view_get + fields_get (but do NOT add them in self._columns), and make custom create/read/write methods to handle these virtual fields appropriately
- or when you simply need multiple lines, you can make a real "line" osv_memory object like we do in the new stock.partial.
Please fix this and resubmit, and be careful about this kind of problem whenever you deal with dynamic views, from now on.
Thanks!
Ujjvala Collins (uco-openerp) wrote : | # |
Hello,
I have converted the wizard as per Olivier's suggestions. Completely refactored the code. Please check.
Thanks,
Ujjvala
Raphael Collet (OpenERP) (rco-openerp) wrote : | # |
Looks good, now.
Thanks,
Raphael
Preview Diff
1 | === modified file 'crm_profiling/__openerp__.py' |
2 | --- crm_profiling/__openerp__.py 2011-10-20 08:33:03 +0000 |
3 | +++ crm_profiling/__openerp__.py 2011-11-08 13:34:25 +0000 |
4 | @@ -39,7 +39,7 @@ |
5 | 'website': 'http://www.openerp.com', |
6 | 'depends': ['base', 'crm'], |
7 | 'init_xml': [], |
8 | - 'update_xml': ['security/ir.model.access.csv', 'crm_profiling_view.xml'], |
9 | + 'update_xml': ['security/ir.model.access.csv', 'wizard/open_questionnaire_view.xml', 'crm_profiling_view.xml'], |
10 | 'demo_xml': ['crm_profiling_demo.xml'], |
11 | 'test': ['test/test_crm_profiling.yml'], |
12 | 'installable': True, |
13 | |
14 | === modified file 'crm_profiling/crm_profiling.py' |
15 | --- crm_profiling/crm_profiling.py 2011-10-20 08:33:03 +0000 |
16 | +++ crm_profiling/crm_profiling.py 2011-11-08 13:34:25 +0000 |
17 | @@ -159,30 +159,6 @@ |
18 | _name="crm_profiling.questionnaire" |
19 | _description= "Questionnaire" |
20 | |
21 | - def build_form(self, cr, uid, data, context=None): |
22 | - """ |
23 | - @param self: The object pointer |
24 | - @param cr: the current row, from the database cursor, |
25 | - @param uid: the current user’s ID for security checks, |
26 | - @param data: Get Data |
27 | - @param context: A standard dictionary for contextual values """ |
28 | - |
29 | - query = """ |
30 | - select name, id |
31 | - from crm_profiling_question |
32 | - where id in ( select question from profile_questionnaire_quest_rel where questionnaire = %s)""" |
33 | - res = cr.execute(query, (data['form']['questionnaire_name'],)) |
34 | - result = cr.fetchall() |
35 | - quest_fields={} |
36 | - quest_form='''<?xml version="1.0"?> |
37 | - <form string="%s">''' % _('Questionnaire') |
38 | - for name, oid in result: |
39 | - quest_form = quest_form + '<field name="quest_form%d"/><newline/>' % (oid,) |
40 | - quest_fields['quest_form%d' % (oid,)] = {'string': name, 'type': 'many2one', \ |
41 | - 'relation': 'crm_profiling.answer', 'domain': [('question_id','=',oid)] } |
42 | - quest_form = quest_form + '''</form>''' |
43 | - return quest_form, quest_fields |
44 | - |
45 | _columns = { |
46 | 'name': fields.char("Questionnaire",size=128, required=True), |
47 | 'description':fields.text("Description", required=True), |
48 | @@ -210,25 +186,19 @@ |
49 | "partner","answer","Answers"), |
50 | } |
51 | |
52 | - def _questionnaire_compute(self, cr, uid, data, context=None): |
53 | + def _questionnaire_compute(self, cr, uid, answers, context=None): |
54 | """ |
55 | @param self: The object pointer |
56 | @param cr: the current row, from the database cursor, |
57 | @param uid: the current user’s ID for security checks, |
58 | @param data: Get Data |
59 | @param context: A standard dictionary for contextual values """ |
60 | - |
61 | - temp = [] |
62 | - for x in data['form']: |
63 | - if x.startswith("quest_form") and data['form'][x] != 0 : |
64 | - temp.append(data['form'][x]) |
65 | - |
66 | + partner_id = context.get('active_id') |
67 | query = "select answer from partner_question_rel where partner=%s" |
68 | - cr.execute(query, (data['id'],)) |
69 | + cr.execute(query, (partner_id,)) |
70 | for x in cr.fetchall(): |
71 | - temp.append(x[0]) |
72 | - |
73 | - self.write(cr, uid, [data['id']], {'answers_ids':[[6, 0, temp]]}, context=context) |
74 | + answers.append(x[0]) |
75 | + self.write(cr, uid, [partner_id], {'answers_ids': [[6, 0, answers]]}, context=context) |
76 | return {} |
77 | |
78 | |
79 | |
80 | === modified file 'crm_profiling/crm_profiling_view.xml' |
81 | --- crm_profiling/crm_profiling_view.xml 2011-10-20 08:33:03 +0000 |
82 | +++ crm_profiling/crm_profiling_view.xml 2011-11-08 13:34:25 +0000 |
83 | @@ -2,13 +2,6 @@ |
84 | <openerp> |
85 | <data> |
86 | |
87 | - <wizard |
88 | - string="Using a questionnaire" |
89 | - model="crm_profiling.questionnaire" |
90 | - name="open_questionnaire" |
91 | - menu="False" |
92 | - id="wizard_open_questionnaire"/> |
93 | - |
94 | <record model="ir.actions.act_window" id="open_questionnaires"> |
95 | <field name="name">Questionnaires</field> |
96 | <field name="res_model">crm_profiling.questionnaire</field> |
97 | @@ -140,7 +133,7 @@ |
98 | <notebook position="inside"> |
99 | <page string="Profiling"> |
100 | <button string="Use a questionnaire" |
101 | - name="%(wizard_open_questionnaire)d" type="action" colspan="1" |
102 | + name="%(action_open_questionnaire)d" type="action" colspan="1" |
103 | icon="gtk-justify-fill" /> |
104 | <newline/> |
105 | <field name="answers_ids" colspan="4" nolabel="1"/> |
106 | |
107 | === removed file 'crm_profiling/crm_profiling_wizard.xml' |
108 | --- crm_profiling/crm_profiling_wizard.xml 2011-11-08 13:30:05 +0000 |
109 | +++ crm_profiling/crm_profiling_wizard.xml 1970-01-01 00:00:00 +0000 |
110 | @@ -1,5 +0,0 @@ |
111 | -<?xml version="1.0"?> |
112 | -<openerp> |
113 | - <data> |
114 | - </data> |
115 | -</openerp> |
116 | |
117 | === modified file 'crm_profiling/test/test_crm_profiling.yml' |
118 | --- crm_profiling/test/test_crm_profiling.yml 2011-09-22 11:43:25 +0000 |
119 | +++ crm_profiling/test/test_crm_profiling.yml 2011-11-08 13:34:25 +0000 |
120 | @@ -32,15 +32,14 @@ |
121 | name: John |
122 | category_id: |
123 | - res_partner_category_customers0 |
124 | - answers_ids: |
125 | - - crm_profiling_answer_openerppartner0 |
126 | |
127 | - |
128 | Define the answers and category to partner. |
129 | - |
130 | !python {model: res.partner}: | |
131 | data ={'form': {'questionnaire_name': ref('res_partner_john0')}, 'ids': [ref('res_partner_john0')], 'report_type': 'pdf', 'model': 'res.partner', 'id': ref('res_partner_john0')} |
132 | - self._questionnaire_compute(cr, uid, data, context) |
133 | + context['active_id'] = ref('res_partner_john0') |
134 | + self._questionnaire_compute(cr, uid, [ref('crm_profiling_answer_openerppartner0')], context) |
135 | - | |
136 | I start by creating new Questionnaire. |
137 | - |
138 | @@ -51,13 +50,6 @@ |
139 | - crm_profiling.activity_sector |
140 | - crm_profiling.nb_employees |
141 | - crm_profiling.partner_level |
142 | -- | |
143 | - I create the form for the "Base questionnaire". |
144 | -- |
145 | - !python {model: crm_profiling.questionnaire}: | |
146 | - context.update({'active_id':ref('res_partner_john0')}) |
147 | - data ={'form': {'questionnaire_name': ref('res_partner_john0')}, 'ids': [ref('res_partner_john0')], 'report_type': 'pdf', 'model': 'res.partner', 'id': ref('res_partner_john0')} |
148 | - self.build_form(cr, uid, data, context) |
149 | - |
150 | I create a segmentation record. |
151 | - |
152 | |
153 | === modified file 'crm_profiling/wizard/open_questionnaire.py' |
154 | --- crm_profiling/wizard/open_questionnaire.py 2011-10-20 08:33:03 +0000 |
155 | +++ crm_profiling/wizard/open_questionnaire.py 2011-11-08 13:34:25 +0000 |
156 | @@ -18,50 +18,72 @@ |
157 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
158 | # |
159 | ############################################################################## |
160 | -import pooler |
161 | -import wizard |
162 | -from tools import UpdateableStr, UpdateableDict |
163 | - |
164 | -_QUEST_FORM = UpdateableStr() |
165 | -_QUEST_FIELDS=UpdateableDict() |
166 | - |
167 | -class open_questionnaire(wizard.interface): |
168 | - |
169 | - def _questionnaire_compute(self, cr, uid, data, context): |
170 | - pooler.get_pool(cr.dbname).get(data['model'])._questionnaire_compute(cr, uid, data, context) |
171 | - return {} |
172 | - |
173 | - |
174 | - def build_form(self, cr, uid, data, context): |
175 | - quest_form, quest_fields = pooler.get_pool(cr.dbname).get('crm_profiling.questionnaire').build_form(cr, uid, data, context) |
176 | - _QUEST_FORM. __init__(quest_form) |
177 | - _QUEST_FIELDS.__init__(quest_fields) |
178 | - return{} |
179 | - |
180 | - _questionnaire_choice_arch = '''<?xml version="1.0"?> |
181 | - <form string="Questionnaire"> |
182 | - <field name="questionnaire_name"/> |
183 | - </form>''' |
184 | - |
185 | - _questionnaire_choice_fields = { |
186 | - 'questionnaire_name': {'string': 'Questionnaire name', 'type': 'many2one', 'relation': 'crm_profiling.questionnaire', 'required': True }, |
187 | - } |
188 | - |
189 | - states = { |
190 | - 'init': { |
191 | - 'actions': [], |
192 | - 'result': {'type': 'form', 'arch': _questionnaire_choice_arch, 'fields': _questionnaire_choice_fields, 'state':[('end', 'Cancel','gtk-cancel'), ('open', 'Open Questionnaire','terp-camera_test')]} |
193 | - }, |
194 | - 'open': { |
195 | - 'actions': [build_form], |
196 | - 'result': {'type': 'form', 'arch':_QUEST_FORM, 'fields': _QUEST_FIELDS, 'state':[('end', 'Cancel','gtk-cancel'), ('compute', 'Save Data','terp-stock_format-scientific')]} |
197 | - }, |
198 | - 'compute': { |
199 | - 'actions': [], |
200 | - 'result': {'type': 'action', 'action': _questionnaire_compute, 'state':'end'} |
201 | + |
202 | +from osv import osv, fields |
203 | +from tools.translate import _ |
204 | + |
205 | +class open_questionnaire_line(osv.TransientModel): |
206 | + _name = 'open.questionnaire.line' |
207 | + _rec_name = 'question_id' |
208 | + _columns = { |
209 | + 'question_id': fields.many2one('crm_profiling.question','Question', required=True), |
210 | + 'answer_id': fields.many2one('crm_profiling.answer', 'Answer'), |
211 | + 'wizard_id': fields.many2one('open.questionnaire', 'Questionnaire'), |
212 | + } |
213 | + |
214 | +open_questionnaire_line() |
215 | + |
216 | +class open_questionnaire(osv.osv_memory): |
217 | + _name = 'open.questionnaire' |
218 | + _columns = { |
219 | + 'questionnaire_id': fields.many2one('crm_profiling.questionnaire', 'Questionnaire name'), |
220 | + 'question_ans_ids': fields.one2many('open.questionnaire.line', 'wizard_id', 'Question / Answers'), |
221 | + } |
222 | + |
223 | + def default_get(self, cr, uid, fields, context=None): |
224 | + if context is None: context = {} |
225 | + res = super(open_questionnaire, self).default_get(cr, uid, fields, context=context) |
226 | + questionnaire_id = context.get('questionnaire_id', False) |
227 | + if questionnaire_id and 'question_ans_ids' in fields: |
228 | + query = """ |
229 | + select question as question_id from profile_questionnaire_quest_rel where questionnaire = %s""" |
230 | + cr.execute(query, (questionnaire_id,)) |
231 | + result = cr.dictfetchall() |
232 | + res.update(question_ans_ids=result) |
233 | + return res |
234 | + |
235 | + def questionnaire_compute(self, cr, uid, ids, context=None): |
236 | + """ Adds selected answers in partner form """ |
237 | + model = context.get('active_model') |
238 | + answers = [] |
239 | + if model == 'res.partner': |
240 | + data = self.browse(cr, uid, ids[0], context=context) |
241 | + for d in data.question_ans_ids: |
242 | + if d.answer_id: |
243 | + answers.append(d.answer_id.id) |
244 | + self.pool.get(model)._questionnaire_compute(cr, uid, answers, context=context) |
245 | + return {'type': 'ir.actions.act_window_close'} |
246 | + |
247 | + |
248 | + def build_form(self, cr, uid, ids, context=None): |
249 | + """ Dynamically generates form according to selected questionnaire """ |
250 | + models_data = self.pool.get('ir.model.data') |
251 | + result = models_data._get_id(cr, uid, 'crm_profiling', 'open_questionnaire_form') |
252 | + res_id = models_data.browse(cr, uid, result, context=context).res_id |
253 | + datas = self.browse(cr, uid, ids[0], context=context) |
254 | + context.update({'questionnaire_id': datas.questionnaire_id.id}) |
255 | + |
256 | + return { |
257 | + 'name': _('Questionnaire'), |
258 | + 'view_type': 'form', |
259 | + 'view_mode': 'form', |
260 | + 'res_model': 'open.questionnaire', |
261 | + 'type': 'ir.actions.act_window', |
262 | + 'views': [(res_id,'form')], |
263 | + 'target': 'new', |
264 | + 'context': context |
265 | } |
266 | - } |
267 | |
268 | -open_questionnaire('open_questionnaire') |
269 | +open_questionnaire() |
270 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
271 | |
272 | |
273 | === added file 'crm_profiling/wizard/open_questionnaire_view.xml' |
274 | --- crm_profiling/wizard/open_questionnaire_view.xml 1970-01-01 00:00:00 +0000 |
275 | +++ crm_profiling/wizard/open_questionnaire_view.xml 2011-11-08 13:34:25 +0000 |
276 | @@ -0,0 +1,86 @@ |
277 | +<?xml version="1.0" ?> |
278 | +<openerp> |
279 | + <data> |
280 | + |
281 | + <record id="view_open_questionnaire_form" model="ir.ui.view"> |
282 | + <field name="name">Open Questionnaires</field> |
283 | + <field name="model">open.questionnaire</field> |
284 | + <field name="type">form</field> |
285 | + <field name="arch" type="xml"> |
286 | + <form string="Questionnaires"> |
287 | + <field name="questionnaire_id" required="1"/> |
288 | + <newline/> |
289 | + <separator string="" colspan="4"/> |
290 | + <group col="4" colspan="4"> |
291 | + <group col="2" colspan="2"/> |
292 | + <button special="cancel" icon="gtk-cancel" string="Cancel"/> |
293 | + <button name="build_form" string="Open Questionnaire" icon="terp-camera_test" type="object"/> |
294 | + </group> |
295 | + </form> |
296 | + </field> |
297 | + </record> |
298 | + |
299 | + <record model="ir.actions.act_window" id="action_open_questionnaire"> |
300 | + <field name="name">Open Questionnaire</field> |
301 | + <field name="res_model">open.questionnaire</field> |
302 | + <field name="view_type">form</field> |
303 | + <field name="view_mode">form</field> |
304 | + <field name="view_id" ref="view_open_questionnaire_form"/> |
305 | + <field name="target">new</field> |
306 | + </record> |
307 | + |
308 | + <record id="open_questionnaire_form" model="ir.ui.view"> |
309 | + <field name="name">open.questionnaire.form</field> |
310 | + <field name="model">open.questionnaire</field> |
311 | + <field name="type">form</field> |
312 | + <field name="arch" type="xml"> |
313 | + <form> |
314 | + <separator colspan="4" string="Questionnaire"/> |
315 | + <field name="question_ans_ids" colspan="4" nolabel="1" mode="tree,form" width="550" height="200"/> |
316 | + <separator string="" colspan="4" /> |
317 | + <label string="" colspan="2"/> |
318 | + <group col="2" colspan="2"> |
319 | + <button icon='gtk-cancel' special="cancel" string="_Cancel" /> |
320 | + <button name="questionnaire_compute" string="Save Data" icon="terp-stock_format-scientific" colspan="1" type="object"/> |
321 | + </group> |
322 | + </form> |
323 | + </field> |
324 | + </record> |
325 | + |
326 | + <record id="view_open_questionnaire_line_tree" model="ir.ui.view"> |
327 | + <field name="name">open.questionnaire.line.list</field> |
328 | + <field name="model">open.questionnaire.line</field> |
329 | + <field name="type">tree</field> |
330 | + <field name="arch" type="xml"> |
331 | + <tree editable="bottom" string="Questionnaire"> |
332 | + <field name="question_id"/> |
333 | + <field name="answer_id" domain="[('question_id', '=', question_id)]"/> |
334 | + </tree> |
335 | + </field> |
336 | + </record> |
337 | + |
338 | + <record id="view_open_questionnaire_line_form" model="ir.ui.view"> |
339 | + <field name="name">open.questionnaire.line.form</field> |
340 | + <field name="model">open.questionnaire.line</field> |
341 | + <field name="type">form</field> |
342 | + <field name="arch" type="xml"> |
343 | + <form string="Questionnaire"> |
344 | + <field name="question_id"/> |
345 | + <field name="answer_id" domain="[('question_id', '=', question_id)]"/> |
346 | + </form> |
347 | + </field> |
348 | + </record> |
349 | + |
350 | + <!-- Questionnaire form view --> |
351 | + <!--<act_window |
352 | + context="{}" |
353 | + id="act_open_questionnaire" |
354 | + name="Using a Questionnaire" |
355 | + res_model="open.questionnaire" |
356 | + src_model="crm_profiling.questionnaire" |
357 | + view_id="view_open_questionnaire_form" |
358 | + target="new" |
359 | + view_mode="form"/>--> |
360 | + |
361 | + </data> |
362 | +</openerp> |
Thanks for improvement.
Mustufa