2021-08-26 20:16:55 +02: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.
2022-01-18 22:23:18 +01:00
import copy
2021-12-29 17:41:02 +01:00
from datetime import date , datetime , timedelta
2021-08-28 18:27:55 +02:00
from decimal import Decimal
2021-08-26 20:16:55 +02:00
from trytond . model import fields , ModelView
from trytond . pool import Pool , PoolMeta
from trytond . pyson import Eval , Not , Bool
from trytond . wizard import Wizard , StateView , StateReport , Button
from trytond . report import Report
from trytond . transaction import Transaction
STATES = { ' invisible ' : ( Eval ( ' type ' ) != ' goods ' ) }
STATES_MOVE = {
' readonly ' : Eval ( ' state ' ) . in_ ( [ ' cancel ' , ' assigned ' , ' done ' ] ) ,
}
2021-09-23 15:15:13 +02:00
class Lot ( metaclass = PoolMeta ) :
__name__ = ' stock.lot '
active = fields . Boolean ( ' Active ' )
@staticmethod
def default_active ( ) :
return True
2021-08-26 20:16:55 +02:00
class Move ( metaclass = PoolMeta ) :
__name__ = ' stock.move '
2022-02-21 18:27:26 +01:00
description = fields . Function ( fields . Char ( ' Description ' ) , ' on_change_with_description ' )
2021-08-26 20:16:55 +02:00
current_stock = fields . Function ( fields . Float ( ' Current Stock ' ,
depends = [ ' product ' ] ) , ' on_change_with_current_stock ' )
2021-12-09 20:10:33 +01:00
reference = fields . Function ( fields . Char ( ' Reference ' ,
depends = [ ' product ' ] , help = ' reference of product ' ) , ' get_reference ' )
2021-08-26 20:16:55 +02:00
2021-09-25 07:02:37 +02:00
@fields.depends ( ' current_stock ' )
2021-08-26 20:16:55 +02:00
def on_change_product ( self , name = None ) :
super ( Move , self ) . on_change_product ( )
self . current_stock = self . on_change_with_current_stock ( )
2021-12-09 20:10:33 +01:00
@fields.depends ( ' product ' )
def get_reference ( self , name = None ) :
reference = None
if self . product and hasattr ( self . product , ' reference ' ) and self . product . reference :
reference = self . product . reference
return reference
2021-08-26 20:16:55 +02:00
@fields.depends ( ' product ' , ' from_location ' , ' to_location ' )
def on_change_with_current_stock ( self , name = None ) :
res = 0
location = None
2022-01-24 15:57:35 +01:00
if self . from_location and self . from_location . type == ' storage ' and self . from_location . parent :
2021-08-26 20:16:55 +02:00
location = self . from_location . parent . storage_location
2022-01-24 15:57:35 +01:00
elif self . to_location and self . to_location . type == ' storage ' and self . to_location . parent :
2021-08-26 20:16:55 +02:00
location = self . to_location . parent . storage_location
if self . product and location :
context = {
' location_ids ' : [ location . id ] ,
' stock_date_end ' : date . today ( ) ,
}
with Transaction ( ) . set_context ( context ) :
res_dict = self . product . _get_quantity (
2021-09-25 07:02:37 +02:00
[ self . product ] ,
' quantity ' ,
[ location . id ] ,
grouping_filter = ( [ self . product . id ] , )
)
2021-08-26 20:16:55 +02:00
if res_dict . get ( self . product . id ) :
res + = res_dict [ self . product . id ]
2022-02-18 16:22:54 +01:00
return res
2021-08-26 20:16:55 +02:00
2022-02-21 18:27:26 +01:00
@fields.depends ( ' product ' )
def on_change_with_description ( self , name = None ) :
res = ' '
if self . product and self . product . description :
description = self . product . description
res = description . rstrip ( ' \n ' )
return res
2022-04-27 00:20:35 +02:00
@classmethod
def do ( cls , moves ) :
super ( Move , cls ) . do ( moves )
for move in moves :
2022-04-28 17:54:03 +02:00
if move . origin and move . origin . __name__ in ( ' purchase.line ' , ' stock.inventory.line ' ) :
2022-04-27 00:20:35 +02:00
move . set_average_cost ( )
def set_average_cost ( self ) :
AverageCost = Pool ( ) . get ( ' product.average_cost ' )
data = {
" stock_move " : self . id ,
" product " : self . product . id ,
" effective_date " : self . effective_date ,
" cost_price " : self . product . cost_price ,
}
AverageCost . create ( [ data ] )
2021-08-26 20:16:55 +02:00
class MoveByProductStart ( ModelView ) :
' Move By Product Start '
__name__ = ' stock_co.move_by_product.start '
start_date = fields . Date ( ' Start Date ' , required = True )
end_date = fields . Date ( ' End Date ' , required = True )
from_location = fields . Many2One ( ' stock.location ' , ' From Location ' )
to_location = fields . Many2One ( ' stock.location ' , ' To Location ' ,
required = True )
categories = fields . Many2Many ( ' product.category ' , None , None , ' Categories ' )
company = fields . Many2One ( ' company.company ' , ' Company ' ,
required = True )
brand = fields . Many2One ( ' product.brand ' , ' Brand ' )
party = fields . Many2One ( ' party.party ' , ' Party ' )
shipment_draft = fields . Boolean ( ' Shipment Draft ' )
start_time = fields . Time ( ' Start Time ' , )
end_time = fields . Time ( ' End Time ' , states = {
' required ' : Bool ( Eval ( ' start_time ' ) ) ,
' invisible ' : Not ( Bool ( Eval ( ' start_time ' ) ) ) ,
} , depends = [ ' start_time ' ] )
product = fields . Many2One ( ' product.product ' , ' Product ' )
@staticmethod
def default_company ( ) :
return Transaction ( ) . context . get ( ' company ' )
@staticmethod
def default_end_date ( ) :
Date_ = Pool ( ) . get ( ' ir.date ' )
return Date_ . today ( )
@staticmethod
def default_start_date ( ) :
Date_ = Pool ( ) . get ( ' ir.date ' )
return Date_ . today ( )
class PrintMoveByProduct ( Wizard ) :
' Move By Product '
__name__ = ' stock_co.print_move_by_product '
start = StateView ( ' stock_co.move_by_product.start ' ,
' stock_co.print_move_by_product_start_view_form ' , [
Button ( ' Cancel ' , ' end ' , ' tryton-cancel ' ) ,
Button ( ' Print ' , ' print_ ' , ' tryton-print ' , default = True ) ,
] )
print_ = StateReport ( ' stock_co.move_by_product ' )
def do_print_ ( self , action ) :
category_ids = [ ]
from_location_id = None
brand_id = None
party_id = None
start_time = None
end_time = None
if self . start . from_location :
from_location_id = self . start . from_location . id
if self . start . categories :
category_ids = [ acc . id for acc in self . start . categories ]
if self . start . brand :
brand_id = self . start . brand . id
if self . start . party :
party_id = self . start . party . id
if self . start . start_time :
start_time = self . start . start_time
if self . start . end_time :
end_time = self . start . end_time
data = {
' company ' : self . start . company . id ,
' from_location ' : from_location_id ,
' to_location ' : self . start . to_location . id ,
' start_date ' : self . start . start_date ,
' end_date ' : self . start . end_date ,
' categories ' : category_ids ,
' brand ' : brand_id ,
' party ' : party_id ,
' shipment_draft ' : self . start . shipment_draft ,
' start_time ' : start_time ,
' end_time ' : end_time ,
' product ' : self . start . product . id if self . start . product else None
}
return action , data
def transition_print_ ( self ) :
return ' end '
class MoveByProduct ( Report ) :
' Move By Product Report '
__name__ = ' stock_co.move_by_product '
@classmethod
def get_context ( cls , records , header , data ) :
report_context = super ( ) . get_context ( records , header , data )
pool = Pool ( )
Company = pool . get ( ' company.company ' )
Move = pool . get ( ' stock.move ' )
Location = pool . get ( ' stock.location ' )
Party = pool . get ( ' party.party ' )
Brand = pool . get ( ' product.brand ' )
Category = pool . get ( ' product.template-product.category ' )
company = Company ( data [ ' company ' ] )
from_location = None
brand_name = ' '
party_name = ' '
start_date = None
end_date = None
categories = Category . search ( [ ( ' category ' , ' in ' , data [ ' categories ' ] ) ] )
products_ids = [ c . template . id for c in categories ]
dom_products = [ ]
if data [ ' start_time ' ] :
start_date = datetime . combine ( data [ ' start_date ' ] , data [ ' start_time ' ] )
end_date = datetime . combine ( data [ ' end_date ' ] , data [ ' end_time ' ] )
_start_date = Company . convert_timezone ( start_date , True )
_end_date = Company . convert_timezone ( end_date , True )
dom_products . append (
( ' to_location.id ' , ' = ' , data [ ' to_location ' ] ) ,
( ' create_date ' , ' >= ' , _start_date ) ,
( ' create_date ' , ' <= ' , _end_date )
)
else :
start_date = data [ ' start_date ' ]
end_date = data [ ' end_date ' ]
dom_products . extend ( [
( ' to_location ' , ' = ' , data [ ' to_location ' ] ) ,
[ ' AND ' ,
[ ' OR ' , [
( ' planned_date ' , ' >= ' , start_date ) ,
( ' planned_date ' , ' <= ' , end_date ) ,
] , [
( ' effective_date ' , ' >= ' , start_date ) ,
( ' effective_date ' , ' <= ' , end_date ) ,
] ,
] ]
] )
if data [ ' shipment_draft ' ] :
dom_products . append ( ( ' state ' , ' = ' , ' draft ' ) )
if data [ ' from_location ' ] :
dom_products . append (
( ' from_location.id ' , ' = ' , data [ ' from_location ' ] ) ,
)
from_location = Location ( data [ ' from_location ' ] )
if data [ ' categories ' ] :
if products_ids :
dom_products . append (
( ' product.template ' , ' in ' , products_ids )
)
else :
dom_products . append (
( ' product.template.account_category ' , ' in ' , data [ ' categories ' ] )
)
if data [ ' brand ' ] :
dom_products . append (
( ' product.template.brand ' , ' = ' , data [ ' brand ' ] ) ,
)
brand_name = Brand ( data [ ' brand ' ] ) . name
if data [ ' party ' ] :
dom_products . append (
( ' invoice_lines.invoice.party ' , ' = ' , data [ ' party ' ] ) ,
)
party_name = Party ( data [ ' party ' ] ) . name
if data [ ' product ' ] :
dom_products . append (
( ' product ' , ' = ' , data [ ' product ' ] ) ,
)
moves = Move . search ( [ dom_products ] )
products = { }
for move in moves :
product = move . product
amount = move . quantity * float ( product . cost_price )
try :
row = products [ product . id ]
row [ 3 ] . append ( move . quantity )
row [ 5 ] . append ( amount )
except Exception as e :
template = product . template
brand = template . brand and template . brand . name
category = template . account_category and template . account_category . name
products [ product . id ] = [
product . code ,
product . rec_name ,
template . default_uom . symbol ,
[ move . quantity ] ,
product . cost_price ,
[ amount ] ,
category ,
brand ,
template . list_price ,
]
report_context [ ' records ' ] = products . values ( )
report_context [ ' from_location ' ] = from_location
report_context [ ' to_location ' ] = Location ( data [ ' to_location ' ] )
report_context [ ' start_date ' ] = start_date
report_context [ ' end_date ' ] = end_date
report_context [ ' company ' ] = company
report_context [ ' brand_name ' ] = brand_name
report_context [ ' party_name ' ] = party_name
return report_context
class WarehouseStockStart ( ModelView ) :
' Warehouse Stock Start '
__name__ = ' stock_co.warehouse_stock.start '
company = fields . Many2One ( ' company.company ' , ' Company ' , required = True )
locations = fields . Many2Many ( ' stock.location ' , None , None , " Locations " ,
domain = [
( ' type ' , ' in ' , [ ' storage ' , ' customer ' ] ) ,
( ' active ' , ' = ' , True )
] , required = True )
to_date = fields . Date ( ' To Date ' , required = True )
only_minimal_level = fields . Boolean ( ' Only Minimal Level ' )
group_by_location = fields . Boolean ( ' Group By Location ' )
2022-01-12 15:35:56 +01:00
group_by_supplier = fields . Boolean ( ' Group By Supplier ' )
2021-08-26 20:16:55 +02:00
category = fields . Many2One ( ' product.category ' , ' Category ' )
2022-01-12 15:35:56 +01:00
suppliers = fields . Many2Many ( ' party.party ' , None , None , " Suppliers " ,
domain = [
( ' active ' , ' = ' , True )
] )
2021-09-24 05:16:20 +02:00
zero_quantity = fields . Boolean ( ' Zero Quantity ' )
2021-08-26 20:16:55 +02:00
@staticmethod
def default_company ( ) :
return Transaction ( ) . context . get ( ' company ' )
@staticmethod
def default_to_date ( ) :
Date_ = Pool ( ) . get ( ' ir.date ' )
return Date_ . today ( )
class WarehouseStock ( Wizard ) :
' Warehouse Stock '
__name__ = ' stock_co.warehouse_stock '
start = StateView ( ' stock_co.warehouse_stock.start ' ,
' stock_co.warehouse_stock_start_view_form ' , [
Button ( ' Cancel ' , ' end ' , ' tryton-cancel ' ) ,
Button ( ' Print ' , ' print_ ' , ' tryton-ok ' , default = True ) ,
] )
print_ = StateReport ( ' stock_co.warehouse_stock.report ' )
def do_print_ ( self , action ) :
category_id = None
if self . start . category :
category_id = self . start . category . id
data = {
' company ' : self . start . company . id ,
' locations ' : [ l . id for l in self . start . locations ] ,
' location_names ' : ' , ' . join ( [ l . name for l in self . start . locations ] ) ,
' only_minimal_level ' : self . start . only_minimal_level ,
' group_by_location ' : self . start . group_by_location ,
2022-01-12 15:35:56 +01:00
' group_by_supplier ' : self . start . group_by_supplier ,
2021-09-24 05:16:20 +02:00
' zero_quantity ' : self . start . zero_quantity ,
2021-08-26 20:16:55 +02:00
' to_date ' : self . start . to_date ,
' category ' : category_id ,
2022-01-12 15:35:56 +01:00
' suppliers ' : [ l . id for l in self . start . suppliers ] ,
2021-08-26 20:16:55 +02:00
}
return action , data
class WarehouseReport ( Report ) :
' Warehouse Report '
__name__ = ' stock_co.warehouse_stock.report '
@classmethod
def get_context ( cls , records , header , data ) :
report_context = super ( ) . get_context ( records , header , data )
pool = Pool ( )
Company = pool . get ( ' company.company ' )
Product = pool . get ( ' product.product ' )
OrderPoint = pool . get ( ' stock.order_point ' )
Location = pool . get ( ' stock.location ' )
ids_location = data [ ' locations ' ]
locations = Location . browse ( data [ ' locations ' ] )
dom_products = [
( ' active ' , ' = ' , True ) ,
( ' template.active ' , ' = ' , True ) ,
( ' type ' , ' = ' , ' goods ' ) ,
( ' consumable ' , ' = ' , False ) ,
]
stock_context = {
' stock_date_end ' : data [ ' to_date ' ] ,
' locations ' : ids_location ,
}
if data [ ' category ' ] :
dom_products . append ( [ ' AND ' , [ ' OR ' , [
( ' account_category ' , ' = ' , data [ ' category ' ] ) ,
] , [
( ' categories ' , ' in ' , [ data [ ' category ' ] ] ) ,
] ,
] ] )
2021-09-24 05:16:20 +02:00
if not data [ ' zero_quantity ' ] :
2021-08-26 20:16:55 +02:00
dom_products . append ( [ ( ' quantity ' , ' != ' , 0 ) ] )
if data [ ' only_minimal_level ' ] :
order_points = OrderPoint . search ( [
( ' warehouse_location ' , ' in ' , ids_location ) ,
( ' type ' , ' = ' , ' purchase ' ) ,
] )
min_quantities = { op . product . id : op . min_quantity for op in order_points }
products_ids = min_quantities . keys ( )
dom_products . append ( ( ' id ' , ' in ' , products_ids ) )
2022-01-12 15:35:56 +01:00
if data [ ' suppliers ' ] :
2022-01-14 00:00:08 +01:00
dom_products . append ( [ ( ' template.product_suppliers.party ' , ' in ' , data [ ' suppliers ' ] ) ] )
2021-08-26 20:16:55 +02:00
total_amount = 0
values = { }
products = [ ]
if data [ ' group_by_location ' ] :
for l in locations :
stock_context [ ' locations ' ] = [ l . id ]
with Transaction ( ) . set_context ( stock_context ) :
prdts = Product . search ( dom_products , order = [ ( ' code ' , ' ASC ' ) ] )
2022-01-12 15:35:56 +01:00
suppliers = { }
if data [ ' group_by_supplier ' ] :
for p in prdts :
if not p . template . product_suppliers :
continue
2022-01-14 00:00:08 +01:00
for prod_sup in p . template . product_suppliers :
sup_id = prod_sup . party . id
2022-01-13 18:38:19 +01:00
try :
suppliers [ sup_id ] [ ' products ' ] . append ( p )
2022-05-14 17:09:14 +02:00
suppliers [ sup_id ] [ ' total_amount ' ] . append ( p . amount_cost if p . amount_cost else 0 )
2022-01-13 18:38:19 +01:00
except :
suppliers [ sup_id ] = { }
suppliers [ sup_id ] [ ' products ' ] = [ p ]
2022-01-14 00:00:08 +01:00
suppliers [ sup_id ] [ ' party ' ] = prod_sup . party
2022-05-14 17:09:14 +02:00
suppliers [ sup_id ] [ ' total_amount ' ] = [ p . amount_cost if p . amount_cost else 0 ]
2022-04-27 00:20:35 +02:00
total_amount = sum ( [ p . amount_cost for p in prdts if p . amount_cost ] )
2021-08-26 20:16:55 +02:00
values [ l . id ] = {
' name ' : l . name ,
' products ' : prdts ,
2022-01-12 15:35:56 +01:00
' suppliers ' : suppliers . values ( ) ,
2021-08-26 20:16:55 +02:00
' total_amount ' : total_amount
}
products = values . values ( )
else :
with Transaction ( ) . set_context ( stock_context ) :
products = Product . search ( dom_products , order = [ ( ' code ' , ' ASC ' ) ] )
2022-01-12 15:35:56 +01:00
if data [ ' only_minimal_level ' ] :
products = [ p for p in products if p . quantity < = min_quantities [ p . id ] ]
2022-04-27 00:20:35 +02:00
total_amount = sum ( [ p . amount_cost for p in products if p . amount_cost ] )
2022-01-12 15:35:56 +01:00
suppliers = { }
if data [ ' group_by_supplier ' ] :
for p in products :
if not p . template . product_suppliers :
continue
2022-01-14 00:00:08 +01:00
for prod_sup in p . template . product_suppliers :
sup_id = prod_sup . party . id
2022-01-13 18:38:19 +01:00
try :
suppliers [ sup_id ] [ ' products ' ] . append ( p )
2022-05-14 17:05:15 +02:00
suppliers [ sup_id ] [ ' total_amount ' ] . append ( p . amount_cost if p . amount_cost else 0 )
2022-01-13 18:38:19 +01:00
except :
suppliers [ sup_id ] = { }
suppliers [ sup_id ] [ ' products ' ] = [ p ]
2022-01-14 00:00:08 +01:00
suppliers [ sup_id ] [ ' party ' ] = prod_sup . party
2022-05-14 17:05:15 +02:00
suppliers [ sup_id ] [ ' total_amount ' ] = [ p . amount_cost if p . amount_cost else 0 ]
2022-01-12 15:35:56 +01:00
products = suppliers . values ( )
2021-08-26 20:16:55 +02:00
2021-09-13 20:14:58 +02:00
cursor = Transaction ( ) . connection . cursor ( )
query = " select distinct on(p.id) p.id, t.name, p.code, s.effective_date from product_product as p right join stock_move as s on p.id=s.product join product_template as t on p.template=t.id where s.shipment ilike ' stock.shipment.in, % ' and state= ' done ' order by p.id, s.effective_date DESC; "
cursor . execute ( query )
columns = list ( cursor . description )
result = cursor . fetchall ( )
2021-09-24 05:16:20 +02:00
last_purchase = { }
2021-09-13 20:14:58 +02:00
for row in result :
row_dict = { }
for i , col in enumerate ( columns ) :
row_dict [ col . name ] = row [ i ]
2021-09-24 05:16:20 +02:00
last_purchase [ row [ 0 ] ] = row_dict
2021-09-13 20:14:58 +02:00
2021-08-26 20:16:55 +02:00
report_context [ ' group_by_location ' ] = data [ ' group_by_location ' ]
2022-01-12 15:35:56 +01:00
report_context [ ' group_by_supplier ' ] = data [ ' group_by_supplier ' ]
2021-08-26 20:16:55 +02:00
report_context [ ' records ' ] = products
report_context [ ' total_amount ' ] = total_amount
2021-09-24 05:16:20 +02:00
report_context [ ' last_purchase ' ] = last_purchase
2021-08-26 20:16:55 +02:00
report_context [ ' location ' ] = data [ ' location_names ' ]
report_context [ ' stock_date_end ' ] = data [ ' to_date ' ]
report_context [ ' company ' ] = Company ( data [ ' company ' ] )
return report_context
class PrintProductsStart ( ModelView ) :
' Products Start '
__name__ = ' stock_co.print_products.start '
company = fields . Many2One ( ' company.company ' , ' Company ' , required = True )
category = fields . Many2One ( ' product.category ' , ' Category ' )
@staticmethod
def default_company ( ) :
return Transaction ( ) . context . get ( ' company ' )
class PrintProducts ( Wizard ) :
' Warehouse Stock '
__name__ = ' stock_co.print_products '
start = StateView ( ' stock_co.print_products.start ' ,
' stock_co.print_products_start_view_form ' , [
Button ( ' Cancel ' , ' end ' , ' tryton-cancel ' ) ,
Button ( ' Print ' , ' print_ ' , ' tryton-ok ' , default = True ) ,
] )
print_ = StateReport ( ' stock_co.print_products.report ' )
def do_print_ ( self , action ) :
category_id = None
if self . start . category :
category_id = self . start . category . id
data = {
' company ' : self . start . company . id ,
' category ' : category_id ,
}
return action , data
class PrintProductsReport ( Report ) :
' Warehouse Report '
__name__ = ' stock_co.print_products.report '
@classmethod
def get_context ( cls , records , header , data ) :
report_context = super ( ) . get_context ( records , header , data )
pool = Pool ( )
Company = pool . get ( ' company.company ' )
Product = pool . get ( ' product.product ' )
Date_ = Pool ( ) . get ( ' ir.date ' )
dom_products = [
( ' active ' , ' = ' , True ) ,
( ' type ' , ' = ' , ' goods ' ) ,
( ' consumable ' , ' = ' , False ) ,
]
if data [ ' category ' ] :
dom_products . append ( ( ' account_category ' , ' = ' , data [ ' category ' ] ) )
products = Product . search ( dom_products , order = [ ( ' code ' , ' ASC ' ) ] )
report_context [ ' records ' ] = products
report_context [ ' stock_date_end ' ] = Date_ . today ( )
report_context [ ' company ' ] = Company ( data [ ' company ' ] )
return report_context
2021-08-28 18:27:55 +02:00
class WarehouseStockDetailedStart ( ModelView ) :
' Warehouse Stock Detailed Start '
__name__ = ' stock_co.warehouse_stock_detailed.start '
company = fields . Many2One ( ' company.company ' , ' Company ' , required = True )
locations = fields . Many2Many ( ' stock.location ' , None , None , " Locations " ,
domain = [
( ' id ' , ' in ' , Eval ( ' location_storage ' ) ) ,
( ' active ' , ' = ' , True )
] , depends = [ ' location_storage ' ] )
location_storage = fields . One2Many ( ' stock.location ' , None , ' Locations Storage ' )
to_date = fields . Date ( ' To Date ' , required = True )
2022-04-18 20:15:11 +02:00
lot = fields . Boolean ( ' Grouping Lot ' )
2021-08-28 18:27:55 +02:00
@staticmethod
def default_company ( ) :
return Transaction ( ) . context . get ( ' company ' )
@staticmethod
def default_to_date ( ) :
Date_ = Pool ( ) . get ( ' ir.date ' )
return Date_ . today ( )
@staticmethod
def default_location_storage ( ) :
Location = Pool ( ) . get ( ' stock.location ' )
locations = Location . search ( [ ( ' type ' , ' = ' , ' warehouse ' ) ] )
2021-12-29 21:48:04 +01:00
return [ l . storage_location . id for l in locations if l . storage_location . id ]
2021-08-28 18:27:55 +02:00
class WarehouseStockDetailed ( Wizard ) :
' Warehouse Stock Detailed '
__name__ = ' stock_co.warehouse_stock_detailed '
start = StateView ( ' stock_co.warehouse_stock_detailed.start ' ,
' stock_co.warehouse_stock_detailed_view_form ' , [
Button ( ' Cancel ' , ' end ' , ' tryton-cancel ' ) ,
Button ( ' Print ' , ' print_ ' , ' tryton-ok ' , default = True ) ,
] )
print_ = StateReport ( ' stock_co.warehouse_stock_detailed.report ' )
def do_print_ ( self , action ) :
location_ids = None
if self . start . locations :
location_ids = [ l . id for l in self . start . locations ]
data = {
' company ' : self . start . company . id ,
' locations ' : location_ids ,
' to_date ' : self . start . to_date ,
2022-04-18 20:15:11 +02:00
' lot ' : self . start . lot ,
2021-08-28 18:27:55 +02:00
}
return action , data
class WarehouseStockDetailedReport ( Report ) :
' Warehouse Stock Detailed Report '
__name__ = ' stock_co.warehouse_stock_detailed.report '
@classmethod
def get_context ( cls , records , header , data ) :
report_context = super ( ) . get_context ( records , header , data )
pool = Pool ( )
Company = pool . get ( ' company.company ' )
Product = pool . get ( ' product.product ' )
Location = pool . get ( ' stock.location ' )
2022-04-18 20:15:11 +02:00
LotbyLocation = pool . get ( ' stock.lots_by_locations ' )
2021-08-28 18:27:55 +02:00
if data [ ' locations ' ] :
ids_location = data [ ' locations ' ]
locations = Location . browse ( ids_location )
else :
locations = Location . search ( [
( ' type ' , ' = ' , ' warehouse ' )
] )
ids_location = [ l . storage_location . id for l in locations if l . storage_location ]
dom_products = [
( ' active ' , ' = ' , True ) ,
( ' template.active ' , ' = ' , True ) ,
( ' type ' , ' = ' , ' goods ' ) ,
( ' consumable ' , ' = ' , False ) ,
]
stock_context = {
' stock_date_end ' : data [ ' to_date ' ] ,
' locations ' : ids_location ,
}
# dom_products.append(('account_category', '=', data['category']))
2021-08-30 22:39:59 +02:00
cursor = Transaction ( ) . connection . cursor ( )
2021-09-23 15:15:13 +02:00
query = " select distinct on(p.id) p.id, t.name, p.code, t.reference, s.effective_date from product_product as p right join stock_move as s on p.id=s.product join product_template as t on p.template=t.id where s.shipment ilike ' stock.shipment.in, % ' and state= ' done ' order by p.id, s.effective_date DESC "
2021-08-30 22:39:59 +02:00
cursor . execute ( query )
columns = list ( cursor . description )
result = cursor . fetchall ( )
2021-09-24 05:16:20 +02:00
last_purchase = { }
2021-08-30 22:39:59 +02:00
for row in result :
row_dict = { }
for i , col in enumerate ( columns ) :
row_dict [ col . name ] = row [ i ]
2021-09-24 05:16:20 +02:00
last_purchase [ row [ 0 ] ] = row_dict
2021-08-30 22:39:59 +02:00
2021-08-28 18:27:55 +02:00
values = [ ]
2021-09-23 15:15:13 +02:00
add_ = values . append
2021-08-28 18:27:55 +02:00
for l in locations :
stock_context [ ' locations ' ] = [ l . id ]
with Transaction ( ) . set_context ( stock_context ) :
prdts = Product . search ( dom_products , order = [ ( ' code ' , ' ASC ' ) ] )
2022-04-18 20:15:11 +02:00
if data [ ' lot ' ] :
prd_ids = [ p . id for p in prdts ]
prdts = LotbyLocation . search ( [ ( ' product ' , ' in ' , prd_ids ) ] )
2021-08-28 18:27:55 +02:00
for p in prdts :
2021-09-23 15:15:13 +02:00
add_ ( {
2021-08-28 18:27:55 +02:00
' parent_name ' : l . parent . name if l . parent else ' ' ,
' name ' : l . name ,
2022-04-18 20:15:11 +02:00
' product ' : p . product if data [ ' lot ' ] else p ,
' lot ' : p if data [ ' lot ' ] else None ,
2021-08-28 18:27:55 +02:00
} )
2021-08-30 22:39:59 +02:00
2021-08-28 18:27:55 +02:00
products = values
report_context [ ' records ' ] = products
report_context [ ' Decimal ' ] = Decimal
2021-09-24 05:16:20 +02:00
report_context [ ' last_purchase ' ] = last_purchase
2021-08-28 18:27:55 +02:00
report_context [ ' stock_date_end ' ] = data [ ' to_date ' ]
report_context [ ' company ' ] = Company ( data [ ' company ' ] )
return report_context
2021-12-29 17:41:02 +01:00
class WarehouseKardexStockStart ( ModelView ) :
' Warehouse Kardex Stock Start '
__name__ = ' stock_co.warehouse_kardex_stock.start '
company = fields . Many2One ( ' company.company ' , ' Company ' , required = True )
2022-02-07 23:48:18 +01:00
locations = fields . Many2Many ( ' stock.location ' , None , None , " Location " ,
2021-12-29 17:41:02 +01:00
domain = [
( ' type ' , ' in ' , [ ' warehouse ' ] ) ,
( ' active ' , ' = ' , True )
] , required = True )
from_date = fields . Date ( ' From Date ' , required = True )
to_date = fields . Date ( ' To Date ' , required = True )
categories = fields . Many2Many ( ' product.category ' , None , None , ' Categories ' )
@staticmethod
def default_company ( ) :
return Transaction ( ) . context . get ( ' company ' )
@staticmethod
def default_to_date ( ) :
Date_ = Pool ( ) . get ( ' ir.date ' )
return Date_ . today ( )
class WarehouseKardexStock ( Wizard ) :
' Warehouse Kardex Stock '
__name__ = ' stock_co.warehouse_kardex_stock '
start = StateView ( ' stock_co.warehouse_kardex_stock.start ' ,
' stock_co.warehouse_kardex_stock_start_view_form ' , [
Button ( ' Cancel ' , ' end ' , ' tryton-cancel ' ) ,
Button ( ' Print ' , ' print_ ' , ' tryton-ok ' , default = True ) ,
] )
print_ = StateReport ( ' stock_co.warehouse_kardex_stock.report ' )
def do_print_ ( self , action ) :
data = {
' company ' : self . start . company . id ,
2022-02-07 23:48:18 +01:00
# 'location': self.start.location.id,
2021-12-29 17:41:02 +01:00
' from_date ' : self . start . from_date ,
' to_date ' : self . start . to_date ,
' categories ' : [ l . id for l in self . start . categories ] ,
2022-02-07 23:48:18 +01:00
' locations ' : [ l . id for l in self . start . locations ] ,
2021-12-29 17:41:02 +01:00
}
return action , data
class WarehouseKardexReport ( Report ) :
' Warehouse Kardex Report '
__name__ = ' stock_co.warehouse_kardex_stock.report '
@classmethod
def get_context ( cls , records , header , data ) :
report_context = super ( ) . get_context ( records , header , data )
pool = Pool ( )
Company = pool . get ( ' company.company ' )
Product = pool . get ( ' product.product ' )
Location = pool . get ( ' stock.location ' )
2022-02-07 23:48:18 +01:00
warehouses = Location . browse ( data [ ' locations ' ] )
2021-12-29 17:41:02 +01:00
# StockMove = pool.get('stock.move')
2022-02-07 23:48:18 +01:00
id_locations = [ w . storage_location . id for w in warehouses if w . storage_location ]
# input_location = warehouse.input_location.id
# output_location = warehouse.output_location.id
2021-12-29 17:41:02 +01:00
dom_products = [
( ' active ' , ' = ' , True ) ,
( ' template.active ' , ' = ' , True ) ,
( ' type ' , ' = ' , ' goods ' ) ,
( ' consumable ' , ' = ' , False ) ,
2022-04-08 21:25:14 +02:00
( ' quantity ' , ' != ' , 0 ) ,
2021-12-29 17:41:02 +01:00
]
if data [ ' categories ' ] :
dom_products . append ( [ ' AND ' , [ ' OR ' , [
( ' account_category ' , ' in ' , data [ ' categories ' ] ) ,
] , [
( ' categories ' , ' in ' , data [ ' categories ' ] ) ,
] ,
] ] )
stock_context_start = {
' stock_date_end ' : ( data [ ' from_date ' ] - timedelta ( 1 ) ) ,
2022-02-07 23:48:18 +01:00
' locations ' : id_locations ,
2021-12-29 17:41:02 +01:00
}
stock_context_end = {
' stock_date_end ' : data [ ' to_date ' ] ,
2022-02-07 23:48:18 +01:00
' locations ' : id_locations ,
2021-12-29 17:41:02 +01:00
}
2022-01-18 22:23:18 +01:00
products = { }
2021-12-29 17:41:02 +01:00
fields_names = [ ' code ' , ' name ' , ' reference ' , ' quantity ' ]
with Transaction ( ) . set_context ( stock_context_start ) :
products_start = Product . search_read ( dom_products , fields_names = fields_names , order = [ ( ' code ' , ' ASC ' ) ] )
with Transaction ( ) . set_context ( stock_context_end ) :
products_end = Product . search_read ( dom_products , fields_names = fields_names , order = [ ( ' code ' , ' ASC ' ) ] )
2022-01-18 22:23:18 +01:00
for p in products_start :
cls . set_value ( p , ' start ' , products )
for p in products_end :
cls . set_value ( p , ' end ' , products )
# products = {p['id']: p for p in products_start}
# type = {'input': f'and from_location != {output_location} and to_location = {id_location}',
# 'input_dif': f'and from_location = {id_location} and to_location = {input_location}',
# 'output': f'and from_location = {id_location} and to_location != {output_location}',
# 'output_dif': f'and from_location = {output_location} and to_location = {id_location}'
# }
2022-02-07 23:48:18 +01:00
tup_locations = str ( tuple ( id_locations ) ) . replace ( ' , ' , ' ' ) if len (
id_locations ) == 1 else str ( tuple ( id_locations ) )
2022-01-18 22:23:18 +01:00
type = {
2022-02-07 23:48:18 +01:00
' input ' : f ' and to_location in { tup_locations } ' ,
' output ' : f ' and from_location in { tup_locations } ' ,
2022-01-18 22:23:18 +01:00
}
2021-12-29 17:41:02 +01:00
2022-01-18 22:23:18 +01:00
# where product in {tuple(products)}
2021-12-29 17:41:02 +01:00
moves = { }
for k , v in type . items ( ) :
clause = v
2022-01-18 22:23:18 +01:00
query = f """ select s.product as id, p.code, t.name, t.reference, sum(s.quantity) as quantity from stock_move as s
join product_product as p on p . id = s . product
join product_template as t on p . template = t . id
where effective_date > = ' { str(data[ ' from_date ' ])} '
2021-12-29 17:41:02 +01:00
and effective_date < = ' { str(data[ ' to_date ' ])} '
{ clause }
2022-01-18 22:23:18 +01:00
group by s . product , p . code , t . name , t . reference ; """
moves = cls . query_to_dict ( query )
for m , v in moves . items ( ) :
cls . set_value ( v , k , products )
# moves[k] = cls.query_to_dict(query)
# for m, v in moves.items():
# if not m.endswith('dif'):
# continue
#
# for k, value in v.items():
# move = moves[m[0:-4]].get(k, None)
# quantity = 0
# if move:
# quantity = move['quantity']
# moves[m[0:-4]][k] = quantity - value['quantity']
# report_context['products_out'] = moves['output']
# report_context['products_in'] = moves['input']
# report_context['products_start'] = products_start
# report_context['products_end'] = products_end
2022-02-07 23:48:18 +01:00
wh_name = ' '
for l in warehouses :
wh_name + = ( l . name + ' , ' )
2022-01-18 22:23:18 +01:00
report_context [ ' products ' ] = products . values ( )
2022-02-07 23:48:18 +01:00
report_context [ ' warehouse ' ] = wh_name
2021-12-29 17:41:02 +01:00
report_context [ ' company ' ] = Company ( data [ ' company ' ] )
return report_context
2022-01-18 22:23:18 +01:00
@classmethod
def set_value ( cls , p , key , products ) :
defaults = {
' start ' : 0 ,
' input ' : 0 ,
' output ' : 0 ,
' end ' : 0
}
try :
products [ p [ ' id ' ] ] . update ( {
key : p [ ' quantity ' ]
} )
except :
products [ p [ ' id ' ] ] = copy . deepcopy ( defaults )
products [ p [ ' id ' ] ] . update ( {
' code ' : p [ ' code ' ] ,
' name ' : p [ ' name ' ] ,
' reference ' : p [ ' reference ' ] ,
key : p [ ' quantity ' ]
} )
2021-12-29 17:41:02 +01:00
@classmethod
def query_to_dict ( cls , query ) :
cursor = Transaction ( ) . connection . cursor ( )
cursor . execute ( query )
columns = list ( cursor . description )
result = cursor . fetchall ( )
res_dict = { }
for row in result :
row_dict = { }
for i , col in enumerate ( columns ) :
row_dict [ col . name ] = row [ i ]
res_dict [ row [ 0 ] ] = row_dict
return res_dict