[MERGE] forward port of branch saas-1 up to revid 8745 chs@openerp.com-20130613181503-82234mo34wxb0oap
bzr revid: chs@openerp.com-20130614091924-z5ta02kwhmwcrgox
This commit is contained in:
commit
aa133b4d29
|
@ -65,12 +65,11 @@ class bank(osv.osv):
|
||||||
# Find the code and parent of the bank account to create
|
# Find the code and parent of the bank account to create
|
||||||
dig = 6
|
dig = 6
|
||||||
current_num = 1
|
current_num = 1
|
||||||
ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id)], context=context)
|
ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id), ('parent_id', '!=', False)], context=context)
|
||||||
# No liquidity account exists, no template available
|
# No liquidity account exists, no template available
|
||||||
if not ids: continue
|
if not ids: continue
|
||||||
|
|
||||||
ref_acc_bank_temp = obj_acc.browse(cr, uid, ids[0], context=context)
|
ref_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context).parent_id
|
||||||
ref_acc_bank = ref_acc_bank_temp.parent_id
|
|
||||||
while True:
|
while True:
|
||||||
new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num)
|
new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num)
|
||||||
ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', bank.company_id.id)])
|
ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', bank.company_id.id)])
|
||||||
|
@ -82,7 +81,7 @@ class bank(osv.osv):
|
||||||
'name': name,
|
'name': name,
|
||||||
'code': new_code,
|
'code': new_code,
|
||||||
'type': 'liquidity',
|
'type': 'liquidity',
|
||||||
'user_type': ref_acc_bank_temp.user_type.id,
|
'user_type': ref_acc_bank.user_type.id,
|
||||||
'reconcile': False,
|
'reconcile': False,
|
||||||
'parent_id': ref_acc_bank.id,
|
'parent_id': ref_acc_bank.id,
|
||||||
'company_id': bank.company_id.id,
|
'company_id': bank.company_id.id,
|
||||||
|
|
|
@ -51,9 +51,12 @@ class account_invoice(osv.osv):
|
||||||
company_id = context.get('company_id', user.company_id.id)
|
company_id = context.get('company_id', user.company_id.id)
|
||||||
type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale_refund', 'in_refund': 'purchase_refund'}
|
type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale_refund', 'in_refund': 'purchase_refund'}
|
||||||
journal_obj = self.pool.get('account.journal')
|
journal_obj = self.pool.get('account.journal')
|
||||||
res = journal_obj.search(cr, uid, [('type', '=', type2journal.get(type_inv, 'sale')),
|
domain = [('company_id', '=', company_id)]
|
||||||
('company_id', '=', company_id)],
|
if isinstance(type_inv, list):
|
||||||
limit=1)
|
domain.append(('type', 'in', [type2journal.get(type) for type in type_inv if type2journal.get(type)]))
|
||||||
|
else:
|
||||||
|
domain.append(('type', '=', type2journal.get(type_inv, 'sale')))
|
||||||
|
res = journal_obj.search(cr, uid, domain, limit=1)
|
||||||
return res and res[0] or False
|
return res and res[0] or False
|
||||||
|
|
||||||
def _get_currency(self, cr, uid, context=None):
|
def _get_currency(self, cr, uid, context=None):
|
||||||
|
@ -578,6 +581,10 @@ class account_invoice(osv.osv):
|
||||||
return {'value': {}}
|
return {'value': {}}
|
||||||
|
|
||||||
def onchange_company_id(self, cr, uid, ids, company_id, part_id, type, invoice_line, currency_id, context=None):
|
def onchange_company_id(self, cr, uid, ids, company_id, part_id, type, invoice_line, currency_id, context=None):
|
||||||
|
#TODO: add the missing context parameter when forward-porting in trunk so we can remove
|
||||||
|
# this hack!
|
||||||
|
context = self.pool['res.users'].context_get(cr, uid)
|
||||||
|
|
||||||
val = {}
|
val = {}
|
||||||
dom = {}
|
dom = {}
|
||||||
obj_journal = self.pool.get('account.journal')
|
obj_journal = self.pool.get('account.journal')
|
||||||
|
@ -634,14 +641,13 @@ class account_invoice(osv.osv):
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
if company_id and type:
|
if company_id and type:
|
||||||
if type in ('out_invoice'):
|
journal_mapping = {
|
||||||
journal_type = 'sale'
|
'out_invoice': 'sale',
|
||||||
elif type in ('out_refund'):
|
'out_refund': 'sale_refund',
|
||||||
journal_type = 'sale_refund'
|
'in_refund': 'purchase_refund',
|
||||||
elif type in ('in_refund'):
|
'in_invoice': 'purchase',
|
||||||
journal_type = 'purchase_refund'
|
}
|
||||||
else:
|
journal_type = journal_mapping[type]
|
||||||
journal_type = 'purchase'
|
|
||||||
journal_ids = obj_journal.search(cr, uid, [('company_id','=',company_id), ('type', '=', journal_type)])
|
journal_ids = obj_journal.search(cr, uid, [('company_id','=',company_id), ('type', '=', journal_type)])
|
||||||
if journal_ids:
|
if journal_ids:
|
||||||
val['journal_id'] = journal_ids[0]
|
val['journal_id'] = journal_ids[0]
|
||||||
|
@ -651,7 +657,12 @@ class account_invoice(osv.osv):
|
||||||
if r[1] == 'journal_id' and r[2] in journal_ids:
|
if r[1] == 'journal_id' and r[2] in journal_ids:
|
||||||
val['journal_id'] = r[2]
|
val['journal_id'] = r[2]
|
||||||
if not val.get('journal_id', False):
|
if not val.get('journal_id', False):
|
||||||
raise osv.except_osv(_('Configuration Error!'), (_('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % (journal_type)))
|
journal_type_map = dict(obj_journal._columns['type'].selection)
|
||||||
|
journal_type_label = self.pool['ir.translation']._get_source(cr, uid, None, ('code','selection'),
|
||||||
|
context.get('lang'),
|
||||||
|
journal_type_map.get(journal_type))
|
||||||
|
raise osv.except_osv(_('Configuration Error!'),
|
||||||
|
_('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % ('"%s"' % journal_type_label))
|
||||||
dom = {'journal_id': [('id', 'in', journal_ids)]}
|
dom = {'journal_id': [('id', 'in', journal_ids)]}
|
||||||
else:
|
else:
|
||||||
journal_ids = obj_journal.search(cr, uid, [])
|
journal_ids = obj_journal.search(cr, uid, [])
|
||||||
|
@ -968,7 +979,7 @@ class account_invoice(osv.osv):
|
||||||
total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml, context=ctx)
|
total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml, context=ctx)
|
||||||
acc_id = inv.account_id.id
|
acc_id = inv.account_id.id
|
||||||
|
|
||||||
name = inv['name'] or '/'
|
name = inv['name'] or inv['supplier_invoice_number'] or '/'
|
||||||
totlines = False
|
totlines = False
|
||||||
if inv.payment_term:
|
if inv.payment_term:
|
||||||
totlines = payment_term_obj.compute(cr,
|
totlines = payment_term_obj.compute(cr,
|
||||||
|
@ -1167,12 +1178,12 @@ class account_invoice(osv.osv):
|
||||||
if not ids:
|
if not ids:
|
||||||
return []
|
return []
|
||||||
types = {
|
types = {
|
||||||
'out_invoice': 'Invoice ',
|
'out_invoice': _('Invoice'),
|
||||||
'in_invoice': 'Sup. Invoice ',
|
'in_invoice': _('Supplier Invoice'),
|
||||||
'out_refund': 'Refund ',
|
'out_refund': _('Refund'),
|
||||||
'in_refund': 'Supplier Refund ',
|
'in_refund': _('Supplier Refund'),
|
||||||
}
|
}
|
||||||
return [(r['id'], (r['number']) or types[r['type']] + (r['name'] or '')) for r in self.read(cr, uid, ids, ['type', 'number', 'name'], context, load='_classic_write')]
|
return [(r['id'], '%s %s' % (r['number'] or types[r['type']], r['name'] or '')) for r in self.read(cr, uid, ids, ['type', 'number', 'name'], context, load='_classic_write')]
|
||||||
|
|
||||||
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
|
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
|
||||||
if not args:
|
if not args:
|
||||||
|
|
|
@ -1066,12 +1066,12 @@ class account_move_line(osv.osv):
|
||||||
|
|
||||||
for line in self.browse(cr, uid, ids, context=context):
|
for line in self.browse(cr, uid, ids, context=context):
|
||||||
ctx = context.copy()
|
ctx = context.copy()
|
||||||
if ('journal_id' not in ctx):
|
if not ctx.get('journal_id'):
|
||||||
if line.move_id:
|
if line.move_id:
|
||||||
ctx['journal_id'] = line.move_id.journal_id.id
|
ctx['journal_id'] = line.move_id.journal_id.id
|
||||||
else:
|
else:
|
||||||
ctx['journal_id'] = line.journal_id.id
|
ctx['journal_id'] = line.journal_id.id
|
||||||
if ('period_id' not in ctx):
|
if not ctx.get('period_id'):
|
||||||
if line.move_id:
|
if line.move_id:
|
||||||
ctx['period_id'] = line.move_id.period_id.id
|
ctx['period_id'] = line.move_id.period_id.id
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -585,7 +585,10 @@
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="ref"/>
|
<field name="ref"/>
|
||||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="['|',('parent_id','=',False),('is_company','=',True)]"/>
|
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="[
|
||||||
|
'&',
|
||||||
|
'|',('parent_id','=',False),('is_company','=',True),
|
||||||
|
'|',('customer','=',True),('supplier','=',True)]"/>
|
||||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||||
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
|
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
|
||||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
||||||
|
|
|
@ -363,7 +363,7 @@
|
||||||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="type" position="after">
|
<field name="type" position="after">
|
||||||
<field name="analytic_journal_id"/>
|
<field name="analytic_journal_id" groups="analytic.group_analytic_accounting"/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -239,7 +239,7 @@
|
||||||
<td><para style="terp_default_8">[[ line.account_id.code ]]</para></td>
|
<td><para style="terp_default_8">[[ line.account_id.code ]]</para></td>
|
||||||
<td><para style="terp_default_8">[[ line.partner_id and strip_name(line.partner_id.name,15) ]]</para></td>
|
<td><para style="terp_default_8">[[ line.partner_id and strip_name(line.partner_id.name,15) ]]</para></td>
|
||||||
<td><para style="terp_default_8">[[ strip_name(line.name,25) ]]</para></td>
|
<td><para style="terp_default_8">[[ strip_name(line.name,25) ]]</para></td>
|
||||||
<td><para style="P8">[[ line.tax_code_id and (line.tax_code_id.code + ':') ]]</para></td>
|
<td><para style="P8">[[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]]</para></td>
|
||||||
<td><para style="terp_default_8">[[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]]</para></td>
|
<td><para style="terp_default_8">[[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]]</para></td>
|
||||||
<td><para style="P8">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
|
<td><para style="P8">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
|
||||||
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>
|
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>
|
||||||
|
@ -292,7 +292,7 @@
|
||||||
<td><para style="terp_default_8">[[ line.account_id.code ]]</para></td>
|
<td><para style="terp_default_8">[[ line.account_id.code ]]</para></td>
|
||||||
<td><para style="terp_default_8">[[ line.partner_id and strip_name(line.partner_id.name,12) ]]</para></td>
|
<td><para style="terp_default_8">[[ line.partner_id and strip_name(line.partner_id.name,12) ]]</para></td>
|
||||||
<td><para style="terp_default_8">[[ strip_name(line.name,16) ]]</para></td>
|
<td><para style="terp_default_8">[[ strip_name(line.name,16) ]]</para></td>
|
||||||
<td><para style="terp_default_8">[[ line.tax_code_id and (line.tax_code_id.code + ':') ]]</para></td>
|
<td><para style="terp_default_8">[[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]]</para></td>
|
||||||
<td><para style="P8">[[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]]</para></td>
|
<td><para style="P8">[[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]]</para></td>
|
||||||
<td><para style="P8">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
|
<td><para style="P8">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
|
||||||
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>
|
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>
|
||||||
|
|
|
@ -38,7 +38,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
||||||
'report_name': fields.char('Name of new entries',size=64, required=True, help="Give name of the new entries"),
|
'report_name': fields.char('Name of new entries',size=64, required=True, help="Give name of the new entries"),
|
||||||
}
|
}
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'report_name': _('End of Fiscal Year Entry'),
|
'report_name': lambda self, cr, uid, context: _('End of Fiscal Year Entry'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def data_save(self, cr, uid, ids, context=None):
|
def data_save(self, cr, uid, ids, context=None):
|
||||||
|
|
|
@ -72,8 +72,8 @@ class account_invoice_line(osv.osv):
|
||||||
_inherit = "account.invoice.line"
|
_inherit = "account.invoice.line"
|
||||||
_description = "Invoice Line"
|
_description = "Invoice Line"
|
||||||
|
|
||||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||||
res_prod = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id=currency_id, context=context, company_id=company_id)
|
res_prod = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit, currency_id=currency_id, context=context, company_id=company_id)
|
||||||
rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), context=context)
|
rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), context=context)
|
||||||
if rec:
|
if rec:
|
||||||
res_prod['value'].update({'account_analytic_id': rec.analytic_id.id})
|
res_prod['value'].update({'account_analytic_id': rec.analytic_id.id})
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="centralisation" position="before">
|
<field name="centralisation" position="before">
|
||||||
<field name="plan_id" />
|
<field name="plan_id" groups="analytic.group_analytic_accounting"/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -136,9 +136,9 @@ class account_invoice_line(osv.osv):
|
||||||
res += diff_res
|
res += diff_res
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||||
fiscal_pool = self.pool.get('account.fiscal.position')
|
fiscal_pool = self.pool.get('account.fiscal.position')
|
||||||
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context, company_id)
|
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context, company_id)
|
||||||
if not product:
|
if not product:
|
||||||
return res
|
return res
|
||||||
if type in ('in_invoice','in_refund'):
|
if type in ('in_invoice','in_refund'):
|
||||||
|
|
|
@ -13,6 +13,17 @@
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="view_invoice_asset_category">
|
||||||
|
<field name="name">account.invoice.supplier.form</field>
|
||||||
|
<field name="model">account.invoice</field>
|
||||||
|
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='invoice_line']/tree/field[@name='quantity']" position="before">
|
||||||
|
<field name="asset_category_id"/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -203,7 +203,9 @@
|
||||||
<field name="view_id" ref="crossovered_budget_view_tree"/>
|
<field name="view_id" ref="crossovered_budget_view_tree"/>
|
||||||
<field name="search_view_id" ref="view_crossovered_budget_search"/>
|
<field name="search_view_id" ref="view_crossovered_budget_search"/>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p>
|
<p class="oe_view_nocontent_create">
|
||||||
|
Click to create a new budget.
|
||||||
|
</p><p>
|
||||||
A budget is a forecast of your company's income and/or expenses
|
A budget is a forecast of your company's income and/or expenses
|
||||||
expected for a period in the future. A budget is defined on some
|
expected for a period in the future. A budget is defined on some
|
||||||
financial accounts and/or analytic accounts (that may represent
|
financial accounts and/or analytic accounts (that may represent
|
||||||
|
|
|
@ -3,5 +3,5 @@ access_account_followup_followup_line,account_followup.followup.line,model_accou
|
||||||
access_account_followup_followup_line_manager,account_followup.followup.line.manager,model_account_followup_followup_line,account.group_account_manager,1,1,1,1
|
access_account_followup_followup_line_manager,account_followup.followup.line.manager,model_account_followup_followup_line,account.group_account_manager,1,1,1,1
|
||||||
access_account_followup_followup_accountant,account_followup.followup user,model_account_followup_followup,account.group_account_invoice,1,0,0,0
|
access_account_followup_followup_accountant,account_followup.followup user,model_account_followup_followup,account.group_account_invoice,1,0,0,0
|
||||||
access_account_followup_followup_manager,account_followup.followup.manager,model_account_followup_followup,account.group_account_manager,1,1,1,1
|
access_account_followup_followup_manager,account_followup.followup.manager,model_account_followup_followup,account.group_account_manager,1,1,1,1
|
||||||
access_account_followup_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,1,1,1,1
|
access_account_followup_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,1,1,0,0
|
||||||
access_account_followup_stat_by_partner_manager,account_followup.stat.by.partner,model_account_followup_stat_by_partner,account.group_account_user,1,1,1,1
|
access_account_followup_stat_by_partner_manager,account_followup.stat.by.partner,model_account_followup_stat_by_partner,account.group_account_user,1,1,0,0
|
||||||
|
|
|
|
@ -88,6 +88,7 @@ class payment_order_create(osv.osv_memory):
|
||||||
'order_id': payment.id,
|
'order_id': payment.id,
|
||||||
'partner_id': line.partner_id and line.partner_id.id or False,
|
'partner_id': line.partner_id and line.partner_id.id or False,
|
||||||
'communication': line.ref or '/',
|
'communication': line.ref or '/',
|
||||||
|
'state': line.invoice and line.invoice.reference_type != 'none' and 'structured' or 'normal',
|
||||||
'date': date_to_pay,
|
'date': date_to_pay,
|
||||||
'currency': (line.invoice and line.invoice.currency_id.id) or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id,
|
'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)
|
}, context=context)
|
||||||
|
|
|
@ -102,7 +102,10 @@ class OAuthController(oeweb.Controller):
|
||||||
registry = RegistryManager.get(dbname)
|
registry = RegistryManager.get(dbname)
|
||||||
with registry.cursor() as cr:
|
with registry.cursor() as cr:
|
||||||
IMD = registry['ir.model.data']
|
IMD = registry['ir.model.data']
|
||||||
model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
|
try:
|
||||||
|
model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
|
||||||
|
except ValueError:
|
||||||
|
return set_cookie_and_redirect(req, '/?db=%s' % dbname)
|
||||||
assert model == 'auth.oauth.provider'
|
assert model == 'auth.oauth.provider'
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
Name,Is a company,Related company,Address type,Customer,Supplier,Street,ZIP,City,State,Country
|
||||||
|
Aurora Shelves,1,,,1,0,25 Pacific Road,95101,San José,CA,United States
|
||||||
|
Roger Martins,0,Aurora Shelves,Invoice,1,0,27 Pacific Road,95102,San José,CA,United States
|
||||||
|
House Sales Direct,1,,,1,0,104 Saint Mary Avenue,94059,Redwood,CA,United States
|
||||||
|
Yvan Holiday,0,House Sales Direct,Default,1,0,104 Saint Mary Avenue,94060,Redwood,CA,United States
|
||||||
|
Jack Unsworth,0,House Sales Direct,Invoice,1,0,227 Jackson Road,94061,Redwood,CA,United States
|
||||||
|
Michael Mason,0,,,1,0,16 5th Avenue,94104,San Francisco,CA,United States
|
||||||
|
International Wood,1,,,1,0,748 White House Boulevard,20004,Washington,DC,United States
|
||||||
|
Sharon Pecker,0,International Wood,Invoice,1,0,755 White House Boulevard,20005,Washington,DC,United States
|
|
|
@ -1,8 +0,0 @@
|
||||||
Name,Address type,Street,City,Country,Tags,Supplier,Customer,Is a company,Companies that refers to partner / Parent company
|
|
||||||
Wood y Wood Pecker,,"Snow Street, 25",Kainuu,Finland,Supplier,1,0,1,
|
|
||||||
Roger Pecker,Default,"Snow Street, 27",Kainuu,Finland,Supplier,1,0,0,Wood y Wood Pecker
|
|
||||||
Sharon Pecker,Delivery,"Snow Street, 28",Kainuu,Finland,Supplier,1,0,0,Wood y Wood Pecker
|
|
||||||
Thomas Pecker,Contact,"Snow Street, 27",Kainuu,Finland,Supplier,1,0,0,Wood y Wood Pecker
|
|
||||||
Vicking Direct,,"Atonium Street, 45a",Brussels,Belgium,Supplier,1,0,1,
|
|
||||||
Yvan Holiday,Invoice,"Atonium Street, 45b",Brussels,Belgium,Supplier,1,0,0,Vicking Direct
|
|
||||||
Jack Unsworth,Contact,"Atonium Street, 45a",Brussels,Belgium,Supplier,1,0,0,Vicking Direct
|
|
|
|
@ -229,8 +229,8 @@
|
||||||
orders with their respective purchase order lines:</p>
|
orders with their respective purchase order lines:</p>
|
||||||
<a href="/base_import/static/csv/o2m_purchase_order_lines.csv">Purchase orders with their respective purchase order lines</a>
|
<a href="/base_import/static/csv/o2m_purchase_order_lines.csv">Purchase orders with their respective purchase order lines</a>
|
||||||
<p>The following CSV file shows how to import
|
<p>The following CSV file shows how to import
|
||||||
suppliers and their respective contacts</p>
|
customers and their respective contacts</p>
|
||||||
<a href="/base_import/static/csv/o2m_suppliers_contacts.csv">Suppliers and their respective contacts</a>
|
<a href="/base_import/static/csv/o2m_customers_contacts.csv">Customers and their respective contacts</a>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ class RPCSession(object):
|
||||||
protocol = m.group(1)
|
protocol = m.group(1)
|
||||||
if not m:
|
if not m:
|
||||||
return -1
|
return -1
|
||||||
if protocol == 'http://' or protocol == 'http://':
|
if protocol == 'http://' or protocol == 'https://':
|
||||||
self.gateway = XMLRPCGateway(host, port, 'http')
|
self.gateway = XMLRPCGateway(host, port, protocol[:-3])
|
||||||
elif protocol == 'socket://':
|
elif protocol == 'socket://':
|
||||||
|
|
||||||
self.gateway = NETRPCGateway(host, port)
|
self.gateway = NETRPCGateway(host, port)
|
||||||
|
|
Binary file not shown.
|
@ -344,7 +344,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
|
||||||
},
|
},
|
||||||
load_data:function(){
|
load_data:function(){
|
||||||
var board = new instance.web.Model('board.board');
|
var board = new instance.web.Model('board.board');
|
||||||
return board.call('list');
|
return board.call('list', [board.context()]);
|
||||||
},
|
},
|
||||||
_x:function() {
|
_x:function() {
|
||||||
if (!instance.webclient) { return $.Deferred().reject(); }
|
if (!instance.webclient) { return $.Deferred().reject(); }
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
<field name="view_id" ref="crm_case_claims_tree_view"/>
|
<field name="view_id" ref="crm_case_claims_tree_view"/>
|
||||||
<field name="context">{"search_default_user_id":uid, "stage_type":'claim'}</field>
|
<field name="context">{"search_default_user_id":uid, "stage_type":'claim'}</field>
|
||||||
<field name="search_view_id" ref="crm_claim.view_crm_case_claims_filter"/>
|
<field name="search_view_id" ref="crm_claim.view_crm_case_claims_filter"/>
|
||||||
<field name="help">Record and track your customers' claims. Claims may be linked to a sales order or a lot. You can send emails with attachments and keep the full history for a claim (emails sent, intervention type and so on). Claims may automatically be linked to an email address using the mail gateway module.</field>
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Record and track your customers' claims. Claims may be linked to a sales order or a lot.You can send emails with attachments and keep the full history for a claim (emails sent, intervention type and so on).Claims may automatically be linked to an email address using the mail gateway module.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_claim0">
|
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_claim0">
|
||||||
|
|
|
@ -88,7 +88,11 @@
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="view_id" ref="view_wiki_tree"/>
|
<field name="view_id" ref="view_wiki_tree"/>
|
||||||
<field name="search_view_id" ref="view_wiki_filter"/>
|
<field name="search_view_id" ref="view_wiki_filter"/>
|
||||||
<field name="help">Create web pages</field>
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Click to create a new web page.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<menuitem id="menu_page" parent="menu_wiki" name="Pages" action="action_page" sequence="10"/>
|
<menuitem id="menu_page" parent="menu_wiki" name="Pages" action="action_page" sequence="10"/>
|
||||||
<record id="action_category" model="ir.actions.act_window">
|
<record id="action_category" model="ir.actions.act_window">
|
||||||
|
|
|
@ -24,8 +24,8 @@ import base64
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import openerp
|
import openerp
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.osv import osv, fields
|
from openerp.osv import osv, fields
|
||||||
from openerp.osv import fields
|
|
||||||
from openerp import tools
|
from openerp import tools
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
from urllib import urlencode, quote as quote
|
from urllib import urlencode, quote as quote
|
||||||
|
@ -191,7 +191,6 @@ class email_template(osv.osv):
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_action(self, cr, uid, ids, context=None):
|
def create_action(self, cr, uid, ids, context=None):
|
||||||
vals = {}
|
|
||||||
action_obj = self.pool.get('ir.actions.act_window')
|
action_obj = self.pool.get('ir.actions.act_window')
|
||||||
data_obj = self.pool.get('ir.model.data')
|
data_obj = self.pool.get('ir.model.data')
|
||||||
for template in self.browse(cr, uid, ids, context=context):
|
for template in self.browse(cr, uid, ids, context=context):
|
||||||
|
@ -199,7 +198,7 @@ class email_template(osv.osv):
|
||||||
model_data_id = data_obj._get_id(cr, uid, 'mail', 'email_compose_message_wizard_form')
|
model_data_id = data_obj._get_id(cr, uid, 'mail', 'email_compose_message_wizard_form')
|
||||||
res_id = data_obj.browse(cr, uid, model_data_id, context=context).res_id
|
res_id = data_obj.browse(cr, uid, model_data_id, context=context).res_id
|
||||||
button_name = _('Send Mail (%s)') % template.name
|
button_name = _('Send Mail (%s)') % template.name
|
||||||
vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
|
act_id = action_obj.create(cr, SUPERUSER_ID, {
|
||||||
'name': button_name,
|
'name': button_name,
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'res_model': 'mail.compose.message',
|
'res_model': 'mail.compose.message',
|
||||||
|
@ -211,27 +210,29 @@ class email_template(osv.osv):
|
||||||
'target': 'new',
|
'target': 'new',
|
||||||
'auto_refresh':1
|
'auto_refresh':1
|
||||||
}, context)
|
}, context)
|
||||||
vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, {
|
ir_values_id = self.pool.get('ir.values').create(cr, SUPERUSER_ID, {
|
||||||
'name': button_name,
|
'name': button_name,
|
||||||
'model': src_obj,
|
'model': src_obj,
|
||||||
'key2': 'client_action_multi',
|
'key2': 'client_action_multi',
|
||||||
'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']),
|
'value': "ir.actions.act_window,%s" % act_id,
|
||||||
'object': True,
|
'object': True,
|
||||||
}, context)
|
}, context)
|
||||||
self.write(cr, uid, ids, {
|
|
||||||
'ref_ir_act_window': vals.get('ref_ir_act_window',False),
|
template.write({
|
||||||
'ref_ir_value': vals.get('ref_ir_value',False),
|
'ref_ir_act_window': act_id,
|
||||||
}, context)
|
'ref_ir_value': ir_values_id,
|
||||||
|
})
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unlink_action(self, cr, uid, ids, context=None):
|
def unlink_action(self, cr, uid, ids, context=None):
|
||||||
for template in self.browse(cr, uid, ids, context=context):
|
for template in self.browse(cr, uid, ids, context=context):
|
||||||
try:
|
try:
|
||||||
if template.ref_ir_act_window:
|
if template.ref_ir_act_window:
|
||||||
self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context)
|
self.pool.get('ir.actions.act_window').unlink(cr, SUPERUSER_ID, template.ref_ir_act_window.id, context)
|
||||||
if template.ref_ir_value:
|
if template.ref_ir_value:
|
||||||
ir_values_obj = self.pool.get('ir.values')
|
ir_values_obj = self.pool.get('ir.values')
|
||||||
ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context)
|
ir_values_obj.unlink(cr, SUPERUSER_ID, template.ref_ir_value.id, context)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
|
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -54,18 +54,22 @@ class mail_compose_message(osv.TransientModel):
|
||||||
Indeed, basic mail.compose.message wizard duplicates attachments in mass
|
Indeed, basic mail.compose.message wizard duplicates attachments in mass
|
||||||
mailing mode. But in 'single post' mode, attachments of an email template
|
mailing mode. But in 'single post' mode, attachments of an email template
|
||||||
also have to be duplicated to avoid changing their ownership. """
|
also have to be duplicated to avoid changing their ownership. """
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
wizard_context = dict(context)
|
||||||
for wizard in self.browse(cr, uid, ids, context=context):
|
for wizard in self.browse(cr, uid, ids, context=context):
|
||||||
|
if wizard.template_id and not wizard.template_id.user_signature:
|
||||||
|
wizard_context['mail_notify_user_signature'] = False # template user_signature is added when generating body_html
|
||||||
if not wizard.attachment_ids or wizard.composition_mode == 'mass_mail' or not wizard.template_id:
|
if not wizard.attachment_ids or wizard.composition_mode == 'mass_mail' or not wizard.template_id:
|
||||||
continue
|
continue
|
||||||
template = self.pool.get('email.template').browse(cr, uid, wizard.template_id.id, context=context)
|
|
||||||
new_attachment_ids = []
|
new_attachment_ids = []
|
||||||
for attachment in wizard.attachment_ids:
|
for attachment in wizard.attachment_ids:
|
||||||
if attachment in template.attachment_ids:
|
if attachment in wizard.template_id.attachment_ids:
|
||||||
new_attachment_ids.append(self.pool.get('ir.attachment').copy(cr, uid, attachment.id, {'res_model': 'mail.compose.message', 'res_id': wizard.id}, context=context))
|
new_attachment_ids.append(self.pool.get('ir.attachment').copy(cr, uid, attachment.id, {'res_model': 'mail.compose.message', 'res_id': wizard.id}, context=context))
|
||||||
else:
|
else:
|
||||||
new_attachment_ids.append(attachment.id)
|
new_attachment_ids.append(attachment.id)
|
||||||
self.write(cr, uid, wizard.id, {'attachment_ids': [(6, 0, new_attachment_ids)]}, context=context)
|
self.write(cr, uid, wizard.id, {'attachment_ids': [(6, 0, new_attachment_ids)]}, context=context)
|
||||||
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)
|
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=wizard_context)
|
||||||
|
|
||||||
def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None):
|
def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None):
|
||||||
""" - mass_mailing: we cannot render, so return the template values
|
""" - mass_mailing: we cannot render, so return the template values
|
||||||
|
|
|
@ -591,6 +591,9 @@
|
||||||
<field name="view_mode">tree,graph</field>
|
<field name="view_mode">tree,graph</field>
|
||||||
<field name="context">{"search_default_groupby_vehicle" : True}</field>
|
<field name="context">{"search_default_groupby_vehicle" : True}</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Click to create a new odometer log.
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Here you can add various odometer entries for all vehicles.
|
Here you can add various odometer entries for all vehicles.
|
||||||
You can also show odometer value for a particular vehicle using
|
You can also show odometer value for a particular vehicle using
|
||||||
|
|
|
@ -210,6 +210,11 @@
|
||||||
<field name="context">{"default_hr_expense_ok":1}</field>
|
<field name="context">{"default_hr_expense_ok":1}</field>
|
||||||
<field name="domain">[('hr_expense_ok','=',True)]</field>
|
<field name="domain">[('hr_expense_ok','=',True)]</field>
|
||||||
<field name="search_view_id" ref="product.product_search_form_view"/>
|
<field name="search_view_id" ref="product.product_search_form_view"/>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Click to create a new expense category.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem id="menu_hr_product" name="Expense Categories" parent="hr.menu_hr_configuration" action="hr_expense_product"/>
|
<menuitem id="menu_hr_product" name="Expense Categories" parent="hr.menu_hr_configuration" action="hr_expense_product"/>
|
||||||
|
|
|
@ -146,6 +146,7 @@
|
||||||
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
||||||
<field name="manager_id" invisible="1"/>
|
<field name="manager_id" invisible="1"/>
|
||||||
<field name="user_id" invisible="1"/>
|
<field name="user_id" invisible="1"/>
|
||||||
|
<field name="date_from" invisible="1"/>
|
||||||
<!--field name="type"/-->
|
<!--field name="type"/-->
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
</tree>
|
</tree>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<field name="name">timesheet.report.tree</field>
|
<field name="name">timesheet.report.tree</field>
|
||||||
<field name="model">timesheet.report</field>
|
<field name="model">timesheet.report</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree colors="blue:state == 'draft';black:state in ('confirm','new');gray:state == 'cancel'" string="Timesheet">
|
<tree colors="blue:state == 'draft';black:state in ('confirm','new');gray:state == 'cancel'" string="Timesheet" create="false">
|
||||||
<field name="date" invisible="1"/>
|
<field name="date" invisible="1"/>
|
||||||
<field name="name" invisible="1"/>
|
<field name="name" invisible="1"/>
|
||||||
<field name="user_id" invisible="1"/>
|
<field name="user_id" invisible="1"/>
|
||||||
|
|
|
@ -3,7 +3,7 @@ access_hr_timesheet_sheet_sheet_user,hr_timesheet_sheet.sheet.user,model_hr_time
|
||||||
access_hr_timesheet_sheet_sheet_system_employee,hr_timesheet_sheet.sheet.system.employee,model_hr_timesheet_sheet_sheet,base.group_user,1,1,1,0
|
access_hr_timesheet_sheet_sheet_system_employee,hr_timesheet_sheet.sheet.system.employee,model_hr_timesheet_sheet_sheet,base.group_user,1,1,1,0
|
||||||
access_hr_timesheet_sheet_sheet_day,hr_timesheet_sheet.sheet.day,model_hr_timesheet_sheet_sheet_day,base.group_hr_user,1,1,1,1
|
access_hr_timesheet_sheet_sheet_day,hr_timesheet_sheet.sheet.day,model_hr_timesheet_sheet_sheet_day,base.group_hr_user,1,1,1,1
|
||||||
access_hr_timesheet_sheet_sheet_account,hr_timesheet_sheet.sheet.account,model_hr_timesheet_sheet_sheet_account,base.group_hr_user,1,1,1,1
|
access_hr_timesheet_sheet_sheet_account,hr_timesheet_sheet.sheet.account,model_hr_timesheet_sheet_sheet_account,base.group_hr_user,1,1,1,1
|
||||||
access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,1,1
|
access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,0,0
|
||||||
access_hr_analytic_timesheet_system_user,hr.analytic.timesheet.system.user,model_hr_analytic_timesheet,base.group_user,1,0,0,0
|
access_hr_analytic_timesheet_system_user,hr.analytic.timesheet.system.user,model_hr_analytic_timesheet,base.group_user,1,0,0,0
|
||||||
access_hr_timesheet_sheet_sheet_day,hr.timesheet.sheet.sheet.day.user,model_hr_timesheet_sheet_sheet_day,base.group_user,1,1,1,0
|
access_hr_timesheet_sheet_sheet_day,hr.timesheet.sheet.sheet.day.user,model_hr_timesheet_sheet_sheet_day,base.group_user,1,1,1,0
|
||||||
access_timesheet_report,timesheet.report,model_timesheet_report,base.group_hr_manager,1,1,1,1
|
access_timesheet_report,timesheet.report,model_timesheet_report,base.group_hr_manager,1,1,0,0
|
||||||
|
|
|
|
@ -190,8 +190,13 @@ openerp.hr_timesheet_sheet = function(instance) {
|
||||||
$(this).val(self.sum_box(account, day_count, true));
|
$(this).val(self.sum_box(account, day_count, true));
|
||||||
} else {
|
} else {
|
||||||
account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
|
account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
|
||||||
self.display_totals();
|
var product = (account.days[day_count].lines[0].product_id instanceof Array) ? account.days[day_count].lines[0].product_id[0] : account.days[day_count].lines[0].product_id
|
||||||
self.sync();
|
var journal = (account.days[day_count].lines[0].journal_id instanceof Array) ? account.days[day_count].lines[0].journal_id[0] : account.days[day_count].lines[0].journal_id
|
||||||
|
new instance.web.Model("hr.analytic.timesheet").call("on_change_unit_amount", [[], product, account.days[day_count].lines[0].unit_amount, false, false, journal]).then(function(res) {
|
||||||
|
account.days[day_count].lines[0]['amount'] = res.value.amount || 0;
|
||||||
|
self.display_totals();
|
||||||
|
self.sync();
|
||||||
|
});
|
||||||
if(!isNaN($(this).val())){
|
if(!isNaN($(this).val())){
|
||||||
$(this).val(self.sum_box(account, day_count, true));
|
$(this).val(self.sum_box(account, day_count, true));
|
||||||
}
|
}
|
||||||
|
@ -308,10 +313,10 @@ openerp.hr_timesheet_sheet = function(instance) {
|
||||||
generate_o2m_value: function() {
|
generate_o2m_value: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var ops = [];
|
var ops = [];
|
||||||
|
|
||||||
_.each(self.accounts, function(account) {
|
_.each(self.accounts, function(account) {
|
||||||
var auth_keys = _.extend(_.clone(account.account_defaults), {
|
var auth_keys = _.extend(_.clone(account.account_defaults), {
|
||||||
name: true, unit_amount: true, date: true, account_id:true,
|
name: true, amount:true, unit_amount: true, date: true, account_id:true,
|
||||||
});
|
});
|
||||||
_.each(account.days, function(day) {
|
_.each(account.days, function(day) {
|
||||||
_.each(day.lines, function(line) {
|
_.each(day.lines, function(line) {
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
<para style="terp_default_9">[[ l['vat'] ]]</para>
|
<para style="terp_default_9">[[ l['vat'] ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_9">[[ l['code'] (l['intra_code']) ]]</para>
|
<para style="terp_default_9">[[ l['code'] ]]([[ l['intra_code'] ]])</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9">[[ formatLang(l['amount'], currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9">[[ formatLang(l['amount'], currency_obj=company.currency_id) ]]</para>
|
||||||
|
|
|
@ -35,24 +35,24 @@
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="view_account_bank_statement_line_coda_tree" model="ir.ui.view">
|
<record id="view_account_bank_statement_line_coda_tree" model="ir.ui.view">
|
||||||
<field name="name">account.bank.statement.line.coda.tree</field>
|
<field name="name">account.bank.statement.line.coda.tree</field>
|
||||||
<field name="model">account.bank.statement.line</field>
|
<field name="model">account.bank.statement.line</field>
|
||||||
<field name="priority">10</field>
|
<field name="priority">10</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree editable="bottom" string="Statement lines">
|
<tree editable="bottom" string="Statement lines" create="0">
|
||||||
<field name="statement_id" readonly="1" invisible="1"/>
|
<field name="sequence" readonly="1" invisible="1"/>
|
||||||
<field name="sequence" readonly="1" invisible="1"/>
|
<field name="statement_id" readonly="1" />
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="ref"/>
|
<field name="ref"/>
|
||||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||||
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
|
<field name="account_id" options='{"no_open":True}' domain="[('type', '<>', 'view')]"/>
|
||||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '<>', 'view')]"/>
|
||||||
<field name="amount"/>
|
<field name="amount"/>
|
||||||
<field name="note"/>
|
<field name="note"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -150,11 +150,17 @@ class mail_notification(osv.Model):
|
||||||
|
|
||||||
return footer
|
return footer
|
||||||
|
|
||||||
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None):
|
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None,
|
||||||
|
force_send=False, user_signature=True):
|
||||||
""" Send by email the notification depending on the user preferences
|
""" Send by email the notification depending on the user preferences
|
||||||
|
|
||||||
:param list partners_to_notify: optional list of partner ids restricting
|
:param list partners_to_notify: optional list of partner ids restricting
|
||||||
the notifications to process
|
the notifications to process
|
||||||
|
:param bool force_send: if True, the generated mail.mail is
|
||||||
|
immediately sent after being created, as if the scheduler
|
||||||
|
was executed for this message only.
|
||||||
|
:param bool user_signature: if True, the generated mail.mail body is
|
||||||
|
the body of the related mail.message with the author's signature
|
||||||
"""
|
"""
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
|
@ -189,8 +195,9 @@ class mail_notification(osv.Model):
|
||||||
# add signature
|
# add signature
|
||||||
body_html = msg.body
|
body_html = msg.body
|
||||||
user_id = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0] and msg.author_id.user_ids[0].id or None
|
user_id = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0] and msg.author_id.user_ids[0].id or None
|
||||||
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
if user_signature:
|
||||||
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
||||||
|
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
||||||
|
|
||||||
references = False
|
references = False
|
||||||
if msg.parent_id:
|
if msg.parent_id:
|
||||||
|
@ -203,13 +210,9 @@ class mail_notification(osv.Model):
|
||||||
'recipient_ids': [(4, id) for id in notify_partner_ids],
|
'recipient_ids': [(4, id) for id in notify_partner_ids],
|
||||||
'references': references,
|
'references': references,
|
||||||
}
|
}
|
||||||
if msg.email_from:
|
|
||||||
mail_values['email_from'] = msg.email_from
|
|
||||||
if msg.reply_to:
|
|
||||||
mail_values['reply_to'] = msg.reply_to
|
|
||||||
mail_mail = self.pool.get('mail.mail')
|
mail_mail = self.pool.get('mail.mail')
|
||||||
email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
|
email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
|
||||||
try:
|
|
||||||
return mail_mail.send(cr, uid, [email_notif_id], context=context)
|
if force_send:
|
||||||
except Exception:
|
mail_mail.send(cr, uid, [email_notif_id], context=context)
|
||||||
return False
|
return True
|
||||||
|
|
|
@ -55,7 +55,6 @@ class mail_mail(osv.Model):
|
||||||
'auto_delete': fields.boolean('Auto Delete',
|
'auto_delete': fields.boolean('Auto Delete',
|
||||||
help="Permanently delete this email after sending it, to save space"),
|
help="Permanently delete this email after sending it, to save space"),
|
||||||
'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1),
|
'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1),
|
||||||
'email_from': fields.char('From', help='Message sender, taken from user preferences.'),
|
|
||||||
'email_to': fields.text('To', help='Message recipients (emails)'),
|
'email_to': fields.text('To', help='Message recipients (emails)'),
|
||||||
'recipient_ids': fields.many2many('res.partner', string='To (Partners)'),
|
'recipient_ids': fields.many2many('res.partner', string='To (Partners)'),
|
||||||
'email_cc': fields.char('Cc', help='Carbon copy message recipients'),
|
'email_cc': fields.char('Cc', help='Carbon copy message recipients'),
|
||||||
|
@ -67,16 +66,13 @@ class mail_mail(osv.Model):
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_default_from(self, cr, uid, context=None):
|
def _get_default_from(self, cr, uid, context=None):
|
||||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
""" Kept for compatibility
|
||||||
if this.alias_domain:
|
TDE TODO: remove me in 8.0
|
||||||
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
"""
|
||||||
elif this.email:
|
return self.pool['mail.message']._get_default_from(cr, uid, context=context)
|
||||||
return '%s <%s>' % (this.name, this.email)
|
|
||||||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'state': 'outgoing',
|
'state': 'outgoing',
|
||||||
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def default_get(self, cr, uid, fields, context=None):
|
def default_get(self, cr, uid, fields, context=None):
|
||||||
|
@ -93,19 +89,24 @@ class mail_mail(osv.Model):
|
||||||
# if value specified: directly return it
|
# if value specified: directly return it
|
||||||
if values.get('reply_to'):
|
if values.get('reply_to'):
|
||||||
return values.get('reply_to')
|
return values.get('reply_to')
|
||||||
|
format_name = True # whether to use a 'Followers of Pigs <pigs@openerp.com' format
|
||||||
|
|
||||||
mailgateway = True # tells whether the answer will go through the mailgateway, leading to the formatting of reply_to <Followers of ...>
|
|
||||||
ir_config_parameter = self.pool.get("ir.config_parameter")
|
ir_config_parameter = self.pool.get("ir.config_parameter")
|
||||||
catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
|
catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
|
||||||
|
|
||||||
# model, res_id, email_from, reply_to: comes from values OR related message
|
# model, res_id, email_from: comes from values OR related message
|
||||||
message = None
|
model, res_id, email_from = values.get('model'), values.get('res_id'), values.get('email_from')
|
||||||
if values.get('mail_message_id'):
|
if values.get('mail_message_id'):
|
||||||
message = self.pool.get('mail.message').browse(cr, uid, values.get('mail_message_id'), context=context)
|
message = self.pool.get('mail.message').browse(cr, uid, values.get('mail_message_id'), context=context)
|
||||||
model = values.get('model', message and message.model or False)
|
if message.reply_to:
|
||||||
res_id = values.get('res_id', message and message.res_id or False)
|
email_reply_to = message.reply_to
|
||||||
email_from = values.get('email_from', message and message.email_from or False)
|
format_name = False
|
||||||
email_reply_to = message and message.reply_to or False
|
if not model:
|
||||||
|
model = message.model
|
||||||
|
if not res_id:
|
||||||
|
res_id = message.res_id
|
||||||
|
if not email_from:
|
||||||
|
email_from = message.email_from
|
||||||
|
|
||||||
# if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
|
# if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
|
||||||
if not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
|
if not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
|
||||||
|
@ -115,16 +116,12 @@ class mail_mail(osv.Model):
|
||||||
catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context)
|
catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context)
|
||||||
if catchall_domain and catchall_alias:
|
if catchall_domain and catchall_alias:
|
||||||
email_reply_to = '%s@%s' % (catchall_alias, catchall_domain)
|
email_reply_to = '%s@%s' % (catchall_alias, catchall_domain)
|
||||||
# no alias reply_to -> reply_to will be the email_from, only the email part
|
|
||||||
if not email_reply_to and email_from:
|
|
||||||
emails = tools.email_split(email_from)
|
|
||||||
if emails:
|
|
||||||
email_reply_to = emails[0]
|
|
||||||
if emails[0].split('@')[1] != catchall_domain:
|
|
||||||
mailgateway = False
|
|
||||||
|
|
||||||
# format 'Document name <email_address>'
|
# format 'Document name <email_address>'
|
||||||
if email_reply_to and model and res_id and mailgateway:
|
if email_reply_to and model and res_id and format_name:
|
||||||
|
emails = tools.email_split(email_reply_to)
|
||||||
|
if emails:
|
||||||
|
email_reply_to = emails[0]
|
||||||
document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0]
|
document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0]
|
||||||
if document_name:
|
if document_name:
|
||||||
# sanitize document name
|
# sanitize document name
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
<field name="res_model">mail.mail</field>
|
<field name="res_model">mail.mail</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="context">{'search_default_outgoing': 1, 'search_default_type_email': 1}</field>
|
<field name="context">{'search_default_outgoing': 1}</field>
|
||||||
<field name="search_view_id" ref="view_mail_search"/>
|
<field name="search_view_id" ref="view_mail_search"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,14 @@ class mail_message(osv.Model):
|
||||||
def _needaction_domain_get(self, cr, uid, context=None):
|
def _needaction_domain_get(self, cr, uid, context=None):
|
||||||
return [('to_read', '=', True)]
|
return [('to_read', '=', True)]
|
||||||
|
|
||||||
|
def _get_default_from(self, cr, uid, context=None):
|
||||||
|
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||||
|
if this.alias_domain:
|
||||||
|
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
||||||
|
elif this.email:
|
||||||
|
return '%s <%s>' % (this.name, this.email)
|
||||||
|
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||||
|
|
||||||
def _get_default_author(self, cr, uid, context=None):
|
def _get_default_author(self, cr, uid, context=None):
|
||||||
return self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
return self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||||
|
|
||||||
|
@ -204,7 +212,7 @@ class mail_message(osv.Model):
|
||||||
'date': lambda *a: fields.datetime.now(),
|
'date': lambda *a: fields.datetime.now(),
|
||||||
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
|
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
|
||||||
'body': '',
|
'body': '',
|
||||||
'email_from': lambda self, cr, uid, ctx=None: self.pool.get('mail.mail')._get_default_from(cr, uid, ctx),
|
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
#------------------------------------------------------
|
#------------------------------------------------------
|
||||||
|
@ -329,8 +337,10 @@ class mail_message(osv.Model):
|
||||||
for key, message in message_tree.iteritems():
|
for key, message in message_tree.iteritems():
|
||||||
if message.author_id:
|
if message.author_id:
|
||||||
partner_ids |= set([message.author_id.id])
|
partner_ids |= set([message.author_id.id])
|
||||||
if message.notified_partner_ids:
|
if message.subtype_id and message.notified_partner_ids: # take notified people of message with a subtype
|
||||||
partner_ids |= set([partner.id for partner in message.notified_partner_ids])
|
partner_ids |= set([partner.id for partner in message.notified_partner_ids])
|
||||||
|
elif not message.subtype_id and message.partner_ids: # take specified people of message without a subtype (log)
|
||||||
|
partner_ids |= set([partner.id for partner in message.partner_ids])
|
||||||
if message.attachment_ids:
|
if message.attachment_ids:
|
||||||
attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
|
attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
|
||||||
# Read partners as SUPERUSER -> display the names like classic m2o even if no access
|
# Read partners as SUPERUSER -> display the names like classic m2o even if no access
|
||||||
|
@ -350,9 +360,12 @@ class mail_message(osv.Model):
|
||||||
else:
|
else:
|
||||||
author = (0, message.email_from)
|
author = (0, message.email_from)
|
||||||
partner_ids = []
|
partner_ids = []
|
||||||
for partner in message.notified_partner_ids:
|
if message.subtype_id:
|
||||||
if partner.id in partner_tree:
|
partner_ids = [partner_tree[partner.id] for partner in message.notified_partner_ids
|
||||||
partner_ids.append(partner_tree[partner.id])
|
if partner.id in partner_tree]
|
||||||
|
else:
|
||||||
|
partner_ids = [partner_tree[partner.id] for partner in message.partner_ids
|
||||||
|
if partner.id in partner_tree]
|
||||||
attachment_ids = []
|
attachment_ids = []
|
||||||
for attachment in message.attachment_ids:
|
for attachment in message.attachment_ids:
|
||||||
if attachment.id in attachments_tree:
|
if attachment.id in attachments_tree:
|
||||||
|
@ -766,7 +779,9 @@ class mail_message(osv.Model):
|
||||||
elif not values.get('message_id'):
|
elif not values.get('message_id'):
|
||||||
values['message_id'] = tools.generate_tracking_message_id('private')
|
values['message_id'] = tools.generate_tracking_message_id('private')
|
||||||
newid = super(mail_message, self).create(cr, uid, values, context)
|
newid = super(mail_message, self).create(cr, uid, values, context)
|
||||||
self._notify(cr, uid, newid, context=context)
|
self._notify(cr, uid, newid, context=context,
|
||||||
|
force_send=context.get('mail_notify_force_send', True),
|
||||||
|
user_signature=context.get('mail_notify_user_signature', True))
|
||||||
# TDE FIXME: handle default_starred. Why not setting an inv on starred ?
|
# TDE FIXME: handle default_starred. Why not setting an inv on starred ?
|
||||||
# Because starred will call set_message_starred, that looks for notifications.
|
# Because starred will call set_message_starred, that looks for notifications.
|
||||||
# When creating a new mail_message, it will create a notification to a message
|
# When creating a new mail_message, it will create a notification to a message
|
||||||
|
@ -880,20 +895,16 @@ class mail_message(osv.Model):
|
||||||
return ''
|
return ''
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _notify(self, cr, uid, newid, context=None):
|
def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True):
|
||||||
""" Add the related record followers to the destination partner_ids if is not a private message.
|
""" Add the related record followers to the destination partner_ids if is not a private message.
|
||||||
Call mail_notification.notify to manage the email sending
|
Call mail_notification.notify to manage the email sending
|
||||||
"""
|
"""
|
||||||
notification_obj = self.pool.get('mail.notification')
|
notification_obj = self.pool.get('mail.notification')
|
||||||
message = self.browse(cr, uid, newid, context=context)
|
message = self.browse(cr, uid, newid, context=context)
|
||||||
|
|
||||||
partners_to_notify = set([])
|
partners_to_notify = set([])
|
||||||
# message has no subtype_id: pure log message -> no partners, no one notified
|
|
||||||
if not message.subtype_id:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# all followers of the mail.message document have to be added as partners and notified
|
# all followers of the mail.message document have to be added as partners and notified if a subtype is defined (otherwise: log message)
|
||||||
if message.model and message.res_id:
|
if message.subtype_id and message.model and message.res_id:
|
||||||
fol_obj = self.pool.get("mail.followers")
|
fol_obj = self.pool.get("mail.followers")
|
||||||
# browse as SUPERUSER because rules could restrict the search results
|
# browse as SUPERUSER because rules could restrict the search results
|
||||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
||||||
|
@ -903,7 +914,7 @@ class mail_message(osv.Model):
|
||||||
], context=context)
|
], context=context)
|
||||||
partners_to_notify |= set(fo.partner_id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context))
|
partners_to_notify |= set(fo.partner_id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context))
|
||||||
# remove me from notified partners, unless the message is written on my own wall
|
# remove me from notified partners, unless the message is written on my own wall
|
||||||
if message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
|
if message.subtype_id and message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
|
||||||
partners_to_notify |= set([message.author_id])
|
partners_to_notify |= set([message.author_id])
|
||||||
elif message.author_id:
|
elif message.author_id:
|
||||||
partners_to_notify -= set([message.author_id])
|
partners_to_notify -= set([message.author_id])
|
||||||
|
@ -914,7 +925,8 @@ class mail_message(osv.Model):
|
||||||
|
|
||||||
# notify
|
# notify
|
||||||
if partners_to_notify:
|
if partners_to_notify:
|
||||||
notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context)
|
notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context,
|
||||||
|
force_send=force_send, user_signature=user_signature)
|
||||||
message.refresh()
|
message.refresh()
|
||||||
|
|
||||||
# An error appear when a user receive a notification without notifying
|
# An error appear when a user receive a notification without notifying
|
||||||
|
|
|
@ -30,9 +30,9 @@
|
||||||
<field name="subject"/>
|
<field name="subject"/>
|
||||||
<field name="author_id"/>
|
<field name="author_id"/>
|
||||||
<field name="email_from"/>
|
<field name="email_from"/>
|
||||||
|
<field name="reply_to"/>
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="type"/>
|
<field name="type"/>
|
||||||
<field name="subtype_id"/>
|
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="model"/>
|
<field name="model"/>
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
<field name="parent_id"/>
|
<field name="parent_id"/>
|
||||||
<field name="partner_ids" widget="many2many_tags"/>
|
<field name="partner_ids" widget="many2many_tags"/>
|
||||||
<field name="notified_partner_ids" widget="many2many_tags"/>
|
<field name="notified_partner_ids" widget="many2many_tags"/>
|
||||||
|
<field name="subtype_id"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<field name="body"/>
|
<field name="body"/>
|
||||||
|
|
|
@ -580,7 +580,7 @@ class mail_thread(osv.AbstractModel):
|
||||||
ret_dict = {}
|
ret_dict = {}
|
||||||
for model_name in self.pool.obj_list():
|
for model_name in self.pool.obj_list():
|
||||||
model = self.pool[model_name]
|
model = self.pool[model_name]
|
||||||
if 'mail.thread' in getattr(model, '_inherit', []):
|
if hasattr(model, "message_process") and hasattr(model, "message_post"):
|
||||||
ret_dict[model_name] = model._description
|
ret_dict[model_name] = model._description
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
|
@ -815,6 +815,9 @@ class mail_thread(osv.AbstractModel):
|
||||||
else:
|
else:
|
||||||
assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
|
assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
|
||||||
model_pool = self.pool.get('mail.thread')
|
model_pool = self.pool.get('mail.thread')
|
||||||
|
if not hasattr(model_pool, 'message_post'):
|
||||||
|
context['thread_model'] = model
|
||||||
|
model_pool = self.pool['mail.thread']
|
||||||
new_msg_id = model_pool.message_post(cr, uid, [thread_id], context=context, subtype='mail.mt_comment', **msg)
|
new_msg_id = model_pool.message_post(cr, uid, [thread_id], context=context, subtype='mail.mt_comment', **msg)
|
||||||
|
|
||||||
if partner_ids:
|
if partner_ids:
|
||||||
|
@ -1149,7 +1152,7 @@ class mail_thread(osv.AbstractModel):
|
||||||
model = False
|
model = False
|
||||||
if thread_id:
|
if thread_id:
|
||||||
model = context.get('thread_model', self._name) if self._name == 'mail.thread' else self._name
|
model = context.get('thread_model', self._name) if self._name == 'mail.thread' else self._name
|
||||||
if model != self._name:
|
if model != self._name and hasattr(self.pool[model], 'message_post'):
|
||||||
del context['thread_model']
|
del context['thread_model']
|
||||||
return self.pool[model].message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs)
|
return self.pool[model].message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs)
|
||||||
|
|
||||||
|
@ -1308,7 +1311,10 @@ class mail_thread(osv.AbstractModel):
|
||||||
|
|
||||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||||
""" Add partners to the records followers. """
|
""" Add partners to the records followers. """
|
||||||
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
mail_followers_obj = self.pool.get('mail.followers')
|
||||||
|
subtype_obj = self.pool.get('mail.message.subtype')
|
||||||
|
|
||||||
|
user_pid = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||||
if set(partner_ids) == set([user_pid]):
|
if set(partner_ids) == set([user_pid]):
|
||||||
try:
|
try:
|
||||||
self.check_access_rights(cr, uid, 'read')
|
self.check_access_rights(cr, uid, 'read')
|
||||||
|
@ -1317,27 +1323,35 @@ class mail_thread(osv.AbstractModel):
|
||||||
else:
|
else:
|
||||||
self.check_access_rights(cr, uid, 'write')
|
self.check_access_rights(cr, uid, 'write')
|
||||||
|
|
||||||
# subscribe partners
|
for record in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||||
self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
|
existing_pids = set([f.id for f in record.message_follower_ids
|
||||||
|
if f.id in partner_ids])
|
||||||
|
new_pids = set(partner_ids) - existing_pids
|
||||||
|
|
||||||
# subtype specified: update the subscriptions
|
# subtype_ids specified: update already subscribed partners
|
||||||
fol_obj = self.pool.get('mail.followers')
|
if subtype_ids and existing_pids:
|
||||||
if subtype_ids is not None:
|
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [
|
||||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids), ('partner_id', 'in', partner_ids)], context=context)
|
('res_model', '=', self._name),
|
||||||
fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
('res_id', '=', record.id),
|
||||||
# no subtypes: default ones for new subscription, do not update existing subscriptions
|
('partner_id', 'in', list(existing_pids)),
|
||||||
else:
|
], context=context)
|
||||||
# search new subscriptions: subtype_ids is False
|
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
||||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
|
||||||
('res_model', '=', self._name),
|
else:
|
||||||
('res_id', 'in', ids),
|
subtype_ids = subtype_obj.search(cr, uid, [
|
||||||
('partner_id', 'in', partner_ids),
|
('default', '=', True),
|
||||||
('subtype_ids', '=', False)
|
'|',
|
||||||
], context=context)
|
('res_model', '=', self._name),
|
||||||
if fol_ids:
|
('res_model', '=', False)
|
||||||
subtype_obj = self.pool.get('mail.message.subtype')
|
], context=context)
|
||||||
subtype_ids = subtype_obj.search(cr, uid, [('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
|
# subscribe new followers
|
||||||
fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
for new_pid in new_pids:
|
||||||
|
mail_followers_obj.create(cr, SUPERUSER_ID, {
|
||||||
|
'res_model': self._name,
|
||||||
|
'res_id': record.id,
|
||||||
|
'partner_id': new_pid,
|
||||||
|
'subtype_ids': [(6, 0, subtype_ids)],
|
||||||
|
}, context=context)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,7 @@ openerp.mail = function (session) {
|
||||||
|
|
||||||
//formating and add some fields for render
|
//formating and add some fields for render
|
||||||
this.date = this.date ? session.web.str_to_datetime(this.date) : false;
|
this.date = this.date ? session.web.str_to_datetime(this.date) : false;
|
||||||
|
this.display_date = this.date.toString('ddd MMM dd yyyy HH:mm');
|
||||||
if (this.date && new Date().getTime()-this.date.getTime() < 7*24*60*60*1000) {
|
if (this.date && new Date().getTime()-this.date.getTime() < 7*24*60*60*1000) {
|
||||||
this.timerelative = $.timeago(this.date);
|
this.timerelative = $.timeago(this.date);
|
||||||
}
|
}
|
||||||
|
@ -986,8 +987,8 @@ openerp.mail = function (session) {
|
||||||
expender: function () {
|
expender: function () {
|
||||||
this.$('.oe_msg_body:first').expander({
|
this.$('.oe_msg_body:first').expander({
|
||||||
slicePoint: this.options.truncate_limit,
|
slicePoint: this.options.truncate_limit,
|
||||||
expandText: 'read more',
|
expandText: _t('read more'),
|
||||||
userCollapseText: 'read less',
|
userCollapseText: _t('read less'),
|
||||||
detailClass: 'oe_msg_tail',
|
detailClass: 'oe_msg_tail',
|
||||||
moreClass: 'oe_mail_expand',
|
moreClass: 'oe_mail_expand',
|
||||||
lessClass: 'oe_mail_reduce',
|
lessClass: 'oe_mail_reduce',
|
||||||
|
|
|
@ -281,16 +281,16 @@
|
||||||
<span class='oe_subtle'>•</span>
|
<span class='oe_subtle'>•</span>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
<t t-if="widget.type == 'comment' and ! widget.subtype">
|
<t t-if="widget.type == 'comment' and ! widget.subtype and widget.partner_ids.length == 0">
|
||||||
logged a note
|
logged a note
|
||||||
</t>
|
</t>
|
||||||
<t t-if="(widget.type == 'comment' or widget.type == 'email') and widget.subtype">
|
<t t-if="(widget.type == 'comment' or widget.type == 'email') and (widget.subtype or widget.partner_ids.length > 0)">
|
||||||
to
|
to
|
||||||
<t t-if="widget.partner_ids.length == 0">
|
<t t-if="widget.partner_ids.length == 0">
|
||||||
nobody
|
nobody
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and widget.subtype)"
|
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
|
||||||
t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
|
t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
|
||||||
<span t-attf-class="oe_partner_follower">
|
<span t-attf-class="oe_partner_follower">
|
||||||
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a>
|
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a>
|
||||||
|
@ -305,7 +305,10 @@
|
||||||
notified
|
notified
|
||||||
</t>
|
</t>
|
||||||
<span class='oe_subtle'>•</span>
|
<span class='oe_subtle'>•</span>
|
||||||
<span t-att-title="widget.date"><t t-if="widget.timerelative" t-raw="widget.timerelative"/><t t-if="!widget.timerelative" t-raw="widget.date"/></span>
|
<span t-att-title="widget.date">
|
||||||
|
<t t-if="widget.timerelative" t-raw="widget.timerelative"/>
|
||||||
|
<t t-if="!widget.timerelative" t-raw="widget.display_date"/>
|
||||||
|
</span>
|
||||||
<span t-if="!widget.options.readonly" class='oe_subtle'>•</span>
|
<span t-if="!widget.options.readonly" class='oe_subtle'>•</span>
|
||||||
<t t-if="!widget.options.readonly" t-call="mail.thread.message.vote"/>
|
<t t-if="!widget.options.readonly" t-call="mail.thread.message.vote"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -69,6 +69,7 @@ class TestMailBase(common.TransactionCase):
|
||||||
self.group_employee_id = group_employee_ref and group_employee_ref[1] or False
|
self.group_employee_id = group_employee_ref and group_employee_ref[1] or False
|
||||||
|
|
||||||
# Test users to use through the various tests
|
# Test users to use through the various tests
|
||||||
|
self.res_users.write(cr, uid, uid, {'name': 'Administrator'})
|
||||||
self.user_raoul_id = self.res_users.create(cr, uid,
|
self.user_raoul_id = self.res_users.create(cr, uid,
|
||||||
{'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
|
{'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
|
||||||
self.user_bert_id = self.res_users.create(cr, uid,
|
self.user_bert_id = self.res_users.create(cr, uid,
|
||||||
|
|
|
@ -124,6 +124,102 @@ class TestMailgateway(TestMailBase):
|
||||||
self.assertEqual(partner_info['partner_id'], p_b_id,
|
self.assertEqual(partner_info['partner_id'], p_b_id,
|
||||||
'mail_thread: message_find_partner_from_emails wrong partner found')
|
'mail_thread: message_find_partner_from_emails wrong partner found')
|
||||||
|
|
||||||
|
def test_05_mail_message_mail_mail(self):
|
||||||
|
""" Tests designed for testing email values based on mail.message, aliases, ... """
|
||||||
|
cr, uid, user_raoul_id = self.cr, self.uid, self.user_raoul_id
|
||||||
|
|
||||||
|
# Data: update + generic variables
|
||||||
|
reply_to1 = '_reply_to1@example.com'
|
||||||
|
reply_to2 = '_reply_to2@example.com'
|
||||||
|
email_from1 = 'from@example.com'
|
||||||
|
alias_domain = 'schlouby.fr'
|
||||||
|
raoul_from = 'Raoul Grosbedon <raoul@raoul.fr>'
|
||||||
|
raoul_from_alias = 'Raoul Grosbedon <raoul@schlouby.fr>'
|
||||||
|
raoul_reply = '"Followers of Pigs" <raoul@raoul.fr>'
|
||||||
|
raoul_reply_alias = '"Followers of Pigs" <group+pigs@schlouby.fr>'
|
||||||
|
# Data: remove alias_domain to see emails with alias
|
||||||
|
param_ids = self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.domain')])
|
||||||
|
self.registry('ir.config_parameter').unlink(cr, uid, param_ids)
|
||||||
|
|
||||||
|
# Do: free message; specified values > default values
|
||||||
|
msg_id = self.mail_message.create(cr, user_raoul_id, {'reply_to': reply_to1, 'email_from': email_from1})
|
||||||
|
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||||
|
# Test: message content
|
||||||
|
self.assertIn('reply_to', msg.message_id,
|
||||||
|
'mail_message: message_id should be specific to a mail_message with a given reply_to')
|
||||||
|
self.assertEqual(msg.reply_to, reply_to1,
|
||||||
|
'mail_message: incorrect reply_to: should come from values')
|
||||||
|
self.assertEqual(msg.email_from, email_from1,
|
||||||
|
'mail_message: incorrect email_from: should come from values')
|
||||||
|
# Do: create a mail_mail with the previous mail_message
|
||||||
|
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||||
|
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||||
|
# Test: mail_mail content
|
||||||
|
self.assertEqual(mail.reply_to, reply_to1,
|
||||||
|
'mail_mail: incorrect reply_to: should come from mail.message')
|
||||||
|
self.assertEqual(mail.email_from, email_from1,
|
||||||
|
'mail_mail: incorrect email_from: should come from mail.message')
|
||||||
|
# Do: create a mail_mail with the previous mail_message + specified reply_to
|
||||||
|
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel', 'reply_to': reply_to2})
|
||||||
|
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||||
|
# Test: mail_mail content
|
||||||
|
self.assertEqual(mail.reply_to, reply_to2,
|
||||||
|
'mail_mail: incorrect reply_to: should come from values')
|
||||||
|
self.assertEqual(mail.email_from, email_from1,
|
||||||
|
'mail_mail: incorrect email_from: should come from mail.message')
|
||||||
|
|
||||||
|
# Do: mail_message attached to a document
|
||||||
|
msg_id = self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_pigs_id})
|
||||||
|
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||||
|
# Test: message content
|
||||||
|
self.assertIn('mail.group', msg.message_id,
|
||||||
|
'mail_message: message_id should contain model')
|
||||||
|
self.assertIn('%s' % self.group_pigs_id, msg.message_id,
|
||||||
|
'mail_message: message_id should contain res_id')
|
||||||
|
self.assertFalse(msg.reply_to,
|
||||||
|
'mail_message: incorrect reply_to: should not be generated if not specified')
|
||||||
|
self.assertEqual(msg.email_from, raoul_from,
|
||||||
|
'mail_message: incorrect email_from: should be Raoul')
|
||||||
|
# Do: create a mail_mail based on the previous mail_message
|
||||||
|
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||||
|
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||||
|
# Test: mail_mail content
|
||||||
|
self.assertEqual(mail.reply_to, raoul_reply,
|
||||||
|
'mail_mail: incorrect reply_to: should be Raoul')
|
||||||
|
|
||||||
|
# Data: set catchall domain
|
||||||
|
self.registry('ir.config_parameter').set_param(cr, uid, 'mail.catchall.domain', alias_domain)
|
||||||
|
|
||||||
|
# Update message
|
||||||
|
self.mail_message.write(cr, user_raoul_id, [msg_id], {'email_from': False, 'reply_to': False})
|
||||||
|
msg.refresh()
|
||||||
|
# Do: create a mail_mail based on the previous mail_message
|
||||||
|
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||||
|
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||||
|
# Test: mail_mail content
|
||||||
|
self.assertEqual(mail.reply_to, raoul_reply_alias,
|
||||||
|
'mail_mail: incorrect reply_to: should be Pigs alias')
|
||||||
|
|
||||||
|
# Update message: test alias on email_from
|
||||||
|
msg_id = self.mail_message.create(cr, user_raoul_id, {})
|
||||||
|
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||||
|
# Do: create a mail_mail based on the previous mail_message
|
||||||
|
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||||
|
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||||
|
# Test: mail_mail content
|
||||||
|
self.assertEqual(mail.reply_to, raoul_from_alias,
|
||||||
|
'mail_mail: incorrect reply_to: should be message email_from using Raoul alias')
|
||||||
|
|
||||||
|
# Update message
|
||||||
|
self.mail_message.write(cr, user_raoul_id, [msg_id], {'res_id': False, 'email_from': 'someone@schlouby.fr', 'reply_to': False})
|
||||||
|
msg.refresh()
|
||||||
|
# Do: create a mail_mail based on the previous mail_message
|
||||||
|
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||||
|
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||||
|
# Test: mail_mail content
|
||||||
|
self.assertEqual(mail.reply_to, msg.email_from,
|
||||||
|
'mail_mail: incorrect reply_to: should be message email_from')
|
||||||
|
|
||||||
def test_05_mail_message_mail_mail(self):
|
def test_05_mail_message_mail_mail(self):
|
||||||
""" Tests designed for testing email values based on mail.message, aliases, ... """
|
""" Tests designed for testing email values based on mail.message, aliases, ... """
|
||||||
cr, uid = self.cr, self.uid
|
cr, uid = self.cr, self.uid
|
||||||
|
|
|
@ -126,7 +126,6 @@ class mail_compose_message(osv.TransientModel):
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'composition_mode': 'comment',
|
'composition_mode': 'comment',
|
||||||
'email_from': lambda self, cr, uid, ctx={}: self.pool.get('mail.mail')._get_default_from(cr, uid, context=ctx),
|
|
||||||
'body': lambda self, cr, uid, ctx={}: '',
|
'body': lambda self, cr, uid, ctx={}: '',
|
||||||
'subject': lambda self, cr, uid, ctx={}: False,
|
'subject': lambda self, cr, uid, ctx={}: False,
|
||||||
'partner_ids': lambda self, cr, uid, ctx={}: [],
|
'partner_ids': lambda self, cr, uid, ctx={}: [],
|
||||||
|
@ -158,7 +157,7 @@ class mail_compose_message(osv.TransientModel):
|
||||||
|
|
||||||
return super(mail_compose_message, self).check_access_rule(cr, uid, ids, operation, context=context)
|
return super(mail_compose_message, self).check_access_rule(cr, uid, ids, operation, context=context)
|
||||||
|
|
||||||
def _notify(self, cr, uid, newid, context=None):
|
def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True):
|
||||||
""" Override specific notify method of mail.message, because we do
|
""" Override specific notify method of mail.message, because we do
|
||||||
not want that feature in the wizard. """
|
not want that feature in the wizard. """
|
||||||
return
|
return
|
||||||
|
@ -235,6 +234,9 @@ class mail_compose_message(osv.TransientModel):
|
||||||
for wizard in self.browse(cr, uid, ids, context=context):
|
for wizard in self.browse(cr, uid, ids, context=context):
|
||||||
mass_mail_mode = wizard.composition_mode == 'mass_mail'
|
mass_mail_mode = wizard.composition_mode == 'mass_mail'
|
||||||
active_model_pool = self.pool[wizard.model if wizard.model else 'mail.thread']
|
active_model_pool = self.pool[wizard.model if wizard.model else 'mail.thread']
|
||||||
|
if not hasattr(active_model_pool, 'message_post'):
|
||||||
|
context['thread_model'] = wizard.model
|
||||||
|
active_model_pool = self.pool['mail.thread']
|
||||||
|
|
||||||
# wizard works in batch mode: [res_id] or active_ids
|
# wizard works in batch mode: [res_id] or active_ids
|
||||||
res_ids = active_ids if mass_mail_mode and wizard.model and active_ids else [wizard.res_id]
|
res_ids = active_ids if mass_mail_mode and wizard.model and active_ids else [wizard.res_id]
|
||||||
|
@ -257,13 +259,15 @@ class mail_compose_message(osv.TransientModel):
|
||||||
new_attach_id = ir_attachment_obj.copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context)
|
new_attach_id = ir_attachment_obj.copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context)
|
||||||
attachment_ids.append(new_attach_id)
|
attachment_ids.append(new_attach_id)
|
||||||
post_values['attachment_ids'] = attachment_ids
|
post_values['attachment_ids'] = attachment_ids
|
||||||
post_values.update(email_dict)
|
|
||||||
# email_from: mass mailing only can specify another email_from
|
# email_from: mass mailing only can specify another email_from
|
||||||
if email_dict.get('email_from'):
|
if email_dict.get('email_from'):
|
||||||
post_values['email_from'] = email_dict.pop('email_from')
|
post_values['email_from'] = email_dict.pop('email_from')
|
||||||
# replies redirection: mass mailing only
|
# replies redirection: mass mailing only
|
||||||
if not wizard.same_thread:
|
if not wizard.same_thread:
|
||||||
post_values['reply_to'] = email_dict.pop('reply_to')
|
post_values['reply_to'] = email_dict.pop('reply_to')
|
||||||
|
else:
|
||||||
|
email_dict.pop('reply_to')
|
||||||
|
post_values.update(email_dict)
|
||||||
# clean the context (hint: mass mailing sets some default values that
|
# clean the context (hint: mass mailing sets some default values that
|
||||||
# could be wrongly interpreted by mail_mail)
|
# could be wrongly interpreted by mail_mail)
|
||||||
context.pop('default_email_to', None)
|
context.pop('default_email_to', None)
|
||||||
|
@ -280,11 +284,10 @@ class mail_compose_message(osv.TransientModel):
|
||||||
elif mass_mail_mode: # mass mail: is a log pushed to recipients unless specified, author not added
|
elif mass_mail_mode: # mass mail: is a log pushed to recipients unless specified, author not added
|
||||||
if not wizard.notify:
|
if not wizard.notify:
|
||||||
subtype = False
|
subtype = False
|
||||||
context = dict(context, mail_create_nosubscribe=True) # add context key to avoid subscribing the author
|
context = dict(context,
|
||||||
msg_id = active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values)
|
mail_notify_force_send=False, # do not send emails directly but use the queue instead
|
||||||
# mass_mailing, post without notify: notify specific partners
|
mail_create_nosubscribe=True) # add context key to avoid subscribing the author
|
||||||
if mass_mail_mode and not wizard.notify and post_values['partner_ids']:
|
active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values)
|
||||||
self.pool.get('mail.notification')._notify(cr, uid, msg_id, post_values['partner_ids'], context=context)
|
|
||||||
|
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
return {'type': 'ir.actions.act_window_close'}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
// hide()s
|
// hide()s
|
||||||
|
|
||||||
function openerp_pos_screens(instance, module){ //module is instance.point_of_sale
|
function openerp_pos_screens(instance, module){ //module is instance.point_of_sale
|
||||||
var QWeb = instance.web.qweb;
|
var QWeb = instance.web.qweb,
|
||||||
|
_t = instance.web._t;
|
||||||
|
|
||||||
module.ScreenSelector = instance.web.Class.extend({
|
module.ScreenSelector = instance.web.Class.extend({
|
||||||
init: function(options){
|
init: function(options){
|
||||||
|
@ -264,7 +265,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
// we add the help button by default. we do this because the buttons are cleared on each refresh so that
|
// we add the help button by default. we do this because the buttons are cleared on each refresh so that
|
||||||
// the button stay local to each screen
|
// the button stay local to each screen
|
||||||
this.pos_widget.left_action_bar.add_new_button({
|
this.pos_widget.left_action_bar.add_new_button({
|
||||||
label: 'help',
|
label: _t('Help'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
||||||
click: function(){ self.help_button_action(); },
|
click: function(){ self.help_button_action(); },
|
||||||
});
|
});
|
||||||
|
@ -454,7 +455,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
},500);
|
},500);
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'back',
|
label: _t('Back'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
clearInterval(this.intervalID);
|
clearInterval(this.intervalID);
|
||||||
|
@ -483,7 +484,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
|
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'back',
|
label: _t('Back'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||||
|
@ -491,7 +492,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
});
|
});
|
||||||
|
|
||||||
this.validate_button = this.add_action_button({
|
this.validate_button = this.add_action_button({
|
||||||
label: 'Validate',
|
label: _t('Validate'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
self.order_product();
|
self.order_product();
|
||||||
|
@ -674,7 +675,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
}
|
}
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'back',
|
label: _t('Back'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
self.queue.schedule(self.cancel);
|
self.queue.schedule(self.cancel);
|
||||||
|
@ -714,7 +715,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'help',
|
label: _t('Help'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
$('.goodbye-message').css({opacity:1}).hide();
|
$('.goodbye-message').css({opacity:1}).hide();
|
||||||
|
@ -768,7 +769,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
|
|
||||||
if(this.pos_widget.screen_selector.current_mode === 'client'){
|
if(this.pos_widget.screen_selector.current_mode === 'client'){
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'pay',
|
label: _t('Pay'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.client_next_screen);
|
self.pos_widget.screen_selector.set_current_screen(self.client_next_screen);
|
||||||
|
@ -808,13 +809,13 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'Print',
|
label: _t('Print'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/printer.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/printer.png',
|
||||||
click: function(){ self.print(); },
|
click: function(){ self.print(); },
|
||||||
});
|
});
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: 'Next Order',
|
label: _t('Next Order'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
||||||
click: function() { self.finishOrder(); },
|
click: function() { self.finishOrder(); },
|
||||||
});
|
});
|
||||||
|
@ -870,7 +871,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
this.set_numpad_state(this.pos_widget.numpad.state);
|
this.set_numpad_state(this.pos_widget.numpad.state);
|
||||||
|
|
||||||
this.back_button = this.add_action_button({
|
this.back_button = this.add_action_button({
|
||||||
label: 'Back',
|
label: _t('Back'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.back_screen);
|
self.pos_widget.screen_selector.set_current_screen(self.back_screen);
|
||||||
|
@ -878,7 +879,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
});
|
});
|
||||||
|
|
||||||
this.validate_button = this.add_action_button({
|
this.validate_button = this.add_action_button({
|
||||||
label: 'Validate',
|
label: _t('Validate'),
|
||||||
name: 'validation',
|
name: 'validation',
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
function openerp_pos_widgets(instance, module){ //module is instance.point_of_sale
|
function openerp_pos_widgets(instance, module){ //module is instance.point_of_sale
|
||||||
var QWeb = instance.web.qweb;
|
var QWeb = instance.web.qweb,
|
||||||
|
_t = instance.web._t;
|
||||||
|
|
||||||
// The ImageCache is used to hide the latency of the application cache on-disk access in chrome
|
// The ImageCache is used to hide the latency of the application cache on-disk access in chrome
|
||||||
// that causes annoying flickering on product pictures. Why the hell a simple access to
|
// that causes annoying flickering on product pictures. Why the hell a simple access to
|
||||||
|
@ -980,13 +981,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||||
this.onscreen_keyboard.appendTo($(".point-of-sale #content"));
|
this.onscreen_keyboard.appendTo($(".point-of-sale #content"));
|
||||||
|
|
||||||
this.close_button = new module.HeaderButtonWidget(this,{
|
this.close_button = new module.HeaderButtonWidget(this,{
|
||||||
label:'Close',
|
label: _t('Close'),
|
||||||
action: function(){ self.try_close(); },
|
action: function(){ self.try_close(); },
|
||||||
});
|
});
|
||||||
this.close_button.appendTo(this.$('#rightheader'));
|
this.close_button.appendTo(this.$('#rightheader'));
|
||||||
|
|
||||||
this.client_button = new module.HeaderButtonWidget(this,{
|
this.client_button = new module.HeaderButtonWidget(this,{
|
||||||
label:'Self-Checkout',
|
label: _t('Self-Checkout'),
|
||||||
action: function(){ self.screen_selector.set_user_mode('client'); },
|
action: function(){ self.screen_selector.set_user_mode('client'); },
|
||||||
});
|
});
|
||||||
this.client_button.appendTo(this.$('#rightheader'));
|
this.client_button.appendTo(this.$('#rightheader'));
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<field name="model">hr.employee</field>
|
<field name="model">hr.employee</field>
|
||||||
<field name="inherit_id" eval="False"/>
|
<field name="inherit_id" eval="False"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<kanban>
|
<kanban create="false">
|
||||||
<field name="last_login"/>
|
<field name="last_login"/>
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kanban-box">
|
<t t-name="kanban-box">
|
||||||
|
|
|
@ -256,7 +256,7 @@
|
||||||
<field name="search_view_id" ref="warehouse_orderpoint_search" />
|
<field name="search_view_id" ref="warehouse_orderpoint_search" />
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="oe_view_nocontent_create">
|
<p class="oe_view_nocontent_create">
|
||||||
Click to add a reordering rules.
|
Click to add a reordering rule.
|
||||||
</p><p>You can define your minimum stock rules, so that OpenERP will automatically create draft manufacturing orders or request for quotations according to the stock level. Once the virtual stock of a product (= stock on hand minus all confirmed orders and reservations) is below the minimum quantity, OpenERP will generate a procurement request to increase the stock up to the maximum quantity.</p>
|
</p><p>You can define your minimum stock rules, so that OpenERP will automatically create draft manufacturing orders or request for quotations according to the stock level. Once the virtual stock of a product (= stock on hand minus all confirmed orders and reservations) is below the minimum quantity, OpenERP will generate a procurement request to increase the stock up to the maximum quantity.</p>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Procurement Request" version="7.0">
|
<form string="Procurement Request" version="7.0">
|
||||||
<p class="oe_gray">
|
<p class="oe_gray">
|
||||||
Fill is this for to launch a procurement request for this
|
Use this assistant to generate a procurement request for this
|
||||||
product. According to the product configuration, this may
|
product. According to the product configuration, this may
|
||||||
trigger a draft purchase order, a manufacturing order or
|
trigger a draft purchase order, a manufacturing order or
|
||||||
a new task.
|
a new task.
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<page string="Sales & Purchases" position="inside">
|
<page string="Sales & Purchases" position="inside">
|
||||||
<group>
|
<group>
|
||||||
<group name="pricelists" groups="product.group_sale_pricelist" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
|
<group name="pricelists" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
|
||||||
<field name="property_product_pricelist"/>
|
<field name="property_product_pricelist" groups="product.group_sale_pricelist"/>
|
||||||
</group>
|
</group>
|
||||||
<div name="parent_pricelists" groups="product.group_sale_pricelist" attrs="{'invisible': ['|',('is_company','=',True),('parent_id','=',False)]}">
|
<div name="parent_pricelists" groups="product.group_sale_pricelist" attrs="{'invisible': ['|',('is_company','=',True),('parent_id','=',False)]}">
|
||||||
<p>Pricelists are managed on <button name="open_commercial_entity" type="object" string="the parent company" class="oe_link"/></p>
|
<p>Pricelists are managed on <button name="open_commercial_entity" type="object" string="the parent company" class="oe_link"/></p>
|
||||||
|
|
|
@ -60,6 +60,8 @@
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:param name="pmaxChars" as="xs:integer" select="80"/>
|
||||||
|
|
||||||
<xsl:template match="lot-line" mode="story">
|
<xsl:template match="lot-line" mode="story">
|
||||||
<blockTable style="mytable" colWidths="2.8cm,5.4cm">
|
<blockTable style="mytable" colWidths="2.8cm,5.4cm">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -75,7 +77,7 @@
|
||||||
<barCode><xsl:value-of select="ean13" /></barCode>
|
<barCode><xsl:value-of select="ean13" /></barCode>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="nospace"><xsl:value-of select="product"/></para><xsl:text>, </xsl:text>
|
<para style="nospace"><xsl:value-of select="substring(product, 1, pmaxChars)"/></para><xsl:text>, </xsl:text>
|
||||||
<para style="nospace"><xsl:value-of select="variant"/></para>
|
<para style="nospace"><xsl:value-of select="variant"/></para>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -98,10 +98,10 @@ class sale_order_line(osv.osv):
|
||||||
class account_invoice_line(osv.osv):
|
class account_invoice_line(osv.osv):
|
||||||
_inherit = "account.invoice.line"
|
_inherit = "account.invoice.line"
|
||||||
|
|
||||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||||
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit,currency_id, context=context, company_id=company_id)
|
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit,currency_id, context=context, company_id=company_id)
|
||||||
|
|
||||||
def get_real_price(res_dict, product_id, qty, uom, pricelist):
|
def get_real_price(res_dict, product_id, qty, uom_id, pricelist):
|
||||||
item_obj = self.pool.get('product.pricelist.item')
|
item_obj = self.pool.get('product.pricelist.item')
|
||||||
price_type_obj = self.pool.get('product.price.type')
|
price_type_obj = self.pool.get('product.price.type')
|
||||||
product_obj = self.pool.get('product.product')
|
product_obj = self.pool.get('product.product')
|
||||||
|
@ -119,7 +119,7 @@ class account_invoice_line(osv.osv):
|
||||||
product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)
|
product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)
|
||||||
|
|
||||||
factor = 1.0
|
factor = 1.0
|
||||||
if uom and uom != product.uom_id.id:
|
if uom_id and uom_id != product.uom_id.id:
|
||||||
product_uom_obj = self.pool.get('product.uom')
|
product_uom_obj = self.pool.get('product.uom')
|
||||||
uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id)
|
uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id)
|
||||||
factor = uom_data.factor
|
factor = uom_data.factor
|
||||||
|
@ -137,18 +137,18 @@ class account_invoice_line(osv.osv):
|
||||||
pricelist =partner_obj.browse(cr, uid, partner_id).property_product_pricelist_purchase.id
|
pricelist =partner_obj.browse(cr, uid, partner_id).property_product_pricelist_purchase.id
|
||||||
if not pricelist:
|
if not pricelist:
|
||||||
raise osv.except_osv(_('No Purchase Pricelist Found!'),_("You must first define a pricelist on the supplier form!"))
|
raise osv.except_osv(_('No Purchase Pricelist Found!'),_("You must first define a pricelist on the supplier form!"))
|
||||||
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom})
|
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom_id})
|
||||||
price_unit = price_unit_res[pricelist]
|
price_unit = price_unit_res[pricelist]
|
||||||
real_price = get_real_price(price_unit_res, product.id, qty, uom, pricelist)
|
real_price = get_real_price(price_unit_res, product.id, qty, uom_id, pricelist)
|
||||||
else:
|
else:
|
||||||
if partner_id:
|
if partner_id:
|
||||||
pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id
|
pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id
|
||||||
if not pricelist:
|
if not pricelist:
|
||||||
raise osv.except_osv(_('No Sale Pricelist Found!'),_("You must first define a pricelist on the customer form!"))
|
raise osv.except_osv(_('No Sale Pricelist Found!'),_("You must first define a pricelist on the customer form!"))
|
||||||
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom})
|
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom_id})
|
||||||
price_unit = price_unit_res[pricelist]
|
price_unit = price_unit_res[pricelist]
|
||||||
|
|
||||||
real_price = get_real_price(price_unit_res, product.id, qty, uom, pricelist)
|
real_price = get_real_price(price_unit_res, product.id, qty, uom_id, pricelist)
|
||||||
if pricelist:
|
if pricelist:
|
||||||
pricelists=pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
|
pricelists=pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
|
||||||
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and real_price != 0):
|
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and real_price != 0):
|
||||||
|
|
|
@ -29,6 +29,14 @@ class res_partner(osv.osv):
|
||||||
'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'),
|
'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def copy(self, cr, uid, record_id, default=None, context=None):
|
||||||
|
if default is None:
|
||||||
|
default = {}
|
||||||
|
|
||||||
|
default['task_ids'] = []
|
||||||
|
return super(res_partner, self).copy(
|
||||||
|
cr, uid, record_id, default=default, context=context)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<field name="priority">36</field>
|
<field name="priority">36</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="property_product_pricelist" position="after">
|
<field name="property_product_pricelist" position="after">
|
||||||
<field name="property_product_pricelist_purchase" />
|
<field name="property_product_pricelist_purchase" groups="product.group_purchase_pricelist"/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -65,7 +65,9 @@
|
||||||
<field name="context">{"default_type": "in", "contact_display": "partner_address", "search_default_done": 1, "search_default_to_invoice": 1}</field>
|
<field name="context">{"default_type": "in", "contact_display": "partner_address", "search_default_done": 1, "search_default_to_invoice": 1}</field>
|
||||||
<field name="search_view_id" ref="stock.view_picking_in_search"/>
|
<field name="search_view_id" ref="stock.view_picking_in_search"/>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p>
|
<p class="oe_view_nocontent_create">
|
||||||
|
Click to create a new incoming shipment.
|
||||||
|
</p><p>
|
||||||
Here you can track all the product receptions of purchase
|
Here you can track all the product receptions of purchase
|
||||||
orders where the invoicing is "Based on Incoming Shipments",
|
orders where the invoicing is "Based on Incoming Shipments",
|
||||||
and for which you have not received a supplier invoice yet.
|
and for which you have not received a supplier invoice yet.
|
||||||
|
|
|
@ -242,8 +242,13 @@ class WebKitParser(report_sxw):
|
||||||
def translate_call(self, src):
|
def translate_call(self, src):
|
||||||
"""Translate String."""
|
"""Translate String."""
|
||||||
ir_translation = self.pool['ir.translation']
|
ir_translation = self.pool['ir.translation']
|
||||||
|
name = self.tmpl and 'addons/' + self.tmpl or None
|
||||||
res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid,
|
res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid,
|
||||||
None, 'report', self.parser_instance.localcontext.get('lang', 'en_US'), src)
|
name, 'report', self.parser_instance.localcontext.get('lang', 'en_US'), src)
|
||||||
|
if res == src:
|
||||||
|
# no translation defined, fallback on None (backward compatibility)
|
||||||
|
res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid,
|
||||||
|
None, 'report', self.parser_instance.localcontext.get('lang', 'en_US'), src)
|
||||||
if not res :
|
if not res :
|
||||||
return src
|
return src
|
||||||
return res
|
return res
|
||||||
|
|
|
@ -90,7 +90,11 @@
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="view_id" eval="False"/>
|
<field name="view_id" eval="False"/>
|
||||||
<field name="search_view_id" ref="view_resource_calendar_search"/>
|
<field name="search_view_id" ref="view_resource_calendar_search"/>
|
||||||
<field name="help">Define working hours and time table that could be scheduled to your project members</field>
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Define working hours and time table that could be scheduled to your project members
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_resource_calendar_attendance_tree" model="ir.ui.view">
|
<record id="view_resource_calendar_attendance_tree" model="ir.ui.view">
|
||||||
|
|
|
@ -78,11 +78,13 @@ class crm_make_sale(osv.osv_memory):
|
||||||
['default', 'invoice', 'delivery', 'contact'])
|
['default', 'invoice', 'delivery', 'contact'])
|
||||||
pricelist = partner.property_product_pricelist.id
|
pricelist = partner.property_product_pricelist.id
|
||||||
fpos = partner.property_account_position and partner.property_account_position.id or False
|
fpos = partner.property_account_position and partner.property_account_position.id or False
|
||||||
|
payment_term = partner.property_payment_term and partner.property_payment_term.id or False
|
||||||
new_ids = []
|
new_ids = []
|
||||||
for case in case_obj.browse(cr, uid, data, context=context):
|
for case in case_obj.browse(cr, uid, data, context=context):
|
||||||
if not partner and case.partner_id:
|
if not partner and case.partner_id:
|
||||||
partner = case.partner_id
|
partner = case.partner_id
|
||||||
fpos = partner.property_account_position and partner.property_account_position.id or False
|
fpos = partner.property_account_position and partner.property_account_position.id or False
|
||||||
|
payment_term = partner.property_payment_term and partner.property_payment_term.id or False
|
||||||
partner_addr = partner_obj.address_get(cr, uid, [partner.id],
|
partner_addr = partner_obj.address_get(cr, uid, [partner.id],
|
||||||
['default', 'invoice', 'delivery', 'contact'])
|
['default', 'invoice', 'delivery', 'contact'])
|
||||||
pricelist = partner.property_product_pricelist.id
|
pricelist = partner.property_product_pricelist.id
|
||||||
|
@ -100,6 +102,7 @@ class crm_make_sale(osv.osv_memory):
|
||||||
'partner_shipping_id': partner_addr['delivery'],
|
'partner_shipping_id': partner_addr['delivery'],
|
||||||
'date_order': fields.date.context_today(self,cr,uid,context=context),
|
'date_order': fields.date.context_today(self,cr,uid,context=context),
|
||||||
'fiscal_position': fpos,
|
'fiscal_position': fpos,
|
||||||
|
'payment_term':payment_term,
|
||||||
}
|
}
|
||||||
if partner.id:
|
if partner.id:
|
||||||
vals['user_id'] = partner.user_id and partner.user_id.id or uid
|
vals['user_id'] = partner.user_id and partner.user_id.id or uid
|
||||||
|
|
|
@ -587,9 +587,6 @@ class sale_order_line(osv.osv):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
#update of result obtained in super function
|
#update of result obtained in super function
|
||||||
res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
|
|
||||||
res['value'].update(res_packing.get('value', {}))
|
|
||||||
warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or ''
|
|
||||||
product_obj = product_obj.browse(cr, uid, product, context=context)
|
product_obj = product_obj.browse(cr, uid, product, context=context)
|
||||||
res['value']['delay'] = (product_obj.sale_delay or 0.0)
|
res['value']['delay'] = (product_obj.sale_delay or 0.0)
|
||||||
res['value']['type'] = product_obj.procure_method
|
res['value']['type'] = product_obj.procure_method
|
||||||
|
@ -602,6 +599,11 @@ class sale_order_line(osv.osv):
|
||||||
uom = False
|
uom = False
|
||||||
if not uom2:
|
if not uom2:
|
||||||
uom2 = product_obj.uom_id
|
uom2 = product_obj.uom_id
|
||||||
|
|
||||||
|
# Calling product_packaging_change function after updating UoM
|
||||||
|
res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
|
||||||
|
res['value'].update(res_packing.get('value', {}))
|
||||||
|
warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or ''
|
||||||
compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding)
|
compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding)
|
||||||
if (product_obj.type=='product') and int(compare_qty) == -1 \
|
if (product_obj.type=='product') and int(compare_qty) == -1 \
|
||||||
and (product_obj.procure_method=='make_to_stock'):
|
and (product_obj.procure_method=='make_to_stock'):
|
||||||
|
|
|
@ -14,7 +14,7 @@ openerp.share = function(session) {
|
||||||
else rec_name = '';
|
else rec_name = '';
|
||||||
session.web.pyeval.eval_domains_and_contexts({
|
session.web.pyeval.eval_domains_and_contexts({
|
||||||
domains: [domain],
|
domains: [domain],
|
||||||
contexts: [view.dataset.context]
|
contexts: [Share.get_context()]
|
||||||
}).done(function (result) {
|
}).done(function (result) {
|
||||||
Share.create({
|
Share.create({
|
||||||
name: action.name,
|
name: action.name,
|
||||||
|
@ -25,7 +25,7 @@ openerp.share = function(session) {
|
||||||
view_type: view.fields_view.type,
|
view_type: view.fields_view.type,
|
||||||
invite: invite || false,
|
invite: invite || false,
|
||||||
}).done(function(share_id) {
|
}).done(function(share_id) {
|
||||||
var step1 = Share.call('go_step_1', [[share_id]]).done(function(result) {
|
var step1 = Share.call('go_step_1', [[share_id], Share.get_context()]).done(function(result) {
|
||||||
var action = result;
|
var action = result;
|
||||||
self.do_action(action);
|
self.do_action(action);
|
||||||
});
|
});
|
||||||
|
|
|
@ -258,7 +258,9 @@
|
||||||
<para style="terp_default_Centre_9">[[ (move_lines.prodlot_id and move_lines.prodlot_id.name) or '' ]]</para>
|
<para style="terp_default_Centre_9">[[ (move_lines.prodlot_id and move_lines.prodlot_id.name) or '' ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_9">[[ move_lines.state ]]</para>
|
<para style="terp_default_9">Waiting Availability[[ move_lines.state == 'confirmed' and ' ' or removeParentNode('para') ]]</para>
|
||||||
|
<para style="terp_default_9">Done[[ move_lines.state == 'done' and ' ' or removeParentNode('para') ]]</para>
|
||||||
|
<para style="terp_default_9">Available[[ move_lines.state == 'assigned' and ' ' or removeParentNode('para') ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9">[[ (move_lines.location_id and move_lines.location_id.name) or '' ]] </para>
|
<para style="terp_default_Right_9">[[ (move_lines.location_id and move_lines.location_id.name) or '' ]] </para>
|
||||||
|
|
|
@ -1637,7 +1637,7 @@ class stock_move(osv.osv):
|
||||||
"* Waiting Availability: This state is reached when the procurement resolution is not straight forward. It may need the scheduler to run, a component to me manufactured...\n"\
|
"* Waiting Availability: This state is reached when the procurement resolution is not straight forward. It may need the scheduler to run, a component to me manufactured...\n"\
|
||||||
"* Available: When products are reserved, it is set to \'Available\'.\n"\
|
"* Available: When products are reserved, it is set to \'Available\'.\n"\
|
||||||
"* Done: When the shipment is processed, the state is \'Done\'."),
|
"* Done: When the shipment is processed, the state is \'Done\'."),
|
||||||
'price_unit': fields.float('Unit Price', digits_compute= dp.get_precision('Account'), help="Technical field used to record the product cost set by the user during a picking confirmation (when average price costing method is used)"),
|
'price_unit': fields.float('Unit Price', digits_compute= dp.get_precision('Product Price'), help="Technical field used to record the product cost set by the user during a picking confirmation (when average price costing method is used)"),
|
||||||
'price_currency_id': fields.many2one('res.currency', 'Currency for average price', help="Technical field used to record the currency chosen by the user during a picking confirmation (when average price costing method is used)"),
|
'price_currency_id': fields.many2one('res.currency', 'Currency for average price', help="Technical field used to record the currency chosen by the user during a picking confirmation (when average price costing method is used)"),
|
||||||
'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
|
'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
|
||||||
'backorder_id': fields.related('picking_id','backorder_id',type='many2one', relation="stock.picking", string="Back Order of", select=True),
|
'backorder_id': fields.related('picking_id','backorder_id',type='many2one', relation="stock.picking", string="Back Order of", select=True),
|
||||||
|
@ -2192,7 +2192,7 @@ class stock_move(osv.osv):
|
||||||
if move.picking_id:
|
if move.picking_id:
|
||||||
pickings.add(move.picking_id.id)
|
pickings.add(move.picking_id.id)
|
||||||
if move.move_dest_id and move.move_dest_id.state == 'waiting':
|
if move.move_dest_id and move.move_dest_id.state == 'waiting':
|
||||||
self.write(cr, uid, [move.move_dest_id.id], {'state': 'assigned'})
|
self.write(cr, uid, [move.move_dest_id.id], {'state': 'confirmed'})
|
||||||
if context.get('call_unlink',False) and move.move_dest_id.picking_id:
|
if context.get('call_unlink',False) and move.move_dest_id.picking_id:
|
||||||
wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr)
|
wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr)
|
||||||
self.write(cr, uid, ids, {'state': 'cancel', 'move_dest_id': False})
|
self.write(cr, uid, ids, {'state': 'cancel', 'move_dest_id': False})
|
||||||
|
@ -2412,8 +2412,8 @@ class stock_move(osv.osv):
|
||||||
# or if it's the same as that of the secondary amount being posted.
|
# or if it's the same as that of the secondary amount being posted.
|
||||||
account_obj = self.pool.get('account.account')
|
account_obj = self.pool.get('account.account')
|
||||||
src_acct, dest_acct = account_obj.browse(cr, uid, [src_account_id, dest_account_id], context=context)
|
src_acct, dest_acct = account_obj.browse(cr, uid, [src_account_id, dest_account_id], context=context)
|
||||||
src_main_currency_id = src_acct.currency_id and src_acct.currency_id.id or src_acct.company_id.currency_id.id
|
src_main_currency_id = src_acct.company_id.currency_id.id
|
||||||
dest_main_currency_id = dest_acct.currency_id and dest_acct.currency_id.id or dest_acct.company_id.currency_id.id
|
dest_main_currency_id = dest_acct.company_id.currency_id.id
|
||||||
cur_obj = self.pool.get('res.currency')
|
cur_obj = self.pool.get('res.currency')
|
||||||
if reference_currency_id != src_main_currency_id:
|
if reference_currency_id != src_main_currency_id:
|
||||||
# fix credit line:
|
# fix credit line:
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields, osv
|
||||||
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
|
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
|
||||||
import time
|
import time
|
||||||
|
from openerp.tools.translate import _
|
||||||
|
|
||||||
class stock_partial_move_line(osv.osv_memory):
|
class stock_partial_move_line(osv.osv_memory):
|
||||||
_inherit = "stock.partial.picking.line"
|
_inherit = "stock.partial.picking.line"
|
||||||
|
@ -67,6 +68,8 @@ class stock_partial_move(osv.osv_memory):
|
||||||
}
|
}
|
||||||
moves_ids = []
|
moves_ids = []
|
||||||
for move in partial.move_ids:
|
for move in partial.move_ids:
|
||||||
|
if not move.move_id:
|
||||||
|
raise osv.except_osv(_('Warning !'), _("You have manually created product lines, please delete them to proceed"))
|
||||||
move_id = move.move_id.id
|
move_id = move.move_id.id
|
||||||
partial_data['move%s' % (move_id)] = {
|
partial_data['move%s' % (move_id)] = {
|
||||||
'product_id': move.product_id.id,
|
'product_id': move.product_id.id,
|
||||||
|
|
|
@ -180,6 +180,8 @@ class stock_return_picking(osv.osv_memory):
|
||||||
for v in val_id:
|
for v in val_id:
|
||||||
data_get = data_obj.browse(cr, uid, v, context=context)
|
data_get = data_obj.browse(cr, uid, v, context=context)
|
||||||
mov_id = data_get.move_id.id
|
mov_id = data_get.move_id.id
|
||||||
|
if not mov_id:
|
||||||
|
raise osv.except_osv(_('Warning !'), _("You have manually created product lines, please delete them to proceed"))
|
||||||
new_qty = data_get.quantity
|
new_qty = data_get.quantity
|
||||||
move = move_obj.browse(cr, uid, mov_id, context=context)
|
move = move_obj.browse(cr, uid, mov_id, context=context)
|
||||||
new_location = move.location_dest_id.id
|
new_location = move.location_dest_id.id
|
||||||
|
|
|
@ -498,7 +498,7 @@ class survey_question(osv.osv):
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
minimum_ans = 0
|
minimum_ans = 0
|
||||||
maximum_ans = 0
|
maximum_ans = 0
|
||||||
page = self.pool.get('survey.page').browse(cr, uid, vals['page_id'], context=context).title
|
page = self.pool.get('survey.page').browse(cr, uid, int(vals.get('page_id', 0)), context=context).title
|
||||||
if vals.has_key('answer_choice_ids') and not len(vals['answer_choice_ids']):
|
if vals.has_key('answer_choice_ids') and not len(vals['answer_choice_ids']):
|
||||||
if vals.has_key('type') and vals['type'] not in ['descriptive_text', 'single_textbox', 'comment','table']:
|
if vals.has_key('type') and vals['type'] not in ['descriptive_text', 'single_textbox', 'comment','table']:
|
||||||
raise osv.except_osv(_('Warning!'),_('You must enter one or more answers for question "%s" of page %s .') % (vals['question'], page))
|
raise osv.except_osv(_('Warning!'),_('You must enter one or more answers for question "%s" of page %s .') % (vals['question'], page))
|
||||||
|
|
|
@ -772,6 +772,7 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Survey Question">
|
<form string="Survey Question">
|
||||||
<field name="question" colspan="4"/>
|
<field name="question" colspan="4"/>
|
||||||
|
<field name="page_id"/>
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="tot_resp"/>
|
<field name="tot_resp"/>
|
||||||
<field name="type" on_change="on_change_type(type)"/>
|
<field name="type" on_change="on_change_type(type)"/>
|
||||||
|
|
|
@ -1038,6 +1038,7 @@ class survey_question_wiz(osv.osv_memory):
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'target': 'new',
|
'target': 'new',
|
||||||
'view_id': view_id,
|
'view_id': view_id,
|
||||||
|
'page_id': int(context.get('page_id',0)),
|
||||||
'context': context
|
'context': context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<record id="product_warning_form_view" model="ir.ui.view">
|
<record id="product_warning_form_view" model="ir.ui.view">
|
||||||
<field name="name">product.warning.form.inherit</field>
|
<field name="name">product.warning.form.inherit</field>
|
||||||
<field name="model">product.product</field>
|
<field name="model">product.product</field>
|
||||||
<field name="inherit_id" ref="procurement.product_template_form_view_procurement"/>
|
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<notebook position="inside">
|
<notebook position="inside">
|
||||||
<page string="Warnings">
|
<page string="Warnings">
|
||||||
|
|
Loading…
Reference in New Issue