[MERGE] Sync with trunk. Cleaned a bit things lastly added in trunk/mail/tests.

bzr revid: tde@openerp.com-20121211161458-d7wv4lnkvs9s7srj
This commit is contained in:
Thibault Delavallée 2012-12-11 17:14:58 +01:00
commit b541e7ce64
23 changed files with 177 additions and 51 deletions

View File

@ -9,13 +9,13 @@
<field name="arch" type="xml">
<tree toolbar="1" colors="red:state=='pending';grey:state in ('cancelled','close');blue:type=='view'" string="Analytic Accounts">
<field name="complete_name"/>
<field name="partner_id"/>
<field name="code"/>
<field name="date"/>
<field name="date_start" invisible="1"/>
<field name="user_id" invisible="1"/>
<field name="manager_id" invisible="1"/>
<field name="parent_id" invisible="1"/>
<field name="partner_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="type" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
@ -50,6 +50,7 @@
<field name="field_parent">child_complete_ids</field>
<field name="arch" type="xml">
<tree colors="blue:state=='pending';grey:state in ('close','cancelled');blue:type=='view'" string="Analytic account" toolbar="1">
<field name="name" invisible="1"/>
<field name="complete_name"/>
<field name="code"/>
<field name="debit"/>

View File

@ -166,7 +166,7 @@ class account_analytic_account(osv.osv):
_columns = {
'name': fields.char('Account/Contract Name', size=128, required=True),
'complete_name': fields.function(_get_full_name, type='char', string='Full Account Name'),
'code': fields.char('Reference', size=24, select=True),
'code': fields.char('Reference', select=True),
'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Contract')], 'Type of Account', required=True,
help="If you select the View Type, it means you won\'t allow to create journal entries using that account.\n"\
"The type 'Analytic account' stands for usual accounts that you only want to use in accounting.\n"\

View File

@ -22,6 +22,7 @@
'name' : 'Fleet Management',
'version' : '0.1',
'author' : 'OpenERP S.A.',
'sequence': 110,
'category': 'Managing vehicles and contracts',
'website' : 'http://www.openerp.com',
'summary' : 'Vehicle, leasing, insurances, costs',

View File

@ -333,9 +333,9 @@ class fleet_vehicle(osv.Model):
'company_id': fields.many2one('res.company', 'Company'),
'license_plate': fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
'vin_sn': fields.char('Chassis Number', size=32, help='Unique number written on the vehicle motor (VIN/SN number)'),
'driver_id': fields.many2one('res.partner', 'Driver', _idhelp='Driver of the vehicle'),
'model_id': fields.many2one('fleet.vehicle.model', 'Model', requ_idired=True, help='Model of the vehicle'),
'log_fuel': fields.one2many('fleet.vehicle.log.f_iduel', 'vehicle_id', 'Fuel Logs'),
'driver_id': fields.many2one('res.partner', 'Driver', help='Driver of the vehicle'),
'model_id': fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
'log_fuel': fields.one2many('fleet.vehicle.log.fuel', 'vehicle_id', 'Fuel Logs'),
'log_services': fields.one2many('fleet.vehicle.log.services', 'vehicle_id', 'Services Logs'),
'log_contracts': fields.one2many('fleet.vehicle.log.contract', 'vehicle_id', 'Contracts'),
'acquisition_date': fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
@ -468,10 +468,13 @@ class fleet_vehicle_log_fuel(osv.Model):
def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
if not vehicle_id:
return {}
odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
vehicle = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context)
odometer_unit = vehicle.odometer_unit
driver = vehicle.driver_id.id
return {
'value': {
'odometer_unit': odometer_unit,
'purchaser_id': driver,
}
}
@ -546,7 +549,6 @@ class fleet_vehicle_log_fuel(osv.Model):
'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
}
_defaults = {
'purchaser_id': lambda self, cr, uid, ctx: uid,
'date': fields.date.context_today,
'cost_subtype_id': _get_default_service_type,
'cost_type': 'fuel',
@ -558,10 +560,13 @@ class fleet_vehicle_log_services(osv.Model):
def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
if not vehicle_id:
return {}
odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
vehicle = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context)
odometer_unit = vehicle.odometer_unit
driver = vehicle.driver_id.id
return {
'value': {
'odometer_unit': odometer_unit,
'purchaser_id': driver,
}
}
@ -583,7 +588,6 @@ class fleet_vehicle_log_services(osv.Model):
'notes': fields.text('Notes'),
}
_defaults = {
'purchaser_id': lambda self, cr, uid, ctx: uid,
'date': fields.date.context_today,
'cost_subtype_id': _get_default_service_type,
'cost_type': 'services'

View File

@ -16,6 +16,17 @@
</record>
-->
<!-- After installation of the module, open the related menu -->
<record id="action_fleet_menu" model="ir.actions.client">
<field name="name">Open Fleet Menu</field>
<field name="tag">reload</field>
<field name="params" eval="{'menu_id': ref('fleet.menu_root')}"/>
</record>
<record id="base.open_menu" model="ir.actions.todo">
<field name="action_id" ref="action_fleet_menu"/>
<field name="state">open</field>
</record>
<record forcecreate="True" id="ir_cron_contract_costs_generator" model="ir.cron">
<field name="name">Generation of contracts costs based on the costs frequency</field>
<field eval="True" name="active" />

View File

@ -28,9 +28,9 @@
<field name="color">Black</field>
<field name="location">Grand-Rosiere</field>
<field name="doors">5</field>
<field name="driver_id" ref="base.res_partner_address_18" />
<field name="driver_id" ref="base.user_demo" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state" ref="vehicle_state_active"/>
<field name="state_id" ref="vehicle_state_active"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">20000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_break'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
@ -45,7 +45,7 @@
<field name="doors">5</field>
<field name="driver_id" ref="base.res_partner_address_19" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state" ref="vehicle_state_inactive"/>
<field name="state_id" ref="vehicle_state_inactive"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">16000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_compact'),ref('fleet.vehicle_tag_junior')])]" name="tag_ids"/>
@ -60,7 +60,7 @@
<field name="doors">3</field>
<field name="driver_id" ref="base.res_partner_address_17" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state" ref="vehicle_state_active"/>
<field name="state_id" ref="vehicle_state_active"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">20000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_compact'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
@ -75,7 +75,7 @@
<field name="doors">3</field>
<field name="driver_id" ref="base.res_partner_address_16" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state" ref="vehicle_state_active"/>
<field name="state_id" ref="vehicle_state_active"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">20000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_compact'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
@ -90,7 +90,7 @@
<field name="doors">5</field>
<field name="driver_id" ref="base.res_partner_address_15" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state" ref="vehicle_state_active"/>
<field name="state_id" ref="vehicle_state_active"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">18000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_compact'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>

View File

@ -20,7 +20,23 @@
</div>
<notebook>
<page string="Vendors">
<field name="vendors" widget="many2many_kanban"/>
<field name="vendors" widget="many2many_kanban">
<kanban quick_create="false" create="true">
<field name="name"/>
<templates>
<t t-name="kanban-box">
<div style="position: relative">
<a t-if="! read_only_mode" type="delete" style="position: absolute; right: 0; padding: 4px; diplay: inline-block">X</a>
<div class="oe_module_vignette">
<div class="oe_module_desc">
<field name="name"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</page>
</notebook>
</sheet>
@ -38,11 +54,25 @@
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_model_search'>
<field name="name">fleet.vehicle.model.search</field>
<field name="model">fleet.vehicle.model</field>
<field name="arch" type="xml">
<search string="Vehicles costs" >
<field name="brand_id" />
<group expand="1" string="Group By...">
<filter name="groupby_brand" context="{'group_by' : 'brand_id'}" string="Brand"/>
</group>
</search>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_model_act'>
<field name="name">Vehicle Model</field>
<field name="res_model">fleet.vehicle.model</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{"search_default_groupby_brand" : True,}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new model.

View File

@ -8,11 +8,13 @@
<record id="group_fleet_user" model="res.groups">
<field name="name">User</field>
<field name="category_id" ref="module_fleet_category"/>
<field name="users" eval="[(4, ref('base.user_demo'))]"/>
</record>
<record id="group_fleet_manager" model="res.groups">
<field name="name">Manager</field>
<field name="implied_ids" eval="[(4, ref('group_fleet_user'))]"/>
<field name="category_id" ref="module_fleet_category"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
<record id="fleet_user_contract_visibility" model="ir.rule">
<field name="name">User can only see his/her contracts</field>

View File

@ -16,10 +16,8 @@
</div>
</group>
<group>
<separator string="Journals" colspan="4"/>
<field name="journal_ids" colspan="4" nolabel="1"/>
<separator string="Users" colspan="4"/>
<field name="employee_ids" colspan="4" nolabel="1"/>
<field name="journal_ids" widget="many2many_tags"/>
<field name="employee_ids" widget="many2many_tags"/>
</group>
</sheet>
<footer>

View File

@ -33,5 +33,6 @@ import wizard
import res_config
import mail_group_menu
import update
import controllers
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,3 @@
import main
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,22 @@
import base64
import openerp.addons.web.http as oeweb
from openerp.addons.web.controllers.main import content_disposition
#----------------------------------------------------------
# Controller
#----------------------------------------------------------
class MailController(oeweb.Controller):
_cp_path = '/mail'
@oeweb.httprequest
def download_attachment(self, req, model, id, method, attachment_id, **kw):
Model = req.session.model(model)
res = getattr(Model, method)(int(id), int(attachment_id))
if res:
filecontent = base64.b64decode(res.get('base64'))
filename = res.get('filename')
if filecontent and filename:
return req.make_response(filecontent,
headers=[('Content-Type', 'application/octet-stream'),
('Content-Disposition', content_disposition(filename, req))])
return req.not_found()

View File

@ -204,6 +204,22 @@ class mail_message(osv.Model):
self.write(cr, SUPERUSER_ID, message.get('id'), {'vote_user_ids': [(3, uid)]}, context=context)
return new_has_voted or False
#------------------------------------------------------
# download an attachment
#------------------------------------------------------
def download_attachment(self, cr, uid, id_message, attachment_id, context=None):
""" Return the content of linked attachments. """
message = self.browse(cr, uid, id_message, context=context)
if attachment_id in [attachment.id for attachment in message.attachment_ids]:
attachment = self.pool.get('ir.attachment').browse(cr, SUPERUSER_ID, attachment_id, context=context)
if attachment.datas and attachment.datas_fname:
return {
'base64': attachment.datas,
'filename': attachment.datas_fname,
}
return False
#------------------------------------------------------
# Notification API
#------------------------------------------------------

View File

@ -29,8 +29,13 @@ openerp.mail = function (session) {
},
/* Get the url of an attachment {'id': id} */
get_attachment_url: function (session, attachment) {
return session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: attachment['id']});
get_attachment_url: function (session, message_id, attachment_id) {
return session.url('/mail/download_attachment', {
'model': 'mail.message',
'id': message_id,
'method': 'download_attachment',
'attachment_id': attachment_id
});
},
/**
@ -258,7 +263,7 @@ openerp.mail = function (session) {
for (var l in this.attachment_ids) {
var attach = this.attachment_ids[l];
if (!attach.formating) {
attach.url = mail.ChatterUtils.get_attachment_url(this.session, attach);
attach.url = mail.ChatterUtils.get_attachment_url(this.session, this.id, attach.id);
attach.filetype = mail.ChatterUtils.filetype(attach.filename);
attach.name = mail.ChatterUtils.breakword(attach.name || attach.filename);
attach.formating = true;
@ -420,18 +425,23 @@ openerp.mail = function (session) {
/* when the file is uploaded
*/
on_attachment_loaded: function (event, result) {
for (var i in this.attachment_ids) {
if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) {
this.attachment_ids[i]={
'id': result.id,
'name': result.name,
'filename': result.filename,
'url': mail.ChatterUtils.get_attachment_url(this.session, result)
};
if (result.erorr || !result.id ) {
this.do_warn( session.web.qweb.render('mail.error_upload'), result.error);
this.attachment_ids = _.filter(this.attachment_ids, function (val) { return !val.upload; });
} else {
for (var i in this.attachment_ids) {
if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) {
this.attachment_ids[i]={
'id': result.id,
'name': result.name,
'filename': result.filename,
'url': mail.ChatterUtils.get_attachment_url(this.session, this.id, result.id)
};
}
}
}
this.display_attachments();
var $input = this.$('input.oe_form_binary_file');
$input.after($input.clone(true)).remove();
this.$(".oe_attachment_file").show();
@ -484,6 +494,11 @@ openerp.mail = function (session) {
},
on_compose_fullmail: function (default_composition_mode) {
if(!this.do_check_attachment_upload()) {
return false;
}
if (default_composition_mode == 'reply') {
var context = {
'default_composition_mode': default_composition_mode,
@ -534,31 +549,31 @@ openerp.mail = function (session) {
this.reinit();
},
/* return true if all file are complete else return false and make an alert */
do_check_attachment_upload: function () {
if (_.find(this.attachment_ids, function (file) {return file.upload;})) {
this.do_warn(session.web.qweb.render('mail.error_upload'), session.web.qweb.render('mail.error_upload_please_wait'));
return false;
} else {
return true;
}
},
/*post a message and fetch the message*/
on_message_post: function (event) {
var self = this;
var comment_node = this.$('textarea');
var body = comment_node.val();
comment_node.val('');
var attachments=[];
for (var i in this.attachment_ids) {
if (this.attachment_ids[i].upload) {
session.web.dialog($('<div>' + session.web.qweb.render('CrashManager.warning', {message: 'Please, wait while the file is uploading.'}) + '</div>'));
return false;
}
attachments.push(this.attachment_ids[i].id);
}
if (body.match(/\S+/)) {
if (this.do_check_attachment_upload() && (this.attachment_ids.length || body.match(/\S+/))) {
//session.web.blockUI();
this.parent_thread.ds_thread.call('message_post_user_api', [
this.context.default_res_id,
body,
false,
this.context.default_parent_id,
attachments,
_.map(this.attachment_ids, function (file) {return file.id;}),
this.parent_thread.context
]).done(function (record) {
var thread = self.parent_thread;
@ -571,8 +586,8 @@ openerp.mail = function (session) {
var message = thread.create_message_object( data[0] );
// insert the message on dom
thread.insert_message( message, root ? undefined : self.$el, root );
self.on_cancel();
});
self.on_cancel();
//session.web.unblockUI();
});
return true;

View File

@ -75,7 +75,7 @@
<t t-foreach='widget.attachment_ids' t-as='attachment'>
<t t-if="attachment.filetype !== 'webimage'">
<div t-attf-class="oe_attachment #{attachment.upload ? 'oe_uploading' : ''}">
<a t-att-href='attachment.url'>
<a t-att-href='attachment.url' target="_blank">
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img>
<div class='oe_name'><t t-raw='attachment.name' /></div>
</a>
@ -87,7 +87,7 @@
</t>
<t t-if="attachment.filetype === 'webimage'">
<div t-attf-class="oe_attachment oe_preview #{attachment.upload ? 'oe_uploading' : ''}">
<a t-att-href='attachment.url'>
<a t-att-href='attachment.url' target="_blank">
<img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img>
<div class='oe_name'><t t-raw='attachment.name' /></div>
</a>
@ -179,6 +179,12 @@
<div class="oe_view_nocontent">No messages.</div>
</t>
<!--
error message for uploading
-->
<t t-name="mail.error_upload">Uploading error</t>
<t t-name="mail.error_upload_please_wait">Please, wait while the file is uploading.</t>
<!--
record_thread main template
Template used to display the communication history in documents

View File

@ -50,6 +50,7 @@ class TestMailBase(common.TransactionCase):
# Usefull models
self.ir_model = self.registry('ir.model')
self.ir_attachment = self.registry('ir.attachment')
self.mail_alias = self.registry('mail.alias')
self.mail_thread = self.registry('mail.thread')
self.mail_group = self.registry('mail.group')

View File

@ -422,6 +422,10 @@ class test_mail(TestMailBase):
self.assertEqual(attach.res_id, self.group_pigs_id, 'mail.message attachment res_id incorrect')
self.assertIn((attach.name, attach.datas.decode('base64')), _attachments,
'mail.message attachment name / data incorrect')
# Test: download attachments
for attach in message2.attachment_ids:
dl_attach = self.mail_message.download_attachment(cr, user_raoul.id, id_message=message2.id, attachment_id=attach.id)
self.assertIn((dl_attach['filename'], dl_attach['base64'].decode('base64')), _attachments, 'mail.message download_attachment is incorrect')
# 2. Dédé has been notified -> should also have been notified of the parent message
message1.refresh()

View File

@ -128,12 +128,16 @@ class test_mail_access_rights(TestMailBase):
# Prepare groups: Pigs (employee), Jobs (public)
self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message')
# prepare an attachment
attachment_id = self.ir_attachment.create(cr, uid, {'datas': 'My attachment'.encode('base64'), 'name': 'doc.txt', 'datas_fname': 'doc.txt'})
# ----------------------------------------
# CASE1: read
# ----------------------------------------
# Do: create a new mail.message
message_id = self.mail_message.create(cr, uid, {'body': 'My Body'})
message_id = self.mail_message.create(cr, uid, {'body': 'My Body', 'attachment_ids': [(4, attachment_id)]})
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
self.assertRaises(except_orm, self.mail_message.read,
cr, user_bert_id, message_id)
@ -141,11 +145,16 @@ class test_mail_access_rights(TestMailBase):
notif_id = self.mail_notification.create(cr, uid, {'message_id': message_id, 'partner_id': partner_bert_id})
# Test: Bert reads the message, ok because notification pushed
self.mail_message.read(cr, user_bert_id, message_id)
# Test: Bert downloads attachment, ok because he can read message
self.mail_message.download_attachment(cr, user_bert_id, message_id, attachment_id)
# Do: remove notification
self.mail_notification.unlink(cr, uid, notif_id)
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
self.assertRaises(except_orm, self.mail_message.read,
cr, self.user_bert_id, message_id)
# Test: Bert downloads attachment, crash because he can't read message
self.assertRaises(except_orm, self.mail_message.download_attachment,
cr, user_bert_id, message_id, attachment_id)
# Do: Bert is now the author
self.mail_message.write(cr, uid, [message_id], {'author_id': partner_bert_id})
# Test: Bert reads the message, ok because Bert is the author

View File

@ -7,3 +7,4 @@ access_res_partner_category,res.partner_category,base.model_res_partner_category
access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal,1,0,0,0
access_acquirer,portal.payment.acquirer,portal.model_portal_payment_acquirer,,1,0,0,0
access_acquirer_all,portal.payment.acquirer,portal.model_portal_payment_acquirer,base.group_system,1,1,1,1
access_ir_attachment_group_portal,ir.attachment group_portal,base.model_ir_attachment,portal.group_portal,1,0,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
7 access_res_partner_title res.partner_title base.model_res_partner_title portal.group_portal 1 0 0 0
8 access_acquirer portal.payment.acquirer portal.model_portal_payment_acquirer 1 0 0 0
9 access_acquirer_all portal.payment.acquirer portal.model_portal_payment_acquirer base.group_system 1 1 1 1
10 access_ir_attachment_group_portal ir.attachment group_portal base.model_ir_attachment portal.group_portal 1 0 1 0

View File

@ -281,7 +281,7 @@
groups="stock.group_stock_user"/>
<!-- Procurements are located in Warehouse menu hierarchy, MRP users should come to Stock application to use it. -->
<menuitem id="menu_stock_sched" name="Schedulers" parent="stock.menu_stock_root" sequence="4"/>
<menuitem id="menu_stock_sched" name="Schedulers" parent="stock.menu_stock_root" sequence="4" groups="stock.group_stock_manager"/>
<menuitem action="action_compute_schedulers" id="menu_stock_proc_schedulers" parent="menu_stock_sched" sequence="20" groups="stock.group_stock_manager"/>
<menuitem action="procurement_exceptions" id="menu_stock_procurement_action" parent="menu_stock_sched" sequence="50" groups="stock.group_stock_manager"/>
<menuitem id="menu_stock_procurement" name="Automatic Procurements" parent="stock.menu_stock_configuration" sequence="5"/>

View File

@ -17,6 +17,7 @@ access_project_project_sale_user,project.project salesman,model_project_project,
access_account_analytic_line_project,account.analytic.line project,analytic.model_account_analytic_line,project.group_project_manager,1,1,1,1
access_project_task_history,project.task.history project,project.model_project_task_history,project.group_project_user,1,1,1,0
access_project_task_history_cumulative,project.task.history project,project.model_project_task_history_cumulative,project.group_project_manager,1,0,0,0
access_project_task_history_cumulative,project.task.history project,project.model_project_task_history_cumulative,project.group_project_user,1,0,0,0
access_resource_calendar,project.resource_calendar manager,resource.model_resource_calendar,project.group_project_manager,1,0,0,0
access_project_category,project.project_category,model_project_category,,1,0,0,0
access_project_category_manager,project.project_category,model_project_category,project.group_project_manager,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
17 access_account_analytic_line_project account.analytic.line project analytic.model_account_analytic_line project.group_project_manager 1 1 1 1
18 access_project_task_history project.task.history project project.model_project_task_history project.group_project_user 1 1 1 0
19 access_project_task_history_cumulative project.task.history project project.model_project_task_history_cumulative project.group_project_manager 1 0 0 0
20 access_project_task_history_cumulative project.task.history project project.model_project_task_history_cumulative project.group_project_user 1 0 0 0
21 access_resource_calendar project.resource_calendar manager resource.model_resource_calendar project.group_project_manager 1 0 0 0
22 access_project_category project.project_category model_project_category 1 0 0 0
23 access_project_category_manager project.project_category model_project_category project.group_project_manager 1 1 1 1

View File

@ -22,7 +22,7 @@
<!-- Resource: sale.shop -->
<record id="sale_shop_1" model="sale.shop">
<field name="company_id" ref="base.main_company"/>
<field name="payment_default_id" ref="account.account_payment_term"/>
<field name="payment_default_id" ref="account.account_payment_term_net"/>
<field name="pricelist_id" ref="product.list0"/>
<!-- Copy the name of any company. Without demo data this will yield

View File

@ -9,7 +9,7 @@
<menuitem name="Reporting" parent="base.menu_tools"
id="base.menu_lunch_reporting" sequence="6"/>
<menuitem name="Reporting" id="menu_reporting" parent="menu_surveys" sequence="60"/>
<menuitem id="base.next_id_10" name="Survey" parent="base.menu_reporting" sequence="1" />
<menuitem id="base.next_id_10" name="Survey" parent="base.menu_reporting" sequence="1" groups="base.group_survey_user"/>
<!--
Survey