[MERGE]sync with trunk

bzr revid: sgo@tinyerp.com-20130620065402-084b1k96gep06i0m
This commit is contained in:
sgo@tinyerp.com 2013-06-20 12:24:02 +05:30
commit 6edcb21cb8
177 changed files with 12982 additions and 2156 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

@ -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-06-07 12:52+0000\n"
"PO-Revision-Date: 2013-06-19 11:49+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-06-08 05:52+0000\n"
"X-Generator: Launchpad (build 16667)\n"
"X-Launchpad-Export-Date: 2013-06-20 05:17+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: account
#: model:process.transition,name:account.process_transition_supplierreconcilepaid0
@ -134,10 +134,10 @@ msgstr ""
#: code:addons/account/account.py:686
#: code:addons/account/account.py:781
#: code:addons/account/account.py:1058
#: code:addons/account/account_invoice.py:817
#: code:addons/account/account_invoice.py:820
#: code:addons/account/account_invoice.py:823
#: code:addons/account/account_invoice.py:1542
#: code:addons/account/account_invoice.py:826
#: code:addons/account/account_invoice.py:1545
#: code:addons/account/account_move_line.py:98
#: code:addons/account/account_move_line.py:771
#: code:addons/account/account_move_line.py:824
@ -257,7 +257,8 @@ msgid ""
"entries."
msgstr ""
"Тип счета используется в информационных целях, при создании официальных "
"отчетов для конкретной страны, определении правил"
"отчетов для конкретной страны, определении правил закрытия финансового года "
"и проводок открытия."
#. module: account
#: field:account.config.settings,sale_refund_sequence_next:0
@ -285,7 +286,7 @@ msgstr "Разрешить списание"
#. module: account
#: view:account.analytic.chart:0
msgid "Select the Period for Analysis"
msgstr "Выберите период для проведения анализа"
msgstr "Выберите период для анализа"
#. module: account
#: model:ir.actions.act_window,help:account.action_invoice_tree3
@ -355,7 +356,7 @@ msgid "Allow multi currencies"
msgstr "Разрешить мульти-валютность"
#. module: account
#: code:addons/account/account_invoice.py:74
#: code:addons/account/account_invoice.py:77
#, python-format
msgid "You must define an analytic journal of type '%s'!"
msgstr "Вы должны определить журнал аналитики типа '%s'!"
@ -757,7 +758,9 @@ msgstr ""
#: selection:account.common.partner.report,result_selection:0
#: selection:account.partner.balance,result_selection:0
#: selection:account.partner.ledger,result_selection:0
#: report:account.third_party_ledger:0
#: code:addons/account/report/account_partner_balance.py:297
#: code:addons/account/report/account_partner_ledger.py:272
#, python-format
msgid "Receivable Accounts"
msgstr "Счета к получению"
@ -797,7 +800,7 @@ msgid "Are you sure you want to create entries?"
msgstr "Вы действительно хотите создать проводки?"
#. module: account
#: code:addons/account/account_invoice.py:1358
#: code:addons/account/account_invoice.py:1361
#, python-format
msgid "Invoice partially paid: %s%s of %s%s (%s%s remaining)."
msgstr "Счет частично оплачен: %s%s из %s%s (%s%s остаток)."
@ -866,7 +869,7 @@ msgid "Type"
msgstr "Тип"
#. module: account
#: code:addons/account/account_invoice.py:823
#: code:addons/account/account_invoice.py:826
#, python-format
msgid ""
"Taxes are missing!\n"
@ -1052,7 +1055,7 @@ msgid "Liability"
msgstr "Обязательства"
#. module: account
#: code:addons/account/account_invoice.py:896
#: code:addons/account/account_invoice.py:899
#, python-format
msgid "Please define sequence on the journal related to this invoice."
msgstr "Пожалуйста, определите нумерацию в журнале, связанном с этим счетом."
@ -1128,8 +1131,8 @@ msgstr "Возможности"
#. module: account
#: code:addons/account/account.py:2346
#: code:addons/account/account_bank_statement.py:424
#: code:addons/account/account_invoice.py:74
#: code:addons/account/account_invoice.py:772
#: code:addons/account/account_invoice.py:77
#: code:addons/account/account_invoice.py:775
#: code:addons/account/account_move_line.py:195
#, python-format
msgid "No Analytic Journal !"
@ -1168,7 +1171,7 @@ msgstr "Название счета."
#. module: account
#: field:account.journal,with_last_closing_balance:0
msgid "Opening With Last Closing Balance"
msgstr ""
msgstr "Открыть с предыдущим остатком"
#. module: account
#: help:account.tax.code,notprintable:0
@ -1567,8 +1570,10 @@ msgid "%s (copy)"
msgstr "%s (копия)"
#. module: account
#: report:account.account.balance:0
#: selection:account.balance.report,display_account:0
#: selection:account.common.account.report,display_account:0
#: report:account.general.ledger_landscape:0
#: selection:account.partner.balance,display_partner:0
#: selection:account.report.general.ledger,display_account:0
msgid "With balance is not equal to 0"
@ -1803,7 +1808,7 @@ msgstr ""
#: view:account.invoice:0
#: view:account.invoice.report:0
#: field:account.move.line,invoice:0
#: code:addons/account/account_invoice.py:1154
#: code:addons/account/account_invoice.py:1157
#: model:ir.model,name:account.model_account_invoice
#: model:res.request.link,name:account.req_link_invoice
#, python-format
@ -2029,6 +2034,12 @@ msgid ""
"useful because it enables you to preview at any time the tax that you owe at "
"the start and end of the month or quarter."
msgstr ""
"Это меню печати налоговой декларации на основе счетов и платежей. Выберите "
"один или несколько периодов финансового года. Информация, необходимая для "
"налоговой декларации генерируется автоматически OpenERP из счета (или "
"платежей, в некоторых странах). Эти данные обновляются в режиме реального "
"времени. Это очень полезно, потому что позволяет просматривать в любое время "
"налоги, которые вы должны в начале и в конце месяца или квартала."
#. module: account
#: code:addons/account/account.py:409
@ -2057,9 +2068,9 @@ msgstr ""
#: code:addons/account/account_bank_statement.py:419
#: code:addons/account/account_cash_statement.py:256
#: code:addons/account/account_cash_statement.py:300
#: code:addons/account/account_invoice.py:896
#: code:addons/account/account_invoice.py:930
#: code:addons/account/account_invoice.py:1121
#: code:addons/account/account_invoice.py:899
#: code:addons/account/account_invoice.py:933
#: code:addons/account/account_invoice.py:1124
#: code:addons/account/account_move_line.py:579
#: code:addons/account/account_move_line.py:828
#: code:addons/account/account_move_line.py:851
@ -2104,7 +2115,7 @@ msgstr ""
" </p><p>\n"
" Вы можете управлять счетом от поставщика в соответствии с\n"
" тем, что вы приобрели. OpenERP также может создавать\n"
" черновые счета автоматически из заказов на закупку.\n"
" черновые счета автоматически из заказов закупки.\n"
" </p>\n"
" "
@ -2230,7 +2241,7 @@ msgstr "Счет - печать журнала"
#. module: account
#: model:ir.model,name:account.model_product_category
msgid "Product Category"
msgstr "Категория ТМЦ"
msgstr "Категория продукции"
#. module: account
#: code:addons/account/account.py:656
@ -2307,7 +2318,9 @@ msgstr "Управление активами"
#: selection:account.common.partner.report,result_selection:0
#: selection:account.partner.balance,result_selection:0
#: selection:account.partner.ledger,result_selection:0
#: report:account.third_party_ledger:0
#: code:addons/account/report/account_partner_balance.py:299
#: code:addons/account/report/account_partner_ledger.py:274
#, python-format
msgid "Payable Accounts"
msgstr "Кредиторская задолженность"
@ -2600,7 +2613,7 @@ msgstr "Учетный год"
#: help:accounting.report,fiscalyear_id:0
#: help:accounting.report,fiscalyear_id_cmp:0
msgid "Keep empty for all open fiscal year"
msgstr "Keep empty for all open fiscal year"
msgstr "Оставьте пустым для всех открытых финансовых лет"
#. module: account
#: code:addons/account/account.py:653
@ -2623,7 +2636,7 @@ msgid "Create an Account Based on this Template"
msgstr "Создать счет на основе этого шаблона"
#. module: account
#: code:addons/account/account_invoice.py:930
#: code:addons/account/account_invoice.py:933
#, python-format
msgid ""
"Cannot create the invoice.\n"
@ -2896,11 +2909,11 @@ msgstr "Счета"
#. module: account
#: code:addons/account/account.py:3541
#: code:addons/account/account_bank_statement.py:405
#: code:addons/account/account_invoice.py:504
#: code:addons/account/account_invoice.py:606
#: code:addons/account/account_invoice.py:621
#: code:addons/account/account_invoice.py:629
#: code:addons/account/account_invoice.py:654
#: code:addons/account/account_invoice.py:507
#: code:addons/account/account_invoice.py:609
#: code:addons/account/account_invoice.py:624
#: code:addons/account/account_invoice.py:632
#: code:addons/account/account_invoice.py:657
#: code:addons/account/account_move_line.py:536
#, python-format
msgid "Configuration Error!"
@ -2932,7 +2945,7 @@ msgstr "Метка"
#. module: account
#: view:res.partner.bank:0
msgid "Accounting Information"
msgstr "Бухгалтерская информация"
msgstr "Учетная информация"
#. module: account
#: view:account.tax:0
@ -3098,6 +3111,8 @@ msgid ""
"Selected invoice(s) cannot be confirmed as they are not in 'Draft' or 'Pro-"
"Forma' state."
msgstr ""
"Выбранные счета нельзя подтвердить, так как состояние не \"Черновик\" и не "
"\"Проформа\""
#. module: account
#: code:addons/account/account.py:1071
@ -3130,7 +3145,7 @@ msgstr "Журнал продаж"
#. module: account
#: code:addons/account/account.py:2346
#: code:addons/account/account_invoice.py:772
#: code:addons/account/account_invoice.py:775
#: code:addons/account/account_move_line.py:195
#, python-format
msgid "You have to define an analytic journal on the '%s' journal!"
@ -3299,7 +3314,7 @@ msgid "Fiscal Position"
msgstr "Система налогообложения"
#. module: account
#: code:addons/account/account_invoice.py:820
#: code:addons/account/account_invoice.py:823
#, python-format
msgid ""
"Tax base different!\n"
@ -3464,7 +3479,7 @@ msgstr "Вид"
#. module: account
#: code:addons/account/account.py:3460
#: code:addons/account/account_bank.py:95
#: code:addons/account/account_bank.py:94
#, python-format
msgid "BNK"
msgstr "BNK"
@ -3734,7 +3749,7 @@ msgstr ""
"иметь названия как и у самого документа"
#. module: account
#: code:addons/account/account_invoice.py:1013
#: code:addons/account/account_invoice.py:1016
#, python-format
msgid ""
"You cannot create an invoice on a centralized journal. Uncheck the "
@ -3749,7 +3764,7 @@ msgid "Starting Balance"
msgstr "Начальный баланс"
#. module: account
#: code:addons/account/account_invoice.py:1462
#: code:addons/account/account_invoice.py:1465
#, python-format
msgid "No Partner Defined !"
msgstr "Партнер не определен!"
@ -4040,9 +4055,13 @@ msgid "VAT :"
msgstr "НДС:"
#. module: account
#: report:account.account.balance:0
#: report:account.central.journal:0
#: view:account.config.settings:0
#: report:account.general.journal:0
#: report:account.general.ledger:0
#: report:account.general.ledger_landscape:0
#: report:account.journal.period.print:0
#: report:account.partner.balance:0
#: report:account.third_party_ledger:0
#: report:account.third_party_ledger_other:0
@ -4145,8 +4164,10 @@ msgstr ""
"условии оплаты контрагента."
#. module: account
#: report:account.account.balance:0
#: selection:account.balance.report,display_account:0
#: selection:account.common.account.report,display_account:0
#: report:account.general.ledger_landscape:0
#: selection:account.report.general.ledger,display_account:0
#: selection:account.tax,type_tax_use:0
#: selection:account.tax.template,type_tax_use:0
@ -4283,7 +4304,7 @@ msgstr "Открыть счет"
#. module: account
#: field:account.invoice.tax,factor_tax:0
msgid "Multipication factor Tax code"
msgstr ""
msgstr "Коэффициент кода налога"
#. module: account
#: field:account.config.settings,complete_tax_set:0
@ -4409,7 +4430,7 @@ msgid "Consolidated Children"
msgstr "Субсчета"
#. module: account
#: code:addons/account/account_invoice.py:570
#: code:addons/account/account_invoice.py:573
#: code:addons/account/wizard/account_invoice_refund.py:146
#, python-format
msgid "Insufficient Data!"
@ -4592,7 +4613,7 @@ msgstr ""
#: field:account.account,shortcut:0
#: field:account.account.template,shortcut:0
msgid "Shortcut"
msgstr "Горячая клвиша"
msgstr "Закладка"
#. module: account
#: view:account.account:0
@ -4666,6 +4687,8 @@ msgid ""
"Error!\n"
"The duration of the Period(s) is/are invalid."
msgstr ""
"Ошибка!\n"
"Не допустимая продолжительность периода."
#. module: account
#: field:account.entries.report,month:0
@ -4690,8 +4713,8 @@ msgid "Supplier invoice sequence"
msgstr "Нумерация счетов поставщиков"
#. module: account
#: code:addons/account/account_invoice.py:607
#: code:addons/account/account_invoice.py:622
#: code:addons/account/account_invoice.py:610
#: code:addons/account/account_invoice.py:625
#, python-format
msgid ""
"Cannot find a chart of account, you should create one from Settings\\"
@ -4826,7 +4849,7 @@ msgstr "Документ из счета или платежа"
msgid ""
"There is currently no company without chart of account. The wizard will "
"therefore not be executed."
msgstr ""
msgstr "Не ни одной компании без плана счетов. Мастер не будет запущен."
#. module: account
#: model:ir.actions.act_window,name:account.action_wizard_multi_chart
@ -4971,7 +4994,7 @@ msgstr ""
"Нельзя создать счет, который имеет родительский счет другой компании."
#. module: account
#: code:addons/account/account_invoice.py:655
#: code:addons/account/account_invoice.py:658
#, python-format
msgid ""
"Cannot find any account journal of %s type for this company.\n"
@ -5019,7 +5042,7 @@ msgstr "Контроль типа"
#. module: account
#: help:account.journal,default_credit_account_id:0
msgid "It acts as a default account for credit amount"
msgstr "Выступает в качестве счета по умолчанию для сумм по кредиту"
msgstr "Используется как кредитовый счет по умолчанию"
#. module: account
#: view:cash.box.out:0
@ -5036,7 +5059,7 @@ msgstr "Отменено"
#. module: account
#: help:account.config.settings,group_proforma_invoices:0
msgid "Allows you to put invoices in pro-forma state."
msgstr ""
msgstr "Позволяет устанавливать статус \"Проформа\" для счетов."
#. module: account
#: view:account.journal:0
@ -5050,6 +5073,7 @@ msgid ""
"It adds the currency column on report if the currency differs from the "
"company currency."
msgstr ""
"Добавляет колонку валюты в отчет, если валюта отлична от валюты компании."
#. module: account
#: code:addons/account/account.py:3394
@ -5281,7 +5305,7 @@ msgstr "Проводки журнала для проверки"
#. module: account
#: selection:res.company,tax_calculation_rounding_method:0
msgid "Round Globally"
msgstr ""
msgstr "Глобальное округление"
#. module: account
#: view:account.bank.statement:0
@ -5295,7 +5319,7 @@ msgid "Tax Application"
msgstr "Применение налога"
#. module: account
#: code:addons/account/account_invoice.py:919
#: code:addons/account/account_invoice.py:922
#, python-format
msgid ""
"Please verify the price of the invoice !\n"
@ -5561,7 +5585,7 @@ msgstr ""
#. module: account
#: view:account.invoice:0
msgid "Pro Forma Invoice "
msgstr "Предварительный счет "
msgstr "Проформа счета "
#. module: account
#: selection:account.subscription,period_type:0
@ -5597,7 +5621,7 @@ msgstr "Прибыль и убыток (счет доходов)"
#. module: account
#: field:account.journal,allow_date:0
msgid "Check Date in Period"
msgstr ""
msgstr "Проверка даты в периоде"
#. module: account
#: model:ir.ui.menu,name:account.final_accounting_reports
@ -5622,7 +5646,7 @@ msgid "Compute Code (if type=code)"
msgstr "Вычислить код (если тип=код)"
#. module: account
#: code:addons/account/account_invoice.py:505
#: code:addons/account/account_invoice.py:508
#, python-format
msgid ""
"Cannot find a chart of accounts for this company, you should create one."
@ -5973,7 +5997,7 @@ msgstr "Сумма в валюте"
#. module: account
#: selection:res.company,tax_calculation_rounding_method:0
msgid "Round per Line"
msgstr ""
msgstr "Округление каждой позиции"
#. module: account
#: report:account.analytic.account.balance:0
@ -6063,7 +6087,7 @@ msgstr "Открыть кассу"
#. module: account
#: selection:account.financial.report,style_overwrite:0
msgid "Automatic formatting"
msgstr ""
msgstr "Автоматическое форматирование"
#. module: account
#: view:account.move.line.reconcile:0
@ -6166,7 +6190,7 @@ msgstr "Доход"
#: view:account.config.settings:0
#: view:account.invoice:0
#: view:account.invoice.report:0
#: code:addons/account/account_invoice.py:387
#: code:addons/account/account_invoice.py:390
#, python-format
msgid "Supplier"
msgstr "Поставщик"
@ -6186,7 +6210,7 @@ msgid "Account n°"
msgstr "№ счета"
#. module: account
#: code:addons/account/account_invoice.py:92
#: code:addons/account/account_invoice.py:95
#, python-format
msgid "Free Reference"
msgstr "Свободная Ссылка"
@ -6196,7 +6220,9 @@ msgstr "Свободная Ссылка"
#: selection:account.common.partner.report,result_selection:0
#: selection:account.partner.balance,result_selection:0
#: selection:account.partner.ledger,result_selection:0
#: report:account.third_party_ledger:0
#: code:addons/account/report/account_partner_balance.py:301
#: code:addons/account/report/account_partner_ledger.py:276
#, python-format
msgid "Receivable and Payable Accounts"
msgstr "Счета дебиторской и кредиторской задолженности"
@ -6323,7 +6349,7 @@ msgstr ""
#. module: account
#: field:account.journal,loss_account_id:0
msgid "Loss Account"
msgstr ""
msgstr "Счет убытков"
#. module: account
#: field:account.tax,account_collected_id:0
@ -6501,7 +6527,7 @@ msgid "Models"
msgstr ""
#. module: account
#: code:addons/account/account_invoice.py:1121
#: code:addons/account/account_invoice.py:1124
#, python-format
msgid ""
"You cannot cancel an invoice which is partially paid. You need to "
@ -6673,7 +6699,7 @@ msgid "You cannot create journal items on closed account."
msgstr ""
#. module: account
#: code:addons/account/account_invoice.py:630
#: code:addons/account/account_invoice.py:633
#, python-format
msgid "Invoice line account's company and invoice's compnay does not match."
msgstr ""
@ -6718,7 +6744,7 @@ msgstr "Собственные средства"
#. module: account
#: field:account.journal,internal_account_id:0
msgid "Internal Transfers Account"
msgstr ""
msgstr "Счет внутренних переводов"
#. module: account
#: code:addons/account/wizard/pos_box.py:32
@ -6734,7 +6760,7 @@ msgstr "Процент"
#. module: account
#: selection:account.config.settings,tax_calculation_rounding_method:0
msgid "Round globally"
msgstr ""
msgstr "Глобальное округление"
#. module: account
#: selection:account.report.general.ledger,sortby:0
@ -6825,7 +6851,7 @@ msgstr ""
#: code:addons/account/account.py:1453
#: code:addons/account/account.py:1482
#: code:addons/account/account.py:1489
#: code:addons/account/account_invoice.py:1012
#: code:addons/account/account_invoice.py:1015
#: code:addons/account/account_move_line.py:1005
#: code:addons/account/wizard/account_automatic_reconcile.py:148
#: code:addons/account/wizard/account_fiscalyear_close.py:88
@ -6912,7 +6938,7 @@ msgstr ""
#: report:account.invoice:0
#: selection:account.invoice,type:0
#: selection:account.invoice.report,type:0
#: code:addons/account/account_invoice.py:1157
#: code:addons/account/account_invoice.py:1160
#: selection:report.invoice.created,type:0
#, python-format
msgid "Supplier Refund"
@ -7553,7 +7579,7 @@ msgstr "Для процентных налогов, введите % как чи
#. module: account
#: model:ir.actions.act_window,name:account.action_account_report_tree_hierarchy
msgid "Financial Reports Hierarchy"
msgstr ""
msgstr "Структура финансовых отчетов"
#. module: account
#: model:ir.actions.act_window,name:account.act_account_invoice_partner_relation
@ -7718,7 +7744,7 @@ msgstr ""
#. module: account
#: field:account.config.settings,group_proforma_invoices:0
msgid "Allow pro-forma invoices"
msgstr ""
msgstr "Разрешить проформы счетов"
#. module: account
#: view:account.bank.statement:0
@ -7789,7 +7815,7 @@ msgstr "Журнал счета"
#. module: account
#: field:account.config.settings,tax_calculation_rounding_method:0
msgid "Tax calculation rounding method"
msgstr ""
msgstr "Метод округления при расчете налога"
#. module: account
#: model:process.node,name:account.process_node_paidinvoice0
@ -7912,7 +7938,7 @@ msgstr "Нормальный"
#: model:ir.actions.act_window,name:account.action_email_templates
#: model:ir.ui.menu,name:account.menu_email_templates
msgid "Email Templates"
msgstr ""
msgstr "Шаблоны писем"
#. module: account
#: view:account.move.line:0
@ -7974,7 +8000,7 @@ msgstr "Нет номера части !"
#: view:account.financial.report:0
#: model:ir.ui.menu,name:account.menu_account_report_tree_hierarchy
msgid "Account Reports Hierarchy"
msgstr ""
msgstr "Структура отчетов по счетам"
#. module: account
#: help:account.account.template,chart_template_id:0
@ -8050,6 +8076,8 @@ msgstr "Отмена выбранных счетов"
msgid ""
"This field is used to generate legal reports: profit and loss, balance sheet."
msgstr ""
"Это поле используется для генерации официальных отчетов: прибыль и убыток, "
"баланс."
#. module: account
#: selection:account.entries.report,month:0
@ -8061,7 +8089,7 @@ msgid "May"
msgstr "Май"
#. module: account
#: code:addons/account/account_invoice.py:817
#: code:addons/account/account_invoice.py:820
#, python-format
msgid "Global taxes defined, but they are not in invoice lines !"
msgstr ""
@ -8102,7 +8130,7 @@ msgstr "Провести записи журнала"
#: view:account.config.settings:0
#: view:account.invoice:0
#: view:account.invoice.report:0
#: code:addons/account/account_invoice.py:385
#: code:addons/account/account_invoice.py:388
#, python-format
msgid "Customer"
msgstr "Заказчик"
@ -8303,7 +8331,7 @@ msgstr ""
#. module: account
#: field:res.company,tax_calculation_rounding_method:0
msgid "Tax Calculation Rounding Method"
msgstr ""
msgstr "Метод округления при расчете налога"
#. module: account
#: field:account.entries.report,move_line_state:0
@ -8357,7 +8385,7 @@ msgid "Select a currency to apply on the invoice"
msgstr "Выбрать валюту применяемую в счете"
#. module: account
#: code:addons/account/account_invoice.py:898
#: code:addons/account/account_invoice.py:901
#, python-format
msgid "No Invoice Lines !"
msgstr "Нет позиций в счете !"
@ -8433,7 +8461,7 @@ msgid "Associated Partner"
msgstr "Связанный контрагент"
#. module: account
#: code:addons/account/account_invoice.py:1462
#: code:addons/account/account_invoice.py:1465
#, python-format
msgid "You must first select a partner !"
msgstr "Сначала вы должны выбрать партнера !"
@ -8998,7 +9026,7 @@ msgstr "Вы уверены?"
#. module: account
#: view:account.journal:0
msgid "Accounts Allowed (empty for no control)"
msgstr "Разрешенные счета (остваьте пустым для снятия проверок)"
msgstr "Разрешенные счета (оставьте пустым для снятия проверок)"
#. module: account
#: field:account.config.settings,sale_tax_rate:0
@ -9384,7 +9412,7 @@ msgid "Purchase Tax(%)"
msgstr "Налог на покупку(%)"
#. module: account
#: code:addons/account/account_invoice.py:898
#: code:addons/account/account_invoice.py:901
#, python-format
msgid "Please create some invoice lines."
msgstr "Пожалуйста, создайте позиции счета"
@ -9396,6 +9424,8 @@ msgid ""
"Please check that the field 'Internal Transfers Account' is set on the "
"payment method '%s'."
msgstr ""
"Пожалуйста, проверьте , что поле \"Счет внутренних переводов\" установлено "
"для способа оплаты '%s'."
#. module: account
#: field:account.vat.declaration,display_detail:0
@ -9448,7 +9478,7 @@ msgstr "Конец периода"
#: model:ir.actions.act_window,name:account.action_account_report
#: model:ir.ui.menu,name:account.menu_account_reports
msgid "Financial Reports"
msgstr ""
msgstr "Финансовые отчеты"
#. module: account
#: model:account.account.type,name:account.account_type_liability_view1
@ -9737,6 +9767,7 @@ msgid ""
"This field contains the information related to the numbering of the journal "
"entries of this journal."
msgstr ""
"Это поле содержит информацию, связанную с нумерацией проводок этого журнала."
#. module: account
#: field:account.invoice,sent:0
@ -9768,7 +9799,7 @@ msgstr ""
#. module: account
#: model:ir.ui.menu,name:account.menu_finance_periodical_processing
msgid "Periodic Processing"
msgstr ""
msgstr "Периодическая обработка"
#. module: account
#: view:account.invoice.report:0
@ -9940,7 +9971,7 @@ msgid "Unreconciled"
msgstr "Не сверенные"
#. module: account
#: code:addons/account/account_invoice.py:919
#: code:addons/account/account_invoice.py:922
#, python-format
msgid "Bad total !"
msgstr "Плохой итог !"
@ -10046,7 +10077,7 @@ msgstr ""
#. module: account
#: field:account.bank.statement.line,name:0
msgid "OBI"
msgstr ""
msgstr "Назначение"
#. module: account
#: help:res.partner,property_account_payable:0
@ -10196,7 +10227,7 @@ msgstr "Апрель"
#. module: account
#: model:account.financial.report,name:account.account_financial_report_profitloss_toreport0
msgid "Profit (Loss) to report"
msgstr ""
msgstr "Прибыль (убыток) в отчет"
#. module: account
#: code:addons/account/account_invoice.py:379
@ -10401,7 +10432,7 @@ msgstr "Всего"
#: code:addons/account/wizard/account_invoice_refund.py:109
#, python-format
msgid "Cannot %s draft/proforma/cancel invoice."
msgstr ""
msgstr "Нельзя %s черновик/проформу/закрытый счет."
#. module: account
#: field:account.tax,account_analytic_paid_id:0
@ -10415,6 +10446,7 @@ msgstr "Открыть для банковской сверки"
#. module: account
#: field:account.account,company_id:0
#: report:account.account.balance:0
#: field:account.aged.trial.balance,company_id:0
#: field:account.analytic.journal,company_id:0
#: field:account.balance.report,company_id:0
@ -10430,7 +10462,9 @@ msgstr "Открыть для банковской сверки"
#: field:account.entries.report,company_id:0
#: field:account.fiscal.position,company_id:0
#: field:account.fiscalyear,company_id:0
#: report:account.general.journal:0
#: field:account.general.journal,company_id:0
#: report:account.general.ledger_landscape:0
#: field:account.installer,company_id:0
#: field:account.invoice,company_id:0
#: field:account.invoice.line,company_id:0
@ -10439,6 +10473,7 @@ msgstr "Открыть для банковской сверки"
#: field:account.invoice.tax,company_id:0
#: field:account.journal,company_id:0
#: field:account.journal.period,company_id:0
#: report:account.journal.period.print:0
#: field:account.model,company_id:0
#: field:account.move,company_id:0
#: field:account.move.line,company_id:0
@ -10603,7 +10638,7 @@ msgstr "Счета системы налогообложения"
#: view:account.invoice:0
#: selection:account.invoice,type:0
#: selection:account.invoice.report,type:0
#: code:addons/account/account_invoice.py:1155
#: code:addons/account/account_invoice.py:1158
#: model:process.process,name:account.process_process_supplierinvoiceprocess0
#: selection:report.invoice.created,type:0
#, python-format
@ -10692,8 +10727,10 @@ msgid ""
msgstr ""
#. module: account
#: report:account.account.balance:0
#: selection:account.balance.report,display_account:0
#: selection:account.common.account.report,display_account:0
#: report:account.general.ledger_landscape:0
#: selection:account.report.general.ledger,display_account:0
msgid "With movements"
msgstr "С движением"
@ -10789,7 +10826,7 @@ msgid "Entries Sorted by"
msgstr ""
#. module: account
#: code:addons/account/account_invoice.py:1543
#: code:addons/account/account_invoice.py:1546
#, python-format
msgid ""
"The selected unit of measure is not compatible with the unit of measure of "
@ -10870,7 +10907,7 @@ msgstr "Искать счет"
#: report:account.invoice:0
#: view:account.invoice:0
#: view:account.invoice.report:0
#: code:addons/account/account_invoice.py:1156
#: code:addons/account/account_invoice.py:1159
#, python-format
msgid "Refund"
msgstr "Возвраты"
@ -10942,7 +10979,7 @@ msgid "Manual Invoice Taxes"
msgstr ""
#. module: account
#: code:addons/account/account_invoice.py:570
#: code:addons/account/account_invoice.py:573
#, python-format
msgid "The payment term of supplier does not have a payment term line."
msgstr ""
@ -11096,7 +11133,7 @@ msgstr ""
#. module: account
#: selection:account.config.settings,tax_calculation_rounding_method:0
msgid "Round per line"
msgstr ""
msgstr "Округление каждой позиции"
#. module: account
#: help:account.move.line,amount_residual_currency:0

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

@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev_rc3\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-05-31 07:35+0000\n"
"PO-Revision-Date: 2013-06-19 13:43+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-06-01 05:16+0000\n"
"X-Generator: Launchpad (build 16660)\n"
"X-Launchpad-Export-Date: 2013-06-20 05:17+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "No order to invoice, create"
msgstr ""
msgstr "Нет заказа для счета, создать"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
@ -39,7 +39,7 @@ msgstr "Остаётся"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "Contracts in progress"
msgstr ""
msgstr "Незавершенные контракты"
#. module: account_analytic_analysis
#: help:account.analytic.account,last_worked_invoiced_date:0
@ -88,7 +88,7 @@ msgstr "Дата последнего счета расходов"
#. module: account_analytic_analysis
#: help:account.analytic.account,fix_price_to_invoice:0
msgid "Sum of quotations for this contract."
msgstr ""
msgstr "Сумма предложений по этому контракту."
#. module: account_analytic_analysis
#: help:account.analytic.account,ca_invoiced:0
@ -98,18 +98,18 @@ msgstr "Итого сумма к оплате заказчику для этог
#. module: account_analytic_analysis
#: help:account.analytic.account,timesheet_ca_invoiced:0
msgid "Sum of timesheet lines invoiced for this contract."
msgstr ""
msgstr "Сумма позиций табеля выставленная в счет за этот контракт ."
#. module: account_analytic_analysis
#: code:addons/account_analytic_analysis/account_analytic_analysis.py:466
#: code:addons/account_analytic_analysis/account_analytic_analysis.py:464
#, python-format
msgid "Sales Order Lines of %s"
msgstr ""
msgstr "Позиции заказа продаж %s"
#. module: account_analytic_analysis
#: help:account.analytic.account,revenue_per_hour:0
msgid "Computed using the formula: Invoiced Amount / Total Time"
msgstr ""
msgstr "Рассчитанный по формуле: Сумма по счетам / Итоговое время"
#. module: account_analytic_analysis
#: field:account_analytic_analysis.summary.month,account_id:0
@ -126,7 +126,7 @@ msgstr "Партнёр"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "Contracts that are not assigned to an account manager."
msgstr ""
msgstr "Контракты, которые не назначены бухгалтеру."
#. module: account_analytic_analysis
#: model:ir.actions.act_window,help:account_analytic_analysis.action_account_analytic_overdue
@ -161,6 +161,7 @@ msgstr "Управляющий счётом"
#: help:account.analytic.account,remaining_hours_to_invoice:0
msgid "Computed using the formula: Maximum Time - Total Invoiced Time"
msgstr ""
"Рассчитанный по формуле: Максимальное время - Всё время выставленное в счетах"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
@ -170,12 +171,12 @@ msgstr "Ожидается"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "Contracts not assigned"
msgstr ""
msgstr "Контракты не назначены"
#. module: account_analytic_analysis
#: help:account.analytic.account,theorical_margin:0
msgid "Computed using the formula: Theoretical Revenue - Total Costs"
msgstr ""
msgstr "Рассчитанный по формуле: теоретическая выручка - общие издержки"
#. module: account_analytic_analysis
#: field:account.analytic.account,hours_qtt_invoiced:0
@ -219,17 +220,17 @@ msgstr ""
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "Nothing to invoice, create"
msgstr ""
msgstr "Нечего выставить в счете, создать"
#. module: account_analytic_analysis
#: model:res.groups,name:account_analytic_analysis.group_template_required
msgid "Mandatory use of templates in contracts"
msgstr ""
msgstr "Обязательное использование шаблонов в контрактах"
#. module: account_analytic_analysis
#: field:account.analytic.account,hours_quantity:0
msgid "Total Worked Time"
msgstr ""
msgstr "Всё отработанное время"
#. module: account_analytic_analysis
#: field:account.analytic.account,real_margin:0
@ -249,12 +250,12 @@ msgstr "Вычисляется по формуле: (Реальная маржа
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "or view"
msgstr ""
msgstr "или вид"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "Customer Contracts"
msgstr ""
msgstr "Контакты заказчика"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
@ -271,7 +272,7 @@ msgstr "Месяц"
#: model:ir.actions.act_window,name:account_analytic_analysis.action_hr_tree_invoiced_all
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_hr_tree_invoiced_all
msgid "Time & Materials to Invoice"
msgstr ""
msgstr "Время и материалы в счет"
#. module: account_analytic_analysis
#: view:account.analytic.account:0
@ -343,9 +344,10 @@ msgstr "К продлению"
#: view:account.analytic.account:0
msgid ""
"A contract in OpenERP is an analytic account having a partner set on it."
msgstr ""
msgstr "Контракт в OpenERP это аналитический счет с установленным партнером."
#. module: account_analytic_analysis
#: view:account.analytic.account:0
#: model:ir.actions.act_window,name:account_analytic_analysis.action_sales_order
msgid "Sales Orders"
msgstr "Заказы продаж"
@ -412,7 +414,7 @@ msgstr ""
#. module: account_analytic_analysis
#: field:account.analytic.account,revenue_per_hour:0
msgid "Revenue per Time (real)"
msgstr ""
msgstr "Выручка за время (реальная)"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,help:account_analytic_analysis.action_account_analytic_overdue_all
@ -578,7 +580,7 @@ msgstr ""
#. module: account_analytic_analysis
#: field:account.analytic.account,est_total:0
msgid "Total Estimation"
msgstr ""
msgstr "Общая оценка"
#. module: account_analytic_analysis
#: field:account.analytic.account,remaining_ca:0

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

@ -43,7 +43,8 @@ account.""",
'depends': ['product', 'purchase'],
'category': 'Accounting & Finance',
'demo': [],
'data': ['product_view.xml',],
'data': ['product_view.xml'],
'test': ['test/anglo_saxon.yml'],
'auto_install': False,
'installable': True,
}

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

@ -0,0 +1,299 @@
-
In order to test anglo_saxon Configure Different Accounts.
-
!record {model: account.account, id: account_anglo_stock_valuation}:
code: X3000
name: Stock Valuation Account- (test)
parent_id: account.cas
type: other
user_type: account.data_account_type_asset
-
Configure Stock Interim account (Received).
-
!record {model: account.account, id: account_anglo_stock_input}:
code: X2800
name: Stock Interim account (Received)
parent_id: account.cos
type: other
user_type: account.data_account_type_expense
-
Configure Stock Interim account (Delivered).
-
!record {model: account.account, id: account_anglo_stock_output}:
code: X2801
name: Stock Interim account (Delivered)
parent_id: account.rev
type: other
user_type: account.data_account_type_income
-
Configure Price difference creditor Account.
-
!record {model: account.account, id: account_anglo_price_difference}:
code: X7095
name: Price difference creditor Account
parent_id: account.cos
type: other
user_type: account.data_account_type_expense
-
Configure Cash Bank Account.
-
!record {model: account.account, id: account_anglo_cash}:
code: X5000
name: Cash/Bank Account
parent_id: account.cash
type: other
user_type: account.data_account_type_asset
-
Configure Creditor Account Payable.
-
!record {model: account.account, id: account_anglo_payable}:
code: X440001
name: Creditor Account Payable
parent_id: account.a_pay
type: other
user_type: account.data_account_type_payable
-
Configure Debtor Account Receivable.
-
!record {model: account.account, id: account_anglo_receivable}:
code: X400001
name: Debtor Account Receivable
parent_id: account.a_recv
type: other
user_type: account.data_account_type_receivable
-
Configure Cost of Good sale Account.
-
!record {model: account.account, id: account_anglo_cogs}:
code: X7000
name: Cost of goods sale account
parent_id: account.o_expense
type: other
user_type: account.data_account_type_expense
-
Configure Income Account.
-
!record {model: account.account, id: account_anglo_income}:
code: X8000
name: Income Account
parent_id: account.o_income
type: other
user_type: account.data_account_type_income
-
I configure the account receivable of supplier
-
!record {model: res.partner, id: base.res_partner_3}:
property_account_payable: account_anglo_payable
property_account_receivable: account_anglo_receivable
-
I configure the account receivable of Customer.
-
!record {model: res.partner, id: base.res_partner_13}:
property_account_payable: account_anglo_payable
property_account_receivable: account_anglo_receivable
-
I configure the product category with stock valuation account.
-
!record {model: product.category, id: product.product_category_4}:
property_stock_valuation_account_id: account_anglo_stock_valuation
-
I configure the product with required accounts, and cost method = standard
-
!python {model: product.product}: |
self.write(cr, uid, [ref('product.product_product_3')], {'list_price': 20.00,'standard_price': 9,'categ_id': ref('product.product_category_4'),'valuation': 'real_time',
'property_account_income': ref('account_anglo_income'),'property_account_expense': ref('account_anglo_cogs'),
'property_account_creditor_price_difference': ref('account_anglo_price_difference'),'property_stock_account_input': ref('account_anglo_stock_input'),
'property_stock_account_output': ref('account_anglo_stock_output'), 'cost_method': 'standard'})
-
I create a draft Purchase Order.
-
!record {model: purchase.order, id: purchase_order_001}:
partner_id: base.res_partner_3
location_id: stock.stock_location_3
pricelist_id: 1
order_line:
- product_id: product.product_product_3
product_qty: 1
price_unit: 10
date_planned: '2013-08-31'
-
I confirm the purchase order.
-
!workflow {model: purchase.order, ref: purchase_order_001, action: purchase_confirm}
-
Reception is ready for process so now done the reception.
-
!python {model: stock.partial.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001")).picking_ids
partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_partial(cr, uid, [partial_id])
-
I check the Stock Interim account (Received) is credit successfully.
-
!assert {model: account.account, id : account_anglo_stock_input, string : Stock Interim account (Received) is not credited successfully.}:
- credit == 9
-
I check the Stock valuation account is debit sucessfully.
-
!assert {model: account.account, id : account_anglo_stock_valuation, string : Stock valuation account is not debited successfully.}:
- debit == 9
-
I Validate Invoice of Purchase Order.
-
!python {model: purchase.order}: |
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001")).invoice_ids]
self.pool.get('account.invoice').signal_invoice_open(cr, uid, invoice_ids)
-
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
-
!assert {model: account.account, id : account_anglo_stock_input, string : Stock Interim account (Received) is not debited successfully.}:
- debit == 9
-
I check the Price difference creditor Account is debited sucessfully when Invoice validated.
-
!assert {model: account.account, id : account_anglo_price_difference, string : Price difference creditor Account is not debited successfully.}:
- debit == 1
-
I check Payable(creditor) Account is Credited sucessfully when Invoice validated.
-
!assert {model: account.account, id : account_anglo_payable, string : Payable(creditor) Account is not Credited successfully.}:
- credit == 10
-
I open the Invoice.
-
!python {model: purchase.order}: |
po = self.browse(cr, uid, ref("purchase_order_001"))
for invoice in po.invoice_ids:
self.pool.get('account.invoice').signal_invoice_open(cr, uid, [invoice.id])
-
I pay the invoice.
-
!python {model: purchase.order}: |
invoice_ids = self.browse(cr, uid, ref("purchase_order_001")).invoice_ids
order = self.browse(cr, uid, ref("purchase_order_001"))
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
for invoice in invoice_ids:
invoice.pay_and_reconcile(invoice.amount_total, ref('account_anglo_cash'), ref('account.period_8'), journal_ids[0], ref('account_anglo_cash'), ref('account.period_8'), journal_ids[0], name='test')
-
I check Payable(Creditors) Account is Debited sucessfully after invoice paid.
-
!assert {model: account.account, id : account_anglo_payable, string : Payable(Creditors) Account is not Debited successfully.}:
- debit == 10
-
I check Bank/Cash account is credited sucessfully after invoice paid.
-
!assert {model: account.account, id : account_anglo_cash, string: Bank/Cash account is not credited successfully.}:
- credit == 10
-
I create an Outgoing Picking order
-
!record {model: stock.picking, id: stock_picking_out001}:
partner_id: base.res_partner_13
invoice_state: 2binvoiced
move_lines:
- company_id: base.main_company
location_id: stock.stock_location_3
product_id: product.product_product_3
product_qty: 1.0
product_uom: product.product_uom_unit
location_dest_id: stock.stock_location_customers
move_type: direct
type: out
-
I need to check the availability of the product, So I make my picking order for processing later.
-
!python {model: stock.picking}: |
self.draft_force_assign(cr, uid, [ref("stock_picking_out001")], {"lang": "en_US", "search_default_available":
1, "tz": False, "active_model": "ir.ui.menu", "contact_display": "partner",
"active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"),
})
-
I check the product availability, Product is available in the stock and ready to be sent.
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("stock_picking_out001")], {"lang": "en_US", "search_default_available":
1, "tz": False, "active_model": "ir.ui.menu", "contact_display": "partner",
"active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"),
})
-
I process the delivery.
-
!python {model: stock.partial.picking}: |
partial_id = self.create(cr, uid, {}, context={'active_model':'stock.picking','active_ids':[ref('stock_picking_out001')]})
self.do_partial(cr, uid, [partial_id])
-
I check Stock Interim account (Delivery) is debited successfully.
-
!assert {model: account.account, id : account_anglo_stock_output, string : Stock Interim account (Delivery) is not debited successfully.}:
- debit == 9
-
I check the Stock valuation account is credited sucessfully.
-
!assert {model: account.account, id : account_anglo_stock_valuation, string : Stock valuation account is not credited successfully.}:
- credit == 9
-
As the Invoice state of the picking order is To be invoiced. I create invoice for my outgoing picking order.
-
!python {model: stock.invoice.onshipping}: |
wiz_id = self.create(cr, uid, {'invoice_date': '2013-03-04', 'journal_id': ref('account.sales_journal')},
{'active_ids': [ref("stock_picking_out001")], "active_model": "stock.picking"})
self.create_invoice(cr, uid, [wiz_id], {"lang": "en_US",
"search_default_available": 1, "tz": False, "active_model": "stock.picking",
"contact_display": "partner", "active_ids": [ref("stock_picking_out001")], "active_id": ref("stock_picking_out001")})
-
I check that the customer invoice is created successfully.
-
!python {model: account.invoice}: |
partner_id = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001')).partner_id.id
inv_ids = self.search(cr, uid, [('type','=','out_invoice'),('partner_id','=',partner_id)])
assert inv_ids, 'No Invoice is generated!'
-
I open the Invoice.
-
!python {model: stock.picking}: |
move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001')).name
account_invoice = self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)])
self.pool.get('account.invoice').signal_invoice_open(cr, uid, account_invoice)
-
I check Income Account is Credited sucessfully when Invoice validated.
-
!assert {model: account.account, id : account_anglo_income, string : Income Account is not Credited successfully.}:
- credit == 20
-
I check Cost of goods sold account for debit.
-
!assert {model: account.account, id : account_anglo_cogs, string : Cost of goods sale is not Debited successfully.}:
- debit == 9
-
I check Stock Interim account (Delivery)
-
!assert {model: account.account, id : account_anglo_stock_output, string : Stock Interim account (Delivery) is not credited successfully.}:
- credit == 9
-
I check Receivable(Debtor) Account for debit.
-
!assert {model: account.account, id : account_anglo_receivable, string : Receivable(Debtors) Account is not Debited successfully.}:
- debit == 20
-
I pay the invoice.
-
!python {model: account.invoice}: |
move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001')).name
account_invoice= self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)])
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash')], limit=1)
pay = self.pay_and_reconcile(cr, uid, account_invoice,
20.0, ref('account_anglo_cash'), ref('account.period_8'),
journal_ids[0], ref('account_anglo_cash'),
ref('account.period_8'), journal_ids[0],
name='Payment for test customer invoice')
assert (pay == True), "Incorrect Payment."
-
I check Receivable(Debtor) Account for credit.
-
!assert {model: account.account, id : account_anglo_receivable, string : Receivable(Debtors) Account is not Credited successfully.}:
- credit == 20
-
I check Bank/Cash account is debited sucessfully after invoice paid.
-
!assert {model: account.account, id : account_anglo_cash, string: Bank/Cash account is not successfully credited.}:
- debit == 20

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

@ -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:05+0000\n"
"PO-Revision-Date: 2013-05-27 12:19+0000\n"
"Last-Translator: leksei <lirgus@gmail.com>\n"
"PO-Revision-Date: 2013-06-17 10: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-28 05:17+0000\n"
"X-Generator: Launchpad (build 16640)\n"
"X-Launchpad-Export-Date: 2013-06-18 05:46+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: base_setup
#: view:sale.config.settings:0
@ -92,7 +92,7 @@ msgstr "Общие настройки"
#. module: base_setup
#: selection:base.setup.terminology,partner:0
msgid "Donor"
msgstr ""
msgstr "Спонсор"
#. module: base_setup
#: view:base.config.settings:0
@ -147,7 +147,7 @@ msgstr "res_config_contents"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Customer Features"
msgstr ""
msgstr "Свойства заказчика"
#. module: base_setup
#: view:base.config.settings:0
@ -157,7 +157,7 @@ msgstr "Импорт / Экспорт"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Sale Features"
msgstr ""
msgstr "Свойства продаж"
#. module: base_setup
#: field:sale.config.settings,module_plugin_outlook:0
@ -232,7 +232,7 @@ msgstr ""
#. module: base_setup
#: model:ir.model,name:base_setup.model_sale_config_settings
msgid "sale.config.settings"
msgstr ""
msgstr "sale.config.settings"
#. module: base_setup
#: field:base.setup.terminology,partner:0
@ -263,7 +263,7 @@ msgstr ""
#. module: base_setup
#: model:ir.model,name:base_setup.model_base_setup_terminology
msgid "base.setup.terminology"
msgstr ""
msgstr "base.setup.terminology"
#. module: base_setup
#: selection:base.setup.terminology,partner:0

View File

@ -31,7 +31,7 @@ Lets the user create a custom dashboard.
Allows users to create custom dashboard.
""",
'author': 'OpenERP SA',
'depends': ['base'],
'depends': ['base', 'web'],
'data': [
'security/ir.model.access.csv',
'board_view.xml',

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

@ -0,0 +1,85 @@
# Danish 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-19 17:34+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Danish <da@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-20 05:17+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: crm_todo
#: model:ir.model,name:crm_todo.model_project_task
msgid "Task"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "Timebox"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "Lead"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "For cancelling the task"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "Next"
msgstr ""
#. module: crm_todo
#: model:ir.actions.act_window,name:crm_todo.crm_todo_action
#: model:ir.ui.menu,name:crm_todo.menu_crm_todo
msgid "My Tasks"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
#: field:crm.lead,task_ids:0
msgid "Tasks"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "Done"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "Cancel"
msgstr ""
#. module: crm_todo
#: model:ir.model,name:crm_todo.model_crm_lead
msgid "Lead/Opportunity"
msgstr ""
#. module: crm_todo
#: field:project.task,lead_id:0
msgid "Lead / Opportunity"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "For changing to done state"
msgstr ""
#. module: crm_todo
#: view:crm.lead:0
msgid "Previous"
msgstr ""

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

@ -0,0 +1,90 @@
# Danish 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-19 17:36+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Danish <da@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-20 05:17+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: event_sale
#: model:ir.model,name:event_sale.model_product_product
msgid "Product"
msgstr ""
#. module: event_sale
#: help:product.product,event_ok:0
msgid ""
"Determine if a product needs to create automatically an event registration "
"at the confirmation of a sales order line."
msgstr ""
#. module: event_sale
#: help:sale.order.line,event_id:0
msgid ""
"Choose an event and it will automatically create a registration for this "
"event."
msgstr ""
#. module: event_sale
#: model:event.event,name:event_sale.event_technical_training
msgid "Technical training in Grand-Rosiere"
msgstr ""
#. module: event_sale
#: help:product.product,event_type_id:0
msgid ""
"Select event types so when we use this product in sales order lines, it will "
"filter events of this type only."
msgstr ""
#. module: event_sale
#: field:product.product,event_type_id:0
msgid "Type of Event"
msgstr ""
#. module: event_sale
#: field:sale.order.line,event_ok:0
msgid "event_ok"
msgstr ""
#. module: event_sale
#: field:product.product,event_ok:0
msgid "Event Subscription"
msgstr ""
#. module: event_sale
#: field:sale.order.line,event_type_id:0
msgid "Event Type"
msgstr ""
#. module: event_sale
#: model:product.template,name:event_sale.event_product_product_template
msgid "Technical Training"
msgstr ""
#. module: event_sale
#: code:addons/event_sale/event_sale.py:88
#, python-format
msgid "The registration %s has been created from the Sales Order %s."
msgstr ""
#. module: event_sale
#: field:sale.order.line,event_id:0
msgid "Event"
msgstr ""
#. module: event_sale
#: model:ir.model,name:event_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

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

1912
addons/fleet/i18n/bg.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,5 +23,6 @@ import hr_department
import hr
import res_config
import res_users
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -59,6 +59,8 @@ You can manage:
'hr_installer.xml',
'hr_data.xml',
'res_config_view.xml',
'mail_hr_view.xml',
'res_users_view.xml',
],
'demo': ['hr_demo.xml'],
'test': [
@ -69,5 +71,7 @@ You can manage:
'application': True,
'auto_install': False,
'css': [ 'static/src/css/hr.css' ],
'js': [ 'static/src/js/suggestions.js' ],
'qweb': [ 'static/src/xml/suggestions.xml' ],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -25,9 +25,11 @@ from openerp.modules.module import get_module_resource
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp import tools
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
class hr_employee_category(osv.osv):
def name_get(self, cr, uid, ids, context=None):
@ -150,6 +152,7 @@ class hr_job(osv.osv):
class hr_employee(osv.osv):
_name = "hr.employee"
_description = "Employee"
_order = 'name_related'
_inherits = {'resource.resource': "resource_id"}
_inherit = ['mail.thread']
@ -158,10 +161,10 @@ class hr_employee(osv.osv):
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
#we need a related field in order to be able to sort the employee by name
'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
@ -171,12 +174,12 @@ class hr_employee(osv.osv):
'sinid': fields.char('SIN No', size=32, help="Social Insurance Number"),
'identification_id': fields.char('Identification No', size=32),
'otherid': fields.char('Other Id', size=64),
'gender': fields.selection([('male', 'Male'),('female', 'Female')], 'Gender'),
'gender': fields.selection([('male', 'Male'), ('female', 'Female')], 'Gender'),
'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
'department_id':fields.many2one('hr.department', 'Department'),
'department_id': fields.many2one('hr.department', 'Department'),
'address_id': fields.many2one('res.partner', 'Working Address'),
'address_home_id': fields.many2one('res.partner', 'Home Address'),
'bank_account_id':fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
'work_phone': fields.char('Work Phone', size=32, readonly=False),
'mobile_phone': fields.char('Work Mobile', size=32, readonly=False),
'work_email': fields.char('Work Email', size=240),
@ -207,25 +210,42 @@ class hr_employee(osv.osv):
help="Small-sized photo of the employee. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'passport_id':fields.char('Passport No', size=64),
'passport_id': fields.char('Passport No', size=64),
'color': fields.integer('Color Index'),
'city': fields.related('address_id', 'city', type='char', string='City'),
'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
}
_order='name_related'
def _get_default_image(self, cr, uid, context=None):
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
defaults = {
'active': 1,
'image': _get_default_image,
'color': 0,
}
def create(self, cr, uid, data, context=None):
employee_id = super(hr_employee, self).create(cr, uid, data, context=context)
try:
(model, mail_group_id) = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'group_all_employees')
employee = self.browse(cr, uid, employee_id, context=context)
self.pool.get('mail.group').message_post(cr, uid, [mail_group_id],
body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
subtype='mail.mt_comment', context=context)
except:
pass # group deleted: do not push a message
if context is None:
context = {}
create_ctx = dict(context, mail_create_nolog=True)
employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
employee = self.browse(cr, uid, employee_id, context=context)
if employee.user_id:
# send a copy to every user of the company
company_id = employee.user_id.partner_id.company_id.id
partner_ids = self.pool.get('res.partner').search(cr, uid, [
('company_id', '=', company_id),
('user_ids', '!=', False)], context=context)
else:
partner_ids = []
self.message_post(cr, uid, [employee_id],
body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
partner_ids=partner_ids,
subtype='mail.mt_comment', context=context
)
return employee_id
def unlink(self, cr, uid, ids, context=None):
@ -246,7 +266,7 @@ class hr_employee(osv.osv):
company_id = self.pool.get('res.company').browse(cr, uid, company, context=context)
address = self.pool.get('res.partner').address_get(cr, uid, [company_id.partner_id.id], ['default'])
address_id = address and address['default'] or False
return {'value': {'address_id' : address_id}}
return {'value': {'address_id': address_id}}
def onchange_department_id(self, cr, uid, ids, department_id, context=None):
value = {'parent_id': False}
@ -259,17 +279,36 @@ class hr_employee(osv.osv):
work_email = False
if user_id:
work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).email
return {'value': {'work_email' : work_email}}
return {'value': {'work_email': work_email}}
def _get_default_image(self, cr, uid, context=None):
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
def action_follow(self, cr, uid, ids, context=None):
""" Wrapper because message_subscribe_users take a user_ids=None
that receive the context without the wrapper. """
return self.message_subscribe_users(cr, uid, ids, context=context)
_defaults = {
'active': 1,
'image': _get_default_image,
'color': 0,
}
def action_unfollow(self, cr, uid, ids, context=None):
""" Wrapper because message_unsubscribe_users take a user_ids=None
that receive the context without the wrapper. """
return self.message_unsubscribe_users(cr, uid, ids, context=context)
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
"""Show the suggestion of employees if display_employees_suggestions if the
user perference allows it. """
user = self.pool.get('res.users').browse(cr, uid, uid, context)
if not user.display_employees_suggestions:
return []
else:
return super(hr_employee, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
""" Overwrite of the original method to always follow user_id field,
even when not track_visibility so that a user will follow it's employee
"""
user_field_lst = []
for name, column_info in self._all_columns.items():
if name in auto_follow_fields and name in updated_fields and column_info.column._obj == 'res.users':
user_field_lst.append(name)
return user_field_lst
def _check_recursion(self, cr, uid, ids, context=None):
level = 100
@ -285,6 +324,22 @@ class hr_employee(osv.osv):
(_check_recursion, 'Error! You cannot create recursive hierarchy of Employee(s).', ['parent_id']),
]
# ---------------------------------------------------
# Mail gateway
# ---------------------------------------------------
def check_mail_message_access(self, cr, uid, mids, operation, model_obj=None, context=None):
""" mail.message document permission rule: can post a new message if can read
because of portal document. """
if not model_obj:
model_obj = self
employee_ids = model_obj.search(cr, uid, [('user_id', '=', uid)], context=context)
if employee_ids and operation == 'create':
model_obj.check_access_rights(cr, uid, 'read')
model_obj.check_access_rule(cr, uid, mids, 'read', context=context)
else:
return super(hr_employee, self).check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context)
class hr_department(osv.osv):
_description = "Department"

View File

@ -27,6 +27,10 @@
</h1>
<label for="category_ids" class="oe_edit_only" groups="base.group_hr_user"/>
<field name="category_ids" widget="many2many_tags" placeholder="e.g. Part Time" groups="base.group_hr_user"/>
<label for="work_email" class="oe_edit_only"/>
<field name="work_email" widget="email"/>
<label for="work_phone" class="oe_edit_only"/>
<field name="work_phone"/>
</div>
<div class="oe_right oe_button_box" name="button_box">
<!-- Put here related buttons -->
@ -36,8 +40,6 @@
<group>
<group string="Contact Information">
<field name="address_id" on_change="onchange_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True, "highlight_first_line": True}'/>
<field name="work_email" widget="email"/>
<field name="work_phone"/>
<field name="mobile_phone"/>
<field name="work_location"/>
</group>
@ -136,6 +138,9 @@
<field name="arch" type="xml">
<kanban>
<field name="last_login"/>
<field name="message_is_follower"/>
<field name="message_follower_ids"/>
<field name="message_ids"/>
<templates>
<t t-name="kanban-box">
<div class="oe_employee_vignette">
@ -154,10 +159,19 @@
</li>
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
<li t-if="record.work_location.raw_value"><field name="work_location"/></li>
<li t-if="record.work_phone.raw_value">Tel: <field name="work_phone"/></li>
<li t-if="record.mobile_phone.raw_value">Mobile: <field name="mobile_phone"/></li>
<li t-if="record.work_email.raw_value"><a t-attf-href="mailto:#{record.work_email.value}"><field name="work_email"/></a></li>
</ul>
<div class="oe_kanban_footer_left">
<span title='Messages'><span class='oe_e'>9</span><t t-esc="record.message_ids.raw_value.length"/></span>
<span title='Followers'><span class='oe_e'>+</span><t t-esc="record.message_follower_ids.raw_value.length"/></span>
</div>
<div class="oe_followers" groups="base.group_user">
<button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="oe_follower oe_following">
<span class="oe_unfollow">Unfollow</span>
<span class="oe_following">Following</span>
</button>
<button t-if="! record.message_is_follower.raw_value" name="action_follow" type="object" class="oe_follower oe_notfollow">Follow</button>
</div>
</div>
</div>
<script>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="mail.action_mail_inbox_feeds" model="ir.actions.client">
<field name="params" eval="&quot;{
'domain': [
('to_read', '=', True),
('starred', '=', False),
],
'view_mailbox': True,
'view_inbox': True,
'read_action': 'read',
'show_compose_message': True
}&quot;"/>
</record>
</data>
</openerp>

65
addons/hr/res_users.py Normal file
View File

@ -0,0 +1,65 @@
from openerp.osv import fields, osv
from openerp.tools.translate import _
class res_users(osv.Model):
""" Update of res.users class
- if adding groups to an user, check if base.group_user is in it
(member of 'Employee'), create an employee form linked to it.
"""
_name = 'res.users'
_inherit = ['res.users']
_columns = {
'display_employees_suggestions': fields.boolean("Display Employees Suggestions"),
}
_defaults = {
'display_employees_suggestions': True,
}
def __init__(self, pool, cr):
""" Override of __init__ to add access rights on
display_employees_suggestions fields. Access rights are disabled by
default, but allowed on some specific fields defined in
self.SELF_{READ/WRITE}ABLE_FIELDS.
"""
init_res = super(res_users, self).__init__(pool, cr)
# duplicate list to avoid modifying the original reference
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
self.SELF_WRITEABLE_FIELDS.append('display_employees_suggestions')
# duplicate list to avoid modifying the original reference
self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
self.SELF_READABLE_FIELDS.append('display_employees_suggestions')
return init_res
def stop_showing_employees_suggestions(self, cr, uid, user_id, context=None):
"""Update display_employees_suggestions value to False"""
if context is None:
context = {}
self.write(cr, uid, user_id, {"display_employees_suggestions": False}, context)
def _create_welcome_message(self, cr, uid, user, context=None):
"""Do not welcome new users anymore, welcome new employees instead"""
return True
def _message_post_get_eid(self, cr, uid, thread_id, context=None):
assert thread_id, "res.users does not support posting global messages"
if context and 'thread_model' in context:
context['thread_model'] = 'hr.employee'
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id[0]
return self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', thread_id)], context=context)
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
""" Redirect the posting of message on res.users to the related employee.
This is done because when giving the context of Chatter on the
various mailboxes, we do not have access to the current partner_id. """
if kwargs.get('type') == 'email':
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
employee_ids = self._message_post_get_eid(cr, uid, thread_id, context=context)
if not employee_ids:
pass # dpo something
for employee_id in employee_ids:
res = self.pool.get('hr.employee').message_post(cr, uid, employee_id, context=context, **kwargs)
return res

View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Update user form !-->
<record id="view_users_form_mail" model="ir.ui.view">
<field name="name">res.users.form.hr</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="mail.view_users_form_mail"/>
<field name="arch" type="xml">
<data>
<field name="display_groups_suggestions" position="after">
<field name="display_employees_suggestions"/>
</field>
</data>
</field>
</record>
</data>
</openerp>

View File

@ -68,3 +68,8 @@
margin: 2px 0;
padding: 0;
}
.openerp .oe_employee_vignette .oe_followers {
width: auto;
float: none;
}

View File

@ -0,0 +1,78 @@
openerp.hr = function(session) {
var _t = session.web._t;
var QWeb = session.web.qweb;
var suggestions = session.suggestions;
var removed_suggested_employee = session.suggestions.removed_suggested_employee = [];
suggestions.Employees = session.web.Widget.extend({
events: {
'click .oe_suggestion_remove.oe_suggestion_employee': 'stop_employee_suggestion',
'click .oe_suggestion_remove_item.oe_suggestion_employee': 'remove_employee_suggestion',
'click .oe_suggestion_follow': 'follow_employee',
},
init: function () {
this._super(this, arguments);
this.hr_employee = new session.web.DataSetSearch(this, 'hr.employee');
this.res_users = new session.web.DataSetSearch(this, 'res.users');
this.employees = [];
},
start: function () {
this._super.apply(this, arguments);
return this.fetch_suggested_employee();
},
fetch_suggested_employee: function () {
var self = this;
var employee = self.hr_employee.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_employee}).then(function (res) {
_(res).each(function (result) {
result['image']=self.session.url('/web/binary/image', {model: 'hr.employee', field: 'image_small', id: result.id});
});
self.employees = res;
});
return $.when(employee).done(this.proxy('display_suggested_employees'));
},
display_suggested_employees: function () {
var suggested_employees = this.$('.oe_sidebar_suggestion.oe_suggestion_employee');
if (suggested_employees) {
suggested_employees.remove();
}
if (this.employees.length === 0) {
return this.$el.empty();
}
return this.$el.empty().html(QWeb.render('hr.suggestions.employees', {'widget': this}));
},
follow_employee: function (event) {
var self = this;
var employee_id = parseInt($(event.currentTarget).attr('id'), 10);
return this.hr_employee.call('message_subscribe_users', [[employee_id], [this.session.uid], undefined]).then(function(res) {
self.fetch_suggested_employee();
});
},
remove_employee_suggestion: function (event) {
removed_suggested_employee.push($(event.currentTarget).attr('id'));
return this.fetch_suggested_employee();
},
stop_employee_suggestion: function (event) {
var self = this;
return this.res_users.call('stop_showing_employees_suggestions', [this.session.uid]).then(function(res) {
self.$(".oe_sidebar_suggestion.oe_suggestion_employee").hide();
});
}
});
session.mail.WallSidebar.include({
start: function () {
this._super.apply(this, arguments);
var sug_employees = new suggestions.Employees(this);
return sug_employees.appendTo(this.$('.oe_suggestions_employees'));
},
});
};

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<!-- Employees placeholder in sidebar -->
<t t-extend="mail.wall.sidebar">
<t t-jquery=".oe_mail_wall_sidebar" t-operation="append">
<div class="oe_suggestions_employees"></div>
</t>
</t>
<!-- Suggested employees -->
<div t-name="hr.suggestions.employees" class="oe_sidebar_suggestion oe_suggestion_employee">
<div class="oe_suggest_title">
<a class="oe_suggestion_remove oe_suggestion_employee oe_e">X</a>
<h2>Suggested Employees</h2>
</div>
<div class="oe_suggest_items">
<t t-foreach="widget.employees" t-as="result">
<div class="oe_suggested_item">
<div class="oe_suggested_item_image">
<a t-attf-href="#model=hr.employee&amp;id=#{result.id}">
<img t-attf-src="{result.image}" t-attf-alt="{result.name}"/>
</a>
</div>
<div class="oe_suggested_item_content">
<a class="oe_suggestion_item_name" t-attf-href="#model=hr.employee&amp;id=#{result.id}"><t t-esc="result.name"/></a>
<a class="oe_suggestion_remove_item oe_suggestion_employee oe_e" t-attf-id="{result.id}">X</a>
<br/>
<button class="oe_suggestion_follow" t-att-id="result.id">Follow</button>
</div>
</div>
</t>
</div>
</div>
</template>

View File

@ -0,0 +1,466 @@
# 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-20 01:48+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-20 05:17+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: hr_attendance
#: model:ir.model,name:hr_attendance.model_hr_attendance_month
msgid "Print Monthly Attendance Report"
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
msgid "Hr Attendance Search"
msgstr ""
#. module: hr_attendance
#: field:hr.employee,last_sign:0
msgid "Last Sign"
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
#: field:hr.employee,state:0
#: model:ir.model,name:hr_attendance.model_hr_attendance
msgid "Attendance"
msgstr ""
#. module: hr_attendance
#. openerp-web
#: code:addons/hr_attendance/static/src/js/attendance.js:34
#, python-format
msgid "Last sign in: %s,<br />%s.<br />Click to sign out."
msgstr ""
#. module: hr_attendance
#: constraint:hr.attendance:0
msgid "Error ! Sign in (resp. Sign out) must follow Sign out (resp. Sign in)"
msgstr ""
#. module: hr_attendance
#: help:hr.action.reason,name:0
msgid "Specifies the reason for Signing In/Signing Out."
msgstr ""
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid ""
"(*) A positive delay means that the employee worked less than recorded."
msgstr ""
#. module: hr_attendance
#: view:hr.attendance.month:0
msgid "Print Attendance Report Monthly"
msgstr ""
#. module: hr_attendance
#: code:addons/hr_attendance/report/timesheet.py:120
#, python-format
msgid "Attendances by Week"
msgstr ""
#. module: hr_attendance
#: selection:hr.action.reason,action_type:0
msgid "Sign out"
msgstr "ลงชื่อออก"
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Delay"
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
msgid "Group By..."
msgstr "จัดกลุ่มตาม..."
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "October"
msgstr "ตุลาคม"
#. module: hr_attendance
#: field:hr.employee,attendance_access:0
msgid "Attendance Access"
msgstr ""
#. module: hr_attendance
#: code:addons/hr_attendance/hr_attendance.py:154
#: selection:hr.attendance,action:0
#: view:hr.employee:0
#, python-format
msgid "Sign Out"
msgstr "ออกจากระบบ"
#. module: hr_attendance
#: code:addons/hr_attendance/wizard/hr_attendance_error.py:49
#, python-format
msgid "No records are found for your selection!"
msgstr ""
#. module: hr_attendance
#: view:hr.attendance.error:0
#: view:hr.attendance.month:0
#: view:hr.attendance.week:0
msgid "Print"
msgstr "พิมพ์"
#. module: hr_attendance
#: view:hr.attendance:0
#: field:hr.attendance,employee_id:0
#: model:ir.model,name:hr_attendance.model_hr_employee
msgid "Employee"
msgstr "พนักงาน"
#. module: hr_attendance
#: field:hr.attendance.month,month:0
msgid "Month"
msgstr "เดือน"
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Date Recorded"
msgstr ""
#. module: hr_attendance
#: code:addons/hr_attendance/hr_attendance.py:154
#: selection:hr.attendance,action:0
#: view:hr.employee:0
#, python-format
msgid "Sign In"
msgstr "เข้าสู่ระบบ"
#. module: hr_attendance
#: field:hr.attendance.error,init_date:0
#: field:hr.attendance.week,init_date:0
msgid "Starting Date"
msgstr "วันที่เริ่ม"
#. module: hr_attendance
#: model:ir.actions.act_window,name:hr_attendance.open_view_attendance
#: model:ir.ui.menu,name:hr_attendance.menu_hr_attendance
#: model:ir.ui.menu,name:hr_attendance.menu_open_view_attendance
msgid "Attendances"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "March"
msgstr "มีนาคม"
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "August"
msgstr "สิงหาคม"
#. module: hr_attendance
#: code:addons/hr_attendance/hr_attendance.py:161
#, python-format
msgid "Warning"
msgstr "คำเตือน"
#. module: hr_attendance
#: help:hr.config.settings,group_hr_attendance:0
msgid "Allocates attendance group to all users."
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
msgid "My Attendance"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "June"
msgstr "มิถุนายน"
#. module: hr_attendance
#: code:addons/hr_attendance/report/attendance_by_month.py:190
#, python-format
msgid "Attendances by Month"
msgstr ""
#. module: hr_attendance
#: model:ir.actions.act_window,name:hr_attendance.action_hr_attendance_week
msgid "Attendances By Week"
msgstr ""
#. module: hr_attendance
#: model:ir.model,name:hr_attendance.model_hr_attendance_error
msgid "Print Error Attendance Report"
msgstr ""
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Total period:"
msgstr ""
#. module: hr_attendance
#: field:hr.action.reason,name:0
msgid "Reason"
msgstr "เหตุผล"
#. module: hr_attendance
#: view:hr.attendance.error:0
msgid "Print Attendance Report Error"
msgstr ""
#. module: hr_attendance
#: model:ir.actions.act_window,help:hr_attendance.open_view_attendance
msgid ""
"The Time Tracking functionality aims to manage employee attendances from "
"Sign in/Sign out actions. You can also link this feature to an attendance "
"device using OpenERP's web service features."
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
msgid "Today"
msgstr "วันนี้"
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Date Signed"
msgstr ""
#. module: hr_attendance
#: field:hr.attendance,name:0
msgid "Date"
msgstr "วันที่"
#. module: hr_attendance
#: field:hr.config.settings,group_hr_attendance:0
msgid "Track attendances for all employees"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "July"
msgstr "กรกฎาคม"
#. module: hr_attendance
#: model:ir.actions.act_window,name:hr_attendance.action_hr_attendance_error
#: model:ir.actions.report.xml,name:hr_attendance.attendance_error_report
msgid "Attendance Error Report"
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
#: field:hr.attendance,day:0
msgid "Day"
msgstr "วัน"
#. module: hr_attendance
#: selection:hr.employee,state:0
msgid "Present"
msgstr "นำเสนอ"
#. module: hr_attendance
#: selection:hr.employee,state:0
msgid "Absent"
msgstr "ขาด"
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "February"
msgstr "กุมภาพันธ์"
#. module: hr_attendance
#: field:hr.attendance,action_desc:0
#: model:ir.model,name:hr_attendance.model_hr_action_reason
msgid "Action Reason"
msgstr ""
#. module: hr_attendance
#: field:hr.attendance.month,year:0
msgid "Year"
msgstr "ปี"
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Min Delay"
msgstr ""
#. module: hr_attendance
#: view:hr.attendance:0
msgid "Employee attendances"
msgstr ""
#. module: hr_attendance
#: view:hr.action.reason:0
msgid "Define attendance reason"
msgstr ""
#. module: hr_attendance
#: selection:hr.action.reason,action_type:0
msgid "Sign in"
msgstr "ลงชื่อเข้าใช้"
#. module: hr_attendance
#: view:hr.attendance.error:0
msgid "Analysis Information"
msgstr ""
#. module: hr_attendance
#: model:ir.actions.act_window,name:hr_attendance.action_hr_attendance_month
msgid "Attendances By Month"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "January"
msgstr "มกราคม"
#. module: hr_attendance
#: code:addons/hr_attendance/wizard/hr_attendance_error.py:49
#, python-format
msgid "No Data Available !"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "April"
msgstr "เมษายน"
#. module: hr_attendance
#: view:hr.attendance.week:0
msgid "Print Attendance Report Weekly"
msgstr ""
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Attendance Errors"
msgstr ""
#. module: hr_attendance
#: field:hr.attendance,action:0
#: selection:hr.attendance,action:0
msgid "Action"
msgstr "ปฏิบัติ"
#. module: hr_attendance
#: model:ir.ui.menu,name:hr_attendance.menu_hr_time_tracking
msgid "Time Tracking"
msgstr "ติดตามเวลา"
#. module: hr_attendance
#: model:ir.actions.act_window,name:hr_attendance.open_view_attendance_reason
#: model:ir.ui.menu,name:hr_attendance.menu_open_view_attendance_reason
msgid "Attendance Reasons"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "November"
msgstr "พฤศจิกายน"
#. module: hr_attendance
#: view:hr.attendance.error:0
msgid "Bellow this delay, the error is considered to be voluntary"
msgstr ""
#. module: hr_attendance
#: field:hr.attendance.error,max_delay:0
msgid "Max. Delay (Min)"
msgstr ""
#. module: hr_attendance
#: field:hr.attendance.error,end_date:0
#: field:hr.attendance.week,end_date:0
msgid "Ending Date"
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "September"
msgstr "กันยายน"
#. module: hr_attendance
#: view:hr.action.reason:0
msgid "Attendance reasons"
msgstr ""
#. module: hr_attendance
#: model:ir.model,name:hr_attendance.model_hr_attendance_week
msgid "Print Week Attendance Report"
msgstr ""
#. module: hr_attendance
#: model:ir.model,name:hr_attendance.model_hr_config_settings
msgid "hr.config.settings"
msgstr "hr.config.settings"
#. module: hr_attendance
#. openerp-web
#: code:addons/hr_attendance/static/src/js/attendance.js:36
#, python-format
msgid "Click to Sign In at %s."
msgstr ""
#. module: hr_attendance
#: field:hr.action.reason,action_type:0
msgid "Action Type"
msgstr "ชนิดการทำงาน"
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "May"
msgstr "พฤษภาคม"
#. module: hr_attendance
#: code:addons/hr_attendance/hr_attendance.py:161
#, python-format
msgid ""
"You tried to %s with a date anterior to another event !\n"
"Try to contact the HR Manager to correct attendances."
msgstr ""
#. module: hr_attendance
#: selection:hr.attendance.month,month:0
msgid "December"
msgstr "ธันวาคม"
#. module: hr_attendance
#: view:hr.attendance.error:0
#: view:hr.attendance.month:0
#: view:hr.attendance.week:0
msgid "Cancel"
msgstr "ยกเลิก"
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid "Operation"
msgstr "ปฏิบัติการ"
#. module: hr_attendance
#: report:report.hr.timesheet.attendance.error:0
msgid ""
"(*) A negative delay means that the employee worked more than encoded."
msgstr ""
#. module: hr_attendance
#: view:hr.attendance.error:0
#: view:hr.attendance.month:0
#: view:hr.attendance.week:0
msgid "or"
msgstr "หรือ"
#. module: hr_attendance
#: help:hr.attendance,action_desc:0
msgid ""
"Specifies the reason for Signing In/Signing Out in case of extra hours."
msgstr ""

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>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,669 @@
# 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:04+0000\n"
"PO-Revision-Date: 2013-06-17 06:13+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-18 05:46+0000\n"
"X-Generator: Launchpad (build 16673)\n"
#. module: hr_timesheet
#: model:ir.actions.act_window,help:hr_timesheet.act_analytic_cost_revenue
msgid ""
"<p>\n"
" No activity yet on this contract.\n"
" </p><p>\n"
" In OpenERP, contracts and projects are implemented using\n"
" analytic account. So, you can track costs and revenues to "
"analyse\n"
" your margins easily.\n"
" </p><p>\n"
" Costs will be created automatically when you register "
"supplier\n"
" invoices, expenses or timesheets.\n"
" </p><p>\n"
" Revenues will be created automatically when you create "
"customer\n"
" invoices. Customer invoices can be created based on sale "
"orders\n"
" (fixed price invoices), on timesheets (based on the work "
"done) or\n"
" on expenses (e.g. reinvoicing of travel costs).\n"
" </p>\n"
" "
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Wed"
msgstr "พุธ"
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "(Keep empty for current_time)"
msgstr ""
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Group By..."
msgstr "จัดกลุ่มตาม..."
#. module: hr_timesheet
#: model:ir.actions.act_window,help:hr_timesheet.action_hr_timesheet_sign_in
msgid ""
"Employees can encode their time spent on the different projects. A project "
"is an analytic account and the time spent on a project generate costs on the "
"analytic account. This feature allows to record at the same time the "
"attendance and the timesheet."
msgstr ""
#. module: hr_timesheet
#: field:hr.employee,uom_id:0
msgid "Unit of Measure"
msgstr "หน่วยของการวัด"
#. module: hr_timesheet
#: field:hr.employee,journal_id:0
msgid "Analytic Journal"
msgstr ""
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "Stop Working"
msgstr "หยุดทำงาน"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.action_hr_timesheet_employee
#: model:ir.ui.menu,name:hr_timesheet.menu_hr_timesheet_employee
msgid "Employee Timesheet"
msgstr "เวลาทำงาน พนักงาน"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
#: model:ir.ui.menu,name:hr_timesheet.menu_hr_timesheet_reports
msgid "Timesheet"
msgstr "เวลาทำงาน"
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_print_employee.py:43
#, python-format
msgid "Please define employee for this user!"
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Mon"
msgstr "จัน"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "Sign in"
msgstr "ลงชื่อเข้าใช้"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Fri"
msgstr "ศุกร์"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
#: model:ir.actions.act_window,name:hr_timesheet.act_hr_timesheet_line_evry1_all_form
#: model:ir.ui.menu,name:hr_timesheet.menu_hr_working_hours
msgid "Timesheet Activities"
msgstr "กิจกรรม เวลาทำงาน"
#. module: hr_timesheet
#: field:hr.sign.out.project,analytic_amount:0
msgid "Minimum Analytic Amount"
msgstr ""
#. module: hr_timesheet
#: view:hr.analytical.timesheet.employee:0
msgid "Monthly Employee Timesheet"
msgstr "รายเดือน เวลาทำงานพนักงาน"
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "Work done in the last period"
msgstr "งานที่ทำทั้งหมดในระยะเวลาสุดท้าย"
#. module: hr_timesheet
#: field:hr.sign.in.project,name:0
#: field:hr.sign.out.project,name:0
msgid "Employees name"
msgstr "ชื่อพนักงาน"
#. module: hr_timesheet
#: field:hr.sign.out.project,account_id:0
msgid "Project / Analytic Account"
msgstr "โครงการ /วิเคราะห์ บัญชี"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_analytical_timesheet_users
msgid "Print Employees Timesheet"
msgstr "พิมพ์ เวลาทำงาน พนักงาน"
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:132
#, python-format
msgid "Please define employee for your user."
msgstr "กรุณากำหนดพนักงานสำหรับผู้ใช้ของคุณ"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.act_analytic_cost_revenue
msgid "Costs & Revenues"
msgstr "ค่าใช้จ่ายและรายได้"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Tue"
msgstr "อังคาร"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_account_analytic_account
msgid "Analytic Account"
msgstr "วิเคราะห์บัญชี"
#. module: hr_timesheet
#: view:account.analytic.account:0
msgid "Costs and Revenues"
msgstr "ค่าใช้จ่ายและรายได้"
#. module: hr_timesheet
#: code:addons/hr_timesheet/hr_timesheet.py:150
#: code:addons/hr_timesheet/hr_timesheet.py:155
#: code:addons/hr_timesheet/hr_timesheet.py:186
#: code:addons/hr_timesheet/hr_timesheet.py:188
#: code:addons/hr_timesheet/wizard/hr_timesheet_print_employee.py:43
#, python-format
msgid "Warning!"
msgstr "คำเตือน!"
#. module: hr_timesheet
#: field:hr.analytic.timesheet,partner_id:0
msgid "Partner"
msgstr "พาร์ทเนอร์"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Sat"
msgstr "เสาร์"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Sun"
msgstr "อาทิตย์"
#. module: hr_timesheet
#: xsl:hr.analytical.timesheet:0
msgid "Sum"
msgstr "ผลรวม"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Analytic account"
msgstr "วิเคราะห์บัญชี"
#. module: hr_timesheet
#: model:ir.actions.act_window,help:hr_timesheet.act_hr_timesheet_line_evry1_all_form
msgid ""
"<p class=\"oe_view_nocontent_create\">\n"
" Click to record activities.\n"
" </p><p>\n"
" You can register and track your workings hours by project "
"every\n"
" day. Every time spent on a project will become a cost in "
"the\n"
" analytic accounting/contract and can be re-invoiced to\n"
" customers if required.\n"
" </p>\n"
" "
msgstr ""
#. module: hr_timesheet
#: view:hr.analytical.timesheet.employee:0
#: view:hr.analytical.timesheet.users:0
msgid "Print"
msgstr "พิมพ์"
#. module: hr_timesheet
#: help:account.analytic.account,use_timesheets:0
msgid "Check this field if this project manages timesheets"
msgstr ""
#. module: hr_timesheet
#: view:hr.analytical.timesheet.users:0
msgid "Monthly Employees Timesheet"
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "July"
msgstr "กรกฎาคม"
#. module: hr_timesheet
#: field:hr.sign.in.project,date:0
#: field:hr.sign.out.project,date_start:0
msgid "Starting Date"
msgstr "วันที่เริ่ม"
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:77
#, python-format
msgid "Please define cost unit for this employee."
msgstr ""
#. module: hr_timesheet
#: help:hr.employee,product_id:0
msgid "Specifies employee's designation as a product with type 'service'."
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/hr_timesheet.py:188
#, python-format
msgid ""
"No analytic account is defined on the project.\n"
"Please set one or we cannot automatically fill the timesheet."
msgstr ""
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Total cost"
msgstr "รวมค่าใช้จ่าย"
#. module: hr_timesheet
#: code:addons/hr_timesheet/hr_timesheet.py:186
#, python-format
msgid ""
"No 'Analytic Journal' is defined for employee %s \n"
"Define an employee for the selected user and assign an 'Analytic Journal'!"
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "September"
msgstr "กันยายน"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "December"
msgstr "ธันวาคม"
#. module: hr_timesheet
#: field:hr.analytical.timesheet.users,employee_ids:0
msgid "employees"
msgstr "พนักงาน"
#. module: hr_timesheet
#: field:hr.analytical.timesheet.employee,month:0
#: field:hr.analytical.timesheet.users,month:0
msgid "Month"
msgstr "เดือน"
#. module: hr_timesheet
#: field:hr.sign.out.project,info:0
msgid "Work Description"
msgstr "รายละเอียดการทำงาน"
#. module: hr_timesheet
#: view:hr.analytical.timesheet.employee:0
#: view:hr.analytical.timesheet.users:0
#: view:hr.sign.in.project:0
#: view:hr.sign.out.project:0
msgid "or"
msgstr "หรือ"
#. module: hr_timesheet
#: xsl:hr.analytical.timesheet:0
msgid "Timesheet by Employee"
msgstr "บันทึกเวลา โดยพนักงาน"
#. module: hr_timesheet
#: model:ir.actions.report.xml,name:hr_timesheet.report_user_timesheet
msgid "Employee timesheet"
msgstr "บันทึกเวลาของพนักงาน"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.action_hr_timesheet_sign_in
#: model:ir.actions.act_window,name:hr_timesheet.action_hr_timesheet_sign_out
msgid "Sign in / Sign out by project"
msgstr "เข้าสู่ระบบ / ออกจากระบบ โดยโครงการ"
#. module: hr_timesheet
#: model:ir.actions.act_window,name:hr_timesheet.action_define_analytic_structure
msgid "Define your Analytic Structure"
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:146
#: view:hr.sign.in.project:0
#, python-format
msgid "Sign in / Sign out"
msgstr "เข้าสู่ระบบ / ออกจากระบบ"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "(Keep empty for current time)"
msgstr ""
#. module: hr_timesheet
#: field:account.analytic.account,use_timesheets:0
#: view:hr.employee:0
msgid "Timesheets"
msgstr "ตารางเวลา"
#. module: hr_timesheet
#: model:ir.actions.act_window,help:hr_timesheet.action_define_analytic_structure
msgid ""
"You should create an analytic account structure depending on your needs to "
"analyse costs and revenues. In OpenERP, analytic accounts are also used to "
"track customer contracts."
msgstr ""
#. module: hr_timesheet
#: field:hr.analytic.timesheet,line_id:0
msgid "Analytic Line"
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "August"
msgstr "สิงหาคม"
#. module: hr_timesheet
#: code:addons/hr_timesheet/hr_timesheet.py:155
#, python-format
msgid ""
"No analytic journal defined for '%s'.\n"
"You should assign an analytic journal on the employee form."
msgstr ""
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "June"
msgstr "มิถุนายน"
#. module: hr_timesheet
#: field:hr.sign.in.project,state:0
#: field:hr.sign.out.project,state:0
msgid "Current Status"
msgstr "สถานะปัจจุบัน"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Date"
msgstr "วันที่"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "November"
msgstr "พฤศจิกายน"
#. module: hr_timesheet
#: field:hr.sign.out.project,date:0
msgid "Closing Date"
msgstr "ปิดวันที่"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "October"
msgstr "ตุลาคม"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "January"
msgstr "มกราคม"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:44
#: code:addons/hr_timesheet/report/users_timesheet.py:77
#, python-format
msgid "Thu"
msgstr "พฤหัสบดี"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
#: view:hr.sign.out.project:0
msgid "Sign In/Out by Project"
msgstr "ลงซื่อ เข้า/ออก ตามโครงการ"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_analytical_timesheet_employee
msgid "Print Employee Timesheet & Print My Timesheet"
msgstr ""
#. module: hr_timesheet
#: field:hr.sign.in.project,emp_id:0
#: field:hr.sign.out.project,emp_id:0
msgid "Employee ID"
msgstr "หมายเลข พนักงาน"
#. module: hr_timesheet
#: view:hr.analytical.timesheet.users:0
msgid "Period"
msgstr "คาบ"
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "General Information"
msgstr "ข้อมูลทั่วไป"
#. module: hr_timesheet
#: view:hr.analytical.timesheet.employee:0
#: view:hr.analytical.timesheet.users:0
#: view:hr.sign.in.project:0
#: view:hr.sign.out.project:0
msgid "Cancel"
msgstr "ยกเลิก"
#. module: hr_timesheet
#: xsl:hr.analytical.timesheet_users:0
#: model:ir.actions.act_window,name:hr_timesheet.action_hr_timesheet_users
#: model:ir.actions.report.xml,name:hr_timesheet.report_users_timesheet
#: model:ir.ui.menu,name:hr_timesheet.menu_hr_timesheet_users
msgid "Employees Timesheet"
msgstr "เวลาทำงาน พนักงาน"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Information"
msgstr "รายละเอียด"
#. module: hr_timesheet
#: field:hr.analytical.timesheet.employee,employee_id:0
#: model:ir.model,name:hr_timesheet.model_hr_employee
msgid "Employee"
msgstr "พนักงาน"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid ""
"Employees can encode their time spent on the different projects they are "
"assigned on. A project is an analytic account and the time spent on a "
"project generates costs on the analytic account. This feature allows to "
"record at the same time the attendance and the timesheet."
msgstr ""
#. module: hr_timesheet
#: field:hr.sign.in.project,server_date:0
#: field:hr.sign.out.project,server_date:0
msgid "Current Date"
msgstr "วันที่ปัจจุบัน"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_analytic_timesheet
msgid "Timesheet Line"
msgstr ""
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
#: field:hr.employee,product_id:0
msgid "Product"
msgstr "ผลิตภัณฑ์"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Users"
msgstr "ผู้ใช้"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "May"
msgstr "พฤษภาคม"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Total time"
msgstr "เวลารวม"
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "(local time on the server side)"
msgstr ""
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_sign_in_project
msgid "Sign In By Project"
msgstr "เข้าสู่ระบบตามโครงการ"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "February"
msgstr "กุมภาพันธ์"
#. module: hr_timesheet
#: model:ir.model,name:hr_timesheet.model_hr_sign_out_project
msgid "Sign Out By Project"
msgstr "ลงชื่อออก ตามโครงการ"
#. module: hr_timesheet
#: code:addons/hr_timesheet/hr_timesheet.py:150
#, python-format
msgid ""
"Please create an employee for this user, using the menu: Human Resources > "
"Employees."
msgstr ""
#. module: hr_timesheet
#: view:hr.analytical.timesheet.users:0
msgid "Employees"
msgstr "พนักงาน"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "March"
msgstr "มีนาคม"
#. module: hr_timesheet
#: code:addons/hr_timesheet/report/user_timesheet.py:41
#: code:addons/hr_timesheet/report/users_timesheet.py:73
#: selection:hr.analytical.timesheet.employee,month:0
#: selection:hr.analytical.timesheet.users,month:0
#, python-format
msgid "April"
msgstr "เมษายน"
#. module: hr_timesheet
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:77
#: code:addons/hr_timesheet/wizard/hr_timesheet_sign_in_out.py:132
#, python-format
msgid "User Error!"
msgstr ""
#. module: hr_timesheet
#: view:hr.sign.in.project:0
msgid "Start Working"
msgstr "เริ่มทำงาน"
#. module: hr_timesheet
#: field:hr.analytical.timesheet.employee,year:0
#: field:hr.analytical.timesheet.users,year:0
msgid "Year"
msgstr "ปี"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Duration"
msgstr "ระยะเวลา"
#. module: hr_timesheet
#: view:hr.analytic.timesheet:0
msgid "Accounting"
msgstr "บัญชี"
#. module: hr_timesheet
#: xsl:hr.analytical.timesheet:0
#: xsl:hr.analytical.timesheet_users:0
msgid "Total"
msgstr "รวม"
#. module: hr_timesheet
#: view:hr.sign.out.project:0
msgid "Change Work"
msgstr "เปลี่ยนงาน"

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>

File diff suppressed because it is too large Load Diff

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

@ -17,7 +17,7 @@ chat in real time. It support several chats in parallel.
'security/ir.model.access.csv',
'security/im_security.xml',
],
'depends' : ['base'],
'depends' : ['base', 'web'],
'js': ['static/src/js/*.js'],
'css': ['static/src/css/*.css'],
'qweb': ['static/src/xml/*.xml'],

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

@ -87,10 +87,12 @@ Main Features
'static/src/js/mail.js',
'static/src/js/mail_followers.js',
'static/src/js/many2many_tags_email.js',
'static/src/js/suggestions.js',
],
'qweb': [
'static/src/xml/mail.xml',
'static/src/xml/mail_followers.xml',
'static/src/xml/suggestions.xml',
],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,4 +1,7 @@
import base64
import openerp
from openerp import SUPERUSER_ID
import openerp.addons.web.http as oeweb
from openerp.addons.web.controllers.main import content_disposition
@ -20,3 +23,18 @@ class MailController(oeweb.Controller):
headers=[('Content-Type', 'application/octet-stream'),
('Content-Disposition', content_disposition(filename, req))])
return req.not_found()
@oeweb.jsonrequest
def receive(self, req):
""" End-point to receive mail from an external SMTP server. """
dbs = req.jsonrequest.get('databases')
for db in dbs:
message = dbs[db].decode('base64')
try:
registry = openerp.registry(db)
with registry.cursor() as cr:
mail_thread = registry['mail.thread']
mail_thread.message_process(cr, SUPERUSER_ID, None, message)
except psycopg2.Error:
pass
return True

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

@ -208,3 +208,12 @@ class mail_group(osv.Model):
""" Wrapper because message_unsubscribe_users take a user_ids=None
that receive the context without the wrapper. """
return self.message_unsubscribe_users(cr, uid, ids, context=context)
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
"""Show the suggestion of groups if display_groups_suggestions if the
user perference allows it."""
user = self.pool.get('res.users').browse(cr, uid, uid, context)
if not user.display_groups_suggestions:
return []
else:
return super(mail_group, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)

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:
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

@ -240,21 +240,42 @@ class mail_thread(osv.AbstractModel):
fol_obj.create(cr, SUPERUSER_ID, {'res_model': self._name, 'res_id': id, 'partner_id': partner_id})
def _search_followers(self, cr, uid, obj, name, args, context):
"""Search function for message_follower_ids
Do not use with operator 'not in'. Use instead message_is_followers
"""
fol_obj = self.pool.get('mail.followers')
res = []
for field, operator, value in args:
assert field == name
# TOFIX make it work with not in
assert operator != "not in", "Do not search message_follower_ids with 'not in'"
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('partner_id', operator, value)])
res_ids = [fol.res_id for fol in fol_obj.browse(cr, SUPERUSER_ID, fol_ids)]
res.append(('id', 'in', res_ids))
return res
def _search_is_follower(self, cr, uid, obj, name, args, context):
"""Search function for message_is_follower"""
fol_obj = self.pool.get('mail.followers')
res = []
for field, operator, value in args:
assert field == name
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
if (operator == '=' and value) or (operator == '!=' and not value): # is a follower
res_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
else: # is not a follower or unknown domain
mail_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
res_ids = self.search(cr, uid, [('id', 'not in', mail_ids)], context=context)
res.append(('id', 'in', res_ids))
return res
_columns = {
'message_is_follower': fields.function(_get_followers,
type='boolean', string='Is a Follower', multi='_get_followers,'),
'message_is_follower': fields.function(_get_followers, type='boolean',
fnct_search=_search_is_follower, string='Is a Follower', multi='_get_followers,'),
'message_follower_ids': fields.function(_get_followers, fnct_inv=_set_followers,
fnct_search=_search_followers, type='many2many',
obj='res.partner', string='Followers', multi='_get_followers'),
fnct_search=_search_followers, type='many2many',
obj='res.partner', string='Followers', multi='_get_followers'),
'message_ids': fields.one2many('mail.message', 'res_id',
domain=lambda self: [('model', '=', self._name)],
auto_join=True,
@ -559,7 +580,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
@ -794,6 +815,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:
@ -1128,7 +1152,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)
@ -1287,7 +1311,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')
@ -1296,27 +1323,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
@ -1454,4 +1489,33 @@ class mail_thread(osv.AbstractModel):
''', (ids, self._name, partner_id))
return True
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
#------------------------------------------------------
# Thread suggestion
#------------------------------------------------------
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
"""Return a list of suggested threads, sorted by the numbers of followers"""
if context is None:
context = {}
# TDE HACK: originally by MAT from portal/mail_mail.py but not working until the inheritance graph bug is not solved in trunk
# TDE FIXME: relocate in portal when it won't be necessary to reload the hr.employee model in an additional bridge module
if self.pool['res.groups']._all_columns.get('is_portal'):
user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
if any(group.is_portal for group in user.groups_id):
return []
threads = []
if removed_suggested_threads is None:
removed_suggested_threads = []
thread_ids = self.search(cr, uid, [('id', 'not in', removed_suggested_threads), ('message_is_follower', '=', False)], context=context)
for thread in self.browse(cr, uid, thread_ids, context=context):
data = {
'id': thread.id,
'popularity': len(thread.message_follower_ids),
'name': thread.name,
'image_small': thread.image_small
}
threads.append(data)
return sorted(threads, key=lambda x: (x['popularity'], x['id']), reverse=True)[:3]

View File

@ -17,7 +17,8 @@
],
'view_mailbox': True,
'view_inbox': True,
'read_action': 'read'
'read_action': 'read',
'show_compose_message': False
}&quot;"/>
<field name="help" type="html">
<p>

View File

@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.tools.translate import _
from openerp.osv import fields, osv
@ -52,21 +53,4 @@ class res_partner_mail(osv.Model):
self._message_add_suggested_recipient(cr, uid, recipients, partner, partner=partner, reason=_('Partner Profile'))
return recipients
def message_post(self, cr, uid, thread_id, **kwargs):
""" Override related to res.partner. In case of email message, set it as
private:
- add the target partner in the message partner_ids
- set thread_id as None, because this will trigger the 'private'
aspect of the message (model=False, res_id=False)
"""
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id[0]
if kwargs.get('type') == 'email':
partner_ids = kwargs.get('partner_ids', [])
if thread_id not in [command[1] for command in partner_ids]:
partner_ids.append((4, thread_id))
kwargs['partner_ids'] = partner_ids
thread_id = False
return super(res_partner_mail, self).message_post(cr, uid, thread_id, **kwargs)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -28,6 +28,7 @@ class res_users(osv.Model):
- add a preference about sending emails about notifications
- make a new user follow itself
- add a welcome message
- add suggestion preference
"""
_name = 'res.users'
_inherit = ['res.users']
@ -37,10 +38,12 @@ class res_users(osv.Model):
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
help="Email address internally associated with this user. Incoming "\
"emails will appear in the user's notifications."),
'display_groups_suggestions': fields.boolean("Display Groups Suggestions"),
}
_defaults = {
'alias_domain': False, # always hide alias during creation
'display_groups_suggestions': True,
}
def __init__(self, pool, cr):
@ -51,10 +54,10 @@ class res_users(osv.Model):
init_res = super(res_users, self).__init__(pool, cr)
# duplicate list to avoid modifying the original reference
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
self.SELF_WRITEABLE_FIELDS.append('notification_email_send')
self.SELF_WRITEABLE_FIELDS.extend(['notification_email_send', 'display_groups_suggestions'])
# duplicate list to avoid modifying the original reference
self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name'])
self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name', 'display_groups_suggestions'])
return init_res
def _auto_init(self, cr, context=None):
@ -109,7 +112,7 @@ class res_users(osv.Model):
def _message_post_get_pid(self, cr, uid, thread_id, context=None):
assert thread_id, "res.users does not support posting global messages"
if context and 'thread_model' in context:
context['thread_model'] = 'res.partner'
context['thread_model'] = 'res.users'
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id[0]
return self.browse(cr, SUPERUSER_ID, thread_id).partner_id.id
@ -118,44 +121,32 @@ class res_users(osv.Model):
""" Redirect the posting of message on res.users to the related partner.
This is done because when giving the context of Chatter on the
various mailboxes, we do not have access to the current partner_id. """
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id[0]
partner_ids = kwargs.get('partner_ids', [])
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
return self.pool.get('res.partner').message_post(cr, uid, partner_id, context=context, **kwargs)
if partner_id not in [command[1] for command in partner_ids]:
partner_ids.append(partner_id)
kwargs['partner_ids'] = partner_ids
return self.pool.get('mail.thread').message_post(cr, uid, False, **kwargs)
def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
for id in ids:
partner_id = self.browse(cr, SUPERUSER_ID, id).partner_id.id
self.pool.get('res.partner').message_update(cr, uid, [partner_id], msg_dict, update_vals=update_vals, context=context)
return True
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
for id in ids:
partner_id = self.browse(cr, SUPERUSER_ID, id).partner_id.id
self.pool.get('res.partner').message_subscribe(cr, uid, [partner_id], partner_ids, subtype_ids=subtype_ids, context=context)
return True
def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None):
return self.pool.get('res.partner').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
return self.pool.get('mail.thread').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
def message_get_suggested_recipients(self, cr, uid, ids, context=None):
partner_ids = []
for id in ids:
partner_ids.append(self.browse(cr, SUPERUSER_ID, id).partner_id.id)
return self.pool.get('res.partner').message_get_suggested_recipients(cr, uid, partner_ids, context=context)
return dict.fromkeys(ids, list())
#------------------------------------------------------
# Compatibility methods: do not use
# TDE TODO: remove me in 8.0
#------------------------------------------------------
def message_post_user_api(self, cr, uid, thread_id, context=None, **kwargs):
""" Redirect the posting of message on res.users to the related partner.
This is done because when giving the context of Chatter on the
various mailboxes, we do not have access to the current partner_id. """
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, context=context, **kwargs)
def message_create_partners_from_emails(self, cr, uid, emails, context=None):
return self.pool.get('res.partner').message_create_partners_from_emails(cr, uid, emails, context=context)
def stop_showing_groups_suggestions(self, cr, uid, user_id, context=None):
"""Update display_groups_suggestions value to False"""
if context is None:
context = {}
self.write(cr, uid, user_id, {"display_groups_suggestions": False}, context)
class res_users_mail_group(osv.Model):

View File

@ -30,6 +30,12 @@
<field name="alias_domain" invisible="1"/>
<field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
</field>
<group string="Email preferences" position="after">
<group name="misc" string="Miscellaneous"
groups="base.group_no_one">
<field name="display_groups_suggestions"/>
</group>
</group>
</data>
</field>
</record>

View File

@ -22,7 +22,7 @@
width: 32px;
height: 32px;
padding: 0px;
margin: 0px
margin: 0px;
border-radius: 0px;
}
@ -665,8 +665,72 @@
.openerp .oe_mail_wall .oe_mail{
margin: 16px;
width: 600px;
display: inline-block;
}
.openerp .oe_mail .oe_view_nocontent > p {
padding-left: 15px;
}
/* ------------- WALL SIDEBAR ------------- */
.openerp .oe_mail_wall .oe_mail_wall_aside {
margin: 16px;
position: relative;
display: inline-block;
vertical-align: top;
width: 260px;
}
.openerp .oe_mail_wall_aside .oe_sidebar_suggestion {
background-color: #EDEDF6;
border-radius: 2px;
padding-top: 1px;
}
.openerp .oe_sidebar_suggestion .oe_suggest_title h2 {
font-size: 14px;
font-weight: bold;
margin-left: 10px;
padding: 0px;
}
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item {
border-radius: 2px;
width: 100%;
margin-left: 10px;
min-height: 67px; /* image_small 66x66px */
}
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_image {
float: left;
padding-right: 10px;
}
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_image img {
border-radius: 2px;
border: solid 1px rgba(0,0,0,0.03);
}
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content button {
margin-top: 10px;
}
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content a.oe_suggestion_item_name {
text-overflow: ellipsis;
overflow: hidden;
width: 90%;
}
.openerp .oe_sidebar_suggestion .oe_suggest_title a.oe_suggestion_remove {
line-height: 15px;
margin-top: -2px;
float: right;
visibility: hidden;
margin-right: 7px;
}
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content a.oe_suggestion_remove_item {
line-height: 15px;
margin-top: -2px;
float: right;
visibility: hidden;
margin-right: 16px;
}
.openerp .oe_sidebar_suggestion .oe_suggest_title:hover a.oe_suggestion_remove,
.openerp .oe_sidebar_suggestion .oe_suggest_items:hover a.oe_suggestion_remove_item {
visibility: visible;
}

View File

@ -48,7 +48,6 @@
text-align: center;
overflow: hidden;
-moz-border-radius: 3px;
border-collapse: separate;
-webkit-border-radius: 3px;
-o-border-radius: 3px;
-ms-border-radius: 3px;

View File

@ -4,8 +4,8 @@ openerp.mail = function (session) {
var mail = session.mail = {};
openerp_mail_followers(session, mail); // import mail_followers.js
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
openerp_mail_followers(session, mail); // import mail_followers.js
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
/**
* ------------------------------------------------------------
@ -237,8 +237,15 @@ openerp.mail = function (session) {
this.format_data();
// update record_name: Partner profile
if (this.model == 'res.partner') {
this.record_name = 'Partner Profile of ' + this.record_name;
}
else if (this.model == 'hr.employee') {
this.record_name = 'News from ' + this.record_name;
}
// record options and data
this.show_record_name = this.options.show_record_name && this.record_name && !this.thread_level && this.model != 'res.partner';
this.show_record_name = this.options.show_record_name && this.record_name && !this.thread_level;
this.options.show_read = false;
this.options.show_unread = false;
if (this.options.show_read_unread_button) {
@ -257,8 +264,10 @@ openerp.mail = function (session) {
/* Convert date, timerelative and avatar in displayable data. */
format_data: function () {
//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);
}
@ -745,7 +754,7 @@ openerp.mail = function (session) {
}
// create object and attach to the thread object
thread.message_fetch([["id", "=", message_id]], false, [message_id], function (arg, data) {
var message = thread.create_message_object( data[0] );
var message = thread.create_message_object( data.slice(-1)[0] );
// insert the message on dom
thread.insert_message( message, root ? undefined : self.$el, root );
});
@ -978,8 +987,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',
@ -1840,6 +1849,19 @@ openerp.mail = function (session) {
});
/**
* ------------------------------------------------------------
* Aside Widget
* ------------------------------------------------------------
*
* This widget handles the display of a sidebar on the Wall. Its main use
* is to display group and employees suggestion (if hr is installed).
*/
mail.WallSidebar = session.web.Widget.extend({
template: 'mail.wall.sidebar',
});
/**
* ------------------------------------------------------------
* Wall Widget
@ -1901,6 +1923,9 @@ openerp.mail = function (session) {
if (! this.searchview.has_defaults) {
this.message_render();
}
// render sidebar
var wall_sidebar = new mail.WallSidebar(this);
wall_sidebar.appendTo(this.$el.find('.oe_mail_wall_aside'));
},
/**
@ -2018,4 +2043,16 @@ openerp.mail = function (session) {
});
},
});
/**
* ------------------------------------------------------------
* Sub-widgets loading
* ------------------------------------------------------------
*
* Load here widgets that could depend on widgets defined in mail.js
*/
openerp.mail.suggestions(session, mail); // import suggestion.js (suggestion widget)
};

View File

@ -0,0 +1,77 @@
openerp.mail.suggestions = function(session, mail) {
var _t = session.web._t;
var QWeb = session.web.qweb;
var suggestions = session.suggestions = {};
var removed_suggested_group = session.suggestions.removed_suggested_group = [];
suggestions.Groups = session.web.Widget.extend({
events: {
'click .oe_suggestion_remove.oe_suggestion_group': 'stop_group_suggestion',
'click .oe_suggestion_remove_item.oe_suggestion_group': 'remove_group_suggestion',
'click .oe_suggestion_join': 'join_group',
},
init: function () {
this._super.apply(this, arguments);
this.mail_group = new session.web.DataSetSearch(this, 'mail.group');
this.res_users = new session.web.DataSetSearch(this, 'res.users');
this.groups = [];
},
start: function () {
this._super.apply(this, arguments);
return this.fetch_suggested_groups();
},
fetch_suggested_groups: function () {
var self = this;
var group = self.mail_group.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_group}).then(function (res) {
_(res).each(function (result) {
result['image']=self.session.url('/web/binary/image', {model: 'mail.group', field: 'image_small', id: result.id});
});
self.groups = res;
});
return $.when(group).then(this.proxy('display_suggested_groups'));
},
display_suggested_groups: function () {
var suggested_groups = this.$('.oe_sidebar_suggestion.oe_suggestion_group');
if (suggested_groups) {
suggested_groups.empty();
}
if (this.groups.length === 0) {
return this.$el.empty();
}
return this.$el.empty().html(QWeb.render('mail.suggestions.groups', {'widget': this}));
},
join_group: function (event) {
var self = this;
return this.mail_group.call('message_subscribe_users', [[$(event.currentTarget).attr('id')],[this.session.uid]]).then(function(res) {
self.fetch_suggested_groups();
});
},
remove_group_suggestion: function (event) {
removed_suggested_group.push($(event.currentTarget).attr('id'));
return this.fetch_suggested_groups();
},
stop_group_suggestion: function (event) {
var self = this;
return this.res_users.call('stop_showing_groups_suggestions', [this.session.uid]).then(function(res) {
self.$(".oe_sidebar_suggestion.oe_suggestion_group").hide();
});
}
});
session.mail.WallSidebar.include({
start: function () {
this._super.apply(this, arguments);
var sug_groups = new suggestions.Groups(this);
return sug_groups.appendTo(this.$('.oe_suggestions_groups'));
},
});
};

View File

@ -121,9 +121,11 @@
To:
<t t-if="!widget.is_private">
<span class="oe_all_follower">
Followers of
<t t-if="widget.parent_thread.parent_message.record_name" t-raw="'&quot;' + widget.parent_thread.parent_message.record_name + '&quot;'"/>
<t t-if="!widget.parent_thread.parent_message.record_name">this document</t>
<t t-if="widget.parent_thread.parent_message.record_name" t-raw="'&quot;' + widget.parent_thread.parent_message.record_name + '&quot;'">
Followers of <t t-raw="'&quot;' + widget.parent_thread.parent_message.record_name + '&quot;'"/>
</t>
<t t-if="!widget.parent_thread.parent_message.record_name and widget.options.view_inbox">My Followers</t>
<t t-if="!widget.parent_thread.parent_message.record_name and !widget.options.view_inbox">Followers of this document</t>
</span>
</t>
<t t-if="!widget.is_private and (widget.partner_ids.length or (widget.author_id and widget.author_id[0]))"> and </t>
@ -197,8 +199,16 @@
</tbody>
</table>
<div class="oe_mail-placeholder"></div>
<aside class="oe_mail_wall_aside"></aside>
</div>
<!--
Empty template that holds the sidebar of the Wall
-->
<t t-name="mail.wall.sidebar">
<div class="oe_mail_wall_sidebar"></div>
</t>
<!--
display message on the wall when there are no message
-->
@ -271,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>
@ -295,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>
@ -339,7 +352,4 @@
</a>
</span>
<!-- mail.thread.message.star
Template used to display stared/unstared message in a mail.message
-->
</template>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<!-- Groups placeholder in sidebar -->
<t t-extend="mail.wall.sidebar">
<t t-jquery=".oe_mail_wall_sidebar" t-operation="append">
<div class="oe_suggestions_groups"></div>
</t>
</t>
<!-- Suggested groups -->
<div t-name="mail.suggestions.groups" class="oe_sidebar_suggestion oe_suggestion_group">
<div class="oe_suggest_title">
<a class="oe_suggestion_remove oe_suggestion_group oe_e">X</a>
<h2>Suggested Groups</h2>
</div>
<div class="oe_suggest_items">
<t t-foreach="widget.groups" t-as="result">
<div class="oe_suggested_item">
<div class="oe_suggested_item_image">
<a t-attf-href="#model=mail.group&amp;id=#{result.id}">
<img t-attf-src="{result.image}" t-attf-alt="{result.name}"/>
</a>
</div>
<div class="oe_suggested_item_content">
<a class="oe_suggestion_item_name" t-attf-href="#model=mail.group&amp;id=#{result.id}"><t t-esc="result.name"/></a>
<a class="oe_suggestion_remove_item oe_suggestion_group oe_e" t-attf-id="{result.id}">X</a>
<br/>
<button t-att-id="result.id" class="oe_suggestion_join">Join Group</button>
</div>
</div>
</t>
</div>
</div>
</template>

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', '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_find_partner_from_emails wrong partner found')
def test_05_mail_message_mail_mail(self):
""" Tests designed for testing email values based on mail.message, aliases, ... """
cr, uid, user_raoul_id = self.cr, self.uid, self.user_raoul_id
# Data: update + generic variables
reply_to1 = '_reply_to1@example.com'
reply_to2 = '_reply_to2@example.com'
email_from1 = 'from@example.com'
alias_domain = 'schlouby.fr'
raoul_from = 'Raoul Grosbedon <raoul@raoul.fr>'
raoul_from_alias = 'Raoul Grosbedon <raoul@schlouby.fr>'
raoul_reply = '"Followers of Pigs" <raoul@raoul.fr>'
raoul_reply_alias = '"Followers of Pigs" <group+pigs@schlouby.fr>'
# Data: remove alias_domain to see emails with alias
param_ids = self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.domain')])
self.registry('ir.config_parameter').unlink(cr, uid, param_ids)
# Do: free message; specified values > default values
msg_id = self.mail_message.create(cr, user_raoul_id, {'reply_to': reply_to1, 'email_from': email_from1})
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
# Test: message content
self.assertIn('reply_to', msg.message_id,
'mail_message: message_id should be specific to a mail_message with a given reply_to')
self.assertEqual(msg.reply_to, reply_to1,
'mail_message: incorrect reply_to: should come from values')
self.assertEqual(msg.email_from, email_from1,
'mail_message: incorrect email_from: should come from values')
# Do: create a mail_mail with the previous mail_message
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, reply_to1,
'mail_mail: incorrect reply_to: should come from mail.message')
self.assertEqual(mail.email_from, email_from1,
'mail_mail: incorrect email_from: should come from mail.message')
# Do: create a mail_mail with the previous mail_message + specified reply_to
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel', 'reply_to': reply_to2})
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, reply_to2,
'mail_mail: incorrect reply_to: should come from values')
self.assertEqual(mail.email_from, email_from1,
'mail_mail: incorrect email_from: should come from mail.message')
# Do: mail_message attached to a document
msg_id = self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_pigs_id})
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
# Test: message content
self.assertIn('mail.group', msg.message_id,
'mail_message: message_id should contain model')
self.assertIn('%s' % self.group_pigs_id, msg.message_id,
'mail_message: message_id should contain res_id')
self.assertFalse(msg.reply_to,
'mail_message: incorrect reply_to: should not be generated if not specified')
self.assertEqual(msg.email_from, raoul_from,
'mail_message: incorrect email_from: should be Raoul')
# Do: create a mail_mail based on the previous mail_message
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, raoul_reply,
'mail_mail: incorrect reply_to: should be Raoul')
# Data: set catchall domain
self.registry('ir.config_parameter').set_param(cr, uid, 'mail.catchall.domain', alias_domain)
# Update message
self.mail_message.write(cr, user_raoul_id, [msg_id], {'email_from': False, 'reply_to': False})
msg.refresh()
# Do: create a mail_mail based on the previous mail_message
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, raoul_reply_alias,
'mail_mail: incorrect reply_to: should be Pigs alias')
# Update message: test alias on email_from
msg_id = self.mail_message.create(cr, user_raoul_id, {})
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
# Do: create a mail_mail based on the previous mail_message
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, raoul_from_alias,
'mail_mail: incorrect reply_to: should be message email_from using Raoul alias')
# Update message
self.mail_message.write(cr, user_raoul_id, [msg_id], {'res_id': False, 'email_from': 'someone@schlouby.fr', 'reply_to': False})
msg.refresh()
# Do: create a mail_mail based on the previous mail_message
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
# Test: mail_mail content
self.assertEqual(mail.reply_to, msg.email_from,
'mail_mail: incorrect reply_to: should be message email_from')
def test_05_mail_message_mail_mail(self):
""" 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:

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