[IMP] account_voucher: write-off feature

bzr revid: qdp-launchpad@tinyerp.com-20101213202512-812vonpdu99z2308
This commit is contained in:
qdp-launchpad@tinyerp.com 2010-12-13 21:25:12 +01:00
parent a4f83694b9
commit 70a6430ada
4 changed files with 134 additions and 76 deletions

View File

@ -23,10 +23,11 @@ import time
from lxml import etree
import netsvc
from osv import fields
from osv import osv
from osv import osv, fields
import decimal_precision as dp
from tools.translate import _
class account_move_line(osv.osv):
_inherit = 'account.move.line'
@ -140,18 +141,29 @@ class account_voucher(osv.osv):
res['arch'] = etree.tostring(doc)
return res
def _compute_writeoff_amount(self, cr, uid, line_dr_ids, line_cr_ids, amount):
debit = credit = 0.0
for l in line_dr_ids:
debit += l['amount']
for l in line_cr_ids:
credit += l['amount']
return abs(amount - abs(credit - debit))
def onchange_line_ids(self, cr, uid, ids, line_dr_ids, line_cr_ids, amount):
line_dr_ids = [x[2] for x in line_dr_ids]
line_cr_ids = [x[2] for x in line_cr_ids]
return {'value': {'writeoff_amount': self._compute_writeoff_amount(cr, uid, line_dr_ids, line_cr_ids, amount)}}
def _get_writeoff_amount(self, cr, uid, ids, name, args, context=None):
if not ids: return {}
res = {}
debit = credit = 0.0
for voucher in self.browse(cr, uid, ids, context=context):
debit= credit = 0.0
if voucher.line_dr_ids:
for line in voucher.line_dr_ids:
debit += line.amount_unreconciled
if voucher.line_cr_ids:
for line in voucher.line_cr_ids:
credit += line.amount_unreconciled
res[voucher.id] = abs(voucher.amount - abs(credit - debit))
for l in voucher.line_dr_ids:
debit += l.amount
for l in voucher.line_cr_ids:
credit += l.amount
res[voucher.id] = abs(voucher.amount - abs(credit - debit))
return res
_name = 'account.voucher'
@ -189,8 +201,8 @@ class account_voucher(osv.osv):
\n* The \'Pro-forma\' when voucher is in Pro-forma state,voucher does not have an voucher number. \
\n* The \'Posted\' state is used when user create voucher,a voucher number is generated and voucher entries are created in account \
\n* The \'Cancelled\' state is used when user cancel voucher.'),
'amount': fields.float('Total', digits=(16, 2), required=True, readonly=True, states={'draft':[('readonly',False)]}),
'tax_amount':fields.float('Tax Amount', digits=(14,2), readonly=True, states={'draft':[('readonly',False)]}),
'amount': fields.float('Total', digits_compute=dp.get_precision('Account'), required=True, readonly=True, states={'draft':[('readonly',False)]}),
'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
'reference': fields.char('Ref #', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."),
'number': fields.char('Number', size=32, readonly=True,),
'move_id':fields.many2one('account.move', 'Account Entry'),
@ -205,14 +217,13 @@ class account_voucher(osv.osv):
'pre_line':fields.boolean('Previous Payments ?', required=False),
'date_due': fields.date('Due Date', readonly=True, states={'draft':[('readonly',False)]}),
'payment_option':fields.selection([
('without_writeoff', 'Without Write-off'),
('with_writeoff', 'With Write-off'),
], 'Payment Option', required=True, readonly=True, states={'draft': [('readonly', False)]}),
('without_writeoff', 'Keep Open'),
('with_writeoff', 'Reconcile with Write-Off'),
], 'Payment Difference', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'writeoff_acc_id': fields.many2one('account.account', 'Write-Off account', readonly=True, states={'draft': [('readonly', False)]}),
'writeoff_journal_id': fields.many2one('account.journal', 'Write-Off journal', readonly=True, states={'draft': [('readonly', False)]}),
'comment': fields.char('Comment', size=64, readonly=True, states={'draft': [('readonly', False)]}),
'analytic_id': fields.many2one('account.analytic.account','Analytic Account', readonly=True, states={'draft': [('readonly', False)]}),
'writeoff_amount': fields.function(_get_writeoff_amount, method=True, string='Writeoff Amount', type='float', readonly=True),
'comment': fields.char('Write-Off Comment', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}),
'analytic_id': fields.many2one('account.analytic.account','Write-Off Analytic Account', readonly=True, states={'draft': [('readonly', False)]}),
'writeoff_amount': fields.function(_get_writeoff_amount, method=True, string='Write-Off Amount', type='float', readonly=True),
}
_defaults = {
'period_id': _get_period,
@ -229,7 +240,7 @@ class account_voucher(osv.osv):
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.voucher',context=c),
'tax_id': _get_tax,
'payment_option': 'without_writeoff',
'comment': 'Write-Off',
'comment': _('Write-Off'),
}
def compute_tax(self, cr, uid, ids, context={}):
@ -384,13 +395,17 @@ class account_voucher(osv.osv):
@return: Returns a dict which contains new values, and context
"""
if context is None:
context = {}
if not journal_id:
return {}
if context is None:
context = {}
currency_pool = self.pool.get('res.currency')
line_pool = self.pool.get('account.voucher.line')
line_ids = ids and line_pool.search(cr, uid, [('voucher_id', '=', ids[0])]) or False
if line_ids:
line_pool.unlink(cr, uid, line_ids)
currency_pool = self.pool.get('res.currency')
move_line_pool = self.pool.get('account.move.line')
partner_pool = self.pool.get('res.partner')
journal_pool = self.pool.get('account.journal')
@ -404,13 +419,6 @@ class account_voucher(osv.osv):
if not partner_id:
return default
if not partner_id and ids:
line_ids = line_pool.search(cr, uid, [('voucher_id', '=', ids[0])])
if line_ids:
line_pool.unlink(cr, uid, line_ids)
return default
journal = journal_pool.browse(cr, uid, journal_id)
partner = partner_pool.browse(cr, uid, partner_id)
account_id = False
@ -493,6 +501,7 @@ class account_voucher(osv.osv):
default['value']['pre_line'] = 1
elif ttype == 'receipt' and len(default['value']['line_dr_ids']) > 0:
default['value']['pre_line'] = 1
default['value']['writeoff_amount'] = self._compute_writeoff_amount(cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price)
return default
@ -719,16 +728,20 @@ class account_voucher(osv.osv):
if line.move_line_id.id:
rec_ids = [master_line, line.move_line_id.id]
rec_list_ids.append(rec_ids)
writeoff_account_id = False
writeoff_journal_id = False
writeoff_period_id = inv.period_id.id,
comment = False
if not currency_pool.is_zero(cr, uid, inv.currency_id, line_total):
diff = line_total
account_id = False
if inv.payment_option == 'with_writeoff':
account_id = inv.writeoff_acc_id.id
elif inv.type in ('sale', 'receipt'):
# if inv.journal_id.type in ('sale','sale_refund', 'cash', 'bank'):
account_id = inv.partner_id.property_account_receivable.id
else:
account_id = inv.partner_id.property_account_payable.id
move_line = {
'name': name,
'account_id': False,
'account_id': account_id,
'move_id': move_id,
'partner_id': inv.partner_id.id,
'date': inv.date,
@ -737,24 +750,8 @@ class account_voucher(osv.osv):
'amount_currency': company_currency <> current_currency and currency_pool.compute(cr, uid, company_currency, current_currency, diff * -1) or 0.0,
'currency_id': company_currency <> current_currency and current_currency or False,
}
account_id = False
if inv.type in ('sale', 'receipt'):
# if inv.journal_id.type in ('sale','sale_refund', 'cash', 'bank'):
account_id = inv.partner_id.property_account_receivable.id
else:
account_id = inv.partner_id.property_account_payable.id
move_line['account_id'] = account_id
move_line_pool.create(cr, uid, move_line)
for rec_ids in rec_list_ids:
if len(rec_ids) >= 2:
if inv.payment_option == 'with_writeoff':
writeoff_account_id = inv.writeoff_acc_id.id
writeoff_journal_id = inv.writeoff_journal_id.id
comment = inv.comment
move_line_pool.reconcile(cr, uid, rec_ids, 'manual', writeoff_account_id, writeoff_period_id, writeoff_journal_id, context)
else:
move_line_pool.reconcile_partial(cr, uid, rec_ids)
self.write(cr, uid, [inv.id], {
'move_id': move_id,
@ -762,6 +759,9 @@ class account_voucher(osv.osv):
'number': name,
})
move_pool.post(cr, uid, [move_id], context={})
for rec_ids in rec_list_ids:
if len(rec_ids) >= 2:
move_line_pool.reconcile_partial(cr, uid, rec_ids)
return True
def copy(self, cr, uid, id, default={}, context=None):
@ -813,7 +813,7 @@ class account_voucher_line(osv.osv):
'account_id':fields.many2one('account.account','Account', required=True),
'partner_id':fields.related('voucher_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'),
'untax_amount':fields.float('Untax Amount'),
'amount':fields.float('Amount', digits=(14,2)),
'amount':fields.float('Amount', digits_compute=dp.get_precision('Account')),
'type':fields.selection([('dr','Debit'),('cr','Credit')], 'Cr/Dr'),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'move_line_id': fields.many2one('account.move.line', 'Journal Item'),

View File

@ -70,8 +70,21 @@
<field name="period_id"/>
<field name="audit"/>
</group>
<separator string="Journal Items" colspan="4"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1">
<tree string="Journal Items">
<field name="move_id"/>
<field name="ref"/>
<field name="date"/>
<field name="statement_id"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="name"/>
<field name="debit"/>
<field name="credit"/>
<field name="state"/>
<field name="reconcile_id"/>
</tree>
</field>
</page>
</notebook>
<group col="10" colspan="4">

View File

@ -105,7 +105,7 @@
</group>
<notebook colspan="4">
<page string="Payment Information">
<field name="line_dr_ids" attrs="{'invisible': [('type', '=', 'receipt')]}" default_get="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" colspan="4" nolabel="1" height="140">
<field name="line_dr_ids" attrs="{'invisible': [('type', '=', 'receipt')]}" default_get="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" colspan="4" nolabel="1" height="140" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount)">
<tree string="Open Vendor Journal Entries" editable="bottom">
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
on_change="onchange_move_line_id(move_line_id)"
@ -119,7 +119,7 @@
<field name="amount" sum="Payment"/>
</tree>
</field>
<field name="line_cr_ids" colspan="4" nolabel="1" attrs="{'invisible': [('type', '=', 'payment')]}" default_get="{'journal_id':journal_id, 'partner_id':partner_id}">
<field name="line_cr_ids" colspan="4" nolabel="1" attrs="{'invisible': [('type', '=', 'payment')]}" default_get="{'journal_id':journal_id, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount)">
<tree string="Open Customer Journal Entries" editable="bottom">
<field name="move_line_id"/>
<field name="account_id" groups="base.group_extended" domain="[('type','=','receivable')]"/>
@ -198,22 +198,18 @@
<group col="2" colspan="1">
<group col="2" colspan="1">
<separator string="Payment Options" colspan="2"/>
<field name="payment_option" required="1"/>
<field name="writeoff_amount"
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
<field name="payment_option" required="1"/>
<field name="writeoff_acc_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"
domain="[('type','=','liquidity')]"/>
<!-- should select income accounts only. Or use the journal for this ? -->
<field name="writeoff_journal_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"/>
domain="[('type','=','other')]"/>
<field name="comment"
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
<field name="analytic_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"
groups="analytic.group_analytic_accounting"/>
</group>
<separator string="Other Information" colspan="2"/>
<group col="4" colspan="1">
<field name="date" select="1" on_change="onchange_date(date)"/>
<field name="currency_id" invisible="True"/>
@ -227,8 +223,21 @@
<field name="period_id"/>
<field name="audit"/>
</group>
<separator string="Journal Items" colspan="4"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1">
<tree string="Journal Items">
<field name="move_id"/>
<field name="ref"/>
<field name="date"/>
<field name="statement_id"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="name"/>
<field name="debit"/>
<field name="credit"/>
<field name="state"/>
<field name="reconcile_id"/>
</tree>
</field>
</page>
</notebook>
<group col="10" colspan="4">
@ -295,7 +304,7 @@
</group>
<notebook colspan="4">
<page string="Payment Information">
<field name="line_cr_ids" default_get="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" colspan="4" nolabel="1" height="140">
<field name="line_cr_ids" default_get="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" colspan="4" nolabel="1" height="140" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount)">
<tree string="Invoices and outstanding transactions" editable="bottom">
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
on_change="onchange_move_line_id(move_line_id)"
@ -309,7 +318,7 @@
<field name="amount" sum="Payment"/>
</tree>
</field>
<field name="line_dr_ids" colspan="4" nolabel="1" attrs="{'invisible': [('pre_line','=',False)]}" default_get="{'journal_id':journal_id, 'partner_id':partner_id}">
<field name="line_dr_ids" colspan="4" nolabel="1" attrs="{'invisible': [('pre_line','=',False)]}" default_get="{'journal_id':journal_id, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount)">
<tree string="Credits" editable="bottom">
<field name="move_line_id"/>
<field name="account_id" groups="base.group_extended" domain="[('type','=','receivable')]"/>
@ -330,10 +339,7 @@
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
<field name="writeoff_acc_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"
domain="[('type','=','liquidity')]"/>
<!-- should select income accounts only. Or use the journal for this ? -->
<field name="writeoff_journal_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"/>
domain="[('type','=','other')]"/>
<field name="comment"
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
<field name="analytic_id"
@ -354,8 +360,21 @@
<field name="period_id"/>
<field name="audit"/>
</group>
<separator string="Journal Items" colspan="4"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1">
<tree string="Journal Items">
<field name="move_id"/>
<field name="ref"/>
<field name="date"/>
<field name="statement_id"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="name"/>
<field name="debit"/>
<field name="credit"/>
<field name="state"/>
<field name="reconcile_id"/>
</tree>
</field>
</page>
</notebook>
<group col="10" colspan="4">

View File

@ -144,8 +144,21 @@
<field name="period_id"/>
<field name="audit"/>
</group>
<separator string="Journal Items" colspan="4"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1">
<tree string="Journal Items">
<field name="move_id"/>
<field name="ref"/>
<field name="date"/>
<field name="statement_id"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="name"/>
<field name="debit"/>
<field name="credit"/>
<field name="state"/>
<field name="reconcile_id"/>
</tree>
</field>
</page>
</notebook>
<group col="8" colspan="4">
@ -251,8 +264,21 @@
<field name="period_id"/>
<field name="audit"/>
</group>
<separator string="Journal Items" colspan="4"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1"/>
<field name="move_ids" colspan="4" nolabel="1" readonly="1">
<tree string="Journal Items">
<field name="move_id"/>
<field name="ref"/>
<field name="date"/>
<field name="statement_id"/>
<field name="partner_id"/>
<field name="account_id"/>
<field name="name"/>
<field name="debit"/>
<field name="credit"/>
<field name="state"/>
<field name="reconcile_id"/>
</tree>
</field>
</page>
</notebook>
<group col="10" colspan="4">