diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index e5e13b33830..28fb8756616 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1107,7 +1107,7 @@ class AccountInvoiceLine(models.Model): default=0.0) invoice_line_tax_ids = fields.Many2many('account.tax', 'account_invoice_line_tax', 'invoice_line_id', 'tax_id', - string='Taxes', domain=[('type_tax_use','!=','none')], oldname='invoice_line_tax_id') + string='Taxes', domain=[('type_tax_use','!=','none'), '|', ('active', '=', False), ('active', '=', True)], oldname='invoice_line_tax_id') account_analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account') company_id = fields.Many2one('res.company', string='Company', diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py index 749e3ec3289..e008e3d2d26 100644 --- a/addons/account_asset/account_asset.py +++ b/addons/account_asset/account_asset.py @@ -154,7 +154,7 @@ class AccountAssetAsset(models.Model): def compute_depreciation_board(self): self.ensure_one() - posted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: x.move_check) + posted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: x.move_check).sorted(key=lambda l: l.depreciation_date, reverse=True) unposted_depreciation_line_ids = self.depreciation_line_ids.filtered(lambda x: not x.move_check) # Remove old unposted depreciation lines. We cannot use unlink() with One2many field diff --git a/addons/crm/crm_action_rule_demo.xml b/addons/crm/crm_action_rule_demo.xml index e7f05dca512..ff83639703a 100644 --- a/addons/crm/crm_action_rule_demo.xml +++ b/addons/crm/crm_action_rule_demo.xml @@ -22,7 +22,7 @@ 1 on_time [('stage_id.sequence', '=', 1)] - + 5 day diff --git a/addons/gamification_sale_crm/sale_crm_goals.xml b/addons/gamification_sale_crm/sale_crm_goals.xml index 684d2a51844..40e90cfa1a7 100644 --- a/addons/gamification_sale_crm/sale_crm_goals.xml +++ b/addons/gamification_sale_crm/sale_crm_goals.xml @@ -20,7 +20,7 @@ count leads - + [('user_id','=',user.id), '|', ('type', '=', 'lead'), ('type', '=', 'opportunity')] diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py index 16994c3ced6..cedce7f97f1 100644 --- a/addons/mrp_repair/mrp_repair.py +++ b/addons/mrp_repair/mrp_repair.py @@ -562,7 +562,8 @@ class mrp_repair_line(osv.osv, ProductChangeMixin): 'invoiced': fields.boolean('Invoiced', readonly=True, copy=False), 'price_unit': fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Product Price')), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits=0), - 'tax_id': fields.many2many('account.tax', 'repair_operation_line_tax', 'repair_operation_line_id', 'tax_id', 'Taxes'), + 'tax_id': fields.many2many('account.tax', 'repair_operation_line_tax', 'repair_operation_line_id', 'tax_id', 'Taxes', + domain=['|', ('active', '=', False), ('active', '=', True)]), 'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', readonly=True, copy=False), @@ -656,7 +657,8 @@ class mrp_repair_fee(osv.osv, ProductChangeMixin): 'price_unit': fields.float('Unit Price', required=True), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits=0), - 'tax_id': fields.many2many('account.tax', 'repair_fee_line_tax', 'repair_fee_line_id', 'tax_id', 'Taxes'), + 'tax_id': fields.many2many('account.tax', 'repair_fee_line_tax', 'repair_fee_line_id', 'tax_id', 'Taxes', + domain=['|', ('active', '=', False), ('active', '=', True)]), 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', readonly=True, copy=False), 'to_invoice': fields.boolean('To Invoice'), 'invoiced': fields.boolean('Invoiced', readonly=True, copy=False), diff --git a/addons/payment_ogone/models/ogone.py b/addons/payment_ogone/models/ogone.py index b1a90b64bf7..585ad5a09ba 100644 --- a/addons/payment_ogone/models/ogone.py +++ b/addons/payment_ogone/models/ogone.py @@ -129,6 +129,7 @@ class PaymentAcquirerOgone(osv.Model): 'NCERRORED', 'ORDERID', 'PAYID', + 'PAYIDSUB', 'PM', 'SCO_CATEGORY', 'SCORING', diff --git a/addons/point_of_sale/report/pos_details.py b/addons/point_of_sale/report/pos_details.py index 3e77f35a027..5107c26dc78 100644 --- a/addons/point_of_sale/report/pos_details.py +++ b/addons/point_of_sale/report/pos_details.py @@ -24,6 +24,19 @@ class pos_details(report_sxw.rml_parse): user_obj = self.pool.get('res.users') return user_obj.search(self.cr, self.uid, []) + def _get_utc_time_range(self, form): + user = self.pool['res.users'].browse(self.cr, self.uid, self.uid) + tz_name = user.tz or self.localcontext.get('tz') or 'UTC' + user_tz = pytz.timezone(tz_name) + between_dates = {} + + for date_field, delta in {'date_start': {'days': 0}, 'date_end': {'days': 1}}.items(): + timestamp = datetime.datetime.strptime(form[date_field] + ' 00:00:00', tools.DEFAULT_SERVER_DATETIME_FORMAT) + datetime.timedelta(**delta) + timestamp = user_tz.localize(timestamp).astimezone(pytz.utc) + between_dates[date_field] = timestamp.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + + return between_dates['date_start'], between_dates['date_end'] + def _pos_sales_details(self, form): pos_obj = self.pool.get('pos.order') user_obj = self.pool.get('res.users') @@ -31,18 +44,11 @@ class pos_details(report_sxw.rml_parse): result = {} user_ids = form['user_ids'] or self._get_all_users() company_id = user_obj.browse(self.cr, self.uid, self.uid).company_id.id - user = self.pool['res.users'].browse(self.cr, self.uid, self.uid) - tz_name = user.tz or self.localcontext.get('tz') or 'UTC' - user_tz = pytz.timezone(tz_name) - between_dates = {} - for date_field, delta in {'date_start': {'days': 0}, 'date_end': {'days': 1}}.items(): - timestamp = datetime.datetime.strptime(form[date_field] + ' 00:00:00', tools.DEFAULT_SERVER_DATETIME_FORMAT) + datetime.timedelta(**delta) - timestamp = user_tz.localize(timestamp).astimezone(pytz.utc) - between_dates[date_field] = timestamp.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + date_start, date_end = self._get_utc_time_range(form) pos_ids = pos_obj.search(self.cr, self.uid, [ - ('date_order', '>=', between_dates['date_start']), - ('date_order', '<', between_dates['date_end']), + ('date_order', '>=', date_start), + ('date_order', '<', date_end), ('user_id', 'in', user_ids), ('state', 'in', ['done', 'paid', 'invoiced']), ('company_id', '=', company_id) @@ -81,7 +87,8 @@ class pos_details(report_sxw.rml_parse): user_obj = self.pool.get('res.users') user_ids = form['user_ids'] or self._get_all_users() company_id = user_obj.browse(self.cr, self.uid, self.uid).company_id.id - pos_ids = pos_obj.search(self.cr, self.uid, [('date_order','>=',form['date_start'] + ' 00:00:00'),('date_order','<=',form['date_end'] + ' 23:59:59'),('user_id','in',user_ids),('company_id','=',company_id),('invoice_id','<>',False)]) + date_start, date_end = self._get_utc_time_range(form) + pos_ids = pos_obj.search(self.cr, self.uid, [('date_order','>=', date_start),('date_order','<=',date_end),('user_id','in',user_ids),('company_id','=',company_id),('invoice_id','<>',False)]) for pos in pos_obj.browse(self.cr, self.uid, pos_ids): for pol in pos.lines: self.total_invoiced += (pol.price_unit * pol.qty * (1 - (pol.discount) / 100.0)) @@ -99,7 +106,8 @@ class pos_details(report_sxw.rml_parse): user_obj = self.pool.get('res.users') user_ids = form['user_ids'] or self._get_all_users() company_id = user_obj.browse(self.cr, self.uid, self.uid).company_id.id - pos_ids = pos_obj.search(self.cr, self.uid, [('date_order','>=',form['date_start'] + ' 00:00:00'),('date_order','<=',form['date_end'] + ' 23:59:59'),('user_id','in',user_ids),('company_id','=',company_id)]) + date_start, date_end = self._get_utc_time_range(form) + pos_ids = pos_obj.search(self.cr, self.uid, [('date_order','>=',date_start),('date_order','<=',date_end),('user_id','in',user_ids),('company_id','=',company_id)]) for pos in pos_obj.browse(self.cr, self.uid, pos_ids): for pol in pos.lines: self.total_discount += ((pol.price_unit * pol.qty) * (pol.discount / 100)) @@ -110,7 +118,8 @@ class pos_details(report_sxw.rml_parse): pos_order_obj = self.pool.get("pos.order") user_ids = form['user_ids'] or self._get_all_users() company_id = self.pool['res.users'].browse(self.cr, self.uid, self.uid).company_id.id - pos_ids = pos_order_obj.search(self.cr, self.uid, [('date_order','>=',form['date_start'] + ' 00:00:00'),('date_order','<=',form['date_end'] + ' 23:59:59'),('state','in',['paid','invoiced','done']),('user_id','in',user_ids), ('company_id', '=', company_id)]) + date_start, date_end = self._get_utc_time_range(form) + pos_ids = pos_order_obj.search(self.cr, self.uid, [('date_order','>=',date_start),('date_order','<=',date_end),('state','in',['paid','invoiced','done']),('user_id','in',user_ids), ('company_id', '=', company_id)]) data={} if pos_ids: st_line_ids = statement_line_obj.search(self.cr, self.uid, [('pos_statement_id', 'in', pos_ids)]) @@ -153,7 +162,8 @@ class pos_details(report_sxw.rml_parse): user_ids = form['user_ids'] or self._get_all_users() pos_order_obj = self.pool.get('pos.order') company_id = self.pool['res.users'].browse(self.cr, self.uid, self.uid).company_id.id - pos_ids = pos_order_obj.search(self.cr, self.uid, [('date_order','>=',form['date_start'] + ' 00:00:00'),('date_order','<=',form['date_end'] + ' 23:59:59'),('state','in',['paid','invoiced','done']),('user_id','in',user_ids), ('company_id', '=', company_id)]) + date_start, date_end = self._get_utc_time_range(form) + pos_ids = pos_order_obj.search(self.cr, self.uid, [('date_order','>=',date_start),('date_order','<=',date_end),('state','in',['paid','invoiced','done']),('user_id','in',user_ids), ('company_id', '=', company_id)]) for order in pos_order_obj.browse(self.cr, self.uid, pos_ids): currency = order.session_id.currency_id for line in order.lines: diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 50fcd79c8dc..ad5cbf7907d 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1662,8 +1662,6 @@ exports.Order = Backbone.Model.extend({ client: client ? client.name : null , invoice_id: null, //TODO cashier: cashier ? cashier.name : null, - header: this.pos.config.receipt_header || '', - footer: this.pos.config.receipt_footer || '', precision: { price: 2, money: 2, @@ -1696,11 +1694,17 @@ exports.Order = Backbone.Model.extend({ }; if (is_xml(this.pos.config.receipt_header)){ + receipt.header = ''; receipt.header_xml = render_xml(this.pos.config.receipt_header); + } else { + receipt.header = this.pos.config.receipt_header || ''; } if (is_xml(this.pos.config.receipt_footer)){ + receipt.footer = ''; receipt.footer_xml = render_xml(this.pos.config.receipt_footer); + } else { + receipt.footer = this.pos.config.receipt_footer || ''; } return receipt; diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 0a31e36a896..007d410bcf3 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -514,7 +514,7 @@ class PurchaseOrderLine(models.Model): name = fields.Text(string='Description', required=True) product_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product Unit of Measure'), required=True) date_planned = fields.Datetime(string='Scheduled Date', required=True, select=True) - taxes_id = fields.Many2many('account.tax', string='Taxes') + taxes_id = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)]) product_uom = fields.Many2one('product.uom', string='Product Unit of Measure', required=True) product_id = fields.Many2one('product.product', string='Product', domain=[('purchase_ok', '=', True)], change_default=True, required=True) move_ids = fields.One2many('stock.move', 'purchase_line_id', string='Reservation', readonly=True, ondelete='set null', copy=False) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index c25eff9f74c..d5ec1833bab 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -652,7 +652,7 @@ class SaleOrderLine(models.Model): price_total = fields.Monetary(compute='_compute_amount', string='Total', readonly=True, store=True) price_reduce = fields.Monetary(compute='_get_price_reduce', string='Price Reduce', readonly=True, store=True) - tax_id = fields.Many2many('account.tax', string='Taxes') + tax_id = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)]) discount = fields.Float(string='Discount (%)', digits=dp.get_precision('Discount'), default=0.0) diff --git a/addons/web/static/src/js/views/graph_widget.js b/addons/web/static/src/js/views/graph_widget.js index e458cc483ed..599899dd32f 100644 --- a/addons/web/static/src/js/views/graph_widget.js +++ b/addons/web/static/src/js/views/graph_widget.js @@ -164,7 +164,7 @@ return Widget.extend({ var chart = nv.models.multiBarChart(); var maxVal = _.max(values, function(v) {return v.y}) chart.options({ - margin: {left: 12 * String(maxVal && maxVal.y || 0).length}, + margin: {left: 12 * String(maxVal && maxVal.y || 10000000).length}, delay: 250, transition: 10, showLegend: _.size(data) <= MAX_LEGEND_LENGTH, @@ -296,7 +296,7 @@ return Widget.extend({ var chart = nv.models.lineChart(); var maxVal = _.max(values, function(v) {return v.y}) chart.options({ - margin: {left: 12 * String(maxVal && maxVal.y || 0).length, right: 50}, + margin: {left: 12 * String(maxVal && maxVal.y || 10000000).length, right: 50}, useInteractiveGuideline: true, showLegend: _.size(data) <= MAX_LEGEND_LENGTH, showXAxis: true, diff --git a/addons/website_mass_mailing/controllers/main.py b/addons/website_mass_mailing/controllers/main.py index 2a7596104a8..3deaedbf1cb 100644 --- a/addons/website_mass_mailing/controllers/main.py +++ b/addons/website_mass_mailing/controllers/main.py @@ -51,8 +51,12 @@ class MassMailController(MassMailController): def subscribe(self, list_id, email, **post): cr, uid, context = request.cr, request.uid, request.context Contacts = request.registry['mail.mass_mailing.contact'] + parsed_email = Contacts.get_name_email(email, context=context)[1] - contact_ids = Contacts.search_read(cr, SUPERUSER_ID, [('list_id', '=', int(list_id)), ('email', '=', email)], ['opt_out'], context=context) + contact_ids = Contacts.search_read( + cr, SUPERUSER_ID, + [('list_id', '=', int(list_id)), ('email', '=', parsed_email)], + ['opt_out'], context=context) if not contact_ids: Contacts.add_to_list(cr, SUPERUSER_ID, email, int(list_id), context=context) else: diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index c791cbdd2a5..d384c1d064d 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -132,6 +132,10 @@ class website_sale(http.Controller): for p in product.product_variant_ids] return attribute_value_ids + def _get_search_order(self, post): + # OrderBy will be parsed in orm and so no direct sql injection + return 'website_published desc,%s' % post.get('order', 'website_sequence desc') + @http.route(['/shop/change_pricelist/'], type='http', auth="public", website=True) def pricelist_change(self, pl_id, **post): if request.website.is_pricelist_available(pl_id.id, context=request.context): @@ -230,7 +234,7 @@ class website_sale(http.Controller): product_count = product_obj.search_count(cr, uid, domain, context=context) pager = request.website.pager(url=url, total=product_count, page=page, step=ppg, scope=7, url_args=post) - product_ids = product_obj.search(cr, uid, domain, limit=ppg, offset=pager['offset'], order='website_published desc, website_sequence desc', context=context) + product_ids = product_obj.search(cr, uid, domain, limit=ppg, offset=pager['offset'], order=self._get_search_order(post), context=context) products = product_obj.browse(cr, uid, product_ids, context=context) attributes_obj = request.registry['product.attribute'] diff --git a/addons/website_sale/data/demo.xml b/addons/website_sale/data/demo.xml index 6a94c31f0b1..9126fc0f167 100644 --- a/addons/website_sale/data/demo.xml +++ b/addons/website_sale/data/demo.xml @@ -781,6 +781,12 @@ Weight: 31 grams + + #FFFFFF + + + #000000 + diff --git a/doc/cla/corporate/AetnaSoftwares.md b/doc/cla/corporate/AetnaSoftwares.md new file mode 100644 index 00000000000..406727bfb04 --- /dev/null +++ b/doc/cla/corporate/AetnaSoftwares.md @@ -0,0 +1,13 @@ +France, 2016-05-30 + +Aetna Softwares. agrees to the terms of the Odoo Corporate Contributor License Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Olivier Oriol aetna.softwares@gmail.com https://github.com/aetna-softwares + +List of contributors: + +Olivier Oriol aetna.softwares@gmail.com https://github.com/aetna-softwares diff --git a/doc/cla/corporate/devcocolombia.md b/doc/cla/corporate/devcocolombia.md new file mode 100644 index 00000000000..3ef6e397168 --- /dev/null +++ b/doc/cla/corporate/devcocolombia.md @@ -0,0 +1,15 @@ +Colombia, 2016-04-20 + +DevCO Colombia agrees to the terms of the Odoo Corporate Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +David Arnold dar@devco.co https://github.com/blaggacao + +List of contributors: + +Juan Pablo Arias jpa@devco.co https://github.com/kurkop diff --git a/doc/cla/corporate/therp.md b/doc/cla/corporate/therp.md index 428ecb2b411..e9f7dfae3ba 100644 --- a/doc/cla/corporate/therp.md +++ b/doc/cla/corporate/therp.md @@ -1,5 +1,7 @@ Netherlands, 2015-03-09 +Updated 2016-05-27 + Therp BV agrees to the terms of the Odoo Corporate Contributor License Agreement v1.0. @@ -8,14 +10,12 @@ this declaration. Signed, -* Ronald Portier rportier@therp.nl https://github.com/nl66278 -* Stefan Rijnhart stefan@therp.nl https://github.com/stefanrijnhart +* Ronald Portier ronald@therp.nl https://github.com/nl66278 List of contributors: * Giovanni Capalbo giovanni@therp.nl https://github.com/gfcapalbo * Holger Brunn hbrunn@therp.nl https://github.com/hbrunn * Lara Freeke lfreeke@therp.nl https://github.com/lfreeke -* Ronald Portier rportier@therp.nl https://github.com/nl66278 -* Stefan Rijnhart stefan@therp.nl https://github.com/stefanrijnhart +* Ronald Portier ronald@therp.nl https://github.com/nl66278