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()