This commit is contained in:
zlwu committed 2026-08-06 09:58:20 +08:00
1 parent 2716c2b6f8
commit f3693be913
140 files changed
+799199 -11262

No files matched your search

+1 -1
View File
@@ -1 +1 @@
58367
96958
+62 -16
View File
@@ -79,6 +79,8 @@ from app.services.pl_plan_service import (
collect_hazard_product_ids,
determine_plan_type,
fetch_hazard_flags_map,
plan_has_hazard_product_exists,
plan_has_incomplete_hazard_cert_exists,
record_plan_change,
resolve_hazard_flags_from_crm,
set_hazard_cert_ready,
@@ -249,9 +251,32 @@ def _generate_notify_message(plan: PlPlan, products: list) -> str:
# =============================================================================
def _plan_product_name_exists(db: Session, tenant_no: str, keyword: str):
"""子查询:计划产品名称模糊匹配。"""
return (
db.query(PlPlanProduct.id)
.filter(
PlPlanProduct.plan_id == PlPlan.id,
PlPlanProduct.tenant_no == tenant_no,
PlPlanProduct.del_flag == 0,
func.lower(PlPlanProduct.product_name).contains(keyword.lower()),
)
.exists()
)
def _plan_plate_match(keyword: str):
"""车牌号 / 挂车号模糊匹配。"""
kw = keyword.lower()
return or_(
func.lower(PlPlan.license_plate).contains(kw),
func.lower(PlPlan.trailer_no).contains(kw),
)
@router.get("/", response_model=PlanListResponse)
def list_plans(
q: Optional[str] = Query(default=None, description="模糊搜索"),
q: Optional[str] = Query(default=None, description="模糊搜索(计划编号/客户名称/产品名称/车牌号)"),
plan_no: Optional[str] = Query(default=None, description="计划编号"),
plan_type: Optional[str] = Query(default=None, alias="planType", description="单据类型"),
follow_status: Optional[str] = Query(default=None, alias="followStatus", description="跟进状态"),
@@ -259,8 +284,19 @@ def list_plans(
archive_status: Optional[str] = Query(default=None, alias="archiveStatus", description="归档状态"),
customer_name: Optional[str] = Query(default=None, alias="customerName", description="客户名称"),
product_name: Optional[str] = Query(default=None, alias="productName", description="产品名称"),
license_plate: Optional[str] = Query(default=None, alias="licensePlate", description="车牌号"),
plan_date_from: Optional[date] = Query(default=None, alias="planDateFrom", description="计划日期开始"),
plan_date_to: Optional[date] = Query(default=None, alias="planDateTo", description="计划日期结束"),
has_hazard_product: Optional[int] = Query(
default=None,
alias="hasHazardProduct",
description="1=仅含易制毒/易制爆产品的计划",
),
cert_upload_status: Optional[str] = Query(
default=None,
alias="certUploadStatus",
description="incomplete=至少一张必需危化证书未上传",
),
page: int = Query(default=1, ge=1),
page_size: int = Query(default=20, ge=1, le=100, alias="pageSize"),
db: Session = Depends(get_db),
@@ -273,12 +309,16 @@ def list_plans(
)
if q:
query = query.filter(
or_(
PlPlan.plan_no.contains(q),
func.lower(PlPlan.customer_name).contains(q.lower()),
q_kw = q.strip()
if q_kw:
query = query.filter(
or_(
PlPlan.plan_no.contains(q_kw),
func.lower(PlPlan.customer_name).contains(q_kw.lower()),
_plan_product_name_exists(db, tenant_no, q_kw),
_plan_plate_match(q_kw),
)
)
)
if plan_no:
query = query.filter(PlPlan.plan_no.contains(plan_no))
@@ -301,16 +341,12 @@ def list_plans(
if product_name:
product_name_kw = product_name.strip()
if product_name_kw:
query = query.filter(
db.query(PlPlanProduct.id)
.filter(
PlPlanProduct.plan_id == PlPlan.id,
PlPlanProduct.tenant_no == tenant_no,
PlPlanProduct.del_flag == 0,
func.lower(PlPlanProduct.product_name).contains(product_name_kw.lower()),
)
.exists()
)
query = query.filter(_plan_product_name_exists(db, tenant_no, product_name_kw))
if license_plate:
plate_kw = license_plate.strip()
if plate_kw:
query = query.filter(_plan_plate_match(plate_kw))
if plan_date_from:
query = query.filter(PlPlan.plan_date >= plan_date_from)
@@ -318,6 +354,12 @@ def list_plans(
if plan_date_to:
query = query.filter(PlPlan.plan_date <= plan_date_to)
if has_hazard_product == 1:
query = query.filter(plan_has_hazard_product_exists(tenant_no))
if (cert_upload_status or "").strip().lower() == "incomplete":
query = query.filter(plan_has_incomplete_hazard_cert_exists(tenant_no))
query = apply_pl_scope(query, PlPlan, user, db, tenant_no)
# 统计总数
@@ -479,11 +521,13 @@ def create_plan(
pickup_lng=payload.pickup_lng,
pickup_lat=payload.pickup_lat,
pickup_time=payload.pickup_time,
pickup_contact=payload.pickup_contact,
pickup_notes=payload.pickup_notes,
destination_address=payload.destination_address,
destination_lng=payload.destination_lng,
destination_lat=payload.destination_lat,
delivery_time=payload.delivery_time,
delivery_contact=payload.delivery_contact,
destination_notes=payload.destination_notes,
follow_user_id=payload.follow_user_id or user.id,
follow_user_name=payload.follow_user_name or user.nick_name,
@@ -563,11 +607,13 @@ def create_plan_full(
pickup_lng=payload.pickup_lng,
pickup_lat=payload.pickup_lat,
pickup_time=payload.pickup_time,
pickup_contact=payload.pickup_contact,
pickup_notes=payload.pickup_notes,
destination_address=payload.destination_address,
destination_lng=payload.destination_lng,
destination_lat=payload.destination_lat,
delivery_time=payload.delivery_time,
delivery_contact=payload.delivery_contact,
destination_notes=payload.destination_notes,
total_amount=calc_plan_total_amount(payload.products or []),
follow_user_id=payload.follow_user_id or user.id,
+13 -1
View File
@@ -52,13 +52,21 @@ def _get_by_token(db: Session, kind: str, token: str):
return header, items
def _resolve_io_order_link_flags(plan: Optional[PlPlan], header) -> tuple[bool, bool]:
"""返回 (作废, 归档)。现场链接实际走入库/出库单公共页。"""
voided = header.status == "voided" or bool(plan and plan.follow_status == "cancelled")
archived = bool(plan and plan.archive_status == "archived")
return voided, archived
def _build_page(db: Session, kind: str, header, items) -> dict:
plan = db.query(PlPlan).filter(PlPlan.id == header.plan_id, PlPlan.del_flag == 0).first()
voided = header.status == "voided" or bool(plan and plan.follow_status == "cancelled")
voided, archived = _resolve_io_order_link_flags(plan, header)
data = order_header_to_dict(
kind, header, items, db=db, public_unit_as_label=True
)
data["voided"] = voided
data["archived"] = archived
data["title"] = "入库单" if kind == "inbound" else "出库单"
return data
@@ -81,6 +89,8 @@ def _make_handlers(kind: str):
page = _build_page(db, kind, header, items)
if page["voided"]:
return error_response(400, "单据已作废,无法提交")
if page["archived"]:
return error_response(400, "运输计划已归档,无法提交")
qty_map = {x.id: Decimal(str(x.actual_qty)) for x in payload.items}
brand_qty_map: dict[str, list[dict]] | None = None
if any(x.brand_qtys is not None for x in payload.items):
@@ -121,6 +131,8 @@ def _make_handlers(kind: str):
page = _build_page(db, kind, header, _items)
if page["voided"]:
return error_response(400, "单据已作废,无法上传附件")
if page["archived"]:
return error_response(400, "运输计划已归档,无法上传附件")
if not file or not file.filename:
return error_response(400, "请选择文件")
try:
+13 -4
View File
@@ -56,9 +56,11 @@ def _get_site_link_by_token(db: Session, token: str) -> PlTransportSiteLink:
return row
def _resolve_plan_voided(db: Session, link: PlTransportSiteLink) -> bool:
plan = db.query(PlPlan).filter(PlPlan.id == link.plan_id, PlPlan.del_flag == 0).first()
return bool(plan and plan.follow_status == "cancelled")
def _resolve_site_link_flags(plan: Optional[PlPlan]) -> tuple[bool, bool]:
"""返回 (作废, 归档)。"""
voided = bool(plan and plan.follow_status == "cancelled")
archived = bool(plan and plan.archive_status == "archived")
return voided, archived
def _resolve_unit_label(unit_map: dict[str, str], unit_code: Optional[str]) -> str:
@@ -141,12 +143,12 @@ def _build_site_product_read(
def _build_public_page(db: Session, link: PlTransportSiteLink) -> PublicTransportSitePageRead:
voided = _resolve_plan_voided(db, link)
plan = (
db.query(PlPlan)
.filter(PlPlan.id == link.plan_id, PlPlan.del_flag == 0)
.first()
)
voided, archived = _resolve_site_link_flags(plan)
plan_product = _resolve_plan_product(db, link)
product_read = _build_site_product_read(db, link, plan_product)
@@ -161,6 +163,7 @@ def _build_public_page(db: Session, link: PlTransportSiteLink) -> PublicTranspor
pickup_lng=plan.pickup_lng if plan else None,
pickup_lat=plan.pickup_lat if plan else None,
pickup_time=plan.pickup_time if plan else None,
pickup_contact=plan.pickup_contact if plan else None,
pickup_notes=plan.pickup_notes if plan else None,
destination_name=plan.destination_name if plan else None,
destination_address=(
@@ -169,12 +172,14 @@ def _build_public_page(db: Session, link: PlTransportSiteLink) -> PublicTranspor
destination_lng=plan.destination_lng if plan else None,
destination_lat=plan.destination_lat if plan else None,
delivery_time=plan.delivery_time if plan else None,
delivery_contact=plan.delivery_contact if plan else None,
destination_notes=plan.destination_notes if plan else None,
products=[product_read],
site_feedback_remark=link.site_feedback_remark,
site_feedback_images=_parse_feedback_images(link.site_feedback_images),
site_feedback_time=link.site_feedback_time,
voided=voided,
archived=archived,
)
@@ -195,6 +200,8 @@ def save_public_site_feedback(
page = _build_public_page(db, link)
if page.voided:
return error_response(400, "运输计划已作废,无法提交回执")
if page.archived:
return error_response(400, "运输计划已归档,无法提交回执")
if payload.site_feedback_images is not None:
link.site_feedback_images = json.dumps(payload.site_feedback_images)
@@ -226,6 +233,8 @@ def upload_public_site_attachment(
page = _build_public_page(db, link)
if page.voided:
return error_response(400, "运输计划已作废,无法上传附件")
if page.archived:
return error_response(400, "运输计划已归档,无法上传附件")
if not file or not file.filename:
return error_response(400, "请选择文件")
+21 -4
View File
@@ -87,6 +87,18 @@ def _format_plan_date(value) -> Optional[str]:
return str(value)
def _resolve_driver_link_flags(
plan: Optional[PlPlan], transport: PlTransport
) -> tuple[bool, bool]:
"""返回 (作废, 归档)。"""
voided = (
(plan is not None and plan.follow_status == "cancelled")
or transport.transport_status == "cancelled"
)
archived = bool(plan is not None and plan.archive_status == "archived")
return voided, archived
def _resolve_other_personnel(transport: PlTransport, plan: Optional[PlPlan]) -> list[PublicTransportPersonnelRead]:
raw = transport.resource_snapshot or (plan.resource_snapshot if plan else None)
snapshot = parse_resource_snapshot(raw)
@@ -237,6 +249,7 @@ def _build_public_page(db: Session, transport: PlTransport) -> PublicTransportPa
)
other_personnel = _resolve_other_personnel(transport, plan)
plan_voided, plan_archived = _resolve_driver_link_flags(plan, transport)
return PublicTransportPageRead(
plan_no=plan.plan_no if plan else transport.transport_no,
@@ -246,6 +259,7 @@ def _build_public_page(db: Session, transport: PlTransport) -> PublicTransportPa
pickup_lng=plan.pickup_lng if plan else None,
pickup_lat=plan.pickup_lat if plan else None,
pickup_time=plan.pickup_time if plan else None,
pickup_contact=plan.pickup_contact if plan else None,
pickup_notes=plan.pickup_notes if plan else None,
destination_name=plan.destination_name if plan else None,
destination_address=(
@@ -254,6 +268,7 @@ def _build_public_page(db: Session, transport: PlTransport) -> PublicTransportPa
destination_lng=plan.destination_lng if plan else None,
destination_lat=plan.destination_lat if plan else None,
delivery_time=plan.delivery_time if plan else None,
delivery_contact=plan.delivery_contact if plan else None,
destination_notes=plan.destination_notes if plan else None,
license_plate=transport.license_plate,
driver_name=transport.driver_name,
@@ -264,10 +279,8 @@ def _build_public_page(db: Session, transport: PlTransport) -> PublicTransportPa
feedback_images=_parse_feedback_images(transport.feedback_images),
feedback_qty=transport.feedback_qty,
feedback_time=transport.feedback_time,
plan_voided=(
(plan is not None and plan.follow_status == "cancelled")
or transport.transport_status == "cancelled"
),
plan_voided=plan_voided,
plan_archived=plan_archived,
)
@@ -288,6 +301,8 @@ def save_public_feedback(
page = _build_public_page(db, transport)
if page.plan_voided:
return error_response(400, "运输计划已作废,无法提交回执")
if page.plan_archived:
return error_response(400, "运输计划已归档,无法提交回执")
if payload.feedback_images is not None:
transport.feedback_images = json.dumps(payload.feedback_images)
@@ -354,6 +369,8 @@ def upload_public_attachment(
page = _build_public_page(db, transport)
if page.plan_voided:
return error_response(400, "运输计划已作废,无法上传附件")
if page.plan_archived:
return error_response(400, "运输计划已归档,无法上传附件")
if not file or not file.filename:
return error_response(400, "请选择文件")
+17 -9
View File
@@ -110,8 +110,10 @@ def _generate_transport_no(db: Session) -> str:
return f"{prefix}{seq:06d}"
def _resolve_driver_info(db: Session, tenant_no: str, driver_id: str) -> Optional[dict]:
def _resolve_driver_info(db: Session, tenant_no: str, driver_id: Optional[str]) -> Optional[dict]:
"""解析司机信息:优先 pl_personnel,兼容旧 pl_driver。"""
if not driver_id:
return None
personnel = (
db.query(PlPersonnel)
.filter(
@@ -279,6 +281,8 @@ def _apply_plan_logistics_from_payload(plan: PlPlan, payload: TransportArrange)
plan.pickup_lat = payload.pickup_lat
if payload.pickup_time is not None:
plan.pickup_time = payload.pickup_time
if payload.pickup_contact is not None:
plan.pickup_contact = payload.pickup_contact
if payload.pickup_notes is not None:
plan.pickup_notes = payload.pickup_notes
if payload.destination_address is not None:
@@ -290,6 +294,8 @@ def _apply_plan_logistics_from_payload(plan: PlPlan, payload: TransportArrange)
plan.destination_lat = payload.destination_lat
if payload.delivery_time is not None:
plan.delivery_time = payload.delivery_time
if payload.delivery_contact is not None:
plan.delivery_contact = payload.delivery_contact
if payload.destination_notes is not None:
plan.destination_notes = payload.destination_notes
@@ -314,7 +320,7 @@ def _apply_transport_arrange_fields(
*,
payload: TransportArrange,
vehicle_info: dict,
driver_info: dict,
driver_info: Optional[dict],
carrier_name: Optional[str],
start_point: Optional[str],
end_point: Optional[str],
@@ -323,9 +329,9 @@ def _apply_transport_arrange_fields(
) -> None:
transport.vehicle_id = payload.vehicle_id
transport.license_plate = vehicle_info.get("license_plate")
transport.driver_id = driver_info["id"]
transport.driver_name = driver_info["name"]
transport.driver_phone = driver_info["phone"]
transport.driver_id = driver_info["id"] if driver_info else None
transport.driver_name = driver_info["name"] if driver_info else None
transport.driver_phone = driver_info["phone"] if driver_info else None
transport.carrier_id = payload.carrier_id or vehicle_info.get("carrier_id")
transport.carrier_name = carrier_name
transport.transport_medium = payload.transport_medium
@@ -551,10 +557,12 @@ def arrange_transport(
# 获取车辆信息
vehicle_info = _get_vehicle_info(db, payload.vehicle_id, tenant_no)
# 获取司机信息(driverId 为人员 pl_personnel.id)
driver_info = _resolve_driver_info(db, tenant_no, payload.driver_id)
if not driver_info:
raise HTTPException(status_code=400, detail="司机不存在")
# 获取司机信息(可选;driverId 为人员 pl_personnel.id)
driver_info = None
if payload.driver_id:
driver_info = _resolve_driver_info(db, tenant_no, payload.driver_id)
if not driver_info:
raise HTTPException(status_code=400, detail="司机不存在")
# 检查产品属性(易制毒/易制爆需要证件,以 CRM 产品主数据为准)
products = db.query(PlPlanProduct).filter(
+19 -3
View File
@@ -1248,6 +1248,16 @@ def create_contract(
return get_contract_detail(db, entity.id, tenant_no=tenant_no)
# 允许编辑的合同状态:草稿 / 审批中 / 已审批(未执行);保存后统一回草稿
CONTRACT_EDITABLE_STATUSES = frozenset({"draft", "approving", "approved"})
def assert_contract_editable_for_update(status: str) -> None:
s = (status or "").strip() or "draft"
if s not in CONTRACT_EDITABLE_STATUSES:
raise ValueError("仅草稿、审批中或已审批(未执行)的合同才能修改")
def update_contract(
db: Session,
contract_id: str,
@@ -1262,8 +1272,8 @@ def update_contract(
old = _get_contract_row_in_scope(db, contract_id, tenant_no=tenant_no, user_info=user_info)
if not old:
raise ValueError("合同不存在")
if old.status != "draft":
raise ValueError("只有草稿状态的合同才能修改")
prev_status = (old.status or "").strip() or "draft"
assert_contract_editable_for_update(prev_status)
products = _get_field(data, "products", "productList")
product_rows = [dict(p) for p in products] if products is not None else None
@@ -1278,12 +1288,18 @@ def update_contract(
contract_type = (_get_field(data, "contract_type", "contractType") or old.contract_type or "sale").strip()
old.contract_type = contract_type
old.approval_status = None
if prev_status == "approving":
delete_pending_approvals(db, contract_id)
_apply_contract_entity_fields(
old, data, db=db, tenant_no=tenant_no, user_id=user_id, is_create=False
)
# 编辑保存后统一回草稿(含审批中 / 已审批未执行)
old.status = "draft"
old.approval_status = None
products_to_check = (
product_rows
if product_rows is not None
+4 -3
View File
@@ -941,10 +941,11 @@ def list_product_options(
CrmProduct.status == "on",
)
# 下拉选项供合同/报价等选用,不做 create_by 过滤(产品管理分页列表仍保留数据权限)
# keyword 仅按产品名称模糊匹配(不匹配编号,避免短数字如「32」误命中 SXWL00732x)
_ = user_info
if keyword:
like = f"%{keyword}%"
q = q.filter(or_(CrmProduct.product_name.like(like), CrmProduct.product_no.like(like)))
kw = (keyword or "").strip()
if kw:
q = q.filter(CrmProduct.product_name.like(f"%{kw}%"))
if category_id:
q = q.filter(CrmProduct.category_id == category_id)
q = q.order_by(CrmProduct.create_time.desc())
+2
View File
@@ -295,11 +295,13 @@ class PlPlan(Base):
pickup_lng = Column(DECIMAL(10, 6), nullable=True, comment="取货经度")
pickup_lat = Column(DECIMAL(10, 6), nullable=True, comment="取货纬度")
pickup_time = Column(DateTime, nullable=True, comment="取货时间")
pickup_contact = Column(String(200), nullable=True, comment="取货联系方式")
pickup_notes = Column(String(500), nullable=True, comment="取货注意事项")
destination_address = Column(String(500), nullable=True, comment="目的地地址")
destination_lng = Column(DECIMAL(10, 6), nullable=True, comment="送货经度")
destination_lat = Column(DECIMAL(10, 6), nullable=True, comment="送货纬度")
delivery_time = Column(DateTime, nullable=True, comment="送达时间")
delivery_contact = Column(String(200), nullable=True, comment="送货联系方式")
destination_notes = Column(String(500), nullable=True, comment="目的地注意事项")
transport_id = Column(String(64), nullable=True, comment="运输ID")
transport_no = Column(String(32), nullable=True, comment="运输编号")
+1 -1
View File
@@ -184,6 +184,6 @@ class ProductOptionsBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
keyword: Optional[str] = Field(default=None, description="搜索关键词")
keyword: Optional[str] = Field(default=None, description="搜索关键词(仅产品名称模糊匹配)")
category_id: Optional[str] = Field(default=None, alias="categoryId", description="分类ID")
limit: Optional[int] = Field(default=None, ge=1, le=500, description="返回条数上限(空则全量)")
+2
View File
@@ -91,12 +91,14 @@ class IoOrderRead(BaseModel):
pickup_lng: Optional[float] = Field(default=None, alias="pickupLng")
pickup_lat: Optional[float] = Field(default=None, alias="pickupLat")
pickup_time: Optional[datetime] = Field(default=None, alias="pickupTime")
pickup_contact: Optional[str] = Field(default=None, alias="pickupContact")
pickup_notes: Optional[str] = Field(default=None, alias="pickupNotes")
destination_name: Optional[str] = Field(default=None, alias="destinationName")
destination_address: Optional[str] = Field(default=None, alias="destinationAddress")
destination_lng: Optional[float] = Field(default=None, alias="destinationLng")
destination_lat: Optional[float] = Field(default=None, alias="destinationLat")
delivery_time: Optional[datetime] = Field(default=None, alias="deliveryTime")
delivery_contact: Optional[str] = Field(default=None, alias="deliveryContact")
destination_notes: Optional[str] = Field(default=None, alias="destinationNotes")
create_time: Optional[datetime] = Field(default=None, alias="createTime")
update_time: Optional[datetime] = Field(default=None, alias="updateTime")
+15 -1
View File
@@ -132,11 +132,13 @@ class PlanBase(BaseModel):
pickup_lng: Optional[Decimal] = Field(default=None, alias="pickupLng", description="取货经度")
pickup_lat: Optional[Decimal] = Field(default=None, alias="pickupLat", description="取货纬度")
pickup_time: OptionalPlanDateTime = Field(default=None, alias="pickupTime", description="取货时间")
pickup_contact: Optional[str] = Field(default=None, max_length=200, alias="pickupContact", description="取货联系方式")
pickup_notes: Optional[str] = Field(default=None, max_length=500, alias="pickupNotes", description="取货注意事项")
destination_address: Optional[str] = Field(default=None, max_length=500, alias="destinationAddress", description="目的地地址")
destination_lng: Optional[Decimal] = Field(default=None, alias="destinationLng", description="送货经度")
destination_lat: Optional[Decimal] = Field(default=None, alias="destinationLat", description="送货纬度")
delivery_time: OptionalPlanDateTime = Field(default=None, alias="deliveryTime", description="送达时间")
delivery_contact: Optional[str] = Field(default=None, max_length=200, alias="deliveryContact", description="送货联系方式")
destination_notes: Optional[str] = Field(default=None, max_length=500, alias="destinationNotes", description="目的地注意事项")
notify_message: Optional[str] = Field(default=None, alias="notifyMessage", description="通知信息")
follow_user_id: Optional[str] = Field(default=None, alias="followUserId", description="跟进人ID")
@@ -193,11 +195,13 @@ class PlanUpdate(BaseModel):
pickup_lng: Optional[Decimal] = Field(default=None, alias="pickupLng")
pickup_lat: Optional[Decimal] = Field(default=None, alias="pickupLat")
pickup_time: OptionalPlanDateTime = Field(default=None, alias="pickupTime")
pickup_contact: Optional[str] = Field(default=None, max_length=200, alias="pickupContact")
pickup_notes: Optional[str] = Field(default=None, max_length=500, alias="pickupNotes")
destination_address: Optional[str] = Field(default=None, max_length=500, alias="destinationAddress")
destination_lng: Optional[Decimal] = Field(default=None, alias="destinationLng")
destination_lat: Optional[Decimal] = Field(default=None, alias="destinationLat")
delivery_time: OptionalPlanDateTime = Field(default=None, alias="deliveryTime")
delivery_contact: Optional[str] = Field(default=None, max_length=200, alias="deliveryContact")
destination_notes: Optional[str] = Field(default=None, max_length=500, alias="destinationNotes")
notify_message: Optional[str] = Field(default=None, alias="notifyMessage")
follow_user_id: Optional[str] = Field(default=None, alias="followUserId")
@@ -292,15 +296,25 @@ class PlanCreateFull(PlanCreate):
class PlanListQuery(BaseModel):
q: Optional[str] = Field(default=None, description="模糊搜索计划号/客户名称")
q: Optional[str] = Field(default=None, description="模糊搜索计划号/客户名称/产品名称/车牌号")
plan_no: Optional[str] = Field(default=None, alias="planNo", description="计划编号")
plan_type: Optional[str] = Field(default=None, alias="planType", description="单据类型")
follow_status: Optional[str] = Field(default=None, alias="followStatus", description="跟进状态")
transport_status: Optional[str] = Field(default=None, alias="transportStatus", description="运输状态")
archive_status: Optional[str] = Field(default=None, alias="archiveStatus", description="归档状态")
customer_name: Optional[str] = Field(default=None, alias="customerName", description="客户名称")
product_name: Optional[str] = Field(default=None, alias="productName", description="产品名称")
license_plate: Optional[str] = Field(default=None, alias="licensePlate", description="车牌号")
plan_date_from: Optional[date] = Field(default=None, alias="planDateFrom", description="计划日期开始")
plan_date_to: Optional[date] = Field(default=None, alias="planDateTo", description="计划日期结束")
has_hazard_product: Optional[int] = Field(
default=None, alias="hasHazardProduct", description="1=仅含易制毒/易制爆产品的计划"
)
cert_upload_status: Optional[str] = Field(
default=None,
alias="certUploadStatus",
description="incomplete=至少一张必需危化证书未上传",
)
page: int = Field(default=1, ge=1, description="页码")
page_size: int = Field(default=20, ge=1, le=100, alias="pageSize", description="每页数量")
model_config = {"populate_by_name": True}
+9 -1
View File
@@ -46,18 +46,20 @@ class TransportCreate(TransportBase):
class TransportArrange(BaseModel):
vehicle_id: str = Field(..., alias="vehicleId", description="车辆ID")
driver_id: str = Field(..., alias="driverId", description="司机ID")
driver_id: Optional[str] = Field(default=None, alias="driverId", description="司机ID(可选)")
carrier_id: Optional[str] = Field(default=None, alias="carrierId", description="承运商ID")
transport_medium: Optional[str] = Field(default=None, alias="transportMedium", description="运输介质")
pickup_address: Optional[str] = Field(default=None, alias="pickupAddress", description="取货地址")
pickup_lng: Optional[Decimal] = Field(default=None, alias="pickupLng", description="取货经度")
pickup_lat: Optional[Decimal] = Field(default=None, alias="pickupLat", description="取货纬度")
pickup_time: OptionalPlanDateTime = Field(default=None, alias="pickupTime", description="取货时间")
pickup_contact: Optional[str] = Field(default=None, max_length=200, alias="pickupContact", description="取货联系方式")
pickup_notes: Optional[str] = Field(default=None, alias="pickupNotes", description="取货注意事项")
destination_address: Optional[str] = Field(default=None, alias="destinationAddress", description="送货地址")
destination_lng: Optional[Decimal] = Field(default=None, alias="destinationLng", description="送货经度")
destination_lat: Optional[Decimal] = Field(default=None, alias="destinationLat", description="送货纬度")
delivery_time: OptionalPlanDateTime = Field(default=None, alias="deliveryTime", description="送达时间")
delivery_contact: Optional[str] = Field(default=None, max_length=200, alias="deliveryContact", description="送货联系方式")
destination_notes: Optional[str] = Field(default=None, alias="destinationNotes", description="送货注意事项")
start_point: Optional[str] = Field(default=None, alias="startPoint", description="运输起点(兼容,等同取货地址)")
end_point: Optional[str] = Field(default=None, alias="endPoint", description="运输终点(兼容,等同送货地址)")
@@ -256,12 +258,14 @@ class PublicTransportPageRead(BaseModel):
pickup_lng: Optional[Decimal] = Field(default=None, alias="pickupLng")
pickup_lat: Optional[Decimal] = Field(default=None, alias="pickupLat")
pickup_time: Optional[datetime] = Field(default=None, alias="pickupTime")
pickup_contact: Optional[str] = Field(default=None, alias="pickupContact")
pickup_notes: Optional[str] = Field(default=None, alias="pickupNotes")
destination_name: Optional[str] = Field(default=None, alias="destinationName")
destination_address: Optional[str] = Field(default=None, alias="destinationAddress")
destination_lng: Optional[Decimal] = Field(default=None, alias="destinationLng")
destination_lat: Optional[Decimal] = Field(default=None, alias="destinationLat")
delivery_time: Optional[datetime] = Field(default=None, alias="deliveryTime")
delivery_contact: Optional[str] = Field(default=None, alias="deliveryContact")
destination_notes: Optional[str] = Field(default=None, alias="destinationNotes")
license_plate: Optional[str] = Field(default=None, alias="licensePlate")
driver_name: Optional[str] = Field(default=None, alias="driverName")
@@ -275,6 +279,7 @@ class PublicTransportPageRead(BaseModel):
feedback_qty: Optional[Decimal] = Field(default=None, alias="feedbackQty", description="回传数量")
feedback_time: Optional[datetime] = Field(default=None, alias="feedbackTime")
plan_voided: bool = Field(default=False, alias="planVoided")
plan_archived: bool = Field(default=False, alias="planArchived")
model_config = {"populate_by_name": True}
@@ -289,18 +294,21 @@ class PublicTransportSitePageRead(BaseModel):
pickup_lng: Optional[Decimal] = Field(default=None, alias="pickupLng")
pickup_lat: Optional[Decimal] = Field(default=None, alias="pickupLat")
pickup_time: Optional[datetime] = Field(default=None, alias="pickupTime")
pickup_contact: Optional[str] = Field(default=None, alias="pickupContact")
pickup_notes: Optional[str] = Field(default=None, alias="pickupNotes")
destination_name: Optional[str] = Field(default=None, alias="destinationName")
destination_address: Optional[str] = Field(default=None, alias="destinationAddress")
destination_lng: Optional[Decimal] = Field(default=None, alias="destinationLng")
destination_lat: Optional[Decimal] = Field(default=None, alias="destinationLat")
delivery_time: Optional[datetime] = Field(default=None, alias="deliveryTime")
delivery_contact: Optional[str] = Field(default=None, alias="deliveryContact")
destination_notes: Optional[str] = Field(default=None, alias="destinationNotes")
products: list[PublicTransportPlanProductRead] = Field(default_factory=list)
site_feedback_remark: Optional[str] = Field(default=None, alias="siteFeedbackRemark")
site_feedback_images: list[str] = Field(default_factory=list, alias="siteFeedbackImages")
site_feedback_time: Optional[datetime] = Field(default=None, alias="siteFeedbackTime")
voided: bool = False
archived: bool = False
model_config = {"populate_by_name": True}
+13 -3
View File
@@ -16,8 +16,18 @@ class ProductSnapshot:
specification: str | None
def resolve_crm_product(db: Session, tenant_no: str, product_id: str) -> ProductSnapshot:
"""校验 CRM 产品并返回名称/规格快照。新建单据 product_id 必填。"""
def resolve_crm_product(
db: Session,
tenant_no: str,
product_id: str,
*,
require_on_shelf: bool = True,
) -> ProductSnapshot:
"""校验 CRM 产品并返回名称/规格快照。新建单据 product_id 必填。
require_on_shelf=False 用于运输计划联动地磅等历史单据场景:
合同/计划中的产品可能已下架,但仍允许按主数据快照继续业务。
"""
pid = (product_id or "").strip()
if not pid:
raise HTTPException(
@@ -31,7 +41,7 @@ def resolve_crm_product(db: Session, tenant_no: str, product_id: str) -> Product
status_code=status.HTTP_400_BAD_REQUEST,
detail="产品不存在或不可用",
)
if row.status != "on":
if require_on_shelf and row.status != "on":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="产品已下架,请重新选择",
@@ -214,7 +214,7 @@ def _create_db_plan(
dept_id: str,
contributed_qty: float,
) -> DbPurchasePlan:
snapshot = resolve_crm_product(db, tenant_no, product.product_id)
snapshot = resolve_crm_product(db, tenant_no, product.product_id, require_on_shelf=False)
db_plan = DbPurchasePlan(
id=generate_uuid(),
tenant_no=tenant_no,
@@ -256,7 +256,7 @@ def _create_db_inventory(
user_id: Optional[str],
dept_id: str,
) -> DbInboundOutbound:
snapshot = resolve_crm_product(db, tenant_no, product.product_id)
snapshot = resolve_crm_product(db, tenant_no, product.product_id, require_on_shelf=False)
status_value = "待入库" if business_type == "入库" else "待出库"
inventory_plan_no = ((db_plan.plan_no if db_plan else plan.plan_no) or "").strip() or None
remark = f"运输计划 {plan.plan_no}"
@@ -132,6 +132,18 @@ def get_settlement_by_transport_id(
}
def unsettled_plans_q_filter(q: str):
"""简易搜索:计划编号 / 客户(供应商) / 车牌 / 承运商名称。"""
return or_(
PlPlan.plan_no.contains(q),
PlPlan.customer_name.contains(q),
PlPlan.supplier_name.contains(q),
PlPlan.license_plate.contains(q),
PlTransport.license_plate.contains(q),
PlTransport.carrier_name.contains(q),
)
def list_unsettled_plans(
db: Session,
*,
@@ -163,13 +175,7 @@ def list_unsettled_plans(
)
if q:
query = query.filter(
or_(
PlPlan.plan_no.contains(q),
PlPlan.customer_name.contains(q),
PlPlan.supplier_name.contains(q),
)
)
query = query.filter(unsettled_plans_q_filter(q))
if carrier_id:
query = query.filter(PlTransport.carrier_id == carrier_id)
if plan_type:
@@ -477,12 +477,14 @@ def merge_plan_logistics_into_order(data: dict, plan: Optional[PlPlan]) -> None:
data.setdefault("pickupLng", None)
data.setdefault("pickupLat", None)
data.setdefault("pickupTime", None)
data.setdefault("pickupContact", None)
data.setdefault("pickupNotes", None)
data.setdefault("destinationName", None)
data.setdefault("destinationAddress", None)
data.setdefault("destinationLng", None)
data.setdefault("destinationLat", None)
data.setdefault("deliveryTime", None)
data.setdefault("deliveryContact", None)
data.setdefault("destinationNotes", None)
return
data["businessType"] = PLAN_TYPE_BUSINESS_LABEL.get(plan.plan_type, plan.plan_type)
@@ -491,12 +493,14 @@ def merge_plan_logistics_into_order(data: dict, plan: Optional[PlPlan]) -> None:
data["pickupLng"] = plan.pickup_lng
data["pickupLat"] = plan.pickup_lat
data["pickupTime"] = plan.pickup_time
data["pickupContact"] = plan.pickup_contact
data["pickupNotes"] = plan.pickup_notes
data["destinationName"] = plan.destination_name
data["destinationAddress"] = plan.destination_address or plan.destination_name
data["destinationLng"] = plan.destination_lng
data["destinationLat"] = plan.destination_lat
data["deliveryTime"] = plan.delivery_time
data["deliveryContact"] = plan.delivery_contact
data["destinationNotes"] = plan.destination_notes
+78 -6
View File
@@ -5,9 +5,11 @@ from decimal import Decimal
from typing import Optional, Union
from fastapi import HTTPException
from sqlalchemy import and_, exists, func, or_, select
from sqlalchemy.orm import Session
from app.core.utils import generate_uuid
from app.models.crm_models import CrmProduct
from app.models.pl_models import (
PlCarrier,
PlFreightSettlement,
@@ -154,7 +156,7 @@ def _apply_vehicle_snapshot_to_plan_transport(
plan: PlPlan,
transport: Optional[PlTransport],
vehicle: PlVehicle,
driver_id: str,
driver_id: Optional[str],
) -> None:
snapshot = build_transport_resource_snapshot(
db,
@@ -170,7 +172,8 @@ def _resolve_driver(
tenant_no: str,
vehicle_id: str,
driver_id: Optional[str],
) -> tuple[str, str, Optional[str]]:
) -> tuple[Optional[str], Optional[str], Optional[str]]:
"""解析司机:显式选择优先,否则取车辆关联司机;均无则允许为空。"""
if driver_id:
personnel = (
db.query(PlPersonnel)
@@ -207,7 +210,7 @@ def _resolve_driver(
if personnel:
return personnel.id, personnel.personnel_name, personnel.phone_no
raise HTTPException(status_code=400, detail="请选择司机或确保车辆已关联默认司机")
return None, None, None
def _calc_freight_amount(
@@ -293,6 +296,66 @@ def plan_has_hazard_products(
return bool(collect_hazard_product_ids(db, tenant_no, products))
def _cert_url_blank(column):
"""证书 URL 为空(NULL / 空串 / 纯空白)。"""
return func.nullif(func.trim(func.coalesce(column, "")), "").is_(None)
def plan_has_hazard_product_exists(tenant_no: str):
"""列表筛选:计划下存在 CRM 标识为易制毒/易制爆的产品。"""
return exists(
select(PlPlanProduct.id)
.select_from(PlPlanProduct)
.join(
CrmProduct,
and_(
CrmProduct.id == PlPlanProduct.product_id,
CrmProduct.tenant_no == tenant_no,
CrmProduct.del_flag == 0,
),
)
.where(
PlPlanProduct.plan_id == PlPlan.id,
PlPlanProduct.tenant_no == tenant_no,
PlPlanProduct.del_flag == 0,
or_(CrmProduct.is_toxic == 1, CrmProduct.is_explosive == 1),
)
)
def plan_has_incomplete_hazard_cert_exists(tenant_no: str):
"""列表筛选:存在危化产品且至少一张必需证书未上传。"""
toxic_incomplete = and_(
CrmProduct.is_toxic == 1,
or_(
_cert_url_blank(PlPlanProduct.purchase_cert_url),
_cert_url_blank(PlPlanProduct.transport_cert_url),
),
)
explosive_incomplete = and_(
CrmProduct.is_explosive == 1,
_cert_url_blank(PlPlanProduct.legal_use_cert_url),
)
return exists(
select(PlPlanProduct.id)
.select_from(PlPlanProduct)
.join(
CrmProduct,
and_(
CrmProduct.id == PlPlanProduct.product_id,
CrmProduct.tenant_no == tenant_no,
CrmProduct.del_flag == 0,
),
)
.where(
PlPlanProduct.plan_id == PlPlan.id,
PlPlanProduct.tenant_no == tenant_no,
PlPlanProduct.del_flag == 0,
or_(toxic_incomplete, explosive_incomplete),
)
)
def collect_hazard_product_ids(
db: Session,
tenant_no: str,
@@ -565,7 +628,16 @@ def _resolve_transport_context(
plan: PlPlan,
transport_payload: PlanTransportCreateBlock,
products: list[PlPlanProduct],
) -> tuple[PlVehicle, str, str, Optional[str], Optional[str], Optional[str], Decimal, Optional[Decimal]]:
) -> tuple[
PlVehicle,
Optional[str],
Optional[str],
Optional[str],
Optional[str],
Optional[str],
Decimal,
Optional[Decimal],
]:
vehicle = (
db.query(PlVehicle)
.filter(
@@ -619,8 +691,8 @@ def _apply_payload_to_transport_row(
transport: PlTransport,
*,
vehicle: PlVehicle,
driver_id: str,
driver_name: str,
driver_id: Optional[str],
driver_name: Optional[str],
driver_phone: Optional[str],
carrier_id: Optional[str],
carrier_name: Optional[str],
+26 -8
View File
@@ -134,50 +134,68 @@
"132": "crm_supplier_hazard.py",
"133": "Community 133",
"134": "Community 134",
"135": "post.py",
"135": "unsettled_plans_q_filter",
"136": "Community 136",
"137": "statistics.py",
"138": "Community 138",
"139": "get_current_user_by_token",
"140": "Community 140",
"141": "PlTransport",
"142": "Community 142",
"143": "SysEthnic",
"145": "minio_url.py",
"144": "dict_data.py",
"145": "resolve_crm_product",
"146": "__init__.py",
"147": "Community 147",
"148": "storage.py",
"149": "Community 149",
"150": "apply_site_feedback",
"151": "Community 151",
"152": "response.py",
"153": "Community 153",
"154": "PlCarrier",
"154": "response.py",
"155": "Community 155",
"156": "utils.py",
"157": "Community 157",
"158": "Community 158",
"159": "minio_url.py",
"159": "customer_update",
"160": "register_local_callback",
"161": "backfill_crm_contract_attachment_urls.py",
"164": "ethnic.py",
"162": ".to_tenant_user_dict",
"163": "__init__.py",
"164": "get_client_ip",
"165": "Community 165",
"166": "code:block1 (/iflytek/shanxia2.0/backend)",
"167": "Community 167",
"168": "vehicle_urea.py",
"169": "product.py",
"170": "test_quote_approver_setting.py",
"171": "crm_supplier_hazard.py",
"172": "apply_pl_scope",
"173": "resolve_create_time_bounds",
"174": "datetime_parse.py",
"174": "CrmProductBrand",
"175": "vehicle_maintenance.py",
"176": "_forbid_legacy_invoice_fields",
"177": "vehicle_maintenance.py",
"178": "product_allowed",
"178": "opportunity_export",
"179": "_ensure_subpack_slip_no",
"180": "menu.py",
"180": "OSSStorage",
"181": "storage.py",
"182": "statistics.py",
"183": "MinIOStorage",
"184": "QiniuStorage",
"185": "vehicle_urea.py",
"186": "transport_address.py",
"187": "allocate_next_biz_no",
"188": "list_product_options",
"189": "create",
"190": "menu.py",
"191": "BaseStorage",
"192": "pool_rule.py",
"193": "LocalStorage",
"197": "_coerce_resource_snapshot",
"198": "user.py",
"200": "register_local_callback",
"202": "statistics.py",
"206": "crm_quote_pdf.py",
"207": "shanxia2.0 后端骨架(FastAPI)",
@@ -0,0 +1,533 @@
{
"0": "Community 0",
"1": "Community 1",
"2": "Community 2",
"3": "Community 3",
"4": "Community 4",
"5": "Community 5",
"6": "Community 6",
"7": "Community 7",
"8": "Community 8",
"9": "Community 9",
"10": "Community 10",
"11": "Community 11",
"12": "Community 12",
"13": "Community 13",
"14": "Community 14",
"15": "Community 15",
"16": "Community 16",
"17": "Community 17",
"18": "Community 18",
"19": "Community 19",
"20": "Community 20",
"21": "Community 21",
"22": "Community 22",
"23": "Community 23",
"24": "Community 24",
"25": "Community 25",
"26": "Community 26",
"27": "Community 27",
"28": "Community 28",
"29": "Community 29",
"30": "Community 30",
"31": "Community 31",
"32": "Community 32",
"33": "Community 33",
"34": "Community 34",
"35": "Community 35",
"36": "Community 36",
"37": "Community 37",
"38": "Community 38",
"39": "Community 39",
"40": "Community 40",
"41": "Community 41",
"42": "Community 42",
"43": "Community 43",
"44": "Community 44",
"45": "Community 45",
"46": "Community 46",
"47": "Community 47",
"48": "Community 48",
"49": "Community 49",
"50": "Community 50",
"51": "Community 51",
"52": "Community 52",
"53": "Community 53",
"54": "Community 54",
"55": "Community 55",
"56": "Community 56",
"57": "Community 57",
"58": "Community 58",
"59": "Community 59",
"60": "Community 60",
"61": "Community 61",
"62": "Community 62",
"63": "Community 63",
"64": "Community 64",
"65": "Community 65",
"66": "Community 66",
"67": "Community 67",
"68": "Community 68",
"69": "Community 69",
"70": "Community 70",
"71": "Community 71",
"72": "Community 72",
"73": "Community 73",
"74": "Community 74",
"75": "Community 75",
"76": "Community 76",
"77": "Community 77",
"78": "Community 78",
"79": "Community 79",
"80": "Community 80",
"81": "Community 81",
"82": "Community 82",
"83": "Community 83",
"84": "Community 84",
"85": "Community 85",
"86": "Community 86",
"87": "Community 87",
"88": "Any",
"89": "pl_ocr_service.py",
"90": "Community 90",
"91": "pl_vehicle_recharge_service.py",
"92": "Community 92",
"93": "_invoice_info_by_customer_impl",
"94": "response.py",
"95": "Community 95",
"96": "Community 96",
"97": "_ensure_subpack_slip_no",
"98": "Community 98",
"99": "Community 99",
"100": "price_letter_detail",
"101": ".to_tenant_user_dict",
"102": "dept.py",
"103": "Community 103",
"104": "apply_crm_create_by_scope",
"105": "list_customers",
"106": "Community 106",
"107": "apply_pl_scope",
"108": "Community 108",
"109": "Community 109",
"110": "Base",
"111": "Community 111",
"112": "storage.py",
"113": "quote_share_log.py",
"114": "db_models.py",
"115": "site.py",
"116": "Community 116",
"117": "Community 117",
"118": "Community 118",
"119": "Community 119",
"120": "Community 120",
"121": "Community 121",
"122": "Community 122",
"123": "Community 123",
"124": "Community 124",
"125": "Community 125",
"126": "customer_pool.py",
"127": "Community 127",
"128": "plan.py",
"129": "BaseStorage",
"130": "datetime_parse.py",
"131": "LocalStorage",
"132": "crm_supplier_hazard.py",
"133": "Community 133",
"134": "Community 134",
"135": "post.py",
"136": "Community 136",
"137": "statistics.py",
"138": "Community 138",
"139": "minio_url.py",
"140": "Community 140",
"141": "customer_follow.py",
"142": "Community 142",
"143": "SysEthnic",
"144": "dict_data.py",
"145": "minio_url.py",
"146": "__init__.py",
"147": "Community 147",
"148": "storage.py",
"149": "Community 149",
"150": "list_customers",
"151": "Community 151",
"152": ".upload_file",
"153": "Community 153",
"154": "response.py",
"155": "Community 155",
"156": "create_from_quote",
"157": "Community 157",
"158": "Community 158",
"159": "assert_contract_editable_for_update",
"160": "register_local_callback",
"161": "backfill_crm_contract_attachment_urls.py",
"162": "customer_options",
"163": "__init__.py",
"164": "get_client_ip",
"165": "Community 165",
"166": "code:block1 (/iflytek/shanxia2.0/backend)",
"167": "Community 167",
"168": "vehicle_urea.py",
"169": "product.py",
"170": "test_quote_approver_setting.py",
"171": "context.py",
"173": "resolve_create_time_bounds",
"175": "vehicle_maintenance.py",
"176": "_forbid_legacy_invoice_fields",
"177": "vehicle_maintenance.py",
"178": "product_allowed",
"179": "_ensure_subpack_slip_no",
"180": "menu.py",
"185": "vehicle_urea.py",
"186": "transport_address.py",
"187": "allocate_next_biz_no",
"189": "create",
"190": "menu.py",
"192": "pool_rule.py",
"197": "_coerce_resource_snapshot",
"198": "user.py",
"202": "statistics.py",
"206": "crm_quote_pdf.py",
"207": "shanxia2.0 后端骨架(FastAPI)",
"211": "leave.py",
"216": "io_order.py",
"217": "auth.py",
"218": "pool_rule.py",
"220": "api_crypto_middleware.py",
"223": "workflow.py",
"224": "supplier_info.py",
"226": "get_active",
"228": "advance.py",
"230": "attachment.py",
"232": "transport_address.py",
"233": "customer_pool.py",
"235": "invoice_info.py",
"236": "price_letter.py",
"237": "order_status_compat.py",
"239": "shanxia2.0 Backend 生产部署说明",
"240": "delete",
"242": "leave.py",
"244": "expense_item.py",
"245": "__init__.py",
"246": "db_collation.py",
"247": "expense_item.py",
"249": "__init__.py",
"250": "invoice.py",
"251": "menu.py",
"252": "public_inventory.py",
"254": "Activate.ps1",
"256": "statistics.py",
"259": "一次上传一条发票:多文件挂同一档案,金额为总额,只写一条额度流水。",
"262": "reimburse.py",
"263": "__init__.py",
"264": "__init__.py",
"265": "__init__.py",
"266": "workflow.py",
"269": "__init__.py",
"270": "leave.py",
"271": "menu.py",
"272": "__init__.py",
"273": "__init__.py",
"274": "__init__.py",
"275": "__init__.py",
"276": "__init__.py",
"278": "__init__.py",
"281": "__init__.py",
"286": "send_delivery_notice",
"287": "__init__.py",
"288": "__init__.py",
"289": "send_delivery_warning",
"292": "send_order_status",
"293": "__init__.py",
"294": "__init__.py",
"295": "__init__.py",
"296": "__init__.py",
"297": "__init__.py",
"298": "__init__.py",
"299": "__init__.py",
"300": "__init__.py",
"301": "__init__.py",
"302": "send_payment_success",
"303": "send_refund_result",
"304": "__init__.py",
"305": "__init__.py",
"306": "__init__.py",
"307": "__init__.py",
"308": "__init__.py",
"309": "__init__.py",
"310": "__init__.py",
"311": "__init__.py",
"312": "__init__.py",
"313": "send_urge_notification",
"314": "get",
"315": "get_multi_with_filters",
"317": "base.py",
"318": "clue.py",
"320": "customer_pool.py",
"321": "customer.py",
"323": "invoice_info.py",
"326": "price_letter.py",
"327": "product.py",
"328": "quote.py",
"329": "user.py",
"330": "base.py",
"331": "__tablename__",
"332": "__init__.py",
"333": "advance.py",
"334": "validate_expense_item_id",
"335": "attachment.py",
"336": "common.py",
"337": "validate_parent_id",
"338": "__init__.py",
"339": "invoice.py",
"340": "coerce_applicant_id",
"341": "details_must_not_be_empty",
"342": "reimburse.py",
"343": "validate_advance_id",
"344": "validate_expense_item_id",
"345": "validate_approver_id",
"346": "common.py",
"347": "contact.py",
"348": "customer_follow.py",
"349": "customer.py",
"350": "dashboard.py",
"351": "__init__.py",
"352": "inventory.py",
"353": "plans.py",
"354": "weighing.py",
"355": "__init__.py",
"356": "freight.py",
"357": "__init__.py",
"358": "plan.py",
"360": "validate_coordinates",
"361": "transport.py",
"362": "validate_amount",
"363": "validate_amount",
"364": "validate_recharge_type",
"365": "validate_amount",
"366": "validate_apply_amount",
"367": "validate_quantity",
"368": "approve",
"369": "create",
"370": "finance_issue_stats",
"371": "get_by_id",
"372": "get_paged",
"373": "global_status_counts",
"374": "issue",
"375": "_latest_approval_per_node",
"376": "_my_apply_base",
"377": "my_apply_stats",
"378": "offset_amount_map",
"379": "pending_approval_stats",
"380": "advance.py",
"381": "_query_approvals",
"382": "reject",
"383": "soft_delete",
"384": "submit",
"385": "_tenant_no",
"386": "update",
"387": "_workflow_nodes",
"389": "create",
"390": "get_by_biz",
"391": "get_by_id",
"392": "attachment.py",
"393": "soft_delete",
"394": "_tenant_no",
"395": "get_by_id",
"396": "get_paged",
"397": "base.py",
"398": "soft_delete",
"399": "update",
"401": "_build_tree",
"402": "create",
"403": "get_by_id",
"404": "get_item_tree",
"405": "expense_item.py",
"406": "soft_delete",
"407": "_tenant_no",
"408": "update",
"409": "_count_invoices",
"410": "create",
"411": "delete",
"412": "get_mine_summary",
"413": "is_wallet_admin",
"414": "add_entry",
"415": "assert_can_delete_invoice",
"416": "calc_summary",
"417": "debit_reimburse",
"418": "list_entries",
"419": "_lock_summary",
"420": "refresh_summary",
"421": "release_reimburse",
"422": "list_ledgers",
"423": "list_wallets",
"424": "_lookup_user_name",
"425": "out_rows_with_attachments",
"426": "invoice.py",
"427": "_require_wallet_admin",
"428": "_resolve_owner",
"429": "_resolve_owner_for_query",
"430": "_summary_to_dict",
"431": "_tenant_no",
"432": "approve",
"433": "batch_offset",
"434": "build_apply_out_with_details",
"435": "build_expense_name_condition",
"436": "can_change_applicant",
"437": "create_with_details",
"438": "finance_payment_stats",
"439": "get_by_id",
"440": "get_details",
"441": "get_details_map_by_reimburse_ids",
"442": "get_linked_invoice_ids",
"443": "get_linked_invoice_ids_map",
"444": "get_linked_invoices_brief",
"445": "get_paged",
"446": "global_status_counts",
"447": "_has_debit_reimburse",
"448": "_latest_approval_per_node",
"449": "_my_apply_base",
"450": "my_apply_stats",
"451": "offset",
"452": "out_one_with_attachment_counts",
"453": "out_rows_with_attachment_counts",
"454": "pay",
"455": "reimburse.py",
"456": "_query_approvals",
"457": "reject",
"458": "resolve_applicant",
"459": "soft_delete",
"460": "submit",
"461": "sync_reimburse_invoices",
"462": "_tenant_no",
"463": "update_with_details",
"464": "withdraw",
"465": "_workflow_nodes",
"466": "ensure_by_biz_type",
"467": "get_by_biz_type",
"468": "get_by_id",
"469": "get_paged",
"470": "workflow.py",
"471": "save_nodes",
"472": "soft_delete",
"473": "_tenant_no",
"474": "update",
"487": "_get_variable",
"488": "_parse_node_config",
"489": "_parse_variables",
"490": "customer_pool.py",
"491": "__init__.py",
"495": "code:bash (cd /path/to/shanxia2.0)",
"496": "code:bash (./start-prod.sh status # 查看状态)",
"497": "code:bash (curl -s http://127.0.0.1:9111/health)",
"498": "code:bash (cd /iflytek/shanxia2.0/backend)",
"499": "code:bash (python -m venv venv)",
"500": "code:bash (pip install -r requirements.txt)",
"501": "code:env (# 数据库配置)",
"502": "code:bash (uvicorn app.main:app --reload --port 8000)",
"503": "BaseModel",
"504": "PlanResourceSnapshotMixin",
"510": "advance.py",
"511": "attachment.py",
"512": "expense_item.py",
"514": "workflow.py",
"517": "dashboard.py",
"518": "__init__.py",
"519": "inventory.py",
"520": "plans.py",
"521": "public_inventory.py",
"522": "weighing.py",
"523": "__init__.py",
"524": "leave.py",
"525": "menu.py",
"526": "base_data.py",
"527": "freight.py",
"528": "__init__.py",
"529": "inventory.py",
"530": "io_order.py",
"531": "plan.py",
"533": "transport_address.py",
"534": "transport.py",
"535": "vehicle_maintenance.py",
"536": "vehicle_recharge.py",
"537": "vehicle_urea.py",
"538": "workflow.py",
"539": "auth.py",
"545": "__init__.py",
"548": "storage.py",
"551": "base.py",
"553": "clue.py",
"554": "contact.py",
"555": "contract.py",
"556": "customer_follow.py",
"557": "customer_pool.py",
"558": "customer.py",
"559": "invoice_info.py",
"560": "opportunity.py",
"561": "pool_rule.py",
"562": "price_letter.py",
"563": "product.py",
"564": "quote.py",
"565": "statistics.py",
"566": "supplier_info.py",
"569": "__init__.py",
"570": "leave.py",
"571": "menu.py",
"573": "user.py",
"574": "workflow.py",
"576": "base.py",
"577": "__init__.py",
"578": "attachment.py",
"579": "auth.py",
"580": "advance.py",
"581": "attachment.py",
"582": "common.py",
"583": "expense_item.py",
"584": "__init__.py",
"585": "workflow.py",
"586": "common.py",
"587": "clue.py",
"588": "contact.py",
"589": "contract.py",
"590": "customer_follow.py",
"591": "customer_pool.py",
"592": "customer.py",
"593": "invoice_info.py",
"594": "opportunity.py",
"595": "pool_rule.py",
"596": "price_letter.py",
"597": "product.py",
"598": "quote.py",
"599": "statistics.py",
"600": "supplier_info.py",
"601": "dashboard.py",
"602": "__init__.py",
"603": "inventory.py",
"604": "plans.py",
"605": "public_inventory.py",
"606": "weighing.py",
"607": "__init__.py",
"608": "leave.py",
"609": "menu.py",
"610": "base_data.py",
"611": "freight.py",
"612": "__init__.py",
"613": "inventory.py",
"614": "io_order.py",
"615": "plan.py",
"616": "transport_address.py",
"617": "transport.py",
"618": "vehicle_maintenance.py",
"619": "vehicle_recharge.py",
"620": "vehicle_urea.py",
"621": "user.py",
"622": "workflow.py",
"623": "advance.py",
"624": "attachment.py",
"625": "base.py",
"626": "expense_item.py",
"627": "storage.py",
"628": "workflow.py",
"636": "customer_pool.py",
"638": "__init__.py"
}
@@ -0,0 +1,767 @@
# Graph Report - backend (2026-08-05)
## Corpus Check
- 311 files · ~209,248 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 4635 nodes · 15664 edges · 531 communities (513 shown, 18 thin omitted)
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 410 edges (avg confidence: 0.53)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `5cf67f60`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
## Community Hubs (Navigation)
- [[_COMMUNITY_Community 0|Community 0]]
- [[_COMMUNITY_Community 1|Community 1]]
- [[_COMMUNITY_Community 2|Community 2]]
- [[_COMMUNITY_Community 3|Community 3]]
- [[_COMMUNITY_Community 4|Community 4]]
- [[_COMMUNITY_Community 5|Community 5]]
- [[_COMMUNITY_Community 6|Community 6]]
- [[_COMMUNITY_Community 7|Community 7]]
- [[_COMMUNITY_Community 8|Community 8]]
- [[_COMMUNITY_Community 11|Community 11]]
- [[_COMMUNITY_Community 12|Community 12]]
- [[_COMMUNITY_Community 13|Community 13]]
- [[_COMMUNITY_Community 14|Community 14]]
- [[_COMMUNITY_Community 15|Community 15]]
- [[_COMMUNITY_Community 16|Community 16]]
- [[_COMMUNITY_Community 18|Community 18]]
- [[_COMMUNITY_Community 19|Community 19]]
- [[_COMMUNITY_Community 21|Community 21]]
- [[_COMMUNITY_Community 22|Community 22]]
- [[_COMMUNITY_Community 23|Community 23]]
- [[_COMMUNITY_Community 24|Community 24]]
- [[_COMMUNITY_Community 25|Community 25]]
- [[_COMMUNITY_Community 26|Community 26]]
- [[_COMMUNITY_Community 27|Community 27]]
- [[_COMMUNITY_Community 28|Community 28]]
- [[_COMMUNITY_Community 29|Community 29]]
- [[_COMMUNITY_Community 30|Community 30]]
- [[_COMMUNITY_Community 33|Community 33]]
- [[_COMMUNITY_Community 34|Community 34]]
- [[_COMMUNITY_Community 35|Community 35]]
- [[_COMMUNITY_Community 36|Community 36]]
- [[_COMMUNITY_Community 37|Community 37]]
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 49|Community 49]]
- [[_COMMUNITY_Community 50|Community 50]]
- [[_COMMUNITY_Community 51|Community 51]]
- [[_COMMUNITY_Community 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
- [[_COMMUNITY_Community 54|Community 54]]
- [[_COMMUNITY_Community 58|Community 58]]
- [[_COMMUNITY_Community 59|Community 59]]
- [[_COMMUNITY_Community 60|Community 60]]
- [[_COMMUNITY_Community 61|Community 61]]
- [[_COMMUNITY_Community 62|Community 62]]
- [[_COMMUNITY_Community 63|Community 63]]
- [[_COMMUNITY_Community 64|Community 64]]
- [[_COMMUNITY_Community 65|Community 65]]
- [[_COMMUNITY_Community 66|Community 66]]
- [[_COMMUNITY_Community 67|Community 67]]
- [[_COMMUNITY_Community 68|Community 68]]
- [[_COMMUNITY_Community 69|Community 69]]
- [[_COMMUNITY_Community 70|Community 70]]
- [[_COMMUNITY_Community 71|Community 71]]
- [[_COMMUNITY_Community 72|Community 72]]
- [[_COMMUNITY_Community 73|Community 73]]
- [[_COMMUNITY_Community 74|Community 74]]
- [[_COMMUNITY_Community 77|Community 77]]
- [[_COMMUNITY_Community 78|Community 78]]
- [[_COMMUNITY_Community 81|Community 81]]
- [[_COMMUNITY_Community 83|Community 83]]
- [[_COMMUNITY_Community 84|Community 84]]
- [[_COMMUNITY_Community 86|Community 86]]
- [[_COMMUNITY_Community 87|Community 87]]
- [[_COMMUNITY_Any|Any]]
- [[_COMMUNITY_pl_ocr_service.py|pl_ocr_service.py]]
- [[_COMMUNITY_pl_vehicle_recharge_service.py|pl_vehicle_recharge_service.py]]
- [[_COMMUNITY_Community 92|Community 92]]
- [[_COMMUNITY__invoice_info_by_customer_impl|_invoice_info_by_customer_impl]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_Community 95|Community 95]]
- [[_COMMUNITY__ensure_subpack_slip_no|_ensure_subpack_slip_no]]
- [[_COMMUNITY_price_letter_detail|price_letter_detail]]
- [[_COMMUNITY_.to_tenant_user_dict|.to_tenant_user_dict]]
- [[_COMMUNITY_dept.py|dept.py]]
- [[_COMMUNITY_apply_crm_create_by_scope|apply_crm_create_by_scope]]
- [[_COMMUNITY_list_customers|list_customers]]
- [[_COMMUNITY_Community 106|Community 106]]
- [[_COMMUNITY_apply_pl_scope|apply_pl_scope]]
- [[_COMMUNITY_Community 109|Community 109]]
- [[_COMMUNITY_Base|Base]]
- [[_COMMUNITY_Community 111|Community 111]]
- [[_COMMUNITY_storage.py|storage.py]]
- [[_COMMUNITY_quote_share_log.py|quote_share_log.py]]
- [[_COMMUNITY_db_models.py|db_models.py]]
- [[_COMMUNITY_site.py|site.py]]
- [[_COMMUNITY_Community 116|Community 116]]
- [[_COMMUNITY_Community 118|Community 118]]
- [[_COMMUNITY_Community 119|Community 119]]
- [[_COMMUNITY_Community 122|Community 122]]
- [[_COMMUNITY_Community 125|Community 125]]
- [[_COMMUNITY_customer_pool.py|customer_pool.py]]
- [[_COMMUNITY_Community 127|Community 127]]
- [[_COMMUNITY_plan.py|plan.py]]
- [[_COMMUNITY_BaseStorage|BaseStorage]]
- [[_COMMUNITY_datetime_parse.py|datetime_parse.py]]
- [[_COMMUNITY_LocalStorage|LocalStorage]]
- [[_COMMUNITY_crm_supplier_hazard.py|crm_supplier_hazard.py]]
- [[_COMMUNITY_Community 134|Community 134]]
- [[_COMMUNITY_post.py|post.py]]
- [[_COMMUNITY_Community 136|Community 136]]
- [[_COMMUNITY_statistics.py|statistics.py]]
- [[_COMMUNITY_Community 138|Community 138]]
- [[_COMMUNITY_minio_url.py|minio_url.py]]
- [[_COMMUNITY_customer_follow.py|customer_follow.py]]
- [[_COMMUNITY_SysEthnic|SysEthnic]]
- [[_COMMUNITY_dict_data.py|dict_data.py]]
- [[_COMMUNITY_minio_url.py|minio_url.py]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_Community 147|Community 147]]
- [[_COMMUNITY_list_customers|list_customers]]
- [[_COMMUNITY_Community 151|Community 151]]
- [[_COMMUNITY_.upload_file|.upload_file]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_create_from_quote|create_from_quote]]
- [[_COMMUNITY_assert_contract_editable_for_update|assert_contract_editable_for_update]]
- [[_COMMUNITY_register_local_callback|register_local_callback]]
- [[_COMMUNITY_backfill_crm_contract_attachment_urls.py|backfill_crm_contract_attachment_urls.py]]
- [[_COMMUNITY_customer_options|customer_options]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_get_client_ip|get_client_ip]]
- [[_COMMUNITY_codeblock1 (iflytekshanxia2.0backend)|code:block1 (/iflytek/shanxia2.0/backend)]]
- [[_COMMUNITY_test_quote_approver_setting.py|test_quote_approver_setting.py]]
- [[_COMMUNITY_context.py|context.py]]
- [[_COMMUNITY_resolve_create_time_bounds|resolve_create_time_bounds]]
- [[_COMMUNITY_product_allowed|product_allowed]]
- [[_COMMUNITY__ensure_subpack_slip_no|_ensure_subpack_slip_no]]
- [[_COMMUNITY_menu.py|menu.py]]
- [[_COMMUNITY_allocate_next_biz_no|allocate_next_biz_no]]
- [[_COMMUNITY_crm_quote_pdf.py|crm_quote_pdf.py]]
- [[_COMMUNITY_shanxia2.0 后端骨架(FastAPI)|shanxia2.0 后端骨架(FastAPI)]]
- [[_COMMUNITY_api_crypto_middleware.py|api_crypto_middleware.py]]
- [[_COMMUNITY_order_status_compat.py|order_status_compat.py]]
- [[_COMMUNITY_shanxia2.0 Backend 生产部署说明|shanxia2.0 Backend 生产部署说明]]
- [[_COMMUNITY_db_collation.py|db_collation.py]]
- [[_COMMUNITY_一次上传一条发票:多文件挂同一档案,金额为总额,只写一条额度流水。|一次上传一条发票:多文件挂同一档案,金额为总额,只写一条额度流水。]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_codebash (cd pathtoshanxia2.0)|code:bash (cd /path/to/shanxia2.0)]]
- [[_COMMUNITY_codebash (.start-prod.sh status 查看状态)|code:bash (./start-prod.sh status # 查看状态)]]
- [[_COMMUNITY_codebash (curl -s http127.0.0.19111health)|code:bash (curl -s http://127.0.0.1:9111/health)]]
- [[_COMMUNITY_codebash (cd iflytekshanxia2.0backend)|code:bash (cd /iflytek/shanxia2.0/backend)]]
- [[_COMMUNITY_codebash (python -m venv venv)|code:bash (python -m venv venv)]]
- [[_COMMUNITY_codebash (pip install -r requirements.txt)|code:bash (pip install -r requirements.txt)]]
- [[_COMMUNITY_codeenv ( 数据库配置)|code:env (# 数据库配置)]]
- [[_COMMUNITY_codebash (uvicorn app.mainapp --reload --port 8000)|code:bash (uvicorn app.main:app --reload --port 8000)]]
- [[_COMMUNITY_BaseModel|BaseModel]]
- [[_COMMUNITY_PlanResourceSnapshotMixin|PlanResourceSnapshotMixin]]
## God Nodes (most connected - your core abstractions)
1. `BaseModel` - 443 edges
2. `get_tenant_no()` - 350 edges
3. `DbUserContext` - 254 edges
4. `success_response()` - 254 edges
5. `error_response()` - 236 edges
6. `generate_uuid()` - 195 edges
7. `BxUserContext` - 183 edges
8. `crm_user_info()` - 137 edges
9. `assert_row_deletable_by_creator()` - 83 edges
10. `ApiResponse` - 79 edges
## Surprising Connections (you probably didn't know these)
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_bx_data.py → app/core/config.py
- `StepStats` --uses--> `Settings` [INFERRED]
scripts/migrate_bx_data.py → app/core/config.py
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_clue.py → app/core/config.py
- `StepStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_clue.py → app/core/config.py
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_contract.py → app/core/config.py
## Import Cycles
- None detected.
## Communities (531 total, 18 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.09
Nodes (48): check_document_expiry(), document_reminder_stats(), get_inventory_ledger(), get_summary(), list_document_reminders(), list_transactions(), list_warnings(), date (+40 more)
### Community 1 - "Community 1"
Cohesion: 0.06
Nodes (55): CRM 合同 API 路由 — GET/PUT/DELETE/POST 对齐原 Java CRM, CRM 合同子模块路由 — 变更/模板/审批独立页, 运营端角色守卫:admin / super_admin 可访问。, require_admin_or_super_admin(), execute_change(), _get_change_row(), Java Controller TODO — 保持 pending,记录备注, soft_delete_contract_changes() (+47 more)
### Community 2 - "Community 2"
Cohesion: 0.14
Nodes (15): BxAdvanceApply, BxAdvanceApproval, AdvanceService, Any, Session, 同一节点多次审批时,取 approval_time 最新的一条作为当前节点状态。, 返回全部审批动作,按时间正序排列,用于展示完整审批历史。, current_month_bounds() (+7 more)
### Community 3 - "Community 3"
Cohesion: 0.08
Nodes (60): attachment_download_url(), attachment_preview_url(), create_dept(), create_dict_data(), create_dict_type(), create_menu(), create_post(), create_role_management() (+52 more)
### Community 4 - "Community 4"
Cohesion: 0.12
Nodes (61): _apply_list_filters(), assign_opportunities(), batch_update_expect_date(), batch_update_stage(), change_stage(), create_opportunity(), _decimal_value(), _enrich_user_names() (+53 more)
### Community 5 - "Community 5"
Cohesion: 0.20
Nodes (24): count_source_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings(), load_settings_env(), load_user_mapping() (+16 more)
### Community 6 - "Community 6"
Cohesion: 0.10
Nodes (52): customer_create(), customer_update(), follow_by_customer(), follow_detail(), assign_customer(), batch_claim_customers(), check_duplicate_customer(), claim_customer() (+44 more)
### Community 7 - "Community 7"
Cohesion: 0.12
Nodes (28): create_carrier(), get_carrier(), list_carriers(), reject_carrier(), update_carrier(), carrier_to_read(), CarrierAuditReject, CarrierBase (+20 more)
### Community 8 - "Community 8"
Cohesion: 0.14
Nodes (45): register_quote_routes(), accept_quote(), calculate_quote_amount(), create_new_version(), create_quote(), _decimal_value(), _enrich_contact_fields(), _enrich_supplier_name() (+37 more)
### Community 11 - "Community 11"
Cohesion: 0.10
Nodes (55): cancel_apply(), create_apply(), create_disburse(), delete_applies(), delete_disburses(), get_apply(), get_disburse(), list_applies() (+47 more)
### Community 12 - "Community 12"
Cohesion: 0.10
Nodes (30): AttachmentUploadResponse, ChangePasswordRequest, Config, LoginRequest, LoginResponse, Pydantic schemas - 用户认证, ResetPasswordRequest, UserCreate (+22 more)
### Community 13 - "Community 13"
Cohesion: 0.11
Nodes (39): register_contract_routes(), 接口菜单权限守卫。super_admin 直接放行。, require_menu_code(), batch_assign_owner(), batch_submit_contract_approval(), _build_contract_name_from_parties(), download_contract_pdf(), _ensure_contract_in_scope() (+31 more)
### Community 14 - "Community 14"
Cohesion: 0.12
Nodes (15): API 路由包 — 山峡化工生产一体化门户, get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,14 个一级菜单), Session, recognize_cert(), RecognizeCertBody, RecognizeCertResult, _auto_fill_create_dept_id() (+7 more)
### Community 15 - "Community 15"
Cohesion: 0.12
Nodes (13): BxReimburseApply, BxReimburseApproval, BxReimburseDetail, 报销单勾选的发票附件(同一发票可勾选多个附件,各占一条)。, ReimburseInvoiceBriefOut, ReimburseInvoiceLinkIn, Any, Session (+5 more)
### Community 16 - "Community 16"
Cohesion: 0.09
Nodes (60): cancel_apply(), create_apply(), create_record(), delete_applies(), delete_records(), get_apply(), get_record(), list_applies() (+52 more)
### Community 18 - "Community 18"
Cohesion: 0.14
Nodes (33): advance_pending_approval_stats(), advance_status_counts(), approve_advance(), approved_by_me(), create_advance(), delete_advance(), _fill_offset_amounts(), get_advance() (+25 more)
### Community 19 - "Community 19"
Cohesion: 0.10
Nodes (45): _avatar_url_field(), _build_user_info_payload(), change_current_user_password(), get_current_user_profile(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), public_quote_share() (+37 more)
### Community 21 - "Community 21"
Cohesion: 0.14
Nodes (35): _assert_brand_deletable(), barcode_exists(), category_code_exists(), create_category(), create_oss(), create_product(), generate_auto_product_no(), generate_barcode() (+27 more)
### Community 22 - "Community 22"
Cohesion: 0.08
Nodes (28): parse_admin_request_json(), Any, Request, 运营 Web(/web/admin)JSON 请求体解析。 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `{, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。 Returns:, ApiCryptoError, _b64url_decode(), _b64url_encode() (+20 more)
### Community 23 - "Community 23"
Cohesion: 0.05
Nodes (31): BaseStorage, convert_heic_to_jpeg(), get_storage(), LocalStorage, MinIOStorage, OSSStorage, process_image_content(), Any (+23 more)
### Community 24 - "Community 24"
Cohesion: 0.09
Nodes (27): BaseModel, PagedQuery, PagedResponse, InvoiceAttachmentOut, InvoiceOut, LedgerOut, WalletSummaryOut, ContactByCustomerBody (+19 more)
### Community 25 - "Community 25"
Cohesion: 0.13
Nodes (27): PlInventoryTransaction, 库存流水表 pl_inventory_transaction, load_brand_qtys_by_plan_product_ids(), persist_plan_product_brand_qtys(), Any, Decimal, Session, 按计划产品明细 ID 批量加载归档品牌数量(brandId/brandName/qty)。 (+19 more)
### Community 26 - "Community 26"
Cohesion: 0.12
Nodes (42): approve_carrier(), bind_vehicle_driver(), create_driver(), create_vehicle(), delete_carrier(), delete_driver(), delete_personnel(), delete_vehicle() (+34 more)
### Community 27 - "Community 27"
Cohesion: 0.13
Nodes (43): _apply_plan_product_update(), _apply_plan_update(), AutoGenerateMonthlyResult, _base_query(), create_plan(), delete_plan(), _generate_plan_no(), get_plan() (+35 more)
### Community 28 - "Community 28"
Cohesion: 0.11
Nodes (55): PlFreightSettlement, PlFreightSettlementApproval, PlFreightSettlementTransport, 运费结算表 pl_freight_settlement, 运费结算审批 pl_freight_settlement_approval, 结算单-运输关联表 pl_freight_settlement_transport, _advance_after_approval(), _approval_to_dict() (+47 more)
### Community 29 - "Community 29"
Cohesion: 0.15
Nodes (22): _build_public_page(), _format_file_size(), _format_plan_date(), get_public_transport(), _get_transport_by_token(), _parse_feedback_images(), Session, UploadFile (+14 more)
### Community 30 - "Community 30"
Cohesion: 0.16
Nodes (26): clear_target_categories(), compute_level(), count_target_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings() (+18 more)
### Community 33 - "Community 33"
Cohesion: 0.13
Nodes (22): bind_biz(), delete_attachment(), download_file(), list_by_biz(), _parse_id_list(), preview_attachment(), Session, UploadFile (+14 more)
### Community 34 - "Community 34"
Cohesion: 0.06
Nodes (78): approve_task(), _assert_wf_instance_in_scope(), _business_type_label(), create_process_def(), delete_process_def(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields() (+70 more)
### Community 35 - "Community 35"
Cohesion: 0.18
Nodes (36): clear_portal_workflow(), _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_bx_user_mapping(), load_runtime_settings() (+28 more)
### Community 36 - "Community 36"
Cohesion: 0.16
Nodes (25): 验证密码(哈希非 bcrypt 或损坏时返回 False,避免抛错), verify_password(), change_password(), create_user(), get_user(), get_user_with_relations(), _hash_password(), list_post_ids_for_user() (+17 more)
### Community 37 - "Community 37"
Cohesion: 0.22
Nodes (19): delete_plan(), _actor_ids(), _actor_names(), assert_row_deletable_by_creator(), assert_rows_deletable_by_creator(), can_delete_by_creator(), is_super_admin(), normalize_user_info() (+11 more)
### Community 38 - "Community 38"
Cohesion: 0.18
Nodes (20): _dict_field(), format_brand_qty_summary(), load_transport_driver_product_feedbacks(), persist_io_item_brand_qtys(), persist_transport_product_feedback(), Any, Decimal, Session (+12 more)
### Community 39 - "Community 39"
Cohesion: 0.13
Nodes (42): clue_follow_detail(), assign_clues(), check_convert(), check_duplicate_clue(), convert_clue(), create_clue(), _enrich_user_names(), _ensure_clue_in_scope() (+34 more)
### Community 42 - "Community 42"
Cohesion: 0.19
Nodes (32): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+24 more)
### Community 43 - "Community 43"
Cohesion: 0.11
Nodes (27): create_invoice(), delete_invoice(), get_mine_wallet_summary(), list_invoice_ledgers(), list_invoice_wallets(), list_invoices(), Request, Session (+19 more)
### Community 44 - "Community 44"
Cohesion: 0.11
Nodes (18): ApiCryptoMiddleware, ApiRequestLogMiddleware, _db_pool_keepalive_loop(), _error_json(), lifespan(), Exception, Request, 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误 (+10 more)
### Community 45 - "Community 45"
Cohesion: 0.08
Nodes (72): _build_driver_url(), get_plan_arrange_info(), 获取计划已安排运输后的司机链接与地磅出入库关联(供查看弹窗复制简述/二维码)。, _apply_plan_logistics_from_payload(), _apply_transport_arrange_fields(), arrange_transport(), _assert_vehicle_carrier_eligible(), _build_arrange_result() (+64 more)
### Community 46 - "Community 46"
Cohesion: 0.11
Nodes (37): approve_settlement_legacy(), cancel_settlement(), create_settlement(), delete_settlement(), disburse_settlement(), _generate_settlement_no(), get_settlement(), get_settlement_approval_flow() (+29 more)
### Community 48 - "Community 48"
Cohesion: 0.18
Nodes (27): _apply_inventory_product_update(), _apply_inventory_update(), _base_query(), create_inventory(), create_link_for_plan(), delete_inventory(), _generate_batch_no(), _get_inventory() (+19 more)
### Community 49 - "Community 49"
Cohesion: 0.21
Nodes (17): apply_crm_create_by_scope(), _apply_list_filters(), create_supplier_info(), list_all_supplier_info(), list_supplier_info(), Any, Session, CRM 供方信息 CRUD — 对照 CrmSupplierInfoServiceImpl.java (+9 more)
### Community 50 - "Community 50"
Cohesion: 0.15
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import WechatMes, 发送订单状态通知 Args: openid: 用户openid order_n, 发送支付成功通知 Args: openid: 用户openid order_n, 发送配送通知 Args: openid: 配送员openid task_no:, 发送配送时效预警 Args: openid: 配送员openid task_n, 发送退款结果通知 Args: openid: 用户openid order_n, 发送催单通知给配送员 Args: deliver_openid: 配送员openid, 发送模板消息 Args: openid: 用户openid template_ (+1 more)
### Community 51 - "Community 51"
Cohesion: 0.11
Nodes (53): update_plan(), PlPlanProduct, 计划产品明细表 pl_plan_product, PlanArchiveFreightBlock, PlanArchiveProductItem, PlanProductCreate, PlanTransportCreateBlock, all_hazard_products_cert_complete() (+45 more)
### Community 52 - "Community 52"
Cohesion: 0.18
Nodes (29): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+21 more)
### Community 53 - "Community 53"
Cohesion: 0.11
Nodes (35): 报销模块认证适配:门户 JWT 用户 → bx 业务上下文。, BxReimburseInvoice, BxReimburseOffset, BxWorkflowNode, 报销(bx)模块数据模型 — 对齐 docs/sql/20260606_bx_tables.sql, filter_current_cycle_approvals(), 审批轮次过滤 — 驳回后重新提交时,进度接口仅展示当前轮次。, 审批进度仅展示当前轮次;完整历史由 get_approval_history 返回。 (+27 more)
### Community 54 - "Community 54"
Cohesion: 0.19
Nodes (28): _get_by_plan(), get_inbound(), get_inbound_by_plan(), _get_order(), get_outbound(), get_outbound_by_plan(), inbound_site_url(), list_inbound() (+20 more)
### Community 58 - "Community 58"
Cohesion: 0.16
Nodes (29): approve_reimburse(), approved_by_me(), _build_details_data(), create_reimburse(), delete_reimburse(), get_approval_history(), get_approvals(), get_generated_title() (+21 more)
### Community 59 - "Community 59"
Cohesion: 0.20
Nodes (28): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+20 more)
### Community 60 - "Community 60"
Cohesion: 0.18
Nodes (18): align_contract_no_to_sign_date(), generate_contract_no(), date, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号} 流水与撞号检测须含软删:uk_contr, 标准编号替换日期段,保留序号;非标准返回 None。, 将标准合同编号日期段对齐签订日;撞号则序号顺延(含软删查重)。 非标准编号原样返回。无签订日则原样返回。, replace_contract_no_date(), _mock_last_contract() (+10 more)
### Community 61 - "Community 61"
Cohesion: 0.16
Nodes (33): DbInboundOutbound, PlTransportDbLink, 运输-地磅出入库关联 pl_transport_db_link, _apply_plan_quantity_delta(), _create_db_inventory(), _create_db_plan(), DibangInventoryLinkResult, find_monthly_db_plan() (+25 more)
### Community 62 - "Community 62"
Cohesion: 0.27
Nodes (26): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, MenuCreateBody (+18 more)
### Community 63 - "Community 63"
Cohesion: 0.20
Nodes (13): create_expense_item(), delete_expense_item(), get_expense_item(), get_expense_item_tree(), Session, update_expense_item(), BxExpenseItem, _coerce_id() (+5 more)
### Community 64 - "Community 64"
Cohesion: 0.04
Nodes (174): clue_assign(), clue_check_convert(), clue_check_duplicate(), clue_convert(), clue_create(), clue_delete(), clue_export(), clue_follow_create() (+166 more)
### Community 65 - "Community 65"
Cohesion: 0.10
Nodes (58): cancel_apply(), create_apply(), create_process(), delete_applies(), delete_processes(), get_apply(), get_process(), list_applies() (+50 more)
### Community 66 - "Community 66"
Cohesion: 0.14
Nodes (21): create_workflow(), delete_workflow(), get_workflow(), get_workflow_by_biz_type(), list_workflows(), Session, save_workflow_nodes(), update_workflow() (+13 more)
### Community 67 - "Community 67"
Cohesion: 0.12
Nodes (36): get_password_hash(), Namespace, build_merged_users(), bx_role_labels(), check_minio(), check_mysql(), check_redis(), _clip() (+28 more)
### Community 68 - "Community 68"
Cohesion: 0.32
Nodes (14): PlPersonnel, PlVehicle, ConflictAction, PastePersonnelIn, PasteVehicleIn, 运输计划 - 三方粘贴识别提交 Schema, _conflict_map(), _find_personnel_by_id_card() (+6 more)
### Community 69 - "Community 69"
Cohesion: 0.15
Nodes (27): _append_user_scope_conditions(), apply_data_scope(), assert_row_in_data_scope(), _collect_scope_ids(), _get_child_dept_ids(), get_user_dept_id(), Session, 数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3 (+19 more)
### Community 70 - "Community 70"
Cohesion: 0.39
Nodes (10): create_post(), get_post(), list_posts(), post_code_exists(), Any, Session, _row_to_dict(), soft_delete_post() (+2 more)
### Community 71 - "Community 71"
Cohesion: 0.11
Nodes (32): CRM 报价单 API 路由 — 挂接到 crm.router, QuoteApproverSettingSaveBody, QuoteAcceptBody, QuoteApprovalApproveBody, QuoteApprovalListBody, QuoteApprovalRefreshNamesBody, QuoteApprovalWithdrawBody, QuoteCreateBody (+24 more)
### Community 72 - "Community 72"
Cohesion: 0.18
Nodes (30): Settings, BaseSettings, apply_biz_backfill(), BackfillRule, BizRef, build_biz_index(), count_target_rows(), derive_source_url() (+22 more)
### Community 73 - "Community 73"
Cohesion: 0.20
Nodes (25): derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env(), load_user_mapping() (+17 more)
### Community 74 - "Community 74"
Cohesion: 0.06
Nodes (49): pool_rule_add(), pool_rule_delete(), pool_rule_detail(), pool_rule_execute(), pool_rule_list(), pool_rule_update(), pool_rule_update_status(), get_current_time() (+41 more)
### Community 77 - "Community 77"
Cohesion: 0.11
Nodes (12): get_wechat_pay_client(), get_wechat_pay_v2(), Any, 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.html, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total_amo, 申请退款 Args: out_trade_no: 商户订单号 total_amount: 订单, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 total_f (+4 more)
### Community 78 - "Community 78"
Cohesion: 0.16
Nodes (20): _alias_row_to_dict(), _brand_row_to_dict(), _build_category_tree(), _category_row_to_dict(), _collect_category_with_ancestors(), list_categories(), list_category_tree(), list_oss_by_biz() (+12 more)
### Community 81 - "Community 81"
Cohesion: 0.17
Nodes (24): _build_public_page(), _build_site_product_read(), _format_file_size(), get_public_site(), _get_site_link_by_token(), _parse_feedback_images(), Session, UploadFile (+16 more)
### Community 83 - "Community 83"
Cohesion: 0.16
Nodes (31): register_contract_sub_routes(), _advance_contract_after_approval(), approve_contract(), approve_contract_by_contract_id(), approve_pass(), approve_reject(), approve_transfer(), _build_approval_list_filters() (+23 more)
### Community 84 - "Community 84"
Cohesion: 0.23
Nodes (23): build_id_maps(), clip_text(), count_rows(), export_mapping(), fetch_rows(), legacy_id_to_str(), main(), map_id() (+15 more)
### Community 86 - "Community 86"
Cohesion: 0.16
Nodes (30): _apply_weighing_product_update(), _apply_weighing_update(), _base_query(), create_weighing(), delete_weighing(), _get_weighing(), get_weighing_related(), list_weighing() (+22 more)
### Community 87 - "Community 87"
Cohesion: 0.20
Nodes (19): approve_quote(), can_user_approve(), create_approval_records(), delete_pending_approvals(), get_quote_approval(), list_quote_approvals(), Any, Session (+11 more)
### Community 88 - "Any"
Cohesion: 0.18
Nodes (31): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), legacy_parent_id(), load_oss_id_to_url(), load_runtime_settings() (+23 more)
### Community 89 - "pl_ocr_service.py"
Cohesion: 0.19
Nodes (22): PlOcrUsageMonth, 阿里云 OCR 月度调用计数 pl_ocr_usage_month(按自然月全局统计), assert_quota_available(), _build_ocr_client(), compress_image_bytes(), current_usage_month(), _first_attachment_url(), get_or_create_usage_row() (+14 more)
### Community 91 - "pl_vehicle_recharge_service.py"
Cohesion: 0.10
Nodes (59): _apply_contract_entity_fields(), _build_contract_filters(), _build_customer_address(), _calc_amount_with_tax(), _change_row_to_dict(), contract_no_exists(), _contract_period_key(), contract_row_to_dict() (+51 more)
### Community 92 - "Community 92"
Cohesion: 0.05
Nodes (58): operlog_detail(), operlog_list(), Session, 操作日志分页列表(基于 API 请求日志适配 RuoYi OperLog 结构), _user_info(), _claims_from_auth(), _format_body_bytes(), _persist_log() (+50 more)
### Community 93 - "_invoice_info_by_customer_impl"
Cohesion: 0.16
Nodes (18): _build_quote_filters(), _fill_contract_linked_count(), list_quotes(), _parse_optional_datetime(), _period_key(), Any, datetime, Query (+10 more)
### Community 94 - "response.py"
Cohesion: 0.21
Nodes (15): get_user_menu_codes(), Session, 读取用户授权的菜单权限标识集合(与前端 meta.menuCode / perms 对齐)。, _expand_with_ancestor_menu_ids(), _granted_menu_ids_for_user(), iter_user_menu_perm_codes(), Session, Web 管理端登录:基于 V0.3 sys_user / sys_user_role / sys_role 的角色与菜单权限解析 (+7 more)
### Community 95 - "Community 95"
Cohesion: 0.35
Nodes (11): create_tenant(), get_tenant(), list_tenants(), Any, Session, _row_to_dict(), soft_delete_tenant(), tenant_no_exists() (+3 more)
### Community 97 - "_ensure_subpack_slip_no"
Cohesion: 0.21
Nodes (22): clear_target_products(), count_target_rows(), _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings() (+14 more)
### Community 100 - "price_letter_detail"
Cohesion: 0.31
Nodes (13): apply_renumber(), build_mapping(), fetch_products(), format_new_product_no(), load_settings_env(), main(), product_id_sort_key(), Engine (+5 more)
### Community 101 - ".to_tenant_user_dict"
Cohesion: 0.19
Nodes (14): CRM 模块 Excel 导出列定义(字段与字典类型对齐 Java *Vo @ExcelDictFormat)。, _build_workbook(), DictLabelResolver, export_rows_to_xlsx_response(), ExportColumn, load_dict_label_maps(), Any, Session (+6 more)
### Community 102 - "dept.py"
Cohesion: 0.33
Nodes (13): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), Any (+5 more)
### Community 104 - "apply_crm_create_by_scope"
Cohesion: 0.29
Nodes (15): create_price_letter(), get_price_letter(), list_price_letters(), _parse_date(), Any, date, Session, _row_to_dict() (+7 more)
### Community 105 - "list_customers"
Cohesion: 0.12
Nodes (32): create_personnel(), get_personnel(), list_personnel(), _personnel_to_detail(), _personnel_to_read(), update_personnel(), PlCert, CertRead (+24 more)
### Community 106 - "Community 106"
Cohesion: 0.14
Nodes (27): invoice_info_add(), invoice_info_by_customer(), _invoice_info_by_customer_impl(), invoice_info_delete(), invoice_info_list(), invoice_info_set_default(), invoice_info_update(), 按客户ID查询开票信息(与 by-customer 等价) (+19 more)
### Community 107 - "apply_pl_scope"
Cohesion: 0.30
Nodes (12): PlCarrier, assert_carrier_eligible_for_transport(), carrier_agreement_expired(), carrier_audit_approved(), carrier_eligible_for_transport(), carrier_qualification_complete(), date, 资质附件均为选填,保留函数签名供兼容调用。 (+4 more)
### Community 109 - "Community 109"
Cohesion: 0.35
Nodes (11): create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), Any, Session, 字典类型 CRUD(sys_dict_type), _row_to_dict() (+3 more)
### Community 110 - "Base"
Cohesion: 0.22
Nodes (10): Config, decrypt_login_payload(), ensure_initialized(), extract_login_credentials(), get_public_pem(), Any, 登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。, Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。 (+2 more)
### Community 111 - "Community 111"
Cohesion: 0.28
Nodes (14): _assert_editable(), _build_public_page(), _format_file_size(), _get_inventory_by_token(), get_public_inventory(), _parse_feedback_images(), Session, UploadFile (+6 more)
### Community 112 - "storage.py"
Cohesion: 0.05
Nodes (68): category_add(), category_delete(), category_tree(), category_update(), clue_import_template(), customer_import_template(), pool_customer_assign(), pool_customer_claim() (+60 more)
### Community 113 - "quote_share_log.py"
Cohesion: 0.26
Nodes (12): list_share_logs(), _parse_user_agent(), Any, Session, CRM 报价单分享访问日志 CRUD — 对照 CrmQuoteShareLogServiceImpl.java, Java: statisticsVisits, 简易 User-Agent 解析(替代 Hutool UserAgentUtil), Java: queryLogsByQuoteId (+4 more)
### Community 114 - "db_models.py"
Cohesion: 0.16
Nodes (17): list_public_vehicle_plates(), Session, 地磅公共只读:免登车牌 options(现场填写页), 免登:按出入库/计划解析 tenant_no,返回 pl_vehicle 车牌(self + carrier)。, _resolve_tenant_no(), DbSequence, 地磅(db)模块数据模型 — 对齐 docs/sql/db_tables.sql, _allocate_inbound_outbound_id() (+9 more)
### Community 115 - "site.py"
Cohesion: 0.28
Nodes (17): _address_to_read(), _build_address_query(), create_transport_address(), delete_transport_address(), _get_address(), get_transport_address(), list_all_transport_addresses(), list_transport_addresses() (+9 more)
### Community 116 - "Community 116"
Cohesion: 0.19
Nodes (26): batch_insert_quote_products(), calculate_subtotal(), _decimal_value(), delete_products_by_quote_id(), _ensure_quote_parent_scope(), _get_field(), get_quote_product(), insert_quote_product() (+18 more)
### Community 118 - "Community 118"
Cohesion: 0.22
Nodes (22): batch_insert_contract_products(), calculate_subtotal(), _decimal_value(), delete_price_tiers_by_contract_id(), delete_products_by_contract_id(), _get_field(), insert_contract_product(), _letter_oss_ids_to_json() (+14 more)
### Community 119 - "Community 119"
Cohesion: 0.16
Nodes (28): CertRow, _cert_row_complete(), collect_required_cert_errors(), _find_cert_for_required(), get_required_personnel_cert_names(), match_required_cert_name(), _missing_field_labels(), Session (+20 more)
### Community 122 - "Community 122"
Cohesion: 0.35
Nodes (16): ensure_crm_create_by_row_in_scope(), create_opportunity_follow(), _ensure_parent_opportunity(), get_opportunity_follow(), list_follows_by_opportunity(), list_opportunity_follows(), _parse_optional_datetime(), Any (+8 more)
### Community 125 - "Community 125"
Cohesion: 0.07
Nodes (61): _generate_notify_message(), _build_page(), _get_by_token(), _make_handlers(), _models(), Session, 运输计划 · 入库/出库单现场免登录公共 API, PlInboundOrder (+53 more)
### Community 126 - "customer_pool.py"
Cohesion: 0.27
Nodes (11): create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options(), Any, Session, 字典数据 CRUD(sys_dict_data), 字典下拉选项:租户主数据,忽略数据范围(user_info 保留兼容调用方,不参与过滤)。 (+3 more)
### Community 127 - "Community 127"
Cohesion: 0.27
Nodes (18): _cargo_stats(), get_dashboard_stats(), get_inbound_by_cargo(), get_inbound_by_partner_cargo(), get_outbound_by_cargo(), get_outbound_by_partner_cargo(), _partner_cargo_stats(), Session (+10 more)
### Community 128 - "plan.py"
Cohesion: 0.39
Nodes (10): create_site(), get_site(), list_sites(), Any, Session, _row_to_dict(), site_code_exists(), soft_delete_site() (+2 more)
### Community 129 - "BaseStorage"
Cohesion: 0.12
Nodes (24): _auto_contract_name_body(), generate_contract_name(), 按面板单位全称精确匹配交易主体/客户主数据,取 shortName;对不上则用全称。, 前端预览误用单位全称时,名称片段会等于面板/客户/开票全称。, 按面板供方(partyA)-需方(partyB)生成:{供方简称}-{需方简称}({合同编号})。 - 名称为空:按主数据简称自动生成 - 名, resolve_party_short_name(), _strip_contract_name_no_suffix(), _user_contract_name_uses_party_full_name() (+16 more)
### Community 130 - "datetime_parse.py"
Cohesion: 0.12
Nodes (30): clue_detail(), contact_add(), contact_by_customer(), contact_delete(), contact_detail(), contact_set_primary(), contact_update(), customer_detail() (+22 more)
### Community 131 - "LocalStorage"
Cohesion: 0.07
Nodes (44): ApiRequestLogCRUD, Session, SoftDeleteModel, BizAttachment, 数据模型(与 docs/sql/shanxia2.0.sql 全库导出基线对齐的核心系统表), 角色自定义数据权限明细 sys_role_data_scope_detail, Web 管理端约定角色(由 sys_role.role_name 映射而来,非数据库枚举), 用户-职位关联 sys_user_post (+36 more)
### Community 132 - "crm_supplier_hazard.py"
Cohesion: 0.14
Nodes (23): build_updates(), derive_source_url(), fetch_source_customers(), legacy_id_to_str(), load_oss_map(), load_runtime_settings(), load_settings_env(), main() (+15 more)
### Community 134 - "Community 134"
Cohesion: 0.25
Nodes (18): batch_generate_sample_codes(), batch_issue_sample_codes(), batch_revoke_sample_codes(), create_sample_code(), get_sample_code(), list_sample_codes(), _parse_issued_time(), Any (+10 more)
### Community 135 - "post.py"
Cohesion: 0.24
Nodes (12): get_last_month_range(), month_range(), date, Session, 地磅计划按月自动生成 — 迁移自 simple-dibang-xiaoshou/auto-create-plan/auto_create_monthly_pla, 按月自动生成采购计划。 - 默认仅在每月 1 日执行(force=True 时跳过该限制,供手动触发验收) - 遍历所有租户,按上月计划模板生, run_auto_generate_monthly_plans(), default_execution_status() (+4 more)
### Community 136 - "Community 136"
Cohesion: 0.26
Nodes (14): create_role(), get_role(), get_role_data_scope(), get_role_menu_ids(), list_roles(), Any, Session, 角色 CRUD(sys_role / sys_role_menu / sys_role_data_scope_detail) (+6 more)
### Community 137 - "statistics.py"
Cohesion: 0.12
Nodes (34): advance_issue_stats(), batch_offset(), export_advance_issues(), issue_advance(), list_advance_issues(), list_advance_offset_records(), list_pending_payments(), list_processed_payments() (+26 more)
### Community 138 - "Community 138"
Cohesion: 0.33
Nodes (19): check_python(), create_venv(), ensure_dirs(), ensure_valid_venv(), ensure_venv_and_runtime(), install_dependencies(), is_running(), log_error() (+11 more)
### Community 139 - "minio_url.py"
Cohesion: 0.27
Nodes (10): apply_product_snapshot_to_plan(), ProductSnapshot, Session, 地磅模块 — CRM 产品解析与快照写入。, 校验 CRM 产品并返回名称/规格快照。新建单据 product_id 必填。 require_on_shelf=False 用于运输计划联动地磅等历, resolve_crm_product(), _product(), resolve_crm_product:运输联动场景允许已下架产品。 (+2 more)
### Community 141 - "customer_follow.py"
Cohesion: 0.22
Nodes (10): ChangePasswordRequest, Config, LoginRequest, LoginResponse, ResetPasswordRequest, UserBase, UserCreate, UserListResponse (+2 more)
### Community 143 - "SysEthnic"
Cohesion: 0.33
Nodes (11): create_leave(), get_leave(), list_leaves(), Any, Session, _row_to_dict(), soft_delete_leave(), update_leave() (+3 more)
### Community 144 - "dict_data.py"
Cohesion: 0.33
Nodes (8): allocate_next_biz_no(), _format_biz_no(), _prefix_for(), datetime, Session, 业务协议号自动生成:XBCC / JZCC + YYYYMMDD + 6 位序号, 原子分配下一个业务协议号。 须在 create 事务内调用;使用 MySQL LAST_INSERT_ID 保证并发安全。, BizNoKind
### Community 145 - "minio_url.py"
Cohesion: 0.36
Nodes (7): list_ethnics(), Any, Session, 民族码表 CRUD(全局 sys_ethnic), _row_to_dict(), 民族码表 sys_ethnic(国标 GB/T 3304,全局), SysEthnic
### Community 146 - "__init__.py"
Cohesion: 0.49
Nodes (10): clue_statistics_level(), _apply_create_range(), _base_query(), get_clue_level_statistics(), get_clue_overview_statistics(), get_clue_owner_statistics(), get_clue_source_statistics(), get_clue_trend_statistics() (+2 more)
### Community 147 - "Community 147"
Cohesion: 0.37
Nodes (17): check_env(), check_python(), create_venv(), init_env(), install_dependencies(), log_error(), log_info(), log_success() (+9 more)
### Community 150 - "list_customers"
Cohesion: 0.46
Nodes (7): CrmProductBrand, apply_updates(), collect_candidates(), main(), parse_name(), Path, write_csv()
### Community 152 - ".upload_file"
Cohesion: 0.29
Nodes (6): _format_file_size(), UploadFile, upload_attachment(), 附件上传 bizType 与 MinIO 目录映射(对齐原 CRM oss 上传语义), 优先使用显式 folder;否则按 bizType 映射默认目录。, resolve_upload_folder()
### Community 154 - "response.py"
Cohesion: 0.29
Nodes (6): Config, format_api_error_message(), PageResult, Exception, 将 HTTP/SQLAlchemy 等异常转为可展示的错误文案(避免 str([]) 空列表)。, ResponseModel
### Community 156 - "create_from_quote"
Cohesion: 0.33
Nodes (7): create_from_quote(), _quote_products_to_contract_products(), Java: createFromQuote — 返回合同 id, _parse_optional_date(), date, Java: toContract — 返回 contractId, to_contract()
### Community 159 - "assert_contract_editable_for_update"
Cohesion: 0.60
Nodes (3): assert_contract_editable_for_update(), test_assert_allows_editable(), test_assert_rejects_non_editable()
### Community 160 - "register_local_callback"
Cohesion: 0.23
Nodes (15): create_leave(), delete_leave(), get_leave(), _leave_local_callback(), leave_workflow_callback(), list_leaves(), Session, submit_leave() (+7 more)
### Community 161 - "backfill_crm_contract_attachment_urls.py"
Cohesion: 0.33
Nodes (10): load_oss_map(), load_runtime_settings(), load_settings_env(), main(), Any, Engine, 返回 (新值, 是否发生了 id→url 替换)。, resolve_token() (+2 more)
### Community 162 - "customer_options"
Cohesion: 0.50
Nodes (4): customer_options(), 客户下拉选项(租户内只读,不做 owner 数据权限), CustomerOptionsBody, 客户下拉选项请求体(租户内只读搜索,不做 owner 数据权限)
### Community 170 - "test_quote_approver_setting.py"
Cohesion: 0.20
Nodes (21): _assert_users_exist(), get_setting(), Any, Session, _row_to_dict(), save_setting(), _assert_users_exist(), get_setting() (+13 more)
### Community 173 - "resolve_create_time_bounds"
Cohesion: 0.67
Nodes (3): parse_optional_plan_datetime(), datetime, 运输计划相关日期时间解析:前端 date-picker 仅传 YYYY-MM-DD。
### Community 178 - "product_allowed"
Cohesion: 0.28
Nodes (11): assert_products_allowed_for_supplier(), enrich_products_with_hazard_flags(), get_supplier_hazard_flags(), product_allowed(), Any, Session, 批量回填明细行 isToxic/isExplosive(来自产品主数据,供前端切换主体剔除)。, test_dual_requires_both() (+3 more)
### Community 179 - "_ensure_subpack_slip_no"
Cohesion: 0.06
Nodes (72): archive_plan(), cancel_plan(), cancel_plan_wait_notice(), create_from_contract(), create_plan(), create_plan_full(), _determine_plan_type(), _ensure_subpack_slip_no() (+64 more)
### Community 180 - "menu.py"
Cohesion: 0.36
Nodes (13): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), menu_name_exists(), Any (+5 more)
### Community 187 - "allocate_next_biz_no"
Cohesion: 0.26
Nodes (11): create_oss(), get_oss_by_id(), get_oss_by_url(), Session, 按主键 id 查询附件(兼容旧 CRM 雪花 oss_id 迁入后的记录), 将 fileUrl 或旧 CRM 数字 ossId 解析为 MinIO 相对路径。 门户新上传把相对路径写入业务字段;迁入合同附件仍存数字 ossId, resolve_storage_path(), CrmProductAlias (+3 more)
### Community 206 - "crm_quote_pdf.py"
Cohesion: 0.36
Nodes (10): build_quote_html(), _default_value(), _format_date(), _format_discount(), _format_money(), generate_quote_pdf(), _get_pdf_styles(), Any (+2 more)
### Community 207 - "shanxia2.0 后端骨架(FastAPI)"
Cohesion: 0.18
Nodes (10): 1. 创建虚拟环境, 2. 安装依赖, 3. 配置环境变量, 4. 启动服务, API 路由分组, shanxia2.0 后端骨架(FastAPI), 开发规范, 快速开始 (+2 more)
### Community 220 - "api_crypto_middleware.py"
Cohesion: 0.15
Nodes (21): _claims_from_auth(), _coerce_post_method_override_to_get(), _get_redis_client(), _is_crypto_api(), _json_error_response(), _mark_nonce_once(), _nonce_key(), Redis (+13 more)
### Community 237 - "order_status_compat.py"
Cohesion: 0.36
Nodes (7): derive_legacy_status_from_three(), derive_three_status_from_legacy(), Decimal, 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 239 - "shanxia2.0 Backend 生产部署说明"
Cohesion: 0.25
Nodes (7): 1. 上传到服务器, 2. 服务器首次启动, 3. 日常运维, 4. 配置文件, 5. 与 Nginx 配合, 6. 常见问题, shanxia2.0 Backend 生产部署说明
### Community 246 - "db_collation.py"
Cohesion: 0.38
Nodes (6): eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci()
## Knowledge Gaps
- **30 isolated node(s):** `Config`, `Config`, `Config`, `Config`, `Config` (+25 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **18 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Settings` connect `Community 72` to `backfill_crm_contract_attachment_urls.py`, `_ensure_subpack_slip_no`, `Community 35`, `crm_supplier_hazard.py`, `Community 5`, `Community 67`, `price_letter_detail`, `Community 73`, `Community 42`, `Base`, `Community 52`, `Any`, `Community 59`, `Community 30`?**
_High betweenness centrality (0.109) - this node is a cross-community bridge._
- **Why does `generate_uuid()` connect `Community 26` to `Community 0`, `plan.py`, `datetime_parse.py`, `Community 2`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 136`, `Community 134`, `post.py`, `Community 11`, `SysEthnic`, `dict_data.py`, `Community 15`, `Community 16`, `Community 19`, `Community 21`, `list_customers`, `Community 25`, `Community 27`, `Community 28`, `Community 34`, `Community 36`, `Community 38`, `Community 39`, `test_quote_approver_setting.py`, `Community 43`, `Community 45`, `Community 49`, `_ensure_subpack_slip_no`, `menu.py`, `Community 53`, `Community 51`, `allocate_next_biz_no`, `Community 61`, `Community 65`, `Community 66`, `Community 67`, `Community 68`, `Community 70`, `Community 74`, `Community 81`, `Community 83`, `Community 86`, `Community 87`, `pl_ocr_service.py`, `pl_vehicle_recharge_service.py`, `Community 95`, `dept.py`, `apply_crm_create_by_scope`, `list_customers`, `Community 106`, `Community 109`, `quote_share_log.py`, `db_models.py`, `site.py`, `Community 116`, `Community 118`, `Community 122`, `Community 125`, `customer_pool.py`?**
_High betweenness centrality (0.107) - this node is a cross-community bridge._
- **Why does `BaseModel` connect `Community 24` to `Community 0`, `Community 1`, `datetime_parse.py`, `LocalStorage`, `Community 6`, `Community 7`, `statistics.py`, `Community 11`, `Community 12`, `customer_follow.py`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `response.py`, `Community 27`, `Community 26`, `register_local_callback`, `Community 33`, `Community 34`, `customer_options`, `Community 45`, `Community 46`, `Community 48`, `_ensure_subpack_slip_no`, `Community 51`, `Community 54`, `Community 58`, `Community 62`, `Community 63`, `Community 64`, `Community 65`, `Community 66`, `Community 68`, `Community 71`, `Community 74`, `Community 86`, `Community 92`, `list_customers`, `Community 106`, `Community 111`, `storage.py`, `site.py`, `Community 119`, `Community 127`?**
_High betweenness centrality (0.103) - this node is a cross-community bridge._
- **Are the 8 inferred relationships involving `DbUserContext` (e.g. with `InventoryRelatedData` and `AutoGenerateMonthlyResult`) actually correct?**
_`DbUserContext` has 8 INFERRED edges - model-reasoned connections that need verification._
- **What connects `API 路由包 — 山峡化工生产一体化门户`, `返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。`, `返回用户下拉选项(label=昵称,value=用户ID,附带 nickName/userNo)。 供申请人/审批人等选择场景使用,返回本租户全部有效` to the rest of the system?**
_520 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
_Cohesion score 0.08888888888888889 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.061367621274108705 - nodes in this community are weakly interconnected._
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,536 @@
{
"0": "Community 0",
"1": "Community 1",
"2": "Community 2",
"3": "Community 3",
"4": "Community 4",
"5": "Community 5",
"6": "Community 6",
"7": "Community 7",
"8": "Community 8",
"9": "Community 9",
"10": "Community 10",
"11": "Community 11",
"12": "Community 12",
"13": "Community 13",
"14": "Community 14",
"15": "Community 15",
"16": "Community 16",
"17": "Community 17",
"18": "Community 18",
"19": "Community 19",
"20": "Community 20",
"21": "Community 21",
"22": "Community 22",
"23": "Community 23",
"24": "Community 24",
"25": "Community 25",
"26": "Community 26",
"27": "Community 27",
"28": "Community 28",
"29": "Community 29",
"30": "Community 30",
"31": "Community 31",
"32": "Community 32",
"33": "Community 33",
"34": "Community 34",
"35": "Community 35",
"36": "Community 36",
"37": "Community 37",
"38": "Community 38",
"39": "Community 39",
"40": "Community 40",
"41": "Community 41",
"42": "Community 42",
"43": "Community 43",
"44": "Community 44",
"45": "Community 45",
"46": "Community 46",
"47": "Community 47",
"48": "Community 48",
"49": "Community 49",
"50": "Community 50",
"51": "Community 51",
"52": "Community 52",
"53": "Community 53",
"54": "Community 54",
"55": "Community 55",
"56": "Community 56",
"57": "Community 57",
"58": "Community 58",
"59": "Community 59",
"60": "Community 60",
"61": "Community 61",
"62": "Community 62",
"63": "Community 63",
"64": "Community 64",
"65": "Community 65",
"66": "Community 66",
"67": "Community 67",
"68": "Community 68",
"69": "Community 69",
"70": "Community 70",
"71": "Community 71",
"72": "Community 72",
"73": "Community 73",
"74": "Community 74",
"75": "Community 75",
"76": "Community 76",
"77": "Community 77",
"78": "Community 78",
"79": "Community 79",
"80": "Community 80",
"81": "Community 81",
"82": "Community 82",
"83": "Community 83",
"84": "Community 84",
"85": "Community 85",
"86": "Community 86",
"87": "Community 87",
"88": "Any",
"89": "pl_ocr_service.py",
"90": "Community 90",
"91": "pl_vehicle_recharge_service.py",
"92": "Community 92",
"93": "_invoice_info_by_customer_impl",
"94": "response.py",
"95": "Community 95",
"96": "Community 96",
"97": "_ensure_subpack_slip_no",
"98": "Community 98",
"99": "Community 99",
"100": "price_letter_detail",
"101": ".to_tenant_user_dict",
"102": "dept.py",
"103": "Community 103",
"104": "apply_crm_create_by_scope",
"105": "list_customers",
"106": "Community 106",
"107": "apply_pl_scope",
"108": "Community 108",
"109": "Community 109",
"110": "Base",
"111": "Community 111",
"112": "storage.py",
"113": "quote_share_log.py",
"114": "db_models.py",
"115": "site.py",
"116": "Community 116",
"117": "Community 117",
"118": "Community 118",
"119": "Community 119",
"120": "Community 120",
"121": "Community 121",
"122": "Community 122",
"123": "Community 123",
"124": "Community 124",
"125": "Community 125",
"126": "customer_pool.py",
"127": "Community 127",
"128": "plan.py",
"129": "BaseStorage",
"130": "datetime_parse.py",
"131": "LocalStorage",
"132": "crm_supplier_hazard.py",
"133": "Community 133",
"134": "Community 134",
"135": "unsettled_plans_q_filter",
"136": "Community 136",
"137": "statistics.py",
"138": "Community 138",
"139": "get_current_user_by_token",
"140": "Community 140",
"141": "PlTransport",
"142": "Community 142",
"143": "SysEthnic",
"144": "dict_data.py",
"145": "resolve_crm_product",
"146": "__init__.py",
"147": "Community 147",
"148": "storage.py",
"149": "Community 149",
"150": "apply_site_feedback",
"151": "Community 151",
"152": "response.py",
"153": "Community 153",
"154": "response.py",
"155": "Community 155",
"156": "utils.py",
"157": "Community 157",
"158": "Community 158",
"159": "customer_update",
"160": "register_local_callback",
"161": "backfill_crm_contract_attachment_urls.py",
"162": ".to_tenant_user_dict",
"163": "__init__.py",
"164": "get_client_ip",
"165": "Community 165",
"166": "code:block1 (/iflytek/shanxia2.0/backend)",
"167": "Community 167",
"168": "vehicle_urea.py",
"169": "product.py",
"170": "test_quote_approver_setting.py",
"173": "resolve_create_time_bounds",
"175": "vehicle_maintenance.py",
"176": "_forbid_legacy_invoice_fields",
"177": "vehicle_maintenance.py",
"179": "_ensure_subpack_slip_no",
"182": "statistics.py",
"183": "MinIOStorage",
"185": "vehicle_urea.py",
"186": "transport_address.py",
"187": "allocate_next_biz_no",
"189": "create",
"190": "menu.py",
"191": "BaseStorage",
"192": "pool_rule.py",
"193": "LocalStorage",
"196": "SoftDeleteModel",
"197": "_coerce_resource_snapshot",
"198": "user.py",
"200": "register_local_callback",
"202": "statistics.py",
"206": "crm_quote_pdf.py",
"207": "shanxia2.0 后端骨架(FastAPI)",
"211": "leave.py",
"216": "io_order.py",
"217": "auth.py",
"218": "pool_rule.py",
"220": "api_crypto_middleware.py",
"223": "workflow.py",
"224": "supplier_info.py",
"226": "get_active",
"228": "advance.py",
"230": "attachment.py",
"232": "transport_address.py",
"233": "customer_pool.py",
"235": "invoice_info.py",
"236": "price_letter.py",
"237": "order_status_compat.py",
"239": "shanxia2.0 Backend 生产部署说明",
"240": "delete",
"242": "leave.py",
"244": "expense_item.py",
"245": "__init__.py",
"246": "db_collation.py",
"247": "expense_item.py",
"249": "__init__.py",
"250": "invoice.py",
"251": "menu.py",
"252": "public_inventory.py",
"254": "Activate.ps1",
"256": "statistics.py",
"259": "一次上传一条发票:多文件挂同一档案,金额为总额,只写一条额度流水。",
"262": "reimburse.py",
"263": "__init__.py",
"264": "__init__.py",
"265": "__init__.py",
"266": "workflow.py",
"269": "__init__.py",
"270": "leave.py",
"271": "menu.py",
"272": "__init__.py",
"273": "__init__.py",
"274": "__init__.py",
"275": "__init__.py",
"276": "__init__.py",
"278": "__init__.py",
"281": "__init__.py",
"286": "send_delivery_notice",
"287": "__init__.py",
"288": "__init__.py",
"289": "send_delivery_warning",
"292": "send_order_status",
"293": "__init__.py",
"294": "__init__.py",
"295": "__init__.py",
"296": "__init__.py",
"297": "__init__.py",
"298": "__init__.py",
"299": "__init__.py",
"300": "__init__.py",
"301": "__init__.py",
"302": "send_payment_success",
"303": "send_refund_result",
"304": "__init__.py",
"305": "__init__.py",
"306": "__init__.py",
"307": "__init__.py",
"308": "__init__.py",
"309": "__init__.py",
"310": "__init__.py",
"311": "__init__.py",
"312": "__init__.py",
"313": "send_urge_notification",
"314": "get",
"315": "get_multi_with_filters",
"317": "base.py",
"318": "clue.py",
"320": "customer_pool.py",
"321": "customer.py",
"323": "invoice_info.py",
"326": "price_letter.py",
"327": "product.py",
"328": "quote.py",
"329": "user.py",
"330": "base.py",
"331": "__tablename__",
"332": "__init__.py",
"333": "advance.py",
"334": "validate_expense_item_id",
"335": "attachment.py",
"336": "common.py",
"337": "validate_parent_id",
"338": "__init__.py",
"339": "invoice.py",
"340": "coerce_applicant_id",
"341": "details_must_not_be_empty",
"342": "reimburse.py",
"343": "validate_advance_id",
"344": "validate_expense_item_id",
"345": "validate_approver_id",
"346": "common.py",
"347": "contact.py",
"348": "customer_follow.py",
"349": "customer.py",
"350": "dashboard.py",
"351": "__init__.py",
"352": "inventory.py",
"353": "plans.py",
"354": "weighing.py",
"355": "__init__.py",
"356": "freight.py",
"357": "__init__.py",
"358": "plan.py",
"360": "validate_coordinates",
"361": "transport.py",
"362": "validate_amount",
"363": "validate_amount",
"364": "validate_recharge_type",
"365": "validate_amount",
"366": "validate_apply_amount",
"367": "validate_quantity",
"368": "approve",
"369": "create",
"370": "finance_issue_stats",
"371": "get_by_id",
"372": "get_paged",
"373": "global_status_counts",
"374": "issue",
"375": "_latest_approval_per_node",
"376": "_my_apply_base",
"377": "my_apply_stats",
"378": "offset_amount_map",
"379": "pending_approval_stats",
"380": "advance.py",
"381": "_query_approvals",
"382": "reject",
"383": "soft_delete",
"384": "submit",
"385": "_tenant_no",
"386": "update",
"387": "_workflow_nodes",
"389": "create",
"390": "get_by_biz",
"391": "get_by_id",
"392": "attachment.py",
"393": "soft_delete",
"394": "_tenant_no",
"395": "get_by_id",
"396": "get_paged",
"397": "base.py",
"398": "soft_delete",
"399": "update",
"401": "_build_tree",
"402": "create",
"403": "get_by_id",
"404": "get_item_tree",
"405": "expense_item.py",
"406": "soft_delete",
"407": "_tenant_no",
"408": "update",
"409": "_count_invoices",
"410": "create",
"411": "delete",
"412": "get_mine_summary",
"413": "is_wallet_admin",
"414": "add_entry",
"415": "assert_can_delete_invoice",
"416": "calc_summary",
"417": "debit_reimburse",
"418": "list_entries",
"419": "_lock_summary",
"420": "refresh_summary",
"421": "release_reimburse",
"422": "list_ledgers",
"423": "list_wallets",
"424": "_lookup_user_name",
"425": "out_rows_with_attachments",
"426": "invoice.py",
"427": "_require_wallet_admin",
"428": "_resolve_owner",
"429": "_resolve_owner_for_query",
"430": "_summary_to_dict",
"431": "_tenant_no",
"432": "approve",
"433": "batch_offset",
"434": "build_apply_out_with_details",
"435": "build_expense_name_condition",
"436": "can_change_applicant",
"437": "create_with_details",
"438": "finance_payment_stats",
"439": "get_by_id",
"440": "get_details",
"441": "get_details_map_by_reimburse_ids",
"442": "get_linked_invoice_ids",
"443": "get_linked_invoice_ids_map",
"444": "get_linked_invoices_brief",
"445": "get_paged",
"446": "global_status_counts",
"447": "_has_debit_reimburse",
"448": "_latest_approval_per_node",
"449": "_my_apply_base",
"450": "my_apply_stats",
"451": "offset",
"452": "out_one_with_attachment_counts",
"453": "out_rows_with_attachment_counts",
"454": "pay",
"455": "reimburse.py",
"456": "_query_approvals",
"457": "reject",
"458": "resolve_applicant",
"459": "soft_delete",
"460": "submit",
"461": "sync_reimburse_invoices",
"462": "_tenant_no",
"463": "update_with_details",
"464": "withdraw",
"465": "_workflow_nodes",
"466": "ensure_by_biz_type",
"467": "get_by_biz_type",
"468": "get_by_id",
"469": "get_paged",
"470": "workflow.py",
"471": "save_nodes",
"472": "soft_delete",
"473": "_tenant_no",
"474": "update",
"487": "_get_variable",
"488": "_parse_node_config",
"489": "_parse_variables",
"490": "customer_pool.py",
"491": "__init__.py",
"495": "code:bash (cd /path/to/shanxia2.0)",
"496": "code:bash (./start-prod.sh status # 查看状态)",
"497": "code:bash (curl -s http://127.0.0.1:9111/health)",
"498": "code:bash (cd /iflytek/shanxia2.0/backend)",
"499": "code:bash (python -m venv venv)",
"500": "code:bash (pip install -r requirements.txt)",
"501": "code:env (# 数据库配置)",
"502": "code:bash (uvicorn app.main:app --reload --port 8000)",
"503": "BaseModel",
"504": "PlanResourceSnapshotMixin",
"510": "advance.py",
"511": "attachment.py",
"512": "expense_item.py",
"514": "workflow.py",
"517": "dashboard.py",
"518": "__init__.py",
"519": "inventory.py",
"520": "plans.py",
"521": "public_inventory.py",
"522": "weighing.py",
"523": "__init__.py",
"524": "leave.py",
"525": "menu.py",
"526": "base_data.py",
"527": "freight.py",
"528": "__init__.py",
"529": "inventory.py",
"530": "io_order.py",
"531": "plan.py",
"533": "transport_address.py",
"534": "transport.py",
"535": "vehicle_maintenance.py",
"536": "vehicle_recharge.py",
"537": "vehicle_urea.py",
"538": "workflow.py",
"539": "auth.py",
"545": "__init__.py",
"548": "storage.py",
"551": "base.py",
"553": "clue.py",
"554": "contact.py",
"555": "contract.py",
"556": "customer_follow.py",
"557": "customer_pool.py",
"558": "customer.py",
"559": "invoice_info.py",
"560": "opportunity.py",
"561": "pool_rule.py",
"562": "price_letter.py",
"563": "product.py",
"564": "quote.py",
"565": "statistics.py",
"566": "supplier_info.py",
"569": "__init__.py",
"570": "leave.py",
"571": "menu.py",
"573": "user.py",
"574": "workflow.py",
"576": "base.py",
"577": "__init__.py",
"578": "attachment.py",
"579": "auth.py",
"580": "advance.py",
"581": "attachment.py",
"582": "common.py",
"583": "expense_item.py",
"584": "__init__.py",
"585": "workflow.py",
"586": "common.py",
"587": "clue.py",
"588": "contact.py",
"589": "contract.py",
"590": "customer_follow.py",
"591": "customer_pool.py",
"592": "customer.py",
"593": "invoice_info.py",
"594": "opportunity.py",
"595": "pool_rule.py",
"596": "price_letter.py",
"597": "product.py",
"598": "quote.py",
"599": "statistics.py",
"600": "supplier_info.py",
"601": "dashboard.py",
"602": "__init__.py",
"603": "inventory.py",
"604": "plans.py",
"605": "public_inventory.py",
"606": "weighing.py",
"607": "__init__.py",
"608": "leave.py",
"609": "menu.py",
"610": "base_data.py",
"611": "freight.py",
"612": "__init__.py",
"613": "inventory.py",
"614": "io_order.py",
"615": "plan.py",
"616": "transport_address.py",
"617": "transport.py",
"618": "vehicle_maintenance.py",
"619": "vehicle_recharge.py",
"620": "vehicle_urea.py",
"621": "user.py",
"622": "workflow.py",
"623": "advance.py",
"624": "attachment.py",
"625": "base.py",
"626": "expense_item.py",
"627": "storage.py",
"628": "workflow.py",
"636": "customer_pool.py",
"638": "__init__.py"
}
@@ -0,0 +1,790 @@
# Graph Report - backend (2026-08-06)
## Corpus Check
- 315 files · ~209,958 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 4660 nodes · 15719 edges · 534 communities (518 shown, 16 thin omitted)
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 410 edges (avg confidence: 0.53)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `5cf67f60`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
## Community Hubs (Navigation)
- [[_COMMUNITY_Community 0|Community 0]]
- [[_COMMUNITY_Community 1|Community 1]]
- [[_COMMUNITY_Community 2|Community 2]]
- [[_COMMUNITY_Community 3|Community 3]]
- [[_COMMUNITY_Community 4|Community 4]]
- [[_COMMUNITY_Community 5|Community 5]]
- [[_COMMUNITY_Community 6|Community 6]]
- [[_COMMUNITY_Community 7|Community 7]]
- [[_COMMUNITY_Community 8|Community 8]]
- [[_COMMUNITY_Community 11|Community 11]]
- [[_COMMUNITY_Community 12|Community 12]]
- [[_COMMUNITY_Community 13|Community 13]]
- [[_COMMUNITY_Community 14|Community 14]]
- [[_COMMUNITY_Community 15|Community 15]]
- [[_COMMUNITY_Community 16|Community 16]]
- [[_COMMUNITY_Community 18|Community 18]]
- [[_COMMUNITY_Community 19|Community 19]]
- [[_COMMUNITY_Community 21|Community 21]]
- [[_COMMUNITY_Community 22|Community 22]]
- [[_COMMUNITY_Community 23|Community 23]]
- [[_COMMUNITY_Community 24|Community 24]]
- [[_COMMUNITY_Community 25|Community 25]]
- [[_COMMUNITY_Community 26|Community 26]]
- [[_COMMUNITY_Community 27|Community 27]]
- [[_COMMUNITY_Community 28|Community 28]]
- [[_COMMUNITY_Community 29|Community 29]]
- [[_COMMUNITY_Community 30|Community 30]]
- [[_COMMUNITY_Community 33|Community 33]]
- [[_COMMUNITY_Community 34|Community 34]]
- [[_COMMUNITY_Community 35|Community 35]]
- [[_COMMUNITY_Community 36|Community 36]]
- [[_COMMUNITY_Community 37|Community 37]]
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 49|Community 49]]
- [[_COMMUNITY_Community 50|Community 50]]
- [[_COMMUNITY_Community 51|Community 51]]
- [[_COMMUNITY_Community 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
- [[_COMMUNITY_Community 54|Community 54]]
- [[_COMMUNITY_Community 58|Community 58]]
- [[_COMMUNITY_Community 59|Community 59]]
- [[_COMMUNITY_Community 60|Community 60]]
- [[_COMMUNITY_Community 61|Community 61]]
- [[_COMMUNITY_Community 62|Community 62]]
- [[_COMMUNITY_Community 63|Community 63]]
- [[_COMMUNITY_Community 64|Community 64]]
- [[_COMMUNITY_Community 65|Community 65]]
- [[_COMMUNITY_Community 66|Community 66]]
- [[_COMMUNITY_Community 67|Community 67]]
- [[_COMMUNITY_Community 68|Community 68]]
- [[_COMMUNITY_Community 69|Community 69]]
- [[_COMMUNITY_Community 70|Community 70]]
- [[_COMMUNITY_Community 71|Community 71]]
- [[_COMMUNITY_Community 72|Community 72]]
- [[_COMMUNITY_Community 73|Community 73]]
- [[_COMMUNITY_Community 74|Community 74]]
- [[_COMMUNITY_Community 77|Community 77]]
- [[_COMMUNITY_Community 78|Community 78]]
- [[_COMMUNITY_Community 81|Community 81]]
- [[_COMMUNITY_Community 83|Community 83]]
- [[_COMMUNITY_Community 84|Community 84]]
- [[_COMMUNITY_Community 86|Community 86]]
- [[_COMMUNITY_Community 87|Community 87]]
- [[_COMMUNITY_Any|Any]]
- [[_COMMUNITY_pl_ocr_service.py|pl_ocr_service.py]]
- [[_COMMUNITY_pl_vehicle_recharge_service.py|pl_vehicle_recharge_service.py]]
- [[_COMMUNITY_Community 92|Community 92]]
- [[_COMMUNITY__invoice_info_by_customer_impl|_invoice_info_by_customer_impl]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_Community 95|Community 95]]
- [[_COMMUNITY__ensure_subpack_slip_no|_ensure_subpack_slip_no]]
- [[_COMMUNITY_price_letter_detail|price_letter_detail]]
- [[_COMMUNITY_.to_tenant_user_dict|.to_tenant_user_dict]]
- [[_COMMUNITY_dept.py|dept.py]]
- [[_COMMUNITY_apply_crm_create_by_scope|apply_crm_create_by_scope]]
- [[_COMMUNITY_list_customers|list_customers]]
- [[_COMMUNITY_Community 106|Community 106]]
- [[_COMMUNITY_apply_pl_scope|apply_pl_scope]]
- [[_COMMUNITY_Community 109|Community 109]]
- [[_COMMUNITY_Base|Base]]
- [[_COMMUNITY_Community 111|Community 111]]
- [[_COMMUNITY_storage.py|storage.py]]
- [[_COMMUNITY_quote_share_log.py|quote_share_log.py]]
- [[_COMMUNITY_db_models.py|db_models.py]]
- [[_COMMUNITY_site.py|site.py]]
- [[_COMMUNITY_Community 116|Community 116]]
- [[_COMMUNITY_Community 118|Community 118]]
- [[_COMMUNITY_Community 119|Community 119]]
- [[_COMMUNITY_Community 122|Community 122]]
- [[_COMMUNITY_Community 125|Community 125]]
- [[_COMMUNITY_customer_pool.py|customer_pool.py]]
- [[_COMMUNITY_Community 127|Community 127]]
- [[_COMMUNITY_plan.py|plan.py]]
- [[_COMMUNITY_BaseStorage|BaseStorage]]
- [[_COMMUNITY_datetime_parse.py|datetime_parse.py]]
- [[_COMMUNITY_LocalStorage|LocalStorage]]
- [[_COMMUNITY_crm_supplier_hazard.py|crm_supplier_hazard.py]]
- [[_COMMUNITY_Community 134|Community 134]]
- [[_COMMUNITY_unsettled_plans_q_filter|unsettled_plans_q_filter]]
- [[_COMMUNITY_Community 136|Community 136]]
- [[_COMMUNITY_statistics.py|statistics.py]]
- [[_COMMUNITY_Community 138|Community 138]]
- [[_COMMUNITY_get_current_user_by_token|get_current_user_by_token]]
- [[_COMMUNITY_PlTransport|PlTransport]]
- [[_COMMUNITY_SysEthnic|SysEthnic]]
- [[_COMMUNITY_dict_data.py|dict_data.py]]
- [[_COMMUNITY_resolve_crm_product|resolve_crm_product]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_Community 147|Community 147]]
- [[_COMMUNITY_apply_site_feedback|apply_site_feedback]]
- [[_COMMUNITY_Community 151|Community 151]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_utils.py|utils.py]]
- [[_COMMUNITY_customer_update|customer_update]]
- [[_COMMUNITY_register_local_callback|register_local_callback]]
- [[_COMMUNITY_backfill_crm_contract_attachment_urls.py|backfill_crm_contract_attachment_urls.py]]
- [[_COMMUNITY_.to_tenant_user_dict|.to_tenant_user_dict]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_get_client_ip|get_client_ip]]
- [[_COMMUNITY_codeblock1 (iflytekshanxia2.0backend)|code:block1 (/iflytek/shanxia2.0/backend)]]
- [[_COMMUNITY_test_quote_approver_setting.py|test_quote_approver_setting.py]]
- [[_COMMUNITY_resolve_create_time_bounds|resolve_create_time_bounds]]
- [[_COMMUNITY__ensure_subpack_slip_no|_ensure_subpack_slip_no]]
- [[_COMMUNITY_statistics.py|statistics.py]]
- [[_COMMUNITY_MinIOStorage|MinIOStorage]]
- [[_COMMUNITY_allocate_next_biz_no|allocate_next_biz_no]]
- [[_COMMUNITY_BaseStorage|BaseStorage]]
- [[_COMMUNITY_LocalStorage|LocalStorage]]
- [[_COMMUNITY_SoftDeleteModel|SoftDeleteModel]]
- [[_COMMUNITY_register_local_callback|register_local_callback]]
- [[_COMMUNITY_crm_quote_pdf.py|crm_quote_pdf.py]]
- [[_COMMUNITY_shanxia2.0 后端骨架(FastAPI)|shanxia2.0 后端骨架(FastAPI)]]
- [[_COMMUNITY_api_crypto_middleware.py|api_crypto_middleware.py]]
- [[_COMMUNITY_order_status_compat.py|order_status_compat.py]]
- [[_COMMUNITY_shanxia2.0 Backend 生产部署说明|shanxia2.0 Backend 生产部署说明]]
- [[_COMMUNITY_db_collation.py|db_collation.py]]
- [[_COMMUNITY_一次上传一条发票:多文件挂同一档案,金额为总额,只写一条额度流水。|一次上传一条发票:多文件挂同一档案,金额为总额,只写一条额度流水。]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_codebash (cd pathtoshanxia2.0)|code:bash (cd /path/to/shanxia2.0)]]
- [[_COMMUNITY_codebash (.start-prod.sh status 查看状态)|code:bash (./start-prod.sh status # 查看状态)]]
- [[_COMMUNITY_codebash (curl -s http127.0.0.19111health)|code:bash (curl -s http://127.0.0.1:9111/health)]]
- [[_COMMUNITY_codebash (cd iflytekshanxia2.0backend)|code:bash (cd /iflytek/shanxia2.0/backend)]]
- [[_COMMUNITY_codebash (python -m venv venv)|code:bash (python -m venv venv)]]
- [[_COMMUNITY_codebash (pip install -r requirements.txt)|code:bash (pip install -r requirements.txt)]]
- [[_COMMUNITY_codeenv ( 数据库配置)|code:env (# 数据库配置)]]
- [[_COMMUNITY_codebash (uvicorn app.mainapp --reload --port 8000)|code:bash (uvicorn app.main:app --reload --port 8000)]]
- [[_COMMUNITY_BaseModel|BaseModel]]
- [[_COMMUNITY_PlanResourceSnapshotMixin|PlanResourceSnapshotMixin]]
## God Nodes (most connected - your core abstractions)
1. `BaseModel` - 443 edges
2. `get_tenant_no()` - 350 edges
3. `DbUserContext` - 254 edges
4. `success_response()` - 254 edges
5. `error_response()` - 236 edges
6. `generate_uuid()` - 195 edges
7. `BxUserContext` - 183 edges
8. `crm_user_info()` - 137 edges
9. `assert_row_deletable_by_creator()` - 83 edges
10. `ApiResponse` - 79 edges
## Surprising Connections (you probably didn't know these)
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_bx_data.py → app/core/config.py
- `StepStats` --uses--> `Settings` [INFERRED]
scripts/migrate_bx_data.py → app/core/config.py
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_clue.py → app/core/config.py
- `StepStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_clue.py → app/core/config.py
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_contract.py → app/core/config.py
## Import Cycles
- None detected.
## Communities (534 total, 16 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.11
Nodes (42): check_document_expiry(), document_reminder_stats(), get_inventory_ledger(), get_summary(), list_document_reminders(), list_transactions(), list_warnings(), date (+34 more)
### Community 1 - "Community 1"
Cohesion: 0.08
Nodes (38): CRM 合同 API 路由 — GET/PUT/DELETE/POST 对齐原 Java CRM, 接口菜单权限守卫。super_admin 直接放行。, require_menu_code(), ContractApproverSettingSaveBody, ContractApprovalActionBody, ContractApprovalPassBody, ContractApprovalRejectBody, ContractApprovalTransferBody (+30 more)
### Community 2 - "Community 2"
Cohesion: 0.13
Nodes (33): _apply_inventory_product_update(), _apply_inventory_update(), _base_query(), create_inventory(), create_link_for_plan(), delete_inventory(), _generate_batch_no(), _get_inventory() (+25 more)
### Community 3 - "Community 3"
Cohesion: 0.08
Nodes (90): attachment_download_url(), attachment_preview_url(), AttachmentDownloadUrlBody, create_dept(), create_dict_data(), create_dict_type(), create_menu(), create_post() (+82 more)
### Community 4 - "Community 4"
Cohesion: 0.09
Nodes (76): _apply_list_filters(), assign_opportunities(), batch_update_expect_date(), batch_update_stage(), change_stage(), create_opportunity(), _decimal_value(), _enrich_user_names() (+68 more)
### Community 5 - "Community 5"
Cohesion: 0.20
Nodes (24): count_source_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings(), load_settings_env(), load_user_mapping() (+16 more)
### Community 6 - "Community 6"
Cohesion: 0.18
Nodes (32): assign_customer(), batch_claim_customers(), check_duplicate_customer(), claim_customer(), create_customer(), deal_customer(), _enrich_user_names(), _ensure_customer_in_scope() (+24 more)
### Community 7 - "Community 7"
Cohesion: 0.11
Nodes (41): approve_carrier(), create_carrier(), create_driver(), get_carrier(), get_driver(), list_carriers(), list_drivers(), _personnel_to_driver_read() (+33 more)
### Community 8 - "Community 8"
Cohesion: 0.10
Nodes (68): register_quote_routes(), apply_crm_owner_scope(), accept_quote(), _build_quote_filters(), calculate_quote_amount(), create_new_version(), create_quote(), _decimal_value() (+60 more)
### Community 11 - "Community 11"
Cohesion: 0.10
Nodes (55): cancel_apply(), create_apply(), create_disburse(), delete_applies(), delete_disburses(), get_apply(), get_disburse(), list_applies() (+47 more)
### Community 12 - "Community 12"
Cohesion: 0.05
Nodes (72): contact_add(), contact_delete(), contact_update(), customer_delete(), BaseModel, AttachmentUploadResponse, ChangePasswordRequest, Config (+64 more)
### Community 13 - "Community 13"
Cohesion: 0.11
Nodes (40): register_contract_routes(), batch_assign_owner(), batch_submit_contract_approval(), _build_contract_filters(), contract_row_to_dict(), download_contract_pdf(), _ensure_contract_in_scope(), export_contracts() (+32 more)
### Community 14 - "Community 14"
Cohesion: 0.28
Nodes (17): _address_to_read(), _build_address_query(), create_transport_address(), delete_transport_address(), _get_address(), get_transport_address(), list_all_transport_addresses(), list_transport_addresses() (+9 more)
### Community 15 - "Community 15"
Cohesion: 0.11
Nodes (16): BxReimburseApply, BxReimburseApproval, BxReimburseDetail, BxReimburseInvoice, 报销单勾选的发票附件(同一发票可勾选多个附件,各占一条)。, ReimburseApplyOut, ReimburseInvoiceBriefOut, ReimburseInvoiceLinkIn (+8 more)
### Community 16 - "Community 16"
Cohesion: 0.09
Nodes (60): cancel_apply(), create_apply(), create_record(), delete_applies(), delete_records(), get_apply(), get_record(), list_applies() (+52 more)
### Community 18 - "Community 18"
Cohesion: 0.10
Nodes (42): advance_pending_approval_stats(), advance_status_counts(), approve_advance(), approved_by_me(), create_advance(), delete_advance(), _fill_offset_amounts(), get_advance() (+34 more)
### Community 19 - "Community 19"
Cohesion: 0.33
Nodes (8): _format_summary(), _pick_field(), _preserve_fastapi_signature(), Any, 路由操作日志装饰器:写入 ContextVar 供中间件落库, FastAPI 通过 inspect.signature + wrapper.__globals__ 解析类型;需在原函数命名空间下解析后写回。, _resolve_business_id(), _to_dict()
### Community 21 - "Community 21"
Cohesion: 0.08
Nodes (66): generate_uuid(), _alias_row_to_dict(), _assert_brand_deletable(), barcode_exists(), _brand_row_to_dict(), _build_category_tree(), category_code_exists(), _category_row_to_dict() (+58 more)
### Community 22 - "Community 22"
Cohesion: 0.08
Nodes (28): parse_admin_request_json(), Any, Request, 运营 Web(/web/admin)JSON 请求体解析。 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `{, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。 Returns:, ApiCryptoError, _b64url_decode(), _b64url_encode() (+20 more)
### Community 23 - "Community 23"
Cohesion: 0.11
Nodes (8): convert_heic_to_jpeg(), OSSStorage, process_image_content(), QiniuStorage, 文件存储工具模块 支持多种存储方式: 1. 本地存储 (local) - 默认 2. 七牛云存储 (qiniu) - 推荐生产环境使用 3. 阿里云OSS (, 将 HEIC/HEIF 格式转换为 JPEG 格式, 处理图片内容,如果是 HEIC 格式则转换为 JPEG, BytesIO
### Community 24 - "Community 24"
Cohesion: 0.13
Nodes (35): approve_reimburse(), approved_by_me(), _build_details_data(), create_reimburse(), delete_reimburse(), get_approval_history(), get_approvals(), get_generated_title() (+27 more)
### Community 25 - "Community 25"
Cohesion: 0.13
Nodes (27): PlInventoryTransaction, 库存流水表 pl_inventory_transaction, load_brand_qtys_by_plan_product_ids(), persist_plan_product_brand_qtys(), Any, Decimal, Session, 按计划产品明细 ID 批量加载归档品牌数量(brandId/brandName/qty)。 (+19 more)
### Community 26 - "Community 26"
Cohesion: 0.09
Nodes (38): ApiRequestLogMiddleware, _claims_from_auth(), _format_body_bytes(), _persist_log(), Any, Request, 统一记录 API 请求/响应出入参的中间件, _redact_obj() (+30 more)
### Community 27 - "Community 27"
Cohesion: 0.28
Nodes (15): create_clue_follow(), delete_clue_follow(), get_clue_follow(), get_follow_statistics(), list_clue_follows(), Any, Session, 更新线索跟进记录,必要时同步线索 next_time (+7 more)
### Community 28 - "Community 28"
Cohesion: 0.05
Nodes (98): approve_settlement_legacy(), cancel_settlement(), create_settlement(), delete_settlement(), disburse_settlement(), _generate_settlement_no(), get_settlement(), get_settlement_approval_flow() (+90 more)
### Community 29 - "Community 29"
Cohesion: 0.06
Nodes (60): 返回 (作废, 归档)。现场链接实际走入库/出库单公共页。, _resolve_io_order_link_flags(), _build_public_page(), _build_site_product_read(), _format_file_size(), get_public_site(), _get_site_link_by_token(), _parse_feedback_images() (+52 more)
### Community 30 - "Community 30"
Cohesion: 0.16
Nodes (26): clear_target_categories(), compute_level(), count_target_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings() (+18 more)
### Community 33 - "Community 33"
Cohesion: 0.12
Nodes (24): bind_biz(), delete_attachment(), download_file(), list_by_biz(), _parse_id_list(), preview_attachment(), Session, UploadFile (+16 more)
### Community 34 - "Community 34"
Cohesion: 0.13
Nodes (35): approve_task(), _assert_wf_instance_in_scope(), _business_type_label(), create_process_def(), delete_process_def(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields() (+27 more)
### Community 35 - "Community 35"
Cohesion: 0.18
Nodes (36): clear_portal_workflow(), _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_bx_user_mapping(), load_runtime_settings() (+28 more)
### Community 36 - "Community 36"
Cohesion: 0.14
Nodes (29): 验证密码(哈希非 bcrypt 或损坏时返回 False,避免抛错), verify_password(), change_password(), create_user(), get_user(), get_user_with_relations(), _hash_password(), list_post_ids_for_user() (+21 more)
### Community 37 - "Community 37"
Cohesion: 0.17
Nodes (25): delete_plan(), delete_carrier(), delete_driver(), delete_personnel(), unbind_vehicle_driver(), delete_plan(), _actor_ids(), _actor_names() (+17 more)
### Community 38 - "Community 38"
Cohesion: 0.14
Nodes (24): PlTransportProductBrandQty, PlTransportProductFeedback, 运输单按产品回传 pl_transport_product_feedback, 运输单产品回传品牌数量 pl_transport_product_brand_qty, _dict_field(), format_brand_qty_summary(), load_transport_driver_product_feedbacks(), persist_io_item_brand_qtys() (+16 more)
### Community 39 - "Community 39"
Cohesion: 0.22
Nodes (28): assign_clues(), check_convert(), check_duplicate_clue(), convert_clue(), create_clue(), _enrich_user_names(), _ensure_clue_in_scope(), get_clue() (+20 more)
### Community 42 - "Community 42"
Cohesion: 0.19
Nodes (32): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+24 more)
### Community 43 - "Community 43"
Cohesion: 0.10
Nodes (30): create_invoice(), delete_invoice(), get_mine_wallet_summary(), list_invoice_ledgers(), list_invoice_wallets(), list_invoices(), Request, Session (+22 more)
### Community 44 - "Community 44"
Cohesion: 0.12
Nodes (29): _apply_contract_entity_fields(), _build_contract_name_from_parties(), _build_customer_address(), _calc_amount_with_tax(), contract_no_exists(), create_contract(), create_from_opportunity(), create_from_quote() (+21 more)
### Community 45 - "Community 45"
Cohesion: 0.07
Nodes (75): _build_driver_url(), get_plan_arrange_info(), 获取计划已安排运输后的司机链接与地磅出入库关联(供查看弹窗复制简述/二维码)。, _apply_plan_logistics_from_payload(), _apply_transport_arrange_fields(), arrange_transport(), _assert_vehicle_carrier_eligible(), _build_arrange_result() (+67 more)
### Community 46 - "Community 46"
Cohesion: 0.19
Nodes (24): _apply_weighing_product_update(), _apply_weighing_update(), _base_query(), create_weighing(), delete_weighing(), _get_weighing(), get_weighing_related(), Session (+16 more)
### Community 48 - "Community 48"
Cohesion: 0.23
Nodes (13): get_last_month_range(), month_range(), date, Session, 地磅计划按月自动生成 — 迁移自 simple-dibang-xiaoshou/auto-create-plan/auto_create_monthly_pla, 按月自动生成采购计划。 - 默认仅在每月 1 日执行(force=True 时跳过该限制,供手动触发验收) - 遍历所有租户,按上月计划模板生, run_auto_generate_monthly_plans(), default_execution_status() (+5 more)
### Community 49 - "Community 49"
Cohesion: 0.13
Nodes (28): _apply_list_filters(), create_supplier_info(), get_supplier_info(), list_all_supplier_info(), list_supplier_info(), Any, Session, CRM 供方信息 CRUD — 对照 CrmSupplierInfoServiceImpl.java (+20 more)
### Community 50 - "Community 50"
Cohesion: 0.13
Nodes (14): bx_health(), 报销(bx)API 路由聚合 — REST 风格,协议对齐 bx 原系统。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, API 路由包 — 山峡化工生产一体化门户, get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,14 个一级菜单), _auto_fill_create_dept_id(), get_db() (+6 more)
### Community 51 - "Community 51"
Cohesion: 0.05
Nodes (126): archive_plan(), cancel_plan(), cancel_plan_wait_notice(), count_plans_by_contract(), create_from_contract(), create_plan(), create_plan_full(), _determine_plan_type() (+118 more)
### Community 52 - "Community 52"
Cohesion: 0.18
Nodes (29): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+21 more)
### Community 53 - "Community 53"
Cohesion: 0.11
Nodes (31): 报销模块认证适配:门户 JWT 用户 → bx 业务上下文。, BxReimburseOffset, BxWorkflowNode, 报销(bx)模块数据模型 — 对齐 docs/sql/20260606_bx_tables.sql, filter_current_cycle_approvals(), 审批轮次过滤 — 驳回后重新提交时,进度接口仅展示当前轮次。, 审批进度仅展示当前轮次;完整历史由 get_approval_history 返回。, 报销模块 Service 基类 — 租户隔离 + UUID + 软删除。 (+23 more)
### Community 54 - "Community 54"
Cohesion: 0.26
Nodes (23): _get_by_plan(), get_inbound(), get_inbound_by_plan(), _get_order(), get_outbound(), get_outbound_by_plan(), inbound_site_url(), list_inbound() (+15 more)
### Community 58 - "Community 58"
Cohesion: 0.13
Nodes (42): _apply_plan_product_update(), _apply_plan_update(), AutoGenerateMonthlyResult, _base_query(), create_plan(), _generate_plan_no(), get_plan(), _get_plan_by_id_only() (+34 more)
### Community 59 - "Community 59"
Cohesion: 0.20
Nodes (28): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+20 more)
### Community 60 - "Community 60"
Cohesion: 0.11
Nodes (17): category_add(), category_delete(), category_tree(), category_update(), product_delete(), product_detail(), 删除产品(支持单条 body.id 和批量 body.ids), CategoryDeleteBody (+9 more)
### Community 61 - "Community 61"
Cohesion: 0.16
Nodes (35): DbInboundOutbound, DbPurchasePlan, PlTransportDbLink, 运输-地磅出入库关联 pl_transport_db_link, _apply_plan_quantity_delta(), _create_db_inventory(), DibangInventoryLinkResult, find_monthly_db_plan() (+27 more)
### Community 62 - "Community 62"
Cohesion: 0.30
Nodes (12): PlCarrier, assert_carrier_eligible_for_transport(), carrier_agreement_expired(), carrier_audit_approved(), carrier_eligible_for_transport(), carrier_qualification_complete(), date, 资质附件均为选填,保留函数签名供兼容调用。 (+4 more)
### Community 63 - "Community 63"
Cohesion: 0.15
Nodes (17): create_expense_item(), delete_expense_item(), get_expense_item(), get_expense_item_tree(), Session, update_expense_item(), BxExpenseItem, _coerce_id() (+9 more)
### Community 64 - "Community 64"
Cohesion: 0.04
Nodes (196): clue_assign(), clue_check_convert(), clue_check_duplicate(), clue_convert(), clue_create(), clue_delete(), clue_detail(), clue_export() (+188 more)
### Community 65 - "Community 65"
Cohesion: 0.16
Nodes (40): PlVehicleMaintenanceApply, PlVehicleMaintenanceProcess, 车辆维保申请 pl_vehicle_maintenance_apply, 车辆维保处理登记 pl_vehicle_maintenance_process, Decimal, VehicleMaintenanceApplyCreate, VehicleMaintenanceApplyRead, VehicleMaintenanceApplyUpdate (+32 more)
### Community 66 - "Community 66"
Cohesion: 0.18
Nodes (18): create_workflow(), delete_workflow(), get_workflow(), get_workflow_by_biz_type(), list_workflows(), Session, save_workflow_nodes(), update_workflow() (+10 more)
### Community 67 - "Community 67"
Cohesion: 0.12
Nodes (36): get_password_hash(), Namespace, build_merged_users(), bx_role_labels(), check_minio(), check_mysql(), check_redis(), _clip() (+28 more)
### Community 68 - "Community 68"
Cohesion: 0.33
Nodes (13): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), Any (+5 more)
### Community 69 - "Community 69"
Cohesion: 0.13
Nodes (29): _append_user_scope_conditions(), apply_data_scope(), assert_row_in_data_scope(), _collect_scope_ids(), _get_child_dept_ids(), get_user_dept_id(), Session, 数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3 (+21 more)
### Community 70 - "Community 70"
Cohesion: 0.36
Nodes (13): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), menu_name_exists(), Any (+5 more)
### Community 71 - "Community 71"
Cohesion: 0.11
Nodes (32): CRM 报价单 API 路由 — 挂接到 crm.router, QuoteApproverSettingSaveBody, QuoteAcceptBody, QuoteApprovalApproveBody, QuoteApprovalListBody, QuoteApprovalRefreshNamesBody, QuoteApprovalWithdrawBody, QuoteCreateBody (+24 more)
### Community 72 - "Community 72"
Cohesion: 0.18
Nodes (30): Settings, BaseSettings, apply_biz_backfill(), BackfillRule, BizRef, build_biz_index(), count_target_rows(), derive_source_url() (+22 more)
### Community 73 - "Community 73"
Cohesion: 0.20
Nodes (25): derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env(), load_user_mapping() (+17 more)
### Community 74 - "Community 74"
Cohesion: 0.06
Nodes (56): _apply_create_range(), _base_query(), get_clue_level_statistics(), get_clue_overview_statistics(), get_clue_owner_statistics(), get_clue_source_statistics(), get_clue_trend_statistics(), Any (+48 more)
### Community 77 - "Community 77"
Cohesion: 0.11
Nodes (12): get_wechat_pay_client(), get_wechat_pay_v2(), Any, 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.html, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total_amo, 申请退款 Args: out_trade_no: 商户订单号 total_amount: 订单, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 total_f (+4 more)
### Community 78 - "Community 78"
Cohesion: 0.40
Nodes (12): create_follow(), _enrich_follow_dict(), get_follow(), list_follows(), list_follows_by_customer(), Any, Session, _row_to_dict() (+4 more)
### Community 81 - "Community 81"
Cohesion: 0.27
Nodes (11): create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options(), Any, Session, 字典数据 CRUD(sys_dict_data), 字典下拉选项:租户主数据,忽略数据范围(user_info 保留兼容调用方,不参与过滤)。 (+3 more)
### Community 83 - "Community 83"
Cohesion: 0.15
Nodes (30): _advance_contract_after_approval(), approve_contract(), approve_contract_by_contract_id(), approve_pass(), approve_reject(), approve_transfer(), _build_approval_list_filters(), can_user_approve() (+22 more)
### Community 84 - "Community 84"
Cohesion: 0.10
Nodes (32): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import WechatMes, 发送订单状态通知 Args: openid: 用户openid order_n, 发送支付成功通知 Args: openid: 用户openid order_n, 发送配送通知 Args: openid: 配送员openid task_no:, 发送配送时效预警 Args: openid: 配送员openid task_n, 发送退款结果通知 Args: openid: 用户openid order_n, 发送催单通知给配送员 Args: deliver_openid: 配送员openid, 发送模板消息 Args: openid: 用户openid template_ (+24 more)
### Community 86 - "Community 86"
Cohesion: 0.12
Nodes (16): 供方全量列表(下拉)— Java: CrmSupplierInfoController.listAll, 供方详情 — Java: CrmSupplierInfoController.getInfo, 新增供方 — Java: CrmSupplierInfoController.add, 修改供方 — Java: CrmSupplierInfoController.edit, 删除供方 — Java: CrmSupplierInfoController.remove, supplier_info_add(), supplier_info_delete(), supplier_info_detail() (+8 more)
### Community 87 - "Community 87"
Cohesion: 0.20
Nodes (19): approve_quote(), can_user_approve(), create_approval_records(), delete_pending_approvals(), get_quote_approval(), list_quote_approvals(), Any, Session (+11 more)
### Community 88 - "Any"
Cohesion: 0.18
Nodes (31): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), legacy_parent_id(), load_oss_id_to_url(), load_runtime_settings() (+23 more)
### Community 89 - "pl_ocr_service.py"
Cohesion: 0.19
Nodes (22): PlOcrUsageMonth, 阿里云 OCR 月度调用计数 pl_ocr_usage_month(按自然月全局统计), assert_quota_available(), _build_ocr_client(), compress_image_bytes(), current_usage_month(), _first_attachment_url(), get_or_create_usage_row() (+14 more)
### Community 91 - "pl_vehicle_recharge_service.py"
Cohesion: 0.17
Nodes (19): align_contract_no_to_sign_date(), generate_contract_no(), _parse_optional_date(), date, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号} 流水与撞号检测须含软删:uk_contr, 标准编号替换日期段,保留序号;非标准返回 None。, 将标准合同编号日期段对齐签订日;撞号则序号顺延(含软删查重)。 非标准编号原样返回。无签订日则原样返回。, replace_contract_no_date() (+11 more)
### Community 92 - "Community 92"
Cohesion: 0.24
Nodes (7): camel_to_snake(), CRUDBase, get_model_attr(), HistoryCRUD, Any, Session, ModelType
### Community 93 - "_invoice_info_by_customer_impl"
Cohesion: 0.13
Nodes (47): CRM 合同子模块路由 — 变更/模板/审批独立页, register_contract_sub_routes(), _change_row_to_dict(), _contract_period_key(), create_contract_change(), create_contract_template(), _decimal_value(), _enrich_change_rows() (+39 more)
### Community 94 - "response.py"
Cohesion: 0.21
Nodes (15): get_user_menu_codes(), Session, 读取用户授权的菜单权限标识集合(与前端 meta.menuCode / perms 对齐)。, _expand_with_ancestor_menu_ids(), _granted_menu_ids_for_user(), iter_user_menu_perm_codes(), Session, Web 管理端登录:基于 V0.3 sys_user / sys_user_role / sys_role 的角色与菜单权限解析 (+7 more)
### Community 95 - "Community 95"
Cohesion: 0.35
Nodes (11): create_tenant(), get_tenant(), list_tenants(), Any, Session, _row_to_dict(), soft_delete_tenant(), tenant_no_exists() (+3 more)
### Community 97 - "_ensure_subpack_slip_no"
Cohesion: 0.21
Nodes (22): clear_target_products(), count_target_rows(), _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings() (+14 more)
### Community 100 - "price_letter_detail"
Cohesion: 0.31
Nodes (13): apply_renumber(), build_mapping(), fetch_products(), format_new_product_no(), load_settings_env(), main(), product_id_sort_key(), Engine (+5 more)
### Community 101 - ".to_tenant_user_dict"
Cohesion: 0.19
Nodes (14): CRM 模块 Excel 导出列定义(字段与字典类型对齐 Java *Vo @ExcelDictFormat)。, _build_workbook(), DictLabelResolver, export_rows_to_xlsx_response(), ExportColumn, load_dict_label_maps(), Any, Session (+6 more)
### Community 102 - "dept.py"
Cohesion: 0.35
Nodes (11): create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), Any, Session, 字典类型 CRUD(sys_dict_type), _row_to_dict() (+3 more)
### Community 104 - "apply_crm_create_by_scope"
Cohesion: 0.29
Nodes (15): create_price_letter(), get_price_letter(), list_price_letters(), _parse_date(), Any, date, Session, _row_to_dict() (+7 more)
### Community 105 - "list_customers"
Cohesion: 0.16
Nodes (23): list_vehicles(), _vehicle_to_read(), PlCert, CertRead, SnapshotCertRead, SnapshotPersonnelRow, certs_to_read(), list_owner_certs() (+15 more)
### Community 106 - "Community 106"
Cohesion: 0.17
Nodes (11): pool_customer_assign(), pool_customer_claim(), pool_customer_list(), pool_record_detail(), pool_record_list(), PoolAssignBody, PoolClaimBody, PoolCustomerListBody (+3 more)
### Community 107 - "apply_pl_scope"
Cohesion: 0.17
Nodes (28): create_instance(), create_process_def(), create_task(), get_all_tasks_for_business(), get_instance(), get_latest_version(), get_nodes_by_version(), get_pending_tasks_by_node() (+20 more)
### Community 109 - "Community 109"
Cohesion: 0.26
Nodes (18): bind_vehicle_driver(), paste_recognize_commit(), PlVehicle, ConflictAction, PasteCommitBody, PasteCommitResult, PastePersonnelIn, PasteVehicleIn (+10 more)
### Community 110 - "Base"
Cohesion: 0.22
Nodes (10): Config, decrypt_login_payload(), ensure_initialized(), extract_login_credentials(), get_public_pem(), Any, 登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。, Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。 (+2 more)
### Community 111 - "Community 111"
Cohesion: 0.28
Nodes (14): _assert_editable(), _build_public_page(), _format_file_size(), _get_inventory_by_token(), get_public_inventory(), _parse_feedback_images(), Session, UploadFile (+6 more)
### Community 112 - "storage.py"
Cohesion: 0.20
Nodes (17): create_vehicle(), get_vehicle(), update_vehicle(), _vehicle_to_detail(), PlVehiclePersonnel, 车辆-人员关联表 pl_vehicle_personnel, VehicleDetailRead, build_personnel_summary() (+9 more)
### Community 113 - "quote_share_log.py"
Cohesion: 0.26
Nodes (12): list_share_logs(), _parse_user_agent(), Any, Session, CRM 报价单分享访问日志 CRUD — 对照 CrmQuoteShareLogServiceImpl.java, Java: statisticsVisits, 简易 User-Agent 解析(替代 Hutool UserAgentUtil), Java: queryLogsByQuoteId (+4 more)
### Community 114 - "db_models.py"
Cohesion: 0.16
Nodes (17): list_public_vehicle_plates(), Session, 地磅公共只读:免登车牌 options(现场填写页), 免登:按出入库/计划解析 tenant_no,返回 pl_vehicle 车牌(self + carrier)。, _resolve_tenant_no(), DbSequence, 地磅(db)模块数据模型 — 对齐 docs/sql/db_tables.sql, _allocate_inbound_outbound_id() (+9 more)
### Community 115 - "site.py"
Cohesion: 0.12
Nodes (15): pool_rule_add(), pool_rule_delete(), pool_rule_detail(), pool_rule_execute(), pool_rule_list(), pool_rule_update(), pool_rule_update_status(), PoolRuleAddBody (+7 more)
### Community 116 - "Community 116"
Cohesion: 0.20
Nodes (24): batch_insert_quote_products(), calculate_subtotal(), _decimal_value(), delete_products_by_quote_id(), _ensure_quote_parent_scope(), _get_field(), get_quote_product(), insert_quote_product() (+16 more)
### Community 118 - "Community 118"
Cohesion: 0.22
Nodes (22): batch_insert_contract_products(), calculate_subtotal(), _decimal_value(), delete_price_tiers_by_contract_id(), delete_products_by_contract_id(), _get_field(), insert_contract_product(), _letter_oss_ids_to_json() (+14 more)
### Community 119 - "Community 119"
Cohesion: 0.16
Nodes (29): CertRow, VehiclePersonnelRow, _cert_row_complete(), collect_required_cert_errors(), _find_cert_for_required(), get_required_personnel_cert_names(), match_required_cert_name(), _missing_field_labels() (+21 more)
### Community 122 - "Community 122"
Cohesion: 0.39
Nodes (10): create_post(), get_post(), list_posts(), post_code_exists(), Any, Session, _row_to_dict(), soft_delete_post() (+2 more)
### Community 125 - "Community 125"
Cohesion: 0.05
Nodes (69): _build_page(), _get_by_token(), _make_handlers(), _models(), Session, 运输计划 · 入库/出库单现场免登录公共 API, SoftDeleteModel, BizAttachment (+61 more)
### Community 126 - "customer_pool.py"
Cohesion: 0.36
Nodes (8): operlog_detail(), operlog_list(), Session, 操作日志分页列表(基于 API 请求日志适配 RuoYi OperLog 结构), _user_info(), OperLogDetailBody, OperLogListBody, 操作日志(兼容 RuoYi OperLog 视图)
### Community 127 - "Community 127"
Cohesion: 0.25
Nodes (17): _cargo_stats(), get_dashboard_stats(), get_inbound_by_cargo(), get_inbound_by_partner_cargo(), get_outbound_by_cargo(), get_outbound_by_partner_cargo(), _partner_cargo_stats(), Session (+9 more)
### Community 128 - "plan.py"
Cohesion: 0.39
Nodes (10): create_site(), get_site(), list_sites(), Any, Session, _row_to_dict(), site_code_exists(), soft_delete_site() (+2 more)
### Community 129 - "BaseStorage"
Cohesion: 0.12
Nodes (24): _auto_contract_name_body(), generate_contract_name(), 按面板单位全称精确匹配交易主体/客户主数据,取 shortName;对不上则用全称。, 前端预览误用单位全称时,名称片段会等于面板/客户/开票全称。, 按面板供方(partyA)-需方(partyB)生成:{供方简称}-{需方简称}({合同编号})。 - 名称为空:按主数据简称自动生成 - 名, resolve_party_short_name(), _strip_contract_name_no_suffix(), _user_contract_name_uses_party_full_name() (+16 more)
### Community 130 - "datetime_parse.py"
Cohesion: 0.29
Nodes (16): create_contact(), get_contact(), list_contacts_by_customer(), _parse_optional_date(), Any, date, Session, _row_to_dict() (+8 more)
### Community 131 - "LocalStorage"
Cohesion: 0.60
Nodes (3): assert_contract_editable_for_update(), test_assert_allows_editable(), test_assert_rejects_non_editable()
### Community 132 - "crm_supplier_hazard.py"
Cohesion: 0.14
Nodes (23): build_updates(), derive_source_url(), fetch_source_customers(), legacy_id_to_str(), load_oss_map(), load_runtime_settings(), load_settings_env(), main() (+15 more)
### Community 134 - "Community 134"
Cohesion: 0.25
Nodes (18): batch_generate_sample_codes(), batch_issue_sample_codes(), batch_revoke_sample_codes(), create_sample_code(), get_sample_code(), list_sample_codes(), _parse_issued_time(), Any (+10 more)
### Community 135 - "unsettled_plans_q_filter"
Cohesion: 0.15
Nodes (14): invoice_info_add(), invoice_info_by_customer(), _invoice_info_by_customer_impl(), invoice_info_delete(), invoice_info_list(), invoice_info_set_default(), invoice_info_update(), 按客户ID查询开票信息(与 by-customer 等价) (+6 more)
### Community 136 - "Community 136"
Cohesion: 0.19
Nodes (18): create_role(), get_role(), get_role_data_scope(), get_role_menu_ids(), list_roles(), Any, Session, 角色 CRUD(sys_role / sys_role_menu / sys_role_data_scope_detail) (+10 more)
### Community 137 - "statistics.py"
Cohesion: 0.16
Nodes (28): advance_issue_stats(), batch_offset(), export_advance_issues(), issue_advance(), list_advance_issues(), list_advance_offset_records(), list_pending_payments(), list_processed_payments() (+20 more)
### Community 138 - "Community 138"
Cohesion: 0.33
Nodes (19): check_python(), create_venv(), ensure_dirs(), ensure_valid_venv(), ensure_venv_and_runtime(), install_dependencies(), is_running(), log_error() (+11 more)
### Community 139 - "get_current_user_by_token"
Cohesion: 0.21
Nodes (14): change_current_user_password(), get_current_user_profile(), get_web_auth_menu_codes(), public_quote_share(), Request, Session, 获取当前用户信息(与 sys_user 字段对应)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。 (+6 more)
### Community 141 - "PlTransport"
Cohesion: 0.23
Nodes (12): _ensure_driver_access_token(), _rotate_driver_access_token(), PlTransport, _plan_type_to_business_type(), _normalize_plan_date(), date, Session, 运输计划 · 工厂现场链接(与地磅出入库单解耦) (+4 more)
### Community 143 - "SysEthnic"
Cohesion: 0.33
Nodes (11): create_leave(), get_leave(), list_leaves(), Any, Session, _row_to_dict(), soft_delete_leave(), update_leave() (+3 more)
### Community 144 - "dict_data.py"
Cohesion: 0.33
Nodes (8): allocate_next_biz_no(), _format_biz_no(), _prefix_for(), datetime, Session, 业务协议号自动生成:XBCC / JZCC + YYYYMMDD + 6 位序号, 原子分配下一个业务协议号。 须在 create 事务内调用;使用 MySQL LAST_INSERT_ID 保证并发安全。, BizNoKind
### Community 145 - "resolve_crm_product"
Cohesion: 0.27
Nodes (10): apply_product_snapshot_to_plan(), ProductSnapshot, Session, 地磅模块 — CRM 产品解析与快照写入。, 校验 CRM 产品并返回名称/规格快照。新建单据 product_id 必填。 require_on_shelf=False 用于运输计划联动地磅等历, resolve_crm_product(), _product(), resolve_crm_product:运输联动场景允许已下架产品。 (+2 more)
### Community 146 - "__init__.py"
Cohesion: 0.40
Nodes (11): create_personnel(), delete_vehicle(), get_personnel(), list_personnel(), _personnel_to_detail(), _personnel_to_read(), Session, update_personnel() (+3 more)
### Community 147 - "Community 147"
Cohesion: 0.37
Nodes (17): check_env(), check_python(), create_venv(), init_env(), install_dependencies(), log_error(), log_info(), log_success() (+9 more)
### Community 150 - "apply_site_feedback"
Cohesion: 0.51
Nodes (10): apply_site_feedback(), OrderItem, _header(), _item(), test_apply_site_feedback_does_not_reset_first_submitted_at(), test_apply_site_feedback_keeps_in_progress_when_requested(), test_apply_site_feedback_rejects_already_voided(), test_apply_site_feedback_rejects_invalid_status() (+2 more)
### Community 152 - "response.py"
Cohesion: 0.29
Nodes (6): Config, format_api_error_message(), PageResult, Exception, 将 HTTP/SQLAlchemy 等异常转为可展示的错误文案(避免 str([]) 空列表)。, ResponseModel
### Community 154 - "response.py"
Cohesion: 0.29
Nodes (16): ensure_crm_customer_linked_row_in_scope(), ensure_crm_owner_row_in_scope(), Session, CRM 数据权限辅助(负责人 owner_user_id + 标准 create_by/create_dept_id)。, 客户子表(开票信息等):先校验关联客户 owner scope,否则校验 create_by。, _clear_default_for_customer(), create_invoice_info(), get_invoice_info() (+8 more)
### Community 156 - "utils.py"
Cohesion: 0.47
Nodes (3): get_current_time(), parse_datetime(), datetime
### Community 159 - "customer_update"
Cohesion: 0.40
Nodes (4): customer_create(), customer_update(), customer_name_exists(), CustomerUpdateBody
### Community 160 - "register_local_callback"
Cohesion: 0.19
Nodes (17): create_leave(), delete_leave(), get_leave(), _leave_local_callback(), leave_workflow_callback(), list_leaves(), Session, submit_leave() (+9 more)
### Community 161 - "backfill_crm_contract_attachment_urls.py"
Cohesion: 0.33
Nodes (10): load_oss_map(), load_runtime_settings(), load_settings_env(), main(), Any, Engine, 返回 (新值, 是否发生了 id→url 替换)。, resolve_token() (+2 more)
### Community 162 - ".to_tenant_user_dict"
Cohesion: 0.40
Nodes (3): Any, 供 get_tenant_no 等门户工具使用。, 与门户 JWT / apply_data_scope 所需的 user_info 字段对齐。
### Community 163 - "__init__.py"
Cohesion: 0.25
Nodes (13): get_storage(), download_file_bytes(), file_stream(), get_access_url(), get_download_url(), get_preview_url(), normalize_storage_path(), 报销附件存储适配 — 复用门户 app.core.storage,对外保持 bx 协议。 (+5 more)
### Community 164 - "get_client_ip"
Cohesion: 0.12
Nodes (34): _avatar_url_field(), _build_user_info_payload(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/shanxia2.0.sql 基线), 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。, 与 web-admin 静态路由 meta.roles(admin/super_admin)对齐的单元素数组。, 与 web-admin `userInfo` 字段约定一致。 (+26 more)
### Community 170 - "test_quote_approver_setting.py"
Cohesion: 0.18
Nodes (22): _assert_users_exist(), get_setting(), Any, Session, _row_to_dict(), save_setting(), _assert_users_exist(), get_setting() (+14 more)
### Community 173 - "resolve_create_time_bounds"
Cohesion: 0.67
Nodes (3): parse_optional_plan_datetime(), datetime, 运输计划相关日期时间解析:前端 date-picker 仅传 YYYY-MM-DD。
### Community 179 - "_ensure_subpack_slip_no"
Cohesion: 0.13
Nodes (28): menu_badge_stats(), Session, Session, recognize_cert(), RecognizeCertBody, RecognizeCertResult, cancel_apply(), create_apply() (+20 more)
### Community 182 - "statistics.py"
Cohesion: 0.45
Nodes (11): _customer_base_query(), get_follow_statistics(), get_industry_statistics(), get_level_statistics(), get_overview_statistics(), get_owner_statistics(), get_source_statistics(), get_trend_statistics() (+3 more)
### Community 183 - "MinIOStorage"
Cohesion: 0.21
Nodes (5): MinIOStorage, Any, 从 MINIO_BASE_URL 解析公网 endpoint;未配置或与内网相同时复用 self.client。, MinIO 预签名下载 URL,携带原始文件名。, MinIO 预签名内联预览 URL(PDF 等 iframe 场景)。
### Community 187 - "allocate_next_biz_no"
Cohesion: 0.47
Nodes (8): create_oss(), get_oss_by_id(), get_oss_by_url(), Session, 按主键 id 查询附件(兼容旧 CRM 雪花 oss_id 迁入后的记录), 将 fileUrl 或旧 CRM 数字 ossId 解析为 MinIO 相对路径。 门户新上传把相对路径写入业务字段;迁入合同附件仍存数字 ossId, resolve_storage_path(), SysOss
### Community 191 - "BaseStorage"
Cohesion: 0.22
Nodes (3): BaseStorage, 带下载文件名的访问 URL;默认实现为普通访问地址。, 浏览器内联预览 URL;默认实现为普通访问地址。
### Community 196 - "SoftDeleteModel"
Cohesion: 0.12
Nodes (16): 数据模型(与 docs/sql/shanxia2.0.sql 全库导出基线对齐的核心系统表), Web 管理端约定角色(由 sys_role.role_name 映射而来,非数据库枚举), 流程连线/转移 wf_transition, 流程实例 wf_process_instance, UserRole, WfProcessInstance, WfTransition, _dispatch_local() (+8 more)
### Community 200 - "register_local_callback"
Cohesion: 0.36
Nodes (7): list_ethnics(), Any, Session, 民族码表 CRUD(全局 sys_ethnic), _row_to_dict(), 民族码表 sys_ethnic(国标 GB/T 3304,全局), SysEthnic
### Community 206 - "crm_quote_pdf.py"
Cohesion: 0.36
Nodes (10): build_quote_html(), _default_value(), _format_date(), _format_discount(), _format_money(), generate_quote_pdf(), _get_pdf_styles(), Any (+2 more)
### Community 207 - "shanxia2.0 后端骨架(FastAPI)"
Cohesion: 0.18
Nodes (10): 1. 创建虚拟环境, 2. 安装依赖, 3. 配置环境变量, 4. 启动服务, API 路由分组, shanxia2.0 后端骨架(FastAPI), 开发规范, 快速开始 (+2 more)
### Community 220 - "api_crypto_middleware.py"
Cohesion: 0.14
Nodes (23): ApiCryptoMiddleware, _claims_from_auth(), _coerce_post_method_override_to_get(), _get_redis_client(), _is_crypto_api(), _json_error_response(), _mark_nonce_once(), _nonce_key() (+15 more)
### Community 237 - "order_status_compat.py"
Cohesion: 0.36
Nodes (7): derive_legacy_status_from_three(), derive_three_status_from_legacy(), Decimal, 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 239 - "shanxia2.0 Backend 生产部署说明"
Cohesion: 0.25
Nodes (7): 1. 上传到服务器, 2. 服务器首次启动, 3. 日常运维, 4. 配置文件, 5. 与 Nginx 配合, 6. 常见问题, shanxia2.0 Backend 生产部署说明
### Community 246 - "db_collation.py"
Cohesion: 0.38
Nodes (6): eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci()
## Knowledge Gaps
- **30 isolated node(s):** `Config`, `Config`, `Config`, `Config`, `Config` (+25 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **16 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `generate_uuid()` connect `Community 21` to `Community 0`, `plan.py`, `datetime_parse.py`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 136`, `Community 134`, `Community 11`, `PlTransport`, `Community 14`, `SysEthnic`, `dict_data.py`, `Community 15`, `__init__.py`, `Community 18`, `Community 16`, `Community 25`, `response.py`, `Community 27`, `utils.py`, `Community 28`, `get_client_ip`, `Community 36`, `Community 38`, `Community 39`, `test_quote_approver_setting.py`, `Community 43`, `Community 44`, `Community 45`, `Community 46`, `Community 48`, `Community 49`, `Community 51`, `Community 53`, `Community 58`, `allocate_next_biz_no`, `Community 61`, `Community 63`, `Community 65`, `Community 66`, `Community 67`, `Community 68`, `Community 70`, `Community 74`, `Community 78`, `Community 81`, `Community 83`, `Community 87`, `pl_ocr_service.py`, `_invoice_info_by_customer_impl`, `Community 95`, `dept.py`, `apply_crm_create_by_scope`, `list_customers`, `apply_pl_scope`, `Community 109`, `storage.py`, `quote_share_log.py`, `db_models.py`, `Community 116`, `Community 118`, `Community 122`, `Community 125`?**
_High betweenness centrality (0.127) - this node is a cross-community bridge._
- **Why does `Settings` connect `Community 72` to `backfill_crm_contract_attachment_urls.py`, `_ensure_subpack_slip_no`, `Community 35`, `crm_supplier_hazard.py`, `Community 5`, `Community 67`, `price_letter_detail`, `Community 73`, `Community 42`, `Base`, `Community 52`, `Any`, `Community 59`, `Community 30`?**
_High betweenness centrality (0.108) - this node is a cross-community bridge._
- **Why does `BaseModel` connect `Community 12` to `Community 0`, `Community 1`, `Community 2`, `Community 3`, `unsettled_plans_q_filter`, `Community 7`, `statistics.py`, `Community 11`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `response.py`, `Community 24`, `Community 28`, `Community 29`, `customer_update`, `register_local_callback`, `Community 33`, `Community 34`, `Community 43`, `Community 45`, `Community 46`, `Community 50`, `_ensure_subpack_slip_no`, `Community 51`, `Community 54`, `Community 58`, `Community 60`, `Community 63`, `Community 64`, `Community 65`, `Community 66`, `Community 71`, `Community 86`, `_invoice_info_by_customer_impl`, `list_customers`, `Community 106`, `Community 109`, `Community 111`, `site.py`, `Community 119`, `Community 125`, `customer_pool.py`, `Community 127`?**
_High betweenness centrality (0.090) - this node is a cross-community bridge._
- **Are the 8 inferred relationships involving `DbUserContext` (e.g. with `InventoryRelatedData` and `AutoGenerateMonthlyResult`) actually correct?**
_`DbUserContext` has 8 INFERRED edges - model-reasoned connections that need verification._
- **What connects `API 路由包 — 山峡化工生产一体化门户`, `返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。`, `返回用户下拉选项(label=昵称,value=用户ID,附带 nickName/userNo)。 供申请人/审批人等选择场景使用,返回本租户全部有效` to the rest of the system?**
_525 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
_Cohesion score 0.10917874396135266 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.07804878048780488 - nodes in this community are weakly interconnected._
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+282 -200
View File
@@ -1,16 +1,16 @@
# Graph Report - backend (2026-08-04)
# Graph Report - backend (2026-08-06)
## Corpus Check
- 307 files · ~208,854 words
- 316 files · ~210,215 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 4616 nodes · 15627 edges · 523 communities (506 shown, 17 thin omitted)
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 410 edges (avg confidence: 0.53)
- 4671 nodes · 15744 edges · 541 communities (522 shown, 19 thin omitted)
- Extraction: 97% EXTRACTED · 3% INFERRED · 0% AMBIGUOUS · INFERRED: 412 edges (avg confidence: 0.53)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `5fe53c54`
- Built from commit: `2716c2b6`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
@@ -120,28 +120,46 @@
- [[_COMMUNITY_LocalStorage|LocalStorage]]
- [[_COMMUNITY_crm_supplier_hazard.py|crm_supplier_hazard.py]]
- [[_COMMUNITY_Community 134|Community 134]]
- [[_COMMUNITY_post.py|post.py]]
- [[_COMMUNITY_unsettled_plans_q_filter|unsettled_plans_q_filter]]
- [[_COMMUNITY_Community 136|Community 136]]
- [[_COMMUNITY_statistics.py|statistics.py]]
- [[_COMMUNITY_Community 138|Community 138]]
- [[_COMMUNITY_get_current_user_by_token|get_current_user_by_token]]
- [[_COMMUNITY_PlTransport|PlTransport]]
- [[_COMMUNITY_SysEthnic|SysEthnic]]
- [[_COMMUNITY_minio_url.py|minio_url.py]]
- [[_COMMUNITY_dict_data.py|dict_data.py]]
- [[_COMMUNITY_resolve_crm_product|resolve_crm_product]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_Community 147|Community 147]]
- [[_COMMUNITY_apply_site_feedback|apply_site_feedback]]
- [[_COMMUNITY_Community 151|Community 151]]
- [[_COMMUNITY_PlCarrier|PlCarrier]]
- [[_COMMUNITY_minio_url.py|minio_url.py]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_response.py|response.py]]
- [[_COMMUNITY_utils.py|utils.py]]
- [[_COMMUNITY_customer_update|customer_update]]
- [[_COMMUNITY_register_local_callback|register_local_callback]]
- [[_COMMUNITY_backfill_crm_contract_attachment_urls.py|backfill_crm_contract_attachment_urls.py]]
- [[_COMMUNITY_ethnic.py|ethnic.py]]
- [[_COMMUNITY_.to_tenant_user_dict|.to_tenant_user_dict]]
- [[_COMMUNITY___init__.py|__init__.py]]
- [[_COMMUNITY_get_client_ip|get_client_ip]]
- [[_COMMUNITY_codeblock1 (iflytekshanxia2.0backend)|code:block1 (/iflytek/shanxia2.0/backend)]]
- [[_COMMUNITY_test_quote_approver_setting.py|test_quote_approver_setting.py]]
- [[_COMMUNITY_crm_supplier_hazard.py|crm_supplier_hazard.py]]
- [[_COMMUNITY_apply_pl_scope|apply_pl_scope]]
- [[_COMMUNITY_resolve_create_time_bounds|resolve_create_time_bounds]]
- [[_COMMUNITY_datetime_parse.py|datetime_parse.py]]
- [[_COMMUNITY_product_allowed|product_allowed]]
- [[_COMMUNITY_CrmProductBrand|CrmProductBrand]]
- [[_COMMUNITY_opportunity_export|opportunity_export]]
- [[_COMMUNITY__ensure_subpack_slip_no|_ensure_subpack_slip_no]]
- [[_COMMUNITY_menu.py|menu.py]]
- [[_COMMUNITY_OSSStorage|OSSStorage]]
- [[_COMMUNITY_storage.py|storage.py]]
- [[_COMMUNITY_statistics.py|statistics.py]]
- [[_COMMUNITY_MinIOStorage|MinIOStorage]]
- [[_COMMUNITY_QiniuStorage|QiniuStorage]]
- [[_COMMUNITY_allocate_next_biz_no|allocate_next_biz_no]]
- [[_COMMUNITY_list_product_options|list_product_options]]
- [[_COMMUNITY_BaseStorage|BaseStorage]]
- [[_COMMUNITY_LocalStorage|LocalStorage]]
- [[_COMMUNITY_register_local_callback|register_local_callback]]
- [[_COMMUNITY_crm_quote_pdf.py|crm_quote_pdf.py]]
- [[_COMMUNITY_shanxia2.0 后端骨架(FastAPI)|shanxia2.0 后端骨架(FastAPI)]]
- [[_COMMUNITY_api_crypto_middleware.py|api_crypto_middleware.py]]
@@ -175,6 +193,8 @@
10. `ApiResponse` - 79 edges
## Surprising Connections (you probably didn't know these)
- `BackfillRule` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_sys_oss.py → app/core/config.py
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_bx_data.py → app/core/config.py
- `StepStats` --uses--> `Settings` [INFERRED]
@@ -183,149 +203,147 @@
scripts/migrate_crm_clue.py → app/core/config.py
- `StepStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_clue.py → app/core/config.py
- `MigrationStats` --uses--> `Settings` [INFERRED]
scripts/migrate_crm_contract.py → app/core/config.py
## Import Cycles
- None detected.
## Communities (523 total, 17 thin omitted)
## Communities (541 total, 19 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.16
Nodes (32): check_document_expiry(), document_reminder_stats(), get_inventory_ledger(), get_summary(), list_document_reminders(), list_transactions(), list_warnings(), date (+24 more)
### Community 1 - "Community 1"
Cohesion: 0.10
Nodes (32): CRM 合同 API 路由 — GET/PUT/DELETE/POST 对齐原 Java CRM, 接口菜单权限守卫。super_admin 直接放行。, require_menu_code(), ContractApproverSettingSaveBody, ContractApprovalActionBody, ContractBatchAssignBody, ContractBatchSubmitBody, ContractChangeCreateBody (+24 more)
Cohesion: 0.08
Nodes (38): CRM 合同 API 路由 — GET/PUT/DELETE/POST 对齐原 Java CRM, 接口菜单权限守卫。super_admin 直接放行。, require_menu_code(), ContractApproverSettingSaveBody, ContractApprovalActionBody, ContractApprovalPassBody, ContractApprovalRejectBody, ContractApprovalTransferBody (+30 more)
### Community 2 - "Community 2"
Cohesion: 0.14
Nodes (15): BxAdvanceApply, BxAdvanceApproval, AdvanceService, Any, Session, 同一节点多次审批时,取 approval_time 最新的一条作为当前节点状态。, 返回全部审批动作,按时间正序排列,用于展示完整审批历史。, current_month_bounds() (+7 more)
Cohesion: 0.17
Nodes (27): _apply_inventory_product_update(), _apply_inventory_update(), _base_query(), create_inventory(), create_link_for_plan(), delete_inventory(), _generate_batch_no(), _get_inventory() (+19 more)
### Community 3 - "Community 3"
Cohesion: 0.08
Nodes (99): attachment_download_url(), attachment_preview_url(), AttachmentDownloadUrlBody, create_dept(), create_dict_data(), create_dict_type(), create_menu(), create_post() (+91 more)
Cohesion: 0.09
Nodes (74): attachment_download_url(), attachment_preview_url(), create_dept(), create_dict_data(), create_dict_type(), create_menu(), create_post(), create_role_management() (+66 more)
### Community 4 - "Community 4"
Cohesion: 0.12
Nodes (61): _apply_list_filters(), assign_opportunities(), batch_update_expect_date(), batch_update_stage(), change_stage(), create_opportunity(), _decimal_value(), _enrich_user_names() (+53 more)
Cohesion: 0.09
Nodes (76): _apply_list_filters(), assign_opportunities(), batch_update_expect_date(), batch_update_stage(), change_stage(), create_opportunity(), _decimal_value(), _enrich_user_names() (+68 more)
### Community 5 - "Community 5"
Cohesion: 0.20
Nodes (24): count_source_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings(), load_settings_env(), load_user_mapping() (+16 more)
### Community 6 - "Community 6"
Cohesion: 0.13
Nodes (42): assign_customer(), batch_claim_customers(), claim_customer(), create_customer(), deal_customer(), _enrich_user_names(), _ensure_customer_in_scope(), create_follow() (+34 more)
Cohesion: 0.18
Nodes (32): assign_customer(), batch_claim_customers(), check_duplicate_customer(), claim_customer(), create_customer(), deal_customer(), _enrich_user_names(), _ensure_customer_in_scope() (+24 more)
### Community 7 - "Community 7"
Cohesion: 0.12
Nodes (36): get_password_hash(), Namespace, build_merged_users(), bx_role_labels(), check_minio(), check_mysql(), check_redis(), _clip() (+28 more)
Cohesion: 0.09
Nodes (35): approve_carrier(), create_carrier(), get_carrier(), update_carrier(), PlCarrier, carrier_to_read(), CarrierBase, CarrierCreate (+27 more)
### Community 8 - "Community 8"
Cohesion: 0.12
Nodes (50): register_quote_routes(), accept_quote(), _build_quote_filters(), calculate_quote_amount(), create_new_version(), create_quote(), _decimal_value(), _enrich_contact_fields() (+42 more)
Cohesion: 0.11
Nodes (47): _build_quote_filters(), calculate_quote_amount(), create_quote(), _decimal_value(), _enrich_contact_fields(), _enrich_supplier_name(), _ensure_quote_in_scope(), _fill_contract_linked_count() (+39 more)
### Community 11 - "Community 11"
Cohesion: 0.10
Nodes (55): cancel_apply(), create_apply(), create_disburse(), delete_applies(), delete_disburses(), get_apply(), get_disburse(), list_applies() (+47 more)
Cohesion: 0.15
Nodes (40): PlVehicleUreaApply, PlVehicleUreaDisburse, 车辆尿素申请 pl_vehicle_urea_apply, 车辆尿素发放登记 pl_vehicle_urea_disburse, Decimal, VehicleUreaApplyCreate, VehicleUreaApplyRead, VehicleUreaApplyUpdate (+32 more)
### Community 12 - "Community 12"
Cohesion: 0.05
Nodes (69): contact_add(), contact_delete(), contact_update(), customer_create(), customer_delete(), customer_update(), customer_name_exists(), BaseModel (+61 more)
Nodes (74): contact_add(), contact_delete(), contact_update(), customer_create(), customer_update(), customer_name_exists(), BaseModel, AttachmentUploadResponse (+66 more)
### Community 13 - "Community 13"
Cohesion: 0.15
Nodes (32): create_instance(), create_process_def(), create_task(), get_all_tasks_for_business(), get_instance(), get_latest_version(), get_nodes_by_version(), get_pending_tasks_by_node() (+24 more)
Cohesion: 0.10
Nodes (44): register_contract_routes(), batch_assign_owner(), batch_submit_contract_approval(), _build_contract_filters(), _build_contract_name_from_parties(), download_contract_pdf(), _ensure_contract_in_scope(), export_contracts() (+36 more)
### Community 14 - "Community 14"
Cohesion: 0.10
Nodes (25): list_public_vehicle_plates(), Session, 地磅公共只读:免登车牌 options(现场填写页), 免登:按出入库/计划解析 tenant_no,返回 pl_vehicle 车牌(self + carrier)。, _resolve_tenant_no(), get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,14 个一级菜单), menu_badge_stats() (+17 more)
Cohesion: 0.28
Nodes (17): _address_to_read(), _build_address_query(), create_transport_address(), delete_transport_address(), _get_address(), get_transport_address(), list_all_transport_addresses(), list_transport_addresses() (+9 more)
### Community 15 - "Community 15"
Cohesion: 0.10
Nodes (39): approve_reimburse(), approved_by_me(), _build_details_data(), create_reimburse(), delete_reimburse(), get_approval_history(), get_approvals(), get_generated_title() (+31 more)
Cohesion: 0.11
Nodes (13): BxReimburseApply, BxReimburseApproval, BxReimburseDetail, 报销单勾选的发票附件(同一发票可勾选多个附件,各占一条)。, ReimburseInvoiceBriefOut, ReimburseInvoiceLinkIn, Any, Session (+5 more)
### Community 16 - "Community 16"
Cohesion: 0.10
Nodes (62): cancel_apply(), create_apply(), create_record(), delete_applies(), delete_records(), get_apply(), get_record(), list_applies() (+54 more)
Cohesion: 0.16
Nodes (37): PlVehicleRechargeApply, PlVehicleRechargeRecord, 车辆ETC/加油充值申请 pl_vehicle_recharge_apply, 车辆ETC/加油充值发放登记 pl_vehicle_recharge_record, 发放登记页:申请单 + 关联发放信息(左连接), VehicleRechargeDisburseBoardItem, VehicleRechargeRecordCreate, VehicleRechargeRecordRead (+29 more)
### Community 18 - "Community 18"
Cohesion: 0.10
Nodes (56): advance_pending_approval_stats(), advance_status_counts(), approve_advance(), approved_by_me(), create_advance(), delete_advance(), _fill_offset_amounts(), get_advance() (+48 more)
Cohesion: 0.15
Nodes (30): advance_pending_approval_stats(), advance_status_counts(), approve_advance(), approved_by_me(), create_advance(), delete_advance(), _fill_offset_amounts(), get_advance() (+22 more)
### Community 19 - "Community 19"
Cohesion: 0.09
Nodes (46): _avatar_url_field(), _build_user_info_payload(), change_current_user_password(), get_current_user_profile(), _jwt_user_payload(), logout(), public_quote_share(), Request (+38 more)
Cohesion: 0.11
Nodes (54): update_plan(), PlPlan, PlPlanProduct, 计划产品明细表 pl_plan_product, PlanArchiveFreightBlock, PlanArchiveProductItem, PlanProductCreate, PlanTransportCreateBlock (+46 more)
### Community 21 - "Community 21"
Cohesion: 0.09
Nodes (56): _alias_row_to_dict(), _assert_brand_deletable(), barcode_exists(), _brand_row_to_dict(), _build_category_tree(), category_code_exists(), _category_row_to_dict(), _collect_category_with_ancestors() (+48 more)
Cohesion: 0.15
Nodes (35): ensure_crm_create_by_row_in_scope(), _assert_brand_deletable(), barcode_exists(), category_code_exists(), create_category(), create_oss(), create_product(), generate_auto_product_no() (+27 more)
### Community 22 - "Community 22"
Cohesion: 0.08
Nodes (28): parse_admin_request_json(), Any, Request, 运营 Web(/web/admin)JSON 请求体解析。 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `{, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。 Returns:, ApiCryptoError, _b64url_decode(), _b64url_encode() (+20 more)
### Community 23 - "Community 23"
Cohesion: 0.05
Nodes (31): BaseStorage, convert_heic_to_jpeg(), get_storage(), LocalStorage, MinIOStorage, OSSStorage, process_image_content(), Any (+23 more)
Cohesion: 0.23
Nodes (3): process_image_content(), 处理图片内容,如果是 HEIC 格式则转换为 JPEG, 带下载文件名的访问 URL;默认实现为普通访问地址。
### Community 24 - "Community 24"
Cohesion: 0.08
Nodes (25): category_add(), category_delete(), category_tree(), category_update(), product_add(), product_delete(), product_detail(), product_options() (+17 more)
Cohesion: 0.16
Nodes (31): bx_health(), 报销(bx)API 路由聚合 — REST 风格,协议对齐 bx 原系统。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, approve_reimburse(), approved_by_me(), _build_details_data(), create_reimburse(), delete_reimburse() (+23 more)
### Community 25 - "Community 25"
Cohesion: 0.05
Nodes (72): BizAttachment, PlDriver, PlInboundOrderItemBrandQty, PlInventory, PlInventoryTransaction, PlInventoryWarning, PlOutboundOrderItemBrandQty, PlPlanChange (+64 more)
Cohesion: 0.12
Nodes (29): PlInventoryTransaction, PlPlanProductBrandQty, 计划产品归档品牌数量 pl_plan_product_brand_qty, 库存流水表 pl_inventory_transaction, load_brand_qtys_by_plan_product_ids(), persist_plan_product_brand_qtys(), Any, Decimal (+21 more)
### Community 26 - "Community 26"
Cohesion: 0.14
Nodes (24): list_vehicles(), PlVehiclePersonnel, 车辆-人员关联表 pl_vehicle_personnel, CertRead, VehicleListResponse, VehiclePersonnelRow, SnapshotCertRead, SnapshotPersonnelRow (+16 more)
Cohesion: 0.07
Nodes (42): ApiRequestLogMiddleware, _claims_from_auth(), _format_body_bytes(), _persist_log(), Any, Request, 统一记录 API 请求/响应出入参的中间件, _redact_obj() (+34 more)
### Community 27 - "Community 27"
Cohesion: 0.17
Nodes (32): _apply_plan_product_update(), _apply_plan_update(), AutoGenerateMonthlyResult, _base_query(), create_plan(), delete_plan(), _generate_plan_no(), get_plan() (+24 more)
Cohesion: 0.28
Nodes (15): create_clue_follow(), delete_clue_follow(), get_clue_follow(), get_follow_statistics(), list_clue_follows(), Any, Session, 更新线索跟进记录,必要时同步线索 next_time (+7 more)
### Community 28 - "Community 28"
Cohesion: 0.06
Nodes (92): approve_settlement_legacy(), cancel_settlement(), create_settlement(), delete_settlement(), disburse_settlement(), _generate_settlement_no(), get_settlement(), get_settlement_approval_flow() (+84 more)
Cohesion: 0.09
Nodes (61): PlFreightSettlement, PlFreightSettlementApproval, PlFreightSettlementTransport, PlRemittanceVoucher, 运费结算表 pl_freight_settlement, 运费结算审批 pl_freight_settlement_approval, 结算单-运输关联表 pl_freight_settlement_transport, 汇款凭证表 pl_remittance_voucher (+53 more)
### Community 29 - "Community 29"
Cohesion: 0.17
Nodes (22): _build_public_page(), _build_site_product_read(), _format_file_size(), get_public_site(), _get_site_link_by_token(), _parse_feedback_images(), Session, UploadFile (+14 more)
Cohesion: 0.07
Nodes (55): 返回 (作废, 归档)。现场链接实际走入库/出库单公共页。, _resolve_io_order_link_flags(), _build_public_page(), _build_site_product_read(), _format_file_size(), get_public_site(), _get_site_link_by_token(), _parse_feedback_images() (+47 more)
### Community 30 - "Community 30"
Cohesion: 0.16
Nodes (26): clear_target_categories(), compute_level(), count_target_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings() (+18 more)
### Community 33 - "Community 33"
Cohesion: 0.18
Nodes (17): bind_biz(), delete_attachment(), download_file(), list_by_biz(), _parse_id_list(), preview_attachment(), Session, UploadFile (+9 more)
Cohesion: 0.20
Nodes (15): bind_biz(), delete_attachment(), download_file(), list_by_biz(), _parse_id_list(), preview_attachment(), Session, UploadFile (+7 more)
### Community 34 - "Community 34"
Cohesion: 0.18
Nodes (25): approve_task(), _assert_wf_instance_in_scope(), _business_type_label(), create_process_def(), delete_process_def(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields() (+17 more)
Cohesion: 0.09
Nodes (44): approve_task(), _assert_wf_instance_in_scope(), _business_type_label(), create_process_def(), delete_process_def(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields() (+36 more)
### Community 35 - "Community 35"
Cohesion: 0.18
Nodes (36): clear_portal_workflow(), _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_bx_user_mapping(), load_runtime_settings() (+28 more)
### Community 36 - "Community 36"
Cohesion: 0.13
Nodes (21): ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, StartInstanceBody, 流程实例 wf_process_instance, WfNode, WfProcessInstance, WfTask (+13 more)
Cohesion: 0.14
Nodes (29): 验证密码(哈希非 bcrypt 或损坏时返回 False,避免抛错), verify_password(), change_password(), create_user(), get_user(), get_user_with_relations(), _hash_password(), list_post_ids_for_user() (+21 more)
### Community 37 - "Community 37"
Cohesion: 0.13
Nodes (29): _actor_ids(), _actor_names(), assert_row_deletable_by_creator(), assert_rows_deletable_by_creator(), can_delete_by_creator(), is_super_admin(), normalize_user_info(), Any (+21 more)
Cohesion: 0.24
Nodes (18): _actor_ids(), _actor_names(), assert_row_deletable_by_creator(), assert_rows_deletable_by_creator(), can_delete_by_creator(), is_super_admin(), normalize_user_info(), Any (+10 more)
### Community 38 - "Community 38"
Cohesion: 0.16
Nodes (19): ApiRequestLogMiddleware, _claims_from_auth(), _format_body_bytes(), _persist_log(), Any, Request, 统一记录 API 请求/响应出入参的中间件, _redact_obj() (+11 more)
Cohesion: 0.14
Nodes (24): PlTransportProductBrandQty, PlTransportProductFeedback, 运输单按产品回传 pl_transport_product_feedback, 运输单产品回传品牌数量 pl_transport_product_brand_qty, _dict_field(), format_brand_qty_summary(), load_transport_driver_product_feedbacks(), persist_io_item_brand_qtys() (+16 more)
### Community 39 - "Community 39"
Cohesion: 0.13
Nodes (44): assign_clues(), check_convert(), check_duplicate_clue(), convert_clue(), create_clue(), _enrich_user_names(), _ensure_clue_in_scope(), create_clue_follow() (+36 more)
Cohesion: 0.22
Nodes (28): assign_clues(), check_convert(), check_duplicate_clue(), convert_clue(), create_clue(), _enrich_user_names(), _ensure_clue_in_scope(), get_clue() (+20 more)
### Community 42 - "Community 42"
Cohesion: 0.19
@@ -333,123 +351,127 @@ Nodes (32): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_r
### Community 43 - "Community 43"
Cohesion: 0.10
Nodes (31): create_invoice(), delete_invoice(), get_mine_wallet_summary(), list_invoice_ledgers(), list_invoice_wallets(), list_invoices(), Request, Session (+23 more)
Nodes (30): create_invoice(), delete_invoice(), get_mine_wallet_summary(), list_invoice_ledgers(), list_invoice_wallets(), list_invoices(), Request, Session (+22 more)
### Community 44 - "Community 44"
Cohesion: 0.08
Nodes (25): Config, decrypt_login_payload(), ensure_initialized(), extract_login_credentials(), get_public_pem(), Any, 登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。, Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。 (+17 more)
Cohesion: 0.09
Nodes (41): align_contract_no_to_sign_date(), _apply_contract_entity_fields(), _calc_amount_with_tax(), contract_no_exists(), create_contract(), create_from_opportunity(), create_from_quote(), generate_contract_no() (+33 more)
### Community 45 - "Community 45"
Cohesion: 0.12
Nodes (42): _apply_plan_logistics_from_payload(), _apply_transport_arrange_fields(), arrange_transport(), _assert_vehicle_carrier_eligible(), _build_arrange_result(), _build_driver_url(), create_transport(), _ensure_driver_access_token() (+34 more)
Cohesion: 0.08
Nodes (73): _build_driver_url(), get_plan_arrange_info(), 获取计划已安排运输后的司机链接与地磅出入库关联(供查看弹窗复制简述/二维码)。, _apply_plan_logistics_from_payload(), _apply_transport_arrange_fields(), arrange_transport(), _assert_vehicle_carrier_eligible(), _build_arrange_result() (+65 more)
### Community 46 - "Community 46"
Cohesion: 0.18
Nodes (18): align_contract_no_to_sign_date(), generate_contract_no(), date, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号} 流水与撞号检测须含软删:uk_contr, 标准编号替换日期段,保留序号;非标准返回 None。, 将标准合同编号日期段对齐签订日;撞号则序号顺延(含软删查重)。 非标准编号原样返回。无签订日则原样返回。, replace_contract_no_date(), _mock_last_contract() (+10 more)
Cohesion: 0.13
Nodes (35): _apply_weighing_product_update(), _apply_weighing_update(), _base_query(), create_weighing(), delete_weighing(), _get_weighing(), get_weighing_related(), list_weighing() (+27 more)
### Community 48 - "Community 48"
Cohesion: 0.16
Nodes (32): _apply_inventory_product_update(), _apply_inventory_update(), _base_query(), create_inventory(), create_link_for_plan(), delete_inventory(), _generate_batch_no(), _get_inventory() (+24 more)
Cohesion: 0.30
Nodes (10): get_last_month_range(), month_range(), date, Session, 地磅计划按月自动生成 — 迁移自 simple-dibang-xiaoshou/auto-create-plan/auto_create_monthly_pla, 按月自动生成采购计划。 - 默认仅在每月 1 日执行(force=True 时跳过该限制,供手动触发验收) - 遍历所有租户,按上月计划模板生, run_auto_generate_monthly_plans(), default_execution_status() (+2 more)
### Community 49 - "Community 49"
Cohesion: 0.13
Nodes (31): apply_crm_create_by_scope(), ensure_crm_create_by_row_in_scope(), create_pool_rule(), delete_pool_rules(), execute_pool_rules(), get_pool_rule(), list_pool_rules(), Any (+23 more)
Cohesion: 0.08
Nodes (37): 分页查询供方列表 — Java: CrmSupplierInfoController.list, 供方全量列表(下拉)— Java: CrmSupplierInfoController.listAll, 供方详情 — Java: CrmSupplierInfoController.getInfo, 新增供方 — Java: CrmSupplierInfoController.add, 修改供方 — Java: CrmSupplierInfoController.edit, 删除供方 — Java: CrmSupplierInfoController.remove, 导出供方列表 — Java: CrmSupplierInfoController.export, supplier_info_add() (+29 more)
### Community 50 - "Community 50"
Cohesion: 0.15
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import WechatMes, 发送订单状态通知 Args: openid: 用户openid order_n, 发送支付成功通知 Args: openid: 用户openid order_n, 发送配送通知 Args: openid: 配送员openid task_no:, 发送配送时效预警 Args: openid: 配送员openid task_n, 发送退款结果通知 Args: openid: 用户openid order_n, 发送催单通知给配送员 Args: deliver_openid: 配送员openid, 发送模板消息 Args: openid: 用户openid template_ (+1 more)
Cohesion: 0.10
Nodes (26): list_public_vehicle_plates(), Session, 地磅公共只读:免登车牌 options(现场填写页), 免登:按出入库/计划解析 tenant_no,返回 pl_vehicle 车牌(self + carrier)。, _resolve_tenant_no(), get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,14 个一级菜单), menu_badge_stats() (+18 more)
### Community 51 - "Community 51"
Cohesion: 0.14
Nodes (44): PlPlanProduct, 计划产品明细表 pl_plan_product, PlanArchiveFreightBlock, PlanProductCreate, PlanTransportCreateBlock, all_hazard_products_cert_complete(), apply_archive_freight(), _apply_payload_to_transport_row() (+36 more)
Cohesion: 0.06
Nodes (76): archive_plan(), cancel_plan(), cancel_plan_wait_notice(), count_plans_by_contract(), create_from_contract(), create_plan(), create_plan_full(), delete_plan() (+68 more)
### Community 52 - "Community 52"
Cohesion: 0.18
Nodes (29): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+21 more)
### Community 53 - "Community 53"
Cohesion: 0.14
Nodes (21): 报销模块认证适配:门户 JWT 用户 → bx 业务上下文。, BxReimburseInvoice, BxReimburseOffset, BxWorkflowNode, 报销(bx)模块数据模型 — 对齐 docs/sql/20260606_bx_tables.sql, filter_current_cycle_approvals(), 审批轮次过滤 — 驳回后重新提交时,进度接口仅展示当前轮次。, 审批进度仅展示当前轮次;完整历史由 get_approval_history 返回。 (+13 more)
Cohesion: 0.09
Nodes (41): 报销模块认证适配:门户 JWT 用户 → bx 业务上下文。, BxReimburseInvoice, BxReimburseOffset, BxWorkflowNode, 报销(bx)模块数据模型 — 对齐 docs/sql/20260606_bx_tables.sql, filter_current_cycle_approvals(), 审批轮次过滤 — 驳回后重新提交时,进度接口仅展示当前轮次。, 审批进度仅展示当前轮次;完整历史由 get_approval_history 返回。 (+33 more)
### Community 54 - "Community 54"
Cohesion: 0.19
Nodes (28): _get_by_plan(), get_inbound(), get_inbound_by_plan(), _get_order(), get_outbound(), get_outbound_by_plan(), inbound_site_url(), list_inbound() (+20 more)
### Community 58 - "Community 58"
Cohesion: 0.13
Nodes (37): CRM 合同子模块路由 — 变更/模板/审批独立页, register_contract_sub_routes(), _change_row_to_dict(), create_contract_change(), create_contract_template(), execute_change(), export_contract_changes(), export_contract_templates() (+29 more)
Cohesion: 0.17
Nodes (32): _apply_plan_product_update(), _apply_plan_update(), AutoGenerateMonthlyResult, _base_query(), create_plan(), delete_plan(), _generate_plan_no(), get_plan() (+24 more)
### Community 59 - "Community 59"
Cohesion: 0.20
Nodes (28): _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env() (+20 more)
### Community 60 - "Community 60"
Cohesion: 0.17
Nodes (20): operlog_detail(), operlog_list(), Session, 操作日志分页列表(基于 API 请求日志适配 RuoYi OperLog 结构), _user_info(), business_type_from_path(), title_from_path(), _apply_oper_log_scope() (+12 more)
Cohesion: 0.08
Nodes (25): category_add(), category_delete(), category_tree(), category_update(), product_add(), product_delete(), product_detail(), product_options() (+17 more)
### Community 61 - "Community 61"
Cohesion: 0.17
Nodes (31): DbInboundOutbound, PlTransportDbLink, 运输-地磅出入库关联 pl_transport_db_link, _apply_plan_quantity_delta(), _create_db_inventory(), _create_db_plan(), DibangInventoryLinkResult, find_monthly_db_plan() (+23 more)
### Community 62 - "Community 62"
Cohesion: 0.11
Nodes (45): _generate_notify_message(), PlPlan, PlTransportDbLink, 运输-地磅出入库关联 pl_transport_db_link, _apply_plan_quantity_delta(), _create_db_inventory(), _create_db_plan(), DibangInventoryLinkResult (+37 more)
Nodes (37): approve_settlement_legacy(), cancel_settlement(), create_settlement(), delete_settlement(), disburse_settlement(), _generate_settlement_no(), get_settlement(), get_settlement_approval_flow() (+29 more)
### Community 63 - "Community 63"
Cohesion: 0.20
Nodes (13): create_expense_item(), delete_expense_item(), get_expense_item(), get_expense_item_tree(), Session, update_expense_item(), BxExpenseItem, _coerce_id() (+5 more)
### Community 64 - "Community 64"
Cohesion: 0.04
Nodes (178): clue_assign(), clue_convert(), clue_create(), clue_delete(), clue_detail(), clue_export(), clue_follow_create(), clue_follow_delete() (+170 more)
Cohesion: 0.05
Nodes (114): clue_detail(), clue_follow_detail(), clue_follow_statistics(), clue_import(), contact_birthday(), contact_by_customer(), contact_decision(), contact_detail() (+106 more)
### Community 65 - "Community 65"
Cohesion: 0.10
Nodes (58): cancel_apply(), create_apply(), create_process(), delete_applies(), delete_processes(), get_apply(), get_process(), list_applies() (+50 more)
Cohesion: 0.19
Nodes (34): PlVehicleMaintenanceApply, PlVehicleMaintenanceProcess, 车辆维保申请 pl_vehicle_maintenance_apply, 车辆维保处理登记 pl_vehicle_maintenance_process, VehicleMaintenanceApplyRead, VehicleMaintenanceProcessBoardItem, apply_to_read(), _assert_vehicle_exists() (+26 more)
### Community 66 - "Community 66"
Cohesion: 0.18
Nodes (18): create_workflow(), delete_workflow(), get_workflow(), get_workflow_by_biz_type(), list_workflows(), Session, save_workflow_nodes(), update_workflow() (+10 more)
Cohesion: 0.15
Nodes (24): create_workflow(), delete_workflow(), get_workflow(), get_workflow_by_biz_type(), list_workflows(), Session, save_workflow_nodes(), update_workflow() (+16 more)
### Community 67 - "Community 67"
Cohesion: 0.09
Nodes (48): _build_public_page(), _format_file_size(), _format_plan_date(), get_public_transport(), _get_transport_by_token(), _parse_feedback_images(), Session, UploadFile (+40 more)
Cohesion: 0.12
Nodes (36): get_password_hash(), Namespace, build_merged_users(), bx_role_labels(), check_minio(), check_mysql(), check_redis(), _clip() (+28 more)
### Community 68 - "Community 68"
Cohesion: 0.19
Nodes (25): bind_vehicle_driver(), create_vehicle(), get_vehicle(), paste_recognize_commit(), update_vehicle(), _vehicle_to_detail(), _vehicle_to_read(), PlVehicle (+17 more)
Cohesion: 0.33
Nodes (13): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), Any (+5 more)
### Community 69 - "Community 69"
Cohesion: 0.14
Nodes (28): _append_user_scope_conditions(), apply_data_scope(), assert_row_in_data_scope(), _collect_scope_ids(), _get_child_dept_ids(), get_user_dept_id(), Session, 数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3 (+20 more)
Cohesion: 0.10
Nodes (38): _append_user_scope_conditions(), apply_data_scope(), assert_row_in_data_scope(), _collect_scope_ids(), _get_child_dept_ids(), get_user_dept_id(), Session, 数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3 (+30 more)
### Community 70 - "Community 70"
Cohesion: 0.39
Nodes (10): create_post(), get_post(), list_posts(), post_code_exists(), Any, Session, _row_to_dict(), soft_delete_post() (+2 more)
Cohesion: 0.36
Nodes (13): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), menu_name_exists(), Any (+5 more)
### Community 71 - "Community 71"
Cohesion: 0.11
Nodes (32): CRM 报价单 API 路由 — 挂接到 crm.router, QuoteApproverSettingSaveBody, QuoteAcceptBody, QuoteApprovalApproveBody, QuoteApprovalListBody, QuoteApprovalRefreshNamesBody, QuoteApprovalWithdrawBody, QuoteCreateBody (+24 more)
### Community 72 - "Community 72"
Cohesion: 0.18
Nodes (30): Settings, BaseSettings, apply_biz_backfill(), BackfillRule, BizRef, build_biz_index(), count_target_rows(), derive_source_url() (+22 more)
Cohesion: 0.19
Nodes (28): apply_biz_backfill(), BackfillRule, BizRef, build_biz_index(), count_target_rows(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows() (+20 more)
### Community 73 - "Community 73"
Cohesion: 0.20
Nodes (25): derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_oss_id_to_url(), load_runtime_settings(), load_settings_env(), load_user_mapping() (+17 more)
### Community 74 - "Community 74"
Cohesion: 0.18
Nodes (17): get_pool_record(), list_pool_records(), Any, Session, _row_to_dict(), total_pages(), _execute_single_rule(), CrmCustomerPool (+9 more)
Cohesion: 0.12
Nodes (15): _db_pool_keepalive_loop(), _error_json(), lifespan(), Exception, Request, 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误, 未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin, 定期 ping MySQL,避免远程库/NAT 回收空闲 TCP 后首请求长时间卡住。 (+7 more)
### Community 77 - "Community 77"
Cohesion: 0.11
Nodes (12): get_wechat_pay_client(), get_wechat_pay_v2(), Any, 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.html, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total_amo, 申请退款 Args: out_trade_no: 商户订单号 total_amount: 订单, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 total_f (+4 more)
### Community 78 - "Community 78"
Cohesion: 0.12
Nodes (15): pool_rule_add(), pool_rule_delete(), pool_rule_detail(), pool_rule_execute(), pool_rule_list(), pool_rule_update(), pool_rule_update_status(), PoolRuleAddBody (+7 more)
Cohesion: 0.40
Nodes (12): create_follow(), _enrich_follow_dict(), get_follow(), list_follows(), list_follows_by_customer(), Any, Session, _row_to_dict() (+4 more)
### Community 81 - "Community 81"
Cohesion: 0.18
Nodes (17): get_oper_log_meta(), OperLogMeta, 请求级操作日志元数据(ContextVar), 供异步落库线程使用,避免 ContextVar 跨线程丢失。, set_oper_log_meta(), snapshot_oper_log_meta(), _format_summary(), oper_log() (+9 more)
Cohesion: 0.15
Nodes (37): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, MenuCreateBody (+29 more)
### Community 83 - "Community 83"
Cohesion: 0.15
@@ -460,8 +482,8 @@ Cohesion: 0.23
Nodes (23): build_id_maps(), clip_text(), count_rows(), export_mapping(), fetch_rows(), legacy_id_to_str(), main(), map_id() (+15 more)
### Community 86 - "Community 86"
Cohesion: 0.12
Nodes (39): _apply_weighing_product_update(), _apply_weighing_update(), _base_query(), create_weighing(), delete_weighing(), _get_weighing(), get_weighing_related(), list_weighing() (+31 more)
Cohesion: 0.15
Nodes (11): BxAdvanceApply, BxAdvanceApproval, AdvanceService, Any, Session, 同一节点多次审批时,取 approval_time 最新的一条作为当前节点状态。, 返回全部审批动作,按时间正序排列,用于展示完整审批历史。, Any (+3 more)
### Community 87 - "Community 87"
Cohesion: 0.20
@@ -476,20 +498,20 @@ Cohesion: 0.19
Nodes (22): PlOcrUsageMonth, 阿里云 OCR 月度调用计数 pl_ocr_usage_month(按自然月全局统计), assert_quota_available(), _build_ocr_client(), compress_image_bytes(), current_usage_month(), _first_attachment_url(), get_or_create_usage_row() (+14 more)
### Community 91 - "pl_vehicle_recharge_service.py"
Cohesion: 0.07
Nodes (87): register_contract_routes(), _apply_contract_entity_fields(), batch_assign_owner(), batch_submit_contract_approval(), _build_contract_filters(), _build_contract_name_from_parties(), _build_customer_address(), _calc_amount_with_tax() (+79 more)
Cohesion: 0.17
Nodes (23): cancel_apply(), create_apply(), create_record(), delete_applies(), delete_records(), get_apply(), get_record(), list_applies() (+15 more)
### Community 92 - "Community 92"
Cohesion: 0.09
Nodes (36): 验证密码(哈希非 bcrypt 或损坏时返回 False,避免抛错), verify_password(), camel_to_snake(), CRUDBase, get_model_attr(), HistoryCRUD, Any, Session (+28 more)
Cohesion: 0.24
Nodes (10): _cert_url_blank(), plan_has_hazard_product_exists(), plan_has_incomplete_hazard_cert_exists(), 证书 URL 为空(NULL / 空串 / 纯空白)。, 列表筛选:计划下存在 CRM 标识为易制毒/易制爆的产品。, 列表筛选:存在危化产品且至少一张必需证书未上传。, _compile(), 危化品证上传列表筛选:EXISTS 子查询应覆盖 CRM 危化标识与证书缺口。 (+2 more)
### Community 93 - "_invoice_info_by_customer_impl"
Cohesion: 0.24
Nodes (16): allocate_reimburse_title_seq(), format_reimburse_title(), generate_apply_code(), generate_title(), is_auto_reimburse_title(), parse_reimburse_date(), preview_reimburse_title_seq(), date (+8 more)
Cohesion: 0.12
Nodes (50): CRM 合同子模块路由 — 变更/模板/审批独立页, register_contract_sub_routes(), _build_customer_address(), _change_row_to_dict(), _contract_period_key(), contract_row_to_dict(), create_contract_change(), create_contract_template() (+42 more)
### Community 94 - "response.py"
Cohesion: 0.36
Nodes (15): create_opportunity_follow(), _ensure_parent_opportunity(), get_opportunity_follow(), list_follows_by_opportunity(), list_opportunity_follows(), _parse_optional_datetime(), Any, datetime (+7 more)
Cohesion: 0.23
Nodes (13): get_user_menu_codes(), Session, 读取用户授权的菜单权限标识集合(与前端 meta.menuCode / perms 对齐)。, _expand_with_ancestor_menu_ids(), _granted_menu_ids_for_user(), iter_user_menu_perm_codes(), Session, Web 管理端登录:基于 V0.3 sys_user / sys_user_role / sys_role 的角色与菜单权限解析 (+5 more)
### Community 95 - "Community 95"
Cohesion: 0.35
@@ -500,48 +522,48 @@ Cohesion: 0.21
Nodes (22): clear_target_products(), count_target_rows(), _dec(), derive_source_url(), fetch_portal_admin_id(), fetch_source_rows(), legacy_id_to_str(), load_runtime_settings() (+14 more)
### Community 100 - "price_letter_detail"
Cohesion: 0.31
Nodes (13): apply_renumber(), build_mapping(), fetch_products(), format_new_product_no(), load_settings_env(), main(), product_id_sort_key(), Engine (+5 more)
Cohesion: 0.27
Nodes (15): Settings, BaseSettings, apply_renumber(), build_mapping(), fetch_products(), format_new_product_no(), load_settings_env(), main() (+7 more)
### Community 101 - ".to_tenant_user_dict"
Cohesion: 0.23
Nodes (12): CRM 模块 Excel 导出列定义(字段与字典类型对齐 Java *Vo @ExcelDictFormat)。, _build_workbook(), DictLabelResolver, export_rows_to_xlsx_response(), ExportColumn, Any, Excel 导出工具:集中处理字典 code → label(对齐 Java ExcelDictConvert / ExcelDictPreloadConver, CRM 列表导出统一入口:表头 + 行数据 + 字典 label 转换 + 文件流响应。 (+4 more)
Cohesion: 0.19
Nodes (14): CRM 模块 Excel 导出列定义(字段与字典类型对齐 Java *Vo @ExcelDictFormat)。, _build_workbook(), DictLabelResolver, export_rows_to_xlsx_response(), ExportColumn, load_dict_label_maps(), Any, Session (+6 more)
### Community 102 - "dept.py"
Cohesion: 0.33
Nodes (13): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), Any (+5 more)
Cohesion: 0.35
Nodes (11): create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), Any, Session, 字典类型 CRUD(sys_dict_type), _row_to_dict() (+3 more)
### Community 104 - "apply_crm_create_by_scope"
Cohesion: 0.29
Nodes (15): create_price_letter(), get_price_letter(), list_price_letters(), _parse_date(), Any, date, Session, _row_to_dict() (+7 more)
### Community 105 - "list_customers"
Cohesion: 0.21
Nodes (16): PlCert, PlDocumentReminder, 证件到期提醒表 pl_document_reminder, list_owner_certs(), list_owner_certs_batch(), nearest_expire_date(), _normalize_cert_row(), date (+8 more)
Cohesion: 0.14
Nodes (25): list_personnel(), PlCert, CertRead, PersonnelListResponse, SnapshotCertRead, SnapshotPersonnelRow, certs_to_read(), list_owner_certs() (+17 more)
### Community 106 - "Community 106"
Cohesion: 0.20
Nodes (15): _fill_contract_linked_count(), list_quotes(), _parse_optional_datetime(), _period_key(), Any, datetime, query_versions(), quote_row_to_dict() (+7 more)
Nodes (19): cancel_apply(), create_apply(), create_disburse(), delete_applies(), delete_disburses(), get_apply(), get_disburse(), list_applies() (+11 more)
### Community 107 - "apply_pl_scope"
Cohesion: 0.30
Nodes (12): PlCarrier, assert_carrier_eligible_for_transport(), carrier_agreement_expired(), carrier_audit_approved(), carrier_eligible_for_transport(), carrier_qualification_complete(), date, 资质附件均为选填,保留函数签名供兼容调用。 (+4 more)
Cohesion: 0.16
Nodes (31): create_instance(), create_process_def(), create_task(), get_all_tasks_for_business(), get_instance(), get_latest_version(), get_nodes_by_version(), get_pending_tasks_by_node() (+23 more)
### Community 109 - "Community 109"
Cohesion: 0.35
Nodes (11): create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), Any, Session, 字典类型 CRUD(sys_dict_type), _row_to_dict() (+3 more)
Cohesion: 0.14
Nodes (35): create_vehicle(), get_vehicle(), paste_recognize_commit(), update_vehicle(), _vehicle_to_detail(), _vehicle_to_read(), generate_uuid(), PlVehicle (+27 more)
### Community 110 - "Base"
Cohesion: 0.18
Nodes (17): get_web_auth_menu_codes(), 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。, get_user_menu_codes(), Session, 读取用户授权的菜单权限标识集合(与前端 meta.menuCode / perms 对齐)。, _expand_with_ancestor_menu_ids(), _granted_menu_ids_for_user(), iter_user_menu_perm_codes() (+9 more)
Cohesion: 0.31
Nodes (9): decrypt_login_payload(), ensure_initialized(), extract_login_credentials(), get_public_pem(), Any, 登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。, Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。, 从请求体解析用户名、密码。 返回 (username, password, error_message);error_message 非空时表示失败。 (+1 more)
### Community 111 - "Community 111"
Cohesion: 0.28
Nodes (14): _assert_editable(), _build_public_page(), _format_file_size(), _get_inventory_by_token(), get_public_inventory(), _parse_feedback_images(), Session, UploadFile (+6 more)
### Community 112 - "storage.py"
Cohesion: 0.09
Nodes (21): 分页查询供方列表 — Java: CrmSupplierInfoController.list, 供方全量列表(下拉)— Java: CrmSupplierInfoController.listAll, 供方详情 — Java: CrmSupplierInfoController.getInfo, 新增供方 — Java: CrmSupplierInfoController.add, 修改供方 — Java: CrmSupplierInfoController.edit, 删除供方 — Java: CrmSupplierInfoController.remove, 导出供方列表 — Java: CrmSupplierInfoController.export, supplier_info_add() (+13 more)
Cohesion: 0.15
Nodes (17): get_pool_record(), list_pool_records(), Any, Session, _row_to_dict(), total_pages(), CrmCustomerPool, check_customer_protect_time() (+9 more)
### Community 113 - "quote_share_log.py"
Cohesion: 0.26
@@ -552,8 +574,8 @@ Cohesion: 0.24
Nodes (12): DbSequence, 地磅(db)模块数据模型 — 对齐 docs/sql/db_tables.sql, _allocate_inbound_outbound_id(), _ensure_sequence_row(), max_numeric_inbound_outbound_id(), next_inbound_outbound_id(), Session, 出入库单 id 生成 — 租户内纯数字自增,并发安全。 (+4 more)
### Community 115 - "site.py"
Cohesion: 0.26
Nodes (18): _address_to_read(), _build_address_query(), create_transport_address(), delete_transport_address(), _get_address(), get_transport_address(), list_all_transport_addresses(), list_transport_addresses() (+10 more)
Cohesion: 0.05
Nodes (73): clue_assign(), clue_convert(), clue_create(), clue_delete(), clue_export(), clue_follow_create(), clue_follow_delete(), clue_follow_list() (+65 more)
### Community 116 - "Community 116"
Cohesion: 0.19
@@ -568,20 +590,20 @@ Cohesion: 0.16
Nodes (28): CertRow, _cert_row_complete(), collect_required_cert_errors(), _find_cert_for_required(), get_required_personnel_cert_names(), match_required_cert_name(), _missing_field_labels(), Session (+20 more)
### Community 122 - "Community 122"
Cohesion: 0.16
Nodes (33): create_contact(), get_contact(), list_contacts_by_customer(), _parse_optional_date(), Any, date, Session, _row_to_dict() (+25 more)
Cohesion: 0.39
Nodes (10): create_post(), get_post(), list_posts(), post_code_exists(), Any, Session, _row_to_dict(), soft_delete_post() (+2 more)
### Community 125 - "Community 125"
Cohesion: 0.08
Nodes (53): _build_page(), _get_by_token(), _models(), Session, 运输计划 · 入库/出库单现场免登录公共 API, PlInboundOrder, PlInboundOrderItem, PlOutboundOrder (+45 more)
Nodes (56): _build_page(), _get_by_token(), _make_handlers(), _models(), Session, 运输计划 · 入库/出库单现场免登录公共 API, PlInboundOrderItem, PlOutboundOrder (+48 more)
### Community 126 - "customer_pool.py"
Cohesion: 0.45
Nodes (11): _customer_base_query(), get_follow_statistics(), get_industry_statistics(), get_level_statistics(), get_overview_statistics(), get_owner_statistics(), get_source_statistics(), get_trend_statistics() (+3 more)
Cohesion: 0.20
Nodes (10): 地磅 API 路由聚合 — REST 风格,协议对齐原 simple-dibang-xiaoshou。, API 路由包 — 山峡化工生产一体化门户, operlog_detail(), operlog_list(), Session, 操作日志分页列表(基于 API 请求日志适配 RuoYi OperLog 结构), _user_info(), OperLogDetailBody (+2 more)
### Community 127 - "Community 127"
Cohesion: 0.25
Nodes (17): _cargo_stats(), get_dashboard_stats(), get_inbound_by_cargo(), get_inbound_by_partner_cargo(), get_outbound_by_cargo(), get_outbound_by_partner_cargo(), _partner_cargo_stats(), Session (+9 more)
Cohesion: 0.32
Nodes (16): _cargo_stats(), get_dashboard_stats(), get_inbound_by_cargo(), get_inbound_by_partner_cargo(), get_outbound_by_cargo(), get_outbound_by_partner_cargo(), _partner_cargo_stats(), Session (+8 more)
### Community 128 - "plan.py"
Cohesion: 0.39
@@ -592,8 +614,12 @@ Cohesion: 0.12
Nodes (24): _auto_contract_name_body(), generate_contract_name(), 按面板单位全称精确匹配交易主体/客户主数据,取 shortName;对不上则用全称。, 前端预览误用单位全称时,名称片段会等于面板/客户/开票全称。, 按面板供方(partyA)-需方(partyB)生成:{供方简称}-{需方简称}({合同编号})。 - 名称为空:按主数据简称自动生成 - 名, resolve_party_short_name(), _strip_contract_name_no_suffix(), _user_contract_name_uses_party_full_name() (+16 more)
### Community 130 - "datetime_parse.py"
Cohesion: 0.40
Nodes (3): Any, 供 get_tenant_no 等门户工具使用。, 与门户 JWT / apply_data_scope 所需的 user_info 字段对齐。
Cohesion: 0.23
Nodes (19): create_contact(), get_contact(), list_contacts_by_customer(), _parse_optional_date(), Any, date, Session, _row_to_dict() (+11 more)
### Community 131 - "LocalStorage"
Cohesion: 0.60
Nodes (3): assert_contract_editable_for_update(), test_assert_allows_editable(), test_assert_rejects_non_editable()
### Community 132 - "crm_supplier_hazard.py"
Cohesion: 0.14
@@ -603,9 +629,9 @@ Nodes (23): build_updates(), derive_source_url(), fetch_source_customers(), lega
Cohesion: 0.25
Nodes (18): batch_generate_sample_codes(), batch_issue_sample_codes(), batch_revoke_sample_codes(), create_sample_code(), get_sample_code(), list_sample_codes(), _parse_issued_time(), Any (+10 more)
### Community 135 - "post.py"
Cohesion: 0.24
Nodes (12): get_last_month_range(), month_range(), date, Session, 地磅计划按月自动生成 — 迁移自 simple-dibang-xiaoshou/auto-create-plan/auto_create_monthly_pla, 按月自动生成采购计划。 - 默认仅在每月 1 日执行(force=True 时跳过该限制,供手动触发验收) - 遍历所有租户,按上月计划模板生, run_auto_generate_monthly_plans(), default_execution_status() (+4 more)
### Community 135 - "unsettled_plans_q_filter"
Cohesion: 0.15
Nodes (14): invoice_info_add(), invoice_info_by_customer(), _invoice_info_by_customer_impl(), invoice_info_delete(), invoice_info_list(), invoice_info_set_default(), invoice_info_update(), 按客户ID查询开票信息(与 by-customer 等价) (+6 more)
### Community 136 - "Community 136"
Cohesion: 0.19
@@ -613,75 +639,131 @@ Nodes (18): create_role(), get_role(), get_role_data_scope(), get_role_menu_ids(
### Community 137 - "statistics.py"
Cohesion: 0.09
Nodes (18): _date_to_str(), _dt_to_str(), PagedQuery, PagedResponse, date, datetime, bx 原系统 API 响应包装(code=0 / msg / data.rows),与门户 success_response 分离。, _coerce_id() (+10 more)
Nodes (37): advance_issue_stats(), batch_offset(), export_advance_issues(), issue_advance(), list_advance_issues(), list_advance_offset_records(), list_pending_payments(), list_processed_payments() (+29 more)
### Community 138 - "Community 138"
Cohesion: 0.33
Nodes (19): check_python(), create_venv(), ensure_dirs(), ensure_valid_venv(), ensure_venv_and_runtime(), install_dependencies(), is_running(), log_error() (+11 more)
### Community 139 - "get_current_user_by_token"
Cohesion: 0.22
Nodes (20): register_quote_routes(), accept_quote(), create_new_version(), generate_pdf(), generate_share(), _get_quote_in_scope(), get_template(), invalid_quote() (+12 more)
### Community 141 - "PlTransport"
Cohesion: 0.24
Nodes (11): _plan_type_to_business_type(), 按运输计划单据类型解析地磅往来单位(不区分 CRM 合同类型)。 - 入库单 inbound:供方 → party_a,其次 supplier_nam, resolve_partner_company(), _normalize_plan_date(), date, Session, 运输计划 · 工厂现场链接(与地磅出入库单解耦), 入库/出库安排运输:按产品生成现场链接(不写 db_inbound_outbound)。 (+3 more)
### Community 143 - "SysEthnic"
Cohesion: 0.33
Nodes (11): create_leave(), get_leave(), list_leaves(), Any, Session, _row_to_dict(), soft_delete_leave(), update_leave() (+3 more)
### Community 145 - "minio_url.py"
Cohesion: 0.08
Nodes (22): pool_customer_assign(), pool_customer_claim(), pool_customer_list(), pool_record_detail(), pool_record_list(), price_letter_add(), price_letter_detail(), price_letter_list() (+14 more)
### Community 144 - "dict_data.py"
Cohesion: 0.33
Nodes (8): allocate_next_biz_no(), _format_biz_no(), _prefix_for(), datetime, Session, 业务协议号自动生成:XBCC / JZCC + YYYYMMDD + 6 位序号, 原子分配下一个业务协议号。 须在 create 事务内调用;使用 MySQL LAST_INSERT_ID 保证并发安全。, BizNoKind
### Community 145 - "resolve_crm_product"
Cohesion: 0.16
Nodes (20): _alias_row_to_dict(), _brand_row_to_dict(), _build_category_tree(), _category_row_to_dict(), _collect_category_with_ancestors(), list_categories(), list_category_tree(), list_oss_by_biz() (+12 more)
### Community 146 - "__init__.py"
Cohesion: 0.29
Nodes (15): clue_statistics_level(), clue_statistics_overview(), clue_statistics_owner(), clue_statistics_source(), clue_statistics_trend(), _apply_create_range(), _base_query(), get_clue_level_statistics() (+7 more)
Cohesion: 0.16
Nodes (33): bind_vehicle_driver(), create_driver(), create_personnel(), delete_carrier(), delete_driver(), delete_personnel(), delete_vehicle(), get_driver() (+25 more)
### Community 147 - "Community 147"
Cohesion: 0.37
Nodes (17): check_env(), check_python(), create_venv(), init_env(), install_dependencies(), log_error(), log_info(), log_success() (+9 more)
### Community 154 - "PlCarrier"
Cohesion: 0.09
Nodes (54): approve_carrier(), create_carrier(), create_driver(), create_personnel(), delete_carrier(), delete_driver(), delete_personnel(), delete_vehicle() (+46 more)
### Community 150 - "apply_site_feedback"
Cohesion: 0.15
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import WechatMes, 发送订单状态通知 Args: openid: 用户openid order_n, 发送支付成功通知 Args: openid: 用户openid order_n, 发送配送通知 Args: openid: 配送员openid task_no:, 发送配送时效预警 Args: openid: 配送员openid task_n, 发送退款结果通知 Args: openid: 用户openid order_n, 发送催单通知给配送员 Args: deliver_openid: 配送员openid, 发送模板消息 Args: openid: 用户openid template_ (+1 more)
### Community 159 - "minio_url.py"
Cohesion: 0.49
Nodes (10): apply_pl_scope(), Session, build_menu_badge_counts(), count_document_reminder_expired_pending(), count_freight_approval_pending(), count_freight_disburse_pending(), _count_pending_applies(), count_plan_archive_pending() (+2 more)
### Community 152 - "response.py"
Cohesion: 0.29
Nodes (6): Config, format_api_error_message(), PageResult, Exception, 将 HTTP/SQLAlchemy 等异常转为可展示的错误文案(避免 str([]) 空列表)。, ResponseModel
### Community 154 - "response.py"
Cohesion: 0.38
Nodes (13): ensure_crm_customer_linked_row_in_scope(), 客户子表(开票信息等):先校验关联客户 owner scope,否则校验 create_by。, _clear_default_for_customer(), create_invoice_info(), get_invoice_info(), list_invoice_info_by_customer(), Any, Session (+5 more)
### Community 156 - "utils.py"
Cohesion: 0.21
Nodes (15): format_datetime(), get_current_time(), parse_datetime(), datetime, _create_by_name(), datetime_end_of_day(), fmt_date(), fmt_datetime() (+7 more)
### Community 159 - "customer_update"
Cohesion: 0.29
Nodes (15): clue_statistics_level(), clue_statistics_overview(), clue_statistics_owner(), clue_statistics_source(), clue_statistics_trend(), _apply_create_range(), _base_query(), get_clue_level_statistics() (+7 more)
### Community 160 - "register_local_callback"
Cohesion: 0.13
Nodes (21): API 路由包 — 山峡化工生产一体化门户, create_leave(), delete_leave(), get_leave(), _leave_local_callback(), leave_workflow_callback(), list_leaves(), Session (+13 more)
Cohesion: 0.18
Nodes (18): create_leave(), delete_leave(), get_leave(), _leave_local_callback(), leave_workflow_callback(), list_leaves(), Session, submit_leave() (+10 more)
### Community 161 - "backfill_crm_contract_attachment_urls.py"
Cohesion: 0.33
Nodes (10): load_oss_map(), load_runtime_settings(), load_settings_env(), main(), Any, Engine, 返回 (新值, 是否发生了 id→url 替换)。, resolve_token() (+2 more)
### Community 164 - "ethnic.py"
Cohesion: 0.21
Nodes (11): list_ethnics(), Any, Session, 民族码表 CRUD(全局 sys_ethnic), _row_to_dict(), 数据模型(与 docs/sql/shanxia2.0.sql 全库导出基线对齐的核心系统表), Web 管理端约定角色(由 sys_role.role_name 映射而来,非数据库枚举), 民族码表 sys_ethnic(国标 GB/T 3304,全局) (+3 more)
### Community 162 - ".to_tenant_user_dict"
Cohesion: 0.31
Nodes (14): create_pool_rule(), delete_pool_rules(), execute_pool_rules(), _execute_single_rule(), get_pool_rule(), list_pool_rules(), Any, Session (+6 more)
### Community 163 - "__init__.py"
Cohesion: 0.22
Nodes (15): get_storage(), download_file_bytes(), file_stream(), get_access_url(), get_download_url(), get_preview_url(), normalize_storage_path(), 报销附件存储适配 — 复用门户 app.core.storage,对外保持 bx 协议。 (+7 more)
### Community 164 - "get_client_ip"
Cohesion: 0.09
Nodes (50): _avatar_url_field(), _build_user_info_payload(), change_current_user_password(), get_current_user_profile(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), public_quote_share() (+42 more)
### Community 170 - "test_quote_approver_setting.py"
Cohesion: 0.20
Nodes (21): _assert_users_exist(), get_setting(), Any, Session, _row_to_dict(), save_setting(), _assert_users_exist(), get_setting() (+13 more)
### Community 171 - "crm_supplier_hazard.py"
Cohesion: 0.28
Nodes (11): assert_products_allowed_for_supplier(), enrich_products_with_hazard_flags(), get_supplier_hazard_flags(), product_allowed(), Any, Session, 批量回填明细行 isToxic/isExplosive(来自产品主数据,供前端切换主体剔除)。, test_dual_requires_both() (+3 more)
### Community 172 - "apply_pl_scope"
Cohesion: 0.49
Nodes (10): apply_pl_scope(), Session, build_menu_badge_counts(), count_document_reminder_expired_pending(), count_freight_approval_pending(), count_freight_disburse_pending(), _count_pending_applies(), count_plan_archive_pending() (+2 more)
### Community 173 - "resolve_create_time_bounds"
Cohesion: 0.67
Nodes (3): parse_optional_plan_datetime(), datetime, 运输计划相关日期时间解析:前端 date-picker 仅传 YYYY-MM-DD。
### Community 174 - "datetime_parse.py"
Cohesion: 0.33
Nodes (8): _build_driver_url(), get_plan_arrange_info(), 获取计划已安排运输后的司机链接与地磅出入库关联(供查看弹窗复制简述/二维码)。, TransportSiteLinkRead, build_transport_site_link_read(), build_transport_site_link_read_from_row(), _parse_feedback_images(), Session
### Community 174 - "CrmProductBrand"
Cohesion: 0.46
Nodes (7): CrmProductBrand, apply_updates(), collect_candidates(), main(), parse_name(), Path, write_csv()
### Community 178 - "product_allowed"
Cohesion: 0.28
Nodes (11): assert_products_allowed_for_supplier(), enrich_products_with_hazard_flags(), get_supplier_hazard_flags(), product_allowed(), Any, Session, 批量回填明细行 isToxic/isExplosive(来自产品主数据,供前端切换主体剔除)。, test_dual_requires_both() (+3 more)
### Community 178 - "opportunity_export"
Cohesion: 0.48
Nodes (7): _opp_list_kwargs(), opportunity_export(), opportunity_kanban(), opportunity_list(), opportunity_mine_list(), OpportunityKanbanBody, OpportunityListBody
### Community 179 - "_ensure_subpack_slip_no"
Cohesion: 0.07
Nodes (78): archive_plan(), cancel_plan(), cancel_plan_wait_notice(), count_plans_by_contract(), create_from_contract(), create_plan(), create_plan_full(), delete_plan() (+70 more)
Cohesion: 0.17
Nodes (24): cancel_apply(), create_apply(), create_process(), delete_applies(), delete_processes(), get_apply(), get_process(), list_applies() (+16 more)
### Community 180 - "menu.py"
Cohesion: 0.36
Nodes (13): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), menu_name_exists(), Any (+5 more)
### Community 181 - "storage.py"
Cohesion: 0.40
Nodes (4): convert_heic_to_jpeg(), 文件存储工具模块 支持多种存储方式: 1. 本地存储 (local) - 默认 2. 七牛云存储 (qiniu) - 推荐生产环境使用 3. 阿里云OSS (, 将 HEIC/HEIF 格式转换为 JPEG 格式, BytesIO
### Community 182 - "statistics.py"
Cohesion: 0.45
Nodes (11): _customer_base_query(), get_follow_statistics(), get_industry_statistics(), get_level_statistics(), get_overview_statistics(), get_owner_statistics(), get_source_statistics(), get_trend_statistics() (+3 more)
### Community 183 - "MinIOStorage"
Cohesion: 0.24
Nodes (5): MinIOStorage, Any, 从 MINIO_BASE_URL 解析公网 endpoint;未配置或与内网相同时复用 self.client。, MinIO 预签名下载 URL,携带原始文件名。, MinIO 预签名内联预览 URL(PDF 等 iframe 场景)。
### Community 187 - "allocate_next_biz_no"
Cohesion: 0.11
Nodes (27): generate_uuid(), get_current_time(), parse_datetime(), datetime, allocate_next_biz_no(), _format_biz_no(), _prefix_for(), datetime (+19 more)
Cohesion: 0.22
Nodes (13): create_oss(), get_oss_by_id(), get_oss_by_url(), Session, 按主键 id 查询附件(兼容旧 CRM 雪花 oss_id 迁入后的记录), 将 fileUrl 或旧 CRM 数字 ossId 解析为 MinIO 相对路径。 门户新上传把相对路径写入业务字段;迁入合同附件仍存数字 ossId, resolve_storage_path(), CrmProductAlias (+5 more)
### Community 188 - "list_product_options"
Cohesion: 0.67
Nodes (3): list_product_options(), 产品下拉 options:keyword 仅按产品名称模糊匹配,不匹配产品编号。, test_list_product_options_keyword_only_filters_product_name()
### Community 200 - "register_local_callback"
Cohesion: 0.07
Nodes (39): ApiRequestLogCRUD, Session, list_ethnics(), Any, Session, 民族码表 CRUD(全局 sys_ethnic), _row_to_dict(), SoftDeleteModel (+31 more)
### Community 206 - "crm_quote_pdf.py"
Cohesion: 0.36
@@ -692,7 +774,7 @@ Cohesion: 0.18
Nodes (10): 1. 创建虚拟环境, 2. 安装依赖, 3. 配置环境变量, 4. 启动服务, API 路由分组, shanxia2.0 后端骨架(FastAPI), 开发规范, 快速开始 (+2 more)
### Community 220 - "api_crypto_middleware.py"
Cohesion: 0.14
Cohesion: 0.13
Nodes (23): ApiCryptoMiddleware, _claims_from_auth(), _coerce_post_method_override_to_get(), _get_redis_client(), _is_crypto_api(), _json_error_response(), _mark_nonce_once(), _nonce_key() (+15 more)
### Community 237 - "order_status_compat.py"
@@ -710,22 +792,22 @@ Nodes (6): eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时
## Knowledge Gaps
- **30 isolated node(s):** `Config`, `Config`, `Config`, `Config`, `Config` (+25 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **17 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **19 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Settings` connect `Community 72` to `backfill_crm_contract_attachment_urls.py`, `_ensure_subpack_slip_no`, `Community 35`, `crm_supplier_hazard.py`, `Community 5`, `price_letter_detail`, `Community 7`, `Community 73`, `Community 42`, `Community 44`, `Community 52`, `Any`, `Community 59`, `Community 30`?**
_High betweenness centrality (0.109) - this node is a cross-community bridge._
- **Why does `BaseModel` connect `Community 12` to `Community 0`, `Community 1`, `Community 3`, `LocalStorage`, `statistics.py`, `Community 11`, `Community 14`, `Community 15`, `Community 16`, `minio_url.py`, `Community 18`, `__init__.py`, `Community 24`, `Community 25`, `PlCarrier`, `Community 27`, `Community 26`, `Community 28`, `register_local_callback`, `Community 33`, `Community 34`, `Community 36`, `Community 43`, `Community 45`, `datetime_parse.py`, `Community 48`, `_ensure_subpack_slip_no`, `Community 51`, `Community 54`, `Community 58`, `Community 60`, `Community 63`, `Community 64`, `Community 65`, `Community 66`, `Community 67`, `Community 68`, `Community 71`, `Community 78`, `Community 86`, `Community 111`, `storage.py`, `site.py`, `Community 119`, `Community 127`?**
_High betweenness centrality (0.103) - this node is a cross-community bridge._
- **Why does `generate_uuid()` connect `allocate_next_biz_no` to `Community 0`, `plan.py`, `Community 2`, `Community 4`, `Community 6`, `Community 134`, `Community 8`, `Community 136`, `post.py`, `Community 11`, `Community 7`, `Community 13`, `SysEthnic`, `Community 15`, `Community 16`, `Community 19`, `Community 21`, `Community 25`, `PlCarrier`, `Community 27`, `Community 28`, `Community 26`, `Community 37`, `Community 39`, `test_quote_approver_setting.py`, `Community 43`, `Community 45`, `Community 49`, `_ensure_subpack_slip_no`, `menu.py`, `Community 53`, `Community 51`, `Community 58`, `Community 61`, `Community 65`, `Community 66`, `Community 68`, `Community 70`, `Community 74`, `Community 83`, `Community 86`, `Community 87`, `pl_ocr_service.py`, `pl_vehicle_recharge_service.py`, `Community 92`, `response.py`, `Community 95`, `dept.py`, `apply_crm_create_by_scope`, `list_customers`, `Community 109`, `quote_share_log.py`, `db_models.py`, `site.py`, `Community 116`, `Community 118`, `Community 122`, `Community 125`?**
_High betweenness centrality (0.092) - this node is a cross-community bridge._
- **Why does `generate_uuid()` connect `Community 109` to `Community 0`, `plan.py`, `datetime_parse.py`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 136`, `Community 134`, `get_current_user_by_token`, `Community 11`, `PlTransport`, `Community 14`, `SysEthnic`, `dict_data.py`, `Community 15`, `__init__.py`, `Community 19`, `Community 16`, `Community 21`, `Community 25`, `response.py`, `Community 27`, `utils.py`, `Community 28`, `.to_tenant_user_dict`, `get_client_ip`, `Community 36`, `Community 38`, `Community 39`, `test_quote_approver_setting.py`, `Community 43`, `Community 44`, `Community 45`, `Community 46`, `CrmProductBrand`, `Community 48`, `Community 49`, `Community 51`, `Community 53`, `Community 58`, `allocate_next_biz_no`, `Community 61`, `Community 65`, `Community 66`, `Community 67`, `Community 68`, `Community 70`, `Community 78`, `Community 81`, `Community 83`, `Community 86`, `Community 87`, `pl_ocr_service.py`, `_invoice_info_by_customer_impl`, `Community 95`, `dept.py`, `apply_crm_create_by_scope`, `list_customers`, `apply_pl_scope`, `storage.py`, `quote_share_log.py`, `db_models.py`, `Community 116`, `Community 118`, `Community 122`, `Community 125`?**
_High betweenness centrality (0.121) - this node is a cross-community bridge._
- **Why does `Settings` connect `price_letter_detail` to `backfill_crm_contract_attachment_urls.py`, `_ensure_subpack_slip_no`, `Community 35`, `crm_supplier_hazard.py`, `Community 5`, `Community 67`, `Community 72`, `Community 73`, `Community 42`, `Community 52`, `Any`, `Community 59`, `api_crypto_middleware.py`, `Community 30`?**
_High betweenness centrality (0.107) - this node is a cross-community bridge._
- **Why does `BaseModel` connect `Community 12` to `Community 0`, `Community 1`, `Community 2`, `unsettled_plans_q_filter`, `Community 7`, `statistics.py`, `Community 11`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `__init__.py`, `Community 19`, `response.py`, `Community 24`, `Community 29`, `customer_update`, `register_local_callback`, `Community 33`, `Community 34`, `Community 43`, `Community 45`, `Community 46`, `Community 49`, `Community 50`, `opportunity_export`, `Community 51`, `_ensure_subpack_slip_no`, `Community 54`, `Community 58`, `Community 60`, `Community 62`, `Community 63`, `Community 64`, `Community 65`, `Community 66`, `Community 71`, `register_local_callback`, `Community 81`, `pl_vehicle_recharge_service.py`, `_invoice_info_by_customer_impl`, `list_customers`, `Community 106`, `Community 109`, `Community 111`, `site.py`, `Community 119`, `customer_pool.py`, `Community 127`?**
_High betweenness centrality (0.090) - this node is a cross-community bridge._
- **Are the 8 inferred relationships involving `DbUserContext` (e.g. with `InventoryRelatedData` and `AutoGenerateMonthlyResult`) actually correct?**
_`DbUserContext` has 8 INFERRED edges - model-reasoned connections that need verification._
- **What connects `API 路由包 — 山峡化工生产一体化门户`, `返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。`, `返回用户下拉选项(label=昵称,value=用户ID,附带 nickName/userNo)。 供申请人/审批人等选择场景使用,返回本租户全部有效` to the rest of the system?**
_516 weakly-connected nodes found - possible documentation gaps or missing edges._
_529 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.0957983193277311 - nodes in this community are weakly interconnected._
- **Should `Community 2` be split into smaller, more focused modules?**
_Cohesion score 0.14304993252361672 - nodes in this community are weakly interconnected._
_Cohesion score 0.07804878048780488 - nodes in this community are weakly interconnected._
- **Should `Community 3` be split into smaller, more focused modules?**
_Cohesion score 0.09153153153153153 - nodes in this community are weakly interconnected._
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "label": "public_transport.py", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_resolve_unit_label", "label": "_resolve_unit_label()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_get_transport_by_token", "label": "_get_transport_by_token()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L54"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_parse_feedback_images", "label": "_parse_feedback_images()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L68"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_format_plan_date", "label": "_format_plan_date()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L80"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_resolve_other_personnel", "label": "_resolve_other_personnel()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L90"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "publictransportpersonnelread", "label": "PublicTransportPersonnelRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_build_public_page", "label": "_build_public_page()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L119"}, {"id": "publictransportpageread", "label": "PublicTransportPageRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_get_public_transport", "label": "get_public_transport()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L277"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_save_public_feedback", "label": "save_public_feedback()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L284"}, {"id": "publictransportfeedback", "label": "PublicTransportFeedback", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_format_file_size", "label": "_format_file_size()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L340"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_upload_public_attachment", "label": "upload_public_attachment()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L349"}, {"id": "uploadfile", "label": "UploadFile", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "target": "json", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_transport.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "target": "os", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_transport.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "target": "datetime", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_transport.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_apiLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "label": "io_order.py", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_brandoption", "label": "BrandOption", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L11"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_brandqtyitem", "label": "BrandQtyItem", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L17"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_ioorderitemread", "label": "IoOrderItemRead", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L24"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_ioorderitempatch", "label": "IoOrderItemPatch", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L51"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_ioorderpatch", "label": "IoOrderPatch", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L58"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_ioorderread", "label": "IoOrderRead", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L67"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_ioorderlistresponse", "label": "IoOrderListResponse", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L108"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_publicioorderitemfeedback", "label": "PublicIoOrderItemFeedback", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L113"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_publicioorderfeedback", "label": "PublicIoOrderFeedback", "file_type": "code", "source_file": "app/schemas/pl/io_order.py", "source_location": "L120"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_rationale_1", "label": "\u5165\u5e93\u5355 / \u51fa\u5e93\u5355 Pydantic schemas", "file_type": "rationale", "source_file": "app/schemas/pl/io_order.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "datetime", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "decimal", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "typing", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "pydantic", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_brandoption", "relation": "contains", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_brandoption", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_brandqtyitem", "relation": "contains", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L17", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_brandqtyitem", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "app/schemas/pl/io_order.py", "source_location": "L17", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_io_order_ioorderitemread", "relation": "containsLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_py", "label": "test_pl_transport_arrange_optional_driver.py", "file_type": "code", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_transport_arrange_schema_allows_missing_driver", "label": "test_transport_arrange_schema_allows_missing_driver()", "file_type": "code", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L10"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_apply_transport_arrange_fields_without_driver", "label": "test_apply_transport_arrange_fields_without_driver()", "file_type": "code", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L16"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_py", "target": "types", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_py", "target": "app_api_pl_transport", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_py", "target": "app_schemas_pl_transport", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_transport_arrange_schema_allows_missing_driver", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_apply_transport_arrange_fields_without_driver", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L16", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_transport_arrange_schema_allows_missing_driver", "callee": "model_validate", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L11", "receiver": "TransportArrange"}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_apply_transport_arrange_fields_without_driver", "callee": "SimpleNamespace", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L17", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_apply_transport_arrange_fields_without_driver", "callee": "model_validate", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L37", "receiver": "TransportArrange"}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_apply_transport_arrange_fields_without_driver", "callee": "_apply_transport_arrange_fields", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_transport_arrange_optional_driver.py", "source_location": "L41", "receiver": null}], "callable_nids": ["users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_apply_transport_arrange_fields_without_driver", "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_transport_arrange_optional_driver_test_transport_arrange_schema_allows_missing_driver"]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_py", "label": "pl_plan_service.py", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_determine_plan_type", "label": "determine_plan_type()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L46"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_is_ton_product_unit", "label": "is_ton_product_unit()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L54"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_product_quantity", "label": "_product_quantity()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L61"}, {"id": "planproductcreate", "label": "PlanProductCreate", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "decimal", "label": "Decimal", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_product_create_actual_qty", "label": "_product_create_actual_qty()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L71"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_plan_product_actual_qty", "label": "_plan_product_actual_qty()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L77"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_sum_product_actual_quantities", "label": "sum_product_actual_quantities()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L83"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_sum_plan_product_actual_quantities", "label": "sum_plan_product_actual_quantities()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L87"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_estimate_qty_fields", "label": "_estimate_qty_fields()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L91"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_build_plan_product", "label": "build_plan_product()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L102"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_apply_vehicle_snapshot_to_plan_transport", "label": "_apply_vehicle_snapshot_to_plan_transport()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L152"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "plvehicle", "label": "PlVehicle", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_resolve_driver", "label": "_resolve_driver()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L170"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_calc_freight_amount", "label": "_calc_freight_amount()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L216"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_fetch_hazard_flags_map", "label": "fetch_hazard_flags_map()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L237"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_resolve_hazard_flags_from_crm", "label": "resolve_hazard_flagLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "label": "public_io_order.py", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_models", "label": "_models()", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L31"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_get_by_token", "label": "_get_by_token()", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L37"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_io_order.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_resolve_io_order_link_flags", "label": "_resolve_io_order_link_flags()", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L55"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_io_order.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_build_page", "label": "_build_page()", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L62"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_format_file_size", "label": "_format_file_size()", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L74"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_make_handlers", "label": "_make_handlers()", "file_type": "code", "source_file": "app/api/pl/public_io_order.py", "source_location": "L82"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_rationale_1", "label": "\u8fd0\u8f93\u8ba1\u5212 \u00b7 \u5165\u5e93/\u51fa\u5e93\u5355\u73b0\u573a\u514d\u767b\u5f55\u516c\u5171 API", "file_type": "rationale", "source_file": "app/api/pl/public_io_order.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_rationale_56", "label": "\u8fd4\u56de (\u4f5c\u5e9f, \u5f52\u6863)\u3002\u73b0\u573a\u94fe\u63a5\u5b9e\u9645\u8d70\u5165\u5e93/\u51fa\u5e93\u5355\u516c\u5171\u9875\u3002", "file_type": "rationale", "source_file": "app/api/pl/public_io_order.py", "source_location": "L56"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "os", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "decimal", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "typing", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "fastapi", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "sqlalchemy_orm", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "app_core_attachment_biz", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "app_core_config", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "app_core_database", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_io_order.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_io_order_py", "target": "app_core_responsLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_py", "label": "pl_plan_service.py", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_determine_plan_type", "label": "determine_plan_type()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L44"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_is_ton_product_unit", "label": "is_ton_product_unit()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L52"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_product_quantity", "label": "_product_quantity()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L59"}, {"id": "planproductcreate", "label": "PlanProductCreate", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "decimal", "label": "Decimal", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_product_create_actual_qty", "label": "_product_create_actual_qty()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L69"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_plan_product_actual_qty", "label": "_plan_product_actual_qty()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L75"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_sum_product_actual_quantities", "label": "sum_product_actual_quantities()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L81"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_sum_plan_product_actual_quantities", "label": "sum_plan_product_actual_quantities()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L85"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_estimate_qty_fields", "label": "_estimate_qty_fields()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L89"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_build_plan_product", "label": "build_plan_product()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L100"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_apply_vehicle_snapshot_to_plan_transport", "label": "_apply_vehicle_snapshot_to_plan_transport()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L150"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "plvehicle", "label": "PlVehicle", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_plan_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_resolve_driver", "label": "_resolve_driver()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L168"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_calc_freight_amount", "label": "_calc_freight_amount()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L214"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_fetch_hazard_flags_map", "label": "fetch_hazard_flags_map()", "file_type": "code", "source_file": "app/services/pl_plan_service.py", "source_location": "L235"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_plan_service_resolve_hazard_flags_from_crm", "label": "resolve_hazard_flagLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_py", "label": "pl_models.py", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plcarrier", "label": "PlCarrier", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L28"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plvehicle", "label": "PlVehicle", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L57"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plpersonnel", "label": "PlPersonnel", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L84"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pltransportaddress", "label": "PlTransportAddress", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L119"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plcert", "label": "PlCert", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L143"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pldriver", "label": "PlDriver", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L169"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plvehiclepersonnel", "label": "PlVehiclePersonnel", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L195"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plvehicledriver", "label": "PlVehicleDriver", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L216"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plplan", "label": "PlPlan", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L241"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L348"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plplanproductbrandqty", "label": "PlPlanProductBrandQty", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L407"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plplanchange", "label": "PlPlanChange", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L429"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pltransport", "label": "PlTransport", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L456"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pltransportproductfeedback", "label": "PlTransportProductFeedback", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L518"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pltransportproductbrandqty", "label": "PlTransportProductBrandQty", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L539"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pltransportdblink", "label": "PlTransportDbLink", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L562"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plplantransport", "label": "PlPlanTransport", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L585"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_pltransportsitelink", "label": "PlTransportSiteLink", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L604"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plinboundorder", "label": "PlInboundOrder", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L637"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plinboundorderitem", "label": "PlInboundOrderItem", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L667"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_plinboundorderitembrandqty", "label": "PlInboundOrderItemBrandQty", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L693"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_models_pl_models_ploutboundorder", "label": "PlOutboundOrder", "file_type": "code", "source_file": "app/models/pl_models.py", "source_location": "L716"}, {"id": "users_wuzilong_work_00cLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_py", "label": "plan.py", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_resolve_list_product_name", "label": "_resolve_list_product_name()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L97"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_resolve_create_date", "label": "_resolve_create_date()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L113"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_generate_plan_no", "label": "_generate_plan_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L117"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_format_subpack_slip_no", "label": "_format_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L149"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_normalize_subpack_slip_no", "label": "_normalize_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L153"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_subpack_slip_no_seq", "label": "_subpack_slip_no_seq()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L178"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_ensure_subpack_slip_no", "label": "_ensure_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L186"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_determine_plan_type", "label": "_determine_plan_type()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L218"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_get_plan_type_label", "label": "_get_plan_type_label()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L223"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_generate_notify_message", "label": "_generate_notify_message()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L232"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_list_plans", "label": "list_plans()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L253"}, {"id": "dbusercontext", "label": "DbUserContext", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planlistresponse", "label": "PlanListResponse", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_count_plans_by_contract", "label": "count_plans_by_contract()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L408"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_create_plan", "label": "create_plan()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L436"}, {"id": "plancreate", "label": "PlanCreate", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planread", "label": "PlanRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_create_plan_full", "label": "create_plan_full()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L520"}, {"id": "plancreatefull", "label": "PlanCreateFull", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planwithproducts", "label": "PlanWithProducts", "file_type": "code", "source_file": "", Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_py", "label": "transport.py", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportbase", "label": "TransportBase", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L18"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportcreate", "label": "TransportCreate", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L42"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportarrange", "label": "TransportArrange", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportinventorylinkread", "label": "TransportInventoryLinkRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L75"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportsitelinkread", "label": "TransportSiteLinkRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L85"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportupdate", "label": "TransportUpdate", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L99"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportdriverproductfeedbackread", "label": "TransportDriverProductFeedbackRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L123"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportread", "label": "TransportRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L139"}, {"id": "planresourcesnapshotmixin", "label": "PlanResourceSnapshotMixin", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportioorderbrief", "label": "TransportIoOrderBrief", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L161"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportarrangeresult", "label": "TransportArrangeResult", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L171"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_planarrangeinforead", "label": "PlanArrangeInfoRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L182"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportwithplans", "label": "TransportWithPlans", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L193"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportfeedback", "label": "TransportFeedback", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L202"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportproductfeedbackitem", "label": "PublicTransportProductFeedbackItem", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L211"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportfeedback", "label": "PublicTransportFeedback", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L218"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportplanproductread", "label": "PublicTransportPlanProductRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L226"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportpersonnelread", "label": "PublicTransportPersonnelRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L244"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportpageread", "label": "PublicTransportPageRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L251"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportsitepageread", "label": "PublicTransportSitePageRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L281"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_approvalsubmit", "label": "ApLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_py", "label": "public_site.py", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_parse_feedback_images", "label": "_parse_feedback_images()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L33"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_get_site_link_by_token", "label": "_get_site_link_by_token()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L45"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "pltransportsitelink", "label": "PlTransportSiteLink", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_resolve_plan_voided", "label": "_resolve_plan_voided()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L59"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_resolve_unit_label", "label": "_resolve_unit_label()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L64"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_resolve_plan_product", "label": "_resolve_plan_product()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L71"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_build_site_product_read", "label": "_build_site_product_read()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L84"}, {"id": "publictransportplanproductread", "label": "PublicTransportPlanProductRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_build_public_page", "label": "_build_public_page()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L143"}, {"id": "publictransportsitepageread", "label": "PublicTransportSitePageRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_get_public_site", "label": "get_public_site()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L184"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_save_public_site_feedback", "label": "save_public_site_feedback()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L191"}, {"id": "publicinventoryfeedback", "label": "PublicInventoryFeedback", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_format_file_size", "label": "_format_file_size()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L212"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_upload_public_site_attachment", "label": "upload_public_site_attachment()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L221"}, {"id": "uploadfile", "label": "UploadFile", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_rationale_1", "label": "\u8fd0\u8f93\u8ba1\u5212 \u00b7 \u5de5\u5382\u73b0\u573a\u4eba\u5458\u514d\u767b\u5f55\u516c\u5171 API\uff08pl_transport_site_link\uff09", "file_type": "rationale", "source_file": "app/api/pl/public_site.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_py", "target": "json", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_site.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_py", "target": "os", "relation": "imports", "context": "import", "conLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_py", "label": "plan.py", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductbase", "label": "PlanProductBase", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L16"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcreate", "label": "PlanProductCreate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L49"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductupdate", "label": "PlanProductUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L53"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planarchivebrandqtyitem", "label": "PlanArchiveBrandQtyItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L75"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductread", "label": "PlanProductRead", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L82"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planbase", "label": "PlanBase", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L99"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plancreate", "label": "PlanCreate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L149"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plantransportcreateblock", "label": "PlanTransportCreateBlock", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L158"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planupdate", "label": "PlanUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L172"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_hazardcertreadybody", "label": "HazardCertReadyBody", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L215"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planread", "label": "PlanRead", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L220"}, {"id": "planresourcesnapshotmixin", "label": "PlanResourceSnapshotMixin", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planwithproducts", "label": "PlanWithProducts", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L248"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planinboundsliptemplatesave", "label": "PlanInboundSlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L252"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plandeliverysliptemplatesave", "label": "PlanDeliverySlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L257"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plansubpacksliptemplatesave", "label": "PlanSubpackSlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L264"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_createfromcontractrequest", "label": "CreateFromContractRequest", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L276"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plancreatefull", "label": "PlanCreateFull", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L287"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planlistquery", "label": "PlanListQuery", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L298"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcertitem", "label": "PlanProductCertItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L315"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcertsupdate", "label": "PlanProductCertsUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L323"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planarchiveproductitem", "label": "PlanArchiveProductItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L328"}, {"id": "users_wuzilong_woLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_py", "label": "transport.py", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_transport_to_read", "label": "_transport_to_read()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L70"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "transportread", "label": "TransportRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_generate_transport_no", "label": "_generate_transport_no()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L89"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_resolve_driver_info", "label": "_resolve_driver_info()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L113"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_get_vehicle_info", "label": "_get_vehicle_info()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L151"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_assert_vehicle_carrier_eligible", "label": "_assert_vehicle_carrier_eligible()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L201"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_ensure_driver_access_token", "label": "_ensure_driver_access_token()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L236"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_rotate_driver_access_token", "label": "_rotate_driver_access_token()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L244"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_is_rearrange", "label": "_is_rearrange()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L250"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_transport_has_db_links", "label": "_transport_has_db_links()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L261"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_apply_plan_logistics_from_payload", "label": "_apply_plan_logistics_from_payload()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L274"}, {"id": "transportarrange", "label": "TransportArrange", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_resolve_transport_endpoints", "label": "_resolve_transport_endpoints()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L303"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_apply_transport_arrange_fields", "label": "_apply_transport_arrange_fields()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L318"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_build_driver_url", "label": "_build_driver_url()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L352"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_build_arrange_result", "label": "_build_arrange_result()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L357"}, {"id": "transportsitelinkread", "label": "TransportSiteLinkRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "transportinventorylinkread", "label": "TransportInventoryLinkRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "transportioorderbrief", "label": "TransportIoOrderBrief", "file_type": "code", "source_file": "", "source_location": "", "origiLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_py", "label": "pl_io_order_service.py", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_ioordercreateresult", "label": "IoOrderCreateResult", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L45"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_build_io_order_site_url", "label": "build_io_order_site_url()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L53"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_normalize_plan_date", "label": "_normalize_plan_date()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L59"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_next_order_no", "label": "_next_order_no()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L70"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_dibang_qty_by_plan_product", "label": "_dibang_qty_by_plan_product()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L88"}, {"id": "decimal", "label": "Decimal", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_create_io_order_for_transport", "label": "create_io_order_for_transport()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L120"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_apply_dibang_prefill_to_order", "label": "apply_dibang_prefill_to_order()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L202"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_void_io_orders_for_plan", "label": "void_io_orders_for_plan()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L247"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_get_active_io_order_for_plan", "label": "get_active_io_order_for_plan()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L271"}, {"id": "orderheader", "label": "OrderHeader", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_io_order_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_parse_feedback_images", "label": "parse_feedback_images()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L301"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_dump_feedback_images", "label": "dump_feedback_images()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L313"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_io_item_brand_qty_model", "label": "_io_item_brand_qty_model()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L320"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_io_order_service_update_io_order_items_qty_and_brand", "label": "update_io_order_items_qty_and_brand()", "file_type": "code", "source_file": "app/services/pl_io_order_service.py", "source_location": "L326"}, {"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_py", "label": "plan.py", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductbase", "label": "PlanProductBase", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L16"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcreate", "label": "PlanProductCreate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L49"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductupdate", "label": "PlanProductUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L53"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planarchivebrandqtyitem", "label": "PlanArchiveBrandQtyItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L75"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductread", "label": "PlanProductRead", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L82"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planbase", "label": "PlanBase", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L99"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plancreate", "label": "PlanCreate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L149"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plantransportcreateblock", "label": "PlanTransportCreateBlock", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L158"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planupdate", "label": "PlanUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L172"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_hazardcertreadybody", "label": "HazardCertReadyBody", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L215"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planread", "label": "PlanRead", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L220"}, {"id": "planresourcesnapshotmixin", "label": "PlanResourceSnapshotMixin", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planwithproducts", "label": "PlanWithProducts", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L248"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planinboundsliptemplatesave", "label": "PlanInboundSlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L252"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plandeliverysliptemplatesave", "label": "PlanDeliverySlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L257"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plansubpacksliptemplatesave", "label": "PlanSubpackSlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L264"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_createfromcontractrequest", "label": "CreateFromContractRequest", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L276"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plancreatefull", "label": "PlanCreateFull", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L287"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planlistquery", "label": "PlanListQuery", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L298"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcertitem", "label": "PlanProductCertItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L313"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcertsupdate", "label": "PlanProductCertsUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L321"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planarchiveproductitem", "label": "PlanArchiveProductItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L326"}, {"id": "users_wuzilong_woLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_py", "label": "plan.py", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_resolve_list_product_name", "label": "_resolve_list_product_name()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L97"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_resolve_create_date", "label": "_resolve_create_date()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L113"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_generate_plan_no", "label": "_generate_plan_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L117"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_format_subpack_slip_no", "label": "_format_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L149"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_normalize_subpack_slip_no", "label": "_normalize_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L153"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_subpack_slip_no_seq", "label": "_subpack_slip_no_seq()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L178"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_ensure_subpack_slip_no", "label": "_ensure_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L186"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_determine_plan_type", "label": "_determine_plan_type()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L218"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_get_plan_type_label", "label": "_get_plan_type_label()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L223"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_generate_notify_message", "label": "_generate_notify_message()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L232"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_plan_product_name_exists", "label": "_plan_product_name_exists()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L252"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_plan_plate_match", "label": "_plan_plate_match()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L266"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_list_plans", "label": "list_plans()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L276"}, {"id": "dbusercontext", "label": "DbUserContext", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planlistresponse", "label": "PlanListResponse", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_count_plans_by_contract", "label": "count_plans_by_contract()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L432"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_create_plan", "label": "create_plan()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L460"}, {"id": "plancreate", "label": "PlanCreate", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planread", "label": "PlanRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_crLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_py", "label": "plan.py", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_resolve_list_product_name", "label": "_resolve_list_product_name()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L99"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_resolve_create_date", "label": "_resolve_create_date()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L115"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_generate_plan_no", "label": "_generate_plan_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L119"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_format_subpack_slip_no", "label": "_format_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L151"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_normalize_subpack_slip_no", "label": "_normalize_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L155"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_subpack_slip_no_seq", "label": "_subpack_slip_no_seq()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L180"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_ensure_subpack_slip_no", "label": "_ensure_subpack_slip_no()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L188"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_determine_plan_type", "label": "_determine_plan_type()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L220"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_get_plan_type_label", "label": "_get_plan_type_label()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L225"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_generate_notify_message", "label": "_generate_notify_message()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L234"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_plan_product_name_exists", "label": "_plan_product_name_exists()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L254"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_plan_plate_match", "label": "_plan_plate_match()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L268"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_list_plans", "label": "list_plans()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L278"}, {"id": "dbusercontext", "label": "DbUserContext", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planlistresponse", "label": "PlanListResponse", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_count_plans_by_contract", "label": "count_plans_by_contract()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L450"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_create_plan", "label": "create_plan()", "file_type": "code", "source_file": "app/api/pl/plan.py", "source_location": "L478"}, {"id": "plancreate", "label": "PlanCreate", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "planread", "label": "PlanRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/plan.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_plan_crLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "label": "product_helpers.py", "file_type": "code", "source_file": "app/services/db/product_helpers.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_productsnapshot", "label": "ProductSnapshot", "file_type": "code", "source_file": "app/services/db/product_helpers.py", "source_location": "L13"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_resolve_crm_product", "label": "resolve_crm_product()", "file_type": "code", "source_file": "app/services/db/product_helpers.py", "source_location": "L19"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/db/product_helpers.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_apply_product_snapshot_to_plan", "label": "apply_product_snapshot_to_plan()", "file_type": "code", "source_file": "app/services/db/product_helpers.py", "source_location": "L61"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_apply_product_snapshot_to_inventory", "label": "apply_product_snapshot_to_inventory()", "file_type": "code", "source_file": "app/services/db/product_helpers.py", "source_location": "L67"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_apply_product_snapshot_to_weighing", "label": "apply_product_snapshot_to_weighing()", "file_type": "code", "source_file": "app/services/db/product_helpers.py", "source_location": "L73"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_rationale_1", "label": "\u5730\u78c5\u6a21\u5757 \u2014 CRM \u4ea7\u54c1\u89e3\u6790\u4e0e\u5feb\u7167\u5199\u5165\u3002", "file_type": "rationale", "source_file": "app/services/db/product_helpers.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_rationale_26", "label": "\u6821\u9a8c CRM \u4ea7\u54c1\u5e76\u8fd4\u56de\u540d\u79f0/\u89c4\u683c\u5feb\u7167\u3002\u65b0\u5efa\u5355\u636e product_id \u5fc5\u586b\u3002 require_on_shelf=False \u7528\u4e8e\u8fd0\u8f93\u8ba1\u5212\u8054\u52a8\u5730\u78c5\u7b49\u5386", "file_type": "rationale", "source_file": "app/services/db/product_helpers.py", "source_location": "L26"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "target": "dataclasses", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "target": "fastapi", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "target": "sqlalchemy_orm", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "target": "app_crud_crm_product", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_productsnapshot", "relation": "contains", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_resolve_crm_product", "relation": "contains", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_resolve_crm_product", "target": "session", "relation": "references", "context": "parameter_type", "confidence": "EXTRACTED", "source_file": "app/services/db/product_helpers.py", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_resolve_crm_product", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_db_product_helpers_productsnapshot", "relation": "references", "context": "return_type", "confidence": "EXTRACTED", "source_fLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "label": "test_pl_plan_cert_list_filters.py", "file_type": "code", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_compile", "label": "_compile()", "file_type": "code", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L12"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_test_plan_has_hazard_product_exists_joins_crm_flags", "label": "test_plan_has_hazard_product_exists_joins_crm_flags()", "file_type": "code", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L18"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_test_plan_has_incomplete_hazard_cert_exists_checks_required_urls", "label": "test_plan_has_incomplete_hazard_cert_exists_checks_required_urls()", "file_type": "code", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L29"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_rationale_1", "label": "\u5371\u5316\u54c1\u8bc1\u4e0a\u4f20\u5217\u8868\u7b5b\u9009\uff1aEXISTS \u5b50\u67e5\u8be2\u5e94\u8986\u76d6 CRM \u5371\u5316\u6807\u8bc6\u4e0e\u8bc1\u4e66\u7f3a\u53e3\u3002", "file_type": "rationale", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "target": "sqlalchemy_dialects", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "target": "app_services_pl_plan_service", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_compile", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_test_plan_has_hazard_product_exists_joins_crm_flags", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L18", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_test_plan_has_incomplete_hazard_cert_exists_checks_required_urls", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L29", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_test_plan_has_hazard_product_exists_joins_crm_flags", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_compile", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L20", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_test_plan_has_incomplete_hazard_cert_exists_checks_required_urls", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_compile", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L31", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_rationale_1", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_cert_list_filters.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_compile", "callee": "lower", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_plan_cert_list_filters.py", "source_location": "L13", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_cert_list_filters_compile", "callLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_py", "label": "contract.py", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_ensure_contract_in_scope", "label": "_ensure_contract_in_scope()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L48"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "crmcontract", "label": "CrmContract", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_get_contract_row_in_scope", "label": "_get_contract_row_in_scope()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L52"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L69"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_decimal_value", "label": "_decimal_value()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L75"}, {"id": "any", "label": "Any", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "decimal", "label": "Decimal", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_parse_optional_date", "label": "_parse_optional_date()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L83"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_parse_optional_datetime", "label": "_parse_optional_datetime()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L101"}, {"id": "datetime", "label": "datetime", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_get_field", "label": "_get_field()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L117"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_resolve_user_display_name", "label": "_resolve_user_display_name()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L124"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_is_blank", "label": "_is_blank()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L134"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_first_non_blank", "label": "_first_non_blank()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L138"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_get_default_invoice_info", "label": "_get_default_invoice_info()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L146"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_build_customer_address", "label": "_build_customer_address()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L156"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L168"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_contract_row_to_dict", "label": "contract_row_to_dict()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L245"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_build_contract_filters", "label": "_build_contract_filters()", "file_type": "code", "source_file": "app/crud/crm/contract.py", "source_location": "L249"}, {"id": "query", "label": "Query", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/contract.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_contract_list_contracts", "label": "list_contractsLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "label": "test_pl_freight_unsettled_q_filter.py", "file_type": "code", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "label": "test_unsettled_plans_q_filter_includes_carrier_and_plate()", "file_type": "code", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_rationale_1", "label": "\u672a\u7ed3\u7b97\u8ba1\u5212\u7b80\u6613\u641c\u7d22\uff1aq \u5e94\u8986\u76d6\u8ba1\u5212\u7f16\u53f7/\u5ba2\u6237/\u8f66\u724c/\u627f\u8fd0\u5546\u540d\u79f0\u3002", "file_type": "rationale", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "target": "sqlalchemy_dialects", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "target": "app_services_pl_freight_settlement_service", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_rationale_1", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "unsettled_plans_q_filter", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L10", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "lower", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L11", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "compile", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L12", "receiver": "clause"}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "dialect", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L12", "receiver": "mysql"}], "callable_nids": ["users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate"]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_py", "label": "test_crm_contract_reedit_to_draft.py", "file_type": "code", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_editable_statuses", "label": "test_editable_statuses()", "file_type": "code", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_allows_editable", "label": "test_assert_allows_editable()", "file_type": "code", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L16"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_rejects_non_editable", "label": "test_assert_rejects_non_editable()", "file_type": "code", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L21"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_py", "target": "pytest", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_py", "target": "app_crud_crm_contract", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_editable_statuses", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_allows_editable", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L16", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_rejects_non_editable", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_crm_contract_reedit_to_draft.py", "source_location": "L21", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_editable_statuses", "callee": "frozenset", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_contract_reedit_to_draft.py", "source_location": "L10", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_allows_editable", "callee": "assert_contract_editable_for_update", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_contract_reedit_to_draft.py", "source_location": "L18", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_rejects_non_editable", "callee": "raises", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_contract_reedit_to_draft.py", "source_location": "L23", "receiver": "pytest"}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_rejects_non_editable", "callee": "ValueError", "is_member_call": false, "indirect": true, "context": "argument", "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_contract_reedit_to_draft.py", "source_location": "L23"}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_rejects_non_editable", "callee": "assert_contract_editable_for_update", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_contract_reedit_to_draft.py", "source_location": "L24", "receiver": null}], "callable_nids": ["users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_allows_editable", "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_assert_rejects_non_editable", "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_contract_reedit_to_draft_test_editable_statuses"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_py", "label": "test_crm_product_options_keyword.py", "file_type": "code", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name", "label": "test_list_product_options_keyword_only_filters_product_name()", "file_type": "code", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_rationale_1", "label": "\u4ea7\u54c1\u4e0b\u62c9 options\uff1akeyword \u4ec5\u6309\u4ea7\u54c1\u540d\u79f0\u6a21\u7cca\u5339\u914d\uff0c\u4e0d\u5339\u914d\u4ea7\u54c1\u7f16\u53f7\u3002", "file_type": "rationale", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_py", "target": "unittest_mock", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_py", "target": "app_crud_crm_product", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_rationale_1", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "tests/test_crm_product_options_keyword.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name", "callee": "MagicMock", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_product_options_keyword.py", "source_location": "L10", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name", "callee": "MagicMock", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_product_options_keyword.py", "source_location": "L11", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name", "callee": "list_product_options", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_product_options_keyword.py", "source_location": "L18", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name", "callee": "join", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_crm_product_options_keyword.py", "source_location": "L21", "receiver": null}], "callable_nids": ["users_wuzilong_work_00code_shanxia2_0_backend_tests_test_crm_product_options_keyword_test_list_product_options_keyword_only_filters_product_name"]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "label": "test_pl_freight_unsettled_q_filter.py", "file_type": "code", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "label": "test_unsettled_plans_q_filter_includes_carrier_and_plate()", "file_type": "code", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_rationale_1", "label": "\u672a\u7ed3\u7b97\u8ba1\u5212\u7b80\u6613\u641c\u7d22\uff1aq \u5e94\u8986\u76d6\u8ba1\u5212\u7f16\u53f7/\u5ba2\u6237/\u8f66\u724c/\u627f\u8fd0\u5546\u540d\u79f0\u3002", "file_type": "rationale", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "target": "sqlalchemy_dialects", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "target": "app_services_pl_freight_settlement_service", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_rationale_1", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "unsettled_plans_q_filter", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L10", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "lower", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L11", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "compile", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L12", "receiver": "clause"}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate", "callee": "dialect", "is_member_call": true, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_freight_unsettled_q_filter.py", "source_location": "L12", "receiver": "mysql"}], "callable_nids": ["users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_freight_unsettled_q_filter_test_unsettled_plans_q_filter_includes_carrier_and_plate"]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_py", "label": "pl_freight_settlement_service.py", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_resolve_user_display_name", "label": "_resolve_user_display_name()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L44"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_freight_settlement_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_occupied_transport_ids_subquery", "label": "_occupied_transport_ids_subquery()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L54"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_get_settlement_row", "label": "get_settlement_row()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L71"}, {"id": "plfreightsettlement", "label": "PlFreightSettlement", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_freight_settlement_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_get_settlement_by_transport_id", "label": "get_settlement_by_transport_id()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L95"}, {"id": "any", "label": "Any", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_freight_settlement_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_unsettled_plans_q_filter", "label": "unsettled_plans_q_filter()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L135"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_list_unsettled_plans", "label": "list_unsettled_plans()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L147"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_resolve_transports_for_create", "label": "_resolve_transports_for_create()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L222"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_freight_settlement_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_create_settlement", "label": "create_settlement()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L272"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_recalc_settlement_total_freight_from_links", "label": "_recalc_settlement_total_freight_from_links()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L316"}, {"id": "datetime", "label": "datetime", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_freight_settlement_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_sync_draft_settlement_freight_for_transport", "label": "sync_draft_settlement_freight_for_transport()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L349"}, {"id": "decimal", "label": "Decimal", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_freight_settlement_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_refresh_draft_settlement_freight", "label": "refresh_draft_settlement_freight()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L396"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_freight_settlement_service_delete_draft_settlement", "label": "delete_draft_settlement()", "file_type": "code", "source_file": "app/services/pl_freight_settlement_service.py", "source_location": "L447"}, {"id": "users_wuzilongLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_py", "label": "pl_dibang_bridge_service.py", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_dibanginventorylinkresult", "label": "DibangInventoryLinkResult", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L27"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_resolve_partner_company", "label": "resolve_partner_company()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L36"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_normalize_to_date", "label": "_normalize_to_date()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L49"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "datetime", "label": "datetime", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_normalize_plan_date", "label": "_normalize_plan_date()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L61"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_resolve_dibang_date", "label": "_resolve_dibang_date()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L73"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_month_range", "label": "_month_range()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L84"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_plan_type_to_business_type", "label": "_plan_type_to_business_type()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L91"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_product_quantity", "label": "_product_quantity()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L99"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_apply_plan_quantity_delta", "label": "_apply_plan_quantity_delta()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L106"}, {"id": "dbpurchaseplan", "label": "DbPurchasePlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_resolve_link_contributed_qty", "label": "_resolve_link_contributed_qty()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L117"}, {"id": "pltransportdblink", "label": "PlTransportDbLink", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "dbinboundoutbound", "label": "DbInboundOutbound", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_subtract_plan_contribution", "label": "_subtract_plan_contribution()", "file_type": "code", "source_file": "app/services/pl_dibang_bridge_service.py", "source_location": "L128"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/services/pl_dibang_bridge_service.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_services_pl_dibang_bridge_service_generate_batch_no", "label": "_generate_batch_no()", "file_typLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_py", "label": "product.py", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L32"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_category_row_to_dict", "label": "_category_row_to_dict()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L42"}, {"id": "crmproductcategory", "label": "CrmProductCategory", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/product.py"}, {"id": "any", "label": "Any", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/product.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_list_categories", "label": "list_categories()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L58"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/product.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_build_category_tree", "label": "_build_category_tree()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L85"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_collect_category_with_ancestors", "label": "_collect_category_with_ancestors()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L96"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_list_category_tree", "label": "list_category_tree()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L112"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_get_category", "label": "get_category()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L145"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_create_category", "label": "create_category()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L157"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_update_category", "label": "update_category()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L194"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_soft_delete_category", "label": "soft_delete_category()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L233"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_category_code_exists", "label": "category_code_exists()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L273"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_brand_row_to_dict", "label": "_brand_row_to_dict()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L293"}, {"id": "crmproductbrand", "label": "CrmProductBrand", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/product.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_alias_row_to_dict", "label": "_alias_row_to_dict()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L302"}, {"id": "crmproductalias", "label": "CrmProductAlias", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/crud/crm/product.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_load_brands_aliases_maps", "label": "_load_brands_aliases_maps()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L310"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_assert_brand_deletable", "label": "_assert_brand_deletable()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L344"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_replace_product_brands", "label": "_replace_product_brands()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L381"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_crud_crm_product_replace_product_aliases", "label": "_replace_product_aliases()", "file_type": "code", "source_file": "app/crud/crm/product.py", "source_location": "L450"}, {"id": "users_wuzilonLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "label": "test_pl_public_link_archived.py", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_archived_when_plan_archived", "label": "test_driver_link_flags_archived_when_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_voided_takes_precedence_shape", "label": "test_driver_link_flags_voided_takes_precedence_shape()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L17"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_voided_by_transport_cancelled", "label": "test_driver_link_flags_voided_by_transport_cancelled()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L25"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_site_link_flags_archived_when_plan_archived", "label": "test_site_link_flags_archived_when_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L33"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_site_link_flags_voided_when_cancelled", "label": "test_site_link_flags_voided_when_cancelled()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L40"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_site_link_flags_false_when_no_plan", "label": "test_site_link_flags_false_when_no_plan()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_public_transport_page_schema_exposes_plan_archived", "label": "test_public_transport_page_schema_exposes_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L53"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_public_site_page_schema_exposes_archived", "label": "test_public_site_page_schema_exposes_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L63"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_rationale_1", "label": "\u8fd0\u8f93\u8ba1\u5212\u53f8\u673a/\u73b0\u573a\u516c\u5171\u94fe\u63a5\uff1a\u5f52\u6863\u540e\u5e94\u6807\u8bb0\u5e76\u62e6\u622a\u5199\u64cd\u4f5c\u3002", "file_type": "rationale", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "types", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "app_api_pl_public_site", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "app_api_pl_public_transport", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "app_schemas_pl_transport", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_archived_when_plan_archived", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_voided_takes_precedence_shape", "relation": "contains", "confidence": "EXTRACTEDLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_py", "label": "transport.py", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportbase", "label": "TransportBase", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L18"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportcreate", "label": "TransportCreate", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L42"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportarrange", "label": "TransportArrange", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportinventorylinkread", "label": "TransportInventoryLinkRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L77"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportsitelinkread", "label": "TransportSiteLinkRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L87"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportupdate", "label": "TransportUpdate", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L101"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportdriverproductfeedbackread", "label": "TransportDriverProductFeedbackRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L125"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportread", "label": "TransportRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L141"}, {"id": "planresourcesnapshotmixin", "label": "PlanResourceSnapshotMixin", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportioorderbrief", "label": "TransportIoOrderBrief", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L163"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportarrangeresult", "label": "TransportArrangeResult", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L173"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_planarrangeinforead", "label": "PlanArrangeInfoRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L184"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportwithplans", "label": "TransportWithPlans", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L195"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportfeedback", "label": "TransportFeedback", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L204"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportproductfeedbackitem", "label": "PublicTransportProductFeedbackItem", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L213"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportfeedback", "label": "PublicTransportFeedback", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L220"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportplanproductread", "label": "PublicTransportPlanProductRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L228"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportpersonnelread", "label": "PublicTransportPersonnelRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L246"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportpageread", "label": "PublicTransportPageRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L253"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportsitepageread", "label": "PublicTransportSitePageRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L285"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_approvalsubmit", "label": "ALine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_py", "label": "test_pl_plan_resolve_driver.py", "file_type": "code", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_without_vehicle_link_returns_none", "label": "test_resolve_driver_without_vehicle_link_returns_none()", "file_type": "code", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_with_explicit_id_returns_personnel", "label": "test_resolve_driver_with_explicit_id_returns_personnel()", "file_type": "code", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L19"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_rationale_1", "label": "\u8fd0\u8f93\u8ba1\u5212\u89e3\u6790\u53f8\u673a\uff1a\u8f66\u8f86\u672a\u5173\u8054\u53f8\u673a\u65f6\u5141\u8bb8\u4e3a\u7a7a\u3002", "file_type": "rationale", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_rationale_10", "label": "\u672a\u663e\u5f0f\u9009\u53f8\u673a\u3001\u8f66\u8f86\u4e5f\u65e0\u5173\u8054\u53f8\u673a\u65f6\uff0c\u5e94\u8fd4\u56de\u7a7a\u4e09\u5143\u7ec4\u800c\u975e 400\u3002", "file_type": "rationale", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L10"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_py", "target": "unittest_mock", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_py", "target": "app_services_pl_plan_service", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_without_vehicle_link_returns_none", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_with_explicit_id_returns_personnel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_rationale_1", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_rationale_10", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_without_vehicle_link_returns_none", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "tests/test_pl_plan_resolve_driver.py", "source_location": "L10", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_without_vehicle_link_returns_none", "callee": "MagicMock", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_plan_resolve_driver.py", "source_location": "L11", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_without_vehicle_link_returns_none", "callee": "_resolve_driver", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_plan_resolve_driver.py", "source_location": "L14", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_with_explicit_id_returns_personnel", "callee": "MagicMock", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_plan_resolve_driver.py", "source_location": "L20", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_plan_resolve_driver_test_resolve_driver_with_explicit_id_returns_personneLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_py", "label": "transport.py", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportbase", "label": "TransportBase", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L18"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportcreate", "label": "TransportCreate", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L42"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportarrange", "label": "TransportArrange", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportinventorylinkread", "label": "TransportInventoryLinkRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L77"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportsitelinkread", "label": "TransportSiteLinkRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L87"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportupdate", "label": "TransportUpdate", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L101"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportdriverproductfeedbackread", "label": "TransportDriverProductFeedbackRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L125"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportread", "label": "TransportRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L141"}, {"id": "planresourcesnapshotmixin", "label": "PlanResourceSnapshotMixin", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportioorderbrief", "label": "TransportIoOrderBrief", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L163"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportarrangeresult", "label": "TransportArrangeResult", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L173"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_planarrangeinforead", "label": "PlanArrangeInfoRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L184"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportwithplans", "label": "TransportWithPlans", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L195"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_transportfeedback", "label": "TransportFeedback", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L204"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportproductfeedbackitem", "label": "PublicTransportProductFeedbackItem", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L213"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportfeedback", "label": "PublicTransportFeedback", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L220"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportplanproductread", "label": "PublicTransportPlanProductRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L228"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportpersonnelread", "label": "PublicTransportPersonnelRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L246"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportpageread", "label": "PublicTransportPageRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L253"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_publictransportsitepageread", "label": "PublicTransportSitePageRead", "file_type": "code", "source_file": "app/schemas/pl/transport.py", "source_location": "L286"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_transport_approvalsubmit", "label": "ALine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_py", "label": "plan.py", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductbase", "label": "PlanProductBase", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L16"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcreate", "label": "PlanProductCreate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L49"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductupdate", "label": "PlanProductUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L53"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planarchivebrandqtyitem", "label": "PlanArchiveBrandQtyItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L75"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductread", "label": "PlanProductRead", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L82"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planbase", "label": "PlanBase", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L99"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plancreate", "label": "PlanCreate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L149"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plantransportcreateblock", "label": "PlanTransportCreateBlock", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L158"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planupdate", "label": "PlanUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L172"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_hazardcertreadybody", "label": "HazardCertReadyBody", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L215"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planread", "label": "PlanRead", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L220"}, {"id": "planresourcesnapshotmixin", "label": "PlanResourceSnapshotMixin", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planwithproducts", "label": "PlanWithProducts", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L248"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planinboundsliptemplatesave", "label": "PlanInboundSlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L252"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plandeliverysliptemplatesave", "label": "PlanDeliverySlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L257"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plansubpacksliptemplatesave", "label": "PlanSubpackSlipTemplateSave", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L264"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_createfromcontractrequest", "label": "CreateFromContractRequest", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L276"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_plancreatefull", "label": "PlanCreateFull", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L287"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planlistquery", "label": "PlanListQuery", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L298"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcertitem", "label": "PlanProductCertItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L323"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planproductcertsupdate", "label": "PlanProductCertsUpdate", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L331"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_pl_plan_planarchiveproductitem", "label": "PlanArchiveProductItem", "file_type": "code", "source_file": "app/schemas/pl/plan.py", "source_location": "L336"}, {"id": "users_wuzilong_woLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_py", "label": "public_site.py", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_parse_feedback_images", "label": "_parse_feedback_images()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L33"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_get_site_link_by_token", "label": "_get_site_link_by_token()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L45"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "pltransportsitelink", "label": "PlTransportSiteLink", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_resolve_site_link_flags", "label": "_resolve_site_link_flags()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L59"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_resolve_unit_label", "label": "_resolve_unit_label()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L66"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_resolve_plan_product", "label": "_resolve_plan_product()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L73"}, {"id": "plplanproduct", "label": "PlPlanProduct", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_build_site_product_read", "label": "_build_site_product_read()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L86"}, {"id": "publictransportplanproductread", "label": "PublicTransportPlanProductRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_build_public_page", "label": "_build_public_page()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L145"}, {"id": "publictransportsitepageread", "label": "PublicTransportSitePageRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_get_public_site", "label": "get_public_site()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L187"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_save_public_site_feedback", "label": "save_public_site_feedback()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L194"}, {"id": "publicinventoryfeedback", "label": "PublicInventoryFeedback", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_format_file_size", "label": "_format_file_size()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L217"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_upload_public_site_attachment", "label": "upload_public_site_attachment()", "file_type": "code", "source_file": "app/api/pl/public_site.py", "source_location": "L226"}, {"id": "uploadfile", "label": "UploadFile", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_site.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_rationale_1", "label": "\u8fd0\u8f93\u8ba1\u5212 \u00b7 \u5de5\u5382\u73b0\u573a\u4eba\u5458\u514d\u767b\u5f55\u516c\u5171 API\uff08pl_transport_site_link\uff09", "file_type": "rationale", "source_file": "app/api/pl/public_site.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_site_py", "target": "json", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_siLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_py", "label": "product.py", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productcategorycreatebody", "label": "ProductCategoryCreateBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L12"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productcategoryupdatebody", "label": "ProductCategoryUpdateBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L26"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_categorydeletebody", "label": "CategoryDeleteBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L41"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productcategorytreebody", "label": "ProductCategoryTreeBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productupdatestatusbody", "label": "ProductUpdateStatusBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L56"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productlistbody", "label": "ProductListBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L66"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productbranditem", "label": "ProductBrandItem", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L79"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productaliasitem", "label": "ProductAliasItem", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L90"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productcreatebody", "label": "ProductCreateBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L100"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productupdatebody", "label": "ProductUpdateBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L134"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productdetailbody", "label": "ProductDetailBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L169"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productdeletebody", "label": "ProductDeleteBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L175"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productoptionsbody", "label": "ProductOptionsBody", "file_type": "code", "source_file": "app/schemas/crm/product.py", "source_location": "L182"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_rationale_1", "label": "CRM \u4ea7\u54c1\u6a21\u5757 Pydantic Schemas", "file_type": "rationale", "source_file": "app/schemas/crm/product.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_rationale_48", "label": "\u4ea7\u54c1\u5206\u7c7b\u6811\u67e5\u8be2\uff08\u5bc6\u6587\u89e3\u5bc6\u540e\u987b\u7528 Pydantic \u7ed1\u5b9a\uff0c\u88f8 dict=None \u5728\u90e8\u5206\u94fe\u8def\u4e0b\u4f1a\u4e22 body\uff09", "file_type": "rationale", "source_file": "app/schemas/crm/product.py", "source_location": "L48"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_py", "target": "decimal", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/crm/product.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_py", "target": "typing", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/crm/product.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_py", "target": "pydantic", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "app/schemas/crm/product.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_app_schemas_crm_product_productcategorycreatebody", "relation": "contains", "confidence": "EXTRACTED", "source_file": "app/schemas/crm/product.pLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "label": "public_transport.py", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_resolve_unit_label", "label": "_resolve_unit_label()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L47"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_get_transport_by_token", "label": "_get_transport_by_token()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L54"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_parse_feedback_images", "label": "_parse_feedback_images()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L68"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_format_plan_date", "label": "_format_plan_date()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L80"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_resolve_driver_link_flags", "label": "_resolve_driver_link_flags()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L90"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_resolve_other_personnel", "label": "_resolve_other_personnel()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L102"}, {"id": "publictransportpersonnelread", "label": "PublicTransportPersonnelRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_build_public_page", "label": "_build_public_page()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L131"}, {"id": "publictransportpageread", "label": "PublicTransportPageRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_get_public_transport", "label": "get_public_transport()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L288"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_save_public_feedback", "label": "save_public_feedback()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L295"}, {"id": "publictransportfeedback", "label": "PublicTransportFeedback", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_format_file_size", "label": "_format_file_size()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L353"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_upload_public_attachment", "label": "upload_public_attachment()", "file_type": "code", "source_file": "app/api/pl/public_transport.py", "source_location": "L362"}, {"id": "uploadfile", "label": "UploadFile", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/public_transport.py"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "target": "json", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_transport.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "target": "os", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "app/api/pl/public_transport.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_public_transport_py", "tarLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "label": "test_pl_public_link_archived.py", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_archived_when_plan_archived", "label": "test_driver_link_flags_archived_when_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L10"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_voided_takes_precedence_shape", "label": "test_driver_link_flags_voided_takes_precedence_shape()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L18"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_driver_link_flags_voided_by_transport_cancelled", "label": "test_driver_link_flags_voided_by_transport_cancelled()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L26"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_site_link_flags_archived_when_plan_archived", "label": "test_site_link_flags_archived_when_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L34"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_site_link_flags_voided_when_cancelled", "label": "test_site_link_flags_voided_when_cancelled()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L41"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_site_link_flags_false_when_no_plan", "label": "test_site_link_flags_false_when_no_plan()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L48"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_public_transport_page_schema_exposes_plan_archived", "label": "test_public_transport_page_schema_exposes_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L54"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_public_site_page_schema_exposes_archived", "label": "test_public_site_page_schema_exposes_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L64"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_io_order_link_flags_archived_when_plan_archived", "label": "test_io_order_link_flags_archived_when_plan_archived()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L75"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_test_io_order_link_flags_voided_by_header_or_plan", "label": "test_io_order_link_flags_voided_by_header_or_plan()", "file_type": "code", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L83"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_rationale_1", "label": "\u8fd0\u8f93\u8ba1\u5212\u53f8\u673a/\u73b0\u573a\u516c\u5171\u94fe\u63a5\uff1a\u5f52\u6863\u540e\u5e94\u6807\u8bb0\u5e76\u62e6\u622a\u5199\u64cd\u4f5c\u3002", "file_type": "rationale", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "types", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "app_api_pl_public_io_order", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "app_api_pl_public_site", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_public_link_archived_py", "target": "app_api_pl_public_transport", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_public_link_archived.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backendLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_py", "label": "test_pl_io_order_enrichment.py", "file_type": "code", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_resolve_unit_label_maps_dun", "label": "test_resolve_unit_label_maps_dun()", "file_type": "code", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L9"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_merge_plan_logistics_into_order", "label": "test_merge_plan_logistics_into_order()", "file_type": "code", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L16"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_merge_plan_product_into_item", "label": "test_merge_plan_product_into_item()", "file_type": "code", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L50"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_py", "target": "app_services_pl_io_order_service", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_resolve_unit_label_maps_dun", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_merge_plan_logistics_into_order", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L16", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_merge_plan_product_into_item", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_pl_io_order_enrichment.py", "source_location": "L50", "weight": 1.0}], "raw_calls": [{"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_resolve_unit_label_maps_dun", "callee": "resolve_unit_label", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_io_order_enrichment.py", "source_location": "L10", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_resolve_unit_label_maps_dun", "callee": "resolve_unit_label", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_io_order_enrichment.py", "source_location": "L11", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_resolve_unit_label_maps_dun", "callee": "resolve_unit_label", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_io_order_enrichment.py", "source_location": "L12", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_resolve_unit_label_maps_dun", "callee": "resolve_unit_label", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_io_order_enrichment.py", "source_location": "L13", "receiver": null}, {"caller_nid": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_pl_io_order_enrichment_test_merge_plan_logistics_into_order", "callee": "type(\n \"P\",\n (),\n {\n \"plan_type\": \"outbound\",\n \"remark\": \"plan-remark\",\n \"pickup_address\": \"\u53d6\u8d27\u8def1\u53f7\",\n \"pickup_lng\": 117.0,\n \"pickup_lat\": 30.5,\n \"pickup_time\": None,\n \"pickup_contact\": \"\u5f20\u4e09 13800000000\",\n \"pickup_notes\": \"\u6234\u5e3d\",\n \"destination_name\": \"\u4ed3\u5e93A\",\n \"destination_address\": \"\u9001\u8d27\u8def2\u53f7\",\n \"destination_lng\": None,\n \"destination_lat\": None,\n \"delivery_time\": None,\n \"delivery_contact\": \"\u674e\u56db 13900000000\",\n \"destination_notes\": \"\u5317\u95e8\",\n },\n )", "is_member_call": false, "source_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/tests/test_pl_io_order_enrichment.py", "source_location": "L18", "receiver": null}, {"caller_nidLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "label": "test_db_resolve_crm_product.py", "file_type": "code", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_product", "label": "_product()", "file_type": "code", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L13"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_test_resolve_rejects_off_shelf_by_default", "label": "test_resolve_rejects_off_shelf_by_default()", "file_type": "code", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L25"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_test_resolve_allows_off_shelf_when_not_required", "label": "test_resolve_allows_off_shelf_when_not_required()", "file_type": "code", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L34"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_rationale_1", "label": "resolve_crm_product\uff1a\u8fd0\u8f93\u8054\u52a8\u573a\u666f\u5141\u8bb8\u5df2\u4e0b\u67b6\u4ea7\u54c1\u3002", "file_type": "rationale", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "types", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "unittest_mock", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "pytest", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "fastapi", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "app_services_db_product_helpers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_product", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_test_resolve_rejects_off_shelf_by_default", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L25", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_py", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_test_resolve_allows_off_shelf_when_not_required", "relation": "contains", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L34", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_test_resolve_rejects_off_shelf_by_default", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_product", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L27", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_test_resolve_allows_off_shelf_when_not_required", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_product", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "tests/test_db_resolve_crm_product.py", "source_location": "L36", "weight": 1.0}, {"source": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_rationale_1", "target": "users_wuzilong_work_00code_shanxia2_0_backend_tests_test_db_resolve_crm_product_Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_py", "label": "transport.py", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_transport_to_read", "label": "_transport_to_read()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L70"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "pltransport", "label": "PlTransport", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "transportread", "label": "TransportRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_generate_transport_no", "label": "_generate_transport_no()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L89"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_resolve_driver_info", "label": "_resolve_driver_info()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L113"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_get_vehicle_info", "label": "_get_vehicle_info()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L151"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_assert_vehicle_carrier_eligible", "label": "_assert_vehicle_carrier_eligible()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L201"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_ensure_driver_access_token", "label": "_ensure_driver_access_token()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L236"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_rotate_driver_access_token", "label": "_rotate_driver_access_token()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L244"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_is_rearrange", "label": "_is_rearrange()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L250"}, {"id": "plplan", "label": "PlPlan", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_transport_has_db_links", "label": "_transport_has_db_links()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L261"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_apply_plan_logistics_from_payload", "label": "_apply_plan_logistics_from_payload()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L274"}, {"id": "transportarrange", "label": "TransportArrange", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_resolve_transport_endpoints", "label": "_resolve_transport_endpoints()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L299"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_apply_transport_arrange_fields", "label": "_apply_transport_arrange_fields()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L314"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_build_driver_url", "label": "_build_driver_url()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L348"}, {"id": "users_wuzilong_work_00code_shanxia2_0_backend_app_api_pl_transport_build_arrange_result", "label": "_build_arrange_result()", "file_type": "code", "source_file": "app/api/pl/transport.py", "source_location": "L353"}, {"id": "transportsitelinkread", "label": "TransportSiteLinkRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "transportinventorylinkread", "label": "TransportInventoryLinkRead", "file_type": "code", "source_file": "", "source_location": "", "origin_file": "/Users/wuzilong/work/00code/shanxia2.0/backend/app/api/pl/transport.py"}, {"id": "transportioorderbrief", "label": "TransportIoOrderBrief", "file_type": "code", "source_file": "", "source_location": "", "origiLine truncated
+1 -1
View File
@@ -1 +1 @@
{"/Users/zlwu/work/00code/shanxia2.0/backend/start-prod.sh":{"size":7357,"mtime_ns":1782639355476060453,"hash":"ca89869446be74a2bf2367b3b28f448580220859a39a84ad9613ac5fe35a8433"},"/Users/zlwu/work/00code/shanxia2.0/backend/start.sh":{"size":9548,"mtime_ns":1780114661446983244,"hash":"4d632863e8a0cd81194b491d83a0218a4157435ae812dec76a6f6197b4d48e57"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/__init__.py":{"size":21,"mtime_ns":1780113982281973984,"hash":"60a04ff08fd97084e83ea809fd13feda6d2848be20ebf309e31fc1dad7523230"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/main.py":{"size":6280,"mtime_ns":1782790852770448643,"hash":"8f9da799977bee7134d87a26ff8434ac5ef8eabb0b7368dd537eee49ad7fd00b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/tasks/__init__.py":{"size":2207,"mtime_ns":1783208067881286091,"hash":"313e6da0e91d743ce891dd283458c79b50b24c4d909dc96ca7b3fd9d2bfa5013"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/auth.py":{"size":7457,"mtime_ns":1782790841500516545,"hash":"34bac56e1c2cb6215f4b5fa2dc32d77d4b4abca51428819eebf4afd269cc51cf"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto.py":{"size":1870,"mtime_ns":1780108930724444498,"hash":"c04b748aea86890a5971f749523c7b17dbad1ddd6f9f7f07a5679d159c984e33"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/login_crypto.py":{"size":3858,"mtime_ns":1780108930725155710,"hash":"b82d51afabf2293a9cb1fb2e5f994c383948e7f47ea95fe674686b4f3f3342b1"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/config.py":{"size":6958,"mtime_ns":1784032424448146538,"hash":"c2fb44aedb880733de28afa7f92d2c1c681eb600f821bbeba2bcda3933e5bc37"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_pay.py":{"size":23585,"mtime_ns":1780108930725768130,"hash":"3d52265ce65d21e7103f94afa1e8547aee0823b5ea6d65c50317436ac81fb4fc"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_request_log_middleware.py":{"size":11971,"mtime_ns":1782701669198208175,"hash":"0b84c32828939e6102bb3647691fa8f04b1f68e0e0e9f28127374cc44e19a11c"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/database.py":{"size":1510,"mtime_ns":1782790847265601586,"hash":"8bc9c8ae62e2be2c6920036582ba448dfcd1711c41cebb62274ff6bc6ee14b0b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/security.py":{"size":728,"mtime_ns":1780108930725470004,"hash":"df0f01115064f7b8de1c81dbe9a6db39360c236610b68c33b3234a51d7f0025b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/request_payload.py":{"size":2842,"mtime_ns":1780108930725350836,"hash":"e9937151530ab1417ef297aef59111977725cf90be2a8fa76c00a0618789aba0"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/__init__.py":{"size":61,"mtime_ns":1780108930724312414,"hash":"3dd1842ee59b0c804176b03b4b8a323bd4a252b7feb1bbc32db64f3a8928570e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/response.py":{"size":1824,"mtime_ns":1780108930725412462,"hash":"f1739352d65ea8287d76e282a59553aa8d63c97e35764c64ac378aa5bd9c347e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/menu_guard.py":{"size":1611,"mtime_ns":1780108930725223002,"hash":"3e26077288c3620a4780038b891a326206b45bffe00aca545bdae30172487235"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/db_collation.py":{"size":548,"mtime_ns":1780108930725025043,"hash":"0c680e25a18244ca839a7de6ed1f4313b33bc8da118d89c463aee1b6af00c6f9"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/context.py":{"size":421,"mtime_ns":1780108930724824458,"hash":"83a10aee67162374993c10a30bf8bb8bd9c4b35cf48f42c832415ccebd91660f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/utils.py":{"size":1498,"mtime_ns":1780108930725607296,"hash":"09323693661c1d4560458b86a954128ccff82bbaf6522da0b44f24da99ddf9ea"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/storage.py":{"size":14141,"mtime_ns":1782855136810943216,"hash":"3ae2c413c10898a8adb3d6773870bafbfbc18c739c10e0e8b4f765b4b5ca6c08"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/order_status_compat.py":{"size":2828,"mtime_ns":1780108930725284669,"hash":"5349e5a0745ee6734c4a995337779307adefc46f453906171988a77de2081540"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/exceptions.py":{"size":4946,"mtime_ns":1780108930725084335,"hash":"79c997d964bca1a4f12f2b92fb1f181fdb9e2b3cf72eae39f4cc164d23794fd7"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/data_scope.py":{"size":8043,"mtime_ns":1782648925694296304,"hash":"626dff86937e5cacec634ecbc61cd53d3763d760223a1d4ec7cd11f64e59a220"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/admin_request_json.py":{"size":2669,"mtime_ns":1780108930724378914,"hash":"4f68b3cf84291e7bddad6ecf4bb4d29ca5e1ec246a9f7f9c4cf5909d0ec1174a"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto_middleware.py":{"size":10876,"mtime_ns":1782790001926627098,"hash":"b39f128b6612589ea6ac5babd30752e9585b3af07b82bb1ad53c9e3c0d90816f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_message.py":{"size":11194,"mtime_ns":1780108930725684255,"hash":"5086070deb14d99d1a69e419b2299ec4Line truncated
{"/Users/zlwu/work/00code/shanxia2.0/backend/start-prod.sh":{"size":7357,"mtime_ns":1782639355476060453,"hash":"ca89869446be74a2bf2367b3b28f448580220859a39a84ad9613ac5fe35a8433"},"/Users/zlwu/work/00code/shanxia2.0/backend/start.sh":{"size":9548,"mtime_ns":1780114661446983244,"hash":"4d632863e8a0cd81194b491d83a0218a4157435ae812dec76a6f6197b4d48e57"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/__init__.py":{"size":21,"mtime_ns":1780113982281973984,"hash":"60a04ff08fd97084e83ea809fd13feda6d2848be20ebf309e31fc1dad7523230"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/main.py":{"size":6280,"mtime_ns":1782790852770448643,"hash":"8f9da799977bee7134d87a26ff8434ac5ef8eabb0b7368dd537eee49ad7fd00b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/tasks/__init__.py":{"size":2207,"mtime_ns":1783208067881286091,"hash":"313e6da0e91d743ce891dd283458c79b50b24c4d909dc96ca7b3fd9d2bfa5013"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/auth.py":{"size":7457,"mtime_ns":1782790841500516545,"hash":"34bac56e1c2cb6215f4b5fa2dc32d77d4b4abca51428819eebf4afd269cc51cf"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto.py":{"size":1870,"mtime_ns":1780108930724444498,"hash":"c04b748aea86890a5971f749523c7b17dbad1ddd6f9f7f07a5679d159c984e33"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/login_crypto.py":{"size":3858,"mtime_ns":1780108930725155710,"hash":"b82d51afabf2293a9cb1fb2e5f994c383948e7f47ea95fe674686b4f3f3342b1"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/config.py":{"size":6958,"mtime_ns":1784032424448146538,"hash":"c2fb44aedb880733de28afa7f92d2c1c681eb600f821bbeba2bcda3933e5bc37"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_pay.py":{"size":23585,"mtime_ns":1780108930725768130,"hash":"3d52265ce65d21e7103f94afa1e8547aee0823b5ea6d65c50317436ac81fb4fc"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_request_log_middleware.py":{"size":11971,"mtime_ns":1782701669198208175,"hash":"0b84c32828939e6102bb3647691fa8f04b1f68e0e0e9f28127374cc44e19a11c"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/database.py":{"size":1510,"mtime_ns":1782790847265601586,"hash":"8bc9c8ae62e2be2c6920036582ba448dfcd1711c41cebb62274ff6bc6ee14b0b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/security.py":{"size":728,"mtime_ns":1780108930725470004,"hash":"df0f01115064f7b8de1c81dbe9a6db39360c236610b68c33b3234a51d7f0025b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/request_payload.py":{"size":2842,"mtime_ns":1780108930725350836,"hash":"e9937151530ab1417ef297aef59111977725cf90be2a8fa76c00a0618789aba0"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/__init__.py":{"size":61,"mtime_ns":1780108930724312414,"hash":"3dd1842ee59b0c804176b03b4b8a323bd4a252b7feb1bbc32db64f3a8928570e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/response.py":{"size":1824,"mtime_ns":1780108930725412462,"hash":"f1739352d65ea8287d76e282a59553aa8d63c97e35764c64ac378aa5bd9c347e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/menu_guard.py":{"size":1611,"mtime_ns":1780108930725223002,"hash":"3e26077288c3620a4780038b891a326206b45bffe00aca545bdae30172487235"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/db_collation.py":{"size":548,"mtime_ns":1780108930725025043,"hash":"0c680e25a18244ca839a7de6ed1f4313b33bc8da118d89c463aee1b6af00c6f9"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/context.py":{"size":421,"mtime_ns":1780108930724824458,"hash":"83a10aee67162374993c10a30bf8bb8bd9c4b35cf48f42c832415ccebd91660f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/utils.py":{"size":1498,"mtime_ns":1780108930725607296,"hash":"09323693661c1d4560458b86a954128ccff82bbaf6522da0b44f24da99ddf9ea"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/storage.py":{"size":14141,"mtime_ns":1782855136810943216,"hash":"3ae2c413c10898a8adb3d6773870bafbfbc18c739c10e0e8b4f765b4b5ca6c08"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/order_status_compat.py":{"size":2828,"mtime_ns":1780108930725284669,"hash":"5349e5a0745ee6734c4a995337779307adefc46f453906171988a77de2081540"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/exceptions.py":{"size":4946,"mtime_ns":1780108930725084335,"hash":"79c997d964bca1a4f12f2b92fb1f181fdb9e2b3cf72eae39f4cc164d23794fd7"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/data_scope.py":{"size":8043,"mtime_ns":1782648925694296304,"hash":"626dff86937e5cacec634ecbc61cd53d3763d760223a1d4ec7cd11f64e59a220"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/admin_request_json.py":{"size":2669,"mtime_ns":1780108930724378914,"hash":"4f68b3cf84291e7bddad6ecf4bb4d29ca5e1ec246a9f7f9c4cf5909d0ec1174a"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto_middleware.py":{"size":10876,"mtime_ns":1782790001926627098,"hash":"b39f128b6612589ea6ac5babd30752e9585b3af07b82bb1ad53c9e3c0d90816f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_message.py":{"size":11194,"mtime_ns":1780108930725684255,"hash":"5086070deb14d99d1a69e419b2299ec4Line truncated
+4 -4
View File
@@ -63,12 +63,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">4616 nodes &middot; 15627 edges &middot; 523 communities</div>
<div id="stats">4671 nodes &middot; 15744 edges &middot; 541 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "app_init", "label": "__init__.py", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 304, "community_name": "__init__.py", "source_file": "app/__init__.py", "file_type": "code", "degree": 0}, {"id": "app_api_init", "label": "__init__.py", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.6, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 160, "community_name": "register_local_callback", "source_file": "app/api/__init__.py", "file_type": "code", "degree": 10}, {"id": "app_api_init_rationale_1", "label": "API \u8def\u7531\u5305 \u2014 \u5c71\u5ce1\u5316\u5de5\u751f\u4ea7\u4e00\u4f53\u5316\u95e8\u6237", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "API \u8def\u7531\u5305 \u2014 \u5c71\u5ce1\u5316\u5de5\u751f\u4ea7\u4e00\u4f53\u5316\u95e8\u6237", "community": 160, "community_name": "register_local_callback", "source_file": "app/api/__init__.py", "file_type": "rationale", "degree": 1}, {"id": "app_api_admin", "label": "admin.py", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 17.1, "font": {"size": 12, "color": "#ffffff"}, "title": "admin.py", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 110}, {"id": "app_api_admin_list_roles_for_select", "label": "list_roles_for_select()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "list_roles_for_select()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_py_session", "label": "Session", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 13.4, "font": {"size": 0, "color": "#ffffff"}, "title": "Session", "community": 3, "community_name": "Community 3", "source_file": "", "file_type": "code", "degree": 53}, {"id": "app_api_admin_list_users_for_select", "label": "list_users_for_select()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "list_users_for_select()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_list_roles_for_designer", "label": "list_roles_for_designer()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "list_roles_for_designer()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_tenantcreatebody", "label": "TenantCreateBody", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "TenantCreateBody", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 7}, {"id": "app_api_admin_tenantupdatebody", "label": "TenantUpdateBody", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "TenantUpdateBody", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 7}, {"id": "app_api_admin_list_tenants", "label": "list_tenants()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "list_tenants()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 3}, {"id": "app_api_admin_create_tenant", "label": "create_tenant()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "create_tenant()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_update_tenant", "label": "update_tenant()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "Line truncated
const RAW_EDGES = [{"from": "app_api_init", "to": "app_api_admin", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_bx_init", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_crm", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_db_init", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_leave", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_menu", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_monitor", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_public", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_workflow", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init_rationale_1", "to": "app_api_init", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_attachment_download_url", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_attachment_preview_url", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_attachmentdownloadurlbody", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_dept", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_dict_data", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_dict_type", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_menu", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_post", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_role_management", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_site", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_tenant", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_user", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_delete_dept", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_delete_dict_data", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_delete_dict_type", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {Line truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 35}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 35}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 39}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 100}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 63}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 26}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 44}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 38}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 51}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 1}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 1}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 61}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 82}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 34}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 34}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 80}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 68}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 1}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 63}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 49}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 1}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 57}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 43}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 68}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 26}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 79}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 26}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 34}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 96}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 25}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 27}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 1}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 1}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 26}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 26}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 38}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 36}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 33}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 25}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 47}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 1}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 1}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 34}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 59}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 34}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 44}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 19}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 1}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 35}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 33}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 19}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 45}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 31}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 38}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 30}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 1}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 38}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 30}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 24}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 48}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 4}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 24}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 185}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 62}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 30}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 53}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 27}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 31}, {"cid": 70, "color": "#4E79A7", "label": "CoLine truncated
const RAW_NODES = [{"id": "app_init", "label": "__init__.py", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 304, "community_name": "__init__.py", "source_file": "app/__init__.py", "file_type": "code", "degree": 0}, {"id": "app_api_init", "label": "__init__.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.6, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 126, "community_name": "customer_pool.py", "source_file": "app/api/__init__.py", "file_type": "code", "degree": 10}, {"id": "app_api_init_rationale_1", "label": "API \u8def\u7531\u5305 \u2014 \u5c71\u5ce1\u5316\u5de5\u751f\u4ea7\u4e00\u4f53\u5316\u95e8\u6237", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "API \u8def\u7531\u5305 \u2014 \u5c71\u5ce1\u5316\u5de5\u751f\u4ea7\u4e00\u4f53\u5316\u95e8\u6237", "community": 126, "community_name": "customer_pool.py", "source_file": "app/api/__init__.py", "file_type": "rationale", "degree": 1}, {"id": "app_api_admin", "label": "admin.py", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 17.1, "font": {"size": 12, "color": "#ffffff"}, "title": "admin.py", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 110}, {"id": "app_api_admin_list_roles_for_select", "label": "list_roles_for_select()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "list_roles_for_select()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_py_session", "label": "Session", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 13.4, "font": {"size": 0, "color": "#ffffff"}, "title": "Session", "community": 3, "community_name": "Community 3", "source_file": "", "file_type": "code", "degree": 53}, {"id": "app_api_admin_list_users_for_select", "label": "list_users_for_select()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "list_users_for_select()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_list_roles_for_designer", "label": "list_roles_for_designer()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "list_roles_for_designer()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_tenantcreatebody", "label": "TenantCreateBody", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "TenantCreateBody", "community": 81, "community_name": "Community 81", "source_file": "app/api/admin.py", "file_type": "code", "degree": 7}, {"id": "app_api_admin_tenantupdatebody", "label": "TenantUpdateBody", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "TenantUpdateBody", "community": 81, "community_name": "Community 81", "source_file": "app/api/admin.py", "file_type": "code", "degree": 7}, {"id": "app_api_admin_list_tenants", "label": "list_tenants()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "list_tenants()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 3}, {"id": "app_api_admin_create_tenant", "label": "create_tenant()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "create_tenant()", "community": 3, "community_name": "Community 3", "source_file": "app/api/admin.py", "file_type": "code", "degree": 5}, {"id": "app_api_admin_update_tenant", "label": "update_tenant()", "color": {"background": "#76B7B2", "border": "#76B7B2", "highlight": {"background": "#ffffff", "border": "#76B7B2"}}Line truncated
const RAW_EDGES = [{"from": "app_api_init", "to": "app_api_admin", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_bx_init", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_crm", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_db_init", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_leave", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_menu", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_monitor", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_public", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init", "to": "app_api_workflow", "label": "re_exports", "title": "re_exports [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_init_rationale_1", "to": "app_api_init", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_attachment_download_url", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_attachment_preview_url", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_attachmentdownloadurlbody", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_dept", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_dict_data", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_dict_type", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_menu", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_post", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_role_management", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_site", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_tenant", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_create_user", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_delete_dept", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_delete_dict_data", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_api_admin", "to": "app_api_admin_delete_dict_type", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {Line truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 35}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 41}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 30}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 75}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 79}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 26}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 33}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 43}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 48}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 1}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 1}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 45}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 88}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 44}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 20}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 51}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 39}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 1}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 34}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 56}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 1}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 36}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 43}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 12}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 39}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 32}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 59}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 16}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 63}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 61}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 27}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 1}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 1}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 24}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 60}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 38}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 33}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 20}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 26}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 29}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 1}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 1}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 34}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 58}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 42}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 79}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 40}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 1}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 12}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 39}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 35}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 80}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 31}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 55}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 30}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 1}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 34}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 30}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 26}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 33}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 40}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 24}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 117}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 35}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 38}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 38}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 14}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 42}, {"cid": 70, "color": "#4E79A7", "label": "CoLine truncated
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,6 @@
-- backend/scripts/migrate_20260806_pl_plan_pickup_delivery_contact.sql
-- 运输计划:取货/送货联系方式
ALTER TABLE `pl_plan`
ADD COLUMN `pickup_contact` varchar(200) DEFAULT NULL COMMENT '取货联系方式' AFTER `pickup_time`,
ADD COLUMN `delivery_contact` varchar(200) DEFAULT NULL COMMENT '送货联系方式' AFTER `delivery_time`;
@@ -0,0 +1,24 @@
import pytest
from app.crud.crm.contract import (
CONTRACT_EDITABLE_STATUSES,
assert_contract_editable_for_update,
)
def test_editable_statuses():
assert CONTRACT_EDITABLE_STATUSES == frozenset({"draft", "approving", "approved"})
assert "executing" not in CONTRACT_EDITABLE_STATUSES
assert "finished" not in CONTRACT_EDITABLE_STATUSES
assert "invalid" not in CONTRACT_EDITABLE_STATUSES
def test_assert_allows_editable():
for s in ("draft", "approving", "approved", None, ""):
assert_contract_editable_for_update(s)
def test_assert_rejects_non_editable():
for s in ("executing", "finished", "invalid"):
with pytest.raises(ValueError, match="才能修改"):
assert_contract_editable_for_update(s)
@@ -0,0 +1,23 @@
"""产品下拉 options:keyword 仅按产品名称模糊匹配,不匹配产品编号。"""
from __future__ import annotations
from unittest.mock import MagicMock
from app.crud.crm.product import list_product_options
def test_list_product_options_keyword_only_filters_product_name():
db = MagicMock()
q = MagicMock()
db.query.return_value = q
q.filter.return_value = q
q.order_by.return_value = q
q.limit.return_value = q
q.all.return_value = []
list_product_options(db, "shanxia2.0", keyword="32", limit=50)
assert q.filter.call_count >= 2
keyword_expr = " ".join(str(a) for a in q.filter.call_args_list[1][0])
assert "product_name" in keyword_expr
assert "product_no" not in keyword_expr
@@ -0,0 +1,40 @@
"""resolve_crm_product:运输联动场景允许已下架产品。"""
from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
import pytest
from fastapi import HTTPException
from app.services.db.product_helpers import resolve_crm_product
def _product(**kwargs):
base = dict(
id="p1",
tenant_no="shanxia2.0",
product_name="98% 工业硫酸",
model="98%",
status="off",
)
base.update(kwargs)
return SimpleNamespace(**base)
def test_resolve_rejects_off_shelf_by_default():
db = MagicMock()
with patch("app.services.db.product_helpers.get_product", return_value=_product()):
with pytest.raises(HTTPException) as exc:
resolve_crm_product(db, "shanxia2.0", "p1")
assert exc.value.status_code == 400
assert "下架" in str(exc.value.detail)
def test_resolve_allows_off_shelf_when_not_required():
db = MagicMock()
with patch("app.services.db.product_helpers.get_product", return_value=_product()):
snap = resolve_crm_product(db, "shanxia2.0", "p1", require_on_shelf=False)
assert snap.product_id == "p1"
assert snap.product_name == "98% 工业硫酸"
assert snap.specification == "98%"
@@ -0,0 +1,20 @@
"""未结算计划简易搜索:q 应覆盖计划编号/客户/车牌/承运商名称。"""
from __future__ import annotations
from sqlalchemy.dialects import mysql
from app.services.pl_freight_settlement_service import unsettled_plans_q_filter
def test_unsettled_plans_q_filter_includes_carrier_and_plate():
clause = unsettled_plans_q_filter("华运")
sql = str(
clause.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True})
).lower()
assert "plan_no" in sql
assert "customer_name" in sql
assert "supplier_name" in sql
assert "license_plate" in sql
assert "carrier_name" in sql
assert "华运" in sql
@@ -25,12 +25,14 @@ def test_merge_plan_logistics_into_order():
"pickup_lng": 117.0,
"pickup_lat": 30.5,
"pickup_time": None,
"pickup_contact": "张三 13800000000",
"pickup_notes": "戴帽",
"destination_name": "仓库A",
"destination_address": "送货路2号",
"destination_lng": None,
"destination_lat": None,
"delivery_time": None,
"delivery_contact": "李四 13900000000",
"destination_notes": "北门",
},
)()
@@ -39,8 +41,10 @@ def test_merge_plan_logistics_into_order():
assert data["planRemark"] == "plan-remark"
assert data["remark"] == "order-remark" # 单据备注不被覆盖
assert data["pickupAddress"] == "取货路1号"
assert data["pickupContact"] == "张三 13800000000"
assert data["destinationAddress"] == "送货路2号"
assert data["destinationName"] == "仓库A"
assert data["deliveryContact"] == "李四 13900000000"
def test_merge_plan_product_into_item():
@@ -0,0 +1,37 @@
"""危化品证上传列表筛选:EXISTS 子查询应覆盖 CRM 危化标识与证书缺口。"""
from __future__ import annotations
from sqlalchemy.dialects import mysql
from app.services.pl_plan_service import (
plan_has_hazard_product_exists,
plan_has_incomplete_hazard_cert_exists,
)
def _compile(clause) -> str:
return str(
clause.compile(dialect=mysql.dialect(), compile_kwargs={"literal_binds": True})
).lower()
def test_plan_has_hazard_product_exists_joins_crm_flags():
clause = plan_has_hazard_product_exists("shanxia2.0")
sql = _compile(clause)
assert "pl_plan_product" in sql
assert "crm_product" in sql
assert "is_toxic" in sql
assert "is_explosive" in sql
assert "shanxia2.0" in sql
def test_plan_has_incomplete_hazard_cert_exists_checks_required_urls():
clause = plan_has_incomplete_hazard_cert_exists("shanxia2.0")
sql = _compile(clause)
assert "purchase_cert_url" in sql
assert "transport_cert_url" in sql
assert "legal_use_cert_url" in sql
assert "is_toxic" in sql
assert "is_explosive" in sql
@@ -0,0 +1,29 @@
"""运输计划解析司机:车辆未关联司机时允许为空。"""
from __future__ import annotations
from unittest.mock import MagicMock
from app.services.pl_plan_service import _resolve_driver
def test_resolve_driver_without_vehicle_link_returns_none():
"""未显式选司机、车辆也无关联司机时,应返回空三元组而非 400。"""
db = MagicMock()
db.query.return_value.filter.return_value.order_by.return_value.first.return_value = None
result = _resolve_driver(db, "tenant-1", "vehicle-1", None)
assert result == (None, None, None)
def test_resolve_driver_with_explicit_id_returns_personnel():
db = MagicMock()
personnel = MagicMock()
personnel.id = "driver-1"
personnel.personnel_name = "张三"
personnel.phone_no = "13800000000"
db.query.return_value.filter.return_value.first.return_value = personnel
result = _resolve_driver(db, "tenant-1", "vehicle-1", "driver-1")
assert result == ("driver-1", "张三", "13800000000")
@@ -0,0 +1,94 @@
"""运输计划司机/现场公共链接:归档后应标记并拦截写操作。"""
from types import SimpleNamespace
from app.api.pl.public_io_order import _resolve_io_order_link_flags
from app.api.pl.public_site import _resolve_site_link_flags
from app.api.pl.public_transport import _resolve_driver_link_flags
from app.schemas.pl.transport import PublicTransportPageRead, PublicTransportSitePageRead
def test_driver_link_flags_archived_when_plan_archived():
plan = SimpleNamespace(follow_status="completed", archive_status="archived")
transport = SimpleNamespace(transport_status="arranged")
voided, archived = _resolve_driver_link_flags(plan, transport)
assert voided is False
assert archived is True
def test_driver_link_flags_voided_takes_precedence_shape():
plan = SimpleNamespace(follow_status="cancelled", archive_status="unarchived")
transport = SimpleNamespace(transport_status="arranged")
voided, archived = _resolve_driver_link_flags(plan, transport)
assert voided is True
assert archived is False
def test_driver_link_flags_voided_by_transport_cancelled():
plan = SimpleNamespace(follow_status="arranged", archive_status="unarchived")
transport = SimpleNamespace(transport_status="cancelled")
voided, archived = _resolve_driver_link_flags(plan, transport)
assert voided is True
assert archived is False
def test_site_link_flags_archived_when_plan_archived():
plan = SimpleNamespace(follow_status="completed", archive_status="archived")
voided, archived = _resolve_site_link_flags(plan)
assert voided is False
assert archived is True
def test_site_link_flags_voided_when_cancelled():
plan = SimpleNamespace(follow_status="cancelled", archive_status="unarchived")
voided, archived = _resolve_site_link_flags(plan)
assert voided is True
assert archived is False
def test_site_link_flags_false_when_no_plan():
voided, archived = _resolve_site_link_flags(None)
assert voided is False
assert archived is False
def test_public_transport_page_schema_exposes_plan_archived():
page = PublicTransportPageRead(
planNo="P1",
planType="sale",
planArchived=True,
)
dumped = page.model_dump(by_alias=True)
assert dumped["planArchived"] is True
def test_public_site_page_schema_exposes_archived():
page = PublicTransportSitePageRead(
businessType="入库",
partnerCompany="A",
vehicleNo="浙A",
archived=True,
)
dumped = page.model_dump(by_alias=True)
assert dumped["archived"] is True
def test_io_order_link_flags_archived_when_plan_archived():
plan = SimpleNamespace(follow_status="completed", archive_status="archived")
header = SimpleNamespace(status="completed")
voided, archived = _resolve_io_order_link_flags(plan, header)
assert voided is False
assert archived is True
def test_io_order_link_flags_voided_by_header_or_plan():
plan = SimpleNamespace(follow_status="cancelled", archive_status="unarchived")
header = SimpleNamespace(status="in_progress")
voided, archived = _resolve_io_order_link_flags(plan, header)
assert voided is True
assert archived is False
plan2 = SimpleNamespace(follow_status="arranged", archive_status="unarchived")
header2 = SimpleNamespace(status="voided")
voided2, archived2 = _resolve_io_order_link_flags(plan2, header2)
assert voided2 is True
assert archived2 is False
@@ -0,0 +1,57 @@
"""安排运输:司机可选。"""
from __future__ import annotations
from types import SimpleNamespace
from app.api.pl.transport import _apply_transport_arrange_fields
from app.schemas.pl.transport import TransportArrange
def test_transport_arrange_schema_allows_missing_driver():
payload = TransportArrange.model_validate({"vehicleId": "veh-1"})
assert payload.vehicle_id == "veh-1"
assert payload.driver_id is None
def test_apply_transport_arrange_fields_without_driver():
transport = SimpleNamespace(
vehicle_id=None,
license_plate=None,
driver_id="old",
driver_name="旧司机",
driver_phone="1",
carrier_id=None,
carrier_name=None,
transport_medium=None,
start_point=None,
end_point=None,
distance_km=None,
unit=None,
freight_price=None,
freight_amount=0,
freight_type="by_weight",
has_invoice=0,
remark=None,
update_by=None,
)
payload = TransportArrange.model_validate(
{"vehicleId": "veh-1", "freightType": "by_weight"}
)
_apply_transport_arrange_fields(
transport,
payload=payload,
vehicle_info={"license_plate": "粤A12345", "carrier_id": None},
driver_info=None,
carrier_name=None,
start_point="A",
end_point="B",
freight_amount=0,
user_id="u1",
)
assert transport.vehicle_id == "veh-1"
assert transport.license_plate == "粤A12345"
assert transport.driver_id is None
assert transport.driver_name is None
assert transport.driver_phone is None
+2
View File
@@ -15665,11 +15665,13 @@ CREATE TABLE `pl_plan` (
`pickup_lng` decimal(10,6) DEFAULT NULL COMMENT '取货经度',
`pickup_lat` decimal(10,6) DEFAULT NULL COMMENT '取货纬度',
`pickup_time` datetime DEFAULT NULL COMMENT '取货时间',
`pickup_contact` varchar(200) DEFAULT NULL COMMENT '取货联系方式',
`pickup_notes` varchar(500) DEFAULT NULL COMMENT '取货注意事项',
`destination_address` varchar(500) DEFAULT NULL COMMENT '目的地地址',
`destination_lng` decimal(10,6) DEFAULT NULL COMMENT '送货经度',
`destination_lat` decimal(10,6) DEFAULT NULL COMMENT '送货纬度',
`delivery_time` datetime DEFAULT NULL COMMENT '送达时间',
`delivery_contact` varchar(200) DEFAULT NULL COMMENT '送货联系方式',
`destination_notes` varchar(500) DEFAULT NULL COMMENT '目的地注意事项',
`transport_id` varchar(64) DEFAULT NULL COMMENT '运输ID',
`transport_no` varchar(32) DEFAULT NULL COMMENT '运输编号',
@@ -0,0 +1,128 @@
# 合同审批中/已审批可再编辑回草稿 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 允许 `approving` / `approved`(未执行)合同再次编辑;保存后变为 `draft` 并清理进行中审批,可再次提交审批。
**Architecture:** 后端放宽 `update_contract` 状态门禁,保存时统一回草稿并按需 `delete_pending_approvals`。前端抽出可编辑状态与确认文案工具函数,列表/详情/查看弹窗打开编辑前对非草稿可编辑状态弹确认。
**Tech Stack:** Python 3.9 / FastAPI CRUD、pytest、Vue 3 / Element Plus
**Spec:** `docs/superpowers/specs/2026-08-05-crm-contract-reedit-to-draft-design.md`
---
## File map
| 文件 | 职责 |
|------|------|
| `backend/app/crud/crm/contract.py` | `update_contract`:可编辑状态校验 + 回草稿副作用 |
| `backend/tests/test_crm_contract_reedit_to_draft.py` | 门禁断言单测 |
| `web-admin/src/views/crm/contract/contractType.ts` | `isContractEditableStatus`、`getContractReeditConfirmMessage` |
| `web-admin/src/views/crm/contract/index.vue` | 列表编辑按钮与 `handleUpdate` |
| `web-admin/src/views/crm/contract/detail.vue` | 详情「修改」按钮与 `handleEdit` |
| `web-admin/src/views/crm/contract/components/ContractDetailDialog.vue` | 查看弹窗「修改」 |
---
### Task 1: 后端 `update_contract` 放宽门禁 + 回草稿
**Files:**
- Modify: `backend/app/crud/crm/contract.py`(`update_contract`)
- Create: `backend/tests/test_crm_contract_reedit_to_draft.py`
- [x] **Step 1: 增加可编辑状态常量与断言函数(紧挨 `update_contract` 之前)**
- [x] **Step 2: 改写 `update_contract` 门禁与回草稿副作用**
- [x] **Step 3: 写单测**
- [x] **Step 4: 运行单测**
---
### Task 2: 前端共享工具函数
**Files:**
- Modify: `web-admin/src/views/crm/contract/contractType.ts`
- [ ] **Step 1: 追加导出**
```typescript
export const CONTRACT_EDITABLE_STATUSES = ['draft', 'approving', 'approved'] as const
export type ContractEditableStatus = (typeof CONTRACT_EDITABLE_STATUSES)[number]
export function isContractEditableStatus(status?: string | null): boolean {
return CONTRACT_EDITABLE_STATUSES.includes(
(status || '').trim() as ContractEditableStatus
)
}
export function getContractReeditConfirmMessage(status?: string | null): string | null {
const s = (status || '').trim()
if (s === 'approving') {
return '编辑保存后将作废当前审批流,合同变回草稿,需重新提交审批'
}
if (s === 'approved') {
return '编辑保存后合同将变回草稿,需重新提交审批'
}
return null
}
```
---
### Task 3: 合同列表 `index.vue`
**Files:**
- Modify: `web-admin/src/views/crm/contract/index.vue`
- [ ] **Step 1: import** `isContractEditableStatus`、`getContractReeditConfirmMessage` from `./contractType`
- [ ] **Step 2: 编辑按钮** `:disabled="single || !isContractEditableStatus(selectedRows[0]?.status)"`
- [ ] **Step 3: `handleUpdate` 改为 async:可编辑校验 → 有确认文案则 `$modal.confirm` → 打开表单弹窗**
文案失败提示:`仅草稿、审批中或已审批(未执行)的合同才能修改`
---
### Task 4: 详情页 `detail.vue`
**Files:**
- Modify: `web-admin/src/views/crm/contract/detail.vue`
- [ ] **Step 1: 「修改」按钮** `v-if="isContractEditableStatus(contract?.status)"`
- [ ] **Step 2: `handleEdit` 同样:校验 → 确认 → `router.push` 表单页
---
### Task 5: 查看弹窗 `ContractDetailDialog.vue`
**Files:**
- Modify: `web-admin/src/views/crm/contract/components/ContractDetailDialog.vue`
- [ ] **Step 1: 「修改」按钮 v-if 使用 `isContractEditableStatus`**
- [ ] **Step 2: `handleDetailEdit`:校验 → 确认 → 关闭详情并打开编辑弹窗**
---
### Task 6: 验收与图谱
- [ ] 再跑 `pytest tests/test_crm_contract_reedit_to_draft.py -v`
- [ ] 对照 spec 验收要点手工核对
- [ ] `./scripts/update-graph.sh backend` 与 `./scripts/update-graph.sh frontend`
---
## Spec coverage
| Spec 要求 | Task |
|-----------|------|
| 可编辑 draft/approving/approved | 1, 2 |
| 不开放 executing/finished/invalid | 1, 3–5 |
| 打开编辑前确认文案 | 2–5 |
| 保存回 draft + 清 approval_status | 1 |
| approving 清理待审 | 1 |
| 提交审批仍仅 draft | 不变 |
| 列表/详情/弹窗入口 | 3–5 |
@@ -0,0 +1,44 @@
# 地址库选择:编辑 + 联系方式回填 + 简易检索 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 运输计划「从地址库选择」支持编辑地址、简易工具栏检索、选中后回填「姓名 电话」到联系方式,并去掉坐标列。
**Architecture:** 改动集中在选择弹窗与 `PlAddressWithLibrary`;父表单通过可选 `v-model:contact` 接收回填。后端 list `q` 已覆盖名称/地址/联系人/电话,无需改 API。
**Tech Stack:** Vue 3 + Element Plus + 现有 `transportAddressApi`
**Spec:** `docs/superpowers/specs/2026-08-06-pl-address-select-edit-and-contact-fill-design.md`
---
### Task 1: 选择弹窗 — 检索 / 列表 / 编辑
**Files:**
- Modify: `web-admin/src/components/business/pl-transport-address-select-dialog/index.vue`
- [x] 移除顶部 `filter-block`;工具栏增加简易 `el-input`(回车/清空检索)+「新增地址」
- [x] 去掉「坐标」列;操作列增加「编辑」,`min-width` ≥ 160
- [x] 嵌套表单支持新增/编辑:`editingId`、标题切换、`update` 成功后刷新列表不 select
- [x] 新增成功仍 `handleConfirm`
### Task 2: 地址组件联系方式回填
**Files:**
- Modify: `web-admin/src/components/business/pl-address-with-library/index.vue`
- [x] 增加可选 `contact` prop + `update:contact`
- [x] `handleLibrarySelect`:有联系信息时 emit `姓名 电话`(或单侧)
### Task 3: 父表单绑定
**Files:**
- Modify: `web-admin/src/components/business/pl-plan-form-dialog/index.vue`
- Modify: `web-admin/src/components/business/pl-plan-arrange-dialog/index.vue`
- [x] 取货/送货 `PlAddressWithLibrary` 增加 `v-model:contact` 绑定对应联系方式字段
### Task 4: 收尾
- [x] `./scripts/update-graph.sh frontend`(或 `graphify update .`)
- [ ] 手工核对:检索、编辑、选择回填、空联系人不覆盖
@@ -0,0 +1,44 @@
# 运输计划「从承运商库选择」Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 运输计划弹窗「运输公司」旁提供「从承运商库选择」,支持搜索/选择/新增/编辑并回填 `carrierId`。
**Architecture:** 对齐车辆库/地址库:`PlCarrierLibrarySelectDialog` + 嵌套 `PlCarrierFormDialog`(对照 `views/pl/carrier`);计划表单旁按钮接入。
**Tech Stack:** Vue 3 + Element Plus + `carrierApi`
**Spec:** `docs/superpowers/specs/2026-08-06-pl-plan-carrier-library-select-design.md`
---
## 文件结构
| 操作 | 文件 |
|------|------|
| Create | `web-admin/src/components/business/pl-carrier-form-dialog/index.vue` |
| Create | `web-admin/src/components/business/pl-carrier-library-select-dialog/index.vue` |
| Modify | `web-admin/src/components/business/pl-plan-form-dialog/index.vue` |
---
### Task 1: PlCarrierFormDialog
- [x] Props: `modelValue`, `carrierId?`;Emits: `update:modelValue`, `saved({ mode, carrier })`
- [x] 弹窗 960px,对照管理页完整表单 + 资质附件
- [x] create/update;create 返回详情 emit;edit 后 get 再 emit
### Task 2: PlCarrierLibrarySelectDialog
- [x] 1200px 选弹窗;搜索 + 列表 + 选择/编辑 + 新增
- [x] 新增成功 auto-select;编辑成功刷新列表
### Task 3: 接入计划表单
- [x] 运输公司旁「从承运商库选择」;`ensureSelectedCarrierOption` 回填
### Task 4: 收尾
- [x] 设计文档状态 → 已实现
- [x] `./scripts/update-graph.sh frontend`
- [ ] 浏览器走查(代码已就绪,需本地验证)
@@ -0,0 +1,30 @@
# 危化品证上传筛选 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 危化品证上传页只展示含易制毒/易制爆的计划,并新增「未上传证书」Tab。
**Architecture:** 在 `pl_plan_service` 提供 EXISTS 子查询过滤器;`list_plans` 暴露查询参数;本页 Tab 扩展并始终带上筛选参数。
**Tech Stack:** FastAPI + SQLAlchemy、Vue 3、pytest
---
## File map
| File | Responsibility |
|------|----------------|
| `backend/app/services/pl_plan_service.py` | `plan_has_hazard_product_exists` / `plan_has_incomplete_hazard_cert_exists` |
| `backend/app/api/pl/plan.py` | `list_plans` 接入新参数 |
| `backend/tests/test_pl_plan_cert_list_filters.py` | SQL/行为单测 |
| `web-admin/src/api/pl/index.ts` | `PlanQuery` 字段 |
| `web-admin/src/utils/pl-display.ts` | 本页 Tab 常量与映射 |
| `web-admin/src/components/business/pl-plan-type-tabs/index.vue` | 可选 `tabs` |
| `web-admin/src/views/pl/plan-cert/index.vue` | 请求参数与 Tab 行为 |
## Tasks
- [x] Task 1: 后端过滤器单测(红)
- [x] Task 2: 实现过滤器并接入 `list_plans`(绿)
- [x] Task 3: 前端 Tab + API 参数
- [x] Task 4: 跑测与 graphify 更新
@@ -0,0 +1,19 @@
# 运输计划取货/送货联系方式 Implementation Plan
> **For agentic workers:** Steps use checkbox syntax for tracking.
**Goal:** 在 `pl_plan` 增加取货/送货联系方式,并同步表单布局与各展示面。
**Architecture:** 仅计划表落库;出入库与公开页从计划合并/读取。
**Tech Stack:** FastAPI + SQLAlchemy + Vue 3 web-admin
---
## Tasks
- [x] DB migration + `docs/sql/shanxia2.0.sql` CREATE
- [x] Model / schemas / plan+transport+public APIs / merge service + unit test
- [x] Form dialog + arrange dialog layout & bind
- [x] View tabs + IoOrder view + public H5 + driver summary text
- [x] Frontend API types
@@ -0,0 +1,367 @@
# 运输计划「从车辆库选择」Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 在运输计划新增/编辑弹窗车牌号旁提供「从车辆库选择」,弹窗分三方/自有 Tab,支持搜索、选择、新增、编辑,并回填计划车辆。
**Architecture:** 对齐 `PlTransportAddressSelectDialog`:计划表单旁按钮打开 `PlVehicleLibrarySelectDialog`(Tab + 列表);嵌套 `PlVehicleFormDialog` 对照 `views/pl/vehicle` / `views/pl/self-vehicle` 完整表单。选择或新增成功后写 `vehicleId` 并走现有 `handleVehicleChange`。首期不改造两管理页。
**Tech Stack:** Vue 3 + Element Plus + 现有 `vehicleApi` / `usePlRemoteVehicleOptions` / `PlVehicleCertPartTabs`
**Spec:** `docs/superpowers/specs/2026-08-06-pl-plan-vehicle-library-select-design.md`
---
## 文件结构
| 操作 | 文件 | 职责 |
|------|------|------|
| Create | `web-admin/src/components/business/pl-vehicle-form-dialog/index.vue` | 新增/编辑车辆完整表单(`vehicleType: 'carrier' \| 'self'`) |
| Create | `web-admin/src/components/business/pl-vehicle-library-select-dialog/index.vue` | 选车大弹窗:Tab + 搜索 + 列表 + 挂载表单弹窗 |
| Modify | `web-admin/src/components/business/pl-plan-form-dialog/index.vue` | 车牌旁按钮 + 选车回填 |
参考(只读对照,勿在首期强行抽离改造):
- `web-admin/src/components/business/pl-transport-address-select-dialog/index.vue`
- `web-admin/src/components/business/pl-address-with-library/index.vue`
- `web-admin/src/views/pl/vehicle/index.vue`(三方表单弹窗)
- `web-admin/src/views/pl/self-vehicle/index.vue`(自有表单弹窗)
---
### Task 1: `PlVehicleFormDialog` — 完整新增/编辑表单
**Files:**
- Create: `web-admin/src/components/business/pl-vehicle-form-dialog/index.vue`
- [x] **Step 1: 建立组件壳与 API**
Props / 事件约定:
```ts
const props = defineProps<{
modelValue: boolean
/** carrier=三方,self=自有;锁定类型,不可切换 */
vehicleType: 'carrier' | 'self'
/** 有值则为编辑,无值则为新增 */
vehicleId?: string | null
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
/** 新增成功:返回详情;编辑成功:返回详情(父级刷新列表用) */
saved: [payload: { mode: 'create' | 'edit'; vehicle: VehicleDetail }]
}>()
```
弹窗:
- `width="1360px"`,`class="dialog-form-layout"`,`append-to-body`,`destroy-on-close`
- `modal-class="order-module-dialog-mask"`,`style="backdrop-filter: none"`
- 标题:
- create + carrier → `新增车辆`
- create + self → `新增自有车辆`
- edit + carrier → `编辑车辆`
- edit + self → `编辑自有车辆`
- [x] **Step 2: 移植表单 UI 与状态**
从 `views/pl/vehicle/index.vue` / `self-vehicle/index.vue` 的 `el-dialog` 表单区对照实现:
1. 基本信息 `form-grid-3`:车牌号、挂车号、载重、承运商、车辆状态、备注、车辆照片(`AttachmentUploadField`,`upload-folder="pl/vehicle-photo"`)
2. 关联人员子表(添加人员 / 角色 driver|escort / 删除)
3. `PlVehicleCertPartTabs`:
- `vehicleType === 'self'`:`enforce-self-vehicle-required`(与自有页一致)
- `vehicleType === 'carrier'`:`:enforce-self-vehicle-required="false"` 且 `:enforce-carrier-vehicle-required="false"`(与三方页一致)
人员远程选项:
```ts
usePlRemotePersonnelOptions({
listParams: () => ({
status: '1',
personnelAffiliation: props.vehicleType === 'carrier' ? 'carrier' : 'self'
})
})
```
证书槽初始化:
- carrier:`ensureVehicleCertSlots(..., trailerNo, 'carrier')`
- self:`ensureSelfVehicleCertSlots(..., trailerNo)`
校验:复用管理页 `validateSubTables` 逻辑(人员必选、角色、`validatePersonnelTypeRoleCompat`、`validatePersonnelAffiliationVehicleCompat`)。
- [x] **Step 3: open / submit**
`@open` 或 `watch(modelValue)`:
- 新增:重置表单;`vehicleStatus='available'`;证书空槽;加载人员选项
- 编辑:`vehicleApi.get(vehicleId)` 回填;编辑自有时若 `detail.vehicleType !== 'self'` 则警告并关闭;`ensureSelectedCarrierOption`;`nextTick` 后再填证书并 `refreshRequiredSlots`
提交 payload 与管理页一致(含 `personnelList` / `certList`);`vehicleType` 固定为 prop。
```ts
if (isEdit) {
await vehicleApi.update(formData.id, payload)
const res = await vehicleApi.get(formData.id)
const detail = pickBxData<VehicleDetail>(res)!
emit('saved', { mode: 'edit', vehicle: detail })
} else {
const res = await vehicleApi.create(payload)
let detail = pickBxData<VehicleDetail>(res)
if (!detail?.id) {
// 若 create 未回详情,不应发生;兜底可再 get —— 优先用返回体
ElMessage.error('新增成功但未返回车辆信息')
return
}
emit('saved', { mode: 'create', vehicle: detail })
}
```
成功后关闭弹窗;上传中拦截与管理页相同文案。
- [ ] **Step 4: 手工冒烟(可选先挂临时入口)**
在浏览器临时打开组件或等 Task 2 挂载后验证:三方/自有各新增一条、各编辑一条,证书与人员校验行为与管理页一致。
- [ ] **Step 5: Commit(若用户要求提交时再执行)**
```bash
git add web-admin/src/components/business/pl-vehicle-form-dialog/index.vue
git commit -m "$(cat <<'EOF'
feat(web-admin): add PlVehicleFormDialog for carrier/self vehicle CRUD
EOF
)"
```
---
### Task 2: `PlVehicleLibrarySelectDialog` — Tab 选车弹窗
**Files:**
- Create: `web-admin/src/components/business/pl-vehicle-library-select-dialog/index.vue`
- [x] **Step 1: 弹窗外壳(对齐地址库选择)**
```vue
<el-dialog
v-model="innerVisible"
title="从车辆库选择"
width="1360px"
align-center
destroy-on-close
append-to-body
class="dialog-form-layout pl-vehicle-library-select-dialog"
modal-class="order-module-dialog-mask"
:close-on-click-modal="false"
style="backdrop-filter: none"
@open="handleOpen"
>
```
结构:
1. `el-tabs`:`carrier` / `self`(文案:三方车辆 / 自有车辆)
2. 工具栏:`el-input` 搜索(placeholder:`搜索车牌号`,回车/清空检索)+ `type="primary"`「新增车辆」
3. `ListTable` + `ListPagination`(`dialog-list-body-only` 风格参考地址库弹窗)
4. 嵌套 `<PlVehicleFormDialog v-model="formVisible" :vehicle-type="activeTab" :vehicle-id="editingId" @saved="handleFormSaved" />`
- [x] **Step 2: 列表与选择**
```ts
async function fetchList() {
loading.value = true
try {
const res = await vehicleApi.list({
vehicleType: activeTab.value, // 'carrier' | 'self'
q: keyword.value.trim() || undefined,
page: pagination.page,
pageSize: pagination.pageSize
})
const { list, total } = pickBxPageResult<Vehicle>(res)
rows.value = list
pagination.total = total
} finally {
loading.value = false
}
}
```
列:序号、车牌号(`el-link` → `handleConfirm`)、挂车号、车辆状态 Tag、载重、承运商(`v-if="activeTab === 'carrier'"`)、关联人员摘要、操作(编辑 / 选择)。
```ts
function handleConfirm(row: Vehicle) {
emit('select', row)
innerVisible.value = false
}
function handleFormSaved(payload: { mode: 'create' | 'edit'; vehicle: VehicleDetail }) {
formVisible.value = false
editingId.value = null
if (payload.mode === 'create') {
handleConfirm(payload.vehicle)
return
}
fetchList()
}
```
样式:`:deep(.el-dialog__body) { min-height: 560px; }`;表格 `:max-height="560"`。
- [x] **Step 3: Tab / 打开重置**
`handleOpen`:keyword 清空、page=1、activeTab 默认 `carrier`、关表单、`fetchList`。
Tab `@tab-change`:page=1 再 `fetchList`。
- [ ] **Step 4: Commit(若用户要求)**
```bash
git add web-admin/src/components/business/pl-vehicle-library-select-dialog/index.vue
git commit -m "$(cat <<'EOF'
feat(web-admin): add vehicle library select dialog with carrier/self tabs
EOF
)"
```
---
### Task 3: 接入运输计划表单弹窗
**Files:**
- Modify: `web-admin/src/components/business/pl-plan-form-dialog/index.vue`
- [x] **Step 1: 车牌号旁按钮布局**
将原「车牌号」单项改为与地址库相同的行布局:
```vue
<el-form-item label="车牌号">
<div class="pl-plan-vehicle-with-library">
<el-select
v-model="formData.vehicleId"
class="pl-plan-vehicle-with-library__select"
placeholder="请选择车牌号"
filterable
remote
clearable
:remote-method="searchVehicles"
:loading="vehicleSelectLoading || vehicleLoading"
@focus="onVehicleSelectFocus"
@change="handleVehicleChange"
>
<el-option
v-for="item in vehicleList"
:key="item.id"
:label="item.licensePlate"
:value="item.id"
/>
</el-select>
<el-button
class="pl-plan-vehicle-with-library__btn btn-ghost"
@click="vehicleLibraryVisible = true"
>
<el-icon><FolderOpened /></el-icon>从车辆库选择
</el-button>
</div>
</el-form-item>
<PlVehicleLibrarySelectDialog
v-model="vehicleLibraryVisible"
@select="handleVehicleLibrarySelect"
/>
```
样式(scoped,对照 `pl-address-with-library`):
```scss
.pl-plan-vehicle-with-library {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
}
.pl-plan-vehicle-with-library__select {
flex: 1 1 auto;
min-width: 0;
}
.pl-plan-vehicle-with-library__btn {
flex: 0 0 auto;
white-space: nowrap;
}
```
- [x] **Step 2: 回填处理**
```ts
const vehicleLibraryVisible = ref(false)
async function handleVehicleLibrarySelect(vehicle: Vehicle) {
if (!vehicle?.id) return
await ensureSelectedVehicleOption(vehicle.id)
formData.vehicleId = vehicle.id
await handleVehicleChange(vehicle.id)
if (vehicle.carrierId) {
await ensureSelectedCarrierOption(vehicle.carrierId)
}
}
```
导入:`FolderOpened`、`PlVehicleLibrarySelectDialog`、类型 `Vehicle`(若尚未导入)。
- [ ] **Step 3: Commit(若用户要求)**
```bash
git add web-admin/src/components/business/pl-plan-form-dialog/index.vue
git commit -m "$(cat <<'EOF'
feat(web-admin): wire vehicle library select into plan form dialog
EOF
)"
```
---
### Task 4: 验收与图谱
- [ ] **Step 1: 手工验收清单**(代码已就绪,需在本地浏览器走查)
在 `/#/pl/plan-module/plan` 打开新增/编辑运输计划:
1. 车牌旁可见「从车辆库选择」,布局与「从地址库选择」同类
2. 弹窗 1360 宽、偏高;Tab 切换三方/自有列表正确过滤
3. 搜索车牌有效;选择 / 链接 / 双击可回填车牌,摘要条与承运商更新
4. 三方 Tab「新增车辆」:完整表单可保存,成功后自动选中并关闭选车弹窗
5. 自有 Tab「新增自有车辆」:证书强制与自有管理页一致;成功后回填
6. 「编辑」保存后列表刷新,计划已选车不被覆盖;选车弹窗仍打开
7. 遮罩无 blur;按钮均有图标
- [x] **Step 2: 更新前端图谱**
```bash
./scripts/update-graph.sh frontend
```
或在仓库根目录:`graphify update .`(仅 AST)
- [x] **Step 3: 将设计文档状态改为已实现(实现完成后)**
`docs/superpowers/specs/2026-08-06-pl-plan-vehicle-library-select-design.md` 顶部 `状态:设计中` → `已实现`
---
## Spec 覆盖自检
| Spec 要求 | Task |
|-----------|------|
| 车牌旁按钮「从车辆库选择」 | Task 3 |
| Tab 三方/自有 + 搜索分页 | Task 2 |
| 选择/链接/双击回填 + handleVehicleChange | Task 2 + 3 |
| 新增完整表单(对照管理页) | Task 1 + 2 |
| 编辑 + 刷新列表不自动选中 | Task 1 + 2 |
| 新增成功自动选中关弹窗 | Task 2 |
| 大尺寸 1360 / 列表偏高 | Task 1 + 2 |
| 不改两管理页 | 全任务遵守 |
| 图谱更新 | Task 4 |
@@ -0,0 +1,75 @@
# 合同管理:审批中 / 已审批合同可再编辑并回草稿
## 目标
合同管理支持对「审批中」「已审批(尚未执行)」的合同再次编辑;**编辑保存后**合同变为草稿,可再次提交审批。
采用方案:**编辑保存时回草稿**(不新增独立「退回草稿」动作)。
## 可编辑状态
| 合同状态 `status` | 可否编辑 | 说明 |
|-------------------|----------|------|
| `draft` | 是 | 含审批驳回后回草稿的现有行为 |
| `approving` | 是 | 审批中;保存后作废当前审批流并回草稿 |
| `approved` | 是 | 已审批且尚未开始执行 |
| `executing` / `finished` / `invalid` | 否 | 不在本需求范围;走现有执行 / 变更 / 作废流程 |
## 前端行为
### 打开编辑前确认
对 `approving`、`approved`,在打开编辑弹窗 / 页面之前弹出确认;用户取消则不打开。
| 原状态 | 确认文案 |
|--------|----------|
| `approving` | 编辑保存后将作废当前审批流,合同变回草稿,需重新提交审批 |
| `approved` | 编辑保存后合同将变回草稿,需重新提交审批 |
`draft`(含已驳回)直接打开编辑,无需该确认。
### 入口
以下入口对 `approving`、`approved` 解锁编辑,并走上述确认:
- 合同列表工具栏「编辑」
- 合同详情页 / 查看弹窗「修改」
「提交审批」仍仅 `draft` 可用(保存回草稿后即可再提)。
### 未保存
仅打开编辑、未点保存时,合同状态保持不变。
## 后端行为(更新合同)
放宽更新接口状态校验:允许 `draft` / `approving` / `approved` 更新;其余状态仍拒绝(如「仅草稿 / 审批中 / 已审批(未执行)的合同才能修改」)。
保存成功时统一副作用:
1. `status` 置为 `draft`
2. `approval_status` 清空(`null`)
3. 若原状态为 `approving`:清理待审批记录(复用现有撤回审批的清理逻辑,如 `delete_pending_approvals`)
4. 若原状态为 `approved`:同样清空审批状态;历史审批记录可保留只读展示,不阻塞再次提审
创建与更新字段校验、产品明细等现有业务规则不变;仅放宽状态门禁并增加回草稿副作用。
## 不变范围
- `executing` / `finished` / `invalid` 不可通过本能力直接改合同
- 运输计划等下游仍仅可关联 `approved` / `executing`;合同回草稿后暂时不可新建关联计划,属预期
- 不改审批通过 / 驳回 / 开始执行等既有流转
- 不新增独立「退回草稿」API(本方案在更新保存时完成状态回退)
## 改动落点(实现时)
- `backend/app/crud/crm/contract.py`:`update` 状态门禁;保存后回 `draft` + 清审批状态;审批中清理待审记录
- `web-admin` 合同列表 / 详情 / 查看弹窗 / 表单入口:可编辑状态判断 + 打开编辑前确认文案
## 验收要点
1. 审批中合同:确认 → 编辑 → 保存后为草稿,待审记录已清理,可再提交审批
2. 已审批(未执行)合同:确认 → 编辑 → 保存后为草稿,可再提交审批;保存前下游仍可按原状态关联
3. 执行中 / 已完成 / 已作废:仍不可编辑
4. 草稿 / 已驳回:行为与现网一致,无多余确认
5. 仅打开编辑未保存:状态不变
@@ -1,27 +1,30 @@
# 运输计划「从地址库选择」支持编辑并回填联系方式
**日期:** 2026-08-06
**状态:** 已设计,待实现
**选定方案:** 方案 1 — 选择弹窗内复用新增表单做编辑;选中时按「姓名 电话」回填联系方式;列表去掉坐标列
**状态:** 已实现
**选定方案:** 方案 1 — 选择弹窗内复用新增表单做编辑;选中时按「姓名 电话」回填联系方式;列表去掉坐标列;顶部筛选区改为列表工具栏简易检索
## 1. 目标
1. 在运输计划「从地址库选择」弹窗中,支持编辑已有地址库记录(不离开选择流程)。
2. 选中地址后,若地址库有联系人/联系电话,写入对应「取货联系方式」或「送货联系方式」。
3. 选择弹窗列表不再展示「坐标」列。
4. 去掉顶部 `filter-block` 检索区,改为列表上方工具栏内的简易搜索框;支持按地址名称、详细地址、联系人、电话检索(沿用接口 `q` 参数,后端已覆盖上述字段)。
## 2. 非目标
- 不改地址库管理页(`views/pl/transport-address/index.vue`)结构
- 不抽公共地址表单组件(仍在选择弹窗内复用同一嵌套表单)
- 不改后端 API(沿用现有 `transportAddressApi.update`)
- 不改后端 API(沿用现有 `transportAddressApi.update` / list `q`)
- 编辑成功后不自动选中、不关闭选择弹窗
- 地址库联系人与电话皆空时,不覆盖表单已有联系方式
## 3. 交互
### 3.1 列表
### 3.1 检索与列表
- 移除顶部筛选区块(含「搜索 / 重置」按钮组)。
- 列表工具栏:左侧(或按钮前)放一个 `el-input` 简易检索,placeholder 标明可搜「地址名称、详细地址、联系人或电话」;回车或清空时触发检索;旁侧保留主按钮「新增地址」。
- 移除「坐标」列。
- 操作列增加「编辑」(`Edit` 图标 + 文案),与「选择」并列;操作列宽度适当加大。
- 「选择」、地址名称链接、双击行:行为不变(选中并关闭)。
@@ -43,14 +46,15 @@
- 仅姓名:写入姓名;仅电话:写入电话;皆有:`姓名 电话`;皆空:不修改现有联系方式。
- 取货侧写入 `pickupContact`,送货侧写入 `deliveryContact`。
- 适用页面:运输计划表单弹窗、安排运输弹窗(凡使用 `PlAddressWithLibrary` 处)。
- 组件侧通过可选 `v-model:contact` 回填,便于两侧绑定。
## 4. 改动文件
| 文件 | 变更 |
|------|------|
| `web-admin/src/components/business/pl-transport-address-select-dialog/index.vue` | 去坐标列;操作列编辑;嵌套表单支持新增/编辑 |
| `web-admin/src/components/business/pl-address-with-library/index.vue` | 选中后拼装联系方式并 `emit`(或可选 `v-model:contact`) |
| `web-admin/src/components/business/pl-plan-form-dialog/index.vue` | 取货/送货绑定联系方式回填 |
| `web-admin/src/components/business/pl-transport-address-select-dialog/index.vue` | 去顶部筛选与坐标列;工具栏简易检索;操作列编辑;嵌套表单支持新增/编辑 |
| `web-admin/src/components/business/pl-address-with-library/index.vue` | 选中后拼装联系方式并 `update:contact` |
| `web-admin/src/components/business/pl-plan-form-dialog/index.vue` | 取货/送货绑定 `v-model:contact` |
| `web-admin/src/components/business/pl-plan-arrange-dialog/index.vue` | 同上 |
## 5. 校验与 UI
@@ -62,13 +66,15 @@
## 6. 数据流
```
选择弹窗工具栏 keyword → transportAddressApi.list({ q })
选择弹窗 → 编辑弹窗 → transportAddressApi.update
→ 刷新列表(不 select)
选择 / 新增成功 → emit('select', row)
→ pl-address-with-library:
回填 fullAddress / lng / lat
若有联系信息 → emit('update:contact' | 'select-contact', "姓名 电话")
若有联系信息 → emit('update:contact', "姓名 电话")
→ 父表单写入 pickupContact / deliveryContact
```
@@ -80,3 +86,4 @@
| 地址库联系信息为空 | A:不改动现有联系方式 |
| 编辑交互 | A:编辑保存后刷新列表,不自动选中 |
| 坐标列 | 选择弹窗列表不展示 |
| 检索 UI | 去掉顶部筛选区,改为列表工具栏简易输入框 |
@@ -0,0 +1,103 @@
# 运输计划「从承运商库选择」:选择 + 新增编辑
**日期:** 2026-08-06
**状态:** 已实现
**选定方案:** 方案 1 — 独立选承运商弹窗(对齐「从地址库选择 / 从车辆库选择」)+ 嵌套承运商表单弹窗(对照 `views/pl/carrier` 完整新增编辑)
## 1. 目标
1. 在运输计划新增/编辑弹窗「运输公司」旁增加按钮,打开承运商库选择弹窗。
2. 支持搜索、分页、选择回填计划 `carrierId`。
3. 弹窗内支持 **新增承运商**、**编辑承运商**;表单字段与交互对照承运商管理页(基本信息 + 资质附件)。
4. 新增成功后自动选中并回填;编辑成功仅刷新列表。
## 2. 非目标
- 不改造承运商管理页列表/路由(首期不强制管理页改用新抽组件)
- 不改后端 `carrierApi` 契约
- 不在选承运商弹窗中做批量删除
- 不改安排运输弹窗等其他入口(除非后续单独需求)
## 3. 交互
### 3.1 入口(计划表单)
- 位置:`pl-plan-form-dialog` 运输信息区「运输公司」`el-select` 右侧。
- 布局:与「从车辆库选择 / 从地址库选择」一致(`flex` 行,选择器 `flex:1`,按钮不换行)。
- 按钮文案:**从承运商库选择**(`FolderOpened` + 文案;`btn-ghost`)。
- 点击打开 `PlCarrierLibrarySelectDialog`。
### 3.2 选承运商弹窗
- 标题:从承运商库选择。
- 宽度 **1200px**(或与地址库一致的 1200~1360),`dialog-form-layout`,`align-center`,`append-to-body`,`destroy-on-close`,遮罩无 blur。
- 工具栏:简易搜索(placeholder:搜索承运商名称/联系人/电话,接口 `q`)+ 主按钮「新增承运商」。
- 列表列:序号、承运商名称(主链接选择)、联系人、联系电话、合作状态(Tag)、操作(编辑 / 选择)。
- 选择方式:操作「选择」、名称链接、行双击 → 关闭选弹窗并回填计划。
- 列表 `max-height`:**560**;body `min-height: 560px`。
### 3.3 新增
1. 「新增承运商」打开嵌套 `PlCarrierFormDialog`(无 `carrierId`)。
2. 表单对照 `views/pl/carrier/index.vue`:名称、合作状态、联系人、电话、备注、营业执照 / 道路经营许可证 / 运输协议附件、协议有效期。
3. 确定:`carrierApi.create`;成功后自动 `select` 并关闭选弹窗。
4. 取消:仅关闭表单弹窗。
### 3.4 编辑
1. 「编辑」打开同一表单,加载 `carrierApi.get`。
2. 确定:`carrierApi.update`;成功后刷新列表;选弹窗保持打开,**不**改计划已选承运商。
3. 取消:仅关闭表单弹窗。
### 3.5 回填计划
- 写入 `formData.carrierId`。
- 调用 `ensureSelectedCarrierOption(carrierId)` 保证下拉回显。
- 不强制改车牌/车辆摘要(承运商与车辆独立字段)。
## 4. 组件与改动文件
| 文件 | 变更 |
|------|------|
| `web-admin/src/components/business/pl-plan-form-dialog/index.vue` | 运输公司旁按钮;挂载选弹窗;处理 `select` |
| `web-admin/src/components/business/pl-carrier-library-select-dialog/index.vue` | **新建**:选承运商大弹窗 |
| `web-admin/src/components/business/pl-carrier-form-dialog/index.vue` | **新建**:新增/编辑完整表单 |
实现策略:表单弹窗对照管理页落地;首期管理页可不立刻引用该组件。
## 5. 校验与 UI
- 表单校验与管理页一致(承运商名称必填等)。
- 上传中拦截与管理页相同。
- `dialog-form-layout`,遮罩无 blur,底栏 Close / Check;按钮带图标。
- 合作状态用 `el-tag` 语义色。
## 6. 数据流
```
计划表单 → 「从承运商库选择」→ PlCarrierLibrarySelectDialog
keyword → carrierApi.list({ q, page, pageSize })
选择 / 双击 / 名称链接
→ emit('select', carrier)
→ formData.carrierId = carrier.id
→ ensureSelectedCarrierOption(id)
→ 关闭选弹窗
新增 → PlCarrierFormDialog → carrierApi.create
→ 成功后走「选择」同一路径
编辑 → PlCarrierFormDialog → carrierApi.update
→ 刷新列表(不 select、不关选弹窗)
```
## 7. 决策记录
| 项 | 结论 |
|----|------|
| 弹窗用途 | A:选承运商为主,兼新增/编辑 |
| 表单范围 | A:完整对照承运商管理页 |
| 按钮文案 | 从承运商库选择 |
| 新增成功 | 自动选中并关闭选弹窗 |
| 编辑成功 | 仅刷新列表 |
| 管理页 | 首期不强制抽离改造 |
@@ -0,0 +1,40 @@
# 危化品证上传:仅展示危化计划 +「未上传证书」Tab
## 背景
【危化品证上传】页当前复用运输计划列表,未按危化属性过滤,大量无需上传证书的计划干扰操作。
## 需求
1. 本页所有单据类型 Tab(全部 / 入库 / 出库 / 直销)仅展示至少含一件易制毒或易制爆产品的运输计划。
2. 在「直销单」后增加 Tab「未上传证书」:含危化产品,且至少一件产品缺少必需证书附件。
3. 「未上传证书」判定只看附件是否齐全,与「证书齐备」标记无关。
## 证书缺口规则(与现网一致)
- 易制毒:须有购买证、运输证(`purchaseCertUrl` / `transportCertUrl`)
- 易制爆:须有合法证明(`legalUseCertUrl`)
- 危化标识以 CRM 产品主数据为准(`is_toxic` / `is_explosive`),不信任计划产品快照
## 方案
后端 `GET /transport/plan/` 增加可选查询参数:
| 参数 | 含义 |
|------|------|
| `hasHazardProduct=1` | 计划存在危化产品(CRM) |
| `certUploadStatus=incomplete` | 存在危化产品且至少一张必需证书 URL 为空 |
本页默认始终传 `hasHazardProduct=1`;切到「未上传证书」时额外传 `certUploadStatus=incomplete`,并清空 `planType`。
运输计划、归档等其它页面不传上述参数,行为不变。
## 前端
- `PlPlanTypeTabs` 支持可选 `tabs` 覆盖,本页传入含「未上传证书」的 Tab 列表。
- Tab 值 `cert_incomplete` 与单据类型互斥。
## 非目标
- 不改证书齐备业务语义
- 不改菜单角标算法(若后续要对齐可另开需求)
@@ -0,0 +1,41 @@
# 运输计划取货/送货联系方式
## Goal
在运输计划取货信息、送货信息中各增加一个普通文本「联系方式」字段,并调整表单两行布局;查看、安排车辆、出入库、公开 H5 同步展示。
## Decision
方案 A:仅在 `pl_plan` 落库两字段;出入库/公开页经现有 `merge_plan_logistics_into_order` / 公开接口从计划带出。
## Data
| DB | API | 类型 | 说明 |
|----|-----|------|------|
| `pickup_contact` | `pickupContact` | varchar(200) NULL | 取货联系方式,非必填 |
| `delivery_contact` | `deliveryContact` | varchar(200) NULL | 送货联系方式,非必填 |
无手机号格式校验。
## UI Layout
取货 / 送货顺序(`form-grid-2`):
1. 地址(整行)
2. 时间 | 联系方式
3. 注意事项(整行)
查看态与公开页顺序一致。时间标签为「取货时间 / 送货时间」。
## Surfaces
1. 计划新增/编辑弹窗
2. 计划查看
3. 安排车辆弹窗(及通知文案若含注意事项则一并带出联系方式)
4. 出入库列表/查看(计划合并字段)
5. 公开运输 / 出入库 / 站点 H5
## Out of scope
- 出入库表独立落库联系方式
- 复用合同 `contactName` / `contactPhone`
@@ -0,0 +1,111 @@
# 运输计划「从车辆库选择」:三方 / 自有 Tab + 新增编辑
**日期:** 2026-08-06
**状态:** 已实现
**选定方案:** 方案 1 — 独立选车弹窗(对齐「从地址库选择」)+ 嵌套车辆表单弹窗(对照三方车辆 / 山峡自有车辆管理页已有新增编辑弹窗)
## 1. 目标
1. 在运输计划新增/编辑弹窗「车牌号」旁增加按钮,打开车辆库选择弹窗。
2. 选择弹窗分两个 Tab:**三方车辆**、**自有车辆**;支持搜索、分页、选择回填。
3. 各 Tab 内支持 **新增车辆**、**编辑车辆**;表单字段与交互对照现有管理页弹窗(基本信息 + 关联人员 + 车辆证书)。
4. 选车弹窗与表单弹窗均采用较大宽高,便于操作。
## 2. 非目标
- 不改造三方车辆、山峡自有车辆管理页本身的列表/路由逻辑(首期不强制两管理页改用新抽组件)
- 不改后端车辆 API 契约(沿用 `vehicleApi.list/get/create/update`)
- 不在选车弹窗中做粘贴识别、批量删除
- 不改安排运输弹窗等其他入口(除非后续单独需求)
## 3. 交互
### 3.1 入口(计划表单)
- 位置:`pl-plan-form-dialog` 运输信息区「车牌号」`el-select` 右侧。
- 布局:与 `PlAddressWithLibrary` 一致(`flex` 行,选择器 `flex:1`,按钮不换行)。
- 按钮文案:**从车辆库选择**(`FolderOpened` 图标 + 文案;`btn-ghost` 中性描边,非主色实心)。
- 点击打开 `PlVehicleLibrarySelectDialog`。
### 3.2 选车弹窗
- 标题:从车辆库选择。
- 宽度 **1360px**,`dialog-form-layout`,`align-center`,`append-to-body`,`destroy-on-close`,遮罩无 blur。
- 顶栏 `el-tabs`:`三方车辆`(`carrier`)/ `自有车辆`(`self`);切换 Tab 重置页码并重新拉列表。
- 工具栏:简易搜索(placeholder 标明可搜车牌号,接口 `q`)+ 主按钮「新增车辆」。
- 列表列:序号、车牌号(主链接选择)、挂车号、车辆状态(Tag)、载重(吨)、承运商(仅三方 Tab 显示)、关联人员摘要、操作。
- 操作列:**编辑**、**选择**(与地址库一致);`fixed="right"`,`min-width` 足够容纳两按钮。
- 选择方式:操作「选择」、车牌链接、行双击 → 关闭选车弹窗并回填计划。
- 列表 `max-height`:**560**;body 区域偏高,避免一屏过矮。
### 3.3 新增
1. 点击「新增车辆」打开嵌套 `PlVehicleFormDialog`,`vehicleType` 锁定为当前 Tab。
2. 表单对照:
- 三方:`views/pl/vehicle/index.vue` 新增弹窗(含关联人员、证书;证书校验策略与三方页一致)。
- 自有:`views/pl/self-vehicle/index.vue` 新增弹窗(含 `enforce-self-vehicle-required` 等自有规则)。
3. 确定:校验通过后 `vehicleApi.create`;成功提示「新增成功」,关闭表单弹窗,对返回车辆执行与「选择」相同逻辑(回填并关闭选车弹窗)。
4. 取消:仅关闭表单弹窗。
### 3.4 编辑
1. 点击「编辑」打开同一表单组件;标题:三方为「编辑车辆」,自有为「编辑自有车辆」。
2. 加载 `vehicleApi.get` 回填基本信息、人员、证书。
3. 确定:`vehicleApi.update`;成功提示「编辑成功」,关闭表单弹窗,**刷新当前 Tab 列表**;选车弹窗保持打开,**不**自动改计划已选车辆。
4. 取消:仅关闭表单弹窗。
### 3.5 回填计划
- 写入 `formData.vehicleId`。
- 调用现有 `handleVehicleChange(vehicleId)`:刷新 `PlVehicleSummaryStrip`、回填承运商、默认司机等,行为与下拉选车一致。
- 若下拉选项尚未包含新车,需将车辆加入 `vehicleList`(或触发一次 `searchVehicles`)以保证回显。
## 4. 组件与改动文件
| 文件 | 变更 |
|------|------|
| `web-admin/src/components/business/pl-plan-form-dialog/index.vue` | 车牌旁按钮;挂载选车弹窗;处理 `select` |
| `web-admin/src/components/business/pl-vehicle-library-select-dialog/index.vue` | **新建**:选车大弹窗(Tab + 列表 + 搜索 + 挂载表单弹窗) |
| `web-admin/src/components/business/pl-vehicle-form-dialog/index.vue` | **新建**:新增/编辑车辆完整表单;`vehicleType` prop 区分三方/自有 |
实现策略:表单弹窗**对照**两管理页已有弹窗模式落地(字段、人员子表、证书组件、校验);首期管理页可不立刻改为引用该组件,避免扩大范围。
## 5. 校验与 UI
- 表单校验、人员归属兼容、证书必填规则:分别与对应管理页一致。
- 选车/表单弹窗:`dialog-form-layout`,遮罩 `backdrop-filter: none`,底栏 Close / Check。
- 所有带文案按钮带前置 `el-icon`。
- 状态列用 `el-tag` 语义色(与车辆列表一致)。
- 列表主标识(车牌)用 `el-link type="primary"` 触发选择。
## 6. 数据流
```
计划表单 → 「从车辆库选择」→ PlVehicleLibrarySelectDialog
Tab(carrier|self) + keyword → vehicleApi.list({ vehicleType, q, page, pageSize })
选择 / 双击 / 车牌链接
→ emit('select', vehicle)
→ 计划 formData.vehicleId = vehicle.id
→ handleVehicleChange(vehicleId)
→ 关闭选车弹窗
新增 → PlVehicleFormDialog(vehicleType) → vehicleApi.create
→ 成功后走「选择」同一路径
编辑 → PlVehicleFormDialog → vehicleApi.update
→ 刷新当前 Tab 列表(不 select、不关选车弹窗)
```
## 7. 决策记录
| 项 | 结论 |
|----|------|
| 弹窗用途 | A:选车为主,兼新增/编辑(对齐地址库) |
| 表单范围 | A:完整表单(基本信息 + 人员 + 证书),对照管理页 |
| 操作列 | A:选择 + 编辑 |
| 实现方案 | 方案 1:独立选车弹窗 + 新建表单组件;管理页首期不强制抽离改造 |
| 按钮文案 | 从车辆库选择 |
| 弹窗尺寸 | 选车与表单均约 1360px 宽,列表区偏高 |
| 新增成功 | 自动选中并关闭选车弹窗 |
| 编辑成功 | 仅刷新列表,不自动选中 |
+95 -70
View File
@@ -1070,23 +1070,23 @@
"semantic_hash": ""
},
"src/api/pl/index.ts": {
"mtime": 1785808699.8540757,
"ast_hash": "9006d02ba1167a5ec553edf0f8291d4a",
"mtime": 1785970872.8240886,
"ast_hash": "daefbd0bb02f0f629cfde33fab26b550",
"semantic_hash": ""
},
"src/api/pl/public-io-order.ts": {
"mtime": 1785451222.4657166,
"ast_hash": "cfd027780ddb9c435381e8afa06fa034",
"mtime": 1785969250.5670905,
"ast_hash": "20b96215360ac170e0186c80e43385da",
"semantic_hash": ""
},
"src/api/pl/public-site.ts": {
"mtime": 1783211738.0,
"ast_hash": "f82030b5bc5f7143b2560422c09c0278",
"mtime": 1785969017.3511744,
"ast_hash": "2808f14c99ca7166d1b7f1e5daaef9f2",
"semantic_hash": ""
},
"src/api/pl/public-transport.ts": {
"mtime": 1785451220.2014697,
"ast_hash": "67c174cc3f7aabf0a8c3cda72b10b4f5",
"mtime": 1785969017.3220294,
"ast_hash": "9b006b703df46988951770a0f59622c4",
"semantic_hash": ""
},
"src/api/system.ts": {
@@ -1255,8 +1255,8 @@
"semantic_hash": ""
},
"src/components/business/pl-address-with-library/index.vue": {
"mtime": 1782907231.0,
"ast_hash": "e3c51808508324c011fe3e069edfc646",
"mtime": 1785970459.6940105,
"ast_hash": "395ed9a9f95399aa807d500fc48521b4",
"semantic_hash": ""
},
"src/components/business/pl-carrier-list-attachment-cell/index.vue": {
@@ -1315,8 +1315,8 @@
"semantic_hash": ""
},
"src/components/business/pl-paste-recognize-dialog/index.vue": {
"mtime": 1785808688.3845584,
"ast_hash": "c02675f401a112033d0b9eed7ddcd260",
"mtime": 1785922268.1114755,
"ast_hash": "aaffac3d0a2c9fae0042d167e63d079c",
"semantic_hash": ""
},
"src/components/business/pl-personnel-cert-badges/index.vue": {
@@ -1330,8 +1330,8 @@
"semantic_hash": ""
},
"src/components/business/pl-plan-arrange-dialog/index.vue": {
"mtime": 1785443462.7317212,
"ast_hash": "6589d9a536dd2988ceacc15f22383044",
"mtime": 1785970462.5940857,
"ast_hash": "83a487f5a30203f69cc3629908069aaa",
"semantic_hash": ""
},
"src/components/business/pl-plan-cert-upload-dialog/index.vue": {
@@ -1350,8 +1350,8 @@
"semantic_hash": ""
},
"src/components/business/pl-plan-form-dialog/index.vue": {
"mtime": 1785687974.0307984,
"ast_hash": "528f3c36e3cd50bd4093a8750591d218",
"mtime": 1785974030.3907259,
"ast_hash": "b9de8e039365835574967274a17d2d81",
"semantic_hash": ""
},
"src/components/business/pl-plan-hazard-cert-view-table/index.vue": {
@@ -1365,8 +1365,8 @@
"semantic_hash": ""
},
"src/components/business/pl-plan-list-product-cell/index.vue": {
"mtime": 1785688271.8190951,
"ast_hash": "845bc2c5df1a226b31f39df8d68608de",
"mtime": 1785969517.223329,
"ast_hash": "90734841138bcfdba1cfa737e35bd7cd",
"semantic_hash": ""
},
"src/components/business/pl-plan-site-feedback-dialog/index.vue": {
@@ -1380,8 +1380,8 @@
"semantic_hash": ""
},
"src/components/business/pl-plan-type-tabs/index.vue": {
"mtime": 1783242793.0,
"ast_hash": "5b5e5d2b09074aabe9a2f01485282cc6",
"mtime": 1785970891.6325305,
"ast_hash": "f00893e9b7ac7e393423a5f37c8127c9",
"semantic_hash": ""
},
"src/components/business/pl-plan-view-dialog/index.vue": {
@@ -1390,8 +1390,8 @@
"semantic_hash": ""
},
"src/components/business/pl-plan-view-tabs/index.vue": {
"mtime": 1785747844.2722924,
"ast_hash": "4edadc3dd1197533d76ed4294d203b6b",
"mtime": 1785969982.7022471,
"ast_hash": "a357a04abe3c9f84be6278ce3163d157",
"semantic_hash": ""
},
"src/components/business/pl-product-name-hazard-cell/index.vue": {
@@ -1405,8 +1405,8 @@
"semantic_hash": ""
},
"src/components/business/pl-transport-address-select-dialog/index.vue": {
"mtime": 1785689659.1411273,
"ast_hash": "80a10ecbe0f9dcc4a34c469129cd42cb",
"mtime": 1785970563.4827487,
"ast_hash": "862154db74439c32842ec1051effb75d",
"semantic_hash": ""
},
"src/components/business/pl-vehicle-cert-badges/index.vue": {
@@ -1455,8 +1455,8 @@
"semantic_hash": ""
},
"src/components/business/pl/PlVehicleSelect.vue": {
"mtime": 1785730622.748753,
"ast_hash": "5b2eb73b24d2725e34f76f0a33a1ff63",
"mtime": 1785921685.42262,
"ast_hash": "63404fa2123beef43c1cdb48bb19670d",
"semantic_hash": ""
},
"src/components/business/product-view-dialog/index.vue": {
@@ -2100,8 +2100,8 @@
"semantic_hash": ""
},
"src/composables/usePlPlanArrangeActions.ts": {
"mtime": 1783209485.0,
"ast_hash": "15e180a0d6123c1fd04fa550b62ce42b",
"mtime": 1785967990.0019155,
"ast_hash": "aed2997abed3bbe8790ba02fc7176ec7",
"semantic_hash": ""
},
"src/composables/usePlPlanViewDetail.ts": {
@@ -2109,6 +2109,11 @@
"ast_hash": "93cda33fecdeda4f1e462063408189d5",
"semantic_hash": ""
},
"src/composables/usePlRemoteOptions.ts": {
"mtime": 1785921557.5847423,
"ast_hash": "daa41b4e3e6db39c95dade80a22d3656",
"semantic_hash": ""
},
"src/composables/usePlToxicProductCertCheck.ts": {
"mtime": 1783768767.0,
"ast_hash": "e9bc2c8ed7e5d39fbbb850bdf31a45ff",
@@ -2790,8 +2795,8 @@
"semantic_hash": ""
},
"src/utils/pl-display.ts": {
"mtime": 1785454011.6286995,
"ast_hash": "2c2e8d22486a00f2eba2ca786db7eb38",
"mtime": 1785970876.102445,
"ast_hash": "79d6d55357f9d2415cc9cfcd37a04bcb",
"semantic_hash": ""
},
"src/utils/pl-document-menu-badge.ts": {
@@ -3165,8 +3170,8 @@
"semantic_hash": ""
},
"src/views/crm/contract/components/ContractDetailDialog.vue": {
"mtime": 1785826532.0972168,
"ast_hash": "d01b340ef5e06d2d8371439e410d8fee",
"mtime": 1785923871.545113,
"ast_hash": "3132f4ec9249b1a3ab4bac6e9a2816e7",
"semantic_hash": ""
},
"src/views/crm/contract/components/ContractFormDialog.vue": {
@@ -3200,13 +3205,13 @@
"semantic_hash": ""
},
"src/views/crm/contract/contractType.ts": {
"mtime": 1785826243.6920145,
"ast_hash": "b0eab96786149e6a88652caa16fdc38c",
"mtime": 1785923805.9499578,
"ast_hash": "5d56a83c8974f6ed9066b3d937225857",
"semantic_hash": ""
},
"src/views/crm/contract/detail.vue": {
"mtime": 1785826534.2113764,
"ast_hash": "0d543a840781ed35138747ccb0cab5a9",
"mtime": 1785923862.8611867,
"ast_hash": "cb4c65283229ff7ab920de5e6eb62c8c",
"semantic_hash": ""
},
"src/views/crm/contract/form.vue": {
@@ -3215,8 +3220,8 @@
"semantic_hash": ""
},
"src/views/crm/contract/index.vue": {
"mtime": 1785689714.0325837,
"ast_hash": "18ca91289bad2e59dbefcc2cda6cdf4d",
"mtime": 1785923827.912613,
"ast_hash": "a4f956a6bd6c8eb8e5bdcbb2648a08c4",
"semantic_hash": ""
},
"src/views/crm/contract/partyFields.ts": {
@@ -3545,8 +3550,8 @@
"semantic_hash": ""
},
"src/views/pl/_shared/IoOrderListPage.vue": {
"mtime": 1785689659.091739,
"ast_hash": "bb93e2dc79e6405d1d06c6867330fbbe",
"mtime": 1785969985.6579177,
"ast_hash": "6a77cddabca4256d14260f7d81dd62eb",
"semantic_hash": ""
},
"src/views/pl/carrier/index.vue": {
@@ -3590,13 +3595,13 @@
"semantic_hash": ""
},
"src/views/pl/freight/components/SettlementBillPanel.vue": {
"mtime": 1785689659.0989244,
"ast_hash": "51840c507934e531dd1b3bc6691e293a",
"mtime": 1785922537.9291928,
"ast_hash": "7de234947ccaea14604d93cedd04a52b",
"semantic_hash": ""
},
"src/views/pl/freight/components/UnsettledPlanPanel.vue": {
"mtime": 1785689659.100608,
"ast_hash": "c08ada2d289a844df5dad6621099e66c",
"mtime": 1785967241.5710683,
"ast_hash": "0dfdd295961c12807b39337f6da1f2cb",
"semantic_hash": ""
},
"src/views/pl/freight/freight-status.ts": {
@@ -3640,8 +3645,8 @@
"semantic_hash": ""
},
"src/views/pl/plan-cert/index.vue": {
"mtime": 1785689659.1079135,
"ast_hash": "b421cde5c215d96ece8c3b9d312b7016",
"mtime": 1785970959.0020485,
"ast_hash": "c0e8f641a86c9a0ea18d9a7b28c5536b",
"semantic_hash": ""
},
"src/views/pl/plan/arrange.vue": {
@@ -3660,13 +3665,13 @@
"semantic_hash": ""
},
"src/views/pl/plan/index.vue": {
"mtime": 1785689659.1071281,
"ast_hash": "e8020174adf8ad3ad5fa1cb8aab2b6b6",
"mtime": 1785969729.1505501,
"ast_hash": "6b44256ab21702d9a366d82da026ec91",
"semantic_hash": ""
},
"src/views/pl/self-vehicle/index.vue": {
"mtime": 1785689659.109709,
"ast_hash": "a37797e2867143accab0b12558d564a9",
"mtime": 1785922086.4286242,
"ast_hash": "3757a7067b8d5a10b0728b8613cf3612",
"semantic_hash": ""
},
"src/views/pl/transport-address/index.vue": {
@@ -3680,38 +3685,38 @@
"semantic_hash": ""
},
"src/views/pl/vehicle-maintenance-apply/index.vue": {
"mtime": 1785689659.11126,
"ast_hash": "0d5bdcc4f31e72d69f090d392062517b",
"mtime": 1785921778.9239457,
"ast_hash": "a3944b87a9c11edcc32b817d9298b398",
"semantic_hash": ""
},
"src/views/pl/vehicle-maintenance-process/index.vue": {
"mtime": 1785689659.1116688,
"ast_hash": "229b3bfcc3cb511a2cdd17163c844990",
"mtime": 1785921820.0448418,
"ast_hash": "b9e75cfef5f2384680c0bb724f92a01e",
"semantic_hash": ""
},
"src/views/pl/vehicle-recharge-apply/index.vue": {
"mtime": 1785689659.1125538,
"ast_hash": "f5cdcb35202021ea364e455937c02877",
"mtime": 1785921738.1104023,
"ast_hash": "f518eb3c5365207fb33ee9b8a31b6e77",
"semantic_hash": ""
},
"src/views/pl/vehicle-recharge-record/index.vue": {
"mtime": 1785689659.1142302,
"ast_hash": "44637f667f592155990ed04ae59c25e7",
"mtime": 1785921774.2132099,
"ast_hash": "d14f4733b28153679513687b1bc931f2",
"semantic_hash": ""
},
"src/views/pl/vehicle-urea-apply/index.vue": {
"mtime": 1785689659.1169739,
"ast_hash": "73095969a54820c918bacd64af40b251",
"mtime": 1785921698.241516,
"ast_hash": "118202074a0eced7c3efc0acf39f519c",
"semantic_hash": ""
},
"src/views/pl/vehicle-urea-disburse/index.vue": {
"mtime": 1785689659.117829,
"ast_hash": "4eb933206dc584be037e0c8d27b5239a",
"mtime": 1785921728.8680942,
"ast_hash": "48dcaceb4b4375f13cb8553a4de28231",
"semantic_hash": ""
},
"src/views/pl/vehicle/index.vue": {
"mtime": 1785808583.335664,
"ast_hash": "3bf2ed912aef74dc1e4da60b67f48fc9",
"mtime": 1785922156.3298674,
"ast_hash": "e7356029474598c7738c5b9d37f8f8e8",
"semantic_hash": ""
},
"src/views/public/db/inventory/index.vue": {
@@ -3720,8 +3725,8 @@
"semantic_hash": ""
},
"src/views/public/pl/_shared/PublicIoOrderPage.vue": {
"mtime": 1785452764.8623595,
"ast_hash": "ea20989911844f7a0b09ff0809adf183",
"mtime": 1785969996.7318926,
"ast_hash": "c135015b03cf4d393795dad333b1ec4d",
"semantic_hash": ""
},
"src/views/public/pl/inbound/index.vue": {
@@ -3735,13 +3740,13 @@
"semantic_hash": ""
},
"src/views/public/pl/site/index.vue": {
"mtime": 1783211793.0,
"ast_hash": "39737fda2f6962e1e26f228f53b17b97",
"mtime": 1785970000.3112607,
"ast_hash": "ab28ac92f97f21089c225c09baff56a4",
"semantic_hash": ""
},
"src/views/public/pl/transport/index.vue": {
"mtime": 1785452767.3508966,
"ast_hash": "2c37a5cc8fc350b57faab1cf238afa7e",
"mtime": 1785969992.7442434,
"ast_hash": "317777c38278e11cc552f0d01ecd6b61",
"semantic_hash": ""
},
"src/views/system/dept/index.vue": {
@@ -5228,5 +5233,25 @@
"mtime": 1780108931.0,
"ast_hash": "839d61e0376bb89e1c2bd458ecb2051b",
"semantic_hash": ""
},
"src/components/business/pl-vehicle-form-dialog/index.vue": {
"mtime": 1785973547.3175023,
"ast_hash": "34a245b113e4fe60fd155b858554b30c",
"semantic_hash": ""
},
"src/components/business/pl-vehicle-library-select-dialog/index.vue": {
"mtime": 1785973759.637234,
"ast_hash": "a9373c03f8ed44875e9dfb69be0f40af",
"semantic_hash": ""
},
"src/components/business/pl-carrier-form-dialog/index.vue": {
"mtime": 1785974010.2680976,
"ast_hash": "fd340d2d90566beae2f259c9c160c2c3",
"semantic_hash": ""
},
"src/components/business/pl-carrier-library-select-dialog/index.vue": {
"mtime": 1785974019.7895732,
"ast_hash": "11ac4aff3b926cae53089a18058e1e58",
"semantic_hash": ""
}
}
+5 -15
View File
@@ -82,28 +82,20 @@
"80": "product.ts",
"81": "Community 81",
"82": "Community 82",
"83": "StorageKeyManager",
"84": "Community 84",
"85": "handleEdit",
"86": "Community 86",
"87": "canDeleteByCreator",
"88": "index.vue",
"89": "handleDisburse",
"90": "Community 90",
"91": "Community 91",
"92": "Community 92",
"93": "loadUserOptions",
"94": "error-handle.ts",
"95": "Community 95",
"96": "Community 96",
"97": "canDeleteByCreator",
"98": "loadUserOptions",
"99": "StorageKeyManager",
"100": "v2.4.2.1 - 2025-06-16",
"101": "price-letter.ts",
"102": "handleSearch",
"103": "SettingDrawer.vue",
"104": "loadUserOptions",
"105": "index.vue",
"106": "Community 106",
"107": "Community 107",
"108": "Community 108",
@@ -112,6 +104,7 @@
"112": "Community 112",
"113": "Community 113",
"114": "index.vue",
"115": "loadUserOptions",
"116": "Community 116",
"117": "Community 117",
"118": "zh_CN.js",
@@ -119,16 +112,18 @@
"120": "Community 120",
"125": "Community 125",
"126": "Community 126",
"127": "index.vue",
"128": "Community 128",
"129": "Community 129",
"131": "detail.vue",
"132": "Community 132",
"133": "Community 133",
"134": "weighing.ts",
"136": "Community 136",
"137": "Community 137",
"140": "Community 140",
"141": "Community 141",
"142": "Community 142",
"143": "Community 143",
"144": "Community 144",
"148": "Community 148",
"150": "Community 150",
@@ -138,7 +133,6 @@
"164": "Community 164",
"166": "Community 166",
"167": "Community 167",
"168": "Community 168",
"169": "Community 169",
"170": "Community 170",
"174": "Community 174",
@@ -154,7 +148,6 @@
"194": "Community 194",
"195": "Community 195",
"196": "Community 196",
"197": "Community 197",
"202": "Community 202",
"207": "Community 207",
"208": "Community 208",
@@ -280,7 +273,6 @@
"444": "index.vue",
"445": "Community 445",
"453": "ViewKvTableCell.vue",
"454": "zh_CN.js",
"458": "Community 458",
"459": "Community 459",
"460": "Community 460",
@@ -434,7 +426,6 @@
"857": "index.ts",
"886": "index.vue",
"887": "index.vue",
"888": "fetchUserOptions",
"889": "QuoteSelector.vue",
"892": "index.vue",
"896": "MarkWonDialog.vue",
@@ -529,7 +520,6 @@
"1271": "plugin.js",
"1272": "plugin.min.js",
"1273": "index.js",
"1274": "index.js",
"1275": "index.js",
"1277": "plugin.js",
"1278": "plugin.min.js",
@@ -0,0 +1,809 @@
{
"0": "Community 0",
"1": "Community 1",
"2": "Community 2",
"3": "Community 3",
"4": "Community 4",
"5": "Community 5",
"6": "Community 6",
"7": "Community 7",
"8": "Community 8",
"9": "Community 9",
"10": "Community 10",
"11": "Community 11",
"12": "Community 12",
"13": "Community 13",
"14": "Community 14",
"15": "Community 15",
"16": "Community 16",
"17": "Ha",
"18": "Community 18",
"19": "Community 19",
"20": "Community 20",
"21": "Community 21",
"22": "Community 22",
"23": "Community 23",
"24": "Community 24",
"25": "Community 25",
"26": "theme.min.js",
"27": "Community 27",
"28": "useCommon",
"29": "Community 29",
"30": "loader.ts",
"31": "RenewDialog.vue",
"32": "index.vue",
"33": "Community 33",
"34": "main.ts",
"35": "Community 35",
"36": "VoidDialog.vue",
"37": "pl-batch-print.ts",
"38": "view-fields.ts",
"39": "Community 39",
"40": "Community 40",
"41": "colors.ts",
"42": "Community 42",
"43": "Community 43",
"44": "Community 44",
"45": "Community 45",
"46": "Community 46",
"47": "fetchCustomerDetail",
"48": "Community 48",
"49": "Community 49",
"50": "Community 50",
"51": "price-letter-template.ts",
"52": "Community 52",
"53": "Community 53",
"54": "Community 54",
"55": "Community 55",
"56": "Community 56",
"57": "Community 57",
"58": "Community 58",
"59": "fetchData",
"60": "index.vue",
"61": "Community 61",
"62": "highlight.ts",
"63": "price-letter.ts",
"64": "Community 64",
"65": "detail.vue",
"66": "Community 66",
"67": "index.vue",
"68": "Community 68",
"69": "Community 69",
"70": "Community 70",
"71": "Community 71",
"72": "Community 72",
"73": "Community 73",
"74": "Community 74",
"75": "openEdit",
"76": "handleSearch",
"77": "loadUserOptions",
"78": "customerPool.ts",
"79": "Community 79",
"80": "product.ts",
"81": "Community 81",
"82": "Community 82",
"83": "StorageKeyManager",
"84": "Community 84",
"85": "handleEdit",
"86": "Community 86",
"87": "canDeleteByCreator",
"88": "index.vue",
"89": "handleDisburse",
"90": "Community 90",
"91": "Community 91",
"92": "Community 92",
"93": "loadUserOptions",
"94": "error-handle.ts",
"95": "Community 95",
"96": "Community 96",
"97": "canDeleteByCreator",
"98": "loadUserOptions",
"99": "StorageKeyManager",
"100": "v2.4.2.1 - 2025-06-16",
"101": "price-letter.ts",
"102": "handleSearch",
"103": "SettingDrawer.vue",
"104": "loadUserOptions",
"105": "index.vue",
"106": "Community 106",
"107": "Community 107",
"108": "Community 108",
"109": "Community 109",
"110": "Community 110",
"111": "api",
"112": "Community 112",
"113": "Community 113",
"114": "index.vue",
"115": "loadUserOptions",
"116": "Community 116",
"117": "Community 117",
"118": "zh_CN.js",
"119": "Community 119",
"120": "Community 120",
"121": "zh_CN.js",
"122": "price-letter-template.ts",
"123": "contractType.ts",
"124": "fetchData",
"125": "Community 125",
"126": "Community 126",
"127": "index.vue",
"128": "Community 128",
"129": "Community 129",
"130": "price-letter.ts",
"131": "detail.vue",
"132": "Community 132",
"133": "Community 133",
"134": "weighing.ts",
"135": "detail.vue",
"136": "Community 136",
"137": "Community 137",
"138": "handleSearch",
"139": "applySortAndPage",
"140": "Community 140",
"141": "Community 141",
"142": "Community 142",
"143": "Community 143",
"144": "Community 144",
"145": "handleEdit",
"146": "zh_CN.js",
"148": "Community 148",
"150": "Community 150",
"151": "Community 151",
"161": "Community 161",
"162": "Community 162",
"164": "Community 164",
"166": "Community 166",
"167": "Community 167",
"169": "Community 169",
"170": "Community 170",
"174": "Community 174",
"178": "Community 178",
"179": "Community 179",
"180": "Community 180",
"181": "Community 181",
"182": "Community 182",
"187": "Community 187",
"188": "Community 188",
"189": "Community 189",
"190": "Community 190",
"194": "Community 194",
"195": "Community 195",
"196": "Community 196",
"202": "Community 202",
"207": "Community 207",
"208": "Community 208",
"209": "Community 209",
"210": "Community 210",
"212": "Community 212",
"213": "Community 213",
"214": "Community 214",
"219": "initNew",
"222": "types.ts",
"223": "Community 223",
"224": "Community 224",
"227": "Community 227",
"228": "Community 228",
"233": "Community 233",
"234": "Community 234",
"235": "index.vue",
"237": "index.vue",
"239": "Community 239",
"242": "Community 242",
"243": "Community 243",
"246": "price-letter-template.ts",
"247": "Community 247",
"248": "Community 248",
"251": "handleDisburse",
"253": "Community 253",
"254": "Community 254",
"255": "Community 255",
"259": "Community 259",
"260": "Community 260",
"261": "Community 261",
"265": "Community 265",
"269": "Community 269",
"270": "Community 270",
"276": "Community 276",
"280": "Community 280",
"283": "Community 283",
"284": "Community 284",
"285": "Community 285",
"286": "Community 286",
"292": "Community 292",
"293": "colors.ts",
"294": "Community 294",
"295": "Community 295",
"296": "Community 296",
"302": "Community 302",
"303": "Community 303",
"304": "Community 304",
"305": "isIoPlanFrozen",
"306": "handleArrange",
"307": "Community 307",
"308": "Community 308",
"309": "Community 309",
"310": "Community 310",
"315": "Community 315",
"316": "Community 316",
"317": "Community 317",
"318": "Community 318",
"319": "Community 319",
"320": "Community 320",
"321": "Community 321",
"322": "Community 322",
"323": "Community 323",
"324": "Community 324",
"325": "Community 325",
"326": "Community 326",
"327": "Community 327",
"328": "Community 328",
"329": "Community 329",
"330": "Community 330",
"331": "Community 331",
"332": "Community 332",
"333": "Community 333",
"334": "Community 334",
"335": "Community 335",
"336": "Community 336",
"337": "Community 337",
"338": "Community 338",
"339": "Community 339",
"340": "Community 340",
"341": "Community 341",
"342": "error-handle.ts",
"344": "ArtException.vue",
"346": "Community 346",
"347": "Community 347",
"349": "Community 349",
"350": "Community 350",
"354": "Community 354",
"355": "Community 355",
"362": "Community 362",
"364": "Community 364",
"367": "Community 367",
"372": "detail.vue",
"377": "Community 377",
"379": "Community 379",
"380": "Community 380",
"381": "Community 381",
"383": "ApproverSelector.vue",
"388": "index.vue",
"391": "Community 391",
"392": "Community 392",
"393": "Community 393",
"394": "Community 394",
"405": "zh_CN.js",
"406": "Community 406",
"407": "index.vue",
"408": "Community 408",
"409": "DbCrmCustomerSelect.vue",
"410": "Community 410",
"412": "Community 412",
"416": "Community 416",
"417": "Community 417",
"422": "Community 422",
"423": "Community 423",
"424": "Community 424",
"425": "Community 425",
"426": "Community 426",
"427": "Community 427",
"428": "Community 428",
"435": "index.vue",
"439": "index.vue",
"443": "index.vue",
"444": "index.vue",
"445": "Community 445",
"453": "ViewKvTableCell.vue",
"454": "zh_CN.js",
"458": "Community 458",
"459": "Community 459",
"460": "Community 460",
"462": "Community 462",
"465": "index.vue",
"470": "Ta",
"471": "Community 471",
"472": "Community 472",
"473": "Community 473",
"474": "Community 474",
"475": "Community 475",
"476": "Community 476",
"487": "Community 487",
"488": "Community 488",
"496": "Community 496",
"499": "Community 499",
"521": "Community 521",
"522": "Community 522",
"528": "Community 528",
"534": "Community 534",
"535": "Community 535",
"536": "Community 536",
"537": "Community 537",
"539": "Community 539",
"540": "Community 540",
"550": "Community 550",
"551": "Community 551",
"552": "Community 552",
"553": "Community 553",
"555": "Community 555",
"556": "Community 556",
"557": "Community 557",
"559": "Community 559",
"560": "Community 560",
"561": "Community 561",
"562": "Community 562",
"571": "Community 571",
"572": "Community 572",
"573": "Community 573",
"574": "Community 574",
"575": "Community 575",
"576": "Community 576",
"580": "Community 580",
"581": "Community 581",
"582": "Community 582",
"583": "Community 583",
"584": "Community 584",
"585": "Community 585",
"586": "Community 586",
"597": "Community 597",
"598": "Community 598",
"599": "Community 599",
"600": "Community 600",
"601": "Community 601",
"602": "Community 602",
"603": "Community 603",
"604": "Community 604",
"605": "Community 605",
"606": "Community 606",
"607": "Community 607",
"608": "Community 608",
"609": "Community 609",
"610": "Community 610",
"611": "Community 611",
"612": "Community 612",
"613": "Community 613",
"614": "Community 614",
"615": "Community 615",
"630": "Community 630",
"631": "Community 631",
"632": "Community 632",
"633": "Community 633",
"634": "Community 634",
"635": "Community 635",
"636": "Community 636",
"637": "Community 637",
"638": "Community 638",
"639": "Community 639",
"640": "Community 640",
"641": "Community 641",
"642": "Community 642",
"643": "Community 643",
"644": "Community 644",
"645": "Community 645",
"650": "Community 650",
"651": "Community 651",
"652": "Community 652",
"653": "Community 653",
"654": "Community 654",
"655": "Community 655",
"657": "Community 657",
"658": "Community 658",
"659": "Community 659",
"660": "Community 660",
"662": "Community 662",
"663": "Community 663",
"664": "Community 664",
"665": "Community 665",
"666": "Community 666",
"667": "Community 667",
"668": "Community 668",
"669": "Community 669",
"670": "Community 670",
"671": "Community 671",
"700": "Community 700",
"701": "Fixed",
"702": "Community 702",
"703": "Community 703",
"704": "Community 704",
"705": "Community 705",
"706": "Community 706",
"707": "Community 707",
"708": "Community 708",
"709": "Community 709",
"710": "Community 710",
"711": "Community 711",
"713": "Community 713",
"715": "Community 715",
"716": "Community 716",
"717": "Community 717",
"718": "Community 718",
"720": "Community 720",
"722": "Community 722",
"723": "Community 723",
"724": "Community 724",
"725": "Community 725",
"726": "Community 726",
"727": "Community 727",
"728": "Community 728",
"729": "Community 729",
"730": "Community 730",
"731": "Community 731",
"732": "Community 732",
"733": "Community 733",
"734": "修复",
"764": "新增",
"766": "新增",
"770": "移除",
"772": "重构",
"773": "重构",
"779": "重构",
"785": "⚠️ 重要提示",
"786": "⚠️ 重要提示",
"788": "⚠️ 重要提示",
"796": "OpportunityForm.vue",
"806": "index.vue",
"836": "BxInvoiceFileSelect.vue",
"838": "CustomerSelector.vue",
"840": "index.vue",
"841": "index.vue",
"857": "index.ts",
"886": "index.vue",
"887": "index.vue",
"889": "QuoteSelector.vue",
"892": "index.vue",
"896": "MarkWonDialog.vue",
"919": "ToContractDialog.vue",
"924": "OpportunitySelector.vue",
"950": "BatchUpdateStageDialog.vue",
"1010": "BxApprovalFlowTabs.vue",
"1015": "DealDialog.vue",
"1016": "TransferDialog.vue",
"1017": "BatchUpdateDateDialog.vue",
"1027": "IntoPoolDialog.vue",
"1115": "v2.4.2.7 - 2025-06-25",
"1117": "v2.5.2 - 2025-07-13",
"1118": "v2.4.2.2 - 2025-06-16",
"1123": "v2.4.1.1 - 2025-06-07",
"1126": "v2.4.2.1 - 2025-06-16",
"1127": "v2.4.2.4 - 2025-06-18",
"1175": "index.vue",
"1197": "icons.js",
"1198": "icons.min.js",
"1199": "index.js",
"1200": "index.js",
"1201": "index.js",
"1202": "index.js",
"1203": "index.js",
"1204": "plugin.js",
"1205": "plugin.min.js",
"1206": "index.js",
"1207": "plugin.js",
"1208": "plugin.min.js",
"1209": "index.js",
"1210": "plugin.js",
"1211": "plugin.min.js",
"1212": "index.js",
"1213": "plugin.js",
"1214": "plugin.min.js",
"1215": "index.js",
"1216": "index.js",
"1217": "plugin.js",
"1218": "plugin.min.js",
"1219": "index.js",
"1220": "index.js",
"1221": "index.js",
"1222": "emojiimages.js",
"1223": "emojiimages.min.js",
"1224": "emojis.js",
"1225": "emojis.min.js",
"1226": "index.js",
"1227": "index.js",
"1228": "ar.js",
"1229": "bg_BG.js",
"1230": "ca.js",
"1231": "cs.js",
"1232": "da.js",
"1233": "de.js",
"1234": "el.js",
"1235": "es.js",
"1236": "eu.js",
"1237": "fa.js",
"1238": "fi.js",
"1239": "fr_FR.js",
"1240": "he_IL.js",
"1241": "hi.js",
"1242": "hr.js",
"1243": "hu_HU.js",
"1244": "id.js",
"1245": "it.js",
"1246": "ja.js",
"1247": "kk.js",
"1248": "ko_KR.js",
"1249": "ms.js",
"1250": "nb_NO.js",
"1251": "nl.js",
"1252": "pl.js",
"1253": "pt_BR.js",
"1254": "pt_PT.js",
"1255": "ro.js",
"1256": "ru.js",
"1257": "sk.js",
"1258": "sl_SI.js",
"1259": "sv_SE.js",
"1260": "th_TH.js",
"1261": "tr.js",
"1262": "uk.js",
"1263": "vi.js",
"1265": "zh_TW.js",
"1266": "index.js",
"1267": "index.js",
"1268": "plugin.js",
"1269": "_",
"1270": "index.js",
"1271": "plugin.js",
"1272": "plugin.min.js",
"1273": "index.js",
"1274": "index.js",
"1275": "index.js",
"1277": "plugin.js",
"1278": "plugin.min.js",
"1279": "index.js",
"1280": "plugin.js",
"1281": "plugin.min.js",
"1282": "index.js",
"1283": "plugin.js",
"1284": "plugin.min.js",
"1285": "index.js",
"1286": "index.js",
"1287": "plugin.js",
"1288": "plugin.min.js",
"1289": "index.js",
"1290": "index.js",
"1291": "index.js",
"1292": "index.js",
"1293": "plugin.js",
"1294": "plugin.min.js",
"1295": "index.js",
"1296": "index.js",
"1297": "plugin.js",
"1298": "plugin.min.js",
"1299": "content.js",
"1300": "content.js",
"1301": "content.js",
"1302": "content.js",
"1303": "content.js",
"1304": "content.js",
"1305": "content.inline.js",
"1306": "content.js",
"1307": "skin.js",
"1308": "skin.shadowdom.js",
"1309": "content.inline.js",
"1310": "content.js",
"1311": "skin.js",
"1312": "skin.shadowdom.js",
"1313": "content.inline.js",
"1314": "content.js",
"1315": "skin.js",
"1316": "skin.shadowdom.js",
"1317": "content.inline.js",
"1318": "content.js",
"1319": "skin.js",
"1320": "skin.shadowdom.js",
"1321": "index.js",
"1322": "iconify-loader.ts",
"1323": "index.vue",
"1324": "index.vue",
"1325": "index.vue",
"1326": "route-parent.vue",
"1327": "setupSubpackSlipEditorTypeCheckboxes",
"1328": "修复",
"1329": "优化",
"1330": "新增",
"1331": "⚠️ 重要提示",
"1332": "重构",
"1333": "优化",
"1334": "修复",
"1335": "新增",
"1336": "升级",
"1337": "⚠️ 重要提示",
"1338": "修复",
"1339": "优化",
"1340": "新增",
"1341": "优化",
"1342": "修复",
"1343": "⚠️ 重要提示",
"1344": "升级",
"1345": "修复",
"1346": "优化",
"1347": "⚠️ 重要提示",
"1348": "新增",
"1349": "修复",
"1350": "优化",
"1351": "新增",
"1352": "优化",
"1353": "修复",
"1354": "新增",
"1355": "重构",
"1356": "优化",
"1357": "修复",
"1358": "移除",
"1359": "新增",
"1360": "优化",
"1361": "修复",
"1362": "新增",
"1363": "重构",
"1364": "升级",
"1365": "优化",
"1366": "修复",
"1367": "新增",
"1368": "优化",
"1369": "修复",
"1370": "优化",
"1371": "修复",
"1372": "新增",
"1373": "重构",
"1374": "升级",
"1375": "移除",
"1376": "修复",
"1377": "⚠️ 重要提示",
"1378": "重构",
"1379": "优化",
"1380": "修复",
"1381": "修复",
"1382": "新增",
"1383": "优化",
"1384": "修复",
"1385": "重构",
"1386": "优化",
"1387": "新增",
"1388": "重构",
"1389": "重构",
"1390": "优化",
"1391": "重构",
"1392": "优化",
"1393": "重构",
"1394": "重构",
"1395": "修复",
"1396": "重构",
"1397": "新增",
"1398": "优化",
"1399": "修复",
"1400": "⚠️ 重要提示",
"1401": "优化",
"1402": "修复",
"1403": "新增",
"1404": "优化",
"1405": "修复",
"1406": "重构",
"1407": "新增",
"1408": "优化",
"1409": "⚠️ 重要提示",
"1410": "code:block1 (crm/clue/)",
"1411": "code:typescript ({)",
"1412": "code:block3 (crm:clue:list # 线索列表查询)",
"1413": "code:bash (mysql -u root -p your_database < crm/sql/crm/12-CRM字典数据汇总.md)",
"9890": "README.md",
"9959": "Fixed",
"9960": "Fixed",
"9961": "Fixed",
"9962": "Fixed",
"9963": "Fixed",
"9964": "Fixed",
"9965": "Fixed",
"9966": "Fixed",
"9967": "Fixed",
"9968": "Fixed",
"9969": "Fixed",
"9970": "Fixed",
"9971": "Fixed",
"9972": "Fixed",
"9973": "Fixed",
"9974": "⚠️ Important Notice",
"9975": "⚠️ Important Notice",
"9976": "⚠️ Important Notice",
"9977": "⚠️ Important Notice",
"9978": "⚠️ Important Notice",
"9979": "⚠️ Important Notice",
"9980": "⚠️ Important Notice",
"9981": "Optimized",
"9982": "Optimized",
"9983": "Optimized",
"9984": "Optimized",
"9985": "Optimized",
"9986": "Optimized",
"9987": "Optimized",
"9988": "Optimized",
"9989": "Optimized",
"9990": "Optimized",
"9991": "Optimized",
"9992": "Optimized",
"9993": "Optimized",
"9994": "Optimized",
"9995": "Optimized",
"9996": "Optimized",
"9997": "Optimized",
"9998": "Optimized",
"9999": "Optimized",
"10000": "Optimized",
"10001": "Refactored",
"10002": "Refactored",
"10003": "Refactored",
"10004": "Refactored",
"10005": "Refactored",
"10006": "Refactored",
"10007": "Refactored",
"10008": "Refactored",
"10009": "Refactored",
"10010": "Refactored",
"10011": "Refactored",
"10012": "Refactored",
"10013": "Removed",
"10014": "Removed",
"10015": "Upgraded",
"10016": "Upgraded",
"10017": "Upgraded",
"10018": "Upgraded",
"10019": "优化",
"10020": "修复",
"10021": "⚠️ 重要提示",
"10022": "修复",
"10023": "优化",
"10024": "优化",
"10025": "⚠️ 重要提示",
"10026": "修复",
"10027": "优化",
"10028": "优化",
"10029": "修复",
"10030": "重构",
"10031": "优化",
"10032": "修复",
"10033": "新增",
"10034": "移除",
"10035": "优化",
"10036": "修复",
"10037": "重构",
"10038": "升级",
"10039": "优化",
"10040": "修复",
"10041": "优化",
"10042": "修复",
"10043": "修复",
"10044": "重构",
"10045": "升级",
"10046": "移除",
"10047": "修复",
"10048": "⚠️ 重要提示",
"10049": "⚠️ 重要提示",
"10050": "优化",
"10051": "修复",
"10052": "优化",
"10053": "修复",
"10054": "优化",
"10055": "新增",
"10056": "重构",
"10057": "优化",
"10058": "优化",
"10059": "重构",
"10060": "修复",
"10061": "新增",
"10062": "优化",
"10063": "修复",
"10064": "优化",
"10065": "⚠️ 重要提示",
"10066": "优化",
"10067": "修复",
"10068": "优化",
"10069": "修复",
"10070": "新增",
"10071": "优化",
"10072": "⚠️ 重要提示",
"10073": "修复",
"10074": "新增",
"10075": "升级",
"10076": "⚠️ 重要提示",
"10077": "修复",
"10078": "优化",
"10079": "code:bash (# Install dependencies)",
"10080": "code:bash (pnpm clean:dev)",
"10081": "code:bash (# 安装依赖)",
"10082": "code:bash (pnpm clean:dev)"
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Loaded 100 of 140 files, more files were not shown because too many files have changed in this diff. Show more