[MERGE] Forward-port of latest 7.0 fixes up to rev 9618 rev-id: dle@openerp.com-20131120142131-s333lyva85cyn41o

bzr revid: odo@openerp.com-20131120144059-yyh7emvgdarff09b
bzr revid: odo@openerp.com-20131120144318-11nmn1zj00zmi10z
This commit is contained in:
Olivier Dony 2013-11-20 15:43:18 +01:00
commit 44664076da
44 changed files with 306 additions and 357 deletions

View File

@ -1447,6 +1447,8 @@ class account_move(osv.osv):
def unlink(self, cr, uid, ids, context=None, check=True): def unlink(self, cr, uid, ids, context=None, check=True):
if context is None: if context is None:
context = {} context = {}
if isinstance(ids, (int, long)):
ids = [ids]
toremove = [] toremove = []
obj_move_line = self.pool.get('account.move.line') obj_move_line = self.pool.get('account.move.line')
for move in self.browse(cr, uid, ids, context=context): for move in self.browse(cr, uid, ids, context=context):

View File

@ -311,13 +311,13 @@ class account_move_line(osv.osv):
context = {} context = {}
c = context.copy() c = context.copy()
c['initital_bal'] = True c['initital_bal'] = True
sql = """SELECT l2.id, SUM(l1.debit-l1.credit) sql = """SELECT l1.id, COALESCE(SUM(l2.debit-l2.credit), 0)
FROM account_move_line l1, account_move_line l2 FROM account_move_line l1 LEFT JOIN account_move_line l2
WHERE l2.account_id = l1.account_id ON (l1.account_id = l2.account_id
AND l1.id <= l2.id AND l2.id <= l1.id
AND l2.id IN %s AND """ + \ AND """ + \
self._query_get(cr, uid, obj='l1', context=c) + \ self._query_get(cr, uid, obj='l2', context=c) + \
" GROUP BY l2.id" ") WHERE l1.id IN %s GROUP BY l1.id"
cr.execute(sql, [tuple(ids)]) cr.execute(sql, [tuple(ids)])
return dict(cr.fetchall()) return dict(cr.fetchall())

View File

@ -52,10 +52,19 @@ class account_invoice_refund(osv.osv_memory):
journal = obj_journal.search(cr, uid, [('type', '=', type), ('company_id','=',company_id)], limit=1, context=context) journal = obj_journal.search(cr, uid, [('type', '=', type), ('company_id','=',company_id)], limit=1, context=context)
return journal and journal[0] or False return journal and journal[0] or False
def _get_reason(self, cr, uid, context=None):
active_id = context and context.get('active_id', False)
if active_id:
inv = self.pool.get('account.invoice').browse(cr, uid, active_id, context=context)
return inv.name
else:
return ''
_defaults = { _defaults = {
'date': lambda *a: time.strftime('%Y-%m-%d'), 'date': lambda *a: time.strftime('%Y-%m-%d'),
'journal_id': _get_journal, 'journal_id': _get_journal,
'filter_refund': 'refund', 'filter_refund': 'refund',
'description': _get_reason,
} }
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False): def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):

View File

@ -39,12 +39,6 @@ openerp.auth_signup = function(instance) {
delete self.params.error_message; delete self.params.error_message;
} }
// in case of a signup, retrieve the user information from the token
if (dbname && self.params.token) {
self.rpc("/auth_signup/retrieve", {dbname: dbname, token: self.params.token})
.done(self.on_token_loaded)
.fail(self.on_token_failed);
}
if (dbname && self.params.login) { if (dbname && self.params.login) {
self.$("form input[name=login]").val(self.params.login); self.$("form input[name=login]").val(self.params.login);
} }
@ -53,7 +47,7 @@ openerp.auth_signup = function(instance) {
self.$('a.oe_signup_reset_password').click(self.do_reset_password); self.$('a.oe_signup_reset_password').click(self.do_reset_password);
if (dbname) { if (dbname) {
self.rpc("/auth_signup/get_config", {dbname: dbname}).done(function(result) { self.rpc("/auth_signup/get_config", {dbname: dbname}).then(function(result) {
self.signup_enabled = result.signup; self.signup_enabled = result.signup;
self.reset_password_enabled = result.reset_password; self.reset_password_enabled = result.reset_password;
if (!self.signup_enabled || self.$("form input[name=login]").val()){ if (!self.signup_enabled || self.$("form input[name=login]").val()){
@ -61,6 +55,13 @@ openerp.auth_signup = function(instance) {
} else { } else {
self.set('login_mode', 'signup'); self.set('login_mode', 'signup');
} }
// in case of a signup, retrieve the user information from the token
if (self.params.token) {
self.rpc("/auth_signup/retrieve", {dbname: dbname, token: self.params.token})
.then(self.on_token_loaded, self.on_token_failed);
}
}); });
} else { } else {
// TODO: support multiple database mode // TODO: support multiple database mode

View File

@ -836,9 +836,11 @@ class crm_lead(format_address, osv.osv):
model_data = self.pool.get('ir.model.data') model_data = self.pool.get('ir.model.data')
phonecall_dict = {} phonecall_dict = {}
if not categ_id: if not categ_id:
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2') try:
if res_id: res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
except ValueError:
pass
for lead in self.browse(cr, uid, ids, context=context): for lead in self.browse(cr, uid, ids, context=context):
if not section_id: if not section_id:
section_id = lead.section_id and lead.section_id.id or False section_id = lead.section_id and lead.section_id.id or False
@ -945,6 +947,23 @@ class crm_lead(format_address, osv.osv):
vals.update(onchange_stage_values) vals.update(onchange_stage_values)
return super(crm_lead, self).write(cr, uid, ids, vals, context=context) return super(crm_lead, self).write(cr, uid, ids, vals, context=context)
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
if not context:
context = {}
lead = self.browse(cr, uid, id, context=context)
local_context = dict(context)
local_context.setdefault('default_type', lead.type)
local_context.setdefault('default_section_id', lead.section_id)
if lead.type == 'opportunity':
default['date_open'] = fields.datetime.now()
else:
default['date_open'] = False
default['date_closed'] = False
default['stage_id'] = self._get_default_stage_id(cr, uid, local_context)
return super(crm_lead, self).copy(cr, uid, id, default, context=context)
# ---------------------------------------- # ----------------------------------------
# Mail Gateway # Mail Gateway
# ---------------------------------------- # ----------------------------------------

View File

@ -323,7 +323,7 @@
<field name="model">crm.lead</field> <field name="model">crm.lead</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Search Leads"> <search string="Search Leads">
<field name="name" string="Lead / Customer" filter_domain="['|','|',('partner_name','ilike',self),('email_from','ilike',self),('name','ilike',self)]"/> <field name="name" string="Lead / Customer" filter_domain="['|','|','|',('partner_name','ilike',self),('email_from','ilike',self),('contact_name','ilike',self),('name','ilike',self)]"/>
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/> <field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/>
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/> <field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="user_id"/> <field name="user_id"/>

View File

@ -117,9 +117,11 @@ class crm_phonecall(osv.osv):
model_data = self.pool.get('ir.model.data') model_data = self.pool.get('ir.model.data')
phonecall_dict = {} phonecall_dict = {}
if not categ_id: if not categ_id:
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2') try:
if res_id: res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
except ValueError:
pass
for call in self.browse(cr, uid, ids, context=context): for call in self.browse(cr, uid, ids, context=context):
if not section_id: if not section_id:
section_id = call.section_id and call.section_id.id or False section_id = call.section_id and call.section_id.id or False

View File

@ -34,9 +34,11 @@ class crm_opportunity2phonecall(osv.osv_memory):
opp_obj = self.pool.get('crm.lead') opp_obj = self.pool.get('crm.lead')
categ_id = False categ_id = False
data_obj = self.pool.get('ir.model.data') data_obj = self.pool.get('ir.model.data')
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2') try:
if res_id: res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
except ValueError:
pass
record_ids = context and context.get('active_ids', []) or [] record_ids = context and context.get('active_ids', []) or []
res = {} res = {}

View File

@ -78,9 +78,11 @@ class crm_phonecall2phonecall(osv.osv_memory):
categ_id = False categ_id = False
data_obj = self.pool.get('ir.model.data') data_obj = self.pool.get('ir.model.data')
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2') try:
if res_id: res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
except ValueError:
pass
if 'name' in fields: if 'name' in fields:
res.update({'name': phonecall.name}) res.update({'name': phonecall.name})

View File

@ -108,7 +108,7 @@ class crm_claim(osv.osv):
_defaults = { _defaults = {
'user_id': lambda s, cr, uid, c: uid, 'user_id': lambda s, cr, uid, c: uid,
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c), 'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
'date': fields.datetime.now(), 'date': fields.datetime.now,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c), 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
'active': lambda *a: 1, 'active': lambda *a: 1,
@ -172,7 +172,8 @@ class crm_claim(osv.osv):
through message_process. through message_process.
This override updates the document according to the email. This override updates the document according to the email.
""" """
if custom_values is None: custom_values = {} if custom_values is None:
custom_values = {}
desc = html2plaintext(msg.get('body')) if msg.get('body') else '' desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
defaults = { defaults = {
'name': msg.get('subject') or _("No Subject"), 'name': msg.get('subject') or _("No Subject"),
@ -184,33 +185,7 @@ class crm_claim(osv.osv):
if msg.get('priority'): if msg.get('priority'):
defaults['priority'] = msg.get('priority') defaults['priority'] = msg.get('priority')
defaults.update(custom_values) defaults.update(custom_values)
return super(crm_claim,self).message_new(cr, uid, msg, custom_values=defaults, context=context) return super(crm_claim, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if update_vals is None: update_vals = {}
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
update_vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
for line in msg['body'].split('\n'):
line = line.strip()
res = tools.command_re.match(line)
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
update_vals[key] = res.group(2).lower()
return super(crm_claim,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
class res_partner(osv.osv): class res_partner(osv.osv):
_inherit = 'res.partner' _inherit = 'res.partner'

View File

@ -80,7 +80,7 @@ class crm_helpdesk(osv.osv):
'active': lambda *a: 1, 'active': lambda *a: 1,
'user_id': lambda s, cr, uid, c: uid, 'user_id': lambda s, cr, uid, c: uid,
'state': lambda *a: 'draft', 'state': lambda *a: 'draft',
'date': lambda *a: fields.datetime.now(), 'date': fields.datetime.now,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c), 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
} }
@ -126,7 +126,8 @@ class crm_helpdesk(osv.osv):
through message_process. through message_process.
This override updates the document according to the email. This override updates the document according to the email.
""" """
if custom_values is None: custom_values = {} if custom_values is None:
custom_values = {}
desc = html2plaintext(msg.get('body')) if msg.get('body') else '' desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
defaults = { defaults = {
'name': msg.get('subject') or _("No Subject"), 'name': msg.get('subject') or _("No Subject"),
@ -137,32 +138,6 @@ class crm_helpdesk(osv.osv):
'partner_id': msg.get('author_id', False), 'partner_id': msg.get('author_id', False),
} }
defaults.update(custom_values) defaults.update(custom_values)
return super(crm_helpdesk,self).message_new(cr, uid, msg, custom_values=defaults, context=context) return super(crm_helpdesk, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if update_vals is None: update_vals = {}
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
update_vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
for line in msg['body'].split('\n'):
line = line.strip()
res = tools.command_re.match(line)
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
update_vals[key] = res.group(2).lower()
return super(crm_helpdesk,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -187,6 +187,9 @@ class stock_move(osv.osv):
# Redefinition of the new fields in order to update the model stock.picking.out in the orm # Redefinition of the new fields in order to update the model stock.picking.out in the orm
# FIXME: this is a temporary workaround because of a framework bug (ref: lp996816). It should be removed as soon as # FIXME: this is a temporary workaround because of a framework bug (ref: lp996816). It should be removed as soon as
# the bug is fixed # the bug is fixed
# TODO in trunk: Remove the duplication below using a mixin class!
class stock_picking_out(osv.osv): class stock_picking_out(osv.osv):
_inherit = 'stock.picking.out' _inherit = 'stock.picking.out'
@ -212,6 +215,7 @@ class stock_picking_out(osv.osv):
}), }),
'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32), 'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32),
'number_of_packages': fields.integer('Number of Packages'), 'number_of_packages': fields.integer('Number of Packages'),
'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of measurement for Weight",),
} }
class stock_picking_in(osv.osv): class stock_picking_in(osv.osv):
@ -224,6 +228,8 @@ class stock_picking_in(osv.osv):
return self.pool.get('stock.picking')._get_picking_line(cr, uid, ids, context=context) return self.pool.get('stock.picking')._get_picking_line(cr, uid, ids, context=context)
_columns = { _columns = {
'carrier_id':fields.many2one("delivery.carrier","Carrier"),
'volume': fields.float('Volume'),
'weight': fields.function(_cal_weight, type='float', string='Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_weight', 'weight': fields.function(_cal_weight, type='float', string='Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_weight',
store={ store={
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20), 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
@ -234,6 +240,9 @@ class stock_picking_in(osv.osv):
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20), 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20), 'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20),
}), }),
'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32),
'number_of_packages': fields.integer('Number of Packages'),
'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of measurement for Weight",),
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -9,7 +9,7 @@ openerp.document = function (instance) {
on_attachments_loaded: function(attachments) { on_attachments_loaded: function(attachments) {
//to display number in name if more then one attachment which has same name. //to display number in name if more then one attachment which has same name.
var self = this; var self = this;
_.chain(attachments.reverse()) _.chain(attachments)
.groupBy(function(attachment) { return attachment.name}) .groupBy(function(attachment) { return attachment.name})
.each(function(attachment){ .each(function(attachment){
if(attachment.length > 1) if(attachment.length > 1)

View File

@ -333,7 +333,8 @@ class hr_applicant(osv.Model):
through message_process. through message_process.
This override updates the document according to the email. This override updates the document according to the email.
""" """
if custom_values is None: custom_values = {} if custom_values is None:
custom_values = {}
val = msg.get('from').split('<')[0] val = msg.get('from').split('<')[0]
defaults = { defaults = {
'name': msg.get('subject') or _("No Subject"), 'name': msg.get('subject') or _("No Subject"),
@ -346,38 +347,7 @@ class hr_applicant(osv.Model):
if msg.get('priority'): if msg.get('priority'):
defaults['priority'] = msg.get('priority') defaults['priority'] = msg.get('priority')
defaults.update(custom_values) defaults.update(custom_values)
return super(hr_applicant,self).message_new(cr, uid, msg, custom_values=defaults, context=context) return super(hr_applicant, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Override mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if update_vals is None:
update_vals = {}
update_vals.update({
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
})
if msg.get('priority'):
update_vals['priority'] = msg.get('priority')
maps = {
'cost': 'planned_cost',
'revenue': 'planned_revenue',
'probability': 'probability',
}
for line in msg.get('body', '').split('\n'):
line = line.strip()
res = tools.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
update_vals[key] = res.group(2).lower()
return super(hr_applicant, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
if context is None: if context is None:

View File

@ -185,7 +185,7 @@ class l10n_be_vat_declaration(osv.osv_memory):
for item in cases_list: for item in cases_list:
grid_amount_data = { grid_amount_data = {
'code': str(int(item['code'])), 'code': str(int(item['code'])),
'amount': str(abs(item['sum_period'])), 'amount': '%.2f' % abs(item['sum_period']),
} }
data_of_file += '\n\t\t\t<ns2:Amount GridNumber="%(code)s">%(amount)s</ns2:Amount''>' % (grid_amount_data) data_of_file += '\n\t\t\t<ns2:Amount GridNumber="%(code)s">%(amount)s</ns2:Amount''>' % (grid_amount_data)

View File

@ -1,5 +1,5 @@
"id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","name","category_id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base" "id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","name","category_id/id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base"
1,"fix",1,1,,100,"Education Allowance For One Child","Allowance",23,"CHEAONE","hr_payroll_rule_child1","range","employee.children", 1,"fix",1,1,,100,"Education Allowance For One Child",hr_payroll.ALW,23,"CHEAONE","hr_payroll_rule_child1","range","employee.children",
2,"fix",2,10,,200,"Education Allowance For Two Child","Allowance",24,"CHEATWO","hr_payroll_rule_child1","range","employee.children", 2,"fix",2,10,,200,"Education Allowance For Two Child",hr_payroll.ALW,24,"CHEATWO","hr_payroll_rule_child1","range","employee.children",
3,"fix",1,1,,300,"Child Hostel Allowance For One Child","Allowance",26,"CHOONE","hr_payroll_rule_child2","range","employee.children", 3,"fix",1,1,,300,"Child Hostel Allowance For One Child",hr_payroll.ALW,26,"CHOONE","hr_payroll_rule_child2","range","employee.children",
4,"fix",2,10,,600,"Child Hostel Allowance For Two Child","Allowance",27,"CHOTWO","hr_payroll_rule_child2","range","employee.children", 4,"fix",2,10,,600,"Child Hostel Allowance For Two Child",hr_payroll.ALW,27,"CHOTWO","hr_payroll_rule_child2","range","employee.children",

1 id amount_select condition_range_min condition_range_max amount_percentage amount_fix name category_id category_id/id sequence code parent_rule_id/id condition_select condition_range amount_percentage_base
2 1 fix 1 1 100 Education Allowance For One Child Allowance hr_payroll.ALW 23 CHEAONE hr_payroll_rule_child1 range employee.children
3 2 fix 2 10 200 Education Allowance For Two Child Allowance hr_payroll.ALW 24 CHEATWO hr_payroll_rule_child1 range employee.children
4 3 fix 1 1 300 Child Hostel Allowance For One Child Allowance hr_payroll.ALW 26 CHOONE hr_payroll_rule_child2 range employee.children
5 4 fix 2 10 600 Child Hostel Allowance For Two Child Allowance hr_payroll.ALW 27 CHOTWO hr_payroll_rule_child2 range employee.children

View File

@ -33,6 +33,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
""" """
_inherit = 'wizard.multi.charts.accounts' _inherit = 'wizard.multi.charts.accounts'
# FIXME: in trunk, drop the force_write param entirely
def process_translations(self, cr, uid, langs, in_obj, in_field, in_ids, out_obj, out_ids, force_write=False, context=None): def process_translations(self, cr, uid, langs, in_obj, in_field, in_ids, out_obj, out_ids, force_write=False, context=None):
""" """
This method copies translations values of templates into new Accounts/Taxes/Journals for languages selected This method copies translations values of templates into new Accounts/Taxes/Journals for languages selected
@ -45,8 +46,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
:param in_ids: List of ids of source object :param in_ids: List of ids of source object
:param out_obj: Destination object for which translation is to be copied :param out_obj: Destination object for which translation is to be copied
:param out_ids: List of ids of destination object :param out_ids: List of ids of destination object
:param force_write: boolean that depicts if we need to create a translation OR simply replace the actual value :param force_write: Deprecated as of 7.0, do not use
with the translation in the uid's language by doing a write (in case it's TRUE)
:param context: usual context information. May contain the key 'lang', which is the language of the user running :param context: usual context information. May contain the key 'lang', which is the language of the user running
the wizard, that will be used if force_write is True the wizard, that will be used if force_write is True
@ -65,26 +65,25 @@ class wizard_multi_charts_accounts(osv.osv_memory):
for j in range(len(in_ids)): for j in range(len(in_ids)):
in_id = in_ids[j] in_id = in_ids[j]
if value[in_id]: if value[in_id]:
if not force_write: #copy Translation from Source to Destination object
#copy Translation from Source to Destination object xlat_obj.create(cr, uid, {
xlat_obj.create(cr, uid, { 'name': out_obj._name + ',' + in_field,
'name': out_obj._name + ',' + in_field, 'type': 'model',
'type': 'model', 'res_id': out_ids[j],
'res_id': out_ids[j], 'lang': lang,
'lang': lang, 'src': src[in_id],
'src': src[in_id], 'value': value[in_id],
'value': value[in_id],
}) })
else:
#replace the value in the destination object only if it's the user lang
if context.get('lang') == lang:
self.pool[out_obj._name].write(cr, uid, out_ids[j], {in_field: value[in_id]})
else: else:
_logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name)) _logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name))
return True return True
def execute(self, cr, uid, ids, context=None): def execute(self, cr, uid, ids, context=None):
res = super(wizard_multi_charts_accounts, self).execute(cr, uid, ids, context=context) if not context:
context = {}
# remove the lang to get the untranslated value
ctx = dict(context, lang=None)
res = super(wizard_multi_charts_accounts, self).execute(cr, uid, ids, context=ctx)
obj_multi = self.browse(cr, uid, ids[0], context=context) obj_multi = self.browse(cr, uid, ids[0], context=context)
company_id = obj_multi.company_id.id company_id = obj_multi.company_id.id
@ -125,7 +124,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
acc_root_id = obj_acc.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0] acc_root_id = obj_acc.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0]
in_ids = obj_acc_template.search(cr, uid, [('id', 'child_of', [acc_template_root_id])], order='id')[1:] in_ids = obj_acc_template.search(cr, uid, [('id', 'child_of', [acc_template_root_id])], order='id')[1:]
out_ids = obj_acc.search(cr, uid, [('id', 'child_of', [acc_root_id])], order='id')[1:] out_ids = obj_acc.search(cr, uid, [('id', 'child_of', [acc_root_id])], order='id')[1:]
return self.process_translations(cr, uid, langs, obj_acc_template, field, in_ids, obj_acc, out_ids, force_write=True, context=context) return self.process_translations(cr, uid, langs, obj_acc_template, field, in_ids, obj_acc, out_ids, context=context)
def _process_tax_codes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None): def _process_tax_codes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
obj_tax_code_template = self.pool.get('account.tax.code.template') obj_tax_code_template = self.pool.get('account.tax.code.template')
@ -134,21 +133,21 @@ class wizard_multi_charts_accounts(osv.osv_memory):
tax_code_root_id = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0] tax_code_root_id = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0]
in_ids = obj_tax_code_template.search(cr, uid, [('id', 'child_of', [tax_code_template_root_id])], order='id')[1:] in_ids = obj_tax_code_template.search(cr, uid, [('id', 'child_of', [tax_code_template_root_id])], order='id')[1:]
out_ids = obj_tax_code.search(cr, uid, [('id', 'child_of', [tax_code_root_id])], order='id')[1:] out_ids = obj_tax_code.search(cr, uid, [('id', 'child_of', [tax_code_root_id])], order='id')[1:]
return self.process_translations(cr, uid, langs, obj_tax_code_template, field, in_ids, obj_tax_code, out_ids, force_write=False, context=context) return self.process_translations(cr, uid, langs, obj_tax_code_template, field, in_ids, obj_tax_code, out_ids, context=context)
def _process_taxes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None): def _process_taxes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
obj_tax_template = self.pool.get('account.tax.template') obj_tax_template = self.pool.get('account.tax.template')
obj_tax = self.pool.get('account.tax') obj_tax = self.pool.get('account.tax')
in_ids = sorted([x.id for x in obj_multi.chart_template_id.tax_template_ids]) in_ids = sorted([x.id for x in obj_multi.chart_template_id.tax_template_ids])
out_ids = obj_tax.search(cr, uid, [('company_id', '=', company_id)], order='id') out_ids = obj_tax.search(cr, uid, [('company_id', '=', company_id)], order='id')
return self.process_translations(cr, uid, langs, obj_tax_template, field, in_ids, obj_tax, out_ids, force_write=False, context=context) return self.process_translations(cr, uid, langs, obj_tax_template, field, in_ids, obj_tax, out_ids, context=context)
def _process_fiscal_pos_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None): def _process_fiscal_pos_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
obj_fiscal_position_template = self.pool.get('account.fiscal.position.template') obj_fiscal_position_template = self.pool.get('account.fiscal.position.template')
obj_fiscal_position = self.pool.get('account.fiscal.position') obj_fiscal_position = self.pool.get('account.fiscal.position')
in_ids = obj_fiscal_position_template.search(cr, uid, [('chart_template_id', '=', obj_multi.chart_template_id.id)], order='id') in_ids = obj_fiscal_position_template.search(cr, uid, [('chart_template_id', '=', obj_multi.chart_template_id.id)], order='id')
out_ids = obj_fiscal_position.search(cr, uid, [('company_id', '=', company_id)], order='id') out_ids = obj_fiscal_position.search(cr, uid, [('company_id', '=', company_id)], order='id')
return self.process_translations(cr, uid, langs, obj_fiscal_position_template, field, in_ids, obj_fiscal_position, out_ids, force_write=False, context=context) return self.process_translations(cr, uid, langs, obj_fiscal_position_template, field, in_ids, obj_fiscal_position, out_ids, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -33,6 +33,7 @@ from openerp import tools
from openerp import SUPERUSER_ID from openerp import SUPERUSER_ID
from openerp.addons.mail.mail_message import decode from openerp.addons.mail.mail_message import decode
from openerp.osv import fields, osv, orm from openerp.osv import fields, osv, orm
from openerp.osv.orm import browse_record, browse_null
from openerp.tools.safe_eval import safe_eval as eval from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _ from openerp.tools.translate import _
@ -328,11 +329,11 @@ class mail_thread(osv.AbstractModel):
if not context.get('mail_create_nosubscribe'): if not context.get('mail_create_nosubscribe'):
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context) self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
# auto_subscribe: take values and defaults into account # auto_subscribe: take values and defaults into account
create_values = set(values.keys()) create_values = dict(values)
for key, val in context.iteritems(): for key, val in context.iteritems():
if key.startswith('default_'): if key.startswith('default_'):
create_values.add(key[8:]) create_values[key[8:]] = val
self.message_auto_subscribe(cr, uid, [thread_id], list(create_values), context=context) self.message_auto_subscribe(cr, uid, [thread_id], create_values.keys(), context=context, values=create_values)
# track values # track values
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context) tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context)
@ -353,7 +354,7 @@ class mail_thread(osv.AbstractModel):
# Perform write, update followers # Perform write, update followers
result = super(mail_thread, self).write(cr, uid, ids, values, context=context) result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context) self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values)
# Perform the tracking # Perform the tracking
if tracked_fields: if tracked_fields:
@ -1539,75 +1540,100 @@ class mail_thread(osv.AbstractModel):
user_field_lst.append(name) user_field_lst.append(name)
return user_field_lst return user_field_lst
def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None): def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None, values=None):
""" """ Handle auto subscription. Two methods for auto subscription exist:
1. fetch project subtype related to task (parent_id.res_model = 'project.task')
2. for each project subtype: subscribe the follower to the task - tracked res.users relational fields, such as user_id fields. Those fields
must be relation fields toward a res.users record, and must have the
track_visilibity attribute set.
- using subtypes parent relationship: check if the current model being
modified has an header record (such as a project for tasks) whose followers
can be added as followers of the current records. Example of structure
with project and task:
- st_project_1.parent_id = st_task_1
- st_project_1.res_model = 'project.project'
- st_project_1.relation_field = 'project_id'
- st_task_1.model = 'project.task'
:param list updated_fields: list of updated fields to track
:param dict values: updated values; if None, the first record will be browsed
to get the values. Added after releasing 7.0, therefore
not merged with updated_fields argumment.
""" """
subtype_obj = self.pool.get('mail.message.subtype') subtype_obj = self.pool.get('mail.message.subtype')
follower_obj = self.pool.get('mail.followers') follower_obj = self.pool.get('mail.followers')
new_followers = dict()
# fetch auto_follow_fields # fetch auto_follow_fields: res.users relation fields whose changes are tracked for subscription
user_field_lst = self._message_get_auto_subscribe_fields(cr, uid, updated_fields, context=context) user_field_lst = self._message_get_auto_subscribe_fields(cr, uid, updated_fields, context=context)
# fetch related record subtypes # fetch header subtypes
related_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)], context=context) header_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)], context=context)
subtypes = subtype_obj.browse(cr, uid, related_subtype_ids, context=context) subtypes = subtype_obj.browse(cr, uid, header_subtype_ids, context=context)
default_subtypes = [subtype for subtype in subtypes if subtype.res_model == False]
related_subtypes = [subtype for subtype in subtypes if subtype.res_model != False] # if no change in tracked field or no change in tracked relational field: quit
relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field != False]) relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field is not False])
if (not related_subtypes or not any(relation in updated_fields for relation in relation_fields)) and not user_field_lst: if not any(relation in updated_fields for relation in relation_fields) and not user_field_lst:
return True return True
for record in self.browse(cr, uid, ids, context=context): # legacy behavior: if values is not given, compute the values by browsing
new_followers = dict() # @TDENOTE: remove me in 8.0
parent_res_id = False if values is None:
parent_model = False record = self.browse(cr, uid, ids[0], context=context)
for subtype in related_subtypes: for updated_field in updated_fields:
if not subtype.relation_field or not subtype.parent_id: field_value = getattr(record, updated_field)
continue if isinstance(field_value, browse_record):
if not subtype.relation_field in self._columns or not getattr(record, subtype.relation_field, False): field_value = field_value.id
continue elif isinstance(field_value, browse_null):
parent_res_id = getattr(record, subtype.relation_field).id field_value = False
parent_model = subtype.res_model values[updated_field] = field_value
follower_ids = follower_obj.search(cr, SUPERUSER_ID, [
('res_model', '=', parent_model),
('res_id', '=', parent_res_id),
('subtype_ids', 'in', [subtype.id])
], context=context)
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context):
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.parent_id.id)
if parent_res_id and parent_model: # find followers of headers, update structure for new followers
for subtype in default_subtypes: headers = set()
follower_ids = follower_obj.search(cr, SUPERUSER_ID, [ for subtype in subtypes:
('res_model', '=', parent_model), if subtype.relation_field and values.get(subtype.relation_field):
('res_id', '=', parent_res_id), headers.add((subtype.res_model, values.get(subtype.relation_field)))
('subtype_ids', 'in', [subtype.id]) if headers:
], context=context) header_domain = ['|'] * (len(headers) - 1)
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context): for header in headers:
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.id) header_domain += ['&', ('res_model', '=', header[0]), ('res_id', '=', header[1])]
header_follower_ids = follower_obj.search(
cr, SUPERUSER_ID,
header_domain,
context=context
)
for header_follower in follower_obj.browse(cr, SUPERUSER_ID, header_follower_ids, context=context):
for subtype in header_follower.subtype_ids:
if subtype.res_model and subtype.parent_id:
new_followers.setdefault(header_follower.partner_id.id, set()).add(subtype.parent_id.id)
elif subtype.res_model is False:
new_followers.setdefault(header_follower.partner_id.id, set()).add(subtype.id)
# add followers coming from res.users relational fields that are tracked # add followers coming from res.users relational fields that are tracked
user_ids = [getattr(record, name).id for name in user_field_lst if getattr(record, name)] user_ids = [values[name] for name in user_field_lst if values.get(name)]
user_id_partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, SUPERUSER_ID, user_ids, context=context)] user_pids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, SUPERUSER_ID, user_ids, context=context)]
for partner_id in user_id_partner_ids: for partner_id in user_pids:
new_followers.setdefault(partner_id, None) new_followers.setdefault(partner_id, None)
for pid, subtypes in new_followers.items(): for pid, subtypes in new_followers.items():
subtypes = list(subtypes) if subtypes is not None else None subtypes = list(subtypes) if subtypes is not None else None
self.message_subscribe(cr, uid, [record.id], [pid], subtypes, context=context) self.message_subscribe(cr, uid, ids, [pid], subtypes, context=context)
# find first email message, set it as unread for auto_subscribe fields for them to have a notification # find first email message, set it as unread for auto_subscribe fields for them to have a notification
if user_id_partner_ids: if user_pids:
msg_ids = self.pool.get('mail.message').search(cr, uid, [ for record_id in ids:
('model', '=', self._name), message_obj = self.pool.get('mail.message')
('res_id', '=', record.id), msg_ids = message_obj.search(cr, SUPERUSER_ID, [
('type', '=', 'email')], limit=1, context=context) ('model', '=', self._name),
if not msg_ids and record.message_ids: ('res_id', '=', record_id),
msg_ids = [record.message_ids[-1].id] ('type', '=', 'email')], limit=1, context=context)
if not msg_ids:
msg_ids = message_obj.search(cr, SUPERUSER_ID, [
('model', '=', self._name),
('res_id', '=', record_id)], limit=1, context=context)
if msg_ids: if msg_ids:
self.pool.get('mail.notification')._notify(cr, uid, msg_ids[0], partners_to_notify=user_id_partner_ids, context=context) self.pool.get('mail.notification')._notify(cr, uid, msg_ids[0], partners_to_notify=user_pids, context=context)
return True return True

View File

@ -965,7 +965,10 @@ class mrp_production(osv.osv):
partner_id = routing_loc.partner_id and routing_loc.partner_id.id or False partner_id = routing_loc.partner_id and routing_loc.partner_id.id or False
# Take next Sequence number of shipment base on type # Take next Sequence number of shipment base on type
pick_name = ir_sequence.get(cr, uid, 'stock.picking.' + pick_type) if pick_type!='internal':
pick_name = ir_sequence.get(cr, uid, 'stock.picking.' + pick_type)
else:
pick_name = ir_sequence.get(cr, uid, 'stock.picking')
picking_id = stock_picking.create(cr, uid, { picking_id = stock_picking.create(cr, uid, {
'name': pick_name, 'name': pick_name,

View File

@ -80,11 +80,11 @@ class mrp_production(osv.osv):
_inherit= 'mrp.production' _inherit= 'mrp.production'
def action_confirm(self, cr, uid, ids): def action_confirm(self, cr, uid, ids, context=None):
""" Confirms production order and calculates quantity based on subproduct_type. """ Confirms production order and calculates quantity based on subproduct_type.
@return: Newly generated picking Id. @return: Newly generated picking Id.
""" """
picking_id = super(mrp_production,self).action_confirm(cr, uid, ids) picking_id = super(mrp_production,self).action_confirm(cr, uid, ids, context=context)
product_uom_obj = self.pool.get('product.uom') product_uom_obj = self.pool.get('product.uom')
for production in self.browse(cr, uid, ids): for production in self.browse(cr, uid, ids):
source = production.product_id.property_stock_production.id source = production.product_id.property_stock_production.id

View File

@ -39,7 +39,11 @@ class pad_common(osv.osv_memory):
#if create with content #if create with content
if "field_name" in context and "model" in context and "object_id" in context: if "field_name" in context and "model" in context and "object_id" in context:
myPad = EtherpadLiteClient( pad["key"], pad["server"]+'/api') myPad = EtherpadLiteClient( pad["key"], pad["server"]+'/api')
myPad.createPad(path) try:
myPad.createPad(path)
except urllib2.URLError:
raise osv.except_osv(_("Error"), _("Pad creation failed, \
either there is a problem with your pad server URL or with your connection."))
#get attr on the field model #get attr on the field model
model = self.pool[context["model"]] model = self.pool[context["model"]]

View File

@ -2,7 +2,7 @@
<data> <data>
<record id="base.main_company" model="res.company"> <record id="base.main_company" model="res.company">
<field name="pad_server">pad.openerp.com</field> <field name="pad_server">https://pad.openerp.com</field>
</record> </record>
<record id="base.main_company" model="res.company"> <record id="base.main_company" model="res.company">

View File

@ -694,7 +694,7 @@ class pos_order(osv.osv):
def create_picking(self, cr, uid, ids, context=None): def create_picking(self, cr, uid, ids, context=None):
"""Create a picking for each order and validate it.""" """Create a picking for each order and validate it."""
picking_obj = self.pool.get('stock.picking') picking_obj = self.pool.get('stock.picking.out')
partner_obj = self.pool.get('res.partner') partner_obj = self.pool.get('res.partner')
move_obj = self.pool.get('stock.move') move_obj = self.pool.get('stock.move')

View File

@ -56,7 +56,7 @@
<div class="oe_subtotal_footer_separator oe_inline"> <div class="oe_subtotal_footer_separator oe_inline">
<label for="amount_total" /> <label for="amount_total" />
<button name="button_dummy" <button name="button_dummy"
states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/> states="draft" string="(update)" class="oe_edit_only oe_link"/>
</div> </div>
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/> <field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
</group> </group>

View File

@ -19,6 +19,7 @@
# #
############################################################################## ##############################################################################
from openerp import SUPERUSER_ID
from openerp.osv import osv, orm from openerp.osv import osv, orm
from openerp.tools.translate import _ from openerp.tools.translate import _
@ -32,6 +33,9 @@ class mail_message(osv.Model):
""" Override that adds specific access rights of mail.message, to remove """ Override that adds specific access rights of mail.message, to remove
all internal notes if uid is a non-employee all internal notes if uid is a non-employee
""" """
if uid == SUPERUSER_ID:
return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
context=context, count=False, access_rights_uid=access_rights_uid)
group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id
group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1] group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1]
if group_user_id not in [group.id for group in group_ids]: if group_user_id not in [group.id for group in group_ids]:
@ -45,6 +49,8 @@ class mail_message(osv.Model):
- read: - read:
- raise if the type is comment and subtype NULL (internal note) - raise if the type is comment and subtype NULL (internal note)
""" """
if uid == SUPERUSER_ID:
return super(mail_message, self).check_access_rule(cr, uid, ids=ids, operation=operation, context=context)
group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id
group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1] group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1]
if group_user_id not in [group.id for group in group_ids]: if group_user_id not in [group.id for group in group_ids]:

View File

@ -73,6 +73,9 @@ class test_portal(TestMail):
for message in chell_pigs.message_ids: for message in chell_pigs.message_ids:
trigger_read = message.subject trigger_read = message.subject
for partner in chell_pigs.message_follower_ids: for partner in chell_pigs.message_follower_ids:
if partner.id == self.partner_chell_id:
# Chell can read her own partner record
continue
with self.assertRaises(except_orm): with self.assertRaises(except_orm):
trigger_read = partner.name trigger_read = partner.name

View File

@ -1,17 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data noupdate="1"> <data>
<record id="portal_claim_rule" model="ir.rule"> <record id="portal_claim_rule" model="ir.rule">
<field name="name">Portal Personal Claims</field> <field name="name">Portal Personal Claims</field>
<field ref="crm_claim.model_crm_claim" name="model_id"/> <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="domain_force">['|', ('message_follower_ids','in', [user.partner_id.id]), ('partner_id','=', user.partner_id.id)]</field>
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/> <field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
<field eval="1" name="perm_unlink"/> <field eval="0" name="perm_unlink"/>
<field eval="1" name="perm_write"/> <field eval="0" name="perm_write"/>
<field eval="1" name="perm_read"/> <field eval="1" name="perm_read"/>
<field eval="0" name="perm_create"/> <field eval="1" name="perm_create"/>
</record> </record>
</data> </data>
</openerp> </openerp>

View File

@ -181,10 +181,6 @@ class procurement_order(osv.osv):
""" """
return all(procurement.move_id.state == 'cancel' for procurement in self.browse(cr, uid, ids, context=context)) return all(procurement.move_id.state == 'cancel' for procurement in self.browse(cr, uid, ids, context=context))
#This Function is create to avoid a server side Error Like 'ERROR:tests.mrp:name 'check_move' is not defined'
def check_move(self, cr, uid, ids, context=None):
pass
def check_move_done(self, cr, uid, ids, context=None): def check_move_done(self, cr, uid, ids, context=None):
""" Checks if move is done or not. """ Checks if move is done or not.
@return: True or False. @return: True or False.
@ -297,6 +293,12 @@ class procurement_order(osv.osv):
""" """
return False return False
def check_move(self, cr, uid, ids, context=None):
""" Check whether the given procurement can be satisfied by an internal move,
typically a pulled flow. By default, it's False. Overwritten by the `stock_location` module.
"""
return False
def check_conditions_confirm2wait(self, cr, uid, ids): def check_conditions_confirm2wait(self, cr, uid, ids):
""" condition on the transition to go from 'confirm' activity to 'confirm_wait' activity """ """ condition on the transition to go from 'confirm' activity to 'confirm_wait' activity """
return not self.test_cancel(cr, uid, ids) return not self.test_cancel(cr, uid, ids)

View File

@ -147,13 +147,15 @@
<record id="trans_confirm_mto_make_done" model="workflow.transition"> <record id="trans_confirm_mto_make_done" model="workflow.transition">
<!-- This transition is there to unblock products that would be in MTO with a supply method that would be <!-- This transition is there to unblock products that would be in MTO with a supply method that would be
produce or buy without MRP or purchase module installed. These modules overwrite the check_produce() produce or buy, and without MRP or Purchase modules installed. These modules overwrite the check_produce()
and check_buy() methods -so that it invalidates their part of this 'bypass transition'-, and define and check_buy() methods -so that it invalidates their part of this 'bypass transition'-, and define
their own workflow paths. their own workflow paths.
The stock_location module also introduces a check_move() alternative, for pulled flows that are
satisfied with an internal product move. This yields a threefold test for the bypass transition.
--> -->
<field name="act_from" ref="act_confirm_mto"/> <field name="act_from" ref="act_confirm_mto"/>
<field name="act_to" ref="act_make_done"/> <field name="act_to" ref="act_make_done"/>
<field name="condition">not check_produce() and not check_buy()</field> <field name="condition">not check_produce() and not check_buy() and not check_move()</field>
</record> </record>
<record id="trans_make_to_stock_make_done" model="workflow.transition"> <record id="trans_make_to_stock_make_done" model="workflow.transition">

View File

@ -194,6 +194,7 @@ class procurement_order(osv.osv):
'company_id': orderpoint.company_id.id, 'company_id': orderpoint.company_id.id,
'product_uom': orderpoint.product_uom.id, 'product_uom': orderpoint.product_uom.id,
'location_id': orderpoint.location_id.id, 'location_id': orderpoint.location_id.id,
'warehouse_id': orderpoint.warehouse_id.id,
'procure_method': 'make_to_order', 'procure_method': 'make_to_order',
'origin': orderpoint.name} 'origin': orderpoint.name}

View File

@ -86,78 +86,13 @@ class sale_order_line(osv.osv):
pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount']) pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist) new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist)
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0): if len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0 and new_list_price != 0:
discount = (new_list_price - price) / new_list_price * 100 discount = (new_list_price - price) / new_list_price * 100
result['price_unit'] = new_list_price if discount > 0:
result['discount'] = discount result['price_unit'] = new_list_price
result['discount'] = discount
else:
result['discount'] = 0.0
else: else:
result['discount'] = 0.0 result['discount'] = 0.0
return res return res
class account_invoice_line(osv.osv):
_inherit = "account.invoice.line"
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit,currency_id, context=context, company_id=company_id)
def get_real_price(res_dict, product_id, qty, uom_id, pricelist):
item_obj = self.pool.get('product.pricelist.item')
price_type_obj = self.pool.get('product.price.type')
product_obj = self.pool.get('product.product')
field_name = 'list_price'
if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False):
item = res_dict['item_id'].get(pricelist,False)
item_read = item_obj.read(cr, uid, [item], ['base'])
if item_read:
item_base = item_read[0]['base']
if item_base > 0:
field_name = price_type_obj.browse(cr, uid, item_base).field
product = product_obj.browse(cr, uid, product_id, context)
product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)
factor = 1.0
if uom_id and uom_id != product.uom_id.id:
product_uom_obj = self.pool.get('product.uom')
uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id)
factor = uom_data.factor
return product_read[field_name] * factor
if product:
pricelist_obj = self.pool.get('product.pricelist')
partner_obj = self.pool.get('res.partner')
product = self.pool.get('product.product').browse(cr, uid, product, context=context)
result = res['value']
pricelist = False
real_price = 0.00
if type in ('in_invoice', 'in_refund'):
if not price_unit and partner_id:
pricelist =partner_obj.browse(cr, uid, partner_id).property_product_pricelist_purchase.id
if not pricelist:
raise osv.except_osv(_('No Purchase Pricelist Found!'),_("You must first define a pricelist on the supplier form!"))
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom_id})
price_unit = price_unit_res[pricelist]
real_price = get_real_price(price_unit_res, product.id, qty, uom_id, pricelist)
else:
if partner_id:
pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id
if not pricelist:
raise osv.except_osv(_('No Sale Pricelist Found!'),_("You must first define a pricelist on the customer form!"))
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom_id})
price_unit = price_unit_res[pricelist]
real_price = get_real_price(price_unit_res, product.id, qty, uom_id, pricelist)
if pricelist:
pricelists=pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and real_price != 0):
discount=(real_price-price_unit) / real_price * 100
result['price_unit'] = real_price
result['discount'] = discount
else:
result['discount']=0.0
return res
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1131,7 +1131,8 @@ class task(osv.osv):
def message_new(self, cr, uid, msg, custom_values=None, context=None): def message_new(self, cr, uid, msg, custom_values=None, context=None):
""" Override to updates the document according to the email. """ """ Override to updates the document according to the email. """
if custom_values is None: custom_values = {} if custom_values is None:
custom_values = {}
defaults = { defaults = {
'name': msg.get('subject'), 'name': msg.get('subject'),
'planned_hours': 0.0, 'planned_hours': 0.0,
@ -1141,10 +1142,10 @@ class task(osv.osv):
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None): def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Override to update the task according to the email. """ """ Override to update the task according to the email. """
if update_vals is None: update_vals = {} if update_vals is None:
act = False update_vals = {}
maps = { maps = {
'cost':'planned_hours', 'cost': 'planned_hours',
} }
for line in msg['body'].split('\n'): for line in msg['body'].split('\n'):
line = line.strip() line = line.strip()
@ -1157,9 +1158,7 @@ class task(osv.osv):
update_vals[field] = float(res.group(2).lower()) update_vals[field] = float(res.group(2).lower())
except (ValueError, TypeError): except (ValueError, TypeError):
pass pass
if act: return super(task, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
getattr(self,act)(cr, uid, ids, context=context)
return super(task,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
class project_work(osv.osv): class project_work(osv.osv):
_name = "project.task.work" _name = "project.task.work"

View File

@ -519,40 +519,10 @@ class project_issue(osv.Model):
'partner_id': msg.get('author_id', False), 'partner_id': msg.get('author_id', False),
'user_id': False, 'user_id': False,
} }
if msg.get('priority'):
defaults['priority'] = msg.get('priority')
defaults.update(custom_values) defaults.update(custom_values)
res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=defaults, context=context) res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
return res_id return res_id
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
""" Overrides mail_thread message_update that is called by the mailgateway
through message_process.
This method updates the document according to the email.
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
if update_vals is None: update_vals = {}
# Update doc values according to the message
if msg.get('priority'):
update_vals['priority'] = msg.get('priority')
# Parse 'body' to find values to update
maps = {
'cost': 'planned_cost',
'revenue': 'planned_revenue',
'probability': 'probability',
}
for line in msg.get('body', '').split('\n'):
line = line.strip()
res = tools.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
update_vals[key] = res.group(2).lower()
return super(project_issue, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs): def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs):
""" Overrides mail_thread message_post so that we can set the date of last action field when """ Overrides mail_thread message_post so that we can set the date of last action field when
a new message is posted on the issue. a new message is posted on the issue.

View File

@ -36,6 +36,9 @@
<menuitem <menuitem
id="menu_purchase_config_pricelist" name="Pricelists" id="menu_purchase_config_pricelist" name="Pricelists"
parent="menu_purchase_config_purchase" sequence="50" groups="product.group_purchase_pricelist"/> parent="menu_purchase_config_purchase" sequence="50" groups="product.group_purchase_pricelist"/>
<menuitem
action="product.product_pricelist_action_for_purchase" id="menu_product_pricelist_action2_purchase"
parent="menu_purchase_config_pricelist" sequence="1" groups="product.group_purchase_pricelist" />
<menuitem <menuitem
action="product.product_pricelist_action_for_purchase" id="menu_product_pricelist_action2_purchase" action="product.product_pricelist_action_for_purchase" id="menu_product_pricelist_action2_purchase"

View File

@ -94,23 +94,20 @@ class purchase_report(osv.osv):
extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay, extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay,
extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass, extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
count(*) as nbr, count(*) as nbr,
(l.price_unit*l.product_qty)::decimal(16,2) as price_total, sum(l.price_unit*l.product_qty)::decimal(16,2) as price_total,
avg(100.0 * (l.price_unit*l.product_qty) / NULLIF(t.standard_price*l.product_qty/u.factor*u2.factor, 0.0))::decimal(16,2) as negociation, avg(100.0 * (l.price_unit*l.product_qty) / NULLIF(t.standard_price*l.product_qty/u.factor*u2.factor, 0.0))::decimal(16,2) as negociation,
sum(t.standard_price*l.product_qty/u.factor*u2.factor)::decimal(16,2) as price_standard, sum(t.standard_price*l.product_qty/u.factor*u2.factor)::decimal(16,2) as price_standard,
(sum(l.product_qty*l.price_unit)/NULLIF(sum(l.product_qty/u.factor*u2.factor),0.0))::decimal(16,2) as price_average (sum(l.product_qty*l.price_unit)/NULLIF(sum(l.product_qty/u.factor*u2.factor),0.0))::decimal(16,2) as price_average
from purchase_order s from purchase_order_line l
left join purchase_order_line l on (s.id=l.order_id) join purchase_order s on (l.order_id=s.id)
left join product_product p on (l.product_id=p.id) left join product_product p on (l.product_id=p.id)
left join product_template t on (p.product_tmpl_id=t.id) left join product_template t on (p.product_tmpl_id=t.id)
left join product_uom u on (u.id=l.product_uom) left join product_uom u on (u.id=l.product_uom)
left join product_uom u2 on (u2.id=t.uom_id) left join product_uom u2 on (u2.id=t.uom_id)
where l.product_id is not null
group by group by
s.company_id, s.company_id,
s.create_uid, s.create_uid,
s.partner_id, s.partner_id,
l.product_qty,
u.factor, u.factor,
s.location_id, s.location_id,
l.price_unit, l.price_unit,

View File

@ -177,8 +177,8 @@ class resource_calendar(osv.osv):
if leave_flag: if leave_flag:
break break
else: else:
d1 = datetime(dt_from.year, dt_from.month, dt_from.day, int(math.floor(m)), int((m%1) * 60)) d1 = datetime(dt_from.year, dt_from.month, dt_from.day) + timedelta(hours=int(math.floor(m)), minutes=int((m%1) * 60))
d2 = datetime(dt_from.year, dt_from.month, dt_from.day, int(math.floor(hour_to)), int((hour_to%1) * 60)) d2 = datetime(dt_from.year, dt_from.month, dt_from.day) + timedelta(hours=int(math.floor(hour_to)), minutes=int((hour_to%1) * 60))
result.append((d1, d2)) result.append((d1, d2))
current_hour = hour_to current_hour = hour_to
todo -= (hour_to - m) todo -= (hour_to - m)

View File

@ -70,7 +70,7 @@ class sale_report(osv.osv):
t.uom_id as product_uom, t.uom_id as product_uom,
sum(l.product_uom_qty / u.factor * u2.factor) as product_uom_qty, sum(l.product_uom_qty / u.factor * u2.factor) as product_uom_qty,
sum(l.product_uom_qty * l.price_unit * (100.0-l.discount) / 100.0) as price_total, sum(l.product_uom_qty * l.price_unit * (100.0-l.discount) / 100.0) as price_total,
1 as nbr, count(*) as nbr,
s.date_order as date, s.date_order as date,
s.date_confirm as date_confirm, s.date_confirm as date_confirm,
to_char(s.date_order, 'YYYY') as year, to_char(s.date_order, 'YYYY') as year,
@ -85,15 +85,14 @@ class sale_report(osv.osv):
s.pricelist_id as pricelist_id, s.pricelist_id as pricelist_id,
s.project_id as analytic_account_id s.project_id as analytic_account_id
from from
sale_order s sale_order_line l
join sale_order_line l on (s.id=l.order_id) join sale_order s on (l.order_id=s.id)
left join product_product p on (l.product_id=p.id) left join product_product p on (l.product_id=p.id)
left join product_template t on (p.product_tmpl_id=t.id) left join product_template t on (p.product_tmpl_id=t.id)
left join product_uom u on (u.id=l.product_uom) left join product_uom u on (u.id=l.product_uom)
left join product_uom u2 on (u2.id=t.uom_id) left join product_uom u2 on (u2.id=t.uom_id)
group by group by
l.product_id, l.product_id,
l.product_uom_qty,
l.order_id, l.order_id,
t.uom_id, t.uom_id,
t.categ_id, t.categ_id,

View File

@ -8,7 +8,7 @@
<field name="inherit_id" ref="sale.view_order_form"/> <field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<group name="sale_pay" position="after"> <group name="sale_pay" position="after">
<group colspan="2" col="2" groups="base.group_no_one"> <group colspan="2" col="2" >
<separator string="Dates" colspan="2"/> <separator string="Dates" colspan="2"/>
<field name="requested_date"/> <field name="requested_date"/>
<field name="commitment_date"/> <field name="commitment_date"/>

View File

@ -42,6 +42,8 @@ class sale_report(osv.osv):
def init(self, cr): def init(self, cr):
tools.drop_view_if_exists(cr, 'sale_report') tools.drop_view_if_exists(cr, 'sale_report')
# TODO: make parent view extensible similarly to invoice analysis and
# remove the duplication
cr.execute(""" cr.execute("""
create or replace view sale_report as ( create or replace view sale_report as (
select select
@ -50,7 +52,7 @@ class sale_report(osv.osv):
t.uom_id as product_uom, t.uom_id as product_uom,
sum(l.product_uom_qty / u.factor * u2.factor) as product_uom_qty, sum(l.product_uom_qty / u.factor * u2.factor) as product_uom_qty,
sum(l.product_uom_qty * l.price_unit * (100.0-l.discount) / 100.0) as price_total, sum(l.product_uom_qty * l.price_unit * (100.0-l.discount) / 100.0) as price_total,
1 as nbr, count(*) as nbr,
s.date_order as date, s.date_order as date,
s.date_confirm as date_confirm, s.date_confirm as date_confirm,
to_char(s.date_order, 'YYYY') as year, to_char(s.date_order, 'YYYY') as year,
@ -68,15 +70,14 @@ class sale_report(osv.osv):
s.pricelist_id as pricelist_id, s.pricelist_id as pricelist_id,
s.project_id as analytic_account_id s.project_id as analytic_account_id
from from
sale_order s sale_order_line l
join sale_order_line l on (s.id=l.order_id) join sale_order s on (l.order_id=s.id)
left join product_product p on (l.product_id=p.id) left join product_product p on (l.product_id=p.id)
left join product_template t on (p.product_tmpl_id=t.id) left join product_template t on (p.product_tmpl_id=t.id)
left join product_uom u on (u.id=l.product_uom) left join product_uom u on (u.id=l.product_uom)
left join product_uom u2 on (u2.id=t.uom_id) left join product_uom u2 on (u2.id=t.uom_id)
group by group by
l.product_id, l.product_id,
l.product_uom_qty,
l.order_id, l.order_id,
t.uom_id, t.uom_id,
t.categ_id, t.categ_id,

View File

@ -62,6 +62,15 @@ class stock_picking(osv.osv):
return picking.note or picking.sale_id.note return picking.note or picking.sale_id.note
return super(stock_picking, self)._get_comment_invoice(cursor, user, picking) return super(stock_picking, self)._get_comment_invoice(cursor, user, picking)
def _prepare_invoice_group(self, cr, uid, picking, partner, invoice, context=None):
""" Inherit the original function of the 'stock' module in order to override name field
to pass the customer reference form the sales order
"""
invoice_vals = super(stock_picking, self)._prepare_invoice_group(cr, uid, picking, partner, invoice, context)
if picking.sale_id:
invoice_vals['name'] = (invoice.name or '') + ', ' + (picking.sale_id.client_order_ref or '')
return invoice_vals
def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None): def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
""" Inherit the original function of the 'stock' module in order to override some """ Inherit the original function of the 'stock' module in order to override some
values if the picking has been generated by a sales order values if the picking has been generated by a sales order

View File

@ -224,12 +224,18 @@
<field name="delivery_count"/> <field name="delivery_count"/>
</field> </field>
<xpath expr="//div[@name='tags']" position="inside"> <xpath expr="//div[@name='tags']" position="inside">
<a name="%(action_receive_move)d" type="action" t-if="record.reception_count.raw_value>0"> <a name="%(action_receive_move)d" type="action" t-if="record.reception_count.raw_value&gt;1">
<t t-esc="record.reception_count.value"/> Receptions <t t-esc="record.reception_count.value"/> Receptions
</a> </a>
<a name="%(action_deliver_move)d" type="action" t-if="record.delivery_count.raw_value>0"> <a name="%(action_receive_move)d" type="action" t-if="record.reception_count.raw_value==1">
<t t-esc="record.reception_count.value"/> Reception
</a>
<a name="%(action_deliver_move)d" type="action" t-if="record.delivery_count.raw_value&gt;1">
<t t-esc="record.delivery_count.value"/> Deliveries <t t-esc="record.delivery_count.value"/> Deliveries
</a> </a>
<a name="%(action_deliver_move)d" type="action" t-if="record.delivery_count.raw_value==1">
<t t-esc="record.delivery_count.value"/> Delivery
</a>
</xpath> </xpath>
<ul position="inside"> <ul position="inside">
<li t-if="record.type.raw_value != 'service'">On hand: <field name="qty_available"/> <field name="uom_id"/></li> <li t-if="record.type.raw_value != 'service'">On hand: <field name="qty_available"/> <field name="uom_id"/></li>

View File

@ -243,6 +243,9 @@ class stock_location(osv.osv):
if location.chained_location_type == 'customer': if location.chained_location_type == 'customer':
if partner: if partner:
result = partner.property_stock_customer result = partner.property_stock_customer
else:
loc_id = self.pool['res.partner'].default_get(cr, uid, ['property_stock_customer'], context=context)['property_stock_customer']
result = self.pool['stock.location'].browse(cr, uid, loc_id, context=context)
elif location.chained_location_type == 'fixed': elif location.chained_location_type == 'fixed':
result = location.chained_location_id result = location.chained_location_id
if result: if result:
@ -1267,17 +1270,17 @@ class stock_picking(osv.osv):
context['currency_id'] = move_currency_id context['currency_id'] = move_currency_id
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id) qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
if product.id in product_avail: if product.id not in product_avail:
product_avail[product.id] += qty # keep track of stock on hand including processed lines not yet marked as done
else:
product_avail[product.id] = product.qty_available product_avail[product.id] = product.qty_available
if qty > 0: if qty > 0:
new_price = currency_obj.compute(cr, uid, product_currency, new_price = currency_obj.compute(cr, uid, product_currency,
move_currency_id, product_price) move_currency_id, product_price, round=False)
new_price = uom_obj._compute_price(cr, uid, product_uom, new_price, new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
product.uom_id.id) product.uom_id.id)
if product.qty_available <= 0: if product_avail[product.id] <= 0:
product_avail[product.id] = 0
new_std_price = new_price new_std_price = new_price
else: else:
# Get the standard price # Get the standard price
@ -1293,6 +1296,9 @@ class stock_picking(osv.osv):
{'price_unit': product_price, {'price_unit': product_price,
'price_currency_id': product_currency}) 'price_currency_id': product_currency})
product_avail[product.id] += qty
for move in too_few: for move in too_few:
product_qty = move_product_qty[move.id] product_qty = move_product_qty[move.id]
@ -2359,7 +2365,7 @@ class stock_move(osv.osv):
{ {
'journal_id': j_id, 'journal_id': j_id,
'line_id': move_lines, 'line_id': move_lines,
'ref': move.picking_id and move.picking_id.name}) 'ref': move.picking_id and move.picking_id.name}, context=context)
def action_done(self, cr, uid, ids, context=None): def action_done(self, cr, uid, ids, context=None):
""" Makes the move done and if all moves are done, it will finish the picking. """ Makes the move done and if all moves are done, it will finish the picking.
@ -2697,7 +2703,7 @@ class stock_move(osv.osv):
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id) qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
if qty > 0: if qty > 0:
new_price = currency_obj.compute(cr, uid, product_currency, new_price = currency_obj.compute(cr, uid, product_currency,
move_currency_id, product_price) move_currency_id, product_price, round=False)
new_price = uom_obj._compute_price(cr, uid, product_uom, new_price, new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
product.uom_id.id) product.uom_id.id)
if product.qty_available <= 0: if product.qty_available <= 0:
@ -3031,6 +3037,13 @@ class stock_picking_in(osv.osv):
"""Send the unsubscribe action on stock.picking model to match with subscribe""" """Send the unsubscribe action on stock.picking model to match with subscribe"""
return self.pool.get('stock.picking').message_unsubscribe(*args, **kwargs) return self.pool.get('stock.picking').message_unsubscribe(*args, **kwargs)
def default_get(self, cr, uid, fields_list, context=None):
# merge defaults from stock.picking with possible defaults defined on stock.picking.in
defaults = self.pool['stock.picking'].default_get(cr, uid, fields_list, context=context)
out_defaults = super(stock_picking_in, self).default_get(cr, uid, fields_list, context=context)
defaults.update(in_defaults)
return defaults
_columns = { _columns = {
'backorder_id': fields.many2one('stock.picking.in', 'Back Order of', states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}, help="If this shipment was split, then this field links to the shipment which contains the already processed part.", select=True), 'backorder_id': fields.many2one('stock.picking.in', 'Back Order of', states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}, help="If this shipment was split, then this field links to the shipment which contains the already processed part.", select=True),
'state': fields.selection( 'state': fields.selection(
@ -3104,6 +3117,13 @@ class stock_picking_out(osv.osv):
"""Send the unsubscribe action on stock.picking model to match with subscribe""" """Send the unsubscribe action on stock.picking model to match with subscribe"""
return self.pool.get('stock.picking').message_unsubscribe(*args, **kwargs) return self.pool.get('stock.picking').message_unsubscribe(*args, **kwargs)
def default_get(self, cr, uid, fields_list, context=None):
# merge defaults from stock.picking with possible defaults defined on stock.picking.out
defaults = self.pool['stock.picking'].default_get(cr, uid, fields_list, context=context)
out_defaults = super(stock_picking_out, self).default_get(cr, uid, fields_list, context=context)
defaults.update(out_defaults)
return defaults
_columns = { _columns = {
'backorder_id': fields.many2one('stock.picking.out', 'Back Order of', states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}, help="If this shipment was split, then this field links to the shipment which contains the already processed part.", select=True), 'backorder_id': fields.many2one('stock.picking.out', 'Back Order of', states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}, help="If this shipment was split, then this field links to the shipment which contains the already processed part.", select=True),
'state': fields.selection( 'state': fields.selection(

View File

@ -1251,7 +1251,7 @@
<field name="company_id" groups="base.group_multi_company" widget="selection"/> <field name="company_id" groups="base.group_multi_company" widget="selection"/>
</group> </group>
<group name="origin_grp" string="Origin"> <group name="origin_grp" string="Origin">
<field name="origin"/> <field name="origin" attrs="{'invisible': [('picking_id', '=', False)]}"/>
<field name="picking_id" domain="[('type','=',type)]"/> <field name="picking_id" domain="[('type','=',type)]"/>
<field name="type" on_change="onchange_move_type(type)"/> <field name="type" on_change="onchange_move_type(type)"/>
<field name="location_id" groups="stock.group_locations"/> <field name="location_id" groups="stock.group_locations"/>

View File

@ -51,7 +51,7 @@ class stock_partial_picking_line(osv.TransientModel):
'move_id' : fields.many2one('stock.move', "Move", ondelete='CASCADE'), 'move_id' : fields.many2one('stock.move', "Move", ondelete='CASCADE'),
'wizard_id' : fields.many2one('stock.partial.picking', string="Wizard", ondelete='CASCADE'), 'wizard_id' : fields.many2one('stock.partial.picking', string="Wizard", ondelete='CASCADE'),
'update_cost': fields.boolean('Need cost update'), 'update_cost': fields.boolean('Need cost update'),
'cost' : fields.float("Cost", help="Unit Cost for this product line"), 'cost' : fields.float("Cost", help="Unit Cost for this product line", digits_compute=dp.get_precision('Product Price')),
'currency' : fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'), 'currency' : fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'),
'tracking': fields.function(_tracking, string='Tracking', type='boolean'), 'tracking': fields.function(_tracking, string='Tracking', type='boolean'),
} }