@ -1,6 +1,6 @@
{"id":"entity:store","type":"Entity","name":"Store","nameZh":"门店","domain":"store","fields":["id","name","logo","phone","address","latitude","longitude","intro","owner_id","invite_code","booking_day_start","booking_last_slot_start","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/Store.java","doc":"docs/产品设计文档.md §三 t_store","test":"StoreControllerTest","evidence":"anchored"}
{"id":"entity:store","type":"Entity","name":"Store","nameZh":"门店","domain":"store","fields":["id","name","logo","phone","address","latitude","longitude","intro","owner_id","invite_code","booking_day_start","booking_last_slot_start","booking_capacity"," create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/Store.java","doc":"docs/产品设计文档.md §三 t_store","test":"StoreControllerTest","evidence":"anchored"}
{"id":"entity:user","type":"Entity","name":"User","nameZh":"用户","domain":"user","fields":["id","username","password","name","phone","avatar","store_id","role","wechat_openid","wechat_unionid","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/User.java","doc":"docs/产品设计文档.md §三 t_user; docs/.agents/common-context.md 术语规则","test":"UserServiceLoginStrategyTest; UserJsonIgnoreTest","evidence":"anchored"}
{"id":"entity:appointment","type":"Entity","name":"Appointment","nameZh":"预约","domain":"appointment","fields":["id","pet_name","pet_type","service_type","appointment_time","status","store_id","user_id","customer_user_id","created_by_user_id","assigned_user_id","pet_id","remark","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/Appointment.java; backend/src/main/java/com/petstore/service/AppointmentService.java","doc":"docs/产品设计文档.md §三 t_appointment §5.2","test":"AppointmentServiceTest; AppointmentControllerDetailTest; AppointmentControllerIdentityTest","evidence":"anchored"}
{"id":"entity:appointment","type":"Entity","name":"Appointment","nameZh":"预约","domain":"appointment","fields":["id","pet_name","pet_type","service_type","appointment_time","duration_minutes"," status","store_id","user_id","customer_user_id","created_by_user_id","assigned_user_id","pet_id","remark","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/Appointment.java; backend/src/main/java/com/petstore/service/AppointmentService.java","doc":"docs/产品设计文档.md §三 t_appointment §5.2; docs/架构决策-真实预约容量模型-2026-08-01.md ","test":"AppointmentServiceTest; BookingCapacityServiceTest; AppointmentControllerDetailTest; AppointmentControllerIdentityTest; BookingCapacityMigration Test","evidence":"anchored"}
{"id":"entity:report","type":"Entity","name":"Report","nameZh":"服务报告","domain":"report","fields":["id","appointment_id","remark","user_id","customer_user_id","author_staff_id","store_id","report_token","pet_name","service_type","appointment_time","staff_name","highlight_video_url","highlight_video_status","highlight_video_error","highlight_duration_sec","highlight_compose_mode","highlight_fail_reason","highlight_share_cover_url","create_time","update_time","deleted"],"systems":["Report Media Backend"],"code":"backend/src/main/java/com/petstore/entity/Report.java; backend/src/main/java/com/petstore/service/ReportService.java","doc":"docs/产品设计文档.md §三 t_report §5.3; docs/API-报告成片字段契约.md","test":"ReportServiceTest; ReportControllerTest","evidence":"anchored"}
{"id":"entity:report_lead","type":"Entity","name":"ReportLead","nameZh":"留资线索","domain":"lead","fields":["id","report_id","store_id","phone","pet_name","service_type","wechat_openid","wechat_unionid","reminder_type","remind_date","remind_status","unsubscribe_token","client_ip","create_time","update_time","deleted"],"systems":["Report Media Backend"],"code":"backend/src/main/java/com/petstore/controller/ReportLeadController.java; backend/src/main/java/com/petstore/entity/ReportLead.java","doc":"docs/本期主线-下一步产品优化点.md §C 留资","test":"ReportLeadControllerTest","evidence":"anchored"}
{"id":"entity:business_event","type":"Entity","name":"BusinessEvent","nameZh":"不可变业务事件","domain":"platform","jpa":true,"fields":["id","event_id","event_type","event_version","store_id","store_customer_id","aggregate_type","aggregate_id","actor_user_id","actor_role","source","occurred_at","metadata_json","idempotency_key","create_time"],"systems":["Backend Core","Report Media Backend","Store Admin FE"],"code":"backend/src/main/java/com/petstore/entity/BusinessEvent.java; backend/src/main/java/com/petstore/service/BusinessEventService.java","doc":"docs/ontology/objects.md#entity:business_event; docs/架构决策-业务事件落库-2026-08-01.md","test":"BusinessEventServiceTest; BusinessEventMigrationTest","evidence":"anchored"}
@ -26,7 +26,7 @@
{"id":"event:store_registered","type":"Event","name":"StoreRegistered","nameZh":"门店入驻","domain":"store","payload":["storeId","bossUserId","inviteCode"],"emittedBy":["action:register_boss"],"evidence":"anchored"}
{"id":"event:session_issued","type":"Event","name":"SessionIssued","nameZh":"签发会话令牌","domain":"auth","payload":["userId","storeId","role","exp"],"emittedBy":["action:register_boss","action:login","action:wx_phone_login"],"code":"backend/src/main/java/com/petstore/auth/SessionTokenService.java#issue","test":"SessionTokenServiceTest","evidence":"anchored"}
{"id":"event:wx_bound","type":"Event","name":"WxBound","nameZh":"微信标识绑定","domain":"auth","payload":["userId","openid","unionid"],"emittedBy":["action:bind_wechat"],"code":"backend/src/main/java/com/petstore/service/UserService.java#bindWechatMiniIdentity","evidence":"anchored"}
{"id":"event:appointment_created","type":"Event","name":"AppointmentCreated","nameZh":"预约创建","domain":"appointment","payload":["storeId","storeCustomerId","aggregateId","actorUserId","actorRole","bookingOrigin","occurredAt"],"emittedBy":["action:create_appointment"],"appliesRules":["rule:BR-BE-001"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking; backend/src/main/java/com/petstore/service/BusinessEventService.java#recordAppointmentCreated","test":"AppointmentServiceTest; BusinessEventServiceTest","evidence":"anchored"}
{"id":"event:appointment_created","type":"Event","name":"AppointmentCreated","nameZh":"预约创建","domain":"appointment","payload":["storeId","storeCustomerId","aggregateId","actorUserId","actorRole","bookingOrigin","durationMinutes"," occurredAt"],"emittedBy":["action:create_appointment"],"appliesRules":["rule:BR-BE-001","rule:BR-APPT-004 "],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking; backend/src/main/java/com/petstore/service/BusinessEventService.java#recordAppointmentCreated","test":"AppointmentServiceTest; BusinessEventServiceTest","evidence":"anchored"}
{"id":"event:appointment_status_changed","type":"Event","name":"AppointmentStatusChanged","nameZh":"预约状态迁移","domain":"appointment","payload":["storeId","storeCustomerId","aggregateId","fromStatus","toStatus","actorUserId","actorRole","occurredAt"],"emittedBy":["action:start_service","action:transition_appointment_status","action:submit_report"],"appliesRules":["rule:BR-APPT-001","rule:BR-BE-001"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#startService; #transitionStatus; backend/src/main/java/com/petstore/service/ReportService.java#create; backend/src/main/java/com/petstore/service/BusinessEventService.java#recordAppointmentStatusChanged","test":"AppointmentServiceTest; ReportServiceTest#createDoingAppointmentMarksDone; BusinessEventServiceTest","evidence":"anchored"}
{"id":"event:service_started","type":"Event","name":"ServiceStarted","nameZh":"服务开始","domain":"appointment","payload":["storeId","storeCustomerId","appointmentId","actorUserId","actorRole","occurredAt"],"emittedBy":["action:start_service"],"appliesRules":["rule:BR-APPT-001","rule:BR-BE-001"],"code":"backend/src/main/java/com/petstore/service/BusinessEventService.java#recordAppointmentStatusChanged","test":"BusinessEventServiceTest#statusToDoingRecordsGenericAndServiceStartedFacts","evidence":"anchored"}
{"id":"event:service_completed","type":"Event","name":"ServiceCompleted","nameZh":"服务完成","domain":"appointment","payload":["storeId","storeCustomerId","appointmentId","actorUserId","actorRole","occurredAt"],"emittedBy":["action:transition_appointment_status","action:submit_report"],"appliesRules":["rule:BR-APPT-001","rule:BR-BE-001"],"code":"backend/src/main/java/com/petstore/service/BusinessEventService.java#recordAppointmentStatusChanged; backend/src/main/java/com/petstore/service/ReportService.java#create","test":"AppointmentServiceTest; ReportServiceTest","evidence":"anchored"}
@ -41,7 +41,7 @@
{"id":"rule:BR-APPT-001","type":"Rule","name":"预约状态机","domain":"appointment","appliesTo":["action:start_service","action:transition_appointment_status","action:submit_report"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#startService; #transitionStatus","test":"AppointmentServiceTest","evidence":"anchored"}
{"id":"rule:BR-APPT-002","type":"Rule","name":"预约跨店 403","domain":"appointment","appliesTo":["action:list_appointments","action:start_service","action:transition_appointment_status","action:get_appointment_detail"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java","test":"AppointmentControllerDetailTest","evidence":"anchored"}
{"id":"rule:BR-APPT-003","type":"Rule","name":"预约客户归属与跨用户 403","domain":"appointment","appliesTo":["action:create_appointment","action:get_appointment_detail","action:transition_appointment_status"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#create; #detail; #updateStatus; backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking","test":"AppointmentControllerIdentityTest; AppointmentControllerDetailTest#customerCannotViewOthersAppointment","evidence":"anchored"}
{"id":"rule:BR-APPT-004","type":"Rule","name":"预约时段校验:半小时档 + 营业时间 + 占用 + 已过 ","domain":"appointment","appliesTo":["action:create_appointment"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking","doc":"docs/产品设计文档.md §5.2","evidence":"anchored"}
{"id":"rule:BR-APPT-004","type":"Rule","name":"真实预约容量:服务时长快照 + 跨桶容量 + 同店并发锁 ","domain":"appointment","appliesTo":["action:create_appointment","action:get_available_slots","action:create_schedule_block" ],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking; backend/src/main/java/com/petstore/service/BookingCapacityService.java; backend/src/main/java/com/petstore/service/ScheduleService.java#createBlock ","doc":"docs/产品设计文档.md §5.2; docs/架构决策-真实预约容量模型-2026-08-01.md","test":"BookingCapacityServiceTest; AppointmentServiceTest; BookingCapacityMigrationTest ","evidence":"anchored"}
{"id":"rule:BR-RPT-001","type":"Rule","name":"报告必须绑定预约","domain":"report","appliesTo":["action:submit_report"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#create; service/ReportService.java#create","test":"ReportControllerTest#createMissingAppointmentIdReturnsBizCode; ReportServiceTest#createWithNullAppointmentIdThrows","evidence":"anchored"}
{"id":"rule:BR-RPT-002","type":"Rule","name":"一约一份报告","domain":"report","appliesTo":["action:submit_report"],"code":"backend/src/main/java/com/petstore/entity/Report.java; mapper/ReportMapper.java; service/ReportService.java#create; controller/ReportController.java#create","test":"ReportServiceTest#createDuplicateReportThrows; ReportControllerTest#createDuplicateReportReturnsAlreadyExists","evidence":"anchored"}
{"id":"rule:BR-RPT-003","type":"Rule","name":"报告前后照片必填","domain":"report","appliesTo":["action:submit_report"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#hasPhotoType; frontend/src/pages/report/Report.vue#submitReport","test":"ReportControllerTest#createMissingBeforePhotoReturnsBizCode; createMissingAfterPhotoReturnsBizCode","doc":"docs/产品设计文档.md §5.3 报告提交必填项","evidence":"anchored"}
@ -85,8 +85,8 @@
{"id":"rel:track_report_open_emits_report_reopened","type":"Relation","subject":"action:track_report_open","predicate":"EMITS","object":"event:report_reopened","evidence":"documented","domain":"report"}
{"id":"rel:submit_lead_emits_lead_submitted","type":"Relation","subject":"action:submit_lead","predicate":"EMITS","object":"event:lead_submitted","evidence":"documented","domain":"lead"}
{"id":"entity:pet","type":"Entity","name":"Pet","nameZh":"宠物档案","domain":"pet","fields":["id","name","pet_type","breed","avatar","owner_user_id","remark","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/Pet.java; controller/PetController.java; service/PetService.java","doc":"docs/产品设计文档.md §三 t_pet","test":"PetControllerTest","evidence":"anchored"}
{"id":"entity:service_type","type":"Entity","name":"ServiceType","nameZh":"服务类型","domain":"service_type","fields":["id","store_id","name","create_time"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/ServiceType.java; controller/ServiceTypeController.java","doc":"docs/产品设计文档.md §三 t_service_type §5.2","test":"ServiceTypeControllerTest","evidence":"anchored"}
{"id":"entity:schedule_block","type":"Entity","name":"ScheduleBlock","nameZh":"门店排班占用","domain":"schedule","fields":["id","store_id","slot_start","block_type","note","created_by_user_id","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/ScheduleBlock.java; controller/ScheduleController.java; service/ScheduleService.java","doc":"docs/产品设计文档.md §5.2 预约时段占用","test":"ScheduleControllerTest","evidence":"anchored"}
{"id":"entity:service_type","type":"Entity","name":"ServiceType","nameZh":"服务类型","domain":"service_type","fields":["id","store_id","name","duration_minutes"," create_time"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/ServiceType.java; controller/ServiceTypeController.java","doc":"docs/产品设计文档.md §三 t_service_type §5.2; docs/架构决策-真实预约容量模型-2026-08-01.md ","test":"ServiceTypeControllerTest; BookingCapacityMigration Test","evidence":"anchored"}
{"id":"entity:schedule_block","type":"Entity","name":"ScheduleBlock","nameZh":"门店排班占用","domain":"schedule","fields":["id","store_id","slot_start","duration_minutes"," block_type","note","created_by_user_id","create_time","update_time","deleted"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/entity/ScheduleBlock.java; controller/ScheduleController.java; service/ScheduleService.java","doc":"docs/产品设计文档.md §5.2 预约时段占用; docs/架构决策-真实预约容量模型-2026-08-01.md ","test":"ScheduleControllerTest; BookingCapacityServiceTest; BookingCapacityMigration Test","evidence":"anchored"}
{"id":"entity:report_image","type":"Entity","name":"ReportImage","nameZh":"报告媒体","domain":"report","fields":["id","report_id","photo_url","photo_type","media_type","sort_order","create_time"],"systems":["Report Media Backend"],"code":"backend/src/main/java/com/petstore/entity/ReportImage.java; mapper/ReportImageMapper.java","doc":"docs/产品设计文档.md §三 t_report_image","test":"ReportServiceTest#createWithImagesSavesEachImage","evidence":"anchored"}
{"id":"entity:highlight_video","type":"Entity","name":"HighlightVideo","nameZh":"服务回顾短片","domain":"report","fields":["report_id","highlight_video_url","highlight_video_status","highlight_video_error","highlight_duration_sec","highlight_compose_mode","highlight_fail_reason","highlight_share_cover_url"],"systems":["Report Media Backend"],"code":"backend/src/main/java/com/petstore/entity/Report.java; service/ReportHighlightVideoService.java","doc":"docs/API-报告成片字段契约.md; docs/洗美报告短视频成片方案.md","test":"ReportHighlightVideoServiceTest","evidence":"anchored","jpa":false}
{"id":"entity:session_token","type":"Entity","name":"SessionToken","nameZh":"会话令牌","domain":"auth","fields":["userId","storeId","role","exp"],"systems":["Backend Core"],"code":"backend/src/main/java/com/petstore/auth/SessionTokenService.java; CurrentUser.java; CurrentUserContext.java; AuthInterceptor.java","doc":"docs/ontology/rules.md#rule:BR-AUTH-001","test":"SessionTokenServiceTest","evidence":"anchored","jpa":false}
@ -96,12 +96,12 @@
{"id":"action:delete_pet","type":"Action","name":"deletePet","nameZh":"删除宠物","inputs":["id"],"outputs":[],"entrypoints":["DELETE /api/pet/delete","PetController#delete","PetService#delete"],"appliesRules":["rule:BR-PET-001"],"code":"backend/src/main/java/com/petstore/controller/PetController.java#delete","evidence":"anchored","test":"PetControllerTest","domain":"pet"}
{"id":"action:get_pet_history","type":"Action","name":"getPetHistory","nameZh":"宠物服务时间线","inputs":["petId"],"outputs":[],"entrypoints":["GET /api/pet/history","PetController#history","PetService#getServiceHistory"],"appliesRules":["rule:BR-PET-001"],"code":"backend/src/main/java/com/petstore/controller/PetController.java#history","evidence":"anchored","test":"PetControllerTest","domain":"pet"}
{"id":"action:list_service_types","type":"Action","name":"listServiceTypes","nameZh":"服务类型列表","inputs":["storeId"],"outputs":["entity:service_type"],"entrypoints":["GET /api/service-type/list","ServiceTypeController#list"],"appliesRules":[],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#list","evidence":"anchored","domain":"service_type"}
{"id":"action:create_service_type","type":"Action","name":"createServiceType","nameZh":"新增服务类型","inputs":["name"],"outputs":["entity:service_type"],"entrypoints":["POST /api/service-type/create","ServiceTypeController#create","ServiceTypeService#create"],"appliesRules":["rule:BR-ST-001"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#create","test":"ServiceTypeControllerTest","evidence":"anchored","domain":"service_type"}
{"id":"action:update_service_type","type":"Action","name":"updateServiceType","nameZh":"编辑服务类型","inputs":["id","name"],"outputs":["entity:service_type"],"entrypoints":["PUT /api/service-type/update","ServiceTypeController#update"],"appliesRules":["rule:BR-ST-001"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#update","test":"ServiceTypeControllerTest","evidence":"anchored","domain":"service_type"}
{"id":"action:create_service_type","type":"Action","name":"createServiceType","nameZh":"新增服务类型","inputs":["name","durationMinutes" ],"outputs":["entity:service_type"],"entrypoints":["POST /api/service-type/create","ServiceTypeController#create","ServiceTypeService#create"],"appliesRules":["rule:BR-ST-001"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#create","test":"ServiceTypeControllerTest","evidence":"anchored","domain":"service_type"}
{"id":"action:update_service_type","type":"Action","name":"updateServiceType","nameZh":"编辑服务类型","inputs":["id","name","durationMinutes" ],"outputs":["entity:service_type"],"entrypoints":["PUT /api/service-type/update","ServiceTypeController#update"],"appliesRules":["rule:BR-ST-001"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#update","test":"ServiceTypeControllerTest","evidence":"anchored","domain":"service_type"}
{"id":"action:delete_service_type","type":"Action","name":"deleteServiceType","nameZh":"删除服务类型","inputs":["id"],"outputs":[],"entrypoints":["DELETE /api/service-type/delete","ServiceTypeController#delete"],"appliesRules":["rule:BR-ST-001"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#delete","test":"ServiceTypeControllerTest","evidence":"anchored","domain":"service_type"}
{"id":"action:init_service_types","type":"Action","name":"initServiceTypes","nameZh":"初始化系统默认服务类型","inputs":[],"outputs":[],"entrypoints":["POST /api/service-type/init","ServiceTypeController#init"],"appliesRules":["rule:BR-ST-001"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java#init","test":"ServiceTypeControllerTest","evidence":"anchored","domain":"service_type"}
{"id":"action:day_agenda","type":"Action","name":"dayAgenda","nameZh":"门店某日日程","inputs":["date"],"outputs":["entity:appointment","entity:schedule_block"],"entrypoints":["GET /api/schedule/day","ScheduleController#day","ScheduleService#dayAgenda"],"appliesRules":["rule:BR-SCH-001"],"code":"backend/src/main/java/com/petstore/controller/ScheduleController.java#day","test":"ScheduleControllerTest","evidence":"anchored","domain":"schedule"}
{"id":"action:create_schedule_block","type":"Action","name":"createScheduleBlock","nameZh":"手动占用时段","inputs":["slotStart","blockType","note"],"outputs":["entity:schedule_block"],"entrypoints":["POST /api/schedule/block","ScheduleController#createBlock","ScheduleService#createBlock"],"appliesRules":["rule:BR-SCH-001"],"code":"backend/src/main/java/com/petstore/controller/ScheduleController.java#createBlock","test":"ScheduleControllerTest","evidence":"anchored","domain":"schedule"}
{"id":"action:day_agenda","type":"Action","name":"dayAgenda","nameZh":"门店某日日程","inputs":["date"],"outputs":["entity:appointment","entity:schedule_block"],"entrypoints":["GET /api/schedule/day","ScheduleController#day","ScheduleService#dayAgenda"],"appliesRules":["rule:BR-SCH-001","rule:BR-SCH-002" ],"code":"backend/src/main/java/com/petstore/controller/ScheduleController.java#day","test":"ScheduleControllerTest; BookingCapacityService Test","evidence":"anchored","domain":"schedule"}
{"id":"action:create_schedule_block","type":"Action","name":"createScheduleBlock","nameZh":"手动占用时段","inputs":["slotStart","durationMinutes"," blockType","note"],"outputs":["entity:schedule_block"],"entrypoints":["POST /api/schedule/block","ScheduleController#createBlock","ScheduleService#createBlock"],"appliesRules":["rule:BR-SCH-001","rule:BR-SCH-002","rule:BR-APPT-004" ],"code":"backend/src/main/java/com/petstore/controller/ScheduleController.java#createBlock","test":"ScheduleControllerTest; BookingCapacityService Test","evidence":"anchored","domain":"schedule"}
{"id":"action:delete_schedule_block","type":"Action","name":"deleteScheduleBlock","nameZh":"取消手动占用","inputs":["id"],"outputs":[],"entrypoints":["DELETE /api/schedule/block","ScheduleController#deleteBlock","ScheduleService#deleteBlock"],"appliesRules":["rule:BR-SCH-001"],"code":"backend/src/main/java/com/petstore/controller/ScheduleController.java#deleteBlock; service/ScheduleService.java#deleteBlock","test":"ScheduleControllerTest","evidence":"anchored","domain":"schedule"}
{"id":"action:upload_image","type":"Action","name":"uploadImage","nameZh":"上传图片/视频","inputs":["file"],"outputs":["url"],"entrypoints":["POST /api/upload/image","FileController#uploadImage"],"appliesRules":["rule:BR-UPLOAD-001","rule:BR-UPLOAD-002"],"code":"backend/src/main/java/com/petstore/controller/FileController.java#uploadImage","evidence":"anchored","domain":"upload"}
{"id":"action:get_upload_image","type":"Action","name":"getUploadImage","nameZh":"读取上传资源","inputs":["path"],"outputs":[],"entrypoints":["GET /api/upload/image/**","FileController#getImage"],"appliesRules":["rule:BR-UPLOAD-001"],"code":"backend/src/main/java/com/petstore/controller/FileController.java#getImage","evidence":"anchored","domain":"upload"}
@ -128,6 +128,7 @@
{"id":"rule:BR-HL-001","type":"Rule","name":"成片仅 boss/staff 可触发","domain":"report","appliesTo":["action:generate_highlight"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#startHighlight","evidence":"anchored","test":"ReportHighlightVideoServiceTest#requestGenerateRejectsCustomerWithoutAppointmentOwnershipPath"}
{"id":"rule:BR-HL-002","type":"Rule","name":"成片三态 + composeMode","domain":"report","appliesTo":["action:generate_highlight"],"code":"backend/src/main/java/com/petstore/entity/Report.java; service/ReportHighlightVideoService.java","doc":"docs/洗美报告短视频成片方案.md; docs/API-报告成片字段契约.md","evidence":"anchored","test":"ReportHighlightVideoServiceTest"}
{"id":"rule:BR-SCH-001","type":"Rule","name":"排班仅 boss/staff + 跨店 403","domain":"schedule","appliesTo":["action:day_agenda","action:create_schedule_block","action:delete_schedule_block"],"code":"backend/src/main/java/com/petstore/controller/ScheduleController.java; service/ScheduleService.java#deleteBlock","test":"ScheduleControllerTest","evidence":"anchored"}
{"id":"rule:BR-SCH-002","type":"Rule","name":"手动占用容量语义: walk_in 消耗一份, blocked 关闭全部","domain":"schedule","appliesTo":["action:day_agenda","action:create_schedule_block"],"code":"backend/src/main/java/com/petstore/service/ScheduleService.java; backend/src/main/java/com/petstore/service/BookingCapacityService.java","test":"BookingCapacityServiceTest; ScheduleControllerTest","evidence":"anchored"}
{"id":"rule:BR-ST-001","type":"Rule","name":"服务类型仅 boss + 同店 + 系统默认不可改删","domain":"service_type","appliesTo":["action:create_service_type","action:update_service_type","action:delete_service_type","action:init_service_types"],"code":"backend/src/main/java/com/petstore/controller/ServiceTypeController.java","test":"ServiceTypeControllerTest","evidence":"anchored"}
{"id":"rule:BR-PET-001","type":"Rule","name":"宠物跨用户/跨店","domain":"pet","appliesTo":["action:list_pets","action:create_pet","action:update_pet","action:delete_pet","action:get_pet_history"],"code":"backend/src/main/java/com/petstore/controller/PetController.java","evidence":"anchored","test":"PetControllerTest"}
{"id":"rule:BR-USER-001","type":"Rule","name":"员工管理仅 boss + 同店","domain":"user","appliesTo":["action:create_staff","action:list_staff","action:delete_staff"],"code":"backend/src/main/java/com/petstore/controller/UserController.java","evidence":"anchored"}
@ -157,7 +158,7 @@
{"id":"entity:service_interval","type":"Entity","name":"ServiceInterval","nameZh":"服务建议周期配置","domain":"service_type","fields":["id","store_id","service_name","pet_type","interval_days_min","interval_days_max","create_time"],"systems":["Report Media Backend"],"code":"backend/src/main/java/com/petstore/entity/ServiceInterval.java","doc":"docs/ontology/objects.md#entity:service_interval","test":"","evidence":"anchored"}
{"id":"action:list_stores","type":"Action","name":"listStores","nameZh":"门店列表","inputs":[],"outputs":["entity:store"],"entrypoints":["GET /api/store/list","StoreController#list"],"appliesRules":["rule:BR-STORE-003"],"code":"backend/src/main/java/com/petstore/controller/StoreController.java#list","evidence":"anchored","domain":"store","test":"StoreControllerTest#publicListHidesOwnerIdAndInviteCode"}
{"id":"action:get_store","type":"Action","name":"getStore","nameZh":"门店详情","inputs":["id"],"outputs":["entity:store"],"entrypoints":["GET /api/store/get","StoreController#get"],"appliesRules":["rule:BR-STORE-003"],"code":"backend/src/main/java/com/petstore/controller/StoreController.java#get","evidence":"anchored","domain":"store","test":"StoreControllerTest#publicGetHidesOwnerIdAndInviteCode"}
{"id":"action:get_available_slots","type":"Action","name":"getAvailableSlots","nameZh":"可预约时段","inputs":["storeId","date"],"outputs":[],"entrypoints":["GET /api/appointment/available-slots","AppointmentController#availableSlots"],"appliesRules":["rule:BR-APPT-004"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#availableSlots","evidence":"anchored","domain":"appointment"}
{"id":"action:get_available_slots","type":"Action","name":"getAvailableSlots","nameZh":"可预约时段","inputs":["storeId","date","serviceType" ],"outputs":[],"entrypoints":["GET /api/appointment/available-slots","AppointmentController#availableSlots"],"appliesRules":["rule:BR-APPT-004"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#availableSlots; backend/src/main/java/com/petstore/service/BookingCapacityService.java","test":"BookingCapacityServiceTest ","evidence":"anchored","domain":"appointment"}
{"id":"action:get_report_suggestion","type":"Action","name":"getReportSuggestion","nameZh":"报告下次建议日期","inputs":["token"],"outputs":[],"entrypoints":["GET /api/report/{token}/suggestion","ReportLeadController#suggestion"],"appliesRules":["rule:BR-INT-001"],"code":"backend/src/main/java/com/petstore/controller/ReportLeadController.java#suggestion","evidence":"anchored","domain":"lead"}
{"id":"action:submit_testimonial","type":"Action","name":"submitTestimonial","nameZh":"宠主寄语提交","inputs":["token","content","isPublic"],"outputs":["entity:report_testimonial"],"entrypoints":["POST /api/report/{token}/testimonial","ReportController#submitTestimonial"],"appliesRules":["rule:BR-TST-001"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#submitTestimonial","evidence":"anchored","domain":"report","test":"ReportTestimonialServiceTest"}
{"id":"action:get_legacy_upload","type":"Action","name":"getLegacyUpload","nameZh":"兼容旧路径读取上传资源","inputs":["path"],"outputs":[],"entrypoints":["GET /api/upload/legacy/**","FileController#getLegacyImage"],"appliesRules":["rule:BR-UPLOAD-001"],"code":"backend/src/main/java/com/petstore/controller/FileController.java#getLegacyImage","evidence":"anchored","domain":"upload"}
@ -214,7 +215,7 @@
{"id":"action:admin_list_leads","type":"Action","name":"adminListLeads","nameZh":"后台回访线索列表","domain":"admin","inputs":["remindStatus","remindDateTo","page","pageSize"],"outputs":["entity:report_lead"],"entrypoints":["Admin UI /leads (planned)","reuses GET /api/report/leads"],"appliesRules":["rule:BR-ADMIN-001","rule:BR-ADMIN-002","rule:BR-LEAD-002","rule:BR-LEAD-003"],"code":"backend/.../ReportLeadController.java#leads (reuse)","doc":"docs/ontology/actions.md#action:admin_list_leads","evidence":"documented"}
{"id":"action:admin_list_service_customers","type":"Action","name":"adminListServiceCustomers","nameZh":"后台服务客户列表","domain":"admin","inputs":["source","hasPendingLead","lastVisitFrom","lastVisitTo","q","page","pageSize"],"outputs":["entity:store_customer"],"entrypoints":["GET /api/admin/service-customers","Admin UI /customers"],"appliesRules":["rule:BR-ADMIN-001","rule:BR-ADMIN-002","rule:BR-ADMIN-003","rule:BR-ADMIN-004","rule:BR-SC-001"],"code":"backend/src/main/java/com/petstore/controller/AdminServiceCustomerController.java#listServiceCustomers; backend/src/main/java/com/petstore/service/AdminServiceCustomerService.java","doc":"docs/ontology/actions.md#action:admin_list_service_customers; docs/门店管理后台-PhaseA-页面清单PRD.md §7.6","test":"AdminServiceCustomerControllerTest; AdminServiceCustomerServiceTest","evidence":"anchored","note":"以 t_store_customer 稳定主档为入口,动态聚合宠物/到店/报告/留资;返回 storeCustomerId 和脱敏手机号。"}
{"id":"action:admin_update_settings","type":"Action","name":"adminUpdateSettings","nameZh":"后台门店设置读写","domain":"admin","inputs":["entity:store","entity:service_type","entity:user"],"outputs":["entity:store","entity:service_type","entity:user"],"entrypoints":["GET /api/admin/store","Admin UI /settings","PUT /api/store/update"],"appliesRules":["rule:BR-ADMIN-001","rule:BR-ADMIN-002","rule:BR-ADMIN-003","rule:BR-STORE-001","rule:BR-ST-001","rule:BR-USER-001"],"code":"","doc":"docs/ontology/actions.md#action:admin_update_settings","evidence":"anchored","note":"后台读本店含 inviteCode( GET /api/admin/store) ; 写资料复用 PUT /api/store/update( 仅 boss) ; 服务类型/员工复用既有 API。","code_refs":["backend/src/main/java/com/petstore/controller/AdminStoreController.java#currentStore","backend/src/main/java/com/petstore/controller/StoreController.java#update"]}
{"id":"action:admin_manage_schedule","type":"Action","name":"adminManageSchedule","nameZh":"后台排班与占用","domain":"admin","inputs":["date","entity:schedule_block"],"outputs":["entity:schedule_block","entity:appointment"],"entrypoints":["Admin UI /schedule","GET /api/schedule/day","POST /api/schedule/block","DELETE /api/schedule/block"],"appliesRules":["rule:BR-ADMIN-001","rule:BR-ADMIN-002","rule:BR-SCH-001"],"code":"","doc":"docs/ontology/actions.md#action:admin_manage_schedule","evidence":"anchored","note":"Web 排班日视图;增删占用复用 ScheduleController。"}
{"id":"action:admin_manage_schedule","type":"Action","name":"adminManageSchedule","nameZh":"后台排班与占用","domain":"admin","inputs":["date","entity:schedule_block"],"outputs":["entity:schedule_block","entity:appointment"],"entrypoints":["Admin UI /schedule","GET /api/schedule/day","POST /api/schedule/block","DELETE /api/schedule/block"],"appliesRules":["rule:BR-ADMIN-001","rule:BR-ADMIN-002","rule:BR-SCH-001","rule:BR-SCH-002","rule:BR-APPT-004" ],"code":"","doc":"docs/ontology/actions.md#action:admin_manage_schedule","evidence":"anchored","note":"Web 排班日视图展示容量占用 ;增删带时长 占用复用 ScheduleController。"}
{"id":"event:workbench_viewed","type":"Event","name":"workbenchViewed","nameZh":"工作台已打开","domain":"admin","emittedBy":["action:view_workbench"],"payload":["storeId","userId","ts"],"code":"","doc":"docs/ontology/events.md#event:workbench_viewed","evidence":"gap","note":"可选埋点; A 期可不实现上报。"}
{"id":"rel:admin_console_has_workbench","type":"Relation","subject":"entity:admin_console","predicate":"HAS","object":"entity:workbench","domain":"admin","evidence":"documented","cardinality":"1—1","doc":"登录默认工作台"}
{"id":"rel:workbench_has_todo_items","type":"Relation","subject":"entity:workbench","predicate":"HAS","object":"entity:workbench_todo_item","domain":"admin","evidence":"documented","cardinality":"1—N","doc":"今日待办卡片"}