From 445a87fbe7533826e9025dbafc5c5d40199172b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=20=E6=9F=8F?= Date: Wed, 19 Jul 2023 12:03:43 +0000 Subject: [PATCH] kintone process add&update --- backend/app/api/api_v1/routers/kintone.py | 163 +++++++++++++++++++++- backend/app/core/config.py | 4 +- 2 files changed, 159 insertions(+), 8 deletions(-) diff --git a/backend/app/api/api_v1/routers/kintone.py b/backend/app/api/api_v1/routers/kintone.py index 946e5df..516fb67 100644 --- a/backend/app/api/api_v1/routers/kintone.py +++ b/backend/app/api/api_v1/routers/kintone.py @@ -4,6 +4,7 @@ import typing as t import pandas as pd import json import httpx +import deepdiff import app.core.config as c kinton_router = r = APIRouter() @@ -12,6 +13,8 @@ def getfieldsfromexcel(df): appname = df.iloc[0,2] col=[] for row in range(5,len(df)): + if pd.isna(df.iloc[row,1]): + break if not df.iloc[row,3] in c.KINTONE_FIELD_TYPE: continue p=[] @@ -42,7 +45,6 @@ def getsettingfromkintone(app:str): r = httpx.get(url,headers=headers,params=params) return r.json() - def analysesettings(excel,kintone): updatesettings={} updates = excel.keys() & kintone.keys() @@ -125,6 +127,93 @@ def analysefields(excel,kintone): return {"update":updatefields,"add":addfields,"del":delfields} +def getprocessfromkintone(app:str): + headers={c.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE} + params = {"app":app} + url = f"{c.BASE_URL}{c.API_V1_STR}/app/status.json" + r = httpx.get(url,headers=headers,params=params) + return r.json() + +def getassigneefromkintone(name,users,orgs): + if name in ["作成者"]: + return {"type":"ONE","entities":[{ + "entity": { + "type": "FIELD_ENTITY", + "code": name + }, + "includeSubs": False + }]} + for user in users: + if user["name"] == name: + return {"type":"ONE","entities":[{ + "entity": { + "type": "USER", + "code": user["code"] + }, + "includeSubs": False + }]} + for org in orgs: + if org["organization"]["name"] == name: + return {"type":"ONE","entities":[{ + "entity": { + "type": "ORGANIZATION", + "code": org["organization"]["code"] + }, + "includeSubs": False + }]} + return {"type":"ONE","entities":[]} + +def getprocessfromexcel(df,users,orgs): + begin = df[df[df.columns[1]].isin(["◆プロセス"])].index.values[0] + status=[] + actions=[] + result ="{{}}" + for row in range(begin+2,len(df)): + n = df.iloc[row,1] + i = df.iloc[row,0] + a = df.iloc[row,2] + t = df.iloc[row,4] + u = df.iloc[row,3] + if pd.isna(u): + status.append(f"\"{n}\":{{\"name\":\"{n}\",\"index\":\"{i}\",\"assignee\":{{\"type\":\"ONE\",\"entities\":[]}}}}") + else: + status.append(f"\"{n}\":{{\"name\":\"{n}\",\"index\":\"{i}\",\"assignee\":{json.dumps(getassigneefromkintone(u,users,orgs))}}}") + if not pd.isna(t): + actions.append(f"{{\"name\":\"{a}\",\"from\":\"{n}\",\"to\":\"{t}\",\"filterCond\":\"\"}}") + result = f"{{\"states\":{{{','.join(status)}}}, \"actions\": [{','.join(actions)}]}}" + return json.loads(result) + +def analysprocess(excel,kintone): + excel.update({"enable":kintone["enable"],"revision":kintone["revision"]}) + diff = deepdiff.DeepDiff(excel,kintone) + # diffstates = excel["states"].keys() ^ kintone["states"].keys() + # diffactions = set(excel["actions"]).difference(set(kintone["actions"] + + # for item in diff: + # if item[0] != "enable" and item[0] != "app" and item[0] != "revision": + # return True + return diff + +def updateprocesstokintone(app:str,process:dict): + headers={c.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE,"Content-Type": "application/json"} + url = f"{c.BASE_URL}{c.API_V1_STR}/preview/app/status.json" + data = {"app":app,"enable":True} + data.update(process) + r = httpx.put(url,headers=headers,data=json.dumps(data)) + return r.json() + +def getkintoneusers(): + headers={c.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE} + url = f"{c.BASE_URL}/v1/users.json" + r = httpx.get(url,headers=headers) + return r.json() + +def getkintoneorgs(): + headers={c.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE} + params = {"code":c.KINTONE_USER} + url = f"{c.BASE_URL}/v1/user/organizations.json" + r = httpx.get(url,headers=headers,params=params) + return r.json() @r.post("/test",) async def test(file:UploadFile= File(...),app:str=None): @@ -132,16 +221,22 @@ async def test(file:UploadFile= File(...),app:str=None): try: content = await file.read() df = pd.read_excel(BytesIO(content)) - excel = getfieldsfromexcel(df) - if(app != None): - kintone = getfieldsfromkintone(app) - fields = analysefields(excel,kintone["properties"]) + users = getkintoneusers() + orgs = getkintoneorgs() + # excel = getprocessfromexcel(df) + # kintone = getprocessfromkintone(app) + # process = analysprocess(excel,kintone) + test = getprocessfromexcel(df,users["users"], orgs["organizationTitles"]) + # excel = getfieldsfromexcel(df) + # if(app != None): + # kintone = getfieldsfromkintone(app) + # fields = analysefields(excel,kintone["properties"]) except Exception as e: raise HTTPException(status_code=400, detail=f"Error occurred while parsing file {file.filename}: {str(e)}") else: raise HTTPException(status_code=400, detail=f"File {file.filename} is not an Excel file") - return fields + return test @r.post("/upload",) @@ -172,6 +267,9 @@ async def allapps(): async def appfields(app:str): return getfieldsfromkintone(app) +@r.get("/appprocess") +async def appprocess(app:str): + return getprocessfromkintone(app) @r.get("/alljscs") async def alljscs(app:str): @@ -196,7 +294,7 @@ async def createapp(name:str): property=["label","code","type","required","defaultValue","options"] -@r.post("/createappfromexcel") +@r.post("/createappfromexcel",) async def createappfromexcel(files:t.List[UploadFile] = File(...)): for file in files: if file.filename.endswith('.xlsx'): @@ -208,6 +306,9 @@ async def createappfromexcel(files:t.List[UploadFile] = File(...)): desc = df.iloc[2,2] result = {"app":0,"revision":0,"msg":""} fields = getfieldsfromexcel(df) + users = getkintoneusers() + orgs = getkintoneorgs() + processes = getprocessfromexcel(df,users["users"], orgs["organizationTitles"]) app = createkintoneapp(appname) if app.get("app") != None: result["app"] = app["app"] @@ -215,6 +316,8 @@ async def createappfromexcel(files:t.List[UploadFile] = File(...)): if app.get("revision") != None: result["revision"] = app["revision"] app = addfieldstokintone(result["app"],fields) + if len(processes)> 0: + app = updateprocesstokintone(result["app"],processes) if app.get("revision") != None: result["revision"] = app["revision"] deoployappfromkintone(result["app"],result["revision"]) @@ -238,6 +341,12 @@ async def updateappfromexcel(app:str,files:t.List[UploadFile] = File(...)): settings = analysesettings(excel,kintone) excel = getfieldsfromexcel(df) kintone = getfieldsfromkintone(app) + users = getkintoneusers() + orgs = getkintoneorgs() + exp = getprocessfromexcel(df,users["users"], orgs["organizationTitles"]) + #exp = getprocessfromexcel(df) + kinp = getprocessfromkintone(app) + process = analysprocess(exp,kinp) revision = kintone["revision"] fields = analysefields(excel,kintone["properties"]) result = {"app":app,"revision":revision,"msg":"No Update"} @@ -258,6 +367,10 @@ async def updateappfromexcel(app:str,files:t.List[UploadFile] = File(...)): result = updateappsettingstokintone(app,settings) revision = result["revision"] deploy = True + if len(process)>0: + result = updateprocesstokintone(app,exp) + revision = result["revision"] + deploy = True if deploy: result = deoployappfromkintone(app,revision) except Exception as e: @@ -267,4 +380,40 @@ async def updateappfromexcel(app:str,files:t.List[UploadFile] = File(...)): return result +@r.post("/updateprocessfromexcel",) +async def updateprocessfromexcel(app:str): + + try: + excel = getprocessfromexcel() + kintone = getprocessfromkintone(app) + revision = kintone["revision"] + #fields = analysefields(excel,kintone["properties"]) + result = {"app":app,"revision":revision,"msg":"No Update"} + deploy = False + # if len(fields["update"]) > 0: + # result = updatefieldstokintone(app,revision,fields["update"]) + # revision = result["revision"] + # deploy = True + # if len(fields["add"]) > 0: + # result = addfieldstokintone(app,fields["add"],revision) + # revision = result["revision"] + # deploy = True + # if len(fields["del"]) > 0: + # result = deletefieldsfromkintone(app,revision,fields["del"]) + # revision = result["revision"] + # deploy = True + # if len(settings) > 0: + # result = updateappsettingstokintone(app,settings) + # revision = result["revision"] + # deploy = True + result = updateprocesstokintone(app,excel) + revision = result["revision"] + deploy = True + if deploy: + result = deoployappfromkintone(app,revision) + except Exception as e: + raise HTTPException(status_code=400, detail=f"Error occurred : {str(e)}") + + return result + diff --git a/backend/app/core/config.py b/backend/app/core/config.py index ea605bc..16f64dd 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -12,4 +12,6 @@ API_V1_AUTH_KEY = "X-Cybozu-Authorization" API_V1_AUTH_VALUE = "TVhaOm1heHoxMjA1" -KINTONE_FIELD_TYPE=["GROUP","GROUP_SELECT","CHECK_BOX","SUBTABLE","DROP_DOWN","USER_SELECT","RADIO_BUTTON","RICH_TEXT","LINK","REFERENCE_TABLE","CALC","TIME","NUMBER","ORGANIZATION_SELECT","FILE","DATETIME","DATE","MULTI_SELECT","SINGLE_LINE_TEXT","MULTI_LINE_TEXT"] \ No newline at end of file +KINTONE_USER = "MXZ" + +KINTONE_FIELD_TYPE=["GROUP","GROUP_SELECT","CHECK_BOX","SUBTABLE","DROP_DOWN","USER_SELECT","RADIO_BUTTON","RICH_TEXT","LINK","REFERENCE_TABLE","CALC","TIME","NUMBER","ORGANIZATION_SELECT","FILE","DATETIME","DATE","MULTI_SELECT","SINGLE_LINE_TEXT","MULTI_LINE_TEXT"]