Import ClientFlow production v4928.1.5.132.4
This commit is contained in:
@@ -91,6 +91,33 @@ def _money(value: Any) -> str:
|
||||
return f"{_decimal(value):.2f}"
|
||||
|
||||
|
||||
def _strict_decimal(value: Any, field_name: str) -> Decimal:
|
||||
try:
|
||||
if value is None or str(value).strip() == "":
|
||||
raise InvalidOperation()
|
||||
return Decimal(str(value).replace(",", ".").strip())
|
||||
except (InvalidOperation, ValueError):
|
||||
raise ValueError(f"{field_name} inválido.")
|
||||
|
||||
|
||||
def _non_negative_decimal(value: Any, field_name: str, default: str = "0") -> Decimal:
|
||||
if value is None or str(value).strip() == "":
|
||||
value = default
|
||||
d = _strict_decimal(value, field_name)
|
||||
if d < 0:
|
||||
raise ValueError(f"{field_name} não pode ser negativo.")
|
||||
return d
|
||||
|
||||
|
||||
def _positive_decimal(value: Any, field_name: str, default: str = "1") -> Decimal:
|
||||
if value is None or str(value).strip() == "":
|
||||
value = default
|
||||
d = _strict_decimal(value, field_name)
|
||||
if d <= 0:
|
||||
raise ValueError(f"{field_name} deve ser superior a zero.")
|
||||
return d
|
||||
|
||||
|
||||
def _bool(value: Any) -> bool:
|
||||
return str(value or "").lower() in {"1", "true", "yes", "on", "sim", "ativo"}
|
||||
|
||||
@@ -291,6 +318,8 @@ def create_product(data: Dict[str, Any]) -> str:
|
||||
raise ValueError("SKU é obrigatório.")
|
||||
if not name:
|
||||
raise ValueError("Nome do produto é obrigatório.")
|
||||
default_unit_price = _non_negative_decimal(data.get("default_unit_price", data.get("price")), "Preço base")
|
||||
vat_rate = _non_negative_decimal(data.get("vat_rate", "23"), "IVA")
|
||||
with engine.begin() as conn:
|
||||
conn.execute(text("""
|
||||
INSERT INTO products (
|
||||
@@ -307,8 +336,8 @@ def create_product(data: Dict[str, Any]) -> str:
|
||||
"name": name,
|
||||
"category": str(data.get("category") or "Geral").strip() or "Geral",
|
||||
"description": str(data.get("description") or "").strip(),
|
||||
"default_unit_price": _money(data.get("default_unit_price")),
|
||||
"vat_rate": _money(data.get("vat_rate", "23")),
|
||||
"default_unit_price": _money(default_unit_price),
|
||||
"vat_rate": _money(vat_rate),
|
||||
"active": _bool(data.get("active", "true")),
|
||||
"metadata": _json({}),
|
||||
})
|
||||
@@ -323,6 +352,8 @@ def update_product(product_id: str, data: Dict[str, Any]) -> bool:
|
||||
raise ValueError("SKU é obrigatório.")
|
||||
if not name:
|
||||
raise ValueError("Nome do produto é obrigatório.")
|
||||
default_unit_price = _non_negative_decimal(data.get("default_unit_price", data.get("price")), "Preço base")
|
||||
vat_rate = _non_negative_decimal(data.get("vat_rate", "23"), "IVA")
|
||||
with engine.begin() as conn:
|
||||
result = conn.execute(text("""
|
||||
UPDATE products
|
||||
@@ -343,8 +374,8 @@ def update_product(product_id: str, data: Dict[str, Any]) -> bool:
|
||||
"name": name,
|
||||
"category": str(data.get("category") or "Geral").strip() or "Geral",
|
||||
"description": str(data.get("description") or "").strip(),
|
||||
"default_unit_price": _money(data.get("default_unit_price")),
|
||||
"vat_rate": _money(data.get("vat_rate", "23")),
|
||||
"default_unit_price": _money(default_unit_price),
|
||||
"vat_rate": _money(vat_rate),
|
||||
"active": _bool(data.get("active")),
|
||||
})
|
||||
return result.rowcount > 0
|
||||
@@ -378,6 +409,7 @@ def list_opportunity_items(opportunity_id: str) -> List[Dict[str, Any]]:
|
||||
oi.discount_amount,
|
||||
oi.total_price,
|
||||
oi.status,
|
||||
oi.metadata,
|
||||
oi.created_at,
|
||||
oi.updated_at,
|
||||
p.active AS product_active
|
||||
@@ -424,10 +456,12 @@ def add_opportunity_item(
|
||||
name = str(product_name or (product or {}).get("name") or "").strip()
|
||||
if not name:
|
||||
raise ValueError("Produto é obrigatório.")
|
||||
q = _decimal(quantity, "1")
|
||||
price = _decimal(unit_price if unit_price not in {None, ""} else (product or {}).get("default_unit_price"), "0")
|
||||
discount = _decimal(discount_amount, "0")
|
||||
total = max(Decimal("0"), (q * price) - discount)
|
||||
q = _positive_decimal(quantity, "Quantidade", "1")
|
||||
price = _non_negative_decimal(unit_price if unit_price not in {None, ""} else (product or {}).get("default_unit_price"), "Preço unitário", "0")
|
||||
discount = _non_negative_decimal(discount_amount, "Desconto", "0")
|
||||
total = (q * price) - discount
|
||||
if total < 0:
|
||||
raise ValueError("Total da linha não pode ser negativo.")
|
||||
normalized_status = str(status or "INTERESTED").strip().upper()
|
||||
|
||||
with engine.begin() as conn:
|
||||
@@ -474,10 +508,12 @@ def add_opportunity_item(
|
||||
|
||||
def update_opportunity_item(item_id: str, data: Dict[str, Any]) -> Optional[str]:
|
||||
ensure_product_schema()
|
||||
q = _decimal(data.get("quantity"), "1")
|
||||
price = _decimal(data.get("unit_price"), "0")
|
||||
discount = _decimal(data.get("discount_amount"), "0")
|
||||
total = max(Decimal("0"), (q * price) - discount)
|
||||
q = _positive_decimal(data.get("quantity"), "Quantidade", "1")
|
||||
price = _non_negative_decimal(data.get("unit_price"), "Preço unitário", "0")
|
||||
discount = _non_negative_decimal(data.get("discount_amount"), "Desconto", "0")
|
||||
total = (q * price) - discount
|
||||
if total < 0:
|
||||
raise ValueError("Total da linha não pode ser negativo.")
|
||||
status = str(data.get("status") or "INTERESTED").strip().upper()
|
||||
with engine.begin() as conn:
|
||||
row = conn.execute(text("""
|
||||
|
||||
Reference in New Issue
Block a user