[MERGE] Merged with addons/trunk, with lots of conflicts to solve...
bzr revid: tde@openerp.com-20120920074850-7p7or1ze8555fya5
This commit is contained in:
commit
bcbae5e277
|
@ -13,7 +13,7 @@
|
|||
<field name="groups_id" eval="[(5,)]"/>
|
||||
</record>
|
||||
|
||||
<record id="config_default_template_user" model="ir.config_parameter">
|
||||
<record id="default_template_user_config" model="ir.config_parameter">
|
||||
<field name="key">auth_signup.template_user_id</field>
|
||||
<field name="value" ref="default_template_user"/>
|
||||
</record>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Calendar Layer',
|
||||
'name': 'Calendar',
|
||||
'version': '1.0',
|
||||
'depends': ['base', 'base_status', 'mail', 'base_action_rule'],
|
||||
'description': """
|
||||
|
@ -51,6 +51,7 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
],
|
||||
'test' : ['test/base_calendar_test.yml'],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'certificate': '00694071962960352821',
|
||||
'images': ['images/base_calendar1.jpeg','images/base_calendar2.jpeg','images/base_calendar3.jpeg','images/base_calendar4.jpeg',],
|
||||
|
|
|
@ -1431,7 +1431,10 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
if r['class']=='private':
|
||||
for f in r.keys():
|
||||
if f not in ('id','date','date_deadline','duration','user_id','state'):
|
||||
r[f] = False
|
||||
if isinstance(r[f], list):
|
||||
r[f] = []
|
||||
else:
|
||||
r[f] = False
|
||||
if f=='name':
|
||||
r[f] = _('Busy')
|
||||
|
||||
|
|
|
@ -428,5 +428,6 @@
|
|||
name="Events" parent="base.menu_calendar_configuration"
|
||||
sequence="15" action="action_view_event"/>
|
||||
|
||||
<menuitem name="Agenda" id="mail_menu_agenda" parent="mail.mail_my_stuff" sequence="10" action="action_view_event"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -53,7 +53,7 @@ class crm_meeting(base_state, osv.Model):
|
|||
'partner_ids': fields.many2many('res.partner', 'crm_meeting_partner_rel', 'meeting_id','partner_id',
|
||||
string='Attendees', states={'done': [('readonly', True)]}),
|
||||
'state': fields.selection(
|
||||
[('draft', 'Unconfirmed'), ('open', 'Confirmed'), ('cancel', 'Cancelled'), ('done', 'Done')],
|
||||
[('draft', 'Unconfirmed'), ('open', 'Confirmed')],
|
||||
string='Status', size=16, readonly=True),
|
||||
# Meeting fields
|
||||
'name': fields.char('Meeting Subject', size=128, required=True, states={'done': [('readonly', True)]}),
|
||||
|
|
|
@ -69,9 +69,7 @@
|
|||
<field name="model">crm.meeting</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Meetings" version="7.0">
|
||||
<header>
|
||||
<field name="state" invisible="True"/>
|
||||
</header>
|
||||
<field name="state" invisible="True"/>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
|
@ -69,7 +69,7 @@ class base_stage(object):
|
|||
return False
|
||||
return uid
|
||||
|
||||
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
|
||||
def onchange_partner_address_id(self, cr, uid, ids, add, email=False, context=None):
|
||||
""" This function returns value of partner email based on Partner Address
|
||||
:param add: Id of Partner's address
|
||||
:param email: Partner's email ID
|
||||
|
@ -77,10 +77,20 @@ class base_stage(object):
|
|||
data = {'value': {'email_from': False, 'phone':False}}
|
||||
if add:
|
||||
address = self.pool.get('res.partner').browse(cr, uid, add)
|
||||
data['value'] = {'email_from': address and address.email or False ,
|
||||
'phone': address and address.phone or False}
|
||||
if 'phone' not in self._columns:
|
||||
del data['value']['phone']
|
||||
data['value'] = {'partner_name': address and address.name or False,
|
||||
'email_from': address and address.email or False,
|
||||
'phone': address and address.phone or False,
|
||||
'street': address and address.street or False,
|
||||
'street2': address and address.street2 or False,
|
||||
'city': address and address.city or False,
|
||||
'state_id': address.state_id and address.state_id.id or False,
|
||||
'zip': address and address.zip or False,
|
||||
'country_id': address.country_id and address.country_id.id or False,
|
||||
}
|
||||
fields = self.fields_get(cr, uid, context=context or {})
|
||||
for key in data['value'].keys():
|
||||
if key not in fields:
|
||||
del data['value'][key]
|
||||
return data
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part, email=False):
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Address Book',
|
||||
'version': '1.0',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
This module gives you a quick view of your address book, accessible from your home page.
|
||||
You can track your suppliers, customers and other contacts.
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'website': 'http://openerp.com',
|
||||
'summary': 'Contacts, People and Companies',
|
||||
'depends': [
|
||||
'mail',
|
||||
],
|
||||
'data': [
|
||||
'contacts_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" ?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="action_contacts" model="ir.actions.act_window">
|
||||
<field name="name">Contacts</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.partner</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="search_view_id" ref="base.view_res_partner_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a contact in your address book.
|
||||
</p><p>
|
||||
OpenERP helps you easily track all activities related to
|
||||
a customer; discussions, history of business opportunities,
|
||||
documents, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_contacts_view_kanban" model="ir.actions.act_window.view">
|
||||
<field eval="0" name="sequence"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="base.res_partner_kanban_view"/>
|
||||
<field name="act_window_id" ref="action_contacts"/>
|
||||
</record>
|
||||
<record id="action_contacts_view_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="base.view_partner_tree"/>
|
||||
<field name="act_window_id" ref="action_contacts"/>
|
||||
</record>
|
||||
<record id="action_contacts_view_form" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="base.view_partner_form"/>
|
||||
<field name="act_window_id" ref="action_contacts"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Contacts"
|
||||
id="menu_contacts"
|
||||
parent="mail.mail_my_stuff"
|
||||
sequence="11"
|
||||
action="action_contacts"
|
||||
groups="base.group_user,base.group_partner_manager"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
|
@ -25,7 +25,7 @@
|
|||
'version': '1.0',
|
||||
'category': 'Customer Relationship Management',
|
||||
'sequence': 2,
|
||||
'summary': 'Leads, Opportunities, Agenda',
|
||||
'summary': 'Leads, Opportunities, Phone Calls',
|
||||
'description': """
|
||||
The generic OpenERP Customer Relationship Management
|
||||
=====================================================
|
||||
|
|
|
@ -92,9 +92,10 @@ class crm_case_stage(osv.osv):
|
|||
_defaults = {
|
||||
'sequence': lambda *args: 1,
|
||||
'probability': lambda *args: 0.0,
|
||||
'state': 'draft',
|
||||
'state': 'open',
|
||||
'fold': False,
|
||||
'type': 'both',
|
||||
'case_default': True,
|
||||
}
|
||||
|
||||
class crm_case_section(osv.osv):
|
||||
|
|
|
@ -104,57 +104,55 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Phone Call" version="7.0">
|
||||
<header>
|
||||
<button name="case_close" string="Held" type="object" class="oe_highlight"
|
||||
<button name="case_close" string="Call Done" type="object" class="oe_highlight"
|
||||
states="open,pending"/>
|
||||
<button name="case_reset" string="Reset to Todo" type="object"
|
||||
states="cancel"/>
|
||||
<button string="Convert to Opportunity"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
type="action"
|
||||
attrs="{'invisible':[ '|', ('opportunity_id','!=',False), ('state','!=', 'open')]}"/>
|
||||
<button string="Convert to Opportunity" class="oe_highlight"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
type="action"
|
||||
attrs="{'invisible':[ '|', ('opportunity_id','!=',False), ('state','!=', 'done')]}"/>
|
||||
<button string="Schedule Other Call"
|
||||
name="%(phonecall_to_phonecall_act)d"
|
||||
type="action"/>
|
||||
<button string="Schedule a Meeting" name="action_make_meeting" type="object"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="open,done"/>
|
||||
</header>
|
||||
<sheet string="Phone Call">
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name" string="Title"/>
|
||||
</div>
|
||||
<h1><field name="name" required="1"/></h1>
|
||||
<div class="oe_edit_only">
|
||||
<label for="partner_phone" string="Phone"/>
|
||||
</div>
|
||||
<h2><field name="partner_phone"/></h2>
|
||||
</div>
|
||||
<group col="4">
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
<field name="duration" widget="float_time"/>
|
||||
<field name="section_id" colspan="1" widget="selection"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="categ_id" widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.phonecall')]"/>
|
||||
<field name="partner_mobile"/>
|
||||
<field name="priority"/>
|
||||
<field name="opportunity_id"/>
|
||||
</group>
|
||||
|
||||
<field name="description" placeholder="Description..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
<sheet string="Phone Call">
|
||||
<div class="oe_right">
|
||||
<button string="Convert to Opportunity"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
type="action"
|
||||
attrs="{'invisible':[ '|', ('opportunity_id','!=',False), ('state', 'not in', ('open', 'done'))]}"/>
|
||||
<button string="Schedule Other Call"
|
||||
name="%(phonecall_to_phonecall_act)d"
|
||||
type="action"/>
|
||||
<button string="Schedule a Meeting" name="action_make_meeting" type="object"/>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<div class="oe_edit_only">
|
||||
<label for="name" string="Title"/>
|
||||
</div>
|
||||
<h1><field name="name" required="1"/></h1>
|
||||
<div class="oe_edit_only">
|
||||
<label for="partner_phone" string="Phone"/>
|
||||
</div>
|
||||
<h2><field name="partner_phone"/></h2>
|
||||
</div>
|
||||
|
||||
<group col="4">
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
<field name="duration" widget="float_time"/>
|
||||
<field name="section_id" colspan="1" widget="selection"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="categ_id" widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.phonecall')]"/>
|
||||
<field name="partner_mobile"/>
|
||||
<field name="priority"/>
|
||||
<field name="opportunity_id"/>
|
||||
</group>
|
||||
<field name="description" placeholder="Description..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -130,10 +130,10 @@
|
|||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button type="action"
|
||||
string="Schedule a Meeting"
|
||||
string="Meetings"
|
||||
name="%(base_calendar.action_crm_meeting)d"
|
||||
context="{'search_default_partner_ids': active_id, 'default_partner_ids' : [active_id]}"/>
|
||||
<button type="action" string="Schedule a Call"
|
||||
<button type="action" string="Calls"
|
||||
name="%(crm.crm_case_categ_phone_create_partner)d"
|
||||
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}" />
|
||||
<button type="action" string="Opportunities" attrs="{'invisible': [('customer', '=', False)]}"
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
# Icelandic translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
|
||||
"PO-Revision-Date: 2012-09-19 10:00+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Icelandic <is@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: 2012-09-20 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 15985)\n"
|
||||
|
||||
#. module: google_map
|
||||
#: view:res.partner:0
|
||||
msgid "Map"
|
||||
msgstr "Landakort"
|
||||
|
||||
#. module: google_map
|
||||
#: model:ir.model,name:google_map.model_res_partner_address
|
||||
msgid "Partner Addresses"
|
||||
msgstr "Heimilisfang viðskiptaaðila"
|
||||
|
||||
#. module: google_map
|
||||
#: view:res.partner:0
|
||||
msgid "Street2 : "
|
||||
msgstr "Gata2 : "
|
|
@ -444,11 +444,9 @@ class sugar_import(import_framework):
|
|||
import Tasks
|
||||
"""
|
||||
task_state = {
|
||||
'Completed' : 'done',
|
||||
'Completed' : 'open',
|
||||
'Not Started':'draft',
|
||||
'In Progress': 'open',
|
||||
'Pending Input': 'draft',
|
||||
'deferred': 'cancel'
|
||||
}
|
||||
|
||||
def import_task(self, val):
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
sequence="10"/>
|
||||
|
||||
<!-- Left-side menu: Feeds -->
|
||||
<menuitem id="mail_feeds" name="Feeds" parent="mail_feeds_main" groups="base.group_user" sequence="10"/>
|
||||
<menuitem id="mail_feeds" name="Feeds" parent="mail.mail_feeds_main" groups="base.group_user" sequence="10"/>
|
||||
<menuitem id="mail_my_stuff" name="Organizer" parent="mail.mail_feeds_main"/>
|
||||
|
||||
<record id="mail_wallfeeds" model="ir.ui.menu">
|
||||
<field name="name">My Feeds</field>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Memos',
|
||||
'name': 'Notes',
|
||||
'version': '1.0',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
|
@ -28,12 +28,12 @@ This module allows users to create their own notes inside OpenERP
|
|||
=================================================================
|
||||
|
||||
Use notes to write meeting minutes, organize ideas, organize personnal todo
|
||||
lists, etc. Each user manages his own personnal memos. Notes are available to
|
||||
lists, etc. Each user manages his own personnal Notes. Notes are available to
|
||||
their authors only, but they can share notes to others users so that several
|
||||
people can work on the same note in real time. It's very efficient to share
|
||||
meeting minutes.
|
||||
|
||||
Memos can be found in the 'Home' menu.
|
||||
Notes can be found in the 'Home' menu.
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'website': 'http://openerp.com',
|
||||
|
|
|
@ -63,11 +63,8 @@ class note_note(osv.osv):
|
|||
def _get_note_first_line(self, cr, uid, ids, name="", args={}, context=None):
|
||||
res = {}
|
||||
for note in self.browse(cr, uid, ids, context=context):
|
||||
text_note = (note.memo or '').strip().split('\n')[0]
|
||||
text_note = re.sub(r'(\S?)(<br[ /]*>|<[/]?p>|<[/]?div>|<table>)[\s\S]*',r'\1',text_note)
|
||||
text_note = re.sub(r'<[^>]+>','',text_note)
|
||||
text_note = html2plaintext(text_note)
|
||||
res[note.id] = text_note
|
||||
res[note.id] = (note.memo and html2plaintext(note.memo) or "").strip().replace('*','').split("\n")[0]
|
||||
|
||||
return res
|
||||
|
||||
#unactivate a sticky note and record the date
|
||||
|
@ -98,7 +95,8 @@ class note_note(osv.osv):
|
|||
def _set_stage_per_user(self, cr, uid, id, name, value, args=None, context=None):
|
||||
note = self.browse(cr, uid, id, context=context)
|
||||
if not value: return False
|
||||
return self.write(cr, uid, [id], {'stage_ids': [(4, value)]}, context=context)
|
||||
stage_ids = [value] + [stage.id for stage in note.stage_ids if stage.user_id.id != uid ]
|
||||
return self.write(cr, uid, [id], {'stage_ids': [(6, 0, stage_ids)]}, context=context)
|
||||
|
||||
def _get_stage_per_user(self, cr, uid, ids, name, args, context=None):
|
||||
result = dict.fromkeys(ids, False)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
<record id="note_1" model="note.note">
|
||||
<field name="name">Customer report #349872</field>
|
||||
<field name="memo"><![CDATA[Customer report #349872
|
||||
<field name="memo"><![CDATA[<b>Customer report #349872</b>
|
||||
<br/><br/>* Calendar app in Home
|
||||
<br/>* The base_calendar module should create a menu in Home, like described above.
|
||||
<br/>* This module should become a main application (in the first screen at installation)
|
||||
|
@ -40,7 +40,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_2" model="note.note">
|
||||
<field name="memo"><![CDATA[Call Fabien
|
||||
<field name="memo"><![CDATA[<b>Call Fabien</b>
|
||||
<br/><br/>* Followed by the telephone conversation and mail about D.544.3
|
||||
]]>
|
||||
</field>
|
||||
|
@ -48,21 +48,21 @@
|
|||
</record>
|
||||
|
||||
<record id="note_3" model="note.note">
|
||||
<field name="memo"><![CDATA[Call Marc
|
||||
<field name="memo"><![CDATA[<b>Call Marc</b>
|
||||
<br/><br/>]]>
|
||||
</field>
|
||||
<field name="stage_id" ref="note_stage_01"/>
|
||||
</record>
|
||||
|
||||
<record id="note_4" model="note.note">
|
||||
<field name="memo"><![CDATA[Project N.947.5
|
||||
<field name="memo"><![CDATA[<b>Project N.947.5</b>
|
||||
<br/><br/>]]>
|
||||
</field>
|
||||
<field name="stage_id" ref="note_stage_02"/>
|
||||
</record>
|
||||
|
||||
<record id="note_5" model="note.note">
|
||||
<field name="memo"><![CDATA[Shop for family dinner
|
||||
<field name="memo"><![CDATA[<b>Shop for family dinner</b>
|
||||
<br/>* stuffed turkey
|
||||
<br/>* wine
|
||||
]]>
|
||||
|
@ -71,7 +71,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_6" model="note.note">
|
||||
<field name="memo"><![CDATA[Idea to develop
|
||||
<field name="memo"><![CDATA[<b>Idea to develop</b>
|
||||
<br/><br/>* Create a module note_pad
|
||||
it transforms the html editable memo text field into widget='pad', similar to project_pad depends on 'memo' and 'pad' modules
|
||||
]]>
|
||||
|
@ -80,7 +80,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_7" model="note.note">
|
||||
<field name="memo"><![CDATA[Read some documentation about OpenERP before diving into the code
|
||||
<field name="memo"><![CDATA[<b>Read some documentation about OpenERP before diving into the code</b>
|
||||
<br/><br/>* Open ERP: a modern approach to integrated business management
|
||||
<br/>* Open ERP for Retail and Industrial Management
|
||||
]]>
|
||||
|
@ -89,7 +89,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_8" model="note.note">
|
||||
<field name="memo"><![CDATA[New computer specs
|
||||
<field name="memo"><![CDATA[<b>New computer specs</b>
|
||||
<br/><br/>* Motherboard
|
||||
according to processor
|
||||
<br/>* Processor
|
||||
|
@ -111,7 +111,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_9" model="note.note">
|
||||
<field name="memo"><![CDATA[Read those books
|
||||
<field name="memo"><![CDATA[<b>Read those books</b>
|
||||
<br/><br/>* Open ERP: a modern approach to integrated business management
|
||||
<br/>* Open ERP for Retail and Industrial Management
|
||||
]]>
|
||||
|
@ -120,7 +120,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_10" model="note.note">
|
||||
<field name="memo"><![CDATA[Read some documentation about OpenERP before diving into the code
|
||||
<field name="memo"><![CDATA[<b>Read some documentation about OpenERP before diving into the code</b>
|
||||
<br/><br/>* Open ERP: a modern approach to integrated business management
|
||||
<br/>* Open ERP for Retail and Industrial Management
|
||||
]]>
|
||||
|
@ -129,7 +129,7 @@
|
|||
</record>
|
||||
|
||||
<record id="note_12" model="note.note">
|
||||
<field name="memo"><![CDATA[Read some documentation about OpenERP before diving into the code
|
||||
<field name="memo"><![CDATA[<b>Read some documentation about OpenERP before diving into the code</b>
|
||||
<br/><br/>* Open ERP: a modern approach to integrated business management
|
||||
<br/>* Open ERP for Retail and Industrial Management
|
||||
]]>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<menuitem name="Organizer" id="note_my_stuff" parent="mail.mail_feeds_main"/>
|
||||
|
||||
<!-- note Stage Form View -->
|
||||
<record model="ir.ui.view" id="view_note_stage_form">
|
||||
<field name="name">note.stage.form</field>
|
||||
|
@ -38,8 +36,6 @@
|
|||
<field name="domain">[('user_id','=',uid)]</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Categories" id="menu_notes_stage" parent="note_my_stuff" action="action_note_stage" sequence="40" groups="base.group_no_one"/>
|
||||
|
||||
<!-- New note Kanban View -->
|
||||
<record model="ir.ui.view" id="view_note_note_kanban">
|
||||
<field name="name">note.note.kanban</field>
|
||||
|
@ -117,12 +113,10 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Note" version="7.0">
|
||||
<header>
|
||||
<field name="tag_ids" widget="many2many_tags" class="oe_inline" placeholder="Tags"/>
|
||||
<field name="stage_id" domain="[('user_id','=',uid)]" widget="statusbar" clickable="1"/>
|
||||
</header>
|
||||
<field name="memo" widget="html"/><!-- editor_width="100%%" editor_height="60%%" -->
|
||||
<group groups="note.group_note_tags" col="2">
|
||||
<field name="tag_ids" widget="many2many_tags"/>
|
||||
</group>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
|
@ -188,7 +182,8 @@
|
|||
<field name="context">{'search_default_open_true':True}</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Notes" id="note_notes" parent="note_my_stuff" sequence="20" action="action_note_note"/>
|
||||
<menuitem name="Notes" id="menu_note_notes" parent="mail.mail_my_stuff" sequence="20" action="note.action_note_note"/>
|
||||
<menuitem name="Categories" id="menu_notes_stage" parent="mail.mail_my_stuff" action="note.action_note_stage" sequence="21" groups="base.group_no_one"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -31,11 +31,5 @@ class note_pad_note(osv.osv):
|
|||
_pad_fields = ['note_pad']
|
||||
|
||||
_columns = {
|
||||
'note_pad_url': fields.char('Pad Url',
|
||||
pad_content_field='memo',
|
||||
size=250 ),
|
||||
}
|
||||
|
||||
#_defaults = {
|
||||
# 'note_pad_url': lambda self, cr, uid, context: self.pad_generate_url(cr, uid, context),
|
||||
#}
|
||||
'note_pad_url': fields.char('Pad Url', pad_content_field='memo'),
|
||||
}
|
|
@ -21,7 +21,7 @@ class pad_common(osv.osv_memory):
|
|||
s = string.ascii_uppercase + string.digits
|
||||
salt = ''.join([s[random.randint(0, len(s) - 1)] for i in range(10)])
|
||||
# contruct the url
|
||||
url = '%s/p/%s-%s-%s' % (pad_server, cr.dbname, self._name, salt)
|
||||
url = '%s/p/%s-%s-%s' % (pad_server, cr.dbname.replace('_','-'), self._name, salt)
|
||||
return url
|
||||
|
||||
def pad_get_content(self, cr, uid, url, context=None):
|
||||
|
@ -35,22 +35,21 @@ class pad_common(osv.osv_memory):
|
|||
|
||||
# TODO
|
||||
# reverse engineer protocol to be setHtml without using the api key
|
||||
# override read and copy to generate url and store the content if empty
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
data = super(pad_common, self).default_get(cr, uid, fields, context)
|
||||
for k in fields:
|
||||
field = self._all_columns[k].column
|
||||
if hasattr(field,'pad_content_field'):
|
||||
data[k] = self.pad_generate_url(cr, uid, context=context)
|
||||
return data
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
self._set_pad_value(cr, uid, vals, context)
|
||||
return super(pad_common, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
self._set_pad_value(cr, uid, vals, context)
|
||||
return super(pad_common, self).create(cr, uid, vals, context=context)
|
||||
|
||||
# Set the pad content in vals
|
||||
def _set_pad_value(self, cr, uid, vals, context=None):
|
||||
for k,v in vals.items():
|
||||
field = self._all_columns[k].column
|
||||
if hasattr(field,'pad_content_field'):
|
||||
vals[field.pad_content_field] = self.pad_get_content(cr, uid, v, context=context)
|
||||
return super(pad_common, self).write(cr, uid, ids, vals, context=context)
|
||||
vals[field.pad_content_field] = self.pad_get_content(cr, uid, v, context=context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if not default:
|
||||
|
|
|
@ -16,8 +16,15 @@ instance.web.form.FieldPad = instance.web.form.AbstractField.extend({
|
|||
var self = this;
|
||||
var _super = self._super;
|
||||
_super.apply(self,[val]);
|
||||
if (val === false || val === "") {
|
||||
self.field_manager.dataset.call('pad_generate_url').then(function(r) {
|
||||
_super.apply(self,[r]);
|
||||
self.render_value();
|
||||
});
|
||||
} else {
|
||||
self.render_value();
|
||||
}
|
||||
this._dirty_flag = true;
|
||||
self.render_value();
|
||||
},
|
||||
render_value: function() {
|
||||
console.log("display");
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
# Icelandic translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-09 00:36+0000\n"
|
||||
"PO-Revision-Date: 2012-09-19 10:08+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Icelandic <is@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: 2012-09-20 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 15985)\n"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: field:plugin_thunderbird.installer,pdf_file:0
|
||||
msgid "Installation Manual"
|
||||
msgstr "Uppsetningarhandbók"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: field:plugin_thunderbird.installer,description:0
|
||||
msgid "Description"
|
||||
msgstr "Lýsing"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: view:plugin_thunderbird.installer:0
|
||||
msgid "title"
|
||||
msgstr "titill"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: model:ir.model,name:plugin_thunderbird.model_plugin_thunderbird_installer
|
||||
msgid "plugin_thunderbird.installer"
|
||||
msgstr "plugin_thunderbird.installer"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: field:plugin_thunderbird.installer,config_logo:0
|
||||
msgid "Image"
|
||||
msgstr "Mynd"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: field:plugin_thunderbird.installer,plugin_file:0
|
||||
#: field:plugin_thunderbird.installer,thunderbird:0
|
||||
msgid "Thunderbird Plug-in"
|
||||
msgstr "Thunderbird viðbót"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: view:plugin_thunderbird.installer:0
|
||||
msgid ""
|
||||
"This plug-in allows you to link your email to OpenERP's documents. You can "
|
||||
"attach it to any existing one in OpenERP or create a new one."
|
||||
msgstr ""
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: help:plugin_thunderbird.installer,thunderbird:0
|
||||
msgid ""
|
||||
"Allows you to select an object that you would like to add to your email and "
|
||||
"its attachments."
|
||||
msgstr ""
|
||||
"Gerir þér kleift að velja hlut sem þú vilt bæta við póstinn og viðhengi hans."
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: help:plugin_thunderbird.installer,pdf_file:0
|
||||
msgid "The documentation file :- how to install Thunderbird Plug-in."
|
||||
msgstr "Handbókin :- hvernig á að setja inn Thunderbird viðbót."
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: view:plugin_thunderbird.installer:0
|
||||
msgid "_Close"
|
||||
msgstr "_Loka"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: view:plugin_thunderbird.installer:0
|
||||
msgid "Installation and Configuration Steps"
|
||||
msgstr ""
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: field:plugin_thunderbird.installer,name:0
|
||||
#: field:plugin_thunderbird.installer,pdf_name:0
|
||||
msgid "File name"
|
||||
msgstr "Skrárheiti"
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: help:plugin_thunderbird.installer,plugin_file:0
|
||||
msgid ""
|
||||
"Thunderbird plug-in file. Save as this file and install this plug-in in "
|
||||
"thunderbird."
|
||||
msgstr ""
|
||||
"Skrá með Thunderbird viðbót. Vistaðu skrána og settu viðbótina inn í "
|
||||
"Thunderbird."
|
||||
|
||||
#. module: plugin_thunderbird
|
||||
#: model:ir.actions.act_window,name:plugin_thunderbird.action_thunderbird_installer
|
||||
#: model:ir.ui.menu,name:plugin_thunderbird.menu_base_config_plugins_thunderbird
|
||||
#: view:plugin_thunderbird.installer:0
|
||||
msgid "Install Thunderbird Plug-In"
|
||||
msgstr "Setja inn Thunderbird viðbót"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "This plug-in allows you to link your e-mail to OpenERP's documents. You can "
|
||||
#~ "attach it to any existing one in OpenERP or create a new one."
|
||||
#~ msgstr ""
|
||||
#~ "Þessi viðbót gerir þér kleift að tengja tölvupóst við OpenERP skjöl. Þú "
|
||||
#~ "getur viðhengt póstinn við skjöl sem þegar eru til í OpenERP eða búið til "
|
||||
#~ "nýtt."
|
|
@ -43,7 +43,7 @@ class mail_mail_portal(osv.Model):
|
|||
:param partner: browse_record of the specific recipient partner
|
||||
"""
|
||||
if partner:
|
||||
portal_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal')
|
||||
portal_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal')
|
||||
portal_id = portal_ref and portal_ref[1] or False
|
||||
url = self._generate_signin_url(cr, uid, partner.id, portal_id, 1234, context=context)
|
||||
body = tools.append_content_to_html(mail.body_html, url)
|
||||
|
|
|
@ -20,196 +20,14 @@
|
|||
##############################################################################
|
||||
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
|
||||
|
||||
|
||||
class portal(osv.osv):
|
||||
""" A portal is simply a group of users with the flag 'is_portal' set to True.
|
||||
The flag 'is_portal' makes a user group usable as a portal.
|
||||
"""
|
||||
A portal is a group of users with specific menu, widgets, and typically
|
||||
restricted access rights.
|
||||
"""
|
||||
_name = 'res.portal'
|
||||
_description = 'Portal'
|
||||
_inherits = {'res.groups': 'group_id'}
|
||||
|
||||
_inherit = 'res.groups'
|
||||
_columns = {
|
||||
'group_id': fields.many2one('res.groups', required=True, ondelete='cascade',
|
||||
string='Group',
|
||||
help='The group corresponding to this portal'),
|
||||
'url': fields.char('URL',
|
||||
help="The url where portal users can connect to the server"),
|
||||
'home_action_id': fields.many2one('ir.actions.actions',
|
||||
string='Home Action',
|
||||
help="if set, replaces the standard home action (first screen after loggin) for the portal's users"),
|
||||
'menu_action_id': fields.many2one('ir.actions.act_window', readonly=True,
|
||||
# ISSUE: 'ondelete' constraints do not seem effective on this field...
|
||||
string='Menu Action',
|
||||
help="If set, replaces the standard menu for the portal's users"),
|
||||
'parent_menu_id': fields.many2one('ir.ui.menu', ondelete='restrict',
|
||||
string='Parent Menu',
|
||||
help='The menu action opens the submenus of this menu item'),
|
||||
'widget_ids': fields.one2many('res.portal.widget', 'portal_id',
|
||||
string='Widgets',
|
||||
help='Widgets assigned to portal users'),
|
||||
'is_portal': fields.boolean('Portal', help="If checked, this group is usable as a portal."),
|
||||
}
|
||||
|
||||
def copy(self, cr, uid, id, values, context=None):
|
||||
""" override copy(): menu_action_id must be different """
|
||||
values['menu_action_id'] = None
|
||||
return super(portal, self).copy(cr, uid, id, values, context)
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
""" extend create() to assign the portal menu to users """
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
# create portal (admin should not be included)
|
||||
context['noadmin'] = True
|
||||
portal_id = super(portal, self).create(cr, uid, values, context)
|
||||
|
||||
# assign menu action and widgets to users
|
||||
if values.get('users') or values.get('menu_action_id'):
|
||||
self._assign_menu(cr, uid, [portal_id], context)
|
||||
if values.get('users') or values.get('widget_ids'):
|
||||
self._assign_widgets(cr, uid, [portal_id], context)
|
||||
|
||||
return portal_id
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
""" extend write() to reflect changes on users """
|
||||
# first apply portal changes
|
||||
super(portal, self).write(cr, uid, ids, values, context)
|
||||
|
||||
# assign menu action and widgets to users
|
||||
if values.get('users') or values.get('menu_action_id'):
|
||||
self._assign_menu(cr, uid, ids, context)
|
||||
if values.get('users') or values.get('widget_ids'):
|
||||
self._assign_widgets(cr, uid, ids, context)
|
||||
|
||||
# if parent_menu_id has changed, apply the change on menu_action_id
|
||||
if 'parent_menu_id' in values:
|
||||
act_window_obj = self.pool.get('ir.actions.act_window')
|
||||
portals = self.browse(cr, uid, ids, context)
|
||||
action_ids = [p.menu_action_id.id for p in portals if p.menu_action_id]
|
||||
if action_ids:
|
||||
action_values = {'domain': [('parent_id', '=', values['parent_menu_id'])]}
|
||||
act_window_obj.write(cr, uid, action_ids, action_values, context)
|
||||
|
||||
return True
|
||||
|
||||
def _assign_menu(self, cr, uid, ids, context=None):
|
||||
""" assign portal_menu_settings to users of portals (ids) """
|
||||
user_obj = self.pool.get('res.users')
|
||||
for p in self.browse(cr, uid, ids, context):
|
||||
# user menu action = portal menu action if set in portal
|
||||
if p.menu_action_id:
|
||||
user_ids = [u.id for u in p.users if u.id != 1]
|
||||
user_values = {'menu_id': p.menu_action_id.id}
|
||||
user_obj.write(cr, uid, user_ids, user_values, context)
|
||||
|
||||
def _assign_widgets(self, cr, uid, ids, context=None):
|
||||
""" assign portal widgets to users of portals (ids) """
|
||||
widget_user_obj = self.pool.get('res.widget.user')
|
||||
for p in self.browse(cr, uid, ids, context):
|
||||
for w in p.widget_ids:
|
||||
values = {'sequence': w.sequence, 'widget_id': w.widget_id.id}
|
||||
for u in p.users:
|
||||
if u.id == 1: continue
|
||||
values['user_id'] = u.id
|
||||
widget_user_obj.create(cr, uid, values, context)
|
||||
|
||||
def _res_xml_id(self, cr, uid, module, xml_id):
|
||||
""" return the resource id associated to the given xml_id """
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
data_id = data_obj._get_id(cr, uid, module, xml_id)
|
||||
return data_obj.browse(cr, uid, data_id).res_id
|
||||
|
||||
portal()
|
||||
|
||||
|
||||
|
||||
class portal_override_menu(osv.osv):
|
||||
"""
|
||||
Extend res.portal with a boolean field 'Override Users Menu', that
|
||||
triggers the creation or removal of menu_action_id
|
||||
"""
|
||||
_name = 'res.portal'
|
||||
_inherit = 'res.portal'
|
||||
|
||||
def _get_override_menu(self, cr, uid, ids, field_name, arg, context=None):
|
||||
assert field_name == 'override_menu'
|
||||
result = {}
|
||||
for p in self.browse(cr, uid, ids, context):
|
||||
result[p.id] = bool(p.menu_action_id)
|
||||
return result
|
||||
|
||||
def _set_override_menu(self, cr, uid, id, field_name, field_value, arg, context=None):
|
||||
assert field_name == 'override_menu'
|
||||
if field_value:
|
||||
self.create_menu_action(cr, uid, id, context)
|
||||
else:
|
||||
self.write(cr, uid, [id], {'menu_action_id': False}, context)
|
||||
|
||||
def create_menu_action(self, cr, uid, id, context=None):
|
||||
""" create, if necessary, a menu action that opens the menu items below
|
||||
parent_menu_id """
|
||||
p = self.browse(cr, uid, id, context)
|
||||
if not p.menu_action_id:
|
||||
actions_obj = self.pool.get('ir.actions.act_window')
|
||||
parent_id = p.parent_menu_id.id if p.parent_menu_id else False
|
||||
action_values = {
|
||||
'name': _('%s Menu') % p.name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'usage': 'menu',
|
||||
'res_model': 'ir.ui.menu',
|
||||
'view_type': 'tree',
|
||||
'view_id': self._res_xml_id(cr, uid, 'base', 'view_menu'),
|
||||
'domain': [('parent_id', '=', parent_id)],
|
||||
}
|
||||
action_id = actions_obj.create(cr, uid, action_values, context)
|
||||
self.write(cr, uid, [id], {'menu_action_id': action_id}, context)
|
||||
|
||||
_columns = {
|
||||
'override_menu': fields.function(
|
||||
_get_override_menu, fnct_inv=_set_override_menu,
|
||||
type='boolean', string='Override Menu Action of Users',
|
||||
help='Enable this option to override the Menu Action of portal users'),
|
||||
}
|
||||
|
||||
portal_override_menu()
|
||||
|
||||
|
||||
|
||||
class portal_widget(osv.osv):
|
||||
"""
|
||||
Similar to res.widget.user (res_widget.py), but with a portal instead.
|
||||
New users in a portal are assigned the portal's widgets.
|
||||
"""
|
||||
_name='res.portal.widget'
|
||||
_description = 'Portal Widgets'
|
||||
_order = 'sequence'
|
||||
_columns = {
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'portal_id': fields.many2one('res.portal', select=1, ondelete='cascade',
|
||||
string='Portal'),
|
||||
'widget_id': fields.many2one('res.widget', required=True, ondelete='cascade',
|
||||
string='Widget'),
|
||||
}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
domain = [('portal_id', '=', values.get('portal_id')),
|
||||
('widget_id', '=', values.get('widget_id'))]
|
||||
existing = self.search(cr, uid, domain, context=context)
|
||||
if existing:
|
||||
res = existing[0]
|
||||
else:
|
||||
res = super(portal_widget, self).create(cr, uid, values, context=context)
|
||||
return res
|
||||
|
||||
portal_widget()
|
||||
|
||||
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -2,14 +2,6 @@
|
|||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="portal" model="res.portal">
|
||||
<field name="name">Portal</field>
|
||||
<field name="group_id" ref="group_portal_member"/>
|
||||
<field name="override_menu" eval="False"/>
|
||||
<!-- Insert the template user from auth_signup in the portal members group -->
|
||||
<field name="users" eval="[(4,ref('auth_signup.default_template_user'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Mail group for the company's news -->
|
||||
<record id="company_news_feed" model="mail.group">
|
||||
<field name="name">Company's news</field>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</record>
|
||||
|
||||
<!-- Add the demo user to the portal (and therefore to the portal member group) -->
|
||||
<record id="portal" model="res.portal">
|
||||
<record id="group_portal" model="res.groups">
|
||||
<field name="users" eval="[(4,ref('demo_user0'))]"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<!-- Top menu item -->
|
||||
<menuitem name="Portal"
|
||||
id="portal_menu"
|
||||
groups="base.group_no_one,portal.group_portal_member,auth_anonymous.group_anonymous"
|
||||
groups="base.group_no_one,portal.group_portal,auth_anonymous.group_anonymous"
|
||||
sequence="20"/>
|
||||
|
||||
<menuitem name="Our company" id="portal_company" parent="portal_menu" sequence="10"/>
|
||||
|
@ -21,71 +21,31 @@
|
|||
<menuitem name="Projects" id="portal_projects" parent="portal_menu" sequence="40"/>
|
||||
<menuitem name="After Sale Services" id="portal_after_sales" parent="portal_menu" sequence="50"/>
|
||||
|
||||
<!-- portal tree view -->
|
||||
<record id="portal_list_view" model="ir.ui.view">
|
||||
<field name="name">Portal List</field>
|
||||
<field name="model">res.portal</field>
|
||||
<!-- extend res.groups search view -->
|
||||
<record id="group_search_view" model="ir.ui.view">
|
||||
<field name="name">Group Search</field>
|
||||
<field name="model">res.groups</field>
|
||||
<field name="inherit_id" ref="base.view_groups_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Portals">
|
||||
<field name="name" string="Portal Name"/>
|
||||
</tree>
|
||||
<field name="name" position="after">
|
||||
<filter name="portal" string="Portal Groups" domain="[('is_portal','=',True)]"/>
|
||||
<filter name="no_portal" string="Non-Portal Groups" domain="[('is_portal','=',False)]"/>
|
||||
<separator orientation="vertical"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- portal form view -->
|
||||
<record id="portal_form_view" model="ir.ui.view">
|
||||
<!-- extend res.groups form view -->
|
||||
<record id="group_form_view" model="ir.ui.view">
|
||||
<field name="name">Portal Form</field>
|
||||
<field name="model">res.portal</field>
|
||||
<field name="model">res.groups</field>
|
||||
<field name="inherit_id" ref="base.view_groups_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<page string="Users" position="before">
|
||||
<page string="Portal">
|
||||
<group>
|
||||
<group>
|
||||
<field name="url" widget="url" string="Portal URL"/>
|
||||
<field name="home_action_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="override_menu"/>
|
||||
<field name="parent_menu_id"
|
||||
context="{'ir.ui.menu.full_list': True}"/>
|
||||
<label for="partent_menu_id" colspan="1"/>
|
||||
</group>
|
||||
<separator string="Widgets Assigned to Users" colspan="2"/>
|
||||
<field name="widget_ids" nolabel="1" colspan="2">
|
||||
<tree string="Widgets" editable="bottom">
|
||||
<field name="sequence"/>
|
||||
<field name="widget_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</page>
|
||||
</page>
|
||||
<field name="name" position="after">
|
||||
<field name="is_portal"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- action Administration/Portals/Portals -->
|
||||
<record id="portal_list_action" model="ir.actions.act_window">
|
||||
<field name="name">Portals</field>
|
||||
<field name="res_model">res.portal</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<!-- a context is necessary to get the right portal form view -->
|
||||
<field name="context">{'form_view_ref': 'portal.portal_form_view'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new portal.
|
||||
</p><p>
|
||||
A portal helps defining specific views and rules for a group of
|
||||
users (the portal group). A portal menu, widgets and specific
|
||||
groups may be assigned to the portal's users.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- menu Administration/Portals/Portals -->
|
||||
<menuitem name="Portals Settings" id="portal_menu_settings" parent="base.menu_administration" groups="group_portal_manager"/>
|
||||
<menuitem name="Portals" id="portal_list_menu" parent="portal_menu_settings" action="portal_list_action"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -1,6 +1,2 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_all,access.portal.all,model_res_portal,,1,0,0,0
|
||||
access_widget_all,access.portal.widget.all,model_res_portal_widget,,1,0,0,0
|
||||
access_manager,access.portal.manager,model_res_portal,group_portal_manager,1,1,1,1
|
||||
access_widget_manager,access.portal.widget.manager,model_res_portal_widget,group_portal_manager,1,1,1,1
|
||||
access_mail_message_portal,mail.message.portal,mail.model_mail_message,group_portal_member,1,1,1,1
|
||||
access_mail_message_portal,mail.message.portal,mail.model_mail_message,group_portal,1,0,1,1
|
||||
|
|
|
|
@ -2,31 +2,14 @@
|
|||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Don't use any implied_ids here; this group's behavior is particular -->
|
||||
<record id="group_portal_member" model="res.groups">
|
||||
<field name="name">Portal Member</field>
|
||||
<field name="comment">Portal members can access information through the portal menu. Also, they are chrooted in this specific menu.</field>
|
||||
</record>
|
||||
|
||||
<record id="module_category_portal" model="ir.module.category">
|
||||
<!-- The portal group -->
|
||||
<record id="group_portal" model="res.groups">
|
||||
<field name="name">Portal</field>
|
||||
<field name="parent_id" ref="base.module_category_tools"/>
|
||||
<field name="sequence">25</field>
|
||||
</record>
|
||||
|
||||
<!-- No implied ids with 'member' since this group is highly restrictive (chrooted menu) -->
|
||||
<record id="group_portal_officer" model="res.groups">
|
||||
<field name="name">Officer</field>
|
||||
<field name="comment">Portal officers can create new portal users with the portal wizard.</field>
|
||||
<field name="category_id" ref="module_category_portal"/>
|
||||
</record>
|
||||
|
||||
<record id="group_portal_manager" model="res.groups">
|
||||
<field name="name">Manager</field>
|
||||
<field name="comment">Portal managers have access to the portal definitions, and can easily configure the users, access rights and menus of portal users.</field>
|
||||
<field name="category_id" ref="module_category_portal"/>
|
||||
<field name="implied_ids" eval="[(4, ref('group_portal_officer'))]"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
<field name="comment">Portal members have specific access rights (such as record rules and restricted menus).
|
||||
They usually do not belong to the usual OpenERP groups.</field>
|
||||
<field name="is_portal" eval="True"/>
|
||||
<!-- Insert the template user from auth_signup in the portal members group -->
|
||||
<field name="users" eval="[(4,ref('auth_signup.default_template_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -80,7 +80,7 @@ class test_portal(test_mail.TestMailMockups):
|
|||
user_admin = self.res_users.browse(cr, uid, uid)
|
||||
self.mail_invite = self.registry('mail.wizard.invite')
|
||||
base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='')
|
||||
portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal')
|
||||
portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal')
|
||||
portal_id = portal_ref and portal_ref[1] or False
|
||||
|
||||
# 0 - Admin
|
||||
|
|
|
@ -23,33 +23,43 @@ import logging
|
|||
import random
|
||||
|
||||
from osv import osv, fields
|
||||
from tools.misc import email_re
|
||||
from tools.translate import _
|
||||
from tools.misc import email_re
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
from base.res.res_partner import _lang_get
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# welcome email sent to new portal users (note that calling tools.translate._
|
||||
# has no effect except exporting those strings for translation)
|
||||
# welcome/goodbye email sent to portal users
|
||||
# (note that calling '_' has no effect except exporting those strings for translation)
|
||||
WELCOME_EMAIL_SUBJECT = _("Your OpenERP account at %(company)s")
|
||||
WELCOME_EMAIL_BODY = _("""Dear %(name)s,
|
||||
|
||||
You have been created an OpenERP account at %(url)s.
|
||||
You have been given access to %(portal)s at %(url)s.
|
||||
|
||||
Your login account data is:
|
||||
Database: %(db)s
|
||||
User: %(login)s
|
||||
Password: %(password)s
|
||||
|
||||
%(message)s
|
||||
%(welcome_message)s
|
||||
|
||||
--
|
||||
OpenERP - Open Source Business Applications
|
||||
http://www.openerp.com
|
||||
""")
|
||||
|
||||
ROOT_UID = 1
|
||||
GOODBYE_EMAIL_SUBJECT = _("Your OpenERP account at %(company)s")
|
||||
GOODBYE_EMAIL_BODY = _("""Dear %(name)s,
|
||||
|
||||
Your access to %(portal)s has been withdrawn.
|
||||
|
||||
%(goodbye_message)s
|
||||
|
||||
--
|
||||
OpenERP - Open Source Business Applications
|
||||
http://www.openerp.com
|
||||
""")
|
||||
|
||||
# character sets for passwords, excluding 0, O, o, 1, I, l
|
||||
_PASSU = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'
|
||||
|
@ -71,169 +81,173 @@ def extract_email(email):
|
|||
|
||||
class wizard(osv.osv_memory):
|
||||
"""
|
||||
A wizard to create portal users from instances of 'res.partner'. The purpose
|
||||
is to provide an OpenERP database access to customers or suppliers.
|
||||
A wizard to manage the creation/removal of portal users.
|
||||
"""
|
||||
_name = 'res.portal.wizard'
|
||||
_description = 'Portal Wizard'
|
||||
|
||||
_name = 'portal.wizard'
|
||||
_description = 'Portal Access Management'
|
||||
|
||||
_columns = {
|
||||
'portal_id': fields.many2one('res.portal', required=True,
|
||||
string='Portal',
|
||||
help="The portal in which new users must be added"),
|
||||
'user_ids': fields.one2many('res.portal.wizard.user', 'wizard_id',
|
||||
string='Users'),
|
||||
'message': fields.text(string='Invitation message',
|
||||
help="This text is included in the welcome email sent to the users"),
|
||||
'portal_id': fields.many2one('res.groups', domain=[('is_portal', '=', True)], required=True,
|
||||
string='Portal', help="The portal that users can be added in or removed from."),
|
||||
'user_ids': fields.one2many('portal.wizard.user', 'wizard_id', string='Users'),
|
||||
'welcome_message': fields.text(string='Invitation Message',
|
||||
help="This text is included in the email sent to new users of the portal."),
|
||||
'goodbye_message': fields.text(string='Withdrawal Message',
|
||||
help="This text is included in the email sent to users withdrawn from the portal."),
|
||||
}
|
||||
|
||||
def _default_user_ids(self, cr, uid, context):
|
||||
""" determine default user_ids from the active records """
|
||||
def create_user_from_address(address):
|
||||
if isinstance(address, int):
|
||||
res_partner_obj = self.pool.get('res.partner')
|
||||
address = res_partner_obj.browse(cr, uid, address, context=context)
|
||||
lang = address.id and address.lang or 'en_US'
|
||||
partner_id = address.id
|
||||
|
||||
else:
|
||||
lang = address.parent_id and address.parent_id.lang or 'en_US'
|
||||
partner_id = address.parent_id and address.parent_id.id
|
||||
|
||||
return{
|
||||
'name': address.name,
|
||||
'email': extract_email(address.email),
|
||||
'lang': lang,
|
||||
'partner_id': partner_id,
|
||||
}
|
||||
|
||||
user_ids = []
|
||||
if context.get('active_model') == 'res.partner':
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
partner_ids = context.get('active_ids', [])
|
||||
partners = partner_obj.browse(cr, uid, partner_ids, context)
|
||||
for p in partners:
|
||||
# add one user per contact, or one user if no contact
|
||||
if p.child_ids:
|
||||
user_ids.extend(map(create_user_from_address, p.child_ids))
|
||||
elif p.is_company == False and p.customer == True:
|
||||
user_ids.extend(map(create_user_from_address, [p.id]))
|
||||
else:
|
||||
user_ids.append({'lang': p.lang or 'en_US', 'parent_id': p.id})
|
||||
|
||||
return user_ids
|
||||
def _default_portal(self, cr, uid, context):
|
||||
portal_ids = self.pool.get('res.groups').search(cr, uid, [('is_portal', '=', True)])
|
||||
return portal_ids and portal_ids[0] or False
|
||||
|
||||
_defaults = {
|
||||
'user_ids': _default_user_ids
|
||||
'portal_id': _default_portal,
|
||||
}
|
||||
|
||||
def action_create(self, cr, uid, ids, context=None):
|
||||
""" create new users in portal(s), and notify them by email """
|
||||
# we copy the context to change the language for translating emails
|
||||
context0 = context or {}
|
||||
context0['noshortcut'] = True # prevent shortcut creation
|
||||
context = context0.copy()
|
||||
|
||||
user_obj = self.pool.get('res.users')
|
||||
user = user_obj.browse(cr, ROOT_UID, uid, context0)
|
||||
if not user.email:
|
||||
raise osv.except_osv(_('Email required'),
|
||||
_('You must have an email address in your User Preferences'
|
||||
' to send emails.'))
|
||||
|
||||
portal_obj = self.pool.get('res.portal')
|
||||
for wiz in self.browse(cr, uid, ids, context):
|
||||
# determine existing users
|
||||
login_cond = [('login', 'in', [u.email for u in wiz.user_ids])]
|
||||
existing_uids = user_obj.search(cr, ROOT_UID, login_cond)
|
||||
existing_users = user_obj.browse(cr, ROOT_UID, existing_uids)
|
||||
existing_logins = [u.login for u in existing_users]
|
||||
|
||||
# create new users in portal (skip existing logins)
|
||||
new_users_data = [ {
|
||||
'name': u.name,
|
||||
'login': u.email,
|
||||
'password': random_password(),
|
||||
'email': u.email,
|
||||
'lang': u.lang,
|
||||
'share': True,
|
||||
'action_id': wiz.portal_id.home_action_id and wiz.portal_id.home_action_id.id or False,
|
||||
'partner_id': u.partner_id and u.partner_id.id,
|
||||
'groups_id': [(6, 0, [])],
|
||||
} for u in wiz.user_ids if u.email not in existing_logins ]
|
||||
portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
|
||||
{'users': [(0, 0, data) for data in new_users_data]}, context0)
|
||||
|
||||
# send email to all users (translated in their language)
|
||||
data = {
|
||||
'company': user.company_id.name,
|
||||
'message': wiz.message or "",
|
||||
'url': wiz.portal_id.url or _("(missing url)"),
|
||||
'db': cr.dbname,
|
||||
}
|
||||
mail_mail_obj = self.pool.get('mail.mail')
|
||||
dest_uids = user_obj.search(cr, ROOT_UID, login_cond)
|
||||
dest_users = user_obj.browse(cr, ROOT_UID, dest_uids)
|
||||
for dest_user in dest_users:
|
||||
context['lang'] = dest_user.lang
|
||||
data['login'] = dest_user.login
|
||||
data['password'] = dest_user.password
|
||||
data['name'] = dest_user.name
|
||||
|
||||
email_from = user.email
|
||||
email_to = dest_user.email
|
||||
subject = _(WELCOME_EMAIL_SUBJECT) % data
|
||||
body = _(WELCOME_EMAIL_BODY) % data
|
||||
mail_id = mail_mail_obj.create(cr, uid, {
|
||||
'email_from': email_from ,
|
||||
'email_to': email_to,
|
||||
'subject': subject,
|
||||
'state': 'outgoing',
|
||||
'body_html': '<pre>%s</pre>' % body}, context=context)
|
||||
|
||||
def onchange_portal_id(self, cr, uid, ids, portal_id, context=None):
|
||||
# for each partner, determine corresponding portal.wizard.user records
|
||||
res_partner = self.pool.get('res.partner')
|
||||
partner_ids = context and context.get('active_ids') or []
|
||||
contact_ids = set()
|
||||
user_changes = []
|
||||
for partner in res_partner.browse(cr, SUPERUSER_ID, partner_ids, context):
|
||||
for contact in (partner.child_ids or [partner]):
|
||||
# make sure that each contact appears at most once in the list
|
||||
if contact.id not in contact_ids:
|
||||
contact_ids.add(contact.id)
|
||||
in_portal = False
|
||||
if contact.user_ids:
|
||||
in_portal = portal_id in [g.id for g in contact.user_ids[0].groups_id]
|
||||
user_changes.append((0, 0, {
|
||||
'partner_id': contact.id,
|
||||
'email': contact.email,
|
||||
'in_portal': in_portal,
|
||||
}))
|
||||
return {'value': {'user_ids': user_changes}}
|
||||
|
||||
def action_apply(self, cr, uid, ids, context=None):
|
||||
wizard = self.browse(cr, uid, ids[0], context)
|
||||
portal_user_ids = [user.id for user in wizard.user_ids]
|
||||
self.pool.get('portal.wizard.user').action_apply(cr, uid, portal_user_ids, context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
wizard()
|
||||
|
||||
|
||||
|
||||
class wizard_user(osv.osv_memory):
|
||||
"""
|
||||
A model to configure users in the portal wizard.
|
||||
"""
|
||||
_name = 'res.portal.wizard.user'
|
||||
_name = 'portal.wizard.user'
|
||||
_description = 'Portal User Config'
|
||||
|
||||
_columns = {
|
||||
'wizard_id': fields.many2one('res.portal.wizard', required=True,
|
||||
string='Wizard'),
|
||||
'name': fields.char(size=64, required=True,
|
||||
string='User Name',
|
||||
help="The user's real name"),
|
||||
'email': fields.char(size=64, required=True,
|
||||
string='Email',
|
||||
help="Will be used as user login. "
|
||||
"Also necessary to send the account information to new users"),
|
||||
'lang': fields.selection(_lang_get, required=True,
|
||||
string='Language',
|
||||
help="The language for the user's user interface"),
|
||||
'partner_id': fields.many2one('res.partner',
|
||||
string='Partner'),
|
||||
'wizard_id': fields.many2one('portal.wizard', string='Wizard', required=True),
|
||||
'partner_id': fields.many2one('res.partner', string='Contact', required=True, readonly=True),
|
||||
'email': fields.char(size=240, string='Email'),
|
||||
'in_portal': fields.boolean('In Portal'),
|
||||
}
|
||||
|
||||
def _check_email(self, cr, uid, ids):
|
||||
""" check syntax of email address """
|
||||
for wuser in self.browse(cr, uid, ids):
|
||||
if not email_re.match(wuser.email): return False
|
||||
return True
|
||||
def create(self, cr, uid, values, context=None):
|
||||
""" overridden to update the partner's email (if necessary) """
|
||||
id = super(wizard_user, self).create(cr, uid, values, context)
|
||||
wuser = self.browse(cr, uid, id, context)
|
||||
if wuser.partner_id.email != wuser.email:
|
||||
wuser.partner_id.write({'email': wuser.email})
|
||||
return id
|
||||
|
||||
_constraints = [
|
||||
(_check_email, 'Invalid email address', ['email']),
|
||||
]
|
||||
def action_apply(self, cr, uid, ids, context=None):
|
||||
res_users = self.pool.get('res.users')
|
||||
for wizard_user in self.browse(cr, SUPERUSER_ID, ids, context):
|
||||
portal = wizard_user.wizard_id.portal_id
|
||||
user = self._retrieve_user(cr, SUPERUSER_ID, wizard_user, context)
|
||||
if wizard_user.in_portal:
|
||||
# create a user if necessary, and make sure it is in the portal group
|
||||
if not user:
|
||||
user = self._create_user(cr, SUPERUSER_ID, wizard_user, context)
|
||||
if (not user.active) or (portal not in user.groups_id):
|
||||
user.write({'active': True, 'groups_id': [(4, portal.id)]})
|
||||
wizard_user = self.browse(cr, SUPERUSER_ID, wizard_user.id, context)
|
||||
self._send_email(cr, uid, wizard_user, context)
|
||||
else:
|
||||
# remove the user (if it exists) from the portal group
|
||||
if user and (portal in user.groups_id):
|
||||
# if user belongs to portal only, deactivate it
|
||||
if len(user.groups_id) <= 1:
|
||||
user.write({'groups_id': [(3, portal.id)], 'active': False})
|
||||
else:
|
||||
user.write({'groups_id': [(3, portal.id)]})
|
||||
wizard_user = self.browse(cr, SUPERUSER_ID, wizard_user.id, context)
|
||||
self._send_email(cr, uid, wizard_user, context)
|
||||
|
||||
wizard_user()
|
||||
def _retrieve_user(self, cr, uid, wizard_user, context=None):
|
||||
""" retrieve the (possibly inactive) user corresponding to wizard_user.partner_id
|
||||
@param wizard_user: browse record of model portal.wizard.user
|
||||
@return: browse record of model res.users
|
||||
"""
|
||||
if wizard_user.partner_id.user_ids:
|
||||
return wizard_user.partner_id.user_ids[0]
|
||||
# the user may be inactive, search for it
|
||||
res_users = self.pool.get('res.users')
|
||||
domain = [('partner_id', '=', wizard_user.partner_id.id), ('active', '=', False)]
|
||||
user_ids = res_users.search(cr, uid, domain)
|
||||
return user_ids and res_users.browse(cr, uid, user_ids[0], context) or False
|
||||
|
||||
def _create_user(self, cr, uid, wizard_user, context=None):
|
||||
""" create a new user for wizard_user.partner_id
|
||||
@param wizard_user: browse record of model portal.wizard.user
|
||||
@return: browse record of model res.users
|
||||
"""
|
||||
res_users = self.pool.get('res.users')
|
||||
create_context = dict(context or {}, noshortcut=True) # to prevent shortcut creation
|
||||
values = {
|
||||
'login': extract_email(wizard_user.email),
|
||||
'password': random_password(),
|
||||
'partner_id': wizard_user.partner_id.id,
|
||||
'groups_id': [(6, 0, [])],
|
||||
'share': True,
|
||||
}
|
||||
user_id = res_users.create(cr, uid, values, context=create_context)
|
||||
return res_users.browse(cr, uid, user_id, context)
|
||||
|
||||
def _send_email(self, cr, uid, wizard_user, context=None):
|
||||
""" send notification email to a new/former portal user
|
||||
@param wizard_user: browse record of model portal.wizard.user
|
||||
@return: the id of the created mail.mail record
|
||||
"""
|
||||
this_context = context
|
||||
this_user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context)
|
||||
if not this_user.email:
|
||||
raise osv.except_osv(_('Email required'),
|
||||
_('You must have an email address in your User Preferences to send emails.'))
|
||||
|
||||
# determine subject and body in the portal user's language
|
||||
url = self.pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'web.base.url', context=this_context)
|
||||
user = self._retrieve_user(cr, SUPERUSER_ID, wizard_user, context)
|
||||
context = dict(this_context or {}, lang=user.lang)
|
||||
data = {
|
||||
'company': this_user.company_id.name,
|
||||
'portal': wizard_user.wizard_id.portal_id.name,
|
||||
'welcome_message': wizard_user.wizard_id.welcome_message or "",
|
||||
'goodbye_message': wizard_user.wizard_id.goodbye_message or "",
|
||||
'url': url or _("(missing url)"),
|
||||
'db': cr.dbname,
|
||||
'login': user.login,
|
||||
'password': user.password,
|
||||
'name': user.name
|
||||
}
|
||||
if wizard_user.in_portal:
|
||||
subject = _(WELCOME_EMAIL_SUBJECT) % data
|
||||
body = _(WELCOME_EMAIL_BODY) % data
|
||||
else:
|
||||
subject = _(GOODBYE_EMAIL_SUBJECT) % data
|
||||
body = _(GOODBYE_EMAIL_BODY) % data
|
||||
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
mail_values = {
|
||||
'email_from': this_user.email,
|
||||
'email_to': user.email,
|
||||
'subject': subject,
|
||||
'body_html': '<pre>%s</pre>' % body,
|
||||
'state': 'outgoing',
|
||||
}
|
||||
return mail_mail.create(cr, uid, mail_values, context=this_context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -3,28 +3,34 @@
|
|||
<data>
|
||||
<!-- wizard action on res.partner -->
|
||||
<act_window id="partner_wizard_action"
|
||||
name="Add Portal Access"
|
||||
name="Portal Access Management"
|
||||
src_model="res.partner"
|
||||
res_model="res.portal.wizard"
|
||||
res_model="portal.wizard"
|
||||
view_type="form" view_mode="form"
|
||||
key2="client_action_multi" target="new"
|
||||
groups="group_portal_officer"/>
|
||||
groups="base.group_partner_manager"/>
|
||||
|
||||
<!-- wizard view -->
|
||||
<record id="wizard_view" model="ir.ui.view">
|
||||
<field name="name">Add Portal Access</field>
|
||||
<field name="model">res.portal.wizard</field>
|
||||
<field name="name">Portal Access Management</field>
|
||||
<field name="model">portal.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Add Portal Access" version="7.0">
|
||||
<group col="4">
|
||||
<field name="portal_id" widget="selection"/>
|
||||
<form string="Portal Access Management" version="7.0">
|
||||
<group>
|
||||
<field name="portal_id" widget="selection" on_change="onchange_portal_id(portal_id, context)"/>
|
||||
</group>
|
||||
<div>
|
||||
Select which contacts should belong to the portal in the list below.
|
||||
The email address of each selected contact must be valid and unique.
|
||||
If necessary, you can fix any contact's email address directly in the list.
|
||||
</div>
|
||||
<field name="user_ids"/>
|
||||
<label string="The following text will be included in the welcome email sent to users."/>
|
||||
<field name="message"/>
|
||||
<field name="welcome_message"
|
||||
placeholder="This text is included in the email sent to new portal users."/>
|
||||
<field name="goodbye_message"
|
||||
placeholder="This text is included in the email sent to users withdrawn from the portal."/>
|
||||
<footer>
|
||||
<button string="Send Invitations"
|
||||
name="action_create" type="object" class="oe_highlight" />
|
||||
<button string="Apply" name="action_apply" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
|
@ -35,32 +41,15 @@
|
|||
<!-- wizard user list view -->
|
||||
<record id="wizard_user_tree_view" model="ir.ui.view">
|
||||
<field name="name">Portal Users</field>
|
||||
<field name="model">res.portal.wizard.user</field>
|
||||
<field name="model">portal.wizard.user</field>
|
||||
<field name="arch" type="xml">
|
||||
<!-- the attribute 'editable' is set below to make the elements
|
||||
editable in the web client 6.0 -->
|
||||
<tree string="Portal Users" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<!-- the contact list is editable, but one cannot add or delete rows -->
|
||||
<tree string="Contacts" editable="bottom" create="false" delete="false">
|
||||
<field name="partner_id"/>
|
||||
<field name="email"/>
|
||||
<field name="in_portal"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- wizard user form view -->
|
||||
<record id="wizard_user_form_view" model="ir.ui.view">
|
||||
<field name="name">Portal User</field>
|
||||
<field name="model">res.portal.wizard.user</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Portal User" version="7.0">
|
||||
<group colspan="2" col="2">
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="lang"/>
|
||||
<field name="partner_id"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -44,9 +44,6 @@ class share_wizard_portal(osv.TransientModel):
|
|||
'group_ids': fields.many2many('res.groups', 'share_wizard_res_group_rel', 'share_id', 'group_id', 'Existing groups', domain=[('share', '=', False)]),
|
||||
}
|
||||
|
||||
def is_portal_manager(self, cr, uid, context=None):
|
||||
return self.has_group(cr, uid, module='portal', group_xml_id='group_portal_manager', context=context)
|
||||
|
||||
def _check_preconditions(self, cr, uid, wizard_data, context=None):
|
||||
if wizard_data.user_type == 'existing':
|
||||
self._assert(wizard_data.user_ids,
|
||||
|
@ -122,16 +119,14 @@ class share_wizard_portal(osv.TransientModel):
|
|||
# alter the rules of the groups so they can see the shared data
|
||||
if wizard_data.group_ids:
|
||||
# get the list of portals and the related groups to install their menus.
|
||||
Portals = self.pool.get('res.portal')
|
||||
all_portals = Portals.browse(cr, UID_ROOT, Portals.search(cr, UID_ROOT, [])) #no context!
|
||||
all_portal_group_ids = [p.group_id.id for p in all_portals]
|
||||
res_groups = self.pool.get('res.groups')
|
||||
all_portal_group_ids = res_groups.search(cr, UID_ROOT, [('is_portal', '=', True)])
|
||||
|
||||
# populate result lines with the users of each group and
|
||||
# setup the menu for portal groups
|
||||
for group in wizard_data.group_ids:
|
||||
if group.id in all_portal_group_ids:
|
||||
portal = all_portals[all_portal_group_ids.index(group.id)]
|
||||
self._create_shared_data_menu(cr, uid, wizard_data, portal, context=context)
|
||||
self._create_shared_data_menu(cr, uid, wizard_data, group.id, context=context)
|
||||
|
||||
for user in group.users:
|
||||
new_line = {'user_id': user.id,
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
<field name="inherit_id" ref="share.share_step2_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='result_line_ids']//field[@name='login']" position="after">
|
||||
<field name="share_url" groups="portal.group_portal_manager"/>
|
||||
<field name="share_url" groups="base.group_no_one"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='result_line_ids']" position="after">
|
||||
<newline/>
|
||||
<group string="Details">
|
||||
<field name="share_root_url" groups="portal.group_portal_manager"/>
|
||||
<group string="Details" groups="base.group_no_one">
|
||||
<field name="share_root_url"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_crm_claim,crm.claim,crm_claim.model_crm_claim,portal.group_portal_member,1,0,0,0
|
||||
access_crm_claim_stage,crm.claim.stage,crm_claim.model_crm_claim_stage,portal.group_portal_member,1,0,0,0
|
||||
access_crm_claim,crm.claim,crm_claim.model_crm_claim,portal.group_portal,1,0,0,0
|
||||
access_crm_claim_stage,crm.claim.stage,crm_claim.model_crm_claim_stage,portal.group_portal,1,0,0,0
|
||||
|
|
|
|
@ -6,7 +6,7 @@
|
|||
<field name="name">Portal Personal Claims</field>
|
||||
<field ref="crm_claim.model_crm_claim" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_event,event,event.model_event_event,portal.group_portal_member,1,0,0,0
|
||||
access_registration,registration,event.model_event_registration,portal.group_portal_member,1,0,0,0
|
||||
access_event,event,event.model_event_event,portal.group_portal,1,0,0,0
|
||||
access_registration,registration,event.model_event_registration,portal.group_portal,1,0,0,0
|
||||
|
|
|
|
@ -6,14 +6,14 @@
|
|||
<field name="name">Portal Visible Events</field>
|
||||
<field ref="event.model_event_event" name="model_id"/>
|
||||
<field name="domain_force">[('visibility', '=', 'public')]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_registration_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Registrations</field>
|
||||
<field ref="event.model_event_registration" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_hr_employee_user,hr.employee user,hr.model_hr_employee,portal.group_portal_member,1,0,0,0
|
||||
access_res_partner,res.partner,base.model_res_partner,portal.group_portal_member,1,0,0,0
|
||||
access_res_partner_address,res.partner_address,base.model_res_partner_address,portal.group_portal_member,1,0,0,0
|
||||
access_res_partner_category,res.partner_category,base.model_res_partner_category,portal.group_portal_member,1,0,0,0
|
||||
access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal_member,1,0,0,0
|
||||
access_hr_employee_user,hr.employee user,hr.model_hr_employee,portal.group_portal,1,0,0,0
|
||||
access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0,0
|
||||
access_res_partner_address,res.partner_address,base.model_res_partner_address,portal.group_portal,1,0,0,0
|
||||
access_res_partner_category,res.partner_category,base.model_res_partner_category,portal.group_portal,1,0,0,0
|
||||
access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal,1,0,0,0
|
||||
|
|
|
|
@ -1,5 +1,5 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_task,tasks,project.model_project_task,portal.group_portal_member,1,0,0,0
|
||||
access_task_type,task_type,project.model_project_task_type,portal.group_portal_member,1,0,0,0
|
||||
access_task_work,task_work,project.model_project_task_work,portal.group_portal_member,1,0,0,0
|
||||
access_project_category,project_category,project.model_project_category,portal.group_portal_member,1,0,0,0
|
||||
access_task,tasks,project.model_project_task,portal.group_portal,1,0,0,0
|
||||
access_task_type,task_type,project.model_project_task_type,portal.group_portal,1,0,0,0
|
||||
access_task_work,task_work,project.model_project_task_work,portal.group_portal,1,0,0,0
|
||||
access_project_category,project_category,project.model_project_category,portal.group_portal,1,0,0,0
|
||||
|
|
|
|
@ -6,7 +6,7 @@
|
|||
<field name="name">Portal Personal Task</field>
|
||||
<field ref="project.model_project_task" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_issues,project_issue,project_issue.model_project_issue,portal.group_portal_member,1,0,0,0
|
||||
access_case_section,crm_case_section,crm.model_crm_case_section,portal.group_portal_member,1,0,0,0
|
||||
access_issues,project_issue,project_issue.model_project_issue,portal.group_portal,1,0,0,0
|
||||
access_case_section,crm_case_section,crm.model_crm_case_section,portal.group_portal,1,0,0,0
|
||||
|
|
|
|
@ -6,7 +6,7 @@
|
|||
<field name="name">Portal Personal Issues</field>
|
||||
<field ref="project_issue.model_project_issue" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_order,sale.order,sale.model_sale_order,portal.group_portal_member,1,0,0,0
|
||||
access_sale_order_line,sale.order.line,sale.model_sale_order_line,portal.group_portal_member,1,0,0,0
|
||||
access_stock_picking,stock.picking,stock.model_stock_picking,portal.group_portal_member,1,0,0,0
|
||||
access_stock_picking.out,stock.picking.out,stock.model_stock_picking_out,portal.group_portal_member,1,0,0,0
|
||||
access_stock_move,stock.move,stock.model_stock_move,portal.group_portal_member,1,0,0,0
|
||||
access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,procurement.model_stock_warehouse_orderpoint,portal.group_portal_member,1,0,0,0
|
||||
access_account_invoice,account.invoice,account.model_account_invoice,portal.group_portal_member,1,0,0,0
|
||||
access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,portal.group_portal_member,1,0,0,0
|
||||
access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,portal.group_portal_member,1,0,0,0
|
||||
access_account_journal,account.journal,account.model_account_journal,portal.group_portal_member,1,0,0,0
|
||||
access_account_voucher,account.voucher,account_voucher.model_account_voucher,portal.group_portal_member,1,0,0,0
|
||||
access_account_voucher_line,account.voucher.line,account_voucher.model_account_voucher_line,portal.group_portal_member,1,0,0,0
|
||||
access_account_move,account.move,account.model_account_move,portal.group_portal_member,1,0,0,0
|
||||
access_account_move_line,account.move.line,account.model_account_move_line,portal.group_portal_member,1,0,0,0
|
||||
access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,portal.group_portal_member,1,0,0,0
|
||||
access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,portal.group_portal_member,1,0,0,0
|
||||
access_sale_shop,sale.shop,sale.model_sale_shop,portal.group_portal_member,1,0,0,0
|
||||
access_product_list,product.pricelist,product.model_product_pricelist,portal.group_portal_member,1,0,0,0
|
||||
access_product,product.product,product.model_product_product,portal.group_portal_member,1,0,0,0
|
||||
access_res_partner,res.partner,base.model_res_partner,portal.group_portal_member,1,0,0,0
|
||||
access_product_uom,product.uom,product.model_product_uom,portal.group_portal_member,1,0,0,0
|
||||
access_account_tax,account.tax,account.model_account_tax,portal.group_portal_member,1,0,0,0
|
||||
access_mrp_property,mrp.property,procurement.model_mrp_property,portal.group_portal_member,1,0,0,0
|
||||
access_product_template,product.template,product.model_product_template,portal.group_portal_member,1,0,0,0
|
||||
access_stock_warehouse,stock.warehouse,stock.model_stock_warehouse,portal.group_portal_member,1,0,0,0
|
||||
access_stock_location,stock.location,stock.model_stock_location,portal.group_portal_member,1,0,0,0
|
||||
access_account_fiscalyear,account.fiscalyear,account.model_account_fiscalyear,portal.group_portal_member,1,0,0,0
|
||||
access_res_partner_category,res.partner.category,base.model_res_partner_category,portal.group_portal_member,1,0,0,0
|
||||
access_product_supplierinfo,product.supplierinfo,product.model_product_supplierinfo,portal.group_portal_member,1,0,0,0
|
||||
access_product_packaging,product.packaging,product.model_product_packaging,portal.group_portal_member,1,0,0,0
|
||||
access_account_period,account.period,account.model_account_period,portal.group_portal_member,1,0,0,0
|
||||
access_account_account,account.account,account.model_account_account,portal.group_portal_member,1,0,0,0
|
||||
access_sale_order,sale.order,sale.model_sale_order,portal.group_portal,1,0,0,0
|
||||
access_sale_order_line,sale.order.line,sale.model_sale_order_line,portal.group_portal,1,0,0,0
|
||||
access_stock_picking,stock.picking,stock.model_stock_picking,portal.group_portal,1,0,0,0
|
||||
access_stock_picking.out,stock.picking.out,stock.model_stock_picking_out,portal.group_portal,1,0,0,0
|
||||
access_stock_move,stock.move,stock.model_stock_move,portal.group_portal,1,0,0,0
|
||||
access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,procurement.model_stock_warehouse_orderpoint,portal.group_portal,1,0,0,0
|
||||
access_account_invoice,account.invoice,account.model_account_invoice,portal.group_portal,1,0,0,0
|
||||
access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,portal.group_portal,1,0,0,0
|
||||
access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,portal.group_portal,1,0,0,0
|
||||
access_account_journal,account.journal,account.model_account_journal,portal.group_portal,1,0,0,0
|
||||
access_account_voucher,account.voucher,account_voucher.model_account_voucher,portal.group_portal,1,0,0,0
|
||||
access_account_voucher_line,account.voucher.line,account_voucher.model_account_voucher_line,portal.group_portal,1,0,0,0
|
||||
access_account_move,account.move,account.model_account_move,portal.group_portal,1,0,0,0
|
||||
access_account_move_line,account.move.line,account.model_account_move_line,portal.group_portal,1,0,0,0
|
||||
access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,portal.group_portal,1,0,0,0
|
||||
access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,portal.group_portal,1,0,0,0
|
||||
access_sale_shop,sale.shop,sale.model_sale_shop,portal.group_portal,1,0,0,0
|
||||
access_product_list,product.pricelist,product.model_product_pricelist,portal.group_portal,1,0,0,0
|
||||
access_product,product.product,product.model_product_product,portal.group_portal,1,0,0,0
|
||||
access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0,0
|
||||
access_product_uom,product.uom,product.model_product_uom,portal.group_portal,1,0,0,0
|
||||
access_account_tax,account.tax,account.model_account_tax,portal.group_portal,1,0,0,0
|
||||
access_mrp_property,mrp.property,procurement.model_mrp_property,portal.group_portal,1,0,0,0
|
||||
access_product_template,product.template,product.model_product_template,portal.group_portal,1,0,0,0
|
||||
access_stock_warehouse,stock.warehouse,stock.model_stock_warehouse,portal.group_portal,1,0,0,0
|
||||
access_stock_location,stock.location,stock.model_stock_location,portal.group_portal,1,0,0,0
|
||||
access_account_fiscalyear,account.fiscalyear,account.model_account_fiscalyear,portal.group_portal,1,0,0,0
|
||||
access_res_partner_category,res.partner.category,base.model_res_partner_category,portal.group_portal,1,0,0,0
|
||||
access_product_supplierinfo,product.supplierinfo,product.model_product_supplierinfo,portal.group_portal,1,0,0,0
|
||||
access_product_packaging,product.packaging,product.model_product_packaging,portal.group_portal,1,0,0,0
|
||||
access_account_period,account.period,account.model_account_period,portal.group_portal,1,0,0,0
|
||||
access_account_account,account.account,account.model_account_account,portal.group_portal,1,0,0,0
|
||||
|
|
|
|
@ -7,42 +7,42 @@
|
|||
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
||||
<field ref="sale.model_sale_order" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Delivery Orders</field>
|
||||
<field ref="stock.model_stock_picking" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Delivery Orders Out</field>
|
||||
<field ref="stock.model_stock_picking_out" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_account_invoice_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Account Invoices</field>
|
||||
<field ref="account.model_account_invoice" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_payment" model="ir.rule">
|
||||
<field name="name">Portal Personal Payments</field>
|
||||
<field ref="account_voucher.model_account_voucher" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_contact" model="ir.rule">
|
||||
<field name="name">Portal Personal Contacts</field>
|
||||
<field ref="base.model_res_partner" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal_member'))]"/>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
<record model="ir.ui.view" id="res_groups_search_sharing">
|
||||
<field name="name">res.groups.search.share</field>
|
||||
<field name="model">res.groups</field>
|
||||
<field name="priority" eval="8"/>
|
||||
<field name="inherit_id" ref="base.view_groups_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Groups">
|
||||
<field name="name" string="Group"/>
|
||||
<field name="share"/>
|
||||
<filter name="no_share" string="Regular groups only (no share groups)" icon="terp-partner" domain="[('share','=',False)]"/>
|
||||
</search>
|
||||
<field name="name" position="after">
|
||||
<filter name="share" string="Share Groups" domain="[('share','=',True)]"/>
|
||||
<filter name="no_share" string="Non-Share Groups" domain="[('share','=',False)]"/>
|
||||
<separator orientation="vertical"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ class stock_partial_picking_line(osv.TransientModel):
|
|||
res[tracklot.id] = tracking
|
||||
return res
|
||||
|
||||
|
||||
_name = "stock.partial.picking.line"
|
||||
_rec_name = 'product_id'
|
||||
_columns = {
|
||||
|
@ -56,6 +55,14 @@ class stock_partial_picking_line(osv.TransientModel):
|
|||
'tracking': fields.function(_tracking, string='Tracking', type='boolean'),
|
||||
}
|
||||
|
||||
def onchange_product_id(self, cr, uid, ids, product_id, context=None):
|
||||
uom_id = False
|
||||
if product_id:
|
||||
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
uom_id = product.uom_id.id
|
||||
return {'value': {'product_uom': uom_id}}
|
||||
|
||||
|
||||
class stock_partial_picking(osv.osv_memory):
|
||||
_name = "stock.partial.picking"
|
||||
_description = "Partial Picking Processing Wizard"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<separator string="Transfer Products" name="product_separator"/>
|
||||
<field name="move_ids" context="{'hide_tracking': hide_tracking}">
|
||||
<tree editable="bottom" string="Product Moves">
|
||||
<field name="product_id" />
|
||||
<field name="product_id" on_change="onchange_product_id(product_id)"/>
|
||||
<field name="quantity" />
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="tracking" invisible="1"/>
|
||||
|
|
Loading…
Reference in New Issue