[MERGE] forward port of branch 9.0 up to 3381e7b
This commit is contained in:
@@ -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']]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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){
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -639,6 +639,7 @@ Model Reference
|
||||
.. automethod:: write
|
||||
|
||||
.. automethod:: read
|
||||
.. automethod:: read_group
|
||||
|
||||
.. rubric:: Research
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'),
|
||||
|
||||
Reference in New Issue
Block a user