diff --git a/current_permits.txt b/current_permits.txt deleted file mode 100644 index 849c503..0000000 --- a/current_permits.txt +++ /dev/null @@ -1,69 +0,0 @@ -《卫星地面接收设施安装服务许可证》(换发)审批,《卫星地面接收设施安装服务许可证》(注销)审批,《卫星地面接收设施安装服务许可证》(新证)审批 -《市场准入负面清单》禁止准入类:禁止违规开展金融相关经营活动“非金融机构、不从事金融活动的企业,在注册名称和经营范围中原则上不得使用与金融相关的字样”(设立依据效力层级不足允许暂时保留的禁止或许可措施) -一次性内部资料准印证核发 -互联网上网服务营业场所信息网络安全审核 -人力资源服务(不含职业中介活动、劳务派遣服务)备案 -仅销售预包装食品备案 -从事出版物零售业务许可(含音像制品、电子出版物) -从事包装装潢印刷品和其他印刷品(不含商标、票据、保密印刷)印刷经营活动企业(不含外资企业)的设立、变更审批 -从事县内道路旅客运输包车经营许可 -公共场所卫生许可 -养老机构备案 -农药经营许可 -出版物发行单位在批准的经营范围内通过互联网等信息网络从事出版物发行业务的备案 -出版物批发、零售单位设立不具备法人资格的分支机构,或者出版单位设立发行本版出版物的不具备法人资格的发行分支机构的备案 -出版物批发单位设立、变更审批 -医疗废物经营许可证核发 -医疗机构(三级医院、三级妇幼保健院、急救中心、急救站、临床检验中心、中外合资合作医疗机构、港澳台独资医疗机构)设置审批 -医疗机构(不含诊所)执业许可(执业登记) -印章刻制业许可证核发 -危险化学品建设项目安全条件审查、安全设施设计审查 -危险化学品经营许可证核发 -危险废物收集经营许可证核发(广东省厅事项名称) 【国家标准名:危险废物经营许可】 -巡游出租汽车经营许可 -巡游出租汽车车辆运营证核发 -广播电视节目制作经营许可证(载明事项变更)审批,广播电视节目制作经营许可证(新证)审批 -广播电视视频点播业务许可证(乙种)审批 -废弃电器电子产品处理企业资格审批 -建设项目环境影响评价文件审批(广东省厅事项名称) 【国家标准名:“建设项目环境影响评价审批(海洋工程、核与辐射类除外)”】 -房地产经纪机构及其分支机构设立备案 -托育机构备案 -承印加工境外一般性出版物审批 -承印加工境外包装装潢和其他印刷品备案核准 -排污许可证核发 -放射诊疗许可 -旅馆业特种行业许可证核发 -机动车维修经营备案 -机动车驾驶培训机构备案 -校车使用许可 -歌舞娱乐场所从事娱乐场所经营活动审批 -民办职业培训学校新设立、变更 -水路运输辅助业登记备案 -港口经营许可 -游艺娱乐场所从事娱乐场所经营活动审批 -游艺娱乐场所从事娱乐场所经营活动审批,内资娱乐场所变更、延续、补证、注销审批 -演出经纪机构延续,演出经纪机构从事营业性演出经营活动审批,演出经纪机构变更,演出经纪机构补证,演出经纪机构注销 -烟花爆竹(批发)许可证核发 -烟草专卖零售许可 -烟草专卖零售许可证核发(电子烟零售) -燃气燃烧器具安装、维修企业资质核准 -燃气经营许可证核发 -特种设备使用登记 -生鲜乳准运证明核发 -电视剧制作许可证(乙种)载明内容变更,电视剧制作许可证(乙种)延期,电视剧制作许可证(乙种)申请 -社会力量举办非学历教育机构审批 -种畜禽生产经营许可 -第三类医疗器械经营许可 -第二、三类非药品类易制毒化学品生产、经营备案 -第二类精神药品零售业务审批 -经营性人力资源服务许可 -药品经营许可证(零售) -营业执照 -营业执照 (必填项) -蜂种生产经营许可证核发 -辐射安全许可 -道路旅客运输站(场)经营许可 -道路货物运输经营许可 -金属冶炼建设项目安全设施设计审查 -音像制作单位的变更审批,音像制作单位的设立审批 -饮用水供水单位卫生许可 diff --git a/lawrisk/api/v2.py b/lawrisk/api/v2.py index 086fae9..7dd3848 100644 --- a/lawrisk/api/v2.py +++ b/lawrisk/api/v2.py @@ -45,6 +45,7 @@ from lawrisk.services.licensing_repo import ( filter_permits_advanced, list_unbound_permits, list_operation_logs, + _lic_pg_conn, ) from lawrisk.services.auth_service import ( list_users, @@ -319,15 +320,36 @@ def admin_create_user(): try: dept_name = (payload.get("display_name") or username).strip() or username dept_code = username.upper() - created_department = create_service_department( - name=dept_name, - code=dept_code, - phone=department_phone, - parent_id=parent_department_id, - region_id=region_id, - ) - service_department_id = created_department.get("id") + + # Check if department code already exists + with _lic_pg_conn() as conn: + cur = conn.cursor() + cur.execute("SELECT id, name, code, region_id FROM service_departments WHERE code = %s", (dept_code,)) + row = cur.fetchone() + if row: + service_department_id = str(row[0]) + created_department = { + "id": str(row[0]), + "name": str(row[1]), + "code": str(row[2]), + "region_id": str(row[3]) if row[3] else None + } + + if not service_department_id: + created_department = create_service_department( + name=dept_name, + code=dept_code, + phone=department_phone, + parent_id=parent_department_id, + region_id=region_id, + ) + service_department_id = created_department.get("id") except Exception as exc: + err_msg = str(exc) + if "duplicate key value" in err_msg and "service_departments_code_key" in err_msg: + return jsonify({"success": False, "message": f"创建单位失败: 单位代码 {dept_code} 已存在"}), 400 + if "violates unique constraint" in err_msg: + return jsonify({"success": False, "message": "创建单位失败: 数据重复"}), 400 return jsonify({"success": False, "message": f"创建单位失败: {exc}"}), 400 try: @@ -350,6 +372,9 @@ def admin_create_user(): except ValueError as exc: return jsonify({"success": False, "message": str(exc)}), 400 except Exception as exc: + err_msg = str(exc) + if "duplicate key value" in err_msg and "auth_users_username_key" in err_msg: + return jsonify({"success": False, "message": f"创建账号失败: 用户名 {username} 已存在"}), 400 return jsonify({"success": False, "message": str(exc)}), 500 @@ -596,6 +621,9 @@ def admin_create_service_department(): except ValueError as exc: return jsonify({"success": False, "message": str(exc)}), 400 except Exception as exc: + err_msg = str(exc) + if "duplicate key value" in err_msg: + return jsonify({"success": False, "message": "服务部门代码或名称已存在"}), 400 return jsonify({"success": False, "message": str(exc)}), 500 diff --git a/lawrisk/services/auth_service.py b/lawrisk/services/auth_service.py index 2fa6f3c..83a6db3 100644 --- a/lawrisk/services/auth_service.py +++ b/lawrisk/services/auth_service.py @@ -269,16 +269,24 @@ def _row_to_user(row: tuple[Any, ...], columns: tuple[str, ...]) -> Dict[str, An return {col: row[idx] for idx, col in enumerate(columns)} +def _safe_str(val: Any) -> Optional[str]: + if val is None: + return None + return str(val) + def _public_user_payload(user: Dict[str, Any]) -> Dict[str, Any]: department = None - if user.get("service_department_id"): + # Ensure IDs are strings as psycopg2 might return UUID objects + dept_id = _safe_str(user.get("service_department_id")) + + if dept_id: department = { - "id": user.get("service_department_id"), + "id": dept_id, "name": user.get("service_department_name"), "code": user.get("service_department_code"), "phone": user.get("service_department_phone"), - "parent_id": user.get("service_department_parent_id"), - "region_id": user.get("service_department_region_id"), + "parent_id": _safe_str(user.get("service_department_parent_id")), + "region_id": _safe_str(user.get("service_department_region_id")), "region_name": user.get("service_department_region_name"), "role": user.get("department_role"), } @@ -295,7 +303,7 @@ def _public_user_payload(user: Dict[str, Any]) -> Dict[str, Any]: "grade": user.get("grade"), "is_active": user.get("is_active", True), "department": department, - "department_id": user.get("service_department_id"), + "department_id": dept_id, "created_at": created_at_value, } @@ -437,20 +445,30 @@ def create_user( # 如果未传入部门,则自动创建同名单位并绑定 dept_token = (service_department_id or "").strip() or None if not dept_token: - try: - dept_name = (display_name or username_clean).strip() or username_clean - dept_code = username_clean.upper() - created = lic_repo.create_service_department( - name=dept_name, - code=dept_code, - phone=(service_department_phone or "").strip() or None, - parent_id=(parent_department_id or "").strip() or None, - region_id=(service_department_region_id or "").strip() or None, - operator=operator, - ) - dept_token = created.get("id") - except Exception as exc: - raise ValueError(f"自动创建单位失败: {exc}") + dept_name = (display_name or username_clean).strip() or username_clean + dept_code = username_clean.upper() + + # 检查是否已存在同代码的单位 + with _auth_conn() as conn: + cur = conn.cursor() + cur.execute("SELECT id FROM service_departments WHERE code = %s", (dept_code,)) + row = cur.fetchone() + if row: + dept_token = str(row[0]) + + if not dept_token: + try: + created = lic_repo.create_service_department( + name=dept_name, + code=dept_code, + phone=(service_department_phone or "").strip() or None, + parent_id=(parent_department_id or "").strip() or None, + region_id=(service_department_region_id or "").strip() or None, + operator=operator, + ) + dept_token = created.get("id") + except Exception as exc: + raise ValueError(f"自动创建单位失败: {exc}") user_id = uuid.uuid4().hex password_hash = pwd_context.hash(password) diff --git a/lawrisk/services/licensing_repo.py b/lawrisk/services/licensing_repo.py index 7c6931e..6d68639 100644 --- a/lawrisk/services/licensing_repo.py +++ b/lawrisk/services/licensing_repo.py @@ -2501,18 +2501,40 @@ _THEME_SUMMARY_SELECT = """ t.id, t.name, COUNT(DISTINCT rtp.permit_id) AS permit_count, - COUNT(DISTINCT rtp.region_id) AS region_count + COUNT(DISTINCT rtp.region_id) AS region_count, + STRING_AGG(DISTINCT r.name, ',') AS region_names FROM themes t LEFT JOIN region_theme_permits rtp ON rtp.theme_id = t.id + LEFT JOIN regions r ON rtp.region_id = r.id """ def _serialize_theme_row(record: Dict[str, Any]) -> Dict[str, Any]: + region_names_str = record.get("region_names") or "" + levels = set() + r_names = [n.strip() for n in region_names_str.split(',') if n.strip()] + + for r_name in r_names: + if r_name == "市级" or r_name == "佛山市": + levels.add("市级") + else: + # Assuming any other region is District level (e.g. 禅城区, 南海区) + levels.add("区级") + + impl_level_list = [] + if "市级" in levels: + impl_level_list.append("市级") + if "区级" in levels: + impl_level_list.append("区级") + + impl_level = "、".join(impl_level_list) if impl_level_list else "-" + return { "id": _to_optional_str(record.get("id")), "name": record.get("name"), "permit_count": int(record.get("permit_count") or 0), "region_count": int(record.get("region_count") or 0), + "implementation_level": impl_level, } diff --git a/rebuild_log.txt b/rebuild_log.txt deleted file mode 100644 index ca130b8..0000000 --- a/rebuild_log.txt +++ /dev/null @@ -1,12 +0,0 @@ -Clearing existing data... -Data cleared. -Fetching Region ID for '市级'... -Region ID: 2c29ca08-efc6-4e2c-abc2-d73685e0bdd1 -Reading Excel... -Dropped 1 duplicate rows. -Found 61 unique rows. -Loading existing permits... -Loaded 72 existing permits. -Saving report... -File locked, saving to '主题-事项绑定结果_new.xlsx' instead. -Done. diff --git a/schema_info.txt b/schema_info.txt deleted file mode 100644 index 99295ea..0000000 --- a/schema_info.txt +++ /dev/null @@ -1,68 +0,0 @@ -Connecting to postgres@8.138.196.105:5432/licensing_risks - ---- Listing Tables --- -Table Found: themes -Table Found: region_theme_permits -Table Found: region_themes -Table Found: risks -Table Found: operation_logs -Table Found: permit_approval_departments -Table Found: business_scopes -Table Found: permit_subitems -Table Found: regions -Table Found: permits -Table Found: region_permit_details -Table Found: permit_risk_snapshots -Table Found: region_permit_risk_vw -Table Found: region_permit_risks -Table Found: region_permit_scopes -Table Found: region_scopes -Table Found: permit_theme_rules -Table Found: region_permit_subitems -Table Found: region_permit_theme_overrides -Table Found: auth_users -Table Found: service_departments -Table Found: permit_files -Table Found: permit_sources -Table Found: permit_file_links -Table Found: service_department_permits - ---- Structure of themes --- - id (uuid) - name (text) - ---- Structure of theme_permits --- - (Table not found or empty or different schema) - ---- Structure of region_theme_permits --- - region_id (uuid) - theme_id (uuid) - permit_id (uuid) - ---- Structure of permits --- - id (uuid) - name (text) - ---- Structure of permit_theme_rules --- - id (uuid) - theme_id (uuid) - created_at (timestamp with time zone) - region_id (uuid) - permit_name (text) - responsible_department (text) - ---- Structure of permit_themes --- - (Table not found or empty or different schema) - ---- Excel Analysis --- - 0 ... 13 -0 佛山市企业开办风险提示涉企许可(备案)\n事项清单 ... NaN -1 序号 ... 是否首次上线 -2 1 ... 是 -3 2 ... 是 -4 3 ... 是 - -[5 rows x 14 columns] - -Detected header row: 0 -Columns: ['佛山市企业开办风险提示涉企许可(备案)\n事项清单', 'Unnamed: 1', 'Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4', 'Unnamed: 5', 'Unnamed: 6', 'Unnamed: 7', 'Unnamed: 8', 'Unnamed: 9', 'Unnamed: 10', 'Unnamed: 11', 'Unnamed: 12', 'Unnamed: 13'] diff --git a/static/db_admin.html b/static/db_admin.html index 300c110..a1eb0c4 100644 --- a/static/db_admin.html +++ b/static/db_admin.html @@ -4,7 +4,7 @@ - 数据库维护页面 - LawRisk + 佛山市企业开办风险提示系统