[MERGE] forward port branch 12.0 up to 4870251f0b
This commit is contained in:
@@ -152,6 +152,7 @@ class StockPicking(models.Model):
|
||||
'context': dict(
|
||||
self.env.context,
|
||||
current_package_carrier_type=self.carrier_id.delivery_type,
|
||||
default_picking_id=self.id, # DO NOT FORWARD PORT
|
||||
default_stock_quant_package_id=res.id
|
||||
),
|
||||
}
|
||||
|
||||
@@ -37,14 +37,15 @@ class ChooseDeliveryPackage(models.TransientModel):
|
||||
return res
|
||||
|
||||
def _default_shipping_weight(self):
|
||||
if self.env.context.get('default_stock_quant_package_id'):
|
||||
stock_quant_package = self.env['stock.quant.package'].browse(self.env.context['default_stock_quant_package_id'])
|
||||
return stock_quant_package.shipping_weight
|
||||
else:
|
||||
picking_id = self.env['stock.picking'].browse(self.env.context['active_id'])
|
||||
move_line_ids = [po for po in picking_id.move_line_ids if po.qty_done > 0 and not po.result_package_id]
|
||||
package_id = self.env.context.get('default_stock_quant_package_id')
|
||||
picking_id = self.env.context.get('default_picking_id')
|
||||
if package_id and picking_id: # DO NOT FORWARD PORT
|
||||
picking = self.env['stock.picking'].browse(picking_id)
|
||||
move_line_ids = [po for po in picking.move_line_ids if po.qty_done > 0 and po.result_package_id.id == package_id]
|
||||
total_weight = sum([po.qty_done * po.product_id.weight for po in move_line_ids])
|
||||
return total_weight
|
||||
else:
|
||||
return 0
|
||||
|
||||
@api.depends('stock_quant_package_id', 'delivery_packaging_id')
|
||||
def _compute_weight_uom_name(self):
|
||||
|
||||
@@ -81,7 +81,7 @@ class SyncEvent(object):
|
||||
self.OP = Delete((self.OE.status and "OE") or (self.GG.status and "GG"),
|
||||
'The event has been deleted from one side, we delete on other side !')
|
||||
#If event is not deleted !
|
||||
elif self.OE.status and (self.GG.status or not is_owner):
|
||||
elif self.OE.status and (self.GG.status or (not is_owner and self.GG.update)):
|
||||
if abs(self.OE.update - self.GG.update) > timedelta(seconds=1):
|
||||
if self.OE.update < self.GG.update:
|
||||
tmpSrc = 'GG'
|
||||
|
||||
@@ -35,7 +35,7 @@ class GoogleDrive(models.Model):
|
||||
if not modifiers.get('invisible') and not modifiers.get('column_invisible'):
|
||||
display_fields.append(node.get('name'))
|
||||
fields = " ".join(display_fields)
|
||||
domain = domain.replace("'", r"\'").replace('"', "'")
|
||||
domain = domain.replace("'", r"\'").replace('"', "'").replace('True', 'true').replace('False', 'false')
|
||||
if groupbys:
|
||||
fields = "%s %s" % (groupbys, fields)
|
||||
formula = '=oe_read_group("%s";"%s";"%s";"%s")' % (model, fields, groupbys, domain)
|
||||
|
||||
@@ -172,6 +172,8 @@ class MailMail(models.Model):
|
||||
messages._notify_failure_update() # notify user that we have a failure
|
||||
(notifications - failed).sudo().write({
|
||||
'email_status': 'sent',
|
||||
'failure_type': '',
|
||||
'failure_reason': '',
|
||||
})
|
||||
if not failure_type or failure_type == 'RECIPIENT': # if we have another error, we want to keep the mail.
|
||||
mail_to_delete_ids = [mail.id for mail in self if mail.auto_delete]
|
||||
|
||||
@@ -536,6 +536,7 @@ var BasicComposer = Widget.extend({
|
||||
files: ev.currentTarget.files,
|
||||
submitForm: true
|
||||
});
|
||||
ev.target.value = "";
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
|
||||
@@ -249,7 +249,7 @@ class MrpWorkorder(models.Model):
|
||||
self.qty_producing = float_round(self.production_id.product_qty - self.qty_produced, precision_rounding=rounding)
|
||||
self.generate_wo_lines()
|
||||
|
||||
if self.next_work_order_id and self.production_id.product_id.tracking != 'none':
|
||||
if self.next_work_order_id and self.next_work_order_id.state not in ['done', 'cancel'] and self.production_id.product_id.tracking != 'none':
|
||||
self.next_work_order_id._assign_default_final_lot_id()
|
||||
|
||||
if float_compare(self.qty_produced, self.production_id.product_qty, precision_rounding=rounding) >= 0:
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
<input type="checkbox" name="o_payment_form_save_token" data-remove-me=""/>
|
||||
Save my payment data
|
||||
</label>
|
||||
<t t-if="acq.save_token == 'always'">
|
||||
<input type="checkbox" name="o_payment_form_save_token" checked="'checked'" class="o_hidden" data-remove-me=""/>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="acq.payment_flow == 's2s'">
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
<div class="row">
|
||||
<div t-attf-class="col {{'col-lg-6' if not task.description else 'col-lg-12'}}">
|
||||
<ul class="list-group">
|
||||
<a class="list-group-item list-group-item-action d-flex align-items-center oe_attachments py-1 px-2" t-foreach='task.attachment_ids' t-as='attachment' t-attf-href="/web/content/#{attachment.id}" target="_blank" data-no-post-process="">
|
||||
<a class="list-group-item list-group-item-action d-flex align-items-center oe_attachments py-1 px-2" t-foreach='task.attachment_ids' t-as='attachment' t-attf-href="/web/content/#{attachment.id}?download=true" target="_blank" data-no-post-process="">
|
||||
<div class='oe_attachment_embedded o_image o_image_small mr-2 mr-lg-3' t-att-title="attachment.name" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/50x40"/>
|
||||
<div class='oe_attachment_name text-truncate'><t t-esc='attachment.name'/></div>
|
||||
</a>
|
||||
|
||||
@@ -1242,6 +1242,7 @@ class SaleOrderLine(models.Model):
|
||||
:param additional_domain: domain to restrict AAL to include in computation (required since timesheet is an AAL with a project ...)
|
||||
"""
|
||||
result = {}
|
||||
|
||||
# avoid recomputation if no SO lines concerned
|
||||
if not self:
|
||||
return result
|
||||
|
||||
@@ -6,6 +6,14 @@ from odoo import models, fields, api, _
|
||||
class IrActionsReport(models.Model):
|
||||
_inherit = 'ir.actions.report'
|
||||
|
||||
@api.multi
|
||||
def retrieve_attachment(self, record):
|
||||
# Override this method in order to force to re-render the pdf in case of
|
||||
# using snailmail
|
||||
if self.env.context.get('snailmail_layout'):
|
||||
return False
|
||||
return super(IrActionsReport, self).retrieve_attachment(record)
|
||||
|
||||
@api.model
|
||||
def get_paperformat(self):
|
||||
# force the right format (euro/A4) when sending letters, only if we are not using the l10n_DE layout
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
<!--
|
||||
Resource: stock.location
|
||||
-->
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
<record id="stock_location_locations" model="stock.location">
|
||||
<field name="name">Physical Locations</field>
|
||||
<field name="usage">view</field>
|
||||
|
||||
@@ -433,5 +433,5 @@ class QuantPackage(models.Model):
|
||||
for quant in self._get_contained_quants():
|
||||
if quant.product_id not in res:
|
||||
res[quant.product_id] = 0
|
||||
res[quant.product_id] += quant.qty
|
||||
res[quant.product_id] += quant.quantity
|
||||
return res
|
||||
|
||||
@@ -83,9 +83,8 @@ class UoM(models.Model):
|
||||
self._cr.execute("""
|
||||
SELECT C.id AS category_id, count(U.id) AS uom_count
|
||||
FROM uom_category C
|
||||
LEFT JOIN uom_uom U ON C.id = U.category_id AND uom_type = 'reference'
|
||||
LEFT JOIN uom_uom U ON C.id = U.category_id AND uom_type = 'reference' AND U.active = 't'
|
||||
WHERE C.id IN %s
|
||||
AND U.active = 't'
|
||||
GROUP BY C.id
|
||||
""", (tuple(category_ids),))
|
||||
for uom_data in self._cr.dictfetchall():
|
||||
|
||||
@@ -68,6 +68,16 @@ class TestUom(TransactionCase):
|
||||
'name': 'Custom UoM category',
|
||||
})
|
||||
|
||||
# at first we can not create a non reference in custom category
|
||||
with self.assertRaises(ValidationError):
|
||||
self.env['uom.uom'].create({
|
||||
'name': 'Bigger UoM of my category',
|
||||
'factor_inv': 42,
|
||||
'uom_type': 'bigger',
|
||||
'rounding': 0.5,
|
||||
'category_id': category.id
|
||||
})
|
||||
|
||||
# create the reference
|
||||
self.env['uom.uom'].create({
|
||||
'name': 'Reference UoM of my category',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.o_boxed_footer, .o_boxed_header, .o_report_layout_boxed {
|
||||
font-family: 'Lato' 'Noto';
|
||||
font-family: 'Lato', 'Noto';
|
||||
color: gray('700');
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ class Website(models.Model):
|
||||
public_user_to_change_websites = self.env['website']
|
||||
self._get_languages.clear_cache(self)
|
||||
if 'company_id' in values and 'user_id' not in values:
|
||||
public_user_to_change_websites = self.filtered(lambda w: w.user_id.company_id.id != values['company_id'])
|
||||
public_user_to_change_websites = self.filtered(lambda w: w.sudo().user_id.company_id.id != values['company_id'])
|
||||
if public_user_to_change_websites:
|
||||
company = self.env['res.company'].browse(values['company_id'])
|
||||
super(Website, public_user_to_change_websites).write(dict(values, user_id=company._get_public_user().id))
|
||||
|
||||
@@ -129,11 +129,20 @@ sAnimations.registry.WebsiteSaleOptions = sAnimations.Class.extend(ProductConfig
|
||||
* @param {integer} quantity
|
||||
*/
|
||||
_onOptionsUpdateQuantity: function (quantity) {
|
||||
this.$form
|
||||
var $qtyInput = this.$form
|
||||
.find('.js_main_product input[name="add_qty"]')
|
||||
.first()
|
||||
.val(quantity)
|
||||
.trigger('change');
|
||||
.first();
|
||||
|
||||
if ($qtyInput.length) {
|
||||
$qtyInput.val(quantity).trigger('change');
|
||||
} else {
|
||||
// This handles the case when the "Select Quantity" customize show
|
||||
// is disabled, and therefore the above selector does not find an
|
||||
// element.
|
||||
// To avoid duplicating all RPC, only trigger the variant change if
|
||||
// it is not already done from the above trigger.
|
||||
this.optionalProductsModal.triggerVariantChange(this.optionalProductsModal.$el);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ from odoo.http import request
|
||||
class ProductWishlist(models.Model):
|
||||
_name = 'product.wishlist'
|
||||
_description = 'Product Wishlist'
|
||||
_sql_constrains = [
|
||||
_sql_constraints = [
|
||||
("product_unique_partner_id",
|
||||
"UNIQUE(product_id, partner_id)",
|
||||
"Duplicated wishlisted product for this partner."),
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
'data': [
|
||||
'ir.model.access.csv',
|
||||
'views.xml',
|
||||
'demo_data.xml',
|
||||
'template.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo_data.xml',
|
||||
],
|
||||
}
|
||||
|
||||
+9
-7
@@ -280,13 +280,15 @@ class WebRequest(object):
|
||||
_request_stack.pop()
|
||||
|
||||
if self._cr:
|
||||
if exc_type is None and not self._failed:
|
||||
self._cr.commit()
|
||||
if self.registry:
|
||||
self.registry.signal_changes()
|
||||
elif self.registry:
|
||||
self.registry.reset_changes()
|
||||
self._cr.close()
|
||||
try:
|
||||
if exc_type is None and not self._failed:
|
||||
self._cr.commit()
|
||||
if self.registry:
|
||||
self.registry.signal_changes()
|
||||
elif self.registry:
|
||||
self.registry.reset_changes()
|
||||
finally:
|
||||
self._cr.close()
|
||||
# just to be sure no one tries to re-use the request
|
||||
self.disable_db = True
|
||||
self.uid = None
|
||||
|
||||
Reference in New Issue
Block a user