Merge lp:~camptocamp/openerp-crm/7.0-crm_claim_merge-gbr into lp:~crm-core-editors/openerp-crm/7.0
- 7.0-crm_claim_merge-gbr
- Merge into 7.0
Proposed by
Guewen Baconnier @ Camptocamp
Status: | Rejected |
---|---|
Rejected by: | Guewen Baconnier @ Camptocamp |
Proposed branch: | lp:~camptocamp/openerp-crm/7.0-crm_claim_merge-gbr |
Merge into: | lp:~crm-core-editors/openerp-crm/7.0 |
Diff against target: |
835 lines (+787/-0) 9 files modified
crm_claim_merge/__init__.py (+4/-0) crm_claim_merge/__openerp__.py (+45/-0) crm_claim_merge/crm_claim.py (+370/-0) crm_claim_merge/i18n/crm_claim_merge.pot (+69/-0) crm_claim_merge/i18n/fr.po (+69/-0) crm_claim_merge/test/crm_claim_merge.yml (+103/-0) crm_claim_merge/wizard/__init__.py (+3/-0) crm_claim_merge/wizard/crm_claim_merge.py (+83/-0) crm_claim_merge/wizard/crm_claim_merge_view.xml (+41/-0) |
To merge this branch: | bzr merge lp:~camptocamp/openerp-crm/7.0-crm_claim_merge-gbr |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP CRM Core Editors | Pending | ||
Review via email: mp+217628@code.launchpad.net |
Commit message
Add crm_claim_merge, allows to merge claims.
Description of the change
To post a comment you must log in.
- 24. By Guewen Baconnier @ Camptocamp
-
useless copy
- 25. By Guewen Baconnier @ Camptocamp
-
add translation pot and fr translation
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Unmerged revisions
- 25. By Guewen Baconnier @ Camptocamp
-
add translation pot and fr translation
- 24. By Guewen Baconnier @ Camptocamp
-
useless copy
- 23. By Guewen Baconnier @ Camptocamp
-
use the usual tree view for displaying claims in the wizard
- 22. By Guewen Baconnier @ Camptocamp
-
avoid collisions in attachment names
- 21. By Guewen Baconnier @ Camptocamp
-
use name_get() in subject of summary so if it has been customized (eg. crm_claim_rma with a sequence), it will be displayed correctly
- 20. By Guewen Baconnier @ Camptocamp
-
use name_get() when writing the subject of the merged messages
- 19. By Guewen Baconnier @ Camptocamp
-
completed tests with more types of fields (added date, selection, reference, m2o, char)
- 18. By Guewen Baconnier @ Camptocamp
-
fix display of one2many fields in the summary message after the merge
- 17. By Guewen Baconnier @ Camptocamp
-
merge FK pointing to crm_claim (o2m and m2m)
- 16. By Guewen Baconnier @ Camptocamp
-
introspect the list of fields to merge rather than hardcoding them
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'crm_claim_merge' | |||
2 | === added file 'crm_claim_merge/__init__.py' | |||
3 | --- crm_claim_merge/__init__.py 1970-01-01 00:00:00 +0000 | |||
4 | +++ crm_claim_merge/__init__.py 2014-04-30 14:21:25 +0000 | |||
5 | @@ -0,0 +1,4 @@ | |||
6 | 1 | # -*- coding: utf-8 -*- | ||
7 | 2 | |||
8 | 3 | from . import crm_claim | ||
9 | 4 | from . import wizard | ||
10 | 0 | 5 | ||
11 | === added file 'crm_claim_merge/__openerp__.py' | |||
12 | --- crm_claim_merge/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
13 | +++ crm_claim_merge/__openerp__.py 2014-04-30 14:21:25 +0000 | |||
14 | @@ -0,0 +1,45 @@ | |||
15 | 1 | # -*- coding: utf-8 -*- | ||
16 | 2 | ############################################################################## | ||
17 | 3 | # | ||
18 | 4 | # Author: Guewen Baconnier | ||
19 | 5 | # Copyright 2014 Camptocamp SA | ||
20 | 6 | # | ||
21 | 7 | # This program is free software: you can redistribute it and/or modify | ||
22 | 8 | # it under the terms of the GNU Affero General Public License as | ||
23 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
24 | 10 | # License, or (at your option) any later version. | ||
25 | 11 | # | ||
26 | 12 | # This program is distributed in the hope that it will be useful, | ||
27 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | 15 | # GNU Affero General Public License for more details. | ||
30 | 16 | # | ||
31 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
32 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
33 | 19 | # | ||
34 | 20 | ############################################################################## | ||
35 | 21 | |||
36 | 22 | {'name': 'Claims Merge', | ||
37 | 23 | 'version': '1.0', | ||
38 | 24 | 'author': 'Camptocamp', | ||
39 | 25 | 'maintainer': 'Camptocamp', | ||
40 | 26 | 'license': 'AGPL-3', | ||
41 | 27 | 'category': 'Customer Relationship Management', | ||
42 | 28 | 'depends': ['crm_claim', | ||
43 | 29 | ], | ||
44 | 30 | 'description': """ | ||
45 | 31 | Claims Merge | ||
46 | 32 | ============ | ||
47 | 33 | |||
48 | 34 | Select claims and use the 'Merge' option menu to merge them. | ||
49 | 35 | The messages will be grouped in one thread. | ||
50 | 36 | |||
51 | 37 | """, | ||
52 | 38 | 'website': 'http://www.camptocamp.com', | ||
53 | 39 | 'data': ['wizard/crm_claim_merge_view.xml', | ||
54 | 40 | ], | ||
55 | 41 | 'test': ['test/crm_claim_merge.yml', | ||
56 | 42 | ], | ||
57 | 43 | 'installable': True, | ||
58 | 44 | 'auto_install': False, | ||
59 | 45 | } | ||
60 | 0 | 46 | ||
61 | === added file 'crm_claim_merge/crm_claim.py' | |||
62 | --- crm_claim_merge/crm_claim.py 1970-01-01 00:00:00 +0000 | |||
63 | +++ crm_claim_merge/crm_claim.py 2014-04-30 14:21:25 +0000 | |||
64 | @@ -0,0 +1,370 @@ | |||
65 | 1 | # -*- coding: utf-8 -*- | ||
66 | 2 | ############################################################################## | ||
67 | 3 | # | ||
68 | 4 | # Author: Guewen Baconnier | ||
69 | 5 | # Copyright 2014 Camptocamp SA | ||
70 | 6 | # Merge code freely adapted to claims from merge of crm leads | ||
71 | 7 | # and partners by OpenERP | ||
72 | 8 | # Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>) | ||
73 | 9 | # | ||
74 | 10 | # This program is free software: you can redistribute it and/or modify | ||
75 | 11 | # it under the terms of the GNU Affero General Public License as | ||
76 | 12 | # published by the Free Software Foundation, either version 3 of the | ||
77 | 13 | # License, or (at your option) any later version. | ||
78 | 14 | # | ||
79 | 15 | # This program is distributed in the hope that it will be useful, | ||
80 | 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
81 | 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
82 | 18 | # GNU Affero General Public License for more details. | ||
83 | 19 | # | ||
84 | 20 | # You should have received a copy of the GNU Affero General Public License | ||
85 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
86 | 22 | # | ||
87 | 23 | ############################################################################## | ||
88 | 24 | |||
89 | 25 | from operator import attrgetter | ||
90 | 26 | from itertools import chain | ||
91 | 27 | |||
92 | 28 | from openerp import SUPERUSER_ID | ||
93 | 29 | from openerp.osv import orm | ||
94 | 30 | from openerp.tools.translate import _ | ||
95 | 31 | |||
96 | 32 | CRM_CLAIM_FIELD_BLACKLIST = [ | ||
97 | 33 | 'message_ids', | ||
98 | 34 | 'message_follower_ids', | ||
99 | 35 | ] | ||
100 | 36 | |||
101 | 37 | |||
102 | 38 | class crm_claim(orm.Model): | ||
103 | 39 | _inherit = 'crm.claim' | ||
104 | 40 | |||
105 | 41 | def _merge_get_default_main(self, cr, uid, claims, context=None): | ||
106 | 42 | return sorted(claims, key=attrgetter('date'))[0] | ||
107 | 43 | |||
108 | 44 | def _merge_sort(self, cr, uid, claims, context=None): | ||
109 | 45 | """ Sort the tailing claims. | ||
110 | 46 | |||
111 | 47 | When claims have concurrent values, the (true-ish) value from the | ||
112 | 48 | first claim is used. | ||
113 | 49 | """ | ||
114 | 50 | return sorted(claims, key=attrgetter('date')) | ||
115 | 51 | |||
116 | 52 | def _merge_check(self, cr, uid, claims, context=None): | ||
117 | 53 | if len(claims) <= 1: | ||
118 | 54 | raise orm.except_orm( | ||
119 | 55 | _('Warning'), | ||
120 | 56 | _('Please select more than one claim from the list view.')) | ||
121 | 57 | |||
122 | 58 | partner = next((claim.partner_id for claim in claims), None) | ||
123 | 59 | if partner: | ||
124 | 60 | if any(claim.partner_id != partner for claim in claims | ||
125 | 61 | if claim.partner_id): | ||
126 | 62 | raise orm.except_orm( | ||
127 | 63 | _('Error'), | ||
128 | 64 | _('Cannot merge claims of different partners.')) | ||
129 | 65 | |||
130 | 66 | def _merge_fields(self, cr, uid, context=None): | ||
131 | 67 | fields = self._all_columns | ||
132 | 68 | fields = (name for name, info in fields.iteritems() | ||
133 | 69 | if not info.column.readonly) | ||
134 | 70 | fields = (name for name in fields if | ||
135 | 71 | name not in CRM_CLAIM_FIELD_BLACKLIST) | ||
136 | 72 | return list(fields) | ||
137 | 73 | |||
138 | 74 | def _get_fk_on(self, cr, table): | ||
139 | 75 | """ Get all FK pointing to a table """ | ||
140 | 76 | q = """ SELECT cl1.relname as table, | ||
141 | 77 | att1.attname as column | ||
142 | 78 | FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, | ||
143 | 79 | pg_attribute as att1, pg_attribute as att2 | ||
144 | 80 | WHERE con.conrelid = cl1.oid | ||
145 | 81 | AND con.confrelid = cl2.oid | ||
146 | 82 | AND array_lower(con.conkey, 1) = 1 | ||
147 | 83 | AND con.conkey[1] = att1.attnum | ||
148 | 84 | AND att1.attrelid = cl1.oid | ||
149 | 85 | AND cl2.relname = %s | ||
150 | 86 | AND att2.attname = 'id' | ||
151 | 87 | AND array_lower(con.confkey, 1) = 1 | ||
152 | 88 | AND con.confkey[1] = att2.attnum | ||
153 | 89 | AND att2.attrelid = cl2.oid | ||
154 | 90 | AND con.contype = 'f' | ||
155 | 91 | """ | ||
156 | 92 | return cr.execute(q, (table,)) | ||
157 | 93 | |||
158 | 94 | def _merge_update_foreign_keys(self, cr, uid, merge_in, | ||
159 | 95 | claims, context=None): | ||
160 | 96 | claim_ids = [claim.id for claim in claims] | ||
161 | 97 | |||
162 | 98 | # find the many2one relation to a claim | ||
163 | 99 | self._get_fk_on(cr, 'crm_claim') | ||
164 | 100 | |||
165 | 101 | for table, column in cr.fetchall(): | ||
166 | 102 | if 'crm_claim_merge' in table: | ||
167 | 103 | # ignore the wizard tables (TransientModel + relation | ||
168 | 104 | # table) | ||
169 | 105 | continue | ||
170 | 106 | query = ("SELECT column_name FROM information_schema.columns" | ||
171 | 107 | " WHERE table_name = %s") | ||
172 | 108 | cr.execute(query, (table, )) | ||
173 | 109 | columns = [] | ||
174 | 110 | for data in cr.fetchall(): | ||
175 | 111 | if data[0] != column: | ||
176 | 112 | columns.append(data[0]) | ||
177 | 113 | |||
178 | 114 | query_dic = { | ||
179 | 115 | 'table': table, | ||
180 | 116 | 'column': column, | ||
181 | 117 | 'value': columns[0], | ||
182 | 118 | } | ||
183 | 119 | if len(columns) <= 1: | ||
184 | 120 | # update of m2m | ||
185 | 121 | query = """ | ||
186 | 122 | UPDATE "%(table)s" as ___tu | ||
187 | 123 | SET %(column)s = %%s | ||
188 | 124 | WHERE | ||
189 | 125 | %(column)s = %%s AND | ||
190 | 126 | NOT EXISTS ( | ||
191 | 127 | SELECT 1 | ||
192 | 128 | FROM "%(table)s" as ___tw | ||
193 | 129 | WHERE | ||
194 | 130 | %(column)s = %%s AND | ||
195 | 131 | ___tu.%(value)s = ___tw.%(value)s | ||
196 | 132 | )""" % query_dic | ||
197 | 133 | for claim_id in claim_ids: | ||
198 | 134 | cr.execute(query, (merge_in.id, claim_id, | ||
199 | 135 | merge_in.id)) | ||
200 | 136 | else: | ||
201 | 137 | query = ('UPDATE "%(table)s" SET %(column)s = %%s WHERE ' | ||
202 | 138 | '%(column)s IN %%s') % query_dic | ||
203 | 139 | cr.execute(query, (merge_in.id, tuple(claim_ids))) | ||
204 | 140 | |||
205 | 141 | def _merge_data(self, cr, uid, merge_in, claims, fields, context=None): | ||
206 | 142 | """ | ||
207 | 143 | Prepare claims data into a dictionary for merging. Different types | ||
208 | 144 | of fields are processed in different ways: | ||
209 | 145 | - text: all the values are concatenated | ||
210 | 146 | - m2m and o2m: those fields aren't processed | ||
211 | 147 | - m2o: the first not null value prevails (the other are dropped) | ||
212 | 148 | - any other type of field: same as m2o | ||
213 | 149 | |||
214 | 150 | :param merge_in: other claims will be merged in this one | ||
215 | 151 | :param claims: list of claims to merge | ||
216 | 152 | :param fields: list of leads' fields to process | ||
217 | 153 | :return data: contains the merged values | ||
218 | 154 | """ | ||
219 | 155 | claims = [merge_in] + claims | ||
220 | 156 | |||
221 | 157 | def _get_first_not_falsish(attr): | ||
222 | 158 | for claim in claims: | ||
223 | 159 | value = getattr(claim, attr, None) | ||
224 | 160 | if value: | ||
225 | 161 | return value | ||
226 | 162 | return False | ||
227 | 163 | |||
228 | 164 | def _get_first_reference(attr): | ||
229 | 165 | rel = _get_first_not_falsish(attr) | ||
230 | 166 | return '%s,%s' % (rel._model._name, rel.id) if rel else False | ||
231 | 167 | |||
232 | 168 | def _get_first_m2o(attr): | ||
233 | 169 | rel = _get_first_not_falsish(attr) | ||
234 | 170 | return rel.id if rel else False | ||
235 | 171 | |||
236 | 172 | def _concat_text(attr): | ||
237 | 173 | return '\n\n'.join([getattr(claim, attr) or '' for claim in claims | ||
238 | 174 | if hasattr(claim, attr)]) | ||
239 | 175 | |||
240 | 176 | # Process the fields' values | ||
241 | 177 | data = {} | ||
242 | 178 | for field_name in fields: | ||
243 | 179 | field_info = self._all_columns.get(field_name) | ||
244 | 180 | if field_info is None: | ||
245 | 181 | continue | ||
246 | 182 | field = field_info.column | ||
247 | 183 | field_type = field._type # noqa | ||
248 | 184 | if field_type in ('many2many', 'one2many'): | ||
249 | 185 | continue | ||
250 | 186 | elif field_type == 'many2one': | ||
251 | 187 | data[field_name] = _get_first_m2o(field_name) | ||
252 | 188 | elif field_type == 'text': | ||
253 | 189 | data[field_name] = _concat_text(field_name) | ||
254 | 190 | elif field_type == 'reference': | ||
255 | 191 | data[field_name] = _get_first_reference(field_name) | ||
256 | 192 | else: | ||
257 | 193 | data[field_name] = _get_first_not_falsish(field_name) | ||
258 | 194 | |||
259 | 195 | # Check if the stage is in the stages of the sales team. If not, | ||
260 | 196 | # assign the stage with the lowest sequence | ||
261 | 197 | if data.get('section_id'): | ||
262 | 198 | stage_obj = self.pool['crm.case.stage'] | ||
263 | 199 | section_stage_ids = stage_obj.search( | ||
264 | 200 | cr, uid, | ||
265 | 201 | [('section_ids', 'in', data['section_id'])], | ||
266 | 202 | order='sequence', | ||
267 | 203 | context=context) | ||
268 | 204 | if data.get('stage_id') not in section_stage_ids: | ||
269 | 205 | data['stage_id'] = (section_stage_ids[0] if | ||
270 | 206 | section_stage_ids else False) | ||
271 | 207 | return data | ||
272 | 208 | |||
273 | 209 | def _merge_claim_history(self, cr, uid, merge_in, claims, context=None): | ||
274 | 210 | merge_in_id = merge_in.id | ||
275 | 211 | for claim in claims: | ||
276 | 212 | history_ids = set() | ||
277 | 213 | for history in claim.message_ids: | ||
278 | 214 | history_ids.add(history.id) | ||
279 | 215 | message = self.pool['mail.message'] | ||
280 | 216 | message.write(cr, uid, | ||
281 | 217 | list(history_ids), | ||
282 | 218 | {'res_id': merge_in_id, | ||
283 | 219 | 'subject': _("From %s") % claim.name_get()[0][1], | ||
284 | 220 | }, | ||
285 | 221 | context=context) | ||
286 | 222 | |||
287 | 223 | def _merge_claim_attachments(self, cr, uid, merge_in, claims, context=None): | ||
288 | 224 | attach_obj = self.pool['ir.attachment'] | ||
289 | 225 | |||
290 | 226 | # return attachments of claims | ||
291 | 227 | def _get_attachments(claim_id): | ||
292 | 228 | attachment_ids = attach_obj.search( | ||
293 | 229 | cr, uid, | ||
294 | 230 | [('res_model', '=', self._name), | ||
295 | 231 | ('res_id', '=', claim_id)], | ||
296 | 232 | context=context) | ||
297 | 233 | return attach_obj.browse(cr, uid, attachment_ids, context=context) | ||
298 | 234 | |||
299 | 235 | first_attachments = _get_attachments(merge_in.id) | ||
300 | 236 | merge_in_id = merge_in.id | ||
301 | 237 | |||
302 | 238 | # Counter of all attachments to move. | ||
303 | 239 | # Used to make sure the name is different for all attachments | ||
304 | 240 | existing_names = [att.name for att in first_attachments] | ||
305 | 241 | for claim in claims: | ||
306 | 242 | attachments = _get_attachments(claim.id) | ||
307 | 243 | for attachment in attachments: | ||
308 | 244 | values = {'res_id': merge_in_id} | ||
309 | 245 | name = attachment.name | ||
310 | 246 | count = 1 | ||
311 | 247 | while name in existing_names: | ||
312 | 248 | name = "%s (%s)" % (attachment.name, count) | ||
313 | 249 | count += 1 | ||
314 | 250 | values['name'] = name | ||
315 | 251 | attachment.write(values) | ||
316 | 252 | existing_names.append(name) | ||
317 | 253 | |||
318 | 254 | def _merge_mail_body(self, cr, uid, claim, fields, title=False, context=None): | ||
319 | 255 | body = [] | ||
320 | 256 | if title: | ||
321 | 257 | body.append("%s\n" % title) | ||
322 | 258 | |||
323 | 259 | for field_name in fields: | ||
324 | 260 | field_info = self._all_columns.get(field_name) | ||
325 | 261 | if field_info is None: | ||
326 | 262 | continue | ||
327 | 263 | field = field_info.column | ||
328 | 264 | value = '' | ||
329 | 265 | |||
330 | 266 | field_type = field._type # noqa | ||
331 | 267 | |||
332 | 268 | if field_type == 'selection': | ||
333 | 269 | if hasattr(field.selection, '__call__'): | ||
334 | 270 | key = field.selection(self, cr, uid, context=context) | ||
335 | 271 | else: | ||
336 | 272 | key = field.selection | ||
337 | 273 | value = dict(key).get(claim[field_name], claim[field_name]) | ||
338 | 274 | elif field_type in ('many2one', 'reference'): | ||
339 | 275 | if claim[field_name]: | ||
340 | 276 | value = claim[field_name].name_get()[0][1] | ||
341 | 277 | elif field_type in ('many2many', 'one2many'): | ||
342 | 278 | if claim[field_name]: | ||
343 | 279 | for val in claim[field_name]: | ||
344 | 280 | field_value = val.name_get()[0][1] | ||
345 | 281 | value += field_value + "," | ||
346 | 282 | else: | ||
347 | 283 | value = claim[field_name] | ||
348 | 284 | |||
349 | 285 | body.append("%s: %s" % (field.string, value or '')) | ||
350 | 286 | return "<br/>".join(body + ['<br/>']) | ||
351 | 287 | |||
352 | 288 | def _merge_notify(self, cr, uid, merge_in, claims, context=None): | ||
353 | 289 | """ Create a message gathering merged claims information. """ | ||
354 | 290 | details = [] | ||
355 | 291 | subject = [_('Merged claims')] | ||
356 | 292 | for claim in chain([merge_in] + claims): | ||
357 | 293 | name = claim.name_get()[0][1] | ||
358 | 294 | subject.append(name) | ||
359 | 295 | title = "%s: %s" % (_('Merged claim'), name) | ||
360 | 296 | fields = list(self._merge_fields(cr, uid, context=context)) | ||
361 | 297 | details.append(self._merge_mail_body(cr, uid, claim, fields, | ||
362 | 298 | title=title, context=context)) | ||
363 | 299 | |||
364 | 300 | # Chatter message's subject | ||
365 | 301 | subject = subject[0] + ": " + ", ".join(subject[1:]) | ||
366 | 302 | details = "\n\n".join(details) | ||
367 | 303 | return self.message_post(cr, uid, [merge_in.id], | ||
368 | 304 | body=details, subject=subject, | ||
369 | 305 | context=context) | ||
370 | 306 | |||
371 | 307 | def _merge_followers(self, cr, uid, merge_in, claims, context=None): | ||
372 | 308 | """ Subscribe the same followers on the final claim. """ | ||
373 | 309 | follower_ids = [fol.id for fol in merge_in.message_follower_ids] | ||
374 | 310 | |||
375 | 311 | fol_obj = self.pool.get('mail.followers') | ||
376 | 312 | fol_ids = fol_obj.search( | ||
377 | 313 | cr, SUPERUSER_ID, | ||
378 | 314 | [('res_model', '=', self._name), | ||
379 | 315 | ('res_id', 'in', [claim.id for claim in claims])], | ||
380 | 316 | context=context) | ||
381 | 317 | |||
382 | 318 | for fol in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context): | ||
383 | 319 | if fol.res_id in follower_ids: | ||
384 | 320 | continue | ||
385 | 321 | subtype_ids = [st.id for st in fol.subtype_ids] | ||
386 | 322 | self.message_subscribe(cr, SUPERUSER_ID, [merge_in.id], | ||
387 | 323 | [fol.partner_id.id], | ||
388 | 324 | subtype_ids=subtype_ids, | ||
389 | 325 | context=context) | ||
390 | 326 | |||
391 | 327 | def merge(self, cr, uid, ids, merge_in_id=None, context=None): | ||
392 | 328 | """ Merge claims together. | ||
393 | 329 | |||
394 | 330 | :param merge_in_ids: the other claims will be merged into this one | ||
395 | 331 | if None, the oldest claim will be selected. | ||
396 | 332 | """ | ||
397 | 333 | claims = self.browse(cr, uid, ids, context=context) | ||
398 | 334 | self._merge_check(cr, uid, claims, context=context) | ||
399 | 335 | if merge_in_id is None: | ||
400 | 336 | merge_in = self._merge_get_default_main(cr, uid, claims, | ||
401 | 337 | context=context) | ||
402 | 338 | else: | ||
403 | 339 | for claim in claims: | ||
404 | 340 | if claim.id == merge_in_id: | ||
405 | 341 | merge_in = claim | ||
406 | 342 | break | ||
407 | 343 | claims.remove(merge_in) # keep the tail | ||
408 | 344 | claims = self._merge_sort(cr, uid, claims, context=context) | ||
409 | 345 | |||
410 | 346 | fields = list(self._merge_fields(cr, uid, context=None)) | ||
411 | 347 | data = self._merge_data(cr, uid, merge_in, claims, | ||
412 | 348 | fields, context=context) | ||
413 | 349 | |||
414 | 350 | self._merge_claim_history(cr, uid, merge_in, claims, context=context) | ||
415 | 351 | self._merge_claim_attachments(cr, uid, merge_in, claims, | ||
416 | 352 | context=context) | ||
417 | 353 | |||
418 | 354 | self._merge_notify(cr, uid, merge_in, claims, context=context) | ||
419 | 355 | self._merge_followers(cr, uid, merge_in, claims, context=context) | ||
420 | 356 | |||
421 | 357 | self._merge_update_foreign_keys(cr, uid, merge_in, | ||
422 | 358 | claims, context=context) | ||
423 | 359 | # Write merged data into first claim | ||
424 | 360 | self.write(cr, uid, [merge_in.id], data, context=context) | ||
425 | 361 | |||
426 | 362 | # Delete tail claims | ||
427 | 363 | # We use the SUPERUSER to avoid access rights issues because as | ||
428 | 364 | # the user had the rights to see the records it should be safe | ||
429 | 365 | # to do so | ||
430 | 366 | self.unlink(cr, SUPERUSER_ID, | ||
431 | 367 | [claim.id for claim in claims], | ||
432 | 368 | context=context) | ||
433 | 369 | |||
434 | 370 | return merge_in.id | ||
435 | 0 | 371 | ||
436 | === added directory 'crm_claim_merge/i18n' | |||
437 | === added file 'crm_claim_merge/i18n/crm_claim_merge.pot' | |||
438 | --- crm_claim_merge/i18n/crm_claim_merge.pot 1970-01-01 00:00:00 +0000 | |||
439 | +++ crm_claim_merge/i18n/crm_claim_merge.pot 2014-04-30 14:21:25 +0000 | |||
440 | @@ -0,0 +1,69 @@ | |||
441 | 1 | # Translation of OpenERP Server. | ||
442 | 2 | # This file contains the translation of the following modules: | ||
443 | 3 | # * crm_claim_merge | ||
444 | 4 | # | ||
445 | 5 | msgid "" | ||
446 | 6 | msgstr "" | ||
447 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | ||
448 | 8 | "Report-Msgid-Bugs-To: \n" | ||
449 | 9 | "POT-Creation-Date: 2014-04-30 14:15+0000\n" | ||
450 | 10 | "PO-Revision-Date: 2014-04-30 14:15+0000\n" | ||
451 | 11 | "Last-Translator: <>\n" | ||
452 | 12 | "Language-Team: \n" | ||
453 | 13 | "MIME-Version: 1.0\n" | ||
454 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
455 | 15 | "Content-Transfer-Encoding: \n" | ||
456 | 16 | "Plural-Forms: \n" | ||
457 | 17 | |||
458 | 18 | #. module: crm_claim_merge | ||
459 | 19 | #: view:crm.claim.merge:0 | ||
460 | 20 | msgid "Cancel" | ||
461 | 21 | msgstr "" | ||
462 | 22 | |||
463 | 23 | #. module: crm_claim_merge | ||
464 | 24 | #: code:_description:0 | ||
465 | 25 | #: model:ir.model,name:crm_claim_merge.model_crm_claim | ||
466 | 26 | #, python-format | ||
467 | 27 | msgid "Claim" | ||
468 | 28 | msgstr "" | ||
469 | 29 | |||
470 | 30 | #. module: crm_claim_merge | ||
471 | 31 | #: field:crm.claim.merge,claim_ids:0 | ||
472 | 32 | msgid "Claims" | ||
473 | 33 | msgstr "" | ||
474 | 34 | |||
475 | 35 | #. module: crm_claim_merge | ||
476 | 36 | #: view:crm.claim.merge:0 | ||
477 | 37 | msgid "Merge" | ||
478 | 38 | msgstr "" | ||
479 | 39 | |||
480 | 40 | #. module: crm_claim_merge | ||
481 | 41 | #: code:_description:0 | ||
482 | 42 | #: view:crm.claim.merge:0 | ||
483 | 43 | #: model:ir.actions.act_window,name:crm_claim_merge.action_crm_claim_merge | ||
484 | 44 | #: model:ir.actions.act_window,name:crm_claim_merge.action_merge_claim | ||
485 | 45 | #: model:ir.model,name:crm_claim_merge.model_crm_claim_merge | ||
486 | 46 | #, python-format | ||
487 | 47 | msgid "Merge Claims" | ||
488 | 48 | msgstr "" | ||
489 | 49 | |||
490 | 50 | #. module: crm_claim_merge | ||
491 | 51 | #: field:crm.claim.merge,merge_in_id:0 | ||
492 | 52 | msgid "Merge in" | ||
493 | 53 | msgstr "" | ||
494 | 54 | |||
495 | 55 | #. module: crm_claim_merge | ||
496 | 56 | #: view:crm.claim.merge:0 | ||
497 | 57 | msgid "Select Claims" | ||
498 | 58 | msgstr "" | ||
499 | 59 | |||
500 | 60 | #. module: crm_claim_merge | ||
501 | 61 | #: help:crm.claim.merge,merge_in_id:0 | ||
502 | 62 | msgid "The other claims will be merged into this one." | ||
503 | 63 | msgstr "" | ||
504 | 64 | |||
505 | 65 | #. module: crm_claim_merge | ||
506 | 66 | #: view:crm.claim.merge:0 | ||
507 | 67 | msgid "or" | ||
508 | 68 | msgstr "" | ||
509 | 69 | |||
510 | 0 | 70 | ||
511 | === added file 'crm_claim_merge/i18n/fr.po' | |||
512 | --- crm_claim_merge/i18n/fr.po 1970-01-01 00:00:00 +0000 | |||
513 | +++ crm_claim_merge/i18n/fr.po 2014-04-30 14:21:25 +0000 | |||
514 | @@ -0,0 +1,69 @@ | |||
515 | 1 | # Translation of OpenERP Server. | ||
516 | 2 | # This file contains the translation of the following modules: | ||
517 | 3 | # * crm_claim_merge | ||
518 | 4 | # | ||
519 | 5 | msgid "" | ||
520 | 6 | msgstr "" | ||
521 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | ||
522 | 8 | "Report-Msgid-Bugs-To: \n" | ||
523 | 9 | "POT-Creation-Date: 2014-04-30 14:16+0000\n" | ||
524 | 10 | "PO-Revision-Date: 2014-04-30 14:16+0000\n" | ||
525 | 11 | "Last-Translator: <>\n" | ||
526 | 12 | "Language-Team: \n" | ||
527 | 13 | "MIME-Version: 1.0\n" | ||
528 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
529 | 15 | "Content-Transfer-Encoding: \n" | ||
530 | 16 | "Plural-Forms: \n" | ||
531 | 17 | |||
532 | 18 | #. module: crm_claim_merge | ||
533 | 19 | #: view:crm.claim.merge:0 | ||
534 | 20 | msgid "Cancel" | ||
535 | 21 | msgstr "Annuler" | ||
536 | 22 | |||
537 | 23 | #. module: crm_claim_merge | ||
538 | 24 | #: code:_description:0 | ||
539 | 25 | #: model:ir.model,name:crm_claim_merge.model_crm_claim | ||
540 | 26 | #, python-format | ||
541 | 27 | msgid "Claim" | ||
542 | 28 | msgstr "Réclamation" | ||
543 | 29 | |||
544 | 30 | #. module: crm_claim_merge | ||
545 | 31 | #: field:crm.claim.merge,claim_ids:0 | ||
546 | 32 | msgid "Claims" | ||
547 | 33 | msgstr "Réclamations" | ||
548 | 34 | |||
549 | 35 | #. module: crm_claim_merge | ||
550 | 36 | #: view:crm.claim.merge:0 | ||
551 | 37 | msgid "Merge" | ||
552 | 38 | msgstr "Fusion" | ||
553 | 39 | |||
554 | 40 | #. module: crm_claim_merge | ||
555 | 41 | #: code:_description:0 | ||
556 | 42 | #: view:crm.claim.merge:0 | ||
557 | 43 | #: model:ir.actions.act_window,name:crm_claim_merge.action_crm_claim_merge | ||
558 | 44 | #: model:ir.actions.act_window,name:crm_claim_merge.action_merge_claim | ||
559 | 45 | #: model:ir.model,name:crm_claim_merge.model_crm_claim_merge | ||
560 | 46 | #, python-format | ||
561 | 47 | msgid "Merge Claims" | ||
562 | 48 | msgstr "Fusionner des réclamations" | ||
563 | 49 | |||
564 | 50 | #. module: crm_claim_merge | ||
565 | 51 | #: field:crm.claim.merge,merge_in_id:0 | ||
566 | 52 | msgid "Merge in" | ||
567 | 53 | msgstr "Fusionner dans" | ||
568 | 54 | |||
569 | 55 | #. module: crm_claim_merge | ||
570 | 56 | #: view:crm.claim.merge:0 | ||
571 | 57 | msgid "Select Claims" | ||
572 | 58 | msgstr "Choisir les réclamations" | ||
573 | 59 | |||
574 | 60 | #. module: crm_claim_merge | ||
575 | 61 | #: help:crm.claim.merge,merge_in_id:0 | ||
576 | 62 | msgid "The other claims will be merged into this one." | ||
577 | 63 | msgstr "Les autres réclamations seront fusionnées dans celle-ci." | ||
578 | 64 | |||
579 | 65 | #. module: crm_claim_merge | ||
580 | 66 | #: view:crm.claim.merge:0 | ||
581 | 67 | msgid "or" | ||
582 | 68 | msgstr "ou" | ||
583 | 69 | |||
584 | 0 | 70 | ||
585 | === added directory 'crm_claim_merge/test' | |||
586 | === added file 'crm_claim_merge/test/crm_claim_merge.yml' | |||
587 | --- crm_claim_merge/test/crm_claim_merge.yml 1970-01-01 00:00:00 +0000 | |||
588 | +++ crm_claim_merge/test/crm_claim_merge.yml 2014-04-30 14:21:25 +0000 | |||
589 | @@ -0,0 +1,103 @@ | |||
590 | 1 | - | ||
591 | 2 | Create claims to test their merge | ||
592 | 3 | - | ||
593 | 4 | !record {model: crm.claim, id: test_crm_claim_01}: | ||
594 | 5 | name: 'Test claim 1' | ||
595 | 6 | date: !eval time.strftime('%Y-02-08 00:00:00') | ||
596 | 7 | partner_id: base.res_partner_3 | ||
597 | 8 | stage_id: crm_claim.stage_claim1 | ||
598 | 9 | description: This is the description of the test claim 1. | ||
599 | 10 | partner_phone: (373) 907-1009 | ||
600 | 11 | email_from: bill@example.com | ||
601 | 12 | ref: !eval ('res.partner,%d' % ref('base.res_partner_5')) | ||
602 | 13 | type_action: correction | ||
603 | 14 | - | ||
604 | 15 | !record {model: crm.claim, id: test_crm_claim_02}: | ||
605 | 16 | name: 'Test claim 2' | ||
606 | 17 | date: !eval time.strftime('%Y-02-04 00:00:00') | ||
607 | 18 | partner_id: base.res_partner_3 | ||
608 | 19 | stage_id: crm_claim.stage_claim5 | ||
609 | 20 | description: This is the description of the test claim 2. | ||
610 | 21 | partner_phone: (373) 907-1009 | ||
611 | 22 | email_from: bill@example.com | ||
612 | 23 | - | ||
613 | 24 | !record {model: crm.claim, id: test_crm_claim_03}: | ||
614 | 25 | name: 'Test claim 3' | ||
615 | 26 | date: !eval time.strftime('%Y-02-06 00:00:00') | ||
616 | 27 | partner_id: base.res_partner_3 | ||
617 | 28 | stage_id: crm_claim.stage_claim3 | ||
618 | 29 | description: This is the description of the test claim 3. | ||
619 | 30 | partner_phone: (373) 907-1010 | ||
620 | 31 | email_from: tom@example.com | ||
621 | 32 | type_action: prevention | ||
622 | 33 | section_id: crm.section_sales_department | ||
623 | 34 | - | ||
624 | 35 | !python {model: crm.claim}: | | ||
625 | 36 | claim_ids = [ref('test_crm_claim_01'), | ||
626 | 37 | ref('test_crm_claim_02'), | ||
627 | 38 | ref('test_crm_claim_03')] | ||
628 | 39 | context.update({'active_model': 'crm.claim', | ||
629 | 40 | 'active_ids': claim_ids, | ||
630 | 41 | 'active_id': claim_ids[0]}) | ||
631 | 42 | - | ||
632 | 43 | I create a merge wizard and merge the claims together in the second claim | ||
633 | 44 | - | ||
634 | 45 | !record {model: crm.claim.merge, id: merge_claim_wizard_01}: | ||
635 | 46 | - | ||
636 | 47 | !python {model: crm.claim.merge}: | | ||
637 | 48 | self.action_merge(cr, uid, [ref("merge_claim_wizard_01")], context=context) | ||
638 | 49 | - | ||
639 | 50 | I check for the resulting merged claim (based on name and partner). | ||
640 | 51 | - | ||
641 | 52 | !python {model: crm.claim}: | | ||
642 | 53 | merge_id = self.search(cr, uid, | ||
643 | 54 | [('name', '=', 'Test claim 2'), | ||
644 | 55 | ('partner_id','=', ref("base.res_partner_3"))]) | ||
645 | 56 | assert merge_id, 'Failed to create the merged claim' | ||
646 | 57 | claim = self.browse(cr, uid, merge_id[0]) | ||
647 | 58 | expected = ('This is the description of the test claim 2.\n\n' | ||
648 | 59 | 'This is the description of the test claim 3.\n\n' | ||
649 | 60 | 'This is the description of the test claim 1.') | ||
650 | 61 | assert claim.description == expected, ( | ||
651 | 62 | 'Description mismatch: when merging claims with ' | ||
652 | 63 | 'different text values, these values should get ' | ||
653 | 64 | 'concatenated and separated with line returns') | ||
654 | 65 | expected = 'bill@example.com' | ||
655 | 66 | assert claim.email_from == expected, ( | ||
656 | 67 | 'Email mismatch, expected %s, got: %s' % | ||
657 | 68 | (expected, claim.email_from)) | ||
658 | 69 | import time | ||
659 | 70 | expected = time.strftime('%Y-02-04 00:00:00') | ||
660 | 71 | assert claim.date == expected, ( | ||
661 | 72 | 'Date mismatch, expected %s, got: %s' % | ||
662 | 73 | (expected, claim.date)) | ||
663 | 74 | expected = ref('crm_claim.stage_claim5') | ||
664 | 75 | assert claim.stage_id.id == expected, ( | ||
665 | 76 | 'Stage mismatch, expected %s, got: %s' % | ||
666 | 77 | (expected, claim.stage_id.id)) | ||
667 | 78 | expected = '(373) 907-1009' | ||
668 | 79 | assert claim.partner_phone == expected, ( | ||
669 | 80 | 'Phone mismatch, expected %s, got: %s' % | ||
670 | 81 | (expected, claim.partner_phone)) | ||
671 | 82 | expected = ref('base.res_partner_5') | ||
672 | 83 | assert (claim.ref.id == expected | ||
673 | 84 | and claim.ref._model._name == 'res.partner'), ( | ||
674 | 85 | 'Reference mismatch, expected a partner with id %s, got: %s' % | ||
675 | 86 | (expected, claim.ref)) | ||
676 | 87 | expected = 'prevention' | ||
677 | 88 | assert claim.type_action == expected, ( | ||
678 | 89 | 'Action Type mismatch, expected %s, got: %s' % | ||
679 | 90 | (expected, claim.type_action)) | ||
680 | 91 | expected = ref('crm.section_sales_department') | ||
681 | 92 | assert claim.section_id.id == expected, ( | ||
682 | 93 | 'Section mismatch, expected %s, got: %s' % | ||
683 | 94 | (expected, claim.section_id.id)) | ||
684 | 95 | - | ||
685 | 96 | The other (tailing) claims shouldn't exist anymore. | ||
686 | 97 | - | ||
687 | 98 | !python {model: crm.claim}: | | ||
688 | 99 | tailing_claim = self.search(cr, uid, [('id', '=', ref('test_crm_claim_01'))]) | ||
689 | 100 | assert not tailing_claim, 'This tailing claim (id %s) should not exist anymore' % ref('test_crm_claim_01') | ||
690 | 101 | |||
691 | 102 | tailing_claim = self.search(cr, uid, [('id', '=', ref('test_crm_claim_03'))]) | ||
692 | 103 | assert not tailing_claim, 'This tailing claim (id %s) should not exist anymore' % ref('test_crm_claim_03') | ||
693 | 0 | 104 | ||
694 | === added directory 'crm_claim_merge/wizard' | |||
695 | === added file 'crm_claim_merge/wizard/__init__.py' | |||
696 | --- crm_claim_merge/wizard/__init__.py 1970-01-01 00:00:00 +0000 | |||
697 | +++ crm_claim_merge/wizard/__init__.py 2014-04-30 14:21:25 +0000 | |||
698 | @@ -0,0 +1,3 @@ | |||
699 | 1 | # -*- coding: utf-8 -*- | ||
700 | 2 | |||
701 | 3 | from . import crm_claim_merge | ||
702 | 0 | 4 | ||
703 | === added file 'crm_claim_merge/wizard/crm_claim_merge.py' | |||
704 | --- crm_claim_merge/wizard/crm_claim_merge.py 1970-01-01 00:00:00 +0000 | |||
705 | +++ crm_claim_merge/wizard/crm_claim_merge.py 2014-04-30 14:21:25 +0000 | |||
706 | @@ -0,0 +1,83 @@ | |||
707 | 1 | # -*- coding: utf-8 -*- | ||
708 | 2 | ############################################################################## | ||
709 | 3 | # | ||
710 | 4 | # Author: Guewen Baconnier | ||
711 | 5 | # Copyright 2014 Camptocamp SA | ||
712 | 6 | # | ||
713 | 7 | # This program is free software: you can redistribute it and/or modify | ||
714 | 8 | # it under the terms of the GNU Affero General Public License as | ||
715 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
716 | 10 | # License, or (at your option) any later version. | ||
717 | 11 | # | ||
718 | 12 | # This program is distributed in the hope that it will be useful, | ||
719 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
720 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
721 | 15 | # GNU Affero General Public License for more details. | ||
722 | 16 | # | ||
723 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
724 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
725 | 19 | # | ||
726 | 20 | ############################################################################## | ||
727 | 21 | |||
728 | 22 | from openerp.osv import orm, fields | ||
729 | 23 | from openerp.tools.translate import _ | ||
730 | 24 | |||
731 | 25 | |||
732 | 26 | class crm_claim_merge(orm.TransientModel): | ||
733 | 27 | """ Merge claims together. """ | ||
734 | 28 | |||
735 | 29 | _name = 'crm.claim.merge' | ||
736 | 30 | _description = 'Merge Claims' | ||
737 | 31 | _columns = { | ||
738 | 32 | 'claim_ids': fields.many2many('crm.claim', | ||
739 | 33 | string='Claims'), | ||
740 | 34 | 'merge_in_id': fields.many2one( | ||
741 | 35 | 'crm.claim', | ||
742 | 36 | string='Merge in', | ||
743 | 37 | domain="[('id', 'in', claim_ids[0][2])]", | ||
744 | 38 | help="The other claims will be merged " | ||
745 | 39 | "into this one."), | ||
746 | 40 | } | ||
747 | 41 | |||
748 | 42 | def redirect_new_claim(self, cr, uid, claim_id, context=None): | ||
749 | 43 | models_data = self.pool.get('ir.model.data') | ||
750 | 44 | __, form_view = models_data.get_object_reference( | ||
751 | 45 | cr, uid, 'crm_claim', 'crm_case_claims_form_view') | ||
752 | 46 | return { | ||
753 | 47 | 'name': _('Claim'), | ||
754 | 48 | 'view_type': 'form', | ||
755 | 49 | 'view_mode': 'form', | ||
756 | 50 | 'res_model': 'crm.claim', | ||
757 | 51 | 'res_id': int(claim_id), | ||
758 | 52 | 'view_id': form_view, | ||
759 | 53 | 'type': 'ir.actions.act_window', | ||
760 | 54 | } | ||
761 | 55 | |||
762 | 56 | def action_merge(self, cr, uid, ids, context=None): | ||
763 | 57 | claim_obj = self.pool['crm.claim'] | ||
764 | 58 | if isinstance(ids, (tuple, list)): | ||
765 | 59 | assert len(ids) == 1, "Expect 1 ID, got: %s" % ids | ||
766 | 60 | ids = ids[0] | ||
767 | 61 | wizard = self.browse(cr, uid, ids, context=context) | ||
768 | 62 | merge_ids = [claim.id for claim in wizard.claim_ids] | ||
769 | 63 | merged_id = claim_obj.merge(cr, uid, merge_ids, | ||
770 | 64 | merge_in_id=wizard.merge_in_id.id, | ||
771 | 65 | context=context) | ||
772 | 66 | return self.redirect_new_claim(cr, uid, merged_id, context=context) | ||
773 | 67 | |||
774 | 68 | def default_get(self, cr, uid, fields, context=None): | ||
775 | 69 | """ | ||
776 | 70 | Use active_ids from the context to fetch the claims to merge. | ||
777 | 71 | """ | ||
778 | 72 | if context is None: | ||
779 | 73 | context = {} | ||
780 | 74 | res = super(crm_claim_merge, self).default_get( | ||
781 | 75 | cr, uid, fields, context=context) | ||
782 | 76 | if 'claim_ids' in fields: | ||
783 | 77 | res['claim_ids'] = claim_ids = context.get('active_ids') | ||
784 | 78 | if 'merge_in_id' in fields and claim_ids: | ||
785 | 79 | claim_obj = self.pool['crm.claim'] | ||
786 | 80 | claims = claim_obj.browse(cr, uid, claim_ids, context=context) | ||
787 | 81 | res['merge_in_id'] = claim_obj._merge_get_default_main( | ||
788 | 82 | cr, uid, claims, context=context).id | ||
789 | 83 | return res | ||
790 | 0 | 84 | ||
791 | === added file 'crm_claim_merge/wizard/crm_claim_merge_view.xml' | |||
792 | --- crm_claim_merge/wizard/crm_claim_merge_view.xml 1970-01-01 00:00:00 +0000 | |||
793 | +++ crm_claim_merge/wizard/crm_claim_merge_view.xml 2014-04-30 14:21:25 +0000 | |||
794 | @@ -0,0 +1,41 @@ | |||
795 | 1 | <?xml version="1.0"?> | ||
796 | 2 | <openerp> | ||
797 | 3 | <data> | ||
798 | 4 | |||
799 | 5 | <!-- Merge Claims --> | ||
800 | 6 | <record model="ir.ui.view" id="view_crm_claim_merge_form"> | ||
801 | 7 | <field name="name">crm.claim.merge.form</field> | ||
802 | 8 | <field name="model">crm.claim.merge</field> | ||
803 | 9 | <field name="arch" type="xml"> | ||
804 | 10 | <form string="Merge Claims" version="7.0"> | ||
805 | 11 | <group string="Select Claims"> | ||
806 | 12 | <field name="claim_ids"/> | ||
807 | 13 | <field name="merge_in_id" /> | ||
808 | 14 | </group> | ||
809 | 15 | <footer> | ||
810 | 16 | <button name="action_merge" type="object" string="Merge" class="oe_highlight"/> | ||
811 | 17 | or | ||
812 | 18 | <button string="Cancel" class="oe_link" special="cancel"/> | ||
813 | 19 | </footer> | ||
814 | 20 | </form> | ||
815 | 21 | </field> | ||
816 | 22 | </record> | ||
817 | 23 | |||
818 | 24 | <!-- Merge leads/claim action --> | ||
819 | 25 | <record model="ir.actions.act_window" id="action_crm_claim_merge"> | ||
820 | 26 | <field name="name">Merge Claims</field> | ||
821 | 27 | <field name="res_model">crm.claim.merge</field> | ||
822 | 28 | <field name="view_type">form</field> | ||
823 | 29 | <field name="view_mode">form</field> | ||
824 | 30 | <field name="view_id" ref="view_crm_claim_merge_form"/> | ||
825 | 31 | <field name="target">new</field> | ||
826 | 32 | </record> | ||
827 | 33 | |||
828 | 34 | <act_window id="action_merge_claim" | ||
829 | 35 | multi="True" | ||
830 | 36 | key2="client_action_multi" name="Merge Claims" | ||
831 | 37 | res_model="crm.claim.merge" src_model="crm.claim" | ||
832 | 38 | view_mode="form" target="new" view_type="form"/> | ||
833 | 39 | |||
834 | 40 | </data> | ||
835 | 41 | </openerp> |
Moved to https:/ /github. com/OCA/ crm/pull/ 7