f
This commit is contained in:
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"tyapi-server/internal/application/api/commands"
|
||||
"tyapi-server/internal/config"
|
||||
appconfig "tyapi-server/internal/config"
|
||||
api_repositories "tyapi-server/internal/domains/api/repositories"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/domains/api/services/processors/comb"
|
||||
@@ -50,7 +50,7 @@ type ApiRequestService struct {
|
||||
validator interfaces.RequestValidator
|
||||
processorDeps *processors.ProcessorDependencies
|
||||
combService *comb.CombService
|
||||
config *config.Config
|
||||
config *appconfig.Config
|
||||
|
||||
reportRepo api_repositories.ReportRepository
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func NewApiRequestService(
|
||||
shumaiService *shumai.ShumaiService,
|
||||
validator interfaces.RequestValidator,
|
||||
productManagementService *services.ProductManagementService,
|
||||
cfg *config.Config,
|
||||
cfg *appconfig.Config,
|
||||
) *ApiRequestService {
|
||||
return NewApiRequestServiceWithRepos(
|
||||
westDexService,
|
||||
@@ -85,6 +85,7 @@ func NewApiRequestService(
|
||||
productManagementService,
|
||||
cfg,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -102,12 +103,18 @@ func NewApiRequestServiceWithRepos(
|
||||
shumaiService *shumai.ShumaiService,
|
||||
validator interfaces.RequestValidator,
|
||||
productManagementService *services.ProductManagementService,
|
||||
cfg *config.Config,
|
||||
cfg *appconfig.Config,
|
||||
reportRepo api_repositories.ReportRepository,
|
||||
qyglReportPDFScheduler processors.QYGLReportPDFScheduler,
|
||||
) *ApiRequestService {
|
||||
// 创建组合包服务
|
||||
combService := comb.NewCombService(productManagementService)
|
||||
|
||||
apiPublicBase := ""
|
||||
if cfg != nil {
|
||||
apiPublicBase = appconfig.ResolveAPIPublicBaseURL(&cfg.API)
|
||||
}
|
||||
|
||||
// 创建处理器依赖容器
|
||||
processorDeps := processors.NewProcessorDependencies(
|
||||
westDexService,
|
||||
@@ -123,6 +130,8 @@ func NewApiRequestServiceWithRepos(
|
||||
validator,
|
||||
combService,
|
||||
reportRepo,
|
||||
qyglReportPDFScheduler,
|
||||
apiPublicBase,
|
||||
)
|
||||
|
||||
// 统一注册所有处理器
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"tyapi-server/internal/infrastructure/external/alicloud"
|
||||
"tyapi-server/internal/infrastructure/external/jiguang"
|
||||
"tyapi-server/internal/infrastructure/external/muzi"
|
||||
"tyapi-server/internal/infrastructure/external/shujubao"
|
||||
"tyapi-server/internal/infrastructure/external/shumai"
|
||||
"tyapi-server/internal/infrastructure/external/tianyancha"
|
||||
"tyapi-server/internal/infrastructure/external/westdex"
|
||||
"tyapi-server/internal/infrastructure/external/shujubao"
|
||||
"tyapi-server/internal/infrastructure/external/xingwei"
|
||||
"tyapi-server/internal/infrastructure/external/yushan"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
@@ -47,6 +47,12 @@ type ProcessorDependencies struct {
|
||||
|
||||
// 企业报告记录仓储,用于持久化 QYGLJ1U9 生成的企业报告
|
||||
ReportRepo repositories.ReportRepository
|
||||
|
||||
// 企业报告 PDF 异步预生成(可为 nil)
|
||||
ReportPDFScheduler QYGLReportPDFScheduler
|
||||
|
||||
// APIPublicBaseURL 对外 API 根地址(无尾斜杠),用于 QYGL reportUrl 等
|
||||
APIPublicBaseURL string
|
||||
}
|
||||
|
||||
// NewProcessorDependencies 创建处理器依赖容器
|
||||
@@ -64,23 +70,27 @@ func NewProcessorDependencies(
|
||||
validator interfaces.RequestValidator,
|
||||
combService CombServiceInterface, // Changed to interface
|
||||
reportRepo repositories.ReportRepository,
|
||||
reportPDFScheduler QYGLReportPDFScheduler,
|
||||
apiPublicBaseURL string,
|
||||
) *ProcessorDependencies {
|
||||
return &ProcessorDependencies{
|
||||
WestDexService: westDexService,
|
||||
ShujubaoService: shujubaoService,
|
||||
MuziService: muziService,
|
||||
YushanService: yushanService,
|
||||
TianYanChaService: tianYanChaService,
|
||||
AlicloudService: alicloudService,
|
||||
ZhichaService: zhichaService,
|
||||
XingweiService: xingweiService,
|
||||
JiguangService: jiguangService,
|
||||
ShumaiService: shumaiService,
|
||||
Validator: validator,
|
||||
CombService: combService,
|
||||
Options: nil, // 初始化为nil,在调用时设置
|
||||
CallContext: nil, // 初始化为nil,在调用时设置
|
||||
ReportRepo: reportRepo,
|
||||
WestDexService: westDexService,
|
||||
ShujubaoService: shujubaoService,
|
||||
MuziService: muziService,
|
||||
YushanService: yushanService,
|
||||
TianYanChaService: tianYanChaService,
|
||||
AlicloudService: alicloudService,
|
||||
ZhichaService: zhichaService,
|
||||
XingweiService: xingweiService,
|
||||
JiguangService: jiguangService,
|
||||
ShumaiService: shumaiService,
|
||||
Validator: validator,
|
||||
CombService: combService,
|
||||
Options: nil, // 初始化为nil,在调用时设置
|
||||
CallContext: nil, // 初始化为nil,在调用时设置
|
||||
ReportRepo: reportRepo,
|
||||
ReportPDFScheduler: reportPDFScheduler,
|
||||
APIPublicBaseURL: apiPublicBaseURL,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -17,7 +18,8 @@ import (
|
||||
)
|
||||
|
||||
// ProcessQYGLJ1U9Request 企业全景报告处理器:并发调用企业全量(QYGLUY3S)、股权全景(QYGLJ0Q1)、司法涉诉(QYGL5S1I),
|
||||
// 然后复用 qyglj1u9_processor_build.go 中的 buildReport / map* 逻辑生成企业报告结构
|
||||
// 以及企业年报(QYGLDJ12)、税收违法(QYGL8848)、欠税公告(QYGL7D9A);
|
||||
// 前三者走 buildReport / map*;后三者在 buildReport 中转为 annualReports、taxViolations、ownTaxNotices 供页面展示。
|
||||
func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
// 复用 QYGLUY3S 的入参结构:企业名称/注册号/统一社会信用代码
|
||||
var p dto.QYGLJ1U9Req
|
||||
@@ -34,7 +36,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
data map[string]interface{}
|
||||
err error
|
||||
}
|
||||
resultsCh := make(chan apiResult, 3)
|
||||
resultsCh := make(chan apiResult, 6)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
call := func(key string, req interface{}, fn func(context.Context, []byte, *processors.ProcessorDependencies) ([]byte, error)) {
|
||||
@@ -52,8 +54,15 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
return
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if err := json.Unmarshal(resp, &m); err != nil {
|
||||
resultsCh <- apiResult{key: key, err: err}
|
||||
var uerr error
|
||||
// 根节点可能是数组或非对象,与欠税接口一致用宽松解析
|
||||
if key == "taxArrears" || key == "annualReport" || key == "taxViolation" {
|
||||
m, uerr = unmarshalToReportMap(resp)
|
||||
} else {
|
||||
uerr = json.Unmarshal(resp, &m)
|
||||
}
|
||||
if uerr != nil {
|
||||
resultsCh <- apiResult{key: key, err: uerr}
|
||||
return
|
||||
}
|
||||
resultsCh <- apiResult{key: key, data: m}
|
||||
@@ -62,8 +71,8 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
|
||||
// 企业全量信息核验V2(QYGLUY3S)
|
||||
call("jiguangFull", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGLUY3SRequest)
|
||||
|
||||
// 企业股权结构全景(QYGLJ0Q1)
|
||||
@@ -77,10 +86,30 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGL5S1IRequest)
|
||||
|
||||
// 企业年报信息核验(QYGLDJ12)
|
||||
call("annualReport", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGLDJ12Request)
|
||||
|
||||
// 企业税收违法核查(QYGL8848)
|
||||
call("taxViolation", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGL8848Request)
|
||||
|
||||
// 欠税公告(QYGL7D9A,天眼查 OwnTax,keyword 为统一社会信用代码)
|
||||
call("taxArrears", map[string]interface{}{
|
||||
"ent_code": p.EntCode,
|
||||
"page_size": 20,
|
||||
"page_num": 1,
|
||||
}, ProcessQYGL7D9ARequest)
|
||||
|
||||
wg.Wait()
|
||||
close(resultsCh)
|
||||
|
||||
var jiguang, judicial, equity map[string]interface{}
|
||||
var annualReport, taxViolation, taxArrears map[string]interface{}
|
||||
for r := range resultsCh {
|
||||
if r.err != nil {
|
||||
// 任一关键数据源异常,则返回系统错误(也可以根据需求做降级)
|
||||
@@ -93,6 +122,12 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
judicial = r.data
|
||||
case "equityPanorama":
|
||||
equity = r.data
|
||||
case "annualReport":
|
||||
annualReport = r.data
|
||||
case "taxViolation":
|
||||
taxViolation = r.data
|
||||
case "taxArrears":
|
||||
taxArrears = r.data
|
||||
}
|
||||
}
|
||||
if jiguang == nil {
|
||||
@@ -104,14 +139,28 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
if equity == nil {
|
||||
equity = map[string]interface{}{}
|
||||
}
|
||||
if annualReport == nil {
|
||||
annualReport = map[string]interface{}{}
|
||||
}
|
||||
if taxViolation == nil {
|
||||
taxViolation = map[string]interface{}{}
|
||||
}
|
||||
if taxArrears == nil {
|
||||
taxArrears = map[string]interface{}{}
|
||||
}
|
||||
|
||||
// 复用构建逻辑生成企业报告结构
|
||||
report := buildReport(jiguang, judicial, equity)
|
||||
// 复用构建逻辑生成企业报告结构(含年报 / 税收违法 / 欠税公告的转化结果)
|
||||
report := buildReport(jiguang, judicial, equity, annualReport, taxViolation, taxArrears)
|
||||
|
||||
// 为报告生成唯一编号并缓存,供后续通过编号查看
|
||||
reportID := saveQYGLReport(report)
|
||||
report["reportId"] = reportID
|
||||
|
||||
// 异步预生成 PDF(写入磁盘缓存),用户点击「保存为 PDF」时可直读缓存
|
||||
if deps.ReportPDFScheduler != nil {
|
||||
deps.ReportPDFScheduler.ScheduleQYGLReportPDF(context.Background(), reportID)
|
||||
}
|
||||
|
||||
// 持久化企业报告记录到数据库(忽略持久化失败,不影响接口主流程)
|
||||
if deps.ReportRepo != nil {
|
||||
reqJSON, _ := json.Marshal(p)
|
||||
@@ -127,7 +176,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
})
|
||||
}
|
||||
// 为报告补充前端查看链接,供调用方直接跳转到企业报告页面(通过编号访问)
|
||||
report["reportUrl"] = buildQYGLReportURLByID(reportID)
|
||||
report["reportUrl"] = buildQYGLReportURLByID(deps.APIPublicBaseURL, reportID)
|
||||
|
||||
out, err := json.Marshal(report)
|
||||
if err != nil {
|
||||
@@ -136,6 +185,18 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// unmarshalToReportMap 将 JSON 解析为报告用 map;根节点非对象时包在 data 下(兼容欠税等接口根为数组的情况)。
|
||||
func unmarshalToReportMap(b []byte) (map[string]interface{}, error) {
|
||||
var raw interface{}
|
||||
if err := json.Unmarshal(b, &raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m, ok := raw.(map[string]interface{}); ok {
|
||||
return m, nil
|
||||
}
|
||||
return map[string]interface{}{"data": raw}, nil
|
||||
}
|
||||
|
||||
// 内存中的企业报告缓存(简单实现,进程重启后清空)
|
||||
var qyglReportStore = struct {
|
||||
sync.RWMutex
|
||||
@@ -171,8 +232,12 @@ func generateQYGLReportID() string {
|
||||
return fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// buildQYGLReportURLByID 构造企业报告前端查看链接(通过编号查看)
|
||||
func buildQYGLReportURLByID(id string) string {
|
||||
return "https://api.tianyuanapi.com/reports/qygl/" + url.PathEscape(id)
|
||||
// buildQYGLReportURLByID 构造企业报告前端查看链接(通过编号查看)。
|
||||
// publicBase 为对外 API 基址(如 https://api.example.com),空则返回站内相对路径。
|
||||
func buildQYGLReportURLByID(publicBase, id string) string {
|
||||
path := "/reports/qygl/" + url.PathEscape(id)
|
||||
if publicBase == "" {
|
||||
return path
|
||||
}
|
||||
return strings.TrimRight(publicBase, "/") + path
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,17 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func buildReport(jiguang, judicial, equity map[string]interface{}) map[string]interface{} {
|
||||
func buildReport(jiguang, judicial, equity, annualRaw, taxViolationRaw, taxArrearsRaw map[string]interface{}) map[string]interface{} {
|
||||
report := make(map[string]interface{})
|
||||
report["reportTime"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
|
||||
// 先转化年报接口数据;若有内容则以 QYGLDJ12 为准,不再使用全量 V2 中 YEARREPORT* 表(避免与「企业年报」板块重复)
|
||||
annualReports := mapAnnualReports(annualRaw)
|
||||
jgNoYearReport := jiguang
|
||||
if len(annualReports) > 0 {
|
||||
jgNoYearReport = jiguangWithoutYearReportTables(jiguang)
|
||||
}
|
||||
|
||||
basic := mapFromBASIC(jiguang)
|
||||
report["creditCode"] = str(basic["creditCode"])
|
||||
report["entName"] = str(basic["entName"])
|
||||
@@ -20,21 +27,22 @@ func buildReport(jiguang, judicial, equity map[string]interface{}) map[string]in
|
||||
report["branches"] = mapBranches(jiguang)
|
||||
// 股权/实控人/受益人/对外投资:有股权全景时以其为准,否则用全量信息
|
||||
if len(equity) > 0 {
|
||||
report["shareholding"] = mapShareholdingWithEquity(jiguang, equity)
|
||||
report["shareholding"] = mapShareholdingWithEquity(jgNoYearReport, equity)
|
||||
report["controller"] = mapControllerFromEquity(equity)
|
||||
report["beneficiaries"] = mapBeneficiariesFromEquity(equity)
|
||||
report["investments"] = mapInvestmentsWithEquity(jiguang, equity)
|
||||
} else {
|
||||
report["shareholding"] = mapShareholding(jiguang)
|
||||
report["shareholding"] = mapShareholding(jgNoYearReport)
|
||||
report["controller"] = mapController(jiguang)
|
||||
report["beneficiaries"] = mapBeneficiaries()
|
||||
report["investments"] = mapInvestments(jiguang)
|
||||
}
|
||||
report["guarantees"] = mapGuarantees(jiguang)
|
||||
report["management"] = mapManagement(jiguang)
|
||||
report["assets"] = mapAssets(jiguang)
|
||||
// 以下块在全量 V2 中依赖年报类表;接入 DJ12 后改从 jgNoYearReport 读取(已剔除 YEARREPORT*)
|
||||
report["guarantees"] = mapGuarantees(jgNoYearReport)
|
||||
report["management"] = mapManagement(jgNoYearReport)
|
||||
report["assets"] = mapAssets(jgNoYearReport)
|
||||
report["licenses"] = mapLicenses(jiguang)
|
||||
report["activities"] = mapActivities(jiguang)
|
||||
report["activities"] = mapActivities(jgNoYearReport)
|
||||
report["inspections"] = mapInspections(jiguang)
|
||||
risks := mapRisks(jiguang, judicial)
|
||||
report["risks"] = risks
|
||||
@@ -45,9 +53,215 @@ func buildReport(jiguang, judicial, equity map[string]interface{}) map[string]in
|
||||
if bl, _ := jiguang["BASICLIST"].([]interface{}); len(bl) > 0 {
|
||||
report["basicList"] = bl
|
||||
}
|
||||
|
||||
// QYGLDJ12 企业年报 / QYGL8848 税收违法 / QYGL7D9A 欠税公告(转化后的前端友好结构)
|
||||
report["annualReports"] = annualReports
|
||||
report["taxViolations"] = mapTaxViolations(taxViolationRaw)
|
||||
report["ownTaxNotices"] = mapOwnTaxNotices(taxArrearsRaw)
|
||||
return report
|
||||
}
|
||||
|
||||
// jiguangWithoutYearReportTables 浅拷贝全量 map,并去掉企业全量 V2 中与「公示年报」对应的 YEARREPORT* 键。
|
||||
// 在已接入 QYGLDJ12 且年报列表非空时使用,避免 build 与 HTML 中与「十六、企业年报」重复展示。
|
||||
func jiguangWithoutYearReportTables(jiguang map[string]interface{}) map[string]interface{} {
|
||||
if len(jiguang) == 0 {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
strip := map[string]struct{}{
|
||||
"YEARREPORTFORGUARANTEE": {},
|
||||
"YEARREPORTPAIDUPCAPITAL": {},
|
||||
"YEARREPORTSUBCAPITAL": {},
|
||||
"YEARREPORTBASIC": {},
|
||||
"YEARREPORTSOCSEC": {},
|
||||
"YEARREPORTANASSETSINFO": {},
|
||||
"YEARREPORTWEBSITEINFO": {},
|
||||
}
|
||||
out := make(map[string]interface{}, len(jiguang))
|
||||
for k, v := range jiguang {
|
||||
if _, drop := strip[k]; drop {
|
||||
continue
|
||||
}
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// BuildReportFromRawSources 供开发/测试:将各处理器原始 JSON(与 QYGLJ1U9 并发结果形态一致)走与线上一致的 buildReport 转化。
|
||||
// 任一路传入 nil 时按空 map 处理。
|
||||
func BuildReportFromRawSources(jiguang, judicial, equity, annualRaw, taxViolationRaw, taxArrearsRaw map[string]interface{}) map[string]interface{} {
|
||||
if jiguang == nil {
|
||||
jiguang = map[string]interface{}{}
|
||||
}
|
||||
if judicial == nil {
|
||||
judicial = map[string]interface{}{}
|
||||
}
|
||||
if equity == nil {
|
||||
equity = map[string]interface{}{}
|
||||
}
|
||||
if annualRaw == nil {
|
||||
annualRaw = map[string]interface{}{}
|
||||
}
|
||||
if taxViolationRaw == nil {
|
||||
taxViolationRaw = map[string]interface{}{}
|
||||
}
|
||||
if taxArrearsRaw == nil {
|
||||
taxArrearsRaw = map[string]interface{}{}
|
||||
}
|
||||
return buildReport(jiguang, judicial, equity, annualRaw, taxViolationRaw, taxArrearsRaw)
|
||||
}
|
||||
|
||||
// extractJSONArrayFromEnterpriseAPI 从数据宝/天眼查类响应中提取数组主体(data/list/result 等)。
|
||||
func extractJSONArrayFromEnterpriseAPI(m map[string]interface{}) []interface{} {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
priority := []string{"data", "list", "result", "records", "items", "body"}
|
||||
for _, k := range priority {
|
||||
if arr := sliceOrEmpty(m[k]); len(arr) > 0 {
|
||||
return arr
|
||||
}
|
||||
}
|
||||
if len(m) == 1 {
|
||||
for _, v := range m {
|
||||
if arr, ok := v.([]interface{}); ok {
|
||||
return arr
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func intFromAny(v interface{}) int {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
switch x := v.(type) {
|
||||
case float64:
|
||||
return int(x)
|
||||
case int:
|
||||
return x
|
||||
case int64:
|
||||
return int(x)
|
||||
default:
|
||||
s := strings.TrimSpace(str(x))
|
||||
if s == "" {
|
||||
return 0
|
||||
}
|
||||
if n, err := strconv.Atoi(s); err == nil {
|
||||
return n
|
||||
}
|
||||
if f, err := strconv.ParseFloat(s, 64); err == nil {
|
||||
return int(f)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// mapOwnTaxNotices QYGL7D9A 欠税公告 → { total, items }
|
||||
func mapOwnTaxNotices(raw map[string]interface{}) map[string]interface{} {
|
||||
out := map[string]interface{}{
|
||||
"total": 0,
|
||||
"items": []interface{}{},
|
||||
}
|
||||
if raw == nil {
|
||||
return out
|
||||
}
|
||||
items := sliceOrEmpty(raw["items"])
|
||||
total := intFromAny(raw["total"])
|
||||
if total == 0 {
|
||||
total = len(items)
|
||||
}
|
||||
mapped := make([]interface{}, 0, len(items))
|
||||
for _, it := range items {
|
||||
row, _ := it.(map[string]interface{})
|
||||
if row == nil {
|
||||
continue
|
||||
}
|
||||
mapped = append(mapped, map[string]interface{}{
|
||||
"taxIdNumber": str(row["taxIdNumber"]),
|
||||
"taxpayerName": str(row["name"]),
|
||||
"taxCategory": str(row["taxCategory"]),
|
||||
"ownTaxBalance": str(row["ownTaxBalance"]),
|
||||
"ownTaxAmount": str(row["ownTaxAmount"]),
|
||||
"newOwnTaxBalance": str(row["newOwnTaxBalance"]),
|
||||
"taxType": str(row["type"]),
|
||||
"publishDate": str(row["publishDate"]),
|
||||
"department": str(row["department"]),
|
||||
"location": str(row["location"]),
|
||||
"legalPersonName": str(row["legalpersonName"]),
|
||||
"personIdNumber": str(row["personIdNumber"]),
|
||||
"personIdName": str(row["personIdName"]),
|
||||
"taxpayerType": str(row["taxpayerType"]),
|
||||
"regType": str(row["regType"]),
|
||||
})
|
||||
}
|
||||
out["total"] = total
|
||||
out["items"] = mapped
|
||||
return out
|
||||
}
|
||||
|
||||
// mapTaxViolations QYGL8848 税收违法 → { total, items }(字段驼峰化)
|
||||
func mapTaxViolations(raw map[string]interface{}) map[string]interface{} {
|
||||
out := map[string]interface{}{
|
||||
"total": 0,
|
||||
"items": []interface{}{},
|
||||
}
|
||||
if raw == nil {
|
||||
return out
|
||||
}
|
||||
items := sliceOrEmpty(raw["items"])
|
||||
total := intFromAny(raw["total"])
|
||||
if total == 0 {
|
||||
total = len(items)
|
||||
}
|
||||
mapped := make([]interface{}, 0, len(items))
|
||||
for _, it := range items {
|
||||
row, _ := it.(map[string]interface{})
|
||||
if row == nil {
|
||||
continue
|
||||
}
|
||||
cm := convertReportKeysToCamel(row, true)
|
||||
if mm, ok := cm.(map[string]interface{}); ok {
|
||||
mapped = append(mapped, mm)
|
||||
}
|
||||
}
|
||||
out["total"] = total
|
||||
out["items"] = mapped
|
||||
return out
|
||||
}
|
||||
|
||||
// mapAnnualReports QYGLDJ12 企业年报列表 → []年报对象(键名驼峰化,按 reportYear 降序)
|
||||
func mapAnnualReports(raw map[string]interface{}) []interface{} {
|
||||
rows := extractJSONArrayFromEnterpriseAPI(raw)
|
||||
if len(rows) == 0 {
|
||||
return []interface{}{}
|
||||
}
|
||||
out := make([]interface{}, 0, len(rows))
|
||||
for _, r := range rows {
|
||||
m, ok := r.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if v, ok := m["rpport_change_info"]; ok {
|
||||
if _, has := m["report_change_info"]; !has {
|
||||
m["report_change_info"] = v
|
||||
}
|
||||
}
|
||||
cm := convertReportKeysToCamel(m, true)
|
||||
mm, ok := cm.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
out = append(out, mm)
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
ai, _ := out[i].(map[string]interface{})
|
||||
bj, _ := out[j].(map[string]interface{})
|
||||
return intFromAny(ai["reportYear"]) > intFromAny(bj["reportYear"])
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
func mapFromBASIC(jiguang map[string]interface{}) map[string]interface{} {
|
||||
basic := make(map[string]interface{})
|
||||
b, _ := jiguang["BASIC"].(map[string]interface{})
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package processors
|
||||
|
||||
import "context"
|
||||
|
||||
// QYGLReportPDFScheduler 企业全景报告 PDF 异步预生成调度器(可为 nil 表示禁用)
|
||||
type QYGLReportPDFScheduler interface {
|
||||
// ScheduleQYGLReportPDF 在报告数据就绪后异步生成 PDF 并写入缓存
|
||||
ScheduleQYGLReportPDF(ctx context.Context, reportID string)
|
||||
}
|
||||
Reference in New Issue
Block a user