Improve payment, invoice, statement
- Use the right reference from invoice on account move lines - Add a reference type on invoice - Payment are now multi-currency - Add wizard to populate statement - Make thread safe payment wizard - Add mod10r in utils - Add colors on statement lines bzr revid: ced-35849fea0ca75fec483ba54836f4954c1b26d2c9
This commit is contained in:
parent
ddae539d94
commit
1d480a1df3
|
@ -507,6 +507,25 @@ class account_bank_statement_line(osv.osv):
|
|||
currency_id, balance, context=context)
|
||||
return {'value': {'amount': balance, 'account_id': account_id}}
|
||||
|
||||
def _reconcile_amount(self, cursor, user, ids, name, args, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
res_currency_obj = self.pool.get('res.currency')
|
||||
res_users_obj = self.pool.get('res.users')
|
||||
|
||||
res = {}
|
||||
company_currency_id = res_users_obj.browse(cursor, user, user,
|
||||
context=context).company_id.currency_id.id
|
||||
|
||||
for line in self.browse(cursor, user, ids, context=context):
|
||||
if line.reconcile_id:
|
||||
res[line.id] = res_currency_obj.compute(cursor, user,
|
||||
company_currency_id, line.statement_id.currency.id,
|
||||
line.reconcile_id.total_entry, context=context)
|
||||
else:
|
||||
res[line.id] = 0.0
|
||||
return res
|
||||
|
||||
_order = "date,name desc"
|
||||
_name = "account.bank.statement.line"
|
||||
_description = "Bank Statement Line"
|
||||
|
@ -514,14 +533,25 @@ class account_bank_statement_line(osv.osv):
|
|||
'name': fields.char('Name', size=64, required=True),
|
||||
'date': fields.date('Date', required=True),
|
||||
'amount': fields.float('Amount'),
|
||||
'type': fields.selection([('supplier','Supplier'),('customer','Customer'),('general','General')], 'Type', required=True),
|
||||
'type': fields.selection([
|
||||
('supplier','Supplier'),
|
||||
('customer','Customer'),
|
||||
('general','General')
|
||||
], 'Type', required=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'account_id': fields.many2one('account.account','Account', required=True),
|
||||
'statement_id': fields.many2one('account.bank.statement', 'Statement', select=True, required=True),
|
||||
'reconcile_id': fields.many2one('account.bank.statement.reconcile', 'Reconcile', states={'confirm':[('readonly',True)]}),
|
||||
'move_ids': fields.many2many('account.move', 'account_bank_statement_line_move_rel', 'move_id','statement_id', 'Moves'),
|
||||
'account_id': fields.many2one('account.account','Account',
|
||||
required=True),
|
||||
'statement_id': fields.many2one('account.bank.statement', 'Statement',
|
||||
select=True, required=True),
|
||||
'reconcile_id': fields.many2one('account.bank.statement.reconcile',
|
||||
'Reconcile', states={'confirm':[('readonly',True)]}),
|
||||
'move_ids': fields.many2many('account.move',
|
||||
'account_bank_statement_line_move_rel', 'move_id','statement_id',
|
||||
'Moves'),
|
||||
'ref': fields.char('Ref.', size=32),
|
||||
'note': fields.text('Notes')
|
||||
'note': fields.text('Notes'),
|
||||
'reconcile_amount': fields.function(_reconcile_amount,
|
||||
string='Amount reconciled', method=True, type='float'),
|
||||
}
|
||||
_defaults = {
|
||||
'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'),
|
||||
|
|
|
@ -139,8 +139,10 @@
|
|||
|
||||
|
||||
|
||||
<field name="name" select="2"/>
|
||||
<field name="name" select="2" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="reference" select="1"/>
|
||||
<field name="reference_type" select="2"/>
|
||||
|
||||
<field name="check_total" required="2"/>
|
||||
<field name="currency_id" on_change="onchange_currency_id(currency_id)" select="2"/>
|
||||
|
@ -261,7 +263,9 @@
|
|||
<newline/>
|
||||
<field name="partner_bank_id" domain="[('partner_id','=',partner_id)]"/>
|
||||
<field name="date_due" select="1"/>
|
||||
<newline/>
|
||||
<field name="reference" select="2"/>
|
||||
<field name="reference_type" select="2"/>
|
||||
<field name="origin"/>
|
||||
<field name="address_contact_id" domain="[('partner_id','=',partner_id)]" colspan="4"/>
|
||||
<field name="move_id"/>
|
||||
|
|
|
@ -324,7 +324,8 @@
|
|||
<notebook colspan="4">
|
||||
<page string="Entry encoding">
|
||||
<field name="line_ids" colspan="4" nolabel="1">
|
||||
<tree string="Statement lines" editable="bottom">
|
||||
<tree string="Statement lines" editable="bottom"
|
||||
colors="red:amount!=reconcile_amount and reconcile_id">
|
||||
<field name="date"/>
|
||||
<field name="ref"/>
|
||||
<field name="name"/>
|
||||
|
@ -335,7 +336,8 @@
|
|||
domain="[('journal_id','=',parent.journal_id)]"/>
|
||||
<field name="amount"/>
|
||||
<field name="reconcile_id"
|
||||
context="{'partner_id': partner_id, 'amount': amount, 'account_id': account_id, 'currency_id': parent.currency}"/>
|
||||
context="{'partner_id': partner_id, 'amount': amount, 'account_id': account_id, 'currency_id': parent.currency}"/>
|
||||
<field name="reconcile_amount" invisible="1"/>
|
||||
</tree>
|
||||
<form string="Statement lines">
|
||||
<field name="date"/>
|
||||
|
|
|
@ -95,6 +95,9 @@ class account_invoice(osv.osv):
|
|||
res[id] = self.test_paid(cr, uid, [id])
|
||||
return res
|
||||
|
||||
def _get_reference_type(self, cursor, user, context=None):
|
||||
return [('none', 'None')]
|
||||
|
||||
_name = "account.invoice"
|
||||
_description = 'Invoice'
|
||||
_order = "number"
|
||||
|
@ -110,6 +113,8 @@ class account_invoice(osv.osv):
|
|||
|
||||
'number': fields.char('Invoice Number', size=32, readonly=True),
|
||||
'reference': fields.char('Invoice Reference', size=64),
|
||||
'reference_type': fields.selection(_get_reference_type, 'Reference Type',
|
||||
required=True),
|
||||
'comment': fields.text('Additionnal Information'),
|
||||
|
||||
'state': fields.selection([
|
||||
|
@ -152,9 +157,12 @@ class account_invoice(osv.osv):
|
|||
'state': lambda *a: 'draft',
|
||||
'journal_id': _get_journal,
|
||||
'currency_id': _get_currency,
|
||||
'company_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id,
|
||||
'company_id': lambda self, cr, uid, context: \
|
||||
self.pool.get('res.users').browse(cr, uid, uid,
|
||||
context=context).company_id.id,
|
||||
'reference_type': lambda *a: 'none',
|
||||
}
|
||||
|
||||
|
||||
def unlink(self, cr, uid, ids):
|
||||
invoices = self.read(cr, uid, ids, ['state'])
|
||||
unlink_ids = []
|
||||
|
@ -317,6 +325,10 @@ class account_invoice(osv.osv):
|
|||
iml = self.pool.get('account.invoice.line').move_line_get(cr, uid, inv.id)
|
||||
for il in iml:
|
||||
if il['account_analytic_id']:
|
||||
if inv.type in ('in_invoice', 'in_refund'):
|
||||
ref = inv.reference
|
||||
else:
|
||||
ref = self._convert_ref(cr, uid, inv.number)
|
||||
il['analytic_lines'] = [(0,0, {
|
||||
'name': il['name'],
|
||||
'date': inv['date_invoice'],
|
||||
|
@ -327,7 +339,7 @@ class account_invoice(osv.osv):
|
|||
'product_uom_id': il['uos_id'],
|
||||
'general_account_id': il['account_id'],
|
||||
'journal_id': self._get_journal_analytic(cr, uid, inv.type),
|
||||
'ref': self._convert_ref(cr, uid, inv['number']),
|
||||
'ref': ref,
|
||||
})]
|
||||
return iml
|
||||
|
||||
|
@ -370,7 +382,12 @@ class account_invoice(osv.osv):
|
|||
# one move line per tax line
|
||||
iml += ait_obj.move_line_get(cr, uid, inv.id)
|
||||
|
||||
|
||||
if inv.type in ('in_invoice', 'in_refund'):
|
||||
ref = inv.reference
|
||||
else:
|
||||
ref = self._convert_ref(cr, uid, inv.number)
|
||||
|
||||
diff_currency_p = inv.currency_id.id <> company_currency
|
||||
# create one move line for the total and possibly adjust the other lines amount
|
||||
total = 0
|
||||
total_currency = 0
|
||||
|
@ -378,11 +395,13 @@ class account_invoice(osv.osv):
|
|||
if inv.currency_id.id != company_currency:
|
||||
i['currency_id'] = inv.currency_id.id
|
||||
i['amount_currency'] = i['price']
|
||||
i['price'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, i['price'], context={'date': inv.date_invoice})
|
||||
i['price'] = cur_obj.compute(cr, uid, inv.currency_id.id,
|
||||
company_currency, i['price'],
|
||||
context={'date': inv.date_invoice})
|
||||
else:
|
||||
i['amount_currency'] = False
|
||||
i['currency_id'] = False
|
||||
i['ref'] = self._convert_ref(cr, uid, inv.number)
|
||||
i['ref'] = ref
|
||||
if inv.type in ('out_invoice','in_refund'):
|
||||
total += i['price']
|
||||
total_currency += i['amount_currency'] or i['price']
|
||||
|
@ -409,9 +428,31 @@ class account_invoice(osv.osv):
|
|||
if i == len(totlines):
|
||||
amount_currency += res_amount_currency
|
||||
|
||||
iml.append({ 'type':'dest', 'name':name, 'price': t[1], 'account_id':acc_id, 'date_maturity': t[0], 'amount_currency': amount_currency, 'currency_id': inv.currency_id.id, 'ref': inv.number})
|
||||
iml.append({
|
||||
'type': 'dest',
|
||||
'name': name,
|
||||
'price': t[1],
|
||||
'account_id': acc_id,
|
||||
'date_maturity': t[0],
|
||||
'amount_currency': diff_currency_p \
|
||||
and amount_currency or False,
|
||||
'currency_id': diff_currency_p \
|
||||
and inv.currency_id.id or False,
|
||||
'ref': ref,
|
||||
})
|
||||
else:
|
||||
iml.append({ 'type':'dest', 'name':name, 'price': total, 'account_id':acc_id, 'date_maturity' : inv.date_due or False, 'amount_currency': total_currency, 'currency_id': inv.currency_id.id, 'ref': inv.number})
|
||||
iml.append({
|
||||
'type': 'dest',
|
||||
'name': name,
|
||||
'price': total,
|
||||
'account_id': acc_id,
|
||||
'date_maturity' : inv.date_due or False,
|
||||
'amount_currency': diff_currency_p \
|
||||
and total_currency or False,
|
||||
'currency_id': diff_currency_p \
|
||||
and inv.currency_id.id or False,
|
||||
'ref': ref
|
||||
})
|
||||
|
||||
date = inv.date_invoice
|
||||
part = inv.partner_id.id
|
||||
|
@ -452,13 +493,17 @@ class account_invoice(osv.osv):
|
|||
}
|
||||
|
||||
def action_number(self, cr, uid, ids, *args):
|
||||
cr.execute('SELECT id, type, number, move_id FROM account_invoice WHERE id IN ('+','.join(map(str,ids))+')')
|
||||
for (id, invtype, number, move_id) in cr.fetchall():
|
||||
cr.execute('SELECT id, type, number, move_id, reference FROM account_invoice WHERE id IN ('+','.join(map(str,ids))+')')
|
||||
for (id, invtype, number, move_id, reference) in cr.fetchall():
|
||||
if not number:
|
||||
number = self.pool.get('ir.sequence').get(cr, uid, 'account.invoice.'+invtype)
|
||||
if type in ('in_invoice', 'in_refund'):
|
||||
ref = reference
|
||||
else:
|
||||
ref = self._convert_ref(cr, uid, number)
|
||||
cr.execute('UPDATE account_invoice SET number=%s WHERE id=%d', (number, id))
|
||||
cr.execute('UPDATE account_move_line SET ref=%s WHERE move_id=%d and ref is null', (self._convert_ref(cr, uid, number), move_id))
|
||||
cr.execute('UPDATE account_analytic_line SET ref=%s FROM account_move_line WHERE account_move_line.move_id=%d AND account_analytic_line.move_id=account_move_line.id', (self._convert_ref(cr, uid, number), move_id))
|
||||
cr.execute('UPDATE account_move_line SET ref=%s WHERE move_id=%d and ref is null', (ref, move_id))
|
||||
cr.execute('UPDATE account_analytic_line SET ref=%s FROM account_move_line WHERE account_move_line.move_id=%d AND account_analytic_line.move_id=account_move_line.id', (ref, move_id))
|
||||
return True
|
||||
|
||||
def action_cancel(self, cr, uid, ids, *args):
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
{
|
||||
"name" : "Payment Management",
|
||||
"version" : "1.0",
|
||||
"author" : "Tiny",
|
||||
"category" : "Generic Modules/Payment",
|
||||
"depends" : ["account"],
|
||||
"init_xml" : [],
|
||||
"name": "Payment Management",
|
||||
"version": "1.0",
|
||||
"author": "Tiny",
|
||||
"category": "Generic Modules/Payment",
|
||||
"depends": ["account"],
|
||||
"init_xml": [],
|
||||
"description": """
|
||||
This is the module which Provide an more efficient way to manage invoice payment,
|
||||
Provide a basic mechanism to easily plug various automated payment.
|
||||
""",
|
||||
"demo_xml" : [],
|
||||
"update_xml" : ["payment_wizard.xml","payment_view.xml","payment_workflow.xml","payment_sequence.xml"],
|
||||
This module provide :
|
||||
* a more efficient way to manage invoice payment.
|
||||
* a basic mechanism to easily plug various automated payment.
|
||||
""",
|
||||
"demo_xml": [],
|
||||
"update_xml": ["payment_wizard.xml", "payment_view.xml",
|
||||
"payment_workflow.xml", "payment_sequence.xml"],
|
||||
"active": False,
|
||||
"installable": True
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields
|
||||
from osv import osv
|
||||
from osv import fields, osv
|
||||
|
||||
|
||||
class account_move_line(osv.osv):
|
||||
_inherit = "account.move.line"
|
||||
|
@ -37,8 +37,11 @@ class account_move_line(osv.osv):
|
|||
if not ids:
|
||||
return {}
|
||||
cr.execute("""SELECT ml.id,
|
||||
ml.credit -
|
||||
(SELECT coalesce(sum(amount),0)
|
||||
CASE WHEN ml.amount_currency < 0
|
||||
THEN - ml.amount_currency
|
||||
ELSE ml.credit
|
||||
END -
|
||||
(SELECT coalesce(sum(amount_currency),0)
|
||||
FROM payment_line pl
|
||||
INNER JOIN payment_order po
|
||||
ON (pl.order_id = po.id)
|
||||
|
@ -49,36 +52,42 @@ class account_move_line(osv.osv):
|
|||
r=dict(cr.fetchall())
|
||||
return r
|
||||
|
||||
|
||||
def _to_pay_search(self, cr, uid, obj, name, args):
|
||||
if not len(args):
|
||||
return []
|
||||
query = self.pool.get('account.move.line')._query_get(cr, uid, context={})
|
||||
where = ' and '.join(map(lambda x: '''(select l.credit - coalesce(sum(amount),0)
|
||||
from payment_line pl
|
||||
inner join payment_order po on (pl.order_id = po.id)
|
||||
where move_line_id = l.id and po.state != 'cancel') '''+x[1]+str(x[2])+' ',args))
|
||||
line_obj = self.pool.get('account.move.line')
|
||||
query = line_obj._query_get(cr, uid, context={})
|
||||
where = ' and '.join(map(lambda x: '''(SELECT
|
||||
CASE WHEN l.amount_currency < 0
|
||||
THEN - l.amount_currency
|
||||
ELSE l.credit
|
||||
END - coalesce(sum(pl.amount_currency), 0)
|
||||
FROM payment_line pl
|
||||
INNER JOIN payment_order po ON (pl.order_id = po.id)
|
||||
WHERE move_line_id = l.id AND po.state != 'cancel')''' \
|
||||
+ x[1] + str(x[2])+' ',args))
|
||||
|
||||
cr.execute(('''select id
|
||||
from account_move_line l
|
||||
where account_id in (select id from account_account where type=%s and active)
|
||||
and reconcile_id is null
|
||||
and credit > 0
|
||||
and '''+where+' and '+query), ('payable',) )
|
||||
from account_move_line l
|
||||
where account_id in (select id
|
||||
from account_account
|
||||
where type=%s and active)
|
||||
and reconcile_id is null
|
||||
and credit > 0
|
||||
and ''' + where + ' and ' + query), ('payable',) )
|
||||
|
||||
res = cr.fetchall()
|
||||
if not len(res):
|
||||
return [('id','=','0')]
|
||||
return [('id','in',map(lambda x:x[0], res))]
|
||||
|
||||
|
||||
def line2bank(self,cr,uid,ids,payment_type= 'manual',context=None):
|
||||
"""
|
||||
Try to return for each account move line a corresponding bank
|
||||
account according to the payment type. This work using one of
|
||||
the bank of the partner defined on the invoice eventually
|
||||
associated to the line.
|
||||
Return the first suitable bank for the corresponding partner.
|
||||
Return the first suitable bank for the corresponding partner.
|
||||
"""
|
||||
if not ids: return {}
|
||||
bank_type= self.pool.get('payment.mode').suitable_bank_types(cr,uid,payment_type,context=context)
|
||||
|
@ -102,10 +111,11 @@ class account_move_line(osv.osv):
|
|||
elif (line not in type_ok) and (t in bank_type) :
|
||||
line2bank[line]= bank
|
||||
type_ok.append(line)
|
||||
|
||||
return line2bank
|
||||
|
||||
_columns = {
|
||||
'amount_to_pay' : fields.function(amount_to_pay, method=True, type='float', string='Amount to pay', fnct_search=_to_pay_search),
|
||||
}
|
||||
'amount_to_pay' : fields.function(amount_to_pay, method=True,
|
||||
type='float', string='Amount to pay', fnct_search=_to_pay_search),
|
||||
}
|
||||
|
||||
account_move_line()
|
||||
|
|
|
@ -29,6 +29,8 @@ from osv import fields
|
|||
from osv import osv
|
||||
import time
|
||||
import netsvc
|
||||
|
||||
|
||||
class payment_type(osv.osv):
|
||||
_name= 'payment.type'
|
||||
_description= 'Payment type'
|
||||
|
@ -36,12 +38,11 @@ class payment_type(osv.osv):
|
|||
'name': fields.char('Name', size=64, required=True),
|
||||
'code': fields.char('Code', size=64, required=True),
|
||||
'suitable_bank_types': fields.many2many('res.partner.bank.type',
|
||||
'bank_type_payment_type_rel',
|
||||
'pay_type_id','bank_type_id',
|
||||
'Suitable bank types')
|
||||
}
|
||||
'bank_type_payment_type_rel',
|
||||
'pay_type_id','bank_type_id',
|
||||
'Suitable bank types')
|
||||
}
|
||||
|
||||
|
||||
payment_type()
|
||||
|
||||
|
||||
|
@ -50,19 +51,23 @@ class payment_mode(osv.osv):
|
|||
_description= 'Payment mode'
|
||||
_columns= {
|
||||
'name': fields.char('Name', size=64, required=True),
|
||||
'bank_id': fields.many2one('res.partner.bank',"Bank account",required=True),
|
||||
'journal': fields.many2one('account.journal','Journal',required=True,domain=[('type','=','cash')]),
|
||||
'bank_id': fields.many2one('res.partner.bank', "Bank account",
|
||||
required=True),
|
||||
'journal': fields.many2one('account.journal', 'Journal', required=True,
|
||||
domain=[('type', '=', 'cash')]),
|
||||
'type': fields.many2one('payment.type','Payment type',required=True),
|
||||
'account': fields.many2one('account.account','Default payable account',domain=[('type','=','payable')],required=True),
|
||||
}
|
||||
'account': fields.many2one('account.account', 'Default payable account',
|
||||
domain=[('type', '=', 'payable')], required=True),
|
||||
}
|
||||
|
||||
def suitable_bank_types(self,cr,uid,payment_code= 'manual',context={}):
|
||||
""" Return the codes of the bank type that are suitable for the given payment type code"""
|
||||
"""Return the codes of the bank type that are suitable
|
||||
for the given payment type code"""
|
||||
cr.execute(""" select t.code
|
||||
from res_partner_bank_type t
|
||||
join bank_type_payment_type_rel r on (r.bank_type_id = t.id)
|
||||
join payment_type pt on (r.pay_type_id = pt.id)
|
||||
where pt.code = %s """, [payment_code])
|
||||
from res_partner_bank_type t
|
||||
join bank_type_payment_type_rel r on (r.bank_type_id = t.id)
|
||||
join payment_type pt on (r.pay_type_id = pt.id)
|
||||
where pt.code = %s """, [payment_code])
|
||||
return [x[0] for x in cr.fetchall()]
|
||||
|
||||
payment_mode()
|
||||
|
@ -75,18 +80,20 @@ class payment_order(osv.osv):
|
|||
|
||||
def get_wizard(self,type):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel("warning", netsvc.LOG_WARNING, "No wizard found for the payment type '%s'."%type)
|
||||
logger.notifyChannel("warning", netsvc.LOG_WARNING,
|
||||
"No wizard found for the payment type '%s'." % type)
|
||||
return None
|
||||
|
||||
def _total(self, cr, uid, ids, name, args, context={}):
|
||||
if not ids: return {}
|
||||
cr.execute("""SELECT o.id, coalesce(sum(l.amount),0)
|
||||
FROM payment_order o
|
||||
LEFT JOIN payment_line l
|
||||
ON (o.id = l.order_id)
|
||||
WHERE o.id in (%s)
|
||||
GROUP BY o.id""" % ','.join(map(str,ids)))
|
||||
return dict(cr.fetchall())
|
||||
def _total(self, cursor, user, ids, name, args, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
res = {}
|
||||
for order in self.browse(cursor, user, ids, context=context):
|
||||
if order.line_ids:
|
||||
res[order.id] = reduce(lambda x, y: x + y.amount, order.line_ids, 0.0)
|
||||
else:
|
||||
res[order.id] = 0.0
|
||||
return res
|
||||
|
||||
def nb_line(self, cr, uid, ids, name, args, context={}):
|
||||
if not ids: return {}
|
||||
|
@ -102,15 +109,24 @@ class payment_order(osv.osv):
|
|||
'date_planned': fields.date('Scheduled date if fixed'),
|
||||
'reference': fields.char('Reference',size=128),
|
||||
'mode': fields.many2one('payment.mode','Payment mode', select=True),
|
||||
'state': fields.selection([('draft', 'Draft'),('open','Open'),
|
||||
('cancel','Cancelled'),('done','Done')], 'State', select=True),
|
||||
'state': fields.selection([
|
||||
('draft', 'Draft'),
|
||||
('open','Open'),
|
||||
('cancel','Cancelled'),
|
||||
('done','Done')], 'State', select=True),
|
||||
'line_ids': fields.one2many('payment.line','order_id','Payment lines'),
|
||||
'total': fields.function(_total, string="Total", method=True, type='float'),
|
||||
'total': fields.function(_total, string="Total", method=True,
|
||||
type='float'),
|
||||
'user_id': fields.many2one('res.users','User',required=True),
|
||||
'nb_line': fields.function(nb_line,string='Number of payment',method=True, type='integer'),
|
||||
'date_prefered': fields.selection([('now','Directly'),('due','Due date'),('fixed','Fixed date')],"Prefered date",required=True),
|
||||
'date_created': fields.date('Creation date',readonly=True),
|
||||
'date_done': fields.date('Execution date',readonly=True),
|
||||
'nb_line': fields.function(nb_line,string='Number of payment',
|
||||
method=True, type='integer'),
|
||||
'date_prefered': fields.selection([
|
||||
('now', 'Directly'),
|
||||
('due', 'Due date'),
|
||||
('fixed', 'Fixed date')
|
||||
], "Prefered date", required=True),
|
||||
'date_created': fields.date('Creation date', readonly=True),
|
||||
'date_done': fields.date('Execution date', readonly=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -118,7 +134,9 @@ class payment_order(osv.osv):
|
|||
'state': lambda *a: 'draft',
|
||||
'date_prefered': lambda *a: 'due',
|
||||
'date_created': lambda *a: time.strftime('%Y-%m-%d'),
|
||||
}
|
||||
'reference': lambda self,cr,uid,context: self.pool.get('ir.sequence'
|
||||
).get(cr, uid, 'payment.order'),
|
||||
}
|
||||
|
||||
def set_to_draft(self, cr, uid, ids, *args):
|
||||
self.write(cr, uid, ids, {'state':'draft'})
|
||||
|
@ -135,70 +153,198 @@ class payment_order(osv.osv):
|
|||
return True
|
||||
|
||||
def set_done(self, cr, uid, id, *args):
|
||||
self.write(cr,uid,id,{'date_done':time.strftime('%Y-%m-%d'),
|
||||
'state':'done',})
|
||||
self.write(cr,uid,id,{'date_done': time.strftime('%Y-%m-%d'),
|
||||
'state': 'done',})
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
wf_service.trg_validate(uid, 'payment.order', id, 'done', cr)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
payment_order()
|
||||
|
||||
|
||||
class payment_line(osv.osv):
|
||||
_name = 'payment.line'
|
||||
_description = 'Payment Line'
|
||||
_rec_name = 'move_line_id'
|
||||
|
||||
def partner_payable(self, cr, uid, ids, name, args, context={}):
|
||||
if not ids: return {}
|
||||
partners= self.read(cr, uid, ids, ['partner_id'], context)
|
||||
partners= dict(map(lambda x: (x['id'],x['partner_id']),partners))
|
||||
debit= self.pool.get('res.partner')._debit_get(cr, uid,
|
||||
partners.values(), name,
|
||||
args, context)
|
||||
partners= dict(map(lambda x: (x['id'], x['partner_id'][0]), partners))
|
||||
debit = self.pool.get('res.partner')._debit_get(cr, uid,
|
||||
partners.values(), name, args, context)
|
||||
for i in partners:
|
||||
partners[i]= debit[partners[i]]
|
||||
partners[i] = debit[partners[i]]
|
||||
return partners
|
||||
|
||||
def translate(self,orig):
|
||||
return {"to_pay":"credit",
|
||||
"due_date":"date_maturity",
|
||||
"reference":"ref"}.get(orig,orig)
|
||||
|
||||
def select_by_name(self, cr, uid, ids, name, args, context={}):
|
||||
def translate(self, orig):
|
||||
return {"to_pay": "credit",
|
||||
"due_date": "date_maturity",
|
||||
"reference": "ref"}.get(orig, orig)
|
||||
|
||||
def select_by_name(self, cr, uid, ids, name, args, context=None):
|
||||
if not ids: return {}
|
||||
cr.execute("""SELECT pl.id, ml.%s
|
||||
from account_move_line ml
|
||||
inner join payment_line pl on (ml.id= pl.move_line_id)
|
||||
where pl.id in (%s)"""% (self.translate(name),','.join(map(str,ids))) )
|
||||
return dict(cr.fetchall())
|
||||
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
cr.execute("""SELECT pl.id, ml.%s
|
||||
from account_move_line ml
|
||||
inner join payment_line pl
|
||||
on (ml.id = pl.move_line_id)
|
||||
where pl.id in (%s)"""%
|
||||
(self.translate(name), ','.join(map(str,ids))) )
|
||||
res = dict(cr.fetchall())
|
||||
|
||||
if name == 'partner_id':
|
||||
partner_name = {}
|
||||
for p_id, p_name in partner_obj.name_get(cr,uid,
|
||||
filter(lambda x:x and x != 0,res.values()),context=context):
|
||||
partner_name[p_id] = p_name
|
||||
|
||||
for id in ids:
|
||||
if id in res:
|
||||
res[id] = (res[id],partner_name[res[id]])
|
||||
else:
|
||||
res[id] = (False,False)
|
||||
else:
|
||||
for id in ids:
|
||||
res.setdefault(id, (False, ""))
|
||||
return res
|
||||
|
||||
def _currency(self, cursor, user, ids, name, args, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
res = {}
|
||||
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
account_obj = self.pool.get('account.account')
|
||||
cursor.execute('''SELECT pl.id, ml.currency_id, ml.account_id
|
||||
FROM account_move_line ml
|
||||
INNER JOIN payment_line pl
|
||||
ON (ml.id = pl.move_line_id)
|
||||
WHERE pl.id in (''' + ','.join([str(x) for x in ids]) + ')')
|
||||
|
||||
res2 = {}
|
||||
account_ids = []
|
||||
for payment_line_id, currency_id, account_id in cursor.fetchall():
|
||||
res2[payment_line_id] = [currency_id, account_id]
|
||||
account_ids.append(account_id)
|
||||
|
||||
account2currency_id = {}
|
||||
for account in account_obj.browse(cursor, user, account_ids,
|
||||
context=context):
|
||||
account2currency_id[account.id] = account.company_currency_id.id
|
||||
|
||||
for payment_line_id in ids:
|
||||
if res2[payment_line_id][0]:
|
||||
res[payment_line_id] = res2[payment_line_id][0]
|
||||
else:
|
||||
res[payment_line_id] = \
|
||||
account2currency_id[res2[payment_line_id][1]]
|
||||
|
||||
currency_names = {}
|
||||
for currency_id, name in currency_obj.name_get(cursor, user, res.values(),
|
||||
context=context):
|
||||
currency_names[currency_id] = name
|
||||
for payment_line_id in ids:
|
||||
res[payment_line_id] = (res[payment_line_id],
|
||||
currency_names[res[payment_line_id]])
|
||||
return res
|
||||
|
||||
def _to_pay_currency(self, cursor, user, ids, name , args, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
|
||||
cursor.execute('''SELECT pl.id,
|
||||
CASE WHEN ml.amount_currency < 0
|
||||
THEN - ml.amount_currency
|
||||
ELSE ml.credit
|
||||
END
|
||||
FROM account_move_line ml
|
||||
INNER JOIN payment_line pl
|
||||
ON (ml.id = pl.move_line_id)
|
||||
WHERE pl.id in (''' + ','.join([str(x) for x in ids]) + ')')
|
||||
return dict(cursor.fetchall())
|
||||
|
||||
def _amount(self, cursor, user, ids, name, args, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
for line in self.browse(cursor, user, ids, context=context):
|
||||
ctx = context.copy()
|
||||
ctx['date'] = line.order_id.date_done or time.strftime('%Y-%m-%d')
|
||||
res[line.id] = currency_obj.compute(cursor, user, line.currency.id,
|
||||
line.move_line_id.account_id.company_currency_id.id,
|
||||
line.amount_currency, context=ctx)
|
||||
return res
|
||||
|
||||
def _value_date(self, cursor, user, ids, name, args, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
res = {}
|
||||
for line in self.browse(cursor, user, ids, context=context):
|
||||
if line.order_id.date_prefered == 'fixed':
|
||||
res[line.id] = line.order_id.date_planned
|
||||
elif line.order_id.date_prefered == 'due':
|
||||
res[line.id] = line.due_date or time.strftime('%Y-%m-%d')
|
||||
else:
|
||||
res[line.id] = time.strftime('%Y-%m-%d')
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'move_line_id': fields.many2one('account.move.line','Entry line',required=True),
|
||||
'amount': fields.float('Payment Amount', digits=(16,2), required=True),
|
||||
'bank_id': fields.many2one('res.partner.bank','Bank account'),
|
||||
'order_id': fields.many2one('payment.order','Order', ondelete='cascade', select=True),
|
||||
'partner_id': fields.function(select_by_name, string="Partner", method=True, type='many2one', obj='res.partner'),
|
||||
'to_pay': fields.function(select_by_name, string="To pay", method=True, type='float'),
|
||||
'due_date': fields.function(select_by_name, string="Due date", method=True, type='date'),
|
||||
'date_created': fields.function(select_by_name, string="Creation date", method=True, type='date'),
|
||||
'reference': fields.function(select_by_name, string="Ref", method=True, type='char'),
|
||||
'partner_payable': fields.function(partner_payable, string="Partner payable", method=True, type='float'),
|
||||
'name': fields.char('Name', size=64, required=True, readonly=True),
|
||||
'move_line_id': fields.many2one('account.move.line','Entry line',
|
||||
required=True),
|
||||
'amount_currency': fields.float('Amount', digits=(16,2),
|
||||
required=True, help='Payment amount in the partner currency'),
|
||||
'to_pay_currency': fields.function(_to_pay_currency, string='To Pay',
|
||||
method=True, type='float',
|
||||
help='Amount to pay in the partner currency'),
|
||||
'currency': fields.function(_currency, string='Currency',
|
||||
method=True, type='many2one', obj='res.currency'),
|
||||
'bank_id': fields.many2one('res.partner.bank', 'Bank account'),
|
||||
'order_id': fields.many2one('payment.order', 'Order', required=True,
|
||||
ondelete='cascade', select=True),
|
||||
'partner_id': fields.function(select_by_name, string="Partner",
|
||||
method=True, type='many2one', obj='res.partner'),
|
||||
'amount': fields.function(_amount, string='Amount',
|
||||
method=True, type='float',
|
||||
help='Payment amount in the company currency'),
|
||||
'to_pay': fields.function(select_by_name, string="To Pay", method=True,
|
||||
type='float', help='Amount to pay in the company currency'),
|
||||
'due_date': fields.function(select_by_name, string="Due date",
|
||||
method=True, type='date'),
|
||||
'date_created': fields.function(select_by_name, string="Creation date",
|
||||
method=True, type='date'),
|
||||
'reference': fields.function(select_by_name, string="Ref", method=True,
|
||||
type='char'),
|
||||
'partner_payable': fields.function(partner_payable,
|
||||
string="Partner payable", method=True, type='float'),
|
||||
'value_date': fields.function(_value_date, string='Value Date',
|
||||
method=True, type='date'),
|
||||
}
|
||||
def onchange_move_line(self, cr, uid, id, move_line_id, payment_type,context={}):
|
||||
_defaults = {
|
||||
'name': lambda obj, cursor, user, context: obj.pool.get('ir.sequence'
|
||||
).get(cursor, user, 'payment.line'),
|
||||
}
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'UNIQUE(name)', 'The payment line name must be unique!'),
|
||||
]
|
||||
|
||||
def onchange_move_line(self, cr, uid, id, move_line_id, payment_type,context=None):
|
||||
if not move_line_id:
|
||||
return {}
|
||||
line=self.pool.get('account.move.line').browse(cr,uid,move_line_id)
|
||||
return {'value': {'amount': line.amount_to_pay,
|
||||
'to_pay': line.amount_to_pay,
|
||||
return {'value': {
|
||||
'amount_currency': line.amount_to_pay,
|
||||
'to_pay_currency': line.amount_to_pay,
|
||||
'partner_id': line.partner_id.id,
|
||||
'reference': line.ref,
|
||||
'date_created': line.date_created,
|
||||
'bank_id': self.pool.get('account.move.line').line2bank(cr, uid,
|
||||
[move_line_id],
|
||||
payment_type or 'manual',context)[move_line_id]
|
||||
payment_type or 'manual', context)[move_line_id]
|
||||
}}
|
||||
|
||||
payment_line()
|
||||
|
|
|
@ -1,16 +1,29 @@
|
|||
<?xml version="1.0"?>
|
||||
<terp>
|
||||
<data noupdate="1">
|
||||
<record model="ir.sequence.type" id="seq_type_payment_order">
|
||||
<field name="name">Payment order</field>
|
||||
<field name="code">payment.order</field>
|
||||
</record>
|
||||
<data noupdate="1">
|
||||
<record model="ir.sequence.type" id="seq_type_payment_order" forcecreate="1">
|
||||
<field name="name">Payment order</field>
|
||||
<field name="code">payment.order</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="seq_payment_order">
|
||||
<field name="name">Payment order</field>
|
||||
<field name="code">payment.order</field>
|
||||
<field name="padding" eval="3"/>
|
||||
<field name="prefix">%(year)s/</field>
|
||||
</record>
|
||||
</data>
|
||||
<record model="ir.sequence" id="seq_payment_order" forcecreate="1">
|
||||
<field name="name">Payment order</field>
|
||||
<field name="code">payment.order</field>
|
||||
<field name="padding" eval="3"/>
|
||||
<field name="prefix">%(year)s/</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence.type" id="seq_type_payment_line" forcecreate="1">
|
||||
<field name="name">Payment Line</field>
|
||||
<field name="code">payment.line</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="seq_payment_line" forcecreate="1">
|
||||
<field name="name">Payment Line</field>
|
||||
<field name="code">payment.line</field>
|
||||
<field name="prefix"></field>
|
||||
<field name="padding">3</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</terp>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" ?>
|
||||
<terp>
|
||||
<data>
|
||||
<menuitem name="Financial Management/Payment Management" id="menu_main" />
|
||||
<menuitem name="Financial Management/Payment Management/Configuration" groups="admin" sequence="1"/>
|
||||
<menuitem name="Financial Management/Payment" id="menu_main" />
|
||||
<menuitem name="Financial Management/Configuration" groups="admin" sequence="1"/>
|
||||
|
||||
<record model="ir.ui.view" id="view_payment_type_form">
|
||||
<field name="name">payment.type.form</field>
|
||||
|
@ -13,7 +13,7 @@
|
|||
<field name="name" select="1"/>
|
||||
<field name="code"/>
|
||||
<newline/>
|
||||
<field name="suitable_bank_types" select="1"/>
|
||||
<field name="suitable_bank_types" select="1" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -23,7 +23,8 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem name="Financial Management/Payment Management/Configuration/Payment Type" id="menu_action_payment_type_form" action="action_payment_type_form"/>
|
||||
<menuitem name="Financial Management/Configuration/Payment/Payment Type"
|
||||
id="menu_action_payment_type_form" action="action_payment_type_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="view_payment_mode_tree">
|
||||
<field name="name">payment.mode.tree</field>
|
||||
|
@ -58,10 +59,11 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Financial Management/Payment Management/Configuration/Payment Mode"
|
||||
id="menu_action_payment_mode_form" action="action_payment_mode_form"/>
|
||||
<record model="ir.ui.view" id="view_payment_order_form">
|
||||
<menuitem
|
||||
name="Financial Management/Configuration/Payment/Payment Mode"
|
||||
id="menu_action_payment_mode_form" action="action_payment_mode_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="view_payment_order_form">
|
||||
<field name="name">payment.order.form</field>
|
||||
<field name="model">payment.order</field>
|
||||
<field name="type">form</field>
|
||||
|
@ -88,7 +90,7 @@
|
|||
<button name="set_to_draft" states="cancel"
|
||||
type="object" string="Set to draft"/>
|
||||
</group>
|
||||
</form>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
@ -115,12 +117,12 @@
|
|||
<field name="name">Payment order</field>
|
||||
<field name="res_model">payment.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
</record>
|
||||
<menuitem name="Financial Management/Payment Management/Payment Orders"
|
||||
id="menu_action_payment_order_form"
|
||||
action="action_payment_order_tree"
|
||||
sequence="3"/>
|
||||
<menuitem name="Financial Management/Payment/Payment Orders"
|
||||
id="menu_action_payment_order_form"
|
||||
action="action_payment_order_tree"
|
||||
sequence="3"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_payment_order_draft">
|
||||
<field name="name">Draft payment order</field>
|
||||
|
@ -129,10 +131,10 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
</record>
|
||||
<menuitem name="Financial Management/Payment Management/Payment Orders/Draft Payment Orders"
|
||||
id="menu_action_payment_order_draft"
|
||||
action="action_payment_order_draft"
|
||||
sequence="1"/>
|
||||
<menuitem name="Financial Management/Payment/Payment Orders/Draft Payment Orders"
|
||||
id="menu_action_payment_order_draft"
|
||||
action="action_payment_order_draft"
|
||||
sequence="1"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_payment_order_open">
|
||||
<field name="name">Payment orders to validate</field>
|
||||
|
@ -141,14 +143,10 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','open')]</field>
|
||||
</record>
|
||||
<menuitem name="Financial Management/Payment Management/Payment Orders/Payment Orders to Validate"
|
||||
id="menu_action_payment_order_open"
|
||||
action="action_payment_order_open"
|
||||
sequence="2"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<menuitem name="Financial Management/Payment/Payment Orders/Payment Orders to Validate"
|
||||
id="menu_action_payment_order_open"
|
||||
action="action_payment_order_open"
|
||||
sequence="2"/>
|
||||
|
||||
<record model="ir.ui.view" id="view_payment_line_form">
|
||||
<field name="name">Payment Line</field>
|
||||
|
@ -156,15 +154,21 @@
|
|||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Payment Line">
|
||||
<field name="move_line_id"
|
||||
select="1" on_change="onchange_move_line(move_line_id,parent.mode.type.code)" domain="[('reconcile_id','=', False), ('credit', '>',0),('amount_to_pay','>',0)] "/>
|
||||
<field name="amount" select="1" />
|
||||
<field name="move_line_id"
|
||||
select="1"
|
||||
on_change="onchange_move_line(move_line_id,parent.mode.type.code)"
|
||||
domain="[('reconcile_id','=', False), ('credit', '>',0),('amount_to_pay','>',0)] "/>
|
||||
<newline/>
|
||||
<field name="amount_currency" select="1"/>
|
||||
<field name="to_pay_currency"/>
|
||||
<field name="currency"/>
|
||||
<field name="bank_id" domain="[('partner_id','=',partner_id)]"/>
|
||||
<field name="to_pay"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="partner_payable"/>
|
||||
<field name="reference"/>
|
||||
<field name="due_date"/>
|
||||
<field name="amount" select="2" />
|
||||
<field name="to_pay"/>
|
||||
<field name="partner_payable"/>
|
||||
<field name="date_created"/>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -175,16 +179,23 @@
|
|||
<field name="type">tree</field>
|
||||
<field name="priority" eval="4"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Payment Line" editable="bottom" colors="red:to_pay<amount" >
|
||||
<field name="move_line_id" select="1" on_change="onchange_move_line(move_line_id,parent.mode)" domain="[('reconcile_id','=', False), ('credit', '>',0),('amount_to_pay','>',0)] "/>
|
||||
<field name="bank_id" domain="[('partner_id','=',partner_id)]"/>
|
||||
<field name="amount"/>
|
||||
<field name="to_pay"/>
|
||||
<tree string="Payment Line" editable="bottom"
|
||||
colors="red:to_pay_currency<amount_currency">
|
||||
<field name="move_line_id" select="1"
|
||||
on_change="onchange_move_line(move_line_id,parent.mode)"
|
||||
domain="[('reconcile_id', '=', False), ('credit', '>', 0), ('amount_to_pay', '>', 0)]"/>
|
||||
<field name="bank_id" domain="[('partner_id', '=', partner_id)]"/>
|
||||
<field name="amount_currency"/>
|
||||
<field name="to_pay_currency"/>
|
||||
<field name="currency"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="partner_payable"/>
|
||||
<field name="reference"/>
|
||||
<field name="due_date"/>
|
||||
<field name="amount"/>
|
||||
<field name="to_pay"/>
|
||||
<field name="partner_payable"/>
|
||||
<field name="date_created"/>
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -195,6 +206,18 @@
|
|||
<field name="view_mode">form,tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_bank_statement_form">
|
||||
<field name="name">account.bank.statement.form.inherit</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="period_id" position="after">
|
||||
<button name="%(wizard_populate_statement)d"
|
||||
string="Import payment lines" type="action" colspan="2"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</terp>
|
||||
|
|
|
@ -2,18 +2,25 @@
|
|||
<terp>
|
||||
<data>
|
||||
<wizard
|
||||
string="Populate payment"
|
||||
model="payment.order"
|
||||
name="populate_payment"
|
||||
menu="False"
|
||||
id="wizard_populate_payment"/>
|
||||
string="Populate payment"
|
||||
model="payment.order"
|
||||
name="populate_payment"
|
||||
menu="False"
|
||||
id="wizard_populate_payment"/>
|
||||
|
||||
<wizard
|
||||
string="Pay"
|
||||
model="payment.order"
|
||||
name="pay_payment"
|
||||
menu="False"
|
||||
id="wizard_pay_payment"/>
|
||||
string="Pay"
|
||||
model="payment.order"
|
||||
name="pay_payment"
|
||||
menu="False"
|
||||
id="wizard_pay_payment"/>
|
||||
|
||||
<wizard
|
||||
string="Populate Statement with Payment lines"
|
||||
model="account.bank.statement"
|
||||
name="populate_statement"
|
||||
menu="False"
|
||||
id="wizard_populate_statement"/>
|
||||
|
||||
</data>
|
||||
</terp>
|
||||
|
|
|
@ -29,3 +29,4 @@
|
|||
|
||||
import wizard_payment_order
|
||||
import wizard_pay
|
||||
import wizard_populate_statement
|
||||
|
|
|
@ -25,88 +25,92 @@
|
|||
#
|
||||
##############################################################################
|
||||
import wizard
|
||||
from osv import osv
|
||||
import pooler
|
||||
from osv import fields
|
||||
import time
|
||||
from tools.misc import UpdateableStr
|
||||
|
||||
|
||||
|
||||
ask_form="""<?xml version="1.0"?>
|
||||
<form string="Populate Payment : ">
|
||||
<field name="entries"/>
|
||||
</form>
|
||||
"""
|
||||
ask_fields={
|
||||
'entries': {'string':'Entries', 'type':'many2many',
|
||||
'relation': 'account.move.line',},
|
||||
}
|
||||
FORM = UpdateableStr()
|
||||
|
||||
FIELDS = {
|
||||
'entries': {'string':'Entries', 'type':'many2many',
|
||||
'relation': 'account.move.line',},
|
||||
}
|
||||
|
||||
|
||||
def search_entries(self, cr, uid, data, context):
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
line_obj = pool.get('account.move.line')
|
||||
|
||||
pool= pooler.get_pool(cr.dbname)
|
||||
# Search for move line to pay:
|
||||
mline_ids = pool.get('account.move.line').search(cr, uid,
|
||||
[('reconcile_id', '=', False),
|
||||
('amount_to_pay', '>', 0)],
|
||||
context=context)
|
||||
line_ids = line_obj.search(cr, uid, [
|
||||
('reconcile_id', '=', False),
|
||||
('amount_to_pay', '>', 0)], context=context)
|
||||
|
||||
if not mline_ids:
|
||||
ask_fields['entries']['domain']= [('id', 'in', [])]
|
||||
return {}
|
||||
|
||||
ask_fields['entries']['domain']= [('id', 'in', mline_ids)]
|
||||
return {'entries': mline_ids}
|
||||
FORM.string = '''<?xml version="1.0"?>
|
||||
<form string="Populate Payment:">
|
||||
<field name="entries" colspan="4" height="300" width="800" nolabel="1"
|
||||
domain="[('id', 'in', [%s])]"/>
|
||||
</form>''' % (','.join([str(x) for x in line_ids]))
|
||||
return {'entries': line_ids}
|
||||
|
||||
def create_payment(self, cr, uid, data, context):
|
||||
mline_ids= data['form']['entries'][0][2]
|
||||
if not mline_ids: return {}
|
||||
line_ids= data['form']['entries'][0][2]
|
||||
if not line_ids: return {}
|
||||
|
||||
pool= pooler.get_pool(cr.dbname)
|
||||
payment = pool.get('payment.order').browse(cr, uid, data['id'],
|
||||
order_obj = pool.get('payment.order')
|
||||
line_obj = pool.get('account.move.line')
|
||||
|
||||
payment = order_obj.browse(cr, uid, data['id'],
|
||||
context=context)
|
||||
t= payment.mode and payment.mode.type.code or 'manual'
|
||||
line2bank= pool.get('account.move.line').line2bank(cr,uid,
|
||||
mline_ids,t,context)
|
||||
t = payment.mode and payment.mode.type.code or 'manual'
|
||||
line2bank= pool.get('account.move.line').line2bank(cr, uid,
|
||||
line_ids, t, context)
|
||||
|
||||
## Finally populate the current payment with new lines:
|
||||
for line in pool.get('account.move.line').browse(cr, uid, mline_ids,
|
||||
context=context):
|
||||
for line in line_obj.browse(cr, uid, line_ids, context=context):
|
||||
pool.get('payment.line').create(cr,uid,{
|
||||
'move_line_id': line.id,
|
||||
'amount': line.amount_to_pay,
|
||||
'amount_currency': line.amount_to_pay,
|
||||
'bank_id': line2bank.get(line.id),
|
||||
'order_id': payment.id,
|
||||
})
|
||||
|
||||
}, context=context)
|
||||
return {}
|
||||
|
||||
|
||||
class wizard_payment_order(wizard.interface):
|
||||
"""
|
||||
Create a payment object with lines corresponding to the account move line
|
||||
to pay according to the date and the mode provided by the user.
|
||||
Hypothesis:
|
||||
- Small number of non-reconcilied move line , payment mode and bank account type,
|
||||
- Small number of non-reconcilied move line , payment mode and bank account type,
|
||||
- Big number of partner and bank account.
|
||||
|
||||
If a type is given, unsuitable account move lines are ignored.
|
||||
"""
|
||||
states = {'init' : {'actions':[search_entries],
|
||||
'result': {'type':'form',
|
||||
'arch':ask_form,
|
||||
'fields':ask_fields,
|
||||
'state':[('end','_Cancel'),('create','_Add to payment order')]}
|
||||
|
||||
},
|
||||
|
||||
'create': {'actions': [],
|
||||
'result': {'type':'action',
|
||||
'action':create_payment,
|
||||
'state':'end'}
|
||||
},
|
||||
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [search_entries],
|
||||
'result': {
|
||||
'type': 'form',
|
||||
'arch': FORM,
|
||||
'fields': FIELDS,
|
||||
'state': [
|
||||
('end','_Cancel'),
|
||||
('create','_Add to payment order', '', True)
|
||||
]
|
||||
},
|
||||
},
|
||||
'create': {
|
||||
'actions': [],
|
||||
'result': {
|
||||
'type': 'action',
|
||||
'action': create_payment,
|
||||
'state': 'end'}
|
||||
},
|
||||
}
|
||||
|
||||
wizard_payment_order('populate_payment')
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2005-2007 TINY SPRL. (http://tiny.be) All Rights Reserved.
|
||||
#
|
||||
# WARNING: This program as such is intended to be used by professional
|
||||
# programmers who take the whole responsability of assessing all potential
|
||||
# consequences resulting from its eventual inadequacies and bugs
|
||||
# End users who are looking for a ready-to-use solution with commercial
|
||||
# garantees and support are strongly adviced to contract a Free Software
|
||||
# Service Company
|
||||
#
|
||||
# This program is Free Software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
##############################################################################
|
||||
import wizard
|
||||
import pooler
|
||||
from tools.misc import UpdateableStr
|
||||
|
||||
FORM = UpdateableStr()
|
||||
|
||||
FIELDS = {
|
||||
'lines': {'string': 'Payment Lines', 'type': 'many2many',
|
||||
'relation': 'payment.line'},
|
||||
}
|
||||
|
||||
def _search_entries(obj, cursor, user, data, context):
|
||||
pool = pooler.get_pool(cursor.dbname)
|
||||
line_obj = pool.get('payment.line')
|
||||
statement_obj = pool.get('account.bank.statement')
|
||||
|
||||
statement = statement_obj.browse(cursor, user, data['id'], context=context)
|
||||
|
||||
line_ids = line_obj.search(cursor, user, [
|
||||
('move_line_id.reconcile_id', '=', False),
|
||||
('order_id.mode.journal.id', '=', statement.journal_id.id)])
|
||||
line_ids.extend(line_obj.search(cursor, user, [
|
||||
('move_line_id.reconcile_id', '=', False),
|
||||
('order_id.mode', '=', False)]))
|
||||
|
||||
FORM.string = '''<?xml version="1.0"?>
|
||||
<form string="Populate Statement:">
|
||||
<field name="lines" colspan="4" height="300" width="800" nolabel="1"
|
||||
domain="[('id', 'in', [%s])]"/>
|
||||
</form>''' % (','.join([str(x) for x in line_ids]))
|
||||
return {'lines': line_ids}
|
||||
|
||||
def _populate_statement(obj, cursor, user, data, context):
|
||||
line_ids = data['form']['lines'][0][2]
|
||||
if not line_ids:
|
||||
return {}
|
||||
|
||||
pool = pooler.get_pool(cursor.dbname)
|
||||
line_obj = pool.get('payment.line')
|
||||
statement_obj = pool.get('account.bank.statement')
|
||||
statement_line_obj = pool.get('account.bank.statement.line')
|
||||
currency_obj = pool.get('res.currency')
|
||||
statement_reconcile_obj = pool.get('account.bank.statement.reconcile')
|
||||
|
||||
statement = statement_obj.browse(cursor, user, data['id'], context=context)
|
||||
|
||||
for line in line_obj.browse(cursor, user, line_ids, context=context):
|
||||
ctx = context.copy()
|
||||
ctx['date'] = line.value_date
|
||||
amount = currency_obj.compute(cursor, user, line.currency.id,
|
||||
statement.currency.id, line.amount_currency, context=ctx)
|
||||
reconcile_id = statement_reconcile_obj.create(cursor, user, {
|
||||
'line_ids': [(6, 0, [line.move_line_id.id])]
|
||||
}, context=context)
|
||||
statement_line_obj.create(cursor, user, {
|
||||
'name': line.order_id.reference or '?',
|
||||
'amount': - amount,
|
||||
'type': 'supplier',
|
||||
'partner_id': line.partner_id.id,
|
||||
'account_id': line.move_line_id.account_id.id,
|
||||
'statement_id': statement.id,
|
||||
'ref': line.reference,
|
||||
'reconcile_id': reconcile_id,
|
||||
}, context=context)
|
||||
return {}
|
||||
|
||||
|
||||
class PopulateStatement(wizard.interface):
|
||||
"""
|
||||
Populate the current statement with selected payement lines
|
||||
"""
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [_search_entries],
|
||||
'result': {
|
||||
'type': 'form',
|
||||
'arch': FORM,
|
||||
'fields': FIELDS,
|
||||
'state': [
|
||||
('end', '_Cancel'),
|
||||
('add', '_Add', '', True)
|
||||
]
|
||||
},
|
||||
},
|
||||
'add': {
|
||||
'actions': [],
|
||||
'result': {
|
||||
'type': 'action',
|
||||
'action': _populate_statement,
|
||||
'state': 'end'
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
PopulateStatement('populate_statement')
|
Loading…
Reference in New Issue