Merge lp:~unifield-team/unifield-wm/uftp-120 into lp:unifield-wm
- uftp-120
- Merge into trunk
Proposed by
jftempo
Status: | Merged |
---|---|
Merged at revision: | 2144 |
Proposed branch: | lp:~unifield-team/unifield-wm/uftp-120 |
Merge into: | lp:unifield-wm |
Diff against target: |
288 lines (+92/-55) 2 files modified
msf_doc_import/wizard/wizard_delete_lines.py (+87/-50) msf_doc_import/wizard/wizard_delete_lines_view.xml (+5/-5) |
To merge this branch: | bzr merge lp:~unifield-team/unifield-wm/uftp-120 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Reviewer Team | Pending | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
- 2123. By Quentin THEURET @Amaris
-
UFTP-120 [FIX] Delete multiple wizard: Put the good on views for IR and RfQ
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'msf_doc_import/wizard/wizard_delete_lines.py' | |||
2 | --- msf_doc_import/wizard/wizard_delete_lines.py 2014-01-13 16:51:04 +0000 | |||
3 | +++ msf_doc_import/wizard/wizard_delete_lines.py 2014-05-02 09:09:28 +0000 | |||
4 | @@ -2,7 +2,7 @@ | |||
5 | 2 | ############################################################################## | 2 | ############################################################################## |
6 | 3 | # | 3 | # |
7 | 4 | # OpenERP, Open Source Management Solution | 4 | # OpenERP, Open Source Management Solution |
9 | 5 | # Copyright (C) 2011 TeMPO Consulting, MSF | 5 | # Copyright (C) 2011 TeMPO Consulting, MSF |
10 | 6 | # | 6 | # |
11 | 7 | # This program is free software: you can redistribute it and/or modify | 7 | # This program is free software: you can redistribute it and/or modify |
12 | 8 | # it under the terms of the GNU Affero General Public License as | 8 | # it under the terms of the GNU Affero General Public License as |
13 | @@ -43,21 +43,23 @@ | |||
14 | 43 | * field with the quantity for the line | 43 | * field with the quantity for the line |
15 | 44 | * domain to apply on lines (e.g. : only draft stock moves on picking) | 44 | * domain to apply on lines (e.g. : only draft stock moves on picking) |
16 | 45 | """ | 45 | """ |
32 | 46 | DOCUMENT_DATA = {'product.list': ('product.list.line', 'list_id', 'product_ids', '', ''), | 46 | DOCUMENT_DATA = { |
33 | 47 | 'return.claim': ('claim.product.line', 'claim_id_claim_product_line', 'product_line_ids_return_claim', 'qty_claim_product_line', ''), | 47 | 'product.list': ('product.list.line', 'list_id', 'product_ids', '', ''), |
34 | 48 | 'composition.kit': ('composition.item', 'item_kit_id', 'composition_item_ids', 'item_qty', ''), | 48 | 'return.claim': ('claim.product.line', 'claim_id_claim_product_line', 'product_line_ids_return_claim', 'qty_claim_product_line', ''), |
35 | 49 | 'purchase.order': ('purchase.order.line', 'order_id', 'order_line', 'product_qty', ''), | 49 | 'composition.kit': ('composition.item', 'item_kit_id', 'composition_item_ids', 'item_qty', ''), |
36 | 50 | 'tender': ('tender.line', 'tender_id', 'tender_line_ids', 'qty', ''), | 50 | 'purchase.order': ('purchase.order.line', 'order_id', 'order_line', 'product_qty', ''), |
37 | 51 | 'sale.order': ('sale.order.line', 'order_id', 'order_line', 'product_uom_qty', ''), | 51 | 'tender': ('tender.line', 'tender_id', 'tender_line_ids', 'qty', ''), |
38 | 52 | 'supplier.catalogue': ('supplier.catalogue.line', 'catalogue_id', 'line_ids', 'min_qty', ''), | 52 | 'sale.order': ('sale.order.line', 'order_id', 'order_line', 'product_uom_qty', ''), |
39 | 53 | 'stock.picking': ('stock.move', 'picking_id', 'move_lines', 'product_qty', '(\'state\', \'=\', \'draft\')'), | 53 | 'supplier.catalogue': ('supplier.catalogue.line', 'catalogue_id', 'line_ids', 'min_qty', ''), |
40 | 54 | 'stock.warehouse.automatic.supply': ('stock.warehouse.automatic.supply.line', 'supply_id', 'line_ids', 'product_qty', ''), | 54 | 'stock.picking': ('stock.move', 'picking_id', 'move_lines', 'product_qty', '(\'state\', \'=\', \'draft\')'), |
41 | 55 | 'stock.warehouse.order.cycle': ('stock.warehouse.order.cycle.line', 'order_cycle_id', 'product_ids', 'safety_stock', ''), | 55 | 'stock.warehouse.automatic.supply': ('stock.warehouse.automatic.supply.line', 'supply_id', 'line_ids', 'product_qty', ''), |
42 | 56 | 'threshold.value': ('threshold.value.line', 'threshold_value_id', 'line_ids', '', ''), | 56 | 'stock.warehouse.order.cycle': ('stock.warehouse.order.cycle.line', 'order_cycle_id', 'product_ids', 'safety_stock', ''), |
43 | 57 | 'stock.inventory': ('stock.inventory.line', 'inventory_id', 'inventory_line_id', 'product_qty', ''), | 57 | 'threshold.value': ('threshold.value.line', 'threshold_value_id', 'line_ids', '', ''), |
44 | 58 | 'initial.stock.inventory': ('initial.stock.inventory.line', 'inventory_id', 'inventory_line_id', 'product_qty', ''), | 58 | 'stock.inventory': ('stock.inventory.line', 'inventory_id', 'inventory_line_id', 'product_qty', ''), |
45 | 59 | 'real.average.consumption': ('real.average.consumption.line', 'rac_id', 'line_ids', 'consumed_qty', ''), | 59 | 'initial.stock.inventory': ('initial.stock.inventory.line', 'inventory_id', 'inventory_line_id', 'product_qty', ''), |
46 | 60 | 'monthly.review.consumption': ('monthly.review.consumption.line', 'mrc_id', 'line_ids', 'fmc', ''),} | 60 | 'real.average.consumption': ('real.average.consumption.line', 'rac_id', 'line_ids', 'consumed_qty', ''), |
47 | 61 | 'monthly.review.consumption': ('monthly.review.consumption.line', 'mrc_id', 'line_ids', 'fmc', ''), | ||
48 | 62 | } | ||
49 | 61 | 63 | ||
50 | 62 | 64 | ||
51 | 63 | def brl(self, cr, uid, ids, context=None): | 65 | def brl(self, cr, uid, ids, context=None): |
52 | @@ -74,9 +76,11 @@ | |||
53 | 74 | if not obj[DOCUMENT_DATA.get(self._name)[2]]: | 76 | if not obj[DOCUMENT_DATA.get(self._name)[2]]: |
54 | 75 | raise osv.except_osv(_('Error'), _('No line to remove')) | 77 | raise osv.except_osv(_('Error'), _('No line to remove')) |
55 | 76 | 78 | ||
59 | 77 | context.update({'active_id': ids[0], | 79 | context.update({ |
60 | 78 | 'from_delete_wizard': True, | 80 | 'active_id': ids[0], |
61 | 79 | 'active_model': self._name,}) | 81 | 'from_delete_wizard': True, |
62 | 82 | 'active_model': self._name, | ||
63 | 83 | }) | ||
64 | 80 | 84 | ||
65 | 81 | # Return the wizard to display lines to remove | 85 | # Return the wizard to display lines to remove |
66 | 82 | return {'type': 'ir.actions.act_window', | 86 | return {'type': 'ir.actions.act_window', |
67 | @@ -87,7 +91,7 @@ | |||
68 | 87 | 'context': context} | 91 | 'context': context} |
69 | 88 | 92 | ||
70 | 89 | """ | 93 | """ |
72 | 90 | All the following documents will call the same button_remove_lines method | 94 | All the following documents will call the same button_remove_lines method |
73 | 91 | to remove some or all lines on documents. | 95 | to remove some or all lines on documents. |
74 | 92 | 96 | ||
75 | 93 | Documents which inherit from document.remove.line: | 97 | Documents which inherit from document.remove.line: |
76 | @@ -107,6 +111,7 @@ | |||
77 | 107 | * Monthly consumption report | 111 | * Monthly consumption report |
78 | 108 | """ | 112 | """ |
79 | 109 | 113 | ||
80 | 114 | |||
81 | 110 | class product_list(osv.osv): | 115 | class product_list(osv.osv): |
82 | 111 | _name = 'product.list' | 116 | _name = 'product.list' |
83 | 112 | _inherit = 'product.list' | 117 | _inherit = 'product.list' |
84 | @@ -130,7 +135,11 @@ | |||
85 | 130 | def button_remove_lines(self, cr, uid, ids, context=None): | 135 | def button_remove_lines(self, cr, uid, ids, context=None): |
86 | 131 | for order in self.browse(cr, uid, ids, context=context): | 136 | for order in self.browse(cr, uid, ids, context=context): |
87 | 132 | if order.rfq_ok and order.tender_id: | 137 | if order.rfq_ok and order.tender_id: |
89 | 133 | raise osv.except_osv(_('Warning'), _('You cannot remove lines on a RfQ created by a tender. Leave the lines with Unit price = 0.00 if you dont\'t have answer for them.')) | 138 | raise osv.except_osv( |
90 | 139 | _('Warning'), | ||
91 | 140 | _('You cannot remove lines on a RfQ created by a tender. ' | ||
92 | 141 | 'Leave the lines with Unit price = 0.00 if you dont\'t have answer for them.'), | ||
93 | 142 | ) | ||
94 | 134 | 143 | ||
95 | 135 | return brl(self, cr, uid, ids, context=context) | 144 | return brl(self, cr, uid, ids, context=context) |
96 | 136 | 145 | ||
97 | @@ -281,6 +290,7 @@ | |||
98 | 281 | 290 | ||
99 | 282 | """ | 291 | """ |
100 | 283 | 292 | ||
101 | 293 | |||
102 | 284 | def delete_fields_view_get(self, cr, uid, view_id, view_type, context=None): | 294 | def delete_fields_view_get(self, cr, uid, view_id, view_type, context=None): |
103 | 285 | ''' | 295 | ''' |
104 | 286 | Check if a view exist for the object (self) and the view type (view_type) | 296 | Check if a view exist for the object (self) and the view type (view_type) |
105 | @@ -302,11 +312,12 @@ | |||
106 | 302 | view = data_obj.get_object_reference(cr, uid, 'msf_doc_import', view_name) | 312 | view = data_obj.get_object_reference(cr, uid, 'msf_doc_import', view_name) |
107 | 303 | if view: | 313 | if view: |
108 | 304 | res = view[1] | 314 | res = view[1] |
110 | 305 | except ValueError as e: | 315 | except ValueError: |
111 | 306 | res = None | 316 | res = None |
112 | 307 | 317 | ||
113 | 308 | return res | 318 | return res |
114 | 309 | 319 | ||
115 | 320 | |||
116 | 310 | def noteditable_fields_view_get(res, view_type, context=None): | 321 | def noteditable_fields_view_get(res, view_type, context=None): |
117 | 311 | ''' | 322 | ''' |
118 | 312 | Make the list of lines not editable | 323 | Make the list of lines not editable |
119 | @@ -319,6 +330,10 @@ | |||
120 | 319 | fields = root.xpath('/tree') | 330 | fields = root.xpath('/tree') |
121 | 320 | for field in fields: | 331 | for field in fields: |
122 | 321 | root.set('noteditable', 'True') | 332 | root.set('noteditable', 'True') |
123 | 333 | if context.get('procurement_request'): | ||
124 | 334 | root.set('string', 'Internal request lines') | ||
125 | 335 | if context.get('rfq_ok'): | ||
126 | 336 | root.set('string', 'RfQ lines') | ||
127 | 322 | res['arch'] = etree.tostring(root) | 337 | res['arch'] = etree.tostring(root) |
128 | 323 | 338 | ||
129 | 324 | return res | 339 | return res |
130 | @@ -346,6 +361,12 @@ | |||
131 | 346 | _inherit = 'purchase.order.line' | 361 | _inherit = 'purchase.order.line' |
132 | 347 | 362 | ||
133 | 348 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): | 363 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): |
134 | 364 | if context is None: | ||
135 | 365 | context = {} | ||
136 | 366 | |||
137 | 367 | if context.get('initial_doc_id', False) and context.get('initial_doc_type', False) == 'purchase.order': | ||
138 | 368 | rfq_ok = self.pool.get('purchase.order').browse(cr, uid, context.get('initial_doc_id'), context=context).rfq_ok | ||
139 | 369 | context['rfq_ok'] = rfq_ok | ||
140 | 349 | view_id = delete_fields_view_get(self, cr, uid, view_id, view_type, context=context) | 370 | view_id = delete_fields_view_get(self, cr, uid, view_id, view_type, context=context) |
141 | 350 | res = super(purchase_order_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu) | 371 | res = super(purchase_order_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu) |
142 | 351 | return noteditable_fields_view_get(res, view_type, context) | 372 | return noteditable_fields_view_get(res, view_type, context) |
143 | @@ -373,6 +394,13 @@ | |||
144 | 373 | _inherit = 'sale.order.line' | 394 | _inherit = 'sale.order.line' |
145 | 374 | 395 | ||
146 | 375 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): | 396 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): |
147 | 397 | if context is None: | ||
148 | 398 | context = {} | ||
149 | 399 | |||
150 | 400 | if context.get('initial_doc_id', False) and context.get('initial_doc_type', False) == 'sale.order': | ||
151 | 401 | proc_request = self.pool.get('sale.order').browse(cr, uid, context.get('initial_doc_id'), context=context).procurement_request | ||
152 | 402 | context['procurement_request'] = proc_request | ||
153 | 403 | |||
154 | 376 | view_id = delete_fields_view_get(self, cr, uid, view_id, view_type, context=context) | 404 | view_id = delete_fields_view_get(self, cr, uid, view_id, view_type, context=context) |
155 | 377 | res = super(sale_order_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu) | 405 | res = super(sale_order_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu) |
156 | 378 | return noteditable_fields_view_get(res, view_type, context) | 406 | return noteditable_fields_view_get(res, view_type, context) |
157 | @@ -518,19 +546,13 @@ | |||
158 | 518 | res['linked_field_name'] = DOCUMENT_DATA.get(context.get('active_model'))[1] | 546 | res['linked_field_name'] = DOCUMENT_DATA.get(context.get('active_model'))[1] |
159 | 519 | res['qty_field'] = DOCUMENT_DATA.get(context.get('active_model'))[3] | 547 | res['qty_field'] = DOCUMENT_DATA.get(context.get('active_model'))[3] |
160 | 520 | 548 | ||
165 | 521 | if 'active_id' in context and 'active_model' in context and context.get('active_model') in DOCUMENT_DATA: | 549 | # if 'active_id' in context and 'active_model' in context and context.get('active_model') in DOCUMENT_DATA: |
166 | 522 | line_field = DOCUMENT_DATA.get(context.get('active_model'))[2] | 550 | # line_field = DOCUMENT_DATA.get(context.get('active_model'))[2] |
167 | 523 | lines = self.pool.get(res['initial_doc_type']).read(cr, uid, res['initial_doc_id'], [line_field], context=context) | 551 | # lines = self.pool.get(res['initial_doc_type']).read(cr, uid, res['initial_doc_id'], [line_field], context=context) |
168 | 524 | res['line_ids'] = lines[line_field] | 552 | # res['line_ids'] = lines[line_field] |
169 | 525 | 553 | ||
170 | 526 | return res | 554 | return res |
171 | 527 | 555 | ||
172 | 528 | def remove_empty_lines(self, cr, uid, ids, context=None): | ||
173 | 529 | ''' | ||
174 | 530 | Remove only empty lines | ||
175 | 531 | ''' | ||
176 | 532 | return self.remove_all_lines(cr, uid, ids, context=context, remove_only_empty=True) | ||
177 | 533 | |||
178 | 534 | def remove_selected_lines(self, cr, uid, ids, context=None): | 556 | def remove_selected_lines(self, cr, uid, ids, context=None): |
179 | 535 | ''' | 557 | ''' |
180 | 536 | Remove only the selected lines | 558 | Remove only the selected lines |
181 | @@ -547,37 +569,52 @@ | |||
182 | 547 | for line in wiz.line_ids: | 569 | for line in wiz.line_ids: |
183 | 548 | for l in line[2]: | 570 | for l in line[2]: |
184 | 549 | line_ids.append(l) | 571 | line_ids.append(l) |
186 | 550 | 572 | ||
187 | 551 | context['noraise'] = True | 573 | context['noraise'] = True |
188 | 552 | line_obj.unlink(cr, uid, line_ids, context=context) | 574 | line_obj.unlink(cr, uid, line_ids, context=context) |
189 | 553 | 575 | ||
190 | 554 | return {'type': 'ir.actions.act_window_close'} | 576 | return {'type': 'ir.actions.act_window_close'} |
191 | 555 | 577 | ||
195 | 556 | def remove_all_lines(self, cr, uid, ids, context=None, remove_only_empty=False): | 578 | def select_empty_lines(self, cr, uid, ids, context=None): |
196 | 557 | ''' | 579 | ''' |
197 | 558 | Remove all lines of the initial document | 580 | Add empty lines |
198 | 581 | ''' | ||
199 | 582 | return self.select_all_lines(cr, uid, ids, context=context, select_only_empty=True) | ||
200 | 583 | |||
201 | 584 | def select_all_lines(self, cr, uid, ids, context=None, select_only_empty=False): | ||
202 | 585 | ''' | ||
203 | 586 | Select all lines of the initial document | ||
204 | 559 | ''' | 587 | ''' |
205 | 560 | context = context is None and {} or context | 588 | context = context is None and {} or context |
206 | 561 | if isinstance(ids, (int, long)): | 589 | if isinstance(ids, (int, long)): |
207 | 562 | ids = [ids] | 590 | ids = [ids] |
208 | 563 | 591 | ||
209 | 564 | for wiz in self.browse(cr, uid, ids, context=context): | 592 | for wiz in self.browse(cr, uid, ids, context=context): |
212 | 565 | if remove_only_empty and not wiz.qty_field: | 593 | if select_only_empty and not wiz.qty_field: |
213 | 566 | raise osv.except_osv(_('Error'), _('The remove empty lines is not available for this document')) | 594 | raise osv.except_osv(_('Error'), _('The select empty lines is not available for this document')) |
214 | 567 | 595 | ||
215 | 568 | line_obj = self.pool.get(wiz.to_remove_type) | 596 | line_obj = self.pool.get(wiz.to_remove_type) |
217 | 569 | if remove_only_empty: | 597 | if select_only_empty: |
218 | 570 | line_ids = line_obj.search(cr, uid, [(wiz.linked_field_name, '=', wiz.initial_doc_id), (wiz.qty_field, '=', 0.00)], context=context) | 598 | line_ids = line_obj.search(cr, uid, [(wiz.linked_field_name, '=', wiz.initial_doc_id), (wiz.qty_field, '=', 0.00)], context=context) |
219 | 571 | else: | 599 | else: |
220 | 572 | line_ids = line_obj.search(cr, uid, [(wiz.linked_field_name, '=', wiz.initial_doc_id)], context=context) | 600 | line_ids = line_obj.search(cr, uid, [(wiz.linked_field_name, '=', wiz.initial_doc_id)], context=context) |
224 | 573 | line_obj.unlink(cr, uid, line_ids, context=context) | 601 | |
225 | 574 | 602 | self.write(cr, uid, [wiz.id], {'line_ids': line_ids}, context=context) | |
226 | 575 | return {'type': 'ir.actions.act_window_close'} | 603 | |
227 | 604 | return { | ||
228 | 605 | 'type': 'ir.actions.act_window', | ||
229 | 606 | 'res_model': self._name, | ||
230 | 607 | 'view_type': 'form', | ||
231 | 608 | 'view_mode': 'form', | ||
232 | 609 | 'res_id': ids and wiz.id or False, | ||
233 | 610 | 'context': context, | ||
234 | 611 | 'target': 'new', | ||
235 | 612 | } | ||
236 | 576 | 613 | ||
237 | 577 | def fields_get(self, cr, uid, fields=None, context=None): | 614 | def fields_get(self, cr, uid, fields=None, context=None): |
238 | 578 | ''' | 615 | ''' |
239 | 579 | On this fields_get method, we build the line_ids field. | 616 | On this fields_get method, we build the line_ids field. |
241 | 580 | The line_ids field is defined as a text field but, for users, this | 617 | The line_ids field is defined as a text field but, for users, this |
242 | 581 | field should be displayed as a many2many that allows us to select | 618 | field should be displayed as a many2many that allows us to select |
243 | 582 | lines of document to remove. | 619 | lines of document to remove. |
244 | 583 | The line_ids field is changed to a many2many field according to the | 620 | The line_ids field is changed to a many2many field according to the |
245 | @@ -594,13 +631,13 @@ | |||
246 | 594 | domain = "[('%s', '=', initial_doc_id)]" % ddata[1] | 631 | domain = "[('%s', '=', initial_doc_id)]" % ddata[1] |
247 | 595 | else: | 632 | else: |
248 | 596 | domain = "[%s, ('%s', '=', initial_doc_id)]" % (ddata[4], ddata[1]) | 633 | domain = "[%s, ('%s', '=', initial_doc_id)]" % (ddata[4], ddata[1]) |
256 | 597 | res.update(line_ids={'related_columns': ['wiz_id', 'line_id'], | 634 | res.update(line_ids={'related_columns': ['wiz_id', 'line_id'], |
257 | 598 | 'relation': line_obj, | 635 | 'relation': line_obj, |
258 | 599 | 'string': 'Lines to remove', | 636 | 'string': 'Lines to remove', |
259 | 600 | 'context': context, | 637 | 'context': context, |
260 | 601 | 'third_table': '%sto_remove' % line_obj.replace('.', '_'), | 638 | 'third_table': '%sto_remove' % line_obj.replace('.', '_'), |
261 | 602 | 'selectable': True, | 639 | 'selectable': True, |
262 | 603 | 'type': 'many2many', | 640 | 'type': 'many2many', |
263 | 604 | 'domain': "%s" % domain}) | 641 | 'domain': "%s" % domain}) |
264 | 605 | 642 | ||
265 | 606 | return res | 643 | return res |
266 | 607 | 644 | ||
267 | === modified file 'msf_doc_import/wizard/wizard_delete_lines_view.xml' | |||
268 | --- msf_doc_import/wizard/wizard_delete_lines_view.xml 2014-01-02 13:14:45 +0000 | |||
269 | +++ msf_doc_import/wizard/wizard_delete_lines_view.xml 2014-05-02 09:09:28 +0000 | |||
270 | @@ -14,13 +14,13 @@ | |||
271 | 14 | <field name="linked_field_name" invisible="True" /> | 14 | <field name="linked_field_name" invisible="True" /> |
272 | 15 | <field name="qty_field" invisible="True" /> | 15 | <field name="qty_field" invisible="True" /> |
273 | 16 | <separator colspan="4" string="Lines to remove" /> | 16 | <separator colspan="4" string="Lines to remove" /> |
275 | 17 | <field name="line_ids" colspan="4" nolabel="1" context="{'from_delete_wizard': True}" mode="tree" /> | 17 | <button name="select_all_lines" type="object" icon="gtk-go-down" string="Select all lines" colspan="2" /> |
276 | 18 | <button name="select_empty_lines" type="object" icon="gtk-go-down" string="Select Qty=0 lines" attrs="{'invisible': [('qty_field', '=', False)]}" colspan="2" /> | ||
277 | 19 | <field name="line_ids" colspan="4" nolabel="1" context="{'from_delete_wizard': True, 'initial_doc_id': initial_doc_id, 'initial_doc_type': initial_doc_type}" mode="tree" /> | ||
278 | 18 | <separator colspan="4" string="Actions" /> | 20 | <separator colspan="4" string="Actions" /> |
279 | 19 | <group colspan="4" col="4" > | 21 | <group colspan="4" col="4" > |
284 | 20 | <button special="cancel" icon="gtk-cancel" string="Close window" /> | 22 | <button special="cancel" icon="gtk-cancel" string="Close window" colspan="2" /> |
285 | 21 | <button name="remove_selected_lines" type="object" icon="gtk-execute" string="Remove selected lines" /> | 23 | <button name="remove_selected_lines" type="object" icon="gtk-execute" string="Remove selected lines" colspan="2" /> |
282 | 22 | <button name="remove_all_lines" type="object" icon="gtk-execute" string="Remove all lines" confirm="Are you sure that you want to remove all lines?" /> | ||
283 | 23 | <button name="remove_empty_lines" type="object" icon="gtk-execute" string="Remove Qty=0 lines" attrs="{'invisible': [('qty_field', '=', False)]}" /> | ||
286 | 24 | </group> | 24 | </group> |
287 | 25 | </form> | 25 | </form> |
288 | 26 | </field> | 26 | </field> |