[MERGE] with addons.

bzr revid: nco@tinyerp.com-20130628052246-xyfgxyrcrjfahi92
This commit is contained in:
Nimesh Contractor (OpenERP) 2013-06-28 10:52:46 +05:30
commit 95a9a403a4
178 changed files with 13358 additions and 2301 deletions

View File

@ -221,8 +221,8 @@ class account_invoice(osv.osv):
'type': {
},
'state': {
'account.mt_invoice_paid': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'paid' and obj['type'] in ('out_invoice', 'out_refund'),
'account.mt_invoice_validated': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open' and obj['type'] in ('out_invoice', 'out_refund'),
'account.mt_invoice_paid': lambda self, cr, uid, obj, ctx=None: obj.state == 'paid' and obj.type in ('out_invoice', 'out_refund'),
'account.mt_invoice_validated': lambda self, cr, uid, obj, ctx=None: obj.state == 'open' and obj.type in ('out_invoice', 'out_refund'),
},
}
_columns = {

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

@ -189,44 +189,34 @@ class res_partner(osv.osv):
'debit': fields.function(_credit_debit_get, fnct_search=_debit_search, string='Total Payable', multi='dc', help="Total amount you have to pay to this supplier."),
'debit_limit': fields.float('Payable Limit'),
'property_account_payable': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Account Payable",
view_load=True,
domain="[('type', '=', 'payable')]",
help="This account will be used instead of the default one as the payable account for the current partner",
required=True),
'property_account_receivable': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Account Receivable",
view_load=True,
domain="[('type', '=', 'receivable')]",
help="This account will be used instead of the default one as the receivable account for the current partner",
required=True),
'property_account_position': fields.property(
'account.fiscal.position',
type='many2one',
relation='account.fiscal.position',
string="Fiscal Position",
view_load=True,
help="The fiscal position will determine taxes and accounts used for the partner.",
),
'property_payment_term': fields.property(
'account.payment.term',
type='many2one',
relation='account.payment.term',
string ='Customer Payment Term',
view_load=True,
help="This payment term will be used instead of the default one for sale orders and customer invoices"),
'property_supplier_payment_term': fields.property(
'account.payment.term',
type='many2one',
relation='account.payment.term',
string ='Supplier Payment Term',
view_load=True,
help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
'ref_companies': fields.one2many('res.company', 'partner_id',
'Companies that refers to partner'),

View File

@ -25,18 +25,14 @@ class product_category(osv.osv):
_inherit = "product.category"
_columns = {
'property_account_income_categ': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Income Account",
view_load=True,
help="This account will be used for invoices to value sales."),
'property_account_expense_categ': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
view_load=True,
help="This account will be used for invoices to value expenses."),
}
@ -54,18 +50,14 @@ class product_template(osv.osv):
'product_supplier_taxes_rel', 'prod_id', 'tax_id',
'Supplier Taxes', domain=[('parent_id', '=', False),('type_tax_use','in',['purchase','all'])]),
'property_account_income': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Income Account",
view_load=True,
help="This account will be used for invoices instead of the default one to value sales for the current product."),
'property_account_expense': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
view_load=True,
help="This account will be used for invoices instead of the default one to value expenses for the current product."),
}

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

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

View File

@ -117,21 +117,27 @@ class account_invoice_line(osv.osv):
for line in res:
if a == line['account_id'] and i_line.product_id.id == line['product_id']:
uom = i_line.product_id.uos_id or i_line.product_id.uom_id
standard_price = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
if standard_price != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
price_diff = i_line.price_unit - standard_price
line.update({'price':standard_price * line['quantity']})
valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id:
#for average/fifo/lifo costing method, fetch real cost price from incomming moves
stock_move_obj = self.pool.get('stock.move')
valuation_stock_move = stock_move_obj.search(cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context)
if valuation_stock_move:
valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit
if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
price_diff = i_line.price_unit - valuation_price_unit
line.update({'price': valuation_price_unit * line['quantity']})
diff_res.append({
'type':'src',
'type': 'src',
'name': i_line.name[:64],
'price_unit':price_diff,
'quantity':line['quantity'],
'price_unit': price_diff,
'quantity': line['quantity'],
'price': price_diff * line['quantity'],
'account_id':acc,
'product_id':line['product_id'],
'uos_id':line['uos_id'],
'account_analytic_id':line['account_analytic_id'],
'taxes':line.get('taxes',[]),
'account_id': acc,
'product_id': line['product_id'],
'uos_id': line['uos_id'],
'account_analytic_id': line['account_analytic_id'],
'taxes': line.get('taxes', []),
})
res += diff_res
return res

View File

@ -24,27 +24,21 @@ class product_category(osv.osv):
_inherit = "product.category"
_columns = {
'property_account_creditor_price_difference_categ': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Price Difference Account",
view_load=True,
help="This account will be used to value price difference between purchase price and cost price."),
#Redefine fields to change help text for anglo saxon methodology.
'property_account_income_categ': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Income Account",
view_load=True,
help="This account will be used to value outgoing stock using sale price."),
'property_account_expense_categ': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
view_load=True,
help="This account will be used to value outgoing stock using cost price."),
}
@ -53,27 +47,21 @@ class product_template(osv.osv):
_inherit = "product.template"
_columns = {
'property_account_creditor_price_difference': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Price Difference Account",
view_load=True,
help="This account will be used to value price difference between purchase price and cost price."),
#Redefine fields to change help text for anglo saxon methodology.
'property_account_income': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Income Account",
view_load=True,
help="This account will be used to value outgoing stock using sale price."),
'property_account_expense': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
view_load=True,
help="This account will be used to value outgoing stock using cost price."),
}

View File

@ -26,16 +26,15 @@ class purchase_order(osv.osv):
_inherit = "purchase.order"
_description = "Purchase Order"
def _prepare_inv_line(self, cr, uid, account_id, order_line, context=None):
line = super(purchase_order, self)._prepare_inv_line(cr, uid, account_id, order_line, context=context)
def _choose_account_from_po_line(self, cr, uid, order_line, context=None):
account_id = super(purchase_order, self)._choose_account_from_po_line(cr, uid, order_line, context=context)
if order_line.product_id and not order_line.product_id.type == 'service':
acc_id = order_line.product_id.property_stock_account_input and order_line.product_id.property_stock_account_input.id
if not acc_id:
acc_id = order_line.product_id.categ_id.property_stock_account_input_categ and order_line.product_id.categ_id.property_stock_account_input_categ.id
if acc_id:
fpos = order_line.order_id.fiscal_position or False
new_account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, acc_id)
line.update({'account_id': new_account_id})
return line
account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, acc_id)
return account_id
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -109,7 +109,7 @@
-
!record {model: purchase.order, id: purchase_order_001}:
partner_id: base.res_partner_3
location_id: stock.stock_location_3
location_id: stock.stock_location_stock
pricelist_id: 1
order_line:
- product_id: product.product_product_3
@ -128,12 +128,12 @@
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.
I check the Stock Interim account (Received) is credited 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.
I check the Stock valuation account is debited sucessfully.
-
!assert {model: account.account, id : account_anglo_stock_valuation, string : Stock valuation account is not debited successfully.}:
- debit == 9
@ -192,7 +192,7 @@
invoice_state: 2binvoiced
move_lines:
- company_id: base.main_company
location_id: stock.stock_location_3
location_id: stock.stock_location_stock
product_id: product.product_product_3
product_qty: 1.0
product_uom: product.product_uom_unit

View File

@ -0,0 +1,304 @@
-
In order to test anglo_saxon Configure Different Accounts.
-
!record {model: account.account, id: account_anglo_stock_valuation_fifo}:
code: X3000f
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_fifo}:
code: X2800f
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_fifo}:
code: X2801f
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_fifo}:
code: X7095f
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_fifo}:
code: X5000f
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_fifo}:
code: X440001f
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_fifo}:
code: X400001f
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_fifo}:
code: X7000f
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_fifo}:
code: X8000f
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_fifo
property_account_receivable: account_anglo_receivable_fifo
-
I configure the account receivable of Customer.
-
!record {model: res.partner, id: base.res_partner_13}:
property_account_payable: account_anglo_payable_fifo
property_account_receivable: account_anglo_receivable_fifo
-
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_fifo
-
I create a product with required accounts, and cost method average (but same applies for fifo)
-
!record {model: product.product, id: product_fifo_anglo_saxon}:
name: 'FIFO product for anglo saxon tests'
list_price: 20.00
standard_price: 0
categ_id: product.product_category_4
valuation: 'real_time'
property_account_income: account_anglo_income_fifo
property_account_expense: account_anglo_cogs_fifo
property_account_creditor_price_difference: account_anglo_price_difference_fifo
property_stock_account_input: account_anglo_stock_input_fifo
property_stock_account_output: account_anglo_stock_output_fifo
cost_method: 'average'
-
I create a draft Purchase Order.
-
!record {model: purchase.order, id: purchase_order_001_fifo}:
partner_id: base.res_partner_3
location_id: stock.stock_location_stock
pricelist_id: 1
order_line:
- product_id: product_fifo_anglo_saxon
product_qty: 1
price_unit: 9
date_planned: '2013-08-31'
taxes_id: []
-
I confirm the purchase order.
-
!workflow {model: purchase.order, ref: purchase_order_001_fifo, 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_fifo")).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_fifo, 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_fifo, string : Stock valuation account is not debited successfully.}:
- debit == 9
-
I Validate Invoice of Purchase Order after having changed the price to 10.
-
!python {model: purchase.order}: |
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids]
line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', invoice_ids)])
self.pool.get('account.invoice.line').write(cr, uid, line_ids, {'price_unit': 10})
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_fifo, 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_fifo, 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_fifo, string : Payable(creditor) Account is not Credited successfully.}:
- credit == 10
-
I pay the invoice.
-
!python {model: purchase.order}: |
invoice_ids = self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids
order = self.browse(cr, uid, ref("purchase_order_001_fifo"))
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_fifo'), ref('account.period_8'), journal_ids[0], ref('account_anglo_cash_fifo'), 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_fifo, 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_fifo, string: Bank/Cash account is not credited successfully.}:
- credit == 10
-
I create an Outgoing Picking order
-
!record {model: stock.picking, id: stock_picking_out001_fifo}:
partner_id: base.res_partner_13
invoice_state: 2binvoiced
move_lines:
- company_id: base.main_company
location_id: stock.stock_location_stock
product_id: product_fifo_anglo_saxon
product_qty: 1.0
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_fifo")], {"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_fifo")], {"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_fifo')]})
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_fifo, 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_fifo, 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_fifo")], "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_fifo")], "active_id": ref("stock_picking_out001_fifo")})
-
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_fifo')).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_fifo')).name
account_invoice = self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)])
account_invoice_line = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', account_invoice)])
self.pool.get('account.invoice.line').write(cr, uid, account_invoice_line, {'invoice_line_tax_id': [(6, 0, [])]})
self.pool.get('account.invoice').button_reset_taxes(cr, uid, account_invoice)
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_fifo, 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_fifo, 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_fifo, 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_fifo, 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_fifo')).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_fifo'), ref('account.period_8'),
journal_ids[0], ref('account_anglo_cash_fifo'),
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_fifo, 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_fifo, string: Bank/Cash account is not successfully credited.}:
- debit == 20

View File

@ -33,9 +33,9 @@ class account_analytic_account(osv.osv):
_description = 'Analytic Account'
_track = {
'state': {
'analytic.mt_account_pending': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'pending',
'analytic.mt_account_closed': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'close',
'analytic.mt_account_opened': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open',
'analytic.mt_account_pending': lambda self, cr, uid, obj, ctx=None: obj.state == 'pending',
'analytic.mt_account_closed': lambda self, cr, uid, obj, ctx=None: obj.state == 'close',
'analytic.mt_account_opened': lambda self, cr, uid, obj, ctx=None: obj.state == 'open',
},
}

View File

@ -7,7 +7,8 @@ from werkzeug.exceptions import BadRequest
import openerp
from openerp import SUPERUSER_ID
import openerp.addons.web.http as oeweb
import openerp.addons.web.http as http
from openerp.addons.web.http import request
from openerp.addons.web.controllers.main import db_monodb, set_cookie_and_redirect, login_and_redirect
from openerp.modules.registry import RegistryManager
@ -18,7 +19,7 @@ _logger = logging.getLogger(__name__)
#----------------------------------------------------------
def fragment_to_query_string(func):
@functools.wraps(func)
def wrapper(self, req, **kw):
def wrapper(self, **kw):
if not kw:
return """<html><head><script>
var l = window.location;
@ -30,18 +31,17 @@ def fragment_to_query_string(func):
}
window.location = r;
</script></head><body></body></html>"""
return func(self, req, **kw)
return func(self, **kw)
return wrapper
#----------------------------------------------------------
# Controller
#----------------------------------------------------------
class OAuthController(oeweb.Controller):
_cp_path = '/auth_oauth'
class OAuthController(http.Controller):
@oeweb.jsonrequest
def list_providers(self, req, dbname):
@http.route('/auth_oauth/list_providers', type='json', auth='none')
def list_providers(self, dbname):
try:
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
@ -51,9 +51,9 @@ class OAuthController(oeweb.Controller):
l = []
return l
@oeweb.httprequest
@http.route('/auth_oauth/signin', type='http', auth='none')
@fragment_to_query_string
def signin(self, req, **kw):
def signin(self, **kw):
state = simplejson.loads(kw['state'])
dbname = state['d']
provider = state['p']
@ -71,7 +71,7 @@ class OAuthController(oeweb.Controller):
url = '/#action=%s' % action
elif menu:
url = '/#menu_id=%s' % menu
return login_and_redirect(req, *credentials, redirect_url=url)
return login_and_redirect(*credentials, redirect_url=url)
except AttributeError:
# auth_signup is not installed
_logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,))
@ -88,14 +88,14 @@ class OAuthController(oeweb.Controller):
_logger.exception("OAuth2: %s" % str(e))
url = "/#action=login&oauth_error=2"
return set_cookie_and_redirect(req, url)
return set_cookie_and_redirect(url)
@oeweb.httprequest
def oea(self, req, **kw):
@http.route('/auth_oauth/oea', type='http', auth='none')
def oea(self, **kw):
"""login user via OpenERP Account provider"""
dbname = kw.pop('db', None)
if not dbname:
dbname = db_monodb(req)
dbname = db_monodb()
if not dbname:
return BadRequest()
@ -105,7 +105,7 @@ class OAuthController(oeweb.Controller):
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)
return set_cookie_and_redirect('/?db=%s' % dbname)
assert model == 'auth.oauth.provider'
state = {
@ -115,6 +115,6 @@ class OAuthController(oeweb.Controller):
}
kw['state'] = simplejson.dumps(state)
return self.signin(req, **kw)
return self.signin(**kw)
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -38,6 +38,8 @@ import openerp
from openerp import SUPERUSER_ID
from openerp.modules.registry import RegistryManager
from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect
import openerp.addons.web.http as http
from openerp.addons.web.http import request
from .. import utils
@ -88,20 +90,19 @@ class GoogleAppsAwareConsumer(consumer.GenericConsumer):
return super(GoogleAppsAwareConsumer, self).complete(message, endpoint, return_to)
class OpenIDController(openerp.addons.web.http.Controller):
_cp_path = '/auth_openid/login'
class OpenIDController(http.Controller):
_store = filestore.FileOpenIDStore(_storedir)
_REQUIRED_ATTRIBUTES = ['email']
_OPTIONAL_ATTRIBUTES = 'nickname fullname postcode country language timezone'.split()
def _add_extensions(self, request):
"""Add extensions to the request"""
def _add_extensions(self, oidrequest):
"""Add extensions to the oidrequest"""
sreg_request = sreg.SRegRequest(required=self._REQUIRED_ATTRIBUTES,
optional=self._OPTIONAL_ATTRIBUTES)
request.addExtension(sreg_request)
oidrequest.addExtension(sreg_request)
ax_request = ax.FetchRequest()
for alias in self._REQUIRED_ATTRIBUTES:
@ -111,7 +112,7 @@ class OpenIDController(openerp.addons.web.http.Controller):
uri = utils.SREG2AX[alias]
ax_request.add(ax.AttrInfo(uri, required=False, alias=alias))
request.addExtension(ax_request)
oidrequest.addExtension(ax_request)
def _get_attributes_from_success_response(self, success_response):
attrs = {}
@ -133,58 +134,58 @@ class OpenIDController(openerp.addons.web.http.Controller):
attrs[attr] = value
return attrs
def _get_realm(self, req):
return req.httprequest.host_url
def _get_realm(self):
return request.httprequest.host_url
@openerp.addons.web.http.httprequest
def verify_direct(self, req, db, url):
result = self._verify(req, db, url)
@http.route('/auth_openid/login/verify_direct', type='http', auth='none')
def verify_direct(self, db, url):
result = self._verify(db, url)
if 'error' in result:
return werkzeug.exceptions.BadRequest(result['error'])
if result['action'] == 'redirect':
return werkzeug.utils.redirect(result['value'])
return result['value']
@openerp.addons.web.http.jsonrequest
def verify(self, req, db, url):
return self._verify(req, db, url)
@http.route('/auth_openid/login/verify', type='json', auth='none')
def verify(self, db, url):
return self._verify(db, url)
def _verify(self, req, db, url):
redirect_to = werkzeug.urls.Href(req.httprequest.host_url + 'auth_openid/login/process')(session_id=req.session_id)
realm = self._get_realm(req)
def _verify(self, db, url):
redirect_to = werkzeug.urls.Href(request.httprequest.host_url + 'auth_openid/login/process')(session_id=request.session_id)
realm = self._get_realm()
session = dict(dbname=db, openid_url=url) # TODO add origin page ?
oidconsumer = consumer.Consumer(session, self._store)
try:
request = oidconsumer.begin(url)
oidrequest = oidconsumer.begin(url)
except consumer.DiscoveryFailure, exc:
fetch_error_string = 'Error in discovery: %s' % (str(exc[0]),)
return {'error': fetch_error_string, 'title': 'OpenID Error'}
if request is None:
if oidrequest is None:
return {'error': 'No OpenID services found', 'title': 'OpenID Error'}
req.session.openid_session = session
self._add_extensions(request)
request.session.openid_session = session
self._add_extensions(oidrequest)
if request.shouldSendRedirect():
redirect_url = request.redirectURL(realm, redirect_to)
return {'action': 'redirect', 'value': redirect_url, 'session_id': req.session_id}
if oidrequest.shouldSendRedirect():
redirect_url = oidrequest.redirectURL(realm, redirect_to)
return {'action': 'redirect', 'value': redirect_url, 'session_id': request.session_id}
else:
form_html = request.htmlMarkup(realm, redirect_to)
return {'action': 'post', 'value': form_html, 'session_id': req.session_id}
form_html = oidrequest.htmlMarkup(realm, redirect_to)
return {'action': 'post', 'value': form_html, 'session_id': request.session_id}
@openerp.addons.web.http.httprequest
def process(self, req, **kw):
session = getattr(req.session, 'openid_session', None)
@http.route('/auth_openid/login/process', type='http', auth='none')
def process(self, **kw):
session = getattr(request.session, 'openid_session', None)
if not session:
return set_cookie_and_redirect(req, '/')
return set_cookie_and_redirect('/')
oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer)
query = req.httprequest.args
info = oidconsumer.complete(query, req.httprequest.base_url)
query = request.httprequest.args
info = oidconsumer.complete(query, request.httprequest.base_url)
display_identifier = info.getDisplayIdentifier()
session['status'] = info.status
@ -225,7 +226,7 @@ class OpenIDController(openerp.addons.web.http.Controller):
# TODO fill empty fields with the ones from sreg/ax
cr.commit()
return login_and_redirect(req, dbname, login, key)
return login_and_redirect(dbname, login, key)
session['message'] = 'This OpenID identifier is not associated to any active users'
@ -241,11 +242,11 @@ class OpenIDController(openerp.addons.web.http.Controller):
# information in a log.
session['message'] = 'Verification failed.'
return set_cookie_and_redirect(req, '/#action=login&loginerror=1')
return set_cookie_and_redirect('/#action=login&loginerror=1')
@openerp.addons.web.http.jsonrequest
def status(self, req):
session = getattr(req.session, 'openid_session', {})
@http.route('/auth_openid/login/status', type='json', auth='none')
def status(self):
session = getattr(request.session, 'openid_session', {})
return {'status': session.get('status'), 'message': session.get('message')}

View File

@ -23,14 +23,15 @@ import logging
import openerp
from openerp.modules.registry import RegistryManager
from ..res_users import SignupError
import openerp.addons.web.http as http
from openerp.addons.web.http import request
_logger = logging.getLogger(__name__)
class Controller(openerp.addons.web.http.Controller):
_cp_path = '/auth_signup'
class Controller(http.Controller):
@openerp.addons.web.http.jsonrequest
def get_config(self, req, dbname):
@http.route('/auth_signup/get_config', type='json', auth="none")
def get_config(self, dbname):
""" retrieve the module config (which features are enabled) for the login page """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
@ -41,8 +42,8 @@ class Controller(openerp.addons.web.http.Controller):
}
return config
@openerp.addons.web.http.jsonrequest
def retrieve(self, req, dbname, token):
@http.route('/auth_signup/retrieve', type='json', auth="user")
def retrieve(self, dbname, token):
""" retrieve the user info (name, login or email) corresponding to a signup token """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
@ -50,23 +51,23 @@ class Controller(openerp.addons.web.http.Controller):
user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token)
return user_info
@openerp.addons.web.http.jsonrequest
def signup(self, req, dbname, token, **values):
@http.route('/auth_signup/signup', type='json', auth="user")
def signup(self, dbname, token, **values):
""" sign up a user (new or existing)"""
try:
self._signup_with_values(req, dbname, token, values)
self._signup_with_values(dbname, token, values)
except SignupError, e:
return {'error': openerp.tools.exception_to_unicode(e)}
return {}
def _signup_with_values(self, req, dbname, token, values):
def _signup_with_values(self, dbname, token, values):
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
res_users = registry.get('res.users')
res_users.signup(cr, openerp.SUPERUSER_ID, values, token)
@openerp.addons.web.http.jsonrequest
def reset_password(self, req, dbname, login):
@http.route('/auth_signup/reset_password', type='json', auth="user")
def reset_password(self, dbname, login):
""" retrieve user, and perform reset password """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:

View File

@ -0,0 +1,249 @@
# 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 13:54+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-21 05:36+0000\n"
"X-Generator: Launchpad (build 16677)\n"
#. module: base_gengo
#: view:res.company:0
msgid "Comments for Translator"
msgstr ""
#. module: base_gengo
#: field:ir.translation,job_id:0
msgid "Gengo Job ID"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:114
#, python-format
msgid "This language is not supported by the Gengo translation services."
msgstr ""
#. module: base_gengo
#: field:res.company,gengo_comment:0
msgid "Comments"
msgstr "ความคิดเห็น"
#. module: base_gengo
#: field:res.company,gengo_private_key:0
msgid "Gengo Private Key"
msgstr ""
#. module: base_gengo
#: model:ir.model,name:base_gengo.model_base_gengo_translations
msgid "base.gengo.translations"
msgstr "base.gengo.translations"
#. module: base_gengo
#: help:res.company,gengo_auto_approve:0
msgid "Jobs are Automatically Approved by Gengo."
msgstr ""
#. module: base_gengo
#: field:base.gengo.translations,lang_id:0
msgid "Language"
msgstr "ภาษา"
#. module: base_gengo
#: field:ir.translation,gengo_comment:0
msgid "Comments & Activity Linked to Gengo"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:124
#, python-format
msgid "Gengo Sync Translation (Response)"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:72
#, python-format
msgid ""
"Gengo `Public Key` or `Private Key` are missing. Enter your Gengo "
"authentication parameters under `Settings > Companies > Gengo Parameters`."
msgstr ""
#. module: base_gengo
#: selection:ir.translation,gengo_translation:0
msgid "Translation By Machine"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:155
#, python-format
msgid ""
"%s\n"
"\n"
"--\n"
" Commented on %s by %s."
msgstr ""
#. module: base_gengo
#: field:ir.translation,gengo_translation:0
msgid "Gengo Translation Service Level"
msgstr ""
#. module: base_gengo
#: constraint:ir.translation:0
msgid ""
"The Gengo translation service selected is not supported for this language."
msgstr ""
#. module: base_gengo
#: selection:ir.translation,gengo_translation:0
msgid "Standard"
msgstr ""
#. module: base_gengo
#: help:ir.translation,gengo_translation:0
msgid ""
"You can select here the service level you want for an automatic translation "
"using Gengo."
msgstr ""
#. module: base_gengo
#: field:base.gengo.translations,restart_send_job:0
msgid "Restart Sending Job"
msgstr ""
#. module: base_gengo
#: view:ir.translation:0
msgid "To Approve In Gengo"
msgstr ""
#. module: base_gengo
#: view:res.company:0
msgid "Private Key"
msgstr ""
#. module: base_gengo
#: view:res.company:0
msgid "Public Key"
msgstr ""
#. module: base_gengo
#: field:res.company,gengo_public_key:0
msgid "Gengo Public Key"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:123
#, python-format
msgid "Gengo Sync Translation (Request)"
msgstr ""
#. module: base_gengo
#: view:ir.translation:0
msgid "Translations"
msgstr ""
#. module: base_gengo
#: field:res.company,gengo_auto_approve:0
msgid "Auto Approve Translation ?"
msgstr ""
#. module: base_gengo
#: model:ir.actions.act_window,name:base_gengo.action_wizard_base_gengo_translations
#: model:ir.ui.menu,name:base_gengo.menu_action_wizard_base_gengo_translations
msgid "Gengo: Manual Request of Translation"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/ir_translation.py:62
#: code:addons/base_gengo/wizard/base_gengo_translations.py:109
#, python-format
msgid "Gengo Authentication Error"
msgstr ""
#. module: base_gengo
#: model:ir.model,name:base_gengo.model_res_company
msgid "Companies"
msgstr ""
#. module: base_gengo
#: view:ir.translation:0
msgid ""
"Note: If the translation state is 'In Progress', it means that the "
"translation has to be approved to be uploaded in this system. You are "
"supposed to do that directly by using your Gengo Account"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:82
#, python-format
msgid ""
"Gengo connection failed with this message:\n"
"``%s``"
msgstr ""
#. module: base_gengo
#: view:res.company:0
msgid "Gengo Parameters"
msgstr ""
#. module: base_gengo
#: view:base.gengo.translations:0
msgid "Send"
msgstr ""
#. module: base_gengo
#: selection:ir.translation,gengo_translation:0
msgid "Ultra"
msgstr ""
#. module: base_gengo
#: model:ir.model,name:base_gengo.model_ir_translation
msgid "ir.translation"
msgstr ""
#. module: base_gengo
#: view:ir.translation:0
msgid "Gengo Translation Service"
msgstr ""
#. module: base_gengo
#: selection:ir.translation,gengo_translation:0
msgid "Pro"
msgstr ""
#. module: base_gengo
#: view:base.gengo.translations:0
msgid "Gengo Request Form"
msgstr ""
#. module: base_gengo
#: code:addons/base_gengo/wizard/base_gengo_translations.py:114
#, python-format
msgid "Warning"
msgstr ""
#. module: base_gengo
#: help:res.company,gengo_comment:0
msgid ""
"This comment will be automatically be enclosed in each an every request sent "
"to Gengo"
msgstr ""
#. module: base_gengo
#: view:base.gengo.translations:0
msgid "Cancel"
msgstr ""
#. module: base_gengo
#: view:base.gengo.translations:0
msgid "or"
msgstr ""

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

@ -36,6 +36,8 @@ class base_config_settings(osv.osv_memory):
help="""Enable the public part of openerp, openerp becomes a public website."""),
'module_auth_oauth': fields.boolean('Use external authentication providers, sign in with google, facebook, ...'),
'module_base_import': fields.boolean("Allow users to import data from CSV files"),
'module_google_drive': fields.boolean('Attach Google documents to any record',
help="""This installs the module google_docs."""),
}
def open_company(self, cr, uid, ids, context=None):

View File

@ -81,6 +81,15 @@
</div>
</div>
</group>
<group>
<label for="id" string="Google Drive"/>
<div name="google_drive">
<div name="module_google_drive">
<field name="module_google_drive" class="oe_inline"/>
<label for="module_google_drive"/>
</div>
</div>
</group>
</form>
</field>
</record>

View File

@ -222,17 +222,13 @@ class crm_case_section(osv.osv):
return res
def create(self, cr, uid, vals, context=None):
mail_alias = self.pool.get('mail.alias')
if not vals.get('alias_id'):
alias_name = vals.pop('alias_name', None) or vals.get('name') # prevent errors during copy()
alias_id = mail_alias.create_unique_alias(cr, uid,
{'alias_name': alias_name},
model_name="crm.lead",
context=context)
vals['alias_id'] = alias_id
res = super(crm_case_section, self).create(cr, uid, vals, context)
mail_alias.write(cr, uid, [vals['alias_id']], {'alias_defaults': {'section_id': res, 'type': 'lead'}}, context)
return res
if context is None:
context = {}
create_context = dict(context, alias_model_name='crm.lead', alias_parent_model_name=self._name)
section_id = super(crm_case_section, self).create(cr, uid, vals, context=create_context)
section = self.browse(cr, uid, section_id, context=context)
self.pool.get('mail.alias').write(cr, uid, [section.alias_id.id], {'alias_parent_thread_id': section_id, 'alias_defaults': {'section_id': section_id, 'type': 'lead'}}, context=context)
return section_id
def unlink(self, cr, uid, ids, context=None):
# Cascade-delete mail aliases as well, as they should not exist without the sales team.

View File

@ -94,7 +94,7 @@
<div class="oe_kanban_content">
<h4 class="oe_center"><field name="name"/></h4>
<div class="oe_kanban_alias oe_center" t-if="record.use_leads.raw_value and record.alias_id.value">
<small><span class="oe_e" style="float: none;">%%</span><t t-raw="record.alias_id.raw_value[1]"/></small>
<small><span class="oe_e oe_e_alias" style="float: none;">%%</span><t t-raw="record.alias_id.raw_value[1]"/></small>
</div>
<div class="oe_items_list">
<div class="oe_salesteams_leads" t-if="record.use_leads.raw_value">
@ -168,17 +168,6 @@
<h1>
<field name="name" string="Salesteam"/>
</h1>
<div name="group_alias"
attrs="{'invisible': [('alias_domain', '=', False)]}">
<label for="alias_id" string="Email Alias"/>
<field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
<span name="edit_alias" class="oe_edit_only">
<field name="alias_name" class="oe_inline"
attrs="{'required': [('use_leads', '=', True), ('alias_id', '!=', False)]}"/>
@
<field name="alias_domain" class="oe_inline" readonly="1"/>
</span>
</div>
<div name="options_active">
<field name="use_leads" class="oe_inline"/><label for="use_leads"/>
</div>
@ -187,12 +176,25 @@
<group>
<field name="user_id"/>
<field name="code"/>
</group>
<group>
<field name="parent_id"/>
<field name="change_responsible"/>
<field name="active"/>
</group>
<group>
<label for="alias_name" string="Email Alias"
attrs="{'invisible': [('alias_domain', '=', False)]}"/>
<div name="alias_def"
attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_id" class="oe_read_only oe_inline"
string="Email Alias" required="0"/>
<div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;" >
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
</div>
<field name="alias_contact" class="oe_inline"
string="Accept Emails From"
attrs="{'invisible': [('alias_domain', '=', False)]}"/>
</group>
</group>
<notebook colspan="4">
<page string="Team Members">

View File

@ -77,12 +77,12 @@ class crm_lead(base_stage, format_address, osv.osv):
_track = {
'state': {
'crm.mt_lead_create': lambda self, cr, uid, obj, ctx=None: obj['state'] in ['new', 'draft'],
'crm.mt_lead_won': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done',
'crm.mt_lead_lost': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel',
'crm.mt_lead_create': lambda self, cr, uid, obj, ctx=None: obj.state in ['new', 'draft'],
'crm.mt_lead_won': lambda self, cr, uid, obj, ctx=None: obj.state == 'done',
'crm.mt_lead_lost': lambda self, cr, uid, obj, ctx=None: obj.state == 'cancel',
},
'stage_id': {
'crm.mt_lead_stage': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['new', 'draft', 'cancel', 'done'],
'crm.mt_lead_stage': lambda self, cr, uid, obj, ctx=None: obj.state not in ['new', 'draft', 'cancel', 'done'],
},
}
@ -719,7 +719,6 @@ class crm_lead(base_stage, format_address, osv.osv):
continue
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
self.write(cr, uid, [lead.id], vals, context=context)
self.message_post(cr, uid, ids, body=_("Lead <b>converted into an Opportunity</b>"), subtype="crm.mt_lead_convert_to_opportunity", context=context)
if user_ids or section_id:
self.allocate_salesman(cr, uid, ids, user_ids, section_id, context=context)

View File

@ -163,12 +163,6 @@
<field name="default" eval="False"/>
<field name="description">Opportunity created</field>
</record>
<record id="mt_lead_convert_to_opportunity" model="mail.message.subtype">
<field name="name">Lead to Opportunity</field>
<field name="res_model">crm.lead</field>
<field name="default" eval="False"/>
<field name="description">Lead converted into an opportunity</field>
</record>
<record id="mt_lead_stage" model="mail.message.subtype">
<field name="name">Stage Changed</field>
<field name="res_model">crm.lead</field>
@ -195,13 +189,6 @@
<field name="parent_id" eval="ref('mt_lead_create')"/>
<field name="relation_field">section_id</field>
</record>
<record id="mt_salesteam_lead_opportunity" model="mail.message.subtype">
<field name="name">Lead to Opportunity</field>
<field name="default" eval="False"/>
<field name="res_model">crm.case.section</field>
<field name="parent_id" eval="ref('mt_lead_convert_to_opportunity')"/>
<field name="relation_field">section_id</field>
</record>
<record id="mt_salesteam_lead_stage" model="mail.message.subtype">
<field name="name">Opportunity Stage Changed</field>
<field name="res_model">crm.case.section</field>

View File

@ -709,5 +709,6 @@ Andrew</field>
eval="[ ref('msg_case18_1'), ref('msg_case18_2')], True, {}"
/>
</data>
</openerp>

View File

@ -601,7 +601,9 @@
'default_email_to':'{$object.email or \'\'}',
'default_use_template': True,
'default_template_id': ref('crm.email_template_opportunity_mail'),
}"/>
}"
groups="base.group_sale_salesman"
/>
<!--Update of email_template defined in crm_lead_data, to add ref_ir_act_window
allowing to have a well formed email template (context action considered as set). -->
@ -617,6 +619,7 @@
if context.get('active_model') == 'crm.lead' and context.get('active_ids'):
self.case_cancel(cr, uid, context['active_ids'], context=context)
</field>
<field name="groups_id" eval="[(4,ref('base.group_sale_salesman'))]"/>
</record>
<record id="ir_mark_as_lost" model="ir.values">

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-04-13 08:42+0000\n"
"PO-Revision-Date: 2013-06-21 07:11+0000\n"
"Last-Translator: krnkris <Unknown>\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-04-14 05:12+0000\n"
"X-Generator: Launchpad (build 16564)\n"
"X-Launchpad-Export-Date: 2013-06-22 05:36+0000\n"
"X-Generator: Launchpad (build 16677)\n"
#. module: crm
#: view:crm.lead.report:0
@ -31,7 +31,7 @@ msgstr ""
"létrehozását a bejövő levelekből."
#. module: crm
#: code:addons/crm/crm_lead.py:881
#: code:addons/crm/crm_lead.py:898
#: selection:crm.case.stage,type:0
#: view:crm.lead:0
#: selection:crm.lead,type:0
@ -192,8 +192,8 @@ msgstr ""
"direkt HTML formátumú ahhoz hogy beilleszthető legyen a kanban nézetekbe."
#. module: crm
#: code:addons/crm/crm_lead.py:624
#: code:addons/crm/crm_lead.py:744
#: code:addons/crm/crm_lead.py:640
#: code:addons/crm/crm_lead.py:761
#: code:addons/crm/crm_phonecall.py:280
#, python-format
msgid "Warning!"
@ -304,7 +304,7 @@ msgid "Prospect Partner"
msgstr "Leendő partner"
#. module: crm
#: code:addons/crm/crm_lead.py:982
#: code:addons/crm/crm_lead.py:1002
#, python-format
msgid "No Subject"
msgstr "Nincs tárgy"
@ -482,7 +482,7 @@ msgid "#Opportunities"
msgstr "Lehetőségek száma"
#. module: crm
#: code:addons/crm/crm_lead.py:624
#: code:addons/crm/crm_lead.py:640
#, python-format
msgid ""
"Please select more than one element (lead or opportunity) from the list view."
@ -782,7 +782,7 @@ msgid "Statistics Dashboard"
msgstr "Statisztika vezérlőpult"
#. module: crm
#: code:addons/crm/crm_lead.py:861
#: code:addons/crm/crm_lead.py:878
#: model:crm.case.stage,name:crm.stage_lead2
#: selection:crm.case.stage,type:0
#: view:crm.lead:0
@ -844,7 +844,7 @@ msgid "Exclusive"
msgstr "Kizárólagos"
#. module: crm
#: code:addons/crm/crm_lead.py:584
#: code:addons/crm/crm_lead.py:600
#, python-format
msgid "From %s : %s"
msgstr "Ettől %s : %s"
@ -1016,7 +1016,7 @@ msgid "Next Action"
msgstr "Következő művelet"
#. module: crm
#: code:addons/crm/crm_lead.py:763
#: code:addons/crm/crm_lead.py:780
#, python-format
msgid "<b>Partner</b> set to <em>%s</em>."
msgstr "<b>Partner</b> beállítva mint <em>%s</em>."
@ -1109,7 +1109,7 @@ msgid "Creation Date"
msgstr "Létrehozás dátuma"
#. module: crm
#: code:addons/crm/crm_lead.py:698
#: code:addons/crm/crm_lead.py:715
#, python-format
msgid "Lead <b>converted into an Opportunity</b>"
msgstr "Tervezet <b>lehetőséggé átalakítva lehetőséggé</b>"
@ -1324,7 +1324,9 @@ msgid "Days to Close"
msgstr "Lezárásig hátralévő napok"
#. module: crm
#: code:addons/crm/crm_lead.py:1057
#: field:crm.case.section,complete_name:0
#, python-format
msgid "unknown"
msgstr "Ismeretlen"
@ -1415,7 +1417,7 @@ msgid "Lead Description"
msgstr "Érdeklődés leírása"
#. module: crm
#: code:addons/crm/crm_lead.py:565
#: code:addons/crm/crm_lead.py:581
#, python-format
msgid "Merged opportunities"
msgstr "Lehetőségek összefésülése"
@ -1989,7 +1991,7 @@ msgid "Leads"
msgstr "Érdeklődők"
#. module: crm
#: code:addons/crm/crm_lead.py:563
#: code:addons/crm/crm_lead.py:579
#, python-format
msgid "Merged leads"
msgstr "Össztefésült érdeklődések"
@ -2085,7 +2087,6 @@ msgid "Global CC"
msgstr "Globális CC /másolat/"
#. module: crm
#: view:crm.lead:0
#: view:crm.phonecall:0
#: model:ir.actions.act_window,name:crm.crm_case_categ_phone0
#: model:ir.ui.menu,name:crm.menu_crm_case_phone
@ -2399,7 +2400,7 @@ msgstr "Érdeklődés átalakítva egy lehetőséggé"
#. module: crm
#: view:crm.lead:0
msgid "Unassigned Leads"
msgstr "Nem iktatott rdeklődések"
msgstr "Nem iktatott érdeklődések"
#. module: crm
#: model:mail.message.subtype,description:crm.mt_lead_won
@ -3100,7 +3101,7 @@ msgid "Working Hours"
msgstr "Munkaórák"
#. module: crm
#: code:addons/crm/crm_lead.py:968
#: code:addons/crm/crm_lead.py:986
#: view:crm.lead:0
#: field:crm.lead2opportunity.partner,partner_id:0
#: field:crm.lead2opportunity.partner.mass,partner_id:0

View File

@ -102,7 +102,9 @@
res_model="crm.lead2opportunity.partner.mass" src_model="crm.lead"
view_mode="form" target="new" view_type="form"
context="{'mass_convert' : True}"
view_id="view_crm_lead2opportunity_partner_mass"/>
view_id="view_crm_lead2opportunity_partner_mass"
groups="base.group_sale_salesman"
/>
</data>
</openerp>

View File

@ -45,7 +45,9 @@
multi="True"
key2="client_action_multi" name="Merge leads/opportunities"
res_model="crm.merge.opportunity" src_model="crm.lead"
view_mode="form" target="new" view_type="form"/>
view_mode="form" target="new" view_type="form"
groups="base.group_sale_salesman"
/>
</data>
</openerp>

View File

@ -20,6 +20,7 @@
##############################################################################
import crm_partner_assign
import crm_lead
import wizard
import report

View File

@ -37,17 +37,23 @@ The most appropriate partner can be assigned.
You can also use the geolocalization without using the GPS coordinates.
""",
'author': 'OpenERP SA',
'depends': ['crm', 'account'],
'depends': ['crm', 'account', 'portal'],
'demo': ['res_partner_demo.xml'],
'data': [
'security/ir.model.access.csv',
'res_partner_view.xml',
'wizard/crm_forward_to_partner_view.xml',
'wizard/crm_channel_interested_view.xml',
'crm_lead_view.xml',
'crm_partner_assign_data.xml',
'crm_portal_view.xml',
'portal_data.xml',
'report/crm_lead_report_view.xml',
'report/crm_partner_report_view.xml',
],
'js': [
'static/src/js/next.js',
],
'test': ['test/partner_assign.yml'],
'installable': True,
'auto_install': False,

View File

@ -0,0 +1,44 @@
# -*- 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 osv
from openerp.tools.translate import _
class crm_lead(osv.osv):
_inherit = 'crm.lead'
def get_interested_action(self, cr, uid, interested, context=None):
try:
model, action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'crm_lead_channel_interested_act')
except ValueError:
raise osv.except_osv(_('Error!'), _("The CRM Channel Interested Action is missing"))
action = self.pool[model].read(cr, uid, action_id, context=context)
action_context = eval(action['context'])
action_context['interested'] = interested
action['context'] = str(action_context)
return action
def case_interested(self, cr, uid, ids, context=None):
return self.get_interested_action(cr, uid, True, context=context)
def case_disinterested(self, cr, uid, ids, context=None):
return self.get_interested_action(cr, uid, False, context=context)

View File

@ -8,27 +8,33 @@
<field name="arch" type="xml">
<data>
<xpath expr="//notebook/page[@string='Lead']" position="after">
<page string="Assignation">
<page string="Assigned Partner" groups="base.group_sale_manager">
<group name="partner_assign_group">
<group string="Partner Assignation">
<field name="partner_assigned_id" on_change="onchange_assign_id(partner_assigned_id)" domain="[('grade_id','&lt;&gt;',False)]"/>
<label for="date_assign"/>
<group string="Partner Assignation" col="3" colspan="1">
<label for="partner_latitude" string="Geolocation" />
<div class="oe_title">
<h3>
<span class="oe_grey">( </span>
<field name="partner_latitude" nolabel="1" readonly="1" class="oe_inline"/>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_latitude','&lt;=',0)]}">N </span>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_latitude','&gt;=',0)]}">S </span>
<field name="partner_longitude" class="oe_inline" readonly="1" nolabel="1"/>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_longitude','&lt;=',0)]}">E </span>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_longitude','&gt;=',0)]}">W </span>
<span class="oe_grey">) </span>
</h3>
</div>
<button string="Automatic Assignation" name="action_assign_partner" type="object" colspan="1"
class="oe_inline"/>
<field name="partner_assigned_id" class="oe_inline" on_change="onchange_assign_id(partner_assigned_id)" domain="[('grade_id','&lt;&gt;',False)]"/>
<div>
<field name="date_assign"/>
<button string="Forward"
<button string="Send Email"
attrs="{'invisible':[('partner_assigned_id','=',False)]}"
name="%(crm_lead_forward_to_partner_act)d"
icon="terp-mail-forward" type="action"
context="{'default_composition_mode': 'forward', 'default_partner_ids': [partner_assigned_id]}"/>
type="action"
context="{'default_composition_mode': 'forward','hide_forward_type': 1 , 'default_partner_ids': [partner_assigned_id]}"/>
</div>
</group>
<group string="Geo Assignation">
<field name="partner_latitude"/>
<field name="partner_longitude"/>
<span/>
<button string="Geo Assign" name="action_assign_partner" type="object" colspan="1"
icon="gtk-apply"/>
</group>
</group>
</page>
</xpath>
@ -43,7 +49,7 @@
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="partner_assigned_id"/>
</field>
</field>
</field>
</record>
@ -55,41 +61,46 @@
<filter string="Team" position="after">
<filter string="Assigned Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_assigned_id'}"/>
</filter>
<field name="partner_id" position="after">
<field name="partner_assigned_id"/>
</field>
</field>
</record>
</record>
<record id="view_crm_lead_geo_assign_form" model="ir.ui.view">
<record id="view_crm_lead_geo_assign_form" model="ir.ui.view">
<field name="name">crm.lead.lead.geo_assign.inherit</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_leads"/>
<field name="arch" type="xml">
<data>
<xpath expr="//notebook/page[@string='Extra Info']" position="after">
<page string="Assignation">
<page string="Assigned Partner" groups="base.group_sale_manager">
<group name="partner_assign_group">
<group string="Partner Assignation">
<field name="partner_assigned_id" on_change="onchange_assign_id(partner_assigned_id)" domain="[('grade_id','&lt;&gt;',False)]"/>
<label for="date_assign"/>
<group string="Partner Assignation" col="3">
<label for="partner_latitude" string="Geolocation" />
<div>
<field name="date_assign"/>
<button string="Forward"
<h3>
<span class="oe_grey">( </span>
<field name="partner_latitude" nolabel="1" readonly="1" class="oe_inline"/>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_latitude','&lt;=',0)]}">N </span>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_latitude','&gt;=',0)]}">S </span>
<field name="partner_longitude" class="oe_inline" readonly="1" nolabel="1"/>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_longitude','&lt;=',0)]}">E </span>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_longitude','&gt;=',0)]}">W </span>
<span class="oe_grey">) </span>
</h3>
</div>
<button string="Automatic Assignation" name="action_assign_partner" type="object" colspan="1"
class="oe_inline" />
<field name="partner_assigned_id" class="oe_inline" on_change="onchange_assign_id(partner_assigned_id)" domain="[('grade_id','&lt;&gt;',False)]"/>
<div>
<button string="Send Email"
attrs="{'invisible':[('partner_assigned_id','=',False)]}"
name="%(crm_lead_forward_to_partner_act)d"
icon="terp-mail-forward" type="action"
context="{'default_composition_mode': 'forward', 'default_partner_ids': [partner_assigned_id]}"/>
type="action"
context="{'default_composition_mode': 'forward','hide_forward_type': 1 , 'default_partner_ids': [partner_assigned_id]}"/>
</div>
</group>
<group string="Geo Assignation">
<field name="partner_latitude"/>
<field name="partner_longitude"/>
<span/>
<button string="Geo Assign" name="action_assign_partner" type="object" colspan="1"
icon="gtk-apply"/>
</group>
</group>
</page>
</xpath>
@ -104,7 +115,7 @@
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="partner_assigned_id"/>
</field>
</field>
</field>
</record>
@ -116,12 +127,11 @@
<filter string="Team" position="after">
<filter string="Assigned Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_assigned_id'}"/>
</filter>
<field name="partner_id" position="after">
<field name="partner_assigned_id"/>
</field>
</field>
</record>
</record>
</data>
</openerp>

View File

@ -66,10 +66,13 @@ class res_partner_grade(osv.osv):
_columns = {
'sequence': fields.integer('Sequence'),
'active': fields.boolean('Active'),
'name': fields.char('Grade Name', size=32)
'name': fields.char('Grade Name', size=32),
'partner_weight': fields.integer('Grade Weight',
help="Gives the probability to assign a lead to this partner. (0 means no assignation.)"),
}
_defaults = {
'active': lambda *args: 1
'active': lambda *args: 1,
'partner_weight':1
}
class res_partner_activation(osv.osv):
@ -88,11 +91,11 @@ class res_partner(osv.osv):
'partner_latitude': fields.float('Geo Latitude'),
'partner_longitude': fields.float('Geo Longitude'),
'date_localization': fields.date('Geo Localization Date'),
'partner_weight': fields.integer('Weight',
'partner_weight': fields.integer('Grade Weight',
help="Gives the probability to assign a lead to this partner. (0 means no assignation.)"),
'opportunity_assigned_ids': fields.one2many('crm.lead', 'partner_assigned_id',\
'Assigned Opportunities'),
'grade_id': fields.many2one('res.partner.grade', 'Partner Level'),
'grade_id': fields.many2one('res.partner.grade', 'Grade'),
'activation' : fields.many2one('res.partner.activation', 'Activation', select=1),
'date_partnership' : fields.date('Partnership Date'),
'date_review' : fields.date('Latest Partner Review'),
@ -101,6 +104,13 @@ class res_partner(osv.osv):
_defaults = {
'partner_weight': lambda *args: 0
}
def onchange_grade_id(self, cr, uid, ids, grade_id, context=None):
res = {'value' :{'partner_weight':0}}
if grade_id:
partner_grade = self.pool.get('res.partner.grade').browse(cr, uid, grade_id)
res['value']['partner_weight'] = partner_grade.partner_weight
return res
def geo_localize(self, cr, uid, ids, context=None):
# Don't pass context to browse()! We need country names in english below
for partner in self.browse(cr, uid, ids):
@ -124,7 +134,7 @@ class crm_lead(osv.osv):
_columns = {
'partner_latitude': fields.float('Geo Latitude'),
'partner_longitude': fields.float('Geo Longitude'),
'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner', help="Partner this case has been forwarded/assigned to.", select=True),
'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner',track_visibility='onchange' , help="Partner this case has been forwarded/assigned to.", select=True),
'date_assign': fields.date('Assignation Date', help="Last date this case was forwarded/assigned to a partner"),
}
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
@ -134,6 +144,7 @@ class crm_lead(osv.osv):
def onchange_assign_id(self, cr, uid, ids, partner_assigned_id, context=None):
"""This function updates the "assignation date" automatically, when manually assign a partner in the geo assign tab
"""
if not partner_assigned_id:
return {'value':{'date_assign': False}}
else:
@ -261,4 +272,3 @@ class crm_lead(osv.osv):
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,44 +1,59 @@
<?xml version="1.0" encoding='UTF-8'?>
<?xml version="1.0" ?>
<openerp>
<data>
<record id="crm_partner_assign_email_template" model="email.template">
<field name="name">Lead forward</field>
<field name="email_from"></field>
<field name="subject">Fwd: Lead: ${object.name}</field>
<field name="email_to"></field>
<field name="lang"></field>
<field name="model_id" ref="crm.model_crm_lead"/>
<record model="crm.case.stage" id="stage_portal_lead_assigned">
<field name="name">Assigned</field>
<field eval="1" name="case_default"/>
<field eval="0" name="probability"/>
<field eval="12" name="sequence"/>
<field name="type">lead</field>
</record>
<record model="crm.case.stage" id="stage_portal_lead_recycle">
<field name="name">To Recycle</field>
<field eval="1" name="case_default"/>
<field eval="0" name="probability"/>
<field eval="11" name="sequence"/>
<field name="type">lead</field>
</record>
<record id="email_template_lead_forward_mail" model="email.template">
<field name="name">Lead Mass Mail</field>
<field name="model_id" model="ir.model" search="[('name', '=', 'crm.lead.forward.to.partner')]"></field>
<field name="auto_delete" eval="True"/>
<field name="email_to">${ctx['partner_id'].email}</field>
<field name="email_from">${user.email or ''}</field>
<field name="subject">Fwd: Lead: ${ctx['partner_id'].name}</field>
<field name="body_html"><![CDATA[
Hello ${object.partner_assigned_id.name},
<p>
Here is a lead that might interest you.
</p>
<p>
Please keep me informed about your actions about it so that I can keep an
accurate follow-up of it and help you in the sale cycle.
</p>
<p>
Your account manager,<br/>
${object.user_id.name},<br/>
${object.user_id.email}
</p>
<p>Hello,</p>
<p>
${ctx["mail_body"].replace('\n','<br>') | safe}
</p>
% if ctx["history_mode"] in ('whole'):
% for message in object.message_ids:
---- Original Message (${message.date or ''}) ----<br/>
${message.body | safe}
% endfor
<p>We have been contacted by those prospects that are in your region. Thus, the following leads have been assigned to ${ctx['partner_id'].name}:</p>
<ol>
% for lead in ctx['partner_leads']:
<li><a href="${lead.lead_link}">${lead.lead_id.name or 'Subject Undefined'}</a>, ${lead.lead_id.contact_name or 'Contact Name Undefined'}, ${lead.lead_id.country_id and lead.lead_id.country_id.name or 'Country Undefined' }, ${lead.lead_id.email_from or 'Email Undefined'}, ${lead.lead_id.phone or ''} </li></br>
% endfor
</ol>
% if ctx.get('partner_in_portal'):
<p>Please connect to your <a href="${object.get_portal_url()}">Partner Portal</a> to get details. On each lead are two buttons on the top left corner that you should press after having contacted the lead: "I'm interested" & "I'm not interested".</p>
% else:
<p>
You do not have yet a portal access to our database. Please contact
${ctx['partner_id'].user_id and ctx['partner_id'].user_id.email and 'your account manager %s (%s)' % (ctx['partner_id'].user_id.name,ctx['partner_id'].user_id.email) or 'us'}.
</p>
% endif
% if ctx['history_mode'] == 'latest':
---- Original Message (${object.message_ids[0].date or ''}) ----<br/>
${object.message_ids[0].body | safe}
<p>The lead will be sent to another partner if you do not contact the lead before 20 days.</p>
<p>Thanks,</p>
<pre>
${ctx['partner_id'].user_id and ctx['partner_id'].user_id.signature or ''}
</pre>
% if not ctx['partner_id'].user_id:
PS: It looks like you do not have an account manager assigned to you, please contact us.
% endif
]]></field>
</record>
</data>
</openerp>
</openerp>

View File

@ -0,0 +1,209 @@
<openerp>
<data>
<!-- lead views-->
<record model="ir.ui.view" id="crm_lead_portal_tree">
<field name="name">partner lead</field>
<field name="model">crm.lead</field>
<field name="priority" eval="32"/>
<field name="arch" type="xml">
<tree string="Leads" colors="blue:state=='pending';grey:state in ('cancel', 'done');red:stage_id[1]=='Disinterested';black:stage_id[1]=='Interested'">
<field name="date_deadline" invisible="1"/>
<field name="create_date"/>
<field name="name" string="Subject"/>
<field name="contact_name"/>
<field name="country_id" invisible="context.get('invisible_country', True)" />
<field name="email_from"/>
<field name="phone"/>
<field name="stage_id" invisible="1"/>
<field name="type_id" invisible="1"/>
<field name="referred" invisible="1"/>
<field name="channel_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="section_id" invisible="context.get('invisible_section', True)" />
<button string="I'm interested" name="case_interested" icon="gtk-index" type="object"/>
<button string="I'm not interested" name="case_disinterested" icon="gtk-close" type="object"/>
</tree>
</field>
</record>
<record model= "ir.ui.view" id="crm_lead_portal_form">
<field name="name">crm_portal_form</field>
<field name="model">crm.lead</field>
<field name="priority" eval="32"/>
<field name="arch" type="xml">
<form string="Leads" version="7.0">
<header>
<button string="I'm interested" name="case_interested" icon="gtk-index" type="object"/>
<button string="I'm not interested" name="case_disinterested" icon="gtk-close" type="object"/>
</header>
<sheet>
<group>
<group>
<field name="partner_name" string="Partner Name" readonly="1"/>
<field name="title" widget="selection" readonly="1"/>
<field name="contact_name" readonly="1"/>
<field name="function" readonly="1"/>
<field name="email_from" readonly="1"/>
<field name="phone" readonly="1"/>
<field name="fax" readonly="1"/>
<field name="mobile" readonly="1"/>
</group>
<group>
<field name="street" readonly="1"/>
<field name="street2" readonly="1"/>
<field name="zip" readonly="1"/>
<field name="city" readonly="1"/>
<field name="country_id" readonly="1"/>
<field name="state_id" readonly="1"/>
</group>
<label for="description" colspan="2"/>
<field name="description" nolabel="1" colspan="2"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- opportunity views-->
<record model="ir.ui.view" id="crm_opportunity_portal_tree">
<field name="name">partner lead</field>
<field name="model">crm.lead</field>
<field name="priority" eval="32"/>
<field name="arch" type="xml">
<tree string="Leads" colors="blue:state=='pending';grey:state in ('cancel', 'done')">
<field name="date_deadline" invisible="1"/>
<field name="create_date" groups="base.group_no_one"/>
<field name="name" string="Opportunity"/>
<field name="partner_id" string="Customer"/>
<field name="country_id" invisible="context.get('invisible_country', True)" />
<field name="date_action"/>
<field name="title_action" />
<field name="channel_id" invisible="1"/>
<field name="type_id" invisible="1"/>
<field name="planned_revenue" sum="Expected Revenues"/>
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
<field name="section_id" invisible="context.get('invisible_section', True)" />
<field name="priority" invisible="1"/>
<field name="state" invisible="1"/>
</tree>
</field>
</record>
<record model= "ir.ui.view" id="crm_opportunity_portal_form">
<field name="name">crm_portal_form</field>
<field name="model">crm.lead</field>
<field name="priority" eval="32"/>
<field name="arch" type="xml">
<form string="Leads" version="7.0">
<sheet>
<group>
<field name="name" required="1" string="Opportunity"/>
<field name="planned_revenue" readonly="1"/>
<field name="probability" readonly="1"/>
<field name="date_deadline"/>
<newline/>
<field name="date_action" readonly="1"/>
<field name="title_action" readonly="1"/>
<field name="priority" string="Priority" readonly="1"/>
<newline/>
<field name="type" invisible="1" readonly="1"/>
</group>
<notebook colspan="4">
<page string="Opportunity">
<group col="2">
<separator string="Contact" colspan="2"/>
<group col="2">
<field name="partner_id" select="1"
on_change="onchange_partner_id(partner_id, email_from)" string="Customer"
colspan="2" readonly="1"/>
<field name="partner_name" string="Customer Name" readonly="1"/>
<field domain="[('domain', '=', 'contact')]" name="title" widget="selection" readonly="1"/>
<field name="function" readonly="1"/>
<field name="street" readonly="1"/>
<field name="street2" readonly="1"/>
</group>
<group col="2">
<field name="zip" readonly="1"/>
<field name="city" readonly="1"/>
<field name="country_id" readonly="1"/>
<field name="state_id" readonly="1"/>
<field name="phone" readonly="1"/>
</group>
</group>
<group col="2">
<group col="2">
<separator string="Communication" colspan="2"/>
<field name="email_from" readonly="1"/>
<field name="phone" readonly="1"/>
<field name="fax" readonly="1"/>
<field name="mobile" readonly="1"/>
</group>
<group col="2">
<separator string="Categorization" colspan="2"/>
<field name="type_id" widget="selection" readonly="1"/>
<field name="channel_id" widget="selection" readonly="1"/>
</group>
</group>
<separator string="Details" />
<field name="description" nolabel="1" colspan="4"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- leads -->
<record id="action_portal_leads" model="ir.actions.act_window">
<field name="name">Leads</field>
<field name="res_model">crm.lead</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="crm_lead_portal_tree"/>
<field name="domain">[('type','like','lead')]</field>
</record>
<record id="action_portal_lead_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="0"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="crm_lead_portal_tree"/>
<field name="act_window_id" ref="action_portal_leads"/>
</record>
<record id="action_portal_lead_form" model="ir.actions.act_window.view">
<field name="sequence" eval="1"/>
<field name="view_mode">form</field>
<field name="view_id" ref="crm_lead_portal_form"/>
<field name="act_window_id" ref="action_portal_leads"/>
</record>
<!-- opportunities -->
<record id="action_portal_opportunities" model="ir.actions.act_window">
<field name="name">Opportunities</field>
<field name="res_model">crm.lead</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="crm_opportunity_portal_tree"/>
<field name="domain">[('type','like','opportunity')]</field>
</record>
<record id="action_portal_opportunities_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="0"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="crm_opportunity_portal_tree"/>
<field name="act_window_id" ref="action_portal_opportunities"/>
</record>
<record id="action_portal_opportunities_form" model="ir.actions.act_window.view">
<field name="sequence" eval="1"/>
<field name="view_mode">form</field>
<field name="view_id" ref="crm_opportunity_portal_form"/>
<field name="act_window_id" ref="action_portal_opportunities"/>
</record>
<!--menus-->
<menuitem name="Leads &amp; Opportunities" id="portal_leads" parent="portal.portal_menu" sequence="25"/>
<menuitem action="action_portal_leads" sequence="0" id="openerp_portal_menu_sales_leads_current" parent="portal_leads"/>
<menuitem action="action_portal_opportunities" sequence="1" id="openerp_portal_menu_sales_leads_current1" parent="portal_leads"/>
</data>
</openerp>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Partner and address -->
<record id="res_partner_access" model="ir.model.access">
<field name="name">openerp.portal.res.partner</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="group_id" ref="portal.group_portal"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="res_partner_rule" model="ir.rule">
<field name="name">openerp.portal.res.partner</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="groups" eval="[(6,0,[ref('portal.group_portal')])]"/>
<field name="domain_force">[('id','child_of',user.commercial_partner_id.id)]</field>
</record>
<record id="res_partner_grade_access" model="ir.model.access">
<field name="name">openerp.portal.res.partner.grade</field>
<field name="model_id" ref="crm_partner_assign.model_res_partner_grade"/>
<field name="group_id" ref="portal.group_portal"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>
<!-- CRM Lead portal -->
<record id="assigned_lead_portal_rule_1" model="ir.rule">
<field name="name">openerp.portal.crm.lead</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="groups" eval="[(6,0,[ref('portal.group_portal')])]"/>
<field name="domain_force">[('partner_assigned_id','child_of',user.commercial_partner_id.id)]</field>
</record>
<record id="lead_portal_access" model="ir.model.access">
<field name="name">openerp.portal.crm.lead</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="group_id" ref="portal.group_portal"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
<field name="perm_write" eval="1"/>
<field name="perm_unlink" eval="0"/>
</record>
</data>
</openerp>

View File

@ -2,7 +2,7 @@
<openerp>
<data>
<!--Partner Activation -->
<!--Partner Activation -->
<record model="ir.ui.view" id="res_partner_activation_form">
<field name="name">openerp_custom.res.partner.activation.form</field>
@ -33,145 +33,134 @@
<field name="view_mode">tree,form</field>
</record>
<menuitem id="res_partner_activation_config_mi" parent="base.menu_config_address_book" action="res_partner_activation_act" groups="base.group_no_one"/>
<menuitem id="res_partner_activation_config_mi" parent="base.menu_config_address_book" action="res_partner_activation_act" groups="base.group_no_one" />
<!--Partner Grade -->
<!--Partner Grade -->
<record id="view_partner_grade_tree" model="ir.ui.view">
<field name="name">res.partner.grade.tree</field>
<field name="model">res.partner.grade</field>
<field name="arch" type="xml">
<tree string="Partner Grade">
<field name="sequence" invisible="1"/>
<field name="name"/>
</tree>
</field>
</record>
<record id="view_partner_grade_form" model="ir.ui.view">
<field name="name">res.partner.grade.form</field>
<field name="model">res.partner.grade</field>
<field name="arch" type="xml">
<form string="Partner Grade" version="7.0">
<group col="4">
<field name="name"/>
<field name="sequence"/>
<field name="active"/>
</group>
</form>
</field>
</record>
<record id="res_partner_grade_action" model="ir.actions.act_window">
<field name="name">Partner Grade</field>
<field name="res_model">res.partner.grade</field>
<field name="view_type">form</field>
</record>
<menuitem action="res_partner_grade_action" id="menu_res_partner_grade_action"
groups="base.group_no_one"
parent="base.menu_crm_config_lead" />
<!-- Partner form -->
<record id="view_res_partner_filter_assign_tree" model="ir.ui.view">
<field name="name">res.partner.geo.inherit.tree</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="date_review_next"/>
<field name="grade_id"/>
<field name="activation"/>
<record id="view_partner_grade_tree" model="ir.ui.view">
<field name="name">res.partner.grade.tree</field>
<field name="model">res.partner.grade</field>
<field name="arch" type="xml">
<tree string="Partner Grade">
<field name="sequence" invisible="1" />
<field name="name" />
</tree>
</field>
</field>
</record>
<record id="view_res_partner_filter_assign" model="ir.ui.view">
<field name="name">res.partner.geo.inherit.search</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="arch" type="xml">
<filter string="Salesperson" position="after">
<filter string="Activation" context="{'group_by' : 'activation'}" domain="[]" icon="terp-personal" />
</filter>
<field name="category_id" position="after">
<field name="grade_id"/>
</field>
</field>
</record>
<record id="view_crm_partner_geo_form" model="ir.ui.view">
<field name="name">res.partner.geo.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook[last()]" position="inside">
<page string="Geo Localization">
<group>
</record>
<record id="view_partner_grade_form" model="ir.ui.view">
<field name="name">res.partner.grade.form</field>
<field name="model">res.partner.grade</field>
<field name="arch" type="xml">
<form string="Partner Grade" version="7.0">
<group col="4">
<group>
<separator string="Partner Activation" colspan="2"/>
<field name="grade_id" widget="selection"/>
<field name="activation" widget="selection"/>
<field name="partner_weight"/>
<field name="name" />
<field name="partner_weight" />
<div>
<p class="oe_grey">
Define a weight to this grade. The weight will be used as default in the partner form to compute the chance for this partner to get leads. For instance, for business purpose, you can define a target revenue for each grade. To give the same chance to each partner to get leads, keep 1 in this field.
</p>
</div>
</group>
<group>
<separator string="Partner Review" colspan="2"/>
<field name="date_review"/>
<field name="date_review_next"/>
<field name="date_partnership"/>
<field name="sequence" />
<field name="active" />
</group>
</group>
<group colspan="2" col="2">
<separator string="Geo Localization" colspan="2"/>
<button
string="Geo Localize"
name="geo_localize"
colspan="2"
icon="gtk-apply"
type="object"/>
<field name="partner_latitude"/>
<field name="partner_longitude"/>
<field name="date_localization"/>
</group>
<newline/>
</form>
</field>
</record>
<record id="res_partner_grade_action" model="ir.actions.act_window">
<field name="name">Partner Grade</field>
<field name="res_model">res.partner.grade</field>
<field name="view_type">form</field>
</record>
<menuitem action="res_partner_grade_action" id="menu_res_partner_grade_action" groups="base.group_no_one" parent="base.menu_crm_config_lead" />
<field name="opportunity_assigned_ids" colspan="4" nolabel="1">
<tree string="Assigned Opportunities" colors="blue:state=='pending';gray:state=='cancel'">
<field name="create_date"/>
<field name="name"/>
<field name="type"/>
<field name="stage_id"/>
<button name="stage_previous" string="Previous"
states="open,pending" type="object" icon="gtk-go-back" />
<button name="stage_next" string="Next"
states="open,pending" type="object"
icon="gtk-go-forward" />
<field name="section_id"
invisible="context.get('invisible_section', True)"
groups="base.group_multi_salesteams"/>
<field name="user_id" />
<field name="state" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_open" string="Open"
states="draft,pending" type="object"
icon="gtk-go-forward" />
<button name="case_close" string="Close"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button string="Convert to Opportunity"
name="convert_opportunity"
states="draft,open,pending" icon="gtk-index"
type="object" attrs="{'invisible':[('type','=','opportunity')]}" />
<button name="case_escalate" string="Escalate"
states="open,draft,pending" type="object"
icon="gtk-go-up" />
</tree>
</field>
</page>
</xpath>
</field>
</record>
<!-- Partner form -->
<record id="view_res_partner_filter_assign_tree" model="ir.ui.view">
<field name="name">res.partner.geo.inherit.tree</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree" />
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="date_review_next" />
<field name="grade_id" />
<field name="activation" />
</field>
</field>
</record>
<record id="view_res_partner_filter_assign" model="ir.ui.view">
<field name="name">res.partner.geo.inherit.search</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter" />
<field name="arch" type="xml">
<filter string="Salesperson" position="after">
<filter string="Activation" context="{'group_by' : 'activation'}" domain="[]" icon="terp-personal" />
</filter>
<field name="category_id" position="after">
<field name="grade_id" />
</field>
</field>
</record>
<record id="view_crm_partner_geo_form" model="ir.ui.view">
<field name="name">res.partner.geo.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="arch" type="xml">
<xpath expr="//notebook[last()]" position="inside">
<page string="Forwarded Leads">
<group>
<group string="Partner Activation">
<label for="partner_latitude" string="Geolocalisation" />
<div class="oe_title oe_inline">
<h3 class="oe_inline">
<span class="oe_grey">( </span>
<field name="partner_latitude" nolabel="1" readonly="1" class="oe_inline" />
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_latitude','&lt;=',0)]}">N </span>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_latitude','&gt;=',0)]}">S </span>
<field name="partner_longitude" class="oe_inline" readonly="1" nolabel="1" />
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_longitude','&lt;=',0)]}">E </span>
<span class="oe_grey oe_inline" attrs="{'invisible':[('partner_longitude','&gt;=',0)]}">W </span>
<span class="oe_grey">) </span>
</h3>
<button string="Geolocalize" name="geo_localize" class="oe_inline" type="object" />
</div>
<field name="grade_id" widget="selection" on_change="onchange_grade_id(grade_id)" />
<field name="partner_weight" class="oe_inline" />
<div colspan="2">
<p class="oe_grey">
Higher is the value, higher is the probability for this partner to get more leads.
</p>
</div>
</group>
<group>
<separator string="Partner Review" colspan="2" />
<field name="date_review" />
<field name="date_review_next" />
<field name="date_partnership" />
</group>
<group>
</group>
</group>
<newline />
<separator string="Forwarded Leads" colspan="2" />
<field name="opportunity_assigned_ids" colspan="4" nolabel="1">
<tree string="Assigned Opportunities" colors="blue:state=='pending';gray:state=='cancel'">
<field name="name" />
<field name="contact_name" />
<field name="email_from" />
<field name="phone" />
<field name="stage_id" />
<field name="state" invisible="1" />
</tree>
</field>
</page>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -5,3 +5,4 @@ access_crm_partner_report,crm.partner.report.assign.all,model_crm_partner_report
access_res_partner_grade,res.partner.grade,model_res_partner_grade,base.group_sale_salesman,1,1,1,0
access_res_partner_grade_manager,res.partner.grade.manager,model_res_partner_grade,base.group_sale_manager,1,1,1,1
"access_partner_activation_manager","res.partner.activation.manager","model_res_partner_activation","base.group_partner_manager",1,1,1,1
partner_access_crm_lead,crm.lead,model_crm_lead,portal.group_portal,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
5 access_res_partner_grade res.partner.grade model_res_partner_grade base.group_sale_salesman 1 1 1 0
6 access_res_partner_grade_manager res.partner.grade.manager model_res_partner_grade base.group_sale_manager 1 1 1 1
7 access_partner_activation_manager res.partner.activation.manager model_res_partner_activation base.group_partner_manager 1 1 1 1
8 partner_access_crm_lead crm.lead model_crm_lead portal.group_portal 1 1 0 0

View File

@ -0,0 +1,13 @@
openerp.crm_partner_assign = function (instance) {
instance.crm_partner_assign = instance.crm_partner_assign || {};
instance.crm_partner_assign.next_or_list = function(parent) {
var form = parent.inner_widget.views.form.controller;
form.dataset.remove_ids([form.dataset.ids[form.dataset.index]]);
form.reload();
if (!form.dataset.ids.length){
parent.inner_widget.switch_mode('list');
}
parent.do_action({ type: 'ir.actions.act_window_close' });
};
instance.web.client_actions.add("next_or_list", "instance.crm_partner_assign.next_or_list");
}

View File

@ -20,3 +20,4 @@
##############################################################################
import crm_forward_to_partner
import crm_channel_interested

View File

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# 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
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
class crm_lead_forward_to_partner(osv.TransientModel):
""" Forward info history to partners. """
_name = 'crm.lead.channel.interested'
_columns = {
'interested': fields.boolean('Interested by this lead'),
'contacted': fields.boolean('Did you contact the lead?', help="The lead has been contacted"),
'comment': fields.text('Comment', help="What are the elements that have led to this decision?", required=True),
}
_defaults = {
'interested': lambda self, cr, uid, c: c.get('interested', True),
'contacted': False,
}
def action_confirm(self, cr, uid, ids, context=None):
wizard = self.browse(cr, uid, ids[0], context=context)
if wizard.interested and not wizard.contacted:
raise osv.except_osv(_('Error!'), _("You must contact the lead before saying that you are interested"))
lead_obj = self.pool.get('crm.lead')
lead_obj.check_access_rights(cr, uid, 'write')
if wizard.interested:
message = _('<p>I am interested by this lead.</p>')
values = {}
else:
stage = 'stage_portal_lead_recycle'
message = _('<p>I am not interested by this lead. I %scontacted the lead.</p>') % (not wizard.contacted and 'have not ' or '')
values = {'partner_assigned_id': False}
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
partner_ids = self.pool.get('res.partner').search(cr, SUPERUSER_ID, [('id', 'child_of', user.partner_id.commercial_partner_id.id)], context=context)
lead_obj.message_unsubscribe(cr, SUPERUSER_ID, context.get('active_ids'), partner_ids, context=None)
try:
stage_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', stage)[1]
except ValueError:
stage_id = False
if stage_id:
values.update({'stage_id': stage_id})
if wizard.comment:
message += '<p>%s</p>' % wizard.comment
lead_obj.message_post(cr, uid, context.get('active_ids'), body=message, context=context)
if values:
lead_obj.write(cr, SUPERUSER_ID, context.get('active_ids'), values)
if wizard.interested:
for lead in lead_obj.browse(cr, uid, context.get('active_ids'), context=context):
lead_obj.convert_opportunity(cr, SUPERUSER_ID, [lead.id], lead.partner_id and lead.partner_id.id or None, context=None)
return {
'type': 'ir.actions.client',
'tag': 'next_or_list',
'params': {
},
}

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="crm_lead_channel_interested_form">
<field name="name">crm_lead_channel_interested</field>
<field name="model">crm.lead.channel.interested</field>
<field name="arch" type="xml">
<form string="Send Mail" version="7.0">
<group col="1">
<field name="interested" nolabel="1" invisible="1"/>
<div>
<div invisible="context.get('interested', True)">
<label for="comment" string="Why aren't you interested by this lead?" />
</div>
<div invisible="not context.get('interested', True)">
<label for="comment" string="What is the next action? When? What is the expected revenue?" />
</div>
</div>
<field name="comment" nolabel="1"/>
<div class="oe_inline">
<field name="contacted" nolabel="1" string="Do you have contacted the customer?"/>
<label for="contacted" />
</div>
<p class="oe_grey" invisible="not context.get('interested', True)">
Once the lead is processed, it will be in your "Opportunities" menu.
</p>
</group>
<footer>
<button name="action_confirm" string="Confirm" type="object" class="oe_highlight"/>
or
<button string="Cancel" special="cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="crm_lead_channel_interested_act">
<field name="name">Lead Feedback</field>
<field name="res_model">crm.lead.channel.interested</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="crm_lead_channel_interested_form"/>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@ -27,107 +27,182 @@ from openerp.tools.translate import _
class crm_lead_forward_to_partner(osv.TransientModel):
""" Forward info history to partners. """
_name = 'crm.lead.forward.to.partner'
_inherit = "mail.compose.message"
def _get_composition_mode_selection(self, cr, uid, context=None):
composition_mode = super(crm_lead_forward_to_partner, self)._get_composition_mode_selection(cr, uid, context=context)
composition_mode.append(('forward', 'Forward'))
return composition_mode
_columns = {
'partner_ids': fields.many2many('res.partner',
'lead_forward_to_partner_res_partner_rel',
'wizard_id', 'partner_id', 'Additional contacts'),
'attachment_ids': fields.many2many('ir.attachment',
'lead_forward_to_partner_attachment_rel',
'wizard_id', 'attachment_id', 'Attachments'),
'history_mode': fields.selection([('info', 'Internal notes'),
('latest', 'Latest email'), ('whole', 'Whole Story')],
'Send history', required=True),
}
_defaults = {
'history_mode': 'info',
}
def _convert_to_assignation_line(self, cr, uid, lead, partner, context=None):
lead_location = []
partner_location = []
if lead.country_id:
lead_location.append(lead.country_id.name)
if lead.city:
lead_location.append(lead.city)
if partner:
if partner.country_id:
partner_location.append(partner.country_id.name)
if partner.city:
partner_location.append(partner.city)
return {'lead_id': lead.id,
'lead_location': ", ".join(lead_location),
'partner_assigned_id': partner and partner.id or False,
'partner_location': ", ".join(partner_location),
'lead_link': self.get_lead_portal_url(cr, uid, lead.id, lead.type, context=context),
}
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
# set as comment, perform overrided document-like action that calls get_record_data
old_mode = context.get('default_composition_mode', 'forward')
context['default_composition_mode'] = 'comment'
lead_obj = self.pool.get('crm.lead')
email_template_obj = self.pool.get('email.template')
try:
template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'email_template_lead_forward_mail')[1]
except ValueError:
template_id = False
res = super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
# back to forward mode
context['default_composition_mode'] = old_mode
res['composition_mode'] = context['default_composition_mode']
active_ids = context.get('active_ids')
default_composition_mode = context.get('default_composition_mode')
res['assignation_lines'] = []
if template_id:
res['body'] = email_template_obj.get_email_template(cr, uid, template_id).body_html
if active_ids:
lead_ids = lead_obj.browse(cr, uid, active_ids, context=context)
if default_composition_mode == 'mass_mail':
partner_assigned_ids = lead_obj.search_geo_partner(cr, uid, active_ids, context=context)
else:
partner_assigned_ids = dict((lead.id, lead.partner_assigned_id and lead.partner_assigned_id.id or False) for lead in lead_ids)
res['partner_id'] = lead_ids[0].partner_assigned_id.id
for lead in lead_ids:
partner_id = partner_assigned_ids.get(lead.id) or False
partner = False
if partner_id:
partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
res['assignation_lines'].append(self._convert_to_assignation_line(cr, uid, lead, partner))
return res
def get_record_data(self, cr, uid, model, res_id, context=None):
""" Override of mail.compose.message, to add default values coming
form the related lead.
"""
if context is None:
context = {}
res = super(crm_lead_forward_to_partner, self).get_record_data(cr, uid, model, res_id, context=context)
if model not in ('crm.lead') or not res_id:
return res
template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'crm_partner_assign_email_template')[1]
context['history_mode'] = context.get('history_mode','whole')
mail_body_fields = ['partner_id', 'partner_name', 'title', 'function', 'street', 'street2', 'zip', 'city', 'country_id', 'state_id', 'email_from', 'phone', 'fax', 'mobile', 'description']
lead = self.pool.get('crm.lead').browse(cr, uid, res_id, context=context)
context['mail_body'] = self.pool.get('crm.lead')._mail_body(cr, uid, lead, mail_body_fields, context=context)
template = self.generate_email_for_composer(cr, uid, template_id, res_id, context)
res['subject'] = template['subject']
res['body'] = template['body']
return res
def on_change_history_mode(self, cr, uid, ids, history_mode, model, res_id, context=None):
""" Update body when changing history_mode """
if context is None:
context = {}
if model and model == 'crm.lead' and res_id:
lead = self.pool[model].browse(cr, uid, res_id, context=context)
context['history_mode'] = history_mode
body = self.get_record_data(cr, uid, 'crm.lead', res_id, context=context)['body']
return {'value': {'body': body}}
def create(self, cr, uid, values, context=None):
""" TDE-HACK: remove 'type' from context, because when viewing an
opportunity form view, a default_type is set and propagated
to the wizard, that has a not matching type field. """
default_type = context.pop('default_type', None)
new_id = super(crm_lead_forward_to_partner, self).create(cr, uid, values, context=context)
if default_type:
context['default_type'] = default_type
return new_id
def action_forward(self, cr, uid, ids, context=None):
""" Forward the lead to a partner """
if context is None:
lead_obj = self.pool.get('crm.lead')
record = self.browse(cr, uid, ids[0], context=context)
email_template_obj = self.pool.get('email.template')
try:
template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'email_template_lead_forward_mail')[1]
except ValueError:
raise osv.except_osv(_('Email Template Error'),
_('The Forward Email Template is not in the database'))
try:
portal_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal')[1]
except ValueError:
raise osv.except_osv(_('Portal Group Error'),
_('The Portal group cannot be found'))
local_context = context.copy()
if not (record.forward_type == 'single'):
no_email = set()
for lead in record.assignation_lines:
if lead.partner_assigned_id and not lead.partner_assigned_id.email:
no_email.add(lead.partner_assigned_id.name)
if no_email:
raise osv.except_osv(_('Email Error'),
('Set an email address for the partner(s): %s' % ", ".join(no_email)))
if record.forward_type == 'single' and not record.partner_id.email:
raise osv.except_osv(_('Email Error'),
('Set an email address for the partner %s' % record.partner_id.name))
partners_leads = {}
for lead in record.assignation_lines:
partner = record.forward_type == 'single' and record.partner_id or lead.partner_assigned_id
lead_details = {
'lead_link': lead.lead_link,
'lead_id': lead.lead_id,
}
if partner:
partner_leads = partners_leads.get(partner.id)
if partner_leads:
partner_leads['leads'].append(lead_details)
else:
partners_leads[partner.id] = {'partner': partner, 'leads': [lead_details]}
stage_id = False
if record.assignation_lines and record.assignation_lines[0].lead_id.type == 'lead':
try:
stage_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'stage_portal_lead_assigned')[1]
except ValueError:
pass
for partner_id, partner_leads in partners_leads.items():
in_portal = False
for contact in (partner.child_ids or [partner]):
if contact.user_ids:
in_portal = portal_id in [g.id for g in contact.user_ids[0].groups_id]
local_context['partner_id'] = partner_leads['partner']
local_context['partner_leads'] = partner_leads['leads']
local_context['partner_in_portal'] = in_portal
email_template_obj.send_mail(cr, uid, template_id, ids[0], context=local_context)
lead_ids = [lead['lead_id'].id for lead in partner_leads['leads']]
values = {'partner_assigned_id': partner_id, 'user_id': partner_leads['partner'].user_id.id}
if stage_id:
values['stage_id'] = stage_id
lead_obj.write(cr, uid, lead_ids, values)
self.pool.get('crm.lead').message_subscribe(cr, uid, lead_ids, [partner_id], context=context)
return True
def get_lead_portal_url(self, cr, uid, lead_id, type, context=None):
action = type == 'opportunity' and 'action_portal_opportunities' or 'action_portal_leads'
try:
action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', action)[1]
except ValueError:
action_id = False
portal_link = "%s/?db=%s#id=%s&action=%s&view_type=form" % (self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'), cr.dbname, lead_id, action_id)
return portal_link
def get_portal_url(self, cr, uid, ids, context=None):
portal_link = "%s/?db=%s" % (self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'), cr.dbname)
return portal_link
_columns = {
'forward_type': fields.selection([('single', 'a single partner: manual selection of partner'), ('assigned', "several partners: automatic assignation, using GPS coordinates and partner's grades"), ], 'Forward selected leads to'),
'partner_id': fields.many2one('res.partner', 'Forward Leads To'),
'assignation_lines': fields.one2many('crm.lead.assignation', 'forward_id', 'Partner Assignation'),
'body': fields.html('Contents', help='Automatically sanitized HTML contents'),
}
_defaults = {
'forward_type': lambda self, cr, uid, c: c.get('forward_type') or 'single',
}
class crm_lead_assignation (osv.TransientModel):
_name = 'crm.lead.assignation'
_columns = {
'forward_id': fields.many2one('crm.lead.forward.to.partner', 'Partner Assignation'),
'lead_id': fields.many2one('crm.lead', 'Lead'),
'lead_location': fields.char('Lead Location', size=128),
'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner'),
'partner_location': fields.char('Partner Location', size=128),
'lead_link': fields.char('Lead Single Links', size=128),
}
def on_change_lead_id(self, cr, uid, ids, lead_id, context=None):
if not context:
context = {}
# TDE FIX in 7.0: force mass_mailing mode; this way, the message will be
# send only to partners; default subtype of mass_mailing is indeed False
# Chatter will show 'logged a note', but partner_ids (aka, the assigned partner)
# will effectively receive the message if present in the composition window
self.write(cr, uid, ids, {'composition_mode': 'mass_mail'}, context=context)
res = {'type': 'ir.actions.act_window_close'}
wizard = self.browse(cr, uid, ids[0], context=context)
if wizard.model not in ('crm.lead'):
return res
if context.get('active_ids') is None:
context['active_ids'] = [wizard.res_id]
if not lead_id:
return {'value': {'lead_location': False}}
lead = self.pool.get('crm.lead').browse(cr, uid, lead_id, context=context)
lead_location = []
if lead.country_id:
lead_location.append(lead.country_id.name)
if lead.city:
lead_location.append(lead.city)
return {'value': {'lead_location': ", ".join(lead_location)}}
lead = self.pool[wizard.model]
lead_ids = wizard.res_id and [wizard.res_id] or []
def on_change_partner_assigned_id(self, cr, uid, ids, partner_assigned_id, context=None):
if not context:
context = {}
if not partner_assigned_id:
return {'value': {'lead_location': False}}
partner = self.pool.get('res.partner').browse(cr, uid, partner_assigned_id, context=context)
partner_location = []
if partner.country_id:
partner_location.append(partner.country_id.name)
if partner.city:
partner_location.append(partner.city)
return {'value': {'partner_location': ", ".join(partner_location)}}
if wizard.composition_mode == 'mass_mail':
lead_ids = context and context.get('active_ids', []) or []
value = self.default_get(cr, uid, ['body', 'email_to', 'email_cc', 'subject', 'history_mode'], context=context)
value.pop('composition_mode')
self.pool.get('crm.lead').message_subscribe(cr, uid, lead_ids, [partner.id for partner in wizard.partner_ids], context=context)
self.write(cr, uid, ids, value, context=context)
return self.send_mail(cr, uid, ids, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,36 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="crm_lead_forward_to_partner_form">
<field name="name">crm_lead_forward_to_partner</field>
<field name="model">crm.lead.forward.to.partner</field>
<field name="arch" type="xml">
<form string="Send Mail" version="7.0">
<field name="composition_mode" colspan="2" nolabel="1" invisible="1"/>
<field name="model" colspan="2" nolabel="1" invisible="1"/>
<field name="res_id" colspan="2" nolabel="1" invisible="1"/>
<separator string="Forward to Partner" colspan="4"/>
<group col="4">
<field name="history_mode" colspan="4"
on_change="on_change_history_mode(history_mode, model, res_id)"/>
<field name="subject" colspan="4"/>
<field name="partner_ids" colspan="4" widget="many2many_tags_email"/>
<notebook colspan="4">
<page string="Body">
<field name="body"/>
</page>
<page string="Attachments">
<field name="attachment_ids"/>
</page>
</notebook>
<group>
<field name="forward_type" widget="radio" invisible="context.get('hide_forward_type',False)"/>
</group>
<group>
<group>
<field name="partner_id" attrs="{'invisible': [('forward_type', 'in', ['assigned',False])], 'required': [('forward_type', '=', 'single')]}" />
</group>
<group>
</group>
</group>
<field name="assignation_lines" attrs="{'invisible': [('forward_type', 'in', ['single',False])]}">
<tree create="false" editable="bottom">
<field name="lead_id" readonly="1" on_change="on_change_lead_id(lead_id)"/>
<field name="lead_location" readonly="1"/>
<field name="partner_assigned_id" on_change="on_change_partner_assigned_id(partner_assigned_id)"/>
<field name="partner_location" readonly="1"/>
</tree>
</field>
<notebook colspan="4" groups="base.group_no_one">
<page string="Email Template">
<field name="body" readonly="1"/>
</page>
</notebook>
<footer>
<button name="action_forward" string="Send" type="object"
class="oe_highlight"/>
<button name="action_forward" string="Send" type="object" class="oe_highlight"/>
or
<button string="Cancel" special="cancel"
class="oe_link"/>
<button string="Cancel" special="cancel" class="oe_link"/>
</footer>
</form>
</field>
@ -45,14 +47,11 @@
<field name="target">new</field>
</record>
<act_window id="action_crm_send_mass_forward"
multi="True"
key2="client_action_multi" name="Mass forward to partner"
res_model="crm.lead.forward.to.partner" src_model="crm.lead"
view_mode="form" target="new" view_type="form"
context="{'default_composition_mode' : 'mass_mail'}"
view_id="crm_lead_forward_to_partner_form"
/>
<act_window id="action_crm_send_mass_forward" multi="True"
key2="client_action_multi" name="Forward to Partner" res_model="crm.lead.forward.to.partner"
src_model="crm.lead" view_mode="form" target="new" view_type="form"
groups="base.group_sale_manager"
context="{'default_composition_mode' : 'mass_mail'}" view_id="crm_lead_forward_to_partner_form" />
</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

@ -25,11 +25,9 @@ class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'property_delivery_carrier': fields.property(
'delivery.carrier',
type='many2one',
relation='delivery.carrier',
string="Delivery Method",
view_load=True,
help="This delivery method will be used when invoicing from picking."),
}

View File

@ -172,6 +172,12 @@ class event_event(osv.osv):
continue
return res
def _get_visibility_selection(self, cr, uid, context=None):
return [('public', 'All Users'),
('employees', 'Employees Only')]
# Lambda indirection method to avoid passing a copy of the overridable method when declaring the field
_visibility_selection = lambda self, *args, **kwargs: self._get_visibility_selection(*args, **kwargs)
_columns = {
'name': fields.char('Name', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
'user_id': fields.many2one('res.users', 'Responsible User', readonly=False, states={'done': [('readonly', True)]}),
@ -209,11 +215,14 @@ class event_event(osv.osv):
'note': fields.text('Description', readonly=False, states={'done': [('readonly', True)]}),
'company_id': fields.many2one('res.company', 'Company', required=False, change_default=True, readonly=False, states={'done': [('readonly', True)]}),
'is_subscribed' : fields.function(_subscribe_fnc, type="boolean", string='Subscribed'),
'visibility': fields.selection(_visibility_selection, 'Privacy / Visibility',
select=True, required=True),
}
_defaults = {
'state': 'draft',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'event.event', context=c),
'user_id': lambda obj, cr, uid, context: uid,
'visibility': 'employees',
}
def subscribe_to_event(self, cr, uid, ids, context=None):

View File

@ -76,6 +76,7 @@
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
<field name="visibility"/>
</div>
<group>
<group>

View File

@ -25,25 +25,35 @@
<data noupdate="1">
<!-- Multi - Company Rules -->
<record model="ir.rule" id="event_event_comp_rule">
<field name="name">Event multi-company</field>
<record model="ir.rule" id="event_event_company_rule">
<field name="name">Event: multi-company</field>
<field name="model_id" ref="model_event_event"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
<field name="domain_force">['|',
('company_id', '=', False),
('company_id', 'child_of', [user.company_id.id]),
]
</field>
</record>
<record model="ir.rule" id="event_registration_comp_rule">
<field name="name">Event Registration multi-company</field>
<record model="ir.rule" id="event_registration_company_rule">
<field name="name">Event/Registration: multi-company</field>
<field name="model_id" ref="model_event_registration"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
<field name="domain_force">['|',
('company_id', '=', False),
('company_id', 'child_of', [user.company_id.id]),
]
</field>
</record>
<record model="ir.rule" id="report_event_registration_comp_rule">
<field name="name">Report Event Registration multi-company</field>
<record model="ir.rule" id="report_event_registration_company_rule">
<field name="name">Event/Report Registration: multi-company</field>
<field name="model_id" ref="model_report_event_registration"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
<field name="domain_force">['|',
('company_id', '=', False),
('company_id', 'child_of', [user.company_id.id]),
]
</field>
</record>
</data>

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

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

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,6 @@
##############################################################################
import google_base_account
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -30,10 +30,9 @@ The module adds google user in res user.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base'],
'depends': ['base_setup'],
'data': [
'google_base_account_view.xml',
'wizard/google_login_view.xml',
'google_base_account_data.xml',
],
'demo': [],
'installable': True,

View File

@ -19,14 +19,48 @@
#
##############################################################################
from openerp.osv import fields,osv
class res_users(osv.osv):
_inherit = "res.users"
_columns = {
'gmail_user': fields.char('Username', size=64,),
'gmail_password': fields.char('Password', size=64),
}
from openerp.osv import osv
from openerp import SUPERUSER_ID
from openerp.tools.translate import _
import urllib
import urllib2
import simplejson
class google_service(osv.osv):
_name = 'google.service'
def generate_refresh_token(self, cr, uid, service, authorization_code, context=None):
if authorization_code:
ir_config = self.pool['ir.config_parameter']
client_id = ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service)
client_secret = ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_secret' % service)
redirect_uri = ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri')
#Get the Refresh Token From Google And store it in ir.config_parameter
headers = {"Content-type": "application/x-www-form-urlencoded"}
data = dict(code=authorization_code, client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, grant_type="authorization_code")
data = urllib.urlencode(data)
try:
req = urllib2.Request("https://accounts.google.com/o/oauth2/token", data, headers)
content = urllib2.urlopen(req).read()
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired"), context=context)
content = simplejson.loads(content)
return content.get('refresh_token')
def _get_google_token_uri(self, cr, uid, service, context=None):
ir_config = self.pool['ir.config_parameter']
params = {
'scope': 'https://www.googleapis.com/auth/drive',
'redirect_uri': ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri'),
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
'response_type': 'code',
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
}
uri = 'https://accounts.google.com/o/oauth2/auth?%s' % urllib.urlencode(params)
return uri
# vim:expandtab:smartindent:toabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record id="config_google_redirect_uri" model="ir.config_parameter">
<field name="key">google_redirect_uri</field>
<field name="value">urn:ietf:wg:oauth:2.0:oob</field>
</record>
</data>
</openerp>

View File

@ -1,20 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="view_users_gogole_form" model="ir.ui.view">
<field name="name">res.users.google.form1</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook" position="inside">
<page string="Synchronization">
<group string="Google Account" colspan="4">
<field name="gmail_user"/>
<field name="gmail_password" password="True"/>
</group>
</page>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -1,85 +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
from openerp.tools.translate import _
try:
import gdata.contacts.service
import gdata.contacts.client
import gdata.calendar.service
except ImportError:
raise osv.except_osv(_('Google Contacts Import Error!'), _('Please install gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list'))
class google_login(osv.osv_memory):
_description ='Google Contact'
_name = 'google.login'
_columns = {
'user': fields.char('Google Username', size=64, required=True),
'password': fields.char('Google Password', size=64),
}
def google_login(self, user, password, type='', context=None):
if type == 'group':
gd_client = gdata.contacts.service.ContactsService()
elif type == 'contact':
gd_client = gdata.contacts.service.ContactsService()
elif type == 'calendar':
gd_client = gdata.calendar.service.CalendarService()
elif type =='docs_client':
gd_client = gdata.docs.client.DocsClient()
else:
gd_client = gdata.contacts.service.ContactsService()
try:
gd_client.ClientLogin(user, password, gd_client.source)
except Exception:
return False
return gd_client
def default_get(self, cr, uid, fields, context=None):
res = super(google_login, self).default_get(cr, uid, fields, context=context)
user_obj = self.pool.get('res.users').browse(cr, uid, uid)
if 'user' in fields:
res.update({'user': user_obj.gmail_user})
if 'password' in fields:
res.update({'password': user_obj.gmail_password})
return res
def login(self, cr, uid, ids, context=None):
data = self.read(cr, uid, ids)[0]
user = data['user']
password = data['password']
if self.google_login(user, password):
res = {
'gmail_user': user,
'gmail_password': password
}
self.pool.get('res.users').write(cr, uid, uid, res, context=context)
else:
raise osv.except_osv(_('Error!'), _("Authentication failed. Check the user and password."))
return self._get_next_action(cr, uid, context=context)
def _get_next_action(self, cr, uid, context=None):
return {'type': 'ir.actions.act_window_close'}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,35 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_google_login_form">
<field name="name">google.login.form</field>
<field name="model">google.login</field>
<field name="arch" type="xml">
<form string="Google login" version="7.0">
<group>
<field name="user" placeholder="e.g. user@gmail.com"/>
<field name="password" password="True"/>
</group>
<footer>
<button name="login" string="_Login" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<!--
Login Action
-->
<record model="ir.actions.act_window" id="act_google_login_form">
<field name="name">Google Login</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">google.login</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="view_id" ref="view_google_login_form" />
</record>
</data>
</openerp>

View File

@ -1 +0,0 @@
import google_docs

View File

@ -1,193 +0,0 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2012 OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import logging
from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.osv import fields, osv
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
try:
import gdata.docs.data
import gdata.docs.client
# API breakage madness in the gdata API - those guys are insane.
try:
# gdata 2.0.15+
gdata.docs.client.DocsClient.copy_resource
except AttributeError:
# gdata 2.0.14- : copy_resource() was copy()
gdata.docs.client.DocsClient.copy_resource = gdata.docs.client.DocsClient.copy
try:
# gdata 2.0.16+
gdata.docs.client.DocsClient.get_resource_by_id
except AttributeError:
try:
# gdata 2.0.15+
gdata.docs.client.DocsClient.get_resource_by_self_link
def get_resource_by_id_2_0_16(self, resource_id, **kwargs):
return self.GetResourceBySelfLink(
gdata.docs.client.RESOURCE_FEED_URI + ('/%s' % resource_id), **kwargs)
gdata.docs.client.DocsClient.get_resource_by_id = get_resource_by_id_2_0_16
except AttributeError:
# gdata 2.0.14- : alias get_resource_by_id()
gdata.docs.client.DocsClient.get_resource_by_id = gdata.docs.client.DocsClient.get_doc
try:
import atom.http_interface
_logger.info('GData lib version `%s` detected' % atom.http_interface.USER_AGENT)
except (ImportError, AttributeError):
_logger.debug('GData lib version could not be detected', exc_info=True)
except ImportError:
_logger.warning("Please install latest gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list")
class google_docs_ir_attachment(osv.osv):
_inherit = 'ir.attachment'
def _auth(self, cr, uid, context=None):
'''
Connexion with google base account
@return client object for connexion
'''
#pool the google.login in google_base_account
google_pool = self.pool.get('google.login')
#get gmail password and login. We use default_get() instead of a create() followed by a read() on the
# google.login object, because it is easier. The keys 'user' and 'password' ahve to be passed in the dict
# but the values will be replaced by the user gmail password and login.
user_config = google_pool.default_get(cr, uid, {'user' : '' , 'password' : ''}, context=context)
#login gmail account
client = google_pool.google_login(user_config['user'], user_config['password'], type='docs_client', context=context)
if not client:
raise osv.except_osv(_('Google Docs Error!'), _("Check your google configuration in Users/Users/Synchronization tab."))
_logger.info('Logged into google docs as %s', user_config['user'])
return client
def create_empty_google_doc(self, cr, uid, res_model, res_id, context=None):
'''Create a new google document, empty and with a default type (txt)
:param res_model: the object for which the google doc is created
:param res_id: the Id of the object for which the google doc is created
:return: the ID of the google document object created
'''
#login with the base account google module
client = self._auth(cr, uid, context=context)
# create the document in google docs
title = "%s %s" % (context.get("name","Untitled Document."), datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT))
local_resource = gdata.docs.data.Resource(gdata.docs.data.DOCUMENT_LABEL,title=title)
#create a new doc in Google Docs
gdocs_resource = client.post(entry=local_resource, uri='https://docs.google.com/feeds/default/private/full/')
# create an ir.attachment into the db
self.create(cr, uid, {
'res_model': res_model,
'res_id': res_id,
'type': 'url',
'name': title,
'url': gdocs_resource.get_alternate_link().href,
}, context=context)
return {'resource_id': gdocs_resource.resource_id.text,
'title': title,
'url': gdocs_resource.get_alternate_link().href}
def copy_gdoc(self, cr, uid, res_model, res_id, name_gdocs, gdoc_template_id, context=None):
'''
copy an existing document in google docs
:param res_model: the object for which the google doc is created
:param res_id: the Id of the object for which the google doc is created
:param name_gdocs: the name of the future ir.attachment that will be created. Based on the google doc template foun.
:param gdoc_template_id: the id of the google doc document to copy
:return: the ID of the google document object created
'''
#login with the base account google module
client = self._auth(cr, uid)
# fetch and copy the original document
try:
doc = client.get_resource_by_id(gdoc_template_id)
#copy the document you choose in the configuration
copy_resource = client.copy_resource(doc, name_gdocs)
except:
raise osv.except_osv(_('Google Docs Error!'), _("Your resource id is not correct. You can find the id in the google docs URL."))
# create an ir.attachment
self.create(cr, uid, {
'res_model': res_model,
'res_id': res_id,
'type': 'url',
'name': name_gdocs,
'url': copy_resource.get_alternate_link().href
}, context=context)
return copy_resource.resource_id.text
def google_doc_get(self, cr, uid, res_model, ids, context=None):
'''
Function called by the js, when no google doc are yet associated with a record, with the aim to create one. It
will first seek for a google.docs.config associated with the model `res_model` to find out what's the template
of google doc to copy (this is usefull if you want to start with a non-empty document, a type or a name
different than the default values). If no config is associated with the `res_model`, then a blank text document
with a default name is created.
:param res_model: the object for which the google doc is created
:param ids: the list of ids of the objects for which the google doc is created. This list is supposed to have
a length of 1 element only (batch processing is not supported in the code, though nothing really prevent it)
:return: the google document object created
'''
if len(ids) != 1:
raise osv.except_osv(_('Google Docs Error!'), _("Creating google docs may only be done by one at a time."))
res_id = ids[0]
pool_ir_attachment = self.pool.get('ir.attachment')
pool_gdoc_config = self.pool.get('google.docs.config')
name_gdocs = ''
model_fields_dic = self.pool[res_model].read(cr, uid, res_id, [], context=context)
# check if a model is configured with a template
google_docs_config = pool_gdoc_config.search(cr, uid, [('model_id', '=', res_model)], context=context)
if google_docs_config:
name_gdocs = pool_gdoc_config.browse(cr, uid, google_docs_config, context=context)[0].name_template
try:
name_gdocs = name_gdocs % model_fields_dic
except:
raise osv.except_osv(_('Key Error!'), _("Your Google Doc Name Pattern's key does not found in object."))
google_template_id = pool_gdoc_config.browse(cr, uid, google_docs_config[0], context=context).gdocs_resource_id
google_document = pool_ir_attachment.copy_gdoc(cr, uid, res_model, res_id, name_gdocs, google_template_id, context=context)
else:
google_document = pool_ir_attachment.create_empty_google_doc(cr, uid, res_model, res_id, context=context)
return google_document
class config(osv.osv):
_name = 'google.docs.config'
_description = "Google Docs templates config"
_columns = {
'model_id': fields.many2one('ir.model', 'Model', required=True),
'gdocs_resource_id': fields.char('Google Resource ID to Use as Template', size=64, help='''
This is the id of the template document, on google side. You can find it thanks to its URL:
*for a text document with url like `https://docs.google.com/a/openerp.com/document/d/123456789/edit`, the ID is `document:123456789`
*for a spreadsheet document with url like `https://docs.google.com/a/openerp.com/spreadsheet/ccc?key=123456789#gid=0`, the ID is `spreadsheet:123456789`
*for a presentation (slide show) document with url like `https://docs.google.com/a/openerp.com/presentation/d/123456789/edit#slide=id.p`, the ID is `presentation:123456789`
*for a drawing document with url like `https://docs.google.com/a/openerp.com/drawings/d/123456789/edit`, the ID is `drawings:123456789`
...
''', required=True),
'name_template': fields.char('Google Doc Name Pattern', size=64, help='Choose how the new google docs will be named, on google side. Eg. gdoc_%(field_name)s', required=True),
}
_defaults = {
'name_template': 'gdoc_%(name)s',
}

View File

@ -1,159 +0,0 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * google_docs
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-21 17:05+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: google_docs
#: code:addons/google_docs/google_docs.py:139
#, python-format
msgid "Key Error!"
msgstr ""
#. module: google_docs
#: view:google.docs.config:0
msgid "for a presentation (slide show) document with url like `https://docs.google.com/a/openerp.com/presentation/d/123456789/edit#slide=id.p`, the ID is `presentation:123456789`"
msgstr ""
#. module: google_docs
#: view:google.docs.config:0
msgid "for a text document with url like `https://docs.google.com/a/openerp.com/document/d/123456789/edit`, the ID is `document:123456789`"
msgstr ""
#. module: google_docs
#: field:google.docs.config,gdocs_resource_id:0
msgid "Google Resource ID to Use as Template"
msgstr ""
#. module: google_docs
#: view:google.docs.config:0
msgid "for a drawing document with url like `https://docs.google.com/a/openerp.com/drawings/d/123456789/edit`, the ID is `drawings:123456789`"
msgstr ""
#. module: google_docs
#. openerp-web
#: code:addons/google_docs/static/src/xml/gdocs.xml:6
#, python-format
msgid "Add Google Doc..."
msgstr ""
#. module: google_docs
#: view:google.docs.config:0
msgid "This is the id of the template document, on google side. You can find it thanks to its URL:"
msgstr ""
#. module: google_docs
#: model:ir.model,name:google_docs.model_google_docs_config
msgid "Google Docs templates config"
msgstr ""
#. module: google_docs
#. openerp-web
#: code:addons/google_docs/static/src/js/gdocs.js:25
#, python-format
msgid "The user google credentials are not set yet. Contact your administrator for help."
msgstr ""
#. module: google_docs
#: view:google.docs.config:0
msgid "for a spreadsheet document with url like `https://docs.google.com/a/openerp.com/spreadsheet/ccc?key=123456789#gid=0`, the ID is `spreadsheet:123456789`"
msgstr ""
#. module: google_docs
#: code:addons/google_docs/google_docs.py:101
#, python-format
msgid "Your resource id is not correct. You can find the id in the google docs URL."
msgstr ""
#. module: google_docs
#: code:addons/google_docs/google_docs.py:125
#, python-format
msgid "Creating google docs may only be done by one at a time."
msgstr ""
#. module: google_docs
#: code:addons/google_docs/google_docs.py:56
#: code:addons/google_docs/google_docs.py:101
#: code:addons/google_docs/google_docs.py:125
#, python-format
msgid "Google Docs Error!"
msgstr ""
#. module: google_docs
#: code:addons/google_docs/google_docs.py:56
#, python-format
msgid "Check your google configuration in Users/Users/Synchronization tab."
msgstr ""
#. module: google_docs
#: model:ir.ui.menu,name:google_docs.menu_gdocs_config
msgid "Google Docs configuration"
msgstr ""
#. module: google_docs
#: model:ir.actions.act_window,name:google_docs.action_google_docs_users_config
#: model:ir.ui.menu,name:google_docs.menu_gdocs_model_config
msgid "Models configuration"
msgstr ""
#. module: google_docs
#: field:google.docs.config,model_id:0
msgid "Model"
msgstr ""
#. module: google_docs
#. openerp-web
#: code:addons/google_docs/static/src/js/gdocs.js:28
#, python-format
msgid "User Google credentials are not yet set."
msgstr ""
#. module: google_docs
#: code:addons/google_docs/google_docs.py:139
#, python-format
msgid "Your Google Doc Name Pattern's key does not found in object."
msgstr ""
#. module: google_docs
#: help:google.docs.config,name_template:0
msgid "Choose how the new google docs will be named, on google side. Eg. gdoc_%(field_name)s"
msgstr ""
#. module: google_docs
#: view:google.docs.config:0
msgid "Google Docs Configuration"
msgstr ""
#. module: google_docs
#: help:google.docs.config,gdocs_resource_id:0
msgid "\n"
"This is the id of the template document, on google side. You can find it thanks to its URL: \n"
"*for a text document with url like `https://docs.google.com/a/openerp.com/document/d/123456789/edit`, the ID is `document:123456789`\n"
"*for a spreadsheet document with url like `https://docs.google.com/a/openerp.com/spreadsheet/ccc?key=123456789#gid=0`, the ID is `spreadsheet:123456789`\n"
"*for a presentation (slide show) document with url like `https://docs.google.com/a/openerp.com/presentation/d/123456789/edit#slide=id.p`, the ID is `presentation:123456789`\n"
"*for a drawing document with url like `https://docs.google.com/a/openerp.com/drawings/d/123456789/edit`, the ID is `drawings:123456789`\n"
"...\n"
""
msgstr ""
#. module: google_docs
#: model:ir.model,name:google_docs.model_ir_attachment
msgid "ir.attachment"
msgstr ""
#. module: google_docs
#: field:google.docs.config,name_template:0
msgid "Google Doc Name Pattern"
msgstr ""

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- add google docs config field in user form -->
<record model="ir.ui.view" id="view_google_docs_config_tree">
<field name="name">google_docs.config.tree</field>
<field name="model">google.docs.config</field>
<field name="arch" type="xml">
<tree string="Google Docs Configuration">
<field name="model_id"/>
<field name="name_template"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_google_docs_config_form">
<field name="name">google_docs.config.form</field>
<field name="model">google.docs.config</field>
<field name="arch" type="xml">
<form string="Google Docs Configuration" version="7.0">
<group>
<field name="model_id"/>
<label for='gdocs_resource_id'/>
<div>
<field name='gdocs_resource_id'/>
<p class="oe_grey">
This is the id of the template document, on google side. You can find it thanks to its URL:
<ul>
<li>for a text document with url like `https://docs.google.com/a/openerp.com/document/d/123456789/edit`, the ID is `document:123456789`</li>
<li>for a spreadsheet document with url like `https://docs.google.com/a/openerp.com/spreadsheet/ccc?key=123456789#gid=0`, the ID is `spreadsheet:123456789`</li>
<li>for a presentation (slide show) document with url like `https://docs.google.com/a/openerp.com/presentation/d/123456789/edit#slide=id.p`, the ID is `presentation:123456789`</li>
<li>for a drawing document with url like `https://docs.google.com/a/openerp.com/drawings/d/123456789/edit`, the ID is `drawings:123456789`</li>
</ul>
</p>
</div>
<field name='name_template'/>
</group>
</form>
</field>
</record>
<record model='ir.actions.act_window' id='action_google_docs_users_config'>
<field name='name'>Models configuration</field>
<field name='res_model'>google.docs.config</field>
<field name='type'>ir.actions.act_window</field>
<field name='view_type'>form</field>
<field name='view_id' ref='view_google_docs_config_tree'/>
</record>
<menuitem name='Google Docs configuration' id='menu_gdocs_config' parent='base.menu_administration'/>
<menuitem name='Models configuration' id='menu_gdocs_model_config' parent='menu_gdocs_config' action='action_google_docs_users_config'/>
</data>
</openerp>

View File

@ -1,3 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_google_docs,google.docs.config,model_google_docs_config,,1,0,0,0
access_google_docs,google.docs.config,model_google_docs_config,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_google_docs google.docs.config model_google_docs_config 1 0 0 0
3 access_google_docs google.docs.config model_google_docs_config base.group_system 1 1 1 1

View File

@ -1,40 +0,0 @@
openerp.google_docs = function(instance, m) {
var _t = instance.web._t,
QWeb = instance.web.qweb;
instance.web.Sidebar.include({
redraw: function() {
var self = this;
this._super.apply(this, arguments);
self.$el.find('.oe_sidebar_add_attachment').after(QWeb.render('AddGoogleDocumentItem', {widget: self}))
self.$el.find('.oe_sidebar_add_google_doc').on('click', function (e) {
self.on_google_doc();
});
},
on_google_doc: function() {
var self = this;
var view = self.getParent();
var ids = ( view.fields_view.type != "form" )? view.groups.get_selection().ids : [ view.datarecord.id ];
if( !_.isEmpty(ids) ){
view.sidebar_eval_context().done(function (context) {
var ds = new instance.web.DataSet(this, 'ir.attachment', context);
ds.call('google_doc_get', [view.dataset.model, ids, context]).done(function(r) {
if (r == 'False') {
var params = {
error: response,
message: _t("The user google credentials are not set yet. Contact your administrator for help.")
}
$(openerp.web.qweb.render("DialogWarning", params)).dialog({
title: _t("User Google credentials are not yet set."),
modal: true,
});
}
}).done(function(r){
window.open(r.url,"_blank");
view.reload();
});
});
}
}
});
};

View File

@ -0,0 +1 @@
import google_drive

View File

@ -20,22 +20,31 @@
##############################################################################
{
'name': 'Google Docs integration',
'name': 'Google Drive™ integration',
'version': '0.2',
'author': 'OpenERP SA',
'website': 'http://openerp.com',
'category': 'Tools',
'installable': True,
'auto_install': False,
'js': ['static/src/js/gdocs.js'],
'qweb': ['static/src/xml/gdocs.xml'],
'js': [
'static/lib/gapi/client.js',
'static/src/js/gdrive.js',
],
'data': [
'security/ir.model.access.csv',
'res_config_user_view.xml'
'res_config_user_view.xml',
'google_drive_data.xml'
],
'depends': ['google_base_account','document'],
'demo': [
'google_drive_demo.xml'
],
'depends': ['base_setup', 'google_base_account'],
'description': """
Module to attach a google document to any model.
================================================
Integrate google document to OpenERP record.
============================================
This module allows you to integrate google documents to any of your OpenERP record quickly and easily using OAuth 2.0 for Installed Applications,
You can configure your google Authorization Code from Settings > Configuration > General Settings by clicking on "Generate Google Authorization Code"
"""
}

View File

@ -0,0 +1,211 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2012 OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import logging
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
from openerp.tools.translate import _
import urllib
import urllib2
import json
import re
_logger = logging.getLogger(__name__)
class config(osv.osv):
_name = 'google.drive.config'
_description = "Google Drive templates config"
def get_google_drive_url(self, cr, uid, config_id, res_id, template_id, context=None):
config = self.browse(cr, SUPERUSER_ID, config_id, context=context)
model = config.model_id
filter_name = config.filter_id and config.filter_id.name or False
record = self.pool.get(model.model).read(cr, uid, res_id, [], context=context)
record.update({'model': model.name, 'filter': filter_name})
name_gdocs = config.name_template
try:
name_gdocs = name_gdocs % record
except:
raise osv.except_osv(_('Key Error!'), _("At least one key cannot be found in your Google Drive name pattern"))
attach_pool = self.pool.get("ir.attachment")
attach_ids = attach_pool.search(cr, uid, [('res_model', '=', model.model), ('name', '=', name_gdocs), ('res_id', '=', res_id)])
url = False
if attach_ids:
attachment = attach_pool.browse(cr, uid, attach_ids[0], context)
url = attachment.url
else:
url = self.copy_doc(cr, uid, res_id, template_id, name_gdocs, model.model, context)
return url
def copy_doc(self, cr, uid, res_id, template_id, name_gdocs, res_model, context=None):
ir_config = self.pool['ir.config_parameter']
google_drive_refresh_token = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_refresh_token')
if not google_drive_refresh_token:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("You haven't configured 'Authorization Code' generated from google, Please generate and configure it in %(menu:base_setup.menu_general_configuration)s."), context=context)
google_drive_client_id = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_client_id')
google_drive_client_secret = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_client_secret')
google_web_base_url = ir_config.get_param(cr, SUPERUSER_ID, 'web.base.url')
#For Getting New Access Token With help of old Refresh Token
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip, deflate"}
data = dict(client_id=google_drive_client_id,
refresh_token=google_drive_refresh_token,
client_secret=google_drive_client_secret,
grant_type="refresh_token")
data = urllib.urlencode(data)
try:
req = urllib2.Request('https://accounts.google.com/o/oauth2/token', data, headers)
content = urllib2.urlopen(req).read()
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during the token generation. Please request again an authorization code in %(menu:base_setup.menu_general_configuration)s."), context=context)
content = json.loads(content)
# Copy template in to drive with help of new access token
if 'access_token' in content:
request_url = "https://www.googleapis.com/drive/v2/files/%s?fields=parents/id&access_token=%s" % (template_id, content['access_token'])
try:
req = urllib2.Request(request_url, None, headers)
parents = urllib2.urlopen(req).read()
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("The Google Template cannot be found. Maybe it has been deleted."), context=context)
parents_dict = json.loads(parents)
record_url = "Click on link to open Record in OpenERP\n %s/?db=%s#id=%s&model=%s" % (google_web_base_url, cr.dbname, res_id, res_model)
data = {"title": name_gdocs, "description": record_url, "parents": parents_dict['parents']}
request_url = "https://www.googleapis.com/drive/v2/files/%s/copy?access_token=%s" % (template_id, content['access_token'])
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
data_json = json.dumps(data)
# resp, content = Http().request(request_url, "POST", data_json, headers)
req = urllib2.Request(request_url, data_json, headers)
content = urllib2.urlopen(req).read()
content = json.loads(content)
res = False
if 'alternateLink' in content.keys():
attach_pool = self.pool.get("ir.attachment")
attach_vals = {'res_model': res_model, 'name': name_gdocs, 'res_id': res_id, 'type': 'url', 'url': content['alternateLink']}
attach_pool.create(cr, uid, attach_vals)
res = content['alternateLink']
return res
def get_google_drive_config(self, cr, uid, res_model, res_id, context=None):
'''
Function called by the js, when no google doc are yet associated with a record, with the aim to create one. It
will first seek for a google.docs.config associated with the model `res_model` to find out what's the template
of google doc to copy (this is usefull if you want to start with a non-empty document, a type or a name
different than the default values). If no config is associated with the `res_model`, then a blank text document
with a default name is created.
:param res_model: the object for which the google doc is created
:param ids: the list of ids of the objects for which the google doc is created. This list is supposed to have
a length of 1 element only (batch processing is not supported in the code, though nothing really prevent it)
:return: the config id and config name
'''
if not res_id:
raise osv.except_osv(_('Google Drive Error!'), _("Creating google drive may only be done by one at a time."))
# check if a model is configured with a template
config_ids = self.search(cr, uid, [('model_id', '=', res_model)], context=context)
configs = []
for config in self.browse(cr, uid, config_ids, context=context):
if config.filter_id:
if (config.filter_id.user_id and config.filter_id.user_id.id != uid):
#Private
continue
domain = [('id', 'in', [res_id])] + eval(config.filter_id.domain)
local_context = context and context.copy() or {}
local_context.update(eval(config.filter_id.context))
google_doc_configs = self.pool.get(config.filter_id.model_id).search(cr, uid, domain, context=local_context)
if google_doc_configs:
configs.append({'id': config.id, 'name': config.name})
else:
configs.append({'id': config.id, 'name': config.name})
return configs
def _resource_get(self, cr, uid, ids, name, arg, context=None):
result = {}
for data in self.browse(cr, uid, ids, context):
mo = re.search("(key=|/d/)([A-Za-z0-9-_]+)", data.google_drive_template_url)
if mo:
result[data.id] = mo.group(2)
else:
raise osv.except_osv(_('Incorrect URL!'), _("Please enter a valid Google Document URL."))
return result
def _client_id_get(self, cr, uid, ids, name, arg, context=None):
result = {}
client_id = self.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'google_drive_client_id')
for config_id in ids:
result[config_id] = client_id
return result
_columns = {
'name': fields.char('Template Name', required=True, size=1024),
'model_id': fields.many2one('ir.model', 'Model', ondelete='set null', required=True),
'model': fields.related('model_id', 'model', type='char', string='Model', readonly=True),
'filter_id': fields.many2one('ir.filters', 'Filter', domain="[('model_id', '=', model)]"),
'google_drive_template_url': fields.char('Template URL', required=True, size=1024),
'google_drive_resource_id': fields.function(_resource_get, type="char", string='Resource Id'),
'google_drive_client_id': fields.function(_client_id_get, type="char", string='Google Client '),
'name_template': fields.char('Google Drive Name Pattern', size=64, help='Choose how the new google drive will be named, on google side. Eg. gdoc_%(field_name)s', required=True),
}
def onchange_model_id(self, cr, uid, ids, model_id, context=None):
res = {}
if model_id:
model = self.pool['ir.model'].browse(cr, uid, model_id, context=context)
res['value'] = {'model': model.model}
else:
res['value'] = {'filter_id': False, 'model': False}
return res
_defaults = {
'name_template': 'Document %(name)s',
}
def _check_model_id(self, cr, uid, ids, context=None):
config_id = self.browse(cr, uid, ids[0], context=context)
if config_id.filter_id and config_id.model_id.model != config_id.filter_id.model_id:
return False
return True
_constraints = [
(_check_model_id, 'Model of selected filter is not matching with model of current template.', ['model_id', 'filter_id']),
]
config()
class base_config_settings(osv.osv):
_inherit = "base.config.settings"
_columns = {
'google_drive_authorization_code': fields.char('Authorization Code', size=124),
'google_drive_uri': fields.char('URI', readonly=True, help="The URL to generate the authorization code from Google"),
}
_defaults = {
'google_drive_uri': lambda s, cr, uid, c: s.pool['google.service']._get_google_token_uri(cr, uid, 'drive', context=c),
}
def set_google_authorization_code(self, cr, uid, ids, context=None):
config = self.browse(cr, uid, ids[0], context)
refresh_token = self.pool['google.service'].generate_refresh_token(cr, uid, 'drive', config.google_drive_authorization_code, context=context)
self.pool['ir.config_parameter'].set_param(cr, uid, 'google_drive_refresh_token', refresh_token)

View File

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record id="config_google_drive_client_id" model="ir.config_parameter">
<field name="key">google_drive_client_id</field>
<field name="value">39623646228-eg3ggo3mk6o40m7rguobi3rkl9frh4tb.apps.googleusercontent.com</field>
</record>
<record id="config_google_drive_client_secret" model="ir.config_parameter">
<field name="key">google_drive_client_secret</field>
<field name="value">Ul-PtmnSWs3euWs20fdono0e</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!-- filter demo -->
<record id="filter_partner" model="ir.filters">
<field name="name">Customer</field>
<field name="model_id">res.partner</field>
<field name="domain">[['customer', '=', 1]]</field>
<field name="user_id" eval="False" />
</record>
<!-- template demo -->
<record id="template_partner" model="google.drive.config">
<field name="name">Partner Review</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="filter_id" ref="filter_partner"/>
<field name="google_drive_template_url">https://docs.google.com/spreadsheet/ccc?key=0Ah2qnrLAoZmUdGRvdVdmS1VoSDctWk1kd18taGZ4ckE#gid=0</field>
<field name="name_template">Partner Review %(name)s</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,227 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * google_drive
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 8.0alpha1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-06-27 16:03+0000\n"
"PO-Revision-Date: 2013-06-27 16:03+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: google_drive
#: model:ir.ui.menu,name:google_drive.menu_google_drive_config
msgid "Google Drive configuration"
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:48
#, python-format
msgid "Key Error!"
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "The name of the attached document can use fixed or variable data. To distinguish between documents in\n"
" Google Drive, use fixed words and fields. For instance, in the example above, if you wrote Agrolait_%(name)s_Sales\n"
" in the Google Drive name field, the document in your Google Drive and in OpenERP attachment will be named\n"
" 'Agrolait_SO0001_Sales'."
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "- If filter is not specified, link of google document will appear in \"More\" option for all users for all opportunities."
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "To create a new filter:"
msgstr ""
#. module: google_drive
#: model:ir.model,name:google_drive.model_base_config_settings
msgid "base.config.settings"
msgstr ""
#. module: google_drive
#: model:ir.actions.act_window,help:google_drive.action_google_drive_users_config
msgid "<p class=\"oe_view_nocontent_create\">\n"
" Click to add a new template.\n"
" </p>\n"
" <p>\n"
" Link your own google drive templates to any record of OpenERP. If you have really specific documents you want your collaborator fill in, e.g. Use a spreadsheet to control the quality of your product or review the delivery checklist for each order in a foreign country, ... Its very easy to manage them, link them to OpenERP and use them to collaborate with your employees.\n"
" </p>\n"
" "
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:150
#, python-format
msgid "Incorrect URL!"
msgstr ""
#. module: google_drive
#: view:base.config.settings:0
msgid "Configure your templates"
msgstr ""
#. module: google_drive
#: help:google.drive.config,name_template:0
msgid "Choose how the new google drive will be named, on google side. Eg. gdoc_%(field_name)s"
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "- Go to the OpenERP document you want to filter. For instance, go to Opportunities and search on Sales Department."
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "- In this \"Search\" view, select the option \"Save Current Filter\", enter the name (Ex: Sales Department)"
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "- If you select \"Share with all users\", link of google document in \"More\" options will appear for all users in opportunities of Sales Department."
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "- If you don't select \"Share with all users\", link of google document in \"More\" options will not appear for other users in opportunities of Sales Department."
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:48
#, python-format
msgid "At least one key cannot be found in your Google Drive name pattern"
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:150
#, python-format
msgid "Please enter a valid Google Document URL."
msgstr ""
#. module: google_drive
#: field:google.drive.config,google_drive_client_id:0
msgid "Google Client "
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "https://docs.google.com/document/d/1vOtpJK9scIQz6taD9tJRIETWbEw3fSiaQHArsJYcua4/edit"
msgstr ""
#. module: google_drive
#: field:google.drive.config,filter_id:0
msgid "Filter"
msgstr ""
#. module: google_drive
#: field:google.drive.config,name_template:0
msgid "Google Drive Name Pattern"
msgstr ""
#. module: google_drive
#: help:base.config.settings,google_drive_uri:0
msgid "The URL to generate the authorization code from Google"
msgstr ""
#. module: google_drive
#: model:ir.filters,name:google_drive.filter_partner
msgid "Customer"
msgstr ""
#. module: google_drive
#: field:google.drive.config,google_drive_resource_id:0
msgid "Resource Id"
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:91
#, python-format
msgid "The Google Template cannot be found. Maybe it has been deleted."
msgstr ""
#. module: google_drive
#: model:ir.actions.act_window,name:google_drive.action_google_drive_users_config
#: model:ir.ui.menu,name:google_drive.menu_google_drive_model_config
msgid "Google Drive Templates"
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:81
#, python-format
msgid "Something went wrong during the token generation. Please request again an authorization code in %(menu:base_setup.menu_general_configuration)s."
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:124
#, python-format
msgid "Google Drive Error!"
msgstr ""
#. module: google_drive
#: field:base.config.settings,google_drive_uri:0
msgid "URI"
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:124
#, python-format
msgid "Creating google drive may only be done by one at a time."
msgstr ""
#. module: google_drive
#: field:google.drive.config,model:0
#: field:google.drive.config,model_id:0
msgid "Model"
msgstr ""
#. module: google_drive
#: view:google.drive.config:0
msgid "Google Drive Configuration"
msgstr ""
#. module: google_drive
#: field:google.drive.config,name:0
msgid "Template Name"
msgstr ""
#. module: google_drive
#: constraint:google.drive.config:0
msgid "Model of selected filter is not matching with model of current template."
msgstr ""
#. module: google_drive
#: field:google.drive.config,google_drive_template_url:0
msgid "Template URL"
msgstr ""
#. module: google_drive
#: view:base.config.settings:0
msgid "and paste it here"
msgstr ""
#. module: google_drive
#: field:base.config.settings,google_drive_authorization_code:0
msgid "Authorization Code"
msgstr ""
#. module: google_drive
#: model:ir.model,name:google_drive.model_google_drive_config
msgid "Google Drive templates config"
msgstr ""
#. module: google_drive
#: code:addons/google_drive/google_drive.py:64
#, python-format
msgid "You haven't configured 'Authorization Code' generated from google, Please generate and configure it in %(menu:base_setup.menu_general_configuration)s."
msgstr ""

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- add google drive config field in user form -->
<record model="ir.ui.view" id="view_google_drive_config_tree">
<field name="name">google_drive.config.tree</field>
<field name="model">google.drive.config</field>
<field name="arch" type="xml">
<tree string="Google Drive Configuration">
<field name="name" />
<field name="model_id" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_google_drive_config_form">
<field name="name">google_drive.config.form</field>
<field name="model">google.drive.config</field>
<field name="arch" type="xml">
<form string="Google Drive Configuration" version="7.0">
<field name="model" invisible="1" />
<group>
<field name="name" />
<field name="model_id" on_change="onchange_model_id(model_id)" />
<label for='filter_id' />
<div>
<field name='filter_id' />
<p class="oe_grey">
<b>To create a new filter:</b><br/>
- Go to the OpenERP document you want to filter. For instance, go to Opportunities and search on Sales Department.<br/>
- In this "Search" view, select the option "Save Current Filter", enter the name (Ex: Sales Department)<br/>
- If you select "Share with all users", link of google document in "More" options will appear for all users in opportunities of Sales Department.<br/>
- If you don't select "Share with all users", link of google document in "More" options will not appear for other users in opportunities of Sales Department.<br/>
- If filter is not specified, link of google document will appear in "More" option for all users for all opportunities.
</p>
</div>
<field name='google_drive_template_url' placeholder="https://docs.google.com/document/d/1vOtpJK9scIQz6taD9tJRIETWbEw3fSiaQHArsJYcua4/edit" required="1" />
<field name='google_drive_resource_id' invisible="1" />
<label for='name_template' />
<div>
<field name='name_template' />
<p class="oe_grey">
The name of the attached document can use fixed or variable data. To distinguish between documents in
Google Drive, use fixed words and fields. For instance, in the example above, if you wrote Agrolait_%%(name)s_Sales
in the Google Drive name field, the document in your Google Drive and in OpenERP attachment will be named
'Agrolait_SO0001_Sales'.
</p>
</div>
</group>
</form>
</field>
</record>
<record model='ir.actions.act_window' id='action_google_drive_users_config'>
<field name='name'>Google Drive Templates</field>
<field name='res_model'>google.drive.config</field>
<field name='type'>ir.actions.act_window</field>
<field name='view_type'>form</field>
<field name='view_id' ref='view_google_drive_config_tree' />
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to add a new template.
</p>
<p>
Link your own google drive templates to any record of OpenERP. If you have really specific documents you want your collaborator fill in, e.g. Use a spreadsheet to control the quality of your product or review the delivery checklist for each order in a foreign country, ... Its very easy to manage them, link them to OpenERP and use them to collaborate with your employees.
</p>
</field>
</record>
<record id="inherited_google_view_general_configuration" model="ir.ui.view">
<field name="name">General Settings</field>
<field name="model">base.config.settings</field>
<field name="inherit_id" ref="base_setup.view_general_configuration" />
<field name="arch" type="xml">
<xpath expr="//div[@name='module_google_drive']" position="after">
<div attrs="{'invisible': [('module_google_drive','=',False)]}">
<div class="oe_inline">
<field name="google_drive_uri" widget="url" text="Generate Google Authorization Code" class="oe_inline oe_bold"/>
and paste it here
<field name="google_drive_authorization_code" class="oe_inline" />
</div>
<button type="action" name="%(google_drive.action_google_drive_users_config)d" string="Configure your templates" class="oe_link" />
</div>
</xpath>
</field>
</record>
<menuitem name='Google Drive configuration' id='menu_google_drive_config' parent='base.menu_administration' />
<menuitem id='menu_google_drive_model_config' parent='menu_google_drive_config' action='action_google_drive_users_config' />
</data>
</openerp>

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_google_drive_all,google.drive.config,model_google_drive_config,,1,0,0,0
access_google_drive,google.drive.config,model_google_drive_config,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_google_drive_all google.drive.config model_google_drive_config 1 0 0 0
3 access_google_drive google.drive.config model_google_drive_config base.group_system 1 1 1 1

View File

@ -0,0 +1,7 @@
var gapi=window.gapi=window.gapi||{};gapi._bs=new Date().getTime();(function(){var f=null,g=encodeURIComponent,k=window,m=decodeURIComponent,n="push",r="test",t="shift",u="replace",y="length",B="split",C="join";var D=k,E=document,aa=D.location,ba=function(){},ca=/\[native code\]/,G=function(a,b,c){return a[b]=a[b]||c},da=function(a){for(var b=0;b<this[y];b++)if(this[b]===a)return b;return-1},ea=function(a){a=a.sort();for(var b=[],c=void 0,d=0;d<a[y];d++){var e=a[d];e!=c&&b[n](e);c=e}return b},H=function(){var a;if((a=Object.create)&&ca[r](a))a=a(f);else{a={};for(var b in a)a[b]=void 0}return a},I=G(D,"gapi",{});var J;J=G(D,"___jsl",H());G(J,"I",0);G(J,"hel",10);var K=function(){var a=aa.href,b;if(J.dpo)b=J.h;else{b=J.h;var c=RegExp("([#].*&|[#])jsh=([^&#]*)","g"),d=RegExp("([?#].*&|[?#])jsh=([^&#]*)","g");if(a=a&&(c.exec(a)||d.exec(a)))try{b=m(a[2])}catch(e){}}return b},fa=function(a){var b=G(J,"PQ",[]);J.PQ=[];var c=b[y];if(0===c)a();else for(var d=0,e=function(){++d===c&&a()},h=0;h<c;h++)b[h](e)},L=function(a){return G(G(J,"H",H()),a,H())};var M=G(J,"perf",H()),N=G(M,"g",H()),ga=G(M,"i",H());G(M,"r",[]);H();H();var O=function(a,b,c){var d=M.r;"function"===typeof d?d(a,b,c):d[n]([a,b,c])},Q=function(a,b,c){b&&0<b[y]&&(b=P(b),c&&0<c[y]&&(b+="___"+P(c)),28<b[y]&&(b=b.substr(0,28)+(b[y]-28)),c=b,b=G(ga,"_p",H()),G(b,c,H())[a]=(new Date).getTime(),O(a,"_p",c))},P=function(a){return a[C]("__")[u](/\./g,"_")[u](/\-/g,"_")[u](/\,/g,"_")};var S=H(),T=[],U=function(a){throw Error("Bad hint"+(a?": "+a:""));};T[n](["jsl",function(a){for(var b in a)if(Object.prototype.hasOwnProperty.call(a,b)){var c=a[b];"object"==typeof c?J[b]=G(J,b,[]).concat(c):G(J,b,c)}if(b=a.u)a=G(J,"us",[]),a[n](b),(b=/^https:(.*)$/.exec(b))&&a[n]("http:"+b[1])}]);var ha=/^(\/[a-zA-Z0-9_\-]+)+$/,ia=/^[a-zA-Z0-9\-_\.!]+$/,ja=/^gapi\.loaded_[0-9]+$/,ka=/^[a-zA-Z0-9,._-]+$/,oa=function(a,b,c,d){var e=a[B](";"),h=S[e[t]()],l=f;h&&(l=h(e,b,c,d));if(!(b=!l))b=l,c=b.match(la),d=b.match(ma),b=!(d&&1===d[y]&&na[r](b)&&c&&1===c[y]);b&&U(a);return l},qa=function(a,b,c,d){a=pa(a);ja[r](c)||U("invalid_callback");b=V(b);d=d&&d[y]?V(d):f;var e=function(a){return g(a)[u](/%2C/g,",")};return[g(a.d)[u](/%2C/g,",")[u](/%2F/g,"/"),"/k=",e(a.version),"/m=",e(b),d?"/exm="+e(d):
"","/rt=j/sv=1/d=1/ed=1",a.a?"/am="+e(a.a):"",a.b?"/rs="+e(a.b):"","/cb=",e(c)][C]("")},pa=function(a){"/"!==a.charAt(0)&&U("relative path");for(var b=a.substring(1)[B]("/"),c=[];b[y];){a=b[t]();if(!a[y]||0==a.indexOf("."))U("empty/relative directory");else if(0<a.indexOf("=")){b.unshift(a);break}c[n](a)}a={};for(var d=0,e=b[y];d<e;++d){var h=b[d][B]("="),l=m(h[0]),p=m(h[1]);2!=h[y]||(!l||!p)||(a[l]=a[l]||p)}b="/"+c[C]("/");ha[r](b)||U("invalid_prefix");c=W(a,"k",!0);d=W(a,"am");a=W(a,"rs");return{d:b,
version:c,a:d,b:a}},V=function(a){for(var b=[],c=0,d=a[y];c<d;++c){var e=a[c][u](/\./g,"_")[u](/-/g,"_");ka[r](e)&&b[n](e)}return b[C](",")},W=function(a,b,c){a=a[b];!a&&c&&U("missing: "+b);if(a){if(ia[r](a))return a;U("invalid: "+b)}return f},na=/^https?:\/\/[a-z0-9_.-]+\.google\.com(:\d+)?\/[a-zA-Z0-9_.,!=\-\/]+$/,ma=/\/cb=/g,la=/\/\//g,ra=function(){var a=K();if(!a)throw Error("Bad hint");return a};S.m=function(a,b,c,d){(a=a[0])||U("missing_hint");return"https://apis.google.com"+qa(a,b,c,d)};var X=decodeURI("%73cript"),Y=function(a,b){for(var c=[],d=0;d<a[y];++d){var e=a[d];e&&0>da.call(b,e)&&c[n](e)}return c},sa=function(a){"loading"!=E.readyState?Z(a):E.write("<"+X+' src="'+encodeURI(a)+'"></'+X+">")},Z=function(a){var b=E.createElement(X);b.setAttribute("src",a);b.async="true";(a=E.getElementsByTagName(X)[0])?a.parentNode.insertBefore(b,a):(E.head||E.body||E.documentElement).appendChild(b)},ta=function(a,b){var c=b&&b._c;if(c)for(var d=0;d<T[y];d++){var e=T[d][0],h=T[d][1];h&&Object.prototype.hasOwnProperty.call(c,
e)&&h(c[e],a,b)}},ua=function(a,b){$(function(){var c;c=b===K()?G(I,"_",H()):H();c=G(L(b),"_",c);a(c)})},wa=function(a,b){var c=b||{};"function"==typeof b&&(c={},c.callback=b);ta(a,c);var d=a?a[B](":"):[],e=c.h||ra(),h=G(J,"ah",H());if(!h["::"]||!d[y])va(d||[],c,e);else{for(var l=[],p=f;p=d[t]();){var v=p[B]("."),v=h[p]||h[v[1]&&"ns:"+v[0]||""]||e,s=l[y]&&l[l[y]-1]||f,z=s;if(!s||s.hint!=v)z={hint:v,c:[]},l[n](z);z.c[n](p)}var A=l[y];if(1<A){var F=c.callback;F&&(c.callback=function(){0==--A&&F()})}for(;d=
l[t]();)va(d.c,c,d.hint)}},va=function(a,b,c){a=ea(a)||[];var d=b.callback,e=b.config,h=b.timeout,l=b.ontimeout,p=f,v=!1;if(h&&!l||!h&&l)throw"Timeout requires both the timeout parameter and ontimeout parameter to be set";var s=G(L(c),"r",[]).sort(),z=G(L(c),"L",[]).sort(),A=[].concat(s),F=function(a,b){if(v)return 0;D.clearTimeout(p);z[n].apply(z,q);var d=((I||{}).config||{}).update;d?d(e):e&&G(J,"cu",[])[n](e);if(b){Q("me0",a,A);try{ua(b,c)}finally{Q("me1",a,A)}}return 1};0<h&&(p=D.setTimeout(function(){v=
!0;l()},h));var q=Y(a,z);if(q[y]){var q=Y(a,s),w=G(J,"CP",[]),x=w[y];w[x]=function(a){if(!a)return 0;Q("ml1",q,A);var b=function(b){w[x]=f;F(q,a)&&fa(function(){d&&d();b()})},c=function(){var a=w[x+1];a&&a()};0<x&&w[x-1]?w[x]=function(){b(c)}:b(c)};if(q[y]){var R="loaded_"+J.I++;I[R]=function(a){w[x](a);I[R]=f};a=oa(c,q,"gapi."+R,s);s[n].apply(s,q);Q("ml0",q,A);b.sync||D.___gapisync?sa(a):Z(a)}else w[x](ba)}else F(q)&&d&&d()};var $=function(a){if(J.hee&&0<J.hel)try{return a()}catch(b){J.hel--,wa("debug_error",function(){k.___jsl.hefn(b)})}else return a()};I.load=function(a,b){return $(function(){return wa(a,b)})};N.bs0=k.gapi._bs||(new Date).getTime();O("bs0");N.bs1=(new Date).getTime();O("bs1");delete k.gapi._bs;})();
gapi.load("client",{callback:window["gapi_onload"],_c:{"jsl":{"ci":{"services":{},"deviceType":"desktop","lexps":[102,103,100,71,98,96,110,108,79,106,45,17,86,81,112,61,30],"inline":{"css":1},"report":{},"oauth-flow":{"disableOpt":true,"authUrl":"https://accounts.google.com/o/oauth2/auth","proxyUrl":"https://accounts.google.com/o/oauth2/postmessageRelay","persist":true},"isLoggedIn":true,"isPlusUser":true,"iframes":{"additnow":{"methods":["launchurl"],"url":"https://apis.google.com/additnow/additnow.html?bsv"},"shortlists":{"url":"?bsv"},"plus":{"methods":["onauth"],"url":":socialhost:/u/:session_index:/_/pages/badge?bsv"},":socialhost:":"https://plusone.google.com","recobox":{"params":{"url":""},"url":":socialhost:/:session_prefix:_/widget/render/recobox?bsv"},"plus_followers":{"params":{"url":""},"url":":socialhost:/_/im/_/widget/render/plus/followers?bsv"},"autocomplete":{"params":{"url":""},"url":":socialhost:/:session_prefix:_/widget/render/autocomplete?bsv"},"plus_share":{"params":{"url":""},"url":":socialhost:/:session_prefix:_/+1/sharebutton?plusShare\u003dtrue\u0026bsv"},"savetowallet":{"url":"https://clients5.google.com/s2w/o/savetowallet?bsv"},"panoembed":{"url":"https://ssl.gstatic.com/pano/embed/?bsv"},"signin":{"methods":["onauth"],"params":{"url":""},"url":":socialhost:/:session_prefix:_/widget/render/signin?bsv"},"appcirclepicker":{"url":":socialhost:/:session_prefix:_/widget/render/appcirclepicker?bsv"},"commentcount":{"url":":socialhost:/:session_prefix:_/widget/render/commentcount?bsv"},"hangout":{"url":"https://talkgadget.google.com/:session_prefix:talkgadget/_/widget?bsv"},"plus_circle":{"params":{"url":""},"url":":socialhost:/:session_prefix:_/widget/plus/circle?bsv"},"savetodrive":{"methods":["save"],"url":"https://drive.google.com/savetodrivebutton?usegapi\u003d1\u0026bsv"},"card":{"url":":socialhost:/:session_prefix:_/hovercard/card?bsv"},"evwidget":{"params":{"url":""},"url":":socialhost:/:session_prefix:_/events/widget?bsv"},"zoomableimage":{"url":"https://ssl.gstatic.com/microscope/embed/?bsv"},":signuphost:":"https://plus.google.com","plusone":{"preloadUrl":["https://ssl.gstatic.com/s2/oz/images/stars/po/Publisher/sprite4-a67f741843ffc4220554c34bd01bb0bb.png"],"params":{"count":"","size":"","url":""},"url":":socialhost:/:session_prefix:_/+1/fastbutton?bsv"},"comments":{"methods":["scroll","openwindow"],"params":{"location":["search","hash"]},"url":":socialhost:/:session_prefix:_/widget/render/comments?bsv"}},"debug":{"host":"https://plusone.google.com","reportExceptionRate":0.05,"rethrowException":true},"csi":{"rate":0.01},"googleapis.config":{"mobilesignupurl":"https://m.google.com/app/plus/oob?"}},"h":"m;/_/scs/apps-static/_/js/k\u003doz.gapi.en.02N985CHyyc.O/m\u003d__features__/am\u003dIQ/rt\u003dj/d\u003d1/rs\u003dAItRSTPZZ0JVQCv9Qljsu0NQlsb1ZzD2zQ","u":"https://apis.google.com/js/client.js","hee":true,"fp":"e2aa6cd0095417dbec61deca3abed1394160dab3","dpo":false},"fp":"e2aa6cd0095417dbec61deca3abed1394160dab3","annotation":["autocomplete","profile","interactivepost"],"bimodal":["signin"]}});

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,71 @@
openerp.google_drive = function (instance, m) {
var _t = instance.web._t,
QWeb = instance.web.qweb;
instance.web.Sidebar.include({
start: function () {
var self = this;
var ids
this._super.apply(this, arguments);
var view = self.getParent();
var result;
if (view.fields_view.type == "form") {
ids = []
view.on("load_record", self, function (r) {
ids = [r.id]
self.add_gdoc_items(view, r.id)
});
}
},
add_gdoc_items: function (view, res_id) {
var self = this;
var gdoc_item = _.indexOf(_.pluck(self.items.other, 'classname'), 'oe_share_gdoc');
if (gdoc_item !== -1) {
self.items.other.splice(gdoc_item, 1);
}
if (res_id) {
view.sidebar_eval_context().done(function (context) {
var ds = new instance.web.DataSet(this, 'google.drive.config', context);
ds.call('get_google_drive_config', [view.dataset.model, res_id, context]).done(function (r) {
if (!_.isEmpty(r)) {
_.each(r, function (res) {
var g_item = _.indexOf(_.pluck(self.items.other, 'label'), res.name);
if (g_item !== -1) {
self.items.other.splice(g_item, 1);
}
self.add_items('other', [{
label: res.name+ '<img style="position:absolute;right:5px;height:20px;width:20px;" title="Google Drive" src="google_drive/static/src/img/drive_icon.png"/>',
config_id: res.id,
res_id: res_id,
res_model: view.dataset.model,
callback: self.on_google_doc,
classname: 'oe_share_gdoc'
},
]);
})
}
});
});
}
},
fetch: function (model, fields, domain, ctx) {
return new instance.web.Model(model).query(fields).filter(domain).context(ctx).all()
},
on_google_doc: function (doc_item) {
var self = this;
self.config = doc_item;
var loaded = self.fetch('google.drive.config', ['google_drive_resource_id', 'google_drive_client_id'], [['id', '=', doc_item.config_id]])
.then(function (configs) {
var ds = new instance.web.DataSet(self, 'google.drive.config');
ds.call('get_google_drive_url', [doc_item.config_id, doc_item.res_id,configs[0].google_drive_resource_id]).done(function (url) {
if (url){
window.open(url, '_blank');
}
});
});
},
});
};

View File

@ -348,12 +348,10 @@
<h1><field name="name" class="oe_inline"/></h1>
</div>
<group>
<group>
<group name="job_data">
<field name="no_of_employee" groups="base.group_user"/>
<field name="no_of_recruitment" on_change="on_change_expected_employee(no_of_recruitment,no_of_employee)"/>
<field name="expected_employees" groups="base.group_user"/>
</group>
<group>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
<field name="department_id"/>
</group>

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