292 lines
12 KiB
Python
292 lines
12 KiB
Python
#This file is part account_invoice_line_origin module for Tryton.
|
|
#The COPYRIGHT file at the top level of this repository contains
|
|
#the full copyright notices and license terms.
|
|
from datetime import datetime
|
|
from trytond.model import fields, Model
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.transaction import Transaction
|
|
from sql import Cast, Literal, operators
|
|
from sql.functions import Substring, Position
|
|
from sql.operators import Like
|
|
|
|
|
|
class InvoiceLine(metaclass=PoolMeta):
|
|
__name__ = 'account.invoice.line'
|
|
origin_number = fields.Function(fields.Char('Origin Number'),
|
|
'get_origin_reference', searcher='search_origin_reference')
|
|
origin_reference = fields.Function(fields.Char('Origin Reference'),
|
|
'get_origin_reference', searcher='search_origin_reference')
|
|
origin_date = fields.Function(fields.Date('Origin Date'),
|
|
'get_origin_reference', searcher='search_origin_reference')
|
|
# origin_shipment/date fields in __setup__ method
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(InvoiceLine, cls).__setup__()
|
|
if hasattr(cls, 'stock_moves'):
|
|
cls.origin_shipment = fields.Function(fields.Char('Shipment'),
|
|
'get_origin_shipment', searcher='search_origin_shipment')
|
|
|
|
@classmethod
|
|
def origin_reference_models(cls):
|
|
return {
|
|
'account.invoice.line': 'invoice',
|
|
'purchase.line': 'purchase',
|
|
'sale.line': 'sale',
|
|
}
|
|
|
|
def get_origin_reference(self, name):
|
|
if self.origin and isinstance(self.origin, Model):
|
|
origin = self.origin
|
|
parent = self.origin_reference_models().get(origin.__name__)
|
|
if not parent:
|
|
return
|
|
|
|
source = getattr(origin, parent, None)
|
|
if not source:
|
|
return
|
|
|
|
if name.endswith('number'):
|
|
return source.number if hasattr(source, 'number') else None
|
|
elif name.endswith('reference'):
|
|
if (hasattr(source, 'number')
|
|
and hasattr(source, 'reference')):
|
|
references = []
|
|
if source.number:
|
|
references.append(source.number)
|
|
if source.reference:
|
|
references.append(source.reference)
|
|
reference = ' / '.join(references)
|
|
elif hasattr(source, 'reference'):
|
|
reference = source.reference
|
|
else:
|
|
reference = source.rec_name
|
|
return reference
|
|
elif name.endswith('date'):
|
|
parent_date = getattr(source, parent+'_date', None)
|
|
return parent_date if parent_date else None
|
|
|
|
@classmethod
|
|
def search_origin_reference(cls, name, clause):
|
|
pool = Pool()
|
|
Invoice = pool.get('account.invoice')
|
|
try:
|
|
SaleLine = pool.get('sale.line')
|
|
Sale = pool.get('sale.sale')
|
|
except:
|
|
Sale = None
|
|
try:
|
|
PurchaseLine = pool.get('purchase.line')
|
|
Purchase = pool.get('purchase.purchase')
|
|
except:
|
|
Purchase = None
|
|
|
|
invoice_type = Transaction().context.get('invoice_type', 'both')
|
|
|
|
invoice_line = cls.__table__()
|
|
invoice_line2 = cls.__table__()
|
|
invoice = Invoice.__table__()
|
|
|
|
if Sale:
|
|
sale_line = SaleLine.__table__()
|
|
sale = Sale.__table__()
|
|
if Purchase:
|
|
purchase_line = PurchaseLine.__table__()
|
|
purchase = Purchase.__table__()
|
|
|
|
field, operator_, value = clause
|
|
|
|
if operator_ == '!=':
|
|
PYSQL_CONDITION = 'not'
|
|
elif operator_ == '=':
|
|
PYSQL_CONDITION = 'and'
|
|
elif operator_ == 'not ilike':
|
|
PYSQL_CONDITION = 'not'
|
|
else:
|
|
PYSQL_CONDITION = 'and'
|
|
|
|
Operator = fields.SQL_OPERATORS[operator_]
|
|
|
|
if name.endswith('date'):
|
|
sql_where = (Operator(invoice.invoice_date, value))
|
|
elif name.endswith('number'):
|
|
sql_where = (Operator(invoice.number, value))
|
|
else:
|
|
sql_where = (Operator(invoice.reference, value))
|
|
|
|
query = (invoice_line
|
|
.join(invoice_line2, 'LEFT', condition=(
|
|
(Cast(Substring(invoice_line.origin,
|
|
Position(',', invoice_line.origin)
|
|
+ Literal(1)), 'INTEGER') == invoice_line2.id)
|
|
&
|
|
(Like(invoice_line.origin, 'account.invoice.line,%'))
|
|
))
|
|
.join(invoice, 'LEFT', condition=(
|
|
invoice_line2.invoice == invoice.id
|
|
)))
|
|
|
|
# sales
|
|
if Sale and (invoice_type == 'out' or invoice_type == 'both'):
|
|
query = query.join(sale_line, 'LEFT', condition=(
|
|
(Cast(Substring(invoice_line.origin,
|
|
Position(',', invoice_line.origin)
|
|
+ Literal(1)), 'INTEGER') == sale_line.id)
|
|
&
|
|
(Like(invoice_line.origin, 'sale.line,%'))
|
|
))
|
|
query = query.join(sale, 'LEFT', condition=(
|
|
sale_line.sale == sale.id
|
|
))
|
|
|
|
if name.endswith('date'):
|
|
sql_where = (sql_where
|
|
| (Operator(sale.sale_date, value))
|
|
)
|
|
elif name.endswith('number'):
|
|
sql_where = (sql_where
|
|
| (Operator(sale.number, value))
|
|
)
|
|
else:
|
|
if PYSQL_CONDITION == 'and':
|
|
sql_where = (sql_where
|
|
| (Operator(sale.reference, value))
|
|
| (Operator(sale.number, value))
|
|
)
|
|
else:
|
|
sql_where = (sql_where
|
|
| (Operator(sale.reference, value))
|
|
& (Operator(sale.number, value))
|
|
)
|
|
|
|
# purchase
|
|
if Purchase and (invoice_type == 'in' or invoice_type == 'both'):
|
|
query = query.join(purchase_line, 'LEFT', condition=(
|
|
(Cast(Substring(invoice_line.origin,
|
|
Position(',', invoice_line.origin)
|
|
+ Literal(1)), 'INTEGER') == purchase_line.id)
|
|
&
|
|
(Like(invoice_line.origin, 'purchase.line,%'))
|
|
))
|
|
query = query.join(purchase, 'LEFT', condition=(
|
|
purchase_line.purchase == purchase.id
|
|
))
|
|
|
|
if name.endswith('date'):
|
|
sql_where = (sql_where
|
|
| (Operator(purchase.purchase_date, value))
|
|
)
|
|
elif name.endswith('number'):
|
|
sql_where = (sql_where
|
|
| (Operator(purchase.number, value))
|
|
)
|
|
else:
|
|
if PYSQL_CONDITION == 'and':
|
|
sql_where = (sql_where
|
|
| (Operator(purchase.reference, value))
|
|
| (Operator(purchase.number, value))
|
|
)
|
|
else:
|
|
sql_where = (sql_where
|
|
| (Operator(purchase.reference, value))
|
|
& (Operator(purchase.number, value))
|
|
)
|
|
query = query.select(invoice_line.id, where=sql_where)
|
|
|
|
return [('id', 'in', query)]
|
|
|
|
def get_origin_shipment(self, name):
|
|
locale = Transaction().context.get('locale')
|
|
format = locale.get('date', '%Y-%m-%d') if locale else '%Y-%m-%d'
|
|
|
|
shipments = set()
|
|
for move in self.stock_moves:
|
|
if move.shipment:
|
|
if move.shipment.effective_date and move.shipment.reference:
|
|
key = '%s - %s - %s' % (move.shipment.rec_name,
|
|
move.shipment.effective_date.strftime(format),
|
|
move.shipment.reference)
|
|
elif (move.shipment.effective_date and
|
|
not move.shipment.reference):
|
|
key = '%s - %s' % (move.shipment.rec_name,
|
|
move.shipment.effective_date.strftime(format))
|
|
elif (not move.shipment.effective_date and
|
|
move.shipment.reference):
|
|
key = '%s - %s ' % (move.shipment.rec_name,
|
|
move.shipment.reference)
|
|
else:
|
|
key = '%s' % move.shipment.rec_name
|
|
shipments.add(key)
|
|
|
|
return ', '.join(shipments)
|
|
|
|
@classmethod
|
|
def search_origin_shipment(cls, name, clause):
|
|
pool = Pool()
|
|
LineMove = pool.get('account.invoice.line-stock.move')
|
|
Move = pool.get('stock.move')
|
|
ShipmentOut = pool.get('stock.shipment.out')
|
|
ShipmentOutReturn = pool.get('stock.shipment.out.return')
|
|
ShipmentIn = pool.get('stock.shipment.in')
|
|
ShipmentInReturn = pool.get('stock.shipment.in.return')
|
|
|
|
invoice_line = cls.__table__()
|
|
line_move = LineMove.__table__()
|
|
move = Move.__table__()
|
|
shipment_out = ShipmentOut.__table__()
|
|
shipment_out_return = ShipmentOutReturn.__table__()
|
|
shipment_in = ShipmentIn.__table__()
|
|
shipment_in_return = ShipmentInReturn.__table__()
|
|
|
|
field, operator_, value = clause
|
|
|
|
Operator = fields.SQL_OPERATORS[operator_]
|
|
|
|
try:
|
|
locale = Transaction().context.get('locale')
|
|
format_date = (locale.get('date', '%Y-%m-%d')
|
|
if locale else '%Y-%m-%d')
|
|
value_date = (datetime.strptime(value.replace('%', ''),
|
|
format_date).strftime('%Y-%m-%d') if value else None)
|
|
except ValueError:
|
|
value_date = None
|
|
|
|
if value_date:
|
|
if Operator in (operators.Like, operators.ILike):
|
|
Operator = operators.Equal
|
|
elif Operator in (operators.NotLike, operators.NotILike):
|
|
Operator = operators.NotEqual
|
|
|
|
sql_where = (Operator(shipment_out.effective_date, value_date)
|
|
| Operator(shipment_out_return.effective_date, value_date)
|
|
| Operator(shipment_in.effective_date, value_date)
|
|
| Operator(shipment_in_return.effective_date, value_date))
|
|
else:
|
|
sql_where = (Operator(shipment_out.number, value)
|
|
| Operator(shipment_out_return.number, value)
|
|
| Operator(shipment_in.number, value)
|
|
| Operator(shipment_in_return.number, value)
|
|
| Operator(shipment_out.reference, value)
|
|
| Operator(shipment_out_return.reference, value)
|
|
| Operator(shipment_in.reference, value)
|
|
| Operator(shipment_in_return.reference, value))
|
|
|
|
query = invoice_line.join(line_move,
|
|
condition=invoice_line.id == line_move.invoice_line).join(
|
|
move, condition=move.id == line_move.stock_move)
|
|
query = query.join(shipment_out, 'LEFT',
|
|
condition=Cast(Substring(move.shipment, Position(
|
|
',', move.shipment) + Literal(1)), 'INTEGER') == shipment_out.id)
|
|
query = query.join(shipment_out_return, 'LEFT',
|
|
condition=Cast(Substring(move.shipment, Position(
|
|
',', move.shipment) + Literal(1)), 'INTEGER') == shipment_out_return.id)
|
|
query = query.join(shipment_in, 'LEFT',
|
|
condition=Cast(Substring(move.shipment, Position(
|
|
',', move.shipment) + Literal(1)), 'INTEGER') == shipment_in.id)
|
|
query = query.join(shipment_in_return, 'LEFT',
|
|
condition=Cast(Substring(move.shipment, Position(
|
|
',', move.shipment) + Literal(1)), 'INTEGER') == shipment_in_return.id)
|
|
query = query.select(invoice_line.id, where=sql_where)
|
|
|
|
return [('id', 'in', query)]
|