Files
tryton/modules/sale/invoice.py
T

163 lines
5.2 KiB
Python
Raw Normal View History

2014-12-02 12:55:52 +01:00
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from functools import wraps
2018-12-29 14:20:29 +01:00
from trytond.i18n import gettext
2012-09-24 22:18:13 +02:00
from trytond.model import Workflow, fields
2018-12-29 14:20:29 +01:00
from trytond.model.exceptions import AccessError
2012-09-24 22:18:13 +02:00
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
from trytond.transaction import Transaction, without_check_access
2012-09-24 22:18:13 +02:00
2011-01-16 22:02:53 +01:00
def process_sale(func):
@wraps(func)
def wrapper(cls, invoices):
pool = Pool()
Sale = pool.get('sale.sale')
2022-03-09 00:57:17 +01:00
transaction = Transaction()
context = transaction.context
with without_check_access():
2018-07-27 09:26:03 +02:00
sales = set(s for i in cls.browse(invoices) for s in i.sales)
func(cls, invoices)
2018-07-27 09:26:03 +02:00
if sales:
2022-03-09 00:57:17 +01:00
with transaction.set_context(
queue_batch=context.get('queue_batch', True)):
Sale.__queue__.process(sales)
return wrapper
2018-06-26 19:11:52 +02:00
class Invoice(metaclass=PoolMeta):
2012-09-24 22:18:13 +02:00
__name__ = 'account.invoice'
sale_exception_state = fields.Function(fields.Selection([
('', ''),
('ignored', 'Ignored'),
('recreated', 'Recreated'),
], 'Exception State'), 'get_sale_exception_state')
sales = fields.Function(fields.Many2Many(
'sale.sale', None, None, "Sales"),
'get_sales', searcher='search_sales')
2012-09-24 22:18:13 +02:00
def get_sale_exception_state(self, name):
sales = self.sales
2012-09-24 22:18:13 +02:00
recreated = tuple(i for p in sales for i in p.invoices_recreated)
ignored = tuple(i for p in sales for i in p.invoices_ignored)
if self in recreated:
return 'recreated'
elif self in ignored:
return 'ignored'
return ''
2011-01-16 22:02:53 +01:00
def get_sales(self, name):
pool = Pool()
SaleLine = pool.get('sale.line')
sales = set()
for line in self.lines:
if isinstance(line.origin, SaleLine):
sales.add(line.origin.sale.id)
return list(sales)
@classmethod
def search_sales(cls, name, clause):
return [('lines.origin.sale' + clause[0][len(name):],
*clause[1:3], 'sale.line', *clause[3:])]
2012-09-24 22:18:13 +02:00
@classmethod
@process_sale
2012-09-24 22:18:13 +02:00
def delete(cls, invoices):
super(Invoice, cls).delete(invoices)
@classmethod
@process_sale
2021-02-27 15:23:46 +01:00
def _post(cls, invoices):
super()._post(invoices)
2012-03-25 00:18:13 +01:00
2012-09-24 22:18:13 +02:00
@classmethod
@process_sale
def paid(cls, invoices):
super(Invoice, cls).paid(invoices)
@classmethod
@process_sale
2012-09-24 22:18:13 +02:00
def cancel(cls, invoices):
super(Invoice, cls).cancel(invoices)
2012-03-25 00:18:13 +01:00
2012-09-24 22:18:13 +02:00
@classmethod
@Workflow.transition('draft')
def draft(cls, invoices):
2018-12-29 14:20:29 +01:00
for invoice in invoices:
if invoice.sales and invoice.state == 'cancelled':
2018-12-29 14:20:29 +01:00
raise AccessError(
gettext('sale.msg_sale_invoice_reset_draft',
invoice=invoice.rec_name))
2012-09-24 22:18:13 +02:00
return super(Invoice, cls).draft(invoices)
2011-01-16 22:02:53 +01:00
2020-03-01 12:33:53 +01:00
class Line(metaclass=PoolMeta):
2012-09-24 22:18:13 +02:00
__name__ = 'account.invoice.line'
2011-01-16 22:02:53 +01:00
@classmethod
def __setup__(cls):
super().__setup__()
if not cls.origin.domain:
cls.origin.domain = {}
cls.origin.domain['sale.line'] = [
('type', '=', Eval('type')),
]
@fields.depends('origin')
def on_change_with_product_uom_category(self, name=None):
pool = Pool()
SaleLine = pool.get('sale.line')
category = super().on_change_with_product_uom_category(name=name)
# Enforce the same unit category as they are used to compute the
# remaining quantity to invoice and the quantity to ship.
# Use getattr as reference field can have negative id
if (isinstance(self.origin, SaleLine)
and getattr(self.origin, 'unit', None)):
2023-03-26 09:49:00 +02:00
category = self.origin.unit.category
return category
2021-07-29 09:06:38 +02:00
def get_warehouse(self, name):
pool = Pool()
SaleLine = pool.get('sale.line')
warehouse = super().get_warehouse(name)
if (not warehouse
and isinstance(self.origin, SaleLine)
and self.origin.warehouse):
warehouse = self.origin.warehouse.id
return warehouse
2013-09-19 17:34:09 +02:00
@property
def origin_name(self):
pool = Pool()
SaleLine = pool.get('sale.line')
2020-03-01 12:33:53 +01:00
name = super().origin_name
if isinstance(self.origin, SaleLine) and self.origin.id >= 0:
2019-05-22 18:37:08 +02:00
name = self.origin.sale.rec_name
2013-09-19 17:34:09 +02:00
return name
@classmethod
def _get_origin(cls):
2020-03-01 12:33:53 +01:00
models = super()._get_origin()
models.append('sale.line')
return models
2017-01-18 10:18:29 +01:00
@classmethod
def delete(cls, lines):
pool = Pool()
Sale = pool.get('sale.sale')
2022-03-09 00:57:17 +01:00
transaction = Transaction()
context = transaction.context
with without_check_access():
2018-07-27 09:26:03 +02:00
invoices = (l.invoice for l in cls.browse(lines)
2017-01-18 10:18:29 +01:00
if l.type == 'line' and l.invoice)
2018-07-27 09:26:03 +02:00
sales = set(s for i in invoices for s in i.sales)
2020-03-01 12:33:53 +01:00
super().delete(lines)
2018-07-27 09:26:03 +02:00
if sales:
2022-03-09 00:57:17 +01:00
with transaction.set_context(
queue_batch=context.get('queue_batch', True)):
Sale.__queue__.process(sales)