dodil/erp-brick-inventory
DODIL ERP brick: inventory
src/brick_inventory/application/common.py
"""Who may see what, and the shapes the answers share."""
from decimal import Decimal
from typing import Optional
from erp_platform.bricks import Refused
from brick_inventory.application.unit import can
READ, VALUE, AVAILABILITY = "inv:stock:read", "inv:valuation:read", "inv:availability:read"
MONEY_FIELDS = ("value_amount", "unit_cost", "average_cost", "average_cost_after", "value_after", "value_change", "price_difference",
"standard_price", "consumption_value", "price", "amount", "total_value", "cost")
def need_read(caller: dict) -> None:
"""Stock is seen by whoever holds inv:stock:read; to anyone else a warehouse, bin, lot or move is a 404, never a 403."""
if not can(caller, READ):
raise Refused(404, "not found")
def sees_value(caller: dict) -> bool:
return can(caller, VALUE)
def without_values(obj):
"""A caller without inv:valuation:read never sees a cost or a value in any answer."""
if isinstance(obj, dict):
return {k: without_values(v) for k, v in obj.items() if k not in MONEY_FIELDS}
if isinstance(obj, list):
return [without_values(v) for v in obj]
return obj
def shaped(caller: dict, obj):
return obj if sees_value(caller) else without_values(obj)
def need(caller: dict, permission: str, *, as_404: bool = False) -> None:
if not can(caller, permission):
if as_404:
raise Refused(404, "not found")
raise Refused(403, f"missing permission: {permission}")
def num(d) -> Optional[str]:
"""A quantity or amount as the exact string it leaves as (no float); None stays None."""
if d is None:
return None
return format(Decimal(d), "f")
def qstr(d) -> Optional[str]:
"""A quantity without trailing zeros: '144', '0.75'."""
if d is None:
return None
s = format(Decimal(d), "f")
return s.rstrip("0").rstrip(".") if "." in s else s
def capacity_value(v, what: str):
"""A bin's capacity: empty means unlimited; otherwise a quantity above zero with at most four places."""
from brick_inventory.domain.values import check_quantity
if v in (None, "", "null"):
return None
return check_quantity(v, what)