bzr revid: sbh@tinyerp.com-20100108054918-0km489lzbmfgahz8
This commit is contained in:
sbh (Open ERP)
2010-01-08 11:19:18 +05:30
181 changed files with 130155 additions and 647815 deletions
+4 -4
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-29 10:14+0000\n"
"Last-Translator: NightSpirit <Unknown>\n"
"PO-Revision-Date: 2010-01-05 09:22+0000\n"
"Last-Translator: pmjt <Unknown>\n"
"Language-Team: Finnish <fi@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: 2009-12-30 04:47+0000\n"
"X-Launchpad-Export-Date: 2010-01-06 04:36+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account
@@ -692,7 +692,7 @@ msgstr "Analyyttiset merkinnät"
#. module: account
#: selection:account.subscription,period_type:0
msgid "month"
msgstr ""
msgstr "kuukausi"
#. module: account
#: field:account.analytic.account,partner_id:0
+7 -7
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 09:58+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-01-06 18:48+0000\n"
"Last-Translator: eLBati <elbaddy@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: 2009-12-16 05:11+0000\n"
"X-Launchpad-Export-Date: 2010-01-07 04:49+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account
@@ -24,13 +24,13 @@ msgstr "Nome Interno"
#. module: account
#: view:account.tax.code:0
msgid "Account Tax Code"
msgstr "Codice conto tasse"
msgstr "Codice conto imposte"
#. module: account
#: model:ir.actions.act_window,name:account.action_invoice_tree9
#: model:ir.ui.menu,name:account.menu_action_invoice_tree9
msgid "Unpaid Supplier Invoices"
msgstr "Non pagate"
msgstr "Fatture fornitori non pagate"
#. module: account
#: model:ir.ui.menu,name:account.menu_finance_entries
@@ -139,7 +139,7 @@ msgstr "Annulla riconcigliazione voci"
#. module: account
#: constraint:account.period:0
msgid "Error ! The duration of the Period(s) is/are invalid. "
msgstr ""
msgstr "Errore ! La durata del/dei Periodo/i non è valida "
#. module: account
#: view:account.bank.statement.reconcile:0
@@ -1019,7 +1019,7 @@ msgstr "Posizione fiscale"
#: field:account.analytic.line,product_uom_id:0
#: field:account.move.line,product_uom_id:0
msgid "UoM"
msgstr "UM"
msgstr "Unità di Misura"
#. module: account
#: wizard_field:account.third_party_ledger.report,init,page_split:0
+34 -34
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0_rc3\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 09:38+0000\n"
"Last-Translator: Idler <idler@pcinhk.com>\n"
"PO-Revision-Date: 2010-01-08 03:52+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:16+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_analytic_analysis
@@ -26,7 +26,7 @@ msgstr "可开据加已开据的小时数"
#. module: account_analytic_analysis
#: model:ir.model,name:account_analytic_analysis.model_account_analytic_analysis_summary_user
msgid "Hours summary by user"
msgstr ""
msgstr "按用户汇总小时数"
#. module: account_analytic_analysis
#: field:account.analytic.account,last_invoice_date:0
@@ -41,18 +41,18 @@ msgstr "计算公式: 最大开据价格 - 已开据总计"
#. module: account_analytic_analysis
#: help:account.analytic.account,remaining_hours:0
msgid "Computed using the formula: Maximum Quantity - Hours Tot."
msgstr ""
msgstr "使用以下公式计算: 最大数量 - 总时间"
#. module: account_analytic_analysis
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_all
msgid "All Analytic Accounts"
msgstr ""
msgstr "所有分析科目列表"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_open
#: model:ir.ui.menu,name:account_analytic_analysis.menu_analytic_account_to_valid_open
msgid "My Current Accounts"
msgstr ""
msgstr "我的当前科目列表"
#. module: account_analytic_analysis
#: constraint:ir.ui.view:0
@@ -72,7 +72,7 @@ msgstr "理论收益"
#. module: account_analytic_analysis
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "在动作定义中输入的对象名称错误"
#. module: account_analytic_analysis
#: help:account.analytic.account,theorical_margin:0
@@ -83,7 +83,7 @@ msgstr ""
#: constraint:ir.model:0
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
msgstr "对象名称必须以“x_”起头且不能包含任何特殊字符!"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_new
@@ -105,7 +105,7 @@ msgstr ""
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_all_open
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_all_open
msgid "Current Analytic Accounts"
msgstr ""
msgstr "当前分析科目列表"
#. module: account_analytic_analysis
#: help:account.analytic.account,last_worked_date:0
@@ -127,24 +127,24 @@ msgstr ""
#. module: account_analytic_analysis
#: field:account.analytic.account,last_worked_date:0
msgid "Date of Last Cost/Work"
msgstr ""
msgstr "最后工作日期"
#. module: account_analytic_analysis
#: field:account.analytic.account,total_cost:0
msgid "Total Costs"
msgstr ""
msgstr "总成本"
#. module: account_analytic_analysis
#: help:account.analytic.account,hours_quantity:0
msgid ""
"Number of hours you spent on the analytic account (from timesheet). It "
"computes on all journal of type 'general'."
msgstr ""
msgstr "在当前核算项目上的工时数。根据类型为总账的凭证计算而来。"
#. module: account_analytic_analysis
#: field:account.analytic.account,remaining_hours:0
msgid "Remaining Hours"
msgstr ""
msgstr "剩余小时数"
#. module: account_analytic_analysis
#: help:account.analytic.account,ca_theorical:0
@@ -152,13 +152,13 @@ msgid ""
"Based on the costs you had on the project, what would have been the revenue "
"if all these costs have been invoiced at the normal sale price provided by "
"the pricelist."
msgstr ""
msgstr "根据项目的当前成本测算出来的利润,这些成本对应的收入是按价格表中的一般销售单价计算出来的。"
#. module: account_analytic_analysis
#: field:account.analytic.account,user_ids:0
#: field:account_analytic_analysis.summary.user,user:0
msgid "User"
msgstr ""
msgstr "用户"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_pending
@@ -170,18 +170,18 @@ msgstr ""
#: model:ir.actions.act_window,name:account_analytic_analysis.action_hr_tree_invoiced_my
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_hr_tree_invoiced_my
msgid "My Uninvoiced Entries"
msgstr ""
msgstr "未开发票条目"
#. module: account_analytic_analysis
#: help:account.analytic.account,real_margin:0
msgid "Computed using the formula: Invoiced Amount - Total Costs."
msgstr ""
msgstr "计算公式:发票数量 - 总成本"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed
#: model:ir.ui.menu,name:account_analytic_analysis.menu_analytic_account_managed
msgid "My Accounts"
msgstr ""
msgstr "我的科目列表"
#. module: account_analytic_analysis
#: model:ir.module.module,description:account_analytic_analysis.module_meta_information
@@ -194,27 +194,27 @@ msgstr ""
#. module: account_analytic_analysis
#: field:account.analytic.account,hours_qtt_non_invoiced:0
msgid "Uninvoiced Hours"
msgstr ""
msgstr "未开发票工时"
#. module: account_analytic_analysis
#: field:account.analytic.account,hours_quantity:0
msgid "Hours Tot"
msgstr ""
msgstr "工时总计"
#. module: account_analytic_analysis
#: model:ir.ui.menu,name:account_analytic_analysis.menu_account
msgid "Analytic Accounts"
msgstr "分析科目"
msgstr "核算项目"
#. module: account_analytic_analysis
#: model:ir.module.module,shortdesc:account_analytic_analysis.module_meta_information
msgid "report_account_analytic"
msgstr ""
msgstr "核算项目报表"
#. module: account_analytic_analysis
#: field:account.analytic.account,ca_invoiced:0
msgid "Invoiced Amount"
msgstr ""
msgstr "已开票数量"
#. module: account_analytic_analysis
#: model:ir.ui.menu,name:account_analytic_analysis.next_id_71
@@ -224,28 +224,28 @@ msgstr ""
#. module: account_analytic_analysis
#: field:account.analytic.account,last_worked_invoiced_date:0
msgid "Date of Last Invoiced Cost"
msgstr ""
msgstr "最后开票日期"
#. module: account_analytic_analysis
#: field:account.analytic.account,ca_to_invoice:0
msgid "Uninvoiced Amount"
msgstr ""
msgstr "未开票金额"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_all_pending
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_all_pending
msgid "Pending Analytic Accounts"
msgstr ""
msgstr "未决分析科目列表"
#. module: account_analytic_analysis
#: field:account.analytic.account,hours_qtt_invoiced:0
msgid "Invoiced Hours"
msgstr ""
msgstr "已开票小时数"
#. module: account_analytic_analysis
#: field:account.analytic.account,real_margin:0
msgid "Real Margin"
msgstr ""
msgstr "实际利润"
#. module: account_analytic_analysis
#: help:account.analytic.account,ca_invoiced:0
@@ -255,12 +255,12 @@ msgstr ""
#. module: account_analytic_analysis
#: model:ir.model,name:account_analytic_analysis.model_account_analytic_analysis_summary_month
msgid "Hours summary by month"
msgstr ""
msgstr "按月汇总工时数"
#. module: account_analytic_analysis
#: help:account.analytic.account,real_margin_rate:0
msgid "Computes using the formula: (Real Margin / Total Costs) * 100."
msgstr ""
msgstr "计算公式: (实际利润 / 总成本) * 100."
#. module: account_analytic_analysis
#: help:account.analytic.account,hours_qtt_non_invoiced:0
@@ -272,7 +272,7 @@ msgstr ""
#. module: account_analytic_analysis
#: view:account.analytic.account:0
msgid "Analytic accounts"
msgstr ""
msgstr "分析科目"
#. module: account_analytic_analysis
#: field:account.analytic.account,remaining_ca:0
@@ -300,7 +300,7 @@ msgstr ""
#: field:account_analytic_analysis.summary.month,unit_amount:0
#: field:account_analytic_analysis.summary.user,unit_amount:0
msgid "Total Time"
msgstr ""
msgstr "总时间"
#. module: account_analytic_analysis
#: field:account.analytic.account,month_ids:0
@@ -312,7 +312,7 @@ msgstr ""
#: field:account_analytic_analysis.summary.month,account_id:0
#: field:account_analytic_analysis.summary.user,account_id:0
msgid "Analytic Account"
msgstr ""
msgstr "分析科目"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_overpassed
+16 -16
View File
@@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-09-08 14:27+0000\n"
"Last-Translator: xu dong <gnodux@gmail.com>\n"
"PO-Revision-Date: 2010-01-08 03:31+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:25+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_budget
#: field:crossovered.budget,creating_user_id:0
msgid "Responsible User"
msgstr ""
msgstr "负责用户"
#. module: account_budget
#: rml:account.budget:0
@@ -30,23 +30,23 @@ msgstr ""
#: model:ir.actions.act_window,name:account_budget.open_budget_post_form
#: model:ir.ui.menu,name:account_budget.menu_budget_post_form
msgid "Budgetary Positions"
msgstr ""
msgstr "预算状况"
#. module: account_budget
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "在动作定义使用了无效的模型名称。"
#. module: account_budget
#: rml:account.analytic.account.budget:0
#: rml:crossovered.budget.report:0
msgid "Printed at:"
msgstr ""
msgstr "打印于:"
#. module: account_budget
#: view:crossovered.budget:0
msgid "Confirm"
msgstr ""
msgstr "确认"
#. module: account_budget
#: field:crossovered.budget,validating_user_id:0
@@ -57,12 +57,12 @@ msgstr ""
#: constraint:ir.model:0
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
msgstr "对象名称必须以“x_”起头且不能包含任何特殊字符!"
#. module: account_budget
#: selection:crossovered.budget,state:0
msgid "Confirmed"
msgstr ""
msgstr "已确认"
#. module: account_budget
#: field:account.budget.post.dotation,period_id:0
@@ -80,12 +80,12 @@ msgstr "期末"
#. module: account_budget
#: rml:account.budget:0
msgid "Printing date:"
msgstr ""
msgstr "打印时间:"
#. module: account_budget
#: selection:crossovered.budget,state:0
msgid "Draft"
msgstr ""
msgstr "草稿"
#. module: account_budget
#: rml:account.analytic.account.budget:0
@@ -109,7 +109,7 @@ msgstr ""
#: rml:account.budget:0
#: rml:crossovered.budget.report:0
msgid "Currency:"
msgstr ""
msgstr "货币:"
#. module: account_budget
#: rml:account.budget:0
@@ -203,7 +203,7 @@ msgstr ""
#: rml:account.budget:0
#: rml:crossovered.budget.report:0
msgid "Total :"
msgstr ""
msgstr "总计:"
#. module: account_budget
#: rml:account.analytic.account.budget:0
@@ -256,12 +256,12 @@ msgstr ""
#: field:crossovered.budget,date_to:0
#: field:crossovered.budget.lines,date_to:0
msgid "End Date"
msgstr ""
msgstr "结束时间"
#. module: account_budget
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
msgstr "无效的 XML 视图架构!"
#. module: account_budget
#: field:crossovered.budget.lines,theoritical_amount:0
+4 -4
View File
@@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-01-30 12:43+0000\n"
"Last-Translator: <>\n"
"PO-Revision-Date: 2010-01-08 03:45+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:17+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_date_check
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
msgstr "无效的 XML 视图架构!"
#. module: account_date_check
#: field:account.journal,allow_date:0
+5 -5
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-01-30 12:49+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-01-08 04:00+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:17+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_payment
@@ -29,7 +29,7 @@ msgstr ""
#. module: account_payment
#: view:payment.order:0
msgid "Set to draft"
msgstr ""
msgstr "设为草稿"
#. module: account_payment
#: help:payment.order,mode:0
@@ -39,7 +39,7 @@ msgstr ""
#. module: account_payment
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "在动作定义使用了无效的模型名称。"
#. module: account_payment
#: view:payment.line:0
@@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-04-10 10:16+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-01-06 14:14+0000\n"
"Last-Translator: Kalle Kniivilä <kalle@kniivila.net>\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: 2009-12-16 05:24+0000\n"
"X-Launchpad-Export-Date: 2010-01-07 04:49+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: analytic_journal_billing_rate
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
msgstr "Felaktig XML för Vyarkitektur!"
#. module: analytic_journal_billing_rate
#: field:analytic_journal_rate_grid,journal_id:0
+4 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 09:13+0000\n"
"Last-Translator: Kuvaly <kuvaly@seznam.cz>\n"
"PO-Revision-Date: 2010-01-04 19:11+0000\n"
"Last-Translator: Konki <pavel.konkol@seznam.cz>\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: 2009-12-16 05:25+0000\n"
"X-Launchpad-Export-Date: 2010-01-05 04:40+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: analytic_user_function
@@ -24,7 +24,7 @@ msgstr "Invalidní XML pro zobrazení architektury!"
#. module: analytic_user_function
#: model:ir.model,name:analytic_user_function.model_analytic_user_funct_grid
msgid "Relation table between users and products on a analytic account"
msgstr ""
msgstr "Vztah mezi uživateli a tabulkou produktů na analytickém účtu"
#. module: analytic_user_function
#: field:analytic_user_funct_grid,product_id:0
+31 -31
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-29 10:07+0000\n"
"Last-Translator: NightSpirit <Unknown>\n"
"PO-Revision-Date: 2010-01-05 09:13+0000\n"
"Last-Translator: pmjt <Unknown>\n"
"Language-Team: Finnish <fi@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: 2009-12-30 04:47+0000\n"
"X-Launchpad-Export-Date: 2010-01-06 04:36+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_contact
@@ -31,7 +31,7 @@ msgstr ""
#: constraint:ir.model:0
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
msgstr "Objektin nimen tulee alkaa x_ ja se ei saa sisältää erikoismerkkejä!"
#. module: base_contact
#: field:res.partner.job,function_id:0
@@ -46,7 +46,7 @@ msgstr ""
#: view:res.partner.address:0
#: field:res.partner.address,job_ids:0
msgid "Contacts"
msgstr ""
msgstr "Kontaktit"
#. module: base_contact
#: field:res.partner.job,sequence_partner:0
@@ -56,7 +56,7 @@ msgstr ""
#. module: base_contact
#: selection:res.partner.job,state:0
msgid "Current"
msgstr ""
msgstr "Nykyinen"
#. module: base_contact
#: field:res.partner.contact,first_name:0
@@ -71,7 +71,7 @@ msgstr ""
#. module: base_contact
#: field:res.partner.job,other:0
msgid "Other"
msgstr ""
msgstr "Muu"
#. module: base_contact
#: model:process.transition,name:base_contact.process_transition_contacttofunction0
@@ -81,7 +81,7 @@ msgstr ""
#. module: base_contact
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "Virheellinen mallin nimi toimenpiteen määrittelyssä."
#. module: base_contact
#: model:process.transition,name:base_contact.process_transition_partnertoaddress0
@@ -101,22 +101,22 @@ msgstr "Lisäpuheliinnumero:"
#. module: base_contact
#: model:process.node,name:base_contact.process_node_function0
msgid "Function"
msgstr ""
msgstr "Toiminto"
#. module: base_contact
#: field:res.partner.job,fax:0
msgid "Fax"
msgstr ""
msgstr "Faksi"
#. module: base_contact
#: field:res.partner.contact,lang_id:0
msgid "Language"
msgstr ""
msgstr "Kieli"
#. module: base_contact
#: field:res.partner.job,phone:0
msgid "Phone"
msgstr ""
msgstr "Puhelin"
#. module: base_contact
#: model:process.transition,note:base_contact.process_transition_contacttofunction0
@@ -149,7 +149,7 @@ msgstr ""
#: field:res.partner.contact,email:0
#: field:res.partner.job,email:0
msgid "E-Mail"
msgstr ""
msgstr "Sähköposti"
#. module: base_contact
#: field:res.partner.job,date_stop:0
@@ -160,7 +160,7 @@ msgstr "Loppupäivämäärä"
#: view:res.partner:0
#: field:res.partner.job,address_id:0
msgid "Address"
msgstr ""
msgstr "Osoite"
#. module: base_contact
#: model:ir.actions.act_window,name:base_contact.action_res_partner_job
@@ -189,7 +189,7 @@ msgstr "Päätyötehtävä"
#. module: base_contact
#: view:res.partner:0
msgid "Categories"
msgstr ""
msgstr "Kategoriat"
#. module: base_contact
#: field:res.partner.contact,function_id:0
@@ -204,7 +204,7 @@ msgstr "Määrittää kumppanit ja heidän osoitteet"
#. module: base_contact
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
msgstr "Virheellinen XML näkymä-arkkitehtuurille!"
#. module: base_contact
#: model:process.process,name:base_contact.process_process_basecontactprocess0
@@ -219,12 +219,12 @@ msgstr ""
#. module: base_contact
#: field:res.partner.job,extension:0
msgid "Extension"
msgstr ""
msgstr "Laajennus"
#. module: base_contact
#: field:res.partner.contact,mobile:0
msgid "Mobile"
msgstr ""
msgstr "Matkapuhelin"
#. module: base_contact
#: help:res.partner.job,extension:0
@@ -250,12 +250,12 @@ msgstr "Toiminnot ja osoitteet"
#. module: base_contact
#: field:res.partner.contact,active:0
msgid "Active"
msgstr ""
msgstr "Aktiivinen"
#. module: base_contact
#: field:res.partner.job,contact_id:0
msgid "Contact"
msgstr ""
msgstr "Kontakti"
#. module: base_contact
#: model:process.node,note:base_contact.process_node_partners0
@@ -275,23 +275,23 @@ msgstr ""
#. module: base_contact
#: model:ir.actions.act_window,name:base_contact.act_res_partner_jobs
msgid "Partner Contacts"
msgstr ""
msgstr "Kumppanien yhteishenkilöt"
#. module: base_contact
#: view:res.partner.contact:0
msgid "Partner Contact"
msgstr ""
msgstr "Kumppanin Yhteystiedot"
#. module: base_contact
#: model:process.node,name:base_contact.process_node_partners0
msgid "Partners"
msgstr ""
msgstr "Kumppanit"
#. module: base_contact
#: model:process.node,name:base_contact.process_node_addresses0
#: view:res.partner:0
msgid "Addresses"
msgstr ""
msgstr "Osoitteet"
#. module: base_contact
#: model:process.node,note:base_contact.process_node_addresses0
@@ -301,7 +301,7 @@ msgstr "Työ -ja yksityisosoitteet"
#. module: base_contact
#: field:res.partner.contact,name:0
msgid "Last Name"
msgstr ""
msgstr "Sukunimi"
#. module: base_contact
#: field:res.partner.job,state:0
@@ -312,7 +312,7 @@ msgstr ""
#: view:res.partner.contact:0
#: view:res.partner.job:0
msgid "General"
msgstr ""
msgstr "Yleiset"
#. module: base_contact
#: selection:res.partner.job,state:0
@@ -322,7 +322,7 @@ msgstr ""
#. module: base_contact
#: view:res.partner.contact:0
msgid "General Information"
msgstr ""
msgstr "Yleiset Tiedot"
#. module: base_contact
#: model:process.node,note:base_contact.process_node_function0
@@ -332,12 +332,12 @@ msgstr ""
#. module: base_contact
#: field:res.partner.job,name:0
msgid "Partner"
msgstr ""
msgstr "Kumppani"
#. module: base_contact
#: field:res.partner.job,date_start:0
msgid "Date Start"
msgstr ""
msgstr "Aloituspäivämäärä"
#. module: base_contact
#: model:process.transition,note:base_contact.process_transition_functiontoaddress0
@@ -347,9 +347,9 @@ msgstr ""
#. module: base_contact
#: field:res.partner.contact,website:0
msgid "Website"
msgstr ""
msgstr "Websivu"
#. module: base_contact
#: field:res.partner.contact,birthdate:0
msgid "Birth Date"
msgstr ""
msgstr "Syntymäaika"
+15 -13
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-16 13:06+0000\n"
"Last-Translator: Silence <Unknown>\n"
"PO-Revision-Date: 2010-01-07 11:24+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-17 04:44+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_merge
@@ -29,7 +29,7 @@ msgstr "信息"
#. module: base_module_merge
#: wizard_view:base_module_merge.module_merge,init:0
msgid "Module Merging"
msgstr ""
msgstr "模块合并"
#. module: base_module_merge
#: wizard_field:base_module_merge.module_merge,info,author:0
@@ -60,12 +60,12 @@ msgstr "版本"
#: wizard_view:base_module_merge.module_merge,info:0
#: wizard_view:base_module_merge.module_merge,save:0
msgid "Module Recording"
msgstr ""
msgstr "模块记录"
#. module: base_module_merge
#: wizard_view:base_module_merge.module_merge,save:0
msgid "Thanks in advance for your contribution."
msgstr ""
msgstr "感谢您的贡献。"
#. module: base_module_merge
#: wizard_field:base_module_merge.module_merge,info,description:0
@@ -81,12 +81,12 @@ msgstr "模块名称"
#: model:ir.actions.wizard,name:base_module_merge.wizard_base_module_merger
#: model:ir.ui.menu,name:base_module_merge.menu_wizard_base_module_merger
msgid "Merge module"
msgstr ""
msgstr "合并模块"
#. module: base_module_merge
#: wizard_field:base_module_merge.module_merge,save,module_file:0
msgid "Module .zip File"
msgstr ""
msgstr "模块 .zip 文件"
#. module: base_module_merge
#: model:ir.module.module,shortdesc:base_module_merge.module_meta_information
@@ -96,7 +96,7 @@ msgstr "模块合并"
#. module: base_module_merge
#: wizard_view:base_module_merge.module_merge,save:0
msgid "Module successfully created !"
msgstr ""
msgstr "模块已成功创建!"
#. module: base_module_merge
#: wizard_field:base_module_merge.module_merge,info,website:0
@@ -117,7 +117,7 @@ msgstr "继续"
#. module: base_module_merge
#: selection:base_module_merge.module_merge,info,data_kind:0
msgid "Normal Data"
msgstr ""
msgstr "普通数据"
#. module: base_module_merge
#: wizard_view:base_module_merge.module_merge,save:0
@@ -126,21 +126,23 @@ msgid ""
"publish it on OpenERP.com, in the 'Modules' section. You can do it through "
"the website or using features of the 'base_module_publish' module."
msgstr ""
"如果您认为您的模块其他人也会感兴趣,我们希望您能够把它发布到 OpenERP.com "
"的“Modules”部分中。您可以直接通过网站进行发布或者使用“base_module_publish”模块。"
#. module: base_module_merge
#: help:base_module_merge.module_merge,init,modules_list:0
msgid "Select Modules which you want to merge in single module"
msgstr ""
msgstr "选择您希望合并成为单个模块的模块列表"
#. module: base_module_merge
#: wizard_field:base_module_merge.module_merge,info,data_kind:0
msgid "Type of Data"
msgstr ""
msgstr "数据类型"
#. module: base_module_merge
#: wizard_view:base_module_merge.module_merge,info:0
msgid "Module Information"
msgstr ""
msgstr "模块信息"
#. module: base_module_merge
#: wizard_button:base_module_merge.module_merge,info,end:0
+34 -32
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-01 15:51+0000\n"
"PO-Revision-Date: 2010-01-07 11:38+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:09+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_record
@@ -43,7 +43,7 @@ msgstr "对象名必须以“x_”开始且不能包含任何特殊字符!"
#. module: base_module_record
#: wizard_view:base_module_record.module_record_objects,init:0
msgid "Choose objects to record"
msgstr ""
msgstr "选择要记录的对象列表"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,intro,author:0
@@ -83,7 +83,7 @@ msgstr "版本"
#. module: base_module_record
#: wizard_view:base_module_record.module_record_objects,init:0
msgid "Objects Recording"
msgstr ""
msgstr "对象记录"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,init,check_date:0
@@ -94,7 +94,7 @@ msgstr ""
#: wizard_view:base_module_record.module_record,stop:0
#: wizard_view:base_module_record.module_save,init:0
msgid "Recording Information"
msgstr ""
msgstr "记录信息"
#. module: base_module_record
#: wizard_field:base_module_record.module_save,init,info_status:0
@@ -111,24 +111,24 @@ msgstr "状态"
#: wizard_view:base_module_record.module_save,init:0
#: wizard_view:base_module_record.module_save,save:0
msgid "Module Recording"
msgstr ""
msgstr "模块记录"
#. module: base_module_record
#: model:ir.actions.wizard,name:base_module_record.wizard_base_module_record_objects
#: model:ir.ui.menu,name:base_module_record.menu_wizard_base_module_record_objects
msgid "Export Customizations As a Module"
msgstr ""
msgstr "把自定义设置作为模块导出"
#. module: base_module_record
#: wizard_view:base_module_record.module_record_objects,save:0
#: wizard_view:base_module_record.module_save,save:0
msgid "Thanks in advance for your contribution."
msgstr ""
msgstr "感谢您的贡献。"
#. module: base_module_record
#: help:base_module_record.module_record_objects,init,objects:0
msgid "List of objects to be recorded"
msgstr ""
msgstr "将被记录的对象列表"
#. module: base_module_record
#: wizard_button:base_module_record.module_record,start,start_confirm:0
@@ -139,30 +139,30 @@ msgstr "开始录制"
#. module: base_module_record
#: selection:base_module_record.module_save,init,info_status:0
msgid "Not Recording"
msgstr ""
msgstr "没有记录"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,intro,description:0
#: wizard_field:base_module_record.module_save,info,description:0
msgid "Full Description"
msgstr ""
msgstr "完整描述"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,intro,name:0
#: wizard_field:base_module_record.module_save,info,name:0
msgid "Module Name"
msgstr ""
msgstr "模块名称"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,init,objects:0
msgid "Objects"
msgstr ""
msgstr "对象"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,save,module_file:0
#: wizard_field:base_module_record.module_save,save,module_file:0
msgid "Module .zip File"
msgstr ""
msgstr "模块 .zip 文件"
#. module: base_module_record
#: wizard_view:base_module_record.module_record,start:0
@@ -173,49 +173,49 @@ msgstr ""
#: wizard_view:base_module_record.module_record_objects,save:0
#: wizard_view:base_module_record.module_save,save:0
msgid "Module successfully created !"
msgstr ""
msgstr "模块已成功创建!"
#. module: base_module_record
#: wizard_view:base_module_record.module_record,start:0
msgid "Recording Stopped"
msgstr ""
msgstr "记录已停止"
#. module: base_module_record
#: selection:base_module_record.module_record_objects,init,filter_cond:0
msgid "Created"
msgstr ""
msgstr "已创建"
#. module: base_module_record
#: wizard_view:base_module_record.module_record_objects,end:0
#: wizard_view:base_module_record.module_save,end:0
msgid "Thanks For using Module Recorder"
msgstr ""
msgstr "感谢使用模块记录器"
#. module: base_module_record
#: wizard_field:base_module_record.module_record,start,continue:0
msgid "Continue Previous Session"
msgstr ""
msgstr "继续上次会话"
#. module: base_module_record
#: wizard_field:base_module_record.module_record_objects,intro,website:0
#: wizard_field:base_module_record.module_save,info,website:0
msgid "Documentation URL"
msgstr ""
msgstr "文档地址-URL"
#. module: base_module_record
#: selection:base_module_record.module_record_objects,init,filter_cond:0
msgid "Modified"
msgstr ""
msgstr "已修改"
#. module: base_module_record
#: selection:base_module_record.module_save,init,info_status:0
msgid "Recording"
msgstr ""
msgstr "记录中"
#. module: base_module_record
#: wizard_button:base_module_record.module_record_objects,init,record:0
msgid "Record"
msgstr ""
msgstr "记录"
#. module: base_module_record
#: wizard_button:base_module_record.module_record,stop,end:0
@@ -223,25 +223,25 @@ msgstr ""
#: wizard_button:base_module_record.module_save,info,save:0
#: wizard_button:base_module_record.module_save,init,check:0
msgid "Continue"
msgstr ""
msgstr "继续"
#. module: base_module_record
#: model:ir.module.module,shortdesc:base_module_record.module_meta_information
#: model:ir.ui.menu,name:base_module_record.menu_wizard_base_mod_rec_rec
msgid "Module Recorder"
msgstr ""
msgstr "模块记录器"
#. module: base_module_record
#: selection:base_module_record.module_record_objects,intro,data_kind:0
#: selection:base_module_record.module_save,info,data_kind:0
msgid "Normal Data"
msgstr ""
msgstr "普通数据"
#. module: base_module_record
#: wizard_button:base_module_record.module_record_objects,end,end:0
#: wizard_button:base_module_record.module_save,end,end:0
msgid "OK"
msgstr ""
msgstr "确定"
#. module: base_module_record
#: wizard_view:base_module_record.module_record_objects,save:0
@@ -251,6 +251,8 @@ msgid ""
"publish it on OpenERP.com, in the 'Modules' section. You can do it through "
"the website or using features of the 'base_module_publish' module."
msgstr ""
"如果您认为您的模块其他人也会感兴趣,我们希望您能够把它发布到 OpenERP.com "
"的“Modules”部分中。您可以直接通过网站进行发布或者使用“base_module_publish”模块。"
#. module: base_module_record
#: wizard_view:base_module_record.module_record,start:0
@@ -281,13 +283,13 @@ msgstr ""
#: wizard_field:base_module_record.module_record_objects,intro,data_kind:0
#: wizard_field:base_module_record.module_save,info,data_kind:0
msgid "Type of Data"
msgstr ""
msgstr "数据类型"
#. module: base_module_record
#: wizard_view:base_module_record.module_record_objects,intro:0
#: wizard_view:base_module_record.module_save,info:0
msgid "Module Information"
msgstr ""
msgstr "模块信息"
#. module: base_module_record
#: model:ir.actions.wizard,name:base_module_record.wizard_base_module_save
@@ -308,13 +310,13 @@ msgstr ""
#: wizard_button:base_module_record.module_save,info,end:0
#: wizard_button:base_module_record.module_save,init,end:0
msgid "Cancel"
msgstr ""
msgstr "取消"
#. module: base_module_record
#: wizard_button:base_module_record.module_record_objects,save,end:0
#: wizard_button:base_module_record.module_save,save,end:0
msgid "Close"
msgstr ""
msgstr "关闭"
#. module: base_module_record
#: selection:base_module_record.module_record_objects,init,filter_cond:0
@@ -324,4 +326,4 @@ msgstr ""
#. module: base_module_record
#: model:ir.ui.menu,name:base_module_record.menu_wizard_base_module_record_stop
msgid "Stop Recording"
msgstr ""
msgstr "结束记录"
+10 -6
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2008-11-01 13:18+0000\n"
"Last-Translator: Sergei Kostigoff <sergei.kostigoff@gmail.com>\n"
"PO-Revision-Date: 2010-01-04 08:52+0000\n"
"Last-Translator: Stanislav Terentyev <stas@chinese-russian.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: 2009-12-16 05:18+0000\n"
"X-Launchpad-Export-Date: 2010-01-05 04:40+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_report_designer
@@ -24,7 +24,7 @@ msgstr "Введение"
#. module: base_report_designer
#: wizard_view:base_report_designer.modify,send_form:0
msgid "Upload your modified report"
msgstr "Выгрузить ваш измененный отчет"
msgstr "Выгрузить измененный вами отчет"
#. module: base_report_designer
#: wizard_button:base_report_designer.modify,get_form_result,send_form:0
@@ -54,7 +54,7 @@ msgstr "Ваш отчет был изменен"
#. module: base_report_designer
#: model:ir.module.module,shortdesc:base_report_designer.module_meta_information
msgid "Report designer interface module"
msgstr ""
msgstr "Модуль интерфейса для оформления отчетов"
#. module: base_report_designer
#: wizard_field:base_report_designer.modify,get_form,report_id:0
@@ -99,6 +99,10 @@ msgid ""
"to modify it. Once it is modified, re-upload it in Open ERP using this "
"wizard."
msgstr ""
"Это шаблон запрошенного вами отчета. Сохраните его как файл формата .SXW и "
"откройте с помощью программы OpenOffice. Не забудьте установить пакет Tiny "
"OpenOffice для его изменения. По завершении изменения загрузите его снова в "
"Open ERP с помощью этого мастера."
#. module: base_report_designer
#: wizard_button:base_report_designer.modify,send_form,send_form_result:0
@@ -108,7 +112,7 @@ msgstr "Обновить отчет"
#. module: base_report_designer
#: selection:base_report_designer.modify,init,operation:0
msgid "Create a new report"
msgstr ""
msgstr "Создать новый отчет"
#. module: base_report_designer
#: selection:base_report_designer.modify,init,operation:0
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -7,24 +7,24 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-15 13:43+0000\n"
"Last-Translator: Silence <Unknown>\n"
"PO-Revision-Date: 2010-01-08 04:21+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:21+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: board_account
#: view:board.board:0
msgid "Analytic accounts to close"
msgstr ""
msgstr "要关闭的分析科目"
#. module: board_account
#: view:board.board:0
msgid "Draft invoices"
msgstr ""
msgstr "发票草稿"
#. module: board_account
#: constraint:ir.ui.view:0
@@ -35,12 +35,12 @@ msgstr "无效的XML视图结构!"
#: model:ir.actions.act_window,name:board_account.open_board_account
#: model:ir.ui.menu,name:board_account.menu_board_account
msgid "Accounting Dashboard"
msgstr ""
msgstr "会计看板"
#. module: board_account
#: model:ir.actions.act_window,name:board_account.action_aged_receivable
msgid "Receivable Accounts"
msgstr ""
msgstr "应收款科目"
#. module: board_account
#: view:board.board:0
@@ -77,7 +77,7 @@ msgstr ""
#. module: board_account
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "在动作定义使用了无效的模型名称。"
#. module: board_account
#: model:ir.ui.menu,name:board_account.next_id_68
@@ -87,7 +87,7 @@ msgstr "会计及账簿"
#. module: board_account
#: view:board.board:0
msgid "Account Board"
msgstr ""
msgstr "会计看板"
#. module: board_account
#: view:board.board:0
+5 -5
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2008-11-04 11:07+0000\n"
"Last-Translator: Sergei Kostigoff <sergei.kostigoff@gmail.com>\n"
"PO-Revision-Date: 2010-01-04 08:44+0000\n"
"Last-Translator: Stanislav Terentyev <stas@chinese-russian.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: 2009-12-16 05:04+0000\n"
"X-Launchpad-Export-Date: 2010-01-05 04:40+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: board_association
@@ -24,7 +24,7 @@ msgstr "Ассоциации"
#. module: board_association
#: model:ir.module.module,shortdesc:board_association.module_meta_information
msgid "Dashboard for Associations"
msgstr ""
msgstr "Панель инструментов для ассоциаций"
#. module: board_association
#: constraint:ir.ui.view:0
@@ -55,7 +55,7 @@ msgstr "НЕоплаченные счета"
#. module: board_association
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "Недопустимое имя модели в определении действия."
#. module: board_association
#: view:board.board:0
+5 -5
View File
@@ -7,25 +7,25 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-15 13:24+0000\n"
"Last-Translator: Silence <Unknown>\n"
"PO-Revision-Date: 2010-01-07 11:12+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@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: 2009-12-16 05:06+0000\n"
"X-Launchpad-Export-Date: 2010-01-08 04:38+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: board_sale
#: model:ir.module.module,shortdesc:board_sale.module_meta_information
msgid "Dashboard for sales"
msgstr ""
msgstr "销售情况看板"
#. module: board_sale
#: model:ir.actions.act_window,name:board_sale.open_board_sales_manager
#: model:ir.ui.menu,name:board_sale.menu_board_sales_manager
msgid "Sale Dashboard"
msgstr ""
msgstr "销售看板"
#. module: board_sale
#: view:board.board:0
+3 -1
View File
@@ -37,7 +37,9 @@
"author" : "Tiny",
'category': 'Generic Modules/Others',
'website': 'http://www.openerp.com',
"init_xml" : [],
"init_xml" : [
'caldav_data.xml'
],
"demo_xml" : [],
"update_xml" : [
'security/ir.model.access.csv',
+134
View File
@@ -0,0 +1,134 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record model="res.alarm" id="alarm1">
<field name="name">1 minute before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="1" />
<field name="trigger_interval">minutes</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm2">
<field name="name">5 minutes before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="5" />
<field name="trigger_interval">minutes</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm3">
<field name="name">10 minutes before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="10" />
<field name="trigger_interval">minutes</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm4">
<field name="name">15 minutes before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="15" />
<field name="trigger_interval">minutes</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm5">
<field name="name">30 minutes before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="30" />
<field name="trigger_interval">minutes</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm6">
<field name="name">45 minutes before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="45" />
<field name="trigger_interval">minutes</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm7">
<field name="name">1 hour before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="1" />
<field name="trigger_interval">hours</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm8">
<field name="name">2 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="2" />
<field name="trigger_interval">hours</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm9">
<field name="name">3 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="3" />
<field name="trigger_interval">hours</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm10">
<field name="name">4 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="4" />
<field name="trigger_interval">hours</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm11">
<field name="name">5 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="5" />
<field name="trigger_interval">hours</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<record model="res.alarm" id="alarm12">
<field name="name">18 hours before</field>
<field name="active" eval="1" />
<field name="trigger_duration" eval="18" />
<field name="trigger_interval">hours</field>
<field name="trigger_occurs">before</field>
<field name="trigger_related">start</field>
</record>
<!-- Scheduler for Event Alarm-->
<record forcecreate="True" id="ir_cron_scheduler_alarm"
model="ir.cron">
<field name="name">Run Event Reminder</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field eval="'calendar.alarm'" name="model" />
<field eval="'do_run_scheduler'" name="function" />
<field eval="'(False,)'" name="args" />
</record>
</data>
</openerp>
+159 -50
View File
@@ -1,86 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Attendee invite wizard-->
<record id="view_calendar_invite_attendee_wizard" model="ir.ui.view">
<field name="name">Invite Attendees</field>
<field name="model">caldav.invite.attendee</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Invite Attendees">
<separator string="Select User" colspan="4"/>
<newline/>
<field name="user_id" select="1" on_change="onchange_user_id(user_id)"/>
<field name="email" />
<field name="role" select="1" />
<field name="rsvp" />
<separator string="" colspan="6" />
<label string="" colspan="2"/>
<button icon='gtk-cancel' special="cancel" string="Cancel"/>
<button name="do_invite" string="Invite" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
<record id="action_view_calendar_invite_attendee_wizard" model="ir.actions.act_window">
<field name="name">Invite Attendees</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">caldav.invite.attendee</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="caldav_attendee_form_view" model="ir.ui.view">
<field name="name">crm.case.caldav.attendee</field>
<field name="model">crm.caldav.attendee</field>
<field name="name">calendar.attendee.form</field>
<field name="model">calendar.attendee</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Atendee details">
<field name="user_id" on_change="onchange_user_id(user_id)" />
<field name="email" select="1"/>
<newline />
<field name="role" select="1" />
<field name="cutype" select="1" />
<newline />
<field name="rsvp" />
<notebook colspan="4">
<page string="Basic details">
<field name="cn" select="1" colspan="2" />
<field name="partstat" />
<field name="cutype" select="1" />
<field name="role" select="1" />
<field name="rsvp" />
</page>
<page string="Other">
<field name="delegated_to" select="1" />
<field name="delegated_from" select="1" />
<field name="sent_by" />
<field name="dir" />
<page string="Details">
<field name="sent_by_uid" />
<field name="dir" widget='url' />
<field name="language" />
</page>
<page string="Delegation Info">
<separator string="Delegated to" colspan="4" />
<field name="del_to_user_ids" nolabel="1" colspan="4" />
<separator string="Delegated from" colspan="4" />
<field name="del_from_user_ids" nolabel="1" colspan="4" />
</page>
</notebook>
<group col="6" colspan="4">
<field name="state" select="2" />
<button name="do_tentative"
string="Uncertain"
states="needs-action" type="object"
icon="terp-crm" />
<button name="do_accept"
string="Accept"
states="needs-action" type="object"
icon="gtk-apply" />
<button name="do_decline"
string="Decline"
states="needs-action" type="object"
icon="gtk-cancel" />
<button
name="%(caldav.action_view_calendar_invite_attendee_wizard)d"
states="needs-action" string="Delegate"
type="action" icon="gtk-sort-descending"
context="{'model' : 'calendar.attendee'}" />
</group>
</form>
</field>
</record>
<record id="caldav_attendee_tree_view" model="ir.ui.view">
<field name="name">crm.case.caldav.attendee</field>
<field name="model">crm.caldav.attendee</field>
<field name="name">calendar.attendee.tree</field>
<field name="model">calendar.attendee</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Atendee details">
<field name="cn" select="1" />
<field name="partstat" />
<field name="state" />
<field name="cutype" select="1" />
<field name="role" select="1" />
</tree>
</field>
</record>
<record id="action_view_attendee_form" model="ir.actions.act_window">
<field name="name">My Invitations</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">calendar.attendee</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="caldav_attendee_tree_view" />
<field name="domain">[('user_id', '=', uid)]</field>
<field name="context">{'default_sent_by_uid': uid}</field>
</record>
<record id="action_invitation_tree_view1" model="ir.actions.act_window.view">
<field eval="1" name="sequence" />
<field name="view_mode">tree</field>
<field name="view_id" ref="caldav_attendee_tree_view" />
<field name="act_window_id" ref="action_view_attendee_form" />
</record>
<record id="action_invitation_form_view1" model="ir.actions.act_window.view">
<field eval="2" name="sequence" />
<field name="view_mode">form</field>
<field name="view_id" ref="caldav_attendee_form_view" />
<field name="act_window_id" ref="action_view_attendee_form" />
</record>
<record id="caldav_attendee_tree_model" model="ir.ui.view">
<field name="name">calendar.attendee.tree1</field>
<field name="model">calendar.attendee</field>
<field name="type">tree</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<tree string="Atendee details">
<field name="user_id" select="1" />
<field name="email" />
<field name="state" />
<field name="cutype" select="1" />
<field name="role" select="1" />
</tree>
</field>
</record>
<record id="caldav_alarm_form_view" model="ir.ui.view">
<field name="name">crm.case.caldav.alarm.form</field>
<field name="model">crm.caldav.alarm</field>
<record id="caldav_attendee_form_model" model="ir.ui.view">
<field name="name">calendar.attendee.form1</field>
<field name="model">calendar.attendee</field>
<field name="type">form</field>
<field name="priority">10</field>
<field name="arch" type="xml">
<form string="Atendee details">
<field name="user_id" select="1"/>
<field name="state" />
<field name="cutype" select="1" />
<field name="role" select="1" />
<newline/>
<field name="rsvp" select="1" />
</form>
</field>
</record>
<record id="res_alarm_form_view" model="ir.ui.view">
<field name="name">res.alarm.form</field>
<field name="model">res.alarm</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Alarm details">
<field name="action"/>
<field name="name" select="1" attrs="{'required' : [('action','in',('EMAIL', 'DISPLAY'))]}"/>
<separator string="Description" colspan="4"/>
<field name="description" colspan="4" nolabel="1" attrs="{'required' : [('action','in',('EMAIL'))]}"/>
<form string="Reminder details">
<field name="name" select="1"/>
<field name="active"/>
<group string="Reminder details" col="4" colspan="4">
<field name="trigger_duration" nolabel="1" select="1"/>
<field name="trigger_interval" nolabel="1" select="1"/>
<field name="trigger_occurs" nolabel="1" select="1"/>
<field name="trigger_related" nolabel="1" select="1"/>
</group>
<field name="duration"/>
<field name="repeat"/>
<field name="attach" colspan="4" attrs="{'required' : [('action','in',('AUDIO', 'PROCEDURE'))]}"/>
</group>
<field name="duration"/>
<field name="repeat"/>
</form>
</field>
</record>
<record id="caldav_alarm_tree_view" model="ir.ui.view">
<field name="name">crm.case.caldav.alarm.tree</field>
<field name="model">crm.caldav.alarm</field>
<record id="res_tree_view" model="ir.ui.view">
<field name="name">res.alarm.tree</field>
<field name="model">res.alarm</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Alarm details">
<field name="name" select="1"/>
<field name="action"/>
<field name="trigger_interval" select="1"/>
<field name="trigger_duration" select="1"/>
<field name="trigger_related" select="1"/>
<field name="trigger_occurs" select="1"/>
<field name="active"/>
</tree>
<field name="arch" type="xml">
<tree string="Reminder details">
<field name="name" select="1"/>
<field name="trigger_interval" select="1"/>
<field name="trigger_duration" select="1"/>
<field name="trigger_related" select="1"/>
<field name="trigger_occurs" select="1"/>
</tree>
</field>
</record>
</record>
<record id="view_caldav_set_rrule_wizard" model="ir.ui.view">
<field name="name">Add RRule</field>
@@ -97,7 +206,7 @@
<field name="end_date"
attrs="{'required' : [('count','&lt;=',0), ('freq', '!=', 'None')]}"/>
<group col="7" colspan="4" name="Select weekdays"
attrs="{'invisible' : [('freq','!=','WEEKLY')]}">
attrs="{'invisible' : [('freq','!=','weekly')]}">
<separator string="" colspan="6" />
<newline />
<field name="mo" colspan="1" />
@@ -109,7 +218,7 @@
<field name="su" colspan="1" />
<newline />
</group>
<group col="4" colspan="4" attrs="{'invisible' : [('freq','!=','MONTHLY'), ('freq','!=','YEARLY')]}">
<group col="4" colspan="4" attrs="{'invisible' : [('freq','!=','monthly'), ('freq','!=','yearly')]}">
<separator string="" colspan="6"/>
<group col="2" colspan="4">
<field name="select1"/>
@@ -127,14 +236,15 @@
<label string="of the Month" />
<newline />
</group>
<group col="2" colspan="4" attrs="{'invisible' : [('freq','!=','YEARLY')]}">
<group col="2" colspan="4" attrs="{'invisible' : [('freq','!=','yearly')]}">
<field name="month_list" string="of" colspan="1"
attrs="{'required' : [('freq','=','YEARLY')]}"/>
attrs="{'required' : [('freq','=','yearly')]}"/>
</group>
</group>
<separator string="" colspan="6" />
<label string="" colspan="3"/>
<button name="add_rrule" string="Ok" type="object" icon="gtk-ok"/>
<label string="" colspan="2"/>
<button icon='gtk-cancel' special="cancel" string="Cancel"/>
<button name="do_add" string="Ok" type="object" icon="gtk-ok"/>
</form>
</field>
</record>
@@ -148,6 +258,5 @@
<field name="target">new</field>
</record>
</data>
</openerp>
+31 -37
View File
@@ -75,14 +75,8 @@ class CalDAV(object):
__attribute__ = {
}
def get_recurrent_dates(self, rrulestring, exdate, startdate=None):
def todate(date):
val = parser.parse(''.join((re.compile('\d')).findall(date)) + 'Z')
return val
if not startdate:
startdate = datetime.now()
else:
startdate = todate(startdate)
startdate = datetime.now()
rset1 = rrulestr(rrulestring, dtstart=startdate, forceset=True)
for date in exdate:
@@ -133,10 +127,10 @@ class CalDAV(object):
uidval = common.openobjectid2uid(cr, data[map_field], model)
vevent.add('uid').value = uidval
elif field == 'attendee' and data[map_field]:
attendee_obj = self.pool.get('caldav.attendee')
attendee_obj = self.pool.get('basic.calendar.attendee')
vevent = attendee_obj.export_ical(cr, uid, data[map_field], vevent, context=context)
elif field == 'valarm' and data[map_field]:
alarm_obj = self.pool.get('caldav.alarm')
alarm_obj = self.pool.get('basic.calendar.alarm')
vevent = alarm_obj.export_ical(cr, uid, data[map_field][0], vevent, context=context)
elif data[map_field]:
if map_type == "text":
@@ -161,12 +155,12 @@ class CalDAV(object):
for child in parsedCal.getChildren():
for cal_data in child.getChildren():
if cal_data.name.lower() == 'attendee':
attendee = self.pool.get('caldav.attendee')
attendee = self.pool.get('basic.calendar.attendee')
att_data.append(attendee.import_ical(cr, uid, cal_data))
self.ical_set(cal_data.name.lower(), att_data, 'value')
continue
if cal_data.name.lower() == 'valarm':
alarm = self.pool.get('caldav.alarm')
alarm = self.pool.get('basic.calendar.alarm')
vals = alarm.import_ical(cr, uid, cal_data)
self.ical_set(cal_data.name.lower(), vals, 'value')
continue
@@ -183,7 +177,7 @@ class CalDAV(object):
class Calendar(CalDAV, osv.osv_memory):
_name = 'caldav.calendar'
_name = 'basic.calendar'
__attribute__ = {
'prodid': None, # Use: R-1, Type: TEXT, Specifies the identifier for the product that created the iCalendar object.
'version': None, # Use: R-1, Type: TEXT, Specifies the identifier corresponding to the highest version number
@@ -202,7 +196,7 @@ class Calendar(CalDAV, osv.osv_memory):
Calendar()
class Event(CalDAV, osv.osv_memory):
_name = 'caldav.event'
_name = 'basic.calendar.event'
__attribute__ = {
'class': None, # Use: O-1, Type: TEXT, Defines the access classification for a calendar component like "PUBLIC" / "PRIVATE" / "CONFIDENTIAL"
'created': None, # Use: O-1, Type: DATE-TIME, Specifies the date and time that the calendar information was created by the calendar user agent in the calendar store.
@@ -230,7 +224,7 @@ class Event(CalDAV, osv.osv_memory):
'exrule': None, # Use: O-n, Type: RECUR, Defines a rule or repeating pattern for an exception to a recurrence set.
'rstatus': None,
'related': None, # Use: O-n, Specify the relationship of the alarm trigger with respect to the start or end of the calendar component.
# like A trigger set 5 minutes after the end of the event or to-do.---> TRIGGER;RELATED=END:PT5M
# like A trigger set 5 minutes after the end of the event or to-do.---> TRIGGER;related=END:PT5M
'resources': None, # Use: O-n, Type: TEXT, Defines the equipment or resources anticipated for an activity specified by a calendar entity like RESOURCES:EASEL,PROJECTOR,VCR, LANGUAGE=fr:1 raton-laveur
'rdate': None, # Use: O-n, Type: DATE-TIME, Defines the list of date/times for a recurrence set.
'rrule': None, # Use: O-n, Type: RECUR, Defines a rule or repeating pattern for recurring events, to-dos, or time zone definitions.
@@ -244,7 +238,7 @@ class Event(CalDAV, osv.osv_memory):
Event()
class ToDo(CalDAV, osv.osv_memory):
_name = 'caldav.todo'
_name = 'basic.calendar.todo'
__attribute__ = {
'class': None,
@@ -320,13 +314,13 @@ class Timezone(CalDAV):
class Alarm(CalDAV, osv.osv_memory):
_name = 'caldav.alarm'
_name = 'basic.calendar.alarm'
__attribute__ = {
'action': None, # Use: R-1, Type: Text, defines the action to be invoked when an alarm is triggered LIKE "AUDIO" / "DISPLAY" / "EMAIL" / "PROCEDURE"
'description': None, # Type: Text, Provides a more complete description of the calendar component, than that provided by the "SUMMARY" property. Use:- R-1 for DISPLAY,Use:- R-1 for EMAIL,Use:- R-1 for PROCEDURE
'summary': None, # Use: R-1, Type: Text Which contains the text to be used as the message subject. Use for EMAIL
'attendee': None, # Use: R-n, Type: CAL-ADDRESS, Contain the email address of attendees to receive the message. It can also include one or more. Use for EMAIL
'trigger': None, # Use: R-1, Type: DURATION, The "TRIGGER" property specifies a duration prior to the start of an event or a to-do. The "TRIGGER" edge may be explicitly set to be relative to the "START" or "END" of the event or to-do with the "RELATED" parameter of the "TRIGGER" property. The "TRIGGER" property value type can alternatively be set to an absolute calendar date and time of day value. Use for all action like AUDIO, DISPLAY, EMAIL and PROCEDURE
'trigger': None, # Use: R-1, Type: DURATION, The "TRIGGER" property specifies a duration prior to the start of an event or a to-do. The "TRIGGER" edge may be explicitly set to be relative to the "START" or "END" of the event or to-do with the "related" parameter of the "TRIGGER" property. The "TRIGGER" property value type can alternatively be set to an absolute calendar date and time of day value. Use for all action like AUDIO, DISPLAY, EMAIL and PROCEDURE
'duration': None, # Type: DURATION, Duration' and 'repeat' are both optional, and MUST NOT occur more than once each, but if one occurs, so MUST the other. Use:- 0-1 for AUDIO, EMAIL and PROCEDURE, Use:- 0-n for DISPLAY
'repeat': None, # Type: INTEGER, Duration' and 'repeat' are both optional, and MUST NOT occur more than once each, but if one occurs, so MUST the other. Use:- 0-1 for AUDIO, EMAIL and PROCEDURE, Use:- 0-n for DISPLAY
'attach': None, # Use:- O-n: which MUST point to a sound resource, which is rendered when the alarm is triggered for AUDIO, Use:- O-n: which are intended to be sent as message attachments for EMAIL, Use:- R-1:which MUST point to a procedure resource, which is invoked when the alarm is triggered for PROCEDURE.
@@ -335,28 +329,28 @@ class Alarm(CalDAV, osv.osv_memory):
def export_ical(self, cr, uid, alarm_id, vevent, context={}):
valarm = vevent.add('valarm')
alarm_object = self.pool.get('crm.caldav.alarm')
alarm_object = self.pool.get('calendar.alarm')
alarm_data = alarm_object.read(cr, uid, alarm_id, [])
# Compute trigger data
interval = alarm_data['trigger_interval']
occurs = alarm_data['trigger_occurs']
duration = (occurs == 'AFTER' and alarm_data['trigger_duration']) \
duration = (occurs == 'after' and alarm_data['trigger_duration']) \
or -(alarm_data['trigger_duration'])
related = alarm_data['trigger_related']
trigger = valarm.add('TRIGGER')
trigger.params['RELATED'] = [related.upper()]
if interval == 'DAYS':
trigger = valarm.add('trigger')
trigger.params['related'] = [related.upper()]
if interval == 'days':
delta = timedelta(days=duration)
if interval == 'HOURS':
if interval == 'hours':
delta = timedelta(hours=duration)
if interval == 'MINUTES':
if interval == 'minutes':
delta = timedelta(minutes=duration)
trigger.value = delta
# Compute other details
valarm.add('DESCRIPTION').value = alarm_data['name']
valarm.add('ACTION').value = alarm_data['action']
valarm.add('description').value = alarm_data['name']
valarm.add('action').value = alarm_data['action']
return vevent
def import_ical(self, cr, uid, ical_data):
@@ -365,25 +359,25 @@ class Alarm(CalDAV, osv.osv_memory):
seconds = child.value.seconds
days = child.value.days
diff = (days * 86400) + seconds
interval = 'DAYS'
related = 'BEFORE'
interval = 'days'
related = 'before'
if not seconds:
duration = abs(days)
related = days>0 and 'AFTER' or 'BEFORE'
related = days>0 and 'after' or 'before'
elif (abs(diff) / 3600) == 0:
duration = abs(diff / 60)
interval = 'MINUTES'
related = days>=0 and 'AFTER' or 'BEFORE'
interval = 'minutes'
related = days>=0 and 'after' or 'before'
else:
duration = abs(diff / 3600)
interval = 'HOURS'
related = days>=0 and 'AFTER' or 'BEFORE'
interval = 'hours'
related = days>=0 and 'after' or 'before'
self.ical_set('trigger_interval', interval, 'value')
self.ical_set('trigger_duration', duration, 'value')
self.ical_set('trigger_occurs', related, 'value')
if child.params:
if child.params.get('RELATED'):
self.ical_set('trigger_related', child.params.get('RELATED')[0].lower(), 'value')
if child.params.get('related'):
self.ical_set('trigger_related', child.params.get('related')[0].lower(), 'value')
else:
self.ical_set(child.name.lower(), child.value, 'value')
vals = map_data(cr, uid, self)
@@ -392,7 +386,7 @@ class Alarm(CalDAV, osv.osv_memory):
Alarm()
class Attendee(CalDAV, osv.osv_memory):
_name = 'caldav.attendee'
_name = 'basic.calendar.attendee'
__attribute__ = {
'cutype': None, # Use: 0-1 Specify the type of calendar user specified by the property like "INDIVIDUAL"/"GROUP"/"RESOURCE"/"ROOM"/"UNKNOWN".
'member': None, # Use: 0-1 Specify the group or list membership of the calendar user specified by the property.
@@ -419,7 +413,7 @@ class Attendee(CalDAV, osv.osv_memory):
return vals
def export_ical(self, cr, uid, attendee_id, vevent, context={}):
attendee_object = self.pool.get('crm.caldav.attendee')
attendee_object = self.pool.get('calendar.attendee')
for attendee in attendee_object.read(cr, uid, attendee_id, []):
attendee_add = vevent.add('attendee')
for a_key, a_val in attendee_object.__attribute__.items():
+335 -131
View File
@@ -23,22 +23,37 @@ from osv import fields, osv
from service import web_services
from tools.translate import _
import re
import time
import datetime
months = {1:"January", 2:"February", 3:"March", 4:"April", 5:"May", 6:"June", \
7:"July", 8:"August", 9:"September", 10:"October", 11:"November", \
12:"December"}
months = {
1:"January", 2:"February", 3:"March", 4:"April", \
5:"May", 6:"June", 7:"July", 8:"August", 9:"September", \
10:"October", 11:"November", 12:"December"}
def caldevIDs2readIDs(caldev_ID = None):
if caldev_ID:
if isinstance(caldev_ID, str):
return int(caldev_ID.split('-')[0])
return caldev_ID
def caldav_id2real_id(caldav_id = None, with_date=False):
if caldav_id and isinstance(caldav_id, (str, unicode)):
res = caldav_id.split('-')
if len(res) >= 2:
real_id = res[0]
if with_date:
real_date = time.strftime("%Y-%m-%d %H:%M:%S", \
time.strptime(res[1], "%Y%m%d%H%M%S"))
return (int(real_id), real_date)
return int(real_id)
return caldav_id and int(caldav_id) or caldav_id
def real_id2caldav_id(real_id, recurrent_date):
if real_id and recurrent_date:
recurrent_date = time.strftime("%Y%m%d%H%M%S", \
time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S"))
return '%d-%s'%(real_id, recurrent_date)
return real_id
def uid2openobjectid(cr, uidval, oomodel):
__rege = re.compile(r'OpenERP-([\w|\.]+)_([0-9]+)@(\w+)$')
__rege = re.compile(r'OpenObject-([\w|\.]+)_([0-9]+)@(\w+)$')
wematch = __rege.match(uidval.encode('utf8'))
if not wematch:
# raise osv.except_osv('Warning!!', "Cannot locate UID in %s" % val['id'])
return False
else:
model, id, dbname = wematch.groups()
@@ -51,11 +66,11 @@ def uid2openobjectid(cr, uidval, oomodel):
return False
def openobjectid2uid(cr, uidval, oomodel):
value = 'OpenERP-%s_%s@%s' % (oomodel, uidval, cr.dbname)
value = 'OpenObject-%s_%s@%s' % (oomodel, uidval, cr.dbname)
return value
class crm_caldav_attendee(osv.osv):
_name = 'crm.caldav.attendee'
class calendar_attendee(osv.osv):
_name = 'calendar.attendee'
_description = 'Attendee information'
_rec_name = 'cutype'
@@ -63,53 +78,143 @@ class crm_caldav_attendee(osv.osv):
'cutype': {'field':'cutype', 'type':'text'},
'member': {'field':'member', 'type':'text'},
'role': {'field':'role', 'type':'selection'},
'partstat': {'field':'partstat', 'type':'text'},
'partstat': {'field':'state', 'type':'text'},
'rsvp': {'field':'rsvp', 'type':'boolean'},
'delegated-to': {'field':'delegated_to', 'type':'char'},
'delegated-from': {'field':'delegated_from', 'type':'char'},
'delegated-to': {'field':'delegated_to', 'type':'text'},
'delegated-from': {'field':'delegated_from', 'type':'text'},
'sent-by': {'field':'sent_by', 'type':'text'},
'cn': {'field':'cn', 'type':'text'},
'dir': {'field':'dir', 'type':'text'},
'language': {'field':'language', 'type':'text'},
}
def _get_address(self, name=None, email=None):
if name and email:
name += ':'
return (name or '') + (email and ('MAILTO:' + email) or '')
def _compute_data(self, cr, uid, ids, name, arg, context):
name = name[0]
result = {}
def get_delegate_data(user):
email = user.address_id and user.address_id.email or ''
return self._get_address(user.name, email)
for id in ids:
result[id] = {}
attdata = self.browse(cr, uid, id, context=context)
if name == 'sent_by':
if not attdata.sent_by_uid:
result[id][name] = ''
continue
else:
result[id][name] = self._get_address(attdata.sent_by_uid.name, \
attdata.sent_by_uid.address_id.email)
if name == 'cn':
result[id][name] = self._get_address(attdata.user_id.name, attdata.email)
if name == 'delegated_to':
user_obj = self.pool.get('res.users')
todata = map(get_delegate_data, attdata.del_to_user_ids)
result[id][name] = ', '.join(todata)
if name == 'delegated_from':
dstring = []
user_obj = self.pool.get('res.users')
fromdata = map(get_delegate_data, attdata.del_from_user_ids)
result[id][name] = ', '.join(fromdata)
return result
_columns = {
'cutype': fields.selection([('INDIVIDUAL', 'INDIVIDUAL'), ('GROUP', 'GROUP'), \
('RESOURCE', 'RESOURCE'), ('ROOM', 'ROOM'), \
('UNKNOWN', 'UNKNOWN') ], 'CUTYPE', \
help="Specify the type of calendar user"),
'member': fields.char('Member', size=124, help="Indicate the groups that the attendee belongs to"),
'role': fields.selection([ ('REQ-PARTICIPANT', 'REQ-PARTICIPANT'), \
('CHAIR', 'CHAIR'), ('OPT-PARTICIPANT', 'OPT-PARTICIPANT'), \
('NON-PARTICIPANT', 'NON-PARTICIPANT')], 'ROLE', \
help='Participation role for the calendar user'),
'partstat': fields.selection([('TENTATIVE', 'TENTATIVE'),
('NEEDS-ACTION', 'NEEDS-ACTION'),
('ACCEPTED', 'ACCEPTED'),
('DECLINED', 'DECLINED'),
('DELEGATED', 'DELEGATED')], 'PARTSTAT', \
help="Status of the attendee's participation"),
'rsvp': fields.boolean('RSVP', help="Indicats whether the favor of a reply is requested"),
'delegated_to': fields.char('DELEGATED-TO', size=124, \
help="The calendar users that the original request was delegated to"),
'delegated_from': fields.char('DELEGATED-FROM', size=124, \
help="Indicates whom the request was delegated from"),
'sent_by': fields.char('SENT-BY', size=124, \
help="Specify the calendar user that is acting on behalf of the calendar user"),
'cn': fields.char('CN', size=124, help="The common or displayable name to be associated with the calendar user"),
'dir': fields.char('DIR', size=124, help="Reference to the URI that points to the directory information corresponding to the attendee."),
'language': fields.char('LANGUAGE', size=124, help="To specify the language for text values in a property or property parameter."),
'cutype': fields.selection([('individual', 'Individual'), \
('group', 'Group'), ('resource', 'Resource'), \
('room', 'Room'), ('unknown', 'Unknown') ], \
'User Type', help="Specify the type of calendar user"),
'member': fields.char('Member', size=124, help="Indicate the groups \
that the attendee belongs to"),
'role': fields.selection([ ('req-participant', 'req-participant'), \
('chair', 'chair'), ('opt-participant', 'opt-participant'), \
('non-participant', 'non-participant')], 'User\'s Role', \
help='Participation role for the calendar user'),
'state': fields.selection([('tentative', 'Tentative'),
('needs-action', 'Needs Action'),
('accepted', 'Accepted'),
('declined', 'Declined'),
('delegated', 'Delegated')], 'Status', readonly=True,
help="Status of the attendee's participation"),
'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
favor of a reply is requested"),
'delegated_to': fields.function(_compute_data, method=True, \
string='Delegated To', type="char", size=124, store=True, \
multi='delegated_to', help="The users that the original request \
was delegated to"),
'del_to_user_ids': fields.many2many('res.users', 'att_del_to_user_rel',
'attendee_id', 'user_id', 'Users'),
'delegated_from': fields.function(_compute_data, method=True, string=\
'Delegated From', type="char", store=True, size=124, multi='delegated_from'),
'del_from_user_ids': fields.many2many('res.users', 'att_del_from_user_rel', \
'attendee_id', 'user_id', 'Users'),
'sent_by': fields.function(_compute_data, method=True, string='Sent By', type="char", multi='sent_by', store=True, size=124, help="Specify the user that is acting on behalf of the calendar user"),
'sent_by_uid': fields.many2one('res.users', 'Sent by User'),
'cn': fields.function(_compute_data, method=True, string='Common name', type="char", size=124, multi='cn', store=True),
'dir': fields.char('URI Reference', size=124, help="Reference to the URI that points to the directory information corresponding to the attendee."),
'language': fields.char('Language', size=124, help="To specify the language for text values in a property or property parameter."),
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
}
_defaults = {
'cn': lambda *x: 'MAILTO:',
'state': lambda *x: 'needs-action',
}
crm_caldav_attendee()
class crm_caldav_alarm(osv.osv):
_name = 'crm.caldav.alarm'
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:
return {'value': {'email': ''}}
user = self.pool.get('res.users').browse(cr, uid, user_id, *args)
return {'value': {'email': user.address_id.email}}
def do_tentative(self, cr, uid, ids, context=None, *args):
self.write(cr, uid, ids, {'state': 'tentative'}, context)
def do_accept(self, cr, uid, ids, context=None, *args):
self.write(cr, uid, ids, {'state': 'accepted'}, context)
def do_decline(self, cr, uid, ids, context=None, *args):
self.write(cr, uid, ids, {'state': 'declined'}, context)
calendar_attendee()
class res_alarm(osv.osv):
_name = 'res.alarm'
_description = 'basic alarm information'
_columns = {
'name':fields.char('Name', size=256, required=True),
'trigger_occurs': fields.selection([('before', 'Before'), ('after', 'After')], \
'Trigger time', required=True),
'trigger_interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), \
('days', 'Days')], 'Trigger duration', required=True),
'trigger_duration': fields.integer('Time', required=True),
'trigger_related': fields.selection([('start', 'The event starts'), ('end', \
'The event ends')], 'Trigger Occures at', required=True),
'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \
are both optional, but if one occurs, so MUST the other"""),
'repeat': fields.integer('Repeat'),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it."),
}
_defaults = {
'trigger_interval': lambda *x: 'minutes',
'trigger_duration': lambda *x: 5,
'trigger_occurs': lambda *x: 'before',
'trigger_related': lambda *x: 'start',
'active': lambda *x: 1,
}
res_alarm()
class calendar_alarm(osv.osv):
_name = 'calendar.alarm'
_description = 'Event alarm information'
_inherits = {'res.alarm': "alarm_id"}
__attribute__ = {
'action': {'field': 'action', 'type': 'text'},
'description': {'field': 'name', 'type': 'text'},
@@ -122,43 +227,111 @@ class crm_caldav_alarm(osv.osv):
'duration': {'field': 'duration', 'type': 'text'},
'repeat': {'field': 'repeat', 'type': 'text'},
'attach': {'field': 'attach', 'type': 'text'},
}
_columns = {
'name': fields.char('Summary', size=124, help="""Contains the text to be used as the message subject for EMAIL
or contains the text to be used for DISPLAY"""),
'action': fields.selection([('AUDIO', 'AUDIO'), ('DISPLAY', 'DISPLAY'), \
('PROCEDURE', 'PROCEDURE'), ('EMAIL', 'EMAIL') ], 'Action', \
}
_columns = {
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
'name': fields.char('Summary', size=124, help="""Contains the text to be used as the message subject for email
or contains the text to be used for display"""),
'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
('procedure', 'Procedure'), ('email', 'Email') ], 'Action', \
required=True, help="Defines the action to be invoked when an alarm is triggered"),
'description': fields.text('Description', help='Provides a more complete description of the calendar component, than that provided by the "SUMMARY" property'),
'attendee_ids': fields.many2many('crm.caldav.attendee', 'alarm_attendee_rel', \
'alarm_id', 'attendee_id', 'Attendees'),
'trigger_occurs': fields.selection([('BEFORE', 'BEFORE'), ('AFTER', 'AFTER')], \
'Trigger time', required=True),
'trigger_interval': fields.selection([('MINUTES', 'MINUTES'), ('HOURS', 'HOURS'), \
('DAYS', 'DAYS')], 'Trigger duration', required=True),
'trigger_duration': fields.integer('TIme', required=True),
'trigger_related': fields.selection([('start', 'The event starts'), ('end', \
'The event ends')], 'Trigger Occures at', required=True),
'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \
are both optional, but if one occurs, so MUST the other"""),
'repeat': fields.integer('Repeat'), # TODO
'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for AUDIO,
* File which is intended to be sent as message attachments for EMAIL,
* Points to a procedure resource, which is invoked when the alarm is triggered for PROCEDURE.
"""),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the event alarm information without removing it."),
}
'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
'alarm_id', 'attendee_id', 'Attendees', readonly=True),
'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio,
* File which is intended to be sent as message attachments for email,
* Points to a procedure resource, which is invoked when the alarm is triggered for procedure."""),
'res_id' : fields.integer('Resource ID'),
'model_id': fields.many2one('ir.model', 'Model'),
'user_id': fields.many2one('res.users', 'Owner'),
'event_date' : fields.datetime('Event Date'),
'trigger_date' : fields.datetime('Trigger Date', readonly="True"),
'state':fields.selection([
('draft','Draft'),
('run','Run'),
('stop','Stop'),
('done','Done'),
],'State', select=True, readonly=True),
}
_defaults = {
'action': lambda *x: 'EMAIL',
'trigger_interval': lambda *x: 'MINUTES',
'trigger_duration': lambda *x: 5,
'trigger_occurs': lambda *x: 'BEFORE',
'trigger_related': lambda *x: 'start',
}
crm_caldav_alarm()
'action': lambda *x: 'email',
'state' : lambda *x: 'run',
}
def create(self, cr, uid, vals, context={}):
event_date = vals.get('event_date', False)
if event_date:
dtstart = datetime.datetime.strptime(vals['event_date'], "%Y-%m-%d %H:%M:%S")
if vals['trigger_interval'] == 'days':
delta = datetime.timedelta(days=vals['trigger_duration'])
if vals['trigger_interval'] == 'hours':
delta = datetime.timedelta(hours=vals['trigger_duration'])
if vals['trigger_interval'] == 'minutes':
delta = datetime.timedelta(minutes=vals['trigger_duration'])
trigger_date = dtstart + (vals['trigger_occurs'] == 'after' and delta or -delta)
vals['trigger_date'] = trigger_date
res = super(calendar_alarm, self).create(cr, uid, vals, context)
return res
def do_run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \
context=None):
if not context:
context = {}
current_datetime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
cr.execute("select alarm.id as id \
from calendar_alarm alarm \
where alarm.state = %s and alarm.trigger_date <= %s", ('run', current_datetime))
res = cr.dictfetchall()
alarm_ids = map(lambda x: x['id'], res)
attendee_obj = self.pool.get('calendar.attendee')
request_obj = self.pool.get('res.request')
mail_to = []
for alarm in self.browse(cr, uid, alarm_ids):
if alarm.action == 'display':
value = {
'name': alarm.name,
'act_from': alarm.user_id.id,
'act_to': alarm.user_id.id,
'body': alarm.description,
'trigger_date': alarm.trigger_date,
'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
}
request_id = request_obj.create(cr, uid, value)
request_ids = [request_id]
for attendee in alarm.attendee_ids:
value['act_to'] = attendee.act_to.id
request_id = request_obj.create(cr, uid, value)
request_ids.append(request_id)
request_obj.request_send(cr, uid, request_ids)
if alarm.action == 'email':
sub = '[Openobject Remainder] %s' %(alarm.name)
body = """
Name : %s
Date : %s
Description : %s
From :
%s
%s
""" %(alarm.name, alarm.trigger_date, alarm.description, alarm.user_id.name, alarm.user_id.sign)
mail_to = [alarm.user_id.address_id.email]
for att in alarm.attendee_ids:
mail_to.append(att.act_to.address_id.email)
tools.email_send(
tools.confirm['from_mail'],
mail_to,
sub,
body
)
self.write(cr, uid, [alarm.id], {'state':'done'})
return True
calendar_alarm()
class ir_attachment(osv.osv):
_name = 'ir.attachment'
@@ -175,7 +348,7 @@ class ir_attachment(osv.osv):
new_args = args
for i, arg in enumerate(new_args):
if arg[0] == 'res_id':
new_args[i] = (arg[0], arg[1], caldevIDs2readIDs(arg[2]))
new_args[i] = (arg[0], arg[1], caldav_id2real_id(arg[2]))
return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
limit=limit, order=order,
context=context, count=False)
@@ -189,7 +362,7 @@ class ir_values(osv.osv):
new_model = []
for data in models:
if type(data) in (list, tuple):
new_model.append((data[0], caldevIDs2readIDs(data[1])))
new_model.append((data[0], caldav_id2real_id(data[1])))
else:
new_model.append(data)
return super(ir_values, self).set(cr, uid, key, key2, name, new_model, value, \
@@ -200,7 +373,7 @@ class ir_values(osv.osv):
new_model = []
for data in models:
if type(data) in (list, tuple):
new_model.append((data[0], caldevIDs2readIDs(data[1])))
new_model.append((data[0], caldav_id2real_id(data[1])))
else:
new_model.append(data)
return super(ir_values, self).get(cr, uid, key, key2, new_model, meta, context, \
@@ -217,7 +390,7 @@ class ir_model(osv.osv):
data = super(ir_model, self).read(cr, uid, ids, fields=fields, context=context, load=load)
if data:
for val in data:
val['id'] = caldevIDs2readIDs(val['id'])
val['id'] = caldav_id2real_id(val['id'])
return data
ir_model()
@@ -229,47 +402,26 @@ class virtual_report_spool(web_services.report_spool):
return super(virtual_report_spool, self).exp_report(db, uid, object, ids, datas, context)
new_ids = []
for id in ids:
new_ids.append(caldevIDs2readIDs(id))
datas['id'] = caldevIDs2readIDs(datas['id'])
new_ids.append(caldav_id2real_id(id))
datas['id'] = caldav_id2real_id(datas['id'])
super(virtual_report_spool, self).exp_report(db, uid, object, new_ids, datas, context)
return super(virtual_report_spool, self).exp_report(db, uid, object, new_ids, datas, context)
virtual_report_spool()
class virtual_wizard(web_services.wizard):
def exp_execute(self, db, uid, wiz_id, datas, action='init', context=None):
#if wiz_id not in self.wiz_uid:
# # TODO: To Check why need it
# if wiz_id == 1:
# wiz_name ='base_setup.base_setup'
# if wiz_id == 2:
# wiz_name ='module.upgrade'
# super(virtual_wizard,self).exp_create(db, uid, wiz_name, datas)
new_ids = []
if 'id' in datas:
datas['id'] = caldevIDs2readIDs(datas['id'])
for id in datas['ids']:
new_ids.append(caldevIDs2readIDs(id))
datas['ids'] = new_ids
res=super(virtual_wizard, self).exp_execute(db, uid, wiz_id, datas, action, context)
return res
virtual_wizard()
class set_rrule_wizard(osv.osv_memory):
_name = "caldav.set.rrule"
_description = "Set RRULE"
_columns = {
'freq': fields.selection([('None', 'No Repeat'), \
('SECONDLY', 'SECONDLY'), \
('MINUTELY', 'MINUTELY'), \
('HOURLY', 'HOURLY'), \
('DAILY', 'DAILY'), \
('WEEKLY', 'WEEKLY'), \
('MONTHLY', 'MONTHLY'), \
('YEARLY', 'YEARLY')], 'Frequency', required=True),
('secondly', 'Secondly'), \
('minutely', 'Minutely'), \
('hourly', 'Hourly'), \
('daily', 'Daily'), \
('weekly', 'Weekly'), \
('monthly', 'Monthly'), \
('yearly', 'Yearly')], 'Frequency', required=True),
'interval': fields.integer('Interval'),
'count': fields.integer('Count'),
'mo': fields.boolean('Mon'),
@@ -294,19 +446,12 @@ class set_rrule_wizard(osv.osv_memory):
}
_defaults = {
'freq': lambda *x: 'DAILY',
'freq': lambda *x: 'daily',
'select1': lambda *x: 'date',
'interval': lambda *x: 1,
}
def add_rrule(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if not context or not context.get('model'):
return {}
else:
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
def compute_rule_string(self, cr, uid, datas, context=None, *args):
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
weekstring = ''
monthstring = ''
@@ -318,14 +463,13 @@ class set_rrule_wizard(osv.osv_memory):
if freq == 'None':
obj.write(cr, uid, [res_obj.id], {'rrule' : ''})
return {}
if datas.get('interval') <= 0:
raise osv.except_osv(_('Error!'), ("Please select proper Interval"))
if freq == 'WEEKLY':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'MONTHLY':
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
if byday:
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'monthly':
byday = ''
if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
raise osv.except_osv(_('Error!'), ("Please select proper Day of month"))
@@ -333,7 +477,7 @@ class set_rrule_wizard(osv.osv_memory):
byday = ';BYDAY=' + datas.get('byday') + datas.get('week_list')
monthstring = byday or (';BYMONTHDAY=' + str(datas.get('day')))
elif freq == 'YEARLY':
elif freq == 'yearly':
bymonth = ''
byday = ''
if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
@@ -354,9 +498,69 @@ class set_rrule_wizard(osv.osv_memory):
str(datas.get('interval')) + enddate + monthstring + yearstring
# End logic
return rrule_string
def do_add(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if datas.get('interval') <= 0:
raise osv.except_osv(_('Error!'), ("Please select proper Interval"))
if not context or not context.get('model'):
return {}
else:
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
rrule_string = self.compute_rule_string(cr, uid, datas)
obj.write(cr, uid, [res_obj.id], {'rrule' : rrule_string})
return {}
set_rrule_wizard()
class invite_attendee_wizard(osv.osv_memory):
_name = "caldav.invite.attendee"
_description = "Invite Attendees"
_columns = {
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
'role': fields.selection([ ('REQ-PARTICIPANT', 'REQ-PARTICIPANT'), \
('CHAIR', 'CHAIR'), ('OPT-PARTICIPANT', 'OPT-PARTICIPANT'), \
('NON-PARTICIPANT', 'NON-PARTICIPANT')], 'User\'s Role', \
help='Participation role for the calendar user'),
'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
favor of a reply is requested"),
}
def do_invite(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if not context or not context.get('model') or not datas.get('user_id'):
return {}
else:
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
user_obj = self.pool.get('res.users')
attendee_obj = self.pool.get('calendar.attendee')
for user_id in datas.get('users', []):
user = user_obj.browse(cr, uid, user_id)
if not user.address_id.email:
raise osv.except_osv(_('Error!'), \
("User does not have an email Address"))
attendee_id = attendee_obj.create(cr, uid, {'user_id': user_id,\
'cn': user.name + ':MAILTO:' + user.address_id.email})
obj.write(cr, uid, res_obj.id, {'attendee_ids': [(6, 0, [attendee_id])]})
return {}
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:
return {'value': {'email': ''}}
user = self.pool.get('res.users').browse(cr, uid, user_id, *args)
return {'value': {'email': user.address_id.email}}
invite_attendee_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+5 -5
View File
@@ -1,6 +1,6 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"caldav_calendar_all","caldav.calendar","model_caldav_calendar",,1,1,1,1
"caldav_event_all","caldav.event","model_caldav_event",,1,1,1,1
"caldav_attendee_all","caldav.attendee","model_caldav_attendee",,1,1,1,1
"access_crm_caldav_attendee","crm.caldav.attendee","model_crm_caldav_attendee",,1,1,1,1
"access_crm_caldav_alarm","crm.caldav.alarm","model_crm_caldav_alarm",,1,1,1,1
"basic_calendar_all","basic.calendar","model_basic_calendar",,1,1,1,1
"basic_calendar_event_all","basic.calendar.event","model_basic_calendar_event",,1,1,1,1
"basic_calendar_attendee_all","basic.calendar.attendee","model_basic_calendar_attendee",,1,1,1,1
"access_basic_calendar_attendee","calendar.attendee","model_basic_calendar_attendee",,1,1,1,1
"access_basic_calendar_alarm","calendar.alarm","model_basic_calendar_alarm",,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 caldav_calendar_all basic_calendar_all caldav.calendar basic.calendar model_caldav_calendar model_basic_calendar 1 1 1 1
3 caldav_event_all basic_calendar_event_all caldav.event basic.calendar.event model_caldav_event model_basic_calendar_event 1 1 1 1
4 caldav_attendee_all basic_calendar_attendee_all caldav.attendee basic.calendar.attendee model_caldav_attendee model_basic_calendar_attendee 1 1 1 1
5 access_crm_caldav_attendee access_basic_calendar_attendee crm.caldav.attendee calendar.attendee model_crm_caldav_attendee model_basic_calendar_attendee 1 1 1 1
6 access_crm_caldav_alarm access_basic_calendar_alarm crm.caldav.alarm calendar.alarm model_crm_caldav_alarm model_basic_calendar_alarm 1 1 1 1
+58 -59
View File
@@ -21,9 +21,9 @@
{
'name': 'Customer & Supplier Relationship Management',
'version': '1.0',
'category': 'Generic Modules/CRM & SRM',
'name': 'Customer & Supplier Relationship Management',
'version': '1.0',
'category': 'Generic Modules/CRM & SRM',
'description': """The generic Open ERP Customer Relationship Management
system enables a group of people to intelligently and efficiently manage
leads, opportunities, tasks, issues, requests, bugs, campaign, claims, etc.
@@ -41,68 +41,67 @@ appropriate staff, and making sure all future correspondence gets to the right
place.
The CRM module has a email gateway for the synchronisation interface
between mails and Open ERP.""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base',
'caldav',
'process',
'mail_gateway',
],
between mails and Open ERP.""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base',
'caldav',
'process',
'mail_gateway',
],
'init_xml': ['crm_data.xml',
'crm_meeting_data.xml',
'crm_claims_data.xml',
'crm_fund_data.xml',
'crm_helpdesk_data.xml',
'crm_jobs_data.xml',
'crm_lead_data.xml',
'crm_meeting_data.xml',
'crm_claims_data.xml',
'crm_fund_data.xml',
'crm_helpdesk_data.xml',
'crm_jobs_data.xml',
'crm_lead_data.xml',
'crm_meeting_data.xml',
'crm_opportunity_data.xml',
'crm_phonecall_data.xml',
],
'crm_opportunity_data.xml',
'crm_phonecall_data.xml',
],
'update_xml': [
'crm_wizard.xml',
'crm_view.xml',
'crm_config_view.xml',
'crm_job_wizard.xml',
'crm_jobs_view.xml',
'crm_jobs_menu.xml',
'crm_lead_wizard.xml',
'crm_lead_view.xml',
'crm_lead_menu.xml',
'crm_meeting_wizard.xml',
'crm_meeting_view.xml',
'crm_meeting_menu.xml',
'crm_opportunity_wizard.xml',
'crm_opportunity_view.xml',
'crm_opportunity_menu.xml',
'crm_fund_view.xml',
'crm_fund_menu.xml',
'crm_claims_view.xml',
'crm_claims_menu.xml',
'crm_phonecall_wizard.xml',
'crm_phonecall_view.xml',
'crm_phonecall_menu.xml',
'crm_report_view.xml',
'crm_helpdesk_view.xml',
'crm_report.xml',
'security/crm_security.xml',
'security/ir.model.access.csv',
'crm_wizard.xml',
'crm_view.xml',
'crm_config_view.xml',
'crm_job_wizard.xml',
'crm_jobs_view.xml',
'crm_jobs_menu.xml',
'crm_lead_wizard.xml',
'crm_lead_view.xml',
'crm_lead_menu.xml',
'crm_meeting_wizard.xml',
'crm_meeting_view.xml',
'crm_meeting_menu.xml',
'crm_opportunity_wizard.xml',
'crm_opportunity_view.xml',
'crm_opportunity_menu.xml',
'crm_fund_view.xml',
'crm_fund_menu.xml',
'crm_claims_view.xml',
'crm_claims_menu.xml',
'crm_phonecall_wizard.xml',
'crm_phonecall_view.xml',
'crm_phonecall_menu.xml',
'crm_report_view.xml',
'crm_helpdesk_view.xml',
'crm_report.xml',
'security/crm_security.xml',
'security/ir.model.access.csv',
'process/crm_configuration_process.xml'
],
],
'demo_xml': [
'crm_demo.xml',
'crm_meeting_demo.xml',
'crm_claims_demo.xml',
'crm_fund_demo.xml',
'crm_helpdesk_demo.xml',
'crm_jobs_demo.xml',
'crm_lead_demo.xml',
'crm_claims_demo.xml',
'crm_fund_demo.xml',
'crm_helpdesk_demo.xml',
'crm_jobs_demo.xml',
'crm_lead_demo.xml',
'crm_meeting_demo.xml',
'crm_opportunity_demo.xml',
'crm_phonecall_demo.xml'],
'installable': True,
'active': False,
'certificate': '0079056041421',
'crm_opportunity_demo.xml',
'crm_phonecall_demo.xml'],
'installable': True,
'active': False,
'certificate': '0079056041421',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+4 -4
View File
@@ -52,7 +52,7 @@ class crm_cases(osv.osv):
data.update(res)
return self.create(cr, uid, data)
def msg_update(self, cr, uid, id, msg, data={}, default_act='pending'):
def msg_update(self, cr, uid, ids, msg, data={}, default_act='pending'):
mailgate_obj = self.pool.get('mail.gateway')
msg_actions, body_data = mailgate_obj.msg_act_get(msg)
data.update({
@@ -77,9 +77,9 @@ class crm_cases(osv.osv):
if 'partner' in msg_actions:
data['email_from'] = msg_actions['partner'][:128]
self.write(cr, uid, [id], data)
getattr(self,act)(cr, uid, [id])
return True
res = self.write(cr, uid, ids, data)
getattr(self,act)(cr, uid, ids)
return res
def emails_get(self, cr, uid, ids, context={}):
res = []
+397 -224
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@@ -15,144 +15,189 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from caldav import common
from dateutil.rrule import *
from osv import fields, osv
import datetime
import datetime
import base64
import re
import time
import tools
from tools.translate import _
from dateutil import parser
class crm_meeting(osv.osv):
_name = 'crm.meeting'
_name = 'crm.meeting'
_description = "Meeting Cases"
_order = "id desc"
_inherits = {'crm.case':"inherit_case_id"}
_inherits = {'crm.case': "inherit_case_id"}
__attribute__ = {
'class' : {'field':'class', 'type':'text'},
'created' : {'field':'create_date', 'type':'datetime'}, # keep none for now
'description' : {'field':'description', 'type':'text'},
'dtstart' : {'field':'date', 'type':'datetime'},
#'last-mod' : {'field':'write_date', 'type':'datetime'},
'location' : {'field':'location', 'type':'text'},
# 'organizer' : {'field':'partner_id', 'sub-field':'name', 'type':'many2one'},
'priority' : {'field':'priority', 'type':'int'},
'dtstamp' : {'field':'date', 'type':'datetime'},
'seq' : None,
'status' : {'field':'state', 'type':'selection', 'mapping' : {'TENTATIVE' : 'draft', \
'CONFIRMED' : 'open' , 'CANCELLED' : 'cancel'}},
'summary' : {'field':'name', 'type':'text'},
'transp' : {'field':'transparent', 'type':'text'},
'uid' : {'field':'id', 'type':'text'},
'url' : {'field':'caldav_url', 'type':'text'},
'recurid' : None,
# 'attach' : {'field':'attachment_ids', 'sub-field':'datas', 'type':'list'},
'attendee' : {'field':'attendees', 'type':'many2many', 'object' : 'crm.caldav.attendee'},
# 'categories' : {'field':'categ_id', 'sub-field':'name'},
# 'categories' : {'field':None , 'sub-field':'name', 'type':'text'},
'comment' : None,
'contact' : None,
'exdate' : {'field':'exdate', 'type':'datetime'},
'exrule' : {'field':'exrule', 'type':'text'},
'rstatus' : None,
'related' : None,
'resources' : None,
'rdate' : None,
'rrule' : {'field':'rrule', 'type':'text'},
'x-openobject-model' : {'value':_name, 'type':'text'},
# 'duration' : {'field':'duration'},
'dtend' : {'field':'date_closed', 'type':'datetime'},
'valarm' : {'field':'alarm_id', 'type':'many2one', 'object' : 'crm.caldav.alarm'},
}
'class': {'field': 'class', 'type': 'text'},
'created': {'field': 'create_date', 'type': 'datetime'}, # keep none for now
'description': {'field': 'description', 'type': 'text'},
'dtstart': {'field': 'date', 'type': 'datetime'},
'location': {'field': 'location', 'type': 'text'},
#'organizer': {'field': 'partner_id', 'sub-field': 'name', 'type': 'many2one'},
'priority': {'field': 'priority', 'type': 'int'},
'dtstamp' : {'field': 'date', 'type': 'datetime'},
'seq': None,
'status': {'field': 'state', 'type': 'selection', 'mapping': {'TENTATIVE': 'draft', \
'CONFIRMED': 'open' , 'CANCELLED': 'cancel'}},
'summary': {'field': 'name', 'type': 'text'},
'transp': {'field': 'transparent', 'type': 'text'},
'uid': {'field': 'id', 'type': 'text'},
'url': {'field': 'caldav_url', 'type': 'text'},
'recurid': None,
# 'attach': {'field': 'attachment_ids', 'sub-field': 'datas', 'type': 'list'},
'attendee': {'field': 'attendee_ids', 'type': 'many2many', 'object': 'calendar.attendee'},
# 'categories': {'field': 'categ_id', 'sub-field': 'name'},
# 'categories': {'field':None , 'sub-field': 'name', 'type': 'text'},
'comment': None,
'contact': None,
'exdate' : {'field': 'exdate', 'type': 'datetime'},
'exrule' : {'field': 'exrule', 'type': 'text'},
'rstatus': None,
'related': None,
'resources': None,
'rdate': None,
'rrule': {'field': 'rrule', 'type': 'text'},
'x-openobject-model': {'value': _name, 'type': 'text'},
# 'duration': {'field': 'duration'},
'dtend': {'field': 'date_closed', 'type': 'datetime'},
'valarm': {'field': 'caldav_alarm_id', 'type': 'many2one', 'object': 'calendar.alarm'},
}
def _get_attendee_data(self, cr, uid, ids, name, arg, context):
result = {}
for id in ids:
eventdata = self.browse(cr, uid, id, context=context)
if not eventdata.attendee_ids:
return result
att_data = map(lambda x: x.cn or '', eventdata.attendee_ids)
result[id] = ', '.join(att_data)
return result
def _set_attendee_data(self, cr, uid, id, name, value, arg, context):
if not value:
return
eventdata = self.browse(cr, uid, id, context=context)
att_len = len(eventdata.attendee_ids)
if att_len == len(value.split(',')):
return
if att_len > len(value.split(',')):
for attendee in eventdata.attendee_ids[len(value.split(',')):]:
self.write(cr, uid, id, {'attendee_ids': [(3, attendee.id)]})
return
attendee_obj = self.pool.get('calendar.attendee')
for val in value.split(',')[att_len:]:
attendee_id = attendee_obj.create(cr, uid, {'cn': val.strip()})
self.write(cr, uid, id, {'attendee_ids': [(4, attendee_id)]})
return
_columns = {
'inherit_case_id': fields.many2one('crm.case','Case',ondelete='cascade'),
'class' : fields.selection([('PUBLIC', 'PUBLIC'), ('PRIVATE', 'PRIVATE'), \
('CONFIDENTIAL', 'CONFIDENTIAL')], 'Privacy'),
'location' : fields.char('Location', size=264, help="Gives Location of Meeting"),
'freebusy' : fields.text('FreeBusy'),
'transparent' : fields.selection([('TRANSPARENT', 'TRANSPARENT'), \
('OPAQUE', 'OPAQUE')], 'Trensparent'),
'caldav_url' : fields.char('Caldav URL', size=264),
'exdate' : fields.text('Exception Date/Times', help="This property defines the list\
'inherit_case_id': fields.many2one('crm.case', 'Case', ondelete='cascade'),
'date_deadline': fields.datetime('Deadline', help="Deadline Date is automatically computed from Start Date + Duration"),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), \
('confidential', 'Confidential')], 'Privacy'),
'location': fields.char('Location', size=264, help="Gives Location of Meeting"),
'freebusy': fields.text('FreeBusy'),
'show_as': fields.selection([('free', 'Free'), \
('busy', 'Busy')],
'show_as'),
'caldav_url': fields.char('Caldav URL', size=264),
'exdate': fields.text('Exception Date/Times', help="This property defines the list\
of date/time exceptions for arecurring calendar component."),
'exrule' : fields.char('Exception Rule', size=352, help="defines a rule or repeating pattern\
'exrule': fields.char('Exception Rule', size=352, help="defines a rule or repeating pattern\
for anexception to a recurrence set"),
'rrule' : fields.char('Recurrent Rule', size=352),
'attendees': fields.many2many('crm.caldav.attendee', 'crm_attendee_rel', 'case_id', \
'rrule': fields.char('Recurrent Rule', size=352, invisible="True"),
'rrule_type' : fields.selection([('none', 'None'), ('daily', 'Daily'), \
('weekly', 'Weekly'), ('monthly', 'Monthly'), ('yearly', 'Yearly'), ('custom','Custom')], 'Recurrency'),
'attendees': fields.function(_get_attendee_data, method=True,\
fnct_inv=_set_attendee_data, string='Attendees', type="text"),
'alarm_id': fields.many2one('res.alarm', 'Alarm'),
'caldav_alarm_id': fields.many2one('calendar.alarm', 'Alarm'),
'attendee_ids': fields.many2many('calendar.attendee', 'crm_attendee_rel', 'case_id', \
'attendee_id', 'Attendees'),
'alarm_id' : fields.many2one('crm.caldav.alarm', 'Alarm'),
}
_defaults = {
'class': lambda *a: 'PUBLIC',
'transparent': lambda *a: 'OPAQUE',
_defaults = {
'class': lambda *a: 'public',
}
def do_alarm_create(self, cr, uid, ids, context={}):
alarm_obj = self.pool.get('calendar.alarm')
model_obj = self.pool.get('ir.model')
model_id = model_obj.search(cr, uid, [('model','=',self._name)])[0]
for meeting in self.browse(cr, uid, ids):
self.do_alarm_unlink(cr, uid, [meeting.id])
basic_alarm = meeting.alarm_id
if basic_alarm and meeting.state in ('open'):
vals = {
'action': 'display',
'description': meeting.description,
'name': meeting.name,
'attendee_ids': [(6,0, map(lambda x:x.id, meeting.attendee_ids))],
'trigger_related': basic_alarm.trigger_related,
'trigger_duration': basic_alarm.trigger_duration,
'trigger_occurs': basic_alarm.trigger_occurs,
'trigger_interval': basic_alarm.trigger_interval,
'duration': basic_alarm.duration,
'repeat': basic_alarm.repeat,
'state' : 'run',
'event_date' : meeting.date,
'res_id' : meeting.id,
'model_id' : model_id,
'user_id' : uid
}
alarm_id = alarm_obj.create(cr, uid, vals)
cr.execute('Update crm_meeting set caldav_alarm_id=%s where id=%s' % (alarm_id, meeting.id))
cr.commit()
return True
def run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \
context=None):
if not context:
context = {}
cr.execute('select c.id as id, crm_case.date as date, alarm.id as alarm_id, alarm.name as name,\
alarm.trigger_interval, alarm.trigger_duration, alarm.trigger_related, \
alarm.trigger_occurs from crm_meeting c \
join crm_case on c.inherit_case_id = crm_case.id \
join crm_caldav_alarm alarm on (alarm.id=c.alarm_id) \
where alarm_id is not null and alarm.active=True')
case_with_alarm = cr.dictfetchall()
case_obj = self.pool.get('crm.meeting')
attendee_obj = self.pool.get('crm.caldav.attendee')
mail_to = []
for alarmdata in case_with_alarm:
dtstart = datetime.datetime.strptime(alarmdata['date'], "%Y-%m-%d %H:%M:%S")
if alarmdata['trigger_interval'] == 'DAYS':
delta = datetime.timedelta(days=alarmdata['trigger_duration'])
if alarmdata['trigger_interval'] == 'HOURS':
delta = datetime.timedelta(hours=alarmdata['trigger_duration'])
if alarmdata['trigger_interval'] == 'MINUTES':
delta = datetime.timedelta(minutes=alarmdata['trigger_duration'])
alarm_time = dtstart + (alarmdata['trigger_occurs']== 'AFTER' and delta or -delta)
if datetime.datetime.now() >= alarm_time:
case_val = case_obj.browse(cr, uid, alarmdata.get('id'), context)[0]
for att in case_val.attendees:
if att.cn.rsplit(':')[-1]:
mail_to.append(att.cn.rsplit(':')[-1])
if mail_to:
sub = 'Event Reminder for ' + case_val.name or ''
body = (case_val.name or '')+ '\n\t' + (case_val.description or '') + '\n\nEvent time: ' \
+(case_val.date) + '\n\nLocation: ' + (case_val.location or '') + \
'\n\nMembers Details: ' + '\n'.join(mail_to)
tools.email_send(
case_val.user_id.address_id.email,
mail_to,
sub,
body
)
cr.execute('update crm_caldav_alarm set active=False\
where id = %s' % alarmdata['alarm_id'])
cr.commit()
def do_alarm_unlink(self, cr, uid, ids, context={}):
alarm_obj = self.pool.get('calendar.alarm')
model_obj = self.pool.get('ir.model')
model_id = model_obj.search(cr, uid, [('model','=',self._name)])[0]
for meeting in self.browse(cr, uid, ids):
alarm_ids = alarm_obj.search(cr, uid, [('model_id','=',model_id), ('res_id','=',meeting.id)])
if alarm_ids and len(alarm_ids):
alarm_obj.unlink(cr, uid, alarm_ids)
cr.execute('Update crm_meeting set caldav_alarm_id=NULL where id=%s' % (meeting.id))
cr.commit()
return True
def on_change_duration(self, cr, uid, id, date, duration):
if not date:
return {}
start_date = datetime.datetime.fromtimestamp(time.mktime(time.strptime(date, "%Y-%m-%d %H:%M:%S")))
if duration >= 0 :
end = start_date + datetime.timedelta(hours=duration)
if duration < 0:
raise osv.except_osv(_('Warning !'),
_('You can not set negative Duration.'))
res = {'value' : {'date_deadline' : end.strftime('%Y-%m-%d %H:%M:%S')}}
return res
def export_cal(self, cr, uid, ids, context={}):
crm_data = self.read(cr, uid, ids, [], context ={'read' :True})
event_obj = self.pool.get('caldav.event')
crm_data = self.read(cr, uid, ids, [], context ={'read':True})
event_obj = self.pool.get('basic.calendar.event')
event_obj.__attribute__.update(self.__attribute__)
attendee_obj = self.pool.get('caldav.attendee')
crm_attendee = self.pool.get('crm.caldav.attendee')
attendee_obj = self.pool.get('basic.calendar.attendee')
crm_attendee = self.pool.get('calendar.attendee')
attendee_obj.__attribute__.update(crm_attendee.__attribute__)
alarm_obj = self.pool.get('caldav.alarm')
crm_alarm = self.pool.get('crm.caldav.alarm')
alarm_obj = self.pool.get('basic.calendar.alarm')
crm_alarm = self.pool.get('calendar.alarm')
alarm_obj.__attribute__.update(crm_alarm.__attribute__)
ical = event_obj.export_ical(cr, uid, crm_data, {'model': 'crm.meeting'})
caendar_val = ical.serialize()
caendar_val = caendar_val.replace('"', '').strip()
@@ -160,36 +205,107 @@ class crm_meeting(osv.osv):
def import_cal(self, cr, uid, data, context={}):
file_content = base64.decodestring(data)
event_obj = self.pool.get('caldav.event')
event_obj = self.pool.get('basic.calendar.event')
event_obj.__attribute__.update(self.__attribute__)
attendee_obj = self.pool.get('caldav.attendee')
crm_attendee = self.pool.get('crm.caldav.attendee')
attendee_obj = self.pool.get('basic.calendar.attendee')
crm_attendee = self.pool.get('calendar.attendee')
attendee_obj.__attribute__.update(crm_attendee.__attribute__)
alarm_obj = self.pool.get('caldav.alarm')
crm_alarm = self.pool.get('crm.caldav.alarm')
alarm_obj = self.pool.get('basic.calendar.alarm')
crm_alarm = self.pool.get('calendar.alarm')
alarm_obj.__attribute__.update(crm_alarm.__attribute__)
vals = event_obj.import_ical(cr, uid, file_content)
for val in vals:
section_id = self.pool.get('crm.case.section').search(cr, uid, \
[('name', 'like', 'Meeting%')])[0]
val.update({'section_id' : section_id})
is_exists = common.uid2openobjectid(cr, val['id'], self._name )
for val in vals:
is_exists = common.uid2openobjectid(cr, val['id'], self._name)
val.pop('id')
if val.has_key('create_date'): val.pop('create_date')
val['caldav_url'] = context.get('url') or ''
caldav_alarm_id = val['caldav_alarm_id']
if caldav_alarm_id:
caldav_alarm = self.browse(cr, uid, caldav_alarm_id)
val['alarm_id'] = caldav_alarm.alarm_id
if is_exists:
self.write(cr, uid, [is_exists], val)
else:
case_id = self.create(cr, uid, val)
return {'count': len(vals)}
def search(self, cr, uid, args, offset=0, limit=None, order=None,
def get_recurrent_ids(self, cr, uid, ids, start_date, until_date, limit=100):
if not limit:
limit = 100
if ids and (start_date or until_date):
cr.execute("select m.id, m.rrule, c.date, m.exdate from crm_meeting m\
join crm_case c on (c.id=m.inherit_case_id) \
where m.id in ("+ ','.join(map(lambda x: str(x), ids))+")")
result = []
count = 0
start_date = start_date and datetime.datetime.strptime(start_date, "%Y-%m-%d") or False
until_date = until_date and datetime.datetime.strptime(until_date, "%Y-%m-%d") or False
for data in cr.dictfetchall():
if count > limit:
break
event_date = datetime.datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
if start_date and start_date <= event_date:
start_date = event_date
if not data['rrule']:
idval = common.real_id2caldav_id(data['id'], data['date'])
result.append(idval)
count += 1
else:
exdate = data['exdate'] and data['exdate'].split(',') or []
event_obj = self.pool.get('basic.calendar.event')
rrule_str = data['rrule']
new_rrule_str = []
rrule_until_date = False
is_until = False
for rule in rrule_str.split(';'):
name, value = rule.split('=')
if name == "UNTIL":
is_until = True
value = parser.parse(value)
rrule_until_date = parser.parse(value.strftime("%Y-%m-%d"))
if until_date and until_date >= rrule_until_date:
until_date = rrule_until_date
if until_date:
until_date = until_date.strftime("%Y%m%d%H%M%S")
value = until_date
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
if not is_until and until_date:
until_date = until_date.strftime("%Y%m%d%H%M%S")
value = until_date
name = "UNTIL"
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
new_rrule_str = ';'.join(new_rrule_str)
start_date = datetime.datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
rdates = event_obj.get_recurrent_dates(str(new_rrule_str), exdate, start_date)
for rdate in rdates:
idval = common.real_id2caldav_id(data['id'], rdate)
result.append(idval)
count += 1
ids = result
return ids
def search(self, cr, uid, args, offset=0, limit=100, order=None,
context=None, count=False):
res = super(crm_meeting, self).search(cr, uid, args, offset,
args_without_date = []
start_date = False
until_date = False
for arg in args:
if arg[0] not in ('date', unicode('date')):
args_without_date.append(arg)
else:
if arg[1] in ('>', '>='):
start_date = arg[2]
elif arg[1] in ('<', '<='):
until_date = arg[2]
res = super(crm_meeting, self).search(cr, uid, args_without_date, offset,
limit, order, context, count)
return res
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
if isinstance(ids, (str, int, long)):
@@ -198,152 +314,150 @@ class crm_meeting(osv.osv):
select = ids
new_ids = []
for id in select:
id = common.caldevIDs2readIDs(id)
id = common.caldav_id2real_id(id)
if not id in new_ids:
new_ids.append(id)
if 'case_id' in vals :
vals['case_id'] = common.caldevIDs2readIDs(vals['case_id'])
if 'case_id' in vals:
vals['case_id'] = common.caldav_id2real_id(vals['case_id'])
res = super(crm_meeting, self).write(cr, uid, new_ids, vals, context=context)
self.do_alarm_create(cr, uid, ids)
return res
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process={}):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = map(lambda x:common.caldevIDs2readIDs(x), select)
res = super(crm_meeting, self).browse(cr, uid, select, context, list_class, fields_process)
select = ids
select = map(lambda x: common.caldav_id2real_id(x), select)
res = super(crm_meeting, self).browse(cr, uid, select, context, list_class, fields_process)
if isinstance(ids, (str, int, long)):
return res and res[0] or False
return res
def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'):
""" logic for recurrent event
example : 123-20091111170822"""
if context and context.has_key('read'):
return super(crm_meeting, self).read(cr, uid, ids, fields=fields, context=context, \
load=load)
if not type(ids) == list :
# Called from code
return super(crm_meeting, self).read(cr, uid, common.caldevIDs2readIDs(ids), \
fields=fields, context=context, load=load)
def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
ids = map(lambda x:common.caldevIDs2readIDs(x), ids)
select = ids
select = map(lambda x: (x, common.caldav_id2real_id(x)), select)
result = []
if fields and 'date' not in fields:
fields.append('date')
if not ids:
return []
result = []
for read_id in ids:
res = super(crm_meeting, self).read(cr, uid, read_id, fields=fields, context=context, load=load)
cr.execute("""select m.id, m.rrule, c.date, m.exdate from crm_meeting m\
join crm_case c on (c.id=m.inherit_case_id) \
where m.id = %s""" % read_id)
data = cr.dictfetchall()[0]
if not data['rrule']:
strdate = ''.join((re.compile('\d')).findall(data['date']))
idval = str(common.caldevIDs2readIDs(data['id'])) + '-' + strdate
data['id'] = idval
res.update(data)
result.append(res)
else:
exdate = data['exdate'] and data['exdate'].split(',') or []
event_obj = self.pool.get('caldav.event')
rdates = event_obj.get_recurrent_dates(str(data['rrule']), exdate, data['date'])[:10]
for rdate in rdates:
val = res.copy()
idval = (re.compile('\d')).findall(rdate)
val['date'] = rdate
id = str(res['id']).split('-')[0]
val['id'] = id + '-' + ''.join(idval)
val1 = val.copy()
result.append(val1)
for caldav_id, real_id in select:
res = super(crm_meeting, self).read(cr, uid, real_id, fields=fields, context=context, \
load=load)
ls = common.caldav_id2real_id(caldav_id, with_date=True)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
res['date'] = ls[1]
res['id'] = caldav_id
result.append(res)
if isinstance(ids, (str, int, long)):
return result and result[0] or False
return result
def copy(self, cr, uid, id, default=None, context={}):
return super(crm_meeting, self).copy(cr, uid, common.caldevIDs2readIDs(id), \
def copy(self, cr, uid, id, default=None, context={}):
res = super(crm_meeting, self).copy(cr, uid, common.caldav_id2real_id(id), \
default, context)
self.do_alarm_create(cr, uid, [res])
return res
def unlink(self, cr, uid, ids, context=None):
res = False
for id in ids:
if len(str(id).split('-')) > 1:
date_new = time.strftime("%Y-%m-%d %H:%M:%S", \
time.strptime(str(str(id).split('-')[1]), "%Y%m%d%H%M%S"))
for record in self.read(cr, uid, [common.caldevIDs2readIDs(id)], \
ls = common.caldav_id2real_id(id)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
date_new = ls[1]
for record in self.read(cr, uid, [common.caldav_id2real_id(id)], \
['date', 'rrule', 'exdate']):
if record['rrule']:
exdate = (record['exdate'] and (record['exdate'] + ',' ) or '') + \
exdate = (record['exdate'] and (record['exdate'] + ',') or '') + \
''.join((re.compile('\d')).findall(date_new)) + 'Z'
if record['date'] == date_new:
self.write(cr, uid, [common.caldevIDs2readIDs(id)], {'exdate' : exdate})
res = self.write(cr, uid, [common.caldav_id2real_id(id)], {'exdate': exdate})
else:
ids = map(lambda x:common.caldevIDs2readIDs(x), ids)
return super(crm_meeting, self).unlink(cr, uid, common.caldevIDs2readIDs(ids))
ids = map(lambda x: common.caldav_id2real_id(x), ids)
res = super(crm_meeting, self).unlink(cr, uid, common.caldav_id2real_id(ids))
self.do_alarm_unlink(cr, uid, ids)
else:
return super(crm_meeting, self).unlink(cr, uid, ids)
res = super(crm_meeting, self).unlink(cr, uid, ids)
self.do_alarm_unlink(cr, uid, ids)
return res
def create(self, cr, uid, vals, context={}):
if 'case_id' in vals:
vals['case_id'] = common.caldevIDs2readIDs(vals['case_id'])
return super(crm_meeting, self).create(cr, uid, vals, context)
vals['case_id'] = common.caldav_id2real_id(vals['case_id'])
res = super(crm_meeting, self).create(cr, uid, vals, context)
self.do_alarm_create(cr, uid, [res])
return res
def _map_ids(self, method, cr, uid, ids, *args, **argv):
if isinstance(ids, (str, int, long)):
select = [ids]
else:
select = ids
select = ids
case_data = self.browse(cr, uid, select)
new_ids = []
for case in case_data:
if case.inherit_case_id:
new_ids.append(case.inherit_case_id.id)
res = getattr(self.pool.get('crm.case'),method)(cr, uid, new_ids, *args, **argv)
res = getattr(self.pool.get('crm.case'), method)(cr, uid, new_ids, *args, **argv)
if isinstance(ids, (str, int, long)) and isinstance(res, list):
return res and res[0] or False
return res
def onchange_rrule_type(self, cr, uid, ids, type, *args, **argv):
if type == 'none':
return {'value': {'rrule': ''}}
if type == 'custom':
return {}
rrule = self.pool.get('caldav.set.rrule')
rrulestr = rrule.compute_rule_string(cr, uid, {'freq': type.upper(),\
'interval': 1})
return {'value': {'rrule': rrulestr}}
def onchange_case_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_case_id',cr,uid,ids,*args,**argv)
return self._map_ids('onchange_case_id', cr, uid, ids, *args, **argv)
def onchange_partner_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_partner_id',cr,uid,ids,*args,**argv)
return self._map_ids('onchange_partner_id', cr, uid, ids, *args, **argv)
def onchange_partner_address_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_partner_address_id',cr,uid,ids,*args,**argv)
return self._map_ids('onchange_partner_address_id', cr, uid, ids, *args, **argv)
def onchange_categ_id(self, cr, uid, ids, *args, **argv):
return self._map_ids('onchange_categ_id',cr,uid,ids,*args,**argv)
def case_close(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_close',cr,uid,ids,*args,**argv)
def case_open(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_open',cr,uid,ids,*args,**argv)
def case_cancel(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel',cr,uid,ids,*args,**argv)
def case_reset(self,cr, uid, ids, *args, **argv):
return self._map_ids('case_reset',cr,uid,ids,*args,**argv)
return self._map_ids('onchange_categ_id', cr, uid, ids, *args, **argv)
def case_close(self, cr, uid, ids, *args, **argv):
return self._map_ids('case_close', cr, uid, ids, *args, **argv)
def case_open(self, cr, uid, ids, *args, **argv):
return self._map_ids('case_open', cr, uid, ids, *args, **argv)
def case_cancel(self, cr, uid, ids, *args, **argv):
return self._map_ids('case_cancel', cr, uid, ids, *args, **argv)
def case_reset(self, cr, uid, ids, *args, **argv):
return self._map_ids('case_reset', cr, uid, ids, *args, **argv)
def msg_new(self, cr, uid, msg):
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
'name': msg['Subject'],
'email_from': msg['From'],
'email_cc': msg['Cc'],
'user_id': False,
'description': msg_body['body'],
'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })],
}
res = mailgate_obj.partner_get(cr, uid, msg['From'])
if res:
data.update(res)
res = self.create(cr, uid, data)
res = self.create(cr, uid, data)
return res
def msg_update(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_update',cr, uid, ids, *args, **argv)
return self._map_ids('msg_update', cr, uid, ids, *args, **argv)
def emails_get(self, cr, uid, ids, *args, **argv):
return self._map_ids('emails_get',cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send',cr, uid, ids, *args, **argv)
return self._map_ids('emails_get', cr, uid, ids, *args, **argv)
def msg_send(self, cr, uid, ids, *args, **argv):
return self._map_ids('msg_send', cr, uid, ids, *args, **argv)
crm_meeting()
@@ -352,16 +466,16 @@ class crm_meeting_generic_wizard(osv.osv_memory):
_name = 'crm.meeting.generic_wizard'
_columns = {
'section_id': fields.many2one('crm.case.section', 'Section', required=True),
'user_id': fields.many2one('res.users', 'Responsible'),
'section_id': fields.many2one('crm.case.section', 'Section', required=True),
'user_id': fields.many2one('res.users', 'Responsible'),
}
def _get_default_section(self, cr, uid, context):
case_id = context.get('active_id',False)
case_id = context.get('active_id', False)
if not case_id:
return False
case_obj = self.pool.get('crm.meeting')
case = case_obj.read(cr, uid, case_id, ['state','section_id'])
case = case_obj.read(cr, uid, case_id, ['state', 'section_id'])
if case['state'] in ('done'):
raise osv.except_osv(_('Error !'), _('You can not assign Closed Case.'))
return case['section_id']
@@ -372,32 +486,91 @@ class crm_meeting_generic_wizard(osv.osv_memory):
}
def action_create(self, cr, uid, ids, context=None):
case_obj = self.pool.get('crm.meeting')
case_id = context.get('active_id',[])
case_id = context.get('active_id', [])
res = self.read(cr, uid, ids)[0]
case = case_obj.browse(cr, uid, case_id)
if case.state in ('done'):
raise osv.except_osv(_('Error !'), _('You can not assign Closed Case.'))
new_case_id = case_obj.copy(cr, uid, case_id, default=
{
'section_id':res.get('section_id',False),
'user_id':res.get('user_id',False),
'case_id' : case.inherit_case_id.id
}, context=context)
'section_id': res.get('section_id', False),
'user_id': res.get('user_id', False),
'case_id': case.inherit_case_id.id
}, context=context)
case_obj.case_close(cr, uid, [case_id])
data_obj = self.pool.get('ir.model.data')
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter')
search_view = data_obj.read(cr, uid, result, ['res_id'])
new_case = case_obj.read(cr, uid, new_case_id, ['id'])
value = {
'name': _('Meetings'),
'view_type': 'form',
'view_mode': 'calendar, tree, form',
'res_model': 'crm.meeting',
'type': 'ir.actions.act_window',
new_case = case_obj.read(cr, uid, new_case_id, ['id'])
value = {
'name': _('Meetings'),
'view_type': 'form',
'view_mode': 'calendar, tree, form',
'res_model': 'crm.meeting',
'type': 'ir.actions.act_window',
'search_view_id': search_view['res_id']
}
return value
crm_meeting_generic_wizard()
class res_users(osv.osv):
_inherit = 'res.users'
def _get_user_avail(self, cr, uid, ids, name, args, context=None):
res={}
if not context or not context.get('model'):
return {}
else:
model = context.get('model')
obj = self.pool.get(model)
event_obj = obj.browse(cr, uid, context['active_id'])
event_start = event_obj.date
event_end = datetime.datetime.strptime(event_obj.date, "%Y-%m-%d %H:%M:%S") \
+ datetime.timedelta(hours=event_obj.duration)
for id in ids:
datas = self.browse(cr, uid, id)
cr.execute("""SELECT c.date as start, (c.date::timestamp \
+ c.duration * interval '1 hour') as end \
from crm_meeting m \
join crm_case c on (c.id=m.inherit_case_id)\
where c.user_id = %s
and m.id not in (""" % (datas['id']) + str(context['active_id']) +")")
dates = cr.dictfetchall()
overlaps = False
# check event time
for date in dates:
start = date['start']
end = date['end']
cr.execute("SELECT (timestamp '%s', timestamp '%s') OVERLAPS\
(timestamp '%s', timestamp '%s')" % (event_start, event_end, start, end))
over = cr.fetchone()[0]
if over:
overlaps = True
# check for attendee added already
cr.execute("""select att.user_id , c.id
from calendar_attendee att
inner join crm_attendee_rel rel on (rel.attendee_id=att.id)
join crm_meeting m on (rel.case_id=m.id)
join crm_case c on (m.inherit_case_id = c.id )
where (c.date, c.date::timestamp + c.duration * interval '1 hour') overlaps\
(timestamp '%s', timestamp '%s')""" % (event_start, event_end))
added_data = filter(lambda x: x.get('user_id')==id, cr.dictfetchall())
if added_data:
overlaps = True
if overlaps:
res[id] = 'busy'
else:
res[id] = 'free'
return res
_columns = {
'availability': fields.function(_get_user_avail, type='selection', \
selection=[('free', 'Free'), ('busy', 'Busy')], \
string='Free/Busy', method=True),
}
res_users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+5 -14
View File
@@ -58,21 +58,12 @@
<record model="crm.case.stage" id="stage_meet5">
<field name="name">Future</field>
<field name="section_id" ref="section_support1"/>
</record>
<record model="res.request.link" id="request_link_meeting">
<field name="name">Case Meeting</field>
<field name="object">crm.meeting</field>
</record>
<!-- Scheduler for Event Alarm-->
<record forcecreate="True" id="ir_cron_scheduler_alarm"
model="ir.cron">
<field name="name">Run Event Reminder</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field eval="'crm.meeting'" name="model" />
<field eval="'run_scheduler'" name="function" />
<field eval="'(False,)'" name="args" />
</record>
</data>
</openerp>
+4 -1
View File
@@ -86,7 +86,6 @@
<field name="view_id" ref="crm_case_calendar_view_meet"/>
<field name="context" eval="{'default_state':'open'}"/>
<field name="search_view_id" ref="view_crm_case_meetings_filter"/>
<field name="domain" eval="[('section_id.calendar','=',1)]"/>
</record>
<record model="ir.actions.act_window.view" id="action_crm_tag_calendar_meet">
<field name="sequence" eval="1"/>
@@ -113,6 +112,10 @@
<field name="act_window_id" ref="crm_case_categ_meet"/>
</record>
<menuitem parent="crm.menu_crm" name="Calendar" id="menu_crm_case_category_act_meetings"/>
<menuitem parent="crm.menu_crm_case_category_act_meetings"
name="My Invitations" id="menu_crm_meetings_invitation"
action="caldav.action_view_attendee_form" />
<!--
ALL MEETINGS
+75 -38
View File
@@ -33,47 +33,70 @@
<field name="target">new</field>
</record>
<record model="ir.ui.view" id="crm_case_form_view_meet">
<record model="ir.ui.view" id="view_users_form_crm">
<field name="name">caldav.res.users.form</field>
<field name="type">form</field>
<field name="priority">10</field>
<field name="model">res.users</field>
<field name="arch" type="xml">
<form string="User">
<field name="name" />
<field name="availability" />
</form>
</field>
</record>
<record model="ir.ui.view" id="view_users_tree_crm">
<field name="name">caldav.res.users.tree</field>
<field name="type">tree</field>
<field name="priority">10</field>
<field name="model">res.users</field>
<field name="arch" type="xml">
<tree string="Userss">
<field name="name" />
<field name="availability" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="crm_case_form_view_meet">
<field name="name">CRM - Meetings Form</field>
<field name="model">crm.meeting</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Meetings Form">
<field name="name" select="1" string="Title"/>
<field name="section_id" widget="selection"
string="Calendar" domain="[('calendar','=',True)]"/>
<field name="location" />
<field name="categ_id" select="2" on_change="onchange_categ_id(categ_id)"/>
<group colspan="4" col="6">
<field name="name" select="1" string="Title"/>
<field name="section_id" widget="selection"
string="Calendar" domain="[('calendar','=',True)]"/>
<field name="user_id" select="2" string="Responsible" required="1"/>
<newline/>
<field name="date" string="Meeting Date" required="1"/>
<field name="duration" colspan="1" widget="float_time" required="1"/>
<group colspan="2">
<field name="case_id" on_change="onchange_case_id(case_id, name, partner_id)"/>
<button string="Assign" name="%(crm_meeting_generic_wizard_act)d" type="action" />
</group>
<field name="date" string="Start Date" on_change="on_change_duration(date, duration)" required="1"/>
<field name="duration" string="Duration(In Hour)" on_change="on_change_duration(date, duration)" widget="float_time"/>
<field name="date_deadline" string="End Date" required="1"/>
</group>
<notebook colspan="4">
<page string="Meeting">
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)" />
<field name="partner_address_id" on_change="onchange_partner_address_id(partner_address_id, email_from)"/>
<field name="email_from"/>
<newline/>
<field name="categ_id" select="2" on_change="onchange_categ_id(categ_id)"/>
<field name="location" />
<field name="alarm_id" colspan="4" string="Reminder"/>
<group colspan="4">
<field name="rrule" string="Recurrency Rule"/>
<button string="Change RRule"
<page string="Meeting">
<field name="alarm_id" colspan="1" string="Alarm"/>
<group colspan="2" col="3">
<field name="rrule_type" string="Recurrency"
on_change="onchange_rrule_type(rrule_type)"
colspan="1" />
<button string="Custom"
name="%(caldav.action_view_caldav_set_rrule_wizard)d"
icon="gtk-save-as" type="action" context="{'model' : 'crm.meeting'}"/>
icon="gtk-save-as" type="action" context="{'model' : 'crm.meeting'}"
attrs="{'readonly':[('rrule_type','!=','custom')]}"
/>
</group>
<separator string="Description" colspan="4"/>
<field name="description" nolabel="1" colspan="4"/>
<separator colspan="4"/>
<field name="class"/>
<field name="transparent"/>
<separator colspan="4"/>
<separator string="Description" colspan="4"/>
<field name="description" nolabel="1" colspan="4"/>
<separator string="Attendees" colspan="4"/>
<field name="attendees" nolabel="1" colspan="4"/>
<field name="show_as" string="Show as"/>
<field name="class" string="Mark as"/>
<separator string="" colspan="4"/>
<group col="8" colspan="4">
<field name="state" select="2"/>
<button name="case_open" string="Confirm Meeting" states="draft,cancel,pending" type="object" icon="terp-crm"/>
@@ -82,15 +105,29 @@
</group>
</page>
<page string="Attendee Detail">
<separator string="Attendee" colspan="4"/>
<field name="attendees" colspan="4" nolabel="1"/>
</page>
<separator string="Attendees" colspan="4"/>
<field name="attendee_ids" colspan="4" nolabel="1"/>
<button string="Invite Attendees"
name="%(caldav.action_view_calendar_invite_attendee_wizard)d"
icon="terp-partner" type="action"
context="{'model' : 'crm.meeting'}" />
</page>
<page string="Partner Info">
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)" />
<field name="partner_address_id" on_change="onchange_partner_address_id(partner_address_id, email_from)"/>
<field name="email_from"/>
</page>
<page string="Other Info">
<field name="caldav_url" widget="url" readonly="True"/>
<newline/>
<field name="user_id" select="2" string="Responsible" required="1"/>
<group colspan="2">
<field name="case_id" on_change="onchange_case_id(case_id, name, partner_id)"/>
<button string="Assign" name="%(crm_meeting_generic_wizard_act)d" type="action" />
</group>
<field name="rrule" string="Recurrent Rules" colspan="4"/>
<field name="exrule" string="Exception Rules" colspan="4"/>
<separator string="Exception Dates" colspan="4"/>
<field name="exdate" nolabel="1" colspan="4" />
<field name="exdate" nolabel="1" colspan="4" />
</page>
</notebook>
</form>
@@ -123,10 +160,10 @@
<field name="type">calendar</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Meetings" date_start="date" color="user_id" date_delay="duration">
<calendar string="Meetings" date_start="date" color="section_id" date_delay="duration">
<field name="name"/>
<field name="partner_id"/>
<field name="section_id" widget="selection"/>
<field name="user_id" widget="selection"/>
</calendar>
</field>
</record>
+3253 -1025
View File
File diff suppressed because it is too large Load Diff
+3256 -1028
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-02-03 09:18+0000\n"
"POT-Creation-Date: 2010-01-05 16:01+0000\n"
"PO-Revision-Date: 2010-01-05 09:18+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
+3485 -1154
View File
File diff suppressed because it is too large Load Diff
+3324 -953
View File
File diff suppressed because it is too large Load Diff
+3267 -1033
View File
File diff suppressed because it is too large Load Diff
+3532 -1202
View File
File diff suppressed because it is too large Load Diff
+3472 -1193
View File
File diff suppressed because it is too large Load Diff
+3485 -1156
View File
File diff suppressed because it is too large Load Diff
+3458 -1181
View File
File diff suppressed because it is too large Load Diff
+3439 -1135
View File
File diff suppressed because it is too large Load Diff
+3321 -1030
View File
File diff suppressed because it is too large Load Diff
+3704 -1136
View File
File diff suppressed because it is too large Load Diff
+3459 -1196
View File
File diff suppressed because it is too large Load Diff
+3253 -1025
View File
File diff suppressed because it is too large Load Diff
+3255 -1027
View File
File diff suppressed because it is too large Load Diff
+3253 -1025
View File
File diff suppressed because it is too large Load Diff
+3484 -1156
View File
File diff suppressed because it is too large Load Diff
+3253 -1025
View File
File diff suppressed because it is too large Load Diff
+3441 -1175
View File
File diff suppressed because it is too large Load Diff
+3512 -1105
View File
File diff suppressed because it is too large Load Diff
+3253 -1025
View File
File diff suppressed because it is too large Load Diff
+3490 -1155
View File
File diff suppressed because it is too large Load Diff
+3254 -1026
View File
File diff suppressed because it is too large Load Diff
+3381 -1099
View File
File diff suppressed because it is too large Load Diff
+3449 -1131
View File
File diff suppressed because it is too large Load Diff
+3481 -1152
View File
File diff suppressed because it is too large Load Diff
+3267 -1039
View File
File diff suppressed because it is too large Load Diff

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