对账初步实现
diff --git a/config/application-devel-pg-xkx.properties b/config/application-devel-pg-xkx.properties
index 727f38f..3c10fe9 100644
--- a/config/application-devel-pg-xkx.properties
+++ b/config/application-devel-pg-xkx.properties
@@ -29,7 +29,7 @@
 shopbalance.updater.cron=-
 #download.ynrcc.chkfile.cron =3 0/2 * * * ?
 #query.third.transdtl.result.cron=7 0/1 * * * ?
-dayend.settletask.cron=0 0/2 * * * ?
+#dayend.settletask.cron=0 0/2 * * * ?
 #############################################
 spring.cloud.consul.enabled=false
 spring.cloud.consul.host=172.28.201.70
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/CheckFileProvider.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/CheckFileProvider.java
index 88c7f80..b8b3fa5 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/CheckFileProvider.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/CheckFileProvider.java
@@ -3,9 +3,9 @@
 import com.supwisdom.dlpay.api.domain.TSourceTypeCheckStatus;
 
 public interface CheckFileProvider {
-  AgentResponse<TSourceTypeCheckStatus> acquireCheckFile(String checkDate);
+  AgentResponse<TSourceTypeCheckStatus> acquireCheckFile(TSourceTypeCheckStatus checkStatus);
 
-  AgentResponse<TSourceTypeCheckStatus> queryCheckFile(String checkDate);
+  AgentResponse<TSourceTypeCheckStatus> queryCheckFile(TSourceTypeCheckStatus checkStatus);
 
-  AgentResponse<TSourceTypeCheckStatus> downloadCheckFile(String checkDate);
+  AgentResponse<TSourceTypeCheckStatus> downloadCheckFile(TSourceTypeCheckStatus checkStatus);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java
index f516373..c04f3f3 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java
@@ -1,13 +1,18 @@
 package com.supwisdom.dlpay.api.dao;
 
 import com.supwisdom.dlpay.api.domain.TPersondtl;
+import com.supwisdom.dlpay.framework.data.CountAmountBean;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 
 @Repository
 public interface PersondtlDao extends JpaRepository<TPersondtl, String>,JpaSpecificationExecutor<TPersondtl> {
     Page<TPersondtl> findByUseridAndStatus(String userid,String status, Pageable pageable);
+
+    @Query("select count(t.refno) as totalcnt,sum(t.amount) as totalamt from TPersondtl t where t.accdate=?1 and t.sourceType=?2 and t.tenantid=?3 ")
+    CountAmountBean getPersondtlSumInfo(String accdate, String sourcetype, String tenantid);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java
index 1896786..122ce76 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java
@@ -1,12 +1,17 @@
 package com.supwisdom.dlpay.api.dao;
 
+import com.supwisdom.dlpay.api.domain.TPersondtl;
 import com.supwisdom.dlpay.api.domain.TTransactionChkdtl;
 import com.supwisdom.dlpay.framework.data.CountAmountBean;
+import com.supwisdom.dlpay.framework.data.ExistBean;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface TransactionChkdtlDao extends JpaRepository<TTransactionChkdtl, String> {
 
@@ -17,4 +22,18 @@
   @Query("select count(t.id) as totalcnt,sum(t.amount) as totalamt from TTransactionChkdtl t where t.accdate=?1 and t.sourcetype=?2 ")
   CountAmountBean getTransactionSumInfo(String accdate, String sourcetype);
 
+  @Query("select a from TTransactionChkdtl a,TPersondtl b where a.localRefno=b.refno and a.sourcetype=b.sourceType and a.accdate=b.accdate and a.amount=b.amount " +
+      " and a.otherStatus='success' and b.status='success' order by a.recordno ")
+  List<TTransactionChkdtl> getCheckEqualDetails(String chkfileId);
+
+  @Query("from TTransactionChkdtl t where t.chkfileId=?1 and t.chkresult='uncheck' order by t.recordno ")
+  List<TTransactionChkdtl> getUncheckTransactionChkdtls(String chkfileId);
+
+  @Query("select count(t.id) as existed from TTransactionChkdtl t where t.chkfileId=?1 and t.chkresult='uncheck' ")
+  ExistBean getUncheckCount(String chkfileId);
+
+  @Query(value = "select t.refno from TB_PERSONDTL t left join TB_TRANSACTION_CHKDTL a on t.REFNO=a.OTHER_REFNO and a.CHKFILE_ID=:chkfileId " +
+      " where t.ACCDATE=:accdate and t.SOURCETYPE=:sourcetype and t.status='success' and a.id is null order by t.refno ", nativeQuery = true)
+  List<String> findLocalMoreDtls(@Param("accdate")String accdate, @Param("sourcetype")String sourcetype, @Param("chkfileId") String chkfileId);
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TSourceTypeCheckStatus.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TSourceTypeCheckStatus.java
index 4a4f41c..bad55b9 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TSourceTypeCheckStatus.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TSourceTypeCheckStatus.java
@@ -48,6 +48,12 @@
   @NotNull
   private String tenantId;
 
+  @Column(name = "chkfile_url", length = 400)
+  private String chkfileUrl;
+
+  @Column(name = "remark", length = 600)
+  private String remark;
+
   public Integer getId() {
     return id;
   }
@@ -127,4 +133,20 @@
   public void setCheckStatus(Boolean checkStatus) {
     this.checkStatus = checkStatus;
   }
+
+  public String getChkfileUrl() {
+    return chkfileUrl;
+  }
+
+  public void setChkfileUrl(String chkfileUrl) {
+    this.chkfileUrl = chkfileUrl;
+  }
+
+  public String getRemark() {
+    return remark;
+  }
+
+  public void setRemark(String remark) {
+    this.remark = remark;
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java
index 422d766..f5dc80e 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java
@@ -57,6 +57,7 @@
   @Column(name = "RESOLVED", length = 20)
   private String resolved;
 
+  @Version
   @Column(name = "LASTSAVED")
   private Timestamp lastsaved;
 
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
index c7b479c..7d7e809 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
@@ -53,9 +53,11 @@
    * 对账明细状态
    * */
   public static final String CHKDTL_CHKRESULT_UNCHECK= "uncheck"; //未检查
-  public static final String CHKDTL_CHKRESULT_NEGATION= "negation"; //交易流水不存在
+  public static final String CHKDTL_CHKRESULT_EQUAL= "equal"; //一致
+  public static final String CHKDTL_CHKRESULT_NOTEXIST= "notexist"; //交易流水不存在
   public static final String CHKDTL_CHKRESULT_NOCHARGE = "nocharge"; //支付未记账
   public static final String CHKDTL_CHKRESULT_DIFF = "diff"; //金额不相等
+  public static final String CHKDTL_CHKRESULT_ERROR = "error"; //记账日期或支付方式错误
 
   /**
    * 对账明细解决状态
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/citizencard_checkfile_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/citizencard_checkfile_service.kt
new file mode 100644
index 0000000..615db40
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/citizencard_checkfile_service.kt
@@ -0,0 +1,260 @@
+package com.supwisdom.dlpay.agent.service
+
+import com.sun.jersey.api.client.Client
+import com.sun.jersey.api.client.ClientResponse
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.CheckFileProvider
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
+import com.supwisdom.dlpay.api.domain.TSourceTypeCheckStatus
+import com.supwisdom.dlpay.api.domain.TTransactionChkfile
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.api.service.TransactionReconciliationService
+import com.supwisdom.dlpay.exception.TransactionException
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.util.ConstantUtil
+import mu.KotlinLogging
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Component
+import java.io.BufferedReader
+import java.io.InputStream
+import java.io.InputStreamReader
+import javax.ws.rs.core.MediaType
+
+@Component("citizenCardCheckFileProvider")
+class CitizenCardCheckFileProvider : CheckFileProvider {
+    @Autowired
+    private lateinit var systemUtilService: SystemUtilService
+    @Autowired
+    private lateinit var transactionReconciliationService: TransactionReconciliationService
+    @Autowired
+    private lateinit var citizencardPayService: CitizencardPayService
+    @Autowired
+    private lateinit var sourceTypeService: SourceTypeService
+
+    private val logger = KotlinLogging.logger { }
+
+
+    override fun acquireCheckFile(checkStatus: TSourceTypeCheckStatus): AgentResponse<TSourceTypeCheckStatus> {
+        try {
+            val billDate = checkStatus.checkFileDate
+            logger.info("大理农商行对账单下载:download checkdate=【$billDate】")
+
+            val chkfile: TTransactionChkfile = transactionReconciliationService.getTransactionChkfile(billDate, checkStatus.sourceType)?.let { file ->
+                when (file.status) {
+                    ConstantUtil.CHKFILE_STATUS_INIT -> file //初始化直接返回
+                    ConstantUtil.CHKFILE_STATUS_ERROR, ConstantUtil.CHKFILE_STATUS_UNCHECK -> reinitCheckFile(file) //错误或未对账的直接重新拉取
+                    else -> {
+                        when (checkStatus.forceRecheck) {
+                            true -> reinitCheckFile(file) //对账已完成但强制重新对账
+                            false -> throw TransactionException(-1, "大理农商行该天[$billDate]已对账完成") //对账已完成报错
+                        }
+                    }
+                }
+            } ?: transactionReconciliationService.saveInitTransactionChkfile(billDate, checkStatus.sourceType)
+
+            val resp = citizencardPayService.getChkfilename(billDate, null)
+            when(resp.code) {
+                YnrccUtil.CODE_SUCCESS -> {
+                    val agentConfig = sourceTypeService.getChargePaytypeConfig(TradeDict.PAYTYPE_CITIZEN_CARD, true)
+                    val agentUrl = agentConfig[YnrccUtil.YNRCC_ANGENT_URL] + "/download?filename=" + resp.filename
+
+                    //成功
+                    return AgentResponse<TSourceTypeCheckStatus>().also {
+                        it.code = AgentCode.SUCCESS
+                        it.agentMsg = "获取对账文件路径成功"
+                        it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                            this.chkfileUrl = agentUrl
+                        })
+                    }
+
+                }
+                YnrccUtil.NO_RECORDS_TODAY -> {
+                    //当日无交易明细,也创建空记录
+                    transactionReconciliationService.doSuccessTransactionChkfile(chkfile, "请求银行返回:当日无交易明细")
+
+                    //成功
+                    return AgentResponse<TSourceTypeCheckStatus>().also {
+                        it.code = AgentCode.SUCCESS
+                        it.agentMsg = "当日无交易明细"
+                        it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                            this.chkfileUrl = "none"
+                        })
+                    }
+
+                }
+                else -> {
+                    //报错,退出对账单拉取
+                    logger.error("大理农商行对账单下载[$billDate]报错:${resp.message}")
+                    chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                    chkfile.remark = "请求前置获取对账文件报错:${resp.message}"
+                    transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+
+                    //失败
+                    return AgentResponse<TSourceTypeCheckStatus>().also {
+                        it.code = AgentCode.FAIL
+                        it.agentMsg = chkfile.remark
+                        it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                            this.remark = chkfile.remark
+                        })
+                    }
+                }
+            }
+        } catch (et: TransactionException) {
+            return AgentResponse<TSourceTypeCheckStatus>().also {
+                it.code = AgentCode.FAIL
+                it.agentMsg = et.message
+                it.agentCode = "${et.code()}"
+                it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                    this.remark = et.message
+                })
+            }
+        }
+    }
+
+    override fun queryCheckFile(checkStatus: TSourceTypeCheckStatus): AgentResponse<TSourceTypeCheckStatus> {
+        return AgentResponse<TSourceTypeCheckStatus>().also {
+            it.code = AgentCode.SUCCESS
+            it.agentMsg = "OK"
+            it.payload = checkStatus
+        }
+    }
+
+    override fun downloadCheckFile(checkStatus: TSourceTypeCheckStatus): AgentResponse<TSourceTypeCheckStatus> {
+        try{
+            val billDate = checkStatus.checkFileDate
+            val agentUrl = checkStatus.chkfileUrl
+            if ("none" == agentUrl) {
+                return AgentResponse<TSourceTypeCheckStatus>().also {
+                    it.code = AgentCode.SUCCESS
+                    it.agentMsg = "当日无交易明细"
+                    it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                        this.checkFileOk = true
+                        this.remark = "当日无交易明细"
+                    })
+                }
+            }
+
+            val chkfile = transactionReconciliationService.doInitTransactionChkfile(billDate, checkStatus.sourceType)
+
+            //下载对账单数据
+            val client = Client.create()
+            client.setConnectTimeout(30000)
+            val respClient = client.resource(agentUrl).type(MediaType.APPLICATION_OCTET_STREAM_TYPE).get(ClientResponse::class.java)
+            if (200 == respClient.status) {
+                val stream = respClient.getEntity(InputStream::class.java)
+                BufferedReader(InputStreamReader(stream)).use { reader ->
+                    val header = reader.readLine()
+                    val fields = header.split(",").mapNotNull { if (it.isNotEmpty()) it else null }
+                    val batchSize = 10000 //每次保存的数目
+                    var failcnt = 0
+
+                    val datalist = ArrayList<YnrccChkfileBean>()
+                    while (true) {
+                        val line = reader.readLine() ?: break
+                        if (line.isEmpty()) continue
+                        val columns = line.split(",").mapNotNull { if (it.isNotEmpty()) it else null }
+                        val bean = YnrccChkfileBean()
+                        StringUtil.transforToBean(fields, columns, bean)
+                        datalist.add(bean)
+                        if (datalist.size >= batchSize) {
+                            val fcnt = doBatchSaveYnrccCheckDetails(chkfile, datalist) //保存
+                            failcnt += fcnt
+                            datalist.clear()
+                        }
+                    }
+                    //保存最后的不足batchSize的记录
+                    if (datalist.size > 0) {
+                        val fcnt = doBatchSaveYnrccCheckDetails(chkfile, datalist) //保存
+                        failcnt += fcnt
+                    }
+
+                    if (failcnt > 0) {
+                        //该天对账单保存错误
+                        chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                        chkfile.remark = "对账单数据存在保存失败记录,请手动核对对账单数据"
+                        transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+
+                        return AgentResponse<TSourceTypeCheckStatus>().also {
+                            it.code = AgentCode.FAIL
+                            it.agentMsg = chkfile.remark
+                            it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                                this.remark = chkfile.remark
+                            })
+                        }
+                    }
+
+                    //成功
+                    transactionReconciliationService.doSuccessTransactionChkfile(chkfile, "对账单数据下载成功")
+                    return AgentResponse<TSourceTypeCheckStatus>().also {
+                        it.code = AgentCode.SUCCESS
+                        it.agentMsg = "[$billDate]日对账数据入库成功"
+                        it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                            this.checkFileOk = true
+                            this.remark = "[$billDate]日对账数据入库成功"
+                        })
+                    }
+                }
+            } else {
+                logger.error("请求前置download[${chkfile.accdate}]对账单返回失败:httpStatus=[${respClient.status}]。获取对账文件数据失败")
+                chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                chkfile.remark = "请求前置获取对账单数据失败,download返回:httpStatus=${respClient.status}"
+                transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+
+                return AgentResponse<TSourceTypeCheckStatus>().also {
+                    it.code = AgentCode.FAIL
+                    it.agentMsg = chkfile.remark
+                    it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                        this.remark = chkfile.remark
+                    })
+                }
+            }
+
+        }catch (ex:Exception){
+            return AgentResponse<TSourceTypeCheckStatus>().also {
+                it.code = AgentCode.FAIL
+                it.agentMsg = ex.message?:"按对账单路径获取对账数据入库异常"
+                it.payload = checkStatus
+            }
+        }
+    }
+
+    private fun reinitCheckFile(chkfile: TTransactionChkfile): TTransactionChkfile {
+        transactionReconciliationService.deleteTransactionChkdtls(chkfile.id) //删除明细
+        return transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile.apply {
+            this.status = ConstantUtil.CHKFILE_STATUS_INIT
+            this.result = ConstantUtil.CHKFILE_RESULT_NONE
+            this.remark = null
+            this.othercnt = 0
+            this.otheramt = 0.00
+            this.localcnt = 0
+            this.localamt = 0.00
+        }) //初始化chkfile
+    }
+
+    private fun doBatchSaveYnrccCheckDetails(chkfile: TTransactionChkfile, list: ArrayList<YnrccChkfileBean>): Int {
+        try {
+            transactionReconciliationService.doBatchSaveYnrccTransactionChkDtl(chkfile, list)
+            return 0  //批量保存成功,无失败
+        } catch (e1: Exception) {
+        }
+
+        //批量保存有异常,逐笔保存
+        var failcnt = 0
+        for (bean in list) {
+            try {
+                transactionReconciliationService.saveYnrccTransactionChkDtl(chkfile, bean)
+            } catch (e2: Exception) {
+                failcnt++
+                e2.printStackTrace()
+                continue
+            }
+        }
+        return failcnt
+    }
+
+
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt
index 3f895f9..4a552f8 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt
@@ -5,9 +5,13 @@
 import com.supwisdom.dlpay.agent.CheckFileProvider
 import com.supwisdom.dlpay.api.domain.TSourceType
 import com.supwisdom.dlpay.api.domain.TSourceTypeCheckStatus
+import com.supwisdom.dlpay.api.domain.TTransactionChkfile
 import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.api.service.TransactionReconciliationService
+import com.supwisdom.dlpay.exception.TransactionException
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.util.ConstantUtil
 import mu.KotlinLogging
 import net.javacrumbs.shedlock.core.SchedulerLock
 import org.springframework.beans.BeansException
@@ -159,6 +163,12 @@
     @Autowired
     private lateinit var applicationContext: ApplicationContext
 
+    @Autowired
+    private lateinit var transactionReconciliationService: TransactionReconciliationService
+
+    @Autowired
+    private lateinit var sourceTypeService: SourceTypeService
+
     private val logger = KotlinLogging.logger { }
 
     private fun getProvider(sourcetype: String): CheckFileProvider? {
@@ -171,7 +181,7 @@
     }
 
     private fun downloadFile(provider: CheckFileProvider, checkStatus: TSourceTypeCheckStatus): ExecutorResult {
-        return provider.downloadCheckFile(checkStatus.checkFileDate).let { resp ->
+        return provider.downloadCheckFile(checkStatus).let { resp ->
             when {
                 resp.code == AgentCode.SUCCESS -> ExecutorResult(resp.payload, SUCCESS, "成功")
                 resp.code == AgentCode.REQUIRE_QUERY -> ExecutorResult(resp.payload, WAIT, "等待查询对账文件")
@@ -183,37 +193,86 @@
     @Async("sourcetypeCheckTaskExecutor")
     fun checkAndDownloadChkfile(checkStatus: TSourceTypeCheckStatus): Future<ExecutorResult> {
         // 2. 根据对账日期下载对账文件
-        val result = getProvider(checkStatus.sourceType)?.let { provider ->
-            val acResp = provider.acquireCheckFile(checkStatus.checkFileDate)
-            if (acResp.code == AgentCode.REQUIRE_QUERY) {
-                var success: AgentResponse<TSourceTypeCheckStatus> =
-                        AgentResponse<TSourceTypeCheckStatus>().apply {
-                            code = AgentCode.FAIL
+        try {
+            val result = getProvider(checkStatus.sourceType)?.let { provider ->
+                val acResp = provider.acquireCheckFile(checkStatus)
+                if (acResp.code == AgentCode.REQUIRE_QUERY) {
+                    var success: AgentResponse<TSourceTypeCheckStatus> =
+                            AgentResponse<TSourceTypeCheckStatus>().apply {
+                                code = AgentCode.FAIL
+                            }
+                    repeat(10) {
+                        if (success.code != AgentCode.SUCCESS) {
+                            Thread.sleep(3000)
+                            success = provider.queryCheckFile(checkStatus)
                         }
-                repeat(10) {
-                    if (success.code != AgentCode.SUCCESS) {
-                        Thread.sleep(3000)
-                        success = provider.queryCheckFile(checkStatus.checkFileDate)
                     }
-                }
-                if (success.code == AgentCode.SUCCESS) {
-                    downloadFile(provider, success.payload)
+                    if (success.code == AgentCode.SUCCESS) {
+                        downloadFile(provider, success.payload)
+                    } else {
+                        ExecutorResult(checkStatus, FAIL, "下载失败,未能查到对账文件")
+                    }
+                } else if (acResp.code == AgentCode.SUCCESS) {
+                    downloadFile(provider, acResp.payload)
                 } else {
-                    ExecutorResult(checkStatus, FAIL, "下载失败,未能查到对账文件")
+                    ExecutorResult(checkStatus, FAIL, acResp.agentMsg)
                 }
-            } else if (acResp.code == AgentCode.SUCCESS) {
-                downloadFile(provider, acResp.payload)
-            } else {
-                ExecutorResult(checkStatus, FAIL, acResp.agentMsg)
-            }
-        } ?: ExecutorResult(checkStatus, FAIL, "未定义 CheckFileProvider")
-        return AsyncResult(result)
+            } ?: ExecutorResult(checkStatus, FAIL, "未定义 CheckFileProvider")
+            return AsyncResult(result)
+        } catch (ex: Exception) {
+            return AsyncResult(ExecutorResult(checkStatus, FAIL, ex.message ?: "下载对账单异常"))
+        }
+
     }
 
     @Async("sourcetypeCheckTaskExecutor")
     fun reconciliation(checkStatus: TSourceTypeCheckStatus): Future<ExecutorResult> {
         // 3. 完成对账
-        TODO("实现对账逻辑")
-//        return AsyncResult(ExecutorResult(checkStatus, SUCCESS, "成功"))
+        val result = transactionReconciliationService.getTransactionChkfile(checkStatus.checkAccdate, checkStatus.sourceType)?.let { chkfile ->
+            if (ConstantUtil.CHKFILE_STATUS_UNCHECK == chkfile.status) {
+                //TODO:"实现对账逻辑"
+                try {
+                    when (doCheckProcess(chkfile).result) {
+                        ConstantUtil.CHKFILE_RESULT_EQUAL -> {
+                            checkStatus.checkStatus = true //对账成功
+                            sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus)
+                            ExecutorResult(checkStatus, SUCCESS, "对账成功,双方一致")
+                        }
+                        else -> ExecutorResult(checkStatus, FAIL, "对账不平")
+                    }
+                } catch (ex: Exception) {
+                    ex.printStackTrace()
+                    ExecutorResult(checkStatus, FAIL, "对账异常")
+                }
+            } else {
+                ExecutorResult(checkStatus, FAIL, "[${checkStatus.checkAccdate}]日入库的checkfile状态异常[${chkfile.status}]")
+            }
+        } ?: ExecutorResult(checkStatus, FAIL, "未找到[${checkStatus.checkAccdate}]日入库的对账数据")
+        return AsyncResult(result)
     }
+
+    fun doCheckProcess(chkfile: TTransactionChkfile): TTransactionChkfile {
+        try {
+            //统一处理交易一致的记录
+            transactionReconciliationService.doCheckEqualTransdtls(chkfile)
+        } catch (e1: Exception) {
+        }
+
+        //剩余的不平记录逐一对比
+        transactionReconciliationService.getUncheckTransactionChkdtls(chkfile.id).forEach {
+            transactionReconciliationService.doCheckTransactionChkdtl(it)
+        }
+
+        //判断chkdtl是否全部对账完成
+        if (transactionReconciliationService.checkUncheckExists(chkfile.id)) {
+            throw TransactionException(-2, "存在未对账的明细记录")
+        }
+
+        //判断本地是否有多余成功流水,并保存
+        transactionReconciliationService.doCheckLocalMoreDtls(chkfile)
+
+        return transactionReconciliationService.doConfirmChkfileStatus(chkfile)
+    }
+
+
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt
index 7e28739..b1bc339 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt
@@ -48,8 +48,8 @@
     private val logger = KotlinLogging.logger { }
 
 
-    @Scheduled(cron = "\${download.ynrcc.chkfile.cron:-}")
-    @SchedulerLock(name = "DownloadYnrccChkfileSchedulerTask", lockAtMostForString = "PT10M")
+//    @Scheduled(cron = "\${download.ynrcc.chkfile.cron:-}")
+//    @SchedulerLock(name = "DownloadYnrccChkfileSchedulerTask", lockAtMostForString = "PT10M")
     fun doDownloadYnrccChkfile() {
         try {
             if (null == TenantContext.getTenantSchema()) TenantContext.setTenantSchema(Constants.DEFAULT_TENANTID)
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt
index 6e6ade4..af77132 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt
@@ -1,6 +1,5 @@
 package com.supwisdom.dlpay.api.service.impl
 
-import com.supwisdom.dlpay.api.dao.DebitCreditDtlDao
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
 import com.supwisdom.dlpay.api.domain.*
 import com.supwisdom.dlpay.api.repositories.AccountService
@@ -10,11 +9,9 @@
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.DateUtil
 import com.supwisdom.dlpay.framework.util.Subject
-import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeDict.DTL_STATUS_SUCCESS
 import com.supwisdom.dlpay.framework.util.TradeDict.TRADE_FLAG_OUT
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
-import org.hibernate.Transaction
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Repository
 import org.springframework.stereotype.Service
@@ -125,6 +122,9 @@
         if (shopdtl.updateBala) {
             return
         }
+        if (shopdtl.status != DTL_STATUS_SUCCESS) {
+            return
+        }
         val amount = transactionMainDao.findByRefno(refno)?.sumAmountByAccno(shopdtl.shopaccno,
                 Subject.SUBJNO_MACHANT_INCOME, "both")
                 ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt
index d900687..be112d1 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt
@@ -2,15 +2,20 @@
 
 import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
 import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
+import com.supwisdom.dlpay.api.dao.PersondtlDao
 import com.supwisdom.dlpay.api.dao.TransactionChkdtlDao
 import com.supwisdom.dlpay.api.dao.TransactionChkfileDao
+import com.supwisdom.dlpay.api.dao.TransactionMainDao
 import com.supwisdom.dlpay.api.domain.TTransactionChkdtl
 import com.supwisdom.dlpay.api.domain.TTransactionChkfile
 import com.supwisdom.dlpay.api.service.TransactionReconciliationService
+import com.supwisdom.dlpay.api.service.TransactionServiceProxy
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.framework.dao.BusinessparaDao
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.tenant.TenantContext
+import com.supwisdom.dlpay.framework.util.MoneyUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import com.supwisdom.dlpay.util.ConstantUtil
 import org.springframework.beans.factory.annotation.Autowired
@@ -26,6 +31,12 @@
     private lateinit var systemUtilService: SystemUtilService
     @Autowired
     private lateinit var businessparaDao: BusinessparaDao
+    @Autowired
+    private lateinit var transactionMainDao: TransactionMainDao
+    @Autowired
+    private lateinit var persondtlDao: PersondtlDao
+    @Autowired
+    private lateinit var transactionService: TransactionServiceProxy
 
     override fun getTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile? {
         return transactionChkfileDao.getByAccdateAndSourcetype(accdate, sourcetype)
@@ -38,25 +49,13 @@
                     throw TransactionCheckException(TradeErrorCode.BUSINESS_DEAL_ERROR, "accdate=$accdate,sourcetype=$sourcetype 的chkfile已经存在")
                 it
             } else {
-                transactionChkfileDao.save(TTransactionChkfile().apply {
-                    this.accdate = accdate
-                    this.sourcetype = sourcetype
-                    this.status = ConstantUtil.CHKFILE_STATUS_INIT
-                    this.result = ConstantUtil.CHKFILE_RESULT_NONE
-                    this.remark = null
-                    this.othercnt = 0
-                    this.otheramt = 0.00
-                    this.localcnt = 0
-                    this.localamt = 0.00
-                    this.lastsaved = systemUtilService.sysdatetime.sysdate
-                    this.tenantid = TenantContext.getTenantSchema()
-                }) //保存init对账文件
+                saveInitTransactionChkfile(accdate, sourcetype) //保存init对账文件
             }
         }
     }
 
-    override fun saveOrUpdateTransactionChkfile(chkfile: TTransactionChkfile) {
-        transactionChkfileDao.save(chkfile)
+    override fun saveOrUpdateTransactionChkfile(chkfile: TTransactionChkfile): TTransactionChkfile {
+        return transactionChkfileDao.save(chkfile)
     }
 
     override fun saveYnrccTransactionChkDtl(chkfile: TTransactionChkfile, bean: YnrccChkfileBean): TTransactionChkdtl {
@@ -97,4 +96,134 @@
         businessparaDao.updateBusinessparaValue(YnrccUtil.YNRCC_BILLS_DOWNLOAD_LASTDATE, chkfile.accdate) //更新下载对账单日期
     }
 
+    override fun deleteTransactionChkdtls(chkfileId: String) {
+        transactionChkdtlDao.deleteByChkfileid(chkfileId)
+    }
+
+    override fun saveInitTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile {
+        return transactionChkfileDao.save(TTransactionChkfile().apply {
+            this.accdate = accdate
+            this.sourcetype = sourcetype
+            this.status = ConstantUtil.CHKFILE_STATUS_INIT
+            this.result = ConstantUtil.CHKFILE_RESULT_NONE
+            this.remark = null
+            this.othercnt = 0
+            this.otheramt = 0.00
+            this.localcnt = 0
+            this.localamt = 0.00
+            this.lastsaved = systemUtilService.sysdatetime.sysdate
+            this.tenantid = TenantContext.getTenantSchema()
+        })
+    }
+
+    override fun doCheckEqualTransdtls(chkfile: TTransactionChkfile) {
+        //所有一致的记录,一次任务处理
+        transactionChkdtlDao.getCheckEqualDetails(chkfile.id)?.forEach { chkdtl ->
+            chkdtl.chkresult = ConstantUtil.CHKDTL_CHKRESULT_EQUAL
+            chkdtl.resolved = ConstantUtil.CHKDTL_RESOLVED_EQUAL
+            chkdtl.remark = "双方交易一致"
+            transactionChkdtlDao.save(chkdtl) //对账明细表更新
+
+            transactionService.checkSuccessConfirm(chkdtl.localRefno, chkdtl.otherAccdate)
+        }
+    }
+
+    override fun getUncheckTransactionChkdtls(chkfileId: String): List<TTransactionChkdtl> {
+        return transactionChkdtlDao.getUncheckTransactionChkdtls(chkfileId) ?: ArrayList<TTransactionChkdtl>(0)
+    }
+
+    override fun doCheckTransactionChkdtl(chkdtl: TTransactionChkdtl) {
+        val transMain = transactionMainDao.findByRefno(chkdtl.localRefno)
+
+        if (null == transMain || !transMain.person) {
+            chkdtl.chkresult = ConstantUtil.CHKDTL_CHKRESULT_NOTEXIST
+            chkdtl.resolved = ConstantUtil.CHKDTL_RESOLVED_HANGUP
+            chkdtl.remark = "本地流水不存在"
+            transactionChkdtlDao.save(chkdtl) //对账明细表更新
+        }
+
+        if(!MoneyUtil.moneyEqual(chkdtl.amount,transMain.personDtl.amount)){
+            chkdtl.chkresult = ConstantUtil.CHKDTL_CHKRESULT_DIFF
+            chkdtl.resolved = ConstantUtil.CHKDTL_RESOLVED_HANGUP
+            chkdtl.remark = "交易金额不相等"
+            transactionChkdtlDao.save(chkdtl) //对账明细表更新
+        }
+
+        if(transMain.accdate!=chkdtl.accdate || transMain.sourceType != chkdtl.sourcetype){
+            //TODO: 数据异常??
+            chkdtl.chkresult = ConstantUtil.CHKDTL_CHKRESULT_ERROR
+            chkdtl.resolved = ConstantUtil.CHKDTL_RESOLVED_HANGUP
+            chkdtl.remark = "记账日期或支付方式错误"
+            transactionChkdtlDao.save(chkdtl) //对账明细表更新
+        }
+
+        if (transMain.status == TradeDict.DTL_STATUS_SUCCESS) {
+            chkdtl.chkresult = ConstantUtil.CHKDTL_CHKRESULT_EQUAL
+            chkdtl.resolved = ConstantUtil.CHKDTL_RESOLVED_EQUAL
+            chkdtl.remark = "双方交易一致"
+            transactionChkdtlDao.save(chkdtl) //对账明细表更新
+
+            transactionService.checkSuccessConfirm(chkdtl.localRefno, chkdtl.otherAccdate)
+        } else {
+            //补账
+            transactionService.repair(transMain.refno, chkdtl.otherAccdate, chkdtl.otherRefno, "补账成功")
+
+            chkdtl.chkresult = ConstantUtil.CHKDTL_CHKRESULT_NOCHARGE
+            chkdtl.resolved = ConstantUtil.CHKDTL_RESOLVED_EQUAL
+            chkdtl.remark = "本地未入账,补账成功"
+            transactionChkdtlDao.save(chkdtl) //对账明细表更新
+        }
+    }
+
+    override fun checkUncheckExists(chkfileId: String): Boolean {
+        return transactionChkdtlDao.getUncheckCount(chkfileId).existed > 0
+    }
+
+    override fun doCheckLocalMoreDtls(chkfile: TTransactionChkfile) {
+        transactionChkdtlDao.findLocalMoreDtls(chkfile.accdate, chkfile.sourcetype, chkfile.id)?.forEach { refno ->
+            //保存多余的记录
+            transactionMainDao.findByRefno(refno)?.let { transMain ->
+                if (TradeDict.DTL_STATUS_SUCCESS == transMain.status && transMain.accdate == chkfile.accdate && transMain.sourceType == chkfile.sourcetype) {
+                    transactionChkdtlDao.save(TTransactionChkdtl().apply {
+                        this.chkfileId = chkfile.id
+                        this.accdate = chkfile.accdate
+                        this.sourcetype = chkfile.sourcetype
+                        this.recordno = null
+                        this.amount = transMain.personDtl.amount
+                        this.otherRefno = transMain.reverseRefno ?: "0"
+                        this.localRefno = transMain.refno
+                        this.otherAccdate = transMain.accdate
+                        this.transtype = when (transMain.reverseType) {
+                            "none" -> "pay"
+                            else -> transMain.reverseType
+                        }
+                        this.otherStatus = "unknown"
+                        this.remark = "本地成功流水第三方流水不存在"
+                        this.extdata = transMain.personDtl.transdesc
+                        this.chkresult = ConstantUtil.CHKDTL_CHKRESULT_NOTEXIST
+                        this.resolved = ConstantUtil.CHKDTL_RESOLVED_HANGUP
+                        this.lastsaved = systemUtilService.sysdatetime.sysdate
+                        this.tenantid = chkfile.tenantid
+                    }) //保存本地多出的记录
+                }
+            }
+        }
+    }
+
+    override fun doConfirmChkfileStatus(chkfile: TTransactionChkfile): TTransactionChkfile {
+        val personSumInfo = persondtlDao.getPersondtlSumInfo(chkfile.accdate, chkfile.sourcetype, chkfile.tenantid)
+        chkfile.localcnt = personSumInfo.totalcnt ?: 0
+        chkfile.localamt = personSumInfo.totalamt ?: 0.00
+        chkfile.status = ConstantUtil.CHKFILE_STATUS_finish  //对账结束
+        if (chkfile.othercnt == chkfile.localcnt && MoneyUtil.moneyEqual(chkfile.otheramt, chkfile.localamt)) {
+            //fixme: 是否还需判断chkdtl中resolved是否都equal
+            chkfile.result = ConstantUtil.CHKFILE_RESULT_EQUAL
+            chkfile.remark = "对账完成,双方一致"
+        } else {
+            chkfile.result = ConstantUtil.CHKFILE_RESULT_UNEQUAL
+            chkfile.remark = "对账不平,请查看明细数据"
+        }
+        transactionChkfileDao.save(chkfile)
+        return chkfile
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
index eb74c4c..b708983 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
@@ -379,11 +379,11 @@
                     ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
                             "系统异常,无法处理退款流水")
             originTrans.reverseFlag = transaction.reverseType
-            if(originTrans.person){
+            if (originTrans.person) {
                 originTrans.personDtl.reverseFlag = originTrans.reverseFlag
                 originTrans.personDtl.reverseAmount = originTrans.refundAmount
             }
-            if(originTrans.shop){
+            if (originTrans.shop) {
                 originTrans.shopDtl.reverseFlag = originTrans.reverseFlag
             }
             transactionMainDao.save(originTrans)
@@ -391,8 +391,8 @@
 
         transaction.endTime = systemUtilService.sysdatetime.sysdate
         transactionMainDao.save(transaction)
-        if(transaction.person&&!transaction.personDtl.userid.isNullOrEmpty()){
-            kafkaSendMsgService.sendJpushMessage(transaction.personDtl.userid,"交易提醒","你有一笔${transaction.personDtl.amount}元的支出,点击查看详情",transaction.refno, mutableMapOf(),transaction.tenantid)
+        if (transaction.person && !transaction.personDtl.userid.isNullOrEmpty()) {
+            kafkaSendMsgService.sendJpushMessage(transaction.personDtl.userid, "交易提醒", "你有一笔${transaction.personDtl.amount}元的支出,点击查看详情", transaction.refno, mutableMapOf(), transaction.tenantid)
         }
         return transaction
     }
@@ -504,7 +504,7 @@
                     -it.amount, "${it.summary}$summarySuffix")
         }
         builder.dtltype = originTrans.dtltype
-        if(builder.operId.isNullOrEmpty()){
+        if (builder.operId.isNullOrEmpty()) {
             builder.operator(originTrans.operid, originTrans.opertype)
         }
         return builderRecords(builder, TradeDict.DTL_STATUS_INIT)
@@ -533,7 +533,19 @@
         }
     }
 
-    override fun repair(refno: String, remark: String): TTransactionMain {
+    override fun checkSuccessConfirm(refno: String, agentAccdate: String): TTransactionMain {
+        val transMain = transactionMainDao.findByRefnoForUpdate(refno)
+                ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
+                        "本地流水<$refno>不存在")
+        transMain.settleDate = agentAccdate
+        transMain.details?.forEach {
+            it.settleDate = agentAccdate
+        }
+        transactionMainDao.save(transMain)
+        return transMain
+    }
+
+    override fun repair(refno: String, agentAccdate: String, sourcetypeRefno: String, remark: String): TTransactionMain {
         val transaction = transactionMainDao.findByRefnoForUpdate(refno)
                 ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
                         "补帐交易流水<$refno>不存在")
@@ -545,8 +557,22 @@
                     "补帐交易<$refno>状态错误,status<${transaction.status}>")
         }
 
-        transactionOnSuccess(transaction, remark, true)
-        transaction.checkDate = systemUtilService.accdate
+        transaction.status = TradeDict.DTL_STATUS_SUCCESS //置为成功
+        transactionOnSuccess(transaction, sourcetypeRefno, true)
+//        transaction.checkDate = systemUtilService.accdate
+        transaction.settleDate = agentAccdate
+        transaction.details?.forEach {
+            it.settleDate = agentAccdate
+        }
+        if(transaction.person){
+            transaction.personDtl.remark = remark
+        }
+        if(transaction.shop){
+            transaction.personDtl.remark = remark
+        }
+        if(transaction.subject){
+            //
+        }
         transaction.endTime = systemUtilService.sysdatetime.sysdate
 
         transactionMainDao.save(transaction)
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt
index 8147a59..c2935c5 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt
@@ -13,7 +13,7 @@
     fun doInitTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile
 
     @Transactional(rollbackFor = [Exception::class])
-    fun saveOrUpdateTransactionChkfile(chkfile: TTransactionChkfile)
+    fun saveOrUpdateTransactionChkfile(chkfile: TTransactionChkfile): TTransactionChkfile
 
     @Transactional(rollbackFor = [Exception::class])
     fun saveYnrccTransactionChkDtl(chkfile: TTransactionChkfile, bean: YnrccChkfileBean): TTransactionChkdtl
@@ -22,6 +22,30 @@
     fun doBatchSaveYnrccTransactionChkDtl(chkfile: TTransactionChkfile, list: ArrayList<YnrccChkfileBean>): Boolean
 
     @Transactional(rollbackFor = [Exception::class])
-    fun doSuccessTransactionChkfile(chkfile: TTransactionChkfile, remark:String)
+    fun doSuccessTransactionChkfile(chkfile: TTransactionChkfile, remark: String)
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun deleteTransactionChkdtls(chkfileId: String)
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun saveInitTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doCheckEqualTransdtls(chkfile: TTransactionChkfile)
+
+    @Transactional(rollbackFor = [Exception::class], readOnly = true)
+    fun getUncheckTransactionChkdtls(chkfileId: String): List<TTransactionChkdtl>
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doCheckTransactionChkdtl(chkdtl: TTransactionChkdtl)
+
+    @Transactional(rollbackFor = [Exception::class], readOnly = true)
+    fun checkUncheckExists(chkfileId: String):Boolean
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doCheckLocalMoreDtls(chkfile: TTransactionChkfile)
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doConfirmChkfileStatus(chkfile: TTransactionChkfile): TTransactionChkfile
 
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
index eb08287..4ab8b65 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
@@ -44,9 +44,15 @@
     @Transactional
     fun cancelInit(originRefno: String, builder: TransactionBuilder): TTransactionMain
 
+    /**
+     * 对账一致处理接口
+     * */
+    @Transactional(rollbackFor = [Exception::class])
+    fun checkSuccessConfirm(refno: String, agentAccdate: String): TTransactionMain
+
     // 补帐接口
-    @Transactional
-    fun repair(refno: String, remark: String): TTransactionMain
+    @Transactional(rollbackFor = [Exception::class])
+    fun repair(refno: String, agentAccdate: String, sourcetypeRefno: String, remark:String): TTransactionMain
 }
 
 @Service
@@ -111,4 +117,17 @@
         }
         return trans
     }
+
+    fun checkSuccessConfirm(refno: String, agentAccdate: String): TTransactionMain {
+        return transactionService.checkSuccessConfirm(refno, agentAccdate)
+    }
+
+    fun repair(refno: String, agentAccdate: String, sourcetypeRefno: String, remark: String): TTransactionMain {
+        return transactionService.repair(refno, agentAccdate, sourcetypeRefno, remark).also {
+            if (it.shop) {
+                shopAccBalanceAsyncTask.updateShopBalance(it.shopDtl)
+            }
+        }
+    }
+
 }
\ No newline at end of file