mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-28 04:32:07 +02:00
19.0 vanilla
This commit is contained in:
parent
79f83631d5
commit
73afc09215
6267 changed files with 1534193 additions and 1130106 deletions
|
|
@ -1,15 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import timedelta
|
||||
from itertools import chain, starmap, zip_longest
|
||||
|
||||
from odoo import SUPERUSER_ID, api, fields, models, _
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tools import is_html_empty
|
||||
|
||||
from odoo.addons.sale.models.sale_order import READONLY_FIELD_STATES
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = 'sale.order'
|
||||
|
|
@ -19,13 +16,7 @@ class SaleOrder(models.Model):
|
|||
string="Quotation Template",
|
||||
compute='_compute_sale_order_template_id',
|
||||
store=True, readonly=False, check_company=True, precompute=True,
|
||||
states=READONLY_FIELD_STATES,
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
sale_order_option_ids = fields.One2many(
|
||||
comodel_name='sale.order.option', inverse_name='order_id',
|
||||
string="Optional Products Lines",
|
||||
states=READONLY_FIELD_STATES,
|
||||
copy=True)
|
||||
|
||||
#=== COMPUTE METHODS ===#
|
||||
|
||||
|
|
@ -59,6 +50,13 @@ class SaleOrder(models.Model):
|
|||
for order in self.filtered('sale_order_template_id'):
|
||||
order.require_payment = order.sale_order_template_id.require_payment
|
||||
|
||||
@api.depends('sale_order_template_id')
|
||||
def _compute_prepayment_percent(self):
|
||||
super()._compute_prepayment_percent()
|
||||
for order in self.filtered('sale_order_template_id'):
|
||||
if order.require_payment:
|
||||
order.prepayment_percent = order.sale_order_template_id.prepayment_percent
|
||||
|
||||
@api.depends('sale_order_template_id')
|
||||
def _compute_validity_date(self):
|
||||
super()._compute_validity_date()
|
||||
|
|
@ -67,26 +65,18 @@ class SaleOrder(models.Model):
|
|||
if validity_days > 0:
|
||||
order.validity_date = fields.Date.context_today(order) + timedelta(validity_days)
|
||||
|
||||
#=== CONSTRAINT METHODS ===#
|
||||
|
||||
@api.constrains('company_id', 'sale_order_option_ids')
|
||||
def _check_optional_product_company_id(self):
|
||||
for order in self:
|
||||
companies = order.sale_order_option_ids.product_id.company_id
|
||||
if companies and companies != order.company_id:
|
||||
bad_products = order.sale_order_option_ids.product_id.filtered(lambda p: p.company_id and p.company_id != order.company_id)
|
||||
raise ValidationError(_(
|
||||
"Your quotation contains products from company %(product_company)s whereas your quotation belongs to company %(quote_company)s. \n Please change the company of your quotation or remove the products from other companies (%(bad_products)s).",
|
||||
product_company=', '.join(companies.mapped('display_name')),
|
||||
quote_company=order.company_id.display_name,
|
||||
bad_products=', '.join(bad_products.mapped('display_name')),
|
||||
))
|
||||
@api.depends('sale_order_template_id')
|
||||
def _compute_journal_id(self):
|
||||
super()._compute_journal_id()
|
||||
for order in self.filtered('sale_order_template_id'):
|
||||
order.journal_id = order.sale_order_template_id.journal_id
|
||||
|
||||
#=== ONCHANGE METHODS ===#
|
||||
|
||||
@api.onchange('company_id')
|
||||
def _onchange_company_id(self):
|
||||
"""Trigger quotation template recomputation on unsaved records company change"""
|
||||
super()._onchange_company_id()
|
||||
if self._origin.id:
|
||||
return
|
||||
self._compute_sale_order_template_id()
|
||||
|
|
@ -111,14 +101,6 @@ class SaleOrder(models.Model):
|
|||
|
||||
self.order_line = order_lines_data
|
||||
|
||||
option_lines_data = [fields.Command.clear()]
|
||||
option_lines_data += [
|
||||
fields.Command.create(option._prepare_option_line_values())
|
||||
for option in sale_order_template.sale_order_template_option_ids
|
||||
]
|
||||
|
||||
self.sale_order_option_ids = option_lines_data
|
||||
|
||||
@api.onchange('partner_id')
|
||||
def _onchange_partner_id(self):
|
||||
"""Reload template for unsaved orders with unmodified lines & orders."""
|
||||
|
|
@ -126,47 +108,33 @@ class SaleOrder(models.Model):
|
|||
return
|
||||
|
||||
def line_eqv(line, t_line):
|
||||
return line and t_line and (
|
||||
line.product_id == t_line.product_id
|
||||
and line.display_type == t_line.display_type
|
||||
and line.product_uom == t_line.product_uom_id
|
||||
and line.product_uom_qty == t_line.product_uom_qty
|
||||
)
|
||||
|
||||
def option_eqv(option, t_option):
|
||||
return option and t_option and all(
|
||||
option[fname] == t_option[fname]
|
||||
for fname in ['product_id', 'uom_id', 'quantity']
|
||||
return line and t_line and all(
|
||||
line[fname] == t_line[fname]
|
||||
for fname in ['product_id', 'product_uom_id', 'product_uom_qty', 'display_type']
|
||||
)
|
||||
|
||||
lines = self.order_line
|
||||
options = self.sale_order_option_ids
|
||||
t_lines = self.sale_order_template_id.sale_order_template_line_ids
|
||||
t_options = self.sale_order_template_id.sale_order_template_option_ids
|
||||
|
||||
if all(chain(
|
||||
starmap(line_eqv, zip_longest(lines, t_lines)),
|
||||
starmap(option_eqv, zip_longest(options, t_options)),
|
||||
)):
|
||||
if all(starmap(line_eqv, zip_longest(lines, t_lines))):
|
||||
self._onchange_sale_order_template_id()
|
||||
|
||||
#=== ACTION METHODS ===#
|
||||
|
||||
def _get_confirmation_template(self):
|
||||
self.ensure_one()
|
||||
return self.sale_order_template_id.mail_template_id or super()._get_confirmation_template()
|
||||
|
||||
def action_confirm(self):
|
||||
res = super().action_confirm()
|
||||
if self.env.su:
|
||||
self = self.with_user(SUPERUSER_ID)
|
||||
|
||||
if self.env.context.get('send_email'):
|
||||
# Mail already sent in super method
|
||||
return res
|
||||
|
||||
# When an order is confirmed from backend (send_email=False), if the quotation template has
|
||||
# a specified mail template, send it as it's probably meant to share additional information.
|
||||
for order in self:
|
||||
if order.sale_order_template_id and order.sale_order_template_id.mail_template_id:
|
||||
order.sale_order_template_id.mail_template_id.send_mail(order.id)
|
||||
if order.sale_order_template_id.mail_template_id:
|
||||
order._send_order_notification_mail(order.sale_order_template_id.mail_template_id)
|
||||
return res
|
||||
|
||||
def _recompute_prices(self):
|
||||
super()._recompute_prices()
|
||||
# Special case: we want to overwrite the existing discount on _recompute_prices call
|
||||
# i.e. to make sure the discount is correctly reset
|
||||
# if pricelist discount_policy is different than when the price was first computed.
|
||||
self.sale_order_option_ids.discount = 0.0
|
||||
self.sale_order_option_ids._compute_price_unit()
|
||||
self.sale_order_option_ids._compute_discount()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue