1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP - Import operations model 347 engine
5
# Copyright (C) 2009 Asr Oss. All Rights Reserved
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU Affero General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU Affero General Public License for more details.
18
# You should have received a copy of the GNU Affero General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
24
Create FYC entries wizards
26
__author__ = """Borja López Soilán (Pexego) - borja@kami.es"""
28
from tools.translate import _
35
import decimal_precision as dp
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" auto_refresh="1">
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 round(abs(amount), pool.get('decimal.precision').precision_get(cr, uid, 'Account')) > 0:
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
context.update({'fiscalyear': fiscalyear_id, 'periods': period_ids})
359
# Find its children accounts (recursively)
360
# FIXME: _get_children_and_consol is a protected member of account_account but the OpenERP code base uses it like this :(
361
child_ids = pool.get('account.account')._get_children_and_consol(cr, uid, [account_map.source_account_id.id], ctx)
363
# For each children account. (Notice the context filter! the computed balanced is based on this filter)
364
for account in pool.get('account.account').browse(cr, uid, child_ids, ctx):
365
# Check if the children account needs to (and can) be closed
366
# Note: We currently ignore the close_method (account.user_type.close_method)
367
# and always do a balance close.
368
if account.type != 'view':
369
# Compute the balance for the account (uses the previous browse context filter)
370
balance = account.balance
371
# Check if the balance is greater than the limit
372
if round(abs(balance), pool.get('decimal.precision').precision_get(cr, uid, 'Account')) > 0:
374
# Add a new line to the move
377
'account_id': account.id,
378
'debit': balance<0 and -balance,
379
'credit': balance>0 and balance,
382
'period_id': period_id,
383
'journal_id': journal_id,
386
# Update the dest account total (with the inverse of the balance)
387
if account_map.dest_account_id:
388
dest_accounts_totals[account_map.dest_account_id.id] -= balance
390
data['process_task_progress'] = (accounts_done * 90.0) / total_accounts
395
for dest_account_id in dest_accounts_totals.keys():
396
balance = dest_accounts_totals[dest_account_id]
398
'account_id': dest_account_id,
399
'debit': balance<0 and -balance,
400
'credit': balance>0 and balance,
403
'period_id': period_id,
404
'journal_id': journal_id,
406
data['process_task_progress'] = 95.0
409
# Finally create the account move with all the lines (if needed)
412
move_id = pool.get('account.move').create(cr, uid, {
415
'period_id': period_id,
416
'journal_id': journal_id,
417
'line_id': [(0,0,line) for line in move_lines],
421
data['process_task_progress'] = 99.0
424
# Save the reference to the created account move into the fyc object
426
if operation == 'loss_and_profit':
427
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, [fyc.id], { 'loss_and_profit_move_id': move_id })
428
elif operation == 'net_loss_and_profit':
429
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, [fyc.id], { 'net_loss_and_profit_move_id': move_id })
430
elif operation == 'close':
431
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, [fyc.id], { 'closing_move_id': move_id })
433
assert operation in ('loss_and_profit', 'net_loss_and_profit', 'close'), "The operation must be a supported one"
435
data['process_task_progress'] = 100.0
439
def create_opening_move(self, cr, uid, operation, fyc, data, context):
441
Create an opening move (based on the closing one)
443
pool = pooler.get_pool(cr.dbname)
444
data['process_task_progress'] = 0.0
454
# Depending on the operation we will use one or other closing move
455
# as the base for the opening move.
456
# Note: Yes, currently only one 'closing' move exists,
457
# but I want this to be extensible :)
459
if operation == 'open':
460
closing_move = fyc.closing_move_id
461
# Require the user to have performed the closing operation
462
if not (closing_move and closing_move.id):
463
raise wizard.except_wizard(_('UserError'), _("The closing move must exist to create the opening one"))
464
if not closing_move.line_id:
465
raise wizard.except_wizard(_('UserError'), _("The closing move shouldn't be empty"))
467
# Get the values for the lines
469
if not fyc.o_description:
470
raise wizard.except_wizard(_('UserError'), _("The opening description must be defined"))
472
raise wizard.except_wizard(_('UserError'), _("The opening date must be defined"))
473
if not (fyc.o_period_id and fyc.o_period_id.id):
474
raise wizard.except_wizard(_('UserError'), _("The opening period must be defined"))
475
if not (fyc.o_journal_id and fyc.o_journal_id.id):
476
raise wizard.except_wizard(_('UserError'), _("The opening journal must be defined"))
477
description = fyc.o_description
479
period_id = fyc.o_period_id.id
480
journal_id = fyc.o_journal_id.id
482
assert operation in ('open'), "The operation must be a supported one"
485
# Read the lines from the closing move, and append the inverse lines
486
# to the opening move lines.
488
total_accounts = len(closing_move.line_id)
490
for line in closing_move.line_id:
492
'account_id': line.account_id.id,
493
'debit': line.credit,
494
'credit': line.debit,
497
'period_id': period_id,
498
'journal_id': journal_id,
501
data['process_task_progress'] = (accounts_done * 90.0) / total_accounts
504
# Finally create the account move with all the lines (if needed)
507
move_id = pool.get('account.move').create(cr, uid, {
510
'period_id': period_id,
511
'journal_id': journal_id,
512
'line_id': [(0,0,line) for line in move_lines],
516
data['process_task_progress'] = 99.0
519
# Save the reference to the created account move into the fyc object
521
if operation == 'open':
522
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, [fyc.id], { 'opening_move_id': move_id })
524
assert operation in ('open'), "The operation must be a supported one"
526
data['process_task_progress'] = 100.0
530
def remove_move(self, cr, uid, operation, fyc, data, context):
532
Remove a account move (L&P, NL&P, Closing or Opening move)
534
pool = pooler.get_pool(cr.dbname)
535
data['process_task_progress'] = 0.0
538
# Depending on the operation we will delete one or other move
541
if operation == 'loss_and_profit':
542
move = fyc.loss_and_profit_move_id
543
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, fyc.id, { 'loss_and_profit_move_id': None })
544
elif operation == 'net_loss_and_profit':
545
move = fyc.net_loss_and_profit_move_id
546
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, fyc.id, { 'net_loss_and_profit_move_id': None })
547
elif operation == 'close':
548
move = fyc.closing_move_id
549
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, fyc.id, { 'closing_move_id': None })
550
elif operation == 'open':
551
move = fyc.opening_move_id
552
pool.get('account_fiscal_year_closing.fyc').write(cr, uid, fyc.id, { 'opening_move_id': None })
554
assert operation in ('loss_and_profit', 'net_loss_and_profit', 'close', 'open'), "The operation must be a supported one"
555
data['process_task_progress'] = 15.0
557
assert move and move.id, "The move to delete must be defined"
560
# Unreconcile the move if needed
563
for line in move.line_id:
564
if line.reconcile_id and (line.reconcile_id.id not in reconcile_ids):
565
reconcile_ids.append(line.reconcile_id.id)
566
if line.reconcile_partial_id and (line.reconcile_partial_id.id not in reconcile_ids):
567
reconcile_ids.append(line.reconcile_partial_id.id)
569
pool.get('account.move.reconcile').unlink(cr, uid, reconcile_ids, context)
570
data['process_task_progress'] = 30.0
573
# Remove the move after changing it's state to draft
575
pool.get('account.move').write(cr, uid, [move.id], {'state': 'draft'}, context)
576
pool.get('account.move').unlink(cr, uid, [move.id], context)
578
data['process_task_progress'] = 100.0
582
############################################################################
584
############################################################################
586
def _init_choice(self, cr, uid, data, context):
588
Choice-like action that checks whether the operations must be run
593
if context.get('cancel_mode'):
594
data['cancel_mode'] = True
597
data['cancel_mode'] = False
601
def _run(self, db_name, uid, data, context=None):
603
Creates / removes FYC entries
605
data['process_progress'] = 0
606
data['process_task_progress'] = 0
607
data['process_task'] = None
609
conn = sql_db.db_connect(db_name)
611
pool = pooler.get_pool(cr.dbname)
614
# If the wizard is in cancel mode, run the objects cancel action
615
# to let it undo the confirmation action, before running the wizard.
617
if data.get('cancel_mode'):
618
wf_service = netsvc.LocalService("workflow")
619
wf_service.trg_validate(uid, 'account_fiscal_year_closing.fyc', data['id'], 'cancel', cr)
622
fyc = pool.get('account_fiscal_year_closing.fyc').browse(cr, uid, data['id'], context=context)
625
# Calculate the operations to perform (needed to calculate the progress)
629
if fyc.check_invalid_period_moves:
630
total_operations += 1
631
if fyc.check_draft_moves:
632
total_operations += 1
633
if fyc.check_unbalanced_moves:
634
total_operations += 1
635
if (fyc.create_loss_and_profit and not fyc.loss_and_profit_move_id) \
636
or ((not fyc.create_loss_and_profit) and fyc.loss_and_profit_move_id):
637
total_operations += 1
638
if (fyc.create_net_loss_and_profit and not fyc.net_loss_and_profit_move_id) \
639
or ((not fyc.create_net_loss_and_profit) and fyc.net_loss_and_profit_move_id):
640
total_operations += 1
641
if (fyc.create_closing and not fyc.closing_move_id) \
642
or ((not fyc.create_closing) and fyc.closing_move_id):
643
total_operations += 1
644
if (fyc.create_opening and not fyc.opening_move_id) \
645
or ((not fyc.create_opening) and fyc.opening_move_id):
646
total_operations += 1
648
if total_operations > 0:
651
# Check for invalid period moves if needed
653
if fyc.check_invalid_period_moves:
654
data['process_task'] = 'Check invalid period/date moves'
655
self._check_invalid_period_moves(cr, uid, fyc, data, context)
657
data['process_progress'] = (operations_done * 100.0) / total_operations
660
# Check for draft moves if needed
662
if fyc.check_draft_moves:
663
data['process_task'] = 'Check draft moves'
664
self._check_draft_moves(cr, uid, fyc, data, context)
666
data['process_progress'] = (operations_done * 100.0) / total_operations
669
# Check for unbalanced moves if needed
671
if fyc.check_unbalanced_moves:
672
data['process_task'] = 'Check unbalanced moves'
673
self._check_unbalanced_moves(cr, uid, fyc, data, context)
675
data['process_progress'] = (operations_done * 100.0) / total_operations
678
# Create L&P move if needed
680
if fyc.create_loss_and_profit and not fyc.loss_and_profit_move_id:
681
data['process_task'] = 'Create L&P move'
682
self.create_closing_move(cr, uid, 'loss_and_profit', fyc, data, context)
684
data['process_progress'] = (operations_done * 100.0) / total_operations
686
# Remove the L&P move if needed
688
if (not fyc.create_loss_and_profit) and fyc.loss_and_profit_move_id:
689
data['process_task'] = 'Remove L&P move'
690
self.remove_move(cr, uid, 'loss_and_profit', fyc, data, context)
692
data['process_progress'] = (operations_done * 100.0) / total_operations
694
# Refresh the cached fyc object
695
fyc = pool.get('account_fiscal_year_closing.fyc').browse(cr, uid, data['id'], context=context)
699
# Create the Net L&P move if needed
701
if fyc.create_net_loss_and_profit and not fyc.net_loss_and_profit_move_id:
702
data['process_task'] = 'Create NL&P move'
703
self.create_closing_move(cr, uid, 'net_loss_and_profit', fyc, data, context)
705
data['process_progress'] = (operations_done * 100.0) / total_operations
707
# Remove the Net L&P move if needed
709
if (not fyc.create_net_loss_and_profit) and fyc.net_loss_and_profit_move_id:
710
data['process_task'] = 'Remove NL&P move'
711
self.remove_move(cr, uid, 'net_loss_and_profit', fyc, data, context)
713
data['process_progress'] = (operations_done * 100.0) / total_operations
715
# Refresh the cached fyc object
716
fyc = pool.get('account_fiscal_year_closing.fyc').browse(cr, uid, data['id'], context=context)
720
# Create the closing move if needed
722
if fyc.create_closing and not fyc.closing_move_id:
723
data['process_task'] = 'Create closing move'
724
self.create_closing_move(cr, uid, 'close', fyc, data, context)
726
data['process_progress'] = (operations_done * 100.0) / total_operations
728
# Remove the closing move if needed
730
if (not fyc.create_closing) and fyc.closing_move_id:
731
data['process_task'] = 'Remove closing move'
732
self.remove_move(cr, uid, 'close', fyc, data, context)
734
data['process_progress'] = (operations_done * 100.0) / total_operations
736
# Refresh the cached fyc object
737
fyc = pool.get('account_fiscal_year_closing.fyc').browse(cr, uid, data['id'], context=context)
741
# Create the opening move if needed
743
if fyc.create_opening and not fyc.opening_move_id:
744
data['process_task'] = 'Create opening move'
745
self.create_opening_move(cr, uid, 'open', fyc, data, context)
747
data['process_progress'] = (operations_done * 100.0) / total_operations
749
# Remove the opening move if needed
751
if (not fyc.create_opening) and fyc.opening_move_id:
752
data['process_task'] = 'Remove opening move'
753
self.remove_move(cr, uid, 'open', fyc, data, context)
755
data['process_progress'] = (operations_done * 100.0) / total_operations
758
# Set the as done (if not in cancel_mode)
760
if not data.get('cancel_mode'):
761
wf_service = netsvc.LocalService("workflow")
762
wf_service.trg_validate(uid, 'account_fiscal_year_closing.fyc', fyc.id, 'run', cr)
764
data['process_progress'] = 100
766
except Exception, ex:
767
data['process_exception'] = ex
772
data['process_done'] = True
776
def _run_in_background_choice(self, cr, uid, data, context):
778
Choice-like action that runs the process on background,
779
waiting for it to end or timeout.
781
if not data.get('process_thread'):
782
# Run the calculation in background
783
data['process_done'] = False
784
data['process_exception'] = None
785
data['process_thread'] = threading.Thread(target=self._run, args=(cr.dbname, uid, data, context))
786
data['process_thread'].start()
788
# Wait up some seconds seconds for the task to end.
791
while not data['process_done'] and time_left > 0:
792
time_left = time_left - 1
794
message = "Fiscal year closing progress: %s%% (%s: %s%%)" % (data.get('process_progress'), data.get('process_task'), data.get('process_task_progress'))
795
netsvc.Logger().notifyChannel('fyc', netsvc.LOG_DEBUG, message)
797
# Check if we are done
799
if data['process_done']:
800
if data['process_exception']:
801
return 'show_exception'
808
def _progress_action(self, cr, uid, data, context):
810
Action that gets the current progress
813
'task_progress': data['process_task_progress'],
814
'progress': data['process_progress']
817
def _show_exception_action(self, cr, uid, data, context):
819
Action that gets the calculation exception text
822
if data.get('process_exception'):
823
if isinstance(data['process_exception'], wizard.except_wizard):
824
exception_text = data['process_exception'].value
827
exception_text = unicode(data['process_exception'])
829
exception_text = str(data['process_exception'])
830
return { 'exception_text': exception_text }
832
############################################################################
834
############################################################################
839
'result': {'type': 'choice', 'next_state': _init_choice}
843
'result': {'type':'form', 'arch': _init_run_form, 'fields': {}, 'state':[('end', 'Cancel', 'gtk-cancel', True), ('run', 'Run', 'gtk-apply', True)]}
847
'result': {'type':'form', 'arch': _init_cancel_form, 'fields': {}, 'state':[('end', 'Cancel', 'gtk-cancel', True), ('run', 'Run', 'gtk-apply', True)]}
851
'result': {'type': 'choice', 'next_state': _run_in_background_choice}
854
'actions': [_progress_action],
855
'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)]}
859
'result': {'type': 'form', 'arch': _done_form, 'fields': {}, 'state':[('end','Done', 'gtk-ok', True)]}
862
'actions': [_show_exception_action],
863
'result': {'type': 'form', 'arch': _show_exception_form, 'fields': _show_exception_fields, 'state':[('end','Done', 'gtk-ok', True)]}
868
wizard_run('account_fiscal_year_closing.wizard_run')
871
class wizard_cancel(wizard_run):
873
Wizard to remove the FYC entries.
876
def _init_choice(self, cr, uid, data, context):
878
Choice-like action that checks whether the operations must be run
879
or canceled. => Always cancel on wizard_cancel.
881
data['cancel_mode'] = True
884
states = wizard_run.states.copy()
888
'result': {'type': 'choice', 'next_state': _init_choice}
892
wizard_cancel('account_fiscal_year_closing.wizard_cancel')