[MERGE] sync with latest trunk @2012-12-21

bzr revid: xal@openerp.com-20121221100330-b0aw0q6txzbq9t0g
This commit is contained in:
Xavier ALT 2012-12-21 11:03:30 +01:00
commit 6f0f58562d
5060 changed files with 440626 additions and 314329 deletions

View File

@ -133,7 +133,9 @@ for a particular financial year and for preparation of vouchers there is a modul
"static/src/xml/account_move_reconciliation.xml",
"static/src/xml/account_move_line_quickadd.xml",
],
'css':['static/src/css/account_move_reconciliation.css'
'css':[
'static/src/css/account_move_reconciliation.css',
'static/src/css/account_move_line_quickadd.css'
],
'demo': [
'demo/account_demo.xml',
@ -141,7 +143,7 @@ for a particular financial year and for preparation of vouchers there is a modul
'project/analytic_account_demo.xml',
'demo/account_minimal.xml',
'demo/account_invoice_demo.xml',
# 'account_unit_test.xml',
'account_unit_test.xml',
],
'test': [
'test/account_customer_invoice.yml',

View File

@ -19,19 +19,19 @@
#
##############################################################################
import time
import logging
from datetime import datetime
from dateutil.relativedelta import relativedelta
from operator import itemgetter
import time
import logging
import pooler
from osv import fields, osv
import decimal_precision as dp
from tools.translate import _
from tools.float_utils import float_round
from openerp import SUPERUSER_ID
import tools
from openerp import pooler, tools
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round
import openerp.addons.decimal_precision as dp
_logger = logging.getLogger(__name__)
@ -75,8 +75,8 @@ class account_payment_term(osv.osv):
amount = value
result = []
obj_precision = self.pool.get('decimal.precision')
prec = obj_precision.precision_get(cr, uid, 'Account')
for line in pt.line_ids:
prec = obj_precision.precision_get(cr, uid, 'Account')
if line.value == 'fixed':
amt = round(line.value_amount, prec)
elif line.value == 'procent':
@ -92,19 +92,20 @@ class account_payment_term(osv.osv):
next_date += relativedelta(day=line.days2, months=1)
result.append( (next_date.strftime('%Y-%m-%d'), amt) )
amount -= amt
return result
account_payment_term()
amount = reduce(lambda x,y: x+y[1], result, 0.0)
dist = round(value-amount, prec)
if dist:
result.append( (time.strftime('%Y-%m-%d'), dist) )
return result
class account_payment_term_line(osv.osv):
_name = "account.payment.term.line"
_description = "Payment Term Line"
_columns = {
'name': fields.char('Line Name', size=32, required=True),
'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')], 'Valuation',
('fixed', 'Fixed Amount')], 'Computation',
required=True, help="""Select here the kind of valuation related to this payment term line. Note that you should have your last line with the type 'Balance' to ensure that the whole amount will be treated."""),
'value_amount': fields.float('Amount To Pay', digits_compute=dp.get_precision('Payment Term'), help="For percent enter a ratio between 0-1."),
@ -115,10 +116,10 @@ class account_payment_term_line(osv.osv):
}
_defaults = {
'value': 'balance',
'sequence': 5,
'days': 30,
'days2': 0,
}
_order = "sequence"
_order = "value desc,days"
def _check_percent(self, cr, uid, ids, context=None):
obj = self.browse(cr, uid, ids[0], context=context)
@ -1013,10 +1014,15 @@ class account_period(osv.osv):
else:
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
args.append(('company_id', '=', company_id))
ids = self.search(cr, uid, args, context=context)
if not ids:
raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
return ids
result = []
if context.get('account_period_prefer_normal'):
# look for non-special periods first, and fallback to all if no result is found
result = self.search(cr, uid, args + [('special', '=', False)], context=context)
if not result:
result = self.search(cr, uid, args, context=context)
if not result:
raise osv.except_osv(_('Error !'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
return result
def action_draft(self, cr, uid, ids, *args):
mode = 'draft'
@ -1082,7 +1088,7 @@ class account_journal_period(osv.osv):
'journal_id': fields.many2one('account.journal', 'Journal', required=True, ondelete="cascade"),
'period_id': fields.many2one('account.period', 'Period', required=True, ondelete="cascade"),
'icon': fields.function(_icon_get, string='Icon', type='char', size=32),
'active': fields.boolean('Active', required=True, help="If the active field is set to False, it will allow you to hide the journal period without removing it."),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the journal period without removing it."),
'state': fields.selection([('draft','Draft'), ('printed','Printed'), ('done','Done')], 'Status', required=True, readonly=True,
help='When journal period is created. The status is \'Draft\'. If a report is printed it comes to \'Printed\' status. When all transactions are done, it comes in \'Done\' status.'),
'fiscalyear_id': fields.related('period_id', 'fiscalyear_id', string='Fiscal Year', type='many2one', relation='account.fiscalyear'),
@ -1190,10 +1196,9 @@ class account_move(osv.osv):
return res
def _get_period(self, cr, uid, context=None):
periods = self.pool.get('account.period').find(cr, uid)
if periods:
return periods[0]
return False
ctx = dict(context or {}, account_period_prefer_normal=True)
period_ids = self.pool.get('account.period').find(cr, uid, context=ctx)
return period_ids[0]
def _amount_compute(self, cr, uid, ids, name, args, context, where =''):
if not ids: return {}
@ -2304,8 +2309,13 @@ class account_model(osv.osv):
if not line.partner_id:
raise osv.except_osv(_('Error!'), _("Maturity date of entry line generated by model line '%s' of model '%s' is based on partner payment term!" \
"\nPlease define partner on it!")%(line.name, model.name))
if line.partner_id.property_payment_term:
payment_term_id = False
if model.journal_id.type in ('purchase', 'purchase_refund') and line.partner_id.property_supplier_payment_term:
payment_term_id = line.partner_id.property_supplier_payment_term.id
elif line.partner_id.property_payment_term:
payment_term_id = line.partner_id.property_payment_term.id
if payment_term_id:
pterm_list = pt_obj.compute(cr, uid, payment_term_id, value=1, date_ref=date_maturity)
if pterm_list:
pterm_list = [l[0] for l in pterm_list]
@ -3342,10 +3352,25 @@ class wizard_multi_charts_accounts(osv.osv_memory):
all the provided information to create the accounts, the banks, the journals, the taxes, the tax codes, the
accounting properties... accordingly for the chosen company.
'''
obj_data = self.pool.get('ir.model.data')
ir_values_obj = self.pool.get('ir.values')
obj_wizard = self.browse(cr, uid, ids[0])
company_id = obj_wizard.company_id.id
self.pool.get('res.company').write(cr, uid, [company_id], {'currency_id': obj_wizard.currency_id.id})
# When we install the CoA of first company, set the currency to price types and pricelists
if company_id==1:
for ref in (('product','list_price'),('product','standard_price'),('product','list0'),('purchase','list0')):
try:
tmp2 = obj_data.get_object_reference(cr, uid, *ref)
if tmp2:
self.pool.get(tmp2[0]).write(cr, uid, tmp2[1], {
'currency_id': obj_wizard.currency_id.id
})
except ValueError, e:
pass
# If the floats for sale/purchase rates have been filled, create templates from them
self._create_tax_templates_from_rates(cr, uid, obj_wizard, company_id, context=context)

View File

@ -19,9 +19,9 @@
#
##############################################################################
from osv import fields
from osv import osv
from tools.translate import _
from openerp.osv import fields
from openerp.osv import osv
from openerp.tools.translate import _
class account_analytic_line(osv.osv):
_inherit = 'account.analytic.line'
@ -82,7 +82,7 @@ class account_analytic_line(osv.osv):
if j_id.type == 'purchase':
unit = prod.uom_po_id.id
if j_id.type <> 'sale':
a = prod.product_tmpl_id.property_account_expense.id
a = prod.property_account_expense.id
if not a:
a = prod.categ_id.property_account_expense_categ.id
if not a:
@ -91,7 +91,7 @@ class account_analytic_line(osv.osv):
'for this product: "%s" (id:%d).') % \
(prod.name, prod.id,))
else:
a = prod.product_tmpl_id.property_account_income.id
a = prod.property_account_income.id
if not a:
a = prod.categ_id.property_account_income_categ.id
if not a:

View File

@ -19,8 +19,8 @@
#
##############################################################################
from tools.translate import _
from osv import fields, osv
from openerp.tools.translate import _
from openerp.osv import fields, osv
class bank(osv.osv):
_inherit = "res.partner.bank"

View File

@ -21,9 +21,9 @@
import time
from osv import fields, osv
from tools.translate import _
import decimal_precision as dp
from openerp.osv import fields, osv
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
class account_bank_statement(osv.osv):
def create(self, cr, uid, vals, context=None):
@ -439,10 +439,11 @@ class account_bank_statement(osv.osv):
for st in self.browse(cr, uid, ids, context=context):
if st.state=='draft':
continue
ids = []
move_ids = []
for line in st.line_ids:
ids += [x.id for x in line.move_ids]
account_move_obj.unlink(cr, uid, ids, context)
move_ids += [x.id for x in line.move_ids]
account_move_obj.button_cancel(cr, uid, move_ids, context=context)
account_move_obj.unlink(cr, uid, move_ids, context)
done.append(st.id)
return self.write(cr, uid, done, {'state':'draft'}, context=context)
@ -546,7 +547,7 @@ class account_bank_statement_line(osv.osv):
_name = "account.bank.statement.line"
_description = "Bank Statement Line"
_columns = {
'name': fields.char('Communication', size=64, required=True),
'name': fields.char('Communication', required=True),
'date': fields.date('Date', required=True),
'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
'type': fields.selection([

View File

@ -22,9 +22,9 @@
import time
from osv import osv, fields
from tools.translate import _
import decimal_precision as dp
from openerp.osv import fields, osv
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
class account_cashbox_line(osv.osv):

View File

@ -24,11 +24,11 @@ from datetime import datetime
from dateutil.relativedelta import relativedelta
from operator import itemgetter
import netsvc
import pooler
from osv import fields, osv
import decimal_precision as dp
from tools.translate import _
from openerp import netsvc
from openerp import pooler
from openerp.osv import fields, osv
import openerp.addons.decimal_precision as dp
from openerp.tools.translate import _
# ---------------------------------------------------------
# Account Financial Report

View File

@ -21,12 +21,12 @@
import time
from lxml import etree
import decimal_precision as dp
import openerp.addons.decimal_precision as dp
import netsvc
import pooler
from osv import fields, osv, orm
from tools.translate import _
from openerp import netsvc
from openerp import pooler
from openerp.osv import fields, osv, orm
from openerp.tools.translate import _
class account_invoice(osv.osv):
def _amount_all(self, cr, uid, ids, name, args, context=None):
@ -80,8 +80,11 @@ class account_invoice(osv.osv):
def _reconciled(self, cr, uid, ids, name, args, context=None):
res = {}
for id in ids:
res[id] = self.test_paid(cr, uid, [id])
wf_service = netsvc.LocalService("workflow")
for inv in self.browse(cr, uid, ids, context=context):
res[inv.id] = self.test_paid(cr, uid, [inv.id])
if not res[inv.id] and inv.state == 'paid':
wf_service.trg_validate(uid, 'account.invoice', inv.id, 'open_test', cr)
return res
def _get_reference_type(self, cr, uid, context=None):
@ -181,7 +184,14 @@ class account_invoice(osv.osv):
_inherit = ['mail.thread']
_description = 'Invoice'
_order = "id desc"
_track = {
'type': {
},
'state': {
'account.mt_invoice_paid': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'paid' and obj['type'] in ('out_invoice', 'out_refund'),
'account.mt_invoice_validated': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open' and obj['type'] in ('out_invoice', 'out_refund'),
},
}
_columns = {
'name': fields.char('Description', size=64, select=True, readonly=True, states={'draft':[('readonly',False)]}),
'origin': fields.char('Source Document', size=64, help="Reference of the document that produced this invoice.", readonly=True, states={'draft':[('readonly',False)]}),
@ -191,7 +201,7 @@ class account_invoice(osv.osv):
('in_invoice','Supplier Invoice'),
('out_refund','Customer Refund'),
('in_refund','Supplier Refund'),
],'Type', readonly=True, select=True, change_default=True),
],'Type', readonly=True, select=True, change_default=True, track_visibility='always'),
'number': fields.related('move_id','name', type='char', readonly=True, size=64, relation='account.move', store=True, string='Number'),
'internal_number': fields.char('Invoice Number', size=32, readonly=True, help="Unique number of the invoice, computed automatically when the invoice is created."),
@ -207,7 +217,7 @@ class account_invoice(osv.osv):
('open','Open'),
('paid','Paid'),
('cancel','Cancelled'),
],'Status', select=True, readonly=True,
],'Status', select=True, readonly=True, track_visibility='onchange',
help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed Invoice. \
\n* The \'Pro-forma\' when invoice is in Pro-forma status,invoice does not have an invoice number. \
\n* The \'Open\' status is used when user create invoice,a invoice number is generated.Its in open status till user does not pay invoice. \
@ -217,8 +227,8 @@ class account_invoice(osv.osv):
'date_invoice': fields.date('Invoice Date', readonly=True, states={'draft':[('readonly',False)]}, select=True, help="Keep empty to use the current date"),
'date_due': fields.date('Due Date', readonly=True, states={'draft':[('readonly',False)]}, select=True,
help="If you use payment terms, the due date will be computed automatically at the generation "\
"of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."),
'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}),
"of accounting entries. The payment term may compute several due dates, for example 50% now and 50% in one month, but if you want to force a due date, make sure that the payment term is not set on the invoice. If you keep the payment term and the due date empty, it means direct payment."),
'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}, track_visibility='always'),
'payment_term': fields.many2one('account.payment.term', 'Payment Term',readonly=True, states={'draft':[('readonly',False)]},
help="If you use payment terms, the due date will be computed automatically at the generation "\
"of accounting entries. If you keep the payment term and the due date empty, it means direct payment. "\
@ -230,7 +240,7 @@ class account_invoice(osv.osv):
'tax_line': fields.one2many('account.invoice.tax', 'invoice_id', 'Tax Lines', readonly=True, states={'draft':[('readonly',False)]}),
'move_id': fields.many2one('account.move', 'Journal Entry', readonly=True, select=1, ondelete='restrict', help="Link to the automatically generated Journal Items."),
'amount_untaxed': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Untaxed',
'amount_untaxed': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Untaxed', track_visibility='always',
store={
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line'], 20),
'account.invoice.tax': (_get_invoice_tax, None, 20),
@ -251,7 +261,7 @@ class account_invoice(osv.osv):
'account.invoice.line': (_get_invoice_line, ['price_unit','invoice_line_tax_id','quantity','discount','invoice_id'], 20),
},
multi='all'),
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}, track_visibility='always'),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
'check_total': fields.float('Verification Total', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
@ -275,7 +285,7 @@ class account_invoice(osv.osv):
help="Remaining amount due."),
'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'),
'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, states={'draft':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, track_visibility='onchange', states={'draft':[('readonly',False)]}),
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]})
}
_defaults = {
@ -294,6 +304,18 @@ class account_invoice(osv.osv):
('number_uniq', 'unique(number, company_id, journal_id, type)', 'Invoice Number must be unique per Company!'),
]
def _find_partner(self, inv):
'''
Find the partner for which the accounting entries will be created
'''
#if the chosen partner is not a company and has a parent company, use the parent for the journal entries
#because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait'
part = inv.partner_id
if part.parent_id and not part.is_company:
part = part.parent_id
return part
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
journal_obj = self.pool.get('account.journal')
if context is None:
@ -358,10 +380,7 @@ class account_invoice(osv.osv):
if context is None:
context = {}
try:
res = super(account_invoice, self).create(cr, uid, vals, context)
if res:
self.create_send_note(cr, uid, [res], context=context)
return res
return super(account_invoice, self).create(cr, uid, vals, context)
except Exception, e:
if '"journal_id" viol' in e.args[0]:
raise orm.except_orm(_('Configuration Error!'),
@ -425,7 +444,6 @@ class account_invoice(osv.osv):
if context is None:
context = {}
self.write(cr, uid, ids, {'state':'paid'}, context=context)
self.confirm_paid_send_note(cr, uid, ids, context=context)
return True
def unlink(self, cr, uid, ids, context=None):
@ -443,7 +461,6 @@ class account_invoice(osv.osv):
def onchange_partner_id(self, cr, uid, ids, type, partner_id,\
date_invoice=False, payment_term=False, partner_bank_id=False, company_id=False):
invoice_addr_id = False
partner_payment_term = False
acc_id = False
bank_id = False
@ -453,8 +470,6 @@ class account_invoice(osv.osv):
if partner_id:
opt.insert(0, ('id', partner_id))
res = self.pool.get('res.partner').address_get(cr, uid, [partner_id], ['invoice'])
invoice_addr_id = res['invoice']
p = self.pool.get('res.partner').browse(cr, uid, partner_id)
if company_id:
if (p.property_account_receivable.company_id and (p.property_account_receivable.company_id.id != company_id)) and (p.property_account_payable.company_id and (p.property_account_payable.company_id.id != company_id)):
@ -480,10 +495,11 @@ class account_invoice(osv.osv):
if type in ('out_invoice', 'out_refund'):
acc_id = p.property_account_receivable.id
partner_payment_term = p.property_payment_term and p.property_payment_term.id or False
else:
acc_id = p.property_account_payable.id
partner_payment_term = p.property_supplier_payment_term and p.property_supplier_payment_term.id or False
fiscal_position = p.property_account_position and p.property_account_position.id or False
partner_payment_term = p.property_payment_term and p.property_payment_term.id or False
if p.bank_ids:
bank_id = p.bank_ids[0].id
@ -959,11 +975,7 @@ class account_invoice(osv.osv):
date = inv.date_invoice or time.strftime('%Y-%m-%d')
#if the chosen partner is not a company and has a parent company, use the parent for the journal entries
#because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait'
part = inv.partner_id
if part.parent_id and not part.is_company:
part = part.parent_id
part = self._find_partner(inv)
line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part.id, date, context=ctx)),iml)
@ -985,7 +997,8 @@ class account_invoice(osv.osv):
'narration':inv.comment
}
period_id = inv.period_id and inv.period_id.id or False
ctx.update({'company_id': inv.company_id.id})
ctx.update(company_id=inv.company_id.id,
account_period_prefer_normal=True)
if not period_id:
period_ids = period_obj.find(cr, uid, inv.date_invoice, context=ctx)
period_id = period_ids and period_ids[0] or False
@ -1037,13 +1050,12 @@ class account_invoice(osv.osv):
self.write(cr, uid, ids, {})
for obj_inv in self.browse(cr, uid, ids, context=context):
id = obj_inv.id
invtype = obj_inv.type
number = obj_inv.number
move_id = obj_inv.move_id and obj_inv.move_id.id or False
reference = obj_inv.reference or ''
self.write(cr, uid, ids, {'internal_number':number})
self.write(cr, uid, ids, {'internal_number': number})
if invtype in ('in_invoice', 'in_refund'):
if not reference:
@ -1064,13 +1076,6 @@ class account_invoice(osv.osv):
'WHERE account_move_line.move_id = %s ' \
'AND account_analytic_line.move_id = account_move_line.id',
(ref, move_id))
for inv_id, name in self.name_get(cr, uid, [id]):
ctx = context.copy()
if obj_inv.type in ('out_invoice', 'out_refund'):
ctx = self.get_log_context(cr, uid, context=ctx)
message = _("Invoice '%s' is validated.") % name
self.message_post(cr, uid, [inv_id], body=message, context=context)
return True
def action_cancel(self, cr, uid, ids, context=None):
@ -1099,7 +1104,6 @@ class account_invoice(osv.osv):
# will be automatically deleted too
account_move_obj.unlink(cr, uid, move_ids, context=context)
self._log_event(cr, uid, ids, -1.0, 'Cancel Invoice')
self.invoice_cancel_send_note(cr, uid, ids, context=context)
return True
###################
@ -1140,72 +1144,92 @@ class account_invoice(osv.osv):
ids = self.search(cr, user, [('name',operator,name)] + args, limit=limit, context=context)
return self.name_get(cr, user, ids, context)
def _refund_cleanup_lines(self, cr, uid, lines):
def _refund_cleanup_lines(self, cr, uid, lines, context=None):
clean_lines = []
for line in lines:
del line['id']
del line['invoice_id']
for field in ('company_id', 'partner_id', 'account_id', 'product_id',
'uos_id', 'account_analytic_id', 'tax_code_id', 'base_code_id'):
if line.get(field):
line[field] = line[field][0]
if 'invoice_line_tax_id' in line:
line['invoice_line_tax_id'] = [(6,0, line.get('invoice_line_tax_id', [])) ]
return map(lambda x: (0,0,x), lines)
clean_line = {}
for field in line._all_columns.keys():
if line._all_columns[field].column._type == 'many2one':
clean_line[field] = line[field].id
elif line._all_columns[field].column._type not in ['many2many','one2many']:
clean_line[field] = line[field]
elif field == 'invoice_line_tax_id':
tax_list = []
for tax in line[field]:
tax_list.append(tax.id)
clean_line[field] = [(6,0, tax_list)]
clean_lines.append(clean_line)
return map(lambda x: (0,0,x), clean_lines)
def refund(self, cr, uid, ids, date=None, period_id=None, description=None, journal_id=None):
invoices = self.read(cr, uid, ids, ['name', 'type', 'number', 'reference', 'comment', 'date_due', 'partner_id', 'partner_contact', 'partner_insite', 'partner_ref', 'payment_term', 'account_id', 'currency_id', 'invoice_line', 'tax_line', 'journal_id', 'company_id'])
obj_invoice_line = self.pool.get('account.invoice.line')
obj_invoice_tax = self.pool.get('account.invoice.tax')
def _prepare_refund(self, cr, uid, invoice, date=None, period_id=None, description=None, journal_id=None, context=None):
"""Prepare the dict of values to create the new refund from the invoice.
This method may be overridden to implement custom
refund generation (making sure to call super() to establish
a clean extension chain).
:param integer invoice_id: id of the invoice to refund
:param dict invoice: read of the invoice to refund
:param string date: refund creation date from the wizard
:param integer period_id: force account.period from the wizard
:param string description: description of the refund from the wizard
:param integer journal_id: account.journal from the wizard
:return: dict of value to create() the refund
"""
obj_journal = self.pool.get('account.journal')
new_ids = []
for invoice in invoices:
del invoice['id']
type_dict = {
'out_invoice': 'out_refund', # Customer Invoice
'in_invoice': 'in_refund', # Supplier Invoice
'out_refund': 'out_invoice', # Customer Refund
'in_refund': 'in_invoice', # Supplier Refund
}
invoice_lines = obj_invoice_line.read(cr, uid, invoice['invoice_line'])
invoice_lines = self._refund_cleanup_lines(cr, uid, invoice_lines)
tax_lines = obj_invoice_tax.read(cr, uid, invoice['tax_line'])
tax_lines = filter(lambda l: l['manual'], tax_lines)
tax_lines = self._refund_cleanup_lines(cr, uid, tax_lines)
if journal_id:
refund_journal_ids = [journal_id]
elif invoice['type'] == 'in_invoice':
refund_journal_ids = obj_journal.search(cr, uid, [('type','=','purchase_refund')])
type_dict = {
'out_invoice': 'out_refund', # Customer Invoice
'in_invoice': 'in_refund', # Supplier Invoice
'out_refund': 'out_invoice', # Customer Refund
'in_refund': 'in_invoice', # Supplier Refund
}
invoice_data = {}
for field in ['name', 'reference', 'comment', 'date_due', 'partner_id', 'company_id',
'account_id', 'currency_id', 'payment_term', 'user_id', 'fiscal_position']:
if invoice._all_columns[field].column._type == 'many2one':
invoice_data[field] = invoice[field].id
else:
refund_journal_ids = obj_journal.search(cr, uid, [('type','=','sale_refund')])
invoice_data[field] = invoice[field] if invoice[field] else False
if not date:
date = time.strftime('%Y-%m-%d')
invoice.update({
'type': type_dict[invoice['type']],
'date_invoice': date,
'state': 'draft',
'number': False,
'invoice_line': invoice_lines,
'tax_line': tax_lines,
'journal_id': refund_journal_ids
})
if period_id:
invoice.update({
'period_id': period_id,
})
if description:
invoice.update({
'name': description,
})
# take the id part of the tuple returned for many2one fields
for field in ('partner_id', 'company_id',
'account_id', 'currency_id', 'payment_term', 'journal_id'):
invoice[field] = invoice[field] and invoice[field][0]
invoice_lines = self._refund_cleanup_lines(cr, uid, invoice.invoice_line, context=context)
tax_lines = filter(lambda l: l['manual'], invoice.tax_line)
tax_lines = self._refund_cleanup_lines(cr, uid, tax_lines, context=context)
if journal_id:
refund_journal_ids = [journal_id]
elif invoice['type'] == 'in_invoice':
refund_journal_ids = obj_journal.search(cr, uid, [('type','=','purchase_refund')], context=context)
else:
refund_journal_ids = obj_journal.search(cr, uid, [('type','=','sale_refund')], context=context)
if not date:
date = time.strftime('%Y-%m-%d')
invoice_data.update({
'type': type_dict[invoice['type']],
'date_invoice': date,
'state': 'draft',
'number': False,
'invoice_line': invoice_lines,
'tax_line': tax_lines,
'journal_id': refund_journal_ids and refund_journal_ids[0] or False,
})
if period_id:
invoice_data['period_id'] = period_id
if description:
invoice_data['name'] = description
return invoice_data
def refund(self, cr, uid, ids, date=None, period_id=None, description=None, journal_id=None, context=None):
new_ids = []
for invoice in self.browse(cr, uid, ids, context=context):
invoice = self._prepare_refund(cr, uid, invoice,
date=date,
period_id=period_id,
description=description,
journal_id=journal_id,
context=context)
# create the new invoice
new_ids.append(self.create(cr, uid, invoice))
new_ids.append(self.create(cr, uid, invoice, context=context))
return new_ids
@ -1302,8 +1326,8 @@ class account_invoice(osv.osv):
else:
code = invoice.currency_id.symbol
# TODO: use currency's formatting function
msg = _("Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining).") % \
(name, pay_amount, code, invoice.amount_total, code, total, code)
msg = _("Invoice partially paid: %s%s of %s%s (%s%s remaining).") % \
(pay_amount, code, invoice.amount_total, code, total, code)
self.message_post(cr, uid, [inv_id], body=msg, context=context)
self.pool.get('account.move.line').reconcile_partial(cr, uid, line_ids, 'manual', context)
@ -1311,35 +1335,6 @@ class account_invoice(osv.osv):
self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
return True
# -----------------------------------------
# OpenChatter notifications and need_action
# -----------------------------------------
def _get_document_type(self, type):
type_dict = {
# Translation markers will have no effect at runtime, only used to properly flag export
'out_invoice': _('Customer invoice'),
'in_invoice': _('Supplier invoice'),
'out_refund': _('Customer Refund'),
'in_refund': _('Supplier Refund'),
}
return type_dict.get(type, 'Invoice')
def create_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
self.message_post(cr, uid, [obj.id], body=_("%s <b>created</b>.") % (self._get_document_type(obj.type)),
subtype="account.mt_invoice_new", context=context)
def confirm_paid_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
self.message_post(cr, uid, [obj.id], body=_("%s <b>paid</b>.") % (self._get_document_type(obj.type)),
subtype="account.mt_invoice_paid", context=context)
def invoice_cancel_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
self.message_post(cr, uid, [obj.id], body=_("%s <b>cancelled</b>.") % (self._get_document_type(obj.type)),
context=context)
class account_invoice_line(osv.osv):
@ -1423,7 +1418,7 @@ class account_invoice_line(osv.osv):
res['arch'] = etree.tostring(doc)
return res
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
if context is None:
context = {}
company_id = company_id if company_id != None else context.get('company_id',False)
@ -1446,11 +1441,11 @@ class account_invoice_line(osv.osv):
res = self.pool.get('product.product').browse(cr, uid, product, context=context)
if type in ('out_invoice','out_refund'):
a = res.product_tmpl_id.property_account_income.id
a = res.property_account_income.id
if not a:
a = res.categ_id.property_account_income_categ.id
else:
a = res.product_tmpl_id.property_account_expense.id
a = res.property_account_expense.id
if not a:
a = res.categ_id.property_account_expense_categ.id
a = fpos_obj.map_account(cr, uid, fpos, a)
@ -1469,14 +1464,11 @@ class account_invoice_line(osv.osv):
result.update({'price_unit': res.list_price, 'invoice_line_tax_id': tax_id})
result['name'] = res.partner_ref
domain = {}
result['uos_id'] = res.uom_id.id or uom or False
result['uos_id'] = uom_id or res.uom_id.id
if res.description:
result['name'] += '\n'+res.description
if result['uos_id']:
res2 = res.uom_id.category_id.id
if res2:
domain = {'uos_id':[('category_id','=',res2 )]}
domain = {'uos_id':[('category_id','=',res.uom_id.category_id.id)]}
res_final = {'value':result, 'domain':domain}
@ -1492,10 +1484,10 @@ class account_invoice_line(osv.osv):
new_price = res_final['value']['price_unit'] * currency.rate
res_final['value']['price_unit'] = new_price
if uom:
uom = self.pool.get('product.uom').browse(cr, uid, uom, context=context)
if res.uom_id.category_id.id == uom.category_id.id:
new_price = res_final['value']['price_unit'] * uom.factor_inv
if result['uos_id'] != res.uom_id.id:
selected_uom = self.pool.get('product.uom_id').browse(cr, uid, result['uos_id'], context=context)
if res.uom_id.category_id.id == selected_uom.category_id.id:
new_price = res_final['value']['price_unit'] * uom_id.factor_inv
res_final['value']['price_unit'] = new_price
return res_final
@ -1507,8 +1499,6 @@ class account_invoice_line(osv.osv):
context.update({'company_id': company_id})
warning = {}
res = self.product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context=context)
if 'uos_id' in res['value']:
del res['value']['uos_id']
if not uom:
res['value']['price_unit'] = 0.0
if product and uom:

View File

@ -145,7 +145,8 @@
<header>
<button name="invoice_open" states="draft,proforma2" string="Validate" class="oe_highlight" groups="account.group_account_invoice"/>
<button name="%(action_account_invoice_refund)d" type='action' string='Ask Refund' states='open,paid' groups="account.group_account_invoice"/>
<button name="invoice_cancel" states="draft,proforma2,sale,open" string="Cancel" groups="base.group_no_one"/>
<button name="invoice_cancel" states="draft,proforma2" string="Cancel" groups="account.group_account_invoice"/>
<button name="invoice_cancel" states="sale,open" string="Cancel" groups="base.group_no_one"/>
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object" groups="account.group_account_invoice"/>
<button name='%(action_account_state_open)d' type='action' string='Re-Open' groups="account.group_account_invoice" attrs="{'invisible':['|', ('state','&lt;&gt;','paid'), ('reconciled', '=', True)]}" help="This button only appears when the state of the invoice is 'paid' (showing that it has been fully reconciled) and auto-computed boolean 'reconciled' is False (depicting that it's not the case anymore). In other words, the invoice has been dereconciled and it does not fit anymore the 'paid' state. You should press this button to re-open it and let it continue its normal process after having resolved the eventual exceptions it may have created."/>
<field name="state" widget="statusbar" statusbar_visible="draft,open,paid" statusbar_colors='{"proforma":"blue","proforma2":"blue"}'/>
@ -194,7 +195,7 @@
<field name="product_id"
on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.currency_id, context, parent.company_id)"/>
<field name="name"/>
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
<field name="company_id" invisible="1"/>
<field name="account_id" groups="account.group_account_user"
domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '!=', 'view')]"
on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)"/>
@ -349,7 +350,7 @@
<field name="product_id"
on_change="product_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.currency_id, context, parent.company_id)"/>
<field name="name"/>
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
<field name="company_id" invisible="1"/>
<field name="account_id" groups="account.group_account_user"
domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '!=', 'view')]"
on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)"/>
@ -627,6 +628,7 @@
id="act_account_journal_2_account_invoice_opened"
name="Unpaid Invoices"
context="{'search_default_journal_id': [active_id], 'search_default_unpaid':1, 'default_journal_id': active_id}"
domain="[('journal_id','=', active_id)]"
res_model="account.invoice"
src_model="account.journal"/>

View File

@ -26,11 +26,11 @@ from operator import itemgetter
from lxml import etree
import netsvc
from osv import fields, osv, orm
from tools.translate import _
import decimal_precision as dp
import tools
from openerp import netsvc
from openerp.osv import fields, osv, orm
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
from openerp import tools
class account_move_line(osv.osv):
_name = "account.move.line"
@ -443,9 +443,9 @@ class account_move_line(osv.osv):
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1),
'reconcile_id': fields.many2one('account.move.reconcile', 'Reconcile', readonly=True, ondelete='set null', select=2),
'reconcile_partial_id': fields.many2one('account.move.reconcile', 'Partial Reconcile', readonly=True, ondelete='set null', select=2),
'reconcile': fields.function(_get_reconcile, type='char', string='Reconcile'),
'reconcile': fields.function(_get_reconcile, type='char', string='Reconcile Ref'),
'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optional other currency if it is a multi-currency entry.", digits_compute=dp.get_precision('Account')),
'amount_residual_currency': fields.function(_amount_residual, string='Residual Amount', multi="residual", help="The residual amount on a receivable or payable of a journal entry expressed in its currency (maybe different of the company currency)."),
'amount_residual_currency': fields.function(_amount_residual, string='Residual Amount in Currency', multi="residual", help="The residual amount on a receivable or payable of a journal entry expressed in its currency (maybe different of the company currency)."),
'amount_residual': fields.function(_amount_residual, string='Residual Amount', multi="residual", help="The residual amount on a receivable or payable of a journal entry expressed in the company currency."),
'currency_id': fields.many2one('res.currency', 'Currency', help="The optional other currency if it is a multi-currency entry."),
'journal_id': fields.related('move_id', 'journal_id', string='Journal', type='many2one', relation='account.journal', required=True, select=True,
@ -456,7 +456,7 @@ class account_move_line(osv.osv):
store = {
'account.move': (_get_move_lines, ['period_id'], 20)
}),
'blocked': fields.boolean('Litigation', help="You can check this box to mark this journal item as a litigation with the associated partner"),
'blocked': fields.boolean('No Follow-up', help="You can check this box to mark this journal item as a litigation with the associated partner"),
'partner_id': fields.many2one('res.partner', 'Partner', select=1, ondelete='restrict'),
'date_maturity': fields.date('Due date', select=True ,help="This field is used for payable and receivable journal entries. You can put the limit date for the payment of this line."),
'date': fields.related('move_id','date', string='Effective date', type='date', required=True, select=True,
@ -672,17 +672,24 @@ class account_move_line(osv.osv):
return {'value':val}
if not date:
date = datetime.now().strftime('%Y-%m-%d')
jt = False
if journal:
jt = journal_obj.browse(cr, uid, journal).type
part = partner_obj.browse(cr, uid, partner_id)
if part.property_payment_term:
res = payment_term_obj.compute(cr, uid, part.property_payment_term.id, 100, date)
payment_term_id = False
if jt and jt in ('purchase', 'purchase_refund') and part.property_supplier_payment_term:
payment_term_id = part.property_supplier_payment_term.id
elif jt and part.property_payment_term:
payment_term_id = part.property_payment_term.id
if payment_term_id:
res = payment_term_obj.compute(cr, uid, payment_term_id, 100, date)
if res:
val['date_maturity'] = res[0][0]
if not account_id:
id1 = part.property_account_payable.id
id2 = part.property_account_receivable.id
if journal:
jt = journal_obj.browse(cr, uid, journal).type
if jt:
if jt in ('sale', 'purchase_refund'):
val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id2)
elif jt in ('purchase', 'sale_refund'):
@ -849,7 +856,12 @@ class account_move_line(osv.osv):
if r[0][1] != None:
raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.'))
if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \
if context.get('fy_closing'):
# We don't want to generate any write-off when being called from the
# wizard used to close a fiscal year (and it doesn't give us any
# writeoff_acc_id).
pass
elif (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \
(account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))):
if not writeoff_acc_id:
raise osv.except_osv(_('Warning!'), _('You have to provide an account for the write off/exchange difference entry.'))
@ -971,7 +983,8 @@ class account_move_line(osv.osv):
if context is None:
context = {}
period_pool = self.pool.get('account.period')
pids = period_pool.search(cr, user, [('date_start','<=',date), ('date_stop','>=',date)])
ctx = dict(context, account_period_prefer_normal=True)
pids = period_pool.find(cr, user, date, context=ctx)
if pids:
res.update({
'period_id':pids[0]

View File

@ -537,6 +537,7 @@
<record id="view_bank_statement_form" model="ir.ui.view">
<field name="name">account.bank.statement.form</field>
<field name="model">account.bank.statement</field>
<field name="priority">1</field>
<field name="arch" type="xml">
<form string="Bank Statement" version="7.0">
<header>
@ -549,10 +550,8 @@
<div class="oe_right oe_button_box" name="import_buttons">
<!-- Put here related buttons -->
</div>
<label for="name" class="oe_edit_only" attrs="{'invisible':[('name','=','/')]}"/>
<h1>
<field name="name" attrs="{'invisible':[('name','=','/')]}"/>
</h1>
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
<group>
<group>
<field name="journal_id" domain="[('type', '=', 'bank')]" on_change="onchange_journal_id(journal_id)" widget="selection"/>
@ -577,7 +576,7 @@
<field name="date"/>
<field name="name"/>
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="['|',('parent_id','=',False),('is_company','=',True)]"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
@ -1105,7 +1104,7 @@
<field name="invoice" invisible="1"/>
<field name="amount_currency" readonly="True" invisible="not context.get('currency',False)"/>
<field name="currency_id" readonly="True" invisible="not context.get('currency',False)" />
<field name="state" />
<field name="state" invisible="1"/>
<field name="company_id" invisible="1"/>
</tree>
</field>
@ -1137,7 +1136,7 @@
<separator/>
<filter string="Next Partner to Reconcile" help="Next Partner Entries to reconcile" name="next_partner" context="{'next_partner_only': 1}" icon="terp-gtk-jump-to-ltr" domain="[('account_id.reconcile','=',True),('reconcile_id','=',False)]"/>
<field name="move_id" string="Number (Move)"/>
<field name="account_id" filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]"/>
<field name="account_id"/>
<field name="partner_id"/>
<field name="journal_id" context="{'journal_id':self}" widget="selection"/> <!-- it's important to keep widget='selection' in this filter viewbecause without that the value passed in the context is not the ID but the textual value (name) of the selected journal -->
<field name="period_id" context="{'period_id':self}" widget="selection"/> <!-- it's important to keep the widget='selection' in this field, for the same reason as explained above -->
@ -1155,7 +1154,7 @@
<field name="name">Journal Items</field>
<field name="res_model">account.move.line</field>
<field name="view_id" ref="view_move_line_tree"/>
<field name="view_mode">tree_account_move_line_quickadd</field>
<field name="view_mode">tree_account_move_line_quickadd,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Select the period and the journal you want to fill.
@ -1207,12 +1206,6 @@
</p>
</field>
</record>
<menuitem
name="Journal Items to Reconcile"
action="action_account_manual_reconcile"
id="menu_manual_reconcile_bank"
sequence="20"
parent="account.menu_finance_bank_and_cash"/>
<menuitem
name="Manual Reconciliation"
action="action_account_manual_reconcile"
@ -1428,6 +1421,7 @@
context="{'search_default_journal_id': active_id, 'default_journal_id': active_id}"
res_model="account.move.line"
src_model="account.move"/>
<act_window
domain="[('reconcile_id', '=', active_id)]"
id="act_account_acount_move_line_reconcile_open"
@ -1554,10 +1548,8 @@
<field name="model">account.payment.term.line</field>
<field name="arch" type="xml">
<tree string="Payment Term">
<field name="sequence"/>
<field name="name"/>
<field name="value"/>
<field name="value_amount"/>
<field name="value_amount" attrs="{'readonly':[('value','=','balance')]}"/>
<field name="days"/>
<field name="days2"/>
</tree>
@ -1568,37 +1560,20 @@
<field name="model">account.payment.term.line</field>
<field name="arch" type="xml">
<form string="Payment Term" version="7.0">
<group>
<field name="name"/>
<field name="sequence"/>
</group>
<group>
<group string="Amount Computation">
<field name="value"/>
<field name="value_amount" attrs="{'readonly':[('value','=','balance')]}"/>
<field name="value"/>
<label for="value_amount" string="Amount To Pay" attrs="{'invisible':[('value','=','balance')]}"/>
<div attrs="{'invisible':[('value','=','balance')]}">
<field name="value_amount" class="oe_inline"/>
<label string="%%" class="oe_inline" attrs="{'invisible':['!',('value','=','procent')]}" />
</div>
</group>
<group string="Due Date Computation">
<field name="days"/>
<field name="days2"/>
</group>
</group>
<separator string="Example"/>
<label string="At 14 net days 2 percent, remaining amount at 30 days end of month."/>
<group>
<label string="Line 1:" colspan="2"/>
<label string=" Valuation: Percent"/>
<label string=" Number of Days: 14"/>
<label string=" Value amount: 0.02"/>
<label string=" Day of the Month: 0"/>
</group>
<group>
<label string="Line 2:" colspan="2"/>
<label string=" Valuation: Balance"/>
<label string=" Number of Days: 30"/>
<label string=" Value amount: n.a"/>
<label string=" Day of the Month= -1"/>
</group>
</form>
</field>
</record>
@ -1621,7 +1596,7 @@
<field name="name"/>
<field name="active"/>
</group>
<field name="note" placeholder="Note for the invoice..."/>
<field name="note" placeholder="Payment term explanation for the customer..."/>
<separator string="Computation"/>
<field name="line_ids"/>
</form>
@ -2258,6 +2233,7 @@
<record id="view_bank_statement_form2" model="ir.ui.view">
<field name="name">account.bank.statement.form</field>
<field name="model">account.bank.statement</field>
<field name="priority">2</field>
<field name="arch" type="xml">
<form string="Statement" version="7.0">
<header>

View File

@ -19,7 +19,7 @@
#
##############################################################################
from osv import fields, osv
from openerp.osv import fields, osv
class res_company(osv.osv):
_inherit = "res.company"

View File

@ -10,17 +10,33 @@
<!--
Payment term
-->
<record id="account_payment_term" model="account.payment.term">
<field name="name">30 Days End of Month</field>
<field name="note">30 Days End of Month</field>
<record id="account_payment_term_immediate" model="account.payment.term">
<field name="name">Immediate Payment</field>
<field name="note">Immediate Payment</field>
</record>
<record id="account_payment_term_line" model="account.payment.term.line">
<field name="name">30 Days End of Month</field>
<record id="account_payment_term_line_immediate" model="account.payment.term.line">
<field name="name">Immediate Payment</field>
<field name="value">balance</field>
<field eval="30" name="days"/>
<field eval="-1" name="days2"/>
<field eval="account_payment_term" name="payment_id"/>
<field eval="0" name="days"/>
<field eval="0" name="days2"/>
<field eval="account_payment_term_immediate" name="payment_id"/>
</record>
<record id="account_payment_term_15days" model="account.payment.term">
<field name="name">15 Days</field>
<field name="note">15 Days</field>
</record>
<record id="account_payment_term_line_15days" model="account.payment.term.line">
<field name="name">15 Days</field>
<field name="value">balance</field>
<field eval="15" name="days"/>
<field eval="0" name="days2"/>
<field eval="account_payment_term_15days" name="payment_id"/>
</record>
<record forcecreate="True" id="decimal_payment" model="decimal.precision">
<field name="name">Payment Term</field>
<field name="digits">6</field>
@ -30,6 +46,7 @@
<field name="name">30 Net Days</field>
<field name="note">30 Net Days</field>
</record>
<record id="account_payment_term_line_net" model="account.payment.term.line">
<field name="name">30 Net Days</field>
<field name="value">balance</field>
@ -37,28 +54,7 @@
<field eval="0" name="days2"/>
<field eval="account_payment_term_net" name="payment_id"/>
</record>
<record id="account_payment_term_advance" model="account.payment.term">
<field name="name">30% Advance End 30 Days</field>
<field name="note">30% Advance End 30 Days</field>
</record>
<record id="account_payment_term_line_advance1" model="account.payment.term.line">
<field name="name">30% Advance</field>
<field name="value">procent</field>
<field eval="3" name="sequence"/>
<field eval="0.300000" name="value_amount"/>
<field eval="0" name="days"/>
<field eval="0" name="days2"/>
<field eval="account_payment_term_advance" name="payment_id"/>
</record>
<record id="account_payment_term_line_advance2" model="account.payment.term.line">
<field name="name">Remaining Balance</field>
<field name="value">balance</field>
<field eval="30" name="days"/>
<field eval="-1" name="days2"/>
<field eval="account_payment_term_advance" name="payment_id"/>
</record>
<!--
Account Journal Sequences
-->
@ -155,14 +151,16 @@
<field name="object">account.invoice</field>
</record>
<!-- mail: subtypes -->
<record id="mt_invoice_new" model="mail.message.subtype">
<field name="name">created</field>
<!-- Account-related subtypes for messaging / Chatter -->
<record id="mt_invoice_validated" model="mail.message.subtype">
<field name="name">Validated</field>
<field name="res_model">account.invoice</field>
<field name="description">Invoice validated</field>
</record>
<record id="mt_invoice_paid" model="mail.message.subtype">
<field name="name">paid</field>
<field name="name">Paid</field>
<field name="res_model">account.invoice</field>
<field name="description">Invoice paid</field>
</record>
</data>
</openerp>

View File

@ -127,9 +127,60 @@
<field eval="time.strftime('%Y')+'-12-31'" name="date_stop"/>
<field name="company_id" ref="base.main_company"/>
</record>
<!-- Payment Term -->
<record id="account_payment_term" model="account.payment.term">
<field name="name">30 Days End of Month</field>
<field name="note">30 Days End of Month</field>
</record>
<record id="account_payment_term_line" model="account.payment.term.line">
<field name="name">30 Days End of Month</field>
<field name="value">balance</field>
<field eval="30" name="days"/>
<field eval="-1" name="days2"/>
<field eval="account_payment_term" name="payment_id"/>
</record>
<record id="account_payment_term_advance" model="account.payment.term">
<field name="name">30% Advance End 30 Days</field>
<field name="note">30% Advance End 30 Days</field>
</record>
<record id="account_payment_term_line_advance1" model="account.payment.term.line">
<field name="name">30% Advance</field>
<field name="value">procent</field>
<field eval="3" name="sequence"/>
<field eval="0.300000" name="value_amount"/>
<field eval="0" name="days"/>
<field eval="0" name="days2"/>
<field eval="account_payment_term_advance" name="payment_id"/>
</record>
<record id="account_payment_term_line_advance2" model="account.payment.term.line">
<field name="name">Remaining Balance</field>
<field name="value">balance</field>
<field eval="30" name="days"/>
<field eval="-1" name="days2"/>
<field eval="account_payment_term_advance" name="payment_id"/>
</record>
<record id="base.user_demo" model="res.users">
<field name="groups_id" eval="[(4,ref('account.group_account_user'))]"/>
</record>
<!-- Add payment term on some demo partners -->
<record id="base.res_partner_2" model="res.partner">
<field name="property_payment_term" ref="account_payment_term_net"/>
</record>
<record id="base.res_partner_12" model="res.partner">
<field name="property_payment_term" ref="account_payment_term"/>
<field name="property_supplier_payment_term" ref="account_payment_term"/>
</record>
<record id="base.res_partner_4" model="res.partner">
<field name="property_supplier_payment_term" ref="account_payment_term_net"/>
</record>
<record id="base.res_partner_1" model="res.partner">
<field name="property_supplier_payment_term" ref="account_payment_term"/>
</record>
</data>
</openerp>

View File

@ -18,9 +18,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv, fields
from openerp.addons.edi import EDIMixin
from openerp.osv import osv
from edi import EDIMixin
from urllib import urlencode
INVOICE_LINE_EDI_STRUCT = {
'name': True,
@ -258,6 +259,28 @@ class account_invoice(osv.osv, EDIMixin):
pass
return action
def _edi_paypal_url(self, cr, uid, ids, field, arg, context=None):
res = dict.fromkeys(ids, False)
for inv in self.browse(cr, uid, ids, context=context):
if inv.type == 'out_invoice' and inv.company_id.paypal_account:
params = {
"cmd": "_xclick",
"business": inv.company_id.paypal_account,
"item_name": inv.company_id.name + " Invoice " + inv.number,
"invoice": inv.number,
"amount": inv.residual,
"currency_code": inv.currency_id.name,
"button_subtype": "services",
"no_note": "1",
"bn": "OpenERP_Invoice_PayNow_" + inv.currency_id.name,
}
res[inv.id] = "https://www.paypal.com/cgi-bin/webscr?" + urlencode(params)
return res
_columns = {
'paypal_url': fields.function(_edi_paypal_url, type='char', string='Paypal Url'),
}
class account_invoice_line(osv.osv, EDIMixin):
_inherit='account.invoice.line'

View File

@ -23,16 +23,17 @@
<record id="email_template_edi_invoice" model="email.template">
<field name="name">Invoice - Send by Email</field>
<field name="email_from">${object.user_id.email or object.company_id.email or 'noreply@localhost'}</field>
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })</field>
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a'})</field>
<field name="email_recipients">${object.partner_id.id}</field>
<field name="model_id" ref="account.model_account_invoice"/>
<field name="auto_delete" eval="True"/>
<field name="report_template" ref="account_invoices"/>
<field name="report_name">Invoice_${(object.number or '').replace('/','_')}_${object.state == 'draft' and 'draft' or ''}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ">
<p>Hello${object.partner_id.name and ' ' or ''}${object.partner_id.name or ''},</p>
<p>Hello ${object.partner_id.name},</p>
<p>A new invoice is available for you: </p>
@ -49,20 +50,10 @@
% endif
</p>
% if object.company_id.paypal_account and object.type in ('out_invoice', 'in_refund'):
<%
comp_name = quote(object.company_id.name)
inv_number = quote(object.number)
paypal_account = quote(object.company_id.paypal_account)
inv_amount = quote(str(object.residual))
cur_name = quote(object.currency_id.name)
paypal_url = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=%s&amp;item_name=%s%%20Invoice%%20%s&amp;" \
"invoice=%s&amp;amount=%s&amp;currency_code=%s&amp;button_subtype=services&amp;no_note=1&amp;bn=OpenERP_Invoice_PayNow_%s" % \
(paypal_account,comp_name,inv_number,inv_number,inv_amount,cur_name,cur_name)
%>
% if object.paypal_url:
<br/>
<p>It is also possible to directly pay with Paypal:</p>
<a style="margin-left: 120px;" href="${paypal_url}">
<a style="margin-left: 120px;" href="${object.paypal_url}">
<img class="oe_edi_paypal_button" src="https://www.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif"/>
</a>
% endif
@ -73,7 +64,7 @@
<br/>
<br/>
<div style="width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;">
<h3 style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #FFF;">
<h3 style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;">
<strong style="text-transform:uppercase;">${object.company_id.name}</strong></h3>
</div>
<div style="width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;">

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -19,17 +19,17 @@
#
##############################################################################
import logging
import time
import datetime
from dateutil.relativedelta import relativedelta
import logging
from operator import itemgetter
from os.path import join as opj
import time
from openerp import netsvc, tools
from openerp.tools.translate import _
from openerp.osv import fields, osv
from tools.translate import _
from osv import fields, osv
import netsvc
import tools
_logger = logging.getLogger(__name__)
class account_installer(osv.osv_memory):

View File

@ -19,7 +19,7 @@
#
##############################################################################
from osv import fields, osv
from openerp.osv import fields, osv
class ir_sequence_fiscalyear(osv.osv):
_name = 'account.sequence.fiscalyear'

View File

@ -20,9 +20,10 @@
##############################################################################
from operator import itemgetter
from osv import fields, osv
import time
from openerp.osv import fields, osv
class account_fiscal_position(osv.osv):
_name = 'account.fiscal.position'
_description = 'Fiscal Position'
@ -134,18 +135,23 @@ class res_partner(osv.osv):
return []
having_values = tuple(map(itemgetter(2), args))
where = ' AND '.join(
map(lambda x: '(SUM(debit-credit) %(operator)s %%s)' % {
map(lambda x: '(SUM(bal2) %(operator)s %%s)' % {
'operator':x[1]},args))
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
cr.execute(('SELECT partner_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 '+query+' '\
'AND partner_id IS NOT NULL '\
'GROUP BY partner_id HAVING '+where),
(type,) + having_values)
cr.execute(('SELECT pid AS partner_id, SUM(bal2) FROM ' \
'(SELECT CASE WHEN bal IS NOT NULL THEN bal ' \
'ELSE 0.0 END AS bal2, p.id as pid FROM ' \
'(SELECT (debit-credit) AS bal, partner_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 '+query+') AS l ' \
'RIGHT JOIN res_partner p ' \
'ON p.id = partner_id ) AS pl ' \
'GROUP BY pid HAVING ' + where),
(type,) + having_values)
res = cr.fetchall()
if not res:
return [('id','=','0')]
@ -215,9 +221,16 @@ class res_partner(osv.osv):
'account.payment.term',
type='many2one',
relation='account.payment.term',
string ='Payment Term',
string ='Customer Payment Term',
view_load=True,
help="This payment term will be used instead of the default one for the current partner"),
help="This payment term will be used instead of the default one for sale orders and customer invoices"),
'property_supplier_payment_term': fields.property(
'account.payment.term',
type='many2one',
relation='account.payment.term',
string ='Supplier Payment Term',
view_load=True,
help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
'ref_companies': fields.one2many('res.company', 'partner_id',
'Companies that refers to partner'),
'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the date of the last reconciliation made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 ways: either the last debit/credit entry was reconciled, either the user pressed the button "Fully Reconciled" in the manual reconciliation process')

View File

@ -89,6 +89,7 @@
</group>
<group>
<field name="property_account_payable" groups="account.group_account_invoice"/>
<field name="property_supplier_payment_term" widget="selection"/>
<field name="debit"/>
</group>
</group>

View File

@ -68,6 +68,7 @@
<field eval="&quot;&quot;&quot;Accounting&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;Accounting entries.&quot;&quot;&quot;" name="note"/>
<field name="process_id" ref="process_process_supplierinvoiceprocess0"/>
<field eval="&quot;&quot;&quot;object.state=='posted'&quot;&quot;&quot;" name="model_states"/>
<field eval="0" name="flow_start"/>
</record>

View File

@ -19,7 +19,7 @@
#
##############################################################################
from osv import fields, osv
from openerp.osv import fields, osv
class product_category(osv.osv):
_inherit = "product.category"

View File

@ -4,6 +4,7 @@
<record id="product_normal_form_view" model="ir.ui.view">
<field name="name">product.normal.form.inherit</field>
<field name="model">product.product</field>
<field name="priority">5</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<notebook position="inside">

View File

@ -19,8 +19,7 @@
#
##############################################################################
from osv import fields
from osv import osv
from openerp.osv import fields, osv
class account_analytic_journal(osv.osv):
_name = 'account.analytic.journal'

View File

@ -9,13 +9,13 @@
<field name="arch" type="xml">
<tree toolbar="1" colors="red:state=='pending';grey:state in ('cancelled','close');blue:type=='view'" string="Analytic Accounts">
<field name="complete_name"/>
<field name="partner_id"/>
<field name="code"/>
<field name="quantity"/>
<field name="date"/>
<field name="date_start" invisible="1"/>
<field name="user_id" invisible="1"/>
<field name="manager_id" invisible="1"/>
<field name="parent_id" invisible="1"/>
<field name="partner_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="type" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
@ -33,6 +33,7 @@
<filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','pending')]" help="Pending Accounts"/>
<filter icon="terp-camera_test" string="Current" domain="[('state','=','open')]" help="Current Accounts"/>
<field name="partner_id"/>
<field name="manager_id"/>
<field name="user_id"/>
<group expand="0" string="Group By...">
<filter string="Associated Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
@ -49,6 +50,7 @@
<field name="field_parent">child_complete_ids</field>
<field name="arch" type="xml">
<tree colors="blue:state=='pending';grey:state in ('close','cancelled');blue:type=='view'" string="Analytic account" toolbar="1">
<field name="name" invisible="1"/>
<field name="complete_name"/>
<field name="code"/>
<field name="debit"/>

View File

@ -21,7 +21,7 @@
import time
from report import report_sxw
from openerp.report import report_sxw
#
# Use period and Journal for selection or resources

Some files were not shown because too many files have changed in this diff Show More