|
@@ -18,8 +18,8 @@ MOCK = Namespace("https://gesli.example/runtime-mock/")
|
|
|
class MockBatchRequest(BaseModel):
|
|
class MockBatchRequest(BaseModel):
|
|
|
origin: str
|
|
origin: str
|
|
|
destination: str
|
|
destination: str
|
|
|
- supplier_count: int = Field(default=2, ge=1, le=5)
|
|
|
|
|
- customer_count: int = Field(default=1, ge=0, le=3)
|
|
|
|
|
|
|
+ supplier_count: int = Field(default=4, ge=1, le=8)
|
|
|
|
|
+ customer_count: int = Field(default=2, ge=0, le=5)
|
|
|
evaluation_date: date = date(2026, 7, 20)
|
|
evaluation_date: date = date(2026, 7, 20)
|
|
|
|
|
|
|
|
|
|
|
|
@@ -103,6 +103,19 @@ class LocalMockDataService:
|
|
|
"valid_to": valid_to,
|
|
"valid_to": valid_to,
|
|
|
"status": status,
|
|
"status": status,
|
|
|
"dangerous_goods": row.get("supportsDangerousGoods", "false") == "true",
|
|
"dangerous_goods": row.get("supportsDangerousGoods", "false") == "true",
|
|
|
|
|
+ "relationship_tier": row.get("relationshipTier") or "基础合作",
|
|
|
|
|
+ "relationship_strength": _as_float(row.get("relationshipStrength"), 0.60),
|
|
|
|
|
+ "low_price_access_probability": _as_float(
|
|
|
|
|
+ row.get("lowPriceAccessProbability"), 0.50
|
|
|
|
|
+ ),
|
|
|
|
|
+ "priority_space_probability": _as_float(
|
|
|
|
|
+ row.get("prioritySpaceProbability"), 0.60
|
|
|
|
|
+ ),
|
|
|
|
|
+ "relationship_evidence": (
|
|
|
|
|
+ row.get("relationshipEvidence") or "按标准合作机制执行"
|
|
|
|
|
+ ),
|
|
|
|
|
+ "spot_space_status": row.get("spotSpaceStatus") or "需确认",
|
|
|
|
|
+ "spot_space_teu": _as_float(row.get("spotSpaceTeu")),
|
|
|
"runtime_mock": row.get("quote", "").startswith(str(MOCK)),
|
|
"runtime_mock": row.get("quote", "").startswith(str(MOCK)),
|
|
|
})
|
|
})
|
|
|
quote_rows.sort(
|
|
quote_rows.sort(
|
|
@@ -172,31 +185,32 @@ class LocalMockDataService:
|
|
|
schedule = MOCK[f"schedule-{suffix}"]
|
|
schedule = MOCK[f"schedule-{suffix}"]
|
|
|
quote = MOCK[f"quote-{suffix}"]
|
|
quote = MOCK[f"quote-{suffix}"]
|
|
|
performance = MOCK[f"performance-{suffix}"]
|
|
performance = MOCK[f"performance-{suffix}"]
|
|
|
- supplier_name = f"内存模拟供应商 {token[-3:].upper()}{index + 1}"
|
|
|
|
|
|
|
+ profile = self._supplier_profile(index)
|
|
|
|
|
+ supplier_name = (
|
|
|
|
|
+ f"印度航线Mock{profile['supplier_label']} {token[-3:].upper()}{index + 1}"
|
|
|
|
|
+ )
|
|
|
product_name = (
|
|
product_name = (
|
|
|
- f"{request.origin}-{request.destination}动态Mock方案{index + 1}"
|
|
|
|
|
|
|
+ f"{request.origin}-{request.destination}{profile['product_label']}方案{index + 1}"
|
|
|
)
|
|
)
|
|
|
departure = request.evaluation_date + timedelta(days=8 + index)
|
|
departure = request.evaluation_date + timedelta(days=8 + index)
|
|
|
transit_days = self._transit_days(transport_mode, index)
|
|
transit_days = self._transit_days(transport_mode, index)
|
|
|
arrival = departure + timedelta(days=transit_days)
|
|
arrival = departure + timedelta(days=transit_days)
|
|
|
- cost = round(benchmark * (0.76 + index * 0.025), -2)
|
|
|
|
|
- success_rate = min(0.98, 0.87 + index * 0.035)
|
|
|
|
|
|
|
+ cost = round(benchmark * profile["cost_ratio"], -2)
|
|
|
|
|
+ success_rate = profile["booking_success_rate"]
|
|
|
product_class = (
|
|
product_class = (
|
|
|
GESLI.AirFreightProduct
|
|
GESLI.AirFreightProduct
|
|
|
if transport_mode == "空运"
|
|
if transport_mode == "空运"
|
|
|
else GESLI.ContainerOceanProduct
|
|
else GESLI.ContainerOceanProduct
|
|
|
)
|
|
)
|
|
|
- route_type = "直达" if transport_mode == "空运" and index == 0 else (
|
|
|
|
|
- "直航" if index % 2 == 0 else "中转"
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ route_type = "直达" if transport_mode == "空运" and index < 2 else profile["route_type"]
|
|
|
|
|
|
|
|
triples.extend([
|
|
triples.extend([
|
|
|
(brand, RDF.type, GESLI.ServiceBrand),
|
|
(brand, RDF.type, GESLI.ServiceBrand),
|
|
|
(brand, GESLI.brandCode, Literal(f"MOCK-{token}-{index + 1}")),
|
|
(brand, GESLI.brandCode, Literal(f"MOCK-{token}-{index + 1}")),
|
|
|
(brand, GESLI.brandName, Literal(f"Mock品牌 {index + 1}")),
|
|
(brand, GESLI.brandName, Literal(f"Mock品牌 {index + 1}")),
|
|
|
- (supplier, RDF.type, GESLI.FreightForwarderSupplier),
|
|
|
|
|
|
|
+ (supplier, RDF.type, profile["supplier_class"]),
|
|
|
(supplier, RDFS.label, Literal(supplier_name, lang="zh")),
|
|
(supplier, RDFS.label, Literal(supplier_name, lang="zh")),
|
|
|
- (supplier, GESLI.platformSupplierType, Literal("内存Mock供应商")),
|
|
|
|
|
|
|
+ (supplier, GESLI.platformSupplierType, Literal(profile["supplier_type"])),
|
|
|
(supplier, GESLI.isActivePartner, Literal(True)),
|
|
(supplier, GESLI.isActivePartner, Literal(True)),
|
|
|
(product, RDF.type, product_class),
|
|
(product, RDF.type, product_class),
|
|
|
(product, GESLI.productCode, Literal(f"MOCK-PRODUCT-{suffix}")),
|
|
(product, GESLI.productCode, Literal(f"MOCK-PRODUCT-{suffix}")),
|
|
@@ -204,7 +218,7 @@ class LocalMockDataService:
|
|
|
(product, GESLI.hasServiceBrand, brand),
|
|
(product, GESLI.hasServiceBrand, brand),
|
|
|
(product, GESLI.hasProductPerformanceProfile, performance),
|
|
(product, GESLI.hasProductPerformanceProfile, performance),
|
|
|
(product, GESLI.transportMode, Literal(transport_mode)),
|
|
(product, GESLI.transportMode, Literal(transport_mode)),
|
|
|
- (product, GESLI.serviceForm, Literal("Mock标准服务")),
|
|
|
|
|
|
|
+ (product, GESLI.serviceForm, Literal(profile["service_form"])),
|
|
|
(product, GESLI.routeType, Literal(route_type)),
|
|
(product, GESLI.routeType, Literal(route_type)),
|
|
|
(product, GESLI.originLocation, Literal(request.origin)),
|
|
(product, GESLI.originLocation, Literal(request.origin)),
|
|
|
(product, GESLI.destinationLocation, Literal(request.destination)),
|
|
(product, GESLI.destinationLocation, Literal(request.destination)),
|
|
@@ -216,13 +230,22 @@ class LocalMockDataService:
|
|
|
(offering, GESLI.offeringCode, Literal(f"MOCK-OFFER-{suffix}")),
|
|
(offering, GESLI.offeringCode, Literal(f"MOCK-OFFER-{suffix}")),
|
|
|
(offering, GESLI.offeredBySupplier, supplier),
|
|
(offering, GESLI.offeredBySupplier, supplier),
|
|
|
(offering, GESLI.offeringProduct, product),
|
|
(offering, GESLI.offeringProduct, product),
|
|
|
- (offering, GESLI.offeringChannel, Literal("本地动态Mock")),
|
|
|
|
|
- (offering, GESLI.agencyLevel, Literal("一级模拟代理")),
|
|
|
|
|
- (offering, GESLI.capacityCommitment, Literal(f"模拟可用运力{10 + index * 5}单位")),
|
|
|
|
|
|
|
+ (offering, GESLI.offeringChannel, Literal(profile["offering_channel"])),
|
|
|
|
|
+ (offering, GESLI.agencyLevel, Literal(profile["agency_level"])),
|
|
|
|
|
+ (offering, GESLI.capacityCommitment, Literal(profile["capacity_commitment"])),
|
|
|
(offering, GESLI.capacityAvailable, Literal(True)),
|
|
(offering, GESLI.capacityAvailable, Literal(True)),
|
|
|
|
|
+ (offering, GESLI.spotSpaceStatus, Literal(profile["spot_space_status"])),
|
|
|
|
|
+ (offering, GESLI.spotSpaceTeu, Literal(profile["spot_space_teu"], datatype=XSD.decimal)),
|
|
|
(offering, GESLI.supportsDangerousGoods, Literal(index == 0)),
|
|
(offering, GESLI.supportsDangerousGoods, Literal(index == 0)),
|
|
|
|
|
+ (offering, GESLI.solutionAssuranceScore, Literal(profile["solution_assurance"], datatype=XSD.decimal)),
|
|
|
|
|
+ (offering, GESLI.serviceSupportScore, Literal(profile["service_support_score"], datatype=XSD.decimal)),
|
|
|
|
|
+ (offering, GESLI.relationshipTier, Literal(profile["relationship_tier"])),
|
|
|
|
|
+ (offering, GESLI.relationshipStrength, Literal(profile["relationship_strength"], datatype=XSD.decimal)),
|
|
|
|
|
+ (offering, GESLI.lowPriceAccessProbability, Literal(profile["low_price_access_probability"], datatype=XSD.decimal)),
|
|
|
|
|
+ (offering, GESLI.prioritySpaceProbability, Literal(profile["priority_space_probability"], datatype=XSD.decimal)),
|
|
|
|
|
+ (offering, GESLI.relationshipEvidence, Literal(profile["relationship_evidence"])),
|
|
|
(offering, GESLI.bookingSuccessRate, Literal(success_rate, datatype=XSD.decimal)),
|
|
(offering, GESLI.bookingSuccessRate, Literal(success_rate, datatype=XSD.decimal)),
|
|
|
- (offering, GESLI.spaceReleaseSuccessRate, Literal(success_rate - 0.01, datatype=XSD.decimal)),
|
|
|
|
|
|
|
+ (offering, GESLI.spaceReleaseSuccessRate, Literal(profile["space_release_success_rate"], datatype=XSD.decimal)),
|
|
|
(schedule, RDF.type, GESLI.ScheduledServiceInstance),
|
|
(schedule, RDF.type, GESLI.ScheduledServiceInstance),
|
|
|
(schedule, GESLI.scheduleCode, Literal(f"MOCK-SCHEDULE-{suffix}")),
|
|
(schedule, GESLI.scheduleCode, Literal(f"MOCK-SCHEDULE-{suffix}")),
|
|
|
(schedule, GESLI.scheduleOfProduct, product),
|
|
(schedule, GESLI.scheduleOfProduct, product),
|
|
@@ -247,14 +270,14 @@ class LocalMockDataService:
|
|
|
customer = MOCK[f"customer-{suffix}"]
|
|
customer = MOCK[f"customer-{suffix}"]
|
|
|
trade = MOCK[f"customer-trade-{suffix}"]
|
|
trade = MOCK[f"customer-trade-{suffix}"]
|
|
|
credit = MOCK[f"customer-credit-{suffix}"]
|
|
credit = MOCK[f"customer-credit-{suffix}"]
|
|
|
- customer_name = f"内存模拟客户 {token[-3:].upper()}{index + 1}"
|
|
|
|
|
|
|
+ customer_name = f"印度目的港模拟客户 {token[-3:].upper()}{index + 1}"
|
|
|
triples.extend([
|
|
triples.extend([
|
|
|
(customer, RDF.type, GESLI.Customer),
|
|
(customer, RDF.type, GESLI.Customer),
|
|
|
(customer, RDFS.label, Literal(customer_name, lang="zh")),
|
|
(customer, RDFS.label, Literal(customer_name, lang="zh")),
|
|
|
(customer, GESLI.hasTradeProfile, trade),
|
|
(customer, GESLI.hasTradeProfile, trade),
|
|
|
(customer, GESLI.hasCreditProfile, credit),
|
|
(customer, GESLI.hasCreditProfile, credit),
|
|
|
(trade, RDF.type, GESLI.CustomerTradeProfile),
|
|
(trade, RDF.type, GESLI.CustomerTradeProfile),
|
|
|
- (trade, GESLI.industry, Literal("动态Mock行业")),
|
|
|
|
|
|
|
+ (trade, GESLI.industry, Literal("印度市场Mock行业")),
|
|
|
(trade, GESLI.routeName, Literal(f"{request.origin}-{request.destination}")),
|
|
(trade, GESLI.routeName, Literal(f"{request.origin}-{request.destination}")),
|
|
|
(trade, GESLI.repeatPurchaseCount, Literal(4 + index * 6)),
|
|
(trade, GESLI.repeatPurchaseCount, Literal(4 + index * 6)),
|
|
|
(trade, GESLI.quoteWinRate, Literal(0.5 + index * 0.08, datatype=XSD.decimal)),
|
|
(trade, GESLI.quoteWinRate, Literal(0.5 + index * 0.08, datatype=XSD.decimal)),
|
|
@@ -297,7 +320,128 @@ class LocalMockDataService:
|
|
|
|
|
|
|
|
@staticmethod
|
|
@staticmethod
|
|
|
def _transit_days(transport_mode: str, index: int) -> int:
|
|
def _transit_days(transport_mode: str, index: int) -> int:
|
|
|
- return (3 + index) if transport_mode == "空运" else (14 + index * 2)
|
|
|
|
|
|
|
+ return (3 + index) if transport_mode == "空运" else (16 + index * 2)
|
|
|
|
|
+
|
|
|
|
|
+ @staticmethod
|
|
|
|
|
+ def _supplier_profile(index: int) -> dict:
|
|
|
|
|
+ profiles = [
|
|
|
|
|
+ {
|
|
|
|
|
+ "supplier_label": "船公司直营",
|
|
|
|
|
+ "supplier_class": GESLI.Carrier,
|
|
|
|
|
+ "supplier_type": "船公司",
|
|
|
|
|
+ "product_label": "优先直航",
|
|
|
|
|
+ "route_type": "直航",
|
|
|
|
|
+ "service_form": "优先舱位包柜",
|
|
|
|
|
+ "offering_channel": "船公司直营",
|
|
|
|
|
+ "agency_level": "产品品牌本地分支机构",
|
|
|
|
|
+ "capacity_commitment": "年度协议优先保舱20TEU",
|
|
|
|
|
+ "spot_space_status": "可立即订舱",
|
|
|
|
|
+ "spot_space_teu": 18,
|
|
|
|
|
+ "relationship_tier": "战略合作",
|
|
|
|
|
+ "relationship_strength": 0.96,
|
|
|
|
|
+ "low_price_access_probability": 0.90,
|
|
|
|
|
+ "priority_space_probability": 0.95,
|
|
|
|
|
+ "relationship_evidence": "年度协议、价格窗口直连与优先放舱额度",
|
|
|
|
|
+ "solution_assurance": 0.98,
|
|
|
|
|
+ "service_support_score": 0.94,
|
|
|
|
|
+ "booking_success_rate": 0.97,
|
|
|
|
|
+ "space_release_success_rate": 0.96,
|
|
|
|
|
+ "cost_ratio": 0.91,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "supplier_label": "一级订舱代理",
|
|
|
|
|
+ "supplier_class": GESLI.ShippingAgencyCompany,
|
|
|
|
|
+ "supplier_type": "订舱代理",
|
|
|
|
|
+ "product_label": "稳定直航",
|
|
|
|
|
+ "route_type": "直航",
|
|
|
|
|
+ "service_form": "稳定舱位包柜",
|
|
|
|
|
+ "offering_channel": "一级订舱代理",
|
|
|
|
|
+ "agency_level": "一级代理",
|
|
|
|
|
+ "capacity_commitment": "月度保舱12TEU",
|
|
|
|
|
+ "spot_space_status": "现舱有限",
|
|
|
|
|
+ "spot_space_teu": 8,
|
|
|
|
|
+ "relationship_tier": "核心合作",
|
|
|
|
|
+ "relationship_strength": 0.87,
|
|
|
|
|
+ "low_price_access_probability": 0.82,
|
|
|
|
|
+ "priority_space_probability": 0.86,
|
|
|
|
|
+ "relationship_evidence": "核心代理授权与固定订舱窗口",
|
|
|
|
|
+ "solution_assurance": 0.90,
|
|
|
|
|
+ "service_support_score": 0.90,
|
|
|
|
|
+ "booking_success_rate": 0.94,
|
|
|
|
|
+ "space_release_success_rate": 0.92,
|
|
|
|
|
+ "cost_ratio": 0.86,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "supplier_label": "稳定合作代理",
|
|
|
|
|
+ "supplier_class": GESLI.FreightForwarderSupplier,
|
|
|
|
|
+ "supplier_type": "货代公司",
|
|
|
|
|
+ "product_label": "常规直航",
|
|
|
|
|
+ "route_type": "直航",
|
|
|
|
|
+ "service_form": "标准包柜",
|
|
|
|
|
+ "offering_channel": "长期合作货代",
|
|
|
|
|
+ "agency_level": "稳定合作代理",
|
|
|
|
|
+ "capacity_commitment": "周度滚动确认8TEU",
|
|
|
|
|
+ "spot_space_status": "现舱有限",
|
|
|
|
|
+ "spot_space_teu": 4,
|
|
|
|
|
+ "relationship_tier": "稳定合作",
|
|
|
|
|
+ "relationship_strength": 0.74,
|
|
|
|
|
+ "low_price_access_probability": 0.70,
|
|
|
|
|
+ "priority_space_probability": 0.72,
|
|
|
|
|
+ "relationship_evidence": "长期出货记录与周度保舱协同",
|
|
|
|
|
+ "solution_assurance": 0.83,
|
|
|
|
|
+ "service_support_score": 0.82,
|
|
|
|
|
+ "booking_success_rate": 0.90,
|
|
|
|
|
+ "space_release_success_rate": 0.88,
|
|
|
|
|
+ "cost_ratio": 0.79,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "supplier_label": "市场订舱代理",
|
|
|
|
|
+ "supplier_class": GESLI.ShippingAgencyCompany,
|
|
|
|
|
+ "supplier_type": "订舱代理",
|
|
|
|
|
+ "product_label": "中转经济",
|
|
|
|
|
+ "route_type": "中转",
|
|
|
|
|
+ "service_form": "经济包柜",
|
|
|
|
|
+ "offering_channel": "市场订舱代理",
|
|
|
|
|
+ "agency_level": "二级代理",
|
|
|
|
|
+ "capacity_commitment": "按单票确认舱位",
|
|
|
|
|
+ "spot_space_status": "需确认",
|
|
|
|
|
+ "spot_space_teu": 0,
|
|
|
|
|
+ "relationship_tier": "常规合作",
|
|
|
|
|
+ "relationship_strength": 0.52,
|
|
|
|
|
+ "low_price_access_probability": 0.46,
|
|
|
|
|
+ "priority_space_probability": 0.48,
|
|
|
|
|
+ "relationship_evidence": "按市场舱位和临时报价执行",
|
|
|
|
|
+ "solution_assurance": 0.67,
|
|
|
|
|
+ "service_support_score": 0.68,
|
|
|
|
|
+ "booking_success_rate": 0.84,
|
|
|
|
|
+ "space_release_success_rate": 0.82,
|
|
|
|
|
+ "cost_ratio": 0.72,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "supplier_label": "区域货代",
|
|
|
|
|
+ "supplier_class": GESLI.FreightForwarderSupplier,
|
|
|
|
|
+ "supplier_type": "货代公司",
|
|
|
|
|
+ "product_label": "加班船直航",
|
|
|
|
|
+ "route_type": "直航",
|
|
|
|
|
+ "service_form": "加班船包柜",
|
|
|
|
|
+ "offering_channel": "区域货代",
|
|
|
|
|
+ "agency_level": "合作货代",
|
|
|
|
|
+ "capacity_commitment": "加班船窗口优先确认6TEU",
|
|
|
|
|
+ "spot_space_status": "现舱有限",
|
|
|
|
|
+ "spot_space_teu": 3,
|
|
|
|
|
+ "relationship_tier": "稳定合作",
|
|
|
|
|
+ "relationship_strength": 0.69,
|
|
|
|
|
+ "low_price_access_probability": 0.63,
|
|
|
|
|
+ "priority_space_probability": 0.70,
|
|
|
|
|
+ "relationship_evidence": "区域市场协同与加班船资源预留",
|
|
|
|
|
+ "solution_assurance": 0.80,
|
|
|
|
|
+ "service_support_score": 0.79,
|
|
|
|
|
+ "booking_success_rate": 0.89,
|
|
|
|
|
+ "space_release_success_rate": 0.88,
|
|
|
|
|
+ "cost_ratio": 0.82,
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ return profiles[index % len(profiles)]
|
|
|
|
|
|
|
|
|
|
|
|
|
def _as_float(value: str | None, default: float = 0.0) -> float:
|
|
def _as_float(value: str | None, default: float = 0.0) -> float:
|