[MERGE] Sync with trunk

bzr revid: tde@openerp.com-20130805132618-ewjjxjfwnkeg8hue
This commit is contained in:
Thibault Delavallée 2013-08-05 15:26:18 +02:00
commit dce673c6b5
47 changed files with 1678 additions and 816 deletions

View File

@ -8,19 +8,19 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-04-13 22:35+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2013-07-30 22:25+0000\n"
"Last-Translator: Masaki Yamaya <Unknown>\n"
"Language-Team: Japanese <ja@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:47+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-07-31 05:16+0000\n"
"X-Generator: Launchpad (build 16718)\n"
#. module: account_accountant
#: model:ir.actions.client,name:account_accountant.action_client_account_menu
msgid "Open Accounting Menu"
msgstr ""
msgstr "会計メニューを開く"
#~ msgid ""
#~ "\n"

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-05-15 10:09+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2013-07-24 08:53+0000\n"
"Last-Translator: Sumonchai ( เหลา ) <sumonchai@gmail.com>\n"
"Language-Team: Thai <th@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-05-16 05:12+0000\n"
"X-Generator: Launchpad (build 16626)\n"
"X-Launchpad-Export-Date: 2013-07-25 05:13+0000\n"
"X-Generator: Launchpad (build 16700)\n"
#. module: account_asset
#: view:account.asset.asset:0
@ -42,7 +42,7 @@ msgstr ""
#. module: account_asset
#: view:asset.asset.report:0
msgid "Group By..."
msgstr ""
msgstr "จัดกลุ่มตาม..."
#. module: account_asset
#: field:asset.asset.report,gross_value:0
@ -58,7 +58,7 @@ msgstr ""
#: field:asset.asset.report,asset_id:0
#: model:ir.model,name:account_asset.model_account_asset_asset
msgid "Asset"
msgstr ""
msgstr "สินทรัพย์"
#. module: account_asset
#: help:account.asset.asset,prorata:0
@ -72,7 +72,7 @@ msgstr ""
#: selection:account.asset.asset,method:0
#: selection:account.asset.category,method:0
msgid "Linear"
msgstr ""
msgstr "เชิงเส้น"
#. module: account_asset
#: field:account.asset.asset,company_id:0
@ -80,24 +80,24 @@ msgstr ""
#: view:asset.asset.report:0
#: field:asset.asset.report,company_id:0
msgid "Company"
msgstr ""
msgstr "บริษัท"
#. module: account_asset
#: view:asset.modify:0
msgid "Modify"
msgstr ""
msgstr "ปรับเปลี่ยน"
#. module: account_asset
#: selection:account.asset.asset,state:0
#: view:asset.asset.report:0
#: selection:asset.asset.report,state:0
msgid "Running"
msgstr ""
msgstr "กำลังทำงานอยู่"
#. module: account_asset
#: view:account.asset.asset:0
msgid "Set to Draft"
msgstr ""
msgstr "กำหนดให้เป็นแบบร่าง"
#. module: account_asset
#: view:asset.asset.report:0
@ -110,7 +110,7 @@ msgstr ""
#. module: account_asset
#: field:asset.modify,name:0
msgid "Reason"
msgstr ""
msgstr "เหตุผล"
#. module: account_asset
#: field:account.asset.asset,method_progress_factor:0
@ -122,7 +122,7 @@ msgstr ""
#: model:ir.actions.act_window,name:account_asset.action_account_asset_asset_list_normal
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_asset_list_normal
msgid "Asset Categories"
msgstr ""
msgstr "หมวดหมู่สินทรัพย์"
#. module: account_asset
#: view:account.asset.asset:0
@ -173,7 +173,7 @@ msgstr ""
#: model:ir.ui.menu,name:account_asset.menu_finance_assets
#: model:ir.ui.menu,name:account_asset.menu_finance_config_assets
msgid "Assets"
msgstr ""
msgstr "สินทรัพย์"
#. module: account_asset
#: field:account.asset.category,account_depreciation_id:0
@ -187,7 +187,7 @@ msgstr ""
#: view:asset.modify:0
#: field:asset.modify,note:0
msgid "Notes"
msgstr ""
msgstr "บันทึกย่อ"
#. module: account_asset
#: field:account.asset.depreciation.line,move_id:0
@ -221,7 +221,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.asset,code:0
msgid "Reference"
msgstr ""
msgstr "อ้างถึง"
#. module: account_asset
#: view:account.asset.asset:0
@ -246,7 +246,7 @@ msgstr ""
#: view:asset.asset.report:0
#: selection:asset.asset.report,state:0
msgid "Draft"
msgstr ""
msgstr "ฉบับร่าง"
#. module: account_asset
#: view:asset.asset.report:0
@ -273,13 +273,13 @@ msgstr ""
#. module: account_asset
#: field:account.asset.category,account_analytic_id:0
msgid "Analytic account"
msgstr ""
msgstr "วิเคราะห์บัญชี"
#. module: account_asset
#: field:account.asset.asset,method:0
#: field:account.asset.category,method:0
msgid "Computation Method"
msgstr ""
msgstr "วิธีการคำนวณ"
#. module: account_asset
#: constraint:account.asset.asset:0
@ -308,7 +308,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.asset,salvage_value:0
msgid "Salvage Value"
msgstr ""
msgstr "มูลค่าซาก"
#. module: account_asset
#: field:account.asset.asset,category_id:0
@ -364,20 +364,20 @@ msgstr ""
#: field:account.asset.category,method_time:0
#: field:account.asset.history,method_time:0
msgid "Time Method"
msgstr ""
msgstr "วิธีการจัดการเวลา"
#. module: account_asset
#: view:asset.depreciation.confirmation.wizard:0
#: view:asset.modify:0
msgid "or"
msgstr ""
msgstr "หรือ"
#. module: account_asset
#: field:account.asset.asset,note:0
#: field:account.asset.category,note:0
#: field:account.asset.history,note:0
msgid "Note"
msgstr ""
msgstr "บันทึกย่อ"
#. module: account_asset
#: help:account.asset.history,method_time:0
@ -409,7 +409,7 @@ msgstr ""
#. module: account_asset
#: view:account.asset.asset:0
msgid "Closed"
msgstr ""
msgstr "ปิด"
#. module: account_asset
#: help:account.asset.asset,state:0
@ -425,13 +425,13 @@ msgstr ""
#: field:account.asset.asset,state:0
#: field:asset.asset.report,state:0
msgid "Status"
msgstr ""
msgstr "สถานะ"
#. module: account_asset
#: field:account.asset.asset,partner_id:0
#: field:asset.asset.report,partner_id:0
msgid "Partner"
msgstr ""
msgstr "พาร์ทเนอร์"
#. module: account_asset
#: view:asset.asset.report:0
@ -451,7 +451,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.history,user_id:0
msgid "User"
msgstr ""
msgstr "ผู้ใช้"
#. module: account_asset
#: field:account.asset.category,account_asset_id:0
@ -482,12 +482,12 @@ msgstr ""
#. module: account_asset
#: field:account.asset.asset,active:0
msgid "Active"
msgstr ""
msgstr "เปิดใช้งาน"
#. module: account_asset
#: field:account.asset.depreciation.line,parent_state:0
msgid "State of Asset"
msgstr ""
msgstr "สถานะของสินทรัพย์"
#. module: account_asset
#: field:account.asset.depreciation.line,name:0
@ -498,12 +498,12 @@ msgstr ""
#: view:account.asset.asset:0
#: field:account.asset.asset,history_ids:0
msgid "History"
msgstr ""
msgstr "ประวัติ"
#. module: account_asset
#: view:asset.depreciation.confirmation.wizard:0
msgid "Compute Asset"
msgstr ""
msgstr "คำนวณสินทรัพย์"
#. module: account_asset
#: field:asset.depreciation.confirmation.wizard,period_id:0
@ -513,7 +513,7 @@ msgstr ""
#. module: account_asset
#: view:account.asset.asset:0
msgid "General"
msgstr ""
msgstr "ทั่วไป"
#. module: account_asset
#: field:account.asset.asset,prorata:0
@ -524,7 +524,7 @@ msgstr ""
#. module: account_asset
#: model:ir.model,name:account_asset.model_account_invoice
msgid "Invoice"
msgstr ""
msgstr "ใบแจ้งหนี้"
#. module: account_asset
#: view:account.asset.asset:0
@ -535,13 +535,13 @@ msgstr ""
#: view:asset.depreciation.confirmation.wizard:0
#: view:asset.modify:0
msgid "Cancel"
msgstr ""
msgstr "ยกเลิก"
#. module: account_asset
#: selection:account.asset.asset,state:0
#: selection:asset.asset.report,state:0
msgid "Close"
msgstr ""
msgstr "ปิด"
#. module: account_asset
#: model:ir.model,name:account_asset.model_account_move_line
@ -558,7 +558,7 @@ msgstr ""
#: view:asset.asset.report:0
#: field:asset.asset.report,purchase_date:0
msgid "Purchase Date"
msgstr ""
msgstr "วันที่ซื้อ"
#. module: account_asset
#: selection:account.asset.asset,method:0
@ -606,7 +606,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.asset,currency_id:0
msgid "Currency"
msgstr ""
msgstr "สกุลเงิน"
#. module: account_asset
#: field:account.asset.category,journal_id:0
@ -637,7 +637,7 @@ msgstr ""
#: view:asset.asset.report:0
#: field:asset.asset.report,move_check:0
msgid "Posted"
msgstr ""
msgstr "ลงบัญชีแล้ว"
#. module: account_asset
#: model:ir.actions.act_window,help:account_asset.action_asset_asset_report
@ -660,7 +660,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.category,name:0
msgid "Name"
msgstr ""
msgstr "ชื่อ"
#. module: account_asset
#: help:account.asset.category,open_asset:0
@ -672,7 +672,7 @@ msgstr ""
#. module: account_asset
#: field:asset.asset.report,name:0
msgid "Year"
msgstr ""
msgstr "ปี"
#. module: account_asset
#: model:ir.model,name:account_asset.model_account_asset_depreciation_line
@ -693,7 +693,7 @@ msgid "Amount of Depreciation Lines"
msgstr ""
#. module: account_asset
#: code:addons/account_asset/wizard/wizard_asset_compute.py:49
#: code:addons/account_asset/wizard/wizard_asset_compute.py:50
#, python-format
msgid "Created Asset Moves"
msgstr ""
@ -701,7 +701,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.depreciation.line,sequence:0
msgid "Sequence"
msgstr ""
msgstr "ลำดับ"
#. module: account_asset
#: help:account.asset.category,method_period:0
@ -711,7 +711,7 @@ msgstr ""
#. module: account_asset
#: field:account.asset.history,date:0
msgid "Date"
msgstr ""
msgstr "วันที่"
#. module: account_asset
#: field:account.asset.asset,method_number:0

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-06-13 17:16+0000\n"
"Last-Translator: Akira Hiyama <Unknown>\n"
"PO-Revision-Date: 2013-07-30 22:29+0000\n"
"Last-Translator: Masaki Yamaya <Unknown>\n"
"Language-Team: Japanese <ja@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:34+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-07-31 05:16+0000\n"
"X-Generator: Launchpad (build 16718)\n"
#. module: account_budget
#: view:account.budget.analytic:0
@ -418,7 +418,7 @@ msgstr "からの分析"
#. module: account_budget
#: view:crossovered.budget:0
msgid "Draft Budgets"
msgstr "ドラフト予算"
msgstr "予算"
#, python-format
#~ msgid "The General Budget '%s' has no Accounts!"

View File

@ -0,0 +1,23 @@
# Ukrainian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-08-01 11:11+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Ukrainian <uk@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-08-02 05:38+0000\n"
"X-Generator: Launchpad (build 16718)\n"
#. module: account_cancel
#: view:account.invoice:0
msgid "Cancel"
msgstr ""

View File

@ -14,13 +14,7 @@
<field name="condition">True</field>
<field name="type">ir.actions.server</field>
<field name="state">email</field>
<field name="email">object.user_id.email</field>
<field name="subject">Reminder on Lead: [[object.id ]] [[object.partner_id and 'of ' +object.partner_id.name or '']]</field>
<field name="message">Warning unprocessed incoming lead is more than 5 day old.
Name: [[object.name ]]
ID: [[object.id ]]
Description: [[object.description]]
</field>
<field name="template_id" ref="email_template_opportunity_reminder_mail"/>
</record>
<record id="rule_set_reminder_lead" model="base.action.rule">
<field name="name">Set Auto Reminder on leads which are not open since 5 days.</field>

View File

@ -934,42 +934,6 @@ class crm_lead(format_address, osv.osv):
vals.update(onchange_stage_values)
return super(crm_lead, self).write(cr, uid, ids, vals, context=context)
def new_mail_send(self, cr, uid, ids, context=None):
'''
This function opens a window to compose an email, with the edi sale template message loaded by default
'''
assert len(ids) == 1, 'This option should only be used for a single id at a time.'
ir_model_data = self.pool.get('ir.model.data')
try:
template_id = ir_model_data.get_object_reference(cr, uid, 'crm', 'email_template_opportunity_mail')[1]
except ValueError:
template_id = False
try:
compose_form_id = ir_model_data.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
if context is None:
context = {}
ctx = context.copy()
ctx.update({
'default_model': 'crm.lead',
'default_res_id': ids[0],
'default_use_template': bool(template_id),
'default_template_id': template_id,
'default_composition_mode': 'comment',
})
return {
'name': _('Compose Email'),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(compose_form_id, 'form')],
'view_id': compose_form_id,
'target': 'new',
'context': ctx,
}
# ----------------------------------------
# Mail Gateway
# ----------------------------------------

View File

@ -206,6 +206,20 @@
<field name="email_to">${not object.partner_id and object.email_from}</field>
<field name="body_html"></field>
</record>
<record id="email_template_opportunity_reminder_mail" model="email.template">
<field name="name">Reminder to User</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="auto_delete" eval="True"/>
<field name="email_from">admin@example.com</field>
<field name="email_to">${object.user_id != False and object.user_id.email}</field>
<field name="subject">Reminder on Lead: ${object.id} from ${object.partner_id != False and object.partner_id.name or object.contact_name}</field>
<field name="body_html"><![CDATA[<p>This opportunity did not have any activity since at least 5 days. Here are some details:</p>
<ul>
<li>Name: ${object.name}</li>
<li>ID: ${object.id}</li>
<li>Description: ${object.description}</field></li>
</ul>]]></field>
</record>
</data>
</openerp>

View File

@ -406,7 +406,7 @@
<group>
<group>
<field name="partner_id"
on_change="onchange_partner_id(partner_id, email_from)"
on_change="on_change_partner_id(partner_id)"
string="Customer"
context="{'default_name': partner_name, 'default_email': email_from, 'default_phone': phone}"/>
<field name="email_from" string="Email"/>

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-07-09 07:36+0000\n"
"PO-Revision-Date: 2013-07-25 13:52+0000\n"
"Last-Translator: krnkris <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-07-10 05:25+0000\n"
"X-Generator: Launchpad (build 16696)\n"
"X-Launchpad-Export-Date: 2013-07-26 05:14+0000\n"
"X-Generator: Launchpad (build 16700)\n"
#. module: crm
#: model:crm.case.stage,name:crm.stage_lead3
@ -241,7 +241,7 @@ msgstr "Kilép"
#: view:crm.lead:0
#: field:crm.lead,state_id:0
msgid "State"
msgstr "Állapot"
msgstr "Állam/Megye"
#. module: crm
#: field:res.partner,meeting_count:0

File diff suppressed because it is too large Load Diff

View File

@ -22,5 +22,6 @@
import email_template
import wizard
import res_partner
import ir_actions
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -59,6 +59,7 @@ campaigns on any OpenERP document.
'wizard/email_template_preview_view.xml',
'email_template_view.xml',
'res_partner_view.xml',
'ir_actions_view.xml',
'wizard/mail_compose_message_view.xml',
'security/ir.model.access.csv'
],

View File

@ -0,0 +1,12 @@
.. _changelog:
Changelog
=========
`trunk (saas-2)`
----------------
- ``mail.compose.message``: added support of ``mail_server_id`` from template
- Server action update
- added `email` server action type, now entirely based on email templates.

View File

@ -0,0 +1,13 @@
Email Template module documentation
===================================
Email Template documentation topics
'''''''''''''''''''''''''''''''''''
Changelog
'''''''''
.. toctree::
:maxdepth: 1
changelog.rst

View File

@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013 OpenERP S.A. <http://www.openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields, osv
class actions_server(osv.Model):
""" Add email option in server actions. """
_name = 'ir.actions.server'
_inherit = ['ir.actions.server']
def _get_states(self, cr, uid, context=None):
res = super(actions_server, self)._get_states(cr, uid, context=context)
res.insert(0, ('email', 'Send Email'))
return res
_columns = {
'email_from': fields.char('From',
help="Sender address; define the template to see its value. If not set, the default "
"value will be the author's email alias if configured, or email address."),
'email_to': fields.char('To (Emails)',
help="Comma-separated recipient addresses; define the template to see its value"),
'partner_to': fields.char('To (Partners)',
help="Comma-separated ids of recipient partners; define the template to see its value"),
'subject': fields.char('Subject',
help="Email subject; define the template to see its value"),
'body_html': fields.text('Body',
help="Rich-text/HTML version of the message; define the template to see its value"),
'template_id': fields.many2one('email.template', 'Email Template', ondelete='set null',
help="Define the email template to use for the email to send.")
}
def on_change_template_id(self, cr, uid, ids, template_id, context=None):
""" Render the raw template in the server action fields. """
if template_id:
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids']
template_values = self.pool.get('email.template').read(cr, uid, template_id, fields, context)
values = dict((field, template_values[field]) for field in fields if template_values.get(field))
if not values.get('email_from'):
return {'warning': {'title': 'Incomplete template', 'message': 'Your template should define email_from'}, 'value': values}
else:
values = self.default_get(cr, uid, ['subject', 'body_html', 'email_from', 'email_to', 'partner_to'], context=context)
return {'value': values}
def create(self, cr, uid, values, context=None):
if values.get('template_id'):
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids']
template_values = self.pool.get('email.template').read(cr, uid, values.get('template_id'), fields, context)
values.update(dict((field, template_values[field]) for field in fields if template_values.get(field)))
return super(actions_server, self).create(cr, uid, values, context=context)
def write(self, cr, uid, ids, values, context=None):
if values.get('template_id'):
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids']
template_values = self.pool.get('email.template').read(cr, uid, values.get('template_id'), fields, context)
values.update(dict((field, template_values[field]) for field in fields if template_values.get(field)))
return super(actions_server, self).write(cr, uid, ids, values, context=context)
def run_action_email(self, cr, uid, action, eval_context=None, context=None):
if not action.template_id or not context.get('active_id'):
return False
self.pool['email.template'].send_mail(cr, uid, action.template_id.id, context.get('active_id'),
force_send=False, raise_exception=False, context=context)
return False
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_server_action_form_template">
<field name="name">ir.actions.server.form</field>
<field name="model">ir.actions.server</field>
<field name="inherit_id" ref="base.view_server_action_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='code']" position="after">
<page string="Email" autofocus="autofocus"
attrs="{'invisible': [('state', '!=', 'email')]}">
<p attrs="{'invisible': [('model_id', '!=', False)]}">
Please set the Base Model before setting the action details.
</p>
<group attrs="{'invisible': [('model_id', '=', False)]}">
<field name="template_id"
on_change='on_change_template_id(template_id)'
domain="[('model_id', '=', model_id)]"
attrs="{'required': [('state', '=', 'email')]}"/>
<p colspan="2" attrs="{'invisible': [('template_id', '!=', False)]}">
Choose a template to display its values.
</p>
<p colspan="2" attrs="{'invisible': [('template_id', '=', False)]}">
The values displayed hereunder are informative. When sending the email, the values
will be taken from the email template.
</p>
</group>
<group attrs="{'invisible': ['|', ('model_id', '=', False), ('template_id', '=', False)]}">
<label for="email_from"/>
<div>
<field name="email_from" nolabel="1'" readonly="1"
attrs="{'required': [('state', '=', 'email')]}"/>
<p attrs="{'invisible': [('email_from', '!=', False)]}">
Your template does not defined any email_from. Please update your template.
</p>
</div>
<field name="email_to" readonly="1"/>
<field name="partner_to" readonly="1"/>
<field name="subject" readonly="1" attrs="{'required': [('state', '=', 'email')]}"/>
<field name="body_html" readonly="1" attrs="{'required': [('state', '=', 'email')]}"/>
</group>
</page>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -18,10 +18,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import test_mail
from . import test_mail, test_ir_actions
checks = [
test_mail,
test_ir_actions,
]
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013-TODAY OpenERP S.A. <http://www.openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.addons.base.tests.test_ir_actions import TestServerActionsBase
class TestServerActionsEmail(TestServerActionsBase):
def test_00_state_email(self):
""" Test ir.actions.server email type """
cr, uid = self.cr, self.uid
# create email_template
template_id = self.registry('email.template').create(cr, uid, {
'name': 'TestTemplate',
'email_from': 'myself@example.com',
'email_to': 'brigitte@example.com',
'partner_to': '[%s]' % self.test_partner_id,
'model_id': self.res_partner_model_id,
'subject': 'About ${object.name}',
'body_html': '<p>Dear ${object.name}, your parent is ${object.parent_id and object.parent_id.name or "False"}</p>',
})
self.ir_actions_server.write(cr, uid, self.act_id, {
'state': 'email',
'template_id': template_id,
})
run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
self.assertFalse(run_res, 'ir_actions_server: email server action correctly finished should return False')
# check an email is waiting for sending
mail_ids = self.registry('mail.mail').search(cr, uid, [('subject', '=', 'About TestingPartner')])
self.assertEqual(len(mail_ids), 1, 'ir_actions_server: TODO')
# check email content
mail = self.registry('mail.mail').browse(cr, uid, mail_ids[0])
self.assertEqual(mail.body, '<p>Dear TestingPartner, your parent is False</p>',
'ir_actions_server: TODO')

View File

@ -22,6 +22,7 @@
from openerp import tools
from openerp.osv import osv, fields
def _reopen(self, res_id, model):
return {'type': 'ir.actions.act_window',
'view_mode': 'form',
@ -34,7 +35,8 @@ def _reopen(self, res_id, model):
'context': {
'default_model': model,
},
}
}
class mail_compose_message(osv.TransientModel):
_inherit = 'mail.compose.message'
@ -58,7 +60,7 @@ class mail_compose_message(osv.TransientModel):
context = {}
wizard_context = dict(context)
for wizard in self.browse(cr, uid, ids, context=context):
if wizard.template_id and not wizard.template_id.user_signature:
if wizard.template_id:
wizard_context['mail_notify_user_signature'] = False # template user_signature is added when generating body_html
if not wizard.attachment_ids or wizard.composition_mode == 'mass_mail' or not wizard.template_id:
continue
@ -75,7 +77,7 @@ class mail_compose_message(osv.TransientModel):
""" - mass_mailing: we cannot render, so return the template values
- normal mode: return rendered values """
if template_id and composition_mode == 'mass_mail':
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids']
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'mail_server_id']
template_values = self.pool.get('email.template').read(cr, uid, template_id, fields, context)
values = dict((field, template_values[field]) for field in fields if template_values.get(field))
elif template_id:
@ -95,7 +97,7 @@ class mail_compose_message(osv.TransientModel):
}
values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context))
else:
values = self.default_get(cr, uid, ['subject', 'body', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to', 'attachment_ids'], context=context)
values = self.default_get(cr, uid, ['subject', 'body', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to', 'attachment_ids', 'mail_server_id'], context=context)
if values.get('body_html'):
values['body'] = values.pop('body_html')
@ -150,7 +152,7 @@ class mail_compose_message(osv.TransientModel):
mail.compose.message, transform email_cc and email_to into partner_ids """
template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context)
# filter template values
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'attachments']
fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'attachments', 'mail_server_id']
values = dict((field, template_values[field]) for field in fields if template_values.get(field))
values['body'] = values.pop('body_html', '')

View File

@ -28,7 +28,7 @@ import urllib2
import simplejson
class google_service(osv.osv):
class google_service(osv.osv_memory):
_name = 'google.service'
def generate_refresh_token(self, cr, uid, service, authorization_code, context=None):
@ -51,10 +51,10 @@ class google_service(osv.osv):
content = simplejson.loads(content)
return content.get('refresh_token')
def _get_google_token_uri(self, cr, uid, service, context=None):
def _get_google_token_uri(self, cr, uid, service, scope, context=None):
ir_config = self.pool['ir.config_parameter']
params = {
'scope': 'https://www.googleapis.com/auth/drive',
'scope': scope,
'redirect_uri': ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri'),
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
'response_type': 'code',

View File

@ -54,58 +54,69 @@ class config(osv.osv):
attachment = attach_pool.browse(cr, uid, attach_ids[0], context)
url = attachment.url
else:
url = self.copy_doc(cr, uid, res_id, template_id, name_gdocs, model.model, context)
url = self.copy_doc(cr, uid, res_id, template_id, name_gdocs, model.model, context).get('url')
return url
def copy_doc(self, cr, uid, res_id, template_id, name_gdocs, res_model, context=None):
def get_access_token(self, cr, uid, scope=None, context=None):
ir_config = self.pool['ir.config_parameter']
google_drive_refresh_token = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_refresh_token')
group_config = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_erp_manager')[1]
user = self.pool['res.users'].read(cr, uid, uid, "groups_id")
if not google_drive_refresh_token:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("You haven't configured 'Authorization Code' generated from google, Please generate and configure it in %(menu:base_setup.menu_general_configuration)s."), context=context)
if group_config in user['groups_id']:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("You haven't configured 'Authorization Code' generated from google, Please generate and configure it in %(menu:base_setup.menu_general_configuration)s."), context=context)
else:
raise osv.except_osv(_('Error!'), _("Google Drive is not yet configured. Please contact your administrator."))
google_drive_client_id = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_client_id')
google_drive_client_secret = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_client_secret')
google_web_base_url = ir_config.get_param(cr, SUPERUSER_ID, 'web.base.url')
#For Getting New Access Token With help of old Refresh Token
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip, deflate"}
data = dict(client_id=google_drive_client_id,
refresh_token=google_drive_refresh_token,
client_secret=google_drive_client_secret,
grant_type="refresh_token")
data = urllib.urlencode(data)
data = urllib.urlencode(dict(client_id=google_drive_client_id,
refresh_token=google_drive_refresh_token,
client_secret=google_drive_client_secret,
grant_type="refresh_token",
scope=scope or 'https://www.googleapis.com/auth/drive'))
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip, deflate"}
try:
req = urllib2.Request('https://accounts.google.com/o/oauth2/token', data, headers)
content = urllib2.urlopen(req).read()
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during the token generation. Please request again an authorization code in %(menu:base_setup.menu_general_configuration)s."), context=context)
if group_config in user['groups_id']:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during the token generation. Please request again an authorization code in %(menu:base_setup.menu_general_configuration)s."), context=context)
else:
raise osv.except_osv(_('Error!'), _("Google Drive is not yet configured. Please contact your administrator."))
content = json.loads(content)
return content.get('access_token')
def copy_doc(self, cr, uid, res_id, template_id, name_gdocs, res_model, context=None):
ir_config = self.pool['ir.config_parameter']
google_web_base_url = ir_config.get_param(cr, SUPERUSER_ID, 'web.base.url')
access_token = self.get_access_token(cr, uid, context=context)
# Copy template in to drive with help of new access token
if 'access_token' in content:
request_url = "https://www.googleapis.com/drive/v2/files/%s?fields=parents/id&access_token=%s" % (template_id, content['access_token'])
try:
req = urllib2.Request(request_url, None, headers)
parents = urllib2.urlopen(req).read()
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("The Google Template cannot be found. Maybe it has been deleted."), context=context)
parents_dict = json.loads(parents)
request_url = "https://www.googleapis.com/drive/v2/files/%s?fields=parents/id&access_token=%s" % (template_id, access_token)
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept-Encoding": "gzip, deflate"}
try:
req = urllib2.Request(request_url, None, headers)
parents = urllib2.urlopen(req).read()
except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("The Google Template cannot be found. Maybe it has been deleted."), context=context)
parents_dict = json.loads(parents)
record_url = "Click on link to open Record in OpenERP\n %s/?db=%s#id=%s&model=%s" % (google_web_base_url, cr.dbname, res_id, res_model)
data = {"title": name_gdocs, "description": record_url, "parents": parents_dict['parents']}
request_url = "https://www.googleapis.com/drive/v2/files/%s/copy?access_token=%s" % (template_id, content['access_token'])
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
data_json = json.dumps(data)
# resp, content = Http().request(request_url, "POST", data_json, headers)
req = urllib2.Request(request_url, data_json, headers)
content = urllib2.urlopen(req).read()
content = json.loads(content)
res = False
if 'alternateLink' in content.keys():
attach_pool = self.pool.get("ir.attachment")
attach_vals = {'res_model': res_model, 'name': name_gdocs, 'res_id': res_id, 'type': 'url', 'url': content['alternateLink']}
attach_pool.create(cr, uid, attach_vals)
res = content['alternateLink']
record_url = "Click on link to open Record in OpenERP\n %s/?db=%s#id=%s&model=%s" % (google_web_base_url, cr.dbname, res_id, res_model)
data = {"title": name_gdocs, "description": record_url, "parents": parents_dict['parents']}
request_url = "https://www.googleapis.com/drive/v2/files/%s/copy?access_token=%s" % (template_id, access_token)
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
data_json = json.dumps(data)
# resp, content = Http().request(request_url, "POST", data_json, headers)
req = urllib2.Request(request_url, data_json, headers)
content = urllib2.urlopen(req).read()
content = json.loads(content)
res = {}
if content.get('alternateLink'):
attach_pool = self.pool.get("ir.attachment")
attach_vals = {'res_model': res_model, 'name': name_gdocs, 'res_id': res_id, 'type': 'url', 'url': content['alternateLink']}
res['id'] = attach_pool.create(cr, uid, attach_vals)
res['url'] = content['alternateLink']
return res
def get_google_drive_config(self, cr, uid, res_model, res_id, context=None):
@ -166,6 +177,7 @@ class config(osv.osv):
'google_drive_resource_id': fields.function(_resource_get, type="char", string='Resource Id'),
'google_drive_client_id': fields.function(_client_id_get, type="char", string='Google Client '),
'name_template': fields.char('Google Drive Name Pattern', size=64, help='Choose how the new google drive will be named, on google side. Eg. gdoc_%(field_name)s', required=True),
'active': fields.boolean('Active'),
}
def onchange_model_id(self, cr, uid, ids, model_id, context=None):
@ -179,6 +191,7 @@ class config(osv.osv):
_defaults = {
'name_template': 'Document %(name)s',
'active': True,
}
def _check_model_id(self, cr, uid, ids, context=None):
@ -191,6 +204,9 @@ class config(osv.osv):
(_check_model_id, 'Model of selected filter is not matching with model of current template.', ['model_id', 'filter_id']),
]
def get_google_scope(self):
return 'https://www.googleapis.com/auth/drive'
config()
@ -202,7 +218,7 @@ class base_config_settings(osv.osv):
'google_drive_uri': fields.char('URI', readonly=True, help="The URL to generate the authorization code from Google"),
}
_defaults = {
'google_drive_uri': lambda s, cr, uid, c: s.pool['google.service']._get_google_token_uri(cr, uid, 'drive', context=c),
'google_drive_uri': lambda s, cr, uid, c: s.pool['google.service']._get_google_token_uri(cr, uid, 'drive', scope=s.pool['google.drive.config'].get_google_scope(), context=c),
}
def set_google_authorization_code(self, cr, uid, ids, context=None):

View File

@ -4,12 +4,12 @@
<record id="config_google_drive_client_id" model="ir.config_parameter">
<field name="key">google_drive_client_id</field>
<field name="value">39623646228-eg3ggo3mk6o40m7rguobi3rkl9frh4tb.apps.googleusercontent.com</field>
<field name="value">598905559630.apps.googleusercontent.com</field>
</record>
<record id="config_google_drive_client_secret" model="ir.config_parameter">
<field name="key">google_drive_client_secret</field>
<field name="value">Ul-PtmnSWs3euWs20fdono0e</field>
<field name="value">vTmou73c-njP-1qCxm7qx7QE</field>
</record>
</data>

View File

@ -23,6 +23,7 @@
<field name="model" invisible="1" />
<group>
<field name="name" />
<field name="active" />
<field name="model_id" on_change="onchange_model_id(model_id)" />
<label for='filter_id' />
<div>
@ -54,7 +55,7 @@
</record>
<record model='ir.actions.act_window' id='action_google_drive_users_config'>
<field name='name'>Google Drive Templates</field>
<field name='name'>Templates</field>
<field name='res_model'>google.drive.config</field>
<field name='type'>ir.actions.act_window</field>
<field name='view_type'>form</field>
@ -87,7 +88,7 @@
</field>
</record>
<menuitem name='Google Drive configuration' id='menu_google_drive_config' parent='base.menu_administration' />
<menuitem name='Google Drive' id='menu_google_drive_config' parent='base.menu_administration' />
<menuitem id='menu_google_drive_model_config' parent='menu_google_drive_config' action='action_google_drive_users_config' />
</data>
</openerp>

View File

@ -29,19 +29,24 @@ openerp.google_drive = function (instance, m) {
ds.call('get_google_drive_config', [view.dataset.model, res_id, context]).done(function (r) {
if (!_.isEmpty(r)) {
_.each(r, function (res) {
var g_item = _.indexOf(_.pluck(self.items.other, 'label'), res.name);
if (g_item !== -1) {
self.items.other.splice(g_item, 1);
var already_there = false;
for (var i = 0;i < self.items.other.length;i++){
if (self.items.other[i].classname === "oe_share_gdoc" && self.items.other[i].label.indexOf(res.name) > -1){
already_there = true;
break;
}
}
if (!already_there){
self.add_items('other', [{
label: res.name+ '<img style="position:absolute;right:5px;height:20px;width:20px;" title="Google Drive" src="google_drive/static/src/img/drive_icon.png"/>',
config_id: res.id,
res_id: res_id,
res_model: view.dataset.model,
callback: self.on_google_doc,
classname: 'oe_share_gdoc'
},
]);
}
self.add_items('other', [{
label: res.name+ '<img style="position:absolute;right:5px;height:20px;width:20px;" title="Google Drive" src="google_drive/static/src/img/drive_icon.png"/>',
config_id: res.id,
res_id: res_id,
res_model: view.dataset.model,
callback: self.on_google_doc,
classname: 'oe_share_gdoc'
},
]);
})
}
});

View File

@ -0,0 +1 @@
import google_spreadsheet

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Google Spreadsheet',
'version': '1.0',
'category': 'Tools',
'description': """
The module adds the possibility to display data from OpenERP in Google Spreadsheets in real time.
========================================
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['board', 'google_drive'],
'js': [
'static/src/js/search.js',
],
'qweb': ['static/src/xml/*.xml'],
'data': ['google_spreadsheet_view.xml', 'google_spreadsheet_data.xml'],
'demo': [],
'installable': True,
'auto_install': False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,119 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2012 OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import simplejson
import logging
from lxml import etree
import re
import urllib
import urllib2
from openerp.osv import osv
from openerp import SUPERUSER_ID
_logger = logging.getLogger(__name__)
class config(osv.osv):
_inherit = 'google.drive.config'
def get_google_scope(self):
scope = super(config, self).get_google_scope()
return '%s https://spreadsheets.google.com/feeds' % scope
def write_config_formula(self, cr, uid, attachment_id, spreadsheet_key, model, domain, groupbys, view_id, context=None):
access_token = self.get_access_token(cr, uid, scope='https://spreadsheets.google.com/feeds', context=context)
fields = self.pool.get(model).fields_view_get(cr, uid, view_id=view_id, view_type='tree')
doc = etree.XML(fields.get('arch'))
display_fields = []
for node in doc.xpath("//field"):
if node.get('modifiers'):
modifiers = simplejson.loads(node.get('modifiers'))
if not modifiers.get('invisible') and not modifiers.get('tree_invisible'):
display_fields.append(node.get('name'))
fields = " ".join(display_fields)
domain = domain.replace("'", r"\'").replace('"', "'")
if groupbys:
fields = "%s %s" % (groupbys, fields)
formula = '=oe_read_group("%s";"%s";"%s";"%s")' % (model, fields, groupbys, domain)
else:
formula = '=oe_browse("%s";"%s";"%s")' % (model, fields, domain)
url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
dbname = cr.dbname
user = self.pool['res.users'].read(cr, uid, uid, ['login', 'password'], context=context)
username = user['login']
password = user['password']
if self.pool['ir.module.module'].search_count(cr, SUPERUSER_ID, ['&', ('name', '=', 'auth_crypt'), ('state', '=', 'installed')]) == 1:
config_formula = '=oe_settings("%s";"%s")' % (url, dbname)
else:
config_formula = '=oe_settings("%s";"%s";"%s";"%s")' % (url, dbname, username, password)
request = '''<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:batch="http://schemas.google.com/gdata/batch"
xmlns:gs="http://schemas.google.com/spreadsheets/2006">
<id>https://spreadsheets.google.com/feeds/cells/%s/od6/private/full</id>
<entry>
<batch:id>A1</batch:id>
<batch:operation type="update"/>
<id>https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R1C1</id>
<link rel="edit" type="application/atom+xml"
href="https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R1C1"/>
<gs:cell row="1" col="1" inputValue="%s"/>
</entry>
<entry>
<batch:id>A2</batch:id>
<batch:operation type="update"/>
<id>https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R60C15</id>
<link rel="edit" type="application/atom+xml"
href="https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R60C15"/>
<gs:cell row="60" col="15" inputValue="%s"/>
</entry>
</feed>''' % (spreadsheet_key, spreadsheet_key, spreadsheet_key, formula.replace('"', '&quot;'), spreadsheet_key, spreadsheet_key, config_formula.replace('"', '&quot;'))
try:
req = urllib2.Request(
'https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/batch?%s' % (spreadsheet_key, urllib.urlencode({'v': 3, 'access_token': access_token})),
data=request,
headers={'content-type': 'application/atom+xml', 'If-Match': '*'})
urllib2.urlopen(req)
except (urllib2.HTTPError, urllib2.URLError):
_logger.warning("An error occured while writting the formula on the Google Spreadsheet.")
description = '''
formula: %s
''' % formula
if attachment_id:
self.pool['ir.attachment'].write(cr, uid, attachment_id, {'description': description}, context=context)
return True
def set_spreadsheet(self, cr, uid, model, domain, groupbys, view_id, context=None):
try:
config_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'google_spreadsheet', 'google_spreadsheet_template')[1]
except ValueError:
raise
config = self.browse(cr, uid, config_id, context=context)
title = 'Spreadsheet %s' % model
res = self.copy_doc(cr, uid, False, config.google_drive_resource_id, title, model, context=context)
mo = re.search("(key=|/d/)([A-Za-z0-9-_]+)", res['url'])
if mo:
key = mo.group(2)
self.write_config_formula(cr, uid, res.get('id'), key, model, domain, groupbys, view_id, context=context)
return res

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="google_spreadsheet_template" model="google.drive.config">
<field name="name">Base Spreadsheet Template</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="google_drive_template_url">https://docs.google.com/spreadsheet/ccc?key=0ApGVjjwUC-ygdDZ0TG5EQnRlLVFQNlFGdFN5b1ZrY1E</field>
<field name="name_template">Reporting %(name)s</field>
<field name="active" eval="0" />
</record>
</data>
</openerp>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- add google drive config field in user form -->
<record model="ir.ui.view" id="view_ir_attachment_google_spreadsheet_tree">
<field name="name">ir.attachment.google.spreadsheet.tree</field>
<field name="model">ir.attachment</field>
<field name="arch" type="xml">
<tree string="Google Spreadsheets" version="7.0">
<field name="name" string="Name"/>
<field name="url" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_ir_attachment_google_spreadsheet_form">
<field name="name">ir.attachment.google.spreadsheet.form</field>
<field name="model">ir.attachment</field>
<field name="arch" type="xml">
<form string="Google Spreadsheets" version="7.0">
<sheet>
<group>
<group>
<field name="name" string="Name"/>
<field name="url" widget="url"/>
</group>
<group colspan="2">
<label for="description" colspan="2"/>
<field name="description" nolabel="1" colspan="2"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_ir_attachment_google_spreadsheet_tree" model="ir.actions.act_window">
<field name="name">Google Spreadsheets</field>
<field name="res_model">ir.attachment</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{}</field>
<field name="domain">[('url', 'like', '/spreadsheet/')]</field>
<field name="help">Google Spreadsheets</field>
</record>
<record id="action_ir_attachment_google_spreadsheet_tree_view" model="ir.actions.act_window.view">
<field eval="1" name="sequence"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_ir_attachment_google_spreadsheet_tree"/>
<field name="act_window_id" ref="action_ir_attachment_google_spreadsheet_tree"/>
</record>
<record id="action_ir_attachment_google_spreadsheet_form_view" model="ir.actions.act_window.view">
<field eval="2" name="sequence"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_ir_attachment_google_spreadsheet_form"/>
<field name="act_window_id" ref="action_ir_attachment_google_spreadsheet_tree"/>
</record>
<menuitem id="menu_reporting_dashboard_google_spreadsheets" parent="base.menu_reporting_dashboard" action="action_ir_attachment_google_spreadsheet_tree"/>
</data>
</openerp>

View File

@ -0,0 +1,42 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * google_spreadsheet
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 8.0alpha1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-25 12:39+0000\n"
"PO-Revision-Date: 2013-07-25 12:39+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: google_spreadsheet
#: model:ir.actions.act_window,help:google_spreadsheet.action_ir_attachment_google_spreadsheet_tree
#: model:ir.actions.act_window,name:google_spreadsheet.action_ir_attachment_google_spreadsheet_tree
#: view:ir.attachment:0
#: model:ir.ui.menu,name:google_spreadsheet.menu_reporting_dashboard_google_spreadsheets
msgid "Google Spreadsheets"
msgstr ""
#. module: google_spreadsheet
#. openerp-web
#: code:addons/google_spreadsheet/static/src/xml/addtospreadsheet.xml:3
#, python-format
msgid "Add to Google Spreadsheet"
msgstr ""
#. module: google_spreadsheet
#: view:ir.attachment:0
msgid "Name"
msgstr ""
#. module: google_spreadsheet
#: model:ir.model,name:google_spreadsheet.model_google_drive_config
msgid "Google Drive templates config"
msgstr ""

View File

@ -0,0 +1,54 @@
openerp.google_spreadsheet = function(instance) {
var _t = instance.web._t;
instance.web.FormView.include({
on_processed_onchange: function(result, processed) {
var self = this;
var fields = self.fields;
_(result.selection).each(function (selection, fieldname) {
var field = fields[fieldname];
if (!field) { return; }
field.field.selection = selection;
field.values = selection;
field.renderElement();
});
return this._super(result, processed);
},
});
instance.board.AddToGoogleSpreadsheet = instance.web.search.Input.extend({
template: 'SearchView.addtogooglespreadsheet',
_in_drawer: true,
start: function () {
var self = this;
this.$el.on('click', 'h4', function(){
var view = self.view;
var data = view.build_search_data();
var model = view.model;
var list_view = self.view.getParent().views['list'];
var view_id = list_view ? list_view.view_id : false;
var context = new instance.web.CompoundContext(view.dataset.get_context() || []);
var domain = new instance.web.CompoundDomain(view.dataset.get_domain() || []);
_.each(data.contexts, context.add, context);
_.each(data.domains, domain.add, domain);
domain = JSON.stringify(domain.eval());
var groupbys = instance.web.pyeval.eval('groupbys', data.groupbys).join(" ");
var view_id = view_id;
var ds = new instance.web.DataSet(self, 'google.drive.config');
ds.call('set_spreadsheet', [model, domain, groupbys, view_id]).done(function (res) {
if (res['url']){
window.open(res['url'], '_blank');
}
});
});
},
});
instance.web.SearchView.include({
add_common_inputs: function() {
this._super();
var vm = this.getParent().getParent();
if (vm.inner_action && vm.inner_action.views) {
(new instance.board.AddToGoogleSpreadsheet(this));
}
}
});
};

View File

@ -0,0 +1,5 @@
<template>
<div t-name="SearchView.addtogooglespreadsheet" class="oe_searchview_dashboard">
<h4>Add to Google Spreadsheet</h4>
</div>
</template>

View File

@ -0,0 +1,169 @@
# Chinese (Simplified) translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 01:06+0000\n"
"PO-Revision-Date: 2013-07-24 12:29+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-07-25 05:13+0000\n"
"X-Generator: Launchpad (build 16700)\n"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_fiscal_position_template
msgid "Template for Fiscal Position"
msgstr "财务结构模板"
#. module: l10n_multilang
#: sql_constraint:account.account:0
msgid "The code of the account must be unique per company !"
msgstr "该科目的代码,每家公司必须是唯一的!"
#. module: l10n_multilang
#: constraint:account.account.template:0
msgid ""
"Configuration Error!\n"
"You can not define children to an account with internal type different of "
"\"View\"! "
msgstr ""
"配置错误! \n"
"上级科目必须是“视图”类型的科目! "
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_analytic_journal
msgid "Analytic Journal"
msgstr "辅助核算类型"
#. module: l10n_multilang
#: constraint:account.account.template:0
msgid "Error ! You can not create recursive account templates."
msgstr "错误!您不能创建递归的科目模板。"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_journal
msgid "Journal"
msgstr "分录序时薄"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_chart_template
msgid "Templates for Account Chart"
msgstr "科目一览表模板"
#. module: l10n_multilang
#: sql_constraint:account.tax:0
msgid "The description must be unique per company!"
msgstr "此说明必须是每个公司唯一的"
#. module: l10n_multilang
#: constraint:account.tax.code.template:0
msgid "Error ! You can not create recursive Tax Codes."
msgstr "错误!您不能创建递归的税编码。"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_tax_template
msgid "account.tax.template"
msgstr "account.tax.template"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_tax
msgid "account.tax"
msgstr "account.tax"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_account
msgid "Account"
msgstr "科目"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_wizard_multi_charts_accounts
msgid "wizard.multi.charts.accounts"
msgstr "wizard.multi.charts.accounts"
#. module: l10n_multilang
#: constraint:account.journal:0
msgid ""
"Configuration error! The currency chosen should be shared by the default "
"accounts too."
msgstr "设置错误!所选币种应与默认科目共享。"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_account_template
msgid "Templates for Accounts"
msgstr "科目模板"
#. module: l10n_multilang
#: help:account.chart.template,spoken_languages:0
msgid ""
"State here the languages for which the translations of templates could be "
"loaded at the time of installation of this localization module and copied in "
"the final object when generating them from templates. You must provide the "
"language codes separated by ';'"
msgstr ""
#. module: l10n_multilang
#: constraint:account.account:0
msgid "Error ! You can not create recursive accounts."
msgstr "错误!您不能创建递归的科目"
#. module: l10n_multilang
#: constraint:account.account:0
msgid ""
"Configuration Error! \n"
"You can not select an account type with a deferral method different of "
"\"Unreconciled\" for accounts with internal type \"Payable/Receivable\"! "
msgstr ""
"配置错误!\n"
"对于内部类型是‘应收/应付’的会计科目,你需要选择结转方式是‘未核销’的科目类型。 "
#. module: l10n_multilang
#: sql_constraint:account.journal:0
msgid "The name of the journal must be unique per company !"
msgstr "每个公司的日记账名称必须唯一!"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_analytic_account
msgid "Analytic Account"
msgstr "辅助核算项目"
#. module: l10n_multilang
#: sql_constraint:account.journal:0
msgid "The code of the journal must be unique per company !"
msgstr "每个公司的日记账代码必须唯一!"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_fiscal_position
msgid "Fiscal Position"
msgstr "财务结构"
#. module: l10n_multilang
#: constraint:account.account:0
msgid ""
"Configuration Error! \n"
"You can not define children to an account with internal type different of "
"\"View\"! "
msgstr ""
"配置错误! \n"
"您不能给 非“视图”类型的科目定义一个子科目。 "
#. module: l10n_multilang
#: constraint:account.analytic.account:0
msgid "Error! You can not create recursive analytic accounts."
msgstr "错误! 你不能创建递归的辅助核算项目"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_tax_code_template
msgid "Tax Code Template"
msgstr "税编码模板"
#. module: l10n_multilang
#: field:account.chart.template,spoken_languages:0
msgid "Spoken Languages"
msgstr "交流语言"

View File

@ -6,6 +6,12 @@ Changelog
`trunk (saas-2)`
----------------
- added support of ``active_domain`` form context, coming from the list view.
When checking the header hook, the mass mailing will be done on all records
matching the ``active_domain``.
- added ``mail_server_id`` to mail_message, removing it from mail_mail. This allows
to set the preferred mail server to use for notifications emails, when using
templates.
- added ``_mail_post_access`` attribute that specifies the access right that
should have the user in order to post a new message on a given model. Values
are ``read`` (portal documents), ``write`` (default value), ``unlink`` or ``create``.
are ``read`` (portal documents), ``write`` (default value), ``unlink`` or ``create``.

View File

@ -151,7 +151,7 @@ class mail_notification(osv.Model):
return footer
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None,
force_send=False, user_signature=True):
force_send=False, user_signature=True):
""" Send by email the notification depending on the user preferences
:param list partners_to_notify: optional list of partner ids restricting

View File

@ -44,7 +44,6 @@ class mail_mail(osv.Model):
_columns = {
'mail_message_id': fields.many2one('mail.message', 'Message', required=True, ondelete='cascade'),
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing mail server', readonly=1),
'state': fields.selection([
('outgoing', 'Outgoing'),
('sent', 'Sent'),

View File

@ -191,6 +191,7 @@ class mail_message(osv.Model):
'vote_user_ids': fields.many2many('res.users', 'mail_vote',
'message_id', 'user_id', string='Votes',
help='Users that voted for this message'),
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing mail server', readonly=1),
}
def _needaction_domain_get(self, cr, uid, context=None):
@ -780,8 +781,8 @@ class mail_message(osv.Model):
values['message_id'] = tools.generate_tracking_message_id('private')
newid = super(mail_message, self).create(cr, uid, values, context)
self._notify(cr, uid, newid, context=context,
force_send=context.get('mail_notify_force_send', True),
user_signature=context.get('mail_notify_user_signature', True))
force_send=context.get('mail_notify_force_send', True),
user_signature=context.get('mail_notify_user_signature', True))
# TDE FIXME: handle default_starred. Why not setting an inv on starred ?
# Because starred will call set_message_starred, that looks for notifications.
# When creating a new mail_message, it will create a notification to a message

View File

@ -2,7 +2,7 @@ openerp.mail = function (session) {
var _t = session.web._t,
_lt = session.web._lt;
var mail = session.mail = {};
var mail = session.mail;
openerp_mail_followers(session, mail); // import mail_followers.js
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js

View File

@ -640,7 +640,7 @@ class test_mail(TestMailBase):
})
compose = mail_compose.browse(cr, uid, compose_id)
# D: Post the comment, get created message for each group
# Do: Post the comment, get created message for each group
mail_compose.send_mail(cr, user_raoul.id, [compose_id], context={
'default_res_id': -1,
'active_ids': [self.group_pigs_id, group_bird_id]
@ -679,6 +679,37 @@ class test_mail(TestMailBase):
self.assertEqual(set(bird_pids), set(test_pids),
'compose wizard: mail_post_autofollow and mail_create_nosubscribe context keys not correctly taken into account')
# Do: Compose in mass_mail, coming from list_view, we have an active_domain that should be supported
compose_id = mail_compose.create(cr, user_raoul.id,
{
'subject': _subject,
'body': '${object.description}',
'partner_ids': [(4, p_c_id), (4, p_d_id)],
}, context={
'default_composition_mode': 'mass_mail',
'default_model': 'mail.group',
'default_res_id': False,
'active_ids': [self.group_pigs_id],
'active_domain': [('name', 'in', ['Pigs', 'Bird'])],
})
compose = mail_compose.browse(cr, uid, compose_id)
# Do: Post the comment, get created message for each group
mail_compose.send_mail(
cr, user_raoul.id, [compose_id], context={
'default_res_id': -1,
'active_ids': [self.group_pigs_id, group_bird_id]
})
group_pigs.refresh()
group_bird.refresh()
message1 = group_pigs.message_ids[0]
message2 = group_bird.message_ids[0]
# Test: Pigs and Bird did receive their message
test_msg_ids = self.mail_message.search(cr, uid, [], limit=2)
self.assertIn(message1.id, test_msg_ids, 'compose wizard: Pigs did not receive its mass mailing message')
self.assertIn(message2.id, test_msg_ids, 'compose wizard: Bird did not receive its mass mailing message')
def test_30_needaction(self):
""" Tests for mail.message needaction. """
cr, uid, user_admin, user_raoul, group_pigs = self.cr, self.uid, self.user_admin, self.user_raoul, self.group_pigs

View File

@ -73,6 +73,11 @@ class mail_compose_message(osv.TransientModel):
res_id = context.get('default_res_id', context.get('active_id'))
message_id = context.get('default_parent_id', context.get('message_id', context.get('active_id')))
active_ids = context.get('active_ids')
if 'active_domain' in context: # not context.get() because we want to keep global [] domains
result['use_active_domain'] = True
result['active_domain'] = '%s' % context.get('active_domain')
else:
result['active_domain'] = ''
# get default values according to the composition mode
if composition_mode == 'reply':
@ -112,6 +117,8 @@ class mail_compose_message(osv.TransientModel):
'partner_ids': fields.many2many('res.partner',
'mail_compose_message_res_partner_rel',
'wizard_id', 'partner_id', 'Additional contacts'),
'use_active_domain': fields.boolean('Use active domain'),
'active_domain': fields.char('Active domain', readonly=True),
'post': fields.boolean('Post a copy in the document',
help='Post a copy of the message on the document communication history.'),
'notify': fields.boolean('Notify followers',
@ -129,7 +136,6 @@ class mail_compose_message(osv.TransientModel):
'body': lambda self, cr, uid, ctx={}: '',
'subject': lambda self, cr, uid, ctx={}: False,
'partner_ids': lambda self, cr, uid, ctx={}: [],
'notify': lambda self, cr, uid, ctx={}: False,
'post': lambda self, cr, uid, ctx={}: True,
'same_thread': lambda self, cr, uid, ctx={}: True,
}
@ -238,8 +244,14 @@ class mail_compose_message(osv.TransientModel):
context['thread_model'] = wizard.model
active_model_pool = self.pool['mail.thread']
# wizard works in batch mode: [res_id] or active_ids
res_ids = active_ids if mass_mail_mode and wizard.model and active_ids else [wizard.res_id]
# wizard works in batch mode: [res_id] or active_ids or active_domain
if mass_mail_mode and wizard.use_active_domain and wizard.model:
res_ids = self.pool[wizard.model].search(cr, uid, eval(wizard.active_domain), context=context)
elif mass_mail_mode and wizard.model and active_ids:
res_ids = active_ids
else:
res_ids = [wizard.res_id]
for res_id in res_ids:
# mail.message values, according to the wizard options
post_values = {

View File

@ -12,6 +12,9 @@
<field name="model" invisible="1"/>
<field name="res_id" invisible="1"/>
<field name="parent_id" invisible="1"/>
<field name="mail_server_id" invisible="1"/>
<field name="use_active_domain" invisible="1"/>
<field name="active_domain" invisible="1"/>
<!-- visible wizard -->
<field name="email_from"
attrs="{'invisible':[('composition_mode', '!=', 'mass_mail')]}"/>

View File

@ -1,10 +1,10 @@
<openerp>
<data>
<record id="action_dummy" model="ir.actions.server">
<field name="name">Dummy Action</field>
<field name="name">Dummy Python Code</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="state">dummy</field>
<field name="code"/>
<field name="state">code</field>
<field name="code">True</field>
<field eval="5" name="sequence"/>
<field eval="True" name="condition"/>
</record>

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-11-28 14:03+0000\n"
"Last-Translator: hifly <Unknown>\n"
"PO-Revision-Date: 2013-08-02 05:54+0000\n"
"Last-Translator: Joshua Jan(SHINEIT) <popkar77@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:02+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-08-03 05:55+0000\n"
"X-Generator: Launchpad (build 16718)\n"
#. module: mrp
#: help:mrp.config.settings,module_mrp_repair:0
@ -199,7 +199,7 @@ msgstr "用于外购的物料"
#. module: mrp
#: model:ir.ui.menu,name:mrp.menu_mrp_production_order_action
msgid "Order Planning"
msgstr ""
msgstr "制造单计划"
#. module: mrp
#: field:mrp.config.settings,module_mrp_operations:0
@ -286,7 +286,7 @@ msgstr "从一个生产订单生产几个产品"
msgid ""
"The selection of the right Bill of Material to use will depend on the "
"properties specified on the sales order and the Bill of Material."
msgstr ""
msgstr "被正确使用的BOM依赖于销售单和BOM中指定的属性"
#. module: mrp
#: view:mrp.bom:0
@ -294,7 +294,7 @@ msgid ""
"When processing a sales order for this product, the delivery order\n"
" will contain the raw materials, instead of "
"the finished product."
msgstr ""
msgstr "当处理该产品的销售单时,发运单将以原料来替代成品"
#. module: mrp
#: report:mrp.production.order:0
@ -499,7 +499,7 @@ msgid "Scheduled Date"
msgstr "下单日期"
#. module: mrp
#: code:addons/mrp/procurement.py:124
#: code:addons/mrp/procurement.py:129
#, python-format
msgid "Manufacturing Order <em>%s</em> created."
msgstr "生产订单 <em>%s</em> 创建。"
@ -684,7 +684,7 @@ msgid "Work Center Load"
msgstr "工作中心负载"
#. module: mrp
#: code:addons/mrp/procurement.py:50
#: code:addons/mrp/procurement.py:55
#, python-format
msgid "No BoM defined for this product !"
msgstr "该产品尚未定义物料清单!"
@ -991,7 +991,7 @@ msgid "BoM Type"
msgstr "物料清单类型"
#. module: mrp
#: code:addons/mrp/procurement.py:52
#: code:addons/mrp/procurement.py:57
#, python-format
msgid ""
"Procurement '%s' has an exception: 'No BoM defined for this product !'"
@ -1120,7 +1120,7 @@ msgstr "生产订单"
#. module: mrp
#: selection:mrp.production,state:0
msgid "Awaiting Raw Materials"
msgstr ""
msgstr "等待原材料"
#. module: mrp
#: field:mrp.bom,position:0
@ -1774,8 +1774,8 @@ msgid ""
"the quantity selected and it will finish the production order when total "
"ordered quantities are produced."
msgstr ""
"'废料' 模式会仅消耗对应成品数量的原材料而无产成品产出。\n"
"'报工' 模式会消耗对应成品数量的原材料而且产出对应数量的产成品。"
"'投料' 模式会仅消耗对应成品数量的原材料暂无产成品产出。\n"
"'投料并产出' 模式会消耗对应成品数量的原材料并立即产出对应数量的产成品。"
#. module: mrp
#: view:mrp.production:0
@ -1981,7 +1981,7 @@ msgstr "新建"
#. module: mrp
#: selection:mrp.product.produce,mode:0
msgid "Consume Only"
msgstr "料"
msgstr "料"
#. module: mrp
#: view:mrp.production:0
@ -2161,7 +2161,7 @@ msgstr "用户"
#. module: mrp
#: selection:mrp.product.produce,mode:0
msgid "Consume & Produce"
msgstr "报工"
msgstr "投料并产出"
#. module: mrp
#: field:mrp.bom,bom_id:0

View File

@ -246,6 +246,7 @@ class mrp_production(osv.osv):
""" Cancels work order if production order is canceled.
@return: Super method
"""
workcenter_pool = self.pool.get('mrp.production.workcenter.line')
obj = self.browse(cr, uid, ids,context=context)[0]
for workcenter_line in obj.workcenter_lines:
workcenter_pool.signal_button_cancel(cr, uid, [workcenter_line.id])

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-04-24 06:41+0000\n"
"Last-Translator: viney <Unknown>\n"
"PO-Revision-Date: 2013-07-26 07:07+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: 2013-04-25 05:20+0000\n"
"X-Generator: Launchpad (build 16580)\n"
"X-Launchpad-Export-Date: 2013-07-27 05:02+0000\n"
"X-Generator: Launchpad (build 16700)\n"
#. module: point_of_sale
#: field:report.transaction.pos,product_nb:0
@ -51,7 +51,7 @@ msgstr "打印销售订单的收据"
#. module: point_of_sale
#: field:pos.session,cash_register_balance_end:0
msgid "Computed Balance"
msgstr ""
msgstr "计算余额"
#. module: point_of_sale
#: view:pos.session:0
@ -62,7 +62,7 @@ msgstr "今天"
#. module: point_of_sale
#: field:pos.config,iface_electronic_scale:0
msgid "Electronic Scale Interface"
msgstr ""
msgstr "电子称接口"
#. module: point_of_sale
#: model:pos.category,name:point_of_sale.plain_water
@ -85,7 +85,7 @@ msgstr ""
#: field:pos.config,journal_id:0
#: field:pos.order,sale_journal:0
msgid "Sale Journal"
msgstr ""
msgstr "销售日记账"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.spa_2l_product_template
@ -102,7 +102,7 @@ msgstr "销售详情"
#. module: point_of_sale
#: constraint:pos.config:0
msgid "You cannot have two cash controls in one Point Of Sale !"
msgstr ""
msgstr "同一个销售点不能使用两个钱箱"
#. module: point_of_sale
#: field:pos.payment.report.user,user_id:0
@ -111,7 +111,7 @@ msgstr ""
#: view:report.pos.order:0
#: field:report.pos.order,user_id:0
msgid "Salesperson"
msgstr ""
msgstr "销售员"
#. module: point_of_sale
#: view:report.pos.order:0
@ -128,13 +128,13 @@ msgstr "产品名称"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.pamplemousse_rouge_pamplemousse_product_template
msgid "Red grapefruit"
msgstr ""
msgstr "红葡萄柚"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:1343
#: code:addons/point_of_sale/point_of_sale.py:1373
#, python-format
msgid "Assign a Custom EAN"
msgstr ""
msgstr "使用自定义的条码"
#. module: point_of_sale
#: view:pos.session.opening:0
@ -164,12 +164,12 @@ msgstr "取钱"
#: code:addons/point_of_sale/point_of_sale.py:105
#, python-format
msgid "not used"
msgstr ""
msgstr "未被使用"
#. module: point_of_sale
#: field:pos.config,iface_vkeyboard:0
msgid "Virtual KeyBoard Interface"
msgstr ""
msgstr "虚拟键盘接口"
#. module: point_of_sale
#. openerp-web
@ -181,11 +181,11 @@ msgstr "+/-"
#. module: point_of_sale
#: field:pos.ean_wizard,ean13_pattern:0
msgid "Reference"
msgstr ""
msgstr "单号"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:1041
#: code:addons/point_of_sale/point_of_sale.py:1057
#: code:addons/point_of_sale/point_of_sale.py:1066
#: code:addons/point_of_sale/point_of_sale.py:1083
#: report:pos.invoice:0
#: report:pos.lines:0
#, python-format
@ -200,32 +200,32 @@ msgstr "开始日期"
#. module: point_of_sale
#: constraint:pos.session:0
msgid "You cannot create two active sessions with the same responsible!"
msgstr ""
msgstr "同一个负责人不能创建两个活动销售会话"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/static/src/xml/pos.xml:473
#, python-format
msgid "Weighting"
msgstr ""
msgstr "称重"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.fenouil_fenouil_product_template
msgid "Fennel"
msgstr ""
msgstr "小茴香"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/static/src/xml/pos.xml:472
#, python-format
msgid "Help needed"
msgstr ""
msgstr "需要帮助"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:739
#: code:addons/point_of_sale/point_of_sale.py:760
#, python-format
msgid "Configuration Error!"
msgstr ""
msgstr "设置错误!"
#. module: point_of_sale
#: report:account.statement:0
@ -237,7 +237,7 @@ msgstr "业务伙伴"
#. module: point_of_sale
#: view:pos.session:0
msgid "Closing Cash Control"
msgstr ""
msgstr "关闭现金箱"
#. module: point_of_sale
#: report:pos.details:0
@ -259,7 +259,7 @@ msgstr "会计信息"
#. module: point_of_sale
#: field:pos.session.opening,show_config:0
msgid "Show Config"
msgstr ""
msgstr "显示配置"
#. module: point_of_sale
#: report:pos.lines:0
@ -277,7 +277,7 @@ msgstr "折扣合计"
#: code:addons/point_of_sale/static/src/xml/pos.xml:441
#, python-format
msgid "Debug Window"
msgstr ""
msgstr "调试窗口"
#. module: point_of_sale
#. openerp-web
@ -315,10 +315,10 @@ msgid "Disc.(%)"
msgstr "折扣(%)"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:1006
#: code:addons/point_of_sale/point_of_sale.py:1031
#, python-format
msgid "Please define income account for this product: \"%s\" (id:%d)."
msgstr ""
msgstr "请为这个产品定义收益科目:\"%s\" (id:%d)."
#. module: point_of_sale
#: view:report.pos.order:0
@ -336,7 +336,7 @@ msgstr "Leffe Brune 33cl"
msgid ""
"Check this if this point of sale should open by default in a self checkout "
"mode. If unchecked, OpenERP uses the normal cashier mode by default."
msgstr ""
msgstr "如果需要把自助收银作为默认模式,请选中这里。 如果未选, OpenERP 将使用普通收银员作为默认模式。"
#. module: point_of_sale
#: model:ir.actions.report.xml,name:point_of_sale.pos_sales_user
@ -353,7 +353,7 @@ msgstr "饮料类"
#: model:ir.actions.act_window,name:point_of_sale.action_pos_session_opening
#: model:ir.ui.menu,name:point_of_sale.menu_pos_session_opening
msgid "Your Session"
msgstr ""
msgstr "您的销售会话"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.stella_50cl_product_template
@ -375,12 +375,12 @@ msgstr "上级类别"
#: code:addons/point_of_sale/static/src/xml/pos.xml:482
#, python-format
msgid "Open Cashbox"
msgstr ""
msgstr "打开钱箱"
#. module: point_of_sale
#: view:pos.session.opening:0
msgid "Select your Point of Sale"
msgstr ""
msgstr "选择您的销售点"
#. module: point_of_sale
#: field:report.sales.by.margin.pos,total:0
@ -404,25 +404,25 @@ msgstr "Dr. Oetker Ristorante Speciale"
#: code:addons/point_of_sale/static/src/xml/pos.xml:480
#, python-format
msgid "Payment Request"
msgstr ""
msgstr "付款请求"
#. module: point_of_sale
#: field:product.product,to_weight:0
msgid "To Weight"
msgstr ""
msgstr "需要称重"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/static/src/xml/pos.xml:476
#, python-format
msgid "Hardware Events"
msgstr ""
msgstr "硬件事件"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:301
#, python-format
msgid "You should assign a Point of Sale to your session."
msgstr ""
msgstr "您需要为您的销售会话指定一个销售点"
#. module: point_of_sale
#: view:pos.order.line:0
@ -435,7 +435,7 @@ msgid "Fanta Orange 33cl"
msgstr "Fanta Orange 33cl"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:420
#: code:addons/point_of_sale/point_of_sale.py:423
#, python-format
msgid ""
"Please set your profit and loss accounts on your payment method '%s'. This "
@ -446,10 +446,10 @@ msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:315
#: code:addons/point_of_sale/point_of_sale.py:512
#: code:addons/point_of_sale/point_of_sale.py:514
#, python-format
msgid "error!"
msgstr ""
msgstr "错误!"
#. module: point_of_sale
#: model:ir.actions.act_window,name:point_of_sale.action_report_sales_by_user_pos_month
@ -471,12 +471,12 @@ msgstr ""
#. module: point_of_sale
#: model:product.template,name:point_of_sale.Onions_product_template
msgid "Onions"
msgstr ""
msgstr "洋葱"
#. module: point_of_sale
#: view:pos.session:0
msgid "Validate & Open Session"
msgstr ""
msgstr "验证并打开销售会话"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:99
@ -484,18 +484,18 @@ msgstr ""
#: selection:pos.session.opening,pos_state:0
#, python-format
msgid "In Progress"
msgstr ""
msgstr "进行中"
#. module: point_of_sale
#: view:pos.session:0
#: field:pos.session,opening_details_ids:0
msgid "Opening Cash Control"
msgstr ""
msgstr "正在打开钱箱"
#. module: point_of_sale
#: help:res.users,ean13:0
msgid "BarCode"
msgstr ""
msgstr "条码"
#. module: point_of_sale
#: help:pos.category,image_medium:0
@ -508,19 +508,19 @@ msgstr ""
#. module: point_of_sale
#: view:pos.session.opening:0
msgid "Open Session"
msgstr ""
msgstr "打开销售会话"
#. module: point_of_sale
#: model:ir.ui.menu,name:point_of_sale.menu_point_of_sale
msgid "Daily Operations"
msgstr "每天经营"
msgstr "日常经营"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/static/src/xml/pos.xml:42
#, python-format
msgid "Google Chrome"
msgstr ""
msgstr "Google Chrome"
#. module: point_of_sale
#: model:pos.category,name:point_of_sale.sparkling_water
@ -543,7 +543,7 @@ msgstr "查询现金对账单"
#: field:pos.session.opening,pos_state_str:0
#: field:report.pos.order,state:0
msgid "Status"
msgstr ""
msgstr "状态"
#. module: point_of_sale
#: selection:report.pos.order,month:0
@ -568,14 +568,14 @@ msgstr "POS单明细"
#. module: point_of_sale
#: view:pos.config:0
msgid "Point of Sale Configuration"
msgstr ""
msgstr "销售点配置"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/static/src/xml/pos.xml:359
#, python-format
msgid "Your order has to be validated by a cashier."
msgstr ""
msgstr "您的订单已被收银员确认"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.fanta_orange_50cl_product_template
@ -609,7 +609,7 @@ msgid ""
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:867
#: code:addons/point_of_sale/point_of_sale.py:888
#, python-format
msgid "Customer Invoice"
msgstr "客户发票"
@ -619,7 +619,7 @@ msgstr "客户发票"
msgid ""
"You can continue sales from the touchscreen interface by clicking on \"Start "
"Selling\" or close the cash register session."
msgstr ""
msgstr "通过触摸屏幕的“开始销售”或者关闭钱箱之后您就可以继续进行销售。"
#. module: point_of_sale
#: report:account.statement:0
@ -631,7 +631,7 @@ msgstr "结束日期"
#. module: point_of_sale
#: view:pos.session:0
msgid "Opening Cashbox Lines"
msgstr ""
msgstr "正在打开钱箱"
#. module: point_of_sale
#: selection:report.pos.order,month:0
@ -678,7 +678,7 @@ msgstr "行号"
#: code:addons/point_of_sale/static/src/xml/pos.xml:453
#, python-format
msgid "Set Weight"
msgstr ""
msgstr "设置重量"
#. module: point_of_sale
#: view:account.bank.statement:0
@ -693,7 +693,7 @@ msgstr "净合计:"
#. module: point_of_sale
#: model:ir.actions.client,name:point_of_sale.action_client_pos_menu
msgid "Open POS Menu"
msgstr ""
msgstr "打开销售点菜单"
#. module: point_of_sale
#: report:pos.details_summary:0
@ -710,12 +710,12 @@ msgstr "发表POS机日记帐分录"
#: code:addons/point_of_sale/static/src/xml/pos.xml:457
#, python-format
msgid "Barcode Scanner"
msgstr ""
msgstr "条码扫描器"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.pomme_granny_smith_product_template
msgid "Granny Smith apples"
msgstr ""
msgstr "Granny Smith 苹果"
#. module: point_of_sale
#: help:product.product,expense_pdt:0
@ -743,7 +743,7 @@ msgstr ""
#. module: point_of_sale
#: view:pos.session.opening:0
msgid "Click to start a session."
msgstr ""
msgstr "单击开始销售会话"
#. module: point_of_sale
#: view:pos.details:0
@ -778,7 +778,7 @@ msgstr "新增产品"
#. module: point_of_sale
#: field:pos.config,name:0
msgid "Point of Sale Name"
msgstr ""
msgstr "销售点名称"
#. module: point_of_sale
#: field:report.transaction.pos,invoice_am:0
@ -825,7 +825,7 @@ msgstr "期末结余"
#: code:addons/point_of_sale/wizard/pos_box_out.py:89
#, python-format
msgid "please check that account is set to %s."
msgstr ""
msgstr "请检查该科目已经设为为:%s"
#. module: point_of_sale
#: help:pos.category,image:0
@ -863,7 +863,7 @@ msgstr ""
#. module: point_of_sale
#: view:pos.ean_wizard:0
msgid "Ean13 Generator"
msgstr ""
msgstr "条码生成器"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.spa_1l_product_template
@ -879,7 +879,7 @@ msgstr "错误无效的EAN编码"
#. module: point_of_sale
#: model:pos.category,name:point_of_sale.legumes_racine
msgid "Root vegetables"
msgstr ""
msgstr "根类蔬菜"
#. module: point_of_sale
#: model:ir.actions.act_window,name:point_of_sale.act_pos_open_statement
@ -939,7 +939,7 @@ msgstr ""
#. module: point_of_sale
#: view:res.users:0
msgid "Edit EAN"
msgstr ""
msgstr "编辑条码"
#. module: point_of_sale
#: code:addons/point_of_sale/wizard/pos_open_statement.py:80
@ -965,7 +965,7 @@ msgstr ""
#. module: point_of_sale
#: field:pos.session.opening,pos_session_id:0
msgid "PoS Session"
msgstr ""
msgstr "销售点会话"
#. module: point_of_sale
#: selection:report.pos.order,month:0
@ -979,7 +979,7 @@ msgid "User's Product"
msgstr "用户的产品"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:1143
#: code:addons/point_of_sale/point_of_sale.py:1173
#, python-format
msgid ""
"You have to select a pricelist in the sale form !\n"
@ -1011,7 +1011,7 @@ msgstr "增加一个全局折扣"
#. module: point_of_sale
#: view:pos.config:0
msgid "Journals"
msgstr ""
msgstr "日记账"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.oetker_prosciutto_product_template
@ -1031,7 +1031,7 @@ msgstr "Coca-Cola Light Lemon 50cl"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/point_of_sale.py:518
#: code:addons/point_of_sale/point_of_sale.py:520
#: code:addons/point_of_sale/static/src/xml/pos.xml:689
#: code:addons/point_of_sale/static/src/xml/pos.xml:744
#, python-format
@ -1041,7 +1041,7 @@ msgstr ""
#. module: point_of_sale
#: view:product.product:0
msgid "Set a Custom EAN"
msgstr ""
msgstr "设置自定义条码"
#. module: point_of_sale
#. openerp-web
@ -1053,7 +1053,7 @@ msgstr ""
#. module: point_of_sale
#: model:pos.category,name:point_of_sale.legumes
msgid "Fresh vegetables"
msgstr ""
msgstr "新鲜蔬菜"
#. module: point_of_sale
#: view:pos.session:0
@ -1065,7 +1065,7 @@ msgstr ""
#: code:addons/point_of_sale/static/src/xml/pos.xml:478
#, python-format
msgid "Scan Item Success"
msgstr ""
msgstr "扫描条目成功"
#. module: point_of_sale
#: report:account.statement:0
@ -1082,17 +1082,17 @@ msgstr ""
#. module: point_of_sale
#: sql_constraint:pos.session:0
msgid "The name of this POS Session must be unique !"
msgstr ""
msgstr "销售会话名称必须唯一"
#. module: point_of_sale
#: view:pos.session:0
msgid "Opening Subtotal"
msgstr ""
msgstr "小计"
#. module: point_of_sale
#: view:pos.session:0
msgid "payment method."
msgstr ""
msgstr "付款方式"
#. module: point_of_sale
#: view:pos.order:0
@ -1137,7 +1137,7 @@ msgstr "折扣"
#. module: point_of_sale
#: view:pos.order:0
msgid "(update)"
msgstr ""
msgstr "(更新)"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.ijsboerke_vanille_2,5l_product_template
@ -1153,12 +1153,12 @@ msgstr "销售详情"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.evian_2l_product_template
msgid "2L Evian"
msgstr ""
msgstr "2L 依云"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:373
#: code:addons/point_of_sale/point_of_sale.py:472
#: code:addons/point_of_sale/wizard/pos_session_opening.py:34
#: code:addons/point_of_sale/point_of_sale.py:474
#: code:addons/point_of_sale/wizard/pos_session_opening.py:33
#, python-format
msgid "Start Point Of Sale"
msgstr ""
@ -1215,14 +1215,14 @@ msgstr "Chaudfontaine Petillante 50cl"
#: code:addons/point_of_sale/static/src/xml/pos.xml:485
#, python-format
msgid "Read Weighting Scale"
msgstr ""
msgstr "读取电子秤"
#. module: point_of_sale
#. openerp-web
#: code:addons/point_of_sale/static/src/xml/pos.xml:426
#, python-format
msgid "0.00 €"
msgstr ""
msgstr "0.00 €"
#. module: point_of_sale
#: field:pos.order.line,create_date:0
@ -1240,7 +1240,7 @@ msgstr "今天的销售情况"
#: code:addons/point_of_sale/static/src/xml/pos.xml:324
#, python-format
msgid "Welcome"
msgstr ""
msgstr "欢迎"
#. module: point_of_sale
#: code:addons/point_of_sale/wizard/pos_box_entries.py:46
@ -1295,7 +1295,7 @@ msgstr "已开票合计"
#: model:ir.model,name:point_of_sale.model_pos_category
#: field:product.product,pos_categ_id:0
msgid "Point of Sale Category"
msgstr ""
msgstr "销售点商品分类"
#. module: point_of_sale
#: view:report.pos.order:0
@ -1315,7 +1315,7 @@ msgstr ""
#: code:addons/point_of_sale/static/src/xml/pos.xml:324
#, python-format
msgid "Choose your type of receipt:"
msgstr ""
msgstr "选择小票类型"
#. module: point_of_sale
#: model:ir.model,name:point_of_sale.model_report_sales_by_margin_pos_month
@ -1352,7 +1352,7 @@ msgstr ""
#: code:addons/point_of_sale/static/src/xml/pos.xml:479
#, python-format
msgid "Scan Item Unrecognized"
msgstr ""
msgstr "未能识别扫描的条目"
#. module: point_of_sale
#: report:all.closed.cashbox.of.the.day:0
@ -1360,7 +1360,7 @@ msgid "Today's Closed Cashbox"
msgstr "今日关闭的钱箱"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:897
#: code:addons/point_of_sale/point_of_sale.py:920
#, python-format
msgid "Selected orders do not have the same session!"
msgstr ""
@ -1396,7 +1396,7 @@ msgstr "开启日期"
#: model:ir.actions.act_window,name:point_of_sale.action_pos_session
#: model:ir.ui.menu,name:point_of_sale.menu_pos_session_all
msgid "All Sessions"
msgstr ""
msgstr "全部销售会话"
#. module: point_of_sale
#. openerp-web
@ -1415,7 +1415,7 @@ msgstr "税:"
#: code:addons/point_of_sale/static/src/xml/pos.xml:271
#, python-format
msgid "Thank you for shopping with us."
msgstr ""
msgstr "感谢您的光临。"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.coca_light_2l_product_template
@ -1431,7 +1431,7 @@ msgstr "Dr. Oetker Ristorante Funghi"
#: model:ir.actions.act_window,name:point_of_sale.pos_category_action
#: model:ir.ui.menu,name:point_of_sale.menu_pos_category
msgid "Product Categories"
msgstr ""
msgstr "商品类别"
#. module: point_of_sale
#: help:pos.config,journal_id:0
@ -1448,7 +1448,7 @@ msgstr "折扣"
#: code:addons/point_of_sale/static/src/xml/pos.xml:467
#, python-format
msgid "Invalid Ean"
msgstr ""
msgstr "无效的条码"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.lindemans_kriek_37,5cl_product_template
@ -1458,7 +1458,7 @@ msgstr "Lindemans Kriek 37.5cl"
#. module: point_of_sale
#: view:pos.config:0
msgid "Point of Sale Config"
msgstr ""
msgstr "销售点配置"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.coca_zero_33cl_product_template
@ -1511,7 +1511,7 @@ msgstr "税:"
#. module: point_of_sale
#: view:pos.session:0
msgid "+ Transactions"
msgstr ""
msgstr "+ 交易"
#. module: point_of_sale
#: model:ir.actions.act_window,name:point_of_sale.action_pos_discount
@ -1541,12 +1541,12 @@ msgstr "用户"
#: code:addons/point_of_sale/static/src/xml/pos.xml:194
#, python-format
msgid "Kg"
msgstr ""
msgstr "千克"
#. module: point_of_sale
#: field:product.product,available_in_pos:0
msgid "Available in the Point of Sale"
msgstr ""
msgstr "可在销售点销售"
#. module: point_of_sale
#: selection:pos.config,state:0
@ -1563,7 +1563,7 @@ msgstr ""
#: code:addons/point_of_sale/static/src/xml/pos.xml:338
#, python-format
msgid "The scanned product was not recognized"
msgstr ""
msgstr "无法识别扫描的商品"
#. module: point_of_sale
#: model:ir.model,name:point_of_sale.model_report_transaction_pos
@ -1613,7 +1613,7 @@ msgstr "11月"
#: code:addons/point_of_sale/static/src/xml/pos.xml:267
#, python-format
msgid "Please scan an item or your member card"
msgstr ""
msgstr "请扫描商品或您的会员卡"
#. module: point_of_sale
#: model:product.template,name:point_of_sale.poivron_verts_product_template
@ -1644,7 +1644,7 @@ msgid "Number of Transaction"
msgstr "交易数"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:738
#: code:addons/point_of_sale/point_of_sale.py:759
#, python-format
msgid ""
"There is no receivable account defined to make payment for the partner: "
@ -1655,7 +1655,7 @@ msgstr ""
#: view:pos.config:0
#: selection:pos.config,state:0
msgid "Inactive"
msgstr ""
msgstr "不活跃的"
#. module: point_of_sale
#. openerp-web
@ -1679,7 +1679,7 @@ msgstr "取消"
#: code:addons/point_of_sale/static/src/xml/pos.xml:296
#, python-format
msgid "Please put your product on the scale"
msgstr ""
msgstr "请将商品放到称上"
#. module: point_of_sale
#: model:ir.actions.report.xml,name:point_of_sale.pos_details_summary
@ -1699,7 +1699,7 @@ msgstr "Timmermans Kriek 37.5cl"
#. module: point_of_sale
#: field:pos.config,sequence_id:0
msgid "Order IDs Sequence"
msgstr ""
msgstr "订单号序列"
#. module: point_of_sale
#: report:pos.invoice:0
@ -1815,7 +1815,7 @@ msgid "Difference"
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:529
#: code:addons/point_of_sale/point_of_sale.py:549
#, python-format
msgid "Unable to Delete !"
msgstr "不能删除!"
@ -1978,7 +1978,7 @@ msgid "Salespeople"
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:756
#: code:addons/point_of_sale/point_of_sale.py:777
#: code:addons/point_of_sale/wizard/pos_box_entries.py:118
#: code:addons/point_of_sale/wizard/pos_box_out.py:91
#, python-format
@ -1986,7 +1986,7 @@ msgid "You have to open at least one cashbox."
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:1142
#: code:addons/point_of_sale/point_of_sale.py:1172
#, python-format
msgid "No Pricelist !"
msgstr "没有价格表!"
@ -2038,7 +2038,7 @@ msgid "No Cash Register Defined !"
msgstr "没有定义收银机"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:513
#: code:addons/point_of_sale/point_of_sale.py:515
#, python-format
msgid ""
"No cash statement found for this session. Unable to record returned cash."
@ -2761,7 +2761,7 @@ msgid "Pos Lines"
msgstr "销售单明细"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:413
#: code:addons/point_of_sale/point_of_sale.py:416
#, python-format
msgid "Point of Sale Profit"
msgstr ""
@ -2774,7 +2774,7 @@ msgid "Please wait, a cashier is on the way"
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/wizard/pos_session_opening.py:68
#: code:addons/point_of_sale/wizard/pos_session_opening.py:67
#: field:pos.box.entries,session_id:0
#: view:pos.order:0
#: field:pos.order,session_id:0
@ -3085,15 +3085,17 @@ msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:300
#: code:addons/point_of_sale/point_of_sale.py:409
#: code:addons/point_of_sale/point_of_sale.py:419
#: code:addons/point_of_sale/point_of_sale.py:457
#: code:addons/point_of_sale/point_of_sale.py:712
#: code:addons/point_of_sale/point_of_sale.py:756
#: code:addons/point_of_sale/point_of_sale.py:818
#: code:addons/point_of_sale/point_of_sale.py:897
#: code:addons/point_of_sale/point_of_sale.py:1006
#: code:addons/point_of_sale/point_of_sale.py:412
#: code:addons/point_of_sale/point_of_sale.py:422
#: code:addons/point_of_sale/point_of_sale.py:459
#: code:addons/point_of_sale/point_of_sale.py:536
#: code:addons/point_of_sale/point_of_sale.py:733
#: code:addons/point_of_sale/point_of_sale.py:777
#: code:addons/point_of_sale/point_of_sale.py:839
#: code:addons/point_of_sale/point_of_sale.py:920
#: code:addons/point_of_sale/point_of_sale.py:1031
#: code:addons/point_of_sale/report/pos_invoice.py:46
#: code:addons/point_of_sale/wizard/pos_box.py:23
#: code:addons/point_of_sale/wizard/pos_box.py:22
#: code:addons/point_of_sale/wizard/pos_box_entries.py:46
#: code:addons/point_of_sale/wizard/pos_box_entries.py:118
#: code:addons/point_of_sale/wizard/pos_box_entries.py:123
@ -3187,13 +3189,13 @@ msgid "Chaudfontaine 1.5l"
msgstr "Chaudfontaine 1.5l"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:1069
#: code:addons/point_of_sale/point_of_sale.py:1096
#, python-format
msgid "Trade Receivables"
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:529
#: code:addons/point_of_sale/point_of_sale.py:549
#, python-format
msgid "In order to delete a sale, it must be new or cancelled."
msgstr "只有新的或被取消的销售流水可以删除"
@ -3228,7 +3230,7 @@ msgid "Journal Entry"
msgstr "日记账簿"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:736
#: code:addons/point_of_sale/point_of_sale.py:757
#, python-format
msgid "There is no receivable account defined to make payment."
msgstr ""
@ -3259,7 +3261,7 @@ msgid "Supplier Invoice"
msgstr "供应商发票"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:458
#: code:addons/point_of_sale/point_of_sale.py:460
#, python-format
msgid ""
"You cannot confirm all orders of this session, because they have not the "
@ -3338,7 +3340,7 @@ msgid "Coca-Cola Regular 1L"
msgstr "Coca-Cola Regular 1L"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:712
#: code:addons/point_of_sale/point_of_sale.py:733
#, python-format
msgid "Unable to cancel the picking."
msgstr "无法取消发货"
@ -3379,7 +3381,7 @@ msgid "Spa Barisart 1.5l"
msgstr "Spa Barisart 1.5l"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:789
#: code:addons/point_of_sale/point_of_sale.py:810
#: view:pos.order:0
#, python-format
msgid "Return Products"
@ -3495,7 +3497,7 @@ msgid "Default Point of Sale"
msgstr ""
#. module: point_of_sale
#: code:addons/point_of_sale/wizard/pos_box.py:24
#: code:addons/point_of_sale/wizard/pos_box.py:23
#, python-format
msgid "There is no cash register for this PoS Session"
msgstr ""
@ -3539,7 +3541,7 @@ msgid "PRO-FORMA"
msgstr "形式发票"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:818
#: code:addons/point_of_sale/point_of_sale.py:839
#, python-format
msgid "Please provide a partner for the sale."
msgstr "请提供业务伙伴。"
@ -3591,7 +3593,7 @@ msgid "Print Receipt"
msgstr "打印收银条"
#. module: point_of_sale
#: code:addons/point_of_sale/point_of_sale.py:417
#: code:addons/point_of_sale/point_of_sale.py:420
#, python-format
msgid "Point of Sale Loss"
msgstr ""
@ -4020,6 +4022,7 @@ msgstr ""
#~ msgid "Discount percentage"
#~ msgstr "折扣百分比"
#, python-format
#~ msgid "Close"
#~ msgstr "关闭"
@ -4843,9 +4846,11 @@ msgstr ""
#~ msgid "Subtotal:"
#~ msgstr "小计:"
#, python-format
#~ msgid "Validate"
#~ msgstr "确认"
#, python-format
#~ msgid "Print"
#~ msgstr "打印"
@ -4931,6 +4936,7 @@ msgstr ""
#~ msgid "PoS Backend"
#~ msgstr "POS后端"
#, python-format
#~ msgid "Next Order"
#~ msgstr "下一订单"

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
"PO-Revision-Date: 2012-11-27 09:28+0000\n"
"Last-Translator: 盈通 ccdos <ccdos@163.com>\n"
"PO-Revision-Date: 2013-07-28 11:18+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: 2013-03-16 05:25+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-07-29 05:25+0000\n"
"X-Generator: Launchpad (build 16700)\n"
#. module: product
#: field:product.packaging,rows:0
@ -513,7 +513,7 @@ msgstr "标准耳机"
#. module: product
#: model:product.uom,name:product.product_uom_day
msgid "Day(s)"
msgstr ""
msgstr ""
#. module: product
#: help:product.product,incoming_qty:0
@ -800,7 +800,7 @@ msgstr "结束日期"
#. module: product
#: model:product.uom,name:product.product_uom_litre
msgid "Liter(s)"
msgstr ""
msgstr ""
#. module: product
#: view:product.price_list:0
@ -843,7 +843,7 @@ msgstr "价格表"
#. module: product
#: model:product.uom,name:product.product_uom_hour
msgid "Hour(s)"
msgstr ""
msgstr "小时"
#. module: product
#: selection:product.template,state:0
@ -1114,7 +1114,7 @@ msgstr "右父项"
#. module: product
#: field:product.product,price:0
msgid "Price"
msgstr ""
msgstr "价格"
#. module: product
#: field:product.pricelist.item,price_surcharge:0
@ -1192,7 +1192,7 @@ msgstr "显示产品列表的顺序号"
#. module: product
#: model:product.uom,name:product.product_uom_dozen
msgid "Dozen(s)"
msgstr ""
msgstr ""
#. module: product
#: field:product.uom,factor:0
@ -1338,7 +1338,7 @@ msgstr "指定一个产品分类 ,规则只被应用在与这个分类以及
#. module: product
#: view:product.product:0
msgid "Inventory"
msgstr "盘点"
msgstr "库存"
#. module: product
#: field:product.product,seller_info_id:0
@ -1346,7 +1346,7 @@ msgid "Supplier Info"
msgstr "供应商信息"
#. module: product
#: code:addons/product/product.py:729
#: code:addons/product/product.py:732
#, python-format
msgid "%s (copy)"
msgstr "%s (副本)"
@ -1891,7 +1891,7 @@ msgstr "消息"
#. module: product
#: model:product.uom,name:product.product_uom_unit
msgid "Unit(s)"
msgstr ""
msgstr ""
#. module: product
#: code:addons/product/product.py:176
@ -2341,7 +2341,7 @@ msgstr "序列"
msgid ""
"Average delay in days to produce this product. In the case of multi-level "
"BOM, the manufacturing lead times of the components will be added."
msgstr ""
msgstr "生成该产品的平均延时天数。在多级BoM的情况下部件的制造提前期将被累加"
#. module: product
#: model:product.template,name:product.product_assembly_product_template
@ -2364,6 +2364,8 @@ msgid ""
" </p>\n"
" "
msgstr ""
"单击以创建一个新的计量单位\n"
" "
#. module: product
#: model:product.template,name:product.product_product_11_product_template
@ -2444,7 +2446,7 @@ msgid "15” LCD Monitor"
msgstr "15” LCD 显示器"
#. module: product
#: code:addons/product/pricelist.py:376
#: code:addons/product/pricelist.py:379
#: field:product.pricelist.item,base_pricelist_id:0
#, python-format
msgid "Other Pricelist"

File diff suppressed because it is too large Load Diff