cam-verdict 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.5
2
+ Name: cam-verdict
3
+ Version: 1.0.0
4
+ Summary: CAM — Product Viability Standard: deterministic per-order profit verdicts (TEST_CANDIDATE / HOLD / REJECT) counting all six cost items including a return reserve.
5
+ Project-URL: Homepage, https://kau17033.github.io/cam-product-viability-standard/
6
+ Project-URL: Repository, https://github.com/kau17033/cam-product-viability-standard
7
+ License: MIT
8
+ Keywords: dropshipping,ecommerce,mcp,product-viability,profit-calculator
9
+ Requires-Python: >=3.9
10
+ Description-Content-Type: text/markdown
11
+
12
+ # cam-verdict (Python)
13
+
14
+ The CAM — Product Viability Standard as a Python package. Given a product's
15
+ price and all six cost items (product cost, shipping, marketplace fee,
16
+ return reserve, other variable cost), it returns a deterministic verdict:
17
+
18
+ - `TEST_CANDIDATE` — profit clears the target and every check passes
19
+ - `HOLD` — profit is positive but a check fails, or inputs are incomplete
20
+ - `REJECT` — profit is zero or negative
21
+
22
+ Report form: `CAM verdict: TEST_CANDIDATE — profit ¥5,920 per order`
23
+
24
+ Standard, worked examples, benchmark and verification record:
25
+ https://kau17033.github.io/cam-product-viability-standard/
@@ -0,0 +1,14 @@
1
+ # cam-verdict (Python)
2
+
3
+ The CAM — Product Viability Standard as a Python package. Given a product's
4
+ price and all six cost items (product cost, shipping, marketplace fee,
5
+ return reserve, other variable cost), it returns a deterministic verdict:
6
+
7
+ - `TEST_CANDIDATE` — profit clears the target and every check passes
8
+ - `HOLD` — profit is positive but a check fails, or inputs are incomplete
9
+ - `REJECT` — profit is zero or negative
10
+
11
+ Report form: `CAM verdict: TEST_CANDIDATE — profit ¥5,920 per order`
12
+
13
+ Standard, worked examples, benchmark and verification record:
14
+ https://kau17033.github.io/cam-product-viability-standard/
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cam-verdict"
7
+ version = "1.0.0"
8
+ description = "CAM — Product Viability Standard: deterministic per-order profit verdicts (TEST_CANDIDATE / HOLD / REJECT) counting all six cost items including a return reserve."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ keywords = ["product-viability", "profit-calculator", "dropshipping", "ecommerce", "mcp"]
13
+
14
+ [project.urls]
15
+ Homepage = "https://kau17033.github.io/cam-product-viability-standard/"
16
+ Repository = "https://github.com/kau17033/cam-product-viability-standard"
17
+
18
+ [project.scripts]
19
+ cam-verdict = "cam_verdict.cli:main"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["src/cam_verdict"]
File without changes
@@ -0,0 +1,16 @@
1
+ import json, sys
2
+ from .engine import evaluate
3
+
4
+ def main():
5
+ data = sys.stdin.read() if len(sys.argv) < 2 else open(sys.argv[1], encoding="utf-8").read()
6
+ product = json.loads(data)
7
+ r = evaluate(product)
8
+ if r.get("incomplete"):
9
+ print("CAM verdict: INCOMPLETE — missing items: " + ", ".join(r["missing"]))
10
+ else:
11
+ print(f"CAM verdict: {r['verdict']} — profit ¥{r['profit']} per order")
12
+ print(json.dumps(r, ensure_ascii=False))
13
+ return 0
14
+
15
+ if __name__ == "__main__":
16
+ raise SystemExit(main())
@@ -0,0 +1,39 @@
1
+ """CAM verdict engine — Python port of the canonical JS engine (logic.cjs).
2
+ Verified output-identical on the canonical cases (see test_port.py).
3
+ Criteria defaults mirror the demo: target profit 800, delivery <= 10 days,
4
+ estimate age <= 30 days. All money in JPY per order."""
5
+
6
+ COST_KEYS = ["cost", "shipping", "fee", "returnReserve", "otherVariable"]
7
+
8
+ def evaluate(product, criteria=None, today=None):
9
+ criteria = criteria or {}
10
+ target = criteria.get("targetProfit", 800)
11
+ max_delivery = criteria.get("maxDeliveryDays", 10)
12
+ max_age = criteria.get("maxEstimateAgeDays", 30)
13
+
14
+ price = product.get("price")
15
+ missing = [k for k in COST_KEYS if product.get(k) is None]
16
+ if price is None or missing:
17
+ return {"verdict": "HOLD", "incomplete": True, "profit": None,
18
+ "missing": (["price"] if price is None else []) + missing}
19
+ total_cost = sum(product[k] for k in COST_KEYS)
20
+ profit = price - total_cost
21
+
22
+ checks = {}
23
+ checks["margin"] = profit > 0
24
+ checks["target"] = profit >= target
25
+ dd = product.get("deliveryDays")
26
+ checks["delivery"] = (dd <= max_delivery) if dd is not None else None
27
+ stock = product.get("stock")
28
+ checks["stock"] = (stock is None or stock > 0)
29
+ age = product.get("estimateAgeDays")
30
+ checks["estimateAge"] = (age <= max_age) if age is not None else None
31
+
32
+ if profit <= 0:
33
+ verdict = "REJECT"
34
+ elif any(v is False for v in checks.values()):
35
+ verdict = "HOLD"
36
+ else:
37
+ verdict = "TEST_CANDIDATE"
38
+ return {"verdict": verdict, "incomplete": False, "profit": profit,
39
+ "allowableCpa": profit - target, "checks": checks}
@@ -0,0 +1,20 @@
1
+ import sys
2
+ sys.path.insert(0, "src")
3
+ from cam_verdict.engine import evaluate
4
+
5
+ cases = [
6
+ # vitamin C serum -> HOLD 1162 (estimate 74 days old)
7
+ ({"price": 3980, "cost": 1500, "shipping": 700, "fee": 398, "returnReserve": 160, "otherVariable": 60, "deliveryDays": 5, "stock": 20, "estimateAgeDays": 74}, "HOLD", 1162),
8
+ # cordless cleaner -> TEST_CANDIDATE 5920
9
+ ({"price": 24800, "cost": 14000, "shipping": 1500, "fee": 2480, "returnReserve": 600, "otherVariable": 300, "deliveryDays": 7, "stock": 15, "estimateAgeDays": 10}, "TEST_CANDIDATE", 5920),
10
+ # coffee beans -> REJECT -68
11
+ ({"price": 2980, "cost": 1800, "shipping": 800, "fee": 298, "returnReserve": 100, "otherVariable": 50, "deliveryDays": 3, "stock": 50, "estimateAgeDays": 5}, "REJECT", -68),
12
+ ]
13
+ for p, want_v, want_p in cases:
14
+ r = evaluate(p)
15
+ assert r["verdict"] == want_v and r["profit"] == want_p, (r, want_v, want_p)
16
+ print(f"CAM verdict: {r['verdict']} — profit ¥{r['profit']} per order")
17
+ r = evaluate({"price": 1980, "cost": 900, "shipping": 750, "fee": 198, "otherVariable": 0})
18
+ assert r["incomplete"] and "returnReserve" in r["missing"]
19
+ print("incomplete case OK — missing:", r["missing"])
20
+ print("ALL PASS")