[MERGE] forward port of branch saas-2 up to revid 9024 chs@openerp.com-20131130130014-hi5h5a00kjx0dbvp

It’s over NINE THOUSAAAAAAAND!

bzr revid: chs@openerp.com-20131130130725-9ntxdr5r7r04uoht
This commit is contained in:
Christophe Simonis 2013-11-30 14:07:25 +01:00
commit 289023d92f
22 changed files with 110 additions and 59 deletions

View File

@ -3414,6 +3414,8 @@ class wizard_multi_charts_accounts(osv.osv_memory):
all the provided information to create the accounts, the banks, the journals, the taxes, the tax codes, the all the provided information to create the accounts, the banks, the journals, the taxes, the tax codes, the
accounting properties... accordingly for the chosen company. accounting properties... accordingly for the chosen company.
''' '''
if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
obj_data = self.pool.get('ir.model.data') obj_data = self.pool.get('ir.model.data')
ir_values_obj = self.pool.get('ir.values') ir_values_obj = self.pool.get('ir.values')
obj_wizard = self.browse(cr, uid, ids[0]) obj_wizard = self.browse(cr, uid, ids[0])
@ -3430,7 +3432,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
self.pool[tmp2[0]].write(cr, uid, tmp2[1], { self.pool[tmp2[0]].write(cr, uid, tmp2[1], {
'currency_id': obj_wizard.currency_id.id 'currency_id': obj_wizard.currency_id.id
}) })
except ValueError, e: except ValueError:
pass pass
# If the floats for sale/purchase rates have been filled, create templates from them # If the floats for sale/purchase rates have been filled, create templates from them

View File

@ -295,7 +295,7 @@
</para> </para>
</td> </td>
<td> <td>
<para style="terp_tblheader_Details"><b>Total:</b></para> <para style="terp_default_9"><b>Total:</b></para>
</td> </td>
<td> <td>
<para style="terp_default_Bold_Right_9"><b>[[ formatLang(o.amount_total, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]]</b></para> <para style="terp_default_Bold_Right_9"><b>[[ formatLang(o.amount_total, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]]</b></para>

View File

@ -22,13 +22,12 @@
import time import time
import datetime import datetime
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from operator import itemgetter
from os.path import join as opj
import openerp
from openerp import SUPERUSER_ID
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from openerp.tools.translate import _ from openerp.tools.translate import _
from openerp.osv import fields, osv from openerp.osv import fields, osv
from openerp import tools
class account_config_settings(osv.osv_memory): class account_config_settings(osv.osv_memory):
_name = 'account.config.settings' _name = 'account.config.settings'
@ -276,11 +275,13 @@ class account_config_settings(osv.osv_memory):
def set_default_taxes(self, cr, uid, ids, context=None): def set_default_taxes(self, cr, uid, ids, context=None):
""" set default sale and purchase taxes for products """ """ set default sale and purchase taxes for products """
if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
ir_values = self.pool.get('ir.values') ir_values = self.pool.get('ir.values')
config = self.browse(cr, uid, ids[0], context) config = self.browse(cr, uid, ids[0], context)
ir_values.set_default(cr, uid, 'product.product', 'taxes_id', ir_values.set_default(cr, SUPERUSER_ID, 'product.product', 'taxes_id',
config.default_sale_tax and [config.default_sale_tax.id] or False, company_id=config.company_id.id) config.default_sale_tax and [config.default_sale_tax.id] or False, company_id=config.company_id.id)
ir_values.set_default(cr, uid, 'product.product', 'supplier_taxes_id', ir_values.set_default(cr, SUPERUSER_ID, 'product.product', 'supplier_taxes_id',
config.default_purchase_tax and [config.default_purchase_tax.id] or False, company_id=config.company_id.id) config.default_purchase_tax and [config.default_purchase_tax.id] or False, company_id=config.company_id.id)
def set_chart_of_accounts(self, cr, uid, ids, context=None): def set_chart_of_accounts(self, cr, uid, ids, context=None):

View File

@ -373,7 +373,7 @@ openerp.base_import = function (instance) {
return $.when([{ return $.when([{
type: 'error', type: 'error',
record: false, record: false,
message: error.data.fault_code, message: error.data.arguments[1],
}]); }]);
}) ; }) ;
}, },

View File

@ -38,6 +38,9 @@ class crm_lead2opportunity_partner(osv.osv_memory):
'section_id': fields.many2one('crm.case.section', 'Sales Team', select=True), 'section_id': fields.many2one('crm.case.section', 'Sales Team', select=True),
} }
def onchange_action(self, cr, uid, ids, action, context=None):
return {'value': {'partner_id': False if action != 'exist' else self._find_matching_partner(cr, uid, context=context)}}
def default_get(self, cr, uid, fields, context=None): def default_get(self, cr, uid, fields, context=None):
""" """
Default get for name, opportunity_ids. Default get for name, opportunity_ids.

View File

@ -31,7 +31,7 @@
</field> </field>
</group> </group>
<group name="action" attrs="{'invisible': [('name', '!=', 'convert')]}"> <group name="action" attrs="{'invisible': [('name', '!=', 'convert')]}">
<field name="action" class="oe_inline"/> <field name="action" on_change="onchange_action(action, context)" class="oe_inline"/>
<field name="partner_id" <field name="partner_id"
attrs="{'required': [('action', '=', 'exist')], 'invisible':[('action','!=','exist')]}" attrs="{'required': [('action', '=', 'exist')], 'invisible':[('action','!=','exist')]}"
class="oe_inline"/> class="oe_inline"/>

View File

@ -51,7 +51,9 @@
<search string="Search"> <search string="Search">
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]" help="My Sales Team(s)" groups="base.group_multi_salesteams"/> <filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]" help="My Sales Team(s)" groups="base.group_multi_salesteams"/>
<separator/> <separator/>
<filter string="My Company" icon="terp-go-home" context="{'invisible_section': False}" domain="[('section_id.user_id.company_id','=',uid)]" help="My company"/> <!-- A 'My Company' filter makes no sense regarding record rules, and is not possible to do (uid is not a company): remove me in 8.0 -->
<filter string="My Company" icon="terp-go-home" context="{'invisible_section': False}" domain="[]" help="My company"
invisible="1"/>
<separator/> <separator/>
<filter icon="terp-personal" string="My Case(s)" help="My Case(s)" domain="[('user_id','=',uid)]" /> <filter icon="terp-personal" string="My Case(s)" help="My Case(s)" domain="[('user_id','=',uid)]" />
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>

View File

@ -69,7 +69,11 @@ class document_file(osv.osv):
def check(self, cr, uid, ids, mode, context=None, values=None): def check(self, cr, uid, ids, mode, context=None, values=None):
"""Overwrite check to verify access on directory to validate specifications of doc/access_permissions.rst""" """Overwrite check to verify access on directory to validate specifications of doc/access_permissions.rst"""
if not isinstance(ids, list):
ids = [ids]
super(document_file, self).check(cr, uid, ids, mode, context=context, values=values) super(document_file, self).check(cr, uid, ids, mode, context=context, values=values)
if ids: if ids:
self.pool.get('ir.model.access').check(cr, uid, 'document.directory', mode) self.pool.get('ir.model.access').check(cr, uid, 'document.directory', mode)

View File

@ -369,7 +369,7 @@ class email_template(osv.osv):
attachment_ids=[attach.id for attach in template.attachment_ids], attachment_ids=[attach.id for attach in template.attachment_ids],
) )
# Add report in attachments # Add report in attachments: generate once for all template_res_ids
if template.report_template: if template.report_template:
for res_id in template_res_ids: for res_id in template_res_ids:
attachments = [] attachments = []
@ -387,8 +387,7 @@ class email_template(osv.osv):
if not report_name.endswith(ext): if not report_name.endswith(ext):
report_name += ext report_name += ext
attachments.append((report_name, result)) attachments.append((report_name, result))
results[res_id]['attachments'] = attachments
values['attachments'] = attachments
return results return results

View File

@ -60,10 +60,9 @@ class config(osv.Model):
def get_access_token(self, cr, uid, scope=None, context=None): def get_access_token(self, cr, uid, scope=None, context=None):
ir_config = self.pool['ir.config_parameter'] ir_config = self.pool['ir.config_parameter']
google_drive_refresh_token = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_refresh_token') google_drive_refresh_token = ir_config.get_param(cr, SUPERUSER_ID, 'google_drive_refresh_token')
group_config = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_erp_manager')[1] user_is_admin = self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager')
user = self.pool['res.users'].read(cr, uid, uid, "groups_id")
if not google_drive_refresh_token: if not google_drive_refresh_token:
if group_config in user['groups_id']: if user_is_admin:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("You haven't configured 'Authorization Code' generated from google, Please generate and configure it in %(menu:base_setup.menu_general_configuration)s."), context=context) raise self.pool.get('res.config.settings').get_config_warning(cr, _("You haven't configured 'Authorization Code' generated from google, Please generate and configure it in %(menu:base_setup.menu_general_configuration)s."), context=context)
else: else:
raise osv.except_osv(_('Error!'), _("Google Drive is not yet configured. Please contact your administrator.")) raise osv.except_osv(_('Error!'), _("Google Drive is not yet configured. Please contact your administrator."))
@ -81,7 +80,7 @@ class config(osv.Model):
req = urllib2.Request('https://accounts.google.com/o/oauth2/token', data, headers) req = urllib2.Request('https://accounts.google.com/o/oauth2/token', data, headers)
content = urllib2.urlopen(req).read() content = urllib2.urlopen(req).read()
except urllib2.HTTPError: except urllib2.HTTPError:
if group_config in user['groups_id']: if user_is_admin:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during the token generation. Please request again an authorization code in %(menu:base_setup.menu_general_configuration)s."), context=context) raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during the token generation. Please request again an authorization code in %(menu:base_setup.menu_general_configuration)s."), context=context)
else: else:
raise osv.except_osv(_('Error!'), _("Google Drive is not yet configured. Please contact your administrator.")) raise osv.except_osv(_('Error!'), _("Google Drive is not yet configured. Please contact your administrator."))

View File

@ -18,6 +18,7 @@
# #
############################################################################## ##############################################################################
import cgi
import simplejson import simplejson
import logging import logging
from lxml import etree from lxml import etree
@ -67,24 +68,24 @@ class config(osv.osv):
request = '''<feed xmlns="http://www.w3.org/2005/Atom" request = '''<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:batch="http://schemas.google.com/gdata/batch"
xmlns:gs="http://schemas.google.com/spreadsheets/2006"> xmlns:gs="http://schemas.google.com/spreadsheets/2006">
<id>https://spreadsheets.google.com/feeds/cells/%s/od6/private/full</id> <id>https://spreadsheets.google.com/feeds/cells/{key}/od6/private/full</id>
<entry> <entry>
<batch:id>A1</batch:id> <batch:id>A1</batch:id>
<batch:operation type="update"/> <batch:operation type="update"/>
<id>https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R1C1</id> <id>https://spreadsheets.google.com/feeds/cells/{key}/od6/private/full/R1C1</id>
<link rel="edit" type="application/atom+xml" <link rel="edit" type="application/atom+xml"
href="https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R1C1"/> href="https://spreadsheets.google.com/feeds/cells/{key}/od6/private/full/R1C1"/>
<gs:cell row="1" col="1" inputValue="%s"/> <gs:cell row="1" col="1" inputValue="{formula}"/>
</entry> </entry>
<entry> <entry>
<batch:id>A2</batch:id> <batch:id>A2</batch:id>
<batch:operation type="update"/> <batch:operation type="update"/>
<id>https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R60C15</id> <id>https://spreadsheets.google.com/feeds/cells/{key}/od6/private/full/R60C15</id>
<link rel="edit" type="application/atom+xml" <link rel="edit" type="application/atom+xml"
href="https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/R60C15"/> href="https://spreadsheets.google.com/feeds/cells/{key}/od6/private/full/R60C15"/>
<gs:cell row="60" col="15" inputValue="%s"/> <gs:cell row="60" col="15" inputValue="{config}"/>
</entry> </entry>
</feed>''' % (spreadsheet_key, spreadsheet_key, spreadsheet_key, formula.replace('"', '&quot;'), spreadsheet_key, spreadsheet_key, config_formula.replace('"', '&quot;')) </feed>''' .format(key=spreadsheet_key, formula=cgi.escape(formula, quote=True), config=cgi.escape(config_formula, quote=True))
try: try:
req = urllib2.Request( req = urllib2.Request(

View File

@ -1096,7 +1096,7 @@ class mail_thread(osv.AbstractModel):
encoding = part.get_content_charset() # None if attachment encoding = part.get_content_charset() # None if attachment
# 1) Explicit Attachments -> attachments # 1) Explicit Attachments -> attachments
if filename or part.get('content-disposition', '').strip().startswith('attachment'): if filename or part.get('content-disposition', '').strip().startswith('attachment'):
attachments.append((filename or 'attachment', part.get_payload(decode=True))) attachments.append((decode(filename) or 'attachment', part.get_payload(decode=True)))
continue continue
# 2) text/plain -> <pre/> # 2) text/plain -> <pre/>
if part.get_content_type() == 'text/plain' and (not alternative or not body): if part.get_content_type() == 'text/plain' and (not alternative or not body):
@ -1321,6 +1321,40 @@ class mail_thread(osv.AbstractModel):
mail_message_obj.write(cr, SUPERUSER_ID, message_ids, {'author_id': partner_info['partner_id']}, context=context) mail_message_obj.write(cr, SUPERUSER_ID, message_ids, {'author_id': partner_info['partner_id']}, context=context)
return result return result
def _message_preprocess_attachments(self, cr, uid, attachments, attachment_ids, attach_model, attach_res_id, context=None):
""" Preprocess attachments for mail_thread.message_post() or mail_mail.create().
:param list attachments: list of attachment tuples in the form ``(name,content)``,
where content is NOT base64 encoded
:param list attachment_ids: a list of attachment ids, not in tomany command form
:param str attach_model: the model of the attachments parent record
:param integer attach_res_id: the id of the attachments parent record
"""
Attachment = self.pool['ir.attachment']
m2m_attachment_ids = []
if attachment_ids:
filtered_attachment_ids = Attachment.search(cr, SUPERUSER_ID, [
('res_model', '=', 'mail.compose.message'),
('create_uid', '=', uid),
('id', 'in', attachment_ids)], context=context)
if filtered_attachment_ids:
Attachment.write(cr, SUPERUSER_ID, filtered_attachment_ids, {'res_model': attach_model, 'res_id': attach_res_id}, context=context)
m2m_attachment_ids += [(4, id) for id in attachment_ids]
# Handle attachments parameter, that is a dictionary of attachments
for name, content in attachments:
if isinstance(content, unicode):
content = content.encode('utf-8')
data_attach = {
'name': name,
'datas': base64.b64encode(str(content)),
'datas_fname': name,
'description': name,
'res_model': attach_model,
'res_id': attach_res_id,
}
m2m_attachment_ids.append((0, 0, data_attach))
return m2m_attachment_ids
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification',
subtype=None, parent_id=False, attachments=None, context=None, subtype=None, parent_id=False, attachments=None, context=None,
content_subtype='html', **kwargs): content_subtype='html', **kwargs):
@ -1399,28 +1433,7 @@ class mail_thread(osv.AbstractModel):
# 3. Attachments # 3. Attachments
# - HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message # - HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
attachment_ids = kwargs.pop('attachment_ids', []) or [] # because we could receive None (some old code sends None) attachment_ids = self._message_preprocess_attachments(cr, uid, attachments, kwargs.pop('attachment_ids', []), model, thread_id, context)
if attachment_ids:
filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [
('res_model', '=', 'mail.compose.message'),
('create_uid', '=', uid),
('id', 'in', attachment_ids)], context=context)
if filtered_attachment_ids:
ir_attachment.write(cr, SUPERUSER_ID, filtered_attachment_ids, {'res_model': model, 'res_id': thread_id}, context=context)
attachment_ids = [(4, id) for id in attachment_ids]
# Handle attachments parameter, that is a dictionary of attachments
for name, content in attachments:
if isinstance(content, unicode):
content = content.encode('utf-8')
data_attach = {
'name': name,
'datas': base64.b64encode(str(content)),
'datas_fname': name,
'description': name,
'res_model': model,
'res_id': thread_id,
}
attachment_ids.append((0, 0, data_attach))
# 4: mail.message.subtype # 4: mail.message.subtype
subtype_id = False subtype_id = False

View File

@ -634,7 +634,7 @@
margin-bottom: 4px; margin-bottom: 4px;
} }
.openerp .oe_followers .oe_invite{ .openerp .oe_followers .oe_invite{
float: right; padding-left: 5px;
} }
.openerp .oe_followers .oe_partner { .openerp .oe_followers .oe_partner {
height: 32px; height: 32px;

View File

@ -19,7 +19,9 @@
# #
############################################################################## ##############################################################################
import base64
import re import re
from openerp import tools from openerp import tools
from openerp import SUPERUSER_ID from openerp import SUPERUSER_ID
from openerp.osv import osv from openerp.osv import osv
@ -260,6 +262,12 @@ class mail_compose_message(osv.TransientModel):
for res_id, mail_values in all_mail_values.iteritems(): for res_id, mail_values in all_mail_values.iteritems():
if mass_mail_mode and not wizard.post: if mass_mail_mode and not wizard.post:
m2m_attachment_ids = self.pool['mail.thread']._message_preprocess_attachments(
cr, uid, mail_values.pop('attachments', []),
mail_values.pop('attachment_ids', []),
'mail.message', 0,
context=context)
mail_values['attachment_ids'] = m2m_attachment_ids
self.pool.get('mail.mail').create(cr, uid, mail_values, context=context) self.pool.get('mail.mail').create(cr, uid, mail_values, context=context)
else: else:
subtype = 'mail.mt_comment' subtype = 'mail.mt_comment'
@ -298,7 +306,12 @@ class mail_compose_message(osv.TransientModel):
if mass_mail_mode and wizard.model: if mass_mail_mode and wizard.model:
email_dict = rendered_values[res_id] email_dict = rendered_values[res_id]
mail_values['partner_ids'] += email_dict.pop('partner_ids', []) mail_values['partner_ids'] += email_dict.pop('partner_ids', [])
mail_values['attachments'] = email_dict.pop('attachments', []) # process attachments: should not be encoded before being processed by message_post / mail_mail create
attachments = []
if email_dict.get('attachments'):
for name, enc_cont in email_dict.pop('attachments'):
attachments.append((name, base64.b64decode(enc_cont)))
mail_values['attachments'] = attachments
attachment_ids = [] attachment_ids = []
for attach_id in mail_values.pop('attachment_ids'): for attach_id in mail_values.pop('attachment_ids'):
new_attach_id = self.pool.get('ir.attachment').copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context) new_attach_id = self.pool.get('ir.attachment').copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context)

View File

@ -147,6 +147,7 @@ class note_note(osv.osv):
if result and result[0]['stage_id'][0] == current_stage_ids[0]: if result and result[0]['stage_id'][0] == current_stage_ids[0]:
dom_in = result[0]['__domain'].pop() dom_in = result[0]['__domain'].pop()
result[0]['__domain'] = domain + ['|', dom_in, dom_not_in] result[0]['__domain'] = domain + ['|', dom_in, dom_not_in]
result[0]['stage_id_count'] += nb_notes_ws
else: else:
# add the first stage column # add the first stage column
result = [{ result = [{

View File

@ -92,6 +92,7 @@
font-family: arial, sans-serif; font-family: arial, sans-serif;
font-size: 15px; font-size: 15px;
line-height: 19px; line-height: 19px;
word-wrap: break-word;
} }
.openerp .oe_form_nomargin .etherpad_readonly{ .openerp .oe_form_nomargin .etherpad_readonly{

View File

@ -860,6 +860,14 @@ class purchase_order_line(osv.osv):
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total']) res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
return res return res
def _get_uom_id(self, cr, uid, context=None):
try:
proxy = self.pool.get('ir.model.data')
result = proxy.get_object_reference(cr, uid, 'product', 'product_uom_unit')
return result[1]
except Exception, ex:
return False
_columns = { _columns = {
'name': fields.text('Description', required=True), 'name': fields.text('Description', required=True),
'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True),
@ -886,6 +894,7 @@ class purchase_order_line(osv.osv):
} }
_defaults = { _defaults = {
'product_uom' : _get_uom_id,
'product_qty': lambda *a: 1.0, 'product_qty': lambda *a: 1.0,
'state': lambda *args: 'draft', 'state': lambda *args: 'draft',
'invoiced': lambda *a: 0, 'invoiced': lambda *a: 0,
@ -1289,8 +1298,8 @@ class account_invoice(osv.Model):
else: else:
user_id = uid user_id = uid
po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context) po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
if po_ids: for po_id in po_ids:
purchase_order_obj.message_post(cr, user_id, po_ids, body=_("Invoice paid"), context=context) purchase_order_obj.message_post(cr, user_id, po_id, body=_("Invoice paid"), context=context)
return res return res
class account_invoice_line(osv.Model): class account_invoice_line(osv.Model):

View File

@ -199,7 +199,7 @@
</group> </group>
<group> <group>
<field name="date_order"/> <field name="date_order"/>
<field name="origin" attr="{'invisible': [('origin','=',False)]}"/> <field name="origin" attrs="{'invisible': [('origin','=',False)]}"/>
<field name="warehouse_id" on_change="onchange_warehouse_id(warehouse_id)" widget="selection" groups="stock.group_locations"/> <field name="warehouse_id" on_change="onchange_warehouse_id(warehouse_id)" widget="selection" groups="stock.group_locations"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/> <field name="company_id" groups="base.group_multi_company" widget="selection"/>
</group> </group>

View File

@ -61,7 +61,7 @@ class sale_order_line_make_invoice(osv.osv_memory):
else: else:
pay_term = False pay_term = False
inv = { inv = {
'name': order.name, 'name': order.client_order_ref or '',
'origin': order.name, 'origin': order.name,
'type': 'out_invoice', 'type': 'out_invoice',
'reference': "P%dSO%d" % (order.partner_id.id, order.id), 'reference': "P%dSO%d" % (order.partner_id.id, order.id),

View File

@ -19,6 +19,8 @@
# #
############################################################################## ##############################################################################
import openerp
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv from openerp.osv import fields, osv
from openerp.tools.translate import _ from openerp.tools.translate import _
@ -72,12 +74,13 @@ class sale_configuration(osv.osv_memory):
} }
def set_sale_defaults(self, cr, uid, ids, context=None): def set_sale_defaults(self, cr, uid, ids, context=None):
if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
ir_values = self.pool.get('ir.values') ir_values = self.pool.get('ir.values')
ir_model_data = self.pool.get('ir.model.data')
wizard = self.browse(cr, uid, ids)[0] wizard = self.browse(cr, uid, ids)[0]
default_picking_policy = 'one' if wizard.default_picking_policy else 'direct' default_picking_policy = 'one' if wizard.default_picking_policy else 'direct'
ir_values.set_default(cr, uid, 'sale.order', 'picking_policy', default_picking_policy) ir_values.set_default(cr, SUPERUSER_ID, 'sale.order', 'picking_policy', default_picking_policy)
res = super(sale_configuration, self).set_sale_defaults(cr, uid, ids, context) res = super(sale_configuration, self).set_sale_defaults(cr, uid, ids, context)
return res return res

View File

@ -604,7 +604,7 @@ class sale_order_line(osv.osv):
#check if product is available, and if not: raise an error #check if product is available, and if not: raise an error
uom2 = False uom2 = False
if uom: if uom:
uom2 = product_uom_obj.browse(cr, uid, uom) uom2 = product_uom_obj.browse(cr, uid, uom, context=context)
if product_obj.uom_id.category_id.id != uom2.category_id.id: if product_obj.uom_id.category_id.id != uom2.category_id.id:
uom = False uom = False
if not uom2: if not uom2:

View File

@ -1361,9 +1361,9 @@ class stock_picking(osv.osv):
self.action_move(cr, uid, [new_picking], context=context) self.action_move(cr, uid, [new_picking], context=context)
self.signal_button_done(cr, uid, [new_picking]) self.signal_button_done(cr, uid, [new_picking])
workflow.trg_write(uid, 'stock.picking', pick.id, cr) workflow.trg_write(uid, 'stock.picking', pick.id, cr)
delivered_pack_id = new_picking delivered_pack_id = pick.id
back_order_name = self.browse(cr, uid, delivered_pack_id, context=context).name back_order_name = self.browse(cr, uid, delivered_pack_id, context=context).name
self.message_post(cr, uid, ids, body=_("Back order <em>%s</em> has been <b>created</b>.") % (back_order_name), context=context) self.message_post(cr, uid, new_picking, body=_("Back order <em>%s</em> has been <b>created</b>.") % (back_order_name), context=context)
else: else:
self.action_move(cr, uid, [pick.id], context=context) self.action_move(cr, uid, [pick.id], context=context)
self.signal_button_done(cr, uid, [pick.id]) self.signal_button_done(cr, uid, [pick.id])