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

Proposed by jftempo
Status: Merged
Merged at revision: 5777
Proposed branch: lp:~julie-w/unifield-server/US-5216
Merge into: lp:unifield-server
Diff against target: 1436 lines (+578/-168) (has conflicts)
14 files modified
bin/addons/account/account.py (+144/-39)
bin/addons/account/account_view.xml (+25/-19)
bin/addons/account/wizard/account_subscription_generate.py (+4/-3)
bin/addons/account/wizard/account_subscription_generate_view.xml (+2/-2)
bin/addons/account/wizard/account_validate_account_move.py (+10/-0)
bin/addons/account_period_closing_level/account_period.py (+1/-14)
bin/addons/account_subscription/__init__.py (+0/-1)
bin/addons/account_subscription/account_model.py (+125/-7)
bin/addons/account_subscription/account_model_view.xml (+72/-19)
bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py (+5/-0)
bin/addons/msf_profile/data/patches.xml (+7/-0)
bin/addons/msf_profile/i18n/fr_MF.po (+122/-63)
bin/addons/msf_profile/msf_profile.py (+60/-0)
bin/addons/msf_profile/usability.xml (+1/-1)
Text conflict in bin/addons/msf_profile/data/patches.xml
Text conflict in bin/addons/msf_profile/i18n/fr_MF.po
To merge this branch: bzr merge lp:~julie-w/unifield-server/US-5216
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+388868@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.py'
2--- bin/addons/account/account.py 2020-03-11 13:40:27 +0000
3+++ bin/addons/account/account.py 2020-08-07 12:54:52 +0000
4@@ -2354,6 +2354,29 @@
5 break
6 return res
7
8+ def _is_frozen_model(self, cr, uid, ids, name, arg, context=None):
9+ """
10+ Returns True for the Recurring Plans for which the model field should be frozen, i.e. readonly:
11+ - if journal entries have been generated, posted or not
12+ - if the model already selected is in Done state (note that Done models aren't selectable, so the model would
13+ have been selected BEFORE it becomes Done).
14+ """
15+ if context is None:
16+ context = {}
17+ if isinstance(ids, (int, long)):
18+ ids = [ids]
19+ res = {}
20+ for plan in self.browse(cr, uid, ids, fields_to_fetch=['model_id', 'lines_id'], context=context):
21+ res[plan.id] = False
22+ if plan.model_id.state == 'done':
23+ res[plan.id] = True
24+ else:
25+ for line in plan.lines_id:
26+ if line.move_id:
27+ res[plan.id] = True
28+ break
29+ return res
30+
31 _columns = {
32 'name': fields.char('Name', size=64, required=True),
33 'ref': fields.char('Reference', size=16),
34@@ -2361,45 +2384,142 @@
35
36 'date_start': fields.date('Start Date', required=True),
37 'period_total': fields.integer('Number of Periods', required=True),
38- 'period_nbr': fields.integer('Period', required=True),
39+ 'period_nbr': fields.integer('Repeat', required=True,
40+ help="This field will determine how often entries will be generated: if the period type is 'month' and the repeat '2' then entries will be generated every 2 months"),
41 'period_type': fields.selection([('day','days'),('month','month'),('year','year')], 'Period Type', required=True),
42 'state': fields.selection([('draft','Draft'),('running','Running'),('done','Done')], 'State', required=True, readonly=True),
43
44 'lines_id': fields.one2many('account.subscription.line', 'subscription_id', 'Subscription Lines'),
45 'has_unposted_entries': fields.function(_get_has_unposted_entries, method=True, type='boolean',
46 store=False, string='Has unposted entries'),
47+ 'frozen_model': fields.function(_is_frozen_model, method=True, type='boolean', store=False, string='Frozen model'),
48 }
49 _defaults = {
50 'date_start': lambda *a: time.strftime('%Y-%m-%d'),
51 'period_type': 'month',
52- 'period_total': 12,
53+ 'period_total': 0,
54 'period_nbr': 1,
55 'state': 'draft',
56 }
57
58- def check(self, cr, uid, ids, context=None):
59- todone = []
60- for sub in self.browse(cr, uid, ids, context=context):
61- ok = True
62- for line in sub.lines_id:
63- if not line.move_id.id:
64- ok = False
65+ _order = 'date_start desc, id desc'
66+
67+ def _check_repeat_value(self, cr, uid, ids, context=None):
68+ """
69+ Prevents negative frequency
70+ """
71+ for plan in self.read(cr, uid, ids, ['period_nbr']):
72+ if plan['period_nbr'] < 1:
73+ return False
74+ return True
75+
76+ def _check_plan_name_unicity(self, cr, uid, ids, context=None):
77+ """
78+ Prevents having 2 rec. plans using the same name
79+ """
80+ for plan in self.read(cr, uid, ids, ['name']):
81+ if self.search_exist(cr, uid, [('name', '=', plan['name']), ('id', '!=', plan['id'])]):
82+ raise osv.except_osv(_('Error'),
83+ _('It is not possible to have several Recurring Plans with the same name: %s.') % plan['name'])
84+ return True
85+
86+ _constraints = [
87+ (_check_repeat_value, 'The value in the field "Repeat" must be greater than 0!', ['period_nbr']),
88+ (_check_plan_name_unicity, 'It is not possible to have several Recurring Plans with the same name.', ['name']),
89+ ]
90+
91+ def copy(self, cr, uid, acc_sub_id, default=None, context=None):
92+ """
93+ Account Subscription duplication:
94+ - block the process if the model has been set to Done as it shouldn't be used in any plans created afterwards
95+ - don't copy the link with subscription lines
96+ - add " (copy)" after the name
97+ """
98+ if context is None:
99+ context = {}
100+ sub_copied = self.browse(cr, uid, acc_sub_id, fields_to_fetch=['name', 'model_id'], context=context)
101+ if sub_copied.model_id.state == 'done':
102+ raise osv.except_osv(_('Warning'), _('You cannot duplicate a Recurring Plan with a Done model.'))
103+ suffix = ' (copy)'
104+ name = '%s%s' % (sub_copied.name[:64 - len(suffix)], suffix)
105+ if default is None:
106+ default = {}
107+ default.update({
108+ 'lines_id': [],
109+ 'name': name,
110+ })
111+ return super(account_subscription, self).copy(cr, uid, acc_sub_id, default, context=context)
112+
113+ def write(self, cr, uid, ids, vals, context=None):
114+ """
115+ Edition of the Recurring Plans. If the model has been changed, triggers the recomputation of the state of the previous model used.
116+
117+ UC: use the model X in one plan. Compute Rec. entries => the plans and models are Running.
118+ Select another model in the plan => model X must be set back to Draft.
119+ """
120+ if not ids:
121+ return True
122+ if isinstance(ids, (int, long)):
123+ ids = [ids]
124+ if context is None:
125+ context = {}
126+ rec_model_obj = self.pool.get('account.model')
127+ models_to_check = set()
128+ for rec_plan in self.browse(cr, uid, ids, fields_to_fetch=['model_id'], context=context):
129+ previous_model_id = rec_plan.model_id.id
130+ if 'model_id' in vals and vals['model_id'] != previous_model_id:
131+ models_to_check.add(previous_model_id)
132+ res = super(account_subscription, self).write(cr, uid, ids, vals, context=context)
133+ if models_to_check:
134+ # check model states after the plan states have been updated
135+ rec_model_obj._store_set_values(cr, uid, list(models_to_check), ['state'], context)
136+ return res
137+
138+ def unlink(self, cr, uid, ids, context=None):
139+ """
140+ Prevents deletion in case the subscription lines have already been computed
141+ """
142+ if context is None:
143+ context = {}
144+ if isinstance(ids, (int, long)):
145+ ids = [ids]
146+ sub_lines_obj = self.pool.get('account.subscription.line')
147+ if sub_lines_obj.search_exist(cr, uid, [('subscription_id', 'in', ids)], context=context):
148+ raise osv.except_osv(_('Warning'), _('You cannot delete a Recurring Plan if Subscription lines have already been computed.'))
149+ return super(account_subscription, self).unlink(cr, uid, ids, context=context)
150+
151+ def update_plan_state(self, cr, uid, subscription_id, context=None):
152+ """
153+ Updates the Recurring Plan state with the following rules:
154+ - no lines computed = Draft
155+ - lines computed but not all lines posted = Running
156+ - all lines posted = Done
157+ """
158+ if context is None:
159+ context = {}
160+ sub = self.browse(cr, uid, subscription_id, fields_to_fetch=['lines_id'], context=context)
161+ if not sub.lines_id:
162+ state = 'draft'
163+ else:
164+ running = False
165+ for sub_line in sub.lines_id:
166+ if not sub_line.move_id or sub_line.move_id.state != 'posted':
167+ running = True
168 break
169- if ok:
170- todone.append(sub.id)
171- if todone:
172- self.write(cr, uid, todone, {'state':'done'})
173- return False
174+ if running:
175+ state = 'running'
176+ else:
177+ state = 'done'
178+ self.write(cr, uid, subscription_id, {'state': state}, context=context)
179
180 def remove_line(self, cr, uid, ids, context=None):
181 toremove = []
182 for sub in self.browse(cr, uid, ids, context=context):
183 for line in sub.lines_id:
184- if not line.move_id.id:
185+ if not line.move_id:
186 toremove.append(line.id)
187 if toremove:
188 self.pool.get('account.subscription.line').unlink(cr, uid, toremove)
189- self.write(cr, uid, ids, {'state':'draft'})
190 return False
191
192 def delete_unposted(self, cr, uid, ids, context=None):
193@@ -2407,29 +2527,17 @@
194 This method:
195 - searches for the unposted Journal Entries linked to the account subscription(s)
196 - deletes the unposted JEs, and the related JIs and AJIs
197- - deletes all the Subscription Lines not linked to a Posted JE
198- - triggers the "Compute" method on the subscription(s) to get the correct lines and state
199 """
200 if context is None:
201 context = {}
202- subline_obj = self.pool.get('account.subscription.line')
203 je_obj = self.pool.get('account.move')
204- subline_to_delete_ids = []
205 je_to_delete_ids = []
206 for sub in self.browse(cr, uid, ids, fields_to_fetch=['lines_id'], context=context):
207 for subline in sub.lines_id:
208- if not subline.move_id:
209- # also deletes the sub. lines without JE (covers the case where frequency has been modified
210- # => avoids having inconsistent lines at the end of the process)
211- subline_to_delete_ids.append(subline.id)
212- elif subline.move_id.state == 'draft': # draft = Unposted state
213- subline_to_delete_ids.append(subline.id)
214+ if subline.move_id and subline.move_id.state == 'draft': # draft = Unposted state
215 je_to_delete_ids.append(subline.move_id.id)
216- subline_obj.unlink(cr, uid, subline_to_delete_ids, context=context)
217- je_obj.unlink(cr, uid, je_to_delete_ids, context=context) # also deletes JIs / AJIs
218- # retrigger the creation of the subscription lines "to be generated"
219- # and recompute the state of the subscription accordingly (= "Running" if lines have been generated)
220- self.compute(cr, uid, ids, context=context)
221+ if je_to_delete_ids:
222+ je_obj.unlink(cr, uid, je_to_delete_ids, context=context) # also deletes JIs / AJIs
223 return True
224
225 def get_dates_to_create(self, cr, uid, subscription_id, context=None):
226@@ -2460,6 +2568,9 @@
227 if context is None:
228 context = {}
229 for sub in self.browse(cr, uid, ids, context=context):
230+ if sub.state == 'running':
231+ # first remove existing lines without JE
232+ self.remove_line(cr, uid, ids, context=context)
233 if sub.model_id and sub.model_id.has_any_bad_ad_line_exp_in:
234 # UFTP-103: block compute if recurring model has line with
235 # expense/income accounts with invalid AD
236@@ -2474,10 +2585,7 @@
237 'date': date_sub,
238 'subscription_id': sub.id,
239 })
240- if dates_to_create:
241- self.write(cr, uid, sub.id, {'state': 'running'}, context=context)
242- else: # all the subscription lines were already created => the account subscription can be marked as "Done"
243- self.write(cr, uid, sub.id, {'state': 'done'}, context=context)
244+ self.update_plan_state(cr, uid, sub.id, context=context)
245 return True
246 account_subscription()
247
248@@ -2492,19 +2600,16 @@
249 _order = 'date, id'
250
251 def move_create(self, cr, uid, ids, context=None):
252- tocheck = {}
253 all_moves = []
254 obj_model = self.pool.get('account.model')
255 for line in self.browse(cr, uid, ids, context=context):
256 datas = {
257 'date': line.date,
258+ 'ref': line.subscription_id.ref or '',
259 }
260 move_ids = obj_model.generate(cr, uid, [line.subscription_id.model_id.id], datas, context)
261- tocheck[line.subscription_id.id] = True
262 self.write(cr, uid, [line.id], {'move_id':move_ids[0]})
263 all_moves.extend(move_ids)
264- if tocheck:
265- self.pool.get('account.subscription').check(cr, uid, tocheck.keys(), context)
266 return all_moves
267
268 _rec_name = 'date'
269
270=== modified file 'bin/addons/account/account_view.xml'
271--- bin/addons/account/account_view.xml 2019-11-04 09:40:45 +0000
272+++ bin/addons/account/account_view.xml 2020-08-07 12:54:52 +0000
273@@ -1711,10 +1711,12 @@
274 <field name="model">account.model</field>
275 <field name="type">tree</field>
276 <field name="arch" type="xml">
277- <tree string="Journal Entry Model">
278+ <tree string="Journal Entry Model" colors="grey:state=='done';blue:state=='draft';black:state=='running'">
279 <field name="name"/>
280 <field name="journal_id"/>
281 <field name="company_id" groups="base.group_multi_company"/>
282+ <field name="create_date"/>
283+ <field name="state"/>
284 </tree>
285 </field>
286 </record>
287@@ -1729,9 +1731,11 @@
288 <filter string="Sale" icon="terp-camera_test" domain="[('journal_id.type', '=', 'sale')]"/>
289 <filter string="Purchase" icon="terp-purchase" domain="[('journal_id.type', '=', 'purchase')]"/>
290 <separator orientation="vertical"/>
291+ <filter icon="terp-document-new" string="Draft" name="draft" domain="[('state', '=', 'draft')]"/>
292+ <filter icon="terp-camera_test" string="Running" name="running" domain="[('state', '=', 'running')]"/>
293+ <filter icon="terp-dialog-close" string="Done" name="done" domain="[('state', '=', 'done')]" />
294 <field name="name"/>
295- <field name="journal_id" widget="selection"/>
296- <field name="company_id" widget="selection" groups="base.group_multi_company"/>
297+ <field name="journal_id" domain="[('type', '=', 'purchase'), ('is_current_instance', '=', True)]"/>
298 </group>
299 <newline/>
300 <group expand="0" string="Group By...">
301@@ -1746,6 +1750,7 @@
302 <field name="res_model">account.model</field>
303 <field name="view_type">form</field>
304 <field name="view_mode">tree,form</field>
305+ <field name="context">{'search_default_draft': 1, 'search_default_running': 1}</field>
306 <field name="search_view_id" ref="view_model_search"/>
307 </record>
308 <menuitem
309@@ -1885,7 +1890,7 @@
310 <field name="model">account.subscription</field>
311 <field name="type">tree</field>
312 <field name="arch" type="xml">
313- <tree colors="blue:state in ('draft');gray:state in ('done');black:state in ('running')" string="Entry Subscription">
314+ <tree colors="blue:state=='draft';grey:state=='done';black:state=='running'" string="Recurring Plan">
315 <field name="name"/>
316 <field name="model_id"/>
317 <field name="ref"/>
318@@ -1900,10 +1905,10 @@
319 <field name="model">account.subscription</field>
320 <field name="type">search</field>
321 <field name="arch" type="xml">
322- <search string="Entry Subscription">
323+ <search string="Recurring Plan">
324 <group col="8" colspan="4">
325- <filter icon="terp-document-new" string="Draft" name="draft" domain="[('state','=','draft')]" help="Draft Subscription"/>
326- <filter icon="terp-camera_test" string="Running" name="running" domain="[('state','=','running')]" help="Running Subscription"/>
327+ <filter icon="terp-document-new" string="Draft" name="draft" domain="[('state', '=', 'draft')]"/>
328+ <filter icon="terp-camera_test" string="Running" name="running" domain="[('state', '=', 'running')]"/>
329 <filter icon="terp-dialog-close" string="Done" name="done" domain="[('state','=','done')]" />
330 <separator orientation="vertical"/>
331 <field name="name"/>
332@@ -1924,19 +1929,20 @@
333 <field name="model">account.subscription</field>
334 <field name="type">form</field>
335 <field name="arch" type="xml">
336- <form string="Recurring">
337- <group col="6" colspan="4">
338+ <form string="Recurring Plan">
339+ <group col="6" colspan="4" attrs="{'readonly': [('state', '=', 'done')]}">
340 <field name="name" select="1"/>
341- <field name="model_id"/>
342+ <field name="frozen_model" invisible="1"/>
343+ <field name="model_id" domain="[('state', '!=', 'done')]" attrs="{'readonly': [('frozen_model', '=', True)]}"/>
344 <field name="ref" select="1"/>
345 </group>
346- <group col="2" colspan="2">
347+ <group col="2" colspan="2" attrs="{'readonly': [('state', '=', 'done')]}">
348 <separator colspan="4" string="Starts on"/>
349 <field name="date_start" select="1"/>
350 <field name="period_total"/>
351 </group>
352
353- <group col="2" colspan="2">
354+ <group col="2" colspan="2" attrs="{'readonly': [('state', '=', 'done')]}">
355 <separator colspan="4" string="Valid Up to"/>
356 <field name="period_nbr"/>
357 <field name="period_type"/>
358@@ -1945,7 +1951,8 @@
359 <group col="2" colspan="2">
360 </group>
361 <separator colspan="4" string="Subscription Lines"/>
362- <field colspan="4" name="lines_id" widget="one2many_list" nolabel="1"/>
363+ <field colspan="4" name="lines_id" widget="one2many_list" nolabel="1"
364+ attrs="{'readonly': [('state', '=', 'done')]}"/>
365
366 <group col="6" colspan="4">
367 <field name="state"/>
368@@ -1953,23 +1960,22 @@
369 <button name="delete_unposted" type="object" icon="terp-gtk-stop"
370 string="Delete Unposted Entries"
371 attrs="{'readonly': [('has_unposted_entries', '=', False)]}"/>
372- <button name="compute" states="draft" string="Compute" type="object" icon="terp-stock_format-scientific"/>
373- <button name="remove_line" states="running" string="Remove Lines" type="object" icon="gtk-remove"/>
374+ <button name="compute" states="draft,running" string="Compute" type="object" icon="terp-stock_format-scientific"/>
375 </group>
376 </form>
377 </field>
378 </record>
379 <record id="action_subscription_form" model="ir.actions.act_window">
380- <field name="name">Recurring Lines</field>
381+ <field name="name">Recurring Plan</field>
382 <field name="res_model">account.subscription</field>
383 <field name="view_type">form</field>
384 <field name="view_mode">tree,form</field>
385 <field name="search_view_id" ref="view_subscription_search"/>
386- <field name="context">{'search_default_draft': 1, 'search_default_running': 1}</field>
387- <field name="help">A recurring entry is a miscellaneous entry that occurs on a recurrent basis from a specific date, i.e. corresponding to the signature of a contract or an agreement with a customer or a supplier. With Define Recurring Entries, you can create such entries to automate the postings in the system.</field>
388+ <field name="context">{'search_default_running': 1, 'search_default_draft': 1}</field>
389+ <field name="help">A recurring entry is a miscellaneous entry that occurs on a recurrent basis from a specific date, i.e. corresponding to the signature of a contract or an agreement with a customer or a supplier. With Recurring Plan, you can create such entries to automate the postings in the system.</field>
390 </record>
391 <menuitem
392- name="Define Recurring Entries" action="action_subscription_form"
393+ name="Recurring Plan" action="action_subscription_form"
394 groups="base.group_extended"
395 id="menu_action_subscription_form" sequence="1"
396 parent="account.menu_finance_recurrent_entries"/>
397
398=== modified file 'bin/addons/account/wizard/account_subscription_generate.py'
399--- bin/addons/account/wizard/account_subscription_generate.py 2018-10-17 09:25:17 +0000
400+++ bin/addons/account/wizard/account_subscription_generate.py 2020-08-07 12:54:52 +0000
401@@ -41,7 +41,7 @@
402 account_obj = self.pool.get('account.account')
403 moves_created=[]
404 for data in self.read(cr, uid, ids, context=context):
405- cr.execute('select id from account_subscription_line where date<%s and move_id is null', (data['date'],))
406+ cr.execute('select id from account_subscription_line where date<=%s and move_id is null;', (data['date'],))
407 line_ids = map(lambda x: x[0], cr.fetchall())
408 # check that the entry is valid before creating it
409 for sub_line in sub_line_obj.browse(cr, uid, line_ids, context=context):
410@@ -66,10 +66,11 @@
411 raise osv.except_osv(_('Warning'), _('The entry is not balanced for the Recurring Model %s!') % (acc_model.name))
412 moves = self.pool.get('account.subscription.line').move_create(cr, uid, line_ids, context=context)
413 moves_created.extend(moves)
414- result = mod_obj.get_object_reference(cr, uid, 'account', 'action_move_line_form')
415+ result = mod_obj.get_object_reference(cr, uid, 'account_subscription', 'act_account_subscription_to_account_move_line_open')
416 id = result and result[1] or False
417 result = act_obj.read(cr, uid, [id], context=context)[0]
418- result['domain'] = str([('id','in',moves_created)])
419+ # restrict display to Draft lines so that they automatically disappear from the list once the user posts them
420+ result['domain'] = str([('move_id', 'in', moves_created), ('move_state', '=', 'draft')])
421 return result
422
423 account_subscription_generate()
424
425=== modified file 'bin/addons/account/wizard/account_subscription_generate_view.xml'
426--- bin/addons/account/wizard/account_subscription_generate_view.xml 2011-01-14 00:11:01 +0000
427+++ bin/addons/account/wizard/account_subscription_generate_view.xml 2020-08-07 12:54:52 +0000
428@@ -8,8 +8,8 @@
429 <field name="type">form</field>
430 <field name="arch" type="xml">
431 <form string="Subscription Compute">
432- <separator string="Generate Entries before:" colspan="4"/>
433- <label string ="Automatically generate entries based on what has been entered in the system before a specific date." colspan="4" nolabel="1"/>
434+ <separator string="Generate Entries until:" colspan="4"/>
435+ <label string = "Automatically generate entries based on what has been entered in the system until a specific date." colspan="4" nolabel="1"/>
436 <newline/>
437 <field name="date"/>
438 <separator colspan="4" />
439
440=== modified file 'bin/addons/account/wizard/account_validate_account_move.py'
441--- bin/addons/account/wizard/account_validate_account_move.py 2011-01-14 00:11:01 +0000
442+++ bin/addons/account/wizard/account_validate_account_move.py 2020-08-07 12:54:52 +0000
443@@ -49,6 +49,8 @@
444 def validate_move_lines(self, cr, uid, ids, context=None):
445 obj_move_line = self.pool.get('account.move.line')
446 obj_move = self.pool.get('account.move')
447+ obj_subscription_line = self.pool.get('account.subscription.line')
448+ obj_recurring_plan = self.pool.get('account.subscription')
449 move_ids = []
450 if context is None:
451 context = {}
452@@ -60,6 +62,14 @@
453 if not move_ids:
454 raise osv.except_osv(_('Warning'), _('Selected Entry Lines does not have any account move enties in draft state'))
455 obj_move.button_validate(cr, uid, move_ids, context)
456+ # update the state of the related Recurring Plans if any
457+ sub_line_ids = obj_subscription_line.search(cr, uid, [('move_id', 'in', move_ids)], context=context)
458+ if sub_line_ids:
459+ recurring_plans = set()
460+ for sub_line in obj_subscription_line.browse(cr, uid, sub_line_ids, fields_to_fetch=['subscription_id'], context=context):
461+ recurring_plans.add(sub_line.subscription_id.id)
462+ for recurring_plan_id in recurring_plans:
463+ obj_recurring_plan.update_plan_state(cr, uid, recurring_plan_id, context=context)
464 return {'type': 'ir.actions.act_window_close'}
465 validate_account_move_lines()
466
467
468=== modified file 'bin/addons/account_period_closing_level/account_period.py'
469--- bin/addons/account_period_closing_level/account_period.py 2020-03-20 14:08:02 +0000
470+++ bin/addons/account_period_closing_level/account_period.py 2020-08-07 12:54:52 +0000
471@@ -25,7 +25,6 @@
472 from tools.safe_eval import safe_eval
473 from account_period_closing_level import ACCOUNT_PERIOD_STATE_SELECTION
474 from register_accounting import register_tools
475-from datetime import datetime
476
477
478 class account_period(osv.osv):
479@@ -69,7 +68,6 @@
480
481 # Prepare some elements
482 reg_obj = self.pool.get('account.bank.statement')
483- sub_obj = self.pool.get('account.subscription')
484 sub_line_obj = self.pool.get('account.subscription.line')
485 curr_obj = self.pool.get('res.currency')
486 curr_rate_obj = self.pool.get('res.currency.rate')
487@@ -233,21 +231,10 @@
488 "to close and have a balance which isn't equal to 0:\n"
489 "%s") % ", ".join([r.name for r in reg_ko]))
490
491- # check if subscriptions lines haven't been generated yet for this period
492- draft_sub_ids = sub_obj.search(cr, uid, [('state', '=', 'draft')], order='NO_ORDER', context=context)
493- for draft_sub_id in draft_sub_ids:
494- dates_to_create = sub_obj.get_dates_to_create(cr, uid, draft_sub_id, context=context)
495- date_stop_dt = datetime.strptime(period.date_stop, "%Y-%m-%d")
496- for date_to_create in dates_to_create:
497- date_to_create_dt = datetime.strptime(date_to_create, "%Y-%m-%d")
498- if date_to_create_dt <= date_stop_dt:
499- raise osv.except_osv(_('Warning'), _("Subscription Lines included in the Period \"%s\" or before haven't been generated. "
500- "Please generate them and create the related recurring entries "
501- "before closing the period.") % (period.name,))
502 # for subscription lines generated check if some related recurring entries haven't been created yet
503 if sub_line_obj.search_exist(cr, uid, [('date', '<=', period.date_stop), ('move_id', '=', False)], context=context):
504 raise osv.except_osv(_('Warning'), _("Recurring entries included in the Period \"%s\" or before haven't been created. "
505- "Please create them before closing the period.") % (period.name,))
506+ "Please generate them before closing the period.") % (period.name,))
507 # then verify that all currencies have a fx rate in this period
508 # retrieve currencies for this period (in account_move_lines)
509 sql = """SELECT DISTINCT currency_id
510
511=== modified file 'bin/addons/account_subscription/__init__.py'
512--- bin/addons/account_subscription/__init__.py 2012-08-09 11:20:48 +0000
513+++ bin/addons/account_subscription/__init__.py 2020-08-07 12:54:52 +0000
514@@ -22,6 +22,5 @@
515 import account_move_line
516 import account_model
517 import account_use_model
518-import account_subscription
519
520 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
521
522=== modified file 'bin/addons/account_subscription/account_model.py'
523--- bin/addons/account_subscription/account_model.py 2020-01-22 10:35:39 +0000
524+++ bin/addons/account_subscription/account_model.py 2020-08-07 12:54:52 +0000
525@@ -133,6 +133,7 @@
526 selection=[('no_exp_in', 'Not expense/income'), ('no_header', 'No header'),
527 ('valid', 'Valid'), ('invalid', 'Invalid'), ('invalid_small_amount', 'Invalid')],
528 string='Expense/income line status'), # UFTP-103
529+ 'is_balanced': fields.related('model_id', 'is_balanced', type='boolean', string='Is balanced', readonly=True, store=False),
530 }
531
532 _defaults = {
533@@ -253,6 +254,75 @@
534 break
535 return res
536
537+ def _get_model_state(self, cr, uid, ids, name, args, context=None):
538+ """
539+ A model is:
540+ - in Done state if it is used in a least one Done Recurring Plan,
541+ - in Running state if it is used in a least one Running Recurring Plan,
542+ - in Draft state otherwise.
543+ """
544+ if context is None:
545+ context = {}
546+ if isinstance(ids, (int, long)):
547+ ids = [ids]
548+ res = {}
549+ recurring_plan_obj = self.pool.get('account.subscription')
550+ for model_id in ids:
551+ if recurring_plan_obj.search_exist(cr, uid, [('model_id', '=', model_id), ('state', '=', 'done')], context=context):
552+ state = 'done'
553+ elif recurring_plan_obj.search_exist(cr, uid, [('model_id', '=', model_id), ('state', '=', 'running')], context=context):
554+ state = 'running'
555+ else:
556+ state = 'draft'
557+ res[model_id] = state
558+ return res
559+
560+ def _get_models_to_check(self, cr, uid, recurring_plan_ids, context=None):
561+ """
562+ Returns the list of Recurring Models for which the state should be checked and updated if necessary
563+ """
564+ if context is None:
565+ context = {}
566+ res = set()
567+ recurring_plan_obj = self.pool.get('account.subscription')
568+ for rec_plan in recurring_plan_obj.browse(cr, uid, recurring_plan_ids, fields_to_fetch=['model_id'], context=context):
569+ res.add(rec_plan.model_id.id)
570+ return list(res)
571+
572+ def unlink(self, cr, uid, ids, context=None):
573+ """
574+ Prevents deletion in case the model has been selected into a Recurring Plan
575+ """
576+ if context is None:
577+ context = {}
578+ if isinstance(ids, (int, long)):
579+ ids = [ids]
580+ recurring_plan_obj = self.pool.get('account.subscription')
581+ recurring_plan_ids = recurring_plan_obj.search(cr, uid, [('model_id', 'in', ids)], context=context)
582+ if recurring_plan_ids:
583+ plan_names = [p.name for p in recurring_plan_obj.browse(cr, uid, recurring_plan_ids, fields_to_fetch=['name'], context=context)]
584+ raise osv.except_osv(_('Warning'), _('You cannot delete a model which is used in the following plan(s): %s') %
585+ (', '.join(plan_names),))
586+ return super(account_model, self).unlink(cr, uid, ids, context=context)
587+
588+ def _get_is_balanced(self, cr, uid, ids, name, arg, context=None):
589+ """
590+ Returns True for the models for which the total of the lines is zero
591+ """
592+ if context is None:
593+ context = {}
594+ if isinstance(ids, (int, long)):
595+ ids = [ids]
596+ res = {}
597+ for model in self.browse(cr, uid, ids, fields_to_fetch=['lines_id'], context=context):
598+ debit = sum([l.debit or 0.0 for l in model.lines_id]) or 0.0
599+ credit = sum([l.credit or 0.0 for l in model.lines_id]) or 0.0
600+ if abs(debit - credit) <= 10**-3:
601+ res[model.id] = True
602+ else:
603+ res[model.id] = False
604+ return res
605+
606 _columns = {
607 'currency_id': fields.many2one('res.currency', 'Currency', required=True),
608 'analytic_distribution_id': fields.many2one('analytic.distribution', 'Analytic Distribution'),
609@@ -260,13 +330,38 @@
610 method=True, type='boolean',
611 string='Has bad analytic distribution on expense/income lines',
612 help='There is lines with expense or income accounts with invalid analytic distribution or using header AD that is not defined or not compatible.'), # UFTP-103
613+ 'state': fields.function(_get_model_state, method=True, type='selection', string="State",
614+ selection=[('draft', 'Draft'), ('running', 'Running'), ('done', 'Done')],
615+ store={
616+ 'account.subscription': (_get_models_to_check, ['model_id', 'state'], 10),
617+ }),
618+ 'is_balanced': fields.function(_get_is_balanced, method=True, type='boolean', string="Is balanced", readonly=True, store=False),
619+ 'create_date': fields.date('Creation date', readonly=True), # overwrites the standard create_date so it can be displayed in the views
620+ 'recurring_plan_ids': fields.one2many('account.subscription', 'model_id', string='Recurring Plans', readonly=True),
621 }
622
623 _defaults = {
624 'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id,
625 'has_any_bad_ad_line_exp_in': False,
626+ 'state': lambda *a: 'draft',
627 }
628
629+ _order = 'create_date DESC, id DESC'
630+
631+ def _check_model_name_unicity(self, cr, uid, ids, context=None):
632+ """
633+ Prevents having 2 models using the same name
634+ """
635+ for model in self.read(cr, uid, ids, ['name']):
636+ if self.search_exist(cr, uid, [('name', '=', model['name']), ('id', '!=', model['id'])]):
637+ raise osv.except_osv(_('Error'),
638+ _('It is not possible to have several Recurring Models with the same name: %s.') % model['name'])
639+ return True
640+
641+ _constraints = [
642+ (_check_model_name_unicity, 'It is not possible to have several Recurring Models with the same name.', ['name']),
643+ ]
644+
645 # @@@override@account.account_model.generate()
646 def generate(self, cr, uid, ids, datas={}, context=None):
647 move_ids = []
648@@ -275,6 +370,7 @@
649 account_move_line_obj = self.pool.get('account.move.line')
650 pt_obj = self.pool.get('account.payment.term')
651 ana_obj = self.pool.get('analytic.distribution')
652+ period_obj = self.pool.get('account.period')
653
654 if context is None:
655 context = {}
656@@ -282,13 +378,15 @@
657 if datas.get('date', False):
658 context.update({'date': datas['date']})
659
660- period_id = self.pool.get('account.period').find(cr, uid, dt=context.get('date', False))
661- if not period_id:
662+ period_domain = [('date_start', '<=', context.get('date')), ('date_stop', '>=', context.get('date')), ('special', '=', False)]
663+ period_ids = period_obj.search(cr, uid, period_domain, context=context)
664+
665+ if not period_ids:
666 raise osv.except_osv(_('No period found !'), _('Unable to find a valid period !'))
667- period_id = period_id[0]
668+ period_id = period_ids[0]
669 # UFTP-105: Check that period is open. Otherwise raise an error
670- period = self.pool.get('account.period').browse(cr, uid, period_id, context=context)
671- if not period or period.state != 'draft':
672+ period = period_obj.browse(cr, uid, period_id, fields_to_fetch=['state', 'name'], context=context)
673+ if period.state != 'draft':
674 raise osv.except_osv(_('Warning'), _('This period should be in open state: %s') % (period.name))
675
676 for model in self.browse(cr, uid, ids, context=context):
677@@ -315,8 +413,9 @@
678 except Exception:
679 raise osv.except_osv(_('Error'), _('The name of the Recurring Model used is incorrect: %s\n'
680 'You can find a list of the formatted strings usable on the Recurring Model form.') % model.name)
681+ ref = datas.get('ref', '') or entry['name']
682 move_id = account_move_obj.create(cr, uid, {
683- 'ref': entry['name'],
684+ 'ref': ref,
685 'period_id': period_id,
686 'journal_id': model.journal_id.id,
687 'date': context.get('date',time.strftime('%Y-%m-%d'))
688@@ -327,10 +426,11 @@
689 'move_id': move_id,
690 'journal_id': model.journal_id.id,
691 'period_id': period_id,
692+ 'reference': ref,
693 }
694 if line.account_id.is_analytic_addicted:
695 if line.analytic_distribution_state == 'invalid':
696- raise osv.except_osv(_('Invalid Analytic Distribution !'),_("Please define a valid analytic distribution for the recurring model '%s'!") % (line.name))
697+ raise osv.except_osv(_('Invalid Analytic Distribution !'),_("Please define a valid analytic distribution for the recurring model '%s'!") % (line.model_id.name))
698 if not model.journal_id.analytic_journal_id:
699 raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,))
700 if line.analytic_distribution_id:
701@@ -438,5 +538,23 @@
702 recurring_obj.write(cr, uid, to_reset, {'analytic_distribution_id': False})
703 return True
704
705+ def copy(self, cr, uid, model_id, default=None, context=None):
706+ """
707+ Recurring Model duplication: don't copy the link with the rec. plans, and add " (copy)" after the name
708+ """
709+ if context is None:
710+ context = {}
711+ suffix = ' (copy)'
712+ model_copied = self.read(cr, uid, model_id, ['name'], context=context)
713+ name = '%s%s' % (model_copied['name'][:64 - len(suffix)], suffix)
714+ if default is None:
715+ default = {}
716+ default.update({
717+ 'name': name,
718+ 'recurring_plan_ids': [],
719+ })
720+ return super(account_model, self).copy(cr, uid, model_id, default, context=context)
721+
722+
723 account_model()
724 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
725
726=== modified file 'bin/addons/account_subscription/account_model_view.xml'
727--- bin/addons/account_subscription/account_model_view.xml 2020-01-22 10:35:39 +0000
728+++ bin/addons/account_subscription/account_model_view.xml 2020-08-07 12:54:52 +0000
729@@ -9,7 +9,7 @@
730 <field name="inherit_id" ref="account.view_model_form"/>
731 <field name="arch" type="xml">
732 <form string="Journal Entry Model" position="replace">
733- <form string="Journal Entry Model">
734+ <form string="Recurring Models">
735 <group><html>
736 <p id="para_has_any_bad_ad_line_exp_in"
737 style="display:none; text-align:center; color: red; font-weight: bold; font-size: 1.2em;">
738@@ -24,19 +24,38 @@
739 </script>
740 </html></group>
741 <group col="6" colspan="4">
742- <field name="name"/>
743- <field name="journal_id" domain="[('type','=','purchase'),('is_current_instance','=',True)]"/>
744- <field name="currency_id"/>
745+ <group attrs="{'readonly': [('state', '=', 'done')]}" colspan="6" col="6">
746+ <field name="name"/>
747+ <field name="journal_id" domain="[('type', '=', 'purchase'), ('is_current_instance', '=', True)]"/>
748+ <field name="currency_id"/>
749+ </group>
750 <group colspan="6" col="6" attrs="{'invisible': [('analytic_distribution_id', '=', False)]}">
751 <button name="button_analytic_distribution" string="Analytical Distribution" type="object" icon="terp-check" context="context" colspan="3" attrs="{'invisible': [('analytic_distribution_id', '=', False)]}"/>
752- <button name="button_reset_distribution" string="Reset AD at line level" type="object" icon="gtk-undelete" colspan="3"/>
753+ <button name="button_reset_distribution" string="Reset AD at line level" type="object"
754+ icon="gtk-undelete" colspan="3" attrs="{'invisible': [('state', '=', 'done')]}"/>
755 </group>
756 <group colspan="6" col="6" attrs="{'invisible': [('analytic_distribution_id', '!=', False)]}">
757 <button name="button_analytic_distribution" string="Analytical Distribution" type="object" icon="terp-emblem-important" context="context" colspan="3" attrs="{'invisible': [('analytic_distribution_id', '!=', False)]}"/>
758- <button name="button_reset_distribution" string="Reset AD at line level" type="object" icon="gtk-undelete" colspan="3"/>
759+ <button name="button_reset_distribution" string="Reset AD at line level" type="object"
760+ icon="gtk-undelete" colspan="3" attrs="{'invisible': [('state', '=', 'done')]}"/>
761 </group>
762 <field name="analytic_distribution_id" invisible="1"/>
763- <field colspan="6" nolabel="1" name="lines_id" widget="one2many_list"/>
764+ <notebook colspan="4">
765+ <page string="Model">
766+ <field nolabel="1" name="lines_id" widget="one2many_list" colspan="4"
767+ attrs="{'readonly': [('state', '=', 'done')]}"/>
768+ </page>
769+ <page string="Related plans">
770+ <field nolabel="1" name="recurring_plan_ids" colspan="4">
771+ <tree>
772+ <field name="name" string="Plan names"/>
773+ <field name="state" string="Plan status"/>
774+ </tree>
775+ </field>
776+ </page>
777+ </notebook>
778+ <label string="" colspan="4"/>
779+ <field name="state" readonly="1"/>
780 <separator colspan="6" string="Legend (for the Model Name)"/>
781 <group col="8" colspan="6">
782 <group>
783@@ -91,7 +110,8 @@
784 <field name="type">tree</field>
785 <field name="arch" type="xml">
786 <tree string="Journal Entry Model Line" editable="bottom"
787- colors="red: exp_in_ad_state in ('no_header', 'bad_header', 'invalid', 'invalid_small_amount')">
788+ colors="red: exp_in_ad_state in ('no_header', 'bad_header', 'invalid', 'invalid_small_amount');blue:not is_balanced and exp_in_ad_state not in ('no_header', 'bad_header', 'invalid', 'invalid_small_amount')">
789+ <field name="is_balanced" invisible="1"/>
790 <field name="sequence" readonly="1"/>
791 <field name="name"/>
792 <field name="account_id" domain="[('restricted_area', '=', 'recurring_lines')]"/>
793@@ -101,8 +121,8 @@
794 <field name="analytic_distribution_state" invisible="1"/>
795 <field name="is_allocatable" invisible="1"/>
796 <field name="partner_id"/>
797- <field name="debit"/>
798- <field name="credit"/>
799+ <field name="debit" sum="Total Debit"/>
800+ <field name="credit" sum="Total Credit"/>
801 <field name="exp_in_ad_state" invisible="1"/>
802 </tree>
803 </field>
804@@ -162,7 +182,7 @@
805 <field name="type">tree</field>
806 <field name="priority" eval="14"/>
807 <field name="arch" type="xml">
808- <tree string="Recurring Entries To Validate" min_rows="100"
809+ <tree string="Recurring Entries To Post" min_rows="100"
810 hide_new_button="1" hide_delete_button="1" hide_edit_button="1"
811 colors="red:analytic_distribution_state not in ('valid')">
812 <field name="instance_id"/>
813@@ -209,14 +229,47 @@
814 </field>
815 </record>
816
817- <act_window
818- id="act_account_subscription_to_account_move_line_open"
819- name="Recurring Entries To Validate"
820- domain="[('move_id.state','=','draft'), ('is_recurring', '=', True)]"
821- context="{'from_recurring_entries': True}"
822- res_model="account.move.line"
823- src_model="account.subscription"
824- view_id="account_move_line_recurring_entries_to_validate"/>
825+ <!-- Recurring Entries To Post Search View -->
826+ <record id="view_recurring_entries_to_post_search" model="ir.ui.view">
827+ <field name="name">recurring.entries.to.post.search</field>
828+ <field name="model">account.move.line</field>
829+ <field name="type">search</field>
830+ <field name="priority" eval="25"/>
831+ <field name="arch" type="xml">
832+ <search>
833+ <group colspan="6" col="14">
834+ <field name="move_id"/>
835+ <field name="name"/>
836+ <field name="ref"/>
837+ <field name="document_date"/>
838+ <field name="date"/>
839+ <field name="period_id" domain="[('special', '=', False), ('state', '=', 'draft')]"/>
840+ <field name="account_id" domain="[('restricted_area', '=', 'recurring_lines')]"/>
841+ <newline/>
842+ <!-- title matching with the tree view but only Partners are possible -->
843+ <field name="partner_id" string="Third Parties"/>
844+ <field name="debit_currency"/>
845+ <field name="credit_currency"/>
846+ <field name="currency_id"/>
847+ <field name="debit"/>
848+ <field name="credit"/>
849+ </group>
850+ </search>
851+ </field>
852+ </record>
853+
854+ <!-- Recurring Entries To Post Entry Menu -->
855+ <record id="act_account_subscription_to_account_move_line_open" model="ir.actions.act_window">
856+ <field name="name">Recurring Entries To Post</field>
857+ <field name="res_model">account.move.line</field>
858+ <field name="src_model">account.subscription</field>
859+ <field name="view_type">form</field>
860+ <field name="view_mode">tree,form</field>
861+ <field name="view_id" ref="account_move_line_recurring_entries_to_validate"/>
862+ <field name="context">{'from_recurring_entries': True}</field>
863+ <field name="domain">[('move_id.state', '=', 'draft'), ('is_recurring', '=', True)]</field>
864+ <field name="search_view_id" ref="view_recurring_entries_to_post_search"/>
865+ </record>
866
867 </data>
868 </openerp>
869
870=== removed file 'bin/addons/account_subscription/account_subscription.py'
871=== modified file 'bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py'
872--- bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py 2020-02-21 15:15:49 +0000
873+++ bin/addons/analytic_distribution/wizard/analytic_distribution_wizard.py 2020-08-07 12:54:52 +0000
874@@ -549,6 +549,11 @@
875 if not context.get('from_correction', False) and \
876 el.move_id.state and el.move_id.state not in ['draft']:
877 res[el.id] = False
878+ # check Recurring Model state
879+ if el.model_id and el.model_id.state == 'done':
880+ res[el.id] = False
881+ if el.model_line_id and el.model_line_id.model_id.state == 'done':
882+ res[el.id] = False
883 return res
884
885 def _have_header(self, cr, uid, ids, name, args, context=None):
886
887=== modified file 'bin/addons/msf_profile/data/patches.xml'
888--- bin/addons/msf_profile/data/patches.xml 2020-08-04 08:00:56 +0000
889+++ bin/addons/msf_profile/data/patches.xml 2020-08-07 12:54:52 +0000
890@@ -577,9 +577,16 @@
891 <field name="method">us_7412_set_fy_closure_settings</field>
892 </record>
893
894+<<<<<<< TREE
895 <record id="us_6453_set_ref_on_in" model="patch.scripts">
896 <field name="method">us_6453_set_ref_on_in</field>
897 </record>
898
899+=======
900+ <record id="us_5216_update_recurring_object_state" model="patch.scripts">
901+ <field name="method">us_5216_update_recurring_object_state</field>
902+ </record>
903+
904+>>>>>>> MERGE-SOURCE
905 </data>
906 </openerp>
907
908=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
909--- bin/addons/msf_profile/i18n/fr_MF.po 2020-08-04 08:46:20 +0000
910+++ bin/addons/msf_profile/i18n/fr_MF.po 2020-08-07 12:54:52 +0000
911@@ -8436,7 +8436,7 @@
912 msgid "Either there are no moves linked to the picking or Accounting Journals are misconfigured!"
913 msgstr "Soit les Journaux Comptables sont mal configurés, soit il n'y a pas de mouvement connexe à ce prélèvement !"
914
915-#. modules: tender_flow, financing_contract, msf_tools, account_override, purchase_allocation_report, register_accounting, mission_stock, msf_accrual, finance, sync_client, return_claim, account_mcdb, res_currency_tables, supplier_catalogue, procurement_request, stock_forecast, analytic, stock_override, msf_doc_import, analytic_distribution, msf_order_date, msf_homere_interface, consumption_calculation, msf_instance, purchase_override, specific_rules, kit, out_step, base, msf_supply_doc_export, msf_budget, account_corrections, account, msf_outgoing, documents_done, sale, sales_followup, procurement, sourcing, purchase, msf_audittrail, stock, product, procurement_cycle
916+#. modules: tender_flow, financing_contract, msf_tools, account_override, purchase_allocation_report, register_accounting, mission_stock, msf_accrual, finance, sync_client, return_claim, account_mcdb, res_currency_tables, supplier_catalogue, procurement_request, stock_forecast, analytic, stock_override, msf_doc_import, analytic_distribution, msf_order_date, msf_homere_interface, consumption_calculation, msf_instance, purchase_override, specific_rules, kit, out_step, base, msf_supply_doc_export, msf_budget, account_corrections, account, msf_outgoing, documents_done, sale, sales_followup, procurement, sourcing, purchase, msf_audittrail, stock, product, procurement_cycle, account_subscription
917 #: code:addons/msf_supply_doc_export/wizard/po_follow_up.py:106
918 #: selection:msf.instance.cloud,state:0
919 #: field:ppl.processor,draft_step2:0
920@@ -8609,6 +8609,8 @@
921 #: selection:replenishment.segment,state:0
922 #: view:product.stock_out:0
923 #: selection:product.stock_out,state:0
924+#: selection:account.model,state:0
925+#: view:account.model:0
926 #, python-format
927 msgid "Draft"
928 msgstr "Brouillon"
929@@ -10058,11 +10060,6 @@
930 msgid "Funding pools:"
931 msgstr "Funding pools:"
932
933-#. module: account
934-#: view:account.subscription:0
935-msgid "Entry Subscription"
936-msgstr "Ecriture de souscription"
937-
938 #. modules: account, account_period_closing_level
939 #: model:ir.actions.act_window,help:account.action_account_period_tree
940 #: model:ir.actions.act_window,help:account_period_closing_level.action_account_period_closing_level_tree
941@@ -13614,9 +13611,10 @@
942 msgid "Invoice Control"
943 msgstr "Contrôle Facture"
944
945-#. module: account
946+#. modules: account, account_subscription
947 #: model:ir.actions.act_window,name:account.action_model_form
948 #: model:ir.ui.menu,name:account.menu_action_model_form
949+#: view:account.model:0
950 msgid "Recurring Models"
951 msgstr "Modèles périodiques"
952
953@@ -20777,12 +20775,11 @@
954 msgid "Etc/GMT-11"
955 msgstr "Etc/GMT-11"
956
957-#. modules: sales_followup, msf_tools, account
958+#. modules: sales_followup, msf_tools
959 #: selection:ir.followup.location.wizard,state:0
960 #: selection:job.in_progress,state:0
961-#: view:account.subscription:0
962 msgid "Done"
963-msgstr "Cloturé"
964+msgstr "Clôturé"
965
966 #. module: delivery_mechanism
967 #: code:addons/delivery_mechanism/delivery_mechanism.py:360
968@@ -23927,7 +23924,7 @@
969 #. module: account
970 #: field:account.subscription,period_nbr:0
971 msgid "Repeat"
972-msgstr "Repeat"
973+msgstr "Périodicité"
974
975 #. module: sourcing
976 #: code:addons/sourcing/sale_order_line.py:905
977@@ -30362,8 +30359,8 @@
978
979 #. module: account
980 #: view:account.subscription.generate:0
981-msgid "Automatically generate entries based on what has been entered in the system before a specific date."
982-msgstr "Génère automatiquement des écritures en se basant sur ce qui a été enregistré dans le système avant une date spécifique"
983+msgid "Automatically generate entries based on what has been entered in the system until a specific date."
984+msgstr "Génère automatiquement des écritures en se basant sur ce qui a été enregistré dans le système jusqu'à une date spécifique."
985
986 #. module: base
987 #: model:res.currency,currency_name:base.DZD
988@@ -33535,11 +33532,6 @@
989 msgid "used in statement reconciliation domain, but shouldn't be used elswhere."
990 msgstr "utilisé dans le domaine du lettrage de relevés, mais ne devrait pas être utilisé ailleurs"
991
992-#. module: account
993-#: view:account.subscription:0
994-msgid "Draft Subscription"
995-msgstr "Draft Subscription"
996-
997 #. module: base
998 #: view:partner.wizard.ean.check:0
999 msgid "Correct EAN13"
1000@@ -38135,11 +38127,6 @@
1001 msgid "Reservation Destination"
1002 msgstr "Destination de la Réservation"
1003
1004-#. module: account
1005-#: view:account.subscription:0
1006-msgid "Remove Lines"
1007-msgstr "Supprimer des lignes"
1008-
1009 #. module: base
1010 #: help:ir.cron,function:0
1011 msgid "Name of the method to be called on the object when this scheduler is executed."
1012@@ -38308,7 +38295,7 @@
1013 #: code:addons/account/wizard/account_subscription_generate.py:52
1014 #, python-format
1015 msgid "The Recurring Model %s must have at least two lines."
1016-msgstr "Le Modèle Récurrent %s doit au moins avoir deux lignes."
1017+msgstr "Le Modèle Périodique %s doit avoir au moins deux lignes."
1018
1019 #. module: msf_doc_import
1020 #: code:addons/msf_doc_import/msf_import_export.py:103
1021@@ -38581,7 +38568,7 @@
1022 msgid "Is inactive for destination given in context"
1023 msgstr "Is inactive for destination given in context"
1024
1025-#. modules: sales_followup, account, documents_done, consumption_calculation, sale, specific_rules, transport_mgmt, account_override, purchase_allocation_report, product_list, tender_flow, msf_doc_import, stock, product_attributes, purchase_override, purchase
1026+#. modules: sales_followup, account, documents_done, consumption_calculation, sale, specific_rules, transport_mgmt, account_override, purchase_allocation_report, product_list, tender_flow, msf_doc_import, stock, product_attributes, purchase_override, purchase, account_subscription
1027 #: field:account.move.line,date_created:0
1028 #: field:account.move.reconcile,create_date:0
1029 #: report:allocation.invoices.report:0
1030@@ -38608,6 +38595,7 @@
1031 #: field:internal.request.import,in_creation_date:0
1032 #: field:purchase.order.line,create_date:0
1033 #: field:internal.request.import,in_creation_date:0
1034+#: field:account.model,create_date:0
1035 #, python-format
1036 msgid "Creation date"
1037 msgstr "Date de création"
1038@@ -39212,7 +39200,7 @@
1039 msgid "RfQs"
1040 msgstr "DdD"
1041
1042-#. modules: account, sync_client, product_asset, base, msf_audittrail, board, object_query, msf_profile, msf_field_access_rights, msf_button_access_rights,msf_tools
1043+#. modules: account, sync_client, product_asset, base, msf_audittrail, board, object_query, msf_profile, msf_field_access_rights, msf_button_access_rights, msf_tools, account_subscription
1044 #: field:account.model.line,model_id:0
1045 #: view:account.subscription:0
1046 #: field:account.subscription,model_id:0
1047@@ -39241,6 +39229,7 @@
1048 #: field:automated.import.function,model_id:0
1049 #: field:sync.client.log_sale_purchase,model:0
1050 #: field:sync.client.log_sale_purchase,model_id:0
1051+#: view:account.model:0
1052 msgid "Model"
1053 msgstr "Modèle"
1054
1055@@ -43211,6 +43200,7 @@
1056 #. modules: account, finance
1057 #: view:account.move:0
1058 #: view:cash.request:0
1059+#: view:account.model.line:0
1060 msgid "Total Debit"
1061 msgstr "Total Débit"
1062
1063@@ -44394,8 +44384,8 @@
1064
1065 #. module: account
1066 #: model:ir.actions.act_window,help:account.action_subscription_form
1067-msgid "A recurring entry is a miscellaneous entry that occurs on a recurrent basis from a specific date, i.e. corresponding to the signature of a contract or an agreement with a customer or a supplier. With Define Recurring Entries, you can create such entries to automate the postings in the system."
1068-msgstr "Une écriture périodique est une écriture qui est configurée par le biais de la fonctionnalité Définir Ecritures Périodiques. Ceci vous permet d'enregistrer une écriture à partir d'une date spécifique. Cette écriture sera reproduite automatiquement dans votre comptabilité et à une fréquence définie. Vous pouvez utiliser cette fonctionnalité par exemple pour étaler la charge d'un loyer sur plusieurs mensualités. "
1069+msgid "A recurring entry is a miscellaneous entry that occurs on a recurrent basis from a specific date, i.e. corresponding to the signature of a contract or an agreement with a customer or a supplier. With Recurring Plan, you can create such entries to automate the postings in the system."
1070+msgstr "Une écriture périodique est une écriture qui est configurée par le biais de la fonctionnalité Plan d'Ecritures Périodiques. Ceci vous permet d'enregistrer une écriture à partir d'une date spécifique. Cette écriture sera reproduite automatiquement dans votre comptabilité et à une fréquence définie. Vous pouvez utiliser cette fonctionnalité par exemple pour étaler la charge d'un loyer sur plusieurs mensualités."
1071
1072 #. modules: account, finance
1073 #: view:account.bank.statement:0
1074@@ -50461,11 +50451,6 @@
1075 msgid "Logs Sequence"
1076 msgstr "Journaux de bord - Sequence"
1077
1078-#. module: account
1079-#: view:account.subscription:0
1080-msgid "Running Subscription"
1081-msgstr "Running Subscription"
1082-
1083 #. modules: base, msf_currency_revaluation
1084 #: code:addons/msf_currency_revaluation/res_currency.py:40
1085 #: code:addons/base/res/res_currency.py:108
1086@@ -62609,8 +62594,8 @@
1087 #. module: account_subscription
1088 #: model:ir.actions.act_window,name:account_subscription.act_account_subscription_to_account_move_line_open
1089 #: view:account.move.line:0
1090-msgid "Recurring Entries To Validate"
1091-msgstr "Entrées récurrentes à valider"
1092+msgid "Recurring Entries To Post"
1093+msgstr "Lignes Périodiques à Poster"
1094
1095 #. module: product
1096 #: view:product.product:0
1097@@ -62763,8 +62748,8 @@
1098
1099 #. module: account
1100 #: view:account.subscription.generate:0
1101-msgid "Generate Entries before:"
1102-msgstr "Générer les Ecritures avant :"
1103+msgid "Generate Entries until:"
1104+msgstr "Générer les Ecritures jusqu'au :"
1105
1106 #. modules: account, msf_instance
1107 #: field:account.invoice.refund,journal_id:0
1108@@ -65459,10 +65444,9 @@
1109 msgid "Supplier catalogue"
1110 msgstr "Catalogue du fournisseur"
1111
1112-#. module: account_subscription
1113-#: code:addons/account_subscription/account_subscription.py:41
1114-#: code:addons/account_subscription/account_subscription.py:50
1115-#, python-format
1116+#. modules: account, account_subscription
1117+#: constraint:account.subscription:0
1118+#: constraint:account.subscription:0
1119 msgid "The value in the field \"Repeat\" must be greater than 0!"
1120 msgstr "La valeur dans le champ \"Périodicité\" doit être supérieure à 0 !"
1121
1122@@ -66574,6 +66558,7 @@
1123 #. modules: account, finance
1124 #: view:account.move:0
1125 #: view:cash.request:0
1126+#: view:account.model.line:0
1127 msgid "Total Credit"
1128 msgstr "Total Crédit"
1129
1130@@ -74124,14 +74109,8 @@
1131 #. module: account_period_closing_level
1132 #: code:addons/account_period_closing_level/account_period.py:236
1133 #, python-format
1134-msgid "Recurring entries included in the Period \"%s\" or before haven't been created. Please create them before closing the period."
1135-msgstr "Des Ecritures périodiques incluses dans la Période \"%s\" ou avant n'ont pas été créées. Veuillez les créer avant de clôturer la période."
1136-
1137-#. module: account_period_closing_level
1138-#: code:addons/account_period_closing_level/account_period.py:231
1139-#, python-format
1140-msgid "Subscription Lines included in the Period \"%s\" or before haven't been generated. Please generate them and create the related recurring entries before closing the period."
1141-msgstr "Des Lignes d'Abonnement incluses dans la Période \"%s\" ou avant n'ont pas été générées. Veuillez les générer et créer les écritures périodiques associées avant de clôturer la période."
1142+msgid "Recurring entries included in the Period \"%s\" or before haven't been created. Please generate them before closing the period."
1143+msgstr "Des Ecritures périodiques incluses dans la Période \"%s\" ou avant n'ont pas été créées. Veuillez les générer avant de clôturer la période."
1144
1145 #. module: msf_field_access_rights
1146 #: view:msf_field_access_rights.field_access_rule:0
1147@@ -74940,9 +74919,11 @@
1148 msgstr "Line %s in your Excel file: %s: %s\n"
1149 ""
1150
1151-#. module: account
1152+#. modules: account, account_subscription
1153 #: view:account.subscription:0
1154 #: selection:account.subscription,state:0
1155+#: selection:account.model,state:0
1156+#: view:account.model:0
1157 msgid "Running"
1158 msgstr "En cours"
1159
1160@@ -76426,7 +76407,7 @@
1161 #. module: account
1162 #: help:account.subscription,period_nbr:0
1163 msgid "This field will determine how often entries will be generated: if the period type is 'month' and the repeat '2' then entries will be generated every 2 months"
1164-msgstr "This field will determine how often entries will be generated: if the period type is 'month' and the repeat '2' then entries will be generated every 2 months"
1165+msgstr "Ce champ déterminera la fréquence à laquelle les écritures seront générées : si le type de période est 'mois' et la périodicité est '2', alors les écritures seront générées tous les 2 mois."
1166
1167 #. module: sync_client
1168 #: selection:sync.client.log_sale_purchase,action_type:0
1169@@ -81523,7 +81504,7 @@
1170 msgid "Confirm the selected invoices"
1171 msgstr "Confirmer les factures sélectionnées"
1172
1173-#. modules: purchase, res_currency_tables,tender_flow, sync_client, account_mcdb, sales_followup, supplier_catalogue, sale, account, stock_forecast, export_import_lang, purchase_followup, msf_supply_doc_export, specific_rules, analytic_distribution, useability_dashboard_and_menu, procurement_request, out_step, consumption_calculation, stock_override, process, account_reconciliation, msf_instance, purchase_override, account_hq_entries, purchase_allocation_report, msf_tools, vertical_integration, msf_outgoing, register_accounting, documents_done, transport_mgmt, analytic, msf_audittrail, msf_doc_import, stock, msf_budget, msf_homere_interface, kit, hr, finance, financing_contract, update_client, account_override, base, return_claim, procurement, procurement_cycle
1174+#. modules: purchase, res_currency_tables,tender_flow, sync_client, account_mcdb, sales_followup, supplier_catalogue, sale, account, stock_forecast, export_import_lang, purchase_followup, msf_supply_doc_export, specific_rules, analytic_distribution, useability_dashboard_and_menu, procurement_request, out_step, consumption_calculation, stock_override, process, account_reconciliation, msf_instance, purchase_override, account_hq_entries, purchase_allocation_report, msf_tools, vertical_integration, msf_outgoing, register_accounting, documents_done, transport_mgmt, analytic, msf_audittrail, msf_doc_import, stock, msf_budget, msf_homere_interface, kit, hr, finance, financing_contract, update_client, account_override, base, return_claim, procurement, procurement_cycle, account_subscription
1175 #: view:account.bank.statement:0
1176 #: field:account.bank.statement,state:0
1177 #: field:account.entries.report,move_state:0
1178@@ -81735,6 +81716,7 @@
1179 #: field:account.invoice.import,state:0
1180 #: report:addons/procurement_cycle/report/product_stock_out.mako:436
1181 #: field:product.stock_out,state:0
1182+#: field:account.model,state:0
1183 #, python-format
1184 msgid "State"
1185 msgstr "Statut"
1186@@ -82770,10 +82752,9 @@
1187 msgid "Select a supplier"
1188 msgstr "Sélectionner un fournisseur"
1189
1190-#. modules: delivery_mechanism, msf_budget, account, msf_outgoing, msf_homere_interface, sync_client, register_accounting, specific_rules, sale, sales_followup, base, stock, tender_flow, msf_tools, return_claim, msf_doc_import, analytic_distribution, finance, product
1191+#. modules: delivery_mechanism, msf_budget, account, msf_outgoing, msf_homere_interface, sync_client, register_accounting, specific_rules, sale, sales_followup, base, stock, tender_flow, msf_tools, return_claim, msf_doc_import, analytic_distribution, finance, product, account_subscription
1192 #: selection:account.invoice.report,state:0
1193 #: selection:account.journal.period,state:0
1194-#: selection:account.subscription,state:0
1195 #: selection:report.invoice.created,state:0
1196 #: view:account.commitment:0
1197 #: selection:account.commitment,state:0
1198@@ -82838,6 +82819,10 @@
1199 #: selection:wizard.import.product.line,state:0
1200 #: selection:product.mass.update,state:0
1201 #: selection:account.invoice.import,state:0
1202+#: view:account.subscription:0
1203+#: view:account.model:0
1204+#: selection:account.model,state:0
1205+#: selection:account.subscription,state:0
1206 #, python-format
1207 msgid "Done"
1208 msgstr "Terminé"
1209@@ -85076,7 +85061,7 @@
1210 #: code:addons/account_subscription/account_model.py:306
1211 #, python-format
1212 msgid "Please define a valid analytic distribution for the recurring model '%s'!"
1213-msgstr "Please define a valid analytic distribution for the recurring model '%s'!"
1214+msgstr "Veuillez définir une distribution analytique valide pour le modèle périodique '%s' !"
1215
1216 #. module: sale
1217 #: model:ir.actions.act_window,name:sale.action_sale_donation_stock_moves
1218@@ -85148,11 +85133,6 @@
1219 msgid "Qty Balance"
1220 msgstr "Bilan des Qtés"
1221
1222-#. module: account
1223-#: model:ir.actions.act_window,name:account.action_subscription_form
1224-msgid "Recurring Lines"
1225-msgstr "Lignes périodiques"
1226-
1227 #. module: msf_doc_import
1228 #: code:addons/msf_doc_import/account.py:54
1229 #, python-format
1230@@ -93378,7 +93358,7 @@
1231 msgid "Additional Information"
1232 msgstr "Information Complémentaire"
1233
1234-#. modules: account, register_accounting, account_mcdb, msf_homere_interface, msf_audittrail, account_corrections
1235+#. modules: account, register_accounting, account_mcdb, msf_homere_interface, msf_audittrail, account_corrections, account_subscription
1236 #: report:combined.journals.report.pdf:0
1237 #: report:addons/account_mcdb/report/combined_journals_report.mako:226
1238 #: field:hr.payroll.msf,partner_type:0
1239@@ -93396,6 +93376,7 @@
1240 #: selection:account.journal.column,field:0
1241 #: field:account.bank.statement.line,partner_type2:0
1242 #: report:addons/register_accounting/report/fully_report_xls.mako:563
1243+#: view:account.move.line:0
1244 msgid "Third Parties"
1245 msgstr "Tiers"
1246
1247@@ -94298,8 +94279,15 @@
1248
1249 #. module: account
1250 #: model:ir.ui.menu,name:account.menu_action_subscription_form
1251-msgid "Define Recurring Entries"
1252-msgstr "Définir des Ecritures Périodiques"
1253+#: model:ir.actions.act_window,name:account.action_subscription_form
1254+#: view:account.subscription:0
1255+msgid "Recurring Plan"
1256+msgstr "Plan d'Ecritures Périodiques"
1257+
1258+#. module: account_subscription
1259+#: field:account.model,recurring_plan_ids:0
1260+msgid "Recurring Plans"
1261+msgstr "Plans d'Ecritures Périodiques"
1262
1263 #. module: msf_doc_import
1264 #: code:addons/msf_doc_import/wizard/wizard_po_simulation_screen.py:628
1265@@ -110353,6 +110341,68 @@
1266 msgid "IN-line %s Wrong BN/ED attributes"
1267 msgstr "Ligne du IN %s: Mauvais attributs NL/DE"
1268
1269+#. module: account
1270+#: code:addons/account/account.py:2475
1271+#, python-format
1272+msgid "You cannot delete a Recurring Plan if Subscription lines have already been computed."
1273+msgstr "Vous ne pouvez pas supprimer un Plan d'Ecritures Périodiques si les lignes d'Abonnement ont déjà été calculées."
1274+
1275+#. module: account
1276+#: field:account.subscription,frozen_model:0
1277+msgid "Frozen model"
1278+msgstr "Modèle figé"
1279+
1280+#. module: account_subscription
1281+#: code:addons/account_subscription/account_model.py:303
1282+#, python-format
1283+msgid "You cannot delete a model which is used in the following plan(s): %s"
1284+msgstr "Vous ne pouvez pas supprimer un modèle qui est utilisé dans le(s) plan(s) suivant(s) : %s"
1285+
1286+#. modules: account, account_subscription
1287+#: constraint:account.model:0
1288+#: constraint:account.model:0
1289+msgid "It is not possible to have several Recurring Models with the same name."
1290+msgstr "Il n'est pas possible d'avoir plusieurs Modèles périodiques portant le même nom."
1291+
1292+#. module: account_subscription
1293+#: code:addons/account_subscription/account_model.py:358
1294+#, python-format
1295+msgid "It is not possible to have several Recurring Models with the same name: %s."
1296+msgstr "Il n'est pas possible d'avoir plusieurs Modèles périodiques portant le même nom : %s."
1297+
1298+#. modules: account, account_subscription
1299+#: constraint:account.subscription:0
1300+#: constraint:account.subscription:0
1301+msgid "It is not possible to have several Recurring Plans with the same name."
1302+msgstr "Il n'est pas possible d'avoir plusieurs Plans d'Ecritures Périodiques portant le même nom."
1303+
1304+#. module: account
1305+#: code:addons/account/account.py:2423
1306+#, python-format
1307+msgid "It is not possible to have several Recurring Plans with the same name: %s."
1308+msgstr "Il n'est pas possible d'avoir plusieurs Plans d'Ecritures Périodiques portant le même nom : %s."
1309+
1310+#. module: account_subscription
1311+#: field:account.model,is_balanced:0
1312+#: field:account.model.line,is_balanced:0
1313+msgid "Is balanced"
1314+msgstr "Est équilibré"
1315+
1316+#. module: account_subscription
1317+#: view:account.model:0
1318+msgid "Plan names"
1319+msgstr "Nom des plans"
1320+
1321+#. module: account_subscription
1322+#: view:account.model:0
1323+msgid "Plan status"
1324+msgstr "Statut des plans"
1325+
1326+#. module: account_subscription
1327+#: view:account.model:0
1328+msgid "Related plans"
1329+msgstr "Plans associés"
1330+
1331 #. module: product
1332 #: view:product.product:0
1333 msgid "Merge product"
1334@@ -110363,9 +110413,18 @@
1335 #, python-format
1336 msgid "is dispatched."
1337 msgstr "est expédié."
1338+<<<<<<< TREE
1339
1340 #. module: sale
1341 #: code:addons/sale/sale_workflow.py:584
1342 #, python-format
1343 msgid "You can not validate a line of a Regular FO with an Inter-section Customer if it was not created by sync."
1344 msgstr "Vous ne pouvez pas valider une ligne de CdT Normale qui a un Client Inter-section si elle n'a pas été créée par synchro."
1345+=======
1346+
1347+#. module: account
1348+#: code:addons/account/account.py:2441
1349+#, python-format
1350+msgid "You cannot duplicate a Recurring Plan with a Done model."
1351+msgstr "Vous ne pouvez pas dupliquer un Plan d'Ecritures Périodiques utilisant un modèle Terminé."
1352+>>>>>>> MERGE-SOURCE
1353
1354=== modified file 'bin/addons/msf_profile/msf_profile.py'
1355--- bin/addons/msf_profile/msf_profile.py 2020-08-04 08:00:56 +0000
1356+++ bin/addons/msf_profile/msf_profile.py 2020-08-07 12:54:52 +0000
1357@@ -53,6 +53,66 @@
1358 }
1359
1360 # UF18.0
1361+ def us_5216_update_recurring_object_state(self, cr, uid, *a, **b):
1362+ """
1363+ Updates the state of the Recurring Plans and Recurring Models with the new rules set in US-5216.
1364+ """
1365+ if not self.pool.get('sync.server.update'):
1366+ rec_plan_obj = self.pool.get('account.subscription')
1367+ rec_model_obj = self.pool.get('account.model')
1368+ # Recurring Plans
1369+ rec_plans = {
1370+ 'draft': [],
1371+ 'running': [],
1372+ 'done': [],
1373+ }
1374+ rec_plan_ids = rec_plan_obj.search(cr, uid, [], order='NO_ORDER')
1375+ for rec_plan in rec_plan_obj.browse(cr, uid, rec_plan_ids, fields_to_fetch=['lines_id']):
1376+ if not rec_plan.lines_id:
1377+ rec_plans['draft'].append(rec_plan.id)
1378+ else:
1379+ running = False
1380+ for sub_line in rec_plan.lines_id:
1381+ if not sub_line.move_id or sub_line.move_id.state != 'posted':
1382+ running = True
1383+ break
1384+ if running:
1385+ rec_plans['running'].append(rec_plan.id)
1386+ else:
1387+ rec_plans['done'].append(rec_plan.id)
1388+ for plan_state in rec_plans:
1389+ if rec_plans[plan_state]:
1390+ update_rec_plans = """
1391+ UPDATE account_subscription
1392+ SET state = %s
1393+ WHERE id IN %s;
1394+ """
1395+ cr.execute(update_rec_plans, (plan_state, tuple(rec_plans[plan_state])))
1396+ # Recurring Models
1397+ rec_models = {
1398+ 'draft': [],
1399+ 'running': [],
1400+ 'done': [],
1401+ }
1402+ rec_model_ids = rec_model_obj.search(cr, uid, [], order='NO_ORDER')
1403+ for model_id in rec_model_ids:
1404+ if rec_plan_obj.search_exist(cr, uid, [('model_id', '=', model_id), ('state', '=', 'done')]):
1405+ state = 'done'
1406+ elif rec_plan_obj.search_exist(cr, uid, [('model_id', '=', model_id), ('state', '=', 'running')]):
1407+ state = 'running'
1408+ else:
1409+ state = 'draft'
1410+ rec_models[state].append(model_id)
1411+ for model_state in rec_models:
1412+ if rec_models[model_state]:
1413+ update_rec_models = """
1414+ UPDATE account_model
1415+ SET state = %s
1416+ WHERE id IN %s;
1417+ """
1418+ cr.execute(update_rec_models, (model_state, tuple(rec_models[model_state])))
1419+ return True
1420+
1421 def us_7412_set_fy_closure_settings(self, cr, uid, *a, **b):
1422 """
1423 Sets the Fiscal Year Closure options depending on the OC.
1424
1425=== modified file 'bin/addons/msf_profile/usability.xml'
1426--- bin/addons/msf_profile/usability.xml 2012-11-06 14:18:56 +0000
1427+++ bin/addons/msf_profile/usability.xml 2020-08-07 12:54:52 +0000
1428@@ -7,7 +7,7 @@
1429 <!-- reorder existing ones -->
1430 <menuitem id="account.menu_finance_periodical_processing" name="Periodical Processing" parent="account.menu_finance" sequence="7" />
1431 <menuitem id="account.menu_finance_charts" name="Charts" parent="account.menu_finance" sequence="8"/>
1432- <menuitem name="Define Recurring Entries" action="account.action_subscription_form" id="account.menu_action_subscription_form" sequence="2" parent="account.menu_finance_recurrent_entries"/>
1433+ <menuitem name="Recurring Plan" action="account.action_subscription_form" id="account.menu_action_subscription_form" sequence="2" parent="account.menu_finance_recurrent_entries"/>
1434 <menuitem id="account.menu_finance_entries" name="Journal Entries" parent="account.menu_finance" sequence="10" />
1435 <menuitem id="account.menu_action_model_form" action="account.action_model_form" sequence="1" parent="account.menu_finance_recurrent_entries" />
1436 <menuitem id="account.menu_finance_accounting" name="Financial Accounting" parent="account.menu_finance_configuration" sequence="1"/>

Subscribers

People subscribed via source and target branches