Skip to content
Permalink
Browse files

[MERGE] forward port branch 11.0 up to de8cefc

  • Loading branch information...
KangOl committed Feb 20, 2019
2 parents 716a272 + de8cefc commit f1ff55bca1242af86cd5feedbf7c4793b96174a1
Showing with 459 additions and 199 deletions.
  1. +140 −129 addons/account/models/account_move.py
  2. +2 −2 addons/account/static/src/js/reconciliation/reconciliation_model.js
  3. +0 −1 addons/account/views/res_config_settings_views.xml
  4. +32 −1 addons/account_voucher/models/account_voucher.py
  5. +2 −2 addons/auth_signup/models/res_partner.py
  6. +0 −3 addons/base_automation/views/base_automation_view.xml
  7. +1 −0 addons/base_import_module/views/base_import_module_view.xml
  8. +0 −2 addons/crm/views/crm_lead_views.xml
  9. +3 −1 addons/google_calendar/models/google_calendar.py
  10. +1 −1 addons/hr_holidays/models/hr_leave.py
  11. +4 −1 addons/hr_holidays/models/hr_leave_type.py
  12. +1 −0 addons/im_livechat/models/im_livechat_channel.py
  13. +1 −1 addons/l10n_it/__manifest__.py
  14. +4 −0 addons/l10n_mx/data/account_data.xml
  15. +34 −0 addons/l10n_mx/data/account_tax_data.xml
  16. +6 −0 addons/mass_mailing/models/mass_mailing.py
  17. +4 −6 addons/point_of_sale/models/pos_order.py
  18. +4 −2 addons/point_of_sale/static/src/js/gui.js
  19. +1 −1 addons/sale_crm/models/crm_lead.py
  20. +1 −1 addons/sale_timesheet/models/account.py
  21. +3 −1 addons/stock/models/product.py
  22. +3 −6 addons/stock/report/report_deliveryslip.xml
  23. +2 −5 addons/stock/views/stock_picking_views.xml
  24. +1 −1 addons/web/static/src/js/chrome/search_filters.js
  25. +4 −2 addons/web/static/src/js/views/pivot/pivot_model.js
  26. +89 −0 addons/web/static/tests/views/pivot_tests.js
  27. +4 −2 addons/website_sale_delivery/static/src/js/website_sale_delivery.js
  28. +2 −1 doc/cla/corporate/invitu.md
  29. +11 −0 doc/cla/individual/naglis.md
  30. +32 −0 doc/reference/reports.rst
  31. +10 −0 odoo/addons/test_new_api/tests/test_new_fields.py
  32. +8 −3 odoo/api.py
  33. +12 −4 odoo/fields.py
  34. +37 −20 odoo/models.py

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -885,11 +885,11 @@ var StatementModel = BasicModel.extend({
});
var company_currency = session.get_currency(line.st_line.currency_id);
var company_precision = company_currency && company_currency.digits[1] || 2;
total = utils.round_precision(total*1000, company_precision)/1000 || 0;
total = utils.round_decimals(total, company_precision) || 0;
if(isOtherCurrencyId){
var other_currency = session.get_currency(isOtherCurrencyId);
var other_precision = other_currency && other_currency.digits[1] || 2;
amount_currency = utils.round_precision(amount_currency, other_precision)
amount_currency = utils.round_decimals(amount_currency, other_precision);
}
line.balance = {
amount: total,
@@ -97,7 +97,6 @@
</div>
<div class="o_setting_right_pane" name="account_taxcloud_right_pane">
<label for="module_account_taxcloud" string="TaxCloud"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." groups="base.group_multi_company"/>
<div class="text-muted">
Compute tax rates based on U.S. ZIP codes
</div>
@@ -274,6 +274,8 @@ def voucher_move_line_create(self, line_total, move_id, company_currency, curren
:return: Tuple build as (remaining amount not allocated on voucher lines, list of account_move_line created in this method)
:rtype: tuple(float, list of int)
'''
tax_calculation_rounding_method = self.env.user.company_id.tax_calculation_rounding_method
tax_lines_vals = []
for line in self.line_ids:
#create one move line per voucher line where amount is not 0.0
if not line.price_subtotal:
@@ -302,7 +304,36 @@ def voucher_move_line_create(self, line_total, move_id, company_currency, curren
'currency_id': company_currency != current_currency and current_currency or False,
'payment_id': self._context.get('payment_id'),
}
self.env['account.move.line'].with_context(apply_taxes=True).create(move_line)
# When global rounding is activated, we must wait until all tax lines are computed to
# merge them.
if tax_calculation_rounding_method == 'round_globally':
self.env['account.move.line'].create(move_line)
tax_lines_vals += self.env['account.move.line'].with_context(round=False)._apply_taxes(
move_line,
move_line.get('debit', 0.0) - move_line.get('credit', 0.0)
)
else:
self.env['account.move.line'].with_context(apply_taxes=True).create(move_line)

# When round globally is set, we merge the tax lines
if tax_calculation_rounding_method == 'round_globally':
tax_lines_vals_merged = {}
for tax_line_vals in tax_lines_vals:
key = (
tax_line_vals['tax_line_id'],
tax_line_vals['account_id'],
tax_line_vals['analytic_account_id'],
)
if key not in tax_lines_vals_merged:
tax_lines_vals_merged[key] = tax_line_vals
else:
tax_lines_vals_merged[key]['debit'] += tax_line_vals['debit']
tax_lines_vals_merged[key]['credit'] += tax_line_vals['credit']
currency = self.env['res.currency'].browse(company_currency)
for vals in tax_lines_vals_merged.values():
vals['debit'] = currency.round(vals['debit'])
vals['credit'] = currency.round(vals['credit'])
self.env['account.move.line'].create(vals)
return line_total

@api.multi
@@ -28,14 +28,14 @@ class ResPartner(models.Model):
signup_token = fields.Char(copy=False, groups="base.group_erp_manager")
signup_type = fields.Char(string='Signup Token Type', copy=False, groups="base.group_erp_manager")
signup_expiration = fields.Datetime(copy=False, groups="base.group_erp_manager")
signup_valid = fields.Boolean(compute='_compute_signup_valid', string='Signup Token is Valid')
signup_valid = fields.Boolean(compute='_compute_signup_valid', compute_sudo=True, string='Signup Token is Valid')
signup_url = fields.Char(compute='_compute_signup_url', string='Signup URL')

@api.multi
@api.depends('signup_token', 'signup_expiration')
def _compute_signup_valid(self):
dt = now()
for partner in self.sudo():
for partner in self:
partner.signup_valid = bool(partner.signup_token) and \
(not partner.signup_expiration or dt <= partner.signup_expiration)

@@ -11,9 +11,6 @@
<xpath expr="//button[@name='create_action']" position="replace">
</xpath>
<xpath expr="//button[@name='unlink_action']" position="replace">
<button name="unlink_action_for_menu" string="Remove Action" type="object"
attrs="{'invisible':[('binding_model_id','=',False)]}"
help="Remove the contextual action related to this server action"/>
</xpath>
<div class="oe_title" position="before">
<div class="oe_button_box" name="button_box">
@@ -8,6 +8,7 @@
<form string="Import module">
<field name="state" invisible="1"/>
<separator string="Import Module" colspan="4"/>
<p class="alert alert-warning">Note: you can only import data modules (.xml files and static assets)</p>
<group states="init" col="4">
<label string="Select module package to import (.zip file):" colspan="4"/>
<field name="module_file" colspan="4"/>
@@ -865,7 +865,6 @@ for rec in records:
<field name="domain">[('type','=','opportunity')]</field>
<field name="context">{
'default_type': 'opportunity',
'default_user_id': uid
}
</field>
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
@@ -906,7 +905,6 @@ for rec in records:
<field name="domain">[('type','=','opportunity')]</field>
<field name="context">{
'default_type': 'opportunity',
'default_user_id': uid,
'search_default_assigned_to_me': 1,
}</field>
<field name="view_ids"
@@ -441,7 +441,9 @@ def update_from_google(self, event, single_event_dict, type):
if google_attendee.get('found'):
continue

attendee = ResPartner.search([('email', '=', google_attendee['email'])], limit=1)
attendee = ResPartner.search([('email', '=ilike', google_attendee['email']), ('user_ids', '!=', False)], limit=1)
if not attendee:
attendee = ResPartner.search([('email', '=ilike', google_attendee['email'])], limit=1)
if not attendee:
data = {
'email': partner_email,
@@ -9,7 +9,7 @@

from odoo import api, fields, models
from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.tools import float_compare
from odoo.tools import float_compare, float_round
from odoo.tools.translate import _

from odoo.addons.resource.models.resource import HOURS_PER_DAY
@@ -176,7 +176,10 @@ def name_get(self):
if not record.limit:
name = "%(name)s (%(count)s)" % {
'name': name,
'count': _('%g remaining out of %g') % (record.virtual_remaining_leaves or 0.0, record.max_leaves or 0.0)
'count': _('%g remaining out of %g') % (
float_round(record.virtual_remaining_leaves or 0.0, precision_digits=2) + 0.0,
record.max_leaves or 0.0
)
}
res.append((record.id, name))
return res
@@ -177,6 +177,7 @@ def get_mail_channel(self, livechat_channel_id, anonymous_name):
'public': 'private',
'email_send': False,
})
mail_channel._broadcast([operator_partner_id])
return mail_channel.sudo().with_context(im_livechat_operator_partner_id=operator_partner_id).channel_info()[0]

@api.model
@@ -17,7 +17,7 @@
Italian accounting chart and localization.
""",
'category': 'Localization',
'website': 'http://www.openerp-italia.org/',
'website': 'http://www.odoo.com/',
'data': [
'data/l10n_it_chart_data.xml',
'data/account.account.template.csv',
@@ -11,6 +11,10 @@
<field name="name">IVA 16% </field>
</record>

<record id="tax_group_iva_8" model="account.tax.group">
<field name="name">IVA 8%</field>
</record>

<record id="tax_group_iva_ret_4" model="account.tax.group">
<field name="name">IVA Retencion 4%</field>
</record>
@@ -30,6 +30,10 @@
<field name="name">DIOT: 0%</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_diot_8" model="account.account.tag">
<field name="name">DIOT: 8%</field>
<field name="applicability">taxes</field>
</record>
<record id="tag_diot_ret" model="account.account.tag">
<field name="name">DIOT: Retención</field>
<field name="applicability">taxes</field>
@@ -182,5 +186,35 @@
<field name="cash_basis_account_id" ref="cuenta118_01"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_diot_16')])]"/>
</record>

<record id="tax16" model="account.tax.template">
<field name="chart_template_id" ref="mx_coa"/>
<field name="name">IVA(8%) COMPRAS</field>
<field name="description">IVA(8%)</field>
<field name="amount">8</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="cuenta119_01"/>
<field name="refund_account_id" ref="cuenta119_01"/>
<field name="tax_group_id" ref="tax_group_iva_8"/>
<field name="tax_exigibility">on_payment</field>
<field name="cash_basis_account" ref="cuenta118_01"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_diot_8')])]"/>
</record>

<record id="tax17" model="account.tax.template">
<field name="chart_template_id" ref="mx_coa"/>
<field name="name">IVA(8%) VENTAS</field>
<field name="description">IVA(8%)</field>
<field name="amount">8</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">sale</field>
<field name="account_id" ref="cuenta209_01"/>
<field name="refund_account_id" ref="cuenta209_01"/>
<field name="tag_ids" eval="[(6,0,[ref('tag_iva')])]"/>
<field name="tax_group_id" ref="tax_group_iva_8"/>
<field name="tax_exigibility">on_payment</field>
<field name="cash_basis_account" ref="cuenta208_01"/>
</record>
</data>
</odoo>
@@ -610,6 +610,12 @@ def retry_failed_mail(self):
failed_mails = self.env['mail.mail'].search([('mailing_id', 'in', self.ids), ('state', '=', 'exception')])
failed_mails.mapped('statistics_ids').unlink()
failed_mails.sudo().unlink()
res_ids = self.get_recipients()
except_mailed = self.env['mail.mail.statistics'].search([
('model', '=', self.mailing_model_real),
('res_id', 'in', res_ids),
('exception', '!=', False),
('mass_mailing_id', '=', self.id)]).unlink()
self.write({'state': 'in_queue'})

#------------------------------------------------------
@@ -487,13 +487,11 @@ def _reconcile_payments(self):
aml = order.statement_ids.mapped('journal_entry_ids') | order.account_move.line_ids | order.invoice_id.move_id.line_ids
aml = aml.filtered(lambda r: not r.reconciled and r.account_id.internal_type == 'receivable' and r.partner_id == order.partner_id.commercial_partner_id)

# Reconcile returns first
# to avoid mixing up the credit of a payment and the credit of a return
# in the receivable account
aml_returns = aml.filtered(lambda l: (l.journal_id.type == 'sale' and l.credit) or (l.journal_id.type != 'sale' and l.debit))
try:
aml_returns.reconcile()
(aml - aml_returns).reconcile()
# Cash returns will be well reconciled
# Whereas freight returns won't be
# "c'est la vie..."
aml.reconcile()
except Exception:
# There might be unexpected situations where the automatic reconciliation won't
# work. We don't want the user to be blocked because of this, since the automatic
@@ -437,7 +437,7 @@ var Gui = core.Class.extend({
numpad_input: function(buffer, input, options) {
var newbuf = buffer.slice(0);
options = options || {};
var newbuf_float = field_utils.parse.float(newbuf);
var newbuf_float = newbuf === '-' ? newbuf : field_utils.parse.float(newbuf);
var decimal_point = _t.database.parameters.decimal_point;

if (input === decimal_point) {
@@ -457,7 +457,9 @@ var Gui = core.Class.extend({
newbuf = newbuf.substring(1,newbuf.length);
}
} else if (input === '-') {
if ( newbuf[0] === '-' ) {
if (options.firstinput) {
newbuf = '-';
} else if ( newbuf[0] === '-' ) {
newbuf = newbuf.substring(1,newbuf.length);
} else {
newbuf = '-' + newbuf;
@@ -20,7 +20,7 @@ def _compute_sale_amount_total(self):
nbr = 0
company_currency = lead.company_currency or self.env.user.company_id.currency_id
for order in lead.order_ids:
if order.state in ('draft', 'sent', 'sale'):
if order.state in ('draft', 'sent'):
nbr += 1
if order.state not in ('draft', 'sent', 'cancel'):
total += order.currency_id.compute(order.amount_untaxed, company_currency)
@@ -121,7 +121,7 @@ def _timesheet_compute_theorical_revenue_values(self):
total_revenue_invoiced = sum(analytic_lines.mapped('timesheet_revenue'))
# compute (new) revenue of current timesheet line
values['timesheet_revenue'] = min(
analytic_account.currency_id.round(unit_amount * so_line.currency_id.compute(so_line.price_unit, analytic_account.currency_id) * (1-so_line.discount)),
analytic_account.currency_id.round(unit_amount * sale_price * (1-so_line.discount/100)),
total_revenue_so - total_revenue_invoiced
)
values['timesheet_invoice_type'] = 'billable_fixed'
@@ -257,7 +257,9 @@ def _search_product_quantity(self, operator, value, field):

# TODO: Still optimization possible when searching virtual quantities
ids = []
for product in self.with_context(prefetch_fields=False).search([]):
# Order the search on `id` to prevent the default order on the product name which slows
# down the search because of the join on the translation table to get the translated names.
for product in self.with_context(prefetch_fields=False).search([], order='id'):
if OPERATORS[operator](product[field], value):
ids.append(product.id)
return [('id', 'in', ids)]
@@ -11,12 +11,9 @@
<div>
<span><strong>Customer Address:</strong></span>
</div>
<div t-if="o.move_lines and o.move_lines[0].partner_id" name="partner_header">
<div t-field="o.move_lines[0].partner_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True}'/>
</div>
<div t-if="not (o.move_lines and o.move_lines[0].partner_id) and o.partner_id" name="partner_header">
<div t-field="o.partner_id"
<t t-set="partner" t-value="o.partner_id or (o.move_lines and o.move_lines[0].partner_id) or False"/>
<div t-if="partner" name="partner_header">
<div t-esc="partner"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True}'/>
</div>
</div>
@@ -240,11 +240,8 @@
<group>
<group>
<field name="partner_id" attrs="{'invisible': [('picking_type_code', '=', 'internal')]}"/>
<button name="action_assign_partner" string="Assign Partner" type="object" help="Assign the partner to the Operations. Use only if the partner is manually changed!"
attrs="{'invisible': ['|', '|', ('move_line_exist', '=', False), ('state', 'not in', ('draft', 'assigned', 'confirmed')), ('picking_type_code', '=', 'internal')]}"
class="oe_link oe_edit_only"/>
<field name="location_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'incoming')]}"/>
<field name="location_dest_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}"/>
<field name="location_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'incoming')]}" domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]"/>
<field name="location_dest_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}" domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]"/>
<field name="backorder_id" readonly="1" attrs="{'invisible': [('backorder_id','=',False)]}"/>
</group>
<group>
@@ -238,7 +238,7 @@ var DateTime = Field.extend({
_create_new_widget: function (name) {
this[name] = new (this._get_widget_class())(this);
return this[name].appendTo(this.$el).then((function () {
this[name].setValue(moment(new Date()));
this[name].setValue(moment());
}).bind(this));
},
_get_widget_class: function () {
@@ -294,8 +294,10 @@ var PivotModel = AbstractModel.extend({
self._updateMainGroupBys(old_row, self.data.main_row);
}

self._updateTree(old_col.root, self.data.main_col.root);
self._updateMainGroupBys(old_col, self.data.main_col);
if (!('pivot_column_groupby' in (params.context || {}))) {
self._updateTree(old_col.root, self.data.main_col.root);
self._updateMainGroupBys(old_col, self.data.main_col);
}
});
},
/**
Oops, something went wrong.

0 comments on commit f1ff55b

Please sign in to comment.
You can’t perform that action at this time.