[MERGE] forward port branch 11.0 up to 3513e599a7

This commit is contained in:
Christophe Simonis
2018-08-07 13:58:20 +02:00
14 changed files with 66 additions and 14416 deletions
+18
View File
@@ -1470,6 +1470,10 @@ class Meeting(models.Model):
@api.multi @api.multi
def write(self, values): def write(self, values):
# FIXME: neverending recurring events
if 'rrule' in values:
values['rrule'] = self._fix_rrule(values)
# compute duration, only if start and stop are modified # compute duration, only if start and stop are modified
if not 'duration' in values and 'start' in values and 'stop' in values: if not 'duration' in values and 'start' in values and 'stop' in values:
values['duration'] = self._get_duration(values['start'], values['stop']) values['duration'] = self._get_duration(values['start'], values['stop'])
@@ -1538,6 +1542,10 @@ class Meeting(models.Model):
@api.model @api.model
def create(self, values): def create(self, values):
# FIXME: neverending recurring events
if 'rrule' in values:
values['rrule'] = self._fix_rrule(values)
if not 'user_id' in values: # Else bug with quick_create when we are filter on an other user if not 'user_id' in values: # Else bug with quick_create when we are filter on an other user
values['user_id'] = self.env.user.id values['user_id'] = self.env.user.id
@@ -1742,3 +1750,13 @@ class Meeting(models.Model):
activity_values['user_id'] = values['user_id'] activity_values['user_id'] = values['user_id']
if activity_values.keys(): if activity_values.keys():
self.mapped('activity_ids').write(activity_values) self.mapped('activity_ids').write(activity_values)
@api.model
def _fix_rrule(self, values):
rule_str = values.get('rrule')
if rule_str:
rule = rrule.rrulestr(rule_str)
if not rule._until and not rule._count:
rule._count = 100
rule_str = str(rule).split('RRULE:')[-1]
return rule_str
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -531,7 +531,7 @@ class PurchaseOrder(models.Model):
This function returns an action that display existing picking orders of given purchase order ids. This function returns an action that display existing picking orders of given purchase order ids.
When only one found, show the picking immediately. When only one found, show the picking immediately.
''' '''
action = self.env.ref('stock.action_picking_tree') action = self.env.ref('stock.action_picking_tree_all')
result = action.read()[0] result = action.read()[0]
#override the context to get rid of the default filtering on operation type #override the context to get rid of the default filtering on operation type
+1 -2
View File
@@ -3,8 +3,7 @@ access_repair_fee_user,Repair Fee user,model_repair_fee,stock.group_stock_user,1
access_repair_fee_manager,Repair Fee manager,model_repair_fee,stock.group_stock_manager,1,0,0,0 access_repair_fee_manager,Repair Fee manager,model_repair_fee,stock.group_stock_manager,1,0,0,0
access_repair_user,Repair user,model_repair_order,stock.group_stock_user,1,1,1,1 access_repair_user,Repair user,model_repair_order,stock.group_stock_user,1,1,1,1
access_repair_manager,Repair manager,model_repair_order,stock.group_stock_manager,1,0,0,0 access_repair_manager,Repair manager,model_repair_order,stock.group_stock_manager,1,0,0,0
access_product_pricelist_manager,product.pricelist manager,product.model_product_pricelist,stock.group_stock_manager,1,0,0,0 access_product_pricelist_user,product.pricelist user,product.model_product_pricelist,stock.group_stock_user,1,0,0,0
access_product_pricelist_user,product.pricelist user,product.model_product_pricelist,stock.group_stock_user,1,1,1,1
access_stock_production_lot_user,stock.production.lot user,stock.model_stock_production_lot,stock.group_stock_user,1,1,1,1 access_stock_production_lot_user,stock.production.lot user,stock.model_stock_production_lot,stock.group_stock_user,1,1,1,1
access_stock_production_lot_manager,stock.production.lot manager,stock.model_stock_production_lot,stock.group_stock_manager,1,0,0,0 access_stock_production_lot_manager,stock.production.lot manager,stock.model_stock_production_lot,stock.group_stock_manager,1,0,0,0
access_repair_line_user,repair.line user,model_repair_line,stock.group_stock_user,1,1,1,1 access_repair_line_user,repair.line user,model_repair_line,stock.group_stock_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_repair_fee_manager Repair Fee manager model_repair_fee stock.group_stock_manager 1 0 0 0
4 access_repair_user Repair user model_repair_order stock.group_stock_user 1 1 1 1
5 access_repair_manager Repair manager model_repair_order stock.group_stock_manager 1 0 0 0
6 access_product_pricelist_manager access_product_pricelist_user product.pricelist manager product.pricelist user product.model_product_pricelist stock.group_stock_manager stock.group_stock_user 1 0 0 0
access_product_pricelist_user product.pricelist user product.model_product_pricelist stock.group_stock_user 1 1 1 1
7 access_stock_production_lot_user stock.production.lot user stock.model_stock_production_lot stock.group_stock_user 1 1 1 1
8 access_stock_production_lot_manager stock.production.lot manager stock.model_stock_production_lot stock.group_stock_manager 1 0 0 0
9 access_repair_line_user repair.line user model_repair_line stock.group_stock_user 1 1 1 1
+1 -1
View File
@@ -25,7 +25,7 @@ HOURS_PER_DAY = 8
def float_to_time(float_hour): def float_to_time(float_hour):
if float_hour == 24.0: if float_hour == 24.0:
return datetime.time.max return datetime.time.max
return datetime.time(int(math.modf(float_hour)[1]), int(60 * math.modf(float_hour)[0]), 0) return datetime.time(int(math.modf(float_hour)[1]), int(float_round(60 * math.modf(float_hour)[0], precision_digits=0)), 0)
def to_naive_user_tz(datetime, record): def to_naive_user_tz(datetime, record):
+2 -1
View File
@@ -329,7 +329,8 @@ class ProcurementGroup(models.Model):
for orderpoint in orderpoints: for orderpoint in orderpoints:
key = self._procurement_from_orderpoint_get_grouping_key([orderpoint.id]) key = self._procurement_from_orderpoint_get_grouping_key([orderpoint.id])
location_data[key] = makedefault() if not location_data.get(key):
location_data[key] = makedefault()
location_data[key]['products'] += orderpoint.product_id location_data[key]['products'] += orderpoint.product_id
location_data[key]['orderpoints'] += orderpoint location_data[key]['orderpoints'] += orderpoint
location_data[key]['groups'] = self._procurement_from_orderpoint_get_groups([orderpoint.id]) location_data[key]['groups'] = self._procurement_from_orderpoint_get_groups([orderpoint.id])
+5
View File
@@ -578,6 +578,11 @@ class StockMove(models.Model):
res.append((0, 0, price_diff_line)) res.append((0, 0, price_diff_line))
return res return res
def _prepare_move_split_vals(self, uom_qty):
vals = super(StockMove, self)._prepare_move_split_vals(uom_qty)
vals['to_refund'] = self.to_refund
return vals
def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id): def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id):
self.ensure_one() self.ensure_one()
AccountMove = self.env['account.move'] AccountMove = self.env['account.move']
+1 -1
View File
@@ -801,7 +801,7 @@
<t t-foreach="elements" t-as="el"> <t t-foreach="elements" t-as="el">
<t t-set="color" t-value="el[colorField] || 0"/> <t t-set="color" t-value="el[colorField] || 0"/>
<span t-attf-class="badge dropdown o_tag_color_#{color}" t-att-data-color="color" t-att-data-index="el_index" t-att-data-id="el.id"> <span t-attf-class="badge dropdown o_tag_color_#{color}" t-att-data-color="color" t-att-data-index="el_index" t-att-data-id="el.id">
<span class="o_badge_text"><t t-esc="el.display_name"/></span> <span class="o_badge_text" t-att-title="el.display_name"><t t-esc="el.display_name"/></span>
<span t-if="!readonly" class="fa fa-times o_delete"/> <span t-if="!readonly" class="fa fa-times o_delete"/>
</span> </span>
</t> </t>
@@ -10583,6 +10583,31 @@ QUnit.module('relational_fields', {
form.destroy(); form.destroy();
}); });
QUnit.test('widget many2many_tags', function (assert) {
assert.expect(1);
this.data.turtle.records[0].partner_ids = [2];
var form = createView({
View: FormView,
model: 'turtle',
data: this.data,
arch:'<form string="Turtles">' +
'<sheet>' +
'<field name="display_name"/>' +
'<field name="partner_ids" widget="many2many_tags"/>' +
'</sheet>' +
'</form>',
res_id: 1,
});
assert.deepEqual(
form.$('.o_field_many2manytags.o_field_widget .badge .o_badge_text').attr('title'),
'second record', 'the title should be filled in'
);
form.destroy();
});
QUnit.module('FieldStatus'); QUnit.module('FieldStatus');
QUnit.test('static statusbar widget on many2one field', function (assert) { QUnit.test('static statusbar widget on many2one field', function (assert) {
@@ -248,6 +248,10 @@ function applyOverDescendants(node, func) {
func(node); func(node);
applyOverDescendants(node, func); applyOverDescendants(node, func);
} }
var $node = $(node);
if (node.nodeName === 'A' && $node.hasClass('btn') && !$node.children().length && $(node).parents('.o_outlook_hack').length) {
node = $(node).parents('.o_outlook_hack')[0];
}
node = node.nextSibling; node = node.nextSibling;
} }
} }
@@ -283,7 +287,7 @@ function classToStyle($editable) {
// Outlook // Outlook
if (node.nodeName === 'A' && $target.hasClass('btn') && !$target.hasClass('btn-link') && !$target.children().length) { if (node.nodeName === 'A' && $target.hasClass('btn') && !$target.hasClass('btn-link') && !$target.children().length) {
var $hack = $('<table class="o_outlook_hack" style="display: inline-table;"><tr><td></td></tr></table>'); var $hack = $('<table class="o_outlook_hack" style="display: inline-table;vertical-align:middle"><tr><td></td></tr></table>');
$hack.find('td') $hack.find('td')
.attr('height', $target.outerHeight()) .attr('height', $target.outerHeight())
.css({ .css({
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -550,7 +550,11 @@ class IrModelFields(models.Model):
failed_dependencies = [] failed_dependencies = []
for rec in self: for rec in self:
model = self.env[rec.model] model = self.env[rec.model]
field = model._fields[rec.name] if rec.name in model._fields:
field = model._fields[rec.name]
else:
# field hasn't been loaded (yet?)
continue
for dependant, path in model._field_triggers.get(field, ()): for dependant, path in model._field_triggers.get(field, ()):
if dependant.manual: if dependant.manual:
failed_dependencies.append((field, dependant)) failed_dependencies.append((field, dependant))
@@ -747,6 +751,7 @@ class IrModelFields(models.Model):
'readonly': bool(field.readonly), 'readonly': bool(field.readonly),
'required': bool(field.required), 'required': bool(field.required),
'selectable': bool(field.search or field.store), 'selectable': bool(field.search or field.store),
'size': getattr(field, 'size', None),
'translate': bool(field.translate), 'translate': bool(field.translate),
'relation_field': field.inverse_name if field.type == 'one2many' else None, 'relation_field': field.inverse_name if field.type == 'one2many' else None,
'relation_table': field.relation if field.type == 'many2many' else None, 'relation_table': field.relation if field.type == 'many2many' else None,
+1 -1
View File
@@ -45,7 +45,7 @@ class _Cleaner(clean.Cleaner):
_style_whitelist = [ _style_whitelist = [
'font-size', 'font-family', 'font-weight', 'background-color', 'color', 'text-align', 'font-size', 'font-family', 'font-weight', 'background-color', 'color', 'text-align',
'line-height', 'letter-spacing', 'text-transform', 'text-decoration', 'line-height', 'letter-spacing', 'text-transform', 'text-decoration',
'float', 'vertical-align', 'float', 'vertical-align', 'display',
'padding', 'padding-top', 'padding-left', 'padding-bottom', 'padding-right', 'padding', 'padding-top', 'padding-left', 'padding-bottom', 'padding-right',
'margin', 'margin-top', 'margin-left', 'margin-bottom', 'margin-right', 'margin', 'margin-top', 'margin-left', 'margin-bottom', 'margin-right',
# box model # box model