优化记账接口
diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java b/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java
index 376b528..bb52bba 100644
--- a/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java
+++ b/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java
@@ -72,7 +72,7 @@
   private Double reverseAmount = 0D; //撤销金额填写
 
   @Column(name = "TRADEFLAG", nullable = false, length = 10)
-  private String tradeflag; //deposit-充值;pay-消费
+  private String tradeflag; // out - 支出,in - 收入
 
   @Column(name = "REMARK", length = 240)
   private String remark;
diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java b/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java
index 14dcb5d..d65da13 100644
--- a/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java
+++ b/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java
@@ -39,8 +39,11 @@
   @Column(name = "payinfo", length = 200)
   private String payInfo;
 
-  @Column(name = "tradeflag", length = 6)
-  private String tradeflag;
+  @Column(name = "tradeflag", length = 6, nullable = false)
+  private String tradeflag; // out - 支出 , in - 收入
+
+  @Column(name = "TRANSDESC", length = 240)
+  private String transdesc; //交易描述
 
   @Column(name = "status", length = 20)
   private String status;
@@ -51,6 +54,9 @@
   @Column(name = "OPPOSITEACCNAME", length = 200)
   private String oppositeAccName;
 
+  @Column(name = "REMARK", length = 240)
+  private String remark;
+
   public String getRefno() {
     return refno;
   }
@@ -162,4 +168,20 @@
   public void setTradeflag(String tradeflag) {
     this.tradeflag = tradeflag;
   }
+
+  public String getTransdesc() {
+    return transdesc;
+  }
+
+  public void setTransdesc(String transdesc) {
+    this.transdesc = transdesc;
+  }
+
+  public String getRemark() {
+    return remark;
+  }
+
+  public void setRemark(String remark) {
+    this.remark = remark;
+  }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java b/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java
index 6c7507d..78983ae 100644
--- a/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java
+++ b/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java
@@ -1,7 +1,5 @@
 package com.supwisdom.dlpay.api.domain;
 
-import com.supwisdom.dlpay.framework.domain.TSubject;
-
 import javax.persistence.*;
 
 import java.sql.Timestamp;
@@ -185,4 +183,37 @@
   public void setEndTime(Timestamp endTime) {
     this.endTime = endTime;
   }
+
+  public Double sumAmountByAccno(String accno, String subjno,
+                                 int balanceFlag, String debitOrCredit) {
+    Double debitSum = 0.0;
+    Double creditSum = 0.0;
+    for (TDebitCreditDtl dtl : getDetails()) {
+      if (dtl.getDraccno().equals(accno) && dtl.getDrsubjno().equals(subjno)) {
+        debitSum += dtl.getAmount();
+      }
+      if (dtl.getCraccno().equals(accno) && dtl.getCrsubjno().equals(subjno)) {
+        creditSum += dtl.getAmount();
+      }
+    }
+    if ("debit".equals(debitOrCredit)) {
+      if (balanceFlag == 2) {
+        return -debitSum;
+      } else {
+        return debitSum;
+      }
+    } else if ("credit".equals(debitOrCredit)) {
+      if (balanceFlag == 1) {
+        return -creditSum;
+      } else {
+        return creditSum;
+      }
+    } else {
+      if (balanceFlag == 2) {
+        return -(debitSum - creditSum);
+      } else {
+        return debitSum - creditSum;
+      }
+    }
+  }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java b/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java
index 402a9b4..14fc1d7 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java
@@ -9,7 +9,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class APIRequestParam {
+public abstract class APIRequestParam {
   @Sign
   private String sign;
   @Sign
@@ -97,4 +97,6 @@
     }
     return calcSignAndCheck(paramMap,key);
   }
+
+  public abstract boolean checkParam();
 }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt b/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
index f96ba95..f47651d 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
@@ -1,22 +1,27 @@
 package com.supwisdom.dlpay.api
 
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
+import com.supwisdom.dlpay.framework.util.APIRequestParam
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
-import org.aspectj.lang.JoinPoint
+import mu.KotlinLogging
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation.Around
 import org.aspectj.lang.annotation.Aspect
-import org.aspectj.lang.annotation.Before
 import org.aspectj.lang.annotation.Pointcut
 import org.springframework.http.ResponseEntity
 import org.springframework.stereotype.Component
 import org.springframework.web.bind.annotation.ExceptionHandler
 import org.springframework.web.bind.annotation.RestControllerAdvice
+import javax.servlet.http.HttpServletRequest
 
 
-@RestControllerAdvice
+@RestControllerAdvice("com.supwisdom.dlpay.api")
 class RestControllerAdvice {
+    val logger = KotlinLogging.logger { }
 
     @ExceptionHandler
-    fun handleException(ex: Exception): ResponseEntity<Any> {
+    fun handleException(ex: Exception, request: HttpServletRequest): ResponseEntity<Any> {
+        logger.error { "Request unhandler exception, url<${request.requestURI}>, ex<${ex.cause}>" }
         return ResponseEntity.ok().body(ResponseBodyBuilder.create()
                 .exception(TradeErrorCode.BUSINESS_DEAL_ERROR, ex.cause))
     }
@@ -26,14 +31,29 @@
 @Aspect
 class RestControllerAspect {
 
-    @Pointcut("execution( * com.supwisdom.dlpay.api..*(..))")
-    private fun beforeRequest() {
+    private val logger = KotlinLogging.logger { }
+
+    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
+    fun restcontroller() {
     }
 
-    @Before("beforeRequest()")
-    fun check(point: JoinPoint) {
-        point.args.forEach {
-            println("request : $it")
+    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
+    fun postmapping() {
+    }
+
+    @Around("restcontroller() && postmapping() && args(.., @RequestBody body)")
+    @Throws(Throwable::class)
+    fun logPostMethods(joinPoint: ProceedingJoinPoint, body: Any): Any {
+        return try {
+            if (body is APIRequestParam) {
+                body.checkParam()
+            }
+            val result = joinPoint.proceed()
+            logger.debug(result.toString())
+            result
+        } catch (t: Throwable) {
+            logger.error { "request error , ex<${t.message}>" }
+            throw t
         }
     }
 }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt b/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
index f498fee..6e06756 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
@@ -27,7 +27,7 @@
     @Sign
     var zipcode: String? = null
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(uid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "用户唯一号不能为空")
         if (StringUtil.isEmpty(name)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "姓名不能为空")
         if (!StringUtil.isEmpty(sex) && ConstantUtil.SEX_MALE != sex && ConstantUtil.SEX_FEMALE != sex) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "性别非法[male|female]")
@@ -47,7 +47,7 @@
     @Sign
     var uid: String? = null    // 用户ID二选一
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(userid) && StringUtil.isEmpty(uid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "用户唯一号不能为空")
 
         return true
@@ -78,7 +78,7 @@
     @Sign
     var zipcode: String? = null
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(userid) && StringUtil.isEmpty(uid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "用户唯一号不能为空")
         if (!StringUtil.isEmpty(sex) && ConstantUtil.SEX_MALE != sex && ConstantUtil.SEX_FEMALE != sex) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "性别非法[male|female]")
         if (!StringUtil.isEmpty(idtype) && !ConstantUtil.IDTYPE_DICTS.contains(idtype)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "证件类型非法")
@@ -118,7 +118,7 @@
     @Sign
     var zipcode: String? = null
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(shopUniqueId)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "商户唯一号不能为空")
         if (ConstantUtil.SHOPTYPE_GROUP != shoptype && ConstantUtil.SHOPTYPE_LEAF != shoptype) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "请指定商户类型")
         if (StringUtil.isEmpty(shopname)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "商户名称不能为空")
@@ -140,7 +140,7 @@
     @Sign
     var shopUniqueId: String? = null //注册传的商户唯一号
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(shopUniqueId) && null == shopid && StringUtil.isEmpty(shopaccno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "商户唯一标志不能为空")
 
         return true
@@ -166,7 +166,7 @@
     @Sign
     var shopaccno: String?=null
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(refno) && (StringUtil.isEmpty(billno) || StringUtil.isEmpty(shopaccno))) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "流水唯一号不能为空")
 
         return true
@@ -189,7 +189,7 @@
     @Sign
     var transtime: String = "" //必传
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(cardNo)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "卡唯一号不能为空")
         if (StringUtil.isEmpty(shopaccno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "请指定交易商户")
         if (amount <= 0) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "交易金额必须大于零")
@@ -205,7 +205,7 @@
     @Sign
     var refno:String=""
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
         if (StringUtil.isEmpty(refno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "交易参考号不能为空")
 
         return true
@@ -234,7 +234,7 @@
     @Sign
     var devphyid: String? = null
 
-    fun checkParam(): Boolean {
+    override fun checkParam(): Boolean {
 
         if (StringUtil.isEmpty(shopaccno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "请指定交易商户")
         if (amount <= 0) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "交易金额必须大于零")
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
index 873aa8f..eb124dd 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
@@ -4,6 +4,7 @@
 import com.supwisdom.dlpay.api.CallService
 import com.supwisdom.dlpay.api.TransactionBuilder
 import com.supwisdom.dlpay.api.bean.*
+import com.supwisdom.dlpay.api.dao.TransactionMainDao
 import com.supwisdom.dlpay.api.domain.TAccount
 import com.supwisdom.dlpay.api.service.AccountUtilServcie
 import com.supwisdom.dlpay.api.service.ConsumePayService
@@ -42,6 +43,9 @@
     lateinit var commonService: CommonService
 
     @Autowired
+    lateinit var transactionMainDao: TransactionMainDao
+
+    @Autowired
     lateinit var transactionService: TransactionService
 
     /**
@@ -55,27 +59,26 @@
                         .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
             }
 
-//            val dtl = if (StringUtil.isEmpty(param.refno)) {
-//                personBalancePayService.getUserdtlForUpdateNowait(param.refno!!)
-//            } else {
-//                personBalancePayService.getUserdtlByBillnoForUpdateNowait(param.billno!!, param.shopaccno!!)
-//            }
-//            val dtl = if( param.refno.isNullOrEmpty()) {
-//               transactionService.
-//            }
-//            val person = dtl.userid?.let { userService.findPersonByUserid(dtl.userid) }
-//            return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                    .data("refno", dtl.refno)
-//                    .data("amount", dtl.amount)
-//                    .data("paytype", dtl.paytype)
-//                    .data("payinfo", dtl.payinfo)
-//                    .also {
-//                        if (null != person) {
-//                            it.data("name", person.name)
-//                        }
-//                    }
-//                    .success("查询成功"))
-            TODO("未实现功能")
+            val dtl = transactionMainDao.findByRefnoForUpdate(param.refno)
+                    ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "交易参考号错误<${param.refno}>"))
+
+            val person = if (dtl.person) {
+                userService.findPersonByUserid(dtl.personDtl.userid)
+            } else {
+                null
+            }
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .data("refno", dtl.refno)
+                    .data("amount", dtl.personDtl.amount)
+                    .data("paytype", dtl.personDtl.paytype)
+                    .data("payinfo", dtl.personDtl.payinfo)
+                    .also {
+                        if (null != person) {
+                            it.data("name", person.name)
+                        }
+                    }
+                    .success("查询成功"))
         } catch (ex: RequestParamCheckException) {
             return ResponseEntity.ok(ResponseBodyBuilder.create()
                     .requestException(ex, "请求参数错误"))
@@ -83,7 +86,6 @@
             return ResponseEntity.ok(ResponseBodyBuilder.create()
                     .transException(et, "查询错误"))
         }
-
     }
 
     private fun consumeMealer(@Suppress("UNUSED_PARAMETER") param: CitizenCardPayinitParam,
@@ -151,15 +153,18 @@
                     transTime = param.transtime
                     paytype = TradeDict.PAYTYPE_BALANCE
                     transCode = TradeCode.TRANSCODE_BALANCE_PAY
+                    payinfo = "账户余额消费"
+                    outId = shopacc.shopaccno
+                    outtradeno = param.billno
                 }.person(account).apply {
-                    description = "账户余额支付"
-                    summary = "账户余额消费"
+                    description = "账户余额消费"
                     amount = param.amount / 100.0
                     opposite = AccountProxy(shopacc)
+                    tradeOut()
                 }.and().shop(shopacc).apply {
-                    summary = "账户余额消费"
                     amount = param.amount / 100.0
                     opposite = AccountProxy(account)
+                    tradeIn()
                 }.and()
 
                 param.feelist?.forEach {
@@ -222,18 +227,16 @@
                     transTime = param.transtime
                     paytype = TradeDict.PAYTYPE_CITIZEN_CARD
                     payinfo = "市民卡代扣消费"
+                    description = "市民卡代扣消费"
                     outId = shopacc.shopaccno
                     outtradeno = param.billno
                 }.person(account).apply {
                     amount = param.amount / 100.0
                     opposite = AccountProxy(shopacc)
-                    description = "市民卡代扣消费"
-                    summary = "市民卡代扣消费"
                     tradeOut()
                 }.and().shop(shopacc).apply {
                     amount = param.amount / 100.0
                     opposite = AccountProxy(account)
-                    summary = "市民卡代扣消费"
                     tradeIn()
                 }.and().addDebitCreditRecord(AccountProxy(subject), AccountProxy(account),
                         param.amount / 100.0, "市民卡代扣消费")
@@ -316,12 +319,12 @@
      * ============================================================================
      * */
     @PostMapping("/ykt/payinit")
-    fun yktPayInit(@RequestBody param: YktCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
+    fun yktPayInit(@RequestBody param: YktCardPayinitParam, authentication: Authentication): ResponseEntity<Any> {
         try {
-//            if (param.checkParam() && param.checkSign(commonService.getAppidSecretByRequest(request))) {
-//                return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                        .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
-//            }
+            if (param.checkParam() && param.checkSign(commonService.getSecretByAppid(authentication.name))) {
+                return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
+            }
 //
 //            val person = param.uid?.let { userService.findByThirdUniqueIdenty(it) } //没注册,可能匿名?
 //            if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_YKT_CARD, person == null)) {
@@ -376,9 +379,9 @@
      * ============================================================================
      * */
     @PostMapping("/ykt/payfinish")
-    fun yktPayFinish(@RequestBody param: CitizenCardPayfinishParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
+    fun yktPayFinish(@RequestBody param: CitizenCardPayfinishParam, authentication: Authentication): ResponseEntity<Any> {
         try {
-            if (param.checkParam() && param.checkSign(commonService.getAppidSecretByRequest(request))) {
+            if (param.checkParam() && param.checkSign(commonService.getSecretByAppid(authentication.name))) {
                 return ResponseEntity.ok(ResponseBodyBuilder.create()
                         .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
             }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
index ac98e14..a077797 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
@@ -9,6 +9,7 @@
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.exception.TransactionProcessException
 import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.Subject
 import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import org.springframework.beans.factory.annotation.Autowired
@@ -20,6 +21,11 @@
 @Service
 class TransactionServiceImpl : TransactionService {
 
+    companion object {
+        val PERSON_BALANCE_FLAG = 2
+        val SHOP_BALANCE_FLAG = 2
+    }
+
     @Autowired
     lateinit var transactionMainDao: TransactionMainDao
 
@@ -122,7 +128,6 @@
                 createTime = Timestamp(systemUtilService.sysdatetime.sysdate.time)
             }
 
-
             if (builder.hasPerson()) {
                 TPersondtl().apply {
                     this.refno = transaction.refno
@@ -147,6 +152,7 @@
                     oppositeAccNo = builder.person().opposite.getAccountNo()
                     oppositeAccName = builder.person().opposite.getAccountName()
                     reverseFlag = builder.reverseFlag
+                    remark = builder.person().remark
                     this.status = status
                 }.also {
                     // save persondtl
@@ -173,8 +179,10 @@
                     this.tradeflag = builder.shop().tradeFlag()
                     this.shopaccno = builder.shop().shopacc.shopaccno
                     this.shopname = builder.shop().shopacc.shopname
+                    this.transdesc = builder.shop().description
                     this.oppositeAccNo = builder.shop().opposite.getAccountNo()
                     this.oppositeAccName = builder.shop().opposite.getAccountName()
+                    this.remark = builder.shop().remark
                     this.status = status
                 }.also {
                     // save shopdtl
@@ -221,8 +229,9 @@
 
             if (builder.hasPerson()) {
                 val dc = getDebitOrCredit(builder.person().tradeFlag())
-                sumBalanceFromDetails(transaction.details, builder.person().person.accno,
-                        builder.person().person.subjno, 2, dc).also {
+                transaction.sumAmountByAccno(builder.person().person.accno,
+                        Subject.SUBJNO_PERSONAL_DEPOSIT,
+                        PERSON_BALANCE_FLAG, dc).also {
                     if (transaction.personDtl.amount != it) {
                         throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR,
                                 "输入金额错误,个人余额不符<${transaction.personDtl.amount}>")
@@ -232,8 +241,9 @@
 
             if (builder.hasShop()) {
                 val dc = getDebitOrCredit(builder.shop().tradeFlag())
-                sumBalanceFromDetails(transaction.details, builder.shop().shopacc.shopaccno,
-                        builder.shop().shopacc.subjno, 2, dc).also {
+                transaction.sumAmountByAccno(builder.shop().shopacc.shopaccno,
+                        Subject.SUBJNO_MACHANT_INCOME,
+                        SHOP_BALANCE_FLAG, dc).also {
                     if (transaction.shopDtl.amount != it) {
                         throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR,
                                 "输入金额错误,商户余额不符<${transaction.shopDtl.amount}>")
@@ -242,8 +252,8 @@
             }
 
             if (builder.hasSubject()) {
-                sumBalanceFromDetails(transaction.details, builder.subject().subject.subjno,
-                        transaction.subjectDtl.subjectno,
+                transaction.sumAmountByAccno(builder.subject().subject.subjno,
+                        builder.subject().subject.subjno,
                         builder.subject().subject.balflag,
                         "both").also {
                     if (transaction.subjectDtl.amount != it) {
@@ -277,38 +287,6 @@
         return builderRecords(builder, TradeDict.DTL_STATUS_WIP)
     }
 
-    private fun sumBalanceFromDetails(details: List<TDebitCreditDtl>,
-                                      accno: String, subjno: String,
-                                      balanceFlag: Int,
-                                      debitOrCredit: String = "debit"): Double {
-
-        val debitAmount = details.sumByDouble { line ->
-            if (line.drsubjno == subjno && line.draccno == accno) {
-                line.amount
-            } else {
-                0.0
-            }
-        }
-        val creditAmount = details.sumByDouble { line ->
-            if (line.crsubjno == subjno && line.craccno == accno) {
-                line.amount
-            } else {
-                0.0
-            }
-        }
-        return when (debitOrCredit) {
-            "debit" -> {
-                if (balanceFlag == 2) debitAmount * -1.0 else debitAmount
-            }
-            "credit" -> {
-                if (balanceFlag == 2) creditAmount else creditAmount * -1.0
-            }
-            "both" -> creditAmount - debitAmount
-            else -> throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
-                    "结算借贷方向余额错误")
-        }
-    }
-
     private fun updateRecordStatus(transaction: TTransactionMain, status: String) {
         if (transaction.person) {
             transaction.personDtl?.also {
@@ -387,25 +365,35 @@
         transaction.accdate = systemUtilService.accdate
         if (transaction.person) {
             // update account balance
-            transaction.personDtl?.let {
-                if (accountRepository.recalcAccountBalance(it, it.amount, false) != 1) {
-                    throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY,
-                            "个人账户交易冲突")
-                }
-                transaction.personDtl.accdate = transaction.accdate
-            } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
-                    "个人流水<${transaction.refno}>不存在")
+            val amount = transaction.sumAmountByAccno(
+                    transaction.personDtl.accountNo, Subject.SUBJNO_PERSONAL_DEPOSIT,
+                    PERSON_BALANCE_FLAG, "both")
+            if (amount.compareTo(0.0) != 0) {
+                transaction.personDtl?.let {
+                    if (accountRepository.recalcAccountBalance(it, amount, false) != 1) {
+                        throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY,
+                                "个人账户交易冲突")
+                    }
+                    transaction.personDtl.accdate = transaction.accdate
+                } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
+                        "个人流水<${transaction.refno}>不存在")
+            }
             transaction.personDtl.status = TradeDict.DTL_STATUS_SUCCESS
         }
         if (transaction.shop) {
             // update shop balance
-            transaction.shopDtl?.let {
-                if (shopaccRepository.recalcShopBalance(it, it.amount, false) != 1) {
-                    throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY,
-                            "商户账户交易冲突")
-                }
-            } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
-                    "商户流水<${transaction.refno}>不存在")
+            val amount = transaction.sumAmountByAccno(
+                    transaction.shopDtl.shopaccno, Subject.SUBJNO_MACHANT_INCOME,
+                    SHOP_BALANCE_FLAG, "both")
+            if (amount.compareTo(0.0) != 0) {
+                transaction.shopDtl?.let {
+                    if (shopaccRepository.recalcShopBalance(it, it.amount, false) != 1) {
+                        throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY,
+                                "商户账户交易冲突")
+                    }
+                } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
+                        "商户流水<${transaction.refno}>不存在")
+            }
             transaction.shopDtl.status = TradeDict.DTL_STATUS_SUCCESS
             transaction.shopDtl.accdate = transaction.accdate
         }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt b/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt
index 40abd48..7dd9f80 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt
@@ -22,6 +22,15 @@
             return if (field.isEmpty()) parent.payinfo else field
         }
 
+    var description: String = ""
+        get() {
+            return if (field.isEmpty()) parent.description else field
+        }
+
+    var remark: String = ""
+        get() {
+            return if (field.isEmpty()) parent.remark else field
+        }
 
     lateinit var opposite: AccountProxy<*>
 
@@ -55,22 +64,16 @@
 class PersonTranactionBuilder(parent: TransactionBuilder, val person: TAccount)
     : SubTransactionBuilder(parent) {
     var amount: Double = 0.0
-    var summary: String = ""
-    var description: String = ""
-
 }
 
 class ShopTransactionBuilder(parent: TransactionBuilder, val shopacc: TShopacc)
     : SubTransactionBuilder(parent) {
     var amount: Double = 0.0
-    var summary: String = ""
 }
 
 class SubjectTransactionBuilder(parent: TransactionBuilder, val subject: TSubject)
     : SubTransactionBuilder(parent) {
     var amount: Double = 0.0
-    var summary: String = ""
-
 }
 
 class AccountProxy<T>(private val accountObj: T) {
@@ -130,6 +133,8 @@
     var outtradeno: String = "" //第三方流水号
     var outId: String = ""
     var reverseFlag: String = "none"
+    var description: String = ""
+    var remark: String = ""
 
     fun person(): PersonTranactionBuilder {
         return this.personBuilder