[MERGE] Sync with trunk

bzr revid: tde@openerp.com-20130617095141-74uttqtw60iorl5g
This commit is contained in:
Thibault Delavallée 2013-06-17 11:51:41 +02:00
commit 7b7dfb955f
138 changed files with 2143 additions and 1947 deletions

View File

@ -65,12 +65,11 @@ class bank(osv.osv):
# Find the code and parent of the bank account to create
dig = 6
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
if not ids: continue
ref_acc_bank_temp = obj_acc.browse(cr, uid, ids[0], context=context)
ref_acc_bank = ref_acc_bank_temp.parent_id
ref_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context).parent_id
while True:
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)])
@ -82,7 +81,7 @@ class bank(osv.osv):
'name': name,
'code': new_code,
'type': 'liquidity',
'user_type': ref_acc_bank_temp.user_type.id,
'user_type': ref_acc_bank.user_type.id,
'reconcile': False,
'parent_id': ref_acc_bank.id,
'company_id': bank.company_id.id,

View File

@ -51,9 +51,12 @@ class account_invoice(osv.osv):
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'}
journal_obj = self.pool.get('account.journal')
res = journal_obj.search(cr, uid, [('type', '=', type2journal.get(type_inv, 'sale')),
('company_id', '=', company_id)],
limit=1)
domain = [('company_id', '=', company_id)]
if isinstance(type_inv, list):
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
def _get_currency(self, cr, uid, context=None):
@ -578,6 +581,10 @@ class account_invoice(osv.osv):
return {'value': {}}
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 = {}
dom = {}
obj_journal = self.pool.get('account.journal')
@ -634,14 +641,13 @@ class account_invoice(osv.osv):
else:
continue
if company_id and type:
if type in ('out_invoice'):
journal_type = 'sale'
elif type in ('out_refund'):
journal_type = 'sale_refund'
elif type in ('in_refund'):
journal_type = 'purchase_refund'
else:
journal_type = 'purchase'
journal_mapping = {
'out_invoice': 'sale',
'out_refund': 'sale_refund',
'in_refund': 'purchase_refund',
'in_invoice': 'purchase',
}
journal_type = journal_mapping[type]
journal_ids = obj_journal.search(cr, uid, [('company_id','=',company_id), ('type', '=', journal_type)])
if journal_ids:
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:
val['journal_id'] = r[2]
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)]}
else:
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)
acc_id = inv.account_id.id
name = inv['name'] or '/'
name = inv['name'] or inv['supplier_invoice_number'] or '/'
totlines = False
if inv.payment_term:
totlines = payment_term_obj.compute(cr,
@ -1167,12 +1178,12 @@ class account_invoice(osv.osv):
if not ids:
return []
types = {
'out_invoice': 'Invoice ',
'in_invoice': 'Sup. Invoice ',
'out_refund': 'Refund ',
'in_refund': 'Supplier Refund ',
'out_invoice': _('Invoice'),
'in_invoice': _('Supplier Invoice'),
'out_refund': _('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):
if not args:

View File

@ -1066,12 +1066,12 @@ class account_move_line(osv.osv):
for line in self.browse(cr, uid, ids, context=context):
ctx = context.copy()
if ('journal_id' not in ctx):
if not ctx.get('journal_id'):
if line.move_id:
ctx['journal_id'] = line.move_id.journal_id.id
else:
ctx['journal_id'] = line.journal_id.id
if ('period_id' not in ctx):
if not ctx.get('period_id'):
if line.move_id:
ctx['period_id'] = line.move_id.period_id.id
else:

View File

@ -585,7 +585,10 @@
<field name="date"/>
<field name="name"/>
<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="[
'&amp;',
'|',('parent_id','=',False),('is_company','=',True),
'|',('customer','=',True),('supplier','=',True)]"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>

View File

@ -61,7 +61,7 @@
<field name="name">partner.view.buttons</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="priority" eval="10"/>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button type="action" string="Invoices"
@ -96,7 +96,7 @@
<field name="priority">2</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<page string="History" position="before" version="7.0">
<page name="sales_purchases" position="after" version="7.0">
<page string="Accounting" col="4" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<group>
<group>

View File

@ -363,7 +363,7 @@
<field name="inherit_id" ref="account.view_account_journal_form"/>
<field name="arch" type="xml">
<field name="type" position="after">
<field name="analytic_journal_id"/>
<field name="analytic_journal_id" groups="analytic.group_analytic_accounting"/>
</field>
</field>
</record>

View File

@ -239,7 +239,7 @@
<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">[[ 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="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>
@ -292,7 +292,7 @@
<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">[[ 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">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>

View File

@ -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"),
}
_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):

View File

@ -72,8 +72,8 @@ class account_invoice_line(osv.osv):
_inherit = "account.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):
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)
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_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)
if rec:
res_prod['value'].update({'account_analytic_id': rec.analytic_id.id})

View File

@ -10,7 +10,7 @@
<field name="inherit_id" ref="account.view_account_journal_form"/>
<field name="arch" type="xml">
<field name="centralisation" position="before">
<field name="plan_id" />
<field name="plan_id" groups="analytic.group_analytic_accounting"/>
</field>
</field>
</record>

View File

@ -136,9 +136,9 @@ class account_invoice_line(osv.osv):
res += diff_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')
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:
return res
if type in ('in_invoice','in_refund'):

View File

@ -13,6 +13,17 @@
</field>
</field>
</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>
</openerp>

View File

@ -203,7 +203,9 @@
<field name="view_id" ref="crossovered_budget_view_tree"/>
<field name="search_view_id" ref="view_crossovered_budget_search"/>
<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
expected for a period in the future. A budget is defined on some
financial accounts and/or analytic accounts (that may represent

View File

@ -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_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_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,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,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,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_account_followup_followup_line_manager account_followup.followup.line.manager model_account_followup_followup_line account.group_account_manager 1 1 1 1
4 access_account_followup_followup_accountant account_followup.followup user model_account_followup_followup account.group_account_invoice 1 0 0 0
5 access_account_followup_followup_manager account_followup.followup.manager model_account_followup_followup account.group_account_manager 1 1 1 1
6 access_account_followup_stat_invoice account_followup.stat.invoice model_account_followup_stat account.group_account_invoice 1 1 1 0 1 0
7 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 0 1 0

View File

@ -88,6 +88,7 @@ class payment_order_create(osv.osv_memory):
'order_id': payment.id,
'partner_id': line.partner_id and line.partner_id.id or False,
'communication': line.ref or '/',
'state': line.invoice and line.invoice.reference_type != 'none' and 'structured' or 'normal',
'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,
}, context=context)

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-05-29 13:17+0000\n"
"PO-Revision-Date: 2013-06-13 11:30+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-05-30 05:45+0000\n"
"X-Generator: Launchpad (build 16652)\n"
"X-Launchpad-Export-Date: 2013-06-14 05:38+0000\n"
"X-Generator: Launchpad (build 16667)\n"
#. module: account_voucher
#: field:account.bank.statement.line,voucher_id:0
@ -27,7 +27,7 @@ msgid "account.config.settings"
msgstr "account.config.settings"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:369
#: code:addons/account_voucher/account_voucher.py:417
#, python-format
msgid "Write-Off"
msgstr "Списание"
@ -129,7 +129,7 @@ msgid "Voucher Statistics"
msgstr ""
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1547
#: code:addons/account_voucher/account_voucher.py:1641
#, python-format
msgid ""
"You can not change the journal as you already reconciled some statement "
@ -223,8 +223,8 @@ msgid "Journal Item"
msgstr "Элемент журнала"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:508
#: code:addons/account_voucher/account_voucher.py:981
#: code:addons/account_voucher/account_voucher.py:558
#: code:addons/account_voucher/account_voucher.py:1073
#, python-format
msgid "Error!"
msgstr "Ошибка!"
@ -251,7 +251,7 @@ msgid "Cancelled"
msgstr "Отменено"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1153
#: code:addons/account_voucher/account_voucher.py:1249
#, python-format
msgid ""
"You have to configure account base code and account tax code on the '%s' tax!"
@ -295,7 +295,7 @@ msgid "Tax"
msgstr "Налог"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:879
#: code:addons/account_voucher/account_voucher.py:971
#, python-format
msgid "Invalid Action!"
msgstr "Неверное действие!"
@ -348,7 +348,7 @@ msgid "Import Invoices"
msgstr "Импорт счетов"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1112
#: code:addons/account_voucher/account_voucher.py:1208
#, python-format
msgid "Wrong voucher line"
msgstr ""
@ -367,7 +367,7 @@ msgid "Receipt"
msgstr "Приход"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1018
#: code:addons/account_voucher/account_voucher.py:1110
#, python-format
msgid ""
"You should configure the 'Gain Exchange Rate Account' in the accounting "
@ -388,7 +388,7 @@ msgstr "Период"
#. module: account_voucher
#: view:account.voucher:0
#: code:addons/account_voucher/account_voucher.py:211
#: code:addons/account_voucher/account_voucher.py:231
#, python-format
msgid "Supplier"
msgstr "Поставщик"
@ -409,7 +409,7 @@ msgid "Debit"
msgstr "Дебет"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1547
#: code:addons/account_voucher/account_voucher.py:1641
#, python-format
msgid "Unable to change journal !"
msgstr "Невозможно изменить журнал!"
@ -515,7 +515,7 @@ msgid "Pay Invoice"
msgstr "Оплата счета"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1153
#: code:addons/account_voucher/account_voucher.py:1249
#, python-format
msgid "No Account Base Code and Account Tax Code!"
msgstr ""
@ -569,15 +569,15 @@ msgid "To Review"
msgstr "Для проверки"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1025
#: code:addons/account_voucher/account_voucher.py:1039
#: code:addons/account_voucher/account_voucher.py:1194
#: code:addons/account_voucher/account_voucher.py:1120
#: code:addons/account_voucher/account_voucher.py:1134
#: code:addons/account_voucher/account_voucher.py:1286
#, python-format
msgid "change"
msgstr "изменить"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1014
#: code:addons/account_voucher/account_voucher.py:1106
#, python-format
msgid ""
"You should configure the 'Loss Exchange Rate Account' in the accounting "
@ -631,6 +631,7 @@ msgstr "&#1052;&#1077;&#1089;&#1103;&#1094;"
#. module: account_voucher
#: field:account.voucher,currency_id:0
#: field:account.voucher.line,currency_id:0
#: model:ir.model,name:account_voucher.model_res_currency
#: field:sale.receipt.report,currency_id:0
msgid "Currency"
msgstr "Валюта"
@ -674,7 +675,7 @@ msgid "Reconcile Payment Balance"
msgstr "Сверка платежного баланса"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:975
#: code:addons/account_voucher/account_voucher.py:1067
#, python-format
msgid "Configuration Error !"
msgstr "Ошибка конфигурации !"
@ -739,7 +740,7 @@ msgid "October"
msgstr "Октябрь"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:976
#: code:addons/account_voucher/account_voucher.py:1068
#, python-format
msgid "Please activate the sequence of selected journal !"
msgstr "Пожалуйста, включите нумерацию выбранного журнала!"
@ -819,7 +820,7 @@ msgid "Previous Payments ?"
msgstr "Предыдущие платежи ?"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1112
#: code:addons/account_voucher/account_voucher.py:1208
#, python-format
msgid "The invoice you are willing to pay is not valid anymore."
msgstr "Счет, который вы готовы платить, уже не актуален ."
@ -851,7 +852,7 @@ msgid "Active"
msgstr "Активно"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:982
#: code:addons/account_voucher/account_voucher.py:1074
#, python-format
msgid "Please define a sequence on the journal."
msgstr "Пожалуйста, определите нумерацию журнала."
@ -861,7 +862,7 @@ msgstr "Пожалуйста, определите нумерацию журна
#: model:ir.actions.act_window,name:account_voucher.action_vendor_receipt
#: model:ir.ui.menu,name:account_voucher.menu_action_vendor_receipt
msgid "Customer Payments"
msgstr "Платежи клиентов"
msgstr "Платежи заказчиков"
#. module: account_voucher
#: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all
@ -979,7 +980,7 @@ msgid "Journal Items"
msgstr "Элементы журнала"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:508
#: code:addons/account_voucher/account_voucher.py:558
#, python-format
msgid "Please define default credit/debit accounts on the journal \"%s\"."
msgstr ""
@ -1188,7 +1189,7 @@ msgid ""
msgstr ""
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:879
#: code:addons/account_voucher/account_voucher.py:971
#, python-format
msgid "Cannot delete voucher(s) which are already opened or paid."
msgstr ""
@ -1251,8 +1252,8 @@ msgid "Status <b>changed</b>"
msgstr ""
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1014
#: code:addons/account_voucher/account_voucher.py:1018
#: code:addons/account_voucher/account_voucher.py:1106
#: code:addons/account_voucher/account_voucher.py:1110
#, python-format
msgid "Insufficient Configuration!"
msgstr ""

View File

@ -102,7 +102,10 @@ class OAuthController(oeweb.Controller):
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
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'
state = {

View File

@ -60,7 +60,7 @@ class crm_meeting(base_state, osv.Model):
'categ_ids': fields.many2many('crm.meeting.type', 'meeting_category_rel',
'event_id', 'type_id', 'Tags'),
'attendee_ids': fields.many2many('calendar.attendee', 'meeting_attendee_rel',\
'event_id', 'attendee_id', 'Attendees', states={'done': [('readonly', True)]}),
'event_id', 'attendee_id', 'Invited People', states={'done': [('readonly', True)]}),
}
_defaults = {
'state': 'open',

View File

@ -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 Name Is a company Related company Address type Customer Supplier Street ZIP City State Country
2 Aurora Shelves 1 1 0 25 Pacific Road 95101 San José CA United States
3 Roger Martins 0 Aurora Shelves Invoice 1 0 27 Pacific Road 95102 San José CA United States
4 House Sales Direct 1 1 0 104 Saint Mary Avenue 94059 Redwood CA United States
5 Yvan Holiday 0 House Sales Direct Default 1 0 104 Saint Mary Avenue 94060 Redwood CA United States
6 Jack Unsworth 0 House Sales Direct Invoice 1 0 227 Jackson Road 94061 Redwood CA United States
7 Michael Mason 0 1 0 16 5th Avenue 94104 San Francisco CA United States
8 International Wood 1 1 0 748 White House Boulevard 20004 Washington DC United States
9 Sharon Pecker 0 International Wood Invoice 1 0 755 White House Boulevard 20005 Washington DC United States

View File

@ -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
1 Name Address type Street City Country Tags Supplier Customer Is a company Companies that refers to partner / Parent company
2 Wood y Wood Pecker Snow Street, 25 Kainuu Finland Supplier 1 0 1
3 Roger Pecker Default Snow Street, 27 Kainuu Finland Supplier 1 0 0 Wood y Wood Pecker
4 Sharon Pecker Delivery Snow Street, 28 Kainuu Finland Supplier 1 0 0 Wood y Wood Pecker
5 Thomas Pecker Contact Snow Street, 27 Kainuu Finland Supplier 1 0 0 Wood y Wood Pecker
6 Vicking Direct Atonium Street, 45a Brussels Belgium Supplier 1 0 1
7 Yvan Holiday Invoice Atonium Street, 45b Brussels Belgium Supplier 1 0 0 Vicking Direct
8 Jack Unsworth Contact Atonium Street, 45a Brussels Belgium Supplier 1 0 0 Vicking Direct

View File

@ -229,8 +229,8 @@
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>
<p>The following CSV file shows how to import
suppliers and their respective contacts</p>
<a href="/base_import/static/csv/o2m_suppliers_contacts.csv">Suppliers and their respective contacts</a>
customers and their respective contacts</p>
<a href="/base_import/static/csv/o2m_customers_contacts.csv">Customers and their respective contacts</a>
</dd>
</dl>

View File

@ -14,9 +14,13 @@
<label string="This plug-in allows you to create/modify OpenERP Reports into OpenOffice Writer."/>
</separator>
<xpath expr="//button[@string='Install Modules']" position="replace">
<button name="action_next" icon="gtk-go-forward" type="object" string="Configure" invisible="context.get('menu',False)" class="oe_highlight"/>
<button name="action_next" type="object" string="Configure" invisible="context.get('menu',False)" class="oe_highlight"/>
<label string="or" invisible="context.get('menu',False)" class="oe_inline"/>
</xpath>
<xpath expr="//button[@string='Skip']" position="replace">
<button string="Ok" class="oe_highlight" special="cancel" invisible="context.get('active_model',False)"/>
<button string="Skip" class="oe_link" special="cancel" invisible="context.get('menu',False)"/>
</xpath>
<xpath expr="//separator[@string='title']" position="after">
<group colspan="8" height="450" width="750">
<field name="name" invisible="1"/>

View File

@ -61,8 +61,8 @@ class RPCSession(object):
protocol = m.group(1)
if not m:
return -1
if protocol == 'http://' or protocol == 'http://':
self.gateway = XMLRPCGateway(host, port, 'http')
if protocol == 'http://' or protocol == 'https://':
self.gateway = XMLRPCGateway(host, port, protocol[:-3])
elif protocol == 'socket://':
self.gateway = NETRPCGateway(host, port)

View File

@ -344,7 +344,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
},
load_data:function(){
var board = new instance.web.Model('board.board');
return board.call('list');
return board.call('list', [board.context()]);
},
_x:function() {
if (!instance.webclient) { return $.Deferred().reject(); }

View File

@ -2,19 +2,6 @@
<openerp>
<data>
<!-- Add section_id (Sales Team) to res.partner -->
<record id="view_partners_form_crm1" model="ir.ui.view">
<field name="name">view.res.partner.form.crm.inherited1</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field eval="18" name="priority"/>
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="section_id" completion="1" groups="base.group_multi_salesteams"/>
</field>
</field>
</record>
<!-- open meetings related to given partner -->
<record id="crm_meeting_partner" model="ir.actions.act_window">
<field name="name">Meetings</field>
@ -91,24 +78,31 @@
</field>
</record>
<record model="ir.ui.view" id="res_partner_view_buttons">
<field name="name">res.partner.view.buttons</field>
<!-- Add section_id (SalesTeam) and contextual button on partner form view -->
<record id="view_partners_form_crm1" model="ir.ui.view">
<field name="name">view.res.partner.form.crm.inherited1</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="priority" eval="10"/>
<field name="inherit_id" ref="base.view_partner_form"/>
<field eval="18" name="priority"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button type="action"
string="Meetings"
name="%(base_calendar.action_crm_meeting)d"
context="{'search_default_partner_ids': active_id, 'default_partner_ids' : [active_id]}"/>
<button type="action" string="Calls"
name="%(crm.crm_case_categ_phone_incoming0)d"
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}" />
<button type="action" string="Opportunities" attrs="{'invisible': [('customer', '=', False)]}"
name="%(crm.crm_case_category_act_oppor11)d" context="{'search_default_partner_id': active_id}"/>
</xpath>
<data>
<field name="user_id" position="after">
<field name="section_id" completion="1" groups="base.group_multi_salesteams"/>
</field>
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline" type="action" string="Opportunities"
attrs="{'invisible': [('customer', '=', False)]}"
name="%(crm.crm_case_category_act_oppor11)d"
context="{'search_default_partner_id': active_id}"/>
<button class="oe_inline" type="action"
string="Meetings"
name="%(base_calendar.action_crm_meeting)d"
context="{'search_default_partner_ids': active_id, 'default_partner_ids' : [active_id]}"/>
<button class="oe_inline" type="action" string="Calls"
name="%(crm.crm_case_categ_phone_incoming0)d"
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}" />
</xpath>
</data>
</field>
</record>

View File

@ -42,14 +42,20 @@ automatically new claims based on incoming emails.
'security/ir.model.access.csv',
'report/crm_claim_report_view.xml',
'crm_claim_data.xml',
'res_partner_view.xml',
],
'demo': ['crm_claim_demo.xml'],
'test': ['test/process/claim.yml',
'test/ui/claim_demo.yml'
'test': [
'test/process/claim.yml',
'test/ui/claim_demo.yml'
],
'installable': True,
'auto_install': False,
'images': ['images/claim_categories.jpeg','images/claim_stages.jpeg','images/claims.jpeg'],
'images': [
'images/claim_categories.jpeg',
'images/claim_stages.jpeg',
'images/claims.jpeg'
],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -15,7 +15,11 @@
<field name="view_id" ref="crm_case_claims_tree_view"/>
<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="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 model="ir.actions.act_window.view" id="action_crm_tag_tree_claim0">

View File

@ -216,35 +216,5 @@
</search>
</field>
</record>
<record id="view_claim_partner_info_form1" model="ir.ui.view">
<field name="name">res.partner.claim.info.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="priority">20</field>
<field name="arch" type="xml">
<xpath expr="//page[@name='page_history']" position="attributes">
<attribute name="invisible">False</attribute>
</xpath>
<xpath expr="//page[@name='page_history']" position="inside">
<group name="grp_claim" string="Claims">
<field name="claims_ids" colspan="4" nolabel="1">
<tree string="Partners Claim" editable="bottom">
<field name="name"/>
</tree>
</field>
</group>
</xpath>
</field>
</record>
<act_window
context="{'search_default_partner_id': [active_id], 'default_partner_id': active_id}"
id="act_claim_partner"
name="Claims"
view_mode="tree,form"
res_model="crm.claim"
src_model="res.partner"/>
</data>
</openerp>

View File

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Partners inherited form -->
<record id="view_claim_res_partner_info_form" model="ir.ui.view">
<field name="name">res.partner.claim.info.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="priority" eval="50"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline" type="action"
name="%(crm_case_categ_claim0)d"
string="Claims"
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
groups="base.group_sale_salesman" />
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -88,7 +88,11 @@
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_wiki_tree"/>
<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>
<menuitem id="menu_page" parent="menu_wiki" name="Pages" action="action_page" sequence="10"/>
<record id="action_category" model="ir.actions.act_window">

View File

@ -24,8 +24,8 @@ import base64
import logging
import openerp
from openerp import SUPERUSER_ID
from openerp.osv import osv, fields
from openerp.osv import fields
from openerp import tools
from openerp.tools.translate import _
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):
vals = {}
action_obj = self.pool.get('ir.actions.act_window')
data_obj = self.pool.get('ir.model.data')
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')
res_id = data_obj.browse(cr, uid, model_data_id, context=context).res_id
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,
'type': 'ir.actions.act_window',
'res_model': 'mail.compose.message',
@ -211,27 +210,29 @@ class email_template(osv.osv):
'target': 'new',
'auto_refresh':1
}, 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,
'model': src_obj,
'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,
}, context)
self.write(cr, uid, ids, {
'ref_ir_act_window': vals.get('ref_ir_act_window',False),
'ref_ir_value': vals.get('ref_ir_value',False),
}, context)
template.write({
'ref_ir_act_window': act_id,
'ref_ir_value': ir_values_id,
})
return True
def unlink_action(self, cr, uid, ids, context=None):
for template in self.browse(cr, uid, ids, context=context):
try:
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:
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:
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
return True

View File

@ -54,18 +54,22 @@ class mail_compose_message(osv.TransientModel):
Indeed, basic mail.compose.message wizard duplicates attachments in mass
mailing mode. But in 'single post' mode, attachments of an email template
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):
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:
continue
template = self.pool.get('email.template').browse(cr, uid, wizard.template_id.id, context=context)
new_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))
else:
new_attachment_ids.append(attachment.id)
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):
""" - mass_mailing: we cannot render, so return the template values

View File

@ -21,15 +21,13 @@
from openerp.osv import fields, osv
class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'speaker': fields.boolean('Speaker', help="Check this box if this contact is a speaker."),
'event_ids': fields.one2many('event.event','main_speaker_id', readonly=True),
'event_registration_ids': fields.one2many('event.registration','partner_id', readonly=True),
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -2,9 +2,8 @@
<openerp>
<data>
<!-- Partners inherited form -->
<record id="view_event_partner_info_form" model="ir.ui.view">
<!-- Partners inherited form -->
<record id="view_event_partner_info_form" model="ir.ui.view">
<field name="name">res.partner.event.info.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
@ -12,34 +11,8 @@
<field name="supplier" position="after">
<field name="speaker"/>
</field>
<xpath expr="//page[@name='page_history']" position="attributes">
<attribute name="invisible">False</attribute>
</xpath>
<xpath expr="//page[@name='page_history']" position="inside">
<group name="grp_event" string="Events">
<field name="event_ids" colspan="4" nolabel="1">
<tree string="Events">
<field name="name" string="Event"/>
<field name="main_speaker_id"/>
</tree>
</field>
</group>
<group name="grp_registration" string="Registrations">
<field name="event_registration_ids" colspan="4" nolabel="1">
<tree string="Events Registration">
<field name="event_begin_date" string="Date"/>
<field name="event_id" />
<field name="nb_register"/>
<field name="state"/>
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="gtk-cancel"/>
<button name="button_reg_close" string="Close Registration" states="open" type="object" icon="gtk-close"/>
<button name="check_confirm" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
</tree>
</field>
</group>
</xpath>
</field>
</record>
</record>
</data>
</openerp>

View File

@ -591,6 +591,9 @@
<field name="view_mode">tree,graph</field>
<field name="context">{"search_default_groupby_vehicle" : True}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new odometer log.
</p>
<p>
Here you can add various odometer entries for all vehicles.
You can also show odometer value for a particular vehicle using

View File

@ -0,0 +1,232 @@
# Thai translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-06-15 17:09+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Thai <th@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-06-16 04:38+0000\n"
"X-Generator: Launchpad (build 16667)\n"
#. module: hr_contract
#: field:hr.contract,wage:0
msgid "Wage"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Information"
msgstr "ข้อมูล"
#. module: hr_contract
#: field:hr.contract,trial_date_start:0
msgid "Trial Start Date"
msgstr "วันที่เริ่มต้นการทดลอง"
#. module: hr_contract
#: field:hr.employee,vehicle:0
msgid "Company Vehicle"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Group By..."
msgstr "จัดกลุ่มตาม..."
#. module: hr_contract
#: field:hr.contract,department_id:0
msgid "Department"
msgstr "แผนก"
#. module: hr_contract
#: view:hr.contract:0
#: field:hr.contract,employee_id:0
#: model:ir.model,name:hr_contract.model_hr_employee
msgid "Employee"
msgstr "พนักงาน"
#. module: hr_contract
#: view:hr.contract:0
msgid "Search Contract"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
#: view:hr.employee:0
#: field:hr.employee,contract_ids:0
#: model:ir.actions.act_window,name:hr_contract.act_hr_employee_2_hr_contract
#: model:ir.actions.act_window,name:hr_contract.action_hr_contract
#: model:ir.ui.menu,name:hr_contract.hr_menu_contract
msgid "Contracts"
msgstr "สัญญา"
#. module: hr_contract
#: field:hr.employee,children:0
msgid "Number of Children"
msgstr "จำนวนบุตร"
#. module: hr_contract
#: help:hr.employee,contract_id:0
msgid "Latest contract of the employee"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Job"
msgstr "งาน"
#. module: hr_contract
#: field:hr.contract,advantages:0
msgid "Advantages"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Work Permit"
msgstr "ใบอนุญาตทำงาน"
#. module: hr_contract
#: model:ir.actions.act_window,name:hr_contract.action_hr_contract_type
#: model:ir.ui.menu,name:hr_contract.hr_menu_contract_type
msgid "Contract Types"
msgstr "ประเภทสัญญา"
#. module: hr_contract
#: view:hr.employee:0
msgid "Medical Exam"
msgstr ""
#. module: hr_contract
#: field:hr.contract,date_end:0
msgid "End Date"
msgstr "วันสิ้นสุด"
#. module: hr_contract
#: help:hr.contract,wage:0
msgid "Basic Salary of the employee"
msgstr "เงินเดือนของพนักงาน"
#. module: hr_contract
#: view:hr.contract:0
#: field:hr.contract,name:0
msgid "Contract Reference"
msgstr "อ้างอิงตามสัญญา"
#. module: hr_contract
#: help:hr.employee,vehicle_distance:0
msgid "In kilometers"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
#: field:hr.contract,notes:0
msgid "Notes"
msgstr ""
#. module: hr_contract
#: field:hr.contract,permit_no:0
msgid "Work Permit No"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
#: view:hr.employee:0
#: field:hr.employee,contract_id:0
#: model:ir.model,name:hr_contract.model_hr_contract
#: model:ir.ui.menu,name:hr_contract.next_id_56
msgid "Contract"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
#: field:hr.contract,type_id:0
#: view:hr.contract.type:0
#: field:hr.contract.type,name:0
#: model:ir.model,name:hr_contract.model_hr_contract_type
msgid "Contract Type"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
#: field:hr.contract,working_hours:0
msgid "Working Schedule"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Salary and Advantages"
msgstr ""
#. module: hr_contract
#: field:hr.contract,job_id:0
msgid "Job Title"
msgstr ""
#. module: hr_contract
#: constraint:hr.contract:0
msgid "Error! Contract start-date must be less than contract end-date."
msgstr ""
#. module: hr_contract
#: field:hr.employee,manager:0
msgid "Is a Manager"
msgstr ""
#. module: hr_contract
#: field:hr.contract,date_start:0
msgid "Start Date"
msgstr ""
#. module: hr_contract
#: field:hr.contract,visa_no:0
msgid "Visa No"
msgstr ""
#. module: hr_contract
#: field:hr.employee,vehicle_distance:0
msgid "Home-Work Dist."
msgstr ""
#. module: hr_contract
#: field:hr.employee,place_of_birth:0
msgid "Place of Birth"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Trial Period Duration"
msgstr ""
#. module: hr_contract
#: view:hr.contract:0
msgid "Duration"
msgstr ""
#. module: hr_contract
#: field:hr.contract,visa_expire:0
msgid "Visa Expire Date"
msgstr ""
#. module: hr_contract
#: field:hr.employee,medic_exam:0
msgid "Medical Examination Date"
msgstr ""
#. module: hr_contract
#: field:hr.contract,trial_date_end:0
msgid "Trial End Date"
msgstr ""
#. module: hr_contract
#: view:hr.contract.type:0
msgid "Search Contract Type"
msgstr ""

View File

@ -165,9 +165,14 @@
</header>
<sheet>
<label for="employee_id" class="oe_edit_only"/>
<h1><field name="employee_id" on_change="onchange_employee_id(employee_id)" class="oe_inline"/>, <field name="date" class="oe_inline"/></h1>
<h1><field name="employee_id" class="oe_inline"
attrs="{'readonly': [('state', '=', 'done')]}"
on_change="onchange_employee_id(employee_id)"/>,
<field name="date"
attrs="{'readonly': [('state', '=', 'done')]}"/>
</h1>
<label for="plan_id" class="oe_edit_only"/>
<h2><field name="plan_id"/></h2>
<h2><field name="plan_id" attrs="{'readonly': [('state', '=', 'done')]}"/></h2>
<group>
<group colspan="4" attrs="{'invisible':['|', ('state','=','draft'), ('state', '=', 'wait')]}">
<field name="rating" attrs="{'readonly':[('state','&lt;&gt;','progress')]}"/>
@ -175,7 +180,7 @@
</group>
</group>
<group string="Appraisal Forms" attrs="{'invisible':[('state','=','draft')]}">
<field nolabel="1" name="survey_request_ids">
<field nolabel="1" name="survey_request_ids" attrs="{'readonly': [('state', '=', 'done')]}">
<form string="Interview Appraisal" version="7.0">
<div class="oe_right oe_button_box">
<button name="%(survey.action_view_survey_question_message)d" string="Answer Survey" type="action" states="waiting_answer" icon="gtk-execute" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0, 'active' : response,'request' : True, 'object' : 'hr.evaluation.interview', 'cur_id' : active_id}" attrs="{'readonly':[('survey_id','=',False)]}"/>

View File

@ -210,6 +210,11 @@
<field name="context">{"default_hr_expense_ok":1}</field>
<field name="domain">[('hr_expense_ok','=',True)]</field>
<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>
<menuitem id="menu_hr_product" name="Expense Categories" parent="hr.menu_hr_configuration" action="hr_expense_product"/>

View File

@ -146,6 +146,7 @@
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
<field name="manager_id" invisible="1"/>
<field name="user_id" invisible="1"/>
<field name="date_from" invisible="1"/>
<!--field name="type"/-->
<field name="state"/>
</tree>

View File

@ -11,7 +11,7 @@
<group colspan="4">
<field name="month"/>
<field name="year"/>
<field name="employee_id" colspan="3"/>
<field name="employee_id" />
</group>
<footer>
<button string="Print" name="print_report" type="object" class="oe_highlight"/>
@ -33,7 +33,7 @@
<menuitem action="action_hr_timesheet_employee"
id="menu_hr_timesheet_employee"
parent="hr.menu_hr_reporting"
parent="hr.menu_hr_reporting_timesheet"
sequence="2" icon="STOCK_PRINT"/>
</data>

View File

@ -16,7 +16,7 @@
<field name="name">timesheet.report.tree</field>
<field name="model">timesheet.report</field>
<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="name" invisible="1"/>
<field name="user_id" invisible="1"/>

View File

@ -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_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_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_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

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 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
4 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
5 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
6 access_hr_timesheet_report hr.timesheet.report model_hr_timesheet_report base.group_hr_manager 1 1 1 0 1 0
7 access_hr_analytic_timesheet_system_user hr.analytic.timesheet.system.user model_hr_analytic_timesheet base.group_user 1 0 0 0
8 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
9 access_timesheet_report timesheet.report model_timesheet_report base.group_hr_manager 1 1 1 0 1 0

View File

@ -190,8 +190,13 @@ openerp.hr_timesheet_sheet = function(instance) {
$(this).val(self.sum_box(account, day_count, true));
} else {
account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
self.display_totals();
self.sync();
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
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())){
$(this).val(self.sum_box(account, day_count, true));
}
@ -308,10 +313,10 @@ openerp.hr_timesheet_sheet = function(instance) {
generate_o2m_value: function() {
var self = this;
var ops = [];
_.each(self.accounts, function(account) {
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(day.lines, function(line) {

View File

@ -105,7 +105,7 @@
<para style="terp_default_9">[[ l['vat'] ]]</para>
</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>
<para style="terp_default_Right_9">[[ formatLang(l['amount'], currency_obj=company.currency_id) ]]</para>

View File

@ -35,24 +35,24 @@
</form>
</field>
</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="model">account.bank.statement.line</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<tree editable="bottom" string="Statement lines">
<field name="statement_id" readonly="1" invisible="1"/>
<field name="sequence" readonly="1" invisible="1"/>
<field name="date"/>
<field name="name"/>
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
<field name="amount"/>
<field name="note"/>
</tree>
<tree editable="bottom" string="Statement lines" create="0">
<field name="sequence" readonly="1" invisible="1"/>
<field name="statement_id" readonly="1" />
<field name="date"/>
<field name="name"/>
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
<field name="account_id" options='{"no_open":True}' domain="[('type', '&lt;&gt;', 'view')]"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '&lt;&gt;', 'view')]"/>
<field name="amount"/>
<field name="note"/>
</tree>
</field>
</record>

File diff suppressed because it is too large Load Diff

View File

@ -150,11 +150,17 @@ class mail_notification(osv.Model):
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
:param list partners_to_notify: optional list of partner ids restricting
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:
context = {}
@ -189,8 +195,9 @@ class mail_notification(osv.Model):
# add signature
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
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')
if user_signature:
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
if msg.parent_id:
@ -203,13 +210,9 @@ class mail_notification(osv.Model):
'recipient_ids': [(4, id) for id in notify_partner_ids],
'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')
email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
try:
return mail_mail.send(cr, uid, [email_notif_id], context=context)
except Exception:
return False
if force_send:
mail_mail.send(cr, uid, [email_notif_id], context=context)
return True

View File

@ -66,11 +66,11 @@
<!-- Add followers related menu entries in Settings/Email -->
<menuitem name="Followers" id="menu_email_followers" parent="base.menu_email"
action="action_view_followers" sequence="30" groups="base.group_no_one"/> -->
action="action_view_followers" sequence="30" groups="base.group_no_one"/>
<!-- Add notifications related menu entry in Settings/Email -->
<menuitem name="Notifications" id="menu_email_notifications" parent="base.menu_email"
action="action_view_notifications" sequence="35" groups="base.group_no_one"/>
action="action_view_notifications" sequence="13" groups="base.group_no_one"/>
</data>
</openerp>

View File

@ -55,7 +55,6 @@ class mail_mail(osv.Model):
'auto_delete': fields.boolean('Auto Delete',
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),
'email_from': fields.char('From', help='Message sender, taken from user preferences.'),
'email_to': fields.text('To', help='Message recipients (emails)'),
'recipient_ids': fields.many2many('res.partner', string='To (Partners)'),
'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):
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
if this.alias_domain and this.alias_name:
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."))
""" Kept for compatibility
TDE TODO: remove me in 8.0
"""
return self.pool['mail.message']._get_default_from(cr, uid, context=context)
_defaults = {
'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):
@ -93,19 +89,25 @@ class mail_mail(osv.Model):
# if value specified: directly return it
if values.get('reply_to'):
return values.get('reply_to')
format_name = True # whether to use a 'Followers of Pigs <pigs@openerp.com' format
email_reply_to = None
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")
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
message = None
# model, res_id, email_from: comes from values OR related message
model, res_id, email_from = values.get('model'), values.get('res_id'), values.get('email_from')
if values.get('mail_message_id'):
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)
res_id = values.get('res_id', message and message.res_id or False)
email_from = values.get('email_from', message and message.email_from or False)
email_reply_to = message and message.reply_to or False
if message.reply_to:
email_reply_to = message.reply_to
format_name = 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 not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
@ -115,16 +117,16 @@ class mail_mail(osv.Model):
catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context)
if catchall_domain and catchall_alias:
email_reply_to = '%s@%s' % (catchall_alias, catchall_domain)
# no alias reply_to -> reply_to will be the email_from, only the email part
# still no reply_to -> reply_to will be the email_from
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
email_reply_to = email_from
# 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]
if document_name:
# sanitize document name

View File

@ -115,7 +115,7 @@
<field name="res_model">mail.mail</field>
<field name="view_type">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"/>
</record>

View File

@ -196,6 +196,14 @@ class mail_message(osv.Model):
def _needaction_domain_get(self, cr, uid, context=None):
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):
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(),
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
'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():
if message.author_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])
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:
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
@ -350,9 +360,12 @@ class mail_message(osv.Model):
else:
author = (0, message.email_from)
partner_ids = []
for partner in message.notified_partner_ids:
if partner.id in partner_tree:
partner_ids.append(partner_tree[partner.id])
if message.subtype_id:
partner_ids = [partner_tree[partner.id] for partner in message.notified_partner_ids
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 = []
for attachment in message.attachment_ids:
if attachment.id in attachments_tree:
@ -766,7 +779,9 @@ class mail_message(osv.Model):
elif not values.get('message_id'):
values['message_id'] = tools.generate_tracking_message_id('private')
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 ?
# 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
@ -880,20 +895,16 @@ class mail_message(osv.Model):
return ''
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.
Call mail_notification.notify to manage the email sending
"""
notification_obj = self.pool.get('mail.notification')
message = self.browse(cr, uid, newid, context=context)
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
if message.model and message.res_id:
# 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.subtype_id and message.model and message.res_id:
fol_obj = self.pool.get("mail.followers")
# browse as SUPERUSER because rules could restrict the search results
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
@ -903,7 +914,7 @@ class mail_message(osv.Model):
], 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
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])
elif message.author_id:
partners_to_notify -= set([message.author_id])
@ -914,7 +925,8 @@ class mail_message(osv.Model):
# 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()
# An error appear when a user receive a notification without notifying

View File

@ -30,9 +30,9 @@
<field name="subject"/>
<field name="author_id"/>
<field name="email_from"/>
<field name="reply_to"/>
<field name="date"/>
<field name="type"/>
<field name="subtype_id"/>
</group>
<group>
<field name="model"/>
@ -40,6 +40,7 @@
<field name="parent_id"/>
<field name="partner_ids" widget="many2many_tags"/>
<field name="notified_partner_ids" widget="many2many_tags"/>
<field name="subtype_id"/>
</group>
</group>
<field name="body"/>

View File

@ -586,7 +586,7 @@ class mail_thread(osv.AbstractModel):
ret_dict = {}
for model_name in self.pool.obj_list():
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
return ret_dict
@ -861,6 +861,9 @@ class mail_thread(osv.AbstractModel):
else:
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')
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)
if partner_ids:
@ -1208,7 +1211,7 @@ class mail_thread(osv.AbstractModel):
model = False
if thread_id:
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']
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)
@ -1356,7 +1359,10 @@ class mail_thread(osv.AbstractModel):
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
""" 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]):
try:
self.check_access_rights(cr, uid, 'read')
@ -1365,27 +1371,35 @@ class mail_thread(osv.AbstractModel):
else:
self.check_access_rights(cr, uid, 'write')
# subscribe partners
self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
for record in self.browse(cr, SUPERUSER_ID, 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
fol_obj = self.pool.get('mail.followers')
if subtype_ids is not None:
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids), ('partner_id', 'in', partner_ids)], context=context)
fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
# no subtypes: default ones for new subscription, do not update existing subscriptions
else:
# search new subscriptions: subtype_ids is False
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
('res_model', '=', self._name),
('res_id', 'in', ids),
('partner_id', 'in', partner_ids),
('subtype_ids', '=', False)
], context=context)
if fol_ids:
subtype_obj = self.pool.get('mail.message.subtype')
subtype_ids = subtype_obj.search(cr, uid, [('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
# subtype_ids specified: update already subscribed partners
if subtype_ids and existing_pids:
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [
('res_model', '=', self._name),
('res_id', '=', record.id),
('partner_id', 'in', list(existing_pids)),
], context=context)
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
else:
subtype_ids = subtype_obj.search(cr, uid, [
('default', '=', True),
'|',
('res_model', '=', self._name),
('res_model', '=', False)
], context=context)
# subscribe new followers
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

View File

@ -267,6 +267,7 @@ openerp.mail = function (session) {
//formating and add some fields for render
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) {
this.timerelative = $.timeago(this.date);
}
@ -979,8 +980,8 @@ openerp.mail = function (session) {
expender: function () {
this.$('.oe_msg_body:first').expander({
slicePoint: this.options.truncate_limit,
expandText: 'read more',
userCollapseText: 'read less',
expandText: _t('read more'),
userCollapseText: _t('read less'),
detailClass: 'oe_msg_tail',
moreClass: 'oe_mail_expand',
lessClass: 'oe_mail_reduce',

View File

@ -281,16 +281,16 @@
<span class='oe_subtle'></span>
</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
</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
<t t-if="widget.partner_ids.length == 0">
nobody
</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">
<span t-attf-class="oe_partner_follower">
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-raw="partner[1]"/></a>
@ -305,7 +305,10 @@
notified
</t>
<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>
<t t-if="!widget.options.readonly" t-call="mail.thread.message.vote"/>
</div>

View File

@ -69,6 +69,7 @@ class TestMailBase(common.TransactionCase):
self.group_employee_id = group_employee_ref and group_employee_ref[1] or False
# 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,
{'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'alias_name': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
self.user_bert_id = self.res_users.create(cr, uid,

View File

@ -22,7 +22,7 @@
from openerp.addons.mail.mail_mail import mail_mail
from openerp.addons.mail.mail_thread import mail_thread
from openerp.addons.mail.tests.test_mail_base import TestMailBase
from openerp.tools import mute_logger
from openerp.tools import mute_logger, email_split
from openerp.tools.mail import html_sanitize
@ -479,7 +479,7 @@ class test_mail(TestMailBase):
'message_post: notification email sent to more than one email address instead of a precise partner')
self.assertIn(sent_email['email_to'][0], test_emailto,
'message_post: notification email email_to incorrect')
self.assertEqual(sent_email['reply_to'], 'r@r', # was '"Followers of Pigs" <r@r>', but makes no sense
self.assertEqual(email_split(sent_email['reply_to']), ['r@r'], # was '"Followers of Pigs" <r@r>', but makes no sense
'message_post: notification email reply_to incorrect: should have raoul email')
self.assertEqual(_mail_subject, sent_email['subject'],
'message_post: notification email subject incorrect')

View File

@ -20,7 +20,7 @@
##############################################################################
from openerp.addons.mail.tests.test_mail_base import TestMailBase
from openerp.tools import mute_logger
from openerp.tools import mute_logger, email_split
MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
To: {to}
@ -124,6 +124,102 @@ class TestMailgateway(TestMailBase):
self.assertEqual(partner_info['partner_id'], p_b_id,
'mail_thread: message_partner_info_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):
""" Tests designed for testing email values based on mail.message, aliases, ... """
cr, uid = self.cr, self.uid
@ -178,7 +274,7 @@ class TestMailgateway(TestMailBase):
mail_id = self.mail_mail.create(cr, uid, {'mail_message_id': msg_id, 'state': 'cancel'})
mail = self.mail_mail.browse(cr, uid, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, msg.email_from,
self.assertEqual(email_split(mail.reply_to), email_split(msg.email_from),
'mail_mail: reply_to should be equal to mail_message.email_from when having no document or default alias')
# Data: set catchall domain

View File

@ -126,7 +126,6 @@ class mail_compose_message(osv.TransientModel):
_defaults = {
'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={}: '',
'subject': lambda self, cr, uid, ctx={}: False,
'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)
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
not want that feature in the wizard. """
return
@ -235,6 +234,9 @@ class mail_compose_message(osv.TransientModel):
for wizard in self.browse(cr, uid, ids, context=context):
mass_mail_mode = wizard.composition_mode == 'mass_mail'
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
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)
attachment_ids.append(new_attach_id)
post_values['attachment_ids'] = attachment_ids
post_values.update(email_dict)
# email_from: mass mailing only can specify another email_from
if email_dict.get('email_from'):
post_values['email_from'] = email_dict.pop('email_from')
# replies redirection: mass mailing only
if not wizard.same_thread:
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
# could be wrongly interpreted by mail_mail)
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
if not wizard.notify:
subtype = False
context = dict(context, mail_create_nosubscribe=True) # add context key to avoid subscribing the author
msg_id = active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values)
# mass_mailing, post without notify: notify specific partners
if mass_mail_mode and not wizard.notify and post_values['partner_ids']:
self.pool.get('mail.notification')._notify(cr, uid, msg_id, post_values['partner_ids'], context=context)
context = dict(context,
mail_notify_force_send=False, # do not send emails directly but use the queue instead
mail_create_nosubscribe=True) # add context key to avoid subscribing the author
active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values)
return {'type': 'ir.actions.act_window_close'}

View File

@ -20,7 +20,6 @@
##############################################################################
import marketing_campaign
import res_partner
import report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -59,7 +59,6 @@ input segments, workflow.
'marketing_campaign_view.xml',
'marketing_campaign_data.xml',
'marketing_campaign_workflow.xml',
'res_partner_view.xml',
'report/campaign_analysis_view.xml',
'security/marketing_campaign_security.xml',
'security/ir.model.access.csv'

View File

@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields,osv
class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'workitem_ids': fields.one2many('marketing.campaign.workitem',
'partner_id', 'Workitems',
readonly=True),
}
def copy(self, cr, uid, id, default={}, context=None):
default.update({
'workitem_ids': [],
})
return super(res_partner, self).copy(cr, uid, id, default=default, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,23 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Partners inherited form -->
<record id="view_workitem_partner_info_form" model="ir.ui.view">
<field name="name">res.partner.workitem.info.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='page_history']" position="attributes">
<attribute name="invisible">False</attribute>
</xpath>
<xpath expr="//page[@name='page_history']" position="inside">
<group name="grp_campaign" string="Campaigns">
<field name="workitem_ids" colspan="4" nolabel="1"/>
</group>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -440,7 +440,7 @@
<field name="model">mrp.bom</field>
<field name="field_parent">child_complete_ids</field>
<field name="arch" type="xml">
<tree string="Bill of Materials" colors="blue:method">
<tree string="Bill of Materials">
<field name="sequence" invisible="1"/>
<field name="name" invisible="1"/>
<field name="product_id"/>
@ -448,7 +448,6 @@
<field name="product_uom" groups="product.group_uom"/>
<field name="code"/>
<field name="type"/>
<field name="method"/>
<field name="routing_id" groups="mrp.group_mrp_routings"/>
<field name="date_start"/>
<field name="date_stop"/>
@ -460,19 +459,18 @@
<field name="model">mrp.bom</field>
<field name="field_parent">child_complete_ids</field>
<field name="arch" type="xml">
<tree string="BoM Structure" colors="blue:method">
<tree string="BoM Structure">
<field name="sequence" invisible="1"/>
<field name="name" groups="base.group_no_one"/>
<field name="code"/>
<field name="product_id"/>
<field name="bom_id"/>
<field name="bom_id" groups="product.group_mrp_properties"/>
<field name="product_qty"/>
<field name="product_uom" groups="product.group_uom"/>
<field name="type"/>
<field name="method"/>
<field name="routing_id" groups="mrp.group_mrp_routings"/>
<field name="date_start"/>
<field name="date_stop"/>
<field name="date_start" groups="product.group_mrp_properties"/>
<field name="date_stop" groups="product.group_mrp_properties"/>
</tree>
</field>
</record>
@ -545,6 +543,7 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.bom</field>
<field name="domain">[('bom_id', '=',active_ids)]</field>
<field name="view_type">tree</field>
<field name="view_id" ref="mrp_bom_tree_view"/>
</record>
<record id="ir_BOM_structure" model="ir.values">

View File

@ -51,7 +51,7 @@ class pos_config(osv.osv):
'journal_ids' : fields.many2many('account.journal', 'pos_config_journal_rel',
'pos_config_id', 'journal_id', 'Available Payment Methods',
domain="[('journal_user', '=', True ), ('type', 'in', ['bank', 'cash'])]",),
'shop_id' : fields.many2one('sale.shop', 'Shop',
'warehouse_id' : fields.many2one('stock.warehouse', 'Warehouse',
required=True),
'journal_id' : fields.many2one('account.journal', 'Sale Journal',
domain=[('type', '=', 'sale')],
@ -70,6 +70,7 @@ class pos_config(osv.osv):
"to customize the reference numbers of your orders."),
'session_ids': fields.one2many('pos.session', 'config_id', 'Sessions'),
'group_by' : fields.boolean('Group Journal Items', help="Check this if you want to group the Journal Items by Product while closing a Session"),
'pricelist_id': fields.many2one('product.pricelist','Pricelist', required=True)
}
def _check_cash_control(self, cr, uid, ids, context=None):
@ -112,15 +113,21 @@ class pos_config(osv.osv):
res = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale')], limit=1)
return res and res[0] or False
def _default_shop(self, cr, uid, context=None):
res = self.pool.get('sale.shop').search(cr, uid, [])
def _default_warehouse(self, cr, uid, context=None):
user = self.pool.get('res.users').browse(cr, uid, uid, context)
res = self.pool.get('stock.warehouse').search(cr, uid, [('company_id', '=', user.company_id.id)], limit=1, context=context)
return res and res[0] or False
def _default_pricelist(self, cr, uid, context=None):
res = self.pool.get('product.pricelist').search(cr, uid, [('type', '=', 'sale')], limit=1, context=context)
return res and res[0] or False
_defaults = {
'state' : POS_CONFIG_STATE[0][0],
'shop_id': _default_shop,
'warehouse_id': _default_warehouse,
'journal_id': _default_sale_journal,
'group_by' : True,
'pricelist_id': _default_pricelist
}
def set_active(self, cr, uid, ids, context=None):
@ -306,7 +313,7 @@ class pos_session(osv.osv):
# the .xml files as the CoA is not yet installed.
jobj = self.pool.get('pos.config')
pos_config = jobj.browse(cr, uid, config_id, context=context)
context.update({'company_id': pos_config.shop_id.company_id.id})
context.update({'company_id': pos_config.warehouse_id.company_id.id})
if not pos_config.journal_id:
jid = jobj.default_get(cr, uid, ['journal_id'], context=context)['journal_id']
if jid:
@ -333,7 +340,7 @@ class pos_session(osv.osv):
bank_values = {
'journal_id' : journal.id,
'user_id' : uid,
'company_id' : pos_config.shop_id.company_id.id
'company_id' : pos_config.warehouse_id.company_id.id
}
statement_id = self.pool.get('account.bank.statement').create(cr, uid, bank_values, context=context)
bank_statement_ids.append(statement_id)
@ -594,7 +601,7 @@ class pos_order(osv.osv):
_columns = {
'name': fields.char('Order Ref', size=64, required=True, readonly=True),
'company_id':fields.many2one('res.company', 'Company', required=True, readonly=True),
'shop_id': fields.related('session_id', 'config_id', 'shop_id', relation='sale.shop', type='many2one', string='Shop', store=True, readonly=True),
'warehouse_id': fields.related('session_id', 'config_id', 'warehouse_id', relation='stock.warehouse', type='many2one', string='Warehouse', store=True, readonly=True),
'date_order': fields.datetime('Order Date', readonly=True, select=True),
'user_id': fields.many2one('res.users', 'Salesman', help="Person who uses the the cash register. It can be a reliever, a student or an interim employee."),
'amount_tax': fields.function(_amount_all, string='Taxes', digits_compute=dp.get_precision('Point Of Sale'), multi='all'),
@ -638,8 +645,7 @@ class pos_order(osv.osv):
session_ids = self._default_session(cr, uid, context)
if session_ids:
session_record = self.pool.get('pos.session').browse(cr, uid, session_ids, context=context)
shop = self.pool.get('sale.shop').browse(cr, uid, session_record.config_id.shop_id.id, context=context)
return shop.pricelist_id and shop.pricelist_id.id or False
return session_record.config_id.pricelist_id and session_record.config_id.pricelist_id.id or False
return False
_defaults = {
@ -690,8 +696,8 @@ class pos_order(osv.osv):
'auto_picking': True,
}, context=context)
self.write(cr, uid, [order.id], {'picking_id': picking_id}, context=context)
location_id = order.shop_id.warehouse_id.lot_stock_id.id
output_id = order.shop_id.warehouse_id.lot_output_id.id
location_id = order.warehouse_id.lot_stock_id.id
output_id = order.warehouse_id.lot_output_id.id
for line in order.lines:
if line.product_id and line.product_id.type == 'service':

View File

@ -84,7 +84,7 @@
<page string="Extra Info">
<group string="General Information">
<field name="company_id" groups="base.group_multi_company"/>
<field name="shop_id" widget="selection"/>
<field name="warehouse_id" widget="selection" groups="stock.group_locations"/>
<field name="user_id"/>
<field name="pricelist_id" groups="product.group_sale_pricelist" domain="[('type','=','sale')]"/>
<field name="picking_id" readonly="1"/>
@ -769,12 +769,16 @@
</header>
<sheet>
<group>
<field name="name"/>
<field name="shop_id" widget="selection" groups="stock.group_locations" />
<field name="journal_id" widget="selection" />
<field name="sequence_id" readonly="1" groups="base.group_no_one" />
<field name="group_by" groups="account.group_account_user" />
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name"/>
</h1>
<group col="4">
<field name="warehouse_id" widget="selection" groups="stock.group_locations" />
<field name="pricelist_id" groups="product.group_sale_pricelist"/>
<field name="journal_id" widget="selection"/>
<field name="group_by" groups="account.group_account_user"/>
<field name="sequence_id" readonly="1" groups="base.group_no_one"/>
</group>
<separator string="Available Payment Methods" colspan="4"/>
<field name="journal_ids" colspan="4" nolabel="1">
@ -809,7 +813,7 @@
<field name="arch" type="xml">
<tree string="Point of Sale Configuration" colors="grey:state == 'inactive'">
<field name="name" />
<field name="shop_id" />
<field name="warehouse_id" groups="stock.group_locations"/>
<field name="state" />
</tree>
</field>
@ -823,7 +827,7 @@
<field name="name" />
<filter string="Active" domain="[('state', '=', 'active')]" />
<filter string="Inactive" domain="[('state', '=', 'inactive')]" />
<field name="shop_id" />
<field name="warehouse_id" groups="stock.group_locations" />
</search>
</field>
</record>

View File

@ -41,7 +41,7 @@ class pos_order_report(osv.osv):
'price_total':fields.float('Total Price', readonly=True),
'total_discount':fields.float('Total Discount', readonly=True),
'average_price': fields.float('Average Price', readonly=True,group_operator="avg"),
'shop_id':fields.many2one('sale.shop', 'Shop', readonly=True),
'warehouse_id':fields.many2one('stock.warehouse', 'Warehouse', readonly=True),
'company_id':fields.many2one('res.company', 'Company', readonly=True),
'nbr':fields.integer('# of Lines', readonly=True),
'product_qty':fields.integer('# of Qty', readonly=True),
@ -69,7 +69,7 @@ class pos_order_report(osv.osv):
s.partner_id as partner_id,
s.state as state,
s.user_id as user_id,
s.shop_id as shop_id,
s.warehouse_id as warehouse_id,
s.company_id as company_id,
s.sale_journal as journal_id,
l.product_id as product_id
@ -80,7 +80,7 @@ class pos_order_report(osv.osv):
group by
to_char(s.date_order, 'dd-MM-YYYY'),to_char(s.date_order, 'YYYY'),to_char(s.date_order, 'MM'),
to_char(s.date_order, 'YYYY-MM-DD'), s.partner_id,s.state,
s.user_id,s.shop_id,s.company_id,s.sale_journal,l.product_id,s.create_date
s.user_id,s.warehouse_id,s.company_id,s.sale_journal,l.product_id,s.create_date
having
sum(l.qty * u.factor) != 0)""")

View File

@ -13,7 +13,7 @@
<field name="month" invisible="1"/>
<field name="partner_id" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="shop_id" invisible="1"/>
<field name="warehouse_id" invisible="1"/>
<!--<field name="journal_id" invisible="1"/>-->
<field name="company_id" invisible="1" groups="base.group_multi_company"/>
<field name="nbr" sum="# of Lines"/>

View File

@ -75,7 +75,7 @@
<para style="terp_default_Centre_9">[[ address and display_address(address)]]</para>
<para style="terp_default_Centre_9">Tel : [[ address and address.phone ]]</para>
<para style="terp_default_Centre_9">User : [[ o.user_id.name ]]</para>
<para style="terp_default_Centre_9">Shop : [[ o.shop_id.name ]]</para>
<para style="terp_default_Centre_9">Warehouse : [[ o.warehouse_id.name ]]</para>
<para style="terp_default_Centre_9">Date : [[ o.date_order ]]</para>
<para style="P4">
<font color="white"> </font>

View File

@ -8,7 +8,7 @@ access_account_journal_pos_user,account.journal pos_user,account.model_account_j
access_account_move_pos_user,account.move pos_user,account.model_account_move,group_pos_user,1,1,1,0
access_account_account_pos_user,account.account pos_user,account.model_account_account,group_pos_user,1,0,0,0
access_stock_picking_pos_user,stock.picking pos_user,stock.model_stock_picking,group_pos_user,1,1,1,1
access_sale_shop_pos_user,sale.shop pos_user,sale.model_sale_shop,group_pos_user,1,0,0,0
access_stock_warehouse_pos_user,stock.warehouse pos_user,stock.model_stock_warehouse,group_pos_user,1,0,0,0
access_pos_order_stock_worker,pos.order stock_worker,model_pos_order,stock.group_stock_user,1,0,0,0
access_stock_move_pos_user,stock.move pos_user,stock.model_stock_move,group_pos_user,1,1,1,1
access_report_sales_by_user_pos,report.sales.by.user.pos,model_report_sales_by_user_pos,group_pos_user,1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
8 access_account_move_pos_user account.move pos_user account.model_account_move group_pos_user 1 1 1 0
9 access_account_account_pos_user account.account pos_user account.model_account_account group_pos_user 1 0 0 0
10 access_stock_picking_pos_user stock.picking pos_user stock.model_stock_picking group_pos_user 1 1 1 1
11 access_sale_shop_pos_user access_stock_warehouse_pos_user sale.shop pos_user stock.warehouse pos_user sale.model_sale_shop stock.model_stock_warehouse group_pos_user 1 0 0 0
12 access_pos_order_stock_worker pos.order stock_worker model_pos_order stock.group_stock_user 1 0 0 0
13 access_stock_move_pos_user stock.move pos_user stock.model_stock_move group_pos_user 1 1 1 1
14 access_report_sales_by_user_pos report.sales.by.user.pos model_report_sales_by_user_pos group_pos_user 1 0 0 0

View File

@ -142,7 +142,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
return self.fetch(
'pos.config',
['name','journal_ids','shop_id','journal_id',
['name','journal_ids','warehouse_id','journal_id','pricelist_id',
'iface_self_checkout', 'iface_led', 'iface_cashdrawer',
'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard',
'iface_print_via_proxy','iface_cashdrawer','state','sequence_id','session_ids'],
@ -157,7 +157,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
self.iface_self_checkout = !!pos_config.iface_self_checkout;
self.iface_cashdrawer = !!pos_config.iface_cashdrawer;
return self.fetch('sale.shop',[],[['id','=',pos_config.shop_id[0]]]);
return self.fetch('stock.warehouse',[],[['id','=',pos_config.warehouse_id[0]]]);
}).then(function(shops){
self.set('shop',shops[0]);
@ -174,7 +174,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
['name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13',
'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'],
[['sale_ok','=',true],['available_in_pos','=',true]],
{pricelist: self.get('shop').pricelist_id[0]} // context for price
{pricelist: self.get('pos_config').pricelist_id[0]} // context for price
);
}).then(function(products){
self.db.add_products(products);

View File

@ -16,7 +16,8 @@
// hide()s
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({
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
// the button stay local to each screen
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',
click: function(){ self.help_button_action(); },
});
@ -454,7 +455,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
},500);
this.add_action_button({
label: 'back',
label: _t('Back'),
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
click: function(){
clearInterval(this.intervalID);
@ -483,7 +484,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.add_action_button({
label: 'back',
label: _t('Back'),
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
click: function(){
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({
label: 'Validate',
label: _t('Validate'),
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
click: function(){
self.order_product();
@ -674,7 +675,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
}
this.add_action_button({
label: 'back',
label: _t('Back'),
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
click: function(){
self.queue.schedule(self.cancel);
@ -714,7 +715,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
var self = this;
this.add_action_button({
label: 'help',
label: _t('Help'),
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
click: function(){
$('.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'){
this.add_action_button({
label: 'pay',
label: _t('Pay'),
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
click: function(){
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;
this.add_action_button({
label: 'Print',
label: _t('Print'),
icon: '/point_of_sale/static/src/img/icons/png48/printer.png',
click: function(){ self.print(); },
});
this.add_action_button({
label: 'Next Order',
label: _t('Next Order'),
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
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.back_button = this.add_action_button({
label: 'Back',
label: _t('Back'),
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
click: function(){
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({
label: 'Validate',
label: _t('Validate'),
name: 'validation',
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
click: function(){

View File

@ -1,5 +1,6 @@
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
// 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.close_button = new module.HeaderButtonWidget(this,{
label:'Close',
label: _t('Close'),
action: function(){ self.try_close(); },
});
this.close_button.appendTo(this.$('#rightheader'));
this.client_button = new module.HeaderButtonWidget(this,{
label:'Self-Checkout',
label: _t('Self-Checkout'),
action: function(){ self.screen_selector.set_user_mode('client'); },
});
this.client_button.appendTo(this.$('#rightheader'));

View File

@ -112,7 +112,7 @@ class pos_return(osv.osv_memory):
source_stock_id = property_obj.get(cr, uid, 'property_stock_customer', 'res.partner', context=context).id
cr.execute("SELECT s.id FROM stock_location s, stock_warehouse w "
"WHERE w.lot_stock_id=s.id AND w.id=%s ",
(order_id.shop_id.warehouse_id.id,))
(order_id.warehouse_id.id,))
res = cr.fetchone()
location_id = res and res[0] or None
new_picking = picking_obj.copy(cr, uid, order_id.picking_id.id, {'name':'%s (return)' % order_id.name,
@ -205,7 +205,7 @@ class add_product(osv.osv_memory):
stock_dest_id = property_obj.get(cr, uid, 'property_stock_customer', 'res.partner', context=context).id
cr.execute("SELECT s.id FROM stock_location s, stock_warehouse w "
"WHERE w.lot_stock_id=s.id AND w.id=%s ",
(order_id.shop_id.warehouse_id.id,))
(order_id.warehouse_id.id,))
res=cr.fetchone()
location_id=res and res[0] or None
prod_id=prod_obj.browse(cr, uid, prod, context=context)
@ -268,7 +268,7 @@ class add_product(osv.osv_memory):
stock_dest_id = property_obj.get(cr, uid, 'property_stock_customer', 'res.partner', context=context).id
cr.execute("SELECT s.id FROM stock_location s, stock_warehouse w "
" WHERE w.lot_stock_id=s.id AND w.id=%s ",
(order_id.shop_id.warehouse_id.id,))
(order_id.warehouse_id.id,))
res=cr.fetchone()
location_id=res and res[0] or None

View File

@ -37,7 +37,7 @@
<field name="model">hr.employee</field>
<field name="inherit_id" eval="False"/>
<field name="arch" type="xml">
<kanban>
<kanban create="false">
<field name="last_login"/>
<templates>
<t t-name="kanban-box">

View File

@ -11,7 +11,6 @@ access_account_move,account.move,account.model_account_move,portal.group_portal,
access_account_move_line,account.move.line,account.model_account_move_line,portal.group_portal,1,0,0,0
access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,portal.group_portal,1,0,0,0
access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,portal.group_portal,1,0,0,0
access_sale_shop,sale.shop,sale.model_sale_shop,portal.group_portal,1,0,0,0
access_product_list,product.pricelist,product.model_product_pricelist,portal.group_portal,1,0,0,0
access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0,0
access_account_tax,account.tax,account.model_account_tax,portal.group_portal,1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
11 access_account_move_line account.move.line account.model_account_move_line portal.group_portal 1 0 0 0
12 access_account_move_reconcile account.move.reconcile account.model_account_move_reconcile portal.group_portal 1 0 0 0
13 access_account_fiscalyear account.sequence.fiscalyear account.model_account_sequence_fiscalyear portal.group_portal 1 0 0 0
access_sale_shop sale.shop sale.model_sale_shop portal.group_portal 1 0 0 0
14 access_product_list product.pricelist product.model_product_pricelist portal.group_portal 1 0 0 0
15 access_res_partner res.partner base.model_res_partner portal.group_portal 1 0 0 0
16 access_account_tax account.tax account.model_account_tax portal.group_portal 1 0 0 0

View File

@ -256,7 +256,7 @@
<field name="search_view_id" ref="warehouse_orderpoint_search" />
<field name="help" type="html">
<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>
</field>
</record>

View File

@ -10,7 +10,7 @@
<field name="arch" type="xml">
<form string="Procurement Request" version="7.0">
<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
trigger a draft purchase order, a manufacturing order or
a new task.

View File

@ -8,8 +8,8 @@
<field name="arch" type="xml">
<page string="Sales &amp; Purchases" position="inside">
<group>
<group name="pricelists" groups="product.group_sale_pricelist" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<field name="property_product_pricelist"/>
<group name="pricelists" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<field name="property_product_pricelist" groups="product.group_sale_pricelist"/>
</group>
<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>

View File

@ -5,7 +5,7 @@
Resource: product.uom.categ
-->
<record id="product_category_all" model="product.category">
<field name="name">All products</field>
<field name="name">All</field>
</record>
<record id="product_category_1" model="product.category">
<field name="parent_id" ref="product_category_all"/>

View File

@ -60,6 +60,8 @@
</xsl:if>
</xsl:template>
<xsl:param name="pmaxChars" as="xs:integer" select="80"/>
<xsl:template match="lot-line" mode="story">
<blockTable style="mytable" colWidths="2.8cm,5.4cm">
<tr>
@ -75,7 +77,7 @@
<barCode><xsl:value-of select="ean13" /></barCode>
</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>
</td>
</tr>

View File

@ -98,10 +98,10 @@ class sale_order_line(osv.osv):
class account_invoice_line(osv.osv):
_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):
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)
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_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')
price_type_obj = self.pool.get('product.price.type')
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)
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')
uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id)
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
if not pricelist:
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]
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:
if partner_id:
pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id
if not pricelist:
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]
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:
pricelists=pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and real_price != 0):

View File

@ -32,6 +32,7 @@
<separator/>
<filter string="Deadlines" context="{'deadline_visible': False}" domain="[('date_deadline','&lt;&gt;',False)]"
help="Show only tasks having a deadline" icon="terp-gnome-cpu-frequency-applet+"/>
<field name="partner_id"/>
<field name="project_id"/>
<field name="user_id"/>
<group expand="0" string="Group By...">

View File

@ -29,6 +29,14 @@ class res_partner(osv.osv):
'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:

View File

@ -4,28 +4,20 @@
<!-- Partners inherited form -->
<record id="view_task_partner_info_form" model="ir.ui.view">
<field name="name">res.partner.task.info.inherit</field>
<field name="name">res.partner.task.buttons</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="priority" eval="50"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='page_history']" position="attributes">
<attribute name="invisible">False</attribute>
</xpath>
<xpath expr="//page[@name='page_history']" position="inside">
<group name="grp_task" string="Tasks">
<field name="task_ids" colspan="4" nolabel="1">
<tree string="Tasks" editable="bottom">
<field name="name"/>
<field name="user_id"/>
<field name="date_deadline"/>
<field name="state" invisible="1"/>
<button name="do_open" states="pending,draft,done,cancelled" string="Start Task" type="object" icon="gtk-media-play" help="For changing to open state" invisible="context.get('set_visible',False)"/>
<button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/>
</tree>
</field>
</group>
<xpath expr="//div[@name='buttons']" position="inside">
<button class="oe_inline" type="action"
name="%(action_view_task)d"
string="Tasks"
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
groups="project.group_project_user" />
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -283,22 +283,6 @@
</field>
</record>
<record id="view_project_feature_filter" model="ir.ui.view">
<field name="name">Project Issue - Feature Tracker Search</field>
<field name="model">project.issue</field>
<field name="arch" type="xml">
<search string="Feature Tracker Search">
<field name="name" string="Feature description"/>
<field name="date"/>
<field name="state" groups="base.group_no_one"/>
<filter icon="terp-check" domain="[('state','in',('open','draft'))]" help="Current Features" name="current_feature"/>
<filter icon="terp-camera_test" domain="[('state','=','open')]" help="Open Features"/>
<field name="user_id"/>
<field name="project_id" string="Project"/>
</search>
</field>
</record>
<record id="act_project_project_2_project_issue_all" model="ir.actions.act_window">
<field name="res_model">project.issue</field>
<field name="view_type">form</field>
@ -376,16 +360,33 @@
</field>
</record>
<record id="action_view_issues" model="ir.actions.act_window">
<field name="res_model">project.issue</field>
<field name="view_type">form</field>
<field name="name">Issues</field>
<field name="view_mode">kanban,tree,form,calendar,graph</field>
<field name="help" type="html">
<p>
The OpenERP issues tacker allows you to efficiantly manage things
like internal requests, software development bugs, customer
complaints, project troubles, material breakdowns, etc.
</p>
</field>
</record>
<!-- res.partner -->
<record model="ir.ui.view" id="res_partner_issues_button_view">
<field name="name">res.partner.issues.button.view</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="priority" eval="10"/>
<field name="priority" eval="50"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button type="action" string="Issues" attrs="{'invisible': [('customer', '=', False)]}"
name="%(act_project_project_2_project_issue_all)d" context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}" groups="project.group_project_user"/>
<button class="oe_inline" type="action" string="Issues"
attrs="{'invisible': [('customer', '=', False)]}"
name="%(action_view_issues)d"
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
groups="project.group_project_user"/>
</xpath>
</field>
</record>

View File

@ -8,7 +8,7 @@
<field name="priority">36</field>
<field name="arch" type="xml">
<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>
</record>

View File

@ -186,7 +186,7 @@ class purchase_order(osv.osv):
'warehouse_id': fields.many2one('stock.warehouse', 'Destination Warehouse'),
'location_id': fields.many2one('stock.location', 'Destination', required=True, domain=[('usage','<>','view')], states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]} ),
'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]}, help="The pricelist sets the currency used for this purchase order. It also computes the supplier price for the selected products/quantities."),
'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", string="Currency",readonly=True, required=True),
'currency_id': fields.many2one('res.currency','Currency', readonly=True, required=True,states={'draft': [('readonly', False)],'sent': [('readonly', False)]}),
'state': fields.selection(STATE_SELECTION, 'Status', readonly=True, help="The status of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' status. Then the order has to be confirmed by the user, the status switch to 'Confirmed'. Then the supplier must confirm the order to change the status to 'Approved'. When the purchase order is paid and received, the status becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the status becomes in exception.", select=True),
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)],'done':[('readonly',True)]}),
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
@ -237,6 +237,7 @@ class purchase_order(osv.osv):
'pricelist_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').browse(cr, uid, context['partner_id']).property_product_pricelist_purchase.id,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.order', context=c),
'journal_id': _get_journal,
'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
}
_sql_constraints = [
('name_uniq', 'unique(name, company_id)', 'Order Reference must be unique per Company!'),
@ -544,7 +545,7 @@ class purchase_order(osv.osv):
'account_id': pay_acc_id,
'type': 'in_invoice',
'partner_id': order.partner_id.id,
'currency_id': order.pricelist_id.currency_id.id,
'currency_id': order.currency_id.id,
'journal_id': len(journal_ids) and journal_ids[0] or False,
'invoice_line': [(6, 0, inv_lines)],
'origin': order.name,

View File

@ -191,7 +191,7 @@
<field name="partner_id" on_change="onchange_partner_id(partner_id)" context="{'search_default_supplier':1,'default_supplier':1,'default_customer':0}" domain="[('supplier','=',True)]"/>
<field name="partner_ref"/>
<field domain="[('type','=','purchase')]" name="pricelist_id" groups="product.group_purchase_pricelist" on_change="onchange_pricelist(pricelist_id, context)"/>
<field name="currency_id" invisible='1'/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="journal_id" invisible='1'/>
</group>
<group>

View File

@ -70,7 +70,7 @@ class stock_picking(osv.osv):
def get_currency_id(self, cursor, user, picking):
if picking.purchase_id:
return picking.purchase_id.pricelist_id.currency_id.id
return picking.purchase_id.currency_id.id
else:
return super(stock_picking, self).get_currency_id(cursor, user, picking)
@ -129,7 +129,7 @@ class stock_partial_picking(osv.osv_memory):
def _product_cost_for_average_update(self, cr, uid, move):
if move.picking_id.purchase_id:
return {'cost': move.purchase_line_id.price_unit,
'currency': move.picking_id.purchase_id.pricelist_id.currency_id.id}
'currency': move.picking_id.purchase_id.currency_id.id}
return super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move)
# Redefinition of the new field in order to update the model stock.picking.in in the orm

View File

@ -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="search_view_id" ref="stock.view_picking_in_search"/>
<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
orders where the invoicing is "Based on Incoming Shipments",
and for which you have not received a supplier invoice yet.

View File

@ -83,7 +83,7 @@ class purchase_line_invoice(osv.osv_memory):
'account_id': a,
'partner_id': partner.id,
'invoice_line': [(6,0,lines_ids)],
'currency_id' : orders[0].pricelist_id.currency_id.id,
'currency_id' : orders[0].currency_id.id,
'comment': multiple_order_invoice_notes(orders),
'payment_term': orders[0].payment_term_id.id,
'fiscal_position': partner.property_account_position.id

View File

@ -242,8 +242,13 @@ class WebKitParser(report_sxw):
def translate_call(self, src):
"""Translate String."""
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,
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 :
return src
return res

View File

@ -90,7 +90,11 @@
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False"/>
<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 id="view_resource_calendar_attendance_tree" model="ir.ui.view">

View File

@ -40,7 +40,6 @@ class sale_report(osv.osv):
'product_uom_qty': fields.float('# of Qty', readonly=True),
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
'shop_id': fields.many2one('sale.shop', 'Shop', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True),
'price_total': fields.float('Total Price', readonly=True),
@ -79,7 +78,6 @@ class sale_report(osv.osv):
to_char(s.date_order, 'YYYY-MM-DD') as day,
s.partner_id as partner_id,
s.user_id as user_id,
s.shop_id as shop_id,
s.company_id as company_id,
extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
s.state,
@ -103,7 +101,6 @@ class sale_report(osv.osv):
s.date_confirm,
s.partner_id,
s.user_id,
s.shop_id,
s.company_id,
s.state,
s.pricelist_id,

View File

@ -13,7 +13,6 @@
<field name="year" invisible="1"/>
<field name="day" invisible="1"/>
<field name="month" invisible="1"/>
<field name="shop_id" invisible="1"/>
<field name="company_id" invisible="1" groups="base.group_multi_company"/>
<field name="partner_id" invisible="1"/>
<field name="product_id" invisible="1"/>
@ -58,7 +57,6 @@
<field name="product_id"/>
<field name="user_id"/>
<group expand="0" string="Extended Filters...">
<field name="shop_id"/>
<field name="categ_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
@ -70,7 +68,6 @@
<filter string="Category of Product" icon="terp-stock_symbol-selection" name="Category" context="{'group_by':'categ_id'}"/>
<filter string="Analytic Account" icon="terp-folder-green" context="{'group_by':'analytic_account_id'}" groups="analytic.group_analytic_accounting"/>
<filter string="Status" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/>
<filter string="Shop" icon="terp-go-home" context="{'group_by':'shop_id'}"/>
<filter string="Company" icon="terp-go-home" groups="base.group_multi_company" context="{'group_by':'company_id'}"/>
<filter string="Day" icon="terp-go-today" context="{'group_by':'day'}" help="Ordered date of the sales order"/>
<filter string="Month" name="order_month" icon="terp-go-month" context="{'group_by':'month'}" help="Ordered month of the sales order"/>

View File

@ -28,21 +28,6 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO
import openerp.addons.decimal_precision as dp
from openerp import netsvc
class sale_shop(osv.osv):
_name = "sale.shop"
_description = "Sales Shop"
_columns = {
'name': fields.char('Shop Name', size=64, required=True),
'payment_default_id': fields.many2one('account.payment.term', 'Default Payment Term', required=True),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist'),
'project_id': fields.many2one('account.analytic.account', 'Analytic Account', domain=[('parent_id', '!=', False)]),
'company_id': fields.many2one('res.company', 'Company', required=False),
}
_defaults = {
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'sale.shop', context=c),
}
class sale_order(osv.osv):
_name = "sale.order"
_inherit = ['mail.thread', 'ir.needaction_mixin']
@ -54,16 +39,6 @@ class sale_order(osv.osv):
},
}
def onchange_shop_id(self, cr, uid, ids, shop_id, context=None):
v = {}
if shop_id:
shop = self.pool.get('sale.shop').browse(cr, uid, shop_id, context=context)
if shop.project_id.id:
v['project_id'] = shop.project_id.id
if shop.pricelist_id.id:
v['pricelist_id'] = shop.pricelist_id.id
return {'value': v}
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
@ -176,17 +151,15 @@ class sale_order(osv.osv):
result[line.order_id.id] = True
return result.keys()
def _get_default_shop(self, cr, uid, context=None):
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
shop_ids = self.pool.get('sale.shop').search(cr, uid, [('company_id','=',company_id)], context=context)
if not shop_ids:
raise osv.except_osv(_('Error!'), _('There is no default shop for the current user\'s company!'))
return shop_ids[0]
def _get_default_company(self, cr, uid, context=None):
company_id = self.pool.get('res.users')._get_company(cr, uid, context=context)
if not company_id:
raise osv.except_osv(_('Error!'), _('There is no default company for the current user!'))
return company_id
_columns = {
'name': fields.char('Order Reference', size=64, required=True,
readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, select=True),
'shop_id': fields.many2one('sale.shop', 'Shop', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
'origin': fields.char('Source Document', size=64, help="Reference of the document that generated this sales order request."),
'client_order_ref': fields.char('Customer Reference', size=64),
'state': fields.selection([
@ -246,16 +219,16 @@ class sale_order(osv.osv):
'invoice_quantity': fields.selection([('order', 'Ordered Quantities')], 'Invoice on', help="The sales order will automatically create the invoice proposition (draft invoice).", required=True, readonly=True, states={'draft': [('readonly', False)]}),
'payment_term': fields.many2one('account.payment.term', 'Payment Term'),
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
'company_id': fields.related('shop_id','company_id',type='many2one',relation='res.company',string='Company',store=True,readonly=True)
'company_id': fields.many2one('res.company', 'Company'),
}
_defaults = {
'date_order': fields.date.context_today,
'order_policy': 'manual',
'company_id': _get_default_company,
'state': 'draft',
'user_id': lambda obj, cr, uid, context: uid,
'name': lambda obj, cr, uid, context: '/',
'invoice_quantity': 'order',
'shop_id': _get_default_shop,
'partner_invoice_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['invoice'])['invoice'],
'partner_shipping_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['delivery'])['delivery'],
'note': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.sale_note
@ -697,7 +670,7 @@ class sale_order_line(osv.osv):
'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True, readonly=True, states={'draft': [('readonly', False)]}),
'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean',
store={

View File

@ -19,20 +19,6 @@
<field name="object">sale.order</field>
</record>
<!-- Resource: sale.shop -->
<record id="sale_shop_1" model="sale.shop">
<field name="company_id" ref="base.main_company"/>
<field name="payment_default_id" ref="account.account_payment_term_net"/>
<field name="pricelist_id" ref="product.list0"/>
<!-- Copy the name of any company. Without demo data this will yield
the main company name, which is correct. With demo data it will
be random, but it does not matter much -->
<field model="res.company" name="name" search="[]" use="name"/>
</record>
<function eval="('default',False,'shop_id', [('sale.order', False)], sale_shop_1, True, False, False, False, True)" id="sale_default_set" model="ir.values" name="set"/>
<!-- notify all employees of module installation -->
<record model="mail.message" id="module_install_notification">
<field name="model">mail.group</field>

View File

@ -6,7 +6,6 @@
<field name="partner_id" ref="base.res_partner_2"/>
<field name="partner_invoice_id" ref="base.res_partner_2"/>
<field name="partner_shipping_id" ref="base.res_partner_2"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/>
</record>
@ -45,7 +44,6 @@
<field name="partner_id" ref="base.res_partner_7"/>
<field name="partner_invoice_id" ref="base.res_partner_address_13"/>
<field name="partner_shipping_id" ref="base.res_partner_address_13"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
@ -75,7 +73,6 @@
<field name="partner_id" ref="base.res_partner_14"/>
<field name="partner_invoice_id" ref="base.res_partner_14"/>
<field name="partner_shipping_id" ref="base.res_partner_14"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>
@ -105,7 +102,6 @@
<field name="partner_id" ref="base.res_partner_15"/>
<field name="partner_invoice_id" ref="base.res_partner_address_25"/>
<field name="partner_shipping_id" ref="base.res_partner_address_25"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
</record>
@ -154,7 +150,6 @@
<field name="partner_id" ref="base.res_partner_2"/>
<field name="partner_invoice_id" ref="base.res_partner_2"/>
<field name="partner_shipping_id" ref="base.res_partner_2"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/>
</record>
@ -193,7 +188,6 @@
<field name="partner_id" ref="base.res_partner_18"/>
<field name="partner_invoice_id" ref="base.res_partner_18"/>
<field name="partner_shipping_id" ref="base.res_partner_18"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="pricelist_id" ref="product.list0"/>
</record>
@ -261,7 +255,6 @@
<field name="partner_id" ref="base.res_partner_15"/>
<field name="partner_invoice_id" ref="base.res_partner_address_25"/>
<field name="partner_shipping_id" ref="base.res_partner_address_25"/>
<field name="shop_id" ref="sale_shop_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="product.list0"/>
<field name="order_policy">manual</field>

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