gen_love_org_sql.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # -*- coding: utf-8 -*-
  2. """把 specs/010-order-invoice/xca.csv(财政部爱心码清单)转成 updatesql/pos_love_org.sql。
  3. CSV 用 CR(\r) 分隔记录、捐赠码含前导零、简称/县市可空、>7位码 ezPay 不支持置 enabled=0。
  4. 重新生成(CSV 更新后)直接重跑本脚本即可。"""
  5. import os
  6. ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  7. src = os.path.join(ROOT, 'specs', '010-order-invoice', 'xca.csv')
  8. out = os.path.join(ROOT, 'updatesql', 'pos_love_org.sql')
  9. with open(src, 'r', encoding='utf-8-sig') as f:
  10. raw = f.read()
  11. raw = raw.replace('\r\n', '\n').replace('\r', '\n')
  12. lines = [l for l in raw.split('\n') if l.strip()]
  13. def sq(s):
  14. s = (s or '').strip()
  15. if s == '':
  16. return 'NULL'
  17. s = s.replace('\\', '\\\\').replace("'", "''")
  18. return "'" + s + "'"
  19. rows = []
  20. seen = set()
  21. dups = 0
  22. over7 = 0
  23. bad = 0
  24. bad_samples = []
  25. for line in lines[1:]:
  26. parts = line.split(',')
  27. if len(parts) != 6:
  28. bad += 1
  29. if len(bad_samples) < 5:
  30. bad_samples.append(line[:100])
  31. continue
  32. seq, name, love, short, ubn, city = parts
  33. love = love.strip()
  34. if not love or not love.isdigit():
  35. bad += 1
  36. if len(bad_samples) < 5:
  37. bad_samples.append(line[:100])
  38. continue
  39. if love in seen:
  40. dups += 1
  41. continue
  42. seen.add(love)
  43. enabled = 0 if len(love) > 7 else 1
  44. if enabled == 0:
  45. over7 += 1
  46. rows.append((love, name.strip(), short.strip(), ubn.strip(), city.strip(), enabled))
  47. with open(out, 'w', encoding='utf-8', newline='\n') as f:
  48. f.write("-- ============================================================\n")
  49. f.write("-- 捐赠机构字典 pos_love_org (财政部电子发票爱心码清单)\n")
  50. f.write("-- 来源: 财政部电子发票整合服务平台 https://www.einvoice.nat.gov.tw/portal/btc/btc603w\n")
  51. f.write("-- 源 CSV: specs/010-order-invoice/xca.csv (由 gen_love_org_sql.py 生成)\n")
  52. f.write("-- 说明: love_code 含前导零以 VARCHAR 存储; >7 位码 ezPay 不支持, enabled=0\n")
  53. f.write("-- 用法: 直接在 MySQL 执行(DROP+CREATE+INSERT 全量刷新, 可重复执行)\n")
  54. f.write("-- ============================================================\n\n")
  55. f.write("DROP TABLE IF EXISTS `pos_love_org`;\n")
  56. f.write("CREATE TABLE `pos_love_org` (\n")
  57. f.write(" `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',\n")
  58. f.write(" `love_code` VARCHAR(10) NOT NULL COMMENT '捐赠码(爱心码,保留前导零)',\n")
  59. f.write(" `org_name` VARCHAR(255) NOT NULL COMMENT '受捐赠机关或团体名称',\n")
  60. f.write(" `org_short_name` VARCHAR(64) DEFAULT NULL COMMENT '机构简称(可空)',\n")
  61. f.write(" `ubn` VARCHAR(16) DEFAULT NULL COMMENT '统编(保留前导零)',\n")
  62. f.write(" `city` VARCHAR(32) DEFAULT NULL COMMENT '县市(可空)',\n")
  63. f.write(" `enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:1启用 0停用(>7位码ezPay不支持)',\n")
  64. f.write(" `sync_time` DATETIME DEFAULT NULL COMMENT '财政部清单同步时间',\n")
  65. f.write(" `create_time` DATETIME DEFAULT NULL COMMENT '创建时间',\n")
  66. f.write(" PRIMARY KEY (`id`),\n")
  67. f.write(" UNIQUE KEY `uk_love_code` (`love_code`)\n")
  68. f.write(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='捐赠机构字典(财政部电子发票爱心码清单)';\n\n")
  69. cols = "(`love_code`,`org_name`,`org_short_name`,`ubn`,`city`,`enabled`,`sync_time`,`create_time`)"
  70. BATCH = 100
  71. for i in range(0, len(rows), BATCH):
  72. chunk = rows[i:i + BATCH]
  73. vals = []
  74. for love, name, short, ubn, city, enabled in chunk:
  75. vals.append(f"({sq(love)},{sq(name)},{sq(short)},{sq(ubn)},{sq(city)},{enabled},NOW(),NOW())")
  76. f.write("INSERT INTO `pos_love_org` " + cols + " VALUES\n")
  77. f.write(",\n".join(vals))
  78. f.write(";\n\n")
  79. print(f"imported={len(rows)} dups_skipped={dups} over7_disabled={over7} bad={bad}")
  80. for s in bad_samples:
  81. print("BAD:", s)
  82. print(f"output: {out}")