@ -1,7 +1,7 @@
{"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","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: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","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","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; AppointmentControllerIdentity Test","evidence":"anchored"}
{"id":"entity:report","type":"Entity","name":"Report","nameZh":"服务报告","domain":"report","fields":["id","appointment_id","remark","user_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","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: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":"action:register_boss","type":"Action","name":"registerBoss","nameZh":"老板入驻","inputs":["storeName","bossName","phone","password"],"outputs":["entity:store","entity:user","session_token"],"entrypoints":["POST /api/user/register-boss","UserService#registerBoss"],"appliesRules":["rule:BR-AUTH-001"],"code":"backend/src/main/java/com/petstore/service/UserService.java#registerBoss","evidence":"anchored","domain":"user"}
{"id":"action:register_boss","type":"Action","name":"registerBoss","nameZh":"老板入驻","inputs":["storeName","bossName","phone","password"],"outputs":["entity:store","entity:user","session_token"],"entrypoints":["POST /api/user/register-boss","UserService#registerBoss"],"appliesRules":["rule:BR-AUTH-001"],"code":"backend/src/main/java/com/petstore/service/UserService.java#registerBoss","evidence":"anchored","domain":"user"}
{"id":"action:update_store","type":"Action","name":"updateStore","nameZh":"更新店铺","inputs":["entity:store"],"outputs":["entity:store"],"entrypoints":["PUT /api/store/update","StoreController#update","StoreService#update"],"appliesRules":["rule:BR-STORE-001"],"code":"backend/src/main/java/com/petstore/controller/StoreController.java#update","test":"StoreControllerTest","evidence":"anchored","domain":"store"}
{"id":"action:update_store","type":"Action","name":"updateStore","nameZh":"更新店铺","inputs":["entity:store"],"outputs":["entity:store"],"entrypoints":["PUT /api/store/update","StoreController#update","StoreService#update"],"appliesRules":["rule:BR-STORE-001"],"code":"backend/src/main/java/com/petstore/controller/StoreController.java#update","test":"StoreControllerTest","evidence":"anchored","domain":"store"}
@ -10,12 +10,12 @@
{"id":"action:login","type":"Action","name":"login","nameZh":"手机号验证码登录","inputs":["phone","code"],"outputs":["entity:user","entity:store","session_token"],"entrypoints":["POST /api/user/login","UserService#login"],"appliesRules":["rule:BR-AUTH-001","rule:BR-AUTH-002"],"code":"backend/src/main/java/com/petstore/service/UserService.java#login","test":"UserServiceLoginStrategyTest","evidence":"anchored","domain":"auth"}
{"id":"action:login","type":"Action","name":"login","nameZh":"手机号验证码登录","inputs":["phone","code"],"outputs":["entity:user","entity:store","session_token"],"entrypoints":["POST /api/user/login","UserService#login"],"appliesRules":["rule:BR-AUTH-001","rule:BR-AUTH-002"],"code":"backend/src/main/java/com/petstore/service/UserService.java#login","test":"UserServiceLoginStrategyTest","evidence":"anchored","domain":"auth"}
{"id":"action:wx_phone_login","type":"Action","name":"wxPhoneLogin","nameZh":"微信手机号授权登录","inputs":["phoneCode","loginCode"],"outputs":["entity:user","entity:store","session_token"],"entrypoints":["POST /api/user/wx-phone-login","UserController#wxPhoneLogin","UserService#loginByVerifiedPhone"],"appliesRules":["rule:BR-AUTH-001"],"code":"backend/src/main/java/com/petstore/controller/UserController.java#wxPhoneLogin","evidence":"anchored","domain":"auth"}
{"id":"action:wx_phone_login","type":"Action","name":"wxPhoneLogin","nameZh":"微信手机号授权登录","inputs":["phoneCode","loginCode"],"outputs":["entity:user","entity:store","session_token"],"entrypoints":["POST /api/user/wx-phone-login","UserController#wxPhoneLogin","UserService#loginByVerifiedPhone"],"appliesRules":["rule:BR-AUTH-001"],"code":"backend/src/main/java/com/petstore/controller/UserController.java#wxPhoneLogin","evidence":"anchored","domain":"auth"}
{"id":"action:bind_wechat","type":"Action","name":"bindWechat","nameZh":"绑定微信标识","inputs":["userId","openid","unionid"],"outputs":["entity:user"],"entrypoints":["UserService#bindWechatMiniIdentity"],"appliesRules":[],"code":"backend/src/main/java/com/petstore/service/UserService.java#bindWechatMiniIdentity","evidence":"anchored","domain":"auth"}
{"id":"action:bind_wechat","type":"Action","name":"bindWechat","nameZh":"绑定微信标识","inputs":["userId","openid","unionid"],"outputs":["entity:user"],"entrypoints":["UserService#bindWechatMiniIdentity"],"appliesRules":[],"code":"backend/src/main/java/com/petstore/service/UserService.java#bindWechatMiniIdentity","evidence":"anchored","domain":"auth"}
{"id":"action:create_appointment","type":"Action","name":"createAppointment","nameZh":"创建预约","inputs":["petName","petType","serviceType","appointmentTime","storeId","remark","petId"],"outputs":["entity:appointment"],"entrypoints":["POST /api/appointment/create","AppointmentController#create","AppointmentService#createBooking"],"appliesRules":["rule:BR-APPT-001","rule:BR-APPT-004"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#create","evidence":"anchored","domain":"appointment"}
{"id":"action:create_appointment","type":"Action","name":"createAppointment","nameZh":"创建预约","inputs":["petName","petType","serviceType","appointmentTime","storeId","remark","petId","customerUserId","customerPhone","customerName" ],"outputs":["entity:appointment"],"entrypoints":["POST /api/appointment/create","AppointmentController#create","AppointmentService#createBooking"],"appliesRules":["rule:BR-APPT-001","rule:BR-APPT-003 ","rule:BR-APPT-004"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#create","test":"AppointmentControllerIdentityTest; AppointmentServiceTest ","evidence":"anchored","domain":"appointment"}
{"id":"action:start_service","type":"Action","name":"startService","nameZh":"开始服务","inputs":["appointmentId"],"outputs":["entity:appointment"],"entrypoints":["POST /api/appointment/start","AppointmentController#start","AppointmentService#startService"],"appliesRules":["rule:BR-APPT-001","rule:BR-APPT-002"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#start","test":"AppointmentServiceTest","evidence":"anchored","domain":"appointment"}
{"id":"action:start_service","type":"Action","name":"startService","nameZh":"开始服务","inputs":["appointmentId"],"outputs":["entity:appointment"],"entrypoints":["POST /api/appointment/start","AppointmentController#start","AppointmentService#startService"],"appliesRules":["rule:BR-APPT-001","rule:BR-APPT-002"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#start","test":"AppointmentServiceTest","evidence":"anchored","domain":"appointment"}
{"id":"action:transition_appointment_status","type":"Action","name":"transitionAppointmentStatus","nameZh":"更新预约状态","inputs":["id","status"],"outputs":["entity:appointment"],"entrypoints":["PUT /api/appointment/status","AppointmentController#updateStatus","AppointmentService#transitionStatus"],"appliesRules":["rule:BR-APPT-001","rule:BR-APPT-002","rule:BR-APPT-003"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#updateStatus","test":"AppointmentServiceTest","evidence":"anchored","domain":"appointment"}
{"id":"action:transition_appointment_status","type":"Action","name":"transitionAppointmentStatus","nameZh":"更新预约状态","inputs":["id","status"],"outputs":["entity:appointment"],"entrypoints":["PUT /api/appointment/status","AppointmentController#updateStatus","AppointmentService#transitionStatus"],"appliesRules":["rule:BR-APPT-001","rule:BR-APPT-002","rule:BR-APPT-003"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#updateStatus","test":"AppointmentServiceTest","evidence":"anchored","domain":"appointment"}
{"id":"action:get_appointment_detail","type":"Action","name":"getAppointmentDetail","nameZh":"预约详情","inputs":["id"],"outputs":["entity:appointment"],"entrypoints":["GET /api/appointment/detail","AppointmentController#detail"],"appliesRules":["rule:BR-APPT-002","rule:BR-APPT-003"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#detail","test":"AppointmentControllerDetailTest","evidence":"anchored","domain":"appointment"}
{"id":"action:get_appointment_detail","type":"Action","name":"getAppointmentDetail","nameZh":"预约详情","inputs":["id"],"outputs":["entity:appointment"],"entrypoints":["GET /api/appointment/detail","AppointmentController#detail"],"appliesRules":["rule:BR-APPT-002","rule:BR-APPT-003"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#detail","test":"AppointmentControllerDetailTest","evidence":"anchored","domain":"appointment"}
{"id":"action:list_appointments","type":"Action","name":"listAppointments","nameZh":"预约列表","inputs":["status","page","pageSize"],"outputs":["entity:appointment"],"entrypoints":["GET /api/appointment/list","AppointmentController#list"],"appliesRules":["rule:BR-APPT-002","rule:BR-APPT-003"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#list","evidence":"anchored","domain":"appointment"}
{"id":"action:list_appointments","type":"Action","name":"listAppointments","nameZh":"预约列表","inputs":["status","page","pageSize"],"outputs":["entity:appointment"],"entrypoints":["GET /api/appointment/list","AppointmentController#list"],"appliesRules":["rule:BR-APPT-002","rule:BR-APPT-003"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#list","evidence":"anchored","domain":"appointment"}
{"id":"action:submit_report","type":"Action","name":"submitReport","nameZh":"提交报告","inputs":["entity:report "],"outputs":["reportToken","reportId"],"entrypoints":["POST /api/report/create","ReportController#create","ReportService#create"],"appliesRules":["rule:BR-RPT-001","rule:BR-RPT-002","rule:BR-RPT-003","rule:BR-RPT-004","rule:BR-RPT-005"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#create","test":"ReportControllerTest; ReportServiceTest","evidence":"anchored","domain":"report"}
{"id":"action:submit_report","type":"Action","name":"submitReport","nameZh":"提交报告","inputs":["appointmentId","remark","images "],"outputs":["reportToken","reportId"],"entrypoints":["POST /api/report/create","ReportController#create","ReportService#create"],"appliesRules":["rule:BR-RPT-001","rule:BR-RPT-002","rule:BR-RPT-003","rule:BR-RPT-004","rule:BR-RPT-005"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#create","test":"ReportControllerTest; ReportServiceTest","evidence":"anchored","domain":"report","note":"authorStaffId 从登录上下文派生, customerUserId 从预约派生 "}
{"id":"action:get_report_by_token","type":"Action","name":"getReportByToken","nameZh":"公开报告查询","inputs":["token"],"outputs":["entity:report"],"entrypoints":["GET /api/report/get","ReportController#getByAppointmentId"],"appliesRules":["rule:BR-RPT-006"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#getByAppointmentId","test":"ReportControllerTest#publicTokenQueryHidesInternalFields","evidence":"anchored","domain":"report"}
{"id":"action:get_report_by_token","type":"Action","name":"getReportByToken","nameZh":"公开报告查询","inputs":["token"],"outputs":["entity:report"],"entrypoints":["GET /api/report/get","ReportController#getByAppointmentId"],"appliesRules":["rule:BR-RPT-006"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#getByAppointmentId","test":"ReportControllerTest#publicTokenQueryHidesInternalFields","evidence":"anchored","domain":"report"}
{"id":"action:track_report_open","type":"Action","name":"trackReportOpen","nameZh":"报告打开埋点","inputs":["token","visitType"],"outputs":[],"entrypoints":["POST /api/report/open-track","ReportController#trackReportOpen"],"appliesRules":["rule:BR-RPT-007"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#trackReportOpen","evidence":"anchored","domain":"report"}
{"id":"action:track_report_open","type":"Action","name":"trackReportOpen","nameZh":"报告打开埋点","inputs":["token","visitType"],"outputs":[],"entrypoints":["POST /api/report/open-track","ReportController#trackReportOpen"],"appliesRules":["rule:BR-RPT-007"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#trackReportOpen","evidence":"anchored","domain":"report"}
{"id":"action:delete_report","type":"Action","name":"deleteReport","nameZh":"删除报告","inputs":["id"],"outputs":[],"entrypoints":["DELETE /api/report/delete","ReportController#delete"],"appliesRules":["rule:BR-RPT-005"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#delete","evidence":"anchored","domain":"report"}
{"id":"action:delete_report","type":"Action","name":"deleteReport","nameZh":"删除报告","inputs":["id"],"outputs":[],"entrypoints":["DELETE /api/report/delete","ReportController#delete"],"appliesRules":["rule:BR-RPT-005"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#delete","evidence":"anchored","domain":"report"}
@ -25,7 +25,7 @@
{"id":"event:store_registered","type":"Event","name":"StoreRegistered","nameZh":"门店入驻","domain":"store","payload":["storeId","bossUserId","inviteCode"],"emittedBy":["action:register_boss"],"evidence":"anchored"}
{"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: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: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":["appointmentId","storeId","userId","appointmentTime"],"emittedBy":["action:create_appointment"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking","evidence":"anchored"}
{"id":"event:appointment_created","type":"Event","name":"AppointmentCreated","nameZh":"预约创建","domain":"appointment","payload":["appointmentId","storeId","c ustomerUserId","createdByU serId","appointmentTime"],"emittedBy":["action:create_appointment"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking","evidence":"anchored"}
{"id":"event:appointment_status_changed","type":"Event","name":"AppointmentStatusChanged","nameZh":"预约状态迁移","domain":"appointment","payload":["appointmentId","fromStatus","toStatus","assignedUserId"],"emittedBy":["action:start_service","action:transition_appointment_status","action:submit_report"],"appliesRules":["rule:BR-APPT-001"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#startService; #transitionStatus; ReportService#create","test":"AppointmentServiceTest; ReportServiceTest#createDoingAppointmentMarksDone","evidence":"anchored"}
{"id":"event:appointment_status_changed","type":"Event","name":"AppointmentStatusChanged","nameZh":"预约状态迁移","domain":"appointment","payload":["appointmentId","fromStatus","toStatus","assignedUserId"],"emittedBy":["action:start_service","action:transition_appointment_status","action:submit_report"],"appliesRules":["rule:BR-APPT-001"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#startService; #transitionStatus; ReportService#create","test":"AppointmentServiceTest; ReportServiceTest#createDoingAppointmentMarksDone","evidence":"anchored"}
{"id":"event:report_submitted","type":"Event","name":"ReportSubmitted","nameZh":"报告提交","domain":"report","payload":["reportId","appointmentId","storeId","reportToken"],"emittedBy":["action:submit_report"],"appliesRules":["rule:BR-RPT-001","rule:BR-RPT-002","rule:BR-RPT-004"],"code":"backend/src/main/java/com/petstore/service/ReportService.java#create","test":"ReportServiceTest","evidence":"anchored"}
{"id":"event:report_submitted","type":"Event","name":"ReportSubmitted","nameZh":"报告提交","domain":"report","payload":["reportId","appointmentId","storeId","reportToken"],"emittedBy":["action:submit_report"],"appliesRules":["rule:BR-RPT-001","rule:BR-RPT-002","rule:BR-RPT-004"],"code":"backend/src/main/java/com/petstore/service/ReportService.java#create","test":"ReportServiceTest","evidence":"anchored"}
{"id":"event:report_opened","type":"Event","name":"ReportOpened","nameZh":"报告首次打开","domain":"report","payload":["reportTokenHash","isFirstOpen","source","ts"],"emittedBy":["action:track_report_open"],"appliesRules":["rule:BR-RPT-007"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#trackReportOpen","doc":"docs/本期主线-下一步产品优化点.md 埋点事件 schema","evidence":"anchored"}
{"id":"event:report_opened","type":"Event","name":"ReportOpened","nameZh":"报告首次打开","domain":"report","payload":["reportTokenHash","isFirstOpen","source","ts"],"emittedBy":["action:track_report_open"],"appliesRules":["rule:BR-RPT-007"],"code":"backend/src/main/java/com/petstore/controller/ReportController.java#trackReportOpen","doc":"docs/本期主线-下一步产品优化点.md 埋点事件 schema","evidence":"anchored"}
@ -37,7 +37,7 @@
{"id":"rule:BR-STORE-002","type":"Rule","name":"邀请码查询仅 boss/staff + 同店","domain":"store","appliesTo":["action:get_store_by_invite_code"],"code":"backend/src/main/java/com/petstore/controller/StoreController.java#getByInviteCode","test":"StoreControllerTest#inviteCodeCrossStoreForbidden","evidence":"anchored"}
{"id":"rule:BR-STORE-002","type":"Rule","name":"邀请码查询仅 boss/staff + 同店","domain":"store","appliesTo":["action:get_store_by_invite_code"],"code":"backend/src/main/java/com/petstore/controller/StoreController.java#getByInviteCode","test":"StoreControllerTest#inviteCodeCrossStoreForbidden","evidence":"anchored"}
{"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-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-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:get_appointment_detail","action:transition_appointment_status"],"code":"backend/src/main/java/com/petstore/controller/AppointmentController.java#detail; #updateStatus","test":"AppointmentControllerDetailTest#customerCannotViewOthersAppointment","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"],"code":"backend/src/main/java/com/petstore/service/AppointmentService.java#createBooking","doc":"docs/产品设计文档.md §5.2","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-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-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"}
@ -52,11 +52,14 @@
{"id":"rel:store_has_users","type":"Relation","subject":"entity:store","predicate":"HAS","object":"entity:user","cardinality":"1—N","evidence":"anchored","doc":"User.store_id → Store.id","domain":"store"}
{"id":"rel:store_has_users","type":"Relation","subject":"entity:store","predicate":"HAS","object":"entity:user","cardinality":"1—N","evidence":"anchored","doc":"User.store_id → Store.id","domain":"store"}
{"id":"rel:user_belongs_to_store","type":"Relation","subject":"entity:user","predicate":"BELONGS_TO","object":"entity:store","cardinality":"N—1","evidence":"anchored","doc":"boss/staff 归属一个门店; customer 可无门店","domain":"user"}
{"id":"rel:user_belongs_to_store","type":"Relation","subject":"entity:user","predicate":"BELONGS_TO","object":"entity:store","cardinality":"N—1","evidence":"anchored","doc":"boss/staff 归属一个门店; customer 可无门店","domain":"user"}
{"id":"rel:store_has_appointments","type":"Relation","subject":"entity:store","predicate":"HAS","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.store_id","domain":"store"}
{"id":"rel:store_has_appointments","type":"Relation","subject":"entity:store","predicate":"HAS","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.store_id","domain":"store"}
{"id":"rel:user_creates_appointments","type":"Relation","subject":"entity:user","predicate":"CREATES","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.user_id","domain":"user"}
{"id":"rel:user_creates_appointments","type":"Relation","subject":"entity:user","predicate":"CREATES","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.created_by_user_id","domain":"user"}
{"id":"rel:user_owns_appointments","type":"Relation","subject":"entity:user","predicate":"RECEIVES_SERVICE_IN","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.customer_user_id( 客户归属) ","domain":"user"}
{"id":"rel:user_serves_appointments","type":"Relation","subject":"entity:user","predicate":"SERVES","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.assigned_user_id( 谁点谁服务) ","domain":"user"}
{"id":"rel:user_serves_appointments","type":"Relation","subject":"entity:user","predicate":"SERVES","object":"entity:appointment","cardinality":"1—N","evidence":"anchored","doc":"Appointment.assigned_user_id( 谁点谁服务) ","domain":"user"}
{"id":"rel:appointment_has_report","type":"Relation","subject":"entity:appointment","predicate":"HAS","object":"entity:report","cardinality":"1—1","evidence":"anchored","doc":"Report.appointment_id( uk_report_appointment 唯一约束)","domain":"appointment"}
{"id":"rel:appointment_has_report","type":"Relation","subject":"entity:appointment","predicate":"HAS","object":"entity:report","cardinality":"1—1","evidence":"anchored","doc":"Report.appointment_id( uk_report_appointment 唯一约束)","domain":"appointment"}
{"id":"rel:report_belongs_to_store","type":"Relation","subject":"entity:report","predicate":"BELONGS_TO","object":"entity:store","cardinality":"N—1","evidence":"anchored","doc":"Report.store_id","domain":"report"}
{"id":"rel:report_belongs_to_store","type":"Relation","subject":"entity:report","predicate":"BELONGS_TO","object":"entity:store","cardinality":"N—1","evidence":"anchored","doc":"Report.store_id","domain":"report"}
{"id":"rel:report_served_by_user","type":"Relation","subject":"entity:report","predicate":"SERVED_BY","object":"entity:user","cardinality":"N—1","evidence":"anchored","doc":"Report.user_id( 技师) ","domain":"report"}
{"id":"rel:report_served_by_user","type":"Relation","subject":"entity:report","predicate":"SERVED_BY","object":"entity:user","cardinality":"N—1","evidence":"anchored","doc":"Report.appointment_id -> Appointment.assigned_user_id( 服务技师) ","domain":"report"}
{"id":"rel:report_authored_by_user","type":"Relation","subject":"entity:report","predicate":"AUTHORED_BY","object":"entity:user","cardinality":"N—1","evidence":"anchored","doc":"Report.author_staff_id( 报告作者) ","domain":"report"}
{"id":"rel:report_belongs_to_customer","type":"Relation","subject":"entity:report","predicate":"BELONGS_TO_CUSTOMER","object":"entity:user","cardinality":"N—1","evidence":"anchored","doc":"Report.customer_user_id( 报告归属客户) ","domain":"report"}
{"id":"rel:report_has_leads","type":"Relation","subject":"entity:report","predicate":"HAS","object":"entity:report_lead","cardinality":"1—N","evidence":"anchored","doc":"ReportLead.report_id( 同手机号去重) ","domain":"report"}
{"id":"rel:report_has_leads","type":"Relation","subject":"entity:report","predicate":"HAS","object":"entity:report_lead","cardinality":"1—N","evidence":"anchored","doc":"ReportLead.report_id( 同手机号去重) ","domain":"report"}
{"id":"rel:lead_belongs_to_store","type":"Relation","subject":"entity:report_lead","predicate":"BELONGS_TO","object":"entity:store","cardinality":"N—1","evidence":"anchored","doc":"ReportLead.store_id( 回访池范围) ","domain":"lead"}
{"id":"rel:lead_belongs_to_store","type":"Relation","subject":"entity:report_lead","predicate":"BELONGS_TO","object":"entity:store","cardinality":"N—1","evidence":"anchored","doc":"ReportLead.store_id( 回访池范围) ","domain":"lead"}
{"id":"rel:register_boss_emits_store_registered","type":"Relation","subject":"action:register_boss","predicate":"EMITS","object":"event:store_registered","evidence":"anchored","domain":"user"}
{"id":"rel:register_boss_emits_store_registered","type":"Relation","subject":"action:register_boss","predicate":"EMITS","object":"event:store_registered","evidence":"anchored","domain":"user"}