feat(fleet): enforce reviewed trips and original fee coverage for dispatch

This commit is contained in:
2026-10-03 04:18:52 +08:00
parent c50e9f97d1
commit 5e683da3b9
162 changed files with 9642 additions and 218 deletions
@@ -0,0 +1,18 @@
package com.baiyue.lastleg.fleet.customer;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(name = "iam-service", contextId = "fleetCustomerClient", url = "${baiyue.clients.iam.url:}")
public interface FleetCustomerClient {
@GetMapping("/internal/iam/finance-customers")
ApiResponse<PageResult<Customer>> customers(@RequestHeader("X-Internal-Service-Token") String token,
@RequestParam("page") long page, @RequestParam("size") long size, @RequestParam("keyword") String keyword,
@RequestParam("status") String status, @RequestParam("customerId") Long customerId);
@GetMapping("/internal/iam/tenants/{customerId}/order-eligibility")
ApiResponse<Eligibility> eligibility(@RequestHeader("X-Internal-Service-Token") String token, @PathVariable("customerId") long customerId);
record Customer(Long id, String tenantCode, String tenantName, String status, String contactName, String contactPhone) { }
record Eligibility(boolean eligible, String tenantStatus, String reason) { }
}
@@ -0,0 +1,39 @@
package com.baiyue.lastleg.fleet.customer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import java.util.List;
@Component
public class FleetCustomerDirectory {
public record Customer(String id, String code, String name, String contactName, String contactPhone) { }
private final FleetCustomerClient client;
private final String token;
public FleetCustomerDirectory(FleetCustomerClient client, @Value("${baiyue.security.internal-service-token}") String token) {
this.client = client; this.token = token;
}
public List<Customer> options(String keyword) { return load(keyword, null); }
public Customer required(long id) {
var customer = load(null, id).stream().filter(row -> row.id().equals(Long.toString(id))).findFirst()
.orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "请选择有效客户"));
try {
var result = client.eligibility(token, id);
if (result == null || !result.successful() || result.data() == null) throw unavailable();
if (!result.data().eligible()) throw new ResponseStatusException(HttpStatus.CONFLICT, "客户尚不具备下单资格,请先完成客户资料审核");
} catch (ResponseStatusException error) { throw error; }
catch (RuntimeException error) { throw unavailable(); }
return customer;
}
private List<Customer> load(String keyword, Long id) {
try {
var result = client.customers(token, 1, 30, keyword == null || keyword.isBlank() ? null : keyword.trim(), "ACTIVE", id);
if (result == null || !result.successful() || result.data() == null) throw unavailable();
return result.data().records().stream().filter(row -> row.id() != null && row.id() > 0 && "ACTIVE".equals(row.status()))
.map(row -> new Customer(row.id().toString(), row.tenantCode(), row.tenantName(), row.contactName(), row.contactPhone())).toList();
} catch (ResponseStatusException error) { throw error; }
catch (RuntimeException error) { throw unavailable(); }
}
private static ResponseStatusException unavailable() { return new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "客户目录暂不可用,请稍后重试"); }
}