carpet-efficiency / priority_logic.py
DPPATRA's picture
Upload 11 files
78f194c verified
import pandas as pd
import numpy as np
from config import WEIGHTS
REQUIRED_COLS = [
"Name of Product",
"Components Used",
"Quantity of Each Component",
"Oldest Product Required First",
"Priority Assigned",
]
def _normalize_columns(df: pd.DataFrame) -> pd.DataFrame:
df = df.copy()
df.columns = [str(c).strip() for c in df.columns]
return df
def _component_count(series: pd.Series) -> pd.Series:
def _count(x):
if pd.isna(x):
return 0
parts = [p.strip() for p in str(x).split(",") if str(p).strip()]
return len(set(parts)) if parts else 0
return series.apply(_count)
def compute_priority(df: pd.DataFrame, min_qty: int = 50) -> pd.DataFrame:
df = _normalize_columns(df)
missing = [c for c in REQUIRED_COLS if c not in df.columns]
if missing:
raise ValueError(f"Missing required columns: {missing}")
out = df.copy()
out["Oldest Product Required First"] = pd.to_datetime(out["Oldest Product Required First"], errors="coerce")
today = pd.Timestamp.now().normalize()
out["OrderAgeDays"] = (today - pd.to_datetime(out["Oldest Product Required First"], errors="coerce")).dt.days
out["OrderAgeDays"] = out["OrderAgeDays"].fillna(0).clip(lower=0)
if out["OrderAgeDays"].max() > 0:
age_score_01 = out["OrderAgeDays"] / out["OrderAgeDays"].max()
else:
age_score_01 = 0
qty = pd.to_numeric(out["Quantity of Each Component"], errors="coerce").fillna(0)
age_score_01 = np.where(qty >= min_qty, age_score_01, 0)
comp_count = _component_count(out["Components Used"])
if comp_count.max() > 0:
comp_simplicity_01 = 1 - (comp_count / comp_count.max())
else:
comp_simplicity_01 = 0
def manual_to01(x):
if pd.isna(x):
return 0.0
s = str(x).strip().lower()
if s in {"high", "urgent", "yes", "y", "true"}:
return 1.0
try:
return 1.0 if float(s) > 0 else 0.0
except:
return 0.0
manual_01 = out["Priority Assigned"].apply(manual_to01)
w_age = WEIGHTS["AGE_WEIGHT"] / 100.0
w_comp = WEIGHTS["COMPONENT_WEIGHT"] / 100.0
w_man = WEIGHTS["MANUAL_WEIGHT"] / 100.0
out["AgeScore"] = age_score_01 * w_age
if isinstance(comp_simplicity_01, pd.Series):
out["SimplicityScore"] = comp_simplicity_01 * w_comp
else:
out["SimplicityScore"] = comp_simplicity_01
out["ManualScore"] = manual_01 * w_man
out["PriorityScore"] = out["AgeScore"] + out["SimplicityScore"] + out["ManualScore"]
out["ComponentCount"] = comp_count
out["QtyThresholdOK"] = qty >= min_qty
out = out.sort_values(["PriorityScore", "OrderAgeDays"], ascending=[False, False])
return out