diff --git a/addons/account/wizard/wizard_tax_adjustments.py b/addons/account/wizard/wizard_tax_adjustments.py index 2f188b1abab..51f1936b93b 100644 --- a/addons/account/wizard/wizard_tax_adjustments.py +++ b/addons/account/wizard/wizard_tax_adjustments.py @@ -18,7 +18,7 @@ class TaxAdjustments(models.TransientModel): debit_account_id = fields.Many2one('account.account', string='Debit account', required=True, domain=[('deprecated', '=', False)]) credit_account_id = fields.Many2one('account.account', string='Credit account', required=True, domain=[('deprecated', '=', False)]) amount = fields.Monetary(currency_field='company_currency_id', required=True) - adjustment_type = fields.Selection([('debit', 'Adjustment in favor of the Estate'), ('credit', 'Adjustment in your favor')], string="Adjustment Type", store=False, required=True) + adjustment_type = fields.Selection([('debit', 'Applied on debit journal item'), ('credit', 'Applied on credit journal item')], string="Adjustment Type", store=False, required=True) company_currency_id = fields.Many2one('res.currency', readonly=True, default=lambda self: self.env.user.company_id.currency_id) tax_id = fields.Many2one('account.tax', string='Adjustment Tax', ondelete='restrict', domain=[('type_tax_use', '=', 'adjustment')], required=True) diff --git a/addons/account_payment/models/payment.py b/addons/account_payment/models/payment.py index 389cfa206e1..cfc90258289 100644 --- a/addons/account_payment/models/payment.py +++ b/addons/account_payment/models/payment.py @@ -159,7 +159,7 @@ class PaymentTransaction(models.Model): 'currency_id': invoice.currency_id.id, 'partner_id': invoice.partner_id.id, 'partner_country_id': invoice.partner_id.country_id.id, - 'reference': self.get_next_reference(invoice.number), + 'reference': self._get_next_reference(invoice.number, acquirer=acquirer), 'account_invoice_id': invoice.id, } if add_tx_values: diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index f6dd0fbb9d8..b2ffaf67231 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -96,9 +96,10 @@ class SaleOrder(models.Model): taxes_ids = self.fiscal_position_id.map_tax(taxes, carrier.product_id, self.partner_id).ids # Create the sales order line + carrier_name = carrier.product_id.with_context(lang=self.partner_id.lang).name_get()[0][1] values = { 'order_id': self.id, - 'name': carrier.name, + 'name': carrier_name, 'product_uom_qty': 1, 'product_uom': carrier.product_id.uom_id.id, 'product_id': carrier.product_id.id, diff --git a/addons/event/security/ir.model.access.csv b/addons/event/security/ir.model.access.csv index 49d859ad183..ed7ec0e0cc6 100644 --- a/addons/event/security/ir.model.access.csv +++ b/addons/event/security/ir.model.access.csv @@ -5,7 +5,7 @@ access_event_event_portal,event.event.portal,model_event_event,,1,0,0,0 access_event_event_user,event.event.user,model_event_event,event.group_event_user,1,0,0,0 access_event_event_manager,event.event.manager,model_event_event,event.group_event_manager,1,1,1,1 access_event_registration,event.registration,model_event_registration,event.group_event_user,1,1,1,1 -access_event_registration_portal,event.registration,model_event_registration,,1,0,0,0 +access_event_registration_portal,event.registration,model_event_registration,,0,0,0,0 access_event_mail,event.mail,model_event_mail,event.group_event_user,1,0,0,0 access_event_mail_manager,event.mail manager,model_event_mail,event.group_event_manager,1,1,1,1 access_event_mail_registration,event.mail.registration,model_event_mail_registration,event.group_event_user,1,0,0,0 diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py index 7a2dcd8a745..6902d8e4743 100644 --- a/addons/event_sale/models/sale_order.py +++ b/addons/event_sale/models/sale_order.py @@ -41,7 +41,7 @@ class SaleOrderLine(models.Model): order line has a product_uom_qty attribute that will be the number of registrations linked to this line. This method update existing registrations and create new one for missing one. """ - Registration = self.env['event.registration'] + Registration = self.env['event.registration'].sudo() registrations = Registration.search([('sale_order_line_id', 'in', self.ids), ('state', '!=', 'cancel')]) for so_line in self.filtered('event_id'): existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id) diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 9ea99dae38f..2ab11a91a82 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -85,11 +85,6 @@ class HolidaysRequest(models.Model): ('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."), ] - @api.onchange('employee_id') - def _onchange_employee_id(self): - self.manager_id = self.employee_id and self.employee_id.parent_id - self.department_id = self.employee_id.department_id - @api.multi @api.depends('number_of_days_temp') def _compute_number_of_days(self): @@ -121,7 +116,8 @@ class HolidaysRequest(models.Model): self.department_id = None @api.onchange('employee_id') - def _onchange_employee(self): + def _onchange_employee_id(self): + self.manager_id = self.employee_id and self.employee_id.parent_id if self.holiday_type == 'employee': self.department_id = self.employee_id.department_id diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 2d07a174a7e..abaf9ba0368 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -687,6 +687,10 @@ class PaymentTransaction(models.Model): @api.model def get_next_reference(self, reference): + return self._get_next_reference(reference) + + @api.model + def _get_next_reference(self, reference, acquirer=None): ref_suffix = 1 init_ref = reference while self.env['payment.transaction'].sudo().search_count([('reference', '=', reference)]): diff --git a/addons/payment_sips/models/payment.py b/addons/payment_sips/models/payment.py index bbbe64b3feb..874d88508e4 100644 --- a/addons/payment_sips/models/payment.py +++ b/addons/payment_sips/models/payment.py @@ -4,6 +4,7 @@ import json import logging +import re from hashlib import sha256 from werkzeug import urls @@ -111,6 +112,16 @@ class AcquirerSips(models.Model): return self.environment == 'prod' and self.sips_prod_url or self.sips_test_url +class PaymentTransactionSips(models.Model): + _inherit = 'payment.transaction' + + @api.model + def _get_next_reference(self, reference, acquirer=None): + if acquirer and acquirer.provider == 'sips': + reference = re.sub(r'[^0-9a-zA-Z]+', 'x' , reference) + return super(PaymentTransactionSips, self)._get_next_reference(reference, acquirer=acquirer) + + class TxSips(models.Model): _inherit = 'payment.transaction' diff --git a/addons/point_of_sale/models/product.py b/addons/point_of_sale/models/product.py index e1a85cd7c4a..1caded3870e 100644 --- a/addons/point_of_sale/models/product.py +++ b/addons/point_of_sale/models/product.py @@ -21,6 +21,11 @@ class ProductTemplate(models.Model): raise UserError(_('You cannot delete a product saleable in point of sale while a session is still opened.')) return super(ProductTemplate, self).unlink() + @api.onchange('sale_ok') + def _onchange_sale_ok(self): + if not self.sale_ok: + self.available_in_pos = False + class ProductUomCateg(models.Model): _inherit = 'product.uom.categ' diff --git a/addons/project/i18n/project.pot b/addons/project/i18n/project.pot index 5ed93bba242..ae8e38c46ce 100644 --- a/addons/project/i18n/project.pot +++ b/addons/project/i18n/project.pot @@ -1020,6 +1020,12 @@ msgstr "" msgid "Ending Date" msgstr "" +#. module: project +#: code:addons/project/models/project.py:556 +#, python-format +msgid "Error! You cannot create recursive hierarchy of task(s)." +msgstr "" + #. module: project #: sql_constraint:project.project:0 msgid "Error! project start-date must be lower than project end-date." diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 4ca2198b1fc..e02dcf8fac5 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -641,6 +641,12 @@ class Task(models.Model): default['remaining_hours'] = self.planned_hours return super(Task, self).copy(default) + @api.constrains('parent_id') + def _check_parent_id(self): + for task in self: + if not task._check_recursion(): + raise ValidationError(_('Error! You cannot create recursive hierarchy of task(s).')) + # Override view according to the company definition @api.model def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False): @@ -1002,6 +1008,20 @@ class Task(models.Model): 'type': 'ir.actions.act_window' } + def action_subtask(self): + action = self.env.ref('project.project_task_action_sub_task').read()[0] + ctx = self.env.context.copy() + ctx.update({ + 'default_parent_id': self.id, + 'default_project_id': self.env.context.get('project_id', self.project_id.id), + 'default_name': self.env.context.get('name', self.name) + ':', + 'default_partner_id': self.env.context.get('partner_id', self.partner_id.id), + 'search_default_project_id': self.env.context.get('project_id', self.project_id.id), + }) + action['context'] = ctx + action['domain'] = [('id', 'child_of', self.id), ('id', '!=', self.id)] + return action + # --------------------------------------------------- # Rating business # --------------------------------------------------- diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index dd3d3e18201..41dad0fef65 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -84,14 +84,6 @@ Sub-tasks project.task kanban,tree,form,calendar,pivot,graph - [('id', 'child_of', active_id), ('id', '!=', active_id)] - - { - 'default_parent_id' : active_id, - 'default_project_id' : project_id, - 'default_name' : name + ':', - } - @@ -424,7 +416,7 @@ - diff --git a/addons/purchase/models/account_invoice.py b/addons/purchase/models/account_invoice.py index 7f170d4e814..60659c5a7a2 100644 --- a/addons/purchase/models/account_invoice.py +++ b/addons/purchase/models/account_invoice.py @@ -167,7 +167,10 @@ class AccountInvoice(models.Model): #for average/fifo/lifo costing method, fetch real cost price from incomming moves valuation_price_unit = i_line.purchase_line_id.product_uom._compute_price(i_line.purchase_line_id.price_unit, i_line.uom_id) stock_move_obj = self.env['stock.move'] - valuation_stock_move = stock_move_obj.search([('purchase_line_id', '=', i_line.purchase_line_id.id), ('state', '=', 'done')]) + valuation_stock_move = stock_move_obj.search([ + ('purchase_line_id', '=', i_line.purchase_line_id.id), + ('state', '=', 'done'), ('product_qty', '!=', 0.0) + ]) if self.type == 'in_refund': valuation_stock_move = valuation_stock_move.filtered(lambda m: m._is_out()) elif self.type == 'in_invoice': diff --git a/addons/sale_payment/models/payment.py b/addons/sale_payment/models/payment.py index 831af37550f..f710b63630f 100644 --- a/addons/sale_payment/models/payment.py +++ b/addons/sale_payment/models/payment.py @@ -182,7 +182,7 @@ class PaymentTransaction(models.Model): 'currency_id': order.pricelist_id.currency_id.id, 'partner_id': order.partner_id.id, 'partner_country_id': order.partner_id.country_id.id, - 'reference': self.get_next_reference(order.name), + 'reference': self._get_next_reference(order.name, acquirer=acquirer), 'sale_order_id': order.id, } if add_tx_values: diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 2f5f2171a27..77d7304df12 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1116,7 +1116,7 @@ class Binary(http.Controller): if request.httprequest.user_agent.browser == 'safari': # Safari sends NFD UTF-8 (where é is composed by 'e' and [accent]) # we need to send it the same stuff, otherwise it'll fail - filename = unicodedata.normalize('NFD', ufile.filename).encode('UTF-8') + filename = unicodedata.normalize('NFD', ufile.filename) try: attachment = Model.create({ diff --git a/addons/website_event_sale/controllers/main.py b/addons/website_event_sale/controllers/main.py index 7ccb7f9e4b5..d9af6bd312e 100644 --- a/addons/website_event_sale/controllers/main.py +++ b/addons/website_event_sale/controllers/main.py @@ -39,7 +39,7 @@ class WebsiteEventSaleController(WebsiteEventController): # free tickets -> order with amount = 0: auto-confirm, no checkout if not order.amount_total: order.action_confirm() # tde notsure: email sending ? - attendees = request.env['event.registration'].browse(list(attendee_ids)) + attendees = request.env['event.registration'].browse(list(attendee_ids)).sudo() # clean context and session, then redirect to the confirmation page request.website.sale_reset() return request.render("website_event.registration_complete", { diff --git a/addons/website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js b/addons/website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js index d5e7266930c..f313a37dfa3 100644 --- a/addons/website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js +++ b/addons/website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js @@ -147,12 +147,22 @@ var PDFSlidesViewer = (function(){ PDFSlidesViewer.prototype.toggleFullScreenFooter = function(){ if(document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) { - $('div#PDFViewer > div.navbar-fixed-bottom').toggleClass('oe_show_footer'); + var $navBarFooter = $('div#PDFViewer > div.navbar-fixed-bottom'); + $navBarFooter.toggleClass('oe_show_footer'); + + if ($navBarFooter.css('display') === 'none') { + $navBarFooter.css('display', 'block'); + $('div#PDFViewer').css('padding-bottom', '50px'); + } else { + $navBarFooter.css('display', 'none'); + $('div#PDFViewer').css('padding-bottom', '0'); + } } } PDFSlidesViewer.prototype.toggleFullScreen = function(){ - var el = this.canvas.parentNode; + // The canvas and the navigation bar needs to be fullscreened + var el = this.canvas.parentNode.parentNode; var isFullscreenAvailable = document.fullscreenEnabled || document.mozFullScreenEnabled || document.webkitFullscreenEnabled || document.msFullscreenEnabled || false; if(isFullscreenAvailable){ // Full screen supported