Backup database 2025-12-25 and clean up project structure
This commit is contained in:
parent
a9dc7c490e
commit
06944cd251
|
|
@ -31,6 +31,12 @@ analyze_*.py
|
||||||
final_importer.py
|
final_importer.py
|
||||||
ultimate_importer.py
|
ultimate_importer.py
|
||||||
*_importer.py
|
*_importer.py
|
||||||
|
repair_*.py
|
||||||
|
script_*.py
|
||||||
|
test_*.py
|
||||||
|
|
||||||
|
# Database Backups
|
||||||
|
backup_*.sql
|
||||||
|
|
||||||
# Temporary Data/Reports
|
# Temporary Data/Reports
|
||||||
excel_info.txt
|
excel_info.txt
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
《卫星地面接收设施安装服务许可证》(换发)审批,《卫星地面接收设施安装服务许可证》(注销)审批,《卫星地面接收设施安装服务许可证》(新证)审批
|
||||||
|
《市场准入负面清单》禁止准入类:禁止违规开展金融相关经营活动“非金融机构、不从事金融活动的企业,在注册名称和经营范围中原则上不得使用与金融相关的字样”(设立依据效力层级不足允许暂时保留的禁止或许可措施)
|
||||||
|
一次性内部资料准印证核发
|
||||||
|
互联网上网服务营业场所信息网络安全审核
|
||||||
|
人力资源服务(不含职业中介活动、劳务派遣服务)备案
|
||||||
|
仅销售预包装食品备案
|
||||||
|
从事出版物零售业务许可(含音像制品、电子出版物)
|
||||||
|
从事包装装潢印刷品和其他印刷品(不含商标、票据、保密印刷)印刷经营活动企业(不含外资企业)的设立、变更审批
|
||||||
|
从事县内道路旅客运输包车经营许可
|
||||||
|
公共场所卫生许可
|
||||||
|
养老机构备案
|
||||||
|
农药经营许可
|
||||||
|
出版物发行单位在批准的经营范围内通过互联网等信息网络从事出版物发行业务的备案
|
||||||
|
出版物批发、零售单位设立不具备法人资格的分支机构,或者出版单位设立发行本版出版物的不具备法人资格的发行分支机构的备案
|
||||||
|
出版物批发单位设立、变更审批
|
||||||
|
医疗废物经营许可证核发
|
||||||
|
医疗机构(三级医院、三级妇幼保健院、急救中心、急救站、临床检验中心、中外合资合作医疗机构、港澳台独资医疗机构)设置审批
|
||||||
|
医疗机构(不含诊所)执业许可(执业登记)
|
||||||
|
印章刻制业许可证核发
|
||||||
|
危险化学品建设项目安全条件审查、安全设施设计审查
|
||||||
|
危险化学品经营许可证核发
|
||||||
|
危险废物收集经营许可证核发(广东省厅事项名称) 【国家标准名:危险废物经营许可】
|
||||||
|
巡游出租汽车经营许可
|
||||||
|
巡游出租汽车车辆运营证核发
|
||||||
|
广播电视节目制作经营许可证(载明事项变更)审批,广播电视节目制作经营许可证(新证)审批
|
||||||
|
广播电视视频点播业务许可证(乙种)审批
|
||||||
|
废弃电器电子产品处理企业资格审批
|
||||||
|
建设项目环境影响评价文件审批(广东省厅事项名称) 【国家标准名:“建设项目环境影响评价审批(海洋工程、核与辐射类除外)”】
|
||||||
|
房地产经纪机构及其分支机构设立备案
|
||||||
|
托育机构备案
|
||||||
|
承印加工境外一般性出版物审批
|
||||||
|
承印加工境外包装装潢和其他印刷品备案核准
|
||||||
|
排污许可证核发
|
||||||
|
放射诊疗许可
|
||||||
|
旅馆业特种行业许可证核发
|
||||||
|
机动车维修经营备案
|
||||||
|
机动车驾驶培训机构备案
|
||||||
|
校车使用许可
|
||||||
|
歌舞娱乐场所从事娱乐场所经营活动审批
|
||||||
|
民办职业培训学校新设立、变更
|
||||||
|
水路运输辅助业登记备案
|
||||||
|
港口经营许可
|
||||||
|
游艺娱乐场所从事娱乐场所经营活动审批
|
||||||
|
游艺娱乐场所从事娱乐场所经营活动审批,内资娱乐场所变更、延续、补证、注销审批
|
||||||
|
演出经纪机构延续,演出经纪机构从事营业性演出经营活动审批,演出经纪机构变更,演出经纪机构补证,演出经纪机构注销
|
||||||
|
烟花爆竹(批发)许可证核发
|
||||||
|
烟草专卖零售许可
|
||||||
|
烟草专卖零售许可证核发(电子烟零售)
|
||||||
|
燃气燃烧器具安装、维修企业资质核准
|
||||||
|
燃气经营许可证核发
|
||||||
|
特种设备使用登记
|
||||||
|
生鲜乳准运证明核发
|
||||||
|
电视剧制作许可证(乙种)载明内容变更,电视剧制作许可证(乙种)延期,电视剧制作许可证(乙种)申请
|
||||||
|
社会力量举办非学历教育机构审批
|
||||||
|
种畜禽生产经营许可
|
||||||
|
第三类医疗器械经营许可
|
||||||
|
第二、三类非药品类易制毒化学品生产、经营备案
|
||||||
|
第二类精神药品零售业务审批
|
||||||
|
经营性人力资源服务许可
|
||||||
|
药品经营许可证(零售)
|
||||||
|
营业执照
|
||||||
|
营业执照 (必填项)
|
||||||
|
蜂种生产经营许可证核发
|
||||||
|
辐射安全许可
|
||||||
|
道路旅客运输站(场)经营许可
|
||||||
|
道路货物运输经营许可
|
||||||
|
金属冶炼建设项目安全设施设计审查
|
||||||
|
音像制作单位的变更审批,音像制作单位的设立审批
|
||||||
|
饮用水供水单位卫生许可
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,33 @@
|
||||||
|
import sqlite3
|
||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
|
||||||
|
db_path = 'law_risk.db'
|
||||||
|
excel_path = '主题-事项绑定.xlsx'
|
||||||
|
|
||||||
|
print("--- Database Schema ---")
|
||||||
|
if os.path.exists(db_path):
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
||||||
|
tables = cursor.fetchall()
|
||||||
|
for table_name in tables:
|
||||||
|
print(f"Table: {table_name[0]}")
|
||||||
|
cursor.execute(f"PRAGMA table_info({table_name[0]})")
|
||||||
|
columns = cursor.fetchall()
|
||||||
|
for col in columns:
|
||||||
|
print(f" {col[1]} ({col[2]})")
|
||||||
|
conn.close()
|
||||||
|
else:
|
||||||
|
print(f"Database file not found: {db_path}")
|
||||||
|
|
||||||
|
print("\n--- Excel File Preview ---")
|
||||||
|
if os.path.exists(excel_path):
|
||||||
|
try:
|
||||||
|
df = pd.read_excel(excel_path)
|
||||||
|
print(df.head())
|
||||||
|
print("\nColumns:", df.columns.tolist())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading Excel: {e}")
|
||||||
|
else:
|
||||||
|
print(f"Excel file not found: {excel_path}")
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,69 @@
|
||||||
|
import os
|
||||||
|
import pg8000.dbapi as pg
|
||||||
|
import pandas as pd
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Redirect stdout to a file
|
||||||
|
sys.stdout = open('task_analysis.txt', 'w', encoding='utf-8')
|
||||||
|
|
||||||
|
def load_env():
|
||||||
|
env_vars = {}
|
||||||
|
try:
|
||||||
|
with open('.env', 'r', encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
if '=' in line:
|
||||||
|
k, v = line.split('=', 1)
|
||||||
|
env_vars[k.strip()] = v.strip()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return env_vars
|
||||||
|
|
||||||
|
env = load_env()
|
||||||
|
HOST = env.get("LIC_PG_HOST", "172.24.240.1")
|
||||||
|
PORT = int(env.get("LIC_PG_PORT", "5432"))
|
||||||
|
USER = env.get("LIC_PG_USER", "postgres")
|
||||||
|
PASSWORD = env.get("LIC_PG_PASSWORD", "")
|
||||||
|
DATABASE = env.get("LIC_PG_DATABASE", "licensing_risks")
|
||||||
|
|
||||||
|
print(f"Connecting to DB...")
|
||||||
|
try:
|
||||||
|
conn = pg.connect(host=HOST, port=PORT, user=USER, password=PASSWORD, database=DATABASE)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
print("\n--- Regions ---")
|
||||||
|
cursor.execute("SELECT id, name FROM regions")
|
||||||
|
for r in cursor.fetchall():
|
||||||
|
print(f"{r[1]}: {r[0]}")
|
||||||
|
|
||||||
|
print("\n--- Current Counts ---")
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM themes")
|
||||||
|
print(f"Themes: {cursor.fetchone()[0]}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM region_theme_permits")
|
||||||
|
print(f"Region Theme Permits: {cursor.fetchone()[0]}")
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM permit_theme_rules")
|
||||||
|
print(f"Permit Theme Rules: {cursor.fetchone()[0]}")
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DB Error: {e}")
|
||||||
|
|
||||||
|
print("\n--- Excel Structure ---")
|
||||||
|
try:
|
||||||
|
# Read header at row 1
|
||||||
|
df = pd.read_excel('主题-事项绑定.xlsx', header=1)
|
||||||
|
print("Columns:", df.columns.tolist())
|
||||||
|
# Identify key columns
|
||||||
|
print("\nSample Data:")
|
||||||
|
print(df.iloc[:3].to_string())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Excel Error: {e}")
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import pandas as pd
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.stdout = open('excel_sheets.txt', 'w', encoding='utf-8')
|
||||||
|
|
||||||
|
try:
|
||||||
|
xl = pd.ExcelFile('主题-事项绑定.xlsx')
|
||||||
|
print("Sheet names:", xl.sheet_names)
|
||||||
|
|
||||||
|
for sheet in xl.sheet_names:
|
||||||
|
print(f"\n--- Sheet: {sheet} ---")
|
||||||
|
df = pd.read_excel(xl, sheet_name=sheet, header=None, nrows=5)
|
||||||
|
print(df.to_string())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
|
@ -5283,8 +5283,7 @@ def list_permit_risk_snapshot_summaries(
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Return snapshot summaries for checkpoint history views.
|
Return snapshot summaries for checkpoint history views.
|
||||||
|
Groups results by snapshot_batch_id to return one entry per batch operation.
|
||||||
The payload JSON stores the flattened view row, so we project key fields for UI display.
|
|
||||||
"""
|
"""
|
||||||
filters: List[str] = []
|
filters: List[str] = []
|
||||||
params: List[Any] = []
|
params: List[Any] = []
|
||||||
|
|
@ -5301,29 +5300,34 @@ def list_permit_risk_snapshot_summaries(
|
||||||
|
|
||||||
where_clause = f"WHERE {' AND '.join(filters)}" if filters else ""
|
where_clause = f"WHERE {' AND '.join(filters)}" if filters else ""
|
||||||
|
|
||||||
|
# Group by batch_id so that we show one history entry per operation (which may contain multiple risk items).
|
||||||
|
# If snapshot_batch_id is missing (legacy data), fall back to snapshot_id to treat each as unique.
|
||||||
sql = f"""
|
sql = f"""
|
||||||
SELECT
|
SELECT
|
||||||
snapshot_id,
|
MAX(snapshot_id::text) as snapshot_id,
|
||||||
region_id,
|
MAX(region_id::text) as region_id,
|
||||||
permit_id,
|
MAX(permit_id::text) as permit_id,
|
||||||
risk_id,
|
MAX(risk_id::text) as risk_id,
|
||||||
permit_risk_key,
|
MAX(permit_risk_key) as permit_risk_key,
|
||||||
version,
|
MAX(version) as version,
|
||||||
edited_by,
|
MAX(edited_by) as edited_by,
|
||||||
change_summary,
|
MAX(change_summary) as change_summary,
|
||||||
created_at,
|
MAX(created_at) as created_at,
|
||||||
payload ->> 'region_name' AS region_name,
|
|
||||||
payload ->> 'permit_name' AS permit_name,
|
MAX(payload ->> 'region_name') AS region_name,
|
||||||
payload ->> 'risk_content' AS risk_content,
|
MAX(payload ->> 'permit_name') AS permit_name,
|
||||||
payload ->> 'legal_basis' AS legal_basis,
|
MAX(payload ->> 'risk_content') AS risk_content,
|
||||||
payload ->> 'document_no' AS document_no,
|
MAX(payload ->> 'legal_basis') AS legal_basis,
|
||||||
payload ->> 'permit_status' AS permit_status,
|
MAX(payload ->> 'document_no') AS document_no,
|
||||||
payload ->> 'snapshot_batch_id' AS snapshot_batch_id,
|
MAX(payload ->> 'permit_status') AS permit_status,
|
||||||
payload ->> 'permit_source_name' AS permit_source_name,
|
COALESCE(MAX(payload ->> 'snapshot_batch_id'), MAX(snapshot_id::text)) AS snapshot_batch_id,
|
||||||
payload ->> 'permit_source_type' AS permit_source_type
|
MAX(payload ->> 'permit_source_name') AS permit_source_name,
|
||||||
|
MAX(payload ->> 'permit_source_type') AS permit_source_type,
|
||||||
|
COUNT(*) as item_count
|
||||||
FROM permit_risk_snapshots
|
FROM permit_risk_snapshots
|
||||||
{where_clause}
|
{where_clause}
|
||||||
ORDER BY created_at DESC
|
GROUP BY COALESCE(payload ->> 'snapshot_batch_id', snapshot_id::text)
|
||||||
|
ORDER BY MAX(created_at) DESC
|
||||||
LIMIT %s OFFSET %s
|
LIMIT %s OFFSET %s
|
||||||
"""
|
"""
|
||||||
params.extend([limit, offset])
|
params.extend([limit, offset])
|
||||||
|
|
@ -5353,6 +5357,7 @@ def list_permit_risk_snapshot_summaries(
|
||||||
snapshot_batch_id,
|
snapshot_batch_id,
|
||||||
permit_source_name,
|
permit_source_name,
|
||||||
permit_source_type,
|
permit_source_type,
|
||||||
|
item_count,
|
||||||
) in rows:
|
) in rows:
|
||||||
summaries.append(
|
summaries.append(
|
||||||
{
|
{
|
||||||
|
|
@ -5361,7 +5366,7 @@ def list_permit_risk_snapshot_summaries(
|
||||||
"permit_id": str(permit_uuid),
|
"permit_id": str(permit_uuid),
|
||||||
"risk_id": str(risk_uuid),
|
"risk_id": str(risk_uuid),
|
||||||
"permit_risk_key": permit_risk_key,
|
"permit_risk_key": permit_risk_key,
|
||||||
"version": int(version),
|
"version": int(version) if version else 0,
|
||||||
"created_at": _convert_snapshot_value(created_at),
|
"created_at": _convert_snapshot_value(created_at),
|
||||||
"edited_by": editor,
|
"edited_by": editor,
|
||||||
"change_summary": summary_text or "",
|
"change_summary": summary_text or "",
|
||||||
|
|
@ -5374,6 +5379,7 @@ def list_permit_risk_snapshot_summaries(
|
||||||
"snapshot_batch_id": snapshot_batch_id or "",
|
"snapshot_batch_id": snapshot_batch_id or "",
|
||||||
"permit_source_name": permit_source_name or "",
|
"permit_source_name": permit_source_name or "",
|
||||||
"permit_source_type": permit_source_type or "",
|
"permit_source_type": permit_source_type or "",
|
||||||
|
"item_count": int(item_count),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return summaries
|
return summaries
|
||||||
|
|
@ -5385,7 +5391,7 @@ def count_permit_risk_snapshots(
|
||||||
permit_id: Optional[str] = None,
|
permit_id: Optional[str] = None,
|
||||||
edited_by: Optional[str] = None,
|
edited_by: Optional[str] = None,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Return total snapshots matching the optional filters."""
|
"""Return total snapshot batches matching the optional filters."""
|
||||||
filters: List[str] = []
|
filters: List[str] = []
|
||||||
params: List[Any] = []
|
params: List[Any] = []
|
||||||
|
|
||||||
|
|
@ -5400,7 +5406,8 @@ def count_permit_risk_snapshots(
|
||||||
params.append(edited_by)
|
params.append(edited_by)
|
||||||
|
|
||||||
where_clause = f"WHERE {' AND '.join(filters)}" if filters else ""
|
where_clause = f"WHERE {' AND '.join(filters)}" if filters else ""
|
||||||
sql = f"SELECT COUNT(*) FROM permit_risk_snapshots {where_clause}"
|
# Count distinct batches (using same COALESCE logic as list query)
|
||||||
|
sql = f"SELECT COUNT(DISTINCT COALESCE(payload ->> 'snapshot_batch_id', snapshot_id::text)) FROM permit_risk_snapshots {where_clause}"
|
||||||
|
|
||||||
with _lic_pg_conn() as conn:
|
with _lic_pg_conn() as conn:
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
import os
|
||||||
|
import pg8000.dbapi as pg
|
||||||
|
import pandas as pd
|
||||||
|
import uuid
|
||||||
|
import datetime
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Output log
|
||||||
|
log_file = open('rebuild_log.txt', 'w', encoding='utf-8')
|
||||||
|
sys.stdout = log_file
|
||||||
|
|
||||||
|
def log(msg):
|
||||||
|
print(msg)
|
||||||
|
log_file.flush()
|
||||||
|
|
||||||
|
def load_env():
|
||||||
|
env_vars = {}
|
||||||
|
try:
|
||||||
|
with open('.env', 'r', encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
if '=' in line:
|
||||||
|
k, v = line.split('=', 1)
|
||||||
|
env_vars[k.strip()] = v.strip()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return env_vars
|
||||||
|
|
||||||
|
env = load_env()
|
||||||
|
HOST = env.get("LIC_PG_HOST", "172.24.240.1")
|
||||||
|
PORT = int(env.get("LIC_PG_PORT", "5432"))
|
||||||
|
USER = env.get("LIC_PG_USER", "postgres")
|
||||||
|
PASSWORD = env.get("LIC_PG_PASSWORD", "")
|
||||||
|
DATABASE = env.get("LIC_PG_DATABASE", "licensing_risks")
|
||||||
|
|
||||||
|
CONN = None
|
||||||
|
|
||||||
|
def get_conn():
|
||||||
|
global CONN
|
||||||
|
if CONN is None:
|
||||||
|
CONN = pg.connect(host=HOST, port=PORT, user=USER, password=PASSWORD, database=DATABASE)
|
||||||
|
CONN.autocommit = True
|
||||||
|
return CONN
|
||||||
|
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
conn = get_conn()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# 1. Clear existing data
|
||||||
|
log("Clearing existing data...")
|
||||||
|
# Order matters for foreign keys if they exist
|
||||||
|
cursor.execute("DELETE FROM region_theme_permits")
|
||||||
|
cursor.execute("DELETE FROM permit_theme_rules")
|
||||||
|
cursor.execute("DELETE FROM themes")
|
||||||
|
# cursor.execute("DELETE FROM region_themes") # If it exists? Check if it errors?
|
||||||
|
try:
|
||||||
|
cursor.execute("DELETE FROM region_themes")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
log("Data cleared.")
|
||||||
|
|
||||||
|
# 2. Get Region ID for "市级"
|
||||||
|
log("Fetching Region ID for '市级'...")
|
||||||
|
cursor.execute("SELECT id FROM regions WHERE name = '市级'")
|
||||||
|
res = cursor.fetchone()
|
||||||
|
if not res:
|
||||||
|
log("Error: '市级' region not found!")
|
||||||
|
return
|
||||||
|
region_id = res[0]
|
||||||
|
log(f"Region ID: {region_id}")
|
||||||
|
|
||||||
|
# 3. Read Excel
|
||||||
|
log("Reading Excel...")
|
||||||
|
df = pd.read_excel('主题-事项绑定.xlsx', sheet_name='新主题事项表-12个')
|
||||||
|
# Rename columns to standard
|
||||||
|
df.rename(columns={'主题名称': 'theme_name', '风险提示事项名称': 'permit_name'}, inplace=True)
|
||||||
|
# Fallback if old name is used
|
||||||
|
if 'permit_name' not in df.columns and '事项名称' in df.columns:
|
||||||
|
df.rename(columns={'事项名称': 'permit_name'}, inplace=True)
|
||||||
|
# Forward fill theme_name (handle merged cells which come as NaN)
|
||||||
|
df['theme_name'] = df['theme_name'].fillna(method='ffill')
|
||||||
|
|
||||||
|
# Clean data
|
||||||
|
df['theme_name'] = df['theme_name'].astype(str).str.strip()
|
||||||
|
df['permit_name'] = df['permit_name'].astype(str).str.strip()
|
||||||
|
|
||||||
|
# Drop duplicates to prevent unique constraint violations
|
||||||
|
original_count = len(df)
|
||||||
|
df.drop_duplicates(subset=['theme_name', 'permit_name'], inplace=True)
|
||||||
|
log(f"Dropped {original_count - len(df)} duplicate rows.")
|
||||||
|
|
||||||
|
log(f"Found {len(df)} unique rows.")
|
||||||
|
|
||||||
|
# 4. Prepare Lookups
|
||||||
|
log("Loading existing permits...")
|
||||||
|
cursor.execute("SELECT name, id FROM permits")
|
||||||
|
permit_map = {row[0].strip(): row[1] for row in cursor.fetchall()}
|
||||||
|
log(f"Loaded {len(permit_map)} existing permits.")
|
||||||
|
|
||||||
|
# 5. Process
|
||||||
|
theme_map = {} # name -> uuid
|
||||||
|
results = []
|
||||||
|
|
||||||
|
for idx, row in df.iterrows():
|
||||||
|
t_name = row['theme_name']
|
||||||
|
p_name = row['permit_name']
|
||||||
|
|
||||||
|
if pd.isna(t_name) or t_name == 'nan' or not t_name:
|
||||||
|
results.append({'Theme': t_name, 'Permit': p_name, 'Status': 'Skipped (No Theme)'})
|
||||||
|
continue
|
||||||
|
|
||||||
|
if pd.isna(p_name) or p_name == 'nan' or not p_name:
|
||||||
|
results.append({'Theme': t_name, 'Permit': p_name, 'Status': 'Skipped (No Permit Name)'})
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Create Theme if needed
|
||||||
|
if t_name not in theme_map:
|
||||||
|
t_id = uuid.uuid4()
|
||||||
|
cursor.execute("INSERT INTO themes (id, name) VALUES (%s, %s)", (t_id, t_name))
|
||||||
|
theme_map[t_name] = t_id
|
||||||
|
t_id = theme_map[t_name]
|
||||||
|
|
||||||
|
# Bind Rule (name based)
|
||||||
|
rule_id = uuid.uuid4()
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO permit_theme_rules (id, theme_id, permit_name, region_id, created_at)
|
||||||
|
VALUES (%s, %s, %s, %s, NOW())
|
||||||
|
""", (rule_id, t_id, p_name, region_id))
|
||||||
|
|
||||||
|
# Bind Physical (id based)
|
||||||
|
status = "Bound (Rule Only)"
|
||||||
|
if p_name in permit_map:
|
||||||
|
p_id = permit_map[p_name]
|
||||||
|
# Ensure theme is registered in the region
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO region_themes (region_id, theme_id)
|
||||||
|
VALUES (%s, %s)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
""", (region_id, t_id))
|
||||||
|
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO region_theme_permits (region_id, theme_id, permit_id)
|
||||||
|
VALUES (%s, %s, %s)
|
||||||
|
""", (region_id, t_id, p_id))
|
||||||
|
status = "Bound (Success)"
|
||||||
|
else:
|
||||||
|
status = "Bound Rule, but Permit Not Found in DB"
|
||||||
|
|
||||||
|
results.append({'Theme': t_name, 'Permit': p_name, 'Status': status})
|
||||||
|
|
||||||
|
# 6. Save Report
|
||||||
|
log("Saving report...")
|
||||||
|
report_df = pd.DataFrame(results)
|
||||||
|
try:
|
||||||
|
report_df.to_excel('主题-事项绑定结果.xlsx', index=False)
|
||||||
|
except PermissionError:
|
||||||
|
log("File locked, saving to '主题-事项绑定结果_new.xlsx' instead.")
|
||||||
|
report_df.to_excel('主题-事项绑定结果_new.xlsx', index=False)
|
||||||
|
log("Done.")
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
log(f"CRITICAL ERROR: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc(file=log_file)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
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.
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,68 @@
|
||||||
|
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']
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
Connecting to DB...
|
||||||
|
|
||||||
|
--- Regions ---
|
||||||
|
市级: 2c29ca08-efc6-4e2c-abc2-d73685e0bdd1
|
||||||
|
高明区(有意见): 4032e664-9548-4c7b-9e77-82cdb0d0ab85
|
||||||
|
市级(无意见): d01b8aa3-cb59-4bd1-9721-5319ea745708
|
||||||
|
禅城区(无意见): 854ec808-340a-4b9d-a3d5-8521225bddfd
|
||||||
|
南海区(无意见): ea4479ac-2ddf-4e64-8e28-96999defacd9
|
||||||
|
顺德区(无意见): ccfafc9a-0900-423b-8f6d-d87e3614152d
|
||||||
|
三水区(无意见): 54cd17c1-19b7-4d73-ae02-182bc6805a1b
|
||||||
|
Sheet1: 60068d61-992e-4ea5-beb1-cf29227ba135
|
||||||
|
高明区(样版): b6223a86-f053-40f1-b172-ef7ba28df103
|
||||||
|
高明区: 9ba7e257-bef7-4579-a124-9c97ec224e8a
|
||||||
|
营业执照: a2faa968-d8f7-4034-849f-1d20ae8243ce
|
||||||
|
高明区 (样版): 9183cf5f-cf4e-45e8-b7e4-5b31014f1a0f
|
||||||
|
高明区(样版): d1ba645d-2095-44b4-801d-bbab99542c50
|
||||||
|
禅城区: fa078753-974a-4fa7-8240-3b59689dc21d
|
||||||
|
南海区: e86a675c-2047-418a-a0d7-ee341f8e38fd
|
||||||
|
顺德区: 058d6257-25cf-420b-a6bc-52cfa32d562b
|
||||||
|
三水区: bd4dfda9-cbc2-41e3-9f55-5d2608782cab
|
||||||
|
|
||||||
|
--- Current Counts ---
|
||||||
|
Themes: 12
|
||||||
|
Region Theme Permits: 61
|
||||||
|
Permit Theme Rules: 61
|
||||||
|
|
||||||
|
--- Excel Structure ---
|
||||||
|
Columns: ['序号', '事项名称', '是否市级实施', '是否区级实施', '备注', '牵头部门', '部门系统简称\n(审批服务部门)', '市级', '禅城区', '南海区', '顺德区', '高明区', '三水区', '是否首次上线']
|
||||||
|
|
||||||
|
Sample Data:
|
||||||
|
序号 事项名称 是否市级实施 是否区级实施 备注 牵头部门 部门系统简称\n(审批服务部门) 市级 禅城区 南海区 顺德区 高明区 三水区 是否首次上线
|
||||||
|
0 1 旅馆业特种行业许可证核发 NaN NaN NaN 市公安局 公安机关 NaN NaN NaN NaN NaN NaN 是
|
||||||
|
1 2 公章刻制业特种行业许可证核发 NaN NaN NaN 市公安局 公安机关 NaN NaN NaN NaN NaN NaN 是
|
||||||
|
2 3 互联网上网服务营业场所信息网络安全审核 NaN NaN NaN 市公安局 公安机关 NaN NaN NaN NaN NaN NaN 是
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Add project root to path
|
||||||
|
sys.path.append(os.getcwd())
|
||||||
|
|
||||||
|
from lawrisk.services import licensing_repo as lic_repo
|
||||||
|
from lawrisk.utils.env_loader import load_env
|
||||||
|
|
||||||
|
def bind_departments():
|
||||||
|
load_env()
|
||||||
|
file_path = "审批服务部门_修正.xlsx"
|
||||||
|
output_path = "审批部门绑定结果.xlsx"
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"File not found: {file_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Loading Excel...")
|
||||||
|
df = pd.read_excel(file_path)
|
||||||
|
|
||||||
|
# Normalize headers
|
||||||
|
col_map = {c: c.strip() for c in df.columns}
|
||||||
|
df.rename(columns=col_map, inplace=True)
|
||||||
|
|
||||||
|
# Identify key columns
|
||||||
|
permit_col = None
|
||||||
|
dept_col = None
|
||||||
|
|
||||||
|
for c in df.columns:
|
||||||
|
if "事项名称" in c:
|
||||||
|
permit_col = c
|
||||||
|
if "部门系统简称" in c:
|
||||||
|
dept_col = c
|
||||||
|
|
||||||
|
if not permit_col or not dept_col:
|
||||||
|
print(f"Required columns not found. Found: {df.columns.tolist()}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Using Permit Column: '{permit_col}'")
|
||||||
|
print(f"Using Department Column: '{dept_col}'")
|
||||||
|
|
||||||
|
results = []
|
||||||
|
updated_count = 0
|
||||||
|
|
||||||
|
with lic_repo._lic_pg_conn() as conn:
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
for idx, row in df.iterrows():
|
||||||
|
p_name = str(row[permit_col]).strip()
|
||||||
|
d_name = str(row[dept_col]).strip()
|
||||||
|
|
||||||
|
if not p_name or p_name == 'nan':
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check if permit exists
|
||||||
|
cur.execute("SELECT id FROM permits WHERE name = %s", (p_name,))
|
||||||
|
res = cur.fetchone()
|
||||||
|
|
||||||
|
status = "未绑定"
|
||||||
|
note = "事项不存在"
|
||||||
|
|
||||||
|
if res:
|
||||||
|
pid = res[0]
|
||||||
|
# Update unit_name in region_permit_details
|
||||||
|
# We update for ALL regions for this permit, or just '市级'?
|
||||||
|
# Usually 'unit_name' is specific to a sheet/region, but here it seems global for the permit.
|
||||||
|
# We will update for all entries of this permit_id to be safe/consistent with "Service Department" concept.
|
||||||
|
|
||||||
|
try:
|
||||||
|
cur.execute("""
|
||||||
|
UPDATE region_permit_details
|
||||||
|
SET unit_name = %s
|
||||||
|
WHERE permit_id = %s
|
||||||
|
""", (d_name, pid))
|
||||||
|
|
||||||
|
if cur.rowcount > 0:
|
||||||
|
status = "已绑定"
|
||||||
|
note = f"更新了 {cur.rowcount} 条记录"
|
||||||
|
updated_count += 1
|
||||||
|
else:
|
||||||
|
status = "未更新"
|
||||||
|
note = "事项存在但无详情记录"
|
||||||
|
except Exception as e:
|
||||||
|
status = "错误"
|
||||||
|
note = str(e)
|
||||||
|
|
||||||
|
print(f"Processing: {p_name} -> {status} ({note})")
|
||||||
|
|
||||||
|
results.append({
|
||||||
|
"序号": row.get("序号", ""),
|
||||||
|
"事项名称": p_name,
|
||||||
|
"应绑部门": d_name,
|
||||||
|
"绑定状态": status,
|
||||||
|
"备注": note
|
||||||
|
})
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
print(f"Binding complete. Updated {updated_count} permits.")
|
||||||
|
|
||||||
|
# Save report
|
||||||
|
res_df = pd.DataFrame(results)
|
||||||
|
res_df.to_excel(output_path, index=False)
|
||||||
|
|
||||||
|
# Check for unbound
|
||||||
|
unbound = res_df[res_df["绑定状态"] != "已绑定"]
|
||||||
|
if not unbound.empty:
|
||||||
|
print("\n=== 未成功绑定的事项 ===")
|
||||||
|
print(unbound[["事项名称", "备注"]])
|
||||||
|
else:
|
||||||
|
print("\n所有事项均已成功绑定!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bind_departments()
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Init path to allow importing lawrisk
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from lawrisk.services import licensing_repo as lic_repo
|
||||||
|
from lawrisk.utils.env_loader import load_env
|
||||||
|
|
||||||
|
def delete_permit_by_name(permit_name):
|
||||||
|
load_env()
|
||||||
|
conn = lic_repo._lic_pg_conn()
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(f"Searching for permit: {permit_name}")
|
||||||
|
cur.execute("SELECT id FROM permits WHERE name = %s", (permit_name,))
|
||||||
|
row = cur.fetchone()
|
||||||
|
|
||||||
|
if not row:
|
||||||
|
print(f"Permit '{permit_name}' not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
permit_id = row[0]
|
||||||
|
print(f"Found permit ID: {permit_id}")
|
||||||
|
|
||||||
|
# List of tables to clean up that reference permit_id
|
||||||
|
# Based on licensing_repo.py structures
|
||||||
|
tables = [
|
||||||
|
"region_permit_risks",
|
||||||
|
"region_permit_scopes",
|
||||||
|
"region_permit_subitems",
|
||||||
|
"region_permit_details",
|
||||||
|
"region_theme_permits",
|
||||||
|
"region_permit_theme_overrides", # Might not exist or might be empty, but good to try
|
||||||
|
"permit_sources"
|
||||||
|
]
|
||||||
|
|
||||||
|
for table in tables:
|
||||||
|
try:
|
||||||
|
# Check if table exists first to avoid crashing on optional tables
|
||||||
|
cur.execute(f"SELECT to_regclass('{table}')")
|
||||||
|
if cur.fetchone()[0]:
|
||||||
|
print(f"Cleaning table: {table}")
|
||||||
|
cur.execute(f"DELETE FROM {table} WHERE permit_id = %s", (permit_id,))
|
||||||
|
print(f" Deleted {cur.rowcount} rows.")
|
||||||
|
else:
|
||||||
|
print(f"Table {table} does not exist, skipping.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error cleaning {table}: {e}")
|
||||||
|
# Don't abort, try next table
|
||||||
|
|
||||||
|
# Finally delete from permits
|
||||||
|
print("Deleting from permits table...")
|
||||||
|
cur.execute("DELETE FROM permits WHERE id = %s", (permit_id,))
|
||||||
|
print(f"Deleted {cur.rowcount} rows from permits.")
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
print(f"Successfully deleted permit '{permit_name}' and likely associated data.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
conn.rollback()
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
delete_permit_by_name("食品小作坊登记证")
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Init path to allow importing lawrisk
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from lawrisk.services import licensing_repo as lic_repo
|
||||||
|
from lawrisk.utils.env_loader import load_env
|
||||||
|
|
||||||
|
def find_permit():
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
# Try to access _lic_pg_conn, handle if it's not directly exposed or named differently
|
||||||
|
if hasattr(lic_repo, "_lic_pg_conn"):
|
||||||
|
conn_func = getattr(lic_repo, "_lic_pg_conn")
|
||||||
|
elif hasattr(lic_repo, "get_connection"):
|
||||||
|
conn_func = getattr(lic_repo, "get_connection")
|
||||||
|
else:
|
||||||
|
# Fallback to looking for connection logic inside licensing_repo (it might be a context manager)
|
||||||
|
# But for now assume _lic_pg_conn exists as per audit_risks.py
|
||||||
|
conn_func = lic_repo._lic_pg_conn
|
||||||
|
|
||||||
|
# Check if it returns a connection or context manager
|
||||||
|
# _lic_pg_conn in licensing_repo seems to be a context manager based on 'with _lic_pg_conn() as conn'
|
||||||
|
# But audit_risks.py calls it as 'conn = lic_repo._lic_pg_conn()' ?
|
||||||
|
# Let's check audit_risks.py again.
|
||||||
|
# Line 17: conn = lic_repo._lic_pg_conn()
|
||||||
|
# Line 94: conn.close()
|
||||||
|
# This implies it returns a connection object, not a context manager.
|
||||||
|
# But licensing_repo.py line 778 says: 'with _lic_pg_conn() as conn:' ...
|
||||||
|
# This means _lic_pg_conn() can be used as a context manager OR returns something that has __enter__.
|
||||||
|
# A standard pg8000 connection can be used as a context manager.
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn = conn_func()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error connecting to DB: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
permit_name = sys.argv[1]
|
||||||
|
else:
|
||||||
|
permit_name = "仅销售预包装食品备案登记"
|
||||||
|
print(f"Searching for permit: {permit_name}")
|
||||||
|
|
||||||
|
# Check strict match
|
||||||
|
cur.execute("SELECT id, name FROM permits WHERE name = %s", (permit_name,))
|
||||||
|
strict_match = cur.fetchone()
|
||||||
|
|
||||||
|
if strict_match:
|
||||||
|
print(f"Found EXACT match: ID={strict_match[0]}, Name={strict_match[1]}")
|
||||||
|
permit_id = strict_match[0]
|
||||||
|
|
||||||
|
# Check regions
|
||||||
|
cur.execute("""
|
||||||
|
SELECT r.name
|
||||||
|
FROM region_theme_permits rtp
|
||||||
|
JOIN regions r ON r.id = rtp.region_id
|
||||||
|
WHERE rtp.permit_id = %s
|
||||||
|
GROUP BY r.name
|
||||||
|
""", (permit_id,))
|
||||||
|
regions = cur.fetchall()
|
||||||
|
if regions:
|
||||||
|
print("Bind to regions:")
|
||||||
|
for r_name in regions:
|
||||||
|
print(f" - {r_name[0]}")
|
||||||
|
else:
|
||||||
|
print("No region bindings found.")
|
||||||
|
|
||||||
|
# Check risks
|
||||||
|
cur.execute("""
|
||||||
|
SELECT count(*) FROM region_permit_risks WHERE permit_id = %s
|
||||||
|
""", (permit_id,))
|
||||||
|
risk_count_row = cur.fetchone()
|
||||||
|
risk_count = risk_count_row[0] if risk_count_row else 0
|
||||||
|
print(f"Total risk entries: {risk_count}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("No exact match found.")
|
||||||
|
|
||||||
|
# Check fuzzy match
|
||||||
|
print("\nChecking fuzzy matches...")
|
||||||
|
cur.execute("SELECT id, name FROM permits WHERE name ILIKE %s", (f"%{permit_name}%",))
|
||||||
|
fuzzy_matches = cur.fetchall()
|
||||||
|
|
||||||
|
if fuzzy_matches:
|
||||||
|
for mid, mname in fuzzy_matches:
|
||||||
|
if strict_match and mid == strict_match[0]:
|
||||||
|
continue
|
||||||
|
print(f"Found partial match: ID={mid}, Name={mname}")
|
||||||
|
else:
|
||||||
|
if not strict_match:
|
||||||
|
print("No fuzzy matches found.")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
find_permit()
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Add project root to path
|
||||||
|
sys.path.append(os.getcwd())
|
||||||
|
|
||||||
|
from lawrisk.services import licensing_repo as lic_repo
|
||||||
|
from lawrisk.utils.env_loader import load_env
|
||||||
|
|
||||||
|
def generate_report():
|
||||||
|
load_env()
|
||||||
|
file_path = "审批服务部门.xlsx"
|
||||||
|
output_path = "审批服务部门_核对结果.xlsx"
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"File not found: {file_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Loading Excel...")
|
||||||
|
df = pd.read_excel(file_path)
|
||||||
|
|
||||||
|
# Normalize headers to find the correct column
|
||||||
|
col_map = {c: c.strip() for c in df.columns}
|
||||||
|
df.rename(columns=col_map, inplace=True)
|
||||||
|
|
||||||
|
permit_col = None
|
||||||
|
for c in df.columns:
|
||||||
|
if "事项名称" in c:
|
||||||
|
permit_col = c
|
||||||
|
break
|
||||||
|
|
||||||
|
if not permit_col:
|
||||||
|
print("Could not find '事项名称' column.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Using '{permit_col}' as permit name column.")
|
||||||
|
|
||||||
|
print("Fetching system permits...")
|
||||||
|
with lic_repo._lic_pg_conn() as conn:
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("SELECT name FROM permits")
|
||||||
|
db_permits = set(row[0] for row in cur.fetchall())
|
||||||
|
|
||||||
|
print(f"Found {len(db_permits)} permits in database.")
|
||||||
|
|
||||||
|
# Check matches
|
||||||
|
results = []
|
||||||
|
|
||||||
|
for idx, row in df.iterrows():
|
||||||
|
p_name = str(row[permit_col]).strip()
|
||||||
|
if p_name in db_permits:
|
||||||
|
results.append("已匹配") # Matched
|
||||||
|
else:
|
||||||
|
results.append("未匹配") # Not Matched
|
||||||
|
|
||||||
|
df["匹配状态"] = results
|
||||||
|
|
||||||
|
print(f"Saving report to {output_path}...")
|
||||||
|
df.to_excel(output_path, index=False)
|
||||||
|
print("Done.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_report()
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
|
||||||
|
file_path = "审批服务部门.xlsx"
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"File not found: {file_path}")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
df = pd.read_excel(file_path)
|
||||||
|
print("Columns:", df.columns.tolist())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading excel: {e}")
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
|
||||||
|
file_path = "审批服务部门_修正.xlsx"
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"File not found: {file_path}")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
df = pd.read_excel(file_path)
|
||||||
|
print("Columns:", df.columns.tolist())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading excel: {e}")
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import psycopg2
|
||||||
|
|
||||||
|
# Init path to allow importing lawrisk
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from lawrisk.services import licensing_repo as lic_repo
|
||||||
|
from lawrisk.utils.env_loader import load_env
|
||||||
|
|
||||||
|
def rename_permit(permit_id, new_name):
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
if hasattr(lic_repo, "_lic_pg_conn"):
|
||||||
|
conn_func = getattr(lic_repo, "_lic_pg_conn")
|
||||||
|
else:
|
||||||
|
print("Could not find connection function")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn = conn_func()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error connecting to DB: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
# Verify existence
|
||||||
|
cur.execute("SELECT name FROM permits WHERE id = %s", (permit_id,))
|
||||||
|
row = cur.fetchone()
|
||||||
|
if not row:
|
||||||
|
print(f"Permit with ID {permit_id} not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
old_name = row[0]
|
||||||
|
print(f"Renaming permit {permit_id}:")
|
||||||
|
print(f" Old Name: {old_name}")
|
||||||
|
print(f" New Name: {new_name}")
|
||||||
|
|
||||||
|
# Check if new name exists
|
||||||
|
cur.execute("SELECT id FROM permits WHERE name = %s", (new_name,))
|
||||||
|
if cur.fetchone():
|
||||||
|
print(f"Error: A permit with the name '{new_name}' already exists.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Update
|
||||||
|
cur.execute("UPDATE permits SET name = %s WHERE id = %s", (new_name, permit_id))
|
||||||
|
conn.commit()
|
||||||
|
print("Successfully renamed.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
conn.rollback()
|
||||||
|
print(f"Error updating permit: {e}")
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print("Usage: python rename_permit.py <permit_id> <new_name>")
|
||||||
|
else:
|
||||||
|
pid = sys.argv[1]
|
||||||
|
nname = sys.argv[2]
|
||||||
|
rename_permit(pid, nname)
|
||||||
Loading…
Reference in New Issue