[IMP] sale: docstrings improvements/fixes

closes odoo/odoo#104115

X-original-commit: 7018ea22fedf75c16926c19e85b84dd82c23ab1b
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
This commit is contained in:
Victor Feyens
2022-10-27 18:43:08 +02:00
parent ded28245e1
commit 43c559b88c
2 changed files with 84 additions and 35 deletions
+65 -26
View File
@@ -712,12 +712,12 @@ class SaleOrder(models.Model):
lang = mail_template._render_lang(self.ids)[self.id]
ctx = {
'default_model': 'sale.order',
'default_res_id': self.ids[0],
'default_res_id': self.id,
'default_use_template': bool(mail_template),
'default_template_id': mail_template.id if mail_template else None,
'default_composition_mode': 'comment',
'mark_so_as_sent': True,
'default_email_layout_xmlid': "mail.mail_notification_layout_with_responsible_signature",
'default_email_layout_xmlid': 'mail.mail_notification_layout_with_responsible_signature',
'proforma': self.env.context.get('proforma', False),
'force_email': True,
'model_description': self.with_context(lang=lang).type_name,
@@ -748,9 +748,17 @@ class SaleOrder(models.Model):
return self._get_confirmation_template()
def _get_confirmation_template(self):
""" Get the mail template sent on SO confirmation (or for confirmed SO's).
:return: `mail.template` record or None if default template wasn't found
"""
return self.env.ref('sale.mail_template_sale_confirmation', raise_if_not_found=False)
def action_quotation_sent(self):
""" Mark the given draft quotation(s) as sent.
:raise: UserError if any given SO is not in draft state.
"""
if self.filtered(lambda so: so.state != 'draft'):
raise UserError(_("Only draft orders can be marked as sent directly."))
@@ -760,6 +768,14 @@ class SaleOrder(models.Model):
self.write({'state': 'sent'})
def action_confirm(self):
""" Confirm the given quotation(s) and set their confirmation date.
If the corresponding setting is enabled, also locks the Sale Order.
:return: True
:rtype: bool
:raise: UserError if trying to confirm locked or cancelled SO's
"""
if self._get_forbidden_state_confirm() & set(self.mapped('state')):
raise UserError(_(
"It is not allowed to confirm an order in the following states: %s",
@@ -788,6 +804,13 @@ class SaleOrder(models.Model):
return {'done', 'cancel'}
def _prepare_confirmation_values(self):
""" Prepare the sales order confirmation values.
Note: self can contain multiple records.
:return: Sales Order confirmation values
:rtype: dict
"""
return {
'state': 'sale',
'date_order': fields.Datetime.now()
@@ -834,9 +857,9 @@ class SaleOrder(models.Model):
self.write({'state': 'sale'})
def action_cancel(self):
""" Cancel SO after showing the cancel wizard when needed. (cfr `_show_cancel_wizard`)
""" Cancel SO after showing the cancel wizard when needed. (cfr :meth:`_show_cancel_wizard`)
For post-cancel operations, please only override `_action_cancel`.
For post-cancel operations, please only override :meth:`_action_cancel`.
note: self.ensure_one() if the wizard is shown.
"""
@@ -876,6 +899,11 @@ class SaleOrder(models.Model):
return self.write({'state': 'cancel'})
def _show_cancel_wizard(self):
""" Decide whether the sale.order.cancel wizard should be shown to cancel specified orders.
:return: True if there are draft order(s) in the given orders
:rtype: bool
"""
if self.env.context.get('disable_cancel_warning'):
return False
return any(so.state != 'draft' for so in self)
@@ -1026,12 +1054,15 @@ class SaleOrder(models.Model):
return self.env['sale.order.line'].browse(invoiceable_line_ids + down_payment_line_ids)
def _create_invoices(self, grouped=False, final=False, date=None):
"""
Create the invoice associated to the SO.
:param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by
(partner_invoice_id, currency)
:param final: if True, refunds will be generated if necessary
:returns: list of created invoices
""" Create invoice(s) for the given Sales Order(s).
:param bool grouped: if True, invoices are grouped by SO id.
If False, invoices are grouped by keys returned by :meth:`_get_invoice_grouping_keys`
:param bool final: if True, refunds will be generated if necessary
:param date: unused parameter
:returns: created invoices
:rtype: `account.move` recordset
:raises: UserError if one of the orders has no invoiceable lines.
"""
if not self.env['account.move'].check_access_rights('create', False):
try:
@@ -1361,56 +1392,64 @@ class SaleOrder(models.Model):
note=_("Upsell %(order)s for customer %(customer)s", order=order_ref, customer=customer_ref))
def _prepare_analytic_account_data(self, prefix=None):
"""
Prepare method for analytic account data
""" Prepare SO analytic account creation values.
:param prefix: The prefix of the to-be-created analytic account name
:type prefix: string
:return: dictionary of value for new analytic account creation
:param str prefix: The prefix of the to-be-created analytic account name
:return: `account.analytic.account` creation values
:rtype: dict
"""
self.ensure_one()
name = self.name
if prefix:
name = prefix + ": " + self.name
plan = self.env['account.analytic.plan'].search(['|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)], limit=1)
plan = self.env['account.analytic.plan'].search([
'|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)
], limit=1)
if not plan:
plan = self.env['account.analytic.plan'].create({
'name': 'Default',
'company_id': self.company_id.id
'company_id': self.company_id.id,
})
return {
'name': name,
'code': self.client_order_ref,
'company_id': self.company_id.id,
'plan_id': plan.id,
'partner_id': self.partner_id.id
'partner_id': self.partner_id.id,
}
def _create_analytic_account(self, prefix=None):
""" Create a new analytic account for the given orders.
:param str prefix: if specified, the account name will be '<prefix>: <so_reference>'.
If not, the account name will be the Sales Order reference.
:return: None
"""
for order in self:
analytic = self.env['account.analytic.account'].create(order._prepare_analytic_account_data(prefix))
order.analytic_account_id = analytic
@api.model
def _prepare_down_payment_section_line(self, **optional_values):
"""
Prepare the dict of values to create a new down payment section for a sales order line.
""" Prepare the values to create a new down payment section.
:param optional_values: any parameter that should be added to the returned down payment section
:param dict optional_values: any parameter that should be added to the returned down payment section
:return: `account.move.line` creation values
:rtype: dict
"""
self.ensure_one()
context = {'lang': self.partner_id.lang}
down_payments_section_line = {
'display_type': 'line_section',
'name': _('Down Payments'),
'name': _("Down Payments"),
'product_id': False,
'product_uom_id': False,
'quantity': 0,
'discount': 0,
'price_unit': 0,
'account_id': False
'account_id': False,
**optional_values
}
del context
if optional_values:
down_payments_section_line.update(optional_values)
return down_payments_section_line
#=== HOOKS ===#
+19 -9
View File
@@ -986,6 +986,11 @@ class SaleOrderLine(models.Model):
return super().write(values)
def _get_protected_fields(self):
""" Give the fields that should not be modified on a locked SO.
:returns: list of field names
:rtype: list
"""
return [
'product_id', 'name', 'price_unit', 'product_uom', 'product_uom_qty',
'tax_id', 'analytic_distribution'
@@ -1010,21 +1015,26 @@ class SaleOrderLine(models.Model):
order.message_post(body=msg)
def _check_line_unlink(self):
"""
Check whether a line can be deleted or not.
""" Check whether given lines can be deleted or not.
Lines cannot be deleted if the order is confirmed; downpayment
lines who have not yet been invoiced bypass that exception.
Also, allow deleting UX lines (notes/sections).
:rtype: recordset sale.order.line
:returns: set of lines that cannot be deleted
* Lines cannot be deleted if the order is confirmed.
* Down payment lines who have not yet been invoiced bypass that exception.
* Sections and Notes can always be deleted.
:returns: Sales Order Lines that cannot be deleted
:rtype: `sale.order.line` recordset
"""
return self.filtered(lambda line: line.state in ('sale', 'done') and (line.invoice_lines or not line.is_downpayment) and not line.display_type)
return self.filtered(
lambda line:
line.state in ('sale', 'done')
and (line.invoice_lines or not line.is_downpayment)
and not line.display_type
)
@api.ondelete(at_uninstall=False)
def _unlink_except_confirmed(self):
if self._check_line_unlink():
raise UserError(_('You can not remove an order line once the sales order is confirmed.\nYou should rather set the quantity to 0.'))
raise UserError(_("You can not remove an order line once the sales order is confirmed.\nYou should rather set the quantity to 0."))
#=== BUSINESS METHODS ===#