1
# -*- coding: utf-8 -*-
2
# -*- encoding: utf-8 -*-
3
##############################################################################
5
# OpenERP - Import operations model 347 engine
6
# Copyright (C) 2009 Asr Oss. All Rights Reserved
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation, either version 3 of the License, or
12
# (at your option) any later version.
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
19
# You should have received a copy of the GNU General Public License
20
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
##############################################################################
25
Create FYC entries wizards
27
__author__ = """Borja López Soilán (Pexego) - borjals@pexego.es"""
29
from tools.translate import _
36
from tools import config
38
class wizard_run(wizard.interface):
40
Wizard to create the FYC entries.
43
############################################################################
45
############################################################################
47
_init_run_form = """<?xml version="1.0" encoding="utf-8"?>
48
<form string="Fiscal Year Closing" colspan="4" width="400">
49
<label string="This wizard will perform the selected operations." colspan="4"/>
50
<label string="" colspan="4"/>
51
<label string="It will create account moves for the operations you selected, skipping those already created." colspan="4"/>
52
<label string="Non-selected operations will be canceled." colspan="4"/>
55
_init_cancel_form = """<?xml version="1.0" encoding="utf-8"?>
56
<form string="Fiscal Year Closing" colspan="4" width="400">
57
<label string="This wizard will cancel the selected operations." colspan="4"/>
58
<label string="" colspan="4"/>
59
<label string="It will remove the previously generated account moves." colspan="4"/>
60
<label string="Closed periods, and the fiscal year, will be reopened." colspan="4"/>
63
_progress_form = '''<?xml version="1.0"?>
64
<form string="Fiscal Year Closing - Working" colspan="4" width="400">
65
<label string="The process may take a while." colspan="4"/>
66
<label string="" colspan="4"/>
67
<field name="task_progress" widget="progressbar" colspan="4"/>
68
<field name="progress" widget="progressbar" colspan="4"/>
72
'task_progress': { 'string': 'Task Progress', 'type':'float' },
73
'progress': { 'string': 'Total Progress', 'type':'float' },
77
_done_form = """<?xml version="1.0" encoding="utf-8"?>
78
<form string="Fiscal Year Closing - Done" colspan="4" width="400">
79
<label string="The selected operations have been performed sucessfuly." colspan="4"/>
80
<label string="" colspan="4"/>
83
_show_exception_form = """<?xml version="1.0" encoding="utf-8"?>
84
<form string="Fiscal Year Closing - Error!" colspan="4" width="400">
85
<label string="Error: One of the selected operations has failed!" colspan="4"/>
86
<label string="" colspan="4"/>
87
<separator string="Details"/>
88
<field name="exception_text" colspan="4" nolabel="1"/>
91
_show_exception_fields = {
92
'exception_text': {'string': 'Exception', 'type':'text' },
95
############################################################################
97
############################################################################
99
def _check_invalid_period_moves(self, cr, uid, fyc, data, context):
101
Checks for moves with invalid period on the fiscal year that is being closed
103
pool = pooler.get_pool(cr.dbname)
104
data['process_task_progress'] = 0.0
106
# Consider all the periods of the fiscal year.
107
period_ids = [period.id for period in fyc.closing_fiscalyear_id.period_ids]
109
# Find moves on the closing fiscal year with dates of previous years
110
account_move_ids = pool.get('account.move').search(cr, uid, [
111
('period_id', 'in', period_ids),
112
('date', '<', fyc.closing_fiscalyear_id.date_start),
115
# Find moves on the closing fiscal year with dates of next years
116
account_move_ids.extend(pool.get('account.move').search(cr, uid, [
117
('period_id', 'in', period_ids),
118
('date', '>', fyc.closing_fiscalyear_id.date_stop),
121
# Find moves not on the closing fiscal year with dates on its year
122
account_move_ids.extend(pool.get('account.move').search(cr, uid, [
123
('period_id', 'not in', period_ids),
124
('date', '>=', fyc.closing_fiscalyear_id.date_start),
125
('date', '<=', fyc.closing_fiscalyear_id.date_stop),
129
# If one or more moves where found, raise an exception
131
if len(account_move_ids):
132
invalid_period_moves = pool.get('account.move').browse(cr, uid, account_move_ids, context)
133
str_invalid_period_moves = '\n'.join(['id: %s, date: %s, number: %s, ref: %s' % (move.id, move.date, move.name, move.ref) for move in invalid_period_moves])
134
raise wizard.except_wizard(_('Error'), _('One or more moves with invalid period or date found on the fiscal year: \n%s') % str_invalid_period_moves)
136
data['process_task_progress'] = 100.0
139
def _check_draft_moves(self, cr, uid, fyc, data, context):
141
Checks for draft moves on the fiscal year that is being closed
143
pool = pooler.get_pool(cr.dbname)
144
data['process_task_progress'] = 0.0
147
# Consider all the periods of the fiscal year *BUT* the L&P,
148
# Net L&P and the Closing one.
151
for period in fyc.closing_fiscalyear_id.period_ids:
152
if period.id != fyc.lp_period_id.id \
153
and period.id != fyc.nlp_period_id.id \
154
and period.id != fyc.c_period_id.id:
155
period_ids.append(period.id)
157
# Find the moves on the given periods
158
account_move_ids = pool.get('account.move').search(cr, uid, [
159
('period_id', 'in', period_ids),
160
('state', '=', 'draft'),
164
# If one or more draft moves where found, raise an exception
166
if len(account_move_ids):
167
draft_moves = pool.get('account.move').browse(cr, uid, account_move_ids, context)
168
str_draft_moves = '\n'.join(['id: %s, date: %s, number: %s, ref: %s' % (move.id, move.date, move.name, move.ref) for move in draft_moves])
169
raise wizard.except_wizard(_('Error'), _('One or more draft moves found: \n%s') % str_draft_moves)
171
data['process_task_progress'] = 100.0
174
def _check_unbalanced_moves(self, cr, uid, fyc, data, context):
176
Checks for unbalanced moves on the fiscal year that is being closed
178
pool = pooler.get_pool(cr.dbname)
179
data['process_task_progress'] = 0.0
182
# Consider all the periods of the fiscal year *BUT* the L&P,
183
# Net L&P and the Closing one.
186
for period in fyc.closing_fiscalyear_id.period_ids:
187
if period.id != fyc.lp_period_id.id \
188
and period.id != fyc.nlp_period_id.id \
189
and period.id != fyc.c_period_id.id:
190
period_ids.append(period.id)
192
# Find the moves on the given periods
193
account_move_ids = pool.get('account.move').search(cr, uid, [
194
('period_id', 'in', period_ids),
195
('state', '!=', 'draft'),
199
# For each found move, check it
201
unbalanced_moves = []
202
total_accounts = len(account_move_ids)
204
for move in pool.get('account.move').browse(cr, uid, account_move_ids, context):
206
for line in move.line_id:
207
amount += (line.debit - line.credit)
209
if abs(amount) > 0.5 * 10 ** -int(config['price_accuracy']):
210
unbalanced_moves.append(move)
213
data['process_task_progress'] = (accounts_done * 90.0) / total_accounts
216
# If one or more unbalanced moves where found, raise an exception
218
if len(unbalanced_moves):
219
str_unbalanced_moves = '\n'.join(['id: %s, date: %s, number: %s, ref: %s' % (move.id, move.date, move.name, move.ref) for move in unbalanced_moves])
220
raise wizard.except_wizard(_('Error'), _('One or more unbalanced moves found: \n%s') % str_unbalanced_moves)
222
data['process_task_progress'] = 100.0
226
############################################################################
227
# CLOSING/OPENING OPERATIONS
228
############################################################################
230
def create_closing_move(self, cr, uid, operation, fyc, data, context):
232
Create a closing move (L&P, NL&P or Closing move).
234
pool = pooler.get_pool(cr.dbname)
236
data['process_task_progress'] = 0.0
239
dest_accounts_totals = {}
241
account_mapping_ids = []
246
fiscalyear_id = fyc.closing_fiscalyear_id.id
249
# Depending on the operation we will use different data
251
if operation == 'loss_and_profit':
253
# Consider all the periods of the fiscal year *BUT* the L&P,
254
# Net L&P and the Closing one.
256
for period in fyc.closing_fiscalyear_id.period_ids:
257
if period.id != fyc.lp_period_id.id \
258
and period.id != fyc.nlp_period_id.id \
259
and period.id != fyc.c_period_id.id:
260
period_ids.append(period.id)
262
# Set the accounts to use
264
account_mapping_ids = fyc.lp_account_mapping_ids
265
for account_map in account_mapping_ids:
266
if not account_map.dest_account_id:
267
raise wizard.except_wizard(_('UserError'), _("The L&P account mappings are not properly configured: %s") % account_map.name)
270
# Get the values for the lines
272
if not fyc.lp_description:
273
raise wizard.except_wizard(_('UserError'), _("The L&P description must be defined"))
275
raise wizard.except_wizard(_('UserError'), _("The L&P date must be defined"))
276
if not (fyc.lp_period_id and fyc.lp_period_id.id):
277
raise wizard.except_wizard(_('UserError'), _("The L&P period must be defined"))
278
if not (fyc.lp_journal_id and fyc.lp_journal_id.id):
279
raise wizard.except_wizard(_('UserError'), _("The L&P journal must be defined"))
280
description = fyc.lp_description
282
period_id = fyc.lp_period_id.id
283
journal_id = fyc.lp_journal_id.id
284
elif operation == 'net_loss_and_profit':
286
# Consider all the periods of the fiscal year *BUT* the
287
# Net L&P and the Closing one.
289
for period in fyc.closing_fiscalyear_id.period_ids:
290
if period.id != fyc.nlp_period_id.id \
291
and period.id != fyc.c_period_id.id:
292
period_ids.append(period.id)
294
# Set the accounts to use
296
account_mapping_ids = fyc.nlp_account_mapping_ids
297
for account_map in account_mapping_ids:
298
if not account_map.dest_account_id:
299
raise wizard.except_wizard(_('UserError'), _("The Net L&P account mappings are not properly configured: %s") % account_map.name)
301
# Get the values for the lines
303
if not fyc.nlp_description:
304
raise wizard.except_wizard(_('UserError'), _("The Net L&P description must be defined"))
306
raise wizard.except_wizard(_('UserError'), _("The Net L&P date must be defined"))
307
if not (fyc.nlp_period_id and fyc.nlp_period_id.id):
308
raise wizard.except_wizard(_('UserError'), _("The Net L&P period must be defined"))
309
if not (fyc.nlp_journal_id and fyc.nlp_journal_id.id):
310
raise wizard.except_wizard(_('UserError'), _("The Net L&P journal must be defined"))
311
description = fyc.nlp_description
313
period_id = fyc.nlp_period_id.id
314
journal_id = fyc.nlp_journal_id.id
315
elif operation == 'close':
316
# Require the user to have performed the L&P operation
317
if not (fyc.loss_and_profit_move_id and fyc.loss_and_profit_move_id.id):
318
raise wizard.except_wizard(_('UserError'), _("The L&P move must exist before creating the closing one"))
320
# Consider all the periods of the fiscal year *BUT* the Closing one.
322
for period in fyc.closing_fiscalyear_id.period_ids:
323
if period.id != fyc.c_period_id.id:
324
period_ids.append(period.id)
325
# Set the accounts to use
326
account_mapping_ids = fyc.c_account_mapping_ids
328
# Get the values for the lines
330
if not fyc.c_description:
331
raise wizard.except_wizard(_('UserError'), _("The closing description must be defined"))
333
raise wizard.except_wizard(_('UserError'), _("The closing date must be defined"))
334
if not (fyc.c_period_id and fyc.c_period_id.id):
335
raise wizard.except_wizard(_('UserError'), _("The closing period must be defined"))
336
if not (fyc.c_journal_id and fyc.c_journal_id.id):
337
raise wizard.except_wizard(_('UserError'), _("The closing journal must be defined"))
338
description = fyc.c_description
340
period_id = fyc.c_period_id.id
341
journal_id = fyc.c_journal_id.id
343
assert operation in ('loss_and_profit', 'net_loss_and_profit', 'close'), "The operation must be a supported one"
347
# For each (parent) account in the mapping list
349
total_accounts = len(account_mapping_ids)
351
for account_map in account_mapping_ids:
352
# Init (if needed) the dictionary that will store the totals for the dest accounts
353
if account_map.dest_account_id:
354
dest_accounts_totals[account_map.dest_account_id.id] = dest_accounts_totals.get(account_map.dest_account_id.id, 0)
356
# Find its children accounts (recursively)
357
# FIXME: _get_children_and_consol is a protected member of account_account but the OpenERP code base uses it like this :(
358
child_ids = pool.get('account.account')._get_children_and_consol(cr, uid, [account_map.source_account_id.id], context)
360
# For each children account. (Notice the context filter! the computed balanced is based on this filter)
361
for account in pool.get('account.account').browse(cr, uid, child_ids, context={'fiscalyear': fiscalyear_id, 'periods': period_ids}):
362
# Check if the children account needs to (and can) be closed
363
# Note: We currently ignore the close_method (account.user_type.close_method)
364
# and always do a balance close.
365
if account.type != 'view':
366
# Compute the balance for the account (uses the previous browse context filter)
367
balance = account.balance
368
# Check if the balance is greater than the limit
369
if abs(balance) >= 0.5 * 10 ** -int(config['price_accuracy']):
371
# Add a new line to the move
374
'account_id': account.id,
375
'debit': balance<0 and -balance,
376
'credit': balance>0 and balance,
379
'period_id': period_id,
380
'journal_id': journal_id,
383
# Update the dest account total (with the inverse of the balance)
384
if account_map.dest_account_id:
385
dest_accounts_totals[account_map.dest_account_id.id] -= balance
387
data['process_task_progress'] = (accounts_done * 90.0) / total_accounts
392
for dest_account_id in dest_accounts_totals.keys():
393
balance = dest_accounts_totals[dest_account_id]
395
'account_id': dest_account_id,
396
'debit': balance<0 and -balance,
397
'credit': balance>0 and balance,
400
'period_id': period_id,
401
'journal_id': journal_id,
403
data['process_task_progress'] = 95.0
406
# Finally create the account move with all the lines (if needed)
409
move_id = pool.get('account.move').create(cr, uid, {
412
'period_id': period_id,
413
'journal_id': journal_id,
414
'line_id': [(0,0,line) for line in move_lines],
418
data['process_task_progress'] = 99.0
421
# Save the reference to the created account move into the fyc object
423
if operation == 'loss_and_profit':
424
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, [fyc.id], { 'loss_and_profit_move_id': move_id })
425
elif operation == 'net_loss_and_profit':
426
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, [fyc.id], { 'net_loss_and_profit_move_id': move_id })
427
elif operation == 'close':
428
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, [fyc.id], { 'closing_move_id': move_id })
430
assert operation in ('loss_and_profit', 'net_loss_and_profit', 'close'), "The operation must be a supported one"
432
data['process_task_progress'] = 100.0
436
def create_opening_move(self, cr, uid, operation, fyc, data, context):
438
Create an opening move (based on the closing one)
440
pool = pooler.get_pool(cr.dbname)
441
data['process_task_progress'] = 0.0
451
# Depending on the operation we will use one or other closing move
452
# as the base for the opening move.
453
# Note: Yes, currently only one 'closing' move exists,
454
# but I want this to be extensible :)
456
if operation == 'open':
457
closing_move = fyc.closing_move_id
458
# Require the user to have performed the closing operation
459
if not (closing_move and closing_move.id):
460
raise wizard.except_wizard(_('UserError'), _("The closing move must exist to create the opening one"))
461
if not closing_move.line_id:
462
raise wizard.except_wizard(_('UserError'), _("The closing move shouldn't be empty"))
464
# Get the values for the lines
466
if not fyc.o_description:
467
raise wizard.except_wizard(_('UserError'), _("The opening description must be defined"))
469
raise wizard.except_wizard(_('UserError'), _("The opening date must be defined"))
470
if not (fyc.o_period_id and fyc.o_period_id.id):
471
raise wizard.except_wizard(_('UserError'), _("The opening period must be defined"))
472
if not (fyc.o_journal_id and fyc.o_journal_id.id):
473
raise wizard.except_wizard(_('UserError'), _("The opening journal must be defined"))
474
description = fyc.o_description
476
period_id = fyc.o_period_id.id
477
journal_id = fyc.o_journal_id.id
479
assert operation in ('open'), "The operation must be a supported one"
482
# Read the lines from the closing move, and append the inverse lines
483
# to the opening move lines.
485
total_accounts = len(closing_move.line_id)
487
for line in closing_move.line_id:
489
'account_id': line.account_id.id,
490
'debit': line.credit,
491
'credit': line.debit,
494
'period_id': period_id,
495
'journal_id': journal_id,
498
data['process_task_progress'] = (accounts_done * 90.0) / total_accounts
501
# Finally create the account move with all the lines (if needed)
504
move_id = pool.get('account.move').create(cr, uid, {
507
'period_id': period_id,
508
'journal_id': journal_id,
509
'line_id': [(0,0,line) for line in move_lines],
513
data['process_task_progress'] = 99.0
516
# Save the reference to the created account move into the fyc object
518
if operation == 'open':
519
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, [fyc.id], { 'opening_move_id': move_id })
521
assert operation in ('open'), "The operation must be a supported one"
523
data['process_task_progress'] = 100.0
527
def remove_move(self, cr, uid, operation, fyc, data, context):
529
Remove a account move (L&P, NL&P, Closing or Opening move)
531
pool = pooler.get_pool(cr.dbname)
532
data['process_task_progress'] = 0.0
535
# Depending on the operation we will delete one or other move
538
if operation == 'loss_and_profit':
539
move = fyc.loss_and_profit_move_id
540
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, fyc.id, { 'loss_and_profit_move_id': None })
541
elif operation == 'net_loss_and_profit':
542
move = fyc.net_loss_and_profit_move_id
543
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, fyc.id, { 'net_loss_and_profit_move_id': None })
544
elif operation == 'close':
545
move = fyc.closing_move_id
546
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, fyc.id, { 'closing_move_id': None })
547
elif operation == 'open':
548
move = fyc.opening_move_id
549
pool.get('l10n_es_cierre_ejercicio.fyc').write(cr, uid, fyc.id, { 'opening_move_id': None })
551
assert operation in ('loss_and_profit', 'net_loss_and_profit', 'close', 'open'), "The operation must be a supported one"
552
data['process_task_progress'] = 15.0
554
assert move and move.id, "The move to delete must be defined"
557
# Unreconcile the move if needed
560
for line in move.line_id:
561
if line.reconcile_id and (line.reconcile_id.id not in reconcile_ids):
562
reconcile_ids.append(line.reconcile_id.id)
563
if line.reconcile_partial_id and (line.reconcile_partial_id.id not in reconcile_ids):
564
reconcile_ids.append(line.reconcile_partial_id.id)
566
pool.get('account.move.reconcile').unlink(cr, uid, reconcile_ids, context)
567
data['process_task_progress'] = 30.0
570
# Remove the move after changing it's state to draft
572
pool.get('account.move').write(cr, uid, [move.id], {'state': 'draft'}, context)
573
pool.get('account.move').unlink(cr, uid, [move.id], context)
575
data['process_task_progress'] = 100.0
579
############################################################################
581
############################################################################
583
def _init_choice(self, cr, uid, data, context):
585
Choice-like action that checks whether the operations must be run
590
if context.get('cancel_mode'):
591
data['cancel_mode'] = True
594
data['cancel_mode'] = False
598
def _run(self, db_name, uid, data, context=None):
600
Creates / removes FYC entries
602
data['process_progress'] = 0
603
data['process_task_progress'] = 0
604
data['process_task'] = None
606
conn = sql_db.db_connect(db_name)
608
pool = pooler.get_pool(cr.dbname)
611
# If the wizard is in cancel mode, run the objects cancel action
612
# to let it undo the confirmation action, before running the wizard.
614
if data.get('cancel_mode'):
615
wf_service = netsvc.LocalService("workflow")
616
wf_service.trg_validate(uid, 'l10n_es_cierre_ejercicio.fyc', data['id'], 'cancel', cr)
619
fyc = pool.get('l10n_es_cierre_ejercicio.fyc').browse(cr, uid, data['id'], context=context)
622
# Calculate the operations to perform (needed to calculate the progress)
626
if fyc.check_invalid_period_moves:
627
total_operations += 1
628
if fyc.check_draft_moves:
629
total_operations += 1
630
if fyc.check_unbalanced_moves:
631
total_operations += 1
632
if (fyc.create_loss_and_profit and not fyc.loss_and_profit_move_id) \
633
or ((not fyc.create_loss_and_profit) and fyc.loss_and_profit_move_id):
634
total_operations += 1
635
if (fyc.create_net_loss_and_profit and not fyc.net_loss_and_profit_move_id) \
636
or ((not fyc.create_net_loss_and_profit) and fyc.net_loss_and_profit_move_id):
637
total_operations += 1
638
if (fyc.create_closing and not fyc.closing_move_id) \
639
or ((not fyc.create_closing) and fyc.closing_move_id):
640
total_operations += 1
641
if (fyc.create_opening and not fyc.opening_move_id) \
642
or ((not fyc.create_opening) and fyc.opening_move_id):
643
total_operations += 1
645
if total_operations > 0:
647
# Check for invalid period moves if needed
649
if fyc.check_invalid_period_moves:
650
data['process_task'] = 'Check invalid period/date moves'
651
self._check_invalid_period_moves(cr, uid, fyc, data, context)
653
data['process_progress'] = (operations_done * 100.0) / total_operations
656
# Check for draft moves if needed
658
if fyc.check_draft_moves:
659
data['process_task'] = 'Check draft moves'
660
self._check_draft_moves(cr, uid, fyc, data, context)
662
data['process_progress'] = (operations_done * 100.0) / total_operations
665
# Check for unbalanced moves if needed
667
if fyc.check_unbalanced_moves:
668
data['process_task'] = 'Check unbalanced moves'
669
self._check_unbalanced_moves(cr, uid, fyc, data, context)
671
data['process_progress'] = (operations_done * 100.0) / total_operations
674
# Create L&P move if needed
676
if fyc.create_loss_and_profit and not fyc.loss_and_profit_move_id:
677
data['process_task'] = 'Create L&P move'
678
self.create_closing_move(cr, uid, 'loss_and_profit', fyc, data, context)
680
data['process_progress'] = (operations_done * 100.0) / total_operations
682
# Remove the L&P move if needed
684
if (not fyc.create_loss_and_profit) and fyc.loss_and_profit_move_id:
685
data['process_task'] = 'Remove L&P move'
686
self.remove_move(cr, uid, 'loss_and_profit', fyc, data, context)
688
data['process_progress'] = (operations_done * 100.0) / total_operations
690
# Refresh the cached fyc object
691
fyc = pool.get('l10n_es_cierre_ejercicio.fyc').browse(cr, uid, data['id'], context=context)
695
# Create the Net L&P move if needed
697
if fyc.create_net_loss_and_profit and not fyc.net_loss_and_profit_move_id:
698
data['process_task'] = 'Create NL&P move'
699
self.create_closing_move(cr, uid, 'net_loss_and_profit', fyc, data, context)
701
data['process_progress'] = (operations_done * 100.0) / total_operations
703
# Remove the Net L&P move if needed
705
if (not fyc.create_net_loss_and_profit) and fyc.net_loss_and_profit_move_id:
706
data['process_task'] = 'Remove NL&P move'
707
self.remove_move(cr, uid, 'net_loss_and_profit', fyc, data, context)
709
data['process_progress'] = (operations_done * 100.0) / total_operations
711
# Refresh the cached fyc object
712
fyc = pool.get('l10n_es_cierre_ejercicio.fyc').browse(cr, uid, data['id'], context=context)
716
# Create the closing move if needed
718
if fyc.create_closing and not fyc.closing_move_id:
719
data['process_task'] = 'Create closing move'
720
self.create_closing_move(cr, uid, 'close', fyc, data, context)
722
data['process_progress'] = (operations_done * 100.0) / total_operations
724
# Remove the closing move if needed
726
if (not fyc.create_closing) and fyc.closing_move_id:
727
data['process_task'] = 'Remove closing move'
728
self.remove_move(cr, uid, 'close', fyc, data, context)
730
data['process_progress'] = (operations_done * 100.0) / total_operations
732
# Refresh the cached fyc object
733
fyc = pool.get('l10n_es_cierre_ejercicio.fyc').browse(cr, uid, data['id'], context=context)
737
# Create the opening move if needed
739
if fyc.create_opening and not fyc.opening_move_id:
740
data['process_task'] = 'Create opening move'
741
self.create_opening_move(cr, uid, 'open', fyc, data, context)
743
data['process_progress'] = (operations_done * 100.0) / total_operations
745
# Remove the opening move if needed
747
if (not fyc.create_opening) and fyc.opening_move_id:
748
data['process_task'] = 'Remove opening move'
749
self.remove_move(cr, uid, 'open', fyc, data, context)
751
data['process_progress'] = (operations_done * 100.0) / total_operations
754
# Set the as done (if not in cancel_mode)
756
if not data.get('cancel_mode'):
757
wf_service = netsvc.LocalService("workflow")
758
wf_service.trg_validate(uid, 'l10n_es_cierre_ejercicio.fyc', fyc.id, 'run', cr)
760
data['process_progress'] = 100
762
except Exception, ex:
763
data['process_exception'] = ex
768
data['process_done'] = True
772
def _run_in_background_choice(self, cr, uid, data, context):
774
Choice-like action that runs the process on background,
775
waiting for it to end or timeout.
777
if not data.get('process_thread'):
778
# Run the calculation in background
779
data['process_done'] = False
780
data['process_exception'] = None
781
data['process_thread'] = threading.Thread(target=self._run, args=(cr.dbname, uid, data, context))
782
data['process_thread'].start()
784
# Wait up some seconds seconds for the task to end.
787
while not data['process_done'] and time_left > 0:
788
time_left = time_left - 1
790
message = "Fiscal year closing progress: %s%% (%s: %s%%)" % (data.get('process_progress'), data.get('process_task'), data.get('process_task_progress'))
791
netsvc.Logger().notifyChannel('fyc', netsvc.LOG_DEBUG, message)
793
# Check if we are done
795
if data['process_done']:
796
if data['process_exception']:
797
return 'show_exception'
804
def _progress_action(self, cr, uid, data, context):
806
Action that gets the current progress
809
'task_progress': data['process_task_progress'],
810
'progress': data['process_progress']
813
def _show_exception_action(self, cr, uid, data, context):
815
Action that gets the calculation exception text
818
if data.get('process_exception'):
819
if isinstance(data['process_exception'], wizard.except_wizard):
820
exception_text = data['process_exception'].value
823
exception_text = unicode(data['process_exception'])
825
exception_text = str(data['process_exception'])
826
return { 'exception_text': exception_text }
828
############################################################################
830
############################################################################
835
'result': {'type': 'choice', 'next_state': _init_choice}
839
'result': {'type':'form', 'arch': _init_run_form, 'fields': {}, 'state':[('end', 'Cancel', 'gtk-cancel', True), ('run', 'Run', 'gtk-apply', True)]}
843
'result': {'type':'form', 'arch': _init_cancel_form, 'fields': {}, 'state':[('end', 'Cancel', 'gtk-cancel', True), ('run', 'Run', 'gtk-apply', True)]}
847
'result': {'type': 'choice', 'next_state': _run_in_background_choice}
850
'actions': [_progress_action],
851
'result': {'type': 'form', 'arch': _progress_form, 'fields': _progress_fields, 'state':[('end','Close (continues in background)', 'gtk-cancel', True),('run','Keep waiting', 'gtk-go-forward', True)]}
855
'result': {'type': 'form', 'arch': _done_form, 'fields': {}, 'state':[('end','Done', 'gtk-ok', True)]}
858
'actions': [_show_exception_action],
859
'result': {'type': 'form', 'arch': _show_exception_form, 'fields': _show_exception_fields, 'state':[('end','Done', 'gtk-ok', True)]}
864
wizard_run('l10n_es_cierre_ejercicio.wizard_run')
867
class wizard_cancel(wizard_run):
869
Wizard to remove the FYC entries.
872
def _init_choice(self, cr, uid, data, context):
874
Choice-like action that checks whether the operations must be run
875
or canceled. => Always cancel on wizard_cancel.
877
data['cancel_mode'] = True
880
states = wizard_run.states.copy()
884
'result': {'type': 'choice', 'next_state': _init_choice}
888
wizard_cancel('l10n_es_cierre_ejercicio.wizard_cancel')