Преглед на файлове

导出车辆低效明细

weijianghai преди 3 месеца
родител
ревизия
34ea5c3947

+ 62 - 46
car/car-chao-bao/car_chao-bao.py

@@ -64,6 +64,7 @@ def data_process():
         "廊坊市分公司": "廊坊",
         "秦皇岛市分公司": "秦皇岛",
         "省公司本部": "省公司本部",
+        "省本部": "省公司本部",
         "石家庄市分公司": "石家庄",
         "唐山市分公司": "唐山",
         "邢台市分公司": "邢台",
@@ -171,16 +172,28 @@ def data_process():
 
     # 读取 Excel 文件中的数据
     df = pd.read_excel(io=input_path)
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['账期', '车牌号', '车型', '一级单位', '二级单位', '三级单位', '登记日期', '进厂时间',
+                        '进厂公里数', '行驶里程', '是否应该保养', '超出建议保养时间(天)', '超出建议保养公里数']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 获取需要清理的列名列表,排除 "登记日期" 和 "进厂时间" 列
     columns_to_clean = list(filter(lambda x: x not in ('登记日期', '进厂时间'), df.columns))
     # 对需要清理的列进行字符串清理,移除多余的空白字符
     df[columns_to_clean] = df[columns_to_clean].map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)
-    df['账期'] = year_month
+    df['year_month'] = year_month
     # 保存原始单位和车牌号信息到新的列中
-    df['原始一级单位'] = df['一级单位']
-    df['原始二级单位'] = df['二级单位']
-    df['原始三级单位'] = df['三级单位']
-    df['原始车牌号'] = df['车牌号']
+    df['raw_yi_ji'] = df['一级单位']
+    df['raw_er_ji'] = df['二级单位']
+    df['raw_san_ji'] = df['三级单位']
+    df['raw_che_pai_hao'] = df['车牌号']
 
     # 定义函数,用于提取并标准化车牌号
     def get_che_pai(che_pai):
@@ -226,12 +239,12 @@ def data_process():
         return "1"  # 匹配失败
 
     # 应用 che_pai_fail 函数生成车牌匹配失败标记列
-    df['车牌匹配失败'] = df['车牌号'].apply(che_pai_fail)
+    df['che_pai_fail'] = df['车牌号'].apply(che_pai_fail)
 
     # 获取一级单位
     def get_first_unit(x):
-        raw_che_pai = x['原始车牌号']
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
+        raw_che_pai = x['raw_che_pai_hao']
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
         if not raw_first_unit or not raw_first_unit.strip():
             raise RuntimeError(f"一级单位为空:{raw_che_pai}")
         if raw_first_unit in first_unit_map:
@@ -244,7 +257,7 @@ def data_process():
     # 获取二级单位
     def get_second_unit(x):
         first_unit = str(x['一级单位']) if pd.notna(x['一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
         if first_unit in ["华北基地建设部", "雄安基地建设部", "省公司本部"]:
             return first_unit
         if not raw_second_unit or not raw_second_unit.strip():
@@ -284,7 +297,7 @@ def data_process():
     # 获取三级单位
     def get_third_unit(x):
         second_unit = str(x['二级单位']) if pd.notna(x['二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         return raw_third_unit if raw_third_unit and raw_third_unit.strip() else second_unit
 
     # 应用 get_third_unit 函数生成三级单位列
@@ -301,7 +314,7 @@ def data_process():
                 return second_org.get('id')
         return ''
 
-    df['二级组织机构编码'] = df['一级单位'].apply(get_area_no)
+    df['area_no'] = df['一级单位'].apply(get_area_no)
 
     # 用于根据组织机构编码获取组织机构名称
     def get_org_name(x):
@@ -315,16 +328,16 @@ def data_process():
             return po.get('name')
         return ''
 
-    # 将get_org_name函数应用到'二级组织机构编码'列,生成'二级组织机构名称'列
-    df['二级组织机构名称'] = df['二级组织机构编码'].apply(get_org_name)
+    # 将get_org_name函数应用到'area_no'列,生成'area_name'列
+    df['area_name'] = df['area_no'].apply(get_org_name)
 
     # 定义一个函数,用于根据行数据获取三级组织机构编码
     def get_city_no(x):
         # 获取相关字段值,如果为空则设置为""
-        area_no = str(x['二级组织机构编码']) if pd.notna(x['二级组织机构编码']) else ""
-        area_name = str(x['二级组织机构名称']) if pd.notna(x['二级组织机构名称']) else ""
+        area_no = str(x['area_no']) if pd.notna(x['area_no']) else ""
+        area_name = str(x['area_name']) if pd.notna(x['area_name']) else ""
         first_unit = str(x['一级单位']) if pd.notna(x['一级单位']) else ""
-        second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
+        second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
         if not area_no or not area_no.strip() or not area_name or not area_name.strip():
             return ''
         if '华北基地建设部' == first_unit:
@@ -412,16 +425,16 @@ def data_process():
             return "D0130830"
         return ''
 
-    # 将get_city_no函数应用到DataFrame的每一行,生成'三级组织机构编码'列
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
-    # 将get_org_name函数应用到'三级组织机构编码'列,生成'三级组织机构名称'列
-    df['三级组织机构名称'] = df['三级组织机构编码'].apply(get_org_name)
+    # 将get_city_no函数应用到DataFrame的每一行,生成'city_no'列
+    df['city_no'] = df.apply(get_city_no, axis=1)
+    # 将get_org_name函数应用到'city_no'列,生成'city_name'列
+    df['city_name'] = df['city_no'].apply(get_org_name)
 
     # 定义一个函数,用于根据行数据获取二级组织机构编码2
     def get_area_no2(x):
         # 获取相关字段值,如果为空则设置为""
-        area_name = str(x['二级组织机构名称']) if pd.notna(x['二级组织机构名称']) else ""
-        city_name = str(x['三级组织机构名称']) if pd.notna(x['三级组织机构名称']) else ""
+        area_name = str(x['area_name']) if pd.notna(x['area_name']) else ""
+        city_name = str(x['city_name']) if pd.notna(x['city_name']) else ""
         if not area_name or not area_name.strip() or '省本部' == area_name:
             return ''
         # 根据二级组织机构名称和三级组织机构名称的内容,返回对应的编码
@@ -477,16 +490,16 @@ def data_process():
             return "782"
         return ""
 
-    # 将get_area_no2函数应用到DataFrame的每一行,生成'二级组织机构编码2'列
-    df['二级组织机构编码2'] = df.apply(get_area_no2, axis=1)
-    # 将get_org_name函数应用到'二级组织机构编码2'列,生成'二级组织机构名称2'列
-    df['二级组织机构名称2'] = df['二级组织机构编码2'].apply(get_org_name)
+    # 将get_area_no2函数应用到DataFrame的每一行,生成'area_no2'列
+    df['area_no2'] = df.apply(get_area_no2, axis=1)
+    # 将get_org_name函数应用到'area_no2'列,生成'area_name2'列
+    df['area_name2'] = df['area_no2'].apply(get_org_name)
 
     # 获取城市ID
     def get_city_id(x):
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         unit = f"{raw_first_unit}_{raw_second_unit}_{raw_third_unit}"
         if not unit or not unit.strip():
             return ''
@@ -517,9 +530,9 @@ def data_process():
         # 获取相关字段值,如果为空则设置为""
         city_id = str(x['city_id']) if pd.notna(x['city_id']) else ""
         city = str(x['city']) if pd.notna(x['city']) else ""
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         unit = f"{raw_first_unit}_{raw_second_unit}_{raw_third_unit}"
         # 如果城市ID、城市名称或单位为空,则返回""
         if not city_id or not city_id.strip() or not city or not city.strip() or not unit or not unit.strip():
@@ -543,8 +556,8 @@ def data_process():
     df['district'] = df['district_id'].apply(get_area_name)
 
     # 提取账期年份和月份信息
-    df['year_no'] = df['账期'].apply(lambda x: None if pd.isna(x) else str(x)[:4])
-    df['month_no'] = df['账期'].apply(lambda x: None if pd.isna(x) else str(x)[-2:])
+    df['year_no'] = df['year_month'].apply(lambda x: None if pd.isna(x) else str(x)[:4])
+    df['month_no'] = df['year_month'].apply(lambda x: None if pd.isna(x) else str(x)[-2:])
 
 
     def to_datetime(x):
@@ -564,8 +577,8 @@ def data_process():
         except Exception:
             return None
 
-    df['公里数'] = df['公里数'].apply(get_num)
-    df['截止数据提取日行驶里程'] = df['截止数据提取日行驶里程'].apply(get_num)
+    df['进厂公里数'] = df['进厂公里数'].apply(get_num)
+    df['行驶里程'] = df['行驶里程'].apply(get_num)
     df['超出建议保养公里数'] = df['超出建议保养公里数'].apply(get_num)
 
     def get_int(x):
@@ -575,18 +588,21 @@ def data_process():
             return ""
 
     df['超出建议保养时间(天)'] = df['超出建议保养时间(天)'].apply(get_int)
+    df.rename(
+        columns={'车牌号': 'che_pai_hao', '一级单位': 'first_unit', '二级单位': 'second_unit', '三级单位': 'third_unit',
+                 '车型': 'che_xing', '登记日期': 'deng_ji_ri_qi', '进厂时间': 'jin_chang_shi_jian',
+                 '进厂公里数': 'jin_chang_gong_li', '行驶里程': 'li_cheng', '是否应该保养': 'bao_yang',
+                 '超出建议保养时间(天)': 'chao_bao_tian_shu', '超出建议保养公里数': 'chao_bao_gong_li'}, inplace=True)
+    df = df[['year_month', 'che_pai_hao', 'che_xing', 'first_unit', 'second_unit', 'third_unit',
+             'deng_ji_ri_qi', 'jin_chang_shi_jian', 'jin_chang_gong_li', 'li_cheng', 'bao_yang',
+             'chao_bao_tian_shu', 'chao_bao_gong_li', 'raw_yi_ji', 'raw_er_ji', 'raw_san_ji',
+             'raw_che_pai_hao', 'che_pai_fail', 'area_no', 'area_name', 'city_no', 'city_name', 'area_no2',
+             'area_name2', 'city_id', 'city', 'district_id', 'district', 'year_no', 'month_no']]
     # 打印DataFrame的信息
-    print(df.info())
+    df.info()
 
     # 将处理后的数据保存到CSV文件中
-    df.to_csv(path_or_buf=output_path,
-              header=['year_month', 'che_pai_hao', 'che_xing', 'first_unit', 'second_unit', 'third_unit',
-                      'deng_ji_ri_qi', 'jin_chang_shi_jian', 'jin_chang_gong_li', 'li_cheng', 'bao_yang',
-                      'chao_bao_tian_shu', 'chao_bao_gong_li', 'raw_yi_ji', 'raw_er_ji', 'raw_san_ji',
-                      'raw_che_pai_hao', 'che_pai_fail', 'area_no', 'area_name', 'city_no', 'city_name', 'area_no2',
-                      'area_name2', 'city_id', 'city', 'district_id', 'district', 'year_no', 'month_no'],
-              index=False,
-              encoding='utf-8-sig')
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -597,7 +613,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,che_pai_hao,che_xing,first_unit,second_unit,third_unit,deng_ji_ri_qi,jin_chang_shi_jian,jin_chang_gong_li,li_cheng,bao_yang,chao_bao_tian_shu,chao_bao_gong_li,raw_yi_ji,raw_er_ji,raw_san_ji,raw_che_pai_hao,che_pai_fail,area_no,area_name,city_no,city_name,area_no2,area_name2,city_id,city,district_id,district,year_no,month_no"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 102 - 0
car/car-di-xiao-export/car_di_xiao_export.py

@@ -0,0 +1,102 @@
+"""导出车辆低效明细
+"""
+import xlsxwriter
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from loguru import logger
+import psycopg
+
+# 数据库连接信息
+db_host = "172.16.107.5"  # 数据库主机地址
+db_port = 5432  # 数据库端口号
+db_username = "finance"  # 数据库用户名
+db_password = "Finance@unicom23"  # 数据库密码
+dbname = "financialdb"  # 数据库名称
+conn_info = f"host='{db_host}' port={db_port} user='{db_username}' password='{db_password}' dbname='{dbname}'"
+# 获取当前日期,并计算上个月的第一天
+today = datetime.today()
+start_date = today - relativedelta(months=1, day=1)
+year_month = start_date.strftime('%Y%m')
+# 输出文件路径
+output_path = f"{year_month}低效车辆明细.xlsx"
+
+with psycopg.connect(
+        conninfo=conn_info,
+        row_factory=psycopg.rows.dict_row
+) as conn:
+    with conn.cursor() as curs:
+        sql = f"""
+select che_pai_hao,
+    first_unit,
+    second_unit,
+    third_unit,
+    che_liang_suo_shu_dan_wei,
+    che_liang_lai_yuan,
+    che_liang_lei_xing,
+    che_liang_shi_yong_xing_zhi,
+    round(ri_jun_li_cheng_sum, 2) as ri_jun_li_cheng_sum,
+    round(chu_qin_lv_sum, 4) as chu_qin_lv_sum,
+    round(zong_li_cheng_sum, 2) as zong_li_cheng_sum,
+    xing_shi_tian_shu_sum as xing_shi_tian_shu_sum,
+    workday_sum as workday_sum
+from car.car_di_xiao_month
+where year_month = {year_month}
+order by first_unit,
+    second_unit,
+    third_unit,
+    che_pai_hao
+            """
+        logger.info(f"sql: {sql}")
+        curs.execute(sql)
+        l = curs.fetchall()
+        workbook = xlsxwriter.Workbook(output_path)
+        worksheet = workbook.add_worksheet()
+        # 定义单元格格式
+        percent_format = workbook.add_format({'num_format': '0.00%'})  # 百分比格式
+        number_format = workbook.add_format({'num_format': '#,##0.00'})  # 数字格式(千分位 + 两位小数)
+        # 写入表头
+        headers = ['车牌号', '单位', '二级', '三级', '车辆所属单位', '车辆来源', '车辆类型', '车辆使用性质', '日均里程',
+                   '出勤率', '总里程', '行驶天数', '工作日天数']
+        worksheet.write_row(0, 0, headers)
+        for row_num, item in enumerate(l):
+            col = 0
+            worksheet.write(row_num + 1, col, item.get('che_pai_hao'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('first_unit'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('second_unit'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('third_unit'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_suo_shu_dan_wei'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_lai_yuan'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_lei_xing'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_shi_yong_xing_zhi'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('ri_jun_li_cheng_sum'), number_format)
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('chu_qin_lv_sum'), percent_format)
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('zong_li_cheng_sum'), number_format)
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('xing_shi_tian_shu_sum'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('workday_sum'))
+        worksheet.set_column('A:A', 12)
+        worksheet.set_column('B:B', 12)
+        worksheet.set_column('C:C', 12)
+        worksheet.set_column('D:D', 12)
+        worksheet.set_column('E:E', 12)
+        worksheet.set_column('F:F', 12)
+        worksheet.set_column('G:G', 12)
+        worksheet.set_column('H:H', 12)
+        worksheet.set_column('I:I', 12)
+        worksheet.set_column('J:J', 12)
+        worksheet.set_column('K:K', 12)
+        worksheet.set_column('L:L', 12)
+        worksheet.set_column('M:M', 12)
+        # 保存并关闭工作簿
+        workbook.close()

+ 60 - 45
car/car-guo-jian/car_guo_jian.py

@@ -64,6 +64,7 @@ def data_process():
         "廊坊市分公司": "廊坊",
         "秦皇岛市分公司": "秦皇岛",
         "省公司本部": "省公司本部",
+        "省本部": "省公司本部",
         "石家庄市分公司": "石家庄",
         "唐山市分公司": "唐山",
         "邢台市分公司": "邢台",
@@ -171,16 +172,28 @@ def data_process():
 
     # 读取 Excel 文件中的数据
     df = pd.read_excel(io=input_path)
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['序号', '车牌号', '车型', '一级单位', '二级单位', '三级单位', '登记日期', '年检时间',
+                        '是否过检', '是否本月应检', '本月是否年检']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 获取需要清理的列名列表,排除 "登记日期" 和 "年检时间" 列
     columns_to_clean = list(filter(lambda x: x not in ('登记日期', '年检时间'), df.columns))
     # 对需要清理的列进行字符串清理,移除多余的空白字符
     df[columns_to_clean] = df[columns_to_clean].map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)
-    df['账期'] = year_month
+    df['year_month'] = year_month
     # 保存原始单位和车牌号信息到新的列中
-    df['原始一级单位'] = df['一级单位']
-    df['原始二级单位'] = df['二级单位']
-    df['原始三级单位'] = df['三级单位']
-    df['原始车牌号'] = df['车牌号']
+    df['raw_yi_ji'] = df['一级单位']
+    df['raw_er_ji'] = df['二级单位']
+    df['raw_san_ji'] = df['三级单位']
+    df['raw_che_pai_hao'] = df['车牌号']
 
     # 定义函数,用于提取并标准化车牌号
     def get_che_pai(che_pai):
@@ -226,12 +239,12 @@ def data_process():
         return "1"  # 匹配失败
 
     # 应用 che_pai_fail 函数生成车牌匹配失败标记列
-    df['车牌匹配失败'] = df['车牌号'].apply(che_pai_fail)
+    df['che_pai_fail'] = df['车牌号'].apply(che_pai_fail)
 
     # 获取一级单位
     def get_first_unit(x):
-        raw_che_pai = x['原始车牌号']
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
+        raw_che_pai = x['raw_che_pai_hao']
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
         if not raw_first_unit or not raw_first_unit.strip():
             raise RuntimeError(f"一级单位为空:{raw_che_pai}")
         if raw_first_unit in first_unit_map:
@@ -244,7 +257,7 @@ def data_process():
     # 获取二级单位
     def get_second_unit(x):
         first_unit = str(x['一级单位']) if pd.notna(x['一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
         if first_unit in ["华北基地建设部", "雄安基地建设部", "省公司本部"]:
             return first_unit
         if not raw_second_unit or not raw_second_unit.strip():
@@ -284,7 +297,7 @@ def data_process():
     # 获取三级单位
     def get_third_unit(x):
         second_unit = str(x['二级单位']) if pd.notna(x['二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         return raw_third_unit if raw_third_unit and raw_third_unit.strip() else second_unit
 
     # 应用 get_third_unit 函数生成三级单位列
@@ -301,7 +314,7 @@ def data_process():
                 return second_org.get('id')
         return ''
 
-    df['二级组织机构编码'] = df['一级单位'].apply(get_area_no)
+    df['area_no'] = df['一级单位'].apply(get_area_no)
 
     # 用于根据组织机构编码获取组织机构名称
     def get_org_name(x):
@@ -315,16 +328,16 @@ def data_process():
             return po.get('name')
         return ''
 
-    # 将get_org_name函数应用到'二级组织机构编码'列,生成'二级组织机构名称'列
-    df['二级组织机构名称'] = df['二级组织机构编码'].apply(get_org_name)
+    # 将get_org_name函数应用到'area_no'列,生成'area_name'列
+    df['area_name'] = df['area_no'].apply(get_org_name)
 
     # 定义一个函数,用于根据行数据获取三级组织机构编码
     def get_city_no(x):
         # 获取相关字段值,如果为空则设置为""
-        area_no = str(x['二级组织机构编码']) if pd.notna(x['二级组织机构编码']) else ""
-        area_name = str(x['二级组织机构名称']) if pd.notna(x['二级组织机构名称']) else ""
+        area_no = str(x['area_no']) if pd.notna(x['area_no']) else ""
+        area_name = str(x['area_name']) if pd.notna(x['area_name']) else ""
         first_unit = str(x['一级单位']) if pd.notna(x['一级单位']) else ""
-        second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
+        second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
         if not area_no or not area_no.strip() or not area_name or not area_name.strip():
             return ''
         if '华北基地建设部' == first_unit:
@@ -412,16 +425,16 @@ def data_process():
             return "D0130830"
         return ''
 
-    # 将get_city_no函数应用到DataFrame的每一行,生成'三级组织机构编码'列
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
-    # 将get_org_name函数应用到'三级组织机构编码'列,生成'三级组织机构名称'列
-    df['三级组织机构名称'] = df['三级组织机构编码'].apply(get_org_name)
+    # 将get_city_no函数应用到DataFrame的每一行,生成'city_no'列
+    df['city_no'] = df.apply(get_city_no, axis=1)
+    # 将get_org_name函数应用到'city_no'列,生成'city_name'列
+    df['city_name'] = df['city_no'].apply(get_org_name)
 
     # 定义一个函数,用于根据行数据获取二级组织机构编码2
     def get_area_no2(x):
         # 获取相关字段值,如果为空则设置为""
-        area_name = str(x['二级组织机构名称']) if pd.notna(x['二级组织机构名称']) else ""
-        city_name = str(x['三级组织机构名称']) if pd.notna(x['三级组织机构名称']) else ""
+        area_name = str(x['area_name']) if pd.notna(x['area_name']) else ""
+        city_name = str(x['city_name']) if pd.notna(x['city_name']) else ""
         if not area_name or not area_name.strip() or '省本部' == area_name:
             return ''
         # 根据二级组织机构名称和三级组织机构名称的内容,返回对应的编码
@@ -477,16 +490,16 @@ def data_process():
             return "782"
         return ""
 
-    # 将get_area_no2函数应用到DataFrame的每一行,生成'二级组织机构编码2'列
-    df['二级组织机构编码2'] = df.apply(get_area_no2, axis=1)
-    # 将get_org_name函数应用到'二级组织机构编码2'列,生成'二级组织机构名称2'列
-    df['二级组织机构名称2'] = df['二级组织机构编码2'].apply(get_org_name)
+    # 将get_area_no2函数应用到DataFrame的每一行,生成'area_no2'列
+    df['area_no2'] = df.apply(get_area_no2, axis=1)
+    # 将get_org_name函数应用到'area_no2'列,生成'area_name2'列
+    df['area_name2'] = df['area_no2'].apply(get_org_name)
 
     # 获取城市ID
     def get_city_id(x):
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         unit = f"{raw_first_unit}_{raw_second_unit}_{raw_third_unit}"
         if not unit or not unit.strip():
             return ''
@@ -517,9 +530,9 @@ def data_process():
         # 获取相关字段值,如果为空则设置为""
         city_id = str(x['city_id']) if pd.notna(x['city_id']) else ""
         city = str(x['city']) if pd.notna(x['city']) else ""
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         unit = f"{raw_first_unit}_{raw_second_unit}_{raw_third_unit}"
         # 如果城市ID、城市名称或单位为空,则返回""
         if not city_id or not city_id.strip() or not city or not city.strip() or not unit or not unit.strip():
@@ -543,22 +556,24 @@ def data_process():
     df['district'] = df['district_id'].apply(get_area_name)
 
     # 提取账期年份和月份信息
-    df['year_no'] = df['账期'].apply(lambda x: None if pd.isna(x) else str(x)[:4])
-    df['month_no'] = df['账期'].apply(lambda x: None if pd.isna(x) else str(x)[-2:])
+    df['year_no'] = df['year_month'].apply(lambda x: None if pd.isna(x) else str(x)[:4])
+    df['month_no'] = df['year_month'].apply(lambda x: None if pd.isna(x) else str(x)[-2:])
     df['年检时间'] = df['年检时间'].apply(lambda x: None if pd.isna(x) else pd.to_datetime(x).strftime('%Y%m'))
-
+    df.rename(
+        columns={'车牌号': 'che_pai_hao', '一级单位': 'first_unit', '二级单位': 'second_unit', '三级单位': 'third_unit',
+                 '车型': 'che_xing', '登记日期': 'deng_ji_ri_qi', '年检时间': 'nian_jian_shi_jian',
+                 '是否过检': 'shi_fou_guo_jian', '是否本月应检': 'shi_fou_ben_yue_ying_jian',
+                 '本月是否年检': 'ben_yue_shi_fou_nian_jian', }, inplace=True)
+    df = df[['year_month', 'che_pai_hao', 'che_xing', 'first_unit', 'second_unit', 'third_unit', 'deng_ji_ri_qi',
+             'nian_jian_shi_jian', 'shi_fou_guo_jian', 'shi_fou_ben_yue_ying_jian', 'ben_yue_shi_fou_nian_jian',
+             'raw_yi_ji', 'raw_er_ji', 'raw_san_ji', 'raw_che_pai_hao', 'che_pai_fail', 'area_no', 'area_name',
+             'city_no', 'city_name', 'area_no2', 'area_name2', 'city_id', 'city', 'district_id', 'district', 'year_no',
+             'month_no']]
     # 打印DataFrame的信息
-    print(df.info())
+    df.info()
 
     # 将处理后的数据保存到CSV文件中
-    df.to_csv(path_or_buf=output_path,
-              header=['year_month', 'che_pai_hao', 'che_xing', 'first_unit', 'second_unit', 'third_unit',
-                      'deng_ji_ri_qi', 'nian_jian_shi_jian', 'shi_fou_guo_jian', 'shi_fou_ben_yue_ying_jian',
-                      'ben_yue_shi_fou_nian_jian', 'raw_yi_ji', 'raw_er_ji', 'raw_san_ji', 'raw_che_pai_hao',
-                      'che_pai_fail', 'area_no', 'area_name', 'city_no', 'city_name', 'area_no2', 'area_name2',
-                      'city_id', 'city', 'district_id', 'district', 'year_no', 'month_no'],
-              index=False,
-              encoding='utf-8-sig')
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -569,7 +584,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,che_pai_hao,che_xing,first_unit,second_unit,third_unit,deng_ji_ri_qi,nian_jian_shi_jian,shi_fou_guo_jian,shi_fou_ben_yue_ying_jian,ben_yue_shi_fou_nian_jian,raw_yi_ji,raw_er_ji,raw_san_ji,raw_che_pai_hao,che_pai_fail,area_no,area_name,city_no,city_name,area_no2,area_name2,city_id,city,district_id,district,year_no,month_no"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 1 - 1
car/car-li-cheng-day-missing/car_li_cheng_day_missing.py

@@ -69,7 +69,7 @@ with psycopg.connect(
 df = pd.DataFrame(a)
 
 # 打印 DataFrame 的基本信息(如列名、数据类型等)
-print(df.info())
+df.info()
 
 # 将缺失日期保存到 Excel 文件中
 df.to_excel(

+ 97 - 0
car/car-li-cheng-lei-ji-month-export/car_li_cheng_lei_ji_month_export.py

@@ -0,0 +1,97 @@
+"""导出车辆里程累计明细
+"""
+import xlsxwriter
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from loguru import logger
+import psycopg
+
+# 数据库连接信息
+db_host = "172.16.107.5"  # 数据库主机地址
+db_port = 5432  # 数据库端口号
+db_username = "finance"  # 数据库用户名
+db_password = "Finance@unicom23"  # 数据库密码
+dbname = "financialdb"  # 数据库名称
+conn_info = f"host='{db_host}' port={db_port} user='{db_username}' password='{db_password}' dbname='{dbname}'"
+# 获取当前日期,并计算上个月的第一天
+today = datetime.today()
+start_date = today - relativedelta(months=1, day=1)
+year_month = start_date.strftime('%Y%m')
+# 输出文件路径
+output_path = f"{year_month}车辆里程累计明细.xlsx"
+
+with psycopg.connect(
+        conninfo=conn_info,
+        row_factory=psycopg.rows.dict_row
+) as conn:
+    with conn.cursor() as curs:
+        sql = f"""
+select
+*
+from car.car_li_cheng_lei_ji_month
+where year_month = {year_month}
+order by first_unit,
+    second_unit,
+    third_unit,
+    che_pai_hao
+            """
+        logger.info(f"sql: {sql}")
+        curs.execute(sql)
+        l = curs.fetchall()
+        workbook = xlsxwriter.Workbook(output_path)
+        worksheet = workbook.add_worksheet()
+        # 定义单元格格式
+        percent_format = workbook.add_format({'num_format': '0.00%'})  # 百分比格式
+        number_format = workbook.add_format({'num_format': '#,##0.00'})  # 数字格式(千分位 + 两位小数)
+        # 写入表头
+        headers = ['车牌号', '是否低效', '低效排除原因', '单位', '二级', '三级', '车辆所属单位', '车辆来源', '车辆类型',
+                   '车辆使用性质', '日均里程', '出勤率', '累计里程', '累计行驶天数', '工作日天数']
+        worksheet.write_row(0, 0, headers)
+        for row_num, item in enumerate(l):
+            col = 0
+            worksheet.write(row_num + 1, col, item.get('che_pai_hao'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('di_xiao_sum'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('di_xiao_sum_exclude_reason'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('first_unit'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('second_unit'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('third_unit'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_suo_shu_dan_wei'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_lai_yuan'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_lei_xing'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('che_liang_shi_yong_xing_zhi'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('ri_jun_li_cheng_sum'), number_format)
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('chu_qin_lv_sum'), percent_format)
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('zong_li_cheng_sum'), number_format)
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('xing_shi_tian_shu_sum'))
+            col += 1
+            worksheet.write(row_num + 1, col, item.get('workday_sum'))
+        worksheet.set_column('A:A', 12)
+        worksheet.set_column('B:B', 12)
+        worksheet.set_column('C:C', 12)
+        worksheet.set_column('D:D', 12)
+        worksheet.set_column('E:E', 12)
+        worksheet.set_column('F:F', 12)
+        worksheet.set_column('G:G', 12)
+        worksheet.set_column('H:H', 12)
+        worksheet.set_column('I:I', 12)
+        worksheet.set_column('J:J', 12)
+        worksheet.set_column('K:K', 12)
+        worksheet.set_column('L:L', 12)
+        worksheet.set_column('M:M', 12)
+        worksheet.set_column('N:N', 12)
+        worksheet.set_column('O:O', 12)
+        # 保存并关闭工作簿
+        workbook.close()

+ 63 - 49
car/car-wei-zhang/car_wei_zhang.py

@@ -171,16 +171,28 @@ def data_process():
 
     # 读取 Excel 文件中的数据
     df = pd.read_excel(io=input_path)
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['序号', '车牌号', '一级单位', '二级单位', '三级单位', '车架号', '违章时间', '违章地点',
+                        '违章详情', '扣分', '罚款', '三方处理状态', '处理时间', '违章未处理时长(天)']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 获取需要清理的列名列表,排除 "违章时间" 和 "处理时间" 列
     columns_to_clean = list(filter(lambda x: x not in ('违章时间', '处理时间'), df.columns))
     # 对需要清理的列进行字符串清理,移除多余的空白字符
     df[columns_to_clean] = df[columns_to_clean].map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)
-    df['账期'] = year_month
+    df['year_month'] = year_month
     # 保存原始单位和车牌号信息到新的列中
-    df['原始一级单位'] = df['一级单位']
-    df['原始二级单位'] = df['二级单位']
-    df['原始三级单位'] = df['三级单位']
-    df['原始车牌号'] = df['车牌号']
+    df['raw_yi_ji'] = df['一级单位']
+    df['raw_er_ji'] = df['二级单位']
+    df['raw_san_ji'] = df['三级单位']
+    df['raw_che_pai_hao'] = df['车牌号']
 
     # 定义函数,用于提取并标准化车牌号
     def get_che_pai(che_pai):
@@ -224,12 +236,12 @@ def data_process():
         return "1"  # 匹配失败
 
     # 应用 che_pai_fail 函数生成车牌匹配失败标记列
-    df['车牌匹配失败'] = df['车牌号'].apply(che_pai_fail)
+    df['che_pai_fail'] = df['车牌号'].apply(che_pai_fail)
 
     # 获取一级单位
     def get_first_unit(x):
-        raw_che_pai = x['原始车牌号']
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
+        raw_che_pai = x['raw_che_pai_hao']
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
         if not raw_first_unit or not raw_first_unit.strip():
             raise RuntimeError(f"一级单位为空:{raw_che_pai}")
         if raw_first_unit in first_unit_map:
@@ -242,7 +254,7 @@ def data_process():
     # 获取二级单位
     def get_second_unit(x):
         first_unit = str(x['一级单位']) if pd.notna(x['一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
         if first_unit in ["华北基地建设部", "雄安基地建设部", "省公司本部"]:
             return first_unit
         if not raw_second_unit or not raw_second_unit.strip():
@@ -282,7 +294,7 @@ def data_process():
     # 获取三级单位
     def get_third_unit(x):
         second_unit = str(x['二级单位']) if pd.notna(x['二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         return raw_third_unit if raw_third_unit and raw_third_unit.strip() else second_unit
 
     # 应用 get_third_unit 函数生成三级单位列
@@ -299,7 +311,7 @@ def data_process():
                 return second_org.get('id')
         return ''
 
-    df['二级组织机构编码'] = df['一级单位'].apply(get_area_no)
+    df['area_no'] = df['一级单位'].apply(get_area_no)
 
     # 用于根据组织机构编码获取组织机构名称
     def get_org_name(x):
@@ -313,16 +325,16 @@ def data_process():
             return po.get('name')
         return ''
 
-    # 将get_org_name函数应用到'二级组织机构编码'列,生成'二级组织机构名称'列
-    df['二级组织机构名称'] = df['二级组织机构编码'].apply(get_org_name)
+    # 将get_org_name函数应用到'area_no'列,生成'area_name'列
+    df['area_name'] = df['area_no'].apply(get_org_name)
 
     # 定义一个函数,用于根据行数据获取三级组织机构编码
     def get_city_no(x):
         # 获取相关字段值,如果为空则设置为""
-        area_no = str(x['二级组织机构编码']) if pd.notna(x['二级组织机构编码']) else ""
-        area_name = str(x['二级组织机构名称']) if pd.notna(x['二级组织机构名称']) else ""
+        area_no = str(x['area_no']) if pd.notna(x['area_no']) else ""
+        area_name = str(x['area_name']) if pd.notna(x['area_name']) else ""
         first_unit = str(x['一级单位']) if pd.notna(x['一级单位']) else ""
-        second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
+        second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
         if not area_no or not area_no.strip() or not area_name or not area_name.strip():
             return ''
         if '华北基地建设部' == first_unit:
@@ -410,16 +422,16 @@ def data_process():
             return "D0130830"
         return ''
 
-    # 将get_city_no函数应用到DataFrame的每一行,生成'三级组织机构编码'列
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
-    # 将get_org_name函数应用到'三级组织机构编码'列,生成'三级组织机构名称'列
-    df['三级组织机构名称'] = df['三级组织机构编码'].apply(get_org_name)
+    # 将get_city_no函数应用到DataFrame的每一行,生成'city_no'列
+    df['city_no'] = df.apply(get_city_no, axis=1)
+    # 将get_org_name函数应用到'city_no'列,生成'city_name'列
+    df['city_name'] = df['city_no'].apply(get_org_name)
 
     # 定义一个函数,用于根据行数据获取二级组织机构编码2
     def get_area_no2(x):
         # 获取相关字段值,如果为空则设置为""
-        area_name = str(x['二级组织机构名称']) if pd.notna(x['二级组织机构名称']) else ""
-        city_name = str(x['三级组织机构名称']) if pd.notna(x['三级组织机构名称']) else ""
+        area_name = str(x['area_name']) if pd.notna(x['area_name']) else ""
+        city_name = str(x['city_name']) if pd.notna(x['city_name']) else ""
         if not area_name or not area_name.strip() or '省本部' == area_name:
             return ''
         # 根据二级组织机构名称和三级组织机构名称的内容,返回对应的编码
@@ -475,16 +487,16 @@ def data_process():
             return "782"
         return ""
 
-    # 将get_area_no2函数应用到DataFrame的每一行,生成'二级组织机构编码2'列
-    df['二级组织机构编码2'] = df.apply(get_area_no2, axis=1)
-    # 将get_org_name函数应用到'二级组织机构编码2'列,生成'二级组织机构名称2'列
-    df['二级组织机构名称2'] = df['二级组织机构编码2'].apply(get_org_name)
+    # 将get_area_no2函数应用到DataFrame的每一行,生成'area_no2'列
+    df['area_no2'] = df.apply(get_area_no2, axis=1)
+    # 将get_org_name函数应用到'area_no2'列,生成'area_name2'列
+    df['area_name2'] = df['area_no2'].apply(get_org_name)
 
     # 获取城市ID
     def get_city_id(x):
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         unit = f"{raw_first_unit}_{raw_second_unit}_{raw_third_unit}"
         if not unit or not unit.strip():
             return ''
@@ -515,9 +527,9 @@ def data_process():
         # 获取相关字段值,如果为空则设置为""
         city_id = str(x['city_id']) if pd.notna(x['city_id']) else ""
         city = str(x['city']) if pd.notna(x['city']) else ""
-        raw_first_unit = str(x['原始一级单位']) if pd.notna(x['原始一级单位']) else ""
-        raw_second_unit = str(x['原始二级单位']) if pd.notna(x['原始二级单位']) else ""
-        raw_third_unit = str(x['原始三级单位']) if pd.notna(x['原始三级单位']) else ""
+        raw_first_unit = str(x['raw_yi_ji']) if pd.notna(x['raw_yi_ji']) else ""
+        raw_second_unit = str(x['raw_er_ji']) if pd.notna(x['raw_er_ji']) else ""
+        raw_third_unit = str(x['raw_san_ji']) if pd.notna(x['raw_san_ji']) else ""
         unit = f"{raw_first_unit}_{raw_second_unit}_{raw_third_unit}"
         # 如果城市ID、城市名称或单位为空,则返回""
         if not city_id or not city_id.strip() or not city or not city.strip() or not unit or not unit.strip():
@@ -541,26 +553,28 @@ def data_process():
     df['district'] = df['district_id'].apply(get_area_name)
 
     # 提取账期年份和月份信息
-    df['year_no'] = df['账期'].apply(lambda x: None if pd.isna(x) else str(x)[:4])
-    df['month_no'] = df['账期'].apply(lambda x: None if pd.isna(x) else str(x)[-2:])
+    df['year_no'] = df['year_month'].apply(lambda x: None if pd.isna(x) else str(x)[:4])
+    df['month_no'] = df['year_month'].apply(lambda x: None if pd.isna(x) else str(x)[-2:])
     # 格式化违章时间和处理时间为年月格式
-    df['违章年月'] = df['违章时间'].apply(lambda x: None if pd.isna(x) else pd.to_datetime(x).strftime('%Y%m'))
-    df['处理年月'] = df['处理时间'].apply(lambda x: None if pd.isna(x) else pd.to_datetime(x).strftime('%Y%m'))
-
+    df['wei_zhang_nian_yue'] = df['违章时间'].apply(lambda x: None if pd.isna(x) else pd.to_datetime(x).strftime('%Y%m'))
+    df['chu_li_nian_yue'] = df['处理时间'].apply(lambda x: None if pd.isna(x) else pd.to_datetime(x).strftime('%Y%m'))
+    df.rename(
+        columns={'车牌号': 'che_pai_hao', '一级单位': 'first_unit', '二级单位': 'second_unit', '三级单位': 'third_unit',
+                 '车架号': 'che_jia_hao', '违章时间': 'wei_zhang_shi_jian', '违章地点': 'wei_zhang_di_dian',
+                 '违章详情': 'wei_zhang_xiang_qing', '扣分': 'kou_fen', '罚款': 'fa_kuan',
+                 '三方处理状态': 'chu_li_zhuang_tai', '处理时间': 'chu_li_shi_jian',
+                 '违章未处理时长(天)': 'wei_zhang_wei_chu_li_shi_chang'}, inplace=True)
+    df = df[['year_month', 'che_pai_hao', 'first_unit', 'second_unit', 'third_unit', 'che_jia_hao',
+             'wei_zhang_shi_jian', 'wei_zhang_di_dian', 'wei_zhang_xiang_qing', 'kou_fen', 'fa_kuan',
+             'chu_li_zhuang_tai', 'chu_li_shi_jian', 'wei_zhang_wei_chu_li_shi_chang', 'raw_yi_ji', 'raw_er_ji',
+             'raw_san_ji', 'raw_che_pai_hao', 'che_pai_fail', 'area_no', 'area_name', 'city_no', 'city_name',
+             'area_no2', 'area_name2', 'city_id', 'city', 'district_id', 'district', 'year_no', 'month_no',
+             'wei_zhang_nian_yue', 'chu_li_nian_yue']]
     # 打印DataFrame的信息
-    print(df.info())
+    df.info()
 
     # 将处理后的数据保存到CSV文件中
-    df.to_csv(path_or_buf=output_path,
-              header=['year_month', 'che_pai_hao', 'first_unit', 'second_unit', 'third_unit', 'che_jia_hao',
-                      'wei_zhang_shi_jian', 'wei_zhang_di_dian', 'wei_zhang_xiang_qing', 'kou_fen', 'fa_kuan',
-                      'chu_li_zhuang_tai', 'chu_li_shi_jian', 'wei_zhang_wei_chu_li_shi_chang', 'raw_yi_ji',
-                      'raw_er_ji',
-                      'raw_san_ji', 'raw_che_pai_hao', 'che_pai_fail', 'area_no', 'area_name', 'city_no', 'city_name',
-                      'area_no2', 'area_name2', 'city_id', 'city', 'district_id', 'district', 'year_no', 'month_no',
-                      'wei_zhang_nian_yue', 'chu_li_nian_yue'],
-              index=False,
-              encoding='utf-8-sig')
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -571,7 +585,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,che_pai_hao,first_unit,second_unit,third_unit,che_jia_hao,wei_zhang_shi_jian,wei_zhang_di_dian,wei_zhang_xiang_qing,kou_fen,fa_kuan,chu_li_zhuang_tai,chu_li_shi_jian,wei_zhang_wei_chu_li_shi_chang,raw_yi_ji,raw_er_ji,raw_san_ji,raw_che_pai_hao,che_pai_fail,area_no,area_name,city_no,city_name,area_no2,area_name2,city_id,city,district_id,district,year_no,month_no,wei_zhang_nian_yue,chu_li_nian_yue"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 1 - 1
car/car-yue-jie-missing/car_yue_jie_missing.py

@@ -63,7 +63,7 @@ with psycopg.connect(
 # 将列表a转换为pandas DataFrame
 df = pd.DataFrame(a)
 # 打印DataFrame的基本信息,便于调试
-print(df.info())
+df.info()
 # 将DataFrame保存为Excel文件,文件名为“睿行车辆越界报警日统计缺失数据日期.xlsx”
 df.to_excel(
     f"{start_date.strftime('%Y%m')}睿行车辆越界报警日统计缺失数据日期.xlsx",

+ 3 - 5
car/car-zu-lin/car_zu_lin.py

@@ -222,9 +222,7 @@ def data_process():
     print(result_df.info())
 
     # 将处理后的数据保存到CSV文件中
-    result_df.to_csv(path_or_buf=output_path,
-                     index=False,
-                     encoding='utf-8-sig')
+    result_df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8')
 
 
 def data_import():
@@ -235,7 +233,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,raw_che_pai_hao_he_tong,che_xing,che_liang_suo_shu_dan_wei,he_tong_ming_cheng,he_tong_bian_hao,jia_shui_he_ji_jin_e,bu_han_shui_jin_e,shui_e,zu_qi,raw_che_pai_hao_ti_huan,ti_huan_nian_yue,bei_zhu,che_pai_hao_he_tong,che_pai_he_tong_fail,che_pai_hao_ti_huan,che_pai_ti_huan_fail,first_unit,che_pai_hao,year_no,month_no"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出
@@ -263,7 +261,7 @@ def upload_file():
     # 获取当前日期,并计算上个月的第一天
     today = datetime.today()
     start_date = today - relativedelta(months=1, day=1)
-    remote_path = f'{remote_dir_path}{start_date.strftime('%Y%m')}.xlsx'  # 定义远程主机的目标文件路径
+    remote_path = f'{remote_dir_path}{start_date.strftime('%Y%m%d%H%M%S')}.xlsx'  # 定义远程主机的目标文件路径
     # 使用paramiko.SSHClient创建一个SSH客户端对象,并通过with语句管理其上下文
     with paramiko.SSHClient() as ssh:
         # 设置自动添加主机密钥策略,避免因未知主机密钥导致连接失败

+ 101 - 0
doc/sql.md

@@ -104,3 +104,104 @@ order by
     create_time desc
 ```
 
+## 车辆租赁费缺失检查
+```sql
+select
+    *
+from car.car_base_data_month a
+where year_month = TO_CHAR(CURRENT_DATE - INTERVAL '1 month', 'YYYYMM')::int4 and che_liang_lai_yuan = '租赁车辆' and not exists (select 1 from car.car_zu_lin b where a.year_month = b.year_month and a.che_pai_hao = b.che_pai_hao)
+```
+
+## 检查车辆基本信息删除但没有报废
+```sql
+select
+    *
+from
+    car.car_base_data_month a
+where
+    year_month = TO_CHAR(CURRENT_DATE - interval '2 month', 'YYYYMM')::int4
+    and not exists (
+    select
+        1
+    from
+        car.car_base_data_day b
+    where
+        b.year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4
+        and b.data_date = (select max(data_date) from car.car_base_data_day where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4)
+        and a.year_month = b.last_month
+        and a.che_pai_hao = b.che_pai_hao)
+    and not exists (
+    select
+        1
+    from
+        car.car_bao_fei b
+    where a.che_pai_hao = b.che_pai_hao and b.month_id = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4);
+select * from car.car_base_data_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 and car_new = 1;
+```
+```sql
+select
+    *
+from
+    car.car_base_data_month a
+where
+    year_month = TO_CHAR(CURRENT_DATE - interval '2 month', 'YYYYMM')::int4
+    and not exists (
+    select
+        1
+    from
+        car.car_base_data_month b
+    where
+        a.year_month = b.last_month
+        and a.che_pai_hao = b.che_pai_hao)
+    and not exists (
+    select
+        1
+    from
+        car.car_bao_fei b
+    where a.che_pai_hao = b.che_pai_hao and b.month_id = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4);
+select * from car.car_base_data_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 and car_new = 1;
+```
+
+## 检查同时存在车辆基本信息和报废
+```sql
+select
+    b.bao_fei_ri_qi,
+    *
+from
+    car.car_base_data_day a
+join car.car_bao_fei b on
+    a.year_month = b.month_id
+    and a.che_pai_hao = b.che_pai_hao
+where
+    a.year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4
+    and a.data_date = (select max(data_date) from car.car_base_data_day where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4)
+```
+```sql
+select
+    b.bao_fei_ri_qi,
+    a.*
+from
+    car.car_base_data_month a
+join car.car_bao_fei b on
+    a.year_month = b.month_id
+    and a.che_pai_hao = b.che_pai_hao
+where
+    a.year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4
+```
+
+## 降序查询数据
+```sql
+select * from house.building_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by building_area desc;
+select * from house.building_repair_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by final_cost desc;
+select * from house.land_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by total_land_area desc;
+select * from house.rent_in_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 and contract_status = '履行中' order by gross_amount desc;
+select * from house.room_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by building_area desc;
+select * from car.car_bao_xian where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by total_amount desc;
+select * from car.car_da_wei_xiu where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by amount_excluding_tax desc;
+select * from car.car_lu_qiao where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by amount_excluding_tax desc;
+select * from car.car_nian_jian_fei where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by amount_excluding_tax desc;
+select * from car.car_qi_ta where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by amount_excluding_tax desc;
+select * from car.car_ran_you where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by amount_excluding_tax desc;
+select * from car.car_wei_xiu where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by amount_excluding_tax desc;
+select * from car.car_li_cheng_month where year_month = TO_CHAR(CURRENT_DATE - interval '1 month', 'YYYYMM')::int4 order by zong_li_cheng desc;
+```

+ 4 - 6
house/house-abnormal-data/house_abnormal_data.py

@@ -110,7 +110,7 @@ def data_process():
         ny = t.replace('.xlsx', '').split('_')[0]  # 提取年月信息
         ds = t.replace('.xlsx', '').split('_')[1]  # 提取地市信息
         tmp = pd.read_excel(output_dir + t, skiprows=8, header=None)  # 读取Excel文件内容
-        if '省本部' in ds or '省公司' in ds:
+        if '省本部' in ds or '省公司' in ds or '本部' in ds:
             tmp = pd.read_excel(output_dir + t, skiprows=8, header=None, nrows=1)  # 特殊处理省本部文件
         tmp['年月'] = ny  # 添加年月列
         tmp['地市'] = ds  # 添加地市列
@@ -263,12 +263,10 @@ def data_process():
     df['city_name'] = df.apply(get_city_name, axis=1)
 
     # 输出DataFrame的基本信息
-    print(df.info())
+    df.info()
 
     # 将处理后的数据保存为CSV文件
-    df.to_csv(path_or_buf=output_path,
-              index=False,
-              encoding='utf-8-sig')
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -279,7 +277,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "third_unit,wei_guan_lian_tu_di_zheng,wei_guan_lian_fang_chan_zheng,wei_guan_lian_ju_zhi,jian_zhu_tu_di_ju_zhi_bu_dui_ying,tu_di_ju_zhi_bian_hao_bu_cun_zai,jian_zhu_ju_zhi_bian_hao_bu_cun_zai,jian_zhu_tu_di_biao_qian_hao_bu_cun_zai,dai_guan_lian_tu_di,dai_guan_lian_jian_zhu,ju_zhi_gte_three_tu_di,ju_zhi_gt_ten_tu_di,ju_zhi_gte_five_jian_zhu,ju_zhi_gte_ten_jian_zhu,tu_di_gte_seven_jian_zhu,tu_di_gte_ten_jian_zhu,tu_di_zheng_xia_ci_kong_bai,fang_chan_zheng_xia_ci_kong_bai,ju_zhi_di_duan_kong_bai,xian_zhi_jian_zhu_mian_ji,xian_zhi_tu_di_mian_ji,wu_jian_zhu_fei_xian_zhi_tu_di_mian_ji,tu_di_shi_yong_quan_qi_ta,year_month,second_unit,source,area_no,area_name,city_no,city_name"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 65 - 31
house/house-building/house_building.py

@@ -97,6 +97,25 @@ def data_process():
 
     # 读取Excel文件中的数据并进行预处理
     df = pd.read_excel(io=input_path)  # 读取Excel文件
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['资产所属单位(一级)', '资产所属单位(二级)', '资产所属单位(三级)', '建筑别名', '盘点状态',
+                        '盘点情况', '是否修改', '建筑是否存在待核对信息', '楼层房间是否存在待核对信息', '建筑ID',
+                        '得房率', '上级局址名称', '局址ID', '上级土地名称', '房屋来源', '取得日期', '房龄开始年份',
+                        '投资主体', '管理层级', '房屋结构', '楼层总数', '是否临街', '是否有院落', '整栋是否独有',
+                        '是否有房产证', '无房产证原因', '是否有资产卡片', '资产编号', '资产标签号', '使用状态',
+                        '建筑用途', '权属状态', '建筑占地面积(㎡)', '建筑面积(㎡)', '建筑面积-自用(㎡)',
+                        '建筑面积-出租(㎡)', '建筑面积-闲置(㎡)', '建筑面积-不可使用(㎡)', '使用面积(㎡)',
+                        '使用面积-自用(㎡)', '使用面积-出租(㎡)', '使用面积-闲置(㎡)', '使用面积-不可使用(㎡)', '楼长姓名',
+                        '楼长所在单位', '经度', '纬度', '标准地址', '实际产权人', '是否完成清查']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     df = df.map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)  # 去除字符串字段中的多余空格
     df.drop_duplicates(subset=['建筑ID'], keep='last', inplace=True)  # 去重,保留最后一条记录
 
@@ -117,22 +136,22 @@ def data_process():
                 return area_no
         raise RuntimeError(f'二级组织机构编码匹配失败: {second_unit}')
 
-    df['二级组织机构编码'] = df.apply(get_area_no, axis=1)  # 应用函数,生成二级组织机构编码列
+    df['area_no'] = df.apply(get_area_no, axis=1)  # 应用函数,生成二级组织机构编码列
 
     # 定义函数:根据二级组织机构编码获取二级组织机构名称
     def get_area_name(x):
-        area_no = x['二级组织机构编码']
+        area_no = x['area_no']
         second_org = org_map[area_no]
         area_name = second_org['name']
         return area_name
 
-    df['二级组织机构名称'] = df.apply(get_area_name, axis=1)  # 应用函数,生成二级组织机构名称列
+    df['area_name'] = df.apply(get_area_name, axis=1)  # 应用函数,生成二级组织机构名称列
 
     # 定义函数:根据资产所属单位获取三级组织机构编码
     def get_city_no(x):
         third_unit = x['资产所属单位(三级)']
-        area_name = x['二级组织机构名称']
-        area_no = x['二级组织机构编码']
+        area_name = x['area_name']
+        area_no = x['area_no']
         if area_name == '石家庄':
             if '矿区' in third_unit:
                 return 'D0130185'
@@ -215,16 +234,16 @@ def data_process():
             return 'D0130830'
         return 'HE001'
 
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)  # 应用函数,生成三级组织机构编码列
+    df['city_no'] = df.apply(get_city_no, axis=1)  # 应用函数,生成三级组织机构编码列
 
     # 定义函数:根据三级组织机构编码获取三级组织机构名称
     def get_city_name(x):
-        city_no = x['三级组织机构编码']
+        city_no = x['city_no']
         third_org = org_map[city_no]
         city_name = third_org['name']
         return city_name
 
-    df['三级组织机构名称'] = df.apply(get_city_name, axis=1)  # 应用函数,生成三级组织机构名称列
+    df['city_name'] = df.apply(get_city_name, axis=1)  # 应用函数,生成三级组织机构名称列
 
     # 定义函数:根据标准地址获取城市ID
     def get_city_id(x):
@@ -328,30 +347,45 @@ def data_process():
         return ''
 
     df['house_age'] = df.apply(get_house_age, axis=1)  # 应用函数,生成房龄列
-    df.insert(0, '年月', year_month)  # 在数据框第一列插入年月列
-
+    df.insert(0, 'year_month', year_month)  # 在数据框第一列插入年月列
+    df.rename(
+        columns={'资产所属单位(一级)': 'first_unit', '资产所属单位(二级)': 'second_unit', '资产所属单位(三级)': 'third_unit',
+                 '建筑别名': 'building_name', '盘点状态': 'inventory_status', '盘点情况': 'inventory_situation',
+                 '是否修改': 'modify', '建筑是否存在待核对信息': 'building_to_be_verified',
+                 '楼层房间是否存在待核对信息': 'floor_room_to_be_verified', '建筑ID': 'building_id',
+                 '得房率': 'housing_acquisition_rate', '上级局址名称': 'site_name', '局址ID': 'site_id',
+                 '上级土地名称': 'land_name', '房屋来源': 'housing_source', '取得日期': 'acquisition_date',
+                 '房龄开始年份': 'house_year_began', '投资主体': 'investor', '管理层级': 'management_level',
+                 '房屋结构': 'building_structure', '楼层总数': 'total_floors', '是否临街': 'frontage',
+                 '是否有院落': 'courtyard', '整栋是否独有': 'whole_building',
+                 '是否有房产证': 'property_ownership_certificate',
+                 '无房产证原因': 'no_property_ownership_certificate_reason', '是否有资产卡片': 'has_asset_card',
+                 '资产编号': 'assets_num', '资产标签号': 'assets_tag_num', '使用状态': 'usage_status',
+                 '建筑用途': 'building_use', '权属状态': 'ownership_status', '建筑占地面积(㎡)': 'floor_area',
+                 '建筑面积(㎡)': 'building_area', '建筑面积-自用(㎡)': 'building_area_self_use',
+                 '建筑面积-出租(㎡)': 'building_area_rent', '建筑面积-闲置(㎡)': 'building_area_idle',
+                 '建筑面积-不可使用(㎡)': 'building_area_unusable', '使用面积(㎡)': 'usable_area',
+                 '使用面积-自用(㎡)': 'usable_area_self_use', '使用面积-出租(㎡)': 'usable_area_rent',
+                 '使用面积-闲置(㎡)': 'usable_area_idle', '使用面积-不可使用(㎡)': 'usable_area_unusable',
+                 '楼长姓名': 'community_assistant_name', '楼长所在单位': 'community_assistant_unit', '经度': 'lng_jt',
+                 '纬度': 'lat_jt', '标准地址': 'address', '实际产权人': 'property_owner', '是否完成清查': 'checked'}, inplace=True)
+    df = df[['year_month', 'first_unit', 'second_unit', 'third_unit', 'building_name', 'inventory_status',
+             'inventory_situation', 'modify', 'building_to_be_verified', 'floor_room_to_be_verified', 'building_id',
+             'housing_acquisition_rate', 'site_name', 'site_id', 'land_name', 'housing_source', 'acquisition_date',
+             'house_year_began', 'investor', 'management_level', 'building_structure', 'total_floors', 'frontage',
+             'courtyard', 'whole_building', 'property_ownership_certificate',
+             'no_property_ownership_certificate_reason', 'has_asset_card', 'assets_num', 'assets_tag_num',
+             'usage_status', 'building_use', 'ownership_status', 'floor_area', 'building_area',
+             'building_area_self_use', 'building_area_rent', 'building_area_idle', 'building_area_unusable',
+             'usable_area', 'usable_area_self_use', 'usable_area_rent', 'usable_area_idle', 'usable_area_unusable',
+             'community_assistant_name', 'community_assistant_unit', 'lng_jt', 'lat_jt', 'address',
+             'property_owner', 'checked', 'area_no', 'area_name', 'city_no', 'city_name', 'city_id', 'city',
+             'district_id', 'district', 'year_no', 'month_no', 'house_age']]
     # 打印数据框信息
-    print(df.info())
+    df.info()
 
     # 将结果保存为CSV文件
-    df.to_csv(
-        path_or_buf=output_path,
-        index=False,
-        header=[
-            'year_month', 'first_unit', 'second_unit', 'third_unit', 'building_name', 'building_id',
-            'housing_acquisition_rate', 'site_name', 'site_id', 'land_name', 'housing_source', 'acquisition_date',
-            'house_year_began', 'investor', 'management_level', 'building_structure', 'total_floors', 'frontage',
-            'courtyard', 'whole_building', 'property_ownership_certificate',
-            'no_property_ownership_certificate_reason', 'unrelated_assets', 'assets_num', 'assets_tag_num',
-            'usage_status', 'building_use', 'ownership_status', 'floor_area', 'building_area',
-            'building_area_self_use', 'building_area_rent', 'building_area_idle', 'building_area_unusable',
-            'usable_area', 'usable_area_self_use', 'usable_area_rent', 'usable_area_idle', 'usable_area_unusable',
-            'community_assistant_name', 'community_assistant_unit', 'lng_jt', 'lat_jt', 'address',
-            'property_owner', 'checked', 'area_no', 'area_name', 'city_no', 'city_name', 'city_id', 'city',
-            'district_id', 'district', 'year_no', 'month_no', 'house_age'
-        ],
-        encoding='utf-8-sig'
-    )
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -360,9 +394,9 @@ def data_import():
     # 目标表和文件信息
     table = "house.building_month"  # 数据库目标表名
     # 表字段列名,用于指定导入数据的列顺序
-    columns = "year_month,first_unit,second_unit,third_unit,building_name,building_id,housing_acquisition_rate,site_name,site_id,land_name,housing_source,acquisition_date,house_year_began,investor,management_level,building_structure,total_floors,frontage,courtyard,whole_building,property_ownership_certificate,no_property_ownership_certificate_reason,unrelated_assets,assets_num,assets_tag_num,usage_status,building_use,ownership_status,floor_area,building_area,building_area_self_use,building_area_rent,building_area_idle,building_area_unusable,usable_area,usable_area_self_use,usable_area_rent,usable_area_idle,usable_area_unusable,community_assistant_name,community_assistant_unit,lng_jt,lat_jt,address,property_owner,checked,area_no,area_name,city_no,city_name,city_id,city,district_id,district,year_no,month_no,house_age"
+    columns = "year_month,first_unit,second_unit,third_unit,building_name,inventory_status,inventory_situation,modify,building_to_be_verified,floor_room_to_be_verified,building_id,housing_acquisition_rate,site_name,site_id,land_name,housing_source,acquisition_date,house_year_began,investor,management_level,building_structure,total_floors,frontage,courtyard,whole_building,property_ownership_certificate,no_property_ownership_certificate_reason,has_asset_card,assets_num,assets_tag_num,usage_status,building_use,ownership_status,floor_area,building_area,building_area_self_use,building_area_rent,building_area_idle,building_area_unusable,usable_area,usable_area_self_use,usable_area_rent,usable_area_idle,usable_area_unusable,community_assistant_name,community_assistant_unit,lng_jt,lat_jt,address,property_owner,checked,area_no,area_name,city_no,city_name,city_id,city,district_id,district,year_no,month_no,house_age"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 50 - 27
house/house-fang-jian/house_fang_jian.py

@@ -97,7 +97,22 @@ def data_process():
 
     # 读取 Excel 文件中的数据
     df = pd.read_excel(io=input_path)
-
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['资产所属单位(一级)', '资产所属单位(二级)', '资产所属单位(三级)', '建筑名称', '标准地址',
+                        '所在楼层', '楼层建筑总面积(㎡)', '楼层使用总面积(㎡)', '房间名称', '房间状态', '租赁类别',
+                        '房间类别(一级)', '房间类别(二级)', '工位总数', '是否临街', '建筑面积(㎡)', '建筑面积-自用(㎡)',
+                        '建筑面积-闲置(㎡)', '建筑面积-出租(㎡)', '建筑面积-不可使用(㎡)', '使用面积(㎡)',
+                        '使用面积-自用(㎡)', '使用面积-闲置(㎡)', '使用面积-出租(㎡)', '使用面积-不可使用(㎡)',
+                        '闲置开始时间', '不可使用原因', '层高(m)', '承重(kg/㎡)']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 清理 DataFrame 中的空白字符(排除特定列)
     columns_to_clean = list(filter(lambda x: x not in ('房间名称'), df.columns))
     df[columns_to_clean] = df[columns_to_clean].map(
@@ -122,23 +137,23 @@ def data_process():
         raise RuntimeError(f'二级组织机构编码匹配失败: {second_unit}')
 
     # 应用 get_area_no 函数,生成二级组织机构编码列
-    df['二级组织机构编码'] = df.apply(get_area_no, axis=1)
+    df['area_no'] = df.apply(get_area_no, axis=1)
 
     # 定义函数:根据二级组织机构编码获取对应的名称
     def get_area_name(x):
-        area_no = x['二级组织机构编码']
+        area_no = x['area_no']
         second_org = org_map[area_no]
         area_name = second_org['name']
         return area_name
 
     # 应用 get_area_name 函数,生成二级组织机构名称列
-    df['二级组织机构名称'] = df.apply(get_area_name, axis=1)
+    df['area_name'] = df.apply(get_area_name, axis=1)
 
     # 定义函数:根据资产所属单位获取三级组织机构编码
     def get_city_no(x):
         third_unit = x['资产所属单位(三级)']
-        area_name = x['二级组织机构名称']
-        area_no = x['二级组织机构编码']
+        area_name = x['area_name']
+        area_no = x['area_no']
         if area_name == '石家庄':
             if '矿区' in third_unit:
                 return 'D0130185'
@@ -222,17 +237,17 @@ def data_process():
         return 'HE001'
 
     # 应用 get_city_no 函数,生成三级组织机构编码列
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
+    df['city_no'] = df.apply(get_city_no, axis=1)
 
     # 定义函数:根据三级组织机构编码获取对应的名称
     def get_city_name(x):
-        city_no = x['三级组织机构编码']
+        city_no = x['city_no']
         third_org = org_map[city_no]
         city_name = third_org['name']
         return city_name
 
     # 应用 get_city_name 函数,生成三级组织机构名称列
-    df['三级组织机构名称'] = df.apply(get_city_name, axis=1)
+    df['city_name'] = df.apply(get_city_name, axis=1)
 
     # 定义函数:根据地址和资产所属单位获取城市 ID
     def get_city_id(x):
@@ -313,30 +328,38 @@ def data_process():
         try:
             return int(x)
         except Exception:
+            logger.warning(f"转换失败: {x}")
             return ""
 
     df['工位总数'] = df['工位总数'].apply(get_int)
     # 在 DataFrame 中插入年月列
-    df.insert(0, '年月', year_month)
-
+    df.insert(0, 'year_month', year_month)
+    df.rename(
+        columns={'资产所属单位(一级)': 'first_unit', '资产所属单位(二级)': 'second_unit', '资产所属单位(三级)': 'third_unit',
+                 '建筑名称': 'building_name', '标准地址': 'address', '所在楼层': 'floor',
+                 '楼层建筑总面积(㎡)': 'floor_building_area',
+                 '楼层使用总面积(㎡)': 'floor_usable_area', '房间名称': 'room_name', '房间状态': 'room_status',
+                 '租赁类别': 'rent_type', '房间类别(一级)': 'first_room_type', '房间类别(二级)': 'second_room_type',
+                 '工位总数': 'seat_num', '是否临街': 'frontage', '建筑面积(㎡)': 'building_area',
+                 '建筑面积-自用(㎡)': 'building_area_self_use', '建筑面积-闲置(㎡)': 'building_area_idle',
+                 '建筑面积-出租(㎡)': 'building_area_rent', '建筑面积-不可使用(㎡)': 'building_area_unusable',
+                 '使用面积(㎡)': 'usable_area', '使用面积-自用(㎡)': 'usable_area_self_use',
+                 '使用面积-闲置(㎡)': 'usable_area_idle', '使用面积-出租(㎡)': 'usable_area_rent',
+                 '使用面积-不可使用(㎡)': 'usable_area_unusable', '闲置开始时间': 'idle_start_date',
+                 '不可使用原因': 'unusable_reason', '层高(m)': 'floor_height', '承重(kg/㎡)': 'load_bearing'},
+        inplace=True)
+    df = df[['year_month', 'first_unit', 'second_unit', 'third_unit', 'building_name', 'address', 'floor',
+             'floor_building_area', 'floor_usable_area', 'room_name', 'room_status', 'rent_type',
+             'first_room_type', 'second_room_type', 'seat_num', 'frontage', 'building_area',
+             'building_area_self_use', 'building_area_idle', 'building_area_rent', 'building_area_unusable',
+             'usable_area', 'usable_area_self_use', 'usable_area_idle', 'usable_area_rent', 'usable_area_unusable',
+             'idle_start_date', 'unusable_reason', 'floor_height', 'load_bearing', 'area_no', 'area_name',
+             'city_no', 'city_name', 'city_id', 'city', 'district_id', 'district']]
     # 打印 DataFrame 的信息
-    print(df.info())
+    df.info()
 
     # 将处理后的数据保存为 CSV 文件
-    df.to_csv(
-        path_or_buf=output_path,
-        index=False,
-        header=[
-            'year_month', 'first_unit', 'second_unit', 'third_unit', 'building_name', 'address', 'floor',
-            'floor_building_area', 'floor_usable_area', 'room_name', 'room_status', 'rent_type',
-            'first_room_type', 'second_room_type', 'seat_num', 'frontage', 'building_area',
-            'building_area_self_use', 'building_area_idle', 'building_area_rent', 'building_area_unusable',
-            'usable_area', 'usable_area_self_use', 'usable_area_idle', 'usable_area_rent', 'usable_area_unusable',
-            'idle_start_date', 'unusable_reason', 'floor_height', 'load_bearing', 'area_no', 'area_name',
-            'city_no', 'city_name', 'city_id', 'city', 'district_id', 'district'
-        ],
-        encoding='utf-8-sig'
-    )
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -347,7 +370,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,first_unit,second_unit,third_unit,building_name,address,floor,floor_building_area,floor_usable_area,room_name,room_status,rent_type,first_room_type,second_room_type,seat_num,frontage,building_area,building_area_self_use,building_area_idle,building_area_rent,building_area_unusable,usable_area,usable_area_self_use,usable_area_idle,usable_area_rent,usable_area_unusable,idle_start_date,unusable_reason,floor_height,load_bearing,area_no,area_name,city_no,city_name,city_id,city,district_id,district"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 55 - 29
house/house-land/house_land.py

@@ -96,7 +96,23 @@ def data_process():
 
     # 读取Excel文件中的数据
     df = pd.read_excel(io=input_path)
-
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['资产所属单位(一级)', '资产所属单位(二级)', '资产所属单位(三级)', '土地别名', '盘点情况',
+                        '盘点状态', '是否修改', '是否存在待核对信息', '土地编号', '土地ID', '土地性质', '使用权类型',
+                        '地类用途', '取得日期', '闲置开始时间', '局址别名', '局址ID', '标准地址', '投资主体',
+                        '管理层级', '权属状态', '使用状态', '土地总面积(㎡)', '土地自用面积(㎡)', '土地闲置面积(㎡)',
+                        '土地出租面积(㎡)', '土地不可使用面积(㎡)', '是否有土地证', '无土地证原因', '是否有保地风险',
+                        '是否独立成宗土地', '是否空地', '是否有院落', '是否有资产卡片', '资产编号', '资产标签号',
+                        '责任部门', '责任人', '经度', '纬度', '实际产权人', '特殊说明']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 删除字符串字段中的空白字符
     df = df.map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)
 
@@ -123,26 +139,26 @@ def data_process():
 
 
     # 应用函数,生成“二级组织机构编码”列
-    df['二级组织机构编码'] = df.apply(get_area_no, axis=1)
+    df['area_no'] = df.apply(get_area_no, axis=1)
 
 
     # 定义函数:获取二级组织机构名称
     def get_area_name(x):
-        area_no = x['二级组织机构编码']
+        area_no = x['area_no']
         second_org = org_map[area_no]
         area_name = second_org['name']
         return area_name
 
 
     # 应用函数,生成“二级组织机构名称”列
-    df['二级组织机构名称'] = df.apply(get_area_name, axis=1)
+    df['area_name'] = df.apply(get_area_name, axis=1)
 
 
     # 定义函数:获取三级组织机构编码
     def get_city_no(x):
         third_unit = x['资产所属单位(三级)']
-        area_name = x['二级组织机构名称']
-        area_no = x['二级组织机构编码']
+        area_name = x['area_name']
+        area_no = x['area_no']
         if area_name == '石家庄':
             if '矿区' in third_unit:
                 return 'D0130185'
@@ -227,19 +243,19 @@ def data_process():
 
 
     # 应用函数,生成“三级组织机构编码”列
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
+    df['city_no'] = df.apply(get_city_no, axis=1)
 
 
     # 定义函数:获取三级组织机构名称
     def get_city_name(x):
-        city_no = x['三级组织机构编码']
+        city_no = x['city_no']
         third_org = org_map[city_no]
         city_name = third_org['name']
         return city_name
 
 
     # 应用函数,生成“三级组织机构名称”列
-    df['三级组织机构名称'] = df.apply(get_city_name, axis=1)
+    df['city_name'] = df.apply(get_city_name, axis=1)
 
 
     # 定义函数:获取城市ID
@@ -328,27 +344,37 @@ def data_process():
     # 应用函数,生成“district”列
     df['district'] = df.apply(get_district, axis=1)
     # 在DataFrame中插入“年月”列
-    df.insert(0, '年月', year_month)
-
+    df.insert(0, 'year_month', year_month)
+    df.rename(
+        columns={'资产所属单位(一级)': 'first_unit', '资产所属单位(二级)': 'second_unit', '资产所属单位(三级)': 'third_unit',
+                 '土地别名': 'land_name', '盘点情况': 'inventory_situation', '盘点状态': 'inventory_status',
+                 '是否修改': 'modify', '是否存在待核对信息': 'to_be_verified', '土地编号': 'land_no', '土地ID': 'land_id',
+                 '土地性质': 'land_ownership', '使用权类型': 'use_right_type', '地类用途': 'land_use',
+                 '取得日期': 'acquisition_date', '闲置开始时间': 'idle_start_date', '局址别名': 'site_name',
+                 '局址ID': 'site_id', '标准地址': 'address', '投资主体': 'investor', '管理层级': 'management_level',
+                 '权属状态': 'ownership_status', '使用状态': 'usage_status', '土地总面积(㎡)': 'total_land_area',
+                 '土地自用面积(㎡)': 'land_area_self_use', '土地闲置面积(㎡)': 'land_area_idle',
+                 '土地出租面积(㎡)': 'land_area_rent', '土地不可使用面积(㎡)': 'land_area_unusable',
+                 '是否有土地证': 'has_land_deed', '无土地证原因': 'no_land_deed_reason',
+                 '是否有保地风险': 'land_preservation_risk', '是否独立成宗土地': 'independent_parcel_of_land',
+                 '是否空地': 'open_space', '是否有院落': 'courtyard', '是否有资产卡片': 'has_asset_card',
+                 '资产编号': 'assets_num', '资产标签号': 'assets_tag_num', '责任部门': 'responsible_department',
+                 '责任人': 'person_in_charge', '经度': 'lng_jt', '纬度': 'lat_jt', '实际产权人': 'property_owner',
+                 '特殊说明': 'special_specification'}, inplace=True)
+    df = df[['year_month', 'first_unit', 'second_unit', 'third_unit', 'land_name', 'inventory_situation',
+             'inventory_status', 'modify', 'to_be_verified', 'land_no', 'land_id', 'land_ownership',
+             'use_right_type', 'land_use', 'acquisition_date', 'idle_start_date', 'site_name', 'site_id', 'address',
+             'investor', 'management_level', 'ownership_status', 'usage_status', 'total_land_area',
+             'land_area_self_use', 'land_area_idle', 'land_area_rent', 'land_area_unusable', 'has_land_deed',
+             'no_land_deed_reason', 'land_preservation_risk', 'independent_parcel_of_land', 'open_space', 'courtyard',
+             'has_asset_card', 'assets_num', 'assets_tag_num', 'responsible_department', 'person_in_charge', 'lng_jt',
+             'lat_jt','property_owner', 'special_specification', 'area_no', 'area_name', 'city_no', 'city_name',
+             'city_id', 'city', 'district_id', 'district']]
     # 打印DataFrame的基本信息
-    print(df.info())
+    df.info()
 
     # 将处理后的数据保存为CSV文件
-    df.to_csv(
-        path_or_buf=output_path,
-        index=False,
-        header=[
-            'year_month', 'first_unit', 'second_unit', 'third_unit', 'land_name', 'land_id', 'land_ownership',
-            'use_right_type', 'land_use', 'acquisition_date', 'idle_start_date', 'site_name', 'site_id',
-            'address', 'investor', 'management_level', 'ownership_status', 'usage_status', 'total_land_area',
-            'land_area_self_use', 'land_area_idle', 'land_area_rent', 'land_area_unusable', 'has_land_deed',
-            'no_land_deed_reason', 'land_preservation_risk', 'open_space', 'courtyard', 'unrelated_assets',
-            'assets_num', 'assets_tag_num', 'responsible_department', 'person_in_charge', 'lng_jt', 'lat_jt',
-            'property_owner', 'special_specification', 'area_no', 'area_name', 'city_no', 'city_name', 'city_id',
-            'city', 'district_id', 'district'
-        ],
-        encoding='utf-8-sig'  # 确保中文字符不会乱码
-    )
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -357,9 +383,9 @@ def data_import():
     # 目标表和文件信息
     table = "house.land_month"  # 数据库目标表名
     # 表字段列名,用于指定导入数据的列顺序
-    columns = "year_month,first_unit,second_unit,third_unit,land_name,land_id,land_ownership,use_right_type,land_use,acquisition_date,idle_start_date,site_name,site_id,address,investor,management_level,ownership_status,usage_status,total_land_area,land_area_self_use,land_area_idle,land_area_rent,land_area_unusable,has_land_deed,no_land_deed_reason,land_preservation_risk,open_space,courtyard,unrelated_assets,assets_num,assets_tag_num,responsible_department,person_in_charge,lng_jt,lat_jt,property_owner,special_specification,area_no,area_name,city_no,city_name,city_id,city,district_id,district"
+    columns = "year_month,first_unit,second_unit,third_unit,land_name,inventory_situation,inventory_status,modify,to_be_verified,land_no,land_id,land_ownership,use_right_type,land_use,acquisition_date,idle_start_date,site_name,site_id,address,investor,management_level,ownership_status,usage_status,total_land_area,land_area_self_use,land_area_idle,land_area_rent,land_area_unusable,has_land_deed,no_land_deed_reason,land_preservation_risk,independent_parcel_of_land,open_space,courtyard,has_asset_card,assets_num,assets_tag_num,responsible_department,person_in_charge,lng_jt,lat_jt,property_owner,special_specification,area_no,area_name,city_no,city_name,city_id,city,district_id,district"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 33 - 19
house/house-site/house_site.py

@@ -98,7 +98,18 @@ def data_process():
 
     # 读取 Excel 文件数据
     df = pd.read_excel(io=input_path)
-
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['局址ID', '资产所属单位(一级)', '资产所属单位(二级)', '资产所属单位(三级)', '局址编号',
+                        '局址别名', '标准地址', '城市等级 ', '城市区域 ', '地段', '是否有土地资产']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 删除字符串类型的列中的空白字符
     df = df.map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)
 
@@ -126,20 +137,20 @@ def data_process():
         raise RuntimeError(f'二级组织机构编码匹配失败: {second_unit}')
 
 
-    df['二级组织机构编码'] = df.apply(get_area_no, axis=1)
+    df['area_no'] = df.apply(get_area_no, axis=1)
 
 
     def get_area_name(x):
         """
         根据二级组织机构编码获取二级组织机构名称
         """
-        area_no = x['二级组织机构编码']
+        area_no = x['area_no']
         second_org = org_map[area_no]
         area_name = second_org['name']
         return area_name
 
 
-    df['二级组织机构名称'] = df.apply(get_area_name, axis=1)
+    df['area_name'] = df.apply(get_area_name, axis=1)
 
 
     def get_city_no(x):
@@ -147,8 +158,8 @@ def data_process():
         获取三级组织机构编码
         """
         third_unit = x['资产所属单位(三级)']
-        area_name = x['二级组织机构名称']
-        area_no = x['二级组织机构编码']
+        area_name = x['area_name']
+        area_no = x['area_no']
         if area_name == '石家庄':
             if '矿区' in third_unit:
                 return 'D0130185'
@@ -232,20 +243,20 @@ def data_process():
         return 'HE001'
 
 
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
+    df['city_no'] = df.apply(get_city_no, axis=1)
 
 
     def get_city_name(x):
         """
         根据三级组织机构编码获取三级组织机构名称
         """
-        city_no = x['三级组织机构编码']
+        city_no = x['city_no']
         third_org = org_map[city_no]
         city_name = third_org['name']
         return city_name
 
 
-    df['三级组织机构名称'] = df.apply(get_city_name, axis=1)
+    df['city_name'] = df.apply(get_city_name, axis=1)
 
 
     def get_city_id(x):
@@ -338,16 +349,19 @@ def data_process():
 
     df['district'] = df.apply(get_district, axis=1)
     # 在 DataFrame 中插入 '年月' 列
-    df.insert(0, '年月', year_month)
+    df.insert(0, 'year_month', year_month)
+    df.rename(
+        columns={'局址ID': 'site_id', '资产所属单位(一级)': 'first_unit', '资产所属单位(二级)': 'second_unit',
+                 '资产所属单位(三级)': 'third_unit', '局址编号': 'site_num', '局址别名': 'site_name',
+                 '标准地址': 'address', '城市等级 ': 'city_level', '城市区域 ': 'city_region', '地段': 'area_sector',
+                 '是否有土地资产': 'has_land'}, inplace=True)
+    df = df[['year_month', 'site_id', 'first_unit', 'second_unit', 'third_unit', 'site_num', 'site_name',
+             'address', 'city_level', 'city_region', 'area_sector', 'has_land', 'area_no', 'area_name', 'city_no',
+             'city_name', 'city_id', 'city', 'district_id', 'district']]
     # 打印 DataFrame 的基本信息
-    print(df.info())
+    df.info()
     # 将处理后的数据保存为 CSV 文件
-    df.to_csv(path_or_buf=output_path,
-              index=False,
-              header=['year_month', 'site_id', 'first_unit', 'second_unit', 'third_unit', 'site_num', 'site_name',
-                      'address', 'city_level', 'city_region', 'area_sector', 'has_land', 'area_no', 'area_name', 'city_no',
-                      'city_name', 'city_id', 'city', 'district_id', 'district'],
-              encoding='utf-8-sig')
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -358,7 +372,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,site_id,first_unit,second_unit,third_unit,site_num,site_name,address,city_level,city_region,area_sector,has_land,area_no,area_name,city_no,city_name,city_id,city,district_id,district"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出
@@ -404,4 +418,4 @@ def upload_file():
 
 data_process()
 data_import()
-upload_file()
+# upload_file()

+ 62 - 29
house/house-zu-ru-he-tong/house_zu_ru_he_tong.py

@@ -92,6 +92,25 @@ def data_process():
                 area_map[x['area_id']] = x  # 将区域ID与详细信息存入area_map
     # 读取Excel文件中的数据,并跳过第一行
     df = pd.read_excel(io=input_path, skiprows=1)
+    # 获取当前 DataFrame 的列名列表
+    columns = df.columns.tolist()
+    # 定义所需的字段列表
+    required_columns = ['序号', '数据编码', '租入房屋名称', '房屋所有权人属性', '租入形式', '标准地址(一级)',
+                        '标准地址(二级)', '标准地址(三级)', '街/路/村门牌号', '城市区域', '地段', '地址经度坐标',
+                        '地址纬度坐标', '租入建筑面积(平米)', '租入使用面积(平米)', '投资主体', '使用单位层级',
+                        '使用单位隶属的省级公司', '使用单位隶属的地市级公司', '使用单位隶属的区县级公司', '使用专业线',
+                        '租入实际用途', '租入其他用途说明', '自用建筑面积(平米)', '转租建筑面积(平米)', '首次租用时间',
+                        '合同编号', '合同名称', '合同类型', '签订时间', '我方签约主体', '出租方名称',
+                        '合同总金额(含税)(元)', '增值税金额(元)', '租入开始时间(合同生效时间)',
+                        '租入终止时间(合同终止时间)', '承办部门', '承办人', '联系电话', '累计计提金额(元)',
+                        '费用报账总金额(元)', '合同性质', '合同状态']
+    # 检查是否有缺失的字段
+    missing_columns = [col for col in required_columns if col not in columns]
+    # 检查是否有多余的字段
+    ex_columns = [col for col in columns if col not in required_columns]
+    # 如果存在缺失字段,则抛出运行时错误并提示缺少哪些字段
+    if missing_columns or ex_columns:
+        raise RuntimeError(f"缺少以下字段: {missing_columns};存在以下多余字段:{ex_columns}")
     # 删除指定列中的空白字符
     columns_to_clean = list(filter(lambda x: x not in ('签订时间'), df.columns))  # 排除“签订时间”列
     df[columns_to_clean] = df[columns_to_clean].map(lambda x: re.sub(r'\s+', '', x) if type(x) is str else x)
@@ -110,22 +129,22 @@ def data_process():
                 return area_no
         raise RuntimeError(f'二级组织机构编码匹配失败: {second_unit}')
 
-    df['二级组织机构编码'] = df.apply(get_area_no, axis=1)
+    df['area_no'] = df.apply(get_area_no, axis=1)
 
     def get_area_name(x):
         """根据二级组织机构编码获取二级组织机构名称"""
-        area_no = x['二级组织机构编码']
+        area_no = x['area_no']
         second_org = org_map[area_no]
         area_name = second_org['name']
         return area_name
 
-    df['二级组织机构名称'] = df.apply(get_area_name, axis=1)
+    df['area_name'] = df.apply(get_area_name, axis=1)
 
     def get_city_no(x):
         """根据使用单位隶属的区县级公司名称获取三级组织机构编码"""
         third_unit = x['使用单位隶属的区县级公司']
-        area_name = x['二级组织机构名称']
-        area_no = x['二级组织机构编码']
+        area_name = x['area_name']
+        area_no = x['area_no']
         if area_name == '石家庄':
             if '矿区' in third_unit:
                 return 'D0130185'
@@ -208,16 +227,16 @@ def data_process():
             return 'D0130830'
         return 'HE001'
 
-    df['三级组织机构编码'] = df.apply(get_city_no, axis=1)
+    df['city_no'] = df.apply(get_city_no, axis=1)
 
     def get_city_name(x):
         """根据三级组织机构编码获取三级组织机构名称"""
-        city_no = x['三级组织机构编码']
+        city_no = x['city_no']
         third_org = org_map[city_no]
         city_name = third_org['name']
         return city_name
 
-    df['三级组织机构名称'] = df.apply(get_city_name, axis=1)
+    df['city_name'] = df.apply(get_city_name, axis=1)
 
     def get_rent_months(x):
         """根据租入开始时间和终止时间计算租期月数"""
@@ -231,32 +250,32 @@ def data_process():
         rent_months = delta.years * 12 + delta.months + (1 if delta.days > 0 else 0)
         return rent_months
 
-    df['租期月数'] = df.apply(get_rent_months, axis=1)
+    df['rent_months'] = df.apply(get_rent_months, axis=1)
 
     def get_gross_amount_month(x):
         """根据合同总金额和租期月数计算月含税合同额"""
         gross_amount = x['合同总金额(含税)(元)']
-        rent_months = x['租期月数']
+        rent_months = x['rent_months']
         if pd.notna(gross_amount) and pd.notna(rent_months) and rent_months and rent_months > 0:
             return (decimal.Decimal(gross_amount) / decimal.Decimal(rent_months)).quantize(decimal.Decimal('0.00'))
         return None
 
-    df['月含税合同额'] = df.apply(get_gross_amount_month, axis=1)
+    df['gross_amount_month'] = df.apply(get_gross_amount_month, axis=1)
 
     def get_unit_price(x):
         """根据租入建筑面积和月含税合同额计算每平米单价"""
         building_area = x['租入建筑面积(平米)']
-        gross_amount_month = x['月含税合同额']
+        gross_amount_month = x['gross_amount_month']
         if pd.notna(building_area) and pd.notna(gross_amount_month) and building_area > 0 and gross_amount_month > 0:
             return (decimal.Decimal(gross_amount_month) / decimal.Decimal(building_area)).quantize(
                 decimal.Decimal('0.00'))
         return None
 
-    df['每平米单价'] = df.apply(get_unit_price, axis=1)
+    df['unit_price'] = df.apply(get_unit_price, axis=1)
 
     def get_rent_years(x):
         """根据租期月数计算租期年数"""
-        rent_months = x['租期月数']
+        rent_months = x['rent_months']
         if pd.isna(rent_months) or not rent_months:
             return None
         return (decimal.Decimal(rent_months) / decimal.Decimal('12')).quantize(decimal.Decimal('0.00'))
@@ -290,22 +309,36 @@ def data_process():
 
     df['地址经度坐标'] = df['地址经度坐标'].map(remove_extra_dots)
     df['地址纬度坐标'] = df['地址纬度坐标'].map(remove_extra_dots)
-    df.insert(0, '年月', year_month)  # 在数据框的第一列插入年月字段
+    df.insert(0, 'year_month', year_month)  # 在数据框的第一列插入年月字段
+    df.rename(
+        columns={'序号': 'serial_no', '数据编码': 'data_num', '租入房屋名称': 'house_name', '房屋所有权人属性': 'owner_type',
+                 '租入形式': 'rent_type', '标准地址(一级)': 'first_address', '标准地址(二级)': 'second_address',
+                 '标准地址(三级)': 'third_address', '街/路/村门牌号': 'fourth_address', '城市区域': 'city_region',
+                 '地段': 'area_sector', '地址经度坐标': 'lng', '地址纬度坐标': 'lat', '租入建筑面积(平米)': 'building_area',
+                 '租入使用面积(平米)': 'usable_area', '投资主体': 'investor', '使用单位层级': 'unit_level',
+                 '使用单位隶属的省级公司': 'first_unit', '使用单位隶属的地市级公司': 'second_unit',
+                 '使用单位隶属的区县级公司': 'third_unit', '使用专业线': 'field', '租入实际用途': 'use_type',
+                 '租入其他用途说明': 'use_description', '自用建筑面积(平米)': 'building_area_self_use',
+                 '转租建筑面积(平米)': 'building_area_sublet', '首次租用时间': 'first_rent_date', '合同编号': 'contract_no',
+                 '合同名称': 'contract_name', '合同类型': 'contract_type', '签订时间': 'sign_date', '我方签约主体': 'lessee',
+                 '出租方名称': 'lessor', '合同总金额(含税)(元)': 'gross_amount', '增值税金额(元)': 'vat',
+                 '租入开始时间(合同生效时间)': 'rent_start_date', '租入终止时间(合同终止时间)': 'rent_end_date',
+                 '承办部门': 'undertaking_department', '承办人': 'undertaker', '联系电话': 'phone',
+                 '累计计提金额(元)': 'amount_accrued', '费用报账总金额(元)': 'amount_reimbursement',
+                 '合同性质': 'contract_nature', '合同状态': 'contract_status'}, inplace=True)
+    df = df[['year_month', 'serial_no', 'data_num', 'house_name', 'owner_type', 'rent_type', 'first_address',
+             'second_address', 'third_address', 'fourth_address', 'city_region', 'area_sector', 'lng', 'lat',
+             'building_area', 'usable_area', 'investor', 'unit_level', 'first_unit', 'second_unit',
+             'third_unit', 'field', 'use_type', 'use_description', 'building_area_self_use',
+             'building_area_sublet', 'first_rent_date', 'contract_no', 'contract_name', 'contract_type',
+             'sign_date', 'lessee', 'lessor', 'gross_amount', 'vat', 'rent_start_date', 'rent_end_date',
+             'undertaking_department', 'undertaker', 'phone', 'amount_accrued', 'amount_reimbursement',
+             'contract_nature', 'contract_status', 'area_no', 'area_name', 'city_no', 'city_name',
+             'rent_months', 'gross_amount_month', 'unit_price', 'rent_years', 'unit_price2']]
     # 打印数据框的基本信息
-    print(df.info())
+    df.info()
     # 将处理后的数据保存到CSV文件中
-    df.to_csv(path_or_buf=output_path,
-              index=False,
-              header=['year_month', 'serial_no', 'data_num', 'house_name', 'owner_type', 'rent_type', 'first_address',
-                      'second_address', 'third_address', 'fourth_address', 'city_region', 'area_sector', 'lng', 'lat',
-                      'building_area', 'usable_area', 'investor', 'unit_level', 'first_unit', 'second_unit',
-                      'third_unit', 'field', 'use_type', 'use_description', 'building_area_self_use',
-                      'building_area_sublet', 'first_rent_date', 'contract_no', 'contract_name', 'contract_type',
-                      'sign_date', 'lessee', 'lessor', 'gross_amount', 'vat', 'rent_start_date', 'rent_end_date',
-                      'undertaking_department', 'undertaker', 'phone', 'amount_accrued', 'amount_reimbursement',
-                      'contract_nature', 'contract_status', 'area_no', 'area_name', 'city_no', 'city_name',
-                      'rent_months', 'gross_amount_month', 'unit_price', 'rent_years', 'unit_price2'],
-              encoding='utf-8-sig')
+    df.to_csv(path_or_buf=output_path, index=False, encoding='utf-8-sig', lineterminator='\n')
 
 
 def data_import():
@@ -316,7 +349,7 @@ def data_import():
     # 表字段列名,用于指定导入数据的列顺序
     columns = "year_month,serial_no,data_num,house_name,owner_type,rent_type,first_address,second_address,third_address,fourth_address,city_region,area_sector,lng,lat,building_area,usable_area,investor,unit_level,first_unit,second_unit,third_unit,field,use_type,use_description,building_area_self_use,building_area_sublet,first_rent_date,contract_no,contract_name,contract_type,sign_date,lessee,lessor,gross_amount,vat,rent_start_date,rent_end_date,undertaking_department,undertaker,phone,amount_accrued,amount_reimbursement,contract_nature,contract_status,area_no,area_name,city_no,city_name,rent_months,gross_amount_month,unit_price,rent_years,unit_price2"
     # 构造执行 PowerShell 脚本的命令
-    command = f"powershell -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
+    command = f"powershell -NoProfile -NonInteractive -File {script_path} -db_host {db_host} -db_port {db_port} -db_username {db_username} -db_password {db_password} -dbname {dbname} -table {table} -filename {output_path} -columns {columns}"
     # 打印生成的命令,方便调试和日志记录
     logger.info("command: {}", command)
     # 使用 subprocess 模块运行 PowerShell 命令,并捕获输出

+ 1 - 1
test_token.py

@@ -61,7 +61,7 @@ s = {
     "TIME_STAMP": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),  # 当前时间戳
     "REQUEST_URL": "",  # 请求URL(此处为空字符串)
     "LOGIN_ID": "test",  # 登录ID
-    "EXPIRE_TIME": 3600,  # 过期时间(单位:秒)
+    "EXPIRE_TIME": 36000,  # 过期时间(单位:秒)
 }
 
 # 将字典转换为JSON格式字符串,并调用encrypt函数对其进行加密最后打印加密结果