diff --git a/.idea/urban-investment-research.iml b/.idea/urban-investment-research.iml index e24c4b8..41634b9 100644 --- a/.idea/urban-investment-research.iml +++ b/.idea/urban-investment-research.iml @@ -16,6 +16,7 @@ diff --git a/Config/common.ini b/Config/common.ini index dcaff6b..dd75e83 100644 --- a/Config/common.ini +++ b/Config/common.ini @@ -35,3 +35,5 @@ status_call_back = "" [app] port = 8003 +[tianyancha] +token = "" \ No newline at end of file diff --git a/Context/common.py b/Context/common.py index a856bde..e0aea4e 100644 --- a/Context/common.py +++ b/Context/common.py @@ -3,6 +3,7 @@ from logging import getLogger from sqlalchemy.orm import declarative_base +from ThirdPartyApi.Tianyancha.Apis import TianyanchaApi from Utils.AuthUtils import AuthUtil, TokenDataModel from Utils.MongoUtils import MongoConnect from Utils.RedisUtils import RedisPool @@ -50,3 +51,6 @@ phone_msg_send = PhoneMsgSend(conf['hw_msg']['url'], ) phone_verify_code = PhoneVerifyCode(redis_pool, phone_msg_send) + +# 天眼查接口 +tianyancha_api = TianyanchaApi(conf['tianyancha']['token']) diff --git a/Mods/BasicInformation/Crud.py b/Mods/BasicInformation/Crud.py index c1d505f..d090b82 100644 --- a/Mods/BasicInformation/Crud.py +++ b/Mods/BasicInformation/Crud.py @@ -1,10 +1,14 @@ +from fastapi import HTTPException from sqlalchemy.orm import Session from .Mods.CompanyIndexMain.Models import CompanyIndexMain from .Mods.CompanyBaseInfo.Models import CompanyBaseInfo from .Mods.CompanyPlusProperty.Models import CompanyPlusProperty from .Mods.CompanyControl.Models import CompanyControl +from .Mods.CompanyShareholder.Models import CompanyShareholder from . import Schemas from Utils.SqlAlchemyUtils import query_common_core +from Context.common import tianyancha_api +from ..RegionalEconomies.Mods.AreaIndexMain.Models import AreaIndexMain def company_all_info_query(db: Session, query_params: Schemas.CompanyAllInfoQueryParams): @@ -35,3 +39,44 @@ def company_all_info_query(db: Session, query_params: Schemas.CompanyAllInfoQuer company_info_dict[item.company_id][key] = item.to_dict() items = list(company_info_dict.values()) return count, items + + +def create_company(db: Session, req: Schemas.CreateCompanyReq): + company_name = req.company_name + if db.query(CompanyIndexMain).filter(CompanyIndexMain.company_name == company_name).first(): + raise HTTPException(detail="公司名称已经存在", status_code=403) + res = tianyancha_api.企业基本信息(company_name) + company_index_main = CompanyIndexMain(company_id=res.id, company_name=res.name) + db.add(company_index_main) + if not db.query(CompanyBaseInfo).filter(CompanyBaseInfo.company_id == res.id).first(): + company_base_info = CompanyBaseInfo(company_id=res.id, + legal_person=res.legalPersonName, + reg_capital=res.regCapital, + # paid_capital + estiblish_date=res.estiblishTime, + approved_date=res.approvedTime, + # license_duration + reg_status=res.regStatus, + reg_location=res.regLocation, + credit_code=res.creditCode, + social_staff_num=res.socialStaffNum, + business_scope=res.businessScope + ) + db.add(company_base_info) + # company_control=CompanyControl(company_id=res.id,name=res.legalPersonName) + if not db.query(CompanyPlusProperty).filter(CompanyPlusProperty.company_id == res.id).first(): + city_item = db.query(AreaIndexMain).filter(name=res.city).first() + area_item = db.query(AreaIndexMain).filter(name=res.district).first() + company_plus_property = CompanyPlusProperty(company_id=res.id, + # administrative_level + # background + # equity_relationship + # importance + industry=res.industry, + province=city_item.belong if city_item else None, + city=city_item.area_id if city_item else None, + area=area_item.area_id if area_item else None + ) + db.add(company_plus_property) + # company_share_holder = CompanyShareholder() + db.commit() diff --git a/Mods/BasicInformation/Mods/CompanyBaseInfo/Models.py b/Mods/BasicInformation/Mods/CompanyBaseInfo/Models.py index 50aed28..841344b 100644 --- a/Mods/BasicInformation/Mods/CompanyBaseInfo/Models.py +++ b/Mods/BasicInformation/Mods/CompanyBaseInfo/Models.py @@ -11,7 +11,7 @@ class CompanyBaseInfo(common_db.Base): legal_person = Column(String(50), comment="法定代表人") reg_capital = Column(String(50), comment="注册资本") paid_capital = Column(String(50), comment="实缴资本") - establish_date = Column(Date, comment="成立日期") + estiblish_date = Column(Date, comment="成立日期") approved_date = Column(Date, comment="核准日期") license_duration = Column(String(50), comment="营业期限") reg_status = Column(String(50), comment="经营状态") diff --git a/Mods/BasicInformation/Mods/CompanyBaseInfo/Schemas.py b/Mods/BasicInformation/Mods/CompanyBaseInfo/Schemas.py index 224b49f..3476d83 100644 --- a/Mods/BasicInformation/Mods/CompanyBaseInfo/Schemas.py +++ b/Mods/BasicInformation/Mods/CompanyBaseInfo/Schemas.py @@ -9,7 +9,7 @@ class CompanyBaseInfoInfo(BaseModel): legal_person: Optional[str] reg_capital: Optional[str] paid_capital: Optional[str] - establish_date: Optional[date] + estiblish_date: Optional[date] approved_date: Optional[date] license_duration: Optional[str] reg_status: Optional[str] @@ -24,7 +24,7 @@ class CompanyBaseInfoAddInfo(BaseModel): legal_person: Optional[str] reg_capital: Optional[str] paid_capital: Optional[str] - establish_date: Optional[date] + estiblish_date: Optional[date] approved_date: Optional[date] license_duration: Optional[str] reg_status: Optional[str] diff --git a/Mods/BasicInformation/Mods/CompanyShareholder/Models.py b/Mods/BasicInformation/Mods/CompanyShareholder/Models.py index 1e2195a..202a51e 100644 --- a/Mods/BasicInformation/Mods/CompanyShareholder/Models.py +++ b/Mods/BasicInformation/Mods/CompanyShareholder/Models.py @@ -9,11 +9,14 @@ class CompanyShareholder(common_db.Base): __tablename__ = "company_shareholder" id = Column(Integer, primary_key=True, comment="股东信息id") company_id = Column(Integer, comment="企业ID") - name = Column(String(255), comment="平台重要性") - type = Column(String(50), comment="平台重要性") + name = Column(String(255), comment="股东名称") + type = Column(String(50), comment="股东类型") amount = Column(Double, comment="认缴金额") reg_date = Column(Date, comment="认缴时间") percent = Column(Double, comment="持股比例") + number = Column(Double, comment="持股数量") + shareholder_code = Column(Integer, comment="股东代码") + def to_dict(self): data = {c.name: getattr(self, c.name) for c in self.__table__.columns} - return data \ No newline at end of file + return data diff --git a/Mods/BasicInformation/Mods/CompanyShareholder/Schemas.py b/Mods/BasicInformation/Mods/CompanyShareholder/Schemas.py index bb92db0..ffff736 100644 --- a/Mods/BasicInformation/Mods/CompanyShareholder/Schemas.py +++ b/Mods/BasicInformation/Mods/CompanyShareholder/Schemas.py @@ -12,6 +12,7 @@ class CompanyShareholderInfo(BaseModel): amount: Optional[float] reg_date: Optional[date] percent: Optional[float] + number: Optional[int] class CompanyShareholderAddInfo(BaseModel): @@ -21,6 +22,7 @@ class CompanyShareholderAddInfo(BaseModel): amount: Optional[float] reg_date: Optional[date] percent: Optional[float] + number: Optional[int] class CompanyShareholderAddReq(CompanyShareholderAddInfo): diff --git a/Mods/BasicInformation/Router.py b/Mods/BasicInformation/Router.py index c37da9d..3045985 100644 --- a/Mods/BasicInformation/Router.py +++ b/Mods/BasicInformation/Router.py @@ -7,7 +7,7 @@ from .Mods.CompanyPlusProperty import Router as CompanyPlusPropertyRouter from .Mods.CompanyIndexMain import Router as CompanyIndexMainRouter from .Mods.CompanyShareholder import Router as CompanyShareholderRouter from .Mods.CompanyEquityPenetration import Router as CompanyEquityPenetrationRouter -from Context.common import auth_util, common_db +from Context.common import auth_util, common_db, tianyancha_api from . import Crud, Schemas router = APIRouter( @@ -27,3 +27,17 @@ router.include_router(CompanyEquityPenetrationRouter.router) def company_all_info_query(req: Schemas.CompanyAllInfoQueryReq, db: Session = Depends(common_db.get_db)): count, items = Crud.company_all_info_query(db, req) return Schemas.CompanyAllInfoQueryRes(count=count, items=items) + + +@router.post("/company_create", summary="城投信息新建", tags=["城投详细信息"], + response_model=Schemas.CreateCompanyRes) +def create_company(req: Schemas.CreateCompanyReq, db: Session = Depends(common_db.get_db)): + Crud.create_company(db, req) + return "创建成功" + + +@router.post("/company_search", summary="公司搜索", tags=["城投详细信息"], + response_model=Schemas.CompanySearchRes) +def company_search(req: Schemas.CompanySearchReq): + company_name_list = tianyancha_api.公司搜索(req.company_name) + return Schemas.CompanySearchRes(company_name_list=company_name_list) diff --git a/Mods/BasicInformation/Schemas.py b/Mods/BasicInformation/Schemas.py index 5fcd1b7..3eb4377 100644 --- a/Mods/BasicInformation/Schemas.py +++ b/Mods/BasicInformation/Schemas.py @@ -31,3 +31,19 @@ class CompanyAllInfoQueryReq(CompanyAllInfoQueryParams): class CompanyAllInfoQueryRes(BaseModel): count: int items: List[CompanyAllInfo] + + +class CreateCompanyReq(BaseModel): + company_name: str + + +class CreateCompanyRes(BaseModel): + pass + + +class CompanySearchReq(BaseModel): + company_name: str + + +class CompanySearchRes(BaseModel): + company_name_list: List[str] diff --git a/ThirdPartyApi/Tianyancha/Apis.py b/ThirdPartyApi/Tianyancha/Apis.py new file mode 100644 index 0000000..f9dc612 --- /dev/null +++ b/ThirdPartyApi/Tianyancha/Apis.py @@ -0,0 +1,34 @@ +from typing import List + +from .Schemas import 企业基本信息Res + +from Utils.DataUtils import JsDict + + +class TianyanchaConfig: + 企业基本信息url = "http://open.api.tianyancha.com/services/open/ic/baseinfo/normal" + 搜索url = "http://open.api.tianyancha.com/services/open/search/2.0" + + +class TianyanchaApi: + def __init__(self, token: str, config: TianyanchaConfig = TianyanchaConfig): + self.config = config + self.token = token + + def 企业基本信息(self, keyword) -> 企业基本信息Res: + url = f"{self.config.企业基本信息}?keyword={keyword}" + headers = {'Authorization': self.token} + res = self.rq.get(url, headers=headers) + data = res.json() + if data['error_code'] == 0: + return JsDict(data['result']) + + def 公司搜索(self, keyword) -> List[str]: + url = f"{self.config.搜索url}?keyword={keyword}" + headers = {'Authorization': self.token} + res = self.rq.get(url, headers=headers) + data = res.json() + company_names = [] + if data['error_code'] == 0: + company_names = [item["name"] for item in data['result']['items'] if item["matchType"] == '公司名称匹配'] + return company_names diff --git a/ThirdPartyApi/Tianyancha/Schemas.py b/ThirdPartyApi/Tianyancha/Schemas.py new file mode 100644 index 0000000..20f4acb --- /dev/null +++ b/ThirdPartyApi/Tianyancha/Schemas.py @@ -0,0 +1,58 @@ +from typing import List + +from pydantic import BaseModel + + +class 企业基本信息Res: + id: int # + name: str # 企业名 + historyNames: str # 曾用名 + historyNameList: List[str] # 曾用名 + fromTime: int # 经营开始时间 + estiblishTime: int # 成立日期 + legalPersonName: str # 法人 + type: int # 法人类型,1 人 2 公司 + companyOrgType: str # 企业类型 + regStatus: str # 企业状态 + regCapital: str # 注册资本 + city: str # 市 + district: str # 区 + staffNumRange: str # 人员规模 + bondNum: int # 股票号 + bondName: str # 股票名 + usedBondName: str # 股票曾用名 + bondType: str # 股票类型 + revokeDate: int # 吊销日期 + updateTimes: int # 更新时间 + revokeReason: str # 吊销原因 + compForm: int # 组成形式,1-个人经营、2-家庭经营 + regNumber: int # 注册号 + creditCode: str # 统一社会信用代码 + property3: str # 英文名 + approvedTime: int # 核准时间 + socialStaffNum: int # 参保人数 + actualCapitalCurrency: str # 实收注册资本币种 + alias: str # 简称 + cancelReason: str # 注销原因 + cancelDate: int # 注销日期 + orgNumber: int # 组织机构代码 + toTime: int # 经营结束时间 + actualCapital: str # 实收注册资金 + regInstitute: str # 登记机关 + businessScope: str # 经营范围 + taxNumber: str # 纳税人识别号 + regLocation: str # 注册地址 + regCapitalCurrency: str # 注册资本币种 + tags: str + percentileScore: int # 企业评分 + base: str # 省份简称 + + industry: str # 行业 + + class industryAll: + categoryMiddle: str # 国民经济行业分类门类 + categoryBig: str # 国民经济行业分类大类 + category: str # 国民经济行业分类门类 + categorySmall: str # 国民经济行业分类小类 + + isMicroEnt: int # 是否是小微企业 0不是 1是 diff --git a/Utils/DataUtils.py b/Utils/DataUtils.py new file mode 100644 index 0000000..c66231f --- /dev/null +++ b/Utils/DataUtils.py @@ -0,0 +1,24 @@ +# python字典增强 + + +# python字典转js字典 +class JsDict(dict): + + def __new__(cls, *args, **kwargs): + cls.__setitem__ = cls.__setattr__ + return super().__new__(cls) + + def __init__(self, dic): + for key, value in dic.items(): + self.__setattr__(key, value) + + def __make_item__(self, item): + if type(item) == dict: + item = JsDict(item) + elif type(item) == list: + item = [self.__make_item__(one) for one in item] + return item + + def __setattr__(self, key, item): + dict.__setattr__(self, key, self.__make_item__(item)) + self.update(self.__dict__)