feat: 增加线下充值接口
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/DepositCapitalTypeDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/DepositCapitalTypeDao.java
new file mode 100644
index 0000000..e6a0b58
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/DepositCapitalTypeDao.java
@@ -0,0 +1,13 @@
+package com.supwisdom.dlpay.api.dao;
+
+import com.supwisdom.dlpay.api.domain.TDepositCapitalType;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface DepositCapitalTypeDao extends JpaRepository<TDepositCapitalType, Integer> {
+
+  TDepositCapitalType findTDepositCapitalTypeByCodeAndTenantid(String code, String tenantid);
+
+  List<TDepositCapitalType> findTDepositCapitalTypesByTenantid(String tenantid);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TDepositCapitalType.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TDepositCapitalType.java
new file mode 100644
index 0000000..90a3334
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TDepositCapitalType.java
@@ -0,0 +1,94 @@
+package com.supwisdom.dlpay.api.domain;
+
+import javax.persistence.*;
+
+import static javax.persistence.FetchType.LAZY;
+
+@Table(name = "TB_DEPOSIT_CAPITAL_TYPE",
+    indexes = {@Index(name = "deposit_capital_type_idx", columnList = "code, tenantid", unique = true)})
+@Entity
+@SequenceGenerator(name = "deposit_capital_type_seq", initialValue = 50)
+public class TDepositCapitalType {
+
+  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "deposit_capital_type_seq")
+  private Integer id;
+
+  @Column(name = "code", length = 20)
+  private String code;
+
+  @Column(name = "capital", length = 100)
+  private String capital;
+
+  @Column(name = "subjno", length = 20)
+  private String subjno;
+
+  @Column(name = "sourcetypecode", length = 32)
+  private String sourceTypeCode;
+
+  @OneToOne(targetEntity = TSourceType.class, fetch = LAZY, cascade = CascadeType.ALL)
+  @JoinColumns({
+      @JoinColumn(name = "sourcetypecode", referencedColumnName = "SOURCETYPE"),
+      @JoinColumn(name = "tenantid", referencedColumnName = "tenantid")
+  })
+  private TSourceType sourceType;
+
+  @Column(name = "tenantid", length = 20)
+  private String tenantid;
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public String getCode() {
+    return code;
+  }
+
+  public void setCode(String code) {
+    this.code = code;
+  }
+
+  public String getCapital() {
+    return capital;
+  }
+
+  public void setCapital(String capital) {
+    this.capital = capital;
+  }
+
+  public String getSubjno() {
+    return subjno;
+  }
+
+  public void setSubjno(String subjno) {
+    this.subjno = subjno;
+  }
+
+  public String getTenantid() {
+    return tenantid;
+  }
+
+
+  public void setTenantid(String tenantid) {
+    this.tenantid = tenantid;
+  }
+
+  public String getSourceTypeCode() {
+    return sourceTypeCode;
+  }
+
+  public void setSourceTypeCode(String sourceTypeCode) {
+    this.sourceTypeCode = sourceTypeCode;
+  }
+
+  public TSourceType getSourceType() {
+    return sourceType;
+  }
+
+  public void setSourceType(TSourceType sourceType) {
+    this.sourceType = sourceType;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
index d1a85b8..8298977 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
@@ -32,4 +32,6 @@
 
   public static final int TRANSCODE_CARD_BIZ = 1007; // 卡务业务
 
+  public static final int TRANSCODE_MERCHANT_DEPOSIT = 3600;
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
index 9c2162f..d82ded4 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
@@ -88,6 +88,8 @@
   public static final String PAYTYPE_SM = "SM"; //SM内支付
 
   public static final String SOURCETYPE_DEFAULT = "thirduid"; //第三方id默认
+  public static final String SOURCETYPE_INTERNAL = "internal"; //内部资金类型
+  public static final String SOURCETYPE_EXTERNAL = "external"; //外部资金
   /**
    * feetype
    * - 消费:折扣、搭伙费(管理费)
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/charge_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/charge_api_controller.kt
index da8c986..968dab2 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/charge_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/charge_api_controller.kt
@@ -3,11 +3,13 @@
 import com.supwisdom.dlpay.api.AccountProxy
 import com.supwisdom.dlpay.api.TransactionBuilder
 import com.supwisdom.dlpay.api.bean.*
-import com.supwisdom.dlpay.api.service.*
+import com.supwisdom.dlpay.api.service.AccountUtilServcie
+import com.supwisdom.dlpay.api.service.ChargeApiService
+import com.supwisdom.dlpay.api.service.TransactionServiceProxy
+import com.supwisdom.dlpay.api.service.UserService
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.exception.TransactionProcessException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
-import com.supwisdom.dlpay.framework.service.CommonService
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.Subject
 import com.supwisdom.dlpay.framework.util.TradeCode
@@ -20,9 +22,10 @@
 import org.springframework.web.bind.annotation.RequestBody
 import org.springframework.web.bind.annotation.RequestMapping
 import org.springframework.web.bind.annotation.RestController
+import javax.validation.Valid
 
 @RestController
-@RequestMapping("/api/recharge")
+@RequestMapping("/api/deposit")
 class ChargeAPIController {
     @Autowired
     lateinit var accountUtilServcie: AccountUtilServcie
@@ -31,8 +34,6 @@
     @Autowired
     lateinit var transactionService: TransactionServiceProxy
     @Autowired
-    lateinit var commonService: CommonService
-    @Autowired
     lateinit var userService: UserService
     @Autowired
     lateinit var chargeApiService: ChargeApiService
@@ -141,4 +142,75 @@
 
     }
 
+    @PostMapping("/merchant/init")
+    fun merchantDepositInit(@RequestBody @Valid param: MerchantDepositParam, auth: Authentication):
+            ResponseEntity<Any> {
+        val response = MerchantDepositResponse()
+        val account = when {
+            param.userid.isNotBlank() -> {
+                accountUtilServcie.readAccount(param.userid)
+            }
+            param.custcode.isNotBlank() -> {
+                TODO("not implementation")
+            }
+            else -> {
+                return ResponseBodyBuilder.failEntity(response, TradeErrorCode.INPUT_DATA_ERROR,
+                        "用户ID不能为空")
+            }
+        }
+
+        val shopacc = accountUtilServcie.readShopbyShopaccno(param.merchant)
+
+        val capitalType = chargeApiService.getDepositCapital(param.capitalType)
+
+        val subject = accountUtilServcie.readSubject(capitalType.subjno)
+
+        val builder = TransactionBuilder().apply {
+            setTransInfo(param.localDate, param.localTime,
+                    TradeCode.TRANSCODE_MERCHANT_DEPOSIT,
+                    capitalType.sourceTypeCode)
+            setOutTransInfo(auth.principal.toString(), param.billno)
+            dtltype = "deposit"
+            if (param.opercode.isNotBlank()) {
+                operator(param.opercode, TradeDict.OPERTYPE_SHOP)
+            } else {
+                operator(param.merchant, TradeDict.OPERTYPE_SHOP)
+            }
+        }.person(account).apply {
+            setAmount(param.depositAmount / 100.0, TradeDict.TRADE_FLAG_IN)
+            setOpposite(shopacc.shopaccno, shopacc.shopname)
+        }.and().shop(shopacc).apply {
+            setAmount(param.depositAmount / 100.0, TradeDict.TRADE_FLAG_OUT)
+            setOpposite(account.accno, account.accname)
+        }.and()
+                .addDebitCreditRecord(subject.subjno, subject.subjname,
+                        shopacc.shopaccno, shopacc.shopname, param.depositAmount / 100.0,
+                        capitalType.capital + "充值")
+                .addDebitCreditRecord(shopacc.shopaccno, shopacc.shopname,
+                        account.accno, account.accname, param.depositAmount / 100.0,
+                        capitalType.capital + "充值")
+
+        val transaction = builder.init(transactionService)
+        response.apply {
+            refno = transaction.refno
+            summary = transaction.shopDtl.transdesc
+            depositAmount = Math.round(transaction.personDtl.amount * 100) as Int
+            extraAmount = 0
+        }
+        return ResponseBodyBuilder.successEntity(response, "充值初始化成功")
+    }
+
+    @PostMapping("/merchant/confirm")
+    fun merchantDepositConfirm(@RequestBody @Valid param: MerchantDepositParam, auth: Authentication):
+            ResponseEntity<Any> {
+        val response = MerchantDepositResponse()
+        val transaction = transactionService.success(param.refno)
+        response.apply {
+            refno = transaction.refno
+            summary = transaction.shopDtl.transdesc
+            depositAmount = Math.round(transaction.personDtl.amount * 100) as Int
+            extraAmount = 0
+        }
+        return ResponseBodyBuilder.successEntity(response, "充值成功")
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/charge_api_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/charge_api_service.kt
index 2ac22fb..9d737de 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/charge_api_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/charge_api_service.kt
@@ -1,5 +1,6 @@
 package com.supwisdom.dlpay.api.service
 
+import com.supwisdom.dlpay.api.domain.TDepositCapitalType
 import com.supwisdom.dlpay.api.domain.TPersondtl
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import org.springframework.transaction.annotation.Propagation
@@ -14,4 +15,7 @@
 
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class], readOnly = true)
     fun getPersonDtl(refno: String): TPersondtl
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class], readOnly = true)
+    fun getDepositCapital(capital: String): TDepositCapitalType
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/charge_api_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/charge_api_service_impl.kt
index d76880f..f08607d 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/charge_api_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/charge_api_service_impl.kt
@@ -1,11 +1,14 @@
 package com.supwisdom.dlpay.api.service.impl
 
+import com.supwisdom.dlpay.api.dao.DepositCapitalTypeDao
 import com.supwisdom.dlpay.api.dao.PersondtlDao
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
+import com.supwisdom.dlpay.api.domain.TDepositCapitalType
 import com.supwisdom.dlpay.api.domain.TPersondtl
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.service.ChargeApiService
 import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.framework.tenant.TenantContext
 import com.supwisdom.dlpay.framework.util.StringUtil
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
@@ -19,6 +22,9 @@
     @Autowired
     lateinit var persondtlDao: PersondtlDao
 
+    @Autowired
+    lateinit var depositCapitalTypeDao: DepositCapitalTypeDao
+
     override fun checkRechargeSourcetype(sourceType: String): Boolean {
         return sourceTypeService.checkRechargeSourcetype(sourceType)
     }
@@ -30,7 +36,11 @@
         }
     }
 
-    override fun getPersonDtl(refno: String): TPersondtl{
+    override fun getPersonDtl(refno: String): TPersondtl {
         return persondtlDao.getOne(refno)
     }
+
+    override fun getDepositCapital(capital: String): TDepositCapitalType {
+        return depositCapitalTypeDao.findTDepositCapitalTypeByCodeAndTenantid(capital, TenantContext.getTenantSchema());
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql
index 7244bf3..2e5119a 100644
--- a/payapi/src/main/resources/data.sql
+++ b/payapi/src/main/resources/data.sql
@@ -560,6 +560,46 @@
 VALUES ('28EE54CD3B044CC197D6C5B0E309F8B8', 'alipay', 't', '支付宝', 't', 't', 't', 't', 'f', '112230','112210', 1, '103000', '{tenantid}');
 INSERT INTO "tb_sourcetype" ("sourcetype_id", "sourcetype", "checkable", "paydesc", "enable", "charge_enable", "consume_enable", "anonymous_enable", "reversable", "pay_subjno", "deposite_subjno", "tplusn", "start_chktime", "tenantid")
 VALUES ('DAEF88B54B684347B2B83940C38C7671', 'wechat', 't', '微信支付', 't', 't', 't', 't', 'f', '112231','112211', 1, '103000', '{tenantid}');
+INSERT INTO "tb_sourcetype" ("sourcetype_id", "sourcetype", "checkable", "paydesc", "enable", "charge_enable", "consume_enable", "anonymous_enable", "reversable", "pay_subjno", "deposite_subjno", "tplusn", "start_chktime", "tenantid")
+VALUES ('8f86d7c37dd813b8141057c2dbd93250', 'internal', 't', '内部资金', 't', 't', 't', 't', 'f', '','', 1, '', '{tenantid}');
+INSERT INTO "tb_sourcetype" ("sourcetype_id", "sourcetype", "checkable", "paydesc", "enable", "charge_enable", "consume_enable", "anonymous_enable", "reversable", "pay_subjno", "deposite_subjno", "tplusn", "start_chktime", "tenantid")
+VALUES ('52d23e8b38221b15f989af1b910cc104', 'external', 't', '外部资金', 't', 't', 't', 't', 'f', '','', 1, '', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(1, 'cash', '现金', '1001', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(2, 'cheque', '支票', '112101', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(3, 'voucher', '经费本', '112102', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(4, 'wanxiao.weichat', '完美校园微信', '112209', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(5, 'wanxiao.alipay', '完美校园支付宝', '112209', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(6, 'wanxiao.ccb', '完美校园建设银行', '112209', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(7, 'wanxiao.icbc', '完美校园工商银行', '112209', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(8, 'wanxiao.boc', '完美校园中国银行', '112209', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(9, 'wanxiao.abc', '完美校园农业银行', '112209', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(10, 'weichat', '微信', '112211', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(11, 'alipay', '支付宝', '112210', 'external', '{tenantid}');
+
+INSERT INTO TB_DEPOSIT_CAPITAL_TYPE(ID, CODE, CAPITAL, SUBJNO, SOURCETYPECODE, TENANTID)
+VALUES(12, 'unionpay', '银联', '112212', 'external', '{tenantid}');
 
 -- 支付方式
 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")