diff --git a/business/migrations/0004_alter_projectregistration_responsiblefor.py b/business/migrations/0004_alter_projectregistration_responsiblefor.py new file mode 100644 index 0000000..34fac05 --- /dev/null +++ b/business/migrations/0004_alter_projectregistration_responsiblefor.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0.1 on 2026-01-14 07:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('business', '0003_remove_bid_user_remove_case_user_remove_caselog_user_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='projectregistration', + name='responsiblefor', + field=models.TextField(), + ), + ] diff --git a/business/models.py b/business/models.py index f827c15..044c7e0 100644 --- a/business/models.py +++ b/business/models.py @@ -19,7 +19,7 @@ class ProjectRegistration(models.Model): client_info = models.TextField(null=True, blank=True) # 委托人身份信息(临时允许为空,用于数据迁移) party_info = models.TextField(null=True, blank=True) # 相对方身份信息(临时允许为空,用于数据迁移) description = models.TextField(null=True, blank=True) # 项目简述(临时允许为空,用于数据迁移) - responsiblefor = models.CharField(max_length=100) # 负责人 + responsiblefor = models.TextField() # 负责人信息(JSON格式字典:{"负责人":"","主办律师":"","助理律师":"","收益分配":""},负责人必填,其余选填) charge = models.CharField(max_length=100) # 收费情况 contract = models.TextField() # 上传合同 state = models.CharField(max_length=100) # 状态 diff --git a/business/views.py b/business/views.py index 49e1335..6bd7979 100644 --- a/business/views.py +++ b/business/views.py @@ -195,7 +195,7 @@ class Project(APIView): client_info = request.data.get('client_info') # 委托人身份信息 party_info = request.data.get('party_info') # 相对方身份信息 description = request.data.get('description') # 项目简述 - responsiblefor = request.data.get('responsiblefor') + responsiblefor = request.data.get('responsiblefor') # 负责人信息(字典格式) charge = request.data.get('charge') contract = request.FILES.getlist('contract') approvers = request.data.get('approvers') # 审核人列表(可选,多人团队时需要,推荐:用户ID数组如[1,2,3],兼容:用户名数组) @@ -205,11 +205,32 @@ class Project(APIView): approvers = [personincharge] if personincharge else None import datetime + import json # 验证必填字段 - if not all([type, ContractNo, times, client_info, party_info, description, responsiblefor, charge]): + if not all([type, ContractNo, times, client_info, party_info, description, charge]): return Response({'status': 'error', 'message': '缺少必填参数', 'code': 1}, status=status.HTTP_400_BAD_REQUEST) + # 验证负责人信息(字典格式) + if not responsiblefor: + return Response({'status': 'error', 'message': '负责人信息不能为空', 'code': 1}, status=status.HTTP_400_BAD_REQUEST) + + # 解析负责人信息(支持字符串JSON或字典) + try: + if isinstance(responsiblefor, str): + responsiblefor_dict = json.loads(responsiblefor) + else: + responsiblefor_dict = responsiblefor + + # 验证负责人字段必填 + if not responsiblefor_dict.get('负责人'): + return Response({'status': 'error', 'message': '负责人字段不能为空', 'code': 1}, status=status.HTTP_400_BAD_REQUEST) + + # 将字典转换为JSON字符串存储 + responsiblefor_str = json.dumps(responsiblefor_dict, ensure_ascii=False) + except (json.JSONDecodeError, TypeError, AttributeError): + return Response({'status': 'error', 'message': '负责人信息格式错误,应为字典格式', 'code': 1}, status=status.HTTP_400_BAD_REQUEST) + if contract: contract = flies(contract) else: @@ -236,7 +257,7 @@ class Project(APIView): client_info=client_info, party_info=party_info, description=description, - responsiblefor=responsiblefor, + responsiblefor=responsiblefor_str, charge=charge, contract=contract_str, state="审核中", @@ -245,23 +266,32 @@ class Project(APIView): today = datetime.datetime.now() formatted_date = today.strftime("%Y-%m-%d") - # 获取负责人的团队信息 + # 获取负责人的团队信息(从字典中获取负责人字段) team_name = None try: - responsible_user = User.objects.get(username=responsiblefor, is_deleted=False) - team_name = responsible_user.team + responsible_person = responsiblefor_dict.get('负责人') + if responsible_person: + responsible_user = User.objects.get(username=responsible_person, is_deleted=False) + team_name = responsible_user.team except User.DoesNotExist: pass # 使用统一的审核流程函数 from User.utils import create_approval_with_team_logic - content = f"{responsiblefor}在{times}办理立项登记,项目类型:{type},合同编号:{ContractNo},负责人:{responsiblefor},收费情况:{charge}" + # 构建负责人信息描述 + responsible_desc = responsiblefor_dict.get('负责人', '') + if responsiblefor_dict.get('主办律师'): + responsible_desc += f",主办律师:{responsiblefor_dict.get('主办律师')}" + if responsiblefor_dict.get('助理律师'): + responsible_desc += f",助理律师:{responsiblefor_dict.get('助理律师')}" + + content = f"{responsiblefor_dict.get('负责人')}在{times}办理立项登记,项目类型:{type},合同编号:{ContractNo},{responsible_desc},收费情况:{charge}" approval, approvers_order_json, needs_approval = create_approval_with_team_logic( team_name=team_name, approvers=approvers, - title=responsiblefor + "立项登记", + title=responsiblefor_dict.get('负责人', '') + "立项登记", content=content, approval_type="立项登记", user_id=pro.id, @@ -282,7 +312,7 @@ class Project(APIView): 'id': pro.id, 'contract_no': pro.ContractNo, 'type': pro.type, - 'responsiblefor': pro.responsiblefor, + 'responsiblefor': responsiblefor_dict, 'times': pro.times } log_operation( @@ -294,7 +324,7 @@ class Project(APIView): target_id=pro.id, target_name=pro.ContractNo, new_data=new_data, - remark=f'新增立项登记:合同编号 {pro.ContractNo},负责人 {pro.responsiblefor}' + remark=f'新增立项登记:合同编号 {pro.ContractNo},负责人 {responsiblefor_dict.get("负责人", "")}' ) return Response({'message': '登记成功', 'code': 0}, status=status.HTTP_200_OK) @@ -367,7 +397,14 @@ class ProjectDetail(APIView): except EmptyPage: user_agents_page = paginator.page(paginator.num_pages) data = [] + import json for info in user_agents_page.object_list: + # 解析负责人信息(JSON字符串转字典) + try: + responsiblefor_dict = json.loads(info.responsiblefor) if info.responsiblefor else {} + except: + responsiblefor_dict = info.responsiblefor if info.responsiblefor else {} + data.append({ "id": info.id, 'times': info.times, @@ -376,7 +413,7 @@ class ProjectDetail(APIView): "client_info": info.client_info, "party_info": info.party_info, "description": info.description, - "responsiblefor": info.responsiblefor, + "responsiblefor": responsiblefor_dict, # 返回字典格式 "charge": info.charge, "contract": info.contract, "state": info.state, @@ -420,9 +457,11 @@ class EditProject(APIView): client_info = request.data.get('client_info') party_info = request.data.get('party_info') description = request.data.get('description') - responsiblefor = request.data.get('responsiblefor') + responsiblefor = request.data.get('responsiblefor') # 负责人信息(字典格式) charge = request.data.get('charge') contract = request.FILES.getlist('contract') + + import json try: pro = ProjectRegistration.objects.get(id=id, is_deleted=False) @@ -435,7 +474,10 @@ class EditProject(APIView): # 保存原始值用于日志记录 original_type = pro.type original_ContractNo = pro.ContractNo - original_responsiblefor = pro.responsiblefor + try: + original_responsiblefor = json.loads(pro.responsiblefor) if pro.responsiblefor else {} + except: + original_responsiblefor = {} original_times = pro.times original_charge = pro.charge @@ -456,8 +498,23 @@ class EditProject(APIView): update_fields_list.append('times') if responsiblefor: - pro.responsiblefor = responsiblefor - update_fields_list.append('responsiblefor') + # 解析负责人信息(支持字符串JSON或字典) + try: + if isinstance(responsiblefor, str): + responsiblefor_dict = json.loads(responsiblefor) + else: + responsiblefor_dict = responsiblefor + + # 验证负责人字段必填 + if not responsiblefor_dict.get('负责人'): + return Response({'status': 'error', 'message': '负责人字段不能为空', 'code': 1}, status=status.HTTP_400_BAD_REQUEST) + + # 将字典转换为JSON字符串存储 + responsiblefor_str = json.dumps(responsiblefor_dict, ensure_ascii=False) + pro.responsiblefor = responsiblefor_str + update_fields_list.append('responsiblefor') + except (json.JSONDecodeError, TypeError, AttributeError): + return Response({'status': 'error', 'message': '负责人信息格式错误,应为字典格式', 'code': 1}, status=status.HTTP_400_BAD_REQUEST) if charge: pro.charge = charge @@ -478,12 +535,12 @@ class EditProject(APIView): pro.state = "审核中" update_fields_list.append('state') - # 记录操作前的数据 + # 记录操作前的数据(original_responsiblefor已经是字典格式) old_data = { 'id': pro.id, 'contract_no': original_ContractNo, 'type': original_type, - 'responsiblefor': original_responsiblefor, + 'responsiblefor': original_responsiblefor if isinstance(original_responsiblefor, dict) else {}, 'times': original_times, 'charge': original_charge } @@ -492,22 +549,40 @@ class EditProject(APIView): pro.save(update_fields=update_fields_list) # 记录操作后的数据 + try: + current_responsiblefor = json.loads(pro.responsiblefor) if pro.responsiblefor else {} + except: + current_responsiblefor = pro.responsiblefor if pro.responsiblefor else {} + new_data = { 'id': pro.id, 'contract_no': pro.ContractNo, 'type': pro.type, - 'responsiblefor': pro.responsiblefor, + 'responsiblefor': current_responsiblefor, 'times': pro.times, 'charge': pro.charge } today = datetime.datetime.now() formatted_date = today.strftime("%Y-%m-%d") + + # 获取负责人名称用于审批记录 + if responsiblefor: + current_responsiblefor = responsiblefor_dict.get('负责人', '') + # 构建负责人信息描述 + responsible_desc = current_responsiblefor + if responsiblefor_dict.get('主办律师'): + responsible_desc += f",主办律师:{responsiblefor_dict.get('主办律师')}" + if responsiblefor_dict.get('助理律师'): + responsible_desc += f",助理律师:{responsiblefor_dict.get('助理律师')}" + else: + current_responsiblefor = original_responsiblefor.get('负责人', '') if isinstance(original_responsiblefor, dict) else '' + responsible_desc = current_responsiblefor + Approval.objects.create( - title=(responsiblefor or original_responsiblefor) + "立项登记重新编辑", - content=(responsiblefor or original_responsiblefor) + "在" + ( - times or original_times) + "办理立项登记,项目类型:" + original_type + ",合同编号:" + original_ContractNo + "描述:" + ",负责人:" + ( - responsiblefor or original_responsiblefor) + ",收费情况:" + (charge or original_charge), + title=current_responsiblefor + "立项登记重新编辑", + content=current_responsiblefor + "在" + ( + times or original_times) + "办理立项登记,项目类型:" + original_type + ",合同编号:" + original_ContractNo + "描述:" + ",负责人:" + responsible_desc + ",收费情况:" + (charge or original_charge), times=formatted_date, personincharge="", # personincharge不再从请求中获取 state='审核中', @@ -961,12 +1036,19 @@ class caseManagementDetail(APIView): except EmptyPage: user_agents_page = paginator.page(paginator.num_pages) data = [] + import json for info in user_agents_page.object_list: try: pro = ProjectRegistration.objects.get(id=info.project_id, is_deleted=False) except ProjectRegistration.DoesNotExist: continue # 跳过已删除的关联数据 + # 解析负责人信息(JSON字符串转字典) + try: + responsiblefor_dict = json.loads(pro.responsiblefor) if pro.responsiblefor else {} + except: + responsiblefor_dict = pro.responsiblefor if pro.responsiblefor else {} + data.append({ "id": info.id, "ContractNo": pro.ContractNo, # 合同编号 @@ -974,7 +1056,7 @@ class caseManagementDetail(APIView): "client_name": pro.client_info, # 客户名称(委托人身份信息) "party_name": pro.party_info, # 相对方名称 "description": pro.description, # 项目简述 - "responsiblefor": pro.responsiblefor, # 负责人 + "responsiblefor": responsiblefor_dict, # 负责人信息(字典格式) "charge": pro.charge, # 收费情况 'times': info.times, # 立案时间 "AgencyContract": info.AgencyContract, # 代理合同 diff --git a/案件管理模块接口文档.md b/案件管理模块接口文档.md new file mode 100644 index 0000000..431f181 --- /dev/null +++ b/案件管理模块接口文档.md @@ -0,0 +1,1328 @@ +# 案件管理模块接口文档 + +## 目录 +- [1. 预立案登记](#1-预立案登记) +- [2. 投标登记](#2-投标登记) +- [3. 立项登记](#3-立项登记) +- [4. 案件管理](#4-案件管理) +- [5. 发票管理](#5-发票管理) +- [6. 案件日志](#6-案件日志) +- [7. 其他接口](#7-其他接口) + +--- + +## 1. 预立案登记 + +### 1.1 创建预立案登记 + +**接口地址:** `POST /business/register` + +**接口描述:** 创建新的预立案登记。 + +**请求头:** +``` +Content-Type: application/json +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| times | String | 是 | 预立案时间(格式:YYYY-MM-DD) | +| client_username | String | 否 | 委托人信息(自然人姓名/法人名称) | +| party_username | String | 否 | 相对方信息(自然人姓名/法人名称) | +| description | String | 是 | 描述 | +| Undertaker | String | 是 | 承办人员(用户名) | + +**请求示例:** +```json +{ + "times": "2024-01-01", + "client_username": "张三", + "party_username": "李四", + "description": "合同纠纷案件", + "Undertaker": "王律师" +} +``` + +**响应示例:** +```json +{ + "message": "登记成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少参数", + "code": 1 +} +``` + +--- + +### 1.2 预立案登记列表查询(分页) + +**接口地址:** `POST /business/registerdetail` + +**接口描述:** 分页查询预立案登记列表,支持按时间范围、承办人员筛选。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | Integer | 是 | 页码 | +| per_page | Integer | 是 | 每页数量 | +| times | String | 否 | 开始日期(格式:YYYY-MM-DD) | +| end_time | String | 否 | 结束日期(格式:YYYY-MM-DD) | +| Undertaker | String | 否 | 承办人员(模糊搜索) | + +**请求示例:** +```json +{ + "page": 1, + "per_page": 10, + "times": "2024-01-01", + "end_time": "2024-12-31", + "Undertaker": "王律师" +} +``` + +**响应示例:** +```json +{ + "message": "展示成功", + "total": 50, + "data": [ + { + "id": 1, + "times": "2024-01-01", + "client_username": "张三", + "party_username": "李四", + "description": "合同纠纷案件", + "Undertaker": "王律师" + } + ], + "code": 0 +} +``` + +--- + +### 1.3 预立案登记列表查询(简化) + +**接口地址:** `POST /business/registrationlist` + +**接口描述:** 获取所有未删除的预立案登记简化列表(仅包含ID、委托人、相对方)。 + +**请求参数:** 无 + +**响应示例:** +```json +{ + "message": "展示成功", + "data": [ + { + "id": 1, + "client_username": "张三", + "party_username": "李四" + } + ], + "code": 0 +} +``` + +--- + +### 1.4 编辑预立案登记 + +**接口地址:** `POST /business/editRegistration` + +**接口描述:** 编辑预立案登记信息。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 预立案登记ID | +| times | String | 否 | 预立案时间 | +| client_username | String | 否 | 委托人信息 | +| party_username | String | 否 | 相对方信息 | +| description | String | 否 | 描述 | +| Undertaker | String | 否 | 承办人员 | + +**请求示例:** +```json +{ + "id": 1, + "description": "更新后的描述", + "Undertaker": "李律师" +} +``` + +**响应示例:** +```json +{ + "message": "编辑成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "预立案登记不存在", + "code": 1 +} +``` + +--- + +### 1.5 删除预立案登记 + +**接口地址:** `POST /business/deleteRegistration` + +**接口描述:** 删除预立案登记(软删除)。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 预立案登记ID | + +**请求示例:** +```json +{ + "id": 1 +} +``` + +**响应示例:** +```json +{ + "message": "删除成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "预立案登记不存在", + "code": 1 +} +``` + +--- + +## 2. 投标登记 + +### 2.1 创建投标登记 + +**接口地址:** `POST /business/bid` + +**接口描述:** 创建新的投标登记,独立创建,不再关联预立案。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| BiddingUnit | String | 是 | 招标单位(名称、统一社会信用代码/身份证号码) | +| ProjectName | String | 是 | 项目名称 | +| times | String | 是 | 申请日期(格式:YYYY-MM-DD) | +| BiddingAnnouncement | File[] | 否 | 上传招标公告文件 | +| approvers | Array | 否 | 审核人列表(团队类型时需要,推荐:用户ID数组如[1,2,3],兼容:用户名数组) | +| personincharge | String | 否 | 审核人(兼容旧接口,如果传了approvers则忽略) | + +**请求示例:** +```json +{ + "BiddingUnit": "XX公司,统一社会信用代码:91110000123456789X", + "ProjectName": "XX项目招标", + "times": "2024-01-01", + "approvers": [1, 2, 3] +} +``` + +**响应示例:** +```json +{ + "message": "登记成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少必填参数", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "团队类型需要指定审核人,请提供approvers参数", + "code": 1 +} +``` + +--- + +### 2.2 投标登记列表查询 + +**接口地址:** `POST /business/biddetail` + +**接口描述:** 分页查询投标登记列表,支持按时间范围、项目名称筛选。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | Integer | 是 | 页码 | +| per_page | Integer | 是 | 每页数量 | +| times | String | 否 | 开始日期(格式:YYYY-MM-DD) | +| end_time | String | 否 | 结束日期(格式:YYYY-MM-DD) | +| project_name | String | 否 | 项目名称(模糊搜索) | + +**请求示例:** +```json +{ + "page": 1, + "per_page": 10, + "times": "2024-01-01", + "end_time": "2024-12-31", + "project_name": "XX项目" +} +``` + +**响应示例:** +```json +{ + "message": "展示成功", + "total": 30, + "data": [ + { + "id": 1, + "times": "2024-01-01", + "BiddingUnit": "XX公司,统一社会信用代码:91110000123456789X", + "ProjectName": "XX项目招标", + "BiddingAnnouncement": "[\"http://example.com/announcement.pdf\"]", + "state": "审核中" + } + ], + "code": 0 +} +``` + +--- + +### 2.3 编辑投标登记 + +**接口地址:** `POST /business/editBid` + +**接口描述:** 编辑投标登记信息。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 投标登记ID | +| BiddingUnit | String | 否 | 招标单位 | +| ProjectName | String | 否 | 项目名称 | +| times | String | 否 | 申请日期 | +| BiddingAnnouncement | File[] | 否 | 上传招标公告文件 | +| personincharge | String | 否 | 审核人(如果传入会触发审核流程) | + +**请求示例:** +```json +{ + "id": 1, + "ProjectName": "更新后的项目名称", + "times": "2024-01-02" +} +``` + +**响应示例:** +```json +{ + "message": "编辑成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "投标登记不存在", + "code": 1 +} +``` + +--- + +### 2.4 删除投标登记 + +**接口地址:** `POST /business/deleteBid` + +**接口描述:** 删除投标登记(软删除)。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 投标登记ID | + +**请求示例:** +```json +{ + "id": 1 +} +``` + +**响应示例:** +```json +{ + "message": "删除成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "投标登记不存在", + "code": 1 +} +``` + +--- + +## 3. 立项登记 + +### 1.1 创建立项登记 + +**接口地址:** `POST /business/project` + +**接口描述:** 创建新的立项登记,独立创建,不再需要预立案。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| type | String | 是 | 项目类型 | +| ContractNo | String | 是 | 合同编号(唯一) | +| times | String | 是 | 立项日期(格式:YYYY-MM-DD) | +| client_info | String | 是 | 委托人身份信息 | +| party_info | String | 是 | 相对方身份信息 | +| description | String | 是 | 项目简述 | +| responsiblefor | Object/Dict | 是 | 负责人信息(字典格式,负责人必填,其余选填) | +| charge | String | 是 | 收费情况 | +| contract | File[] | 否 | 上传合同文件(可多个) | +| approvers | Array | 否 | 审核人列表(团队类型时需要,推荐:用户ID数组如[1,2,3],兼容:用户名数组) | +| personincharge | String | 否 | 审核人(兼容旧接口,如果传了approvers则忽略) | + +**responsiblefor 字典格式说明:** +```json +{ + "负责人": "王律师", // 必填 + "主办律师": "李律师", // 选填 + "助理律师": "张律师", // 选填 + "收益分配": "50%,30%,20%" // 选填 +} +``` + +**请求示例:** +```json +{ + "type": "民事诉讼", + "ContractNo": "HT20240101001", + "times": "2024-01-01", + "client_info": "张三,身份证号:110101199001011234", + "party_info": "李四,身份证号:110101199002021234", + "description": "合同纠纷案件", + "responsiblefor": { + "负责人": "王律师", + "主办律师": "李律师", + "助理律师": "张律师", + "收益分配": "50%,30%,20%" + }, + "charge": "按标的额5%收费", + "approvers": [1, 2, 3] +} +``` + +或使用JSON字符串格式: +```json +{ + "type": "民事诉讼", + "ContractNo": "HT20240101001", + "times": "2024-01-01", + "client_info": "张三,身份证号:110101199001011234", + "party_info": "李四,身份证号:110101199002021234", + "description": "合同纠纷案件", + "responsiblefor": "{\"负责人\":\"王律师\",\"主办律师\":\"李律师\",\"助理律师\":\"张律师\",\"收益分配\":\"50%,30%,20%\"}", + "charge": "按标的额5%收费", + "approvers": [1, 2, 3] +} +``` + +**响应示例:** +```json +{ + "message": "登记成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少必填参数", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "负责人信息不能为空", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "负责人字段不能为空", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "负责人信息格式错误,应为字典格式", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "该合同编号已存在,不能重复创建", + "code": 1 +} +``` + +--- + +### 1.2 立项登记列表查询 + +**接口地址:** `POST /business/projectdetail` + +**接口描述:** 分页查询立项登记列表,支持按时间范围、委托人信息、相对方信息筛选。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | Integer | 是 | 页码 | +| per_page | Integer | 是 | 每页数量 | +| times | String | 否 | 开始日期(格式:YYYY-MM-DD) | +| end_time | String | 否 | 结束日期(格式:YYYY-MM-DD) | +| client_info | String | 否 | 委托人信息(模糊搜索) | +| party_info | String | 否 | 相对方信息(模糊搜索) | + +**请求示例:** +```json +{ + "page": 1, + "per_page": 10, + "times": "2024-01-01", + "end_time": "2024-12-31", + "client_info": "张三" +} +``` + +**响应示例:** +```json +{ + "message": "展示成功", + "total": 100, + "data": [ + { + "id": 1, + "times": "2024-01-01", + "type": "民事诉讼", + "ContractNo": "HT20240101001", + "client_info": "张三,身份证号:110101199001011234", + "party_info": "李四,身份证号:110101199002021234", + "description": "合同纠纷案件", + "responsiblefor": { + "负责人": "王律师", + "主办律师": "李律师", + "助理律师": "张律师", + "收益分配": "50%,30%,20%" + }, + "charge": "按标的额5%收费", + "contract": "http://example.com/contract.pdf", + "state": "审核中" + } + ], + "code": 0 +} +``` + +--- + +### 1.3 编辑立项登记 + +**接口地址:** `POST /business/editproject` + +**接口描述:** 编辑立项登记信息。注意:项目类型、合同编号不允许修改。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 立项登记ID | +| times | String | 否 | 立项日期 | +| client_info | String | 否 | 委托人身份信息 | +| party_info | String | 否 | 相对方身份信息 | +| description | String | 否 | 项目简述 | +| responsiblefor | Object/Dict | 否 | 负责人信息(字典格式,负责人必填,其余选填) | +| charge | String | 否 | 收费情况 | +| contract | File[] | 否 | 上传合同文件 | + +**请求示例:** +```json +{ + "id": 1, + "times": "2024-01-02", + "charge": "按标的额6%收费", + "responsiblefor": { + "负责人": "王律师", + "主办律师": "李律师", + "助理律师": "张律师", + "收益分配": "50%,30%,20%" + } +} +``` + +**响应示例:** +```json +{ + "message": "编辑成功", + "code": 0 +} +``` + +--- + +### 1.4 删除立项登记 + +**接口地址:** `POST /business/deleteProject` + +**接口描述:** 删除立项登记。如果该立项已被案件管理关联,则无法删除。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 立项登记ID | + +**请求示例:** +```json +{ + "id": 1 +} +``` + +**响应示例:** +```json +{ + "message": "删除成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "该立项已被案件管理关联,无法删除", + "code": 1 +} +``` + +--- + +### 1.5 立项登记类型查询 + +**接口地址:** `POST /business/projectquerytype` + +**接口描述:** 查询指定类型在今年的立项登记数量。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| type | String | 是 | 项目类型 | + +**请求示例:** +```json +{ + "type": "民事诉讼" +} +``` + +**响应示例:** +```json +{ + "message": "查询成功", + "data": { + "count": 25 + }, + "code": 0 +} +``` + +--- + +### 1.6 获取可用于创建案件的立项登记列表 + +**接口地址:** `POST /business/preFilingLinkedCases` + +**接口描述:** 获取可以用于新增案件的立项登记列表,排除已有案件的立项登记。 + +**请求参数:** 无 + +**响应示例:** +```json +{ + "message": "展示成功", + "data": [ + { + "id": 1, + "ContractNo": "HT20240101001", + "type": "民事诉讼", + "client_info": "张三,身份证号:110101199001011234", + "party_info": "李四,身份证号:110101199002021234", + "description": "合同纠纷案件" + } + ], + "code": 0 +} +``` + +--- + +## 4. 案件管理 + +### 2.1 创建/更新案件 + +**接口地址:** `POST /business/casemanagement` + +**接口描述:** 创建新案件或更新已有案件。如果案件不存在则创建,如果已存在则更新。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| project_id | Integer | 是 | 立项登记ID | +| times | String | 否 | 立案时间(格式:YYYY-MM-DD) | +| AgencyContract | File[] | 否 | 代理合同文件 | +| Contractreturn | File[] | 否 | 合同返还文件 | +| Closingapplication | File[] | 否 | 结案申请文件 | +| ChangeRequest | String | 否 | 变更申请(如果传入会触发审核流程) | +| invoice_status | String | 否 | 已开票状态(默认:未开票) | +| paymentcollection | String | 否 | 已收款金额 | +| personincharge | String | 否 | 审核人(变更申请时需要) | + +**请求示例:** +```json +{ + "project_id": 1, + "times": "2024-01-15", + "ChangeRequest": "需要变更代理方案", + "invoice_status": "已开票", + "paymentcollection": "50000" +} +``` + +**响应示例:** +```json +{ + "message": "创建成功", + "code": 0 +} +``` + +或 + +```json +{ + "message": "编辑成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少参数project_id(立项登记ID)", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "该立项登记不存在或已删除,请先完成立项登记", + "code": 1 +} +``` + +--- + +### 2.2 案件列表查询 + +**接口地址:** `POST /business/casemanagementdetail` + +**接口描述:** 分页查询案件列表,支持按时间范围、项目类型筛选。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | Integer | 是 | 页码 | +| per_page | Integer | 是 | 每页数量 | +| times | String | 否 | 开始日期(格式:YYYY-MM-DD) | +| end_time | String | 否 | 结束日期(格式:YYYY-MM-DD) | +| type | String | 否 | 项目类型 | + +**请求示例:** +```json +{ + "page": 1, + "per_page": 10, + "times": "2024-01-01", + "end_time": "2024-12-31", + "type": "民事诉讼" +} +``` + +**响应示例:** +```json +{ + "message": "展示成功", + "total": 50, + "data": [ + { + "id": 1, + "ContractNo": "HT20240101001", + "type": "民事诉讼", + "client_name": "张三,身份证号:110101199001011234", + "party_name": "李四,身份证号:110101199002021234", + "description": "合同纠纷案件", + "responsiblefor": { + "负责人": "王律师", + "主办律师": "李律师", + "助理律师": "张律师", + "收益分配": "50%,30%,20%" + }, + "charge": "按标的额5%收费", + "times": "2024-01-15", + "AgencyContract": "[\"http://example.com/agency.pdf\"]", + "Contractreturn": "[\"http://example.com/return.pdf\"]", + "Closingapplication": "[\"http://example.com/closing.pdf\"]", + "ChangeRequest": "需要变更代理方案", + "invoice_status": "已开票", + "paymentcollection": "50000", + "state": "审核中", + "project_id": 1 + } + ], + "code": 0 +} +``` + +--- + +### 2.3 编辑案件 + +**接口地址:** `POST /business/editCase` + +**接口描述:** 编辑案件信息。注意:project_id不允许修改。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 案件ID | +| times | String | 否 | 立案时间 | +| AgencyContract | File[] | 否 | 代理合同文件 | +| Contractreturn | File[] | 否 | 合同返还文件 | +| Closingapplication | File[] | 否 | 结案申请文件 | +| ChangeRequest | String | 否 | 变更申请(如果传入会触发审核流程) | +| invoice_status | String | 否 | 已开票状态 | +| paymentcollection | String | 否 | 已收款金额 | +| personincharge | String | 否 | 审核人(变更申请时需要) | + +**请求示例:** +```json +{ + "id": 1, + "invoice_status": "已开票", + "paymentcollection": "60000" +} +``` + +**响应示例:** +```json +{ + "message": "编辑成功", + "code": 0 +} +``` + +--- + +### 2.4 删除案件 + +**接口地址:** `POST /business/deleteCase` + +**接口描述:** 删除案件(软删除)。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | Integer | 是 | 案件ID | + +**请求示例:** +```json +{ + "id": 1 +} +``` + +**响应示例:** +```json +{ + "message": "删除成功", + "code": 0 +} +``` + +--- + +## 5. 发票管理 + +### 3.1 上传发票 + +**接口地址:** `POST /business/uploadinvoice` + +**接口描述:** 为案件上传发票。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| case_id | Integer | 是 | 案件ID | +| amount | String | 否 | 金额 | +| file | File[] | 否 | 发票文件(图片或PDF) | + +**请求示例:** +```json +{ + "case_id": 1, + "amount": "50000" +} +``` + +**响应示例:** +```json +{ + "message": "上传成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少参数case_id", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "案件不存在", + "code": 1 +} +``` + +--- + +### 3.2 发票详情查询 + +**接口地址:** `POST /business/invoicedetail` + +**接口描述:** 查询指定案件的所有发票。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| case_id | Integer | 是 | 案件ID | + +**请求示例:** +```json +{ + "case_id": 1 +} +``` + +**响应示例:** +```json +{ + "message": "展示成功", + "data": [ + { + "id": 1, + "amount": "50000", + "file": "[\"http://example.com/invoice1.pdf\", \"http://example.com/invoice2.pdf\"]" + } + ], + "code": 0 +} +``` + +--- + +## 6. 案件日志 + +### 4.1 添加案件日志 + +**接口地址:** `POST /business/log` + +**接口描述:** 为案件添加日志记录。 + +**请求头:** +``` +Content-Type: multipart/form-data +token: {用户token} +``` + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| case_id | Integer | 是 | 案件ID | +| content | String | 是 | 日志内容 | +| file | File[] | 否 | 附件文件 | + +**请求示例:** +```json +{ + "case_id": 1, + "content": "今天与客户进行了电话沟通,确认了案件进展" +} +``` + +**响应示例:** +```json +{ + "message": "添加成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少参数", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "案件不存在", + "code": 1 +} +``` + +--- + +### 4.2 案件日志列表查询 + +**接口地址:** `POST /business/logdetail` + +**接口描述:** 分页查询所有案件日志。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | Integer | 是 | 页码 | +| per_page | Integer | 是 | 每页数量 | + +**请求示例:** +```json +{ + "page": 1, + "per_page": 10 +} +``` + +**响应示例:** +```json +{ + "message": "展示成功", + "total": 100, + "data": [ + { + "id": 1, + "content": "今天与客户进行了电话沟通,确认了案件进展", + "times": "2024-01-20", + "username": "王律师", + "file": "[\"http://example.com/attachment.pdf\"]" + } + ], + "code": 0 +} +``` + +--- + +## 7. 其他接口 + +### 5.1 累加收款 + +**接口地址:** `POST /business/accumulate` + +**接口描述:** 累加案件的已收款金额。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| case_id | Integer | 是 | 案件ID | +| paymentcollection | String | 是 | 要累加的金额 | + +**请求示例:** +```json +{ + "case_id": 1, + "paymentcollection": "10000" +} +``` + +**响应示例:** +```json +{ + "message": "成功", + "code": 0 +} +``` + +**错误响应:** +```json +{ + "status": "error", + "message": "缺少参数case_id", + "code": 1 +} +``` + +或 + +```json +{ + "status": "error", + "message": "案件不存在", + "code": 1 +} +``` + +--- + +## 通用说明 + +### 响应码说明 + +| code | 说明 | +|------|------| +| 0 | 成功 | +| 1 | 失败/错误 | + +### 认证说明 + +所有接口都需要在请求头中携带 `token` 参数进行身份认证。 + +### 文件上传说明 + +- 文件上传使用 `multipart/form-data` 格式 +- 支持多文件上传,使用数组形式:`file[]` +- 文件上传后返回的是文件URL字符串或JSON数组字符串 + +### 分页说明 + +- `page`: 页码,从1开始 +- `per_page`: 每页数量 +- `total`: 总记录数 + +### 状态说明 + +- **立项登记状态:** `审核中`、`已通过`、`已拒绝` 等 +- **案件状态:** `审核中`、`已通过`、`已拒绝` 等 +- **已开票状态:** `未开票`、`已开票` 等 + +### 审核流程说明 + +- 个人团队:直接到财务团队审核 +- 团队类型:需要按顺序经过审核人审核,最后到财务团队 +- 审核人可以通过 `approvers` 参数指定(推荐使用用户ID数组) + +--- + +## 业务流程 + +### 完整流程 + +1. **创建预立案登记**(可选)→ `POST /business/register` +2. **创建投标登记**(可选)→ `POST /business/bid` +3. **创建立项登记** → `POST /business/project` +4. **创建案件** → `POST /business/casemanagement`(使用立项登记的ID) +5. **上传发票** → `POST /business/uploadinvoice`(使用案件的ID) +6. **添加案件日志** → `POST /business/log`(使用案件的ID) +7. **累加收款** → `POST /business/accumulate`(使用案件的ID) + +**注意:** 预立案和投标登记已与立项登记、案件管理拆分,可以独立使用,不再有强制关联关系。 + +### 数据关联关系 + +``` +预立案登记 (PreFiling) - 独立模块,仅增删改查 +投标登记 (Bid) - 独立模块,仅增删改查 + +立项登记 (ProjectRegistration) - 独立创建 + └── 案件 (Case) [通过 project_id 关联] + ├── 发票 (Invoice) [通过 case_id 关联] + └── 案件日志 (Caselog) [通过 case_id 关联] +``` + +**说明:** +- 预立案登记和投标登记已独立,只有增删改查功能,不再与其他模块关联 +- 立项登记独立创建,不再需要预立案 +- 案件管理关联立项登记,不再关联预立案 + +--- + +## 注意事项 + +1. **预立案登记和投标登记**:独立模块,只有增删改查功能,不与其他模块关联 +2. **立项登记必须先创建**,然后才能创建案件 +3. **合同编号必须唯一**,不能重复 +4. **案件创建后会自动关联立项登记**,无法修改关联关系 +5. **删除立项登记前**,需要先删除关联的案件 +6. **变更申请会触发审核流程**,需要提供审核人 +7. **文件上传支持多文件**,返回的是JSON字符串格式的URL数组 +8. **投标登记创建时会触发审核流程**,团队类型需要提供审核人 +9. **负责人信息格式**: + - 接受字典格式(Object)或JSON字符串格式 + - 负责人字段必填,主办律师、助理律师、收益分配为选填 + - 字典格式示例:`{"负责人":"王律师","主办律师":"李律师","助理律师":"张律师","收益分配":"50%,30%,20%"}` + - 返回时统一为字典格式 + +--- + +## 更新日志 + +### 2024-01-14 +- 优化案件逻辑,立项登记和案件管理拆分 +- 预立案和投标登记拆分,独立为仅增删改查模块,不再与其他模块关联 +- 案件管理关联立项登记,不再关联预立案 +- 添加已开票字段到案件管理 +- 发票和案件日志关联案件,不再关联预立案 +- 预立案登记:增、删、改、查(分页查询、简化列表查询) +- 投标登记:增、删、改、查(分页查询) +- **优化立项登记负责人字段**:改为字典格式,包含负责人(必填)、主办律师(选填)、助理律师(选填)、收益分配(选填)