From 35ae2539cb6121a95c4b2adb6d7292cd957f57c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=20=E6=9F=8F?= Date: Tue, 6 Feb 2024 17:37:29 +0900 Subject: [PATCH 1/3] kintone excel new format --- backend/app/api/api_v1/routers/kintone.py | 163 ++++++++++++++++++---- backend/app/core/config.py | 2 + 2 files changed, 140 insertions(+), 25 deletions(-) diff --git a/backend/app/api/api_v1/routers/kintone.py b/backend/app/api/api_v1/routers/kintone.py index 0224937..0b595ae 100644 --- a/backend/app/api/api_v1/routers/kintone.py +++ b/backend/app/api/api_v1/routers/kintone.py @@ -9,7 +9,7 @@ import app.core.config as config import os from pathlib import Path from app.db.session import SessionLocal -from app.db.crud import get_flows_by_app,get_activedomain +from app.db.crud import get_flows_by_app,get_activedomain,get_kintoneformat from app.core.auth import get_current_active_user,get_current_user from app.core.apiexception import APIException @@ -23,28 +23,132 @@ def getkintoneenv(user = Depends(get_current_user)): return kintoneevn -def getfieldsfromexcel(df): +def getkintoneformat(): + db = SessionLocal() + formats = get_kintoneformat(db) + db.close() + return formats + + +def createkintonefields(property,value,trueformat): + p = [] + if(property=="options"): + o=[] + for v in value.split(','): + o.append(f"\"{v.split('|')[0]}\":{{\"label\":\"{v.split('|')[0]}\",\"index\":\"{v.split('|')[1]}\"}}") + p.append(f"\"options\":{{{','.join(o)}}}") + elif(property =="expression"): + p.append(f"\"hideExpression\":true") + p.append(f"\"expression\":\"{value.split(':')[1]}\"") + elif(property =="required" or property =="unique" or property =="defaultNowValue" or property =="hideExpression" or property =="digit"): + if str(value) == trueformat: + p.append(f"\"{property}\":true") + else: + p.append(f"\"{property}\":false") + elif(property =="protocol"): + if(value == "メールアドレス"): + p.append("\"protocol\":\"MAIL\"") + elif(value == "Webサイト"): + p.append("\"protocol\":\"WEB\"") + elif(value == "電話番号"): + p.append("\"protocol\":\"CALL\"") + else: + p.append(f"\"{property}\":\"{value}\"") + return p + +def getfieldsfromexcel(df,mapping): + startrow = mapping.startrow + startcolumn = mapping.startcolumn + typecolumn = mapping.typecolumn + codecolumn = mapping.codecolumn + property = mapping.field.split(",") + trueformat = mapping.trueformat appname = df.iloc[0,2] col=[] - for row in range(5,len(df)): - if pd.isna(df.iloc[row,1]): + for row in range(startrow,len(df)): + if pd.isna(df.iloc[row,startcolumn]): break - if not df.iloc[row,3] in config.KINTONE_FIELD_TYPE: + if not df.iloc[row,typecolumn] in config.KINTONE_FIELD_TYPE: continue p=[] - for column in range(1,7): + for column in range(startcolumn,startcolumn + len(property)): if(not pd.isna(df.iloc[row,column])): - if(property[column-1]=="options"): - o=[] - for v in df.iloc[row,column].split(','): - o.append(f"\"{v.split('|')[0]}\":{{\"label\":\"{v.split('|')[0]}\",\"index\":\"{v.split('|')[1]}\"}}") - p.append(f"\"{property[column-1]}\":{{{','.join(o)}}}") - elif(property[column-1]=="required"): - p.append(f"\"{property[column-1]}\":{df.iloc[row,column]}") + propertyname =property[column-1] + if(propertyname.find("[") == 0): + continue + elif (propertyname =="remark"): + if (df.iloc[row,column].find("|") !=-1): + propertyname = "options" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + if (df.iloc[row,column] == "メールアドレス" or df.iloc[row,column] == "Webサイト" or df.iloc[row,column] == "電話番号"): + propertyname = "protocol" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + if (df.iloc[row,column].find("桁区切り") !=-1): + propertyname = "digit" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + if (df.iloc[row,column].find("前単位") !=-1): + propertyname = "unitPosition" + p = p + createkintonefields(propertyname, "BEFORE",trueformat) + if (df.iloc[row,column].find("後単位") !=-1): + propertyname = "unitPosition" + p = p + createkintonefields(propertyname, "AFTER",trueformat) + if (df.iloc[row,column].find("単位「") !=-1): + propertyname = "unit" + ids = df.iloc[row,column].index("単位「") + ide = df.iloc[row,column].index("」") + unit = df.iloc[row,column][ids+3:ide] + p = p + createkintonefields(propertyname, unit,trueformat) + else: + continue + elif(propertyname =="mixValue"): + if(df.iloc[row,column].find("レコード登録時の日") != -1): + propertyname = "defaultNowValue" + df.iloc[row,column] = trueformat + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + elif(df.iloc[row,column].find("計:") != -1): + propertyname = "expression" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + elif(df.iloc[row,column] !=""): + propertyname = "defaultValue" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + else: + continue + elif(propertyname=="max" or propertyname == "min"): + if(df.iloc[row,typecolumn] == "NUMBER"): + propertyname = property[column-1] + "Value" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + else: + propertyname = property[column-1] + "Length" + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) else: - p.append(f"\"{property[column-1]}\":\"{df.iloc[row,column]}\"") - col.append(f"\"{df.iloc[row,2]}\":{{{','.join(p)}}}") - fields = ",".join(col).replace("False","false").replace("True","true") + p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat) + + # if(propertyname=="options"): + # o=[] + # for v in df.iloc[row,column].split(','): + # o.append(f"\"{v.split('|')[0]}\":{{\"label\":\"{v.split('|')[0]}\",\"index\":\"{v.split('|')[1]}\"}}") + # p.append(f"\"options\":{{{','.join(o)}}}") + # elif(propertyname=="expression"): + # p.append(f"\"hideExpression\":true") + # p.append(f"\"expression\":{df.iloc[row,column].split(':')[1]}") + # elif(propertyname=="required" or propertyname =="unique" or propertyname=="defaultNowValue" or propertyname=="hideExpression" or propertyname=="digit"): + # if (df.iloc[row,column] == trueformat): + # p.append(f"\"{propertyname}\":true") + # else: + # p.append(f"\"{propertyname}\":false") + # elif(propertyname =="protocol"): + # if(df.iloc[row,column] == "メールアドレス"): + # p.append("\"protocol\":\"MAIL\"") + # elif(df.iloc[row,column] == "Webサイト"): + # p.append("\"protocol\":\"WEB\"") + # elif(df.iloc[row,column] == "電話番号"): + # p.append("\"protocol\":\"CALL\"") + # else: + # p.append(f"\"{propertyname}\":\"{df.iloc[row,column]}\"") + + + col.append(f"\"{df.iloc[row,codecolumn]}\":{{{','.join(p)}}}") + fields = ",".join(col).replace("\\", "\\\\") return json.loads(f"{{{fields}}}") def getsettingfromexcel(df): @@ -129,8 +233,8 @@ def analysefields(excel,kintone): adds = excel.keys() - kintone.keys() dels = kintone.keys() - excel.keys() for key in updates: - for p in property: - if excel[key].get(p) != None and kintone[key][p] != excel[key][p]: + for p in config.KINTONE_FIELD_PROPERTY: + if excel[key].get(p) != None and kintone[key].get(p) != None and kintone[key][p] != excel[key][p]: updatefields[key] = excel[key] break for key in adds: @@ -412,10 +516,14 @@ async def createapp(request:Request,name:str,c:config.KINTONE_ENV=Depends(getkin except Exception as e: raise APIException('kintone:createapp',request.url._url, f"Error occurred while create app({c.DOMAIN_NAM}->{name}):",e) -property=["label","code","type","required","defaultValue","options"] @r.post("/createappfromexcel",) -async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(...),env = Depends(getkintoneenv)): +async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(...),format:int = 0,env = Depends(getkintoneenv)): + try: + mapping = getkintoneformat()[format] + except Exception as e: + raise APIException('kintone:createappfromexcel',request.url._url, f"Error occurred while get kintone format:",e) + for file in files: if file.filename.endswith('.xlsx'): try: @@ -425,7 +533,7 @@ async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(... appname = df.iloc[0,2] desc = df.iloc[2,2] result = {"app":0,"revision":0,"msg":""} - fields = getfieldsfromexcel(df) + fields = getfieldsfromexcel(df,mapping) users = getkintoneusers(env) orgs = getkintoneorgs(env) processes = getprocessfromexcel(df,users["users"], orgs["organizationTitles"]) @@ -442,14 +550,19 @@ async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(... result["revision"] = app["revision"] deoployappfromkintone(result["app"],result["revision"],env) except Exception as e: - raise APIException('kintone:createappfromexcel',request.url._url, f"Error occurred while parsing file ({env.DOMAIN_NAM}->{file.filename}):",e) + raise APIException('kintone:createappfromexcel',request.url._url, f"Error occurred while parsing file ({env.DOMAIN_NAME}->{file.filename}):",e) else: raise APIException('kintone:createappfromexcel',request.url._url, f"File {file.filename} is not an Excel file",e) return result @r.post("/updateappfromexcel") -async def updateappfromexcel(request:Request,app:str,files:t.List[UploadFile] = File(...),env = Depends(getkintoneenv)): +async def updateappfromexcel(request:Request,app:str,files:t.List[UploadFile] = File(...),format:int = 0,env = Depends(getkintoneenv)): + try: + mapping = getkintoneformat()[format] + except Exception as e: + raise APIException('kintone:updateappfromexcel',request.url._url, f"Error occurred while get kintone format:",e) + for file in files: if file.filename.endswith('.xlsx'): try: @@ -458,7 +571,7 @@ async def updateappfromexcel(request:Request,app:str,files:t.List[UploadFile] = excel = getsettingfromexcel(df) kintone= getsettingfromkintone(app,env) settings = analysesettings(excel,kintone) - excel = getfieldsfromexcel(df) + excel = getfieldsfromexcel(df,mapping) kintone = getfieldsfromkintone(app,env) users = getkintoneusers(env) orgs = getkintoneorgs(env) @@ -493,7 +606,7 @@ async def updateappfromexcel(request:Request,app:str,files:t.List[UploadFile] = if deploy: result = deoployappfromkintone(app,revision,env) except Exception as e: - raise APIException('kintone:updateappfromexcel',request.url._url, f"Error occurred while parsing file ({env.DOMAIN_NAM}->{file.filename}):",e) + raise APIException('kintone:updateappfromexcel',request.url._url, f"Error occurred while parsing file ({env.DOMAIN_NAME}->{file.filename}):",e) else: raise APIException('kintone:updateappfromexcel',request.url._url, f"File {file.filename} is not an Excel file",e) return result diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 9a1f9aa..24fb0f8 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -16,6 +16,8 @@ DEPLOY_JS_URL = "https://ka-addin.azurewebsites.net/alc_runtime.js" 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"] +KINTONE_FIELD_PROPERTY=['label','code','type','required','unique','maxValue','minValue','maxLength','minLength','defaultValue','defaultNowValue','options','expression','hideExpression','digit','protocol','displayScale','unit','unitPosition'] + class KINTONE_ENV: BASE_URL = "" From 1e7d553bd68cb10cea542403abe9b63aa601d5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=20=E6=9F=8F?= Date: Tue, 6 Feb 2024 17:37:55 +0900 Subject: [PATCH 2/3] kintone excel new format --- backend/app/db/crud.py | 6 +++++- backend/app/db/models.py | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/app/db/crud.py b/backend/app/db/crud.py index 0462218..0ffa054 100644 --- a/backend/app/db/crud.py +++ b/backend/app/db/crud.py @@ -290,4 +290,8 @@ def create_log(db: Session, error:schemas.ErrorCreate): db.add(db_log) db.commit() db.refresh(db_log) - return db_log \ No newline at end of file + return db_log + +def get_kintoneformat(db: Session): + formats = db.query(models.KintoneFormat).order_by(models.KintoneFormat.id).all() + return formats \ No newline at end of file diff --git a/backend/app/db/models.py b/backend/app/db/models.py index 153d5f2..e5285b4 100644 --- a/backend/app/db/models.py +++ b/backend/app/db/models.py @@ -95,7 +95,18 @@ class EventAction(Base): class ErrorLog(Base): __tablename__ = "errorlog" - id = Column(Integer, primary_key=True, index=True) + title = Column(String(50)) location = Column(String(500)) - content = Column(String(5000)) \ No newline at end of file + content = Column(String(5000)) + +class KintoneFormat(Base): + __tablename__ = "kintoneformat" + + name = Column(String(50)) + startrow =Column(Integer) + startcolumn =Column(Integer) + typecolumn =Column(Integer) + codecolumn =Column(Integer) + field = Column(String(5000)) + trueformat = Column(String(10)) \ No newline at end of file From 6e6350d6cec46f51bf894ce62bf5b3a137ff097c Mon Sep 17 00:00:00 2001 From: "maxiaozhe@alicorns.co.jp" Date: Tue, 13 Feb 2024 14:25:09 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E8=A8=AD=E8=A8=88=E6=9B=B8=E5=8F=96?= =?UTF-8?q?=E8=BE=BC=E6=A9=9F=E8=83=BD=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin/kintone-addins/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/kintone-addins/package.json b/plugin/kintone-addins/package.json index 8c83735..c19293e 100644 --- a/plugin/kintone-addins/package.json +++ b/plugin/kintone-addins/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "tsc && vite", "build": "tsc && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y", "build:dev":"tsc && set \"SOURCE_MAP=true\" && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y", "preview": "vite preview"