Lots Management
This commit is contained in:
@@ -702,6 +702,18 @@ Owner technique: `a completer`
|
||||
`All`, `Purchase`, `Sale`.
|
||||
- Le filtre `Shipping status` porte uniquement le lien `shipment_in` du
|
||||
`lot.lot` ou du `lot.qt`.
|
||||
- Les dates de contexte `As of` et `To` filtrent les contrats via
|
||||
`purchase.purchase_date` et `sale.sale_date`.
|
||||
- Si le filtre `Side` vaut `Purchase`, les bornes de dates s'appliquent au
|
||||
`purchase_date`.
|
||||
- Si le filtre `Side` vaut `Sale`, les bornes de dates s'appliquent au
|
||||
`sale_date`.
|
||||
- Si le filtre `Side` vaut `All`, une ligne est conservee si son
|
||||
`purchase_date` ou son `sale_date` entre dans les bornes.
|
||||
- Le filtre `Book` du rapport cible une valeur de dimension analytique
|
||||
rattachee au contrat achat ou vente via `analytic.dimension.assignment`.
|
||||
- Le filtre `Strategy` cible les strategies MTM rattachees aux lignes achat
|
||||
ou vente (`purchase.strategy` / `sale.strategy`).
|
||||
- Resultat attendu:
|
||||
- `Unshipped`: aucun `shipment_in` lie au `lot.lot` ou au `lot.qt`.
|
||||
- `Scheduled`: un `shipment_in` est lie et son etat est `draft`.
|
||||
|
||||
@@ -9,10 +9,11 @@ from trytond.tools import (
|
||||
from trytond.transaction import Transaction, inactive_records
|
||||
from decimal import getcontext, Decimal, ROUND_HALF_UP
|
||||
from sql.aggregate import Count, Max, Min, Sum, Avg, BoolOr
|
||||
from sql.conditionals import Case
|
||||
from sql import Column, Literal, Union, Select
|
||||
from sql.conditionals import Coalesce
|
||||
from sql.functions import CurrentTimestamp, DateTrunc, Abs
|
||||
from sql.conditionals import Case
|
||||
from sql import Column, Literal, Union, Select
|
||||
from sql.conditionals import Coalesce
|
||||
from sql.functions import CurrentTimestamp, DateTrunc, Abs
|
||||
from sql.operators import Exists
|
||||
from trytond.wizard import Button, StateTransition, StateView, Wizard, StateAction
|
||||
from itertools import chain, groupby
|
||||
from operator import itemgetter
|
||||
@@ -1221,7 +1222,8 @@ class LotQt(
|
||||
def getQuery(cls, purchase=None, sale=None, shipment=None, type=None,
|
||||
state=None, qttype=None, supplier=None, client=None, ps=None,
|
||||
lot_status=None, group=None, product=None, location=None,
|
||||
origin=None, finished=False, shipping_status=None):
|
||||
origin=None, finished=False, shipping_status=None, asof=None,
|
||||
todate=None, book=None, strategy=None):
|
||||
pool = Pool()
|
||||
LotQt = pool.get('lot.qt')
|
||||
lqt = LotQt.__table__()
|
||||
@@ -1259,10 +1261,48 @@ class LotQt(
|
||||
final_s = Final_s.__table__()
|
||||
FinalLine_s = pool.get('account.invoice.line')
|
||||
final_line_s = FinalLine_s.__table__()
|
||||
ProductUom = pool.get('product.uom')
|
||||
puom = ProductUom.__table__()
|
||||
ProductUomLine = pool.get('product.uom')
|
||||
puoml = ProductUomLine.__table__()
|
||||
ProductUom = pool.get('product.uom')
|
||||
puom = ProductUom.__table__()
|
||||
ProductUomLine = pool.get('product.uom')
|
||||
puoml = ProductUomLine.__table__()
|
||||
PurchaseStrategy = pool.get('purchase.strategy')
|
||||
pstr = PurchaseStrategy.__table__()
|
||||
SaleStrategy = pool.get('sale.strategy')
|
||||
sstr = SaleStrategy.__table__()
|
||||
AnalyticDimensionAssignment = pool.get('analytic.dimension.assignment')
|
||||
ada = AnalyticDimensionAssignment.__table__()
|
||||
|
||||
def date_filter(purchase_date, sale_date):
|
||||
if not asof and not todate:
|
||||
return None
|
||||
purchase_clause = Literal(True)
|
||||
sale_clause = Literal(True)
|
||||
if asof:
|
||||
purchase_clause &= (purchase_date >= asof)
|
||||
sale_clause &= (sale_date >= asof)
|
||||
if todate:
|
||||
purchase_clause &= (purchase_date <= todate)
|
||||
sale_clause &= (sale_date <= todate)
|
||||
if ps == 'P':
|
||||
return purchase_clause
|
||||
elif ps == 'S':
|
||||
return sale_clause
|
||||
return purchase_clause | sale_clause
|
||||
|
||||
def book_filter(purchase_id, sale_id):
|
||||
if not book:
|
||||
return None
|
||||
purchase_book = Exists(ada.select(
|
||||
ada.id,
|
||||
where=((ada.purchase == purchase_id) & (ada.value == book))))
|
||||
sale_book = Exists(ada.select(
|
||||
ada.id,
|
||||
where=((ada.sale == sale_id) & (ada.value == book))))
|
||||
if ps == 'P':
|
||||
return purchase_book
|
||||
elif ps == 'S':
|
||||
return sale_book
|
||||
return purchase_book | sale_book
|
||||
|
||||
wh = ((lqt.lot_quantity > 0) & ((lp.lot_type == 'virtual') | (ls.lot_type == 'virtual')))
|
||||
|
||||
@@ -1285,8 +1325,28 @@ class LotQt(
|
||||
wh &= (lqt.lot_shipment_in == shipment)
|
||||
if product:
|
||||
wh &= (lqt.lot_product == product)
|
||||
if location:
|
||||
wh &= (Case((lqt.lot_shipment_in > 0, si.to_location),else_=Case((lqt.lot_shipment_internal > 0, sin.to_location),else_=pu.to_location)) == location)
|
||||
if location:
|
||||
wh &= (Case((lqt.lot_shipment_in > 0, si.to_location),else_=Case((lqt.lot_shipment_internal > 0, sin.to_location),else_=pu.to_location)) == location)
|
||||
date_clause = date_filter(pu.purchase_date, sa.sale_date)
|
||||
if date_clause is not None:
|
||||
wh &= date_clause
|
||||
book_clause = book_filter(pu.id, sa.id)
|
||||
if book_clause is not None:
|
||||
wh &= book_clause
|
||||
if strategy:
|
||||
purchase_strategy = Exists(pstr.select(
|
||||
pstr.id,
|
||||
where=((pstr.line == pl.id) & (pstr.strategy == strategy))))
|
||||
sale_strategy = Exists(sstr.select(
|
||||
sstr.id,
|
||||
where=((sstr.sale_line == sl.id)
|
||||
& (sstr.strategy == strategy))))
|
||||
if ps == 'P':
|
||||
wh &= purchase_strategy
|
||||
elif ps == 'S':
|
||||
wh &= sale_strategy
|
||||
else:
|
||||
wh &= (purchase_strategy | sale_strategy)
|
||||
if type=='matched':
|
||||
wh &= ((ls.sale_line > 0) & (lp.line > 0))
|
||||
elif type=='not matched':
|
||||
@@ -1403,10 +1463,30 @@ class LotQt(
|
||||
wh2 &= (lp.lot_shipment_in == shipment)
|
||||
if product:
|
||||
wh2 &= (lp.lot_product == product)
|
||||
if location:
|
||||
wh2 &= (Case((lp.lot_shipment_in > 0, si.to_location), else_=Case((lp.lot_shipment_internal > 0, sin.to_location), else_=pu.to_location)) == location)
|
||||
if type=='matched':
|
||||
wh2 &= (lp.sale_line != None)
|
||||
if location:
|
||||
wh2 &= (Case((lp.lot_shipment_in > 0, si.to_location), else_=Case((lp.lot_shipment_internal > 0, sin.to_location), else_=pu.to_location)) == location)
|
||||
date_clause = date_filter(pu.purchase_date, sa.sale_date)
|
||||
if date_clause is not None:
|
||||
wh2 &= date_clause
|
||||
book_clause = book_filter(pu.id, sa.id)
|
||||
if book_clause is not None:
|
||||
wh2 &= book_clause
|
||||
if strategy:
|
||||
purchase_strategy = Exists(pstr.select(
|
||||
pstr.id,
|
||||
where=((pstr.line == pl.id) & (pstr.strategy == strategy))))
|
||||
sale_strategy = Exists(sstr.select(
|
||||
sstr.id,
|
||||
where=((sstr.sale_line == sl.id)
|
||||
& (sstr.strategy == strategy))))
|
||||
if ps == 'P':
|
||||
wh2 &= purchase_strategy
|
||||
elif ps == 'S':
|
||||
wh2 &= sale_strategy
|
||||
else:
|
||||
wh2 &= (purchase_strategy | sale_strategy)
|
||||
if type=='matched':
|
||||
wh2 &= (lp.sale_line != None)
|
||||
elif type=='not matched':
|
||||
wh2 &= (lp.sale_line == None)
|
||||
if shipping_status == 'unshipped':
|
||||
@@ -1935,8 +2015,10 @@ class LotReport(
|
||||
client = context.get('client')
|
||||
ps = context.get('ps')
|
||||
shipping_status = context.get('shipping_status')
|
||||
#asof = context.get('asof')
|
||||
#todate = context.get('todate')
|
||||
asof = context.get('asof')
|
||||
todate = context.get('todate')
|
||||
book = context.get('book')
|
||||
strategy = context.get('strategy')
|
||||
finished = context.get('finished')
|
||||
query = LotQT.getQuery(
|
||||
purchase=purchase,
|
||||
@@ -1953,7 +2035,11 @@ class LotReport(
|
||||
location=location,
|
||||
origin=origin,
|
||||
finished=finished,
|
||||
shipping_status=shipping_status)
|
||||
shipping_status=shipping_status,
|
||||
asof=asof,
|
||||
todate=todate,
|
||||
book=book,
|
||||
strategy=strategy)
|
||||
return query
|
||||
|
||||
@classmethod
|
||||
@@ -2004,6 +2090,8 @@ class LotContext(ModelView):
|
||||
client = fields.Many2One('party.party', "Client")
|
||||
sale = fields.Many2One('sale.sale', "Sale")
|
||||
shipment = fields.Many2One('stock.shipment.in', "Shipment")
|
||||
book = fields.Many2One('analytic.dimension.value', "Book")
|
||||
strategy = fields.Many2One('mtm.strategy', "Strategy")
|
||||
product = fields.Many2One('product.product',"Product")
|
||||
location = fields.Many2One('stock.location',"Location")
|
||||
type = fields.Selection([
|
||||
@@ -2110,8 +2198,9 @@ class LotContext(ModelView):
|
||||
fields_names = fields_names.copy() if fields_names is not None else []
|
||||
for field_name in [
|
||||
'purchase', 'sale', 'shipment', 'supplier', 'client',
|
||||
'product', 'location', 'type', 'shipping_status', 'ps',
|
||||
'state', 'wh', 'mode', 'group', 'origin', 'finished']:
|
||||
'book', 'strategy', 'product', 'location', 'type',
|
||||
'shipping_status', 'ps', 'state', 'wh', 'mode', 'group',
|
||||
'origin', 'finished', 'asof', 'todate']:
|
||||
if field_name not in fields_names:
|
||||
fields_names.append(field_name)
|
||||
return super().get_context(fields_names=fields_names)
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
<field name="sale"/>
|
||||
<label name="shipment"/>
|
||||
<field name="shipment"/>
|
||||
<label name="book"/>
|
||||
<field name="book"/>
|
||||
<label name="strategy"/>
|
||||
<field name="strategy"/>
|
||||
<label name="supplier"/>
|
||||
<field name="supplier"/>
|
||||
<label name="client"/>
|
||||
@@ -23,12 +27,16 @@
|
||||
<field name="shipping_status"/>
|
||||
<label name="ps"/>
|
||||
<field name="ps"/>
|
||||
<!--
|
||||
<label name="state"/>
|
||||
<field name="state"/>
|
||||
-->
|
||||
<label name="wh"/>
|
||||
<field name="wh"/>
|
||||
<!--
|
||||
<label name="mode"/>
|
||||
<field name="mode"/>
|
||||
-->
|
||||
<label name="group"/>
|
||||
<field name="group"/>
|
||||
<label name="origin"/>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</field>
|
||||
<field name="r_shipping_status" width="100"/>
|
||||
<field name="r_lot_status" width="80"/>
|
||||
<field name="r_lot_av" width="80"/>
|
||||
<field name="r_lot_av" width="80" optional="1" tree_invisible="1"/>
|
||||
<field name="r_lot_quantity" symbol="r_lot_unit_line" width="120" sum="1"/>
|
||||
<field name="r_lot_matched" symbol="r_lot_unit_line" width="120" sum="1"/>
|
||||
<field name="r_tot" symbol="r_lot_unit_line" width="120" sum="1"/>
|
||||
|
||||
Reference in New Issue
Block a user