| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- import json
- from pathlib import Path
- import unittest
- from app.market import MarketService
- from app.market.models import InquiryRequest
- from app.repository import RDFRepository
- ROOT = Path(__file__).resolve().parents[1]
- HAIER = "https://gesli.example/sample#Haier"
- HISENSE = "https://gesli.example/sample#Hisense"
- INDIA_RETAIL = "https://gesli.example/sample#IndiaMockRetail"
- class MarketEngineTest(unittest.TestCase):
- def setUp(self):
- self.service = MarketService(ROOT, RDFRepository(ROOT))
- def test_default_inquiry_builds_three_ranked_solutions(self):
- result = self.service.recommend(InquiryRequest(customer=HAIER))
- self.assertEqual(
- result["pipeline"],
- {
- "discovered": 9,
- "rejected": 6,
- "feasible": 3,
- "generated_solutions": 3,
- },
- )
- self.assertEqual(result["recommendation"]["solution_type"], "方案优选")
- self.assertIn("方案优选", {candidate["solution_type"] for candidate in result["candidates"]})
- self.assertIn("relationship", result["candidates"][0])
- self.assertEqual(result["weights"]["price"], 0.03)
- self.assertEqual(result["weights"]["spot_space"], 0.15)
- def test_form_only_exposes_routes_with_market_context(self):
- options = self.service.form_options()
- self.assertEqual(options["origins"], ["青岛港", "青岛胶东机场"])
- self.assertEqual(
- options["destinations"],
- ["印度那瓦舍瓦港", "印度金奈港", "汉堡港", "法兰克福机场", "洛杉矶港"],
- )
- self.assertEqual(options["route_types"], ["中转", "直航", "直达"])
- self.assertEqual(len(options["routes"]), 5)
- def test_customer_profile_changes_recommendation(self):
- haier = self.service.recommend(InquiryRequest(customer=HAIER))
- hisense = self.service.recommend(InquiryRequest(customer=HISENSE))
- self.assertEqual(haier["recommendation"]["solution_type"], "方案优选")
- self.assertEqual(hisense["recommendation"]["solution_type"], "方案优选")
- self.assertNotEqual(
- haier["recommendation"]["final_quote_amount"],
- hisense["recommendation"]["final_quote_amount"],
- )
- def test_expired_quotes_are_rejected_with_reasons(self):
- result = self.service.recommend(InquiryRequest(customer=HAIER))
- rejected = {item["quote_no"]: item for item in result["rejected_candidates"]}
- self.assertIn("SQ-EGL-20260710-EXPIRED", rejected)
- self.assertTrue(
- any("报价已于2026-07-18失效" in reason for reason in rejected["SQ-EGL-20260710-EXPIRED"]["reasons"])
- )
- def test_dangerous_goods_uses_only_specialized_candidates(self):
- inquiry = InquiryRequest(
- customer="https://gesli.example/sample#Sailun",
- dangerous_goods=True,
- )
- result = self.service.recommend(inquiry)
- self.assertEqual(result["pipeline"]["feasible"], 3)
- self.assertTrue(
- all("危险品" in candidate["product_name"] for candidate in result["candidates"])
- )
- def test_hamburg_route_builds_three_solutions(self):
- result = self.service.recommend(InquiryRequest(
- customer="https://gesli.example/sample#Midea",
- destination="汉堡港",
- requested_departure_date="2026-07-28",
- max_transit_days=36,
- target_amount=42500,
- ))
- self.assertEqual(result["pipeline"]["feasible"], 3)
- self.assertEqual(result["pipeline"]["rejected"], 1)
- def test_time_sensitive_air_customer_gets_express_solution(self):
- result = self.service.recommend(InquiryRequest(
- customer="https://gesli.example/sample#QingdaoMedTech",
- origin="青岛胶东机场",
- destination="法兰克福机场",
- requested_departure_date="2026-07-27",
- max_transit_days=6,
- target_amount=68000,
- preferred_route_type="直达",
- ))
- self.assertEqual(result["recommendation"]["supplier_name"], "汉莎货运青岛代理")
- def test_india_solution_and_relationship_outweigh_lowest_purchase_price(self):
- result = self.service.recommend(InquiryRequest(
- customer=INDIA_RETAIL,
- destination="印度那瓦舍瓦港",
- requested_departure_date="2026-07-28",
- max_transit_days=30,
- target_amount=46000,
- ))
- top = result["candidates"][0]
- lowest_price = max(result["candidates"], key=lambda item: item["price_score"])
- self.assertEqual(top["solution_type"], "方案优选")
- self.assertEqual(top["supplier_name"], "印度航线Mock船公司直营")
- self.assertLess(top["price_score"], lowest_price["price_score"])
- self.assertGreater(
- top["relationship_advantage_score"],
- lowest_price["relationship_advantage_score"],
- )
- self.assertEqual(top["relationship"]["tier"], "战略合作")
- self.assertEqual(top["relationship"]["supplier_name"], "印度航线Mock船公司直营")
- self.assertEqual(top["relationship"]["supplier_channel"], "船公司直营")
- self.assertEqual(top["spot_space"]["status"], "可立即订舱")
- self.assertEqual(top["spot_space"]["teu"], 18)
- self.assertGreater(top["spot_space_score"], lowest_price["spot_space_score"])
- def test_sales_response_does_not_expose_supplier_cost(self):
- result = self.service.recommend(InquiryRequest(customer=HAIER))
- serialized = json.dumps(result, ensure_ascii=False)
- self.assertNotIn("supplier_cost", serialized)
- self.assertNotIn("supplierCostAmount", serialized)
- self.assertIn("cost_risk_status", serialized)
- def test_decision_audit_is_recorded_as_rdf_assertions(self):
- result = self.service.recommend(InquiryRequest(customer=HAIER))
- audit = self.service.get_audit(result["run_id"])
- self.assertIsNotNone(audit)
- self.assertEqual(audit["candidate_count"], 3)
- self.assertGreaterEqual(audit["rdf_assertions"], 20)
- self.assertIn("business_explanation", audit)
- self.assertIn("现舱", audit["business_explanation"]["selection_basis"])
- if __name__ == "__main__":
- unittest.main()
|