[MERGE]:merged with main addons
bzr revid: ssu@tinyerp.com-20121008061925-puy5tlpntcmdrxr9
This commit is contained in:
commit
ae5c833184
|
@ -159,6 +159,5 @@ for a particular financial year and for preparation of vouchers there is a modul
|
|||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0080331923549',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -31,7 +31,7 @@ import decimal_precision as dp
|
|||
from tools.translate import _
|
||||
from tools.float_utils import float_round
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
import tools
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -227,7 +227,7 @@ class account_account(osv.osv):
|
|||
while pos < len(args):
|
||||
|
||||
if args[pos][0] == 'code' and args[pos][1] in ('like', 'ilike') and args[pos][2]:
|
||||
args[pos] = ('code', '=like', str(args[pos][2].replace('%', ''))+'%')
|
||||
args[pos] = ('code', '=like', tools.ustr(args[pos][2].replace('%', ''))+'%')
|
||||
if args[pos][0] == 'journal_id':
|
||||
if not args[pos][2]:
|
||||
del args[pos]
|
||||
|
@ -595,12 +595,15 @@ class account_account(osv.osv):
|
|||
res.append((record['id'], name))
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, id, default={}, context=None, done_list=[], local=False):
|
||||
def copy(self, cr, uid, id, default=None, context=None, done_list=None, local=False):
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
if done_list is None:
|
||||
done_list = []
|
||||
account = self.browse(cr, uid, id, context=context)
|
||||
new_child_ids = []
|
||||
if not default:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
default.update(code=_("%s (copy)") % (account['code'] or ''))
|
||||
if not local:
|
||||
done_list = []
|
||||
|
@ -682,7 +685,7 @@ class account_journal_view(osv.osv):
|
|||
_name = "account.journal.view"
|
||||
_description = "Journal View"
|
||||
_columns = {
|
||||
'name': fields.char('Journal View', size=64, required=True),
|
||||
'name': fields.char('Journal View', size=64, required=True, translate=True),
|
||||
'columns_id': fields.one2many('account.journal.column', 'view_id', 'Columns')
|
||||
}
|
||||
_order = "name"
|
||||
|
@ -777,11 +780,14 @@ class account_journal(osv.osv):
|
|||
(_check_currency, 'Configuration error!\nThe currency chosen should be shared by the default accounts too.', ['currency','default_debit_account_id','default_credit_account_id']),
|
||||
]
|
||||
|
||||
def copy(self, cr, uid, id, default={}, context=None, done_list=[], local=False):
|
||||
journal = self.browse(cr, uid, id, context=context)
|
||||
if not default:
|
||||
def copy(self, cr, uid, id, default=None, context=None, done_list=None, local=False):
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
if done_list is None:
|
||||
done_list = []
|
||||
journal = self.browse(cr, uid, id, context=context)
|
||||
default.update(
|
||||
code=_("%s (copy)") % (journal['code'] or ''),
|
||||
name=_("%s (copy)") % (journal['name'] or ''),
|
||||
|
@ -1178,7 +1184,7 @@ class account_fiscalyear(osv.osv):
|
|||
'end_journal_period_id':fields.many2one('account.journal.period','End of Year Entries Journal', readonly=True),
|
||||
}
|
||||
|
||||
def copy(self, cr, uid, id, default={}, context=None):
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
default.update({
|
||||
'period_ids': [],
|
||||
'end_journal_period_id': False
|
||||
|
@ -1437,9 +1443,15 @@ class account_move(osv.osv):
|
|||
result = super(account_move, self).create(cr, uid, vals, context)
|
||||
return result
|
||||
|
||||
def copy(self, cr, uid, id, default={}, context=None):
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if context is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
if context is None:
|
||||
context = {}
|
||||
else:
|
||||
context = context.copy()
|
||||
default.update({
|
||||
'state':'draft',
|
||||
'name':'/',
|
||||
|
@ -1908,7 +1920,7 @@ class account_tax(osv.osv):
|
|||
'ref_tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
|
||||
'include_base_amount': fields.boolean('Included in base amount', help="Indicates if the amount of tax must be included in the base amount for the computation of the next taxes"),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'description': fields.char('Tax Code',size=32),
|
||||
'description': fields.char('Tax Code'),
|
||||
'price_include': fields.boolean('Tax Included in Price', help="Check this if the price you use on the product and invoices includes this tax."),
|
||||
'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Application', required=True)
|
||||
|
||||
|
@ -2269,7 +2281,10 @@ class account_model(osv.osv):
|
|||
_defaults = {
|
||||
'legend': lambda self, cr, uid, context:_('You can specify year, month and date in the name of the model using the following labels:\n\n%(year)s: To Specify Year \n%(month)s: To Specify Month \n%(date)s: Current Date\n\ne.g. My model on %(date)s'),
|
||||
}
|
||||
def generate(self, cr, uid, ids, datas={}, context=None):
|
||||
|
||||
def generate(self, cr, uid, ids, data=None, context=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
move_ids = []
|
||||
entry = {}
|
||||
account_move_obj = self.pool.get('account.move')
|
||||
|
@ -2280,8 +2295,8 @@ class account_model(osv.osv):
|
|||
if context is None:
|
||||
context = {}
|
||||
|
||||
if datas.get('date', False):
|
||||
context.update({'date': datas['date']})
|
||||
if data.get('date', False):
|
||||
context.update({'date': data['date']})
|
||||
|
||||
move_date = context.get('date', time.strftime('%Y-%m-%d'))
|
||||
move_date = datetime.strptime(move_date,"%Y-%m-%d")
|
||||
|
@ -2467,10 +2482,10 @@ class account_subscription_line(osv.osv):
|
|||
all_moves = []
|
||||
obj_model = self.pool.get('account.model')
|
||||
for line in self.browse(cr, uid, ids, context=context):
|
||||
datas = {
|
||||
data = {
|
||||
'date': line.date,
|
||||
}
|
||||
move_ids = obj_model.generate(cr, uid, [line.subscription_id.model_id.id], datas, context)
|
||||
move_ids = obj_model.generate(cr, uid, [line.subscription_id.model_id.id], data, context)
|
||||
tocheck[line.subscription_id.id] = True
|
||||
self.write(cr, uid, [line.id], {'move_id':move_ids[0]})
|
||||
all_moves.extend(move_ids)
|
||||
|
@ -2518,7 +2533,7 @@ class account_account_template(osv.osv):
|
|||
'reconcile': fields.boolean('Allow Reconciliation', help="Check this option if you want the user to reconcile entries in this account."),
|
||||
'shortcut': fields.char('Shortcut', size=12),
|
||||
'note': fields.text('Note'),
|
||||
'parent_id': fields.many2one('account.account.template', 'Parent Account Template', ondelete='cascade'),
|
||||
'parent_id': fields.many2one('account.account.template', 'Parent Account Template', ondelete='cascade', domain=[('type','=','view')]),
|
||||
'child_parent_ids':fields.one2many('account.account.template', 'parent_id', 'Children'),
|
||||
'tax_ids': fields.many2many('account.tax.template', 'account_account_template_tax_rel', 'account_id', 'tax_id', 'Default Taxes'),
|
||||
'nocreate': fields.boolean('Optional create', help="If checked, the new chart of accounts will not contain this by default."),
|
||||
|
@ -2536,20 +2551,6 @@ class account_account_template(osv.osv):
|
|||
(_check_recursion, 'Error!\nYou cannot create recursive account templates.', ['parent_id']),
|
||||
]
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if 'parent_id' in vals:
|
||||
parent = self.read(cr, uid, [vals['parent_id']], ['type'])
|
||||
if parent and parent[0]['type'] != 'view':
|
||||
raise osv.except_osv(_('Warning!'), _("You may only select a parent account of type 'View'."))
|
||||
return super(account_account_template, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if 'parent_id' in vals:
|
||||
parent = self.read(cr, uid, [vals['parent_id']], ['type'])
|
||||
if parent and parent[0]['type'] != 'view':
|
||||
raise osv.except_osv(_('Warning!'), _("You may only select a parent account of type 'View'."))
|
||||
return super(account_account_template, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not ids:
|
||||
return []
|
||||
|
@ -2828,7 +2829,7 @@ class account_tax_template(osv.osv):
|
|||
'ref_base_sign': fields.float('Base Code Sign', help="Usually 1 or -1."),
|
||||
'ref_tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
|
||||
'include_base_amount': fields.boolean('Include in Base Amount', help="Set if the amount of tax must be included in the base amount before computing the next taxes."),
|
||||
'description': fields.char('Internal Name', size=32),
|
||||
'description': fields.char('Internal Name'),
|
||||
'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Use In', required=True,),
|
||||
'price_include': fields.boolean('Tax Included in Price', help="Check this if the price you use on the product and invoices includes this tax."),
|
||||
}
|
||||
|
@ -3250,7 +3251,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
|||
property_obj.create(cr, uid, vals, context=context)
|
||||
return True
|
||||
|
||||
def _install_template(self, cr, uid, template_id, company_id, code_digits=None, obj_wizard=None, acc_ref={}, taxes_ref={}, tax_code_ref={}, context=None):
|
||||
def _install_template(self, cr, uid, template_id, company_id, code_digits=None, obj_wizard=None, acc_ref=None, taxes_ref=None, tax_code_ref=None, context=None):
|
||||
'''
|
||||
This function recursively loads the template objects and create the real objects from them.
|
||||
|
||||
|
@ -3268,6 +3269,12 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
|||
* a last identical containing the mapping of tax code templates and tax codes
|
||||
:rtype: tuple(dict, dict, dict)
|
||||
'''
|
||||
if acc_ref is None:
|
||||
acc_ref = {}
|
||||
if taxes_ref is None:
|
||||
taxes_ref = {}
|
||||
if tax_code_ref is None:
|
||||
tax_code_ref = {}
|
||||
template = self.pool.get('account.chart.template').browse(cr, uid, template_id, context=context)
|
||||
if template.parent_id:
|
||||
tmp1, tmp2, tmp3 = self._install_template(cr, uid, template.parent_id.id, company_id, code_digits=code_digits, acc_ref=acc_ref, taxes_ref=taxes_ref, tax_code_ref=tax_code_ref, context=context)
|
||||
|
@ -3280,7 +3287,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
|||
tax_code_ref.update(tmp3)
|
||||
return acc_ref, taxes_ref, tax_code_ref
|
||||
|
||||
def _load_template(self, cr, uid, template_id, company_id, code_digits=None, obj_wizard=None, account_ref={}, taxes_ref={}, tax_code_ref={}, context=None):
|
||||
def _load_template(self, cr, uid, template_id, company_id, code_digits=None, obj_wizard=None, account_ref=None, taxes_ref=None, tax_code_ref=None, context=None):
|
||||
'''
|
||||
This function generates all the objects from the templates
|
||||
|
||||
|
@ -3298,6 +3305,12 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
|||
* a last identical containing the mapping of tax code templates and tax codes
|
||||
:rtype: tuple(dict, dict, dict)
|
||||
'''
|
||||
if account_ref is None:
|
||||
account_ref = {}
|
||||
if taxes_ref is None:
|
||||
taxes_ref = {}
|
||||
if tax_code_ref is None:
|
||||
tax_code_ref = {}
|
||||
template = self.pool.get('account.chart.template').browse(cr, uid, template_id, context=context)
|
||||
obj_tax_code_template = self.pool.get('account.tax.code.template')
|
||||
obj_acc_tax = self.pool.get('account.tax')
|
||||
|
|
|
@ -29,12 +29,12 @@ class bank(osv.osv):
|
|||
'currency_id': fields.related('journal_id', 'currency', type="many2one", relation='res.currency', readonly=True,
|
||||
string="Currency", help="Currency of the related account journal."),
|
||||
}
|
||||
def create(self, cr, uid, data, context={}):
|
||||
def create(self, cr, uid, data, context=None):
|
||||
result = super(bank, self).create(cr, uid, data, context=context)
|
||||
self.post_write(cr, uid, [result], context=context)
|
||||
return result
|
||||
|
||||
def write(self, cr, uid, ids, data, context={}):
|
||||
def write(self, cr, uid, ids, data, context=None):
|
||||
result = super(bank, self).write(cr, uid, ids, data, context=context)
|
||||
self.post_write(cr, uid, ids, context=context)
|
||||
return result
|
||||
|
@ -53,7 +53,7 @@ class bank(osv.osv):
|
|||
data['currency_name'] = data['currency_id'] and currency_name[data['currency_id'][0]] or ''
|
||||
return super(bank, self)._prepare_name_get(cr, uid, bank_dicts, context=context)
|
||||
|
||||
def post_write(self, cr, uid, ids, context={}):
|
||||
def post_write(self, cr, uid, ids, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
|
||||
|
|
|
@ -457,12 +457,13 @@ class account_bank_statement(osv.osv):
|
|||
return res and res[0] or 0.0
|
||||
|
||||
def onchange_journal_id(self, cr, uid, statement_id, journal_id, context=None):
|
||||
if not journal_id:
|
||||
return {}
|
||||
balance_start = self._compute_balance_end_real(cr, uid, journal_id, context=context)
|
||||
|
||||
journal_data = self.pool.get('account.journal').read(cr, uid, journal_id, ['default_debit_account_id', 'company_id'], context=context)
|
||||
account_id = journal_data['default_debit_account_id']
|
||||
journal_data = self.pool.get('account.journal').read(cr, uid, journal_id, ['company_id'], context=context)
|
||||
company_id = journal_data['company_id']
|
||||
return {'value': {'balance_start': balance_start, 'account_id': account_id, 'company_id': company_id}}
|
||||
return {'value': {'balance_start': balance_start, 'company_id': company_id}}
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
stat = self.read(cr, uid, ids, ['state'], context=context)
|
||||
|
|
|
@ -508,8 +508,10 @@ class account_invoice(osv.osv):
|
|||
if journal_id:
|
||||
journal = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context)
|
||||
currency_id = journal.currency and journal.currency.id or journal.company_id.currency_id.id
|
||||
company_id = journal.company_id.id
|
||||
result = {'value': {
|
||||
'currency_id': currency_id,
|
||||
'company_id': company_id,
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
@ -1306,17 +1308,19 @@ class account_invoice(osv.osv):
|
|||
|
||||
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))), 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))), 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)
|
||||
self.message_post(cr, uid, [obj.id], body=_("%s <b>cancelled</b>.") % (self._get_document_type(obj.type)),
|
||||
context=context)
|
||||
|
||||
account_invoice()
|
||||
|
||||
class account_invoice_line(osv.osv):
|
||||
|
||||
|
@ -1371,7 +1375,10 @@ class account_invoice_line(osv.osv):
|
|||
'partner_id': fields.related('invoice_id','partner_id',type='many2one',relation='res.partner',string='Partner',store=True)
|
||||
}
|
||||
|
||||
def _default_account_id(self, cr, uid, ids, context=None):
|
||||
def _default_account_id(self, cr, uid, context=None):
|
||||
# XXX this gets the default account for the user's company,
|
||||
# it should get the default account for the invoice's company
|
||||
# however, the invoice's company does not reach this point
|
||||
prop = self.pool.get('ir.property').get(cr, uid, 'property_account_income_categ', 'product.category', context=context)
|
||||
return prop and prop.id or False
|
||||
|
||||
|
@ -1401,7 +1408,7 @@ class account_invoice_line(osv.osv):
|
|||
context = {}
|
||||
company_id = company_id if company_id != None else context.get('company_id',False)
|
||||
context = dict(context)
|
||||
context.update({'company_id': company_id})
|
||||
context.update({'company_id': company_id, 'force_company': company_id})
|
||||
if not partner_id:
|
||||
raise osv.except_osv(_('No Partner Defined !'),_("You must first select a partner !") )
|
||||
if not product:
|
||||
|
@ -1556,16 +1563,19 @@ class account_invoice_line(osv.osv):
|
|||
def onchange_account_id(self, cr, uid, ids, product_id, partner_id, inv_type, fposition_id, account_id):
|
||||
if not account_id:
|
||||
return {}
|
||||
taxes = self.pool.get('account.account').browse(cr, uid, account_id).tax_ids
|
||||
unique_tax_ids = []
|
||||
fpos = fposition_id and self.pool.get('account.fiscal.position').browse(cr, uid, fposition_id) or False
|
||||
tax_ids = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
|
||||
|
||||
account = self.pool.get('account.account').browse(cr, uid, account_id)
|
||||
if not product_id:
|
||||
taxes = account.tax_ids
|
||||
unique_tax_ids = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
|
||||
else:
|
||||
product_change_result = self.product_id_change(cr, uid, ids, product_id, False, type=inv_type,
|
||||
partner_id=partner_id, fposition_id=fposition_id)
|
||||
unique_tax_ids = set(tax_ids)
|
||||
partner_id=partner_id, fposition_id=fposition_id,
|
||||
company_id=account.company_id.id)
|
||||
if product_change_result and 'value' in product_change_result and 'invoice_line_tax_id' in product_change_result['value']:
|
||||
unique_tax_ids |= set(product_change_result['value']['invoice_line_tax_id'])
|
||||
return {'value':{'invoice_line_tax_id': list(unique_tax_ids)}}
|
||||
unique_tax_ids = product_change_result['value']['invoice_line_tax_id']
|
||||
return {'value':{'invoice_line_tax_id': unique_tax_ids}}
|
||||
|
||||
account_invoice_line()
|
||||
|
||||
|
@ -1650,14 +1660,13 @@ class account_invoice_tax(osv.osv):
|
|||
|
||||
for line in inv.invoice_line:
|
||||
for tax in tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, (line.price_unit* (1-(line.discount or 0.0)/100.0)), line.quantity, line.product_id, inv.partner_id)['taxes']:
|
||||
tax['price_unit'] = cur_obj.round(cr, uid, cur, tax['price_unit'])
|
||||
val={}
|
||||
val['invoice_id'] = inv.id
|
||||
val['name'] = tax['name']
|
||||
val['amount'] = tax['amount']
|
||||
val['manual'] = False
|
||||
val['sequence'] = tax['sequence']
|
||||
val['base'] = tax['price_unit'] * line['quantity']
|
||||
val['base'] = cur_obj.round(cr, uid, cur, tax['price_unit'] * line['quantity'])
|
||||
|
||||
if inv.type in ('out_invoice','in_invoice'):
|
||||
val['base_code_id'] = tax['base_code_id']
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
</group>
|
||||
<notebook>
|
||||
<page string="Invoice">
|
||||
<field context="{'partner_id': partner_id, 'price_type': 'price_type' in dir() and price_type or False, 'type': type}" name="invoice_line">
|
||||
<field context="{'partner_id': partner_id, 'price_type': context.get('price_type') or False, 'type': type}" name="invoice_line">
|
||||
<tree string="Invoice lines" editable="bottom">
|
||||
<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)"/>
|
||||
|
@ -299,8 +299,8 @@
|
|||
<button name="invoice_open" states="draft" string="Validate" class="oe_highlight"/>
|
||||
<button name="invoice_open" states="proforma2" string="Validate"/>
|
||||
<button name="invoice_proforma2" states="draft" string="PRO-FORMA" groups="account.group_proforma_invoices"/>
|
||||
<button name="%(action_account_invoice_refund)d" type='action' string='Refund Invoice' states='paid'/>
|
||||
<button name="invoice_cancel" states="draft,proforma2,sale,open" string="Cancel" groups="base.group_no_one"/>
|
||||
<button name="%(action_account_invoice_refund)d" type='action' string='Refund Invoice' states='open,proforma2,paid'/>
|
||||
<button name="invoice_cancel" states="draft,proforma2,open" string="Cancel" groups="base.group_no_one"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Reset to Draft" type="object"/>
|
||||
<button name='%(action_account_state_open)d' type='action' string='Re-Open' groups="account.group_account_invoice" attrs="{'invisible':['|', ('state','<>','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."/>
|
||||
<!--button name="%(account_invoices)d" string="Print Invoice" type="action" states="open,paid,proforma,sale,proforma2"/-->
|
||||
|
|
|
@ -562,6 +562,7 @@ class account_move_line(osv.osv):
|
|||
'journal_id': lambda self, cr, uid, c: c.get('journal_id', False),
|
||||
'credit': 0.0,
|
||||
'debit': 0.0,
|
||||
'amount_currency': 0.0,
|
||||
'account_id': lambda self, cr, uid, c: c.get('account_id', False),
|
||||
'period_id': lambda self, cr, uid, c: c.get('period_id', False),
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.move.line', context=c)
|
||||
|
@ -1104,7 +1105,7 @@ class account_move_line(osv.osv):
|
|||
'has been confirmed.') % res[2])
|
||||
return res
|
||||
|
||||
def _remove_move_reconcile(self, cr, uid, move_ids=[], context=None):
|
||||
def _remove_move_reconcile(self, cr, uid, move_ids=None, context=None):
|
||||
# Function remove move rencocile ids related with moves
|
||||
obj_move_line = self.pool.get('account.move.line')
|
||||
obj_move_rec = self.pool.get('account.move.reconcile')
|
||||
|
@ -1193,12 +1194,12 @@ class account_move_line(osv.osv):
|
|||
jour_period_obj = self.pool.get('account.journal.period')
|
||||
cr.execute('SELECT state FROM account_journal_period WHERE journal_id = %s AND period_id = %s', (journal_id, period_id))
|
||||
result = cr.fetchall()
|
||||
for (state,) in result:
|
||||
if state == 'done':
|
||||
raise osv.except_osv(_('Error!'), _('You cannot add/modify entries in a closed journal.'))
|
||||
if not result:
|
||||
journal = journal_obj.browse(cr, uid, journal_id, context=context)
|
||||
period = period_obj.browse(cr, uid, period_id, context=context)
|
||||
for (state,) in result:
|
||||
if state == 'done':
|
||||
raise osv.except_osv(_('Error !'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name)))
|
||||
if not result:
|
||||
jour_period_obj.create(cr, uid, {
|
||||
'name': (journal.code or journal.name)+':'+(period.name or ''),
|
||||
'journal_id': journal.id,
|
||||
|
|
|
@ -1305,16 +1305,6 @@
|
|||
Account.Entry Edition
|
||||
-->
|
||||
|
||||
<record id="account_move_graph" model="ir.ui.view">
|
||||
<field name="name">account.move.graph</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Account Statistics" type="bar">
|
||||
<field name="period_id"/>
|
||||
<field name="amount" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_move_tree" model="ir.ui.view">
|
||||
<field name="name">account.move.tree</field>
|
||||
<field name="model">account.move</field>
|
||||
|
@ -1338,8 +1328,8 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Account Entry" version="7.0">
|
||||
<header>
|
||||
<button name="button_validate" states="draft" string="Post" type="object" class="oe_highlight"/>
|
||||
<button name="button_cancel" states="posted" string="Cancel" type="object"/>
|
||||
<button name="button_validate" states="draft" string="Post" type="object" class="oe_highlight" groups="account.group_account_invoice"/>
|
||||
<button name="button_cancel" states="posted" string="Cancel" type="object" groups="account.group_account_invoice"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet string="Journal Entries" >
|
||||
|
@ -1488,7 +1478,7 @@
|
|||
<field name="name">Journal Entries</field>
|
||||
<field name="res_model">account.move</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_move_tree"/>
|
||||
<field name="search_view_id" ref="view_account_move_filter"/>
|
||||
<field name="help" type="html">
|
||||
|
@ -1559,10 +1549,7 @@
|
|||
<field name="view_mode">account_reconciliation_list</field>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
Good job!
|
||||
</p><p>
|
||||
There is nothing to reconcile. All invoices and payments
|
||||
have been reconciled, your partner balance is clean.
|
||||
No journal items found.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -2037,7 +2024,7 @@
|
|||
src_model="account.journal"/>
|
||||
|
||||
<act_window
|
||||
context="{'search_default_reconcile_id':False, 'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
|
||||
context="{'search_default_unreconciled':True, 'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
|
||||
domain="[('account_id.reconcile', '=', True),('account_id.type', 'in', ['receivable', 'payable'])]"
|
||||
id="act_account_partner_account_move_all"
|
||||
name="Receivables & Payables"
|
||||
|
@ -2073,7 +2060,7 @@
|
|||
id="account_template_folder"
|
||||
name="Templates"
|
||||
parent="menu_finance_accounting"
|
||||
groups="base.group_multi_company"/>
|
||||
groups="account.group_account_manager"/>
|
||||
<menuitem
|
||||
id="account_template_taxes"
|
||||
name="Taxes"
|
||||
|
|
|
@ -518,7 +518,6 @@
|
|||
<!--
|
||||
Account Statement Sequences
|
||||
-->
|
||||
|
||||
<record id="sequence_reconcile" model="ir.sequence.type">
|
||||
<field name="name">Account Reconcile</field>
|
||||
<field name="code">account.reconcile</field>
|
||||
|
@ -554,8 +553,6 @@
|
|||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!--
|
||||
Invoice requests (deprecated)
|
||||
-->
|
||||
|
@ -564,7 +561,14 @@
|
|||
<field name="object">account.invoice</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<!-- mail: subtypes -->
|
||||
<record id="mt_invoice_new" model="mail.message.subtype">
|
||||
<field name="name">created</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
</record>
|
||||
<record id="mt_invoice_paid" model="mail.message.subtype">
|
||||
<field name="name">paid</field>
|
||||
<field name="res_model">account.invoice</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -44,17 +44,17 @@ class account_fiscal_position(osv.osv):
|
|||
return []
|
||||
if not fposition_id:
|
||||
return map(lambda x: x.id, taxes)
|
||||
result = []
|
||||
result = set()
|
||||
for t in taxes:
|
||||
ok = False
|
||||
for tax in fposition_id.tax_ids:
|
||||
if tax.tax_src_id.id == t.id:
|
||||
if tax.tax_dest_id:
|
||||
result.append(tax.tax_dest_id.id)
|
||||
result.add(tax.tax_dest_id.id)
|
||||
ok=True
|
||||
if not ok:
|
||||
result.append(t.id)
|
||||
return result
|
||||
result.add(t.id)
|
||||
return list(result)
|
||||
|
||||
def map_account(self, cr, uid, fposition_id, account_id, context=None):
|
||||
if not fposition_id:
|
||||
|
@ -77,6 +77,12 @@ class account_fiscal_position_tax(osv.osv):
|
|||
'tax_dest_id': fields.many2one('account.tax', 'Replacement Tax')
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
('tax_src_dest_uniq',
|
||||
'unique (position_id,tax_src_id,tax_dest_id)',
|
||||
'A tax fiscal position could be defined only once time on same taxes.')
|
||||
]
|
||||
|
||||
account_fiscal_position_tax()
|
||||
|
||||
class account_fiscal_position_account(osv.osv):
|
||||
|
@ -89,6 +95,12 @@ class account_fiscal_position_account(osv.osv):
|
|||
'account_dest_id': fields.many2one('account.account', 'Account Destination', domain=[('type','<>','view')], required=True)
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
('account_src_dest_uniq',
|
||||
'unique (position_id,account_src_id,account_dest_id)',
|
||||
'An account fiscal position could be defined only once time on same accounts.')
|
||||
]
|
||||
|
||||
account_fiscal_position_account()
|
||||
|
||||
class res_partner(osv.osv):
|
||||
|
|
|
@ -92,34 +92,7 @@
|
|||
<field name="debit"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="bank_ids">
|
||||
<form string="Bank account" version="7.0">
|
||||
<group col="4">
|
||||
<field name="state"/>
|
||||
<field name="acc_number"/>
|
||||
</group>
|
||||
<group>
|
||||
<group name="owner" string="Bank Account Owner">
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="owner_name"/>
|
||||
<label for="street" string="Address"/>
|
||||
<div>
|
||||
<field name="street" placeholder="Street..."/>
|
||||
<div>
|
||||
<field name="zip" class="oe_inline" placeholder="ZIP"/>
|
||||
<field name="city" class="oe_inline" placeholder="City"/>
|
||||
</div>
|
||||
<field name="state_id" placeholder="State" options='{"no_open": true}'/>
|
||||
<field name="country_id" placeholder="Country" options='{"no_open": true}'/>
|
||||
</div>
|
||||
</group>
|
||||
<group name="bank" string="Information About the Bank">
|
||||
<field name="bank" on_change="onchange_bank_id(bank)"/>
|
||||
<field name="bank_name"/>
|
||||
<field name="bank_bic" placeholder="e.g. GEBABEBB"/>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
<field name="bank_ids" context="{'default_partner_id': active_id, 'form_view_ref': 'base.view_partner_bank_form'}">
|
||||
<tree string="Bank Details">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="acc_number"/>
|
||||
|
@ -141,7 +114,7 @@
|
|||
context="{'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
|
||||
src_model="res.partner"
|
||||
view_type="form"
|
||||
view_mode="tree,form,graph,calendar"/>
|
||||
view_mode="tree,form,calendar"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,graph,form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_account_analytic_account_tree"/>
|
||||
<field name="search_view_id" ref="account.view_account_analytic_account_search"/>
|
||||
</record>
|
||||
|
@ -114,9 +114,6 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem groups="analytic.group_analytic_accounting" id="next_id_40"
|
||||
name="Analytic" parent="account.menu_finance_generic_reporting"
|
||||
sequence="4"/>
|
||||
|
||||
<record id="view_account_analytic_line_form" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.form</field>
|
||||
|
@ -351,15 +348,6 @@
|
|||
# Reporting
|
||||
#
|
||||
|
||||
<record id="action_account_analytic_journal_tree" model="ir.actions.act_window">
|
||||
<field name="name">Print Analytic Journals</field>
|
||||
<field name="res_model">account.analytic.journal</field>
|
||||
<field name="view_type">tree</field>
|
||||
<field name="help">To print an analytics (or costs) journal for a given period. The report give code, move name, account number, general amount and analytic amount.</field>
|
||||
</record>
|
||||
<menuitem groups="analytic.group_analytic_accounting"
|
||||
action="action_account_analytic_journal_tree"
|
||||
id="account_analytic_journal_print" parent="account.next_id_40"/>
|
||||
|
||||
<record id="view_account_journal_1" model="ir.ui.view">
|
||||
<field name="name">account.journal.form.1</field>
|
||||
|
@ -372,16 +360,5 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="analytic_accounts_graph" model="ir.ui.view">
|
||||
<field name="name">analytic.accounts.graph</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Analytic Account Statistics" type="bar">
|
||||
<field name="complete_name"/>
|
||||
<field name="balance" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -29,6 +29,7 @@ class account_analytic_journal_report(osv.osv_memory):
|
|||
_columns = {
|
||||
'date1': fields.date('Start of period', required=True),
|
||||
'date2': fields.date('End of period', required=True),
|
||||
'analytic_account_journal_id': fields.many2many('account.analytic.journal', 'account_analytic_journal_name', 'journal_line_id', 'journal_print_id', 'Analytic Journals', required=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -40,8 +41,15 @@ class account_analytic_journal_report(osv.osv_memory):
|
|||
if context is None:
|
||||
context = {}
|
||||
data = self.read(cr, uid, ids)[0]
|
||||
ids_list = []
|
||||
if context.get('active_id',False):
|
||||
ids_list.append(context.get('active_id',False))
|
||||
else:
|
||||
record = self.browse(cr,uid,ids[0],context=context)
|
||||
for analytic_record in record.analytic_account_journal_id:
|
||||
ids_list.append(analytic_record.id)
|
||||
datas = {
|
||||
'ids': context.get('active_ids',[]),
|
||||
'ids': ids_list,
|
||||
'model': 'account.analytic.journal',
|
||||
'form': data
|
||||
}
|
||||
|
@ -51,5 +59,13 @@ class account_analytic_journal_report(osv.osv_memory):
|
|||
'datas': datas,
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = super(account_analytic_journal_report, self).default_get(cr, uid, fields, context=context)
|
||||
if 'analytic_account_journal_id' in fields:
|
||||
res.update({'analytic_account_journal_id': context.get('active_ids',[])})
|
||||
return res
|
||||
|
||||
account_analytic_journal_report()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -7,15 +7,16 @@
|
|||
<field name="model">account.analytic.journal.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Select Period" version="7.0">
|
||||
<header>
|
||||
<button name="check_report" string="Print" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
</header>
|
||||
<group col="4">
|
||||
<field name="date1"/>
|
||||
<field name="date2"/>
|
||||
<field name="analytic_account_journal_id" widget="many2many_tags" class="oe_inline" required="1"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="check_report" string="Print" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -39,5 +40,12 @@
|
|||
<field name="model">account.analytic.journal</field>
|
||||
</record>
|
||||
|
||||
<menuitem groups="analytic.group_analytic_accounting" id="next_id_40"
|
||||
name="Analytic" parent="account.menu_finance_generic_reporting"
|
||||
sequence="4"/>
|
||||
<menuitem groups="analytic.group_analytic_accounting"
|
||||
action="account.action_account_analytic_journal"
|
||||
id="account_analytic_journal_print" parent="account.next_id_40"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -68,7 +68,7 @@ class account_balance(report_sxw.rml_parse, common_report_header):
|
|||
return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['id']).company_id.name
|
||||
return super(account_balance ,self)._get_account(data)
|
||||
|
||||
def lines(self, form, ids=[], done=None):#, level=1):
|
||||
def lines(self, form, ids=None, done=None):
|
||||
def _process_child(accounts, disp_acc, parent):
|
||||
account_rec = [acct for acct in accounts if acct['id']==parent][0]
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
|
|
|
@ -160,7 +160,7 @@ class tax_report(report_sxw.rml_parse, common_report_header):
|
|||
i+=1
|
||||
return res
|
||||
|
||||
def _get_codes(self, based_on, company_id, parent=False, level=0, period_list=[], context=None):
|
||||
def _get_codes(self, based_on, company_id, parent=False, level=0, period_list=None, context=None):
|
||||
obj_tc = self.pool.get('account.tax.code')
|
||||
ids = obj_tc.search(self.cr, self.uid, [('parent_id','=',parent),('company_id','=',company_id)], order='sequence', context=context)
|
||||
|
||||
|
@ -171,7 +171,11 @@ class tax_report(report_sxw.rml_parse, common_report_header):
|
|||
res += self._get_codes(based_on, company_id, code.id, level+1, context=context)
|
||||
return res
|
||||
|
||||
def _add_codes(self, based_on, account_list=[], period_list=[], context=None):
|
||||
def _add_codes(self, based_on, account_list=None, period_list=None, context=None):
|
||||
if account_list is None:
|
||||
account_list = []
|
||||
if period_list is None:
|
||||
period_list = []
|
||||
res = []
|
||||
obj_tc = self.pool.get('account.tax.code')
|
||||
for account in account_list:
|
||||
|
|
|
@ -117,6 +117,9 @@ class account_config_settings(osv.osv_memory):
|
|||
'group_multi_currency': fields.boolean('Allow multi currencies',
|
||||
implied_group='base.group_multi_currency',
|
||||
help="Allows you multi currency environment"),
|
||||
'group_analytic_accounting': fields.boolean('Analytic accounting',
|
||||
implied_group='analytic.group_analytic_accounting',
|
||||
help="Allows you to use the analytic accounting."),
|
||||
}
|
||||
|
||||
def _default_company(self, cr, uid, context=None):
|
||||
|
|
|
@ -129,6 +129,10 @@
|
|||
<field name="module_account_accountant" class="oe_inline"/>
|
||||
<label for="module_account_accountant"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="group_analytic_accounting" class="oe_inline"/>
|
||||
<label for="group_analytic_accounting"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="module_account_asset" class="oe_inline"/>
|
||||
<label for="module_account_asset"/>
|
||||
|
|
|
@ -45,4 +45,3 @@ class res_currency_account(osv.osv):
|
|||
res_currency_account()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</record>
|
||||
|
||||
<record id="group_account_manager" model="res.groups">
|
||||
<field name="name">Manager</field>
|
||||
<field name="name">Financial Manager</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||
<field name="implied_ids" eval="[(4, ref('group_account_user'))]"/>
|
||||
</record>
|
||||
|
|
|
@ -3,10 +3,17 @@
|
|||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="AccountReconciliation">
|
||||
<div class="oe_account_reconciliation">
|
||||
<t t-if="widget.current_partner === null">
|
||||
There is no pending reconciliation.
|
||||
<div class="oe_view_nocontent">
|
||||
<p>
|
||||
Good job!
|
||||
</p><p>
|
||||
There is nothing to reconcile. All invoices and payments
|
||||
have been reconciled, your partner balance is clean.
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
<div class="oe_account_reconciliation">
|
||||
<t t-if="widget.current_partner !== null">
|
||||
<div>
|
||||
<div>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
-
|
||||
I create a supplier invoice
|
||||
-
|
||||
!record {model: account.invoice, id: account_invoice_supplier0}:
|
||||
!record {model: account.invoice, id: account_invoice_supplier0, view: invoice_supplier_form}:
|
||||
account_id: account.a_pay
|
||||
check_total: 3000.0
|
||||
company_id: base.main_company
|
||||
|
|
|
@ -32,11 +32,11 @@ class account_invoice_refund(osv.osv_memory):
|
|||
_name = "account.invoice.refund"
|
||||
_description = "Invoice Refund"
|
||||
_columns = {
|
||||
'date': fields.date('Operation Date', help='This date will be used as the invoice date for credit note and period will be chosen accordingly!'),
|
||||
'date': fields.date('Date', help='This date will be used as the invoice date for credit note and period will be chosen accordingly!'),
|
||||
'period': fields.many2one('account.period', 'Force period'),
|
||||
'journal_id': fields.many2one('account.journal', 'Refund Journal', help='You can select here the journal to use for the credit note that will be created. If you leave that field empty, it will use the same journal as the current invoice.'),
|
||||
'description': fields.char('Description', size=128, required=True),
|
||||
'filter_refund': fields.selection([('refund', 'Create a draft refund'), ('cancel', 'Cancel: create credit note and reconcile'),('modify', 'Modify: create credit note, reconcile and create a new draft invoice')], "Refund Method", required=True, help='Credit note base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
|
||||
'description': fields.char('Reason', size=128, required=True),
|
||||
'filter_refund': fields.selection([('refund', 'Create a draft credit note'), ('cancel', 'Cancel: create credit note and reconcile'),('modify', 'Modify: create credit note, reconcile and create a new draft invoice')], "Refund Method", required=True, help='Credit note base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
|
||||
}
|
||||
|
||||
def _get_journal(self, cr, uid, context=None):
|
||||
|
|
|
@ -7,19 +7,40 @@
|
|||
<field name="model">account.invoice.refund</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Credit Note" version="7.0">
|
||||
<separator string="Credit Note Options"/>
|
||||
<group col="4">
|
||||
<group>
|
||||
<group colspan="2">
|
||||
<label for="filter_refund"/>
|
||||
<div>
|
||||
<field name="filter_refund" class="oe_inline"/>
|
||||
<p attrs="{'invisible':[('filter_refund','<>','refund')]}" class="oe_grey">
|
||||
You will be able to edit and validate this
|
||||
credit note directly or keep it draft,
|
||||
waiting for the document to be issued by
|
||||
your supplier/customer.
|
||||
</p>
|
||||
<p attrs="{'invisible':[('filter_refund','<>','cancel')]}" class="oe_grey">
|
||||
Use this option if you want to cancel an invoice you should not
|
||||
have issued. The credit note will be created, validated and reconciled
|
||||
with the invoice. You will not be able to modify the credit note.
|
||||
</p>
|
||||
<p attrs="{'invisible':[('filter_refund','<>','modify')]}" class="oe_grey">
|
||||
Use this option if you want to cancel an invoice and create a new
|
||||
one. The credit note will be created, validated and reconciled
|
||||
with the current invoice. A new, draft, invoice will be created
|
||||
so that you can edit it.
|
||||
</p>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="description"/>
|
||||
<field name="journal_id" widget='selection'/>
|
||||
</group><group>
|
||||
<field name="date"/>
|
||||
<field name="period"/>
|
||||
<field name="filter_refund"/>
|
||||
</group>
|
||||
<label string="Modify Invoice: Cancels the current invoice and creates a new copy of it ready for editing."/>
|
||||
<label string="Credit Note: Creates the credit note, ready for editing."/>
|
||||
<label string="Cancel Invoice: Creates the credit note, validate and reconcile it to cancel the current invoice."/>
|
||||
</group>
|
||||
<footer>
|
||||
<button string='Refund' name="invoice_refund" type="object" class="oe_highlight"/>
|
||||
<button string='Create Credit Note' name="invoice_refund" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
|
@ -28,7 +49,7 @@
|
|||
</record>
|
||||
|
||||
<record id="action_account_invoice_refund" model="ir.actions.act_window">
|
||||
<field name="name">Refund</field>
|
||||
<field name="name">Refund Invoice</field>
|
||||
<field name="res_model">account.invoice.refund</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
|
|
|
@ -38,7 +38,7 @@ class account_move_journal(osv.osv_memory):
|
|||
_defaults = {
|
||||
'target_move': 'all'
|
||||
}
|
||||
def _get_period(self, cr, uid, context={}):
|
||||
def _get_period(self, cr, uid, context=None):
|
||||
"""
|
||||
Return default account period value
|
||||
"""
|
||||
|
|
|
@ -23,6 +23,7 @@ import time
|
|||
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
import decimal_precision as dp
|
||||
|
||||
class account_move_line_reconcile(osv.osv_memory):
|
||||
"""
|
||||
|
@ -32,9 +33,9 @@ class account_move_line_reconcile(osv.osv_memory):
|
|||
_description = 'Account move line reconcile'
|
||||
_columns = {
|
||||
'trans_nbr': fields.integer('# of Transaction', readonly=True),
|
||||
'credit': fields.float('Credit amount', readonly=True),
|
||||
'debit': fields.float('Debit amount', readonly=True),
|
||||
'writeoff': fields.float('Write-Off amount', readonly=True),
|
||||
'credit': fields.float('Credit amount', readonly=True, digits_compute=dp.get_precision('Account')),
|
||||
'debit': fields.float('Debit amount', readonly=True, digits_compute=dp.get_precision('Account')),
|
||||
'writeoff': fields.float('Write-Off amount', readonly=True, digits_compute=dp.get_precision('Account')),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
|
|
|
@ -43,6 +43,5 @@ It assigns manager and user access rights to the Administrator and only user rig
|
|||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': True,
|
||||
'certificate': '00395091383933390541',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -26,9 +26,11 @@
|
|||
<field name="res_id" ref="mail.group_all_employees"/>
|
||||
<field name="type">notification</field>
|
||||
<field name="subject">Accounting and Finance application installed!</field>
|
||||
<field name="body">With OpenERP's accounting, you get instant access to your financial data, and can setup analytic accounting, forecast taxes, control budgets, easily create and send invoices, record bank statements, etc.
|
||||
<field name="body"><![CDATA[
|
||||
With OpenERP's accounting, you get instant access to your financial data, and can setup analytic accounting, forecast taxes, control budgets, easily create and send invoices, record bank statements, etc.
|
||||
|
||||
The accounting features are fully integrated with other OpenERP applications to automate all your processes: creation of customer invoices, control of supplier invoices, point-of-sale integration, automated follow-ups, etc.</field>
|
||||
<p>The accounting features are fully integrated with other OpenERP applications to automate all your processes: creation of customer invoices, control of supplier invoices, point-of-sale integration, automated follow-ups, etc.</p>
|
||||
]]></field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -47,7 +47,6 @@ Adds menu to show relevant information to each manager.You can also view the rep
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0042927202589',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<field name="name">Contracts to Renew</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_user_id':uid, 'search_default_draft':1, 'search_default_pending':1, 'search_default_open':1, 'search_default_renew':1}</field>
|
||||
<field name="domain">[('type','=','contract')]</field>
|
||||
<field name="search_view_id" ref="view_account_analytic_account_overdue_search"/>
|
||||
|
@ -72,7 +72,7 @@
|
|||
<field name="name">Contracts</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'default_type':'contract', 'search_default_open':1, 'search_default_pending':1}</field>
|
||||
<field name="domain">[('type','=','contract')]</field>
|
||||
<field name="search_view_id" ref="view_account_analytic_account_overdue_search"/>
|
||||
|
|
|
@ -47,7 +47,6 @@ Allows to automatically select analytic accounts based on criterions:
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0074229833581',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -79,7 +79,6 @@ The analytic plan validates the minimum and maximum percentage at the time of cr
|
|||
'test': ['test/acount_analytic_plans_report.yml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0036417675373',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -262,6 +262,7 @@ account_analytic_plan_instance()
|
|||
class account_analytic_plan_instance_line(osv.osv):
|
||||
_name = "account.analytic.plan.instance.line"
|
||||
_description = "Analytic Instance Line"
|
||||
_rec_name = "analytic_account_id"
|
||||
_columns = {
|
||||
'plan_id': fields.many2one('account.analytic.plan.instance', 'Plan Id'),
|
||||
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', required=True, domain=[('type','<>','view')]),
|
||||
|
|
|
@ -112,7 +112,9 @@ class crossovered_analytic(report_sxw.rml_parse):
|
|||
result.append(res)
|
||||
return result
|
||||
|
||||
def _lines(self, form, ids={}):
|
||||
def _lines(self, form, ids=None):
|
||||
if ids is None:
|
||||
ids = {}
|
||||
if not ids:
|
||||
ids = self.ids
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ account.""",
|
|||
'data': ['product_view.xml',],
|
||||
'auto_install': False,
|
||||
'installable': True,
|
||||
'certificate':'00557423080410733581',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
|
||||
#class sale_order_line(osv.osv):
|
||||
# _name = 'sale.order.line'
|
||||
# _description = 'Sale Order line'
|
||||
# _inherit = 'sale.order.line'
|
||||
#
|
||||
# def invoice_line_create(self, cr, uid, ids, context={}):
|
||||
# line_ids = super('sale_order_line',self).invoice_line_create(cr, uid, ids, context)
|
||||
# invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
# for line in invoice_line_obj.browse(cr, uid, line_ids):
|
||||
# if line.product_id:
|
||||
# a = line.product_id.product_tmpl_id.property_stock_account_output and line.product_id.product_tmpl_id.property_stock_account_output.id
|
||||
# if not a:
|
||||
# a = line.product_id.categ_id.property_stock_account_output_categ and line.product_id.categ_id.property_stock_account_output_categ.id
|
||||
# if a:
|
||||
# a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, a)
|
||||
# invoice_line_obj.write(cr, uid, line.id, {'account_id':a})
|
||||
#
|
||||
#sale_order_line()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -75,7 +75,7 @@ class account_asset_asset(osv.osv):
|
|||
_name = 'account.asset.asset'
|
||||
_description = 'Asset'
|
||||
|
||||
def _get_period(self, cr, uid, context={}):
|
||||
def _get_period(self, cr, uid, context=None):
|
||||
periods = self.pool.get('account.period').find(cr, uid)
|
||||
if periods:
|
||||
return periods[0]
|
||||
|
@ -176,7 +176,9 @@ class account_asset_asset(osv.osv):
|
|||
year = depreciation_date.year
|
||||
return True
|
||||
|
||||
def validate(self, cr, uid, ids, context={}):
|
||||
def validate(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
return self.write(cr, uid, ids, {
|
||||
'state':'open'
|
||||
}, context)
|
||||
|
@ -304,7 +306,7 @@ class account_asset_asset(osv.osv):
|
|||
default.update({'depreciation_line_ids': [], 'state': 'draft'})
|
||||
return super(account_asset_asset, self).copy(cr, uid, id, default, context=context)
|
||||
|
||||
def _compute_entries(self, cr, uid, ids, period_id, context={}):
|
||||
def _compute_entries(self, cr, uid, ids, period_id, context=None):
|
||||
result = []
|
||||
period_obj = self.pool.get('account.period')
|
||||
depreciation_obj = self.pool.get('account.asset.depreciation.line')
|
||||
|
@ -350,7 +352,7 @@ class account_asset_depreciation_line(osv.osv):
|
|||
'amount': fields.float('Depreciation Amount', required=True),
|
||||
'remaining_value': fields.float('Amount to Depreciate', required=True),
|
||||
'depreciated_value': fields.float('Amount Already Depreciated', required=True),
|
||||
'depreciation_date': fields.char('Depreciation Date', size=64, select=1),
|
||||
'depreciation_date': fields.date('Depreciation Date', select=1),
|
||||
'move_id': fields.many2one('account.move', 'Depreciation Entry'),
|
||||
'move_check': fields.function(_get_move_check, method=True, type='boolean', string='Posted', store=True)
|
||||
}
|
||||
|
@ -368,7 +370,7 @@ class account_asset_depreciation_line(osv.osv):
|
|||
for line in self.browse(cr, uid, ids, context=context):
|
||||
if currency_obj.is_zero(cr, uid, line.asset_id.currency_id, line.remaining_value):
|
||||
can_close = True
|
||||
depreciation_date = line.asset_id.prorata and line.asset_id.purchase_date or time.strftime('%Y-%m-%d')
|
||||
depreciation_date = time.strftime('%Y-%m-%d')
|
||||
period_ids = period_obj.find(cr, uid, depreciation_date, context=context)
|
||||
company_currency = line.asset_id.company_id.currency_id.id
|
||||
current_currency = line.asset_id.currency_id.id
|
||||
|
|
|
@ -57,6 +57,7 @@ class account_invoice_line(osv.osv):
|
|||
'partner_id': line.invoice_id.partner_id.id,
|
||||
'company_id': line.invoice_id.company_id.id,
|
||||
'currency_id': line.invoice_id.currency_id.id,
|
||||
'purchase_date' : line.invoice_id.date_invoice,
|
||||
}
|
||||
changed_vals = asset_obj.onchange_category_id(cr, uid, [], vals['category_id'], context=context)
|
||||
vals.update(changed_vals['value'])
|
||||
|
|
|
@ -50,7 +50,7 @@ class asset_asset_report(osv.osv):
|
|||
select
|
||||
min(dl.id) as id,
|
||||
dl.name as name,
|
||||
to_date(dl.depreciation_date, 'YYYY-MM-DD') as depreciation_date,
|
||||
dl.depreciation_date as depreciation_date,
|
||||
a.purchase_date as purchase_date,
|
||||
(CASE WHEN (select min(d.id) from account_asset_depreciation_line as d
|
||||
left join account_asset_asset as ac ON (ac.id=d.asset_id)
|
||||
|
@ -77,7 +77,7 @@ class asset_asset_report(osv.osv):
|
|||
from account_asset_depreciation_line dl
|
||||
left join account_asset_asset a on (dl.asset_id=a.id)
|
||||
group by
|
||||
dl.amount,dl.asset_id,to_date(dl.depreciation_date, 'YYYY-MM-DD'),dl.name,
|
||||
dl.amount,dl.asset_id,dl.depreciation_date,dl.name,
|
||||
a.purchase_date, dl.move_check, a.state, a.category_id, a.partner_id, a.company_id,
|
||||
a.purchase_value, a.id, a.salvage_value
|
||||
)""")
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
<field name="ref" readonly="1"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||
<field name="account_id" domain="[('journal_id','=',parent.journal_id)]"/>
|
||||
<field name="account_id" domain="[('journal_id','=',journal_id)]"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
||||
<field name="amount" readonly="1" sum="Total Amount"/>
|
||||
<field name="globalisation_id" string="Glob. Id"/>
|
||||
|
@ -100,7 +100,7 @@
|
|||
<field name="ref" readonly="0"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||
<field domain="[('journal_id', '=', parent.journal_id), ('type', '<>', 'view')]" name="account_id"/>
|
||||
<field domain="[('journal_id', '=', journal_id), ('type', '<>', 'view')]" name="account_id"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
||||
<field name="amount"/>
|
||||
<field name="globalisation_id"/>
|
||||
|
|
|
@ -69,6 +69,5 @@ Three reports are available:
|
|||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0043819694157',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -35,7 +35,9 @@ class analytic_account_budget_report(report_sxw.rml_parse):
|
|||
})
|
||||
self.context = context
|
||||
|
||||
def funct(self, object, form, ids={}, done=None, level=1):
|
||||
def funct(self, object, form, ids=None, done=None, level=1):
|
||||
if ids is None:
|
||||
ids = {}
|
||||
if not ids:
|
||||
ids = self.ids
|
||||
if not done:
|
||||
|
|
|
@ -34,7 +34,9 @@ class budget_report(report_sxw.rml_parse):
|
|||
})
|
||||
self.context = context
|
||||
|
||||
def funct(self, object, form, ids={}, done=None, level=1):
|
||||
def funct(self, object, form, ids=None, done=None, level=1):
|
||||
if ids is None:
|
||||
ids = {}
|
||||
if not ids:
|
||||
ids = self.ids
|
||||
if not done:
|
||||
|
|
|
@ -37,7 +37,9 @@ class budget_report(report_sxw.rml_parse):
|
|||
})
|
||||
self.context = context
|
||||
|
||||
def funct(self, object, form, ids={}, done=None, level=1):
|
||||
def funct(self, object, form, ids=None, done=None, level=1):
|
||||
if ids is None:
|
||||
ids = {}
|
||||
if not ids:
|
||||
ids = self.ids
|
||||
if not done:
|
||||
|
|
|
@ -38,9 +38,6 @@ If set to true it allows user to cancel entries & invoices.
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '001101250473177981989',
|
||||
|
||||
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -36,6 +36,5 @@ Deactivates minimal chart of accounts.
|
|||
'data': [],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'certificate': '0073332443901',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -64,7 +64,6 @@ Note that if you want to check the follow-up level for a given partner/account e
|
|||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0072481076453',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -65,6 +65,5 @@ have a new option to import payment orders as bank statement lines.
|
|||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0061703998541',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -26,7 +26,7 @@ from tools.translate import _
|
|||
class account_move_line(osv.osv):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
def amount_to_pay(self, cr, uid, ids, name, arg={}, context=None):
|
||||
def amount_to_pay(self, cr, uid, ids, name, arg=None, context=None):
|
||||
""" Return the amount still to pay regarding all the payemnt orders
|
||||
(excepting cancelled orders)"""
|
||||
if not ids:
|
||||
|
|
|
@ -139,7 +139,9 @@ class payment_order(osv.osv):
|
|||
wf_service.trg_validate(uid, 'payment.order', ids[0], 'done', cr)
|
||||
return True
|
||||
|
||||
def copy(self, cr, uid, id, default={}, context=None):
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({
|
||||
'state': 'draft',
|
||||
'line_ids': [],
|
||||
|
|
|
@ -88,7 +88,7 @@ class payment_order_create(osv.osv_memory):
|
|||
'partner_id': line.partner_id and line.partner_id.id or False,
|
||||
'communication': line.ref or '/',
|
||||
'date': date_to_pay,
|
||||
'currency': line.invoice and line.invoice.currency_id.id or False,
|
||||
'currency': (line.invoice and line.invoice.currency_id.id) or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id,
|
||||
}, context=context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
|
|
@ -86,24 +86,24 @@ class account_payment_populate_statement(osv.osv_memory):
|
|||
'name': line.name,
|
||||
'partner_id': line.partner_id.id,
|
||||
'journal_id': statement.journal_id.id,
|
||||
'account_id': result.get('account_id', statement.journal_id.default_credit_account_id.id),
|
||||
'account_id': result['value'].get('account_id', statement.journal_id.default_credit_account_id.id),
|
||||
'company_id': statement.company_id.id,
|
||||
'currency_id': statement.currency.id,
|
||||
'date': line.date or time.strftime('%Y-%m-%d'),
|
||||
'amount': abs(amount),
|
||||
'period_id': statement.period_id.id
|
||||
'period_id': statement.period_id.id,
|
||||
}
|
||||
voucher_id = voucher_obj.create(cr, uid, voucher_res, context=context)
|
||||
voucher_line_dict = False
|
||||
if result['value']['line_ids']:
|
||||
for line_dict in result['value']['line_ids']:
|
||||
|
||||
voucher_line_dict = {}
|
||||
for line_dict in result['value']['line_cr_ids'] + result['value']['line_dr_ids']:
|
||||
move_line = move_line_obj.browse(cr, uid, line_dict['move_line_id'], context)
|
||||
if line.move_line_id.move_id.id == move_line.move_id.id:
|
||||
voucher_line_dict = line_dict
|
||||
|
||||
if voucher_line_dict:
|
||||
voucher_line_dict.update({'voucher_id': voucher_id})
|
||||
voucher_line_obj.create(cr, uid, voucher_line_dict, context=context)
|
||||
|
||||
st_line_id = statement_line_obj.create(cr, uid, {
|
||||
'name': line.order_id.reference or '?',
|
||||
'amount': - amount,
|
||||
|
|
|
@ -49,7 +49,6 @@ You can customize the following attributes of the sequence:
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '00475376442024623469',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -72,7 +72,6 @@ This module manages:
|
|||
'test/case4_cad_chf.yml',
|
||||
'test/case_eur_usd.yml',
|
||||
],
|
||||
'certificate': '0037580727101',
|
||||
'auto_install': False,
|
||||
'application': True,
|
||||
'installable': True,
|
||||
|
|
|
@ -32,11 +32,11 @@ class res_company(osv.osv):
|
|||
_columns = {
|
||||
'income_currency_exchange_account_id': fields.many2one(
|
||||
'account.account',
|
||||
string="Income Currency Rate",
|
||||
string="Gain Exchange Rate Account",
|
||||
domain="[('type', '=', 'other')]",),
|
||||
'expense_currency_exchange_account_id': fields.many2one(
|
||||
'account.account',
|
||||
string="Expense Currency Rate",
|
||||
string="Loss Exchange Rate Account",
|
||||
domain="[('type', '=', 'other')]",),
|
||||
}
|
||||
|
||||
|
@ -547,6 +547,19 @@ class account_voucher(osv.osv):
|
|||
vals = self.recompute_payment_rate(cr, uid, ids, res, currency_id, date, ttype, journal_id, amount, context=context)
|
||||
for key in vals.keys():
|
||||
res[key].update(vals[key])
|
||||
#TODO: onchange_partner_id() should not returns [pre_line, line_dr_ids, payment_rate...] for type sale, and not
|
||||
# [pre_line, line_cr_ids, payment_rate...] for type purchase.
|
||||
# We should definitively split account.voucher object in two and make distinct on_change functions. In the
|
||||
# meanwhile, bellow lines must be there because the fields aren't present in the view, what crashes if the
|
||||
# onchange returns a value for them
|
||||
if ttype == 'sale':
|
||||
del(res['value']['line_dr_ids'])
|
||||
del(res['value']['pre_line'])
|
||||
del(res['value']['payment_rate'])
|
||||
elif ttype == 'purchase':
|
||||
del(res['value']['line_cr_ids'])
|
||||
del(res['value']['pre_line'])
|
||||
del(res['value']['payment_rate'])
|
||||
return res
|
||||
|
||||
def recompute_voucher_lines(self, cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context=None):
|
||||
|
@ -588,7 +601,7 @@ class account_voucher(osv.osv):
|
|||
|
||||
#set default values
|
||||
default = {
|
||||
'value': {'line_ids': [] ,'line_dr_ids': [] ,'line_cr_ids': [] ,'pre_line': False,},
|
||||
'value': {'line_dr_ids': [] ,'line_cr_ids': [] ,'pre_line': False,},
|
||||
}
|
||||
|
||||
#drop existing lines
|
||||
|
@ -667,6 +680,7 @@ class account_voucher(osv.osv):
|
|||
|
||||
#voucher line creation
|
||||
for line in account_move_lines:
|
||||
|
||||
if _remove_noise_in_o2m():
|
||||
continue
|
||||
|
||||
|
@ -771,6 +785,8 @@ class account_voucher(osv.osv):
|
|||
if account_id and account_id.tax_ids:
|
||||
tax_id = account_id.tax_ids[0].id
|
||||
|
||||
vals = {'value':{} }
|
||||
if ttype in ('sale', 'purchase'):
|
||||
vals = self.onchange_price(cr, uid, ids, line_ids, tax_id, partner_id, context)
|
||||
vals['value'].update({'tax_id':tax_id,'amount': amount})
|
||||
currency_id = False
|
||||
|
@ -782,9 +798,16 @@ class account_voucher(osv.osv):
|
|||
vals[key].update(res[key])
|
||||
return vals
|
||||
|
||||
def button_proforma_voucher(self, cr, uid, ids, context=None):
|
||||
context = context or {}
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
for vid in ids:
|
||||
wf_service.trg_validate(uid, 'account.voucher', vid, 'proforma_voucher', cr)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def proforma_voucher(self, cr, uid, ids, context=None):
|
||||
self.action_move_line_create(cr, uid, ids, context=context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
return True
|
||||
|
||||
def action_cancel_draft(self, cr, uid, ids, context=None):
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
|
@ -950,11 +973,11 @@ class account_voucher(osv.osv):
|
|||
if amount_residual > 0:
|
||||
account_id = line.voucher_id.company_id.expense_currency_exchange_account_id
|
||||
if not account_id:
|
||||
raise osv.except_osv(_('Warning!'),_("First you have to configure the 'Income Currency Rate' on the company, then create accounting entry for currency rate difference."))
|
||||
raise osv.except_osv(_('Warning!'),_("First you have to configure the 'Expense Currency Rate' on the company, then create accounting entry for currency rate difference."))
|
||||
else:
|
||||
account_id = line.voucher_id.company_id.income_currency_exchange_account_id
|
||||
if not account_id:
|
||||
raise osv.except_osv(_('Warning!'),_("First you have to configure the 'Expense Currency Rate' on the company, then create accounting entry for currency rate difference."))
|
||||
raise osv.except_osv(_('Warning!'),_("First you have to configure the 'Income Currency Rate' on the company, then create accounting entry for currency rate difference."))
|
||||
# Even if the amount_currency is never filled, we need to pass the foreign currency because otherwise
|
||||
# the receivable/payable account may have a secondary currency, which render this field mandatory
|
||||
account_currency_id = company_currency <> current_currency and current_currency or False
|
||||
|
@ -1176,6 +1199,7 @@ class account_voucher(osv.osv):
|
|||
account_id = voucher_brw.partner_id.property_account_receivable.id
|
||||
else:
|
||||
account_id = voucher_brw.partner_id.property_account_payable.id
|
||||
sign = voucher_brw.type == 'payment' and -1 or 1
|
||||
move_line = {
|
||||
'name': write_off_name or name,
|
||||
'account_id': account_id,
|
||||
|
@ -1184,7 +1208,7 @@ class account_voucher(osv.osv):
|
|||
'date': voucher_brw.date,
|
||||
'credit': diff > 0 and diff or 0.0,
|
||||
'debit': diff < 0 and -diff or 0.0,
|
||||
'amount_currency': company_currency <> current_currency and voucher_brw.writeoff_amount or False,
|
||||
'amount_currency': company_currency <> current_currency and (sign * -1 * voucher_brw.writeoff_amount) or False,
|
||||
'currency_id': company_currency <> current_currency and current_currency or False,
|
||||
'analytic_account_id': voucher_brw.analytic_id and voucher_brw.analytic_id.id or False,
|
||||
}
|
||||
|
@ -1268,7 +1292,9 @@ class account_voucher(osv.osv):
|
|||
self.reconcile_send_note(cr, uid, [voucher.id], context=context)
|
||||
return True
|
||||
|
||||
def copy(self, cr, uid, id, default={}, context=None):
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({
|
||||
'state': 'draft',
|
||||
'number': False,
|
||||
|
@ -1295,17 +1321,17 @@ class account_voucher(osv.osv):
|
|||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
message = "%s <b>created</b>." % self._document_type[obj.type or False]
|
||||
self.message_post(cr, uid, [obj.id], body=message, context=context)
|
||||
self.message_post(cr, uid, [obj.id], body=message, subtype="account_voucher.mt_voucher", context=context)
|
||||
|
||||
def post_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
message = "%s '%s' is <b>posted</b>." % (self._document_type[obj.type or False], obj.move_id.name)
|
||||
self.message_post(cr, uid, [obj.id], body=message, context=context)
|
||||
self.message_post(cr, uid, [obj.id], body=message, subtype="account_voucher.mt_voucher", context=context)
|
||||
|
||||
def reconcile_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
message = "%s <b>reconciled</b>." % self._document_type[obj.type or False]
|
||||
self.message_post(cr, uid, [obj.id], body=message, context=context)
|
||||
self.message_post(cr, uid, [obj.id], body=message, subtype="account_voucher.mt_voucher", context=context)
|
||||
|
||||
account_voucher()
|
||||
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- notify all employees of module installation -->
|
||||
<record model="mail.message" id="module_install_notification">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="res_id" ref="mail.group_all_employees"/>
|
||||
<field name="type">notification</field>
|
||||
<field name="subject">eInvoicing & Payments application installed!</field>
|
||||
<field name="body">OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.
|
||||
<field name="body"><![CDATA[
|
||||
OpenERP's electronic invoicing accelerates the creation of invoices and collection of customer payments. Invoices are created in a few clicks and your customers receive them by email. They can pay online and/or import them in their own system.
|
||||
|
||||
You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability.
|
||||
|
||||
For advanced accounting features, you should install the "Accounting and Finance" module.</field>
|
||||
<p>You can track customer payments easily and automate follow-ups. You get an overview of the discussion with your customers on each invoice for easier traceability. For advanced accounting features, you should install the "Accounting and Finance" module.</p>
|
||||
]]></field>
|
||||
</record>
|
||||
|
||||
<!-- mail: subtypes -->
|
||||
<record id="mt_voucher" model="mail.message.subtype">
|
||||
<field name="name">Status Change</field>
|
||||
<field name="res_model">account.voucher</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- where and when is this view used?? -->
|
||||
<record model="ir.ui.view" id="view_voucher_form">
|
||||
<field name="name">account.voucher.form</field>
|
||||
<field name="model">account.voucher</field>
|
||||
|
|
|
@ -27,11 +27,12 @@ class invoice(osv.osv):
|
|||
|
||||
def invoice_pay_customer(self, cr, uid, ids, context=None):
|
||||
if not ids: return []
|
||||
mod,modid = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_voucher', 'view_vendor_receipt_dialog_form')
|
||||
inv = self.browse(cr, uid, ids[0], context=context)
|
||||
return {
|
||||
'name':_("Pay Invoice"),
|
||||
'view_mode': 'form',
|
||||
'view_id': False,
|
||||
'view_id': modid,
|
||||
'view_type': 'form',
|
||||
'res_model': 'account.voucher',
|
||||
'type': 'ir.actions.act_window',
|
||||
|
@ -41,7 +42,7 @@ class invoice(osv.osv):
|
|||
'context': {
|
||||
'default_partner_id': inv.partner_id.id,
|
||||
'default_amount': inv.type in ('out_refund', 'in_refund') and -inv.residual or inv.residual,
|
||||
'default_name':inv.name,
|
||||
'default_number':inv.name,
|
||||
'close_after_process': True,
|
||||
'invoice_type': inv.type,
|
||||
'invoice_id': inv.id,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
-
|
||||
In order to check account voucher module in OpenERP I create a customer voucher
|
||||
-
|
||||
!record {model: account.voucher, id: account_voucher_voucherforaxelor0}:
|
||||
!record {model: account.voucher, id: account_voucher_voucherforaxelor0, view: view_sale_receipt_form}:
|
||||
type: sale
|
||||
account_id: account.cash
|
||||
amount: 1000.0
|
||||
company_id: base.main_company
|
||||
|
@ -47,7 +48,8 @@
|
|||
-
|
||||
Now I create a Vendor Voucher
|
||||
-
|
||||
!record {model: account.voucher, id: account_voucher_voucheraxelor0, view: False}:
|
||||
!record {model: account.voucher, id: account_voucher_voucheraxelor0, view: view_voucher_filter_vendor}:
|
||||
type: purchase
|
||||
account_id: account.cash
|
||||
amount: 1000.0
|
||||
company_id: base.main_company
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
-
|
||||
Demo for Account Voucher
|
||||
-
|
||||
!record {model: account.voucher, id: account_voucher_voucheraxelor0again}:
|
||||
!record {model: account.voucher, id: account_voucher_voucheraxelor0again, view: view_sale_receipt_form}:
|
||||
type: sale
|
||||
account_id: account.cash
|
||||
company_id: base.main_company
|
||||
journal_id: account.bank_journal
|
||||
|
|
|
@ -216,6 +216,10 @@
|
|||
assert move_line.credit == 63.00, "Debtor account has wrong entry."
|
||||
elif move_line.amount_currency == 10.00:
|
||||
assert move_line.debit == 9.00, "Writeoff amount is wrong."
|
||||
elif move_line.amount_currency == 240.00:
|
||||
assert move_line.debit == 216.00, "Bank entry is wrong."
|
||||
else:
|
||||
assert False, "Unrecognized journal entry"
|
||||
-
|
||||
I check the residual amount of Invoice1, should be 20 in amount_currency
|
||||
-
|
||||
|
@ -237,7 +241,7 @@
|
|||
-
|
||||
On the first April, I create the second voucher of payment with values 45 USD, journal USD,
|
||||
-
|
||||
!record {model: account.voucher, id: account_voucher_2_case1}:
|
||||
!record {model: account.voucher, id: account_voucher_2_case1, view: view_vendor_receipt_form}:
|
||||
account_id: account.cash
|
||||
amount: 45.0
|
||||
company_id: base.main_company
|
||||
|
@ -323,8 +327,16 @@
|
|||
assert move_line.debit == 4.75, "Writeoff amount is wrong."
|
||||
elif move_line.debit == 11.5 and move_line.account_id.reconcile:
|
||||
assert move_line.amount_currency == 0.0 and move_line.reconcile_id.id == reconcile_a, "Exchange difference entry for the invoice of 100$ is wrong"
|
||||
elif move_line.credit == 11.5:
|
||||
assert move_line.amount_currency == 0.0
|
||||
elif move_line.debit == 31.0 and move_line.account_id.reconcile:
|
||||
assert move_line.amount_currency == 0.0 and move_line.reconcile_id.id == reconcile_b, "Exchange difference entry for the invoice of 200$ is wrong"
|
||||
elif move_line.credit == 31.0:
|
||||
assert move_line.amount_currency == 0.0
|
||||
elif move_line.amount_currency == 45.00:
|
||||
assert move_line.debit == 42.75, "Bank entry is wrong."
|
||||
else:
|
||||
assert False, "Unrecognized journal entry"
|
||||
-
|
||||
I check the residual amount of Invoice1, should be 0 in residual currency and 0 in amount_residual and paid
|
||||
-
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
-
|
||||
I check that my currency rate difference is correct. 0 in debit with no amount_currency
|
||||
-
|
||||
I check that my writeoff is correct. 11.05 credit and 13.26 amount_currency
|
||||
I check that my writeoff is correct. 11.05 credit and -13.26 amount_currency
|
||||
-
|
||||
!python {model: account.voucher}: |
|
||||
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 4'), ('partner_id', '=', ref('base.res_partner_19'))])
|
||||
|
@ -179,7 +179,7 @@
|
|||
elif move_line.debit == 0.00 and move_line.credit == 0.00:
|
||||
assert move_line.amount_currency == 0.00, "Incorrect Currency Difference."
|
||||
elif move_line.credit == 10.61:
|
||||
assert move_line.amount_currency == 13.26, "Writeoff amount is wrong."
|
||||
assert move_line.amount_currency == -13.26, "Writeoff amount is wrong."
|
||||
else:
|
||||
assert False, "Wrong entry"
|
||||
-
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
-
|
||||
Creating a Voucher Receipt for partner Seagate with amount 30000.0
|
||||
-
|
||||
!record {model: account.voucher, id: account_voucher_seagate_0}:
|
||||
!record {model: account.voucher, id: account_voucher_seagate_0, view: view_sale_receipt_form}:
|
||||
account_id: account.a_recv
|
||||
amount: 30000.0
|
||||
company_id: base.main_company
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
</group>
|
||||
<notebook>
|
||||
<page string="Payment Information">
|
||||
<label for="line_dr_ids" attrs="{'invisible': [('type', '=', 'receipt')]}"/>
|
||||
<field name="line_dr_ids" attrs="{'invisible': [('type', '=', 'receipt')]}" context="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" colspan="4" nolabel="1" height="140" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
|
||||
<tree string="Open Supplier Journal Entries" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
|
@ -84,6 +85,7 @@
|
|||
<field name="amount" sum="Total Allocation"/>
|
||||
</tree>
|
||||
</field>
|
||||
<label for="line_cr_ids" attrs="{'invisible': [('type', '=', 'payment')]}"/>
|
||||
<field name="line_cr_ids" attrs="{'invisible': [('type', '=', 'payment')]}" context="{'journal_id':journal_id, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
|
||||
<tree string="Open Customer Journal Entries" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
|
@ -155,6 +157,7 @@
|
|||
</group>
|
||||
<notebook>
|
||||
<page string="Payment Information">
|
||||
<label for="line_dr_ids"/>
|
||||
<field name="line_dr_ids" context="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}">
|
||||
<tree string="Supplier Invoices and Outstanding transactions" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
|
@ -170,6 +173,7 @@
|
|||
<field name="amount" sum="Total Allocation" on_change="onchange_amount(amount, amount_unreconciled, context)"/>
|
||||
</tree>
|
||||
</field>
|
||||
<label for="line_cr_ids" attrs="{'invisible': [('pre_line','=',False)]}"/>
|
||||
<field name="line_cr_ids" attrs="{'invisible': [('pre_line','=',False)]}" context="{'journal_id':journal_id, 'partner_id':partner_id}">
|
||||
<tree string="Credits" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
|
@ -280,6 +284,111 @@
|
|||
<menuitem action="action_vendor_payment" icon="STOCK_JUSTIFY_FILL" sequence="12"
|
||||
id="menu_action_vendor_payment" parent="account.menu_finance_payables"/>
|
||||
|
||||
<record model="ir.ui.view" id="view_vendor_receipt_dialog_form">
|
||||
<field name="name">account.voucher.receipt.dialog.form</field>
|
||||
<field name="model">account.voucher</field>
|
||||
<field name="priority">30</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Payment" version="7.0">
|
||||
<group>
|
||||
<group>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="partner_id" required="1" on_change="onchange_partner_id(partner_id, journal_id, amount, currency_id, type, date, context)" string="Customer" context="{'search_default_customer': 1}"/>
|
||||
<label for="amount" string="Paid Amount"/>
|
||||
<div>
|
||||
<field name="amount" class="oe_inline"
|
||||
invisible="context.get('line_type', False)"
|
||||
on_change="onchange_amount(amount, payment_rate, partner_id, journal_id, currency_id, type, date, payment_rate_currency_id, company_id, context)"/>
|
||||
<field name="currency_id" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="journal_id"
|
||||
domain="[('type','in',['bank', 'cash'])]"
|
||||
invisible="context.get('line_type', False)"
|
||||
widget="selection"
|
||||
on_change="onchange_journal(journal_id, line_cr_ids, False, partner_id, date, amount, type, company_id, context)"
|
||||
string="Payment Method"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date" invisible="context.get('line_type', False)" on_change="onchange_date(date, currency_id, payment_rate_currency_id, amount, company_id, context)"/>
|
||||
<field name="reference" invisible="context.get('line_type', False)" string="Payment Ref" placeholder="e.g. 003/10"/>
|
||||
<field name="name" colspan="2" invisible="context.get('line_type', False)" placeholder="e.g. Invoice SAJ/0042"/>
|
||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||
|
||||
<field name="account_id"
|
||||
widget="selection"
|
||||
invisible="True"/>
|
||||
<field name="pre_line" invisible="1"/>
|
||||
<field name="type" invisible="True"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook invisible="1">
|
||||
<page string="Payment Information" groups="base.group_user">
|
||||
<label for="line_cr_ids"/>
|
||||
<field name="line_cr_ids" context="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
|
||||
<tree string="Invoices and outstanding transactions" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
on_change="onchange_move_line_id(move_line_id)"
|
||||
domain="[('account_id.type','in',('receivable','payable')), ('reconcile_id','=', False), ('partner_id','=',parent.partner_id)]"
|
||||
required="1"
|
||||
groups="account.group_account_user"/>
|
||||
<field name="account_id" groups="base.group_no_one" domain="[('type','=','receivable')]"/>
|
||||
<field name="date_original" readonly="1"/>
|
||||
<field name="date_due" readonly="1"/>
|
||||
<field name="amount_original" readonly="1"/>
|
||||
<field name="amount_unreconciled" readonly="1" groups="account.group_account_user"/>
|
||||
<field name="reconcile" on_change="onchange_reconcile(reconcile, amount, amount_unreconciled, context)" groups="account.group_account_user"/>
|
||||
<field name="amount" sum="Total Allocation" on_change="onchange_amount(amount, amount_unreconciled, context)" string="Allocation"/>
|
||||
</tree>
|
||||
</field>
|
||||
<label for="line_dr_ids" attrs="{'invisible': [('pre_line','=',False)]}"/>
|
||||
<field name="line_dr_ids" attrs="{'invisible': [('pre_line','=',False)]}" context="{'journal_id':journal_id, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
|
||||
<tree string="Credits" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
on_change="onchange_move_line_id(move_line_id)"
|
||||
domain="[('account_id.type','in',('receivable','payable')), ('reconcile_id','=', False), ('partner_id','=',parent.partner_id)]"
|
||||
required="1"/>
|
||||
<field name="account_id" groups="base.group_no_one" domain="[('type','=','receivable')]"/>
|
||||
<field name="date_original" readonly="1"/>
|
||||
<field name="date_due" readonly="1"/>
|
||||
<field name="amount_original" readonly="1"/>
|
||||
<field name="amount_unreconciled" readonly="1"/>
|
||||
<field name="reconcile" on_change="onchange_reconcile(reconcile, amount, amount_unreconciled, context)"/>
|
||||
<field name="amount" sum="Total Allocation" on_change="onchange_amount(amount, amount_unreconciled, context)" string="Allocation"/>
|
||||
</tree>
|
||||
</field>
|
||||
<group col="3">
|
||||
<group>
|
||||
<field name="narration" colspan="2" nolabel="1"/>
|
||||
</group>
|
||||
<group col="4" attrs="{'invisible':[('currency_id','=',False),('is_multi_currency','=',False)]}">
|
||||
<field name="is_multi_currency" invisible="1"/>
|
||||
<field name="payment_rate" required="1" on_change="onchange_rate(payment_rate, amount, currency_id, payment_rate_currency_id, company_id, context)" colspan="3"/>
|
||||
<field name="payment_rate_currency_id" colspan="1" nolabel="1" on_change="onchange_payment_rate_currency(currency_id, payment_rate, payment_rate_currency_id, date, amount, company_id, context)" groups="base.group_multi_currency"/>
|
||||
<field name="paid_amount_in_company_currency" colspan="4" invisible="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="writeoff_amount"/>
|
||||
<field name="payment_option" required="1"/>
|
||||
<field name="writeoff_acc_id"
|
||||
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"
|
||||
domain="[('type','=','other')]"/>
|
||||
<field name="comment"
|
||||
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
|
||||
<field name="analytic_id"
|
||||
groups="analytic.group_analytic_accounting"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
<footer>
|
||||
<button name="button_proforma_voucher" string="Pay" class="oe_highlight" type="object"/> or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="view_vendor_receipt_form">
|
||||
<field name="name">account.voucher.receipt.form</field>
|
||||
<field name="model">account.voucher</field>
|
||||
|
@ -293,7 +402,7 @@
|
|||
<field name="state" widget="statusbar" statusbar_visible="draft,posted" statusbar_colors='{"proforma":"blue"}'/>
|
||||
</header>
|
||||
<sheet>
|
||||
<h1><field name="number"/></h1>
|
||||
<h1 attrs="{'invisible': [('number','=',False)]}"><field name="number"/></h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="partner_id" domain="[('customer','=',True)]" required="1" invisible="context.get('line_type', False)" on_change="onchange_partner_id(partner_id, journal_id, amount, currency_id, type, date, context)" string="Customer" context="{'search_default_customer': 1}"/>
|
||||
|
@ -325,9 +434,9 @@
|
|||
<field name="type" invisible="True"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<notebook>
|
||||
<page string="Payment Information" groups="base.group_user">
|
||||
<label for="line_cr_ids"/>
|
||||
<field name="line_cr_ids" context="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
|
||||
<tree string="Invoices and outstanding transactions" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
|
@ -344,6 +453,7 @@
|
|||
<field name="amount" sum="Total Allocation" on_change="onchange_amount(amount, amount_unreconciled, context)" string="Allocation"/>
|
||||
</tree>
|
||||
</field>
|
||||
<label for="line_dr_ids" attrs="{'invisible': [('pre_line','=',False)]}"/>
|
||||
<field name="line_dr_ids" attrs="{'invisible': [('pre_line','=',False)]}" context="{'journal_id':journal_id, 'partner_id':partner_id}" on_change="onchange_line_ids(line_dr_ids, line_cr_ids, amount, currency_id, type, context)">
|
||||
<tree string="Credits" editable="bottom" colors="gray:amount==0">
|
||||
<field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}"
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<h1><label for="number" string="Sale Receipt"/> <field name="number" class="oe_inline" readonly="1"/></h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="type" invisible="True"/>
|
||||
<field name="partner_id" domain="[('customer','=',True)]" on_change="onchange_partner_id(partner_id, journal_id, amount, currency_id, type, date, context)" string="Customer" context="{'search_default_customer':1, 'show_address': 1}" options='{"always_reload": true}'/>
|
||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
|
@ -80,9 +81,9 @@
|
|||
<field name="date" on_change="onchange_date(date, currency_id, currency_id, amount, company_id, context)"/>
|
||||
<field name="name"/>
|
||||
<field name="paid" invisible="1"/>
|
||||
<field name="paid_amount_in_company_currency" invisible="1"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
</group>
|
||||
<field name="type" invisible="True"/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Sales Information">
|
||||
|
@ -235,6 +236,7 @@
|
|||
widget="selection"
|
||||
on_change="onchange_journal(journal_id, line_dr_ids, tax_id, partner_id, date, amount, type, company_id, context)"
|
||||
groups="account.group_account_user"/>
|
||||
<field name="paid_amount_in_company_currency" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
|
|
|
@ -38,11 +38,11 @@ that have no counterpart in the general financial accounts.
|
|||
'security/analytic_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'analytic_sequence.xml',
|
||||
'analytic_view.xml'
|
||||
'analytic_view.xml',
|
||||
'analytic_data.xml'
|
||||
],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate' : '00462253285027988541',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -125,6 +125,7 @@ class account_analytic_account(osv.osv):
|
|||
if account.company_id:
|
||||
if account.company_id.currency_id.id != value:
|
||||
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really usefull for consolidation purposes of several companies charts with different currencies, for example."))
|
||||
if value:
|
||||
return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, ))
|
||||
|
||||
def _currency(self, cr, uid, ids, field_name, arg, context=None):
|
||||
|
@ -163,7 +164,7 @@ class account_analytic_account(osv.osv):
|
|||
'date': fields.date('Date End', select=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts.
|
||||
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','To Renew'),('close','Closed')], 'Status', required=True,),
|
||||
'currency_id': fields.function(_currency, fnct_inv=_set_company_currency,
|
||||
'currency_id': fields.function(_currency, fnct_inv=_set_company_currency, #the currency_id field is readonly except if it's a view account and if there is no company
|
||||
store = {
|
||||
'res.company': (_get_analytic_account, ['currency_id'], 10),
|
||||
}, string='Currency', type='many2one', relation='res.currency'),
|
||||
|
@ -284,7 +285,8 @@ class account_analytic_account(osv.osv):
|
|||
|
||||
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=_("Contract for <em>%s</em> has been <b>created</b>.") % (obj.partner_id.name), context=context)
|
||||
self.message_post(cr, uid, [obj.id], body=_("Contract for <em>%s</em> has been <b>created</b>.") % (obj.partner_id.name),
|
||||
subtype="analytic.mt_account_status", context=context)
|
||||
|
||||
account_analytic_account()
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- mail: subtypes -->
|
||||
<record id="mt_account_status" model="mail.message.subtype">
|
||||
<field name="name">Status Change</field>
|
||||
<field name="res_model">account.analytic.account</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -24,6 +24,7 @@
|
|||
<field name="partner_id" on_change="on_change_partner_id(partner_id, name)" attrs="{'required':[('type','=','contract')]}"/>
|
||||
<field name="manager_id"/>
|
||||
<field name="code"/>
|
||||
<field name="currency_id" attrs="{'invisible': ['|',('type', '<>', 'view'), ('company_id', '<>', False)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="type"/>
|
||||
|
|
|
@ -45,6 +45,5 @@ compatible with older configurations.
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0082277138269',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,63 +1,86 @@
|
|||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * analytic_user_function
|
||||
# Dutch (Belgium) translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0dev\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 15:34:14+0000\n"
|
||||
"PO-Revision-Date: 2009-08-28 15:34:14+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
|
||||
"PO-Revision-Date: 2012-10-02 07:35+0000\n"
|
||||
"Last-Translator: Els Van Vossel (Agaplan) <Unknown>\n"
|
||||
"Language-Team: Dutch (Belgium) <nl_BE@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-03 05:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16061)\n"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: constraint:ir.ui.view:0
|
||||
msgid "Invalid XML for View Architecture!"
|
||||
msgstr ""
|
||||
#: field:analytic.user.funct.grid,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Product"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: model:ir.model,name:analytic_user_function.model_analytic_user_funct_grid
|
||||
msgid "Relation table between users and products on a analytic account"
|
||||
msgstr ""
|
||||
"Relatietabel tussen gebruikers en producten van een analytische rekening"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: field:analytic_user_funct_grid,product_id:0
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
#: constraint:hr.analytic.timesheet:0
|
||||
msgid "You cannot modify an entry in a Confirmed/Done timesheet !."
|
||||
msgstr "In een bevestigde/afgesloten uurrooster kunt u geen regels wijzigen."
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: field:analytic_user_funct_grid,account_id:0
|
||||
#: field:analytic.user.funct.grid,account_id:0
|
||||
#: model:ir.model,name:analytic_user_function.model_account_analytic_account
|
||||
msgid "Analytic Account"
|
||||
msgstr ""
|
||||
msgstr "Analytische rekening"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: view:account.analytic.account:0
|
||||
#: field:account.analytic.account,user_product_ids:0
|
||||
msgid "Users/Products Rel."
|
||||
msgstr ""
|
||||
msgstr "Rel. gebruikers/producten"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: field:analytic_user_funct_grid,user_id:0
|
||||
#: field:analytic.user.funct.grid,user_id:0
|
||||
msgid "User"
|
||||
msgstr "Gebruiker"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: code:addons/analytic_user_function/analytic_user_function.py:96
|
||||
#: code:addons/analytic_user_function/analytic_user_function.py:131
|
||||
#, python-format
|
||||
msgid "There is no expense account define for this product: \"%s\" (id:%d)"
|
||||
msgstr ""
|
||||
"Er is geen kostenrekening gedefinieerd voor dit product: \"%s\" (id:%d)"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: constraint:ir.model:0
|
||||
msgid "The Object name must start with x_ and not contain any special character !"
|
||||
msgstr "De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
|
||||
#: code:addons/analytic_user_function/analytic_user_function.py:95
|
||||
#: code:addons/analytic_user_function/analytic_user_function.py:130
|
||||
#, python-format
|
||||
msgid "Error !"
|
||||
msgstr "Fout"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: model:ir.module.module,shortdesc:analytic_user_function.module_meta_information
|
||||
msgid "Analytic User Function"
|
||||
msgstr ""
|
||||
#: constraint:account.analytic.account:0
|
||||
msgid "Error! You can not create recursive analytic accounts."
|
||||
msgstr "U kunt niet dezelfde analytische rekeningen maken."
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: view:analytic_user_funct_grid:0
|
||||
#: model:ir.model,name:analytic_user_function.model_hr_analytic_timesheet
|
||||
msgid "Timesheet Line"
|
||||
msgstr "Uurroosterlijn"
|
||||
|
||||
#. module: analytic_user_function
|
||||
#: view:analytic.user.funct.grid:0
|
||||
msgid "User's Product for this Analytic Account"
|
||||
msgstr ""
|
||||
msgstr "Product van gebruiker voor deze analytische rekening"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The Object name must start with x_ and not contain any special character !"
|
||||
#~ msgstr ""
|
||||
#~ "De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
|
||||
|
|
|
@ -48,7 +48,6 @@ anonymization process to recover your previous data.
|
|||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '00719010980872226045',
|
||||
'images': ['images/anonymization1.jpeg','images/anonymization2.jpeg','images/anonymization3.jpeg'],
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ membership products (schemes).
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0078696047261',
|
||||
'images': ['images/association1.jpeg'],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -42,7 +42,6 @@ and can check logs.
|
|||
'demo': ['audittrail_demo.xml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate': '0062572348749',
|
||||
'images': ['images/audittrail1.jpeg','images/audittrail2.jpeg','images/audittrail3.jpeg'],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -202,7 +202,7 @@ class audittrail_objects_proxy(object_proxy):
|
|||
res = value
|
||||
return res
|
||||
|
||||
def create_log_line(self, cr, uid, log_id, model, lines=[]):
|
||||
def create_log_line(self, cr, uid, log_id, model, lines=None):
|
||||
"""
|
||||
Creates lines for changed fields with its old and new values
|
||||
|
||||
|
@ -211,6 +211,8 @@ class audittrail_objects_proxy(object_proxy):
|
|||
@param model: Object which values are being changed
|
||||
@param lines: List of values for line is to be created
|
||||
"""
|
||||
if lines is None:
|
||||
lines = []
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
obj_pool = pool.get(model.model)
|
||||
model_pool = pool.get('ir.model')
|
||||
|
@ -349,7 +351,7 @@ class audittrail_objects_proxy(object_proxy):
|
|||
data[(model.id, resource_id)] = {'text':values_text, 'value': values}
|
||||
return data
|
||||
|
||||
def prepare_audittrail_log_line(self, cr, uid, pool, model, resource_id, method, old_values, new_values, field_list=[]):
|
||||
def prepare_audittrail_log_line(self, cr, uid, pool, model, resource_id, method, old_values, new_values, field_list=None):
|
||||
"""
|
||||
This function compares the old data (i.e before the method was executed) and the new data
|
||||
(after the method was executed) and returns a structure with all the needed information to
|
||||
|
@ -378,6 +380,8 @@ class audittrail_objects_proxy(object_proxy):
|
|||
The reason why the structure returned is build as above is because when modifying an existing
|
||||
record, we may have to log a change done in a x2many field of that object
|
||||
"""
|
||||
if field_list is None:
|
||||
field_list = []
|
||||
key = (model.id, resource_id)
|
||||
lines = {
|
||||
key: []
|
||||
|
@ -416,7 +420,7 @@ class audittrail_objects_proxy(object_proxy):
|
|||
lines[key].append(data)
|
||||
return lines
|
||||
|
||||
def process_data(self, cr, uid, pool, res_ids, model, method, old_values={}, new_values={}, field_list=[]):
|
||||
def process_data(self, cr, uid, pool, res_ids, model, method, old_values=None, new_values=None, field_list=None):
|
||||
"""
|
||||
This function processes and iterates recursively to log the difference between the old
|
||||
data (i.e before the method was executed) and the new data and creates audittrail log
|
||||
|
@ -435,6 +439,8 @@ class audittrail_objects_proxy(object_proxy):
|
|||
on specific fields only.
|
||||
:return: True
|
||||
"""
|
||||
if field_list is None:
|
||||
field_list = []
|
||||
# loop on all the given ids
|
||||
for res_id in res_ids:
|
||||
# compare old and new values and get audittrail log lines accordingly
|
||||
|
@ -442,11 +448,13 @@ class audittrail_objects_proxy(object_proxy):
|
|||
|
||||
# if at least one modification has been found
|
||||
for model_id, resource_id in lines:
|
||||
name = pool.get(model.model).name_get(cr, uid, [resource_id])[0][1]
|
||||
vals = {
|
||||
'method': method,
|
||||
'object_id': model_id,
|
||||
'user_id': uid,
|
||||
'res_id': resource_id,
|
||||
'name': name,
|
||||
}
|
||||
if (model_id, resource_id) not in old_values and method not in ('copy', 'read'):
|
||||
# the resource was not existing so we are forcing the method to 'create'
|
||||
|
@ -484,7 +492,7 @@ class audittrail_objects_proxy(object_proxy):
|
|||
if len(rule['user_id']) == 0 or uid in rule['user_id']:
|
||||
if rule.get('log_'+method,0):
|
||||
return True
|
||||
elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'):
|
||||
elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create', 'read_group', 'import_data'):
|
||||
if rule['log_action']:
|
||||
return True
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ authentication if installed at the same time.
|
|||
],
|
||||
'auto_install': False,
|
||||
'installable': True,
|
||||
'certificate' : '001141446349334700221',
|
||||
'external_dependencies' : {
|
||||
'python' : ['ldap'],
|
||||
}
|
||||
|
|
|
@ -180,8 +180,8 @@ class CompanyLDAP(osv.osv):
|
|||
"""
|
||||
|
||||
user_id = False
|
||||
login = tools.ustr(login)
|
||||
cr.execute("SELECT id, active FROM res_users WHERE login=%s", (login,))
|
||||
login = tools.ustr(login.lower())
|
||||
cr.execute("SELECT id, active FROM res_users WHERE lower(login)=%s", (login,))
|
||||
res = cr.fetchone()
|
||||
if res:
|
||||
if res[1]:
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<field name="ldap_server"/>
|
||||
<field name="ldap_server_port"/>
|
||||
<field name="ldap_binddn"/>
|
||||
<field name="ldap_password"/>
|
||||
<field name="ldap_password" password="True"/>
|
||||
<field name="ldap_base"/>
|
||||
<field name="ldap_filter"/>
|
||||
<field name="create_user"/>
|
||||
|
|
|
@ -34,11 +34,15 @@ Allow users to login through Google OAuth2.
|
|||
'depends': ['base', 'web', 'base_setup'],
|
||||
'data': [
|
||||
'auth_oauth_data.xml',
|
||||
'auth_oauth_data.yml',
|
||||
'auth_oauth_view.xml',
|
||||
'security/ir.model.access.csv'
|
||||
],
|
||||
'js': ['static/src/js/auth_oauth.js'],
|
||||
'css': ['static/lib/zocial/css/zocial.css'],
|
||||
'css': [
|
||||
'static/lib/zocial/css/zocial.css',
|
||||
'static/src/css/auth_oauth.css',
|
||||
],
|
||||
'qweb': ['static/src/xml/auth_oauth.xml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="provider_openerp" model="auth.oauth.provider">
|
||||
<field name="name">OpenERP Accounts</field>
|
||||
<field name="auth_endpoint">https://accounts.openerp.com/oauth2/auth</field>
|
||||
<field name="scope">userinfo</field>
|
||||
<field name="validation_endpoint">https://accounts.openerp.com/oauth2/tokeninfo</field>
|
||||
<field name="data_endpoint"></field>
|
||||
<field name="css_class">zocial openerp</field>
|
||||
<field name="body">Sign in with OpenERP account</field>
|
||||
</record>
|
||||
<record id="provider_facebook" model="auth.oauth.provider">
|
||||
<field name="name">Facebook Graph</field>
|
||||
<field name="auth_endpoint">https://www.facebook.com/dialog/oauth</field>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
-
|
||||
Use database uuid as client_id for OpenERP oauth provider
|
||||
-
|
||||
!python {model: ir.config_parameter}: |
|
||||
oauth = self.pool.get('auth.oauth.provider')
|
||||
oauth.write(cr, uid, [ref('provider_openerp')], {'client_id': self.get_param(cr, uid, 'database.uuid')})
|
|
@ -16,10 +16,13 @@ class OAuthController(openerpweb.Controller):
|
|||
|
||||
@openerpweb.jsonrequest
|
||||
def list_providers(self, req, dbname):
|
||||
try:
|
||||
registry = openerp.modules.registry.RegistryManager.get(dbname)
|
||||
with registry.cursor() as cr:
|
||||
providers = registry.get('auth.oauth.provider')
|
||||
l = providers.read(cr, SUPERUSER_ID, providers.search(cr, SUPERUSER_ID, [('enabled','=',True)]))
|
||||
except Exception:
|
||||
l = []
|
||||
return l
|
||||
|
||||
@openerpweb.httprequest
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import logging
|
||||
|
||||
import urllib
|
||||
import urlparse
|
||||
import urllib2
|
||||
import simplejson
|
||||
|
||||
|
@ -21,6 +22,9 @@ class res_users(osv.Model):
|
|||
|
||||
def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
|
||||
params = urllib.urlencode({ 'access_token': access_token })
|
||||
if urlparse.urlparse(endpoint)[4]:
|
||||
url = endpoint + '&' + params
|
||||
else:
|
||||
url = endpoint + '?' + params
|
||||
f = urllib2.urlopen(url)
|
||||
response = f.read()
|
||||
|
@ -38,11 +42,16 @@ class res_users(osv.Model):
|
|||
validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
|
||||
if validation.get("error"):
|
||||
raise openerp.exceptions.AccessDenied
|
||||
login = validation['email']
|
||||
if p.data_endpoint:
|
||||
data = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)
|
||||
validation.update(data)
|
||||
# required
|
||||
oauth_uid = validation['user_id']
|
||||
name = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)['name']
|
||||
|
||||
credentials = (cr.dbname, login, access_token)
|
||||
if not oauth_uid:
|
||||
raise openerp.exceptions.AccessDenied
|
||||
email = validation.get('email', 'provider_%d_user_%d' % (p.id, oauth_uid))
|
||||
# optional
|
||||
name = validation.get('name', email)
|
||||
res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)])
|
||||
if res:
|
||||
self.write(cr, uid, res[0], { 'oauth_access_token': access_token })
|
||||
|
@ -50,14 +59,15 @@ class res_users(osv.Model):
|
|||
# New user
|
||||
new_user = {
|
||||
'name': name,
|
||||
'login': login,
|
||||
'user_email': login,
|
||||
'oauth_provider_id': 1,
|
||||
'login': email,
|
||||
'user_email': email,
|
||||
'oauth_provider_id': p.id,
|
||||
'oauth_uid': oauth_uid,
|
||||
'oauth_access_token': access_token,
|
||||
'active': True,
|
||||
}
|
||||
self.auth_signup_create(cr, uid, new_user)
|
||||
credentials = (cr.dbname, email, access_token)
|
||||
return credentials
|
||||
|
||||
def check_credentials(self, cr, uid, password):
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
.openerp .oe_application .zocial {
|
||||
font: white;
|
||||
}
|
||||
|
||||
.openerp .zocial.openerp:before {
|
||||
content: "\E02E";
|
||||
font-style: italic;
|
||||
text-shadow: 0 1px 1px black;
|
||||
}
|
||||
|
||||
.openerp a.zocial.openerp {
|
||||
float: right;
|
||||
border: 1px solid #222222;
|
||||
color: white;
|
||||
margin: 0;
|
||||
background-color: #b92020;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#b92020), to(#600606));
|
||||
background-image: -webkit-linear-gradient(top, #b92020, #600606);
|
||||
background-image: -moz-linear-gradient(top, #b92020, #600606);
|
||||
background-image: -ms-linear-gradient(top, #b92020, #600606);
|
||||
background-image: -o-linear-gradient(top, #b92020, #600606);
|
||||
background-image: linear-gradient(to bottom, #b92020, #600606);
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
|
||||
text-shadow: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.openerp .oe_login .oe_oauth_provider_login_button {
|
||||
margin-top: 4px;
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
openerp.auth_oauth = function(instance) {
|
||||
var QWeb = instance.web.qweb;
|
||||
|
||||
instance.web.Login = instance.web.Login.extend({
|
||||
instance.web.Login.include({
|
||||
start: function(parent, params) {
|
||||
var self = this;
|
||||
var d = this._super.apply(this, arguments);
|
||||
this.$el.on('click', 'a.zocial', this.on_oauth_sign_in);
|
||||
this.oauth_providers = [];
|
||||
|
@ -11,7 +12,13 @@ openerp.auth_oauth = function(instance) {
|
|||
} else if(this.params.oauth_error === 2) {
|
||||
this.do_warn("Authentication error","");
|
||||
}
|
||||
return d.then(this.do_oauth_load);
|
||||
return d.then(this.do_oauth_load).fail(function() {
|
||||
self.do_oauth_load([]);
|
||||
});
|
||||
},
|
||||
on_db_loaded: function(result) {
|
||||
this._super.apply(this, arguments);
|
||||
this.$("form [name=db]").change(this.do_oauth_load);
|
||||
},
|
||||
do_oauth_load: function() {
|
||||
var db = this.$("form [name=db]").val();
|
||||
|
@ -21,6 +28,7 @@ openerp.auth_oauth = function(instance) {
|
|||
},
|
||||
on_oauth_loaded: function(result) {
|
||||
this.oauth_providers = result;
|
||||
this.$('.oe_oauth_provider_login_button').remove();
|
||||
var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this});
|
||||
this.$(".oe_login_pane form ul").after(buttons);
|
||||
},
|
||||
|
@ -33,7 +41,7 @@ openerp.auth_oauth = function(instance) {
|
|||
var state_object = {
|
||||
d: dbname,
|
||||
p: p.id
|
||||
}
|
||||
};
|
||||
var state = JSON.stringify(state_object);
|
||||
var params = {
|
||||
response_type: 'token',
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="auth_oauth.Login.button">
|
||||
<t t-foreach="widget.oauth_providers" t-as="p">
|
||||
<a href="#" t-att-class="p.css_class" t-att-data-index="p_index"><t t-esc="p.body"/></a>
|
||||
<br/>
|
||||
<a href="#" t-attf-class="oe_oauth_provider_login_button #{p.css_class}" t-att-data-index="p_index"><t t-esc="p.body"/></a>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
|
@ -44,7 +44,6 @@ trigger an automatic reminder email.
|
|||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'certificate' : '001017908446466333429',
|
||||
'images': ['images/base_action_rule1.jpeg','images/base_action_rule2.jpeg','images/base_action_rule3.jpeg'],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -21,6 +21,5 @@
|
|||
|
||||
import base_calendar
|
||||
import crm_meeting
|
||||
import wizard
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
'name': 'Calendar',
|
||||
'version': '1.0',
|
||||
'depends': ['base', 'base_status', 'mail', 'base_action_rule'],
|
||||
'summary': 'Personnal & Shared Agenda',
|
||||
'summary': 'Personal & Shared Calendar',
|
||||
'description': """
|
||||
This is a full-featured calendar system.
|
||||
========================================
|
||||
|
@ -32,7 +32,6 @@ It supports:
|
|||
------------
|
||||
- Calendar of events
|
||||
- Recurring events
|
||||
- Invitations to people
|
||||
|
||||
If you need to manage your meetings, you should install the CRM module.
|
||||
""",
|
||||
|
@ -43,7 +42,6 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'data': [
|
||||
'security/calendar_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'wizard/base_calendar_invite_attendee_view.xml',
|
||||
'base_calendar_view.xml',
|
||||
'crm_meeting_view.xml',
|
||||
'base_calendar_data.xml',
|
||||
|
@ -53,7 +51,6 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'certificate': '00694071962960352821',
|
||||
'images': ['images/base_calendar1.jpeg','images/base_calendar2.jpeg','images/base_calendar3.jpeg','images/base_calendar4.jpeg',],
|
||||
}
|
||||
|
||||
|
|
|
@ -971,8 +971,8 @@ class calendar_event(osv.osv):
|
|||
event = datas['id']
|
||||
if datas.get('interval', 0) < 0:
|
||||
raise osv.except_osv(_('Warning!'), _('Interval cannot be negative.'))
|
||||
if datas.get('count', 0) < 0:
|
||||
raise osv.except_osv(_('Warning!'), _('Count cannot be negative.'))
|
||||
if datas.get('count', 0) <= 0:
|
||||
raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.'))
|
||||
if datas['recurrency']:
|
||||
result[event] = self.compute_rule_string(datas)
|
||||
else:
|
||||
|
@ -1058,8 +1058,40 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
'active': fields.boolean('Active', help="If the active field is set to \
|
||||
true, it will allow you to hide the event alarm information without removing it."),
|
||||
'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
|
||||
'partner_ids': fields.many2many('res.partner', string='Attendees', states={'done': [('readonly', True)]}),
|
||||
}
|
||||
|
||||
def create_attendees(self, cr, uid, ids, context):
|
||||
att_obj = self.pool.get('calendar.attendee')
|
||||
user_obj = self.pool.get('res.users')
|
||||
current_user = user_obj.browse(cr, uid, uid, context=context)
|
||||
for event in self.browse(cr, uid, ids, context):
|
||||
attendees = {}
|
||||
for att in event.attendee_ids:
|
||||
attendees[att.partner_id.id] = True
|
||||
new_attendees = []
|
||||
mail_to = []
|
||||
for partner in event.partner_ids:
|
||||
if partner.id in attendees:
|
||||
continue
|
||||
att_id = self.pool.get('calendar.attendee').create(cr, uid, {
|
||||
'partner_id': partner.id,
|
||||
'user_id': partner.user_ids and partner.user_ids[0].id or False,
|
||||
'ref': self._name+','+str(event.id),
|
||||
'email': partner.email
|
||||
}, context=context)
|
||||
if partner.email:
|
||||
mail_to.append(partner.email)
|
||||
self.write(cr, uid, [event.id], {
|
||||
'attendee_ids': [(4, att_id)]
|
||||
}, context=context)
|
||||
new_attendees.append(att_id)
|
||||
|
||||
if mail_to and current_user.email:
|
||||
att_obj._send_mail(cr, uid, new_attendees, mail_to,
|
||||
email_from = current_user.email)
|
||||
return True
|
||||
|
||||
def default_organizer(self, cr, uid, context=None):
|
||||
user_pool = self.pool.get('res.users')
|
||||
user = user_pool.browse(cr, uid, uid, context=context)
|
||||
|
@ -1082,6 +1114,16 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
'organizer': default_organizer,
|
||||
}
|
||||
|
||||
def _check_closing_date(self, cr, uid, ids, context=None):
|
||||
for event in self.browse(cr, uid, ids, context=context):
|
||||
if event.date_deadline < event.date:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_closing_date, 'Error ! End date cannot be set before start date.', ['date_deadline']),
|
||||
]
|
||||
|
||||
def get_recurrent_ids(self, cr, uid, select, domain, limit=100, context=None):
|
||||
"""Gives virtual event ids for recurring events based on value of Recurrence Rule
|
||||
This method gives ids of dates that comes between start date and end date of calendar views
|
||||
|
@ -1366,6 +1408,8 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
vals['vtimezone'] = vals['vtimezone'][40:]
|
||||
|
||||
res = super(calendar_event, self).write(cr, uid, ids, vals, context=context)
|
||||
if vals.get('partner_ids', False):
|
||||
self.create_attendees(cr, uid, ids, context)
|
||||
|
||||
if ('alarm_id' in vals or 'base_calendar_alarm_id' in vals)\
|
||||
or ('date' in vals or 'duration' in vals or 'date_deadline' in vals):
|
||||
|
@ -1489,17 +1533,10 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
|
||||
vals['vtimezone'] = vals['vtimezone'][40:]
|
||||
|
||||
#updated_vals = self.onchange_dates(cr, uid, [],
|
||||
# vals.get('date', False),
|
||||
# vals.get('duration', False),
|
||||
# vals.get('date_deadline', False),
|
||||
# vals.get('allday', False),
|
||||
# context=context)
|
||||
#vals.update(updated_vals.get('value', {}))
|
||||
|
||||
res = super(calendar_event, self).create(cr, uid, vals, context)
|
||||
alarm_obj = self.pool.get('res.alarm')
|
||||
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
|
||||
self.create_attendees(cr, uid, [res], context)
|
||||
return res
|
||||
|
||||
def do_tentative(self, cr, uid, ids, context=None, *args):
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<header>
|
||||
<button name="do_tentative" states="needs-action,declined,accepted" string="Uncertain" type="object" class="oe_highlight"/>
|
||||
<button name="do_accept" string="Accept" states="needs-action,tentative,declined" type="object" class="oe_highlight"/>
|
||||
<button name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d" string="Delegate" type="action" states="needs-action,tentative,declined,accepted" context="{'model' : 'calendar.attendee', 'attendee_field' : 'child_ids'}"/>
|
||||
<button name="do_decline" string="Decline" states="needs-action,tentative,accepted" type="object" class="oe_highlight"/>
|
||||
<field name="state" widget="statusbar"
|
||||
statusbar_visible="tentative,needs-action,accepted" statusbar_colors='{"proforma":"blue"}'/>
|
||||
|
@ -226,10 +225,6 @@
|
|||
<field name="description"/>
|
||||
</page>
|
||||
<page string="Invitation Detail">
|
||||
<button string="Invite People"
|
||||
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
|
||||
icon="terp-partner" type="action"
|
||||
context="{'model' : 'calendar.event', 'attendee_field':'attendee_ids'}" colspan="2"/>
|
||||
<field name="attendee_ids" colspan="4"
|
||||
nolabel="1" widget="one2many" mode="tree">
|
||||
<tree string="Invitation details" editable="top">
|
||||
|
@ -248,12 +243,6 @@
|
|||
<button name="do_decline" string="Decline"
|
||||
states="needs-action,tentative,accepted"
|
||||
type="object" icon="gtk-cancel"/>
|
||||
<button
|
||||
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
|
||||
string="Delegate" type="action"
|
||||
icon="gtk-sort-descending"
|
||||
states="needs-action,tentative,declined,accepted"
|
||||
context="{'model' : 'calendar.attendee', 'attendee_field' : 'child_ids'}"/>
|
||||
</tree>
|
||||
<form string="Invitation details" version="7.0">
|
||||
<notebook colspan="4">
|
||||
|
@ -281,13 +270,6 @@
|
|||
states="needs-action,tentative,accepted"
|
||||
type="object"
|
||||
icon="gtk-cancel"/>
|
||||
<button
|
||||
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
|
||||
string="Delegate"
|
||||
type="action"
|
||||
icon="gtk-sort-descending"
|
||||
states="needs-action,tentative,declined,accepted"
|
||||
context="{'model' : 'calendar.attendee', 'attendee_field' : 'child_ids'}"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
|
|
|
@ -71,6 +71,34 @@ class crm_meeting(base_state, osv.Model):
|
|||
default['attendee_ids'] = False
|
||||
return super(crm_meeting, self).copy(cr, uid, id, default, context)
|
||||
|
||||
def onchange_partner_ids(self, cr, uid, ids, value, context=None):
|
||||
""" The basic purpose of this method is to check that destination partners
|
||||
effectively have email addresses. Otherwise a warning is thrown.
|
||||
:param value: value format: [[6, 0, [3, 4]]]
|
||||
"""
|
||||
res = {'value': {}}
|
||||
if not value or not value[0] or not value[0][0] == 6:
|
||||
return
|
||||
res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
|
||||
return res
|
||||
|
||||
def check_partners_email(self, cr, uid, partner_ids, context=None):
|
||||
""" Verify that selected partner_ids have an email_address defined.
|
||||
Otherwise throw a warning. """
|
||||
partner_wo_email_lst = []
|
||||
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
|
||||
if not partner.email:
|
||||
partner_wo_email_lst.append(partner)
|
||||
if not partner_wo_email_lst:
|
||||
return {}
|
||||
warning_msg = _('The following contacts have no email address :')
|
||||
for partner in partner_wo_email_lst:
|
||||
warning_msg += '\n- %s' % (partner.name)
|
||||
return {'warning': {
|
||||
'title': _('Email addresses not found'),
|
||||
'message': warning_msg,
|
||||
}
|
||||
}
|
||||
# ----------------------------------------
|
||||
# OpenChatter
|
||||
# ----------------------------------------
|
||||
|
@ -80,7 +108,7 @@ class crm_meeting(base_state, osv.Model):
|
|||
return [('date','<=',time.strftime('%Y-%M-%D 23:59:59')), ('date_deadline','>=', time.strftime('%Y-%M-%D 00:00:00')), ('user_id','=',uid)]
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return 'Meeting'
|
||||
return _('Meeting')
|
||||
|
||||
def case_open_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_post(cr, uid, ids, body=_("Meeting <b>confirmed</b>."), context=context)
|
||||
|
|
|
@ -80,7 +80,9 @@
|
|||
</h1>
|
||||
<label for="partner_ids" class="oe_edit_only"/>
|
||||
<h2>
|
||||
<field name="partner_ids" widget="many2many_tags"/>
|
||||
<field name="partner_ids" widget="many2many_tags"
|
||||
context="{'force_email':True}"
|
||||
on_change="onchange_partner_ids(partner_ids)"/>
|
||||
</h2>
|
||||
</div>
|
||||
<notebook>
|
||||
|
@ -88,11 +90,12 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="date" string="Starting at"/>
|
||||
<label for="duration" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<div attrs="{'invisible': [('allday','=',True)]}">
|
||||
<label for="duration"/>
|
||||
<div>
|
||||
<field name="duration" widget="float_time"
|
||||
on_change="onchange_dates(date,duration,False,allday)"
|
||||
class="oe_inline"/> hours
|
||||
class="oe_inline" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
<label string="hours" attrs="{'invisible': [('allday','=',True)]}"/>
|
||||
(<field name="allday" on_change="onchange_dates(date,False,False,allday)" class="oe_inline"/>
|
||||
<label for="allday" string="All Day?"/>)
|
||||
</div>
|
||||
|
@ -165,34 +168,28 @@
|
|||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Invitation Detail">
|
||||
<button string="Invite People"
|
||||
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
|
||||
type="action"
|
||||
attrs="{'readonly': [('state', '=', 'done')]}"
|
||||
context="{'model' : 'crm.meeting', 'attendee_field':'attendee_ids'}" colspan="2"/>
|
||||
<!--
|
||||
Temporarily removing invitation feature as the implementation
|
||||
was not clean. Invitation should be trigerred automatically
|
||||
based on partner_ids.
|
||||
-->
|
||||
<page string="Invitations">
|
||||
<field name="attendee_ids" widget="one2many" mode="tree">
|
||||
<tree string="Invitation details" editable="top">
|
||||
<field name="sent_by_uid" string="From"/>
|
||||
<field name="user_id" string="To"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="email" string="Mail To"/>
|
||||
<field name="role" />
|
||||
<field name="state" />
|
||||
<button name="do_tentative"
|
||||
states="needs-action,declined,accepted"
|
||||
string="Uncertain" type="object"
|
||||
icon="terp-crm"
|
||||
/>
|
||||
<button name="do_accept" string="Accept"
|
||||
states="needs-action,tentative,declined"
|
||||
type="object" />
|
||||
type="object" icon="gtk-apply"/>
|
||||
<button name="do_decline" string="Decline"
|
||||
states="needs-action,tentative,accepted"
|
||||
type="object" />
|
||||
<button
|
||||
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
|
||||
string="Delegate" type="action"
|
||||
states="needs-action,tentative,declined,accepted"
|
||||
context="{'model' : 'calendar.attendee', 'attendee_field' : 'child_ids'}" />
|
||||
type="object" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
<form string="Invitation details" version="7.0">
|
||||
<header>
|
||||
|
@ -205,10 +202,6 @@
|
|||
<button name="do_decline" type="object"
|
||||
states="needs-action,tentative,accepted"
|
||||
string="Decline" />
|
||||
<button name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d" type="action"
|
||||
states="needs-action,tentative,declined,accepted"
|
||||
string="Delegate"
|
||||
context="{'model' : 'calendar.attendee', 'attendee_field' : 'child_ids'}" />
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,open,done"/>
|
||||
</header>
|
||||
<group>
|
||||
|
@ -219,6 +212,7 @@
|
|||
<field name="role" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="partner_id"/>
|
||||
<field name="user_id"/>
|
||||
</group>
|
||||
</group>
|
||||
|
@ -307,7 +301,7 @@
|
|||
<p class="oe_view_nocontent_create">
|
||||
Click to schedule a new meeting.
|
||||
</p><p>
|
||||
The agenda is shared between employees and fully integrated with
|
||||
The calendar is shared between employees and fully integrated with
|
||||
other applications such as the employee holidays or the business
|
||||
opportunities.
|
||||
</p>
|
||||
|
@ -339,10 +333,10 @@
|
|||
</record>
|
||||
|
||||
<menuitem id="menu_crm_meeting" parent="base.menu_sales" sequence="8"
|
||||
name="Agenda" action="action_crm_meeting"/>
|
||||
name="Calendar" action="action_crm_meeting"/>
|
||||
|
||||
<menuitem name="Agenda"
|
||||
id="mail_menu_agenda" parent="mail.mail_my_stuff"
|
||||
<menuitem name="Calendar"
|
||||
id="mail_menu_calendar" parent="mail.mail_my_stuff"
|
||||
sequence="10" action="action_crm_meeting"/>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -54,24 +54,3 @@
|
|||
-
|
||||
!python {model: calendar.event}: |
|
||||
self.write(cr, uid, [ref("calendar_event_alldaytestevent0")], {'alarm_id': ref("res_alarm_daybeforeeventstarts0")})
|
||||
-
|
||||
In order to assign attendee I will invite Demo user
|
||||
-
|
||||
!record {model: base_calendar.invite.attendee, id: base_calendar_invite_attendee_0}:
|
||||
type: internal
|
||||
send_mail: False
|
||||
partner_id: base.res_partner_9 # Put bcz of problem in read
|
||||
user_ids:
|
||||
- base.user_demo
|
||||
-
|
||||
Then I click on Invite Button
|
||||
-
|
||||
!python {model: base_calendar.invite.attendee}: |
|
||||
self.do_invite(cr, uid, [ref("base_calendar_invite_attendee_0")], {'active_id': ref("calendar_event_alldaytestevent0"), 'model' : 'calendar.event', 'attendee_field':'attendee_ids'})
|
||||
-
|
||||
Now I will Accept this invitation
|
||||
-
|
||||
!python {model: calendar.attendee}: |
|
||||
ids = self.search(cr, uid, [('ref', '=', 'calendar.event' + ',' + str(ref("calendar_event_alldaytestevent0")))])
|
||||
if ids:
|
||||
self.do_accept(cr, uid, ids, context=context)
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import base_calendar_invite_attendee
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from .. import base_calendar
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
import tools
|
||||
|
||||
|
||||
class base_calendar_invite_attendee(osv.osv_memory):
|
||||
"""
|
||||
Invite attendee.
|
||||
"""
|
||||
|
||||
_name = "base_calendar.invite.attendee"
|
||||
_description = "Invite Attendees"
|
||||
|
||||
_columns = {
|
||||
'type': fields.selection([('internal', 'Internal User'), \
|
||||
('external', 'External Email'), \
|
||||
('partner', 'Partner Contacts')], 'Type', required=True, help="Select whom you want to Invite"),
|
||||
'user_ids': fields.many2many('res.users', 'invite_user_rel',
|
||||
'invite_id', 'user_id', 'Users'),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'email': fields.char('Email', size=124, help="Provide external email address who will receive this invitation."),
|
||||
'contact_ids': fields.many2many('res.partner', 'invite_contact_rel',
|
||||
'invite_id', 'contact_id', 'Contacts'),
|
||||
'send_mail': fields.boolean('Send mail?', help='Check this if you want to \
|
||||
send an Email to Invited Person')
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'type': 'internal',
|
||||
'send_mail': True
|
||||
}
|
||||
|
||||
def do_invite(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Invites attendee for meeting..
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of base calendar invite attendee’s IDs.
|
||||
@param context: A standard dictionary for contextual values
|
||||
@return: Dictionary of {}.
|
||||
"""
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
model = False
|
||||
context_id = context and context.get('active_id', False) or False
|
||||
if not context or not context.get('model'):
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
else:
|
||||
model = context.get('model')
|
||||
|
||||
model_field = context.get('attendee_field', False)
|
||||
obj = self.pool.get(model)
|
||||
res_obj = obj.browse(cr, uid, context_id, context=context)
|
||||
att_obj = self.pool.get('calendar.attendee')
|
||||
user_obj = self.pool.get('res.users')
|
||||
current_user = user_obj.browse(cr, uid, uid, context=context)
|
||||
|
||||
for datas in self.read(cr, uid, ids, context=context):
|
||||
type = datas.get('type')
|
||||
vals = []
|
||||
mail_to = []
|
||||
attendees = []
|
||||
ref = {}
|
||||
|
||||
if not model == 'calendar.attendee':
|
||||
if context_id:
|
||||
ref = {'ref': '%s,%s' % (model, base_calendar.base_calendar_id2real_id(context_id))}
|
||||
else:
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
if type == 'internal':
|
||||
|
||||
if not datas.get('user_ids'):
|
||||
raise osv.except_osv(_('Error!'), ("Please select any user."))
|
||||
for user_id in datas.get('user_ids'):
|
||||
user = user_obj.browse(cr, uid, user_id)
|
||||
res = {
|
||||
'user_id': user_id,
|
||||
'email': user.email
|
||||
}
|
||||
res.update(ref)
|
||||
vals.append(res)
|
||||
if user.email:
|
||||
mail_to.append(user.email)
|
||||
|
||||
elif type == 'external' and datas.get('email'):
|
||||
res = {'email': datas['email']}
|
||||
res.update(ref)
|
||||
vals.append(res)
|
||||
mail_to.append(datas['email'])
|
||||
|
||||
elif type == 'partner':
|
||||
add_obj = self.pool.get('res.partner')
|
||||
for contact in add_obj.browse(cr, uid, datas['contact_ids']):
|
||||
res = {
|
||||
'partner_id': contact.id,
|
||||
'email': contact.email
|
||||
}
|
||||
res.update(ref)
|
||||
vals.append(res)
|
||||
if contact.email:
|
||||
mail_to.append(contact.email)
|
||||
|
||||
for att_val in vals:
|
||||
if model == 'calendar.attendee':
|
||||
att = att_obj.browse(cr, uid, context_id)
|
||||
att_val.update({
|
||||
'parent_ids': [(4, att.id)],
|
||||
'ref': att.ref and (att.ref._name + ',' +str(att.ref.id)) or False
|
||||
})
|
||||
|
||||
attendees.append(att_obj.create(cr, uid, att_val))
|
||||
if model_field:
|
||||
for attendee in attendees:
|
||||
obj.write(cr, uid, res_obj.id, {model_field: [(4, attendee)]})
|
||||
|
||||
if datas.get('send_mail'):
|
||||
if not mail_to:
|
||||
name = map(lambda x: x[1], filter(lambda x: type==x[0], \
|
||||
self._columns['type'].selection))
|
||||
raise osv.except_osv(_('Error!'), _("%s must have an email address to send mail.") %(name[0]))
|
||||
att_obj._send_mail(cr, uid, attendees, mail_to, \
|
||||
email_from = current_user.email or tools.config.get('email_from', False))
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, partner_id, *args, **argv):
|
||||
"""
|
||||
Make entry on contact_ids on change of partner_id field.
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of base calendar invite attendee’s IDs.
|
||||
@param partner_id: id of Partner
|
||||
@return: dictionary of value.
|
||||
"""
|
||||
|
||||
if not partner_id:
|
||||
return {'value': {'contact_ids': []}}
|
||||
cr.execute('SELECT id FROM res_partner \
|
||||
WHERE id=%s or parent_id =%s' , (partner_id,partner_id,))
|
||||
contacts = map(lambda x: x[0], cr.fetchall())
|
||||
return {'value': {'contact_ids': contacts}}
|
||||
|
||||
base_calendar_invite_attendee()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -1,55 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Attendee invite wizard-->
|
||||
|
||||
<record id="view_calendar_invite_attendee_wizard"
|
||||
model="ir.ui.view">
|
||||
<field name="name">Invite Attendees</field>
|
||||
<field name="model">base_calendar.invite.attendee</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Invite People" version="7.0">
|
||||
<separator string="Invite People" colspan="4"/>
|
||||
<field name="type"/>
|
||||
<field name="send_mail"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Data">
|
||||
<group col="2" colspan="6" attrs="{'invisible': [('type', '!=', 'external')]}">
|
||||
<field name="email" colspan="4" attrs="{'required': [('type', '=', 'external')]}"/>
|
||||
</group>
|
||||
<group col="2" colspan="6" attrs="{'invisible': [('type', '!=', 'internal')]}">
|
||||
<separator string="Users" colspan="4"/>
|
||||
<field name="user_ids" colspan="4" nolabel="1" height="180"/>
|
||||
<newline/>
|
||||
</group>
|
||||
<group col="2" colspan="6" attrs="{'invisible': [('type', '!=', 'partner')]}">
|
||||
<field name="partner_id" colspan="2" on_change="onchange_partner_id(partner_id)" attrs="{'required': [('type', '=', 'partner')]}"/>
|
||||
<newline/>
|
||||
<separator string="Partner Contacts" colspan="6"/>
|
||||
<field name="contact_ids" colspan="4" nolabel="1" domain="[('id', 'child_of', [partner_id])]" attrs="{'readonly': [('type', '!=', 'partner')]}"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
<footer>
|
||||
<button name="do_invite" string="Invite" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Attendee invite action-->
|
||||
|
||||
<record id="action_view_calendar_invite_attendee_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Invite Attendees</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">base_calendar.invite.attendee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -58,7 +58,6 @@ will disable LDAP authentication completely if installed at the same time.
|
|||
'data': [],
|
||||
'auto_install': False,
|
||||
'installable': True,
|
||||
'certificate': '00721290471310299725',
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -47,7 +47,9 @@ import logging
|
|||
magic_md5 = '$1$'
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
def gen_salt( length=8, symbols=ascii_letters + digits ):
|
||||
def gen_salt( length=8, symbols=None):
|
||||
if symbols is None:
|
||||
symbols = ascii_letters + digits
|
||||
seed()
|
||||
return ''.join( sample( symbols, length ) )
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue