from datetime import datetime
from operator import itemgetter
+from lxml import etree
+
import netsvc
-from osv import fields, osv
+from osv import fields, osv, orm
from tools.translate import _
import decimal_precision as dp
import tools
if context.get('company_id', False):
company_clause = " AND " +obj+".company_id = %s" % context.get('company_id', False)
if not context.get('fiscalyear', False):
- fiscalyear_ids = fiscalyear_obj.search(cr, uid, [('state', '=', 'draft')])
+ if context.get('all_fiscalyear', False):
+ #this option is needed by the aged balance report because otherwise, if we search only the draft ones, an open invoice of a closed fiscalyear won't be displayed
+ fiscalyear_ids = fiscalyear_obj.search(cr, uid, [])
+ else:
+ fiscalyear_ids = fiscalyear_obj.search(cr, uid, [('state', '=', 'draft')])
else:
#for initial balance as well as for normal query, we check only the selected FY because the best practice is to generate the FY opening entries
fiscalyear_ids = [context['fiscalyear']]
if context.get('date_from', False) and context.get('date_to', False):
if initial_bal:
- where_move_lines_by_date = " OR " +obj+".move_id IN (SELECT id FROM account_move WHERE date < '" +context['date_from']+"')"
+ where_move_lines_by_date = " AND " +obj+".move_id IN (SELECT id FROM account_move WHERE date < '" +context['date_from']+"')"
else:
where_move_lines_by_date = " AND " +obj+".move_id IN (SELECT id FROM account_move WHERE date >= '" +context['date_from']+"' AND date <= '"+context['date_to']+"')"
if state:
if state.lower() not in ['all']:
where_move_state= " AND "+obj+".move_id IN (SELECT id FROM account_move WHERE account_move.state = '"+state+"')"
-
if context.get('period_from', False) and context.get('period_to', False) and not context.get('periods', False):
if initial_bal:
period_company_id = fiscalperiod_obj.browse(cr, uid, context['period_from'], context=context).company_id.id
context['periods'] = fiscalperiod_obj.build_ctx_periods(cr, uid, context['period_from'], context['period_to'])
if context.get('periods', False):
if initial_bal:
- query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s) %s %s)" % (fiscalyear_clause, where_move_state, where_move_lines_by_date)
+ query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s)) %s %s" % (fiscalyear_clause, where_move_state, where_move_lines_by_date)
period_ids = fiscalperiod_obj.search(cr, uid, [('id', 'in', context['periods'])], order='date_start', limit=1)
if period_ids and period_ids[0]:
first_period = fiscalperiod_obj.browse(cr, uid, period_ids[0], context=context)
- # Find the old periods where date start of those periods less then Start period
- periods = fiscalperiod_obj.search(cr, uid, [('date_start', '<', first_period.date_start)])
- periods = ','.join([str(x) for x in periods])
- if periods:
- query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s) AND id IN (%s)) %s %s" % (fiscalyear_clause, periods, where_move_state, where_move_lines_by_date)
+ ids = ','.join([str(x) for x in context['periods']])
+ query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s) AND date_start <= '%s' AND id NOT IN (%s)) %s %s" % (fiscalyear_clause, first_period.date_start, ids, where_move_state, where_move_lines_by_date)
else:
ids = ','.join([str(x) for x in context['periods']])
query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s) AND id IN (%s)) %s %s" % (fiscalyear_clause, ids, where_move_state, where_move_lines_by_date)
else:
- query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s) %s %s)" % (fiscalyear_clause, where_move_state, where_move_lines_by_date)
+ query = obj+".state <> 'draft' AND "+obj+".period_id IN (SELECT id FROM account_period WHERE fiscalyear_id IN (%s)) %s %s" % (fiscalyear_clause, where_move_state, where_move_lines_by_date)
+
+ if initial_bal and not context.get('periods', False) and not where_move_lines_by_date:
+ #we didn't pass any filter in the context, and the initial balance can't be computed using only the fiscalyear otherwise entries will be summed twice
+ #so we have to invalidate this query
+ raise osv.except_osv(_('Warning !'),_("You haven't supplied enough argument to compute the initial balance"))
+
if context.get('journal_ids', False):
query += ' AND '+obj+'.journal_id IN (%s)' % ','.join(map(str, context['journal_ids']))
query += ' AND '+obj+'.account_id IN (%s)' % ','.join(map(str, child_ids))
query += company_clause
-
return query
+ def _amount_residual(self, cr, uid, ids, field_names, args, context=None):
+ """
+ This function returns the residual amount on a receivable or payable account.move.line.
+ By default, it returns an amount in the currency of this journal entry (maybe different
+ of the company currency), but if you pass 'residual_in_company_currency' = True in the
+ context then the returned amount will be in company currency.
+ """
+ res = {}
+ if context is None:
+ context = {}
+ cur_obj = self.pool.get('res.currency')
+ for move_line in self.browse(cr, uid, ids, context=context):
+ res[move_line.id] = {
+ 'amount_residual': 0.0,
+ 'amount_residual_currency': 0.0,
+ }
+
+ if move_line.reconcile_id:
+ continue
+ if not move_line.account_id.type in ('payable', 'receivable'):
+ #this function does not suport to be used on move lines not related to payable or receivable accounts
+ continue
+
+ if move_line.currency_id:
+ move_line_total = move_line.amount_currency
+ sign = move_line.amount_currency < 0 and -1 or 1
+ else:
+ move_line_total = move_line.debit - move_line.credit
+ sign = (move_line.debit - move_line.credit) < 0 and -1 or 1
+ line_total_in_company_currency = move_line.debit - move_line.credit
+ context_unreconciled = context.copy()
+ if move_line.reconcile_partial_id:
+ for payment_line in move_line.reconcile_partial_id.line_partial_ids:
+ if payment_line.id == move_line.id:
+ continue
+ if payment_line.currency_id and move_line.currency_id and payment_line.currency_id.id == move_line.currency_id.id:
+ move_line_total += payment_line.amount_currency
+ else:
+ if move_line.currency_id:
+ context_unreconciled.update({'date': payment_line.date})
+ amount_in_foreign_currency = cur_obj.compute(cr, uid, move_line.company_id.currency_id.id, move_line.currency_id.id, (payment_line.debit - payment_line.credit), round=False, context=context_unreconciled)
+ move_line_total += amount_in_foreign_currency
+ else:
+ move_line_total += (payment_line.debit - payment_line.credit)
+ line_total_in_company_currency += (payment_line.debit - payment_line.credit)
+
+ result = move_line_total
+ res[move_line.id]['amount_residual_currency'] = sign * (move_line.currency_id and self.pool.get('res.currency').round(cr, uid, move_line.currency_id, result) or result)
+ res[move_line.id]['amount_residual'] = sign * line_total_in_company_currency
+ return res
+
def default_get(self, cr, uid, fields, context=None):
data = self._default_get(cr, uid, fields, context=context)
for f in data.keys():
'credit': fields.float('Credit', digits_compute=dp.get_precision('Account')),
'account_id': fields.many2one('account.account', 'Account', required=True, ondelete="cascade", domain=[('type','<>','view'), ('type', '<>', 'closed')], select=2),
'move_id': fields.many2one('account.move', 'Move', ondelete="cascade", help="The move of this entry line.", select=2, required=True),
- 'narration': fields.related('move_id','narration', type='text', relation='account.move', string='Narration'),
+ 'narration': fields.related('move_id','narration', type='text', relation='account.move', string='Internal Note'),
'ref': fields.related('move_id', 'ref', string='Reference', type='char', size=64, store=True),
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1),
'reconcile_id': fields.many2one('account.move.reconcile', 'Reconcile', readonly=True, ondelete='set null', select=2),
'reconcile_partial_id': fields.many2one('account.move.reconcile', 'Partial Reconcile', readonly=True, ondelete='set null', select=2),
'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optional other currency if it is a multi-currency entry.", digits_compute=dp.get_precision('Account')),
+ 'amount_residual_currency': fields.function(_amount_residual, string='Residual Amount', multi="residual", help="The residual amount on a receivable or payable of a journal entry expressed in its currency (maybe different of the company currency)."),
+ 'amount_residual': fields.function(_amount_residual, string='Residual Amount', multi="residual", help="The residual amount on a receivable or payable of a journal entry expressed in the company currency."),
'currency_id': fields.many2one('res.currency', 'Currency', help="The optional other currency if it is a multi-currency entry."),
- 'period_id': fields.many2one('account.period', 'Period', required=True, select=2),
- 'journal_id': fields.many2one('account.journal', 'Journal', required=True, select=1),
+ 'journal_id': fields.related('move_id', 'journal_id', string='Journal', type='many2one', relation='account.journal', required=True, select=True, readonly=True,
+ store = {
+ 'account.move': (_get_move_lines, ['journal_id'], 20)
+ }),
+ 'period_id': fields.related('move_id', 'period_id', string='Period', type='many2one', relation='account.period', required=True, select=True, readonly=True,
+ store = {
+ 'account.move': (_get_move_lines, ['period_id'], 20)
+ }),
'blocked': fields.boolean('Litigation', help="You can check this box to mark this journal item as a litigation with the associated partner"),
'partner_id': fields.many2one('res.partner', 'Partner', select=1, ondelete='restrict'),
- 'date_maturity': fields.date('Due date', help="This field is used for payable and receivable journal entries. You can put the limit date for the payment of this line."),
- 'date': fields.related('move_id','date', string='Effective date', type='date', required=True,
+ 'date_maturity': fields.date('Due date', select=True ,help="This field is used for payable and receivable journal entries. You can put the limit date for the payment of this line."),
+ 'date': fields.related('move_id','date', string='Effective date', type='date', required=True, select=True,
store = {
'account.move': (_get_move_lines, ['date'], 20)
}),
- 'date_created': fields.date('Creation date'),
+ 'date_created': fields.date('Creation date', select=True),
'analytic_lines': fields.one2many('account.analytic.line', 'move_id', 'Analytic lines'),
- 'centralisation': fields.selection([('normal','Normal'),('credit','Credit Centralisation'),('debit','Debit Centralisation')], 'Centralisation', size=6),
- 'balance': fields.function(_balance, fnct_search=_balance_search, method=True, string='Balance'),
+ 'centralisation': fields.selection([('normal','Normal'),('credit','Credit Centralisation'),('debit','Debit Centralisation'),('currency','Currency Adjustment')], 'Centralisation', size=8),
+ 'balance': fields.function(_balance, fnct_search=_balance_search, string='Balance'),
'state': fields.selection([('draft','Unbalanced'), ('valid','Valid')], 'State', readonly=True,
help='When new move line is created the state will be \'Draft\'.\n* When all the payments are done it will be in \'Valid\' state.'),
'tax_code_id': fields.many2one('account.tax.code', 'Tax Account', help="The Account can either be a base tax code or a tax code account."),
'tax_amount': fields.float('Tax/Base Amount', digits_compute=dp.get_precision('Account'), select=True, help="If the Tax account is a tax code account, this field will contain the taxed amount.If the tax account is base tax code, "\
"this field will contain the basic amount(without tax)."),
- 'invoice': fields.function(_invoice, method=True, string='Invoice',
+ 'invoice': fields.function(_invoice, string='Invoice',
type='many2one', relation='account.invoice', fnct_search=_invoice_search),
'account_tax_id':fields.many2one('account.tax', 'Tax'),
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
- #TODO: remove this
- #'amount_taxed':fields.float("Taxed Amount", digits_compute=dp.get_precision('Account')),
'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True)
}
'state': 'draft',
'currency_id': _get_currency,
'journal_id': lambda self, cr, uid, c: c.get('journal_id', False),
+ 'credit': 0.0,
+ 'debit': 0.0,
'account_id': lambda self, cr, uid, c: c.get('account_id', False),
'period_id': lambda self, cr, uid, c: c.get('period_id', False),
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.move.line', context=c)
lines = self.browse(cr, uid, ids, context=context)
for l in lines:
if l.account_id.type == 'view':
- return False
+ raise osv.except_osv(_('Error :'), _('You can not create move line on view account %s %s') % (l.account_id.code, l.account_id.name))
return True
def _check_no_closed(self, cr, uid, ids, context=None):
lines = self.browse(cr, uid, ids, context=context)
for l in lines:
if l.account_id.type == 'closed':
- return False
+ raise osv.except_osv(_('Error :'), _('You can not create move line on closed account %s %s') % (l.account_id.code, l.account_id.name))
return True
def _check_company_id(self, cr, uid, ids, context=None):
return False
return True
- def _check_partner_id(self, cr, uid, ids, context=None):
- lines = self.browse(cr, uid, ids, context=context)
- for l in lines:
- if l.account_id.type in ('receivable', 'payable') and not l.partner_id:
- return False
+ def _check_date(self, cr, uid, ids, context=None):
+ for l in self.browse(cr, uid, ids, context=context):
+ if l.journal_id.allow_date:
+ if not time.strptime(l.date[:10],'%Y-%m-%d') >= time.strptime(l.period_id.date_start, '%Y-%m-%d') or not time.strptime(l.date[:10], '%Y-%m-%d') <= time.strptime(l.period_id.date_stop, '%Y-%m-%d'):
+ return False
+ return True
+
+ def _check_currency(self, cr, uid, ids, context=None):
+ for l in self.browse(cr, uid, ids, context=context):
+ if l.account_id.currency_id:
+ if not l.currency_id or not l.currency_id.id == l.account_id.currency_id.id:
+ return False
return True
_constraints = [
(_check_no_view, 'You can not create move line on view account.', ['account_id']),
(_check_no_closed, 'You can not create move line on closed account.', ['account_id']),
- (_check_company_id, 'Company must be same for its related account and period.',['company_id'] ),
- (_check_partner_id, 'You can not create move line on receivable/payable account without partner', ['account_id'] )
+ (_check_company_id, 'Company must be same for its related account and period.', ['company_id']),
+ (_check_date, 'The date of your Journal Entry is not in the defined period!', ['date']),
+ (_check_currency, 'The selected account of your Journal Entry must receive a value in its secondary currency', ['currency_id']),
]
#TODO: ONCHANGE_ACCOUNT_ID: set account_tax_id
id2 = part.property_account_receivable.id
if journal:
jt = journal_obj.browse(cr, uid, journal).type
- #FIXME: Bank and cash journal are such a journal we can not assume a account based on this 2 journals
- # Bank and cash journal can have a payment or receipt transaction, and in both type partner account
- # will not be same id payment then payable, and if receipt then receivable
- #if jt in ('sale', 'purchase_refund', 'bank', 'cash'):
if jt in ('sale', 'purchase_refund'):
val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id2)
- elif jt in ('purchase', 'sale_refund', 'expense', 'bank', 'cash'):
+ elif jt in ('purchase', 'sale_refund'):
val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id1)
+ elif jt in ('general', 'bank', 'cash'):
+ if part.customer:
+ val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id2)
+ elif part.supplier:
+ val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id1)
if val.get('account_id', False):
d = self.onchange_account_id(cr, uid, ids, val['account_id'])
val.update(d['value'])
)
return cr.fetchone()
- def reconcile_partial(self, cr, uid, ids, type='auto', context=None):
+ def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False):
move_rec_obj = self.pool.get('account.move.reconcile')
merges = []
unmerge = []
company_list.append(line.company_id.id)
for line in self.browse(cr, uid, ids, context=context):
+ if line.account_id.currency_id:
+ currency_id = line.account_id.currency_id
+ else:
+ currency_id = line.company_id.currency_id
if line.reconcile_id:
raise osv.except_osv(_('Warning'), _('Already Reconciled!'))
if line.reconcile_partial_id:
if not line2.reconcile_id:
if line2.id not in merges:
merges.append(line2.id)
- total += (line2.debit or 0.0) - (line2.credit or 0.0)
+ if line2.account_id.currency_id:
+ total += line2.amount_currency
+ else:
+ total += (line2.debit or 0.0) - (line2.credit or 0.0)
merges_rec.append(line.reconcile_partial_id.id)
else:
unmerge.append(line.id)
- total += (line.debit or 0.0) - (line.credit or 0.0)
-
- if not total:
- res = self.reconcile(cr, uid, merges+unmerge, context=context)
+ if line.account_id.currency_id:
+ total += line.amount_currency
+ else:
+ total += (line.debit or 0.0) - (line.credit or 0.0)
+ if self.pool.get('res.currency').is_zero(cr, uid, currency_id, total):
+ res = self.reconcile(cr, uid, merges+unmerge, context=context, writeoff_acc_id=writeoff_acc_id, writeoff_period_id=writeoff_period_id, writeoff_journal_id=writeoff_journal_id)
return res
r_id = move_rec_obj.create(cr, uid, {
'type': type,
if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \
(account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))):
if not writeoff_acc_id:
- raise osv.except_osv(_('Warning'), _('You have to provide an account for the write off entry !'))
+ raise osv.except_osv(_('Warning'), _('You have to provide an account for the write off/exchange difference entry !'))
if writeoff > 0:
debit = writeoff
credit = 0.0
libelle = context['comment']
else:
libelle = _('Write-Off')
+
+ cur_obj = self.pool.get('res.currency')
+ cur_id = False
+ amount_currency_writeoff = 0.0
+ if context.get('company_currency_id',False) != context.get('currency_id',False):
+ cur_id = context.get('currency_id',False)
+ for line in unrec_lines:
+ if line.currency_id and line.currency_id.id == context.get('currency_id',False):
+ amount_currency_writeoff += line.amount_currency
+ else:
+ tmp_amount = cur_obj.compute(cr, uid, line.account_id.company_id.currency_id.id, context.get('currency_id',False), abs(line.debit-line.credit), context={'date': line.date})
+ amount_currency_writeoff += (line.debit > 0) and tmp_amount or -tmp_amount
+
writeoff_lines = [
(0, 0, {
'name': libelle,
'account_id': account_id,
'date': date,
'partner_id': partner_id,
- 'currency_id': account.currency_id.id or False,
- 'amount_currency': account.currency_id.id and -currency or 0.0
+ 'currency_id': cur_id or (account.currency_id.id or False),
+ 'amount_currency': amount_currency_writeoff and -1 * amount_currency_writeoff or (account.currency_id.id and -1 * currency or 0.0)
}),
(0, 0, {
'name': libelle,
'account_id': writeoff_acc_id,
'analytic_account_id': context.get('analytic_id', False),
'date': date,
- 'partner_id': partner_id
+ 'partner_id': partner_id,
+ 'currency_id': cur_id or (account.currency_id.id or False),
+ 'amount_currency': amount_currency_writeoff and amount_currency_writeoff or (account.currency_id.id and currency or 0.0)
})
]
})
writeoff_line_ids = self.search(cr, uid, [('move_id', '=', writeoff_move_id), ('account_id', '=', account_id)])
+ if account_id == writeoff_acc_id:
+ writeoff_line_ids = [writeoff_line_ids[1]]
ids += writeoff_line_ids
r_id = move_rec_obj.create(cr, uid, {
if context.get('account_id', False):
cr.execute('SELECT code FROM account_account WHERE id = %s', (context['account_id'], ))
res = cr.fetchone()
- res = _('Entries: ')+ (res[0] or '')
+ if res:
+ res = _('Entries: ')+ (res[0] or '')
return res
if (not context.get('journal_id', False)) or (not context.get('period_id', False)):
return False
cr.execute('SELECT code FROM account_period WHERE id = %s', (context['period_id'], ))
p = cr.fetchone()[0] or ''
if j or p:
- return j+(p and (':'+p) or '')
+ return j + (p and (':' + p) or '')
return False
def onchange_date(self, cr, user, ids, date, context=None):
journal_pool = self.pool.get('account.journal')
if context is None:
context = {}
- result = super(osv.osv, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
+ result = super(account_move_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
if view_type != 'tree':
#Remove the toolbar from the form view
if view_type == 'form':
#Restrict the list of journal view in search view
if view_type == 'search' and result['fields'].get('journal_id', False):
result['fields']['journal_id']['selection'] = journal_pool.name_search(cr, uid, '', [], context=context)
+ ctx = context.copy()
+ #we add the refunds journal in the selection field of journal
+ if context.get('journal_type', False) == 'sale':
+ ctx.update({'journal_type': 'sale_refund'})
+ result['fields']['journal_id']['selection'] += journal_pool.name_search(cr, uid, '', [], context=ctx)
+ elif context.get('journal_type', False) == 'purchase':
+ ctx.update({'journal_type': 'purchase_refund'})
+ result['fields']['journal_id']['selection'] += journal_pool.name_search(cr, uid, '', [], context=ctx)
return result
if context.get('view_mode', False):
return result
fields = {}
flds = []
title = _("Accounting Entries") #self.view_header_get(cr, uid, view_id, view_type, context)
- xml = '''<?xml version="1.0"?>\n<tree string="%s" editable="top" refresh="5" on_write="on_create_write" colors="red:state==\'draft\';black:state==\'valid\'">\n\t''' % (title)
ids = journal_pool.search(cr, uid, [])
journals = journal_pool.browse(cr, uid, ids, context=context)
for field in journal.view_id.columns_id:
if not field.field in fields:
fields[field.field] = [journal.id]
- fld.append((field.field, field.sequence, field.name))
+ fld.append((field.field, field.sequence))
flds.append(field.field)
common_fields[field.field] = 1
else:
fields.get(field.field).append(journal.id)
common_fields[field.field] = common_fields[field.field] + 1
- fld.append(('period_id', 3, _('Period')))
- fld.append(('journal_id', 10, _('Journal')))
+ fld.append(('period_id', 3))
+ fld.append(('journal_id', 10))
flds.append('period_id')
flds.append('journal_id')
fields['period_id'] = all_journal
'tax_code_id': 50,
'move_id': 40,
}
- for field_it in fld:
- field = field_it[0]
+
+ document = etree.Element('tree', string=title, editable="top",
+ refresh="5", on_write="on_create_write",
+ colors="red:state=='draft';black:state=='valid'")
+ fields_get = self.fields_get(cr, uid, flds, context)
+ for field, _seq in fld:
if common_fields.get(field) == total:
fields.get(field).append(None)
-# if field=='state':
-# state = 'colors="red:state==\'draft\'"'
- attrs = []
+ # if field=='state':
+ # state = 'colors="red:state==\'draft\'"'
+ f = etree.SubElement(document, 'field', name=field)
+
if field == 'debit':
- attrs.append('sum = "%s"' % _("Total debit"))
+ f.set('sum', _("Total debit"))
elif field == 'credit':
- attrs.append('sum = "%s"' % _("Total credit"))
+ f.set('sum', _("Total credit"))
elif field == 'move_id':
- attrs.append('required = "False"')
+ f.set('required', 'False')
elif field == 'account_tax_id':
- attrs.append('domain="[(\'parent_id\', \'=\' ,False)]"')
- attrs.append("context=\"{'journal_id': journal_id}\"")
+ f.set('domain', "[('parent_id', '=' ,False)]")
+ f.set('context', "{'journal_id': journal_id}")
elif field == 'account_id' and journal.id:
- attrs.append('domain="[(\'journal_id\', \'=\', '+str(journal.id)+'),(\'type\',\'<>\',\'view\'), (\'type\',\'<>\',\'closed\')]" on_change="onchange_account_id(account_id, partner_id)"')
+ f.set('domain', "[('journal_id', '=', journal_id),('type','!=','view'), ('type','!=','closed')]")
+ f.set('on_change', 'onchange_account_id(account_id, partner_id)')
elif field == 'partner_id':
- attrs.append('on_change="onchange_partner_id(move_id, partner_id, account_id, debit, credit, date, journal_id)"')
+ f.set('on_change', 'onchange_partner_id(move_id, partner_id, account_id, debit, credit, date, journal_id)')
elif field == 'journal_id':
- attrs.append("context=\"{'journal_id': journal_id}\"")
+ f.set('context', "{'journal_id': journal_id}")
elif field == 'statement_id':
- attrs.append("domain=\"[('state', '!=', 'confirm'),('journal_id.type', '=', 'bank')]\"")
+ f.set('domain', "[('state', '!=', 'confirm'),('journal_id.type', '=', 'bank')]")
elif field == 'date':
- attrs.append('on_change="onchange_date(date)"')
+ f.set('on_change', 'onchange_date(date)')
elif field == 'analytic_account_id':
- attrs.append('''groups="analytic.group_analytic_accounting"''') # Currently it is not working due to framework problem may be ..
+ # Currently it is not working due to being executed by superclass's fields_view_get
+ # f.set('groups', 'analytic.group_analytic_accounting')
+ pass
if field in ('amount_currency', 'currency_id'):
- attrs.append('on_change="onchange_currency(account_id, amount_currency, currency_id, date, journal_id)"')
- attrs.append('''attrs="{'readonly': [('state', '=', 'valid')]}"''')
+ f.set('on_change', 'onchange_currency(account_id, amount_currency, currency_id, date, journal_id)')
+ f.set('attrs', "{'readonly': [('state', '=', 'valid')]}")
if field in widths:
- attrs.append('width="'+str(widths[field])+'"')
- attrs.append("invisible=\"context.get('visible_id') not in %s\"" % (fields.get(field)))
- xml += '''<field name="%s" %s/>\n''' % (field,' '.join(attrs))
+ f.set('width', str(widths[field]))
- xml += '''</tree>'''
- result['arch'] = xml
- result['fields'] = self.fields_get(cr, uid, flds, context)
+ if field in ('journal_id',):
+ f.set("invisible", "context.get('journal_id', False)")
+ elif field in ('period_id',):
+ f.set("invisible", "context.get('period_id', False)")
+
+ orm.setup_modifiers(f, fields_get[field], context=context,
+ in_tree_view=True)
+
+ result['arch'] = etree.tostring(document, pretty_print=True)
+ result['fields'] = fields_get
return result
def _check_moves(self, cr, uid, context=None):
move_obj = self.pool.get('account.move')
self._update_check(cr, uid, ids, context)
result = False
+ move_ids = set()
for line in self.browse(cr, uid, ids, context=context):
+ move_ids.add(line.move_id.id)
context['journal_id'] = line.journal_id.id
context['period_id'] = line.period_id.id
result = super(account_move_line, self).unlink(cr, uid, [line.id], context=context)
- if check:
- move_obj.validate(cr, uid, [line.move_id.id], context=context)
+ move_ids = list(move_ids)
+ if check and move_ids:
+ move_obj.validate(cr, uid, move_ids, context=context)
return result
- def _check_date(self, cr, uid, vals, context=None, check=True):
- if context is None:
- context = {}
- move_obj = self.pool.get('account.move')
- journal_obj = self.pool.get('account.journal')
- period_obj = self.pool.get('account.period')
- journal_id = False
- if 'date' in vals.keys():
- if 'journal_id' in vals and 'journal_id' not in context:
- journal_id = vals['journal_id']
- if 'period_id' in vals and 'period_id' not in context:
- period_id = vals['period_id']
- elif 'journal_id' not in context and 'move_id' in vals:
- if vals.get('move_id', False):
- m = move_obj.browse(cr, uid, vals['move_id'])
- journal_id = m.journal_id.id
- period_id = m.period_id.id
- else:
- journal_id = context.get('journal_id', False)
- period_id = context.get('period_id', False)
- if journal_id:
- journal = journal_obj.browse(cr, uid, journal_id, context=context)
- if journal.allow_date and period_id:
- period = period_obj.browse(cr, uid, period_id, context=context)
- if not time.strptime(vals['date'][:10],'%Y-%m-%d') >= time.strptime(period.date_start, '%Y-%m-%d') or not time.strptime(vals['date'][:10], '%Y-%m-%d') <= time.strptime(period.date_stop, '%Y-%m-%d'):
- raise osv.except_osv(_('Error'),_('The date of your Journal Entry is not in the defined period!'))
- else:
- return True
-
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
if context is None:
context={}
move_obj = self.pool.get('account.move')
account_obj = self.pool.get('account.account')
journal_obj = self.pool.get('account.journal')
+ if isinstance(ids, (int, long)):
+ ids = [ids]
if vals.get('account_tax_id', False):
raise osv.except_osv(_('Unable to change tax !'), _('You can not change the tax, you should remove and recreate lines !'))
- self._check_date(cr, uid, vals, context, check)
if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']:
raise osv.except_osv(_('Bad account!'), _('You can not use an inactive account!'))
if update_check:
def _update_check(self, cr, uid, ids, context=None):
done = {}
for line in self.browse(cr, uid, ids, context=context):
+ err_msg = _('Move name (id): %s (%s)') % (line.move_id.name, str(line.move_id.id))
if line.move_id.state <> 'draft' and (not line.journal_id.entry_posted):
- raise osv.except_osv(_('Error !'), _('You can not do this modification on a confirmed entry ! Please note that you can just change some non important fields !'))
+ raise osv.except_osv(_('Error !'), _('You can not do this modification on a confirmed entry ! Please note that you can just change some non important fields ! \n%s') % err_msg)
if line.reconcile_id:
- raise osv.except_osv(_('Error !'), _('You can not do this modification on a reconciled entry ! Please note that you can just change some non important fields !'))
+ raise osv.except_osv(_('Error !'), _('You can not do this modification on a reconciled entry ! Please note that you can just change some non important fields ! \n%s') % err_msg)
t = (line.journal_id.id, line.period_id.id)
if t not in done:
self._update_journal_check(cr, uid, line.journal_id.id, line.period_id.id, context)
company_id = self.pool.get('account.move').read(cr, uid, vals['move_id'], ['company_id']).get('company_id', False)
if company_id:
vals['company_id'] = company_id[0]
- self._check_date(cr, uid, vals, context, check)
if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']:
raise osv.except_osv(_('Bad account!'), _('You can not use an inactive account!'))
if 'journal_id' in vals:
m = move_obj.browse(cr, uid, vals['move_id'])
context['journal_id'] = m.journal_id.id
context['period_id'] = m.period_id.id
-
+ #we need to treat the case where a value is given in the context for period_id as a string
+ if 'period_id' not in context or not isinstance(context.get('period_id', ''), (int, long)):
+ period_candidate_ids = self.pool.get('account.period').name_search(cr, uid, name=context.get('period_id',''))
+ if len(period_candidate_ids) != 1:
+ raise osv.except_osv(_('Encoding error'), _('No period found or period given is ambigous.'))
+ context['period_id'] = period_candidate_ids[0][0]
+ if not context.get('journal_id', False) and context.get('search_default_journal_id', False):
+ context['journal_id'] = context.get('search_default_journal_id')
self._update_journal_check(cr, uid, context['journal_id'], context['period_id'], context)
move_id = vals.get('move_id', False)
journal = journal_obj.browse(cr, uid, context['journal_id'], context=context)
vals['move_id'] = res[0]
if not vals.get('move_id', False):
if journal.sequence_id:
- #name = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id)
+ #name = self.pool.get('ir.sequence').next_by_id(cr, uid, journal.sequence_id.id)
v = {
'date': vals.get('date', time.strftime('%Y-%m-%d')),
'period_id': context['period_id'],
move_id = move_obj.create(cr, uid, v, context)
vals['move_id'] = move_id
else:
- raise osv.except_osv(_('No piece number !'), _('Can not create an automatic sequence for this piece !\n\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
+ raise osv.except_osv(_('No piece number !'), _('Can not create an automatic sequence for this piece!\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
ok = not (journal.type_control_ids or journal.account_control_ids)
if ('account_id' in vals):
account = account_obj.browse(cr, uid, vals['account_id'], context=context)
break
# Automatically convert in the account's secondary currency if there is one and
# the provided values were not already multi-currency
- if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
+ if account.currency_id and (vals.get('amount_currency', False) is False) and account.currency_id.id != account.company_id.currency_id.id:
vals['currency_id'] = account.currency_id.id
ctx = {}
if 'date' in vals:
vals['amount_currency'] = cur_obj.compute(cr, uid, account.company_id.currency_id.id,
account.currency_id.id, vals.get('debit', 0.0)-vals.get('credit', 0.0), context=ctx)
if not ok:
- raise osv.except_osv(_('Bad account !'), _('You can not use this general account in this journal !'))
+ raise osv.except_osv(_('Bad account !'), _('You can not use this general account in this journal, check the tab \'Entry Controls\' on the related journal !'))
if vals.get('analytic_account_id',False):
if journal.analytic_journal_id:
'user_id': uid
})]
- result = super(osv.osv, self).create(cr, uid, vals, context=context)
+ result = super(account_move_line, self).create(cr, uid, vals, context=context)
# CREATE Taxes
if vals.get('account_tax_id', False):
tax_id = tax_obj.browse(cr, uid, vals['account_tax_id'])
total = vals['debit'] - vals['credit']
- if journal.refund_journal:
+ if journal.type in ('purchase_refund', 'sale_refund'):
base_code = 'ref_base_code_id'
tax_code = 'ref_tax_code_id'
account_id = 'account_paid_id'
base_sign = 'base_sign'
tax_sign = 'tax_sign'
tmp_cnt = 0
- for tax in tax_obj.compute_all(cr, uid, [tax_id], total, 1.00).get('taxes'):
+ for tax in tax_obj.compute_all(cr, uid, [tax_id], total, 1.00, force_excluded=True).get('taxes'):
#create the base movement
if tmp_cnt == 0:
if tax[base_code]:
else:
data = {
'move_id': vals['move_id'],
- 'journal_id': vals['journal_id'],
- 'period_id': vals['period_id'],
'name': tools.ustr(vals['name'] or '') + ' ' + tools.ustr(tax['name'] or ''),
'date': vals['date'],
'partner_id': vals.get('partner_id',False),
#create the VAT movement
data = {
'move_id': vals['move_id'],
- 'journal_id': vals['journal_id'],
- 'period_id': vals['period_id'],
'name': tools.ustr(vals['name'] or '') + ' ' + tools.ustr(tax['name'] or ''),
'date': vals['date'],
'partner_id': vals.get('partner_id',False),
account_move_line()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: