[MERGE] forward port branch saas-16 up to 76262f2043
This commit is contained in:
@@ -183,7 +183,7 @@
|
||||
<field name="res_model">account.payment</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,graph</field>
|
||||
<field name="context">{'default_payment_type': 'inbound'}</field>
|
||||
<field name="context">{'default_payment_type': 'inbound', 'default_partner_type': 'customer'}</field>
|
||||
<field name="domain">[('partner_type', '=', 'customer')]</field>
|
||||
<field name="view_id" ref="view_account_payment_tree"/>
|
||||
<field name="help" type="html">
|
||||
@@ -201,7 +201,7 @@
|
||||
<field name="res_model">account.payment</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,graph</field>
|
||||
<field name="context">{'default_payment_type': 'outbound'}</field>
|
||||
<field name="context">{'default_payment_type': 'outbound', 'default_partner_type': 'supplier'}</field>
|
||||
<field name="domain">[('partner_type', '=', 'supplier')]</field>
|
||||
<field name="view_id" ref="view_account_supplier_payment_tree"/>
|
||||
<field name="help" type="html">
|
||||
|
||||
@@ -32,7 +32,7 @@ class BaseConfigSettings(models.TransientModel):
|
||||
|
||||
@api.model
|
||||
def get_oauth_providers(self, fields):
|
||||
google_provider = self.env.ref('auth_oauth.provider_google')
|
||||
google_provider = self.env.ref('auth_oauth.provider_google', False)
|
||||
return {
|
||||
'auth_oauth_google_enabled': google_provider.enabled,
|
||||
'auth_oauth_google_client_id': google_provider.client_id,
|
||||
@@ -42,7 +42,7 @@ class BaseConfigSettings(models.TransientModel):
|
||||
@api.multi
|
||||
def set_oauth_providers(self):
|
||||
self.ensure_one()
|
||||
google_provider = self.env.ref('auth_oauth.provider_google')
|
||||
google_provider = self.env.ref('auth_oauth.provider_google', False)
|
||||
rg = {
|
||||
'enabled': self.auth_oauth_google_enabled,
|
||||
'client_id': self.auth_oauth_google_client_id,
|
||||
|
||||
@@ -247,13 +247,19 @@ class Lead(models.Model):
|
||||
team_id = self.env['crm.team']._get_default_team_id(user_id=user_id)
|
||||
return {'team_id': team_id}
|
||||
|
||||
@api.constrains('user_id')
|
||||
@api.onchange('user_id')
|
||||
def _onchange_user_id(self):
|
||||
""" When changing the user, also set a team_id or restrict team id to the ones user_id is member of. """
|
||||
values = self._onchange_user_values(self.user_id.id)
|
||||
self.update(values)
|
||||
|
||||
@api.constrains('user_id')
|
||||
def _valid_team(self):
|
||||
if self.user_id:
|
||||
values = self.with_context(team_id=self.team_id.id)._onchange_user_values(self.user_id.id)
|
||||
if values:
|
||||
self.update(values)
|
||||
|
||||
@api.onchange('state_id')
|
||||
def _onchange_state(self):
|
||||
if self.state_id:
|
||||
|
||||
@@ -473,9 +473,12 @@ class HrExpenseSheet(models.Model):
|
||||
self.department_id = self.employee_id.department_id
|
||||
|
||||
@api.one
|
||||
@api.depends('expense_line_ids', 'expense_line_ids.total_amount')
|
||||
@api.depends('expense_line_ids', 'expense_line_ids.total_amount', 'expense_line_ids.currency_id')
|
||||
def _compute_amount(self):
|
||||
self.total_amount = sum(self.expense_line_ids.mapped('total_amount'))
|
||||
if len(self.expense_line_ids.mapped('currency_id')) < 2:
|
||||
self.total_amount = sum(self.expense_line_ids.mapped('total_amount'))
|
||||
else:
|
||||
self.total_amount = 0.0
|
||||
|
||||
# FIXME: A 4 command is missing to explicitly declare the one2many relation
|
||||
# between the sheet and the lines when using 'default_expense_line_ids':[ids]
|
||||
|
||||
@@ -71,26 +71,27 @@
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="line.total_amount"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
t-options='{"widget": "monetary", "display_currency": line.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4 pull-right">
|
||||
<table class="table table-condensed">
|
||||
<tr class="border-black">
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-field="o.total_amount"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<t t-if="len(o.mapped('expense_line_ids').mapped('currency_id')) < 2">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 pull-right">
|
||||
<table class="table table-condensed">
|
||||
<tr class="border-black">
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-field="o.total_amount"
|
||||
t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</t>
|
||||
<p>Certified honest and conform,<br/>(Date and signature).<br/><br/></p>
|
||||
</div>
|
||||
</t>
|
||||
@@ -108,4 +109,4 @@
|
||||
print_report_name="'Expenses - %s - %s' % (object.employee_id.name, (object.name).replace('/', ''))"
|
||||
/>
|
||||
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
||||
@@ -459,6 +459,7 @@
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="message_unread" invisible="1"/>
|
||||
<field name="attachment_number" string=" "/>
|
||||
|
||||
@@ -610,11 +610,11 @@ class PosOrder(models.Model):
|
||||
'location_id': location_id,
|
||||
'location_dest_id': destination_id,
|
||||
}
|
||||
pos_qty = any([x.qty > 0 for x in order.lines])
|
||||
pos_qty = any([x.qty > 0 for x in order.lines if x.product_id.type in ['product', 'consu']])
|
||||
if pos_qty:
|
||||
order_picking = Picking.create(picking_vals.copy())
|
||||
order_picking.message_post(body=message)
|
||||
neg_qty = any([x.qty < 0 for x in order.lines])
|
||||
neg_qty = any([x.qty < 0 for x in order.lines if x.product_id.type in ['product', 'consu']])
|
||||
if neg_qty:
|
||||
return_vals = picking_vals.copy()
|
||||
return_vals.update({
|
||||
|
||||
@@ -10,4 +10,4 @@ class SaleReport(models.Model):
|
||||
margin = fields.Float('Margin')
|
||||
|
||||
def _select(self):
|
||||
return super(SaleReport, self)._select() + ", SUM(l.margin) AS margin"
|
||||
return super(SaleReport, self)._select() + ", SUM(l.margin / COALESCE(cr.rate, 1.0)) AS margin"
|
||||
|
||||
@@ -148,5 +148,12 @@
|
||||
<field name="domain_force">['|', ('picking_id.message_partner_ids','in',[user.partner_id.id]), ('picking_id.partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="stock_location_route_comp_rule">
|
||||
<field name="name">stock_location_route multi-company</field>
|
||||
<field name="model_id" ref="model_stock_location_route"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -85,6 +85,7 @@ var AbstractView = Class.extend({
|
||||
edit: viewInfo.arch.attrs.edit ? JSON.parse(viewInfo.arch.attrs.edit) : true,
|
||||
create: viewInfo.arch.attrs.create ? JSON.parse(viewInfo.arch.attrs.create) : true,
|
||||
delete: viewInfo.arch.attrs.delete ? JSON.parse(viewInfo.arch.attrs.delete) : true,
|
||||
duplicate: viewInfo.arch.attrs.duplicate ? JSON.parse(viewInfo.arch.attrs.duplicate) : true,
|
||||
},
|
||||
noContentHelp: params.action && params.action.help,
|
||||
};
|
||||
|
||||
@@ -154,7 +154,7 @@ var FormController = BasicController.extend({
|
||||
callback: this._deleteRecords.bind(this, [this.handle]),
|
||||
});
|
||||
}
|
||||
if (this.is_action_enabled('create')) {
|
||||
if (this.is_action_enabled('create') && this.is_action_enabled('duplicate')) {
|
||||
otherItems.push({
|
||||
label: _t('Duplicate'),
|
||||
callback: this._onDuplicateRecord.bind(this),
|
||||
|
||||
@@ -1421,6 +1421,33 @@ QUnit.module('Views', {
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('cannot duplicate a record', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners" duplicate="false">' +
|
||||
'<field name="foo"/>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
viewOptions: {sidebar: true},
|
||||
mockRPC: function (route, args) {
|
||||
if (args.method === 'search_read' && args.model === 'ir.attachment') {
|
||||
return $.when([]);
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(form.get('title'), 'first record',
|
||||
"should have the display name of the record as title");
|
||||
assert.ok(form.sidebar.$('a:contains(Duplicate)').length === 0,
|
||||
"should not contains a 'Duplicate' action");
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('buttons in footer are moved to $buttons if necessary', function (assert) {
|
||||
// not sure about this test...
|
||||
assert.expect(2);
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
<record id="view_model_fields_form" model="ir.ui.view">
|
||||
<field name="model">ir.model.fields</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Fields">
|
||||
<form string="Fields" duplicate="false">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
@@ -327,7 +327,7 @@
|
||||
<record id="view_model_fields_tree" model="ir.ui.view">
|
||||
<field name="model">ir.model.fields</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Fields">
|
||||
<tree string="Fields" duplicate="false">
|
||||
<field name="name"/>
|
||||
<field name="field_description"/>
|
||||
<field name="model_id"/>
|
||||
|
||||
@@ -14,6 +14,19 @@ class Company(models.Model):
|
||||
_description = 'Companies'
|
||||
_order = 'sequence, name'
|
||||
|
||||
@api.multi
|
||||
def copy(self, default=None):
|
||||
"""
|
||||
Duplicating a company without specifying a partner duplicate the partner
|
||||
"""
|
||||
self.ensure_one()
|
||||
default = dict(default or {})
|
||||
if not default.get('name') and not default.get('partner_id'):
|
||||
copy_partner = self.partner_id.copy()
|
||||
default['partner_id'] = copy_partner.id
|
||||
default['name'] = copy_partner.name
|
||||
return super(Company, self).copy(default)
|
||||
|
||||
def _get_logo(self):
|
||||
return open(os.path.join(tools.config['root_path'], 'addons', 'base', 'res', 'res_company_logo.png'), 'rb') .read().encode('base64')
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ try:
|
||||
import configparser as ConfigParser
|
||||
except ImportError:
|
||||
import ConfigParser
|
||||
|
||||
|
||||
import optparse
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user