##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
_name = "account.payment.term"
_description = "Payment Term"
_columns = {
- 'name': fields.char('Payment Term', size=32, translate=True, required=True),
+ 'name': fields.char('Payment Term', size=64, translate=True, required=True),
'active': fields.boolean('Active'),
'note': fields.text('Description', translate=True),
'line_ids': fields.one2many('account.payment.term.line', 'payment_id', 'Terms'),
'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the payment term lines from the lowest sequences to the higher ones"),
'value': fields.selection([('procent','Percent'),('balance','Balance'),('fixed','Fixed Amount')], 'Value',required=True),
'value_amount': fields.float('Value Amount'),
- 'days': fields.integer('Number of Days',required=True, help="Number of days to add before computation of the day of month."),
- 'days2': fields.integer('Day of the Month',required=True, help="Day of the month, set -1 for the last day of the current month. If it's positive, it gives the day of the next month. Set 0 for net days (otherwise it's based on the end of the month)."),
+ 'days': fields.integer('Number of Days',required=True, help="Number of days to add before computation of the day of month." \
+ "If Date=15/01, Number of Days=22, Day of Month=-1, then the due date is 28/02."),
+ 'days2': fields.integer('Day of the Month',required=True, help="Day of the month, set -1 for the last day of the current month. If it's positive, it gives the day of the next month. Set 0 for net days (otherwise it's based on the beginning of the month)."),
'payment_id': fields.many2one('account.payment.term','Payment Term', required=True, select=True),
}
_defaults = {
_name = "account.account"
_description = "Account"
_parent_store = True
+ _parent_order = 'length(code),code'
def search(self, cr, uid, args, offset=0, limit=None, order=None,
context=None, count=False):
args[pos] = ('id','in',ids1)
pos+=1
- if context and context.has_key('consolidate_childs'): #add concolidated childs of accounts
+ if context and context.has_key('consolidate_childs'): #add consolidated childs of accounts
ids = super(account_account,self).search(cr, uid, args, offset, limit,
order, context=context, count=count)
for consolidate_child in self.browse(cr, uid, context['account_id']).child_consol_ids:
def _get_children_and_consol(self, cr, uid, ids, context={}):
#this function search for all the children and all consolidated children (recursively) of the given account ids
- res = self.search(cr, uid, [('parent_id', 'child_of', ids)])
- for id in res:
- this = self.browse(cr, uid, id, context)
- for child in this.child_consol_ids:
- if child.id not in res:
- res.append(child.id)
- if len(res) != len(ids):
- return self._get_children_and_consol(cr, uid, res, context)
- return res
+ ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)], context=context)
+ ids3 = []
+ for rec in self.browse(cr, uid, ids2, context=context):
+ for child in rec.child_consol_ids:
+ ids3.append(child.id)
+ if ids3:
+ ids3 = self._get_children_and_consol(cr, uid, ids3, context)
+ return ids2+ids3
def __compute(self, cr, uid, ids, field_names, arg, context={}, query=''):
#compute the balance/debit/credit accordingly to the value of field_name for the given account ids
mapping = {
- 'balance': "COALESCE(SUM(l.debit) - SUM(l.credit), 0) as balance ",
+ 'balance': "COALESCE(SUM(l.debit),0) - COALESCE(SUM(l.credit), 0) as balance ",
'debit': "COALESCE(SUM(l.debit), 0) as debit ",
'credit': "COALESCE(SUM(l.credit), 0) as credit "
}
'check_history': fields.boolean('Display History',
help="Check this box if you want to print all entries when printing the General Ledger, "\
"otherwise it will only print its balance."),
- 'merge_invoice': fields.boolean('Merge Invoice Entries',help="Check this box if you want that all lines of "\
- "a customer or supplier invoice using this account are created in one line only"),
}
def _default_company(self, cr, uid, context={}):
'account_control_ids': fields.many2many('account.account', 'account_account_type_rel', 'journal_id','account_id', 'Account', domain=[('type','<>','view'), ('type', '<>', 'closed')]),
'active': fields.boolean('Active'),
- 'view_id': fields.many2one('account.journal.view', 'View', required=True, help="Gives the view used when writing or browsing entries in this journal. The view tell Tiny ERP which fields should be visible, required or readonly and in which order. You can create your own view for a faster encoding in each journal."),
- 'default_credit_account_id': fields.many2one('account.account', 'Default Credit Account'),
- 'default_debit_account_id': fields.many2one('account.account', 'Default Debit Account'),
- 'centralisation': fields.boolean('Centralised counterpart', help="Check this box if you want that each entry doesn't create a counterpart but share the same counterpart for each entry of this journal."),
+ 'view_id': fields.many2one('account.journal.view', 'View', required=True, help="Gives the view used when writing or browsing entries in this journal. The view tell Open ERP which fields should be visible, required or readonly and in which order. You can create your own view for a faster encoding in each journal."),
+ 'default_credit_account_id': fields.many2one('account.account', 'Default Credit Account', domain="[('type','!=','view')]"),
+ 'default_debit_account_id': fields.many2one('account.account', 'Default Debit Account', domain="[('type','!=','view')]"),
+ 'centralisation': fields.boolean('Centralised counterpart', help="Check this box if you want that each entry doesn't create a counterpart but share the same counterpart for each entry of this journal. This is used in fiscal year closing."),
'update_posted': fields.boolean('Allow Cancelling Entries'),
+ 'group_invoice_lines': fields.boolean('Group invoice lines', help="If this box is cheked, the system will try to group the accouting lines when generating them from invoices."),
'sequence_id': fields.many2one('ir.sequence', 'Entry Sequence', help="The sequence gives the display order for a list of journals", required=True),
'user_id': fields.many2one('res.users', 'User', help="The responsible user of this journal"),
'groups_id': fields.many2many('res.groups', 'account_journal_group_rel', 'journal_id', 'group_id', 'Groups'),
'currency': fields.many2one('res.currency', 'Currency', help='The currency used to enter statement'),
'entry_posted': fields.boolean('Skip \'Draft\' State for Created Entries', help='Check this box if you don\'t want that new account moves pass through the \'draft\' state and goes direclty to the \'posted state\' without any manual validation.'),
'company_id': fields.related('default_credit_account_id','company_id',type='many2one', relation="res.company", string="Company"),
+ 'fy_seq_id': fields.one2many('fiscalyear.seq', 'journal_id', 'Sequences'),
}
_defaults = {
_columns = {
'name': fields.char('Fiscal Year', size=64, required=True),
'code': fields.char('Code', size=6, required=True),
+ 'company_id': fields.many2one('res.company', 'Company',
+ help="Keep empty if the fiscal year belongs to several companies."),
'date_start': fields.date('Start date', required=True),
'date_stop': fields.date('End date', required=True),
'period_ids': fields.one2many('account.period', 'fiscalyear_id', 'Periods'),
_columns = {
'name': fields.char('Period Name', size=64, required=True),
'code': fields.char('Code', size=12),
+ 'special': fields.boolean('Opening/Closing Period', size=12,
+ help="These periods can overlap."),
'date_start': fields.date('Start of period', required=True, states={'done':[('readonly',True)]}),
'date_stop': fields.date('End of period', required=True, states={'done':[('readonly',True)]}),
'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year', required=True, states={'done':[('readonly',True)]}, select=True),
}
_order = "date_start"
- def _check_duration(self,cr,uid,ids):
+ def _check_duration(self,cr,uid,ids,context={}):
obj_period=self.browse(cr,uid,ids[0])
if obj_period.date_stop < obj_period.date_start:
return False
return True
- def _check_year_limit(self,cr,uid,ids):
- obj_period=self.browse(cr,uid,ids[0])
- if obj_period.fiscalyear_id.date_stop < obj_period.date_stop or obj_period.fiscalyear_id.date_stop < obj_period.date_start or obj_period.fiscalyear_id.date_start > obj_period.date_start or obj_period.fiscalyear_id.date_start > obj_period.date_stop:
- return False
+ def _check_year_limit(self,cr,uid,ids,context={}):
+ for obj_period in self.browse(cr,uid,ids):
+ if obj_period.special:
+ continue
+ if obj_period.fiscalyear_id.date_stop < obj_period.date_stop or obj_period.fiscalyear_id.date_stop < obj_period.date_start or obj_period.fiscalyear_id.date_start > obj_period.date_start or obj_period.fiscalyear_id.date_start > obj_period.date_stop:
+ return False
+
+ pids = self.search(cr, uid, [('date_stop','>=',obj_period.date_start),('date_start','<=',obj_period.date_stop),('special','=',False),('id','<>',obj_period.id)])
+ for period in self.browse(cr, uid, pids):
+ if period.fiscalyear_id.company_id.id==obj_period.fiscalyear_id.company_id.id:
+ return False
return True
_constraints = [
(_check_duration, 'Error ! The date duration of the Period(s) is invalid. ', ['date_stop']),
- (_check_year_limit, 'Error ! The date duration of the Period(s) should be within the limit of the Fiscal year. ', ['date_stop'])
+ (_check_year_limit, 'Invalid period ! Some periods overlap or the date duration is not in the limit of the fiscal year. ', ['date_stop'])
]
def next(self, cr, uid, period, step, context={}):
if role.name=='Period':
mode = 'draft'
for id in ids:
- cr.execute('update account_journal_period set state=%s where period_id=%d', (mode, id))
- cr.execute('update account_period set state=%s where id=%d', (mode, id))
+ cr.execute('update account_journal_period set state=%s where period_id=%s', (mode, id))
+ cr.execute('update account_period set state=%s where id=%s', (mode, id))
return True
account_period()
def _check(self, cr, uid, ids, context={}):
for obj in self.browse(cr, uid, ids, context):
- cr.execute('select * from account_move_line where journal_id=%d and period_id=%d limit 1', (obj.journal_id.id, obj.period_id.id))
+ cr.execute('select * from account_move_line where journal_id=%s and period_id=%s limit 1', (obj.journal_id.id, obj.period_id.id))
res = cr.fetchall()
if res:
raise osv.except_osv(_('Error !'), _('You can not modify/delete a journal with entries for this period !'))
_inherit = "account.fiscalyear"
_description = "Fiscal Year"
_columns = {
- 'start_journal_period_id':fields.many2one('account.journal.period','New Entries Journal'),
'end_journal_period_id':fields.many2one('account.journal.period','End of Year Entries Journal', readonly=True),
}
class account_move(osv.osv):
_name = "account.move"
_description = "Account Entry"
+ _order = 'id desc'
def name_get(self, cursor, user, ids, context=None):
if not len(ids):
return result
_columns = {
- 'name': fields.char('Entry Number', size=64, required=True),
+ 'name': fields.char('Number', size=64, required=True),
'ref': fields.char('Ref', size=64),
'period_id': fields.many2one('account.period', 'Period', required=True, states={'posted':[('readonly',True)]}),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, states={'posted':[('readonly',True)]}),
'state': fields.selection([('draft','Draft'), ('posted','Posted')], 'Status', required=True, readonly=True),
'line_id': fields.one2many('account.move.line', 'move_id', 'Entries', states={'posted':[('readonly',True)]}),
'to_check': fields.boolean('To Be Verified'),
- 'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store=True),
- 'amount': fields.function(_amount_compute, method=True, string='Amount', digits=(16,2), store=True),
+ 'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner"),
+ 'amount': fields.function(_amount_compute, method=True, string='Amount', digits=(16,2)),
+ 'date': fields.date('Date', required=True),
'type': fields.selection([
('pay_voucher','Cash Payment'),
('bank_pay_voucher','Bank Payment'),
'state': lambda *a: 'draft',
'period_id': _get_period,
'type' : lambda *a : 'journal_voucher',
+ 'date': lambda *a:time.strftime('%Y-%m-%d'),
}
def _check_centralisation(self, cursor, user, ids):
def button_cancel(self, cr, uid, ids, context={}):
for line in self.browse(cr, uid, ids, context):
if not line.journal_id.update_posted:
- raise osv.except_osv(_('Error !'), _('You can not modify a posted entry of this journal !'))
+ raise osv.except_osv(_('Error !'), _('You can not modify a posted entry of this journal !\nYou should mark the journal to allow canceling entries.'))
if len(ids):
cr.execute('update account_move set state=%s where id in ('+','.join(map(str,ids))+')', ('draft',))
return True
context['journal_id'] = move.journal_id.id
context['period_id'] = move.period_id.id
self.pool.get('account.move.line')._update_check(cr, uid, line_ids, context)
+ self.pool.get('account.move.line').unlink(cr, uid, line_ids, context=context)
toremove.append(move.id)
result = super(account_move, self).unlink(cr, uid, toremove, context)
return result
# find the first line of this move with the current mode
# or create it if it doesn't exist
- cr.execute('select id from account_move_line where move_id=%d and centralisation=%s limit 1', (move.id, mode))
+ cr.execute('select id from account_move_line where move_id=%s and centralisation=%s limit 1', (move.id, mode))
res = cr.fetchone()
if res:
line_id = res[0]
# find the first line of this move with the other mode
# so that we can exclude it from our calculation
- cr.execute('select id from account_move_line where move_id=%d and centralisation=%s limit 1', (move.id, mode2))
+ cr.execute('select id from account_move_line where move_id=%s and centralisation=%s limit 1', (move.id, mode2))
res = cr.fetchone()
if res:
line_id2 = res[0]
else:
line_id2 = 0
- cr.execute('select sum('+mode+') from account_move_line where move_id=%d and id<>%d', (move.id, line_id2))
+ cr.execute('select sum('+mode+') from account_move_line where move_id=%s and id<>%s', (move.id, line_id2))
result = cr.fetchone()[0] or 0.0
- cr.execute('update account_move_line set '+mode2+'=%f where id=%d', (result, line_id))
+ cr.execute('update account_move_line set '+mode2+'=%s where id=%s', (result, line_id))
return True
#
def validate(self, cr, uid, ids, context={}):
ok = True
for move in self.browse(cr, uid, ids, context):
+ #unlink analytic lines on move_lines
+ for obj_line in move.line_id:
+ for obj in obj_line.analytic_lines:
+ self.pool.get('account.analytic.line').unlink(cr,uid,obj.id)
+
journal = move.journal_id
amount = 0
line_ids = []
'state': 'draft'
}, context, check=False)
ok = False
+ if ok:
+ list_ids = []
+ for tmp in move.line_id:
+ list_ids.append(tmp.id)
+ self.pool.get('account.move.line').create_analytic_lines(cr, uid, list_ids, context)
return ok
account_move()
res[record.id] = round(_rec_get(record), 2)
return res
+ def _sum_year(self, cr, uid, ids, name, args, context):
+ if 'fiscalyear_id' in context and context['fiscalyear_id']:
+ fiscalyear_id = context['fiscalyear_id']
+ else:
+ fiscalyear_id = self.pool.get('account.fiscalyear').find(cr, uid, exception=False)
+ where = ''
+ if fiscalyear_id:
+ pids = map(lambda x: str(x.id), self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id).period_ids)
+ if pids:
+ where = ' and period_id in (' + (','.join(pids))+')'
+ return self._sum(cr, uid, ids, name, args, context,
+ where=where)
+
def _sum_period(self, cr, uid, ids, name, args, context):
if 'period_id' in context and context['period_id']:
period_id = context['period_id']
'name': fields.char('Tax Case Name', size=64, required=True),
'code': fields.char('Case Code', size=64),
'info': fields.text('Description'),
- 'sum': fields.function(_sum, method=True, string="Year Sum"),
+ 'sum': fields.function(_sum_year, method=True, string="Year Sum"),
'sum_period': fields.function(_sum_period, method=True, string="Period Sum"),
'parent_id': fields.many2one('account.tax.code', 'Parent Code', select=True),
'child_ids': fields.one2many('account.tax.code', 'parent_id', 'Childs Codes'),
'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the taxes lines from the lowest sequences to the higher ones. The order is important if you have a tax that have several tax childs. In this case, the evaluation order is important."),
'amount': fields.float('Amount', required=True, digits=(14,4)),
'active': fields.boolean('Active'),
- 'type': fields.selection( [('percent','Percent'), ('fixed','Fixed'), ('none','None'), ('code','Python Code')], 'Tax Type', required=True),
- 'applicable_type': fields.selection( [('true','True'), ('code','Python Code')], 'Applicable Type', required=True),
+ 'type': fields.selection( [('percent','Percent'), ('fixed','Fixed'), ('none','None'), ('code','Python Code'),('balance','Balance')], 'Tax Type', required=True,
+ help="The computation method for the tax amount."),
+ 'applicable_type': fields.selection( [('true','True'), ('code','Python Code')], 'Applicable Type', required=True,
+ help="If not applicable (computed through a Python code), the tax do not appears on the invoice."),
'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developpers to create specific taxes in a custom domain."),
'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account'),
'account_paid_id':fields.many2one('account.account', 'Refund Tax Account'),
#
'base_code_id': fields.many2one('account.tax.code', 'Base Code', help="Use this code for the VAT declaration."),
'tax_code_id': fields.many2one('account.tax.code', 'Tax Code', help="Use this code for the VAT declaration."),
- 'base_sign': fields.float('Base Code Sign', help="Usualy 1 or -1."),
- 'tax_sign': fields.float('Tax Code Sign', help="Usualy 1 or -1."),
+ 'base_sign': fields.float('Base Code Sign', help="Usually 1 or -1."),
+ 'tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
# Same fields for refund invoices
'ref_base_code_id': fields.many2one('account.tax.code', 'Refund Base Code', help="Use this code for the VAT declaration."),
'ref_tax_code_id': fields.many2one('account.tax.code', 'Refund Tax Code', help="Use this code for the VAT declaration."),
- 'ref_base_sign': fields.float('Base Code Sign', help="Usualy 1 or -1."),
- 'ref_tax_sign': fields.float('Tax Code Sign', help="Usualy 1 or -1."),
+ 'ref_base_sign': fields.float('Base Code Sign', help="Usually 1 or -1."),
+ 'ref_tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
'include_base_amount': fields.boolean('Include in base amount', help="Indicate if the amount of tax must be included in the base amount for the computation of the next taxes"),
'company_id': fields.many2one('res.company', 'Company', required=True),
'description': fields.char('Internal Name',size=32),
+ 'price_include': fields.boolean('Tax Included in Price', help="Check this is the price you use on the product and invoices is including this tax.")
}
def name_get(self, cr, uid, ids, context={}):
'applicable_type': lambda *a: 'true',
'type': lambda *a: 'percent',
'amount': lambda *a: 0,
+ 'price_include': lambda *a: 0,
'active': lambda *a: 1,
'sequence': lambda *a: 1,
'tax_group': lambda *a: 'vat',
for tax in taxes:
# we compute the amount for the current tax object and append it to the result
- if tax.type=='percent':
- amount = cur_price_unit * tax.amount
- res.append({'id':tax.id,
+ data = {'id':tax.id,
'name':tax.name,
- 'amount':amount,
'account_collected_id':tax.account_collected_id.id,
'account_paid_id':tax.account_paid_id.id,
'base_code_id': tax.base_code_id.id,
'price_unit': cur_price_unit,
'tax_code_id': tax.tax_code_id.id,
'ref_tax_code_id': tax.ref_tax_code_id.id,
- })
+ }
+ res.append(data)
+ if tax.type=='percent':
+ amount = cur_price_unit * tax.amount
+ data['amount'] = amount
elif tax.type=='fixed':
- res.append({'id':tax.id,
- 'name':tax.name,
- 'amount':tax.amount,
- 'account_collected_id':tax.account_collected_id.id,
- 'account_paid_id':tax.account_paid_id.id,
- 'base_code_id': tax.base_code_id.id,
- 'ref_base_code_id': tax.ref_base_code_id.id,
- 'sequence': tax.sequence,
- 'base_sign': tax.base_sign,
- 'tax_sign': tax.tax_sign,
- 'ref_base_sign': tax.ref_base_sign,
- 'ref_tax_sign': tax.ref_tax_sign,
- 'price_unit': 1,
- 'tax_code_id': tax.tax_code_id.id,
- 'ref_tax_code_id': tax.ref_tax_code_id.id,})
+ data['amount'] = tax.amount
elif tax.type=='code':
address = address_id and self.pool.get('res.partner.address').browse(cr, uid, address_id) or None
localdict = {'price_unit':cur_price_unit, 'address':address, 'product':product, 'partner':partner}
exec tax.python_compute in localdict
amount = localdict['result']
- res.append({
- 'id': tax.id,
- 'name': tax.name,
- 'amount': amount,
- 'account_collected_id': tax.account_collected_id.id,
- 'account_paid_id': tax.account_paid_id.id,
- 'base_code_id': tax.base_code_id.id,
- 'ref_base_code_id': tax.ref_base_code_id.id,
- 'sequence': tax.sequence,
- 'base_sign': tax.base_sign,
- 'tax_sign': tax.tax_sign,
- 'ref_base_sign': tax.ref_base_sign,
- 'ref_tax_sign': tax.ref_tax_sign,
- 'price_unit': cur_price_unit,
- 'tax_code_id': tax.tax_code_id.id,
- 'ref_tax_code_id': tax.ref_tax_code_id.id,
- })
- amount2 = res[-1]['amount']
+ data['amount'] = amount
+ elif tax.type=='balance':
+ data['amount'] = cur_price_unit - reduce(lambda x,y: y.get('amount',0.0)+x, res, 0.0)
+ data['balance'] = cur_price_unit
+
+ amount2 = data['amount']
if len(tax.child_ids):
if tax.child_depend:
- del res[-1]
+ latest = res.pop()
amount = amount2
child_tax = self._unit_compute(cr, uid, tax.child_ids, amount, address_id, product, partner)
res.extend(child_tax)
+ if tax.child_depend:
+ for r in res:
+ for name in ('base','ref_base'):
+ if latest[name+'_code_id'] and latest[name+'_sign'] and not r[name+'_code_id']:
+ r[name+'_code_id'] = latest[name+'_code_id']
+ r[name+'_sign'] = latest[name+'_sign']
+ r['price_unit'] = latest['price_unit']
+ latest[name+'_code_id'] = False
+ for name in ('tax','ref_tax'):
+ if latest[name+'_code_id'] and latest[name+'_sign'] and not r[name+'_code_id']:
+ r[name+'_code_id'] = latest[name+'_code_id']
+ r[name+'_sign'] = latest[name+'_sign']
+ r['amount'] = data['amount']
+ latest[name+'_code_id'] = False
if tax.include_base_amount:
cur_price_unit+=amount2
return res
one tax for each tax id in IDS and their childs
"""
res = self._unit_compute(cr, uid, taxes, price_unit, address_id, product, partner)
+ total = 0.0
for r in res:
- r['amount'] *= quantity
+ if r.get('balance',False):
+ r['amount'] = round(r['balance'] * quantity, 2) - total
+ else:
+ r['amount'] = round(r['amount'] * quantity, 2)
+ total += r['amount']
+
return res
def _unit_compute_inv(self, cr, uid, taxes, price_unit, address_id=None, product=None, partner=None):
res = []
taxes.reverse()
cur_price_unit=price_unit
+
+ tax_parent_tot = 0.0
for tax in taxes:
- # we compute the amount for the current tax object and append it to the result
+ if (tax.type=='percent') and not tax.include_base_amount:
+ tax_parent_tot+=tax.amount
+ for tax in taxes:
if tax.type=='percent':
- amount = cur_price_unit - (cur_price_unit / (1 + tax.amount))
- res.append({'id':tax.id,
- 'name':tax.name,
- 'amount':amount,
- 'account_collected_id':tax.account_collected_id.id,
- 'account_paid_id':tax.account_paid_id.id,
- 'base_code_id': tax.base_code_id.id,
- 'ref_base_code_id': tax.ref_base_code_id.id,
- 'sequence': tax.sequence,
- 'base_sign': tax.base_sign,
- 'tax_sign': tax.tax_sign,
- 'ref_base_sign': tax.ref_base_sign,
- 'ref_tax_sign': tax.ref_tax_sign,
- 'price_unit': cur_price_unit - amount,
- 'tax_code_id': tax.tax_code_id.id,
- 'ref_tax_code_id': tax.ref_tax_code_id.id,})
+ if tax.include_base_amount:
+ amount = cur_price_unit - (cur_price_unit / (1 + tax.amount))
+ else:
+ amount = (cur_price_unit / (1 + tax_parent_tot)) * tax.amount
elif tax.type=='fixed':
- res.append({'id':tax.id,
- 'name':tax.name,
- 'amount':tax.amount,
- 'account_collected_id':tax.account_collected_id.id,
- 'account_paid_id':tax.account_paid_id.id,
- 'base_code_id': tax.base_code_id.id,
- 'ref_base_code_id': tax.ref_base_code_id.id,
- 'sequence': tax.sequence,
- 'base_sign': tax.base_sign,
- 'tax_sign': tax.tax_sign,
- 'ref_base_sign': tax.ref_base_sign,
- 'ref_tax_sign': tax.ref_tax_sign,
- 'price_unit': 1,
- 'tax_code_id': tax.tax_code_id.id,
- 'ref_tax_code_id': tax.ref_tax_code_id.id,})
+ amount = tax.amount
elif tax.type=='code':
address = address_id and self.pool.get('res.partner.address').browse(cr, uid, address_id) or None
localdict = {'price_unit':cur_price_unit, 'address':address, 'product':product, 'partner':partner}
exec tax.python_compute_inv in localdict
amount = localdict['result']
- res.append({
- 'id': tax.id,
- 'name': tax.name,
- 'amount': amount,
- 'account_collected_id': tax.account_collected_id.id,
- 'account_paid_id': tax.account_paid_id.id,
- 'base_code_id': tax.base_code_id.id,
- 'ref_base_code_id': tax.ref_base_code_id.id,
- 'sequence': tax.sequence,
- 'base_sign': tax.base_sign,
- 'tax_sign': tax.tax_sign,
- 'ref_base_sign': tax.ref_base_sign,
- 'ref_tax_sign': tax.ref_tax_sign,
- 'price_unit': cur_price_unit - amount,
- 'tax_code_id': tax.tax_code_id.id,
- 'ref_tax_code_id': tax.ref_tax_code_id.id,
- })
+ elif tax.type=='balance':
+ data['amount'] = cur_price_unit - reduce(lambda x,y: y.get('amount',0.0)+x, res, 0.0)
+ data['balance'] = cur_price_unit
+
- amount2 = res[-1]['amount']
+ if tax.include_base_amount:
+ cur_price_unit -= amount
+ todo = 0
+ else:
+ todo = 1
+ res.append({
+ 'id': tax.id,
+ 'todo': todo,
+ 'name': tax.name,
+ 'amount': amount,
+ 'account_collected_id': tax.account_collected_id.id,
+ 'account_paid_id': tax.account_paid_id.id,
+ 'base_code_id': tax.base_code_id.id,
+ 'ref_base_code_id': tax.ref_base_code_id.id,
+ 'sequence': tax.sequence,
+ 'base_sign': tax.base_sign,
+ 'tax_sign': tax.tax_sign,
+ 'ref_base_sign': tax.ref_base_sign,
+ 'ref_tax_sign': tax.ref_tax_sign,
+ 'price_unit': cur_price_unit,
+ 'tax_code_id': tax.tax_code_id.id,
+ 'ref_tax_code_id': tax.ref_tax_code_id.id,
+ })
if len(tax.child_ids):
if tax.child_depend:
del res[-1]
amount = price_unit
- else:
- amount = amount2
- for t in tax.child_ids:
- parent_tax = self._unit_compute_inv(cr, uid, [t], amount, address_id, product, partner)
- res.extend(parent_tax)
- if tax.include_base_amount:
- cur_price_unit-=amount
- taxes.reverse()
+
+ parent_tax = self._unit_compute_inv(cr, uid, tax.child_ids, amount, address_id, product, partner)
+ res.extend(parent_tax)
+
+ total = 0.0
+ for r in res:
+ if r['todo']:
+ total += r['amount']
+ for r in res:
+ r['price_unit'] -= total
+ r['todo'] = 0
return res
def compute_inv(self, cr, uid, taxes, price_unit, quantity, address_id=None, product=None, partner=None):
one tax for each tax id in IDS and their childs
"""
res = self._unit_compute_inv(cr, uid, taxes, price_unit, address_id, product, partner=None)
+ total = 0.0
for r in res:
- r['amount'] *= quantity
+ if r.get('balance',False):
+ r['amount'] = round(r['balance'] * quantity, 2) - total
+ else:
+ r['amount'] = round(r['amount'] * quantity, 2)
+ total += r['amount']
return res
account_tax()
}
_defaults = {
- 'legend':lambda *a:'''You can specify year, month and date in the name of the model using the following labels:\n\n%(year)s : To Specify Year \n%(month)s : To Specify Month \n%(date)s : Current Date\n\ne.g. My model on %(date)s''',
+ 'legend': lambda self, cr, uid, context:_('You can specify year, month and date in the name of the model using the following labels:\n\n%(year)s : To Specify Year \n%(month)s : To Specify Month \n%(date)s : Current Date\n\ne.g. My model on %(date)s'),
+
}
account_model()
ids=module_obj.search(cr, uid, [('category_id', '=', 'Account Charts'), ('state', '<>', 'installed')])
res=[(m.id, m.shortdesc) for m in module_obj.browse(cr, uid, ids)]
res.append((-1, 'None'))
- res.sort(lambda x,y: cmp(x[1],y[1]))
+ res.sort(key=lambda x: x[1])
return res
_columns = {
'target':'new',
}
- def install_account_chart(self, cr, uid,ids, context=None):
+ def install_account_chart(self, cr, uid, ids, context=None):
for res in self.read(cr,uid,ids):
- id = res['charts']
- def install(id):
+ chart_id = res['charts']
+ if chart_id > 0:
mod_obj = self.pool.get('ir.module.module')
- mod_obj.write(cr , uid, [id] ,{'state' : 'to install'})
- mod_obj.download(cr, uid, [id], context=context)
- cr.commit()
- cr.execute("select m.id as id from ir_module_module_dependency d inner join ir_module_module m on (m.name=d.name) where d.module_id=%d and m.state='uninstalled'",(id,))
- ret = cr.fetchall()
- if len(ret):
- for r in ret:
- install(r[0])
- else:
- mod_obj.write(cr , uid, [id] ,{'state' : 'to install'})
- mod_obj.download(cr, uid, [id], context=context)
- cr.commit()
- if id>0:
- install(id)
+ mod_obj.button_install(cr, uid, [chart_id], context=context)
cr.commit()
db, pool = pooler.restart_pool(cr.dbname, update_module=True)
account_tax_template()
+# Fiscal Position Templates
+
+class account_fiscal_position_template(osv.osv):
+ _name = 'account.fiscal.position.template'
+ _description = 'Template for Fiscal Position'
+
+ _columns = {
+ 'name': fields.char('Fiscal Position Template', size=64, translate=True, required=True),
+ 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True),
+ 'account_ids': fields.one2many('account.fiscal.position.account.template', 'position_id', 'Accounts Mapping'),
+ 'tax_ids': fields.one2many('account.fiscal.position.tax.template', 'position_id', 'Taxes Mapping')
+ }
+
+account_fiscal_position_template()
+
+class account_fiscal_position_tax_template(osv.osv):
+ _name = 'account.fiscal.position.tax.template'
+ _description = 'Fiscal Position Template Taxes Mapping'
+ _rec_name = 'position_id'
+
+ _columns = {
+ 'position_id': fields.many2one('account.fiscal.position.template', 'Fiscal Position', required=True, ondelete='cascade'),
+ 'tax_src_id': fields.many2one('account.tax.template', 'Tax Source', required=True),
+ 'tax_dest_id': fields.many2one('account.tax.template', 'Replacement Tax')
+ }
+
+account_fiscal_position_tax_template()
+
+class account_fiscal_position_account_template(osv.osv):
+ _name = 'account.fiscal.position.account.template'
+ _description = 'Fiscal Position Template Accounts Mapping'
+ _rec_name = 'position_id'
+ _columns = {
+ 'position_id': fields.many2one('account.fiscal.position.template', 'Fiscal Position', required=True, ondelete='cascade'),
+ 'account_src_id': fields.many2one('account.account.template', 'Account Source', domain=[('type','<>','view')], required=True),
+ 'account_dest_id': fields.many2one('account.account.template', 'Account Destination', domain=[('type','<>','view')], required=True)
+ }
+
+account_fiscal_position_account_template()
+
# Multi charts of Accounts wizard
class wizard_multi_charts_accounts(osv.osv_memory):
obj_acc_tax = self.pool.get('account.tax')
obj_journal = self.pool.get('account.journal')
obj_acc_template = self.pool.get('account.account.template')
+ obj_fiscal_position_template = self.pool.get('account.fiscal.position.template')
+ obj_fiscal_position = self.pool.get('account.fiscal.position')
# Creating Account
obj_acc_root = obj_multi.chart_template_id.account_root_id
'python_compute_inv': tax.python_compute_inv,
'python_applicable': tax.python_applicable,
'tax_group':tax.tax_group,
- 'base_code_id': tax.base_code_id and tax_code_template_ref[tax.base_code_id.id] or False,
- 'tax_code_id': tax.tax_code_id and tax_code_template_ref[tax.tax_code_id.id] or False,
+ 'base_code_id': tax.base_code_id and ((tax.base_code_id.id in tax_code_template_ref) and tax_code_template_ref[tax.base_code_id.id]) or False,
+ 'tax_code_id': tax.tax_code_id and ((tax.tax_code_id.id in tax_code_template_ref) and tax_code_template_ref[tax.tax_code_id.id]) or False,
'base_sign': tax.base_sign,
'tax_sign': tax.tax_sign,
- 'ref_base_code_id': tax.ref_base_code_id and tax_code_template_ref[tax.ref_base_code_id.id] or False,
- 'ref_tax_code_id': tax.ref_tax_code_id and tax_code_template_ref[tax.ref_tax_code_id.id] or False,
+ 'ref_base_code_id': tax.ref_base_code_id and ((tax.ref_base_code_id.id in tax_code_template_ref) and tax_code_template_ref[tax.ref_base_code_id.id]) or False,
+ 'ref_tax_code_id': tax.ref_tax_code_id and ((tax.ref_tax_code_id.id in tax_code_template_ref) and tax_code_template_ref[tax.ref_tax_code_id.id]) or False,
'ref_base_sign': tax.ref_base_sign,
'ref_tax_sign': tax.ref_tax_sign,
'include_base_amount': tax.include_base_amount,
#create the account_account
dig = obj_multi.code_digits
- code_main = len(account_template.code)
- code_acc = account_template.code
- if code_main<=dig and account_template.type != 'view':
+ code_main = account_template.code and len(account_template.code) or 0
+ code_acc = account_template.code or ''
+ if code_main>0 and code_main<=dig and account_template.type != 'view':
code_acc=str(code_acc) + (str('0'*(dig-code_main)))
vals={
'name': (obj_acc_root.id == account_template.id) and obj_multi.company_id.name or account_template.name,
vals_journal['code'] = _('SAJ')
if obj_multi.chart_template_id.property_account_receivable:
- vals_journal['default_credit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_receivable.id]
- vals_journal['default_debit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_receivable.id]
+ vals_journal['default_credit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_income_categ.id]
+ vals_journal['default_debit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_income_categ.id]
obj_journal.create(cr,uid,vals_journal)
vals_journal['code']=_('EXJ')
if obj_multi.chart_template_id.property_account_payable:
- vals_journal['default_credit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_payable.id]
- vals_journal['default_debit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_payable.id]
+ vals_journal['default_credit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_expense_categ.id]
+ vals_journal['default_debit_account_id'] = acc_template_ref[obj_multi.chart_template_id.property_account_expense_categ.id]
obj_journal.create(cr,uid,vals_journal)
vals={
'name': line.acc_no.bank and line.acc_no.bank.name+' '+tmp or tmp,
'currency_id': line.currency_id and line.currency_id.id or False,
- 'code': str(int(ref_acc_bank.code.ljust(dig,'0')) + current_num),
+ 'code': str(ref_acc_bank.code.ljust(dig,'0') + str(current_num)),
'type': 'other',
'user_type': account_template.user_type and account_template.user_type.id or False,
'reconcile': True,
#create the property
property_obj.create(cr, uid, vals)
+ fp_ids = obj_fiscal_position_template.search(cr, uid,[('chart_template_id', '=', obj_multi.chart_template_id.id)])
+
+ if fp_ids:
+ for position in obj_fiscal_position_template.browse(cr, uid, fp_ids):
+
+ vals_fp = {
+ 'company_id' : company_id,
+ 'name' : position.name,
+ }
+ new_fp = obj_fiscal_position.create(cr, uid, vals_fp)
+
+ obj_tax_fp = self.pool.get('account.fiscal.position.tax')
+ obj_ac_fp = self.pool.get('account.fiscal.position.account')
+
+ for tax in position.tax_ids:
+ vals_tax = {
+ 'tax_src_id' : tax_template_ref[tax.tax_src_id.id],
+ 'tax_dest_id' : tax_template_ref[tax.tax_dest_id.id],
+ 'position_id' : new_fp,
+ }
+ obj_tax_fp.create(cr, uid, vals_tax)
+
+ for acc in position.account_ids:
+ vals_acc = {
+ 'account_src_id' : acc_template_ref[acc.account_src_id.id],
+ 'account_dest_id' : acc_template_ref[acc.account_dest_id.id],
+ 'position_id' : new_fp,
+ }
+ obj_ac_fp.create(cr, uid, vals_acc)
+
return {
'view_type': 'form',
"view_mode": 'form',