重构代码
diff --git a/src/main/java/com/supwisdom/dlpay/consume/PayDtlBuilder.java b/src/main/java/com/supwisdom/dlpay/consume/PayDtlBuilder.java
deleted file mode 100644
index 8c0498a..0000000
--- a/src/main/java/com/supwisdom/dlpay/consume/PayDtlBuilder.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.supwisdom.dlpay.consume;
-
-import com.supwisdom.dlpay.consume.domain.TAccount;
-import com.supwisdom.dlpay.consume.domain.TPerson;
-import com.supwisdom.dlpay.framework.service.PersonPayService;
-import com.supwisdom.dlpay.framework.util.TradeDict;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PayDtlBuilder {
-  public static class PayDetail {
-    private String accNo;
-    private String accName;
-    private Double amount;
-    private String direction;
-    private String summary;
-  }
-
-  private TPerson person;
-  private TAccount account;
-  private String direction;
-
-  private Double payAmount;
-
-  private String summary;
-
-  private List<PayDetail> detail;
-
-  public static PayDtlBuilder newBuilder() {
-    return new PayDtlBuilder();
-  }
-
-  private PayDtlBuilder() {
-    this.detail = new ArrayList<>();
-  }
-
-  public PayDtlBuilder person(TPerson per, TAccount acc, String direction) {
-    this.person = per;
-    this.account = acc;
-    this.direction = direction;
-    return this;
-  }
-
-  public PayDtlBuilder setSummary(String s) {
-    this.summary = s;
-    return this;
-  }
-
-  public PayDtlBuilder setTransDatetime(String transDate ,String transTime) {
-
-    return this;
-  }
-
-  public Boolean done(PersonPayService service) {
-    if (this.detail.size() == 0) {
-      return false;
-    }
-    this.payAmount = 0.0;
-
-    for (PayDetail d : detail) {
-      this.payAmount += d.amount;
-    }
-    if (this.payAmount > this.account.getBalance()) {
-      return false;
-    }
-    service.process(this);
-    return true;
-  }
-
-
-  public PayDtlBuilder addSubDtl(String accNo, Double amount, String summary) {
-    PayDetail dtl = new PayDetail();
-    dtl.accNo = accNo;
-    dtl.accName = "";
-    dtl.amount = amount;
-    if (this.direction.equals(TradeDict.TRANS_DIRECTION_CREDIT)) {
-      dtl.direction = TradeDict.TRANS_DIRECTION_DEBIT;
-    } else {
-      dtl.direction = TradeDict.TRANS_DIRECTION_CREDIT;
-    }
-    dtl.summary = summary;
-    this.detail.add(dtl);
-    return this;
-  }
-}
diff --git a/src/main/java/com/supwisdom/dlpay/consume/dao/AccountDao.java b/src/main/java/com/supwisdom/dlpay/consume/dao/AccountDao.java
new file mode 100644
index 0000000..6efee29
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/consume/dao/AccountDao.java
@@ -0,0 +1,15 @@
+package com.supwisdom.dlpay.consume.dao;
+
+import com.supwisdom.dlpay.consume.domain.TAccount;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Lock;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.persistence.LockModeType;
+
+public interface AccountDao extends JpaRepository<TAccount, String> {
+
+  @Lock(LockModeType.PESSIMISTIC_WRITE)
+  @Query("select a from taccount a where a.accno = ?1")
+  TAccount getByAccnoForUpdate(String accno);
+}
diff --git a/src/main/java/com/supwisdom/dlpay/exception/TransactionCheckError.java b/src/main/java/com/supwisdom/dlpay/exception/TransactionCheckError.java
new file mode 100644
index 0000000..e834318
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/exception/TransactionCheckError.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.exception;
+
+public class TransactionCheckError extends TransactionError {
+  public TransactionCheckError(int code, String message) {
+    super(code, String.format("C - %d, %s", code, message));
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/exception/TransactionDataError.java b/src/main/java/com/supwisdom/dlpay/exception/TransactionDataError.java
deleted file mode 100644
index 747f613..0000000
--- a/src/main/java/com/supwisdom/dlpay/exception/TransactionDataError.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.supwisdom.dlpay.exception;
-
-public class TransactionDataError extends Error {
-  public TransactionDataError(int errCode, String message) {
-    super(String.format("E-%d : %s", errCode, message));
-  }
-}
diff --git a/src/main/java/com/supwisdom/dlpay/exception/TransactionError.java b/src/main/java/com/supwisdom/dlpay/exception/TransactionError.java
new file mode 100644
index 0000000..fb247c5
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/exception/TransactionError.java
@@ -0,0 +1,14 @@
+package com.supwisdom.dlpay.exception;
+
+public class TransactionError extends Error {
+  private int errCode;
+
+  public TransactionError(int code, String message) {
+    super(message);
+    errCode = code;
+  }
+
+  public int code() {
+    return this.errCode;
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/exception/TransactionProcessError.java b/src/main/java/com/supwisdom/dlpay/exception/TransactionProcessError.java
new file mode 100644
index 0000000..44b9d80
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/exception/TransactionProcessError.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.exception;
+
+public class TransactionProcessError extends TransactionError {
+  public TransactionProcessError(int errCode, String message) {
+    super(errCode, String.format("E-%d : %s", errCode, message));
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/service/PersonPayService.java b/src/main/java/com/supwisdom/dlpay/framework/service/PersonPayService.java
index 5e7ace6..3174c2b 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/service/PersonPayService.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/service/PersonPayService.java
@@ -1,6 +1,5 @@
 package com.supwisdom.dlpay.framework.service;
 
-import com.supwisdom.dlpay.consume.PayDtlBuilder;
 import com.supwisdom.dlpay.consume.domain.TPaydtl;
 import org.springframework.stereotype.Service;
 
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/TradeSummary.java b/src/main/java/com/supwisdom/dlpay/framework/util/TradeSummary.java
new file mode 100644
index 0000000..c0053f7
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/util/TradeSummary.java
@@ -0,0 +1,6 @@
+package com.supwisdom.dlpay.framework.util;
+
+public class TradeSummary {
+  public static final String POS_PAY = "刷卡消费";
+  public static final String WX_PAYCODE = "微信付款码消费";
+}
diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt
index 517a6d6..b5c73a4 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/consume/comsume_builder.kt
@@ -4,31 +4,64 @@
 import com.supwisdom.dlpay.consume.domain.TPaydtl
 import com.supwisdom.dlpay.consume.domain.TPerson
 import com.supwisdom.dlpay.consume.service.PersonBalancePayService
+import com.supwisdom.dlpay.exception.TransactionCheckError
+import com.supwisdom.dlpay.exception.TransactionProcessError
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
 
-class PersonBalancePayBuilder private constructor() {
+class PersonTransBuilder private constructor() {
     companion object {
-        fun newBuilder() = PersonBalancePayBuilder()
+        fun newBuilder() = PersonTransBuilder()
     }
 
+    inner class TransDetail(val accNo: String, val amount: Double,
+                            val summary: String, val rowno: Int)
+
     lateinit var person: TPerson
     lateinit var account: TAccount
 
     var transDate = ""
     var transTime = ""
     var description = ""
-    val details = mutableListOf<PayDtlBuilder.PayDetail>()
+    var amount: Double = 0.0
+    val details = mutableListOf<TransDetail>()
+    /**
+     * 是否允许透支
+     */
+    var overdraft = false
 
     fun setUserAndAcc(per: TPerson, acc: TAccount) {
         this.person = per
         this.account = acc
     }
 
-    private fun prepareData() {
+    fun enableOverdraft(b: Boolean = false): PersonTransBuilder {
+        this.overdraft = b
+        return this
+    }
 
+    fun setTransDatetime(date: String, time: String): PersonTransBuilder {
+        this.transDate = date
+        this.transTime = time
+        return this
+    }
+
+    private fun prepareData() {
+        amount = 0.0
+        amount = this.details.sumByDouble { it.amount }
     }
 
     private fun preCheckAccount() {
+        // 判断个人账户
+        if (this.account.subjno == "2001") {
+            if(amount > this.account.balance) {
+                throw TransactionCheckError(TradeErrorCode.SHORT_BALANCE_ERROR, "个人账户余额不足")
+            }
+        }
+    }
 
+    fun addDetail(accNo: String, amount: Double, summary: String): PersonTransBuilder {
+        this.details.add(TransDetail(accNo, amount, summary, this.details.size + 1))
+        return this
     }
 
     /**
diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt
index 217ed47..eaec229 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/consume/service/impl/pay_service_impl.kt
@@ -1,45 +1,61 @@
 package com.supwisdom.dlpay.consume.service.impl
 
-import com.supwisdom.dlpay.consume.PersonBalancePayBuilder
+import com.supwisdom.dlpay.consume.PersonTransBuilder
+import com.supwisdom.dlpay.consume.dao.AccountDao
+import com.supwisdom.dlpay.consume.domain.TAccount
 import com.supwisdom.dlpay.consume.domain.TPaydtl
 import com.supwisdom.dlpay.consume.service.PersonBalancePayService
-import com.supwisdom.dlpay.exception.TransactionDataError
+import com.supwisdom.dlpay.exception.TransactionProcessError
 import com.supwisdom.dlpay.framework.dao.PaydtlDao
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
+import javax.persistence.EntityManager
+import javax.persistence.PersistenceContext
 
 @Service
 class PersonBalancePayServiceImpl : PersonBalancePayService {
     @Autowired
     lateinit var paydtlDao: PaydtlDao
 
-    override fun init(builder: PersonBalancePayBuilder): TPaydtl {
+    @Autowired
+    lateinit var accountDao: AccountDao
+
+    @PersistenceContext
+    lateinit var em : EntityManager
+
+    private fun lockAccount(builder: PersonTransBuilder): TAccount {
+        return accountDao.getByAccnoForUpdate(builder.account.accno)
+    }
+
+    override fun process(builder: PersonTransBuilder): TPaydtl {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
-    override fun wip(paydtl: TPaydtl, builder: PersonBalancePayBuilder): TPaydtl {
+    override fun init(builder: PersonTransBuilder): TPaydtl {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
-    override fun wip(refno: String, builder: PersonBalancePayBuilder): TPaydtl {
+    override fun wip(paydtl: TPaydtl, builder: PersonTransBuilder): TPaydtl {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
-    override fun finish(paydtl: TPaydtl, status: String, builder: PersonBalancePayBuilder): TPaydtl {
+    override fun wip(refno: String, builder: PersonTransBuilder): TPaydtl {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
 
-    override fun finish(refno: String, status: String, builder: PersonBalancePayBuilder): TPaydtl {
+    override fun finish(paydtl: TPaydtl, status: String, builder: PersonTransBuilder): TPaydtl {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun finish(refno: String, status: String, builder: PersonTransBuilder): TPaydtl {
         paydtlDao.findById(refno).let {
             if (it.isPresent) {
                 return finish(it.get(), status, builder)
             }
-            throw TransactionDataError(TradeErrorCode.TRANSACTION_NOT_EXISTS, "交易参考号<$refno>不存在")
+            throw TransactionProcessError(TradeErrorCode.TRANSACTION_NOT_EXISTS, "交易参考号<$refno>不存在")
         }
     }
 
-    override fun process(builder: PersonBalancePayBuilder): TPaydtl {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
+
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/consume/service/pay_service.kt b/src/main/kotlin/com/supwisdom/dlpay/consume/service/pay_service.kt
index 2d559ea..8d631aa 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/consume/service/pay_service.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/consume/service/pay_service.kt
@@ -1,6 +1,6 @@
 package com.supwisdom.dlpay.consume.service
 
-import com.supwisdom.dlpay.consume.PersonBalancePayBuilder
+import com.supwisdom.dlpay.consume.PersonTransBuilder
 import com.supwisdom.dlpay.consume.domain.TPaydtl
 
 interface PersonBalancePayService {
@@ -8,24 +8,24 @@
     /**
      * 一步完成交易
      */
-    fun process(builder: PersonBalancePayBuilder): TPaydtl
+    fun process(builder: PersonTransBuilder): TPaydtl
 
     /**
      * 两步交易,交易初始化方法,检查交易参数,记录交易流水
      */
-    fun init(builder: PersonBalancePayBuilder): TPaydtl
+    fun init(builder: PersonTransBuilder): TPaydtl
 
     /**
      * 两步交易,交易过程中判断交易状态,并更新交易状态为 wip
      */
-    fun wip(paydtl: TPaydtl, builder: PersonBalancePayBuilder): TPaydtl
+    fun wip(paydtl: TPaydtl, builder: PersonTransBuilder): TPaydtl
 
-    fun wip(refno: String, builder: PersonBalancePayBuilder): TPaydtl
+    fun wip(refno: String, builder: PersonTransBuilder): TPaydtl
 
     /**
      * 两步交易,完成交易过程,包括更新交易状态(成功、失败),更新借贷双方余额
      */
-    fun finish(paydtl: TPaydtl, status: String, builder: PersonBalancePayBuilder): TPaydtl
+    fun finish(paydtl: TPaydtl, status: String, builder: PersonTransBuilder): TPaydtl
 
-    fun finish(refno: String, status: String, builder: PersonBalancePayBuilder): TPaydtl
+    fun finish(refno: String, status: String, builder: PersonTransBuilder): TPaydtl
 }
\ No newline at end of file