Merge lp:~julie-w/unifield-server/US-9241 into lp:unifield-server

Proposed by jftempo
Status: Merged
Merged at revision: 6138
Proposed branch: lp:~julie-w/unifield-server/US-9241
Merge into: lp:unifield-server
Diff against target: 511 lines (+13/-333)
5 files modified
bin/addons/account/account_invoice_view.xml (+1/-14)
bin/addons/account_override/invoice.py (+7/-285)
bin/addons/analytic_distribution_supply/invoice.py (+1/-1)
bin/addons/msf_profile/i18n/fr_MF.po (+4/-32)
bin/addons/msf_profile/user_rights/msf_button_access_rights.button_access_rule.csv (+0/-1)
To merge this branch: bzr merge lp:~julie-w/unifield-server/US-9241
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+412399@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/addons/account/account_invoice_view.xml'
2--- bin/addons/account/account_invoice_view.xml 2021-10-28 13:09:21 +0000
3+++ bin/addons/account/account_invoice_view.xml 2021-11-25 16:13:30 +0000
4@@ -326,28 +326,15 @@
5 <button name="invoice_open" states="draft,proforma2" type="object" string="Validate" icon="gtk-go-forward"/>
6 <field name="is_direct_invoice" invisible="1"/>
7 <button name="button_split_invoice" states="draft,proforma2" type="object" string="Split Invoice" icon="gtk-cut"/>
8- <newline/>
9- <field name="can_merge_lines" invisible="1"/>
10- <button name="button_merge_lines" type="object"
11- colspan="3"
12- string="Merge Lines by Account" icon="gtk-convert"
13- confirm="You are about to merge invoice lines; are you sure you want to proceed? THIS OPERATION CAN NOT BE UNDONE."
14- attrs="{'invisible': [('can_merge_lines', '!=', True)]}"/>
15 </group>
16
17 </group>
18 </group>
19 <!-- for ISI/STR the display of the buttons takes the whole width -->
20 <group col="8" colspan="6" attrs="{'invisible': [('doc_type', 'not in', ('isi', 'isr'))]}">
21- <button name="button_merge_lines2" type="object"
22- string="Merge Lines by Account"
23- icon="gtk-convert" colspan="2"
24- confirm="You are about to merge invoice lines; are you sure you want to proceed? THIS OPERATION CAN NOT BE UNDONE."
25- attrs="{'invisible': [('can_merge_lines', '!=', True)]}"
26- />
27 <button name="button_split_invoice2" type="object"
28 string="Split Invoice"
29- icon="gtk-cut" colspan="2"
30+ icon="gtk-cut" colspan="4"
31 states="draft"
32 />
33 <button name="invoice_open2" type="object"
34
35=== modified file 'bin/addons/account_override/invoice.py'
36--- bin/addons/account_override/invoice.py 2021-11-16 15:07:34 +0000
37+++ bin/addons/account_override/invoice.py 2021-11-25 16:13:30 +0000
38@@ -184,23 +184,6 @@
39
40 return res
41
42- def _get_can_merge_lines(self, cr, uid, ids, field_name, args,
43- context=None):
44- res = {}
45- if not ids:
46- return res
47- if isinstance(ids, (int, long, )):
48- ids = [ids]
49-
50- for inv_br in self.browse(cr, uid, ids, context=context):
51- # allow to merge lines only for draft SI/ISI
52- res[inv_br.id] = inv_br.state and inv_br.state == 'draft' \
53- and inv_br.invoice_line \
54- and inv_br.doc_type in ('si', 'isi') \
55- or False
56-
57- return res
58-
59 def _get_line_count(self, cr, uid, ids, field_name, args, context=None):
60 """
61 Returns the number of lines for each selected invoice
62@@ -396,8 +379,7 @@
63 'register_posting_date': fields.date(string="Register posting date for Direct Invoice", required=False),
64 'vat_ok': fields.function(_get_vat_ok, method=True, type='boolean', string='VAT OK', store=False, readonly=True),
65 'st_lines': fields.one2many('account.bank.statement.line', 'invoice_id', string="Register lines", readonly=True, help="Register lines that have a link to this invoice."),
66- 'can_merge_lines': fields.function(_get_can_merge_lines, method=True, type='boolean', string='Can merge lines ?'),
67- 'is_merged_by_account': fields.boolean("Is merged by account"),
68+ 'is_merged_by_account': fields.boolean("Is merged by account (deprecated)"),
69 'partner_type': fields.related('partner_id', 'partner_type', string='Partner Type', type='selection',
70 selection=PARTNER_TYPE, readonly=True, store=False),
71 'refunded_invoice_id': fields.many2one('account.invoice', string='Refunded Invoice', readonly=True,
72@@ -416,7 +398,6 @@
73 'is_intermission': lambda obj, cr, uid, c: c.get('is_intermission', False),
74 'is_direct_invoice': lambda *a: False,
75 'vat_ok': lambda obj, cr, uid, context: obj.pool.get('unifield.setup.configuration').get_config(cr, uid).vat_ok,
76- 'can_merge_lines': lambda *a: False,
77 'is_merged_by_account': lambda *a: False,
78 # set a default value on doc type so that the restrictions on fields apply even before the form is saved
79 'doc_type': lambda obj, cr, uid, c: c and c.get('doc_type') or False,
80@@ -625,7 +606,7 @@
81 (force user to enter a custom description)
82 """
83 for self_br in self.browse(cr, uid, ids, context=context):
84- if self_br.is_merged_by_account:
85+ if self_br.is_merged_by_account: # deprecated since US-9241
86 if not all([ l.name for l in self_br.invoice_line ]):
87 raise osv.except_osv(
88 _('Error'),
89@@ -1357,264 +1338,6 @@
90 def button_dummy_compute_total(self, cr, uid, ids, context=None):
91 return True
92
93- def button_merge_lines(self, cr, uid, ids, context=None):
94- # US-357 merge lines (by account) button for draft SIs
95- def check(inv_br):
96- if not inv_br.can_merge_lines:
97- raise osv.except_osv(_('Error'),
98- _("Invoice not eligible for lines merging"))
99-
100- account_iterations = {}
101- for l in inv_br.invoice_line:
102- account_iterations[l.account_id.id] = \
103- account_iterations.setdefault(l.account_id.id, 0) + 1
104-
105- any_to_merge = False
106- if account_iterations:
107- for a in account_iterations:
108- if account_iterations[a] > 1:
109- any_to_merge = True
110- break
111-
112- if not any_to_merge:
113- raise osv.except_osv(_('Error'),
114- _("Invoice has no line to merge by account"))
115-
116- def is_tax_included(inv_br):
117- '''
118- Returns True if ALL the invoice lines have an "included tax", else returns False
119- Note: a "tax included" and a "tax excluded" within the same line wouldn't make sense
120- '''
121- tax_included = True
122- for inv_line in inv_br.invoice_line:
123- if not inv_line.invoice_line_tax_id or not inv_line.invoice_line_tax_id[0].price_include:
124- tax_included = False
125- break
126- return tax_included
127-
128- def check_tax_lines(inv_br, vals):
129- '''
130- Returns vals.
131- vals['invoice_line_tax_id'] will contain the tax lines to use for the whole invoice,
132- if all lines to merge have the same taxes.
133- Otherwise vals['invoice_line_tax_id'] will contain False
134- '''
135- for l in inv_br.invoice_line:
136- # get rid of the product tax line if <> between merged lines
137- if vals['invoice_line_tax_id'] is None:
138- # first tax line browsed for the account
139- if l.invoice_line_tax_id:
140- vals['invoice_line_tax_id'] = [ t.id for t in l.invoice_line_tax_id ]
141- else:
142- vals['invoice_line_tax_id'] = False
143- elif vals['invoice_line_tax_id'] and l.invoice_line_tax_id:
144- # track <> tax lines, if it's the case abort tax(es) in merge
145- tax_ids = [ t.id for t in l.invoice_line_tax_id ]
146- if cmp(vals['invoice_line_tax_id'], tax_ids) != 0:
147- vals['invoice_line_tax_id'] = False
148- else:
149- # no tax(es) for this line, abort tax(es) in merge
150- vals['invoice_line_tax_id'] = False
151- if not vals['invoice_line_tax_id']:
152- break
153- return vals
154-
155- def compute_merge(inv_br):
156- """
157- :result:
158- - A: lines vals by line number
159- - B: and list of inv id to keep (1 line by account (not merged))
160- :rtype : [dict, list]
161-
162- NOTES:
163- - no impact on 'import_invoice_id', 'is_corrected' as the
164- invoice is draft so not imported, and no accounting entries
165- - for order_line_id and sale_order_line_id these m2o are used
166- for AD at line level but when merging we keep only AD from header
167- """
168- index = 1
169- vals_template = {
170- '_index_': index, # internal merged line index
171-
172- 'account_id': False,
173- 'company_id': inv_br.company_id.id,
174- 'discount': 0.,
175- 'invoice_id': inv_br.id,
176- 'invoice_line_tax_id': None, # m2m (None to distinguished False)
177- 'name': '',
178- 'partner_id': inv_br.partner_id.id,
179- 'price_unit': 0.,
180- 'quantity': 1.,
181- }
182-
183- by_account_vals = {} # key: account_id
184- for l in inv_br.invoice_line:
185- # get current merge vals for account or create new
186- if l.account_id.id in by_account_vals:
187- vals = by_account_vals[l.account_id.id]
188- if l.order_line_id:
189- vals.setdefault('purchase_order_line_ids', []).append(l.order_line_id.id)
190- if l.cv_line_ids:
191- vals.setdefault('cv_line_ids', []).extend([cvl.id for cvl in l.cv_line_ids])
192- else:
193- # new account to merge
194- vals = vals_template.copy()
195- vals.update({
196- '_index_': index,
197- 'account_id': l.account_id.id,
198- 'purchase_order_line_ids': [],
199- 'cv_line_ids': [],
200- })
201- if l.order_line_id:
202- vals['purchase_order_line_ids'].append(l.order_line_id.id)
203- if l.cv_line_ids:
204- vals['cv_line_ids'].extend([cvl.id for cvl in l.cv_line_ids])
205- index += 1
206-
207- '''
208- There is only one case where the "base" used for computation must be "tax included":
209- when taxes are the same for ALL lines and that taxes are included in the price.
210- In all other cases, the untaxed amount should be used:
211- - if taxes are identical for each line and are excluded, the tax computation is based on the untaxed amount
212- - if taxes are different, only the untaxed amount is kept (the user has to review the tax amount and change it manually)
213- '''
214- if vals['invoice_line_tax_id'] is None:
215- vals = check_tax_lines(inv_br, vals)
216- if vals['invoice_line_tax_id'] and is_tax_included(inv_br):
217- vals['price_unit'] += (l.price_unit * (1-(l.discount or 0.0)/100.0)) * l.quantity
218- if l.invoice_id.currency_id.rounding:
219- rounding = l.invoice_id.currency_id.rounding
220- vals['price_unit'] = round(vals['price_unit'] / rounding) * rounding
221- else:
222- vals['price_unit'] += l.price_subtotal # qty 1 and price
223-
224- # update merge line
225- by_account_vals[l.account_id.id] = vals
226-
227- # internal merged lines ids
228- if not '_ids_' in by_account_vals[l.account_id.id]:
229- by_account_vals[l.account_id.id]['_ids_'] = []
230- by_account_vals[l.account_id.id]['_ids_'].append(l.id)
231-
232- # result by index
233- res = [{}, []]
234- for a in by_account_vals:
235- if len(by_account_vals[a]['_ids_']) > 1:
236- # more than 1 inv line by account
237- index = by_account_vals[a]['_index_']
238- del by_account_vals[a]['_index_']
239- del by_account_vals[a]['_ids_']
240- res[0][index] = by_account_vals[a]
241- else:
242- res[1].append(by_account_vals[a]['_ids_'][0])
243- return res
244-
245- def delete_lines(inv_br, skip_ids):
246- # get ids to delete
247- ad_to_del_ids = []
248- line_to_del_ids = []
249-
250- for l in inv_br.invoice_line:
251- if l.id in skip_ids:
252- continue # line not to del (1 by account)
253- # delete AD
254- if l.analytic_distribution_id \
255- and not l.analytic_distribution_id.id in ad_to_del_ids:
256- ad_to_del_ids.append(l.analytic_distribution_id.id)
257- line_to_del_ids.append(l.id)
258-
259- # delete ADs
260- if ad_to_del_ids:
261- ad_obj.unlink(cr, uid, ad_to_del_ids, context=context)
262-
263- # delete lines
264- if line_to_del_ids:
265- ail_obj.unlink(cr, uid, line_to_del_ids, context=context)
266-
267- def do_merge(inv_br, lines_vals, not_merged_ids):
268- """
269- :param lines_vals: lines vals in order
270- :type lines_vals: dict
271- """
272- # the invoice is reviewed with merge lines
273- # => reset the line number sequence from 1
274- if inv_br.sequence_id:
275- inv_br.sequence_id.write({'number_next': 1}, context=context)
276-
277- # create merge lines
278- for ln in sorted(lines_vals.keys()):
279- vals = lines_vals[ln]
280-
281- # post encode tax m2m
282- vals['invoice_line_tax_id'] = vals['invoice_line_tax_id'] \
283- and [(6, 0, vals['invoice_line_tax_id'])] or False
284-
285- vals['purchase_order_line_ids'] = vals['purchase_order_line_ids'] and [(6, 0, vals['purchase_order_line_ids'])] or False
286-
287- vals['cv_line_ids'] = vals['cv_line_ids'] and [(6, 0, vals['cv_line_ids'])] or False
288-
289- # create merge line
290- vals.update({'merged_line': True})
291- if not self.pool.get('account.invoice.line').create(cr, uid,
292- vals, context=context):
293- break
294-
295- # recompute seq number for not merged lines
296- ail_obj = self.pool.get('account.invoice.line')
297- if not_merged_ids:
298- for lid in not_merged_ids:
299- ln = inv_br.sequence_id.get_id(code_or_id='id')
300- ail_obj.write(cr, uid, [lid], {
301- 'line_number': ln,
302- })
303-
304- def merge_invoice(inv_br):
305- check(inv_br)
306- merge_res = compute_merge(inv_br)
307- delete_lines(inv_br, merge_res[1])
308- do_merge(inv_br, merge_res[0], merge_res[1])
309-
310- # set merged flag
311- inv_br.write({'is_merged_by_account': True}, context=context)
312-
313- # recompute taxes (reset not manual ones)
314- self.button_reset_taxes(cr, uid, [inv_br.id], context=context)
315-
316- def post_merge(inv_br):
317- inv_br.write({
318- # update check total for accurate check amount at validation
319- 'check_total':
320- inv_br.amount_total or inv_br.check_amount or 0.,
321- }, context=context)
322-
323- res = {}
324- if context is None:
325- context = {}
326- if not ids:
327- return False
328- if isinstance(ids, (int, long, )):
329- ids = [ids]
330-
331- ail_obj = self.pool.get('account.invoice.line')
332- ad_obj = self.pool.get('analytic.distribution')
333-
334- # merging
335- context.update({'from_merge': True})
336- for inv_br in self.browse(cr, uid, ids, context=context):
337- merge_invoice(inv_br)
338-
339- # post processing (reload invoices)
340- for inv_br in self.browse(cr, uid, ids, context=context):
341- post_merge(inv_br)
342-
343- return res
344-
345- def button_merge_lines2(self, cr, uid, ids, context=None):
346- """
347- Alias for button_merge_lines (used to handle different characteristics on both buttons)
348- """
349- return self.button_merge_lines(cr, uid, ids, context=context)
350-
351 def check_accounts_for_partner(self, cr, uid, ids, context=None,
352 header_obj=False, lines_field='invoice_line',
353 line_level_partner_type=False):
354@@ -1848,7 +1571,7 @@
355 ('in_invoice', 'Supplier Invoice'),
356 ('out_refund', 'Customer Refund'),
357 ('in_refund', 'Supplier Refund')]),
358- 'merged_line': fields.boolean(string='Merged Line', help='Line generated by the merging of other lines', readonly=True),
359+ 'merged_line': fields.boolean(string='Merged Line (deprecated)', help='Line generated by the merging of other lines', readonly=True),
360 # - a CV line can be linked to several invoice lines ==> e.g. several partial deliveries, split of invoice lines
361 # - an invoice line can be linked to several CV lines => e.g. merge invoice lines by account
362 'cv_line_ids': fields.many2many('account.commitment.line', 'inv_line_cv_line_rel', 'inv_line_id', 'cv_line_id',
363@@ -2028,7 +1751,7 @@
364 - compute total amount (check_total field)
365 - write total to the register line
366 - Raise error msg if the related inv. has been generated via Sync. or by a Supply workflow (for Intermission/Intersection partners)
367- (for SI from Supply: merging lines is always allowed, deleting lines is allowed only for manual lines not having been merged.)
368+ (for SI from Supply: deleting lines is allowed only for manual lines not having been merged (merging is deprecated since US-9241))
369 """
370 if not context:
371 context = {}
372@@ -2044,11 +1767,10 @@
373 in_invoice = invoice.type == 'in_invoice' and not invoice.is_inkind_donation
374 supp_inv = in_invoice and not invoice.is_intermission
375 donation = invoice.is_inkind_donation
376- from_merge = context.get('from_merge')
377 from_split = context.get('from_split')
378 from_supply = invoice.from_supply
379 intermission_or_section = invoice.partner_type in ('intermission', 'section')
380- check_line_per_line = from_supply and (supp_inv or donation) and not from_merge and not from_split
381+ check_line_per_line = from_supply and (supp_inv or donation) and not from_split
382 if not check_line_per_line:
383 invoice_ids.append(invoice.id) # check each invoice only once
384 deletion_allowed = True
385@@ -2057,10 +1779,10 @@
386 elif from_supply and not from_split: # allow deletion due to the "Split" feature (available in Draft)
387 if intermission_or_section and not donation:
388 deletion_allowed = False
389- elif (supp_inv or donation) and not from_merge and (invl.order_line_id or invl.merged_line):
390+ elif (supp_inv or donation) and (invl.order_line_id or invl.merged_line):
391 deletion_allowed = False
392 if not deletion_allowed:
393- # will be displayed when trying to delete lines manually / merge lines / or split invoices
394+ # will be displayed when trying to delete lines manually or split invoices
395 if donation:
396 raise osv.except_osv(_('Error'),
397 _("This donation has been generated via a Supply workflow. Existing lines can't be deleted."))
398
399=== modified file 'bin/addons/analytic_distribution_supply/invoice.py'
400--- bin/addons/analytic_distribution_supply/invoice.py 2021-11-10 11:18:05 +0000
401+++ bin/addons/analytic_distribution_supply/invoice.py 2021-11-25 16:13:30 +0000
402@@ -208,7 +208,7 @@
403 # CV IN VERSION 1
404 if old_cv_version:
405 # Fetch purchase order line account
406- if inv.is_merged_by_account:
407+ if inv.is_merged_by_account: # deprecated since US-9241
408 if not invl.account_id:
409 continue
410 # US-357: lines without product (get directly account)
411
412=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
413--- bin/addons/msf_profile/i18n/fr_MF.po 2021-11-18 11:18:31 +0000
414+++ bin/addons/msf_profile/i18n/fr_MF.po 2021-11-25 16:13:30 +0000
415@@ -145,12 +145,6 @@
416 msgid "Advance Return"
417 msgstr "Retour d'avance"
418
419-#. module: account_override
420-#: code:addons/account_override/invoice.py:1187
421-#, python-format
422-msgid "Invoice has no line to merge by account"
423-msgstr "Invoice has no line to merge by account"
424-
425 #. module: account
426 #: view:account.addtmpl.wizard:0
427 #: model:ir.actions.act_window,name:account.action_account_addtmpl_wizard_form
428@@ -18699,11 +18693,6 @@
429 msgid "datetime"
430 msgstr "datetime"
431
432-#. module: account_override
433-#: view:account.invoice:0
434-msgid "Merge Lines by Account"
435-msgstr "Fusionner les Lignes par Compte"
436-
437 #. module: tender_flow
438 #: view:tender:0
439 msgid "Update Product's Suppliers"
440@@ -47464,8 +47453,8 @@
441 #. modules: account_override, register_accounting
442 #: field:account.invoice,is_merged_by_account:0
443 #: field:wizard.account.invoice,is_merged_by_account:0
444-msgid "Is merged by account"
445-msgstr "Is merged by account"
446+msgid "Is merged by account (deprecated)"
447+msgstr "Est fusionné par compte (obsolète)"
448
449 #. module: resource
450 #: field:resource.calendar.leaves,calendar_id:0
451@@ -64607,12 +64596,6 @@
452 msgid "Add all Analytic Journals"
453 msgstr "Ajouter tous les Journaux Analytiques"
454
455-#. modules: account_override, register_accounting
456-#: field:account.invoice,can_merge_lines:0
457-#: field:wizard.account.invoice,can_merge_lines:0
458-msgid "Can merge lines ?"
459-msgstr "Can merge lines ?"
460-
461 #. module: msf_doc_import
462 #: code:addons/msf_doc_import/wizard/wiz_common_import.py:344
463 #, python-format
464@@ -65052,11 +65035,6 @@
465 msgstr "option 1"
466
467 #. module: account
468-#: view:account.invoice:0
469-msgid "You are about to merge invoice lines; are you sure you want to proceed? THIS OPERATION CAN NOT BE UNDONE."
470-msgstr "Vous êtes sur le point de fusionner les lignes de facture ; voulez-vous continuer ? CETTE OPÉRATION NE PEUT PAS ÊTRE ANNULÉE."
471-
472-#. module: account
473 #: help:account.payment.term.line,days:0
474 msgid "Number of days to add before computation of the day of month.If Date=15/01, Number of Days=22, Day of Month=-1, then the due date is 28/02."
475 msgstr "Nombre de jours à ajouter avant le calcul du jour du mois. Si la Date est le 15/01, le Nombre de Jours = 22, le Jour du Mois = -1, le résultat obtenu sera le 28/02"
476@@ -99070,12 +99048,6 @@
477 msgid "Allocated Expenses"
478 msgstr "Dépenses allouées"
479
480-#. module: account_override
481-#: code:addons/account_override/invoice.py:1171
482-#, python-format
483-msgid "Invoice not eligible for lines merging"
484-msgstr "Invoice not eligible for lines merging"
485-
486 #. module: finance
487 #: report:cash.request.export:0
488 msgid "Total Cash requested:"
489@@ -108880,8 +108852,8 @@
490
491 #. module: account_override
492 #: field:account.invoice.line,merged_line:0
493-msgid "Merged Line"
494-msgstr "Ligne Fusionnée"
495+msgid "Merged Line (deprecated)"
496+msgstr "Ligne Fusionnée (obsolète)"
497
498 #. module: account_override
499 #: help:account.invoice.line,merged_line:0
500
501=== modified file 'bin/addons/msf_profile/user_rights/msf_button_access_rights.button_access_rule.csv'
502--- bin/addons/msf_profile/user_rights/msf_button_access_rights.button_access_rule.csv 2020-10-27 17:38:34 +0000
503+++ bin/addons/msf_profile/user_rights/msf_button_access_rights.button_access_rule.csv 2021-11-25 16:13:30 +0000
504@@ -46,7 +46,6 @@
505 TRUE,,sd.BAR_msf_accrualview_msf_accrual_line_tree_button_analytic_distribution,"Fin_Config_Coordo,Fin_Config_Admin_Mission"
506 TRUE,,sd.BAR_msf_accrualview_msf_accrual_line_tree_button_delete,"Fin_Config_Coordo,Fin_Config_Admin_Mission"
507 TRUE,,sd.BAR_account_overrideinvoice_supplier_form_3_button_split_invoice,"Fin_Invoicing_Advanced,Fin_Supplier_Invoices"
508-TRUE,,sd.BAR_account_overrideinvoice_supplier_form_3_button_merge_lines,"Fin_Invoicing_Advanced,Fin_Supplier_Invoices"
509 TRUE,,sd.BAR_analytic_distributioninvoice_supplier_form_2_button_reset_distribution,"Fin_Invoicing_Advanced,Fin_Supplier_Invoices"
510 TRUE,,sd.BAR_accountinvoice_supplier_form_accountaction_account_change_currency,"Fin_Invoicing_Advanced,Fin_Supplier_Invoices"
511 TRUE,,sd.BAR_analytic_distributioninvoice_supplier_form_2_button_analytic_distribution,"Fin_Invoicing_Advanced,Fin_Supplier_Invoices"

Subscribers

People subscribed via source and target branches