[MERGE] forward port of branch 9.0 up to 3381e7b

This commit is contained in:
Christophe Simonis
2016-05-04 14:42:54 +02:00
16 changed files with 59 additions and 43 deletions
+1 -1
View File
@@ -248,7 +248,7 @@ class account_payment(models.Model):
invoice_defaults = self.resolve_2many_commands('invoice_ids', rec.get('invoice_ids'))
if invoice_defaults and len(invoice_defaults) == 1:
invoice = invoice_defaults[0]
rec['communication'] = invoice['reference']
rec['communication'] = invoice['reference'] or invoice['name'] or invoice['number']
rec['currency_id'] = invoice['currency_id'][0]
rec['payment_type'] = invoice['type'] in ('out_invoice', 'in_refund') and 'inbound' or 'outbound'
rec['partner_type'] = MAP_INVOICE_TYPE_PARTNER_TYPE[invoice['type']]
+1 -1
View File
@@ -274,7 +274,7 @@ class base_action_rule(osv.osv):
# check conditions, and execute actions on the records that satisfy them
for action in actions:
action._process(action._filter_post(pre[action]))
action._process(action._filter_post(records))
# call original method
return unlink.origin(self, **kwargs)
@@ -41,7 +41,7 @@ class crm_lead_forward_to_partner(osv.TransientModel):
if wizard.comment:
message += '<p>%s</p>' % wizard.comment
for active_id in context.get('active_ids', []):
lead_obj.message_post(cr, uid, active_id, body=message, subtype="mail.mt_comment", context=context)
lead_obj.message_post(cr, uid, active_id, body=message, subtype="mail.mt_note", context=context)
if values:
lead_obj.write(cr, SUPERUSER_ID, context.get('active_ids', []), values)
lead_obj.set_tag_assign(cr, SUPERUSER_ID, context.get('active_ids', []), False)
+13
View File
@@ -450,6 +450,19 @@ class hr_holidays(osv.osv):
return True
def holidays_confirm(self, cr, uid, ids, context=None):
for record in self.browse(cr, uid, ids, context=context):
if record.department_id:
# Subscribe the followers of the department following the `confirmed` subtype
# It's done manually because `message_auto_subscribe` only works on fields for which
# the value is passed to the `create` or `write` methods,
# it doesn't work for related/computed fields
# This can be removed as soon as `department_id` on `hr.holidays` becomes a regular
# fields or as soon as `message_auto_subscribe` works with related/computed fields.
confirmed_subtype = self.pool['ir.model.data'].xmlid_to_object(cr, uid, 'hr_holidays.mt_department_holidays_confirmed', context=context)
self.message_subscribe(cr, uid, [record.id], [
follower.partner_id.id for follower in record.department_id.message_follower_ids
if confirmed_subtype in follower.subtype_ids
], context=context)
return self.write(cr, uid, ids, {'state': 'confirm'})
def holidays_refuse(self, cr, uid, ids, context=None):
+9 -12
View File
@@ -283,12 +283,13 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
},
unselect_message: function() {
if (this.channel.type !== 'static' && !this.channel.mass_mailing) {
this.basic_composer.toggle(true);
this.basic_composer.focus();
this.basic_composer.toggle(this.channel.type !== 'static' && !this.channel.mass_mailing);
this.extended_composer.toggle(this.channel.type !== 'static' && this.channel.mass_mailing);
if (!config.device.touch) {
var composer = this.channel.mass_mailing ? this.extended_composer : this.basic_composer;
composer.focus();
}
this.$el.removeClass('o_mail_selection_mode');
this.extended_composer.toggle(this.channel.mass_mailing);
this.thread.unselect();
this.selected_message = null;
},
@@ -424,10 +425,6 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
.find('.o_mail_chat_button_unstar_all')
.toggle(channel.id === "channel_starred");
self.basic_composer.toggle(channel.type !== 'static' && !channel.mass_mailing);
self.extended_composer.toggle(channel.type !== 'static' && channel.mass_mailing);
self.$el.removeClass('o_mail_selection_mode');
self.$('.o_mail_chat_channel_item')
.removeClass('o_active')
.filter('[data-channel-id=' + channel.id + ']')
@@ -443,14 +440,14 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
// Update control panel before focusing the composer, otherwise focus is on the searchview
self.update_cp();
if (!config.device.touch) {
var composer = channel.mass_mailing ? self.extended_composer : self.basic_composer;
composer.focus();
}
if (config.device.size_class === config.device.SIZES.XS) {
self.$('.o_mail_chat_sidebar').hide();
}
// Display and focus the adequate composer, and unselect possibly selected message
// to prevent sending messages as reply to that message
self.unselect_message();
self.action_manager.do_push_state({
action: self.action.id,
active_id: self.channel.id,
+1 -3
View File
@@ -111,9 +111,7 @@ var MessagingMenu = Widget.extend({
// Generate last message preview (inline message body and compute date to display)
_.each(channels_preview, function (channel) {
channel.last_message_preview =
channel.last_message.displayed_author + ': ' +
chat_manager.get_message_body_preview(channel.last_message.body);
channel.last_message_preview = chat_manager.get_message_body_preview(channel.last_message.body);
if (channel.last_message.date.isSame(new Date(), 'd')) { // today
channel.last_message_date = channel.last_message.date.format('LT');
} else {
+1
View File
@@ -45,6 +45,7 @@
<span class="o_last_message_date"> <t t-esc="channel.last_message_date"/> </span>
</div>
<div class="o_last_message_preview">
<t t-esc="channel.last_message.displayed_author"/>:
<t t-raw="channel.last_message_preview"/>
</div>
</div>
+20 -9
View File
@@ -802,13 +802,7 @@ class mrp_production(osv.osv):
return True
def _compute_costs_from_production(self, cr, uid, ids, context=None):
""" Generate workcenter costs and rectify the value of the quant
Must be called at the end of the production.
The value of the quant was not possible to compute before the end of
the manufacturing order due to the cost of raw manterial and production
costs. The price of the quant was not set in get_price_unit.
"""
""" Generate workcenter costs in analytic accounts"""
for production in self.browse(cr, uid, ids):
total_cost = self._costs_generate(cr, uid, production)
@@ -956,6 +950,16 @@ class mrp_production(osv.osv):
total_cost += sum([x.inventory_value for x in consumed_move.quant_ids if x.qty > 0])
return total_cost
def _calculate_workcenter_cost(self, cr, uid, production_id, context=None):
""" Compute the planned production cost from the workcenters """
production = self.browse(cr, uid, production_id, context=context)
total_cost = 0.0
for wc_line in production.workcenter_lines:
wc = wc_line.workcenter_id
total_cost += wc_line.hour*wc.costs_hour + wc_line.cycle*wc.costs_cycle
return total_cost
def action_produce(self, cr, uid, production_id, production_qty, production_mode, wiz=False, context=None):
""" To produce final product based on production mode (consume/consume&produce).
If Production mode is consume, all stock move lines of raw materials will be done/consumed.
@@ -1011,18 +1015,25 @@ class mrp_production(osv.osv):
total_consume_moves.append(extra_move_id)
if production_mode == 'consume_produce':
# add production lines that have already been consumed since the last 'consume & produce'
last_production_date = production.move_created_ids2 and max(production.move_created_ids2.mapped('date')) or False
already_consumed_lines = production.move_lines2.filtered(lambda l: l.date > last_production_date)
total_consume_moves += already_consumed_lines.ids
price_unit = 0
for produce_product in production.move_created_ids:
is_main_product = (produce_product.product_id.id == production.product_id.id) and production.product_id.cost_method=='real'
if is_main_product:
total_cost = self._calculate_total_cost(cr, uid, total_consume_moves, context=context)
price_unit = total_cost / production_qty_uom
production_cost = self._calculate_workcenter_cost(cr, uid, production_id, context=context)
price_unit = (total_cost + production_cost) / production_qty_uom
subproduct_factor = self._get_subproduct_factor(cr, uid, production.id, produce_product.id, context=context)
lot_id = False
if wiz:
lot_id = wiz.lot_id.id
qty = min(subproduct_factor * production_qty_uom, produce_product.product_qty) #Needed when producing more than maximum quantity
if is_main_product:
if is_main_product and price_unit:
stock_mov_obj.write(cr, uid, [produce_product.id], {'price_unit': price_unit}, context=context)
new_moves = stock_mov_obj.action_consume(cr, uid, [produce_product.id], qty,
location_id=produce_product.location_id.id, restrict_lot_id=lot_id, context=context)
@@ -39,6 +39,7 @@
<field name="price_unit" on_change="onchange_qty(parent.pricelist_id,product_id, discount, qty, price_unit, context)" widget="monetary"/>
<field name="discount" on_change="onchange_qty(parent.pricelist_id,product_id, discount, qty, price_unit, context)" widget="monetary"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tags"/>
<field name="tax_ids" invisible="1"/>
<field name="price_subtotal" widget="monetary"/>
<field name="price_subtotal_incl" widget="monetary"/>
</tree>
@@ -1023,7 +1023,9 @@ var ClientListScreenWidget = ScreenWidget.extend({
if (this.editing_client) {
this.$('.detail.barcode').val(code.code);
} else if (this.pos.db.get_partner_by_barcode(code.code)) {
this.display_client_details('show',this.pos.db.get_partner_by_barcode(code.code));
var partner = this.pos.db.get_partner_by_barcode(code.code);
this.new_client = partner;
this.display_client_details('show', partner);
}
},
perform_search: function(query, associate_result){
+1 -1
View File
@@ -40,7 +40,7 @@ class stock_production_lot(osv.osv):
# Assign dates according to products data
def create(self, cr, uid, vals, context=None):
context = dict(context or {})
context['product_id'] = vals.get('product_id', context.get('default_product_id'))
context['product_id'] = vals.get('product_id', context.get('default_product_id') or context.get('product_id'))
return super(stock_production_lot, self).create(cr, uid, vals, context=context)
_defaults = {
+1 -3
View File
@@ -144,6 +144,4 @@ class AccountInvoiceLine(models.Model):
average_price_unit += factor * self._compute_average_price(prod_qty_done, prod_quantity, prod_moves)
price_unit = average_price_unit or price_unit
price_unit = uom_obj._compute_qty_obj(self.uom_id, price_unit, self.product_id.uom_id, round=False)
return price_unit
else:
return price_unit
return price_unit
@@ -10,15 +10,7 @@ class WebsiteAccount(website_account):
def account(self):
response = super(WebsiteAccount, self).account()
user = request.env.user
# TDE FIXME: shouldn't that be mnaged by the access rule itself ?
# portal projects where you or someone from your company are a follower
project_issues = request.env['project.issue'].search([
'&',
('project_id.privacy_visibility', '=', 'portal'),
'|',
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
('message_partner_ids', 'child_of', [user.partner_id.id])
])
project_issues = request.env['project.issue'].search([])
response.qcontext.update({'issues': project_issues})
return response
+1
View File
@@ -639,6 +639,7 @@ Model Reference
.. automethod:: write
.. automethod:: read
.. automethod:: read_group
.. rubric:: Research
+1 -1
View File
@@ -14902,7 +14902,7 @@ msgstr ""
#. module: base
#: model:ir.model.fields,help:base.field_res_partner_company_type
#: model:ir.model.fields,help:base.field_res_users_company_type
msgid "Technical field, used only to display a boolean using a radio button. As for Odoo v9 RadioButton cannot be used on boolean fields, this one serves as interface. Due to the old API limitations with interface function field, we implement it by hand instead of a true function field. When migrating to the new API the code should be simplified."
msgid "Technical field, used only to display a boolean using a radio button. As for Odoo v9 RadioButton cannot be used on boolean fields, this one serves as interface. Due to the old API limitations with interface function field, we implement it by hand instead of a true function field. When migrating to the new API the code should be simplified. Changing the company_type of a company contact into a company will not display this contact as a company contact but as a standalone company."
msgstr ""
#. module: base
+3 -1
View File
@@ -239,7 +239,9 @@ class res_partner(osv.Model, format_address):
'fields, this one serves as interface. Due to the old API '
'limitations with interface function field, we implement it '
'by hand instead of a true function field. When migrating to '
'the new API the code should be simplified.'),
'the new API the code should be simplified. Changing the'
'company_type of a company contact into a company will not display'
'this contact as a company contact but as a standalone company.'),
'use_parent_address': fields.boolean('Use Company Address', help="Select this if you want to set company's address information for this contact"),
'company_id': fields.many2one('res.company', 'Company', select=1),
'color': fields.integer('Color Index'),