This commit is contained in:
2024-07-01 06:01:50 +03:00
parent a6f7a9d65f
commit 386ee7e460
29 changed files with 727 additions and 296 deletions

316
main.py
View File

@@ -1,302 +1,23 @@
from typing import Annotated
from fastapi import FastAPI, Depends
from sqlalchemy import select, func, and_, cast, String
from celery.result import AsyncResult
from fastapi import FastAPI, Depends, Body
from sqlalchemy import select
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload
from starlette.responses import JSONResponse
from backend.session import get_session
from database import DailyStock
from database.sipro import *
from queries.general import get_stocks_data
from background.tasks import *
from updaters.stocks_updater import StockUpdate
app = FastAPI()
def get_marketplace_suppliers_and_company_warehouses(marketplace: Marketplace):
company = marketplace.company
suppliers = set()
company_warehouses = set()
for warehouse in marketplace.warehouses:
for supplier in warehouse.suppliers:
if supplier.is_pseudo:
continue
suppliers.add(supplier)
company_warehouses.update(warehouse.company_warehouses)
if marketplace.sell_warehouse_products:
company_warehouse = company.warehouse
if company_warehouse and not company.is_denco:
company_warehouses.add(company_warehouse)
return suppliers, company_warehouses
# def get_stocks_data(marketplace: Marketplace):
# suppliers, company_warehouses = get_marketplace_suppliers_and_company_warehouses(marketplace)
# supplier_ids = [supplier.id for supplier in suppliers]
# company_warehouse_ids = [warehouse.id for warehouse in company_warehouses]
#
# sell_mixes: bool = marketplace.sell_mixes
# sell_blocks: bool = marketplace.sell_blocks
# sell_warehouse_products: bool = marketplace.sell_warehouse_products
# sell_from_price: int = marketplace.sell_from_price
#
# stmt = (
# select(
# MarketplaceProduct
# )
# .join(
# Product
# )
# .options(
# joinedload(MarketplaceProduct.product)
# )
# .where(
# MarketplaceProduct.marketplace_id == marketplace.id
# )
# )
# supplier_stock_subquery = (
# select(
# func.sum(SupplierProduct.supplier_stock).label('supplier_stock'),
# Product.id.label('product_id')
# )
# .join(
# Product
# )
# .where(
# SupplierProduct.supplier_id.in_(supplier_ids)
# )
# .group_by(
# Product.id
# )
# .subquery()
# )
#
# warehouse_stock_subquery = (
# select(
# func.count(CompanyWarehouseProduct.is_sold).label('warehouse_stock'),
# CompanyWarehouseProduct.product_id.label('product_id')
# )
# .where(
# CompanyWarehouseProduct.is_sold == False,
# CompanyWarehouseProduct.company_warehouse_id.in_(company_warehouse_ids)
# )
# .group_by(
# CompanyWarehouseProduct.product_id
# )
# .subquery()
# )
async def get_stocks_data(session: AsyncSession, marketplace: Marketplace):
company = marketplace.company
suppliers, company_warehouses = get_marketplace_suppliers_and_company_warehouses(marketplace)
supplier_ids = [supplier.id for supplier in suppliers]
company_warehouse_ids = [warehouse.id for warehouse in company_warehouses]
sell_mixes: bool = marketplace.sell_mixes
sell_blocks: bool = marketplace.sell_blocks
sell_warehouse_products: bool = marketplace.sell_warehouse_products
sell_from_price: int = marketplace.sell_from_price
supplier_stock_subquery = (
select(
func.sum(SupplierProduct.supplier_stock).label('supplier_stock'),
SupplierProduct.product_id.label('product_id')
)
.select_from(SupplierProduct)
.join(Product)
.where(SupplierProduct.supplier_id.in_(supplier_ids))
.group_by(SupplierProduct.product_id)
.subquery()
)
warehouse_stock_subquery = (
select(
func.count(CompanyWarehouseProduct.is_sold).label('warehouse_stock'),
CompanyWarehouseProduct.product_id.label('product_id')
)
.select_from(CompanyWarehouseProduct)
.where(
CompanyWarehouseProduct.is_sold == False,
CompanyWarehouseProduct.company_warehouse_id.in_(company_warehouse_ids)
)
.group_by(CompanyWarehouseProduct.product_id)
.subquery()
)
mix_stock_first_subquery = (
select(
func.sum(SupplierProduct.supplier_stock).label('master_stock'),
SupplierProduct.product_id.label('product_id')
)
.select_from(SupplierProduct)
.where(SupplierProduct.supplier_id.in_(supplier_ids))
.group_by(SupplierProduct.product_id)
.subquery()
)
mix_stock_full_subquery = (
select(
func.min(SupplierProduct.in_block).label('mix_stock'),
Product.id.label('product_id')
)
.select_from(Product)
.join(SupplierProduct)
.join(ProductRelation, Product.id == ProductRelation.slave_product_id)
.join(mix_stock_first_subquery, mix_stock_first_subquery.c.product_id == ProductRelation.master_product_id)
.where(
ProductRelation.relation_type == 5,
mix_stock_first_subquery.c.master_stock > 0
)
.group_by(Product.id)
.subquery()
)
is_master_first_subquery = (
select(
ProductRelation.master_product_id,
(func.count(ProductRelation.master_product_id) > 0).label('is_master')
)
.where(
ProductRelation.relation_type == 5
)
.group_by(ProductRelation.master_product_id)
.subquery()
)
is_master_subquery = (
select(
Product.id.label('product_id'),
func.coalesce(is_master_first_subquery.c.is_master, False).label('is_master')
)
.select_from(
Product
)
.outerjoin(
is_master_first_subquery,
Product.id == is_master_first_subquery.c.master_product_id
)
.subquery()
)
in_block_subquery = (
select(
Product.id.label('product_id'),
func.min(SupplierProduct.in_block).label('in_block_value')
)
.select_from(Product)
.join(SupplierProduct)
.where(
SupplierProduct.supplier_id.in_(supplier_ids),
SupplierProduct.supplier_stock > 0
)
.group_by(Product.id)
.subquery()
)
slaves_stock_first_subquery = (
select(
ProductRelation.master_product_id.label('product_id'),
func.sum(SupplierProduct.supplier_stock).label('slaves_stock')
)
.select_from(ProductRelation)
.join(SupplierProduct, and_(
ProductRelation.slave_product_id == SupplierProduct.product_id,
ProductRelation.relation_type == 7
))
.where(SupplierProduct.supplier_id.in_(supplier_ids))
.group_by(ProductRelation.master_product_id)
.subquery()
)
slaves_stock_subquery = (
select(
Product.id.label('product_id'),
slaves_stock_first_subquery.c.slaves_stock.label('slaves_stock')
)
.select_from(Product)
.join(slaves_stock_first_subquery, slaves_stock_first_subquery.c.product_id == Product.id)
.subquery()
)
stmt = (
select(
MarketplaceProduct,
func.coalesce(Product.article, cast(Product.denco_article, String)).label('denco_article'),
MarketplaceProduct.mp_price_bought.label('price_purchase'),
supplier_stock_subquery.c.supplier_stock.label('supplier_stock'),
warehouse_stock_subquery.c.warehouse_stock.label('warehouse_stock'),
mix_stock_full_subquery.c.mix_stock.label('mix_stock'),
in_block_subquery.c.in_block_value.label('in_block_value'),
is_master_subquery.c.is_master.label('is_master'),
slaves_stock_subquery.c.slaves_stock.label('slaves_stock'),
MarketplaceProduct.price_recommended.label('price_recommended'),
MarketplaceProduct.is_archived.label('is_archived')
)
.select_from(MarketplaceProduct)
.join(Product)
.options(joinedload(MarketplaceProduct.product))
.where(MarketplaceProduct.marketplace_id == marketplace.id)
.outerjoin(supplier_stock_subquery, supplier_stock_subquery.c.product_id == MarketplaceProduct.product_id)
.outerjoin(warehouse_stock_subquery, warehouse_stock_subquery.c.product_id == MarketplaceProduct.product_id)
.outerjoin(mix_stock_full_subquery, mix_stock_full_subquery.c.product_id == MarketplaceProduct.product_id)
.outerjoin(in_block_subquery, in_block_subquery.c.product_id == MarketplaceProduct.product_id)
.outerjoin(is_master_subquery, is_master_subquery.c.product_id == MarketplaceProduct.product_id)
.outerjoin(slaves_stock_subquery, slaves_stock_subquery.c.product_id == MarketplaceProduct.product_id)
)
print(stmt.compile(compile_kwargs={
'literal_binds': True
}))
result = await session.execute(stmt)
marketplace_products = result.all()
result = []
for marketplace_product, denco_article, price_purchase, supplier_stock, warehouse_stock, mix_stock, in_block_value, is_master, slaves_stock, price_recommended, is_archived in marketplace_products:
if is_archived or (sell_from_price > price_recommended):
result.append({
'denco_article': denco_article,
'full_stock': 0,
# 'marketplace_product': marketplace_product,
})
continue
is_mix = mix_stock is not None
in_block_value = in_block_value or 1
price_purchase = price_purchase or 0
supplier_stock = supplier_stock or 0
warehouse_stock = warehouse_stock or 0
mix_stock = mix_stock or 0
slaves_stock = slaves_stock or 0
if not sell_warehouse_products:
warehouse_stock = 0
if all([is_mix, slaves_stock > 0]):
mix_stock = 0
balance_limit = price_purchase > company.balance
if balance_limit:
supplier_stock = 0
full_stock = supplier_stock + warehouse_stock
if all([not is_mix, not sell_blocks, in_block_value > 1]):
full_stock = warehouse_stock
if sell_mixes and (not balance_limit):
full_stock += mix_stock
if (not sell_mixes) and is_master:
full_stock = warehouse_stock
if (not sell_mixes) and is_mix:
full_stock = warehouse_stock
if 45 > company.balance:
full_stock = 0
full_stock = max([0, full_stock])
result.append({
'denco_article': denco_article,
'full_stock': full_stock,
# 'marketplace_product': marketplace_product,
})
return result
@app.get("/")
async def root(
session: Annotated[AsyncSession, Depends(get_session)],
@@ -312,6 +33,19 @@ async def root(
return {"message": data}
@app.get("/hello/{name}")
async def say_hello(name: str):
return {"message": f"Hello {name}"}
@app.post("/tasks", status_code=201)
def run_task(payload=Body(...)):
task_type = payload["type"]
task = test_task.delay()
return JSONResponse({"task_id": task.id})
@app.get("/tasks/{task_id}")
def get_status(task_id):
task_result = AsyncResult(task_id)
result = {
"task_id": task_id,
"task_status": task_result.status,
"task_result": task_result.result
}
return JSONResponse(result)