Files
odoo_source/addons/sale/models/account_move.py
T
Maximilien (malb) ea8acc17b4 [FIX] account,sale: Sale person and team
When creating a Vendor Bill, the default Sales Team & Person of the company is
assigned to the Vendor Bill. The field isn't even displayed, it's hidden, you
can only display it with Studio and can't even change it.

The fact is : purchases and sales are two completely different roles and
business in companies. This has the indirect consequence that any user that
follows the default Sales Team will get notified of any new Vendor Bill created
in Accounting, which he very likely does not need/want to see.

This PR correct that by adding a condition on the filling of these fields. These
 fields will be filled when the move is a sale document.

closes odoo/odoo#120628

Task-id: 3279233
Related: odoo/enterprise#44034
Signed-off-by: Florian Gilbert (flg) <flg@odoo.com>
2023-07-13 16:52:46 +02:00

168 lines
7.0 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class AccountMove(models.Model):
_name = 'account.move'
_inherit = ['account.move', 'utm.mixin']
@api.model
def _get_invoice_default_sale_team(self):
return self.env['crm.team']._get_default_team_id()
team_id = fields.Many2one(
'crm.team', string='Sales Team', default=_get_invoice_default_sale_team,
compute='_compute_team_id', store=True, readonly=False,
ondelete="set null", tracking=True,
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
# UTMs - enforcing the fact that we want to 'set null' when relation is unlinked
campaign_id = fields.Many2one(ondelete='set null')
medium_id = fields.Many2one(ondelete='set null')
source_id = fields.Many2one(ondelete='set null')
sale_order_count = fields.Integer(compute="_compute_origin_so_count", string='Sale Order Count')
def unlink(self):
downpayment_lines = self.mapped('line_ids.sale_line_ids').filtered(lambda line: line.is_downpayment and line.invoice_lines <= self.mapped('line_ids'))
res = super(AccountMove, self).unlink()
if downpayment_lines:
downpayment_lines.unlink()
return res
@api.depends('invoice_user_id')
def _compute_team_id(self):
for move in self:
if not move.invoice_user_id.sale_team_id or not move.is_sale_document(include_receipts=True):
continue
move.team_id = self.env['crm.team']._get_default_team_id(
user_id=move.invoice_user_id.id,
domain=[('company_id', '=', move.company_id.id)])
@api.depends('line_ids.sale_line_ids')
def _compute_origin_so_count(self):
for move in self:
move.sale_order_count = len(move.line_ids.sale_line_ids.order_id)
def _reverse_moves(self, default_values_list=None, cancel=False):
# OVERRIDE
if not default_values_list:
default_values_list = [{} for move in self]
for move, default_values in zip(self, default_values_list):
default_values.update({
'campaign_id': move.campaign_id.id,
'medium_id': move.medium_id.id,
'source_id': move.source_id.id,
})
return super()._reverse_moves(default_values_list=default_values_list, cancel=cancel)
def action_post(self):
#inherit of the function from account.move to validate a new tax and the priceunit of a downpayment
res = super(AccountMove, self).action_post()
down_payment_lines = self.line_ids.filtered('is_downpayment')
for line in down_payment_lines:
if any(order.locked for order in line.sale_line_ids.order_id):
# We cannot change lines content on locked SO, changes on invoices are not
# forwarded to the SO if the SO is locked.
continue
if not line.sale_line_ids.display_type:
line.sale_line_ids._compute_name()
line.sale_line_ids.tax_id = line.tax_ids
line.sale_line_ids.price_unit = line.price_unit
return res
def button_draft(self):
res = super().button_draft()
self.line_ids.filtered('is_downpayment').sale_line_ids.filtered(
lambda sol: not sol.display_type)._compute_name()
return res
def button_cancel(self):
res = super().button_cancel()
self.line_ids.filtered('is_downpayment').sale_line_ids.filtered(
lambda sol: not sol.display_type)._compute_name()
return res
def _post(self, soft=True):
# OVERRIDE
# Auto-reconcile the invoice with payments coming from transactions.
# It's useful when you have a "paid" sale order (using a payment transaction) and you invoice it later.
posted = super()._post(soft)
for invoice in posted.filtered(lambda move: move.is_invoice()):
payments = invoice.mapped('transaction_ids.payment_id').filtered(lambda x: x.state == 'posted')
move_lines = payments.line_ids.filtered(lambda line: line.account_type in ('asset_receivable', 'liability_payable') and not line.reconciled)
for line in move_lines:
invoice.js_assign_outstanding_line(line.id)
return posted
def _invoice_paid_hook(self):
# OVERRIDE
res = super(AccountMove, self)._invoice_paid_hook()
todo = set()
for invoice in self.filtered(lambda move: move.is_invoice()):
for line in invoice.invoice_line_ids:
for sale_line in line.sale_line_ids:
todo.add((sale_line.order_id, invoice.name))
for (order, name) in todo:
order.message_post(body=_("Invoice %s paid", name))
return res
def _action_invoice_ready_to_be_sent(self):
# OVERRIDE
# Make sure the send invoice CRON is called when an invoice becomes ready to be sent by mail.
res = super()._action_invoice_ready_to_be_sent()
send_invoice_cron = self.env.ref('sale.send_invoice_cron', raise_if_not_found=False)
if send_invoice_cron:
send_invoice_cron._trigger()
return res
def action_view_source_sale_orders(self):
self.ensure_one()
source_orders = self.line_ids.sale_line_ids.order_id
result = self.env['ir.actions.act_window']._for_xml_id('sale.action_orders')
if len(source_orders) > 1:
result['domain'] = [('id', 'in', source_orders.ids)]
elif len(source_orders) == 1:
result['views'] = [(self.env.ref('sale.view_order_form', False).id, 'form')]
result['res_id'] = source_orders.id
else:
result = {'type': 'ir.actions.act_window_close'}
return result
def _is_downpayment(self):
# OVERRIDE
self.ensure_one()
return self.line_ids.sale_line_ids and all(sale_line.is_downpayment for sale_line in self.line_ids.sale_line_ids) or False
@api.depends('line_ids.sale_line_ids.order_id', 'currency_id', 'tax_totals', 'date')
def _compute_partner_credit(self):
super()._compute_partner_credit()
for move in self.filtered(lambda m: m.is_invoice(include_receipts=True)):
sale_orders = move.line_ids.sale_line_ids.order_id
amount_total_currency = move.currency_id._convert(
move.tax_totals['amount_total'],
move.company_currency_id,
move.company_id,
move.date
)
amount_to_invoice_currency = sum(
sale_order.currency_id._convert(
sale_order.amount_to_invoice,
move.company_currency_id,
move.company_id,
move.date
) for sale_order in sale_orders
)
move.partner_credit += max(amount_total_currency - amount_to_invoice_currency, 0.0)