税盘的批量抄报税和批量清卡--支持金税盘,税控盘,税务UKey
1. 稅盤抄稅和清卡業(yè)務流程
????????增值稅開票軟件需要插入稅盤才能運行,稅盤分為金稅盤(白盤),稅控盤(黑盤)和稅務UKey三種。其中,金稅盤是航信旗下研發(fā)的開票軟件,所使用的稅盤。稅控盤和稅務UKey,是百旺研發(fā)的開票軟件,所使用的稅盤。從市場占有率來說金稅盤遙遙領先,屬于佼佼者,從趨勢來看當屬稅務UKey首屈一指,代表著未來的趨勢,后來者居上。
????????稅盤每月月初,需要進行抄稅,清卡操作。若不能及時清卡,到鎖死期不能再開具發(fā)票。抄稅是將稅盤中,上月所開的所有發(fā)票數(shù)據(jù),進行匯總上傳(注意:在抄稅操作之前,需要從稅盤中修復所有的發(fā)票,并將發(fā)票全部上傳)。在開票軟件中進行抄稅操作之后,稅務會計登錄到電子稅務局,進行納稅申報,也稱為“報稅”。在電子稅務局進行納稅申報之后,方可在開票軟件中,進行清卡操作,清卡成功后,稅盤的鎖死日期自動變更為次月。若未清卡,到稅盤鎖死日期后,不能再開具發(fā)票。抄稅和清卡的業(yè)務流程如下圖所示。
圖-1 稅盤抄稅和清卡業(yè)務流程
2.?常見的稅盤抄稅和清卡操作方式分析
????????稅盤的抄稅和清卡,從操作方式來講,根據(jù)筆者的理解和調研,大致分為如下四種。第一種,在開票軟件中手工操作,進行抄稅和清卡;第二種,使用RPA技術,模擬鼠標鍵盤操作,進行抄稅和清卡;第三種,通過注入技術,進行稅盤抄稅和清卡進行操作;第四種,通過調用組件的抄稅和清卡接口,進行抄稅和清卡進行操作。筆者,下面分別就這四種操作方式進行詳細的闡述和對比。
圖-2 稅盤抄稅和清卡操作的幾種方式
2.1?手工操
????????在開票軟件上進行手工的抄稅和清卡,是最便捷、最穩(wěn)定的方式。對于只有一個或數(shù)個盤的單個企業(yè)而言,是行之有效的操作手段。這種操作,首先,將稅盤插到電腦上,打開對應的開票軟件,輸入用戶密碼,稅控設備密碼,證書密碼,登錄到開票軟件。然后,修復發(fā)票數(shù)據(jù),以確保當月開具的所有發(fā)票數(shù)據(jù),在開票軟中已存在。如果存在未上傳的發(fā)票,則需進行上傳發(fā)票操作。
????????經(jīng)過以上的準備和前奏操作之后,在開票軟件上進行抄稅操作,在有的開票軟件中,也稱之為“匯總上傳”(不同的開票軟件其入口或者叫法不同,筆者在此不再一一展開贅述)。抄稅成功之后,稅務會計登錄到電子稅務局,進行納稅申報。
????????在稅務會計納稅申報完成之后,開票員插入稅盤,打開并登錄開票軟件,進行清卡操作。在有的開票軟件中,也稱之為 “監(jiān)控回傳”或“監(jiān)控回寫”。不同的開票軟件,其操作入口也不同,筆者也不再展開贅述。清卡完成,則稅盤的鎖死日期自動變?yōu)榇卧碌娜掌?#xff0c;若清卡失敗,則到稅盤鎖死日期不再允許開票(一般是當月中旬,當然具體的日期可以查看稅局的納稅申報截止日期)。
????????上面描述的是手工進行抄稅,清卡的操作流程,這種方式的優(yōu)點是穩(wěn)定可控。但是,如果企業(yè)有數(shù)百甚至更多的盤(例如代賬企業(yè)),其工作量,也是可想而知的。
2.2 RPA技術
????????RPA技術(Robotic Process Automation)即機器人流程自動化,該技術應用在稅盤的抄稅和清卡的場景,是通過技術手段,自動打開稅盤對應的開票軟件,通過模擬鍵盤鼠標操作,進行抄稅和清卡。操作的流程和手工操作完全一致。
????????這種方式的優(yōu)點是,相對于純手工操作來說,會提升一定的效率,但效率提升是有限的。缺點是,稅盤種類和開票軟件種類繁多,和各種單步操作的各種業(yè)務場景(例如多報錯信息的處理等)疊加在一起,有數(shù)不盡的細分場景,很難一一枚舉。同時,開票軟件本身,會使用各種反模擬操作的技術手段,這些因素,也就導致RPA很不穩(wěn)定。開票軟件升級后RPA也要做相關的調整和迭代,開票軟件升級頻繁(至少每月一個版本)。所以,RPA技術很難在稅盤的抄稅,清卡的場景能做到穩(wěn)定,同時提升的效率也是有限的。
2.3 注入技術
????????通過注入技術,進行稅盤的抄稅,清卡操作,相對于RPA技術來說,更加考驗開發(fā)者的技術功底,正所謂“沒有金剛鉆,別攔瓷器活”,注入需要找到正確的注入點,并進行相關的分析,這個過程沒有一定技術底蘊,是很難勝任的。當然,注入也可以分為初級和高級兩個境界,能做到高級注入的話,可以直接調用相關的底層接口,可以做到穩(wěn)定和高效。然而,高級注入沒有“大師”級的技術底蘊,是很難實現(xiàn)的。
????????高級注入雖然可以做大穩(wěn)定和高效,但是開票軟件頻繁升級,也是夢魘一般的存在,每次升級后,都需要進行重新的分析,這個過程也是,極其耗時和繁雜的,所以這種技術也有很大的瓶頸。
2.4 使用組件接口
?
? ? ? ? 相關組件接口提供了抄稅,清卡以及其它功能,使用組件接口可以獲取稅盤狀態(tài)(例如核定票種的最近抄報日期,鎖死日期等),并依此來判斷稅盤的抄稅,清卡狀態(tài)。如果沒有抄稅,則可以調用相關接口,進行未上傳發(fā)票上傳,抄稅,清卡。組件接口的優(yōu)點是穩(wěn)定,高效,同時不用再需要考慮開票軟件的頻繁升級問題,一勞永逸。另外組件接口調用簡單,很容易上手。
?? ?綜上所述,組件接口是最優(yōu)方案。當然組件所提供的接口,不止抄稅和清卡的功能,例如開票,作廢,沖紅,庫存查詢,領購,上傳,發(fā)票查詢,版式文件下載等一應具全。本文著重介紹抄稅和清卡。
3. 組件接口核心代碼分享
????????下面筆者對通過調用組件接口,實現(xiàn)抄稅和清卡的核心代碼進行分享,上節(jié)提到的通過RPA技術,注入技術實現(xiàn)抄稅,清卡的技術細節(jié)不再展開講述,有興趣的朋友,可以和筆者進行溝通交流。
3.1 金稅盤組件核心代碼分享
3.1.1 抄稅操作核心代碼分享
{**********************************************************功能:金稅盤抄稅操作參數(shù):errMsg 輸出參數(shù),錯誤信息返回值:ture - 成功false - 失敗date: 2021-05-0430author: 海之邊 qq-3094353627流程簡述:1. 打開金稅盤2. 獲取金稅盤盤狀態(tài)3. 如果尚未抄稅則進行抄稅4. 抄稅成功后獲取金稅盤狀態(tài),并緩存到本地數(shù)據(jù)庫**********************************************************} function TCtrlItem.reportTax(var errMsg: string): boolean; var idx: integer;bReported: boolean;sFplxdm, sCardClock: string;oJsCardComponent: TJsCardComponent;oTaxCardRespOpenCard: TJsCardResponse_OpenCard;oJsCardRespGetClock: TJsCardResponse_getClock;oJsCardState: TJsCardState;oJsCardRespRep: TJsCardResponse_taxReport;oHdFplxdmLst: TStrings;oDBAJxsb: TDBAJxsb;oDBAPzxx: TDBAPzxx; beginresult := false;oJsCardComponent := TJsCardComponent.Create;oTaxCardRespOpenCard := nil;oJsCardState := nil;oJsCardRespRep := nil;oHdFplxdmLst := nil;oDBAJxsb := nil;oDBAPzxx := nil;tryoDBAJxsb := TDBAJssb.Create;oDBAPzxx := TDBAPzxx.Create;//1. 打開金稅盤oTaxCardRespOpenCard := oJsCardComponent.openTaxCard(Zsmm);if not oTaxCardRespOpenCard.isSucc thenbeginerrMsg := Format('打開金稅盤%s.%s失敗: %s。', [FNsrsbh, FMachineNo, errMsg]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);exit;end;if oTaxCardRespOpenCard.isCertNotPass thenbegin//證書密碼錯誤,設置密碼校驗不通過狀態(tài)Zsmmjyjg := untGolbalConst.JYJG_NotPass;updateToDb(oDBAJxsb);Exit;end;//判斷抄報狀態(tài)//2. 讀取金稅盤時鐘oJsCardRespGetClock := OJsCardComponent.getClock;if not oJsCardRespGetClock.isSucc thenbeginerrMsg := Format('讀取金稅盤時鐘失敗:%d-%s', [oJsCardRespGetClock.retCode, oJsCardRespGetClock.retMsg]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;sCardClock := oJsCardRespGetClock.Clock;//3 讀取金稅盤狀態(tài)oJsCardState := oJsCardComponent.queryTaxcardState_svr(errMsg);if not Assigned(oJsCardState) thenbeginupdateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;updateToDb(oDBAJxsb);//更新設備狀態(tài)信息assignFromJsCardState(oJsCardState);//保存票種核定信息oJsCardState.Pzxxs.saveToDb(Sksblx, SksbNo);//4 逐個核定票種判斷是否能抄報//4.1 判斷是否已經(jīng)抄報bReported := True;oHdFplxdmLst := spliteStr(hdfplxdm, ',');for idx := 0 to oHdFplxdmLst.Count - 1 dobeginsFplxdm := oHdFplxdmLst.Strings[idx];if not oDBAPzxx.isReport(Sksblx, SksbNo, sFplxdm, sCardClock) thenbeginbReported := False;Break;end;end;if bReported thenbegin//已抄報updateCzzt(oDBAJxsb, CZZT_CG, '已抄報,無需再執(zhí)行抄報操作。');result := true;Exit;end;//4.2 是否到抄報期if oTaxCardRespOpenCard.IsRepReached <> '1' thenbeginerrMsg := '未到抄稅期';updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;//5 執(zhí)行抄稅操作oJsCardRespRep := OJsCardComponent.taxReport;if not oJsCardRespRep.reportIsSucc thenbegin//抄稅失敗errMsg := Format('抄報失敗:%s-%s', [oJsCardRespRep.Code, oJsCardRespRep.Mess]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;endelsebegin//抄稅成功updateCzzt(oDBAJxsb, CZZT_CG, '');//更新金稅盤狀態(tài)if Assigned(taskThread) thentaskThread.setThirdPrompt('正在更新金稅盤狀態(tài)信息...');updateCzlb(oDBAJxsb, CZLB_HQJSPZT);oJsCardState := oJsCardComponent.queryTaxcardState(errMsg);if not Assigned(oJsCardState) thenbeginupdateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;updateToDb(oDBAJxsb);//更新設備狀態(tài)信息assignFromJsCardState(oJsCardState);//保存票種核定信息oJsCardState.Pzxxs.saveToDb(Sksblx, SksbNo);result := true;end;finallyif Assigned(oJsCardComponent) then FreeAndNil(oJsCardComponent);if Assigned(oTaxCardRespOpenCard) thenFreeAndNil(oTaxCardRespOpenCard);if Assigned(oJsCardRespGetClock) thenFreeAndNil(oJsCardRespGetClock);if Assigned(oJsCardState) thenFreeAndNil(oJsCardState);if Assigned(oHdFplxdmLst) thenFreeAndNil(oHdFplxdmLst);if Assigned(oJsCardRespRep) thenFreeAndNil(oJsCardRespRep);if Assigned(oDBAJxsb) thenFreeAndNil(oDBAJxsb);if Assigned(oDBAPzxx) then FreeAndNil(oDBAPzxx);end; end;?3.1.2 清卡核心代碼分享
{**********************************************************功能:金稅盤清卡操作參數(shù):errMsg 輸出參數(shù),錯誤信息返回值:ture - 成功false - 失敗date: 2021-05-0430author: 海之邊 qq-3094353627流程簡述:1. 打開金稅盤2. 獲取金稅盤盤狀態(tài)3. 如果尚未清卡則進行清卡4. 清卡成功后獲取金稅盤狀態(tài),并緩存到本地數(shù)據(jù)庫**********************************************************} function TCtrlItem.reportTaxJSP(var errMsg: string): boolean; var idx: integer;bCleared: boolean;sFplxdm, sCardClock: string;oJsCardComponent: TJsCardComponent;oTaxCardRespOpenCard: TJsCardResponse_OpenCard;oJsCardRespGetClock: TJsCardResponse_getClock;oJsCardState: TJsCardState;oJsCardRespClearCard: TJsCardResponse_clearReport;oHdFplxdmLst: TStrings;oDBAJxsb: TDBAJxsb;oDBAPzxx: TDBAPzxx; beginresult := false;oJsCardComponent := TJsCardComponent.Create;oTaxCardRespOpenCard := nil;oJsCardState := nil;oJsCardRespClearCard := nil;oHdFplxdmLst := nil;oDBAJxsb := nil;oDBAPzxx := nil;tryoDBAJxsb := TDBAJssb.Create;oDBAPzxx := TDBAPzxx.Create;//1 打開金稅盤oTaxCardRespOpenCard := oJsCardComponent.openTaxCard(Zsmm);if not oTaxCardRespOpenCard.isSucc thenbeginerrMsg := Format('打開金稅盤%s.%s失敗: %s。', [FNsrsbh, FMachineNo, errMsg]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;if oTaxCardRespOpenCard.isCertNotPass thenbegin//證書密碼錯誤,設置密碼校驗不通過狀態(tài)Zsmmjyjg := untGolbalConst.JYJG_NotPass;updateToDb(oDBAJxsb);Exit;end;//2. 判斷是否已經(jīng)清卡//讀取金稅盤時鐘oJsCardRespGetClock := OJsCardComponent.getClock;if not oJsCardRespGetClock.isSucc thenbeginerrMsg := Format('讀取金稅盤時鐘失敗:%d-%s', [oJsCardRespGetClock.retCode,oJsCardRespGetClock.retMsg]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;sCardClock := oJsCardRespGetClock.Clock;updateLastClock(sCardClock);//讀取金稅盤狀態(tài)oJsCardState := oJsCardComponent.queryTaxcardState(errMsg);if not Assigned(oJsCardState) thenbeginupdateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;updateToDb(oDBAJxsb);//更新設備狀態(tài)信息,保存票種核定信息assignFromJsCardState(oJsCardState);oJsCardState.Pzxxs.saveToDb(Sksblx, SksbNo);//這個核定票種判斷是否已經(jīng)抄報bCleared := True;oHdFplxdmLst := spliteStr(hdfplxdm, ',');for idx := 0 to oHdFplxdmLst.Count - 1 dobeginsFplxdm := oHdFplxdmLst.Strings[idx];if not oDBAPzxx.isClearCard(Sksblx, SksbNo, sFplxdm, sCardClock) thenbeginbCleared := False;Break;end;end;if bCleared thenbegin//已經(jīng)清卡WriteLog('金稅盤%s.%s已清卡,無需再次清卡。', [FNsrsbh, FMachineNo]);updateCzzt(oDBAJxsb, CZZT_CG, '已清卡,無需再執(zhí)行清卡操作。');result := true;Exit;end;//3 執(zhí)行清卡操作oJsCardRespClearCard := OJsCardComponent.clearCard;if not oJsCardRespClearCard.reportIsSucc thenbegin//清卡失敗errMsg := Format('清卡失敗:%s-%s', [oJsCardRespClearCard.Code, oJsCardRespClearCard.Mess]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;endelsebegin//清卡成功updateCzzt(oDBAJxsb, CZZT_CG, '');//更新金稅盤狀態(tài)if Assigned(oJsCardState) thenFreeAndNil(oJsCardState);oJsCardState := oJsCardComponent.queryTaxcardState(errMsg);if not Assigned(oJsCardState) thenbeginWriteLogError('更新金稅盤狀態(tài)信息失敗: %s', [errMsg]);updateCzzt(oDBAJxsb, CZZT_SB, errMsg);Exit;end;updateToDb(oDBAJxsb);oJsCardState.Pzxxs.saveToDb(Sksblx, SksbNo);result := true;end;finallyif Assigned(oJsCardComponent) then FreeAndNil(oJsCardComponent);if Assigned(oTaxCardRespOpenCard) thenFreeAndNil(oTaxCardRespOpenCard);if Assigned(oJsCardRespGetClock) thenFreeAndNil(oJsCardRespGetClock);if Assigned(oJsCardState) thenFreeAndNil(oJsCardState);if Assigned(oHdFplxdmLst) thenFreeAndNil(oHdFplxdmLst);if Assigned(oJsCardRespRep) thenFreeAndNil(oJsCardRespRep);if Assigned(oDBAJxsb) thenFreeAndNil(oDBAJxsb);if Assigned(oDBAPzxx) then FreeAndNil(oDBAPzxx);end; end;3.2 稅控盤組件核心代碼分享
??????? 稅控盤組件的抄稅和清卡相關的核心代碼,和金稅盤類似,筆者不再一一貼出代碼,有興趣或需求的朋友可以和筆者做進一步的溝通交流。
3.3 稅務UKey組件核心代碼分享
?????? 稅務UKey組件的抄稅和清卡相關的核心代碼,和金稅盤類似,筆者不再一一貼出代碼,有興趣或需求的朋友可以和筆者做進一步的溝通交流。
4. 后記
? ? ? ? 由于筆者認知和技術能力有限,文中難免存在不當或錯誤,歡迎批評指正。同時,筆者也殷切的期望,和各位朋友進行相關業(yè)務和技術等方面的交流,以期共同受益。
總結
以上是生活随笔為你收集整理的税盘的批量抄报税和批量清卡--支持金税盘,税控盘,税务UKey的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: htc328d屏幕排线怎么换_HTC T
- 下一篇: 金蝶K3采购价格管控杂谈