diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-09-04 18:12:00 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-09-04 18:12:00 +0200 |
| commit | 3ff4feafd24bdbe8121f16e2c6aaea901204b3a8 (patch) | |
| tree | 7469ee4cfc69c3d27a273ff1dcd97cc7e2edf734 | |
| parent | c39ad11d443cb83891199a48e56af03e6fcdd786 (diff) | |
| parent | 4d4d75709dcd46ffa957a68fa2f884ec59042718 (diff) | |
[MERGE] forward port branch saas-15 up to 4d4d75709dc
| -rw-r--r-- | addons/crm/models/crm_lead.py | 2 | ||||
| -rw-r--r-- | addons/hr_attendance/models/hr_attendance.py | 2 | ||||
| -rw-r--r-- | addons/hr_expense/models/hr_expense.py | 11 | ||||
| -rw-r--r-- | addons/hr_expense/security/ir_rule.xml | 20 | ||||
| -rw-r--r-- | addons/l10n_fr/migrations/9.0.1.1/post-migrate_tags_on_taxes.py | 7 | ||||
| -rw-r--r-- | addons/l10n_fr/migrations/9.0.1.1/pre-set_tags_and_taxes_updatable.py | 7 | ||||
| -rw-r--r-- | addons/mrp/models/mrp_production.py | 1 | ||||
| -rw-r--r-- | addons/stock/models/stock_pack_operation.py | 11 | ||||
| -rw-r--r-- | addons/stock/report/report_deliveryslip.xml | 11 | ||||
| -rw-r--r-- | addons/website_sale/views/templates.xml | 10 | ||||
| -rw-r--r-- | addons/website_sale_delivery/static/src/js/website_sale_delivery.js | 8 | ||||
| -rw-r--r-- | odoo/addons/base/ir/ir_model.py | 4 | ||||
| -rw-r--r-- | odoo/tools/misc.py | 9 | ||||
| -rw-r--r-- | odoo/tools/sql.py | 2 |
14 files changed, 66 insertions, 39 deletions
diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index d48ef6e8cd9..da87d2edc0f 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -928,7 +928,7 @@ class Lead(models.Model): result['activity']['today'] += 1 if date.today() <= date_deadline <= date.today() + timedelta(days=7): result['activity']['next_7_days'] += 1 - if date_deadline < date.today(): + if date_deadline < date.today() and not opp.date_closed: result['activity']['overdue'] += 1 # Won in Opportunities if opp.date_closed and opp.stage_id.probability == 100: diff --git a/addons/hr_attendance/models/hr_attendance.py b/addons/hr_attendance/models/hr_attendance.py index c373bbe23f4..76d442a4b67 100644 --- a/addons/hr_attendance/models/hr_attendance.py +++ b/addons/hr_attendance/models/hr_attendance.py @@ -68,7 +68,7 @@ class HrAttendance(models.Model): ('check_in', '<=', attendance.check_in), ('id', '!=', attendance.id), ], order='check_in desc', limit=1) - if last_attendance_before_check_in and last_attendance_before_check_in.check_out and last_attendance_before_check_in.check_out >= attendance.check_in: + if last_attendance_before_check_in and last_attendance_before_check_in.check_out and last_attendance_before_check_in.check_out > attendance.check_in: raise exceptions.ValidationError(_("Cannot create new attendance record for %(empl_name)s, the employee was already checked in on %(datetime)s") % { 'empl_name': attendance.employee_id.name, 'datetime': fields.Datetime.to_string(fields.Datetime.context_timestamp(self, fields.Datetime.from_string(attendance.check_in))), diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index f2f1545a82e..e87be516e21 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -300,6 +300,13 @@ class HrExpense(models.Model): return account_move @api.multi + def unlink(self): + for expense in self: + if expense.state in ['done']: + raise UserError(_('You cannot delete a posted expense.')) + super(HrExpense, self).unlink() + + @api.multi def action_get_attachment_view(self): self.ensure_one() res = self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment') @@ -441,8 +448,8 @@ class HrExpenseSheet(models.Model): @api.multi def unlink(self): for expense in self: - if expense.state == "post": - raise UserError(_("You cannot delete a posted expense.")) + if expense.state in ['post', 'done']: + raise UserError(_('You cannot delete a posted or paid expense.')) super(HrExpenseSheet, self).unlink() @api.multi diff --git a/addons/hr_expense/security/ir_rule.xml b/addons/hr_expense/security/ir_rule.xml index e86d91211d8..61aba78d7ed 100644 --- a/addons/hr_expense/security/ir_rule.xml +++ b/addons/hr_expense/security/ir_rule.xml @@ -26,26 +26,6 @@ <field eval="True" name="global"/> <field name="domain_force">['|',('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field> </record> - <record id="hr_expense_report_prevent_unlink" model="ir.rule"> - <field name="name">Expense Report Prevent Delete Employee</field> - <field name="model_id" ref="model_hr_expense_sheet"/> - <field name="domain_force">[('state', '=', 'submit')]</field> - <field name="groups" eval="[(4, ref('base.group_user'))]"/> - <field name="perm_read" eval="False"/> - <field name="perm_write" eval="False"/> - <field name="perm_create" eval="False"/> - <field name="perm_unlink" eval="True"/> - </record> - <record id="hr_expense_report_auth_unlink" model="ir.rule"> - <field name="name">Expense Report Authorize Delete Officer</field> - <field name="model_id" ref="model_hr_expense_sheet"/> - <field name="domain_force">[(1, '=', 1)]</field> - <field name="groups" eval="[(4, ref('hr_expense.group_hr_expense_user'))]"/> - <field name="perm_read" eval="False"/> - <field name="perm_write" eval="False"/> - <field name="perm_create" eval="False"/> - <field name="perm_unlink" eval="True"/> - </record> </data> </odoo> diff --git a/addons/l10n_fr/migrations/9.0.1.1/post-migrate_tags_on_taxes.py b/addons/l10n_fr/migrations/9.0.1.1/post-migrate_tags_on_taxes.py new file mode 100644 index 00000000000..6f933404f1d --- /dev/null +++ b/addons/l10n_fr/migrations/9.0.1.1/post-migrate_tags_on_taxes.py @@ -0,0 +1,7 @@ +from openerp.modules.registry import RegistryManager + +def migrate(cr, version): + registry = RegistryManager.get(cr.dbname) + from openerp.addons.account.models.chart_template import migrate_tags_on_taxes + migrate_tags_on_taxes(cr, registry) + diff --git a/addons/l10n_fr/migrations/9.0.1.1/pre-set_tags_and_taxes_updatable.py b/addons/l10n_fr/migrations/9.0.1.1/pre-set_tags_and_taxes_updatable.py new file mode 100644 index 00000000000..586ae984b8c --- /dev/null +++ b/addons/l10n_fr/migrations/9.0.1.1/pre-set_tags_and_taxes_updatable.py @@ -0,0 +1,7 @@ +from openerp.modules.registry import RegistryManager + +def migrate(cr, version): + registry = RegistryManager.get(cr.dbname) + from openerp.addons.account.models.chart_template import migrate_set_tags_and_taxes_updatable + migrate_set_tags_and_taxes_updatable(cr, registry, 'l10n_fr') + diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 1f59087a2c2..bfc48ef2072 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -340,6 +340,7 @@ class MrpProduction(models.Model): source_location = self.location_src_id original_quantity = self.product_qty - self.qty_produced data = { + 'sequence': bom_line.sequence, 'name': self.name, 'date': self.date_planned_start, 'date_expected': self.date_planned_start, diff --git a/addons/stock/models/stock_pack_operation.py b/addons/stock/models/stock_pack_operation.py index edeba5e2c7b..a9116730e5c 100644 --- a/addons/stock/models/stock_pack_operation.py +++ b/addons/stock/models/stock_pack_operation.py @@ -34,6 +34,9 @@ class PackOperation(models.Model): product_qty = fields.Float('To Do', default=0.0, digits=dp.get_precision('Product Unit of Measure'), required=True) ordered_qty = fields.Float('Ordered Quantity', digits=dp.get_precision('Product Unit of Measure')) qty_done = fields.Float('Done', default=0.0, digits=dp.get_precision('Product Unit of Measure')) + qty_done_uom_ordered = fields.Float( + 'Quantity Done', digits=dp.get_precision('Product Unit of Measure'), compute='_compute_qty_done_uom_ordered', + help='Quantity done in UOM ordered') is_done = fields.Boolean(compute='_compute_is_done', string='Done', readonly=False, oldname='processed_boolean') package_id = fields.Many2one('stock.quant.package', 'Source Package') pack_lot_ids = fields.One2many('stock.pack.operation.lot', 'operation_id', 'Lots/Serial Numbers Used') @@ -126,6 +129,14 @@ class PackOperation(models.Model): else: self.lots_visible = self.product_id.tracking != 'none' + @api.multi + def _compute_qty_done_uom_ordered(self): + for pack in self: + if pack.product_uom_id and pack.linked_move_operation_ids: + pack.qty_done_uom_ordered = pack.product_uom_id._compute_quantity(pack.qty_done, pack.linked_move_operation_ids[0].move_id.product_uom) + else: + pack.qty_done_uom_ordered = pack.qty_done + @api.onchange('pack_lot_ids') def _onchange_packlots(self): self.qty_done = sum([x.qty for x in self.pack_lot_ids]) diff --git a/addons/stock/report/report_deliveryslip.xml b/addons/stock/report/report_deliveryslip.xml index 305bea7b34b..79814492932 100644 --- a/addons/stock/report/report_deliveryslip.xml +++ b/addons/stock/report/report_deliveryslip.xml @@ -125,11 +125,16 @@ </t> </td> <td class="text-right" t-if="pack_operation.state == 'done'"> - <t t-if="pack_operation.ordered_qty != pack_operation.qty_done"> + <t t-if="pack_operation.ordered_qty != pack_operation.qty_done_uom_ordered"> <t t-set="backorder" t-value="True"/> </t> - <span t-field="pack_operation.qty_done"/> - <span t-field="pack_operation.product_uom_id"/> + <span t-field="pack_operation.qty_done_uom_ordered"/> + <t t-if="pack_operation.linked_move_operation_ids"> + <span t-field="pack_operation.linked_move_operation_ids[0].move_id.product_uom"></span> + </t> + <t t-else="1"> + <span t-field="pack_operation.product_uom_id"></span> + </t> </td> </tr> </tbody> diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index a7692d25b61..a1d7cf41f0a 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -201,7 +201,7 @@ </tbody> </table> <t t-if="not bins"> - <div class="text-center text-muted"> + <div class="text-center text-muted oe_product"> <h3 class="css_editable_display">No product defined.</h3> <p groups="sales_team.group_sale_manager">Click <i>'New'</i> in the top-right corner to create your first product.</p> </div> @@ -413,8 +413,8 @@ <div id="o-carousel-product" class="carousel slide" data-ride="carousel" data-interval="0"> <div class="carousel-outer"> <div class="carousel-inner"> - <div class="item active" itemprop="image" t-field="product.product_variant_id.image" t-options="{'widget': 'image', 'class': 'product_detail_img js_variant_img', 'alt-field': 'name', 'zoom': 'image', 'unique': product['__last_update'] + product.product_variant_id['__last_update']}"/> - <div t-if="variant_img" class="item" itemprop="image" t-field="product.image" t-options="{'widget': 'image', 'class': 'product_detail_img', 'alt-field': 'name', 'zoom': 'image', 'unique': product['__last_update'] + product.product_variant_id['__last_update']}"/> + <div class="item active" itemprop="image" t-field="product.image" t-options="{'widget': 'image', 'class': 'product_detail_img js_variant_img', 'alt-field': 'name', 'zoom': 'image', 'unique': product['__last_update']}"/> + <div t-if="variant_img" class="item" itemprop="image" t-field="product.product_variant_id.image" t-options="{'widget': 'image', 'class': 'product_detail_img', 'alt-field': 'name', 'zoom': 'image', 'unique': product['__last_update'] + (product.product_variant_id['__last_update'] or '')}"/> <t t-if="len(image_ids)" t-foreach="image_ids" t-as="pimg"> <div class="item" t-field="pimg.image" t-options='{"widget": "image", "class": "product_detail_img", "alt-field": "name", "zoom": "image" }'/> </t> @@ -434,10 +434,10 @@ <ol class="carousel-indicators" t-if="len(image_ids) or variant_img"> <li data-target="#o-carousel-product" data-slide-to="0" class="active"> - <img class="img img-responsive js_variant_img_small" t-attf-src="/website/image/product.product/{{product.product_variant_ids[0].id}}/image/90x90" t-att-alt="product.name"/> + <img class="img img-responsive js_variant_img_small" t-attf-src="/website/image/product.template/{{product.id}}/image/90x90" t-att-alt="product.name"/> </li> <li t-if="variant_img" data-target="#o-carousel-product" data-slide-to="1" class=""> - <img class="img img-responsive" t-attf-src="/website/image/product.template/{{product.id}}/image/90x90" t-att-alt="product.name"/> + <img class="img img-responsive" t-attf-src="/website/image/product.product/{{product.product_variant_id.id}}/image/90x90" t-att-alt="product.name"/> </li> <t t-if="len(image_ids)" t-foreach="image_ids" t-as="pimg"> <li data-target="#o-carousel-product" t-att-data-slide-to="pimg_index + (variant_img and 2 or 1)"> diff --git a/addons/website_sale_delivery/static/src/js/website_sale_delivery.js b/addons/website_sale_delivery/static/src/js/website_sale_delivery.js index 46caab18e0e..0775b7657cc 100644 --- a/addons/website_sale_delivery/static/src/js/website_sale_delivery.js +++ b/addons/website_sale_delivery/static/src/js/website_sale_delivery.js @@ -1,8 +1,14 @@ $(document).ready(function () { - // When choosing an delivery carrier, update the quotation and the acquirers + var $pay_button = $('.oe_sale_acquirer_button button'); + $pay_button.prop('disabled', false); + + // When choosing an delivery carrier, update the quotation and the acquirers. Disable the 'Pay + // Now' button to avoid being redirected to payment acquier if the delivery carrier update is + // not over. var $carrier = $("#delivery_carrier"); $carrier.find("input[name='delivery_type']").click(function (ev) { + $pay_button.prop('disabled', true); var carrier_id = $(ev.currentTarget).val(); window.location.href = '/shop/payment?carrier_id=' + carrier_id; }); diff --git a/odoo/addons/base/ir/ir_model.py b/odoo/addons/base/ir/ir_model.py index a71e76a8033..0ec5dbb9764 100644 --- a/odoo/addons/base/ir/ir_model.py +++ b/odoo/addons/base/ir/ir_model.py @@ -1532,7 +1532,9 @@ class IrModelData(models.Model): if model == 'ir.model.fields': # Don't remove the LOG_ACCESS_COLUMNS unless _log_access # has been turned off on the model. - field = self.env[model].browse(res_id) + field = self.env[model].browse(res_id).with_context( + prefetch_fields=False, + ) if not field.exists(): _logger.info('Deleting orphan external_ids %s', external_ids) external_ids.unlink() diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py index ff45b8d8978..77d27b67868 100644 --- a/odoo/tools/misc.py +++ b/odoo/tools/misc.py @@ -383,11 +383,12 @@ try: # TODO when xlsxwriter bump to 0.9.8, add worksheet_class=None parameter instead of kw def add_worksheet(self, name=None, **kw): - # invalid Excel character: []:*?/\ - name = re.sub(r'[\[\]:*?/\\]', '', name) + if name: + # invalid Excel character: []:*?/\ + name = re.sub(r'[\[\]:*?/\\]', '', name) - # maximum size is 31 characters - name = name[:31] + # maximum size is 31 characters + name = name[:31] return super(PatchedXlsxWorkbook, self).add_worksheet(name, **kw) xlsxwriter.Workbook = PatchedXlsxWorkbook diff --git a/odoo/tools/sql.py b/odoo/tools/sql.py index 563ed08c679..239cee73fd1 100644 --- a/odoo/tools/sql.py +++ b/odoo/tools/sql.py @@ -23,7 +23,7 @@ _CONFDELTYPES = { def table_exists(cr, tablename): """ Return whether the given table exists. """ - query = "SELECT 1 FROM information_schema.tables WHERE table_name=%s" + query = "SELECT 1 FROM pg_class WHERE relkind IN ('r', 'v', 'm') AND relname=%s" cr.execute(query, (tablename,)) return cr.rowcount |
