修改商户更新逻辑,改进业务模式
authorTang Cheng <cheng.tang@supwisdom.com>
Tue, 18 Jun 2019 01:17:30 +0000 (09:17 +0800)
committerTang Cheng <cheng.tang@supwisdom.com>
Tue, 18 Jun 2019 07:53:21 +0000 (15:53 +0800)
src/main/java/com/supwisdom/dlpay/api/dao/ShopdtlDao.java
src/main/java/com/supwisdom/dlpay/api/domain/TAccount.java
src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java
src/main/java/com/supwisdom/dlpay/framework/util/DateUtil.java
src/main/java/com/supwisdom/dlpay/system/service/impl/UserDataServiceImpl.java
src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt [new file with mode: 0644]
src/main/kotlin/com/supwisdom/dlpay/api/controller/shop_api_controller.kt
src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt
src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
src/main/kotlin/com/supwisdom/dlpay/api/service/impl/user_service_impl.kt
src/main/resources/templates/system/user/account.html

index d8dda28..611d3cb 100644 (file)
@@ -3,8 +3,13 @@ package com.supwisdom.dlpay.api.dao;
 import com.supwisdom.dlpay.api.domain.TShopdtl;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Lock;
 import org.springframework.stereotype.Repository;
 
+import javax.persistence.LockModeType;
+
 @Repository
-public interface ShopdtlDao extends JpaRepository<TShopdtl, String>,JpaSpecificationExecutor<TShopdtl> {
+public interface ShopdtlDao extends JpaRepository<TShopdtl, String>, JpaSpecificationExecutor<TShopdtl> {
+  @Lock(LockModeType.OPTIMISTIC)
+  TShopdtl findTShopdtlByRefno(String refno);
 }
index b7dac86..2a89feb 100644 (file)
@@ -2,12 +2,11 @@ package com.supwisdom.dlpay.api.domain;
 
 import com.supwisdom.dlpay.framework.util.MD5;
 import com.supwisdom.dlpay.framework.util.MoneyUtil;
-import com.supwisdom.dlpay.system.common.DictPool;
 import org.hibernate.annotations.GenericGenerator;
-import org.springframework.beans.factory.annotation.Autowired;
 
 import javax.persistence.*;
 import java.io.Serializable;
+import java.sql.Timestamp;
 
 @Entity
 @Table(name = "TB_ACCOUNT",
@@ -54,8 +53,8 @@ public class TAccount implements Serializable {
   @Column(name = "MAX_BAL", precision = 15, scale = 2)
   private Double maxbal; // 最大余额限制
 
-  @Column(name = "LAST_TRANSDATE", length = 8)
-  private String lasttransdate; //最后交易日期
+  @Column(name = "LAST_TRANSTIME", length = 8)
+  private Timestamp lasttranstime; //最后交易日期
 
   @Column(name = "LASTDAY_TRANSAMT", precision = 9, scale = 2)
   private Double lastdayTransamt; //最后一天消费金额
@@ -72,10 +71,6 @@ public class TAccount implements Serializable {
   @Column(name = "CLOSEDATE", length = 8)
   private String closedate;
 
-  @Version
-  @Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false)
-  private Long version;
-
   @OneToOne
   @JoinColumn(name = "USERID", insertable = false, updatable = false)
   private TPerson person;
@@ -83,7 +78,7 @@ public class TAccount implements Serializable {
   public TAccount() {
   }
 
-  public TAccount(String accname, String subjno, String userid, String status, Double balance, Double availbal, Double frozebal, Boolean lowfreeFlag, Double lowfreeLimit, Double daylimit, Double maxbal, String lasttransdate, Double lastdayTransamt, Double lastdayDpsamt, String tac, String opendate, String closedate) {
+  public TAccount(String accname, String subjno, String userid, String status, Double balance, Double availbal, Double frozebal, Boolean lowfreeFlag, Double lowfreeLimit, Double daylimit, Double maxbal, Timestamp lasttranstime, Double lastdayTransamt, Double lastdayDpsamt, String tac, String opendate, String closedate) {
     this.accname = accname;
     this.subjno = subjno;
     this.userid = userid;
@@ -95,7 +90,7 @@ public class TAccount implements Serializable {
     this.lowfreeLimit = lowfreeLimit;
     this.daylimit = daylimit;
     this.maxbal = maxbal;
-    this.lasttransdate = lasttransdate;
+    this.lasttranstime = lasttranstime;
     this.lastdayTransamt = lastdayTransamt;
     this.lastdayDpsamt = lastdayDpsamt;
     this.tac = tac;
@@ -199,12 +194,12 @@ public class TAccount implements Serializable {
     this.maxbal = maxbal;
   }
 
-  public String getLasttransdate() {
-    return lasttransdate;
+  public Timestamp getLasttranstime() {
+    return lasttranstime;
   }
 
-  public void setLasttransdate(String lasttransdate) {
-    this.lasttransdate = lasttransdate;
+  public void setLasttranstime(Timestamp lasttranstime) {
+    this.lasttranstime = lasttranstime;
   }
 
   public Double getLastdayTransamt() {
@@ -297,11 +292,4 @@ public class TAccount implements Serializable {
     this.person = person;
   }
 
-  public Long getVersion() {
-    return version;
-  }
-
-  public void setVersion(Long version) {
-    this.version = version;
-  }
 }
index 76f97a4..aeae783 100644 (file)
@@ -6,7 +6,8 @@ import javax.persistence.*;
 @Table(name = "TB_SHOPDTL",
     indexes = {@Index(name = "shopdtl_accdate", columnList = "accdate"),
         @Index(name = "shopdtl_shopaccno", columnList = "shopaccno"),
-        @Index(name = "shopdtl_transdate", columnList = "transdate")})
+        @Index(name = "shopdtl_transdate", columnList = "transdate"),
+        @Index(name = "shopdtl_updateflag", columnList = "updatebala")})
 public class TShopdtl {
   @Id
   @Column(name = "REFNO", length = 32, nullable = false)
@@ -51,6 +52,9 @@ public class TShopdtl {
   @Column(name = "STATUS", length = 20)
   private String status;
 
+  @Column(name = "updatebala")
+  private Boolean updateBala;
+
   @Column(name = "OPPOSITEACCNO", length = 64)
   private String oppositeAccNo;
 
@@ -195,4 +199,12 @@ public class TShopdtl {
   public void setRemark(String remark) {
     this.remark = remark;
   }
+
+  public Boolean getUpdateBala() {
+    return updateBala;
+  }
+
+  public void setUpdateBala(Boolean updateBala) {
+    this.updateBala = updateBala;
+  }
 }
index 3a7e013..fd18771 100644 (file)
@@ -3,6 +3,7 @@ package com.supwisdom.dlpay.framework.util;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.sql.Timestamp;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
@@ -324,4 +325,21 @@ public class DateUtil {
   public static String getUTCTime() {
     return getUTCTime(System.currentTimeMillis());
   }
+
+  public static int compareDay(Timestamp d1, Timestamp d2) {
+    Calendar cd1 = Calendar.getInstance();
+    cd1.setTimeInMillis(d1.getTime());
+    Calendar cd2 = Calendar.getInstance();
+    cd2.setTimeInMillis(d2.getTime());
+
+    if (cd1.get(Calendar.YEAR) != cd2.get(Calendar.YEAR)) {
+      return cd1.compareTo(cd2);
+    }
+
+    return Integer.compare(cd1.get(Calendar.DAY_OF_YEAR), cd2.get(Calendar.DAY_OF_YEAR));
+  }
+
+  public static Boolean sameDay(Timestamp d1, Timestamp d2) {
+    return (compareDay(d1, d2) == 0);
+  }
 }
index 54694f5..06def11 100644 (file)
@@ -110,7 +110,6 @@ public class UserDataServiceImpl implements UserDataService {
             account.setFrozebal(0.0);
             account.setLowfreeFlag(false);
             account.setMaxbal(systemUtilService.getSysparaValueAsDouble(SysparaUtil.SYSPARAID_NO1, SysparaUtil.SYSPARA_NO1_DEFAULT));
-            account.setLasttransdate(systemDateTime.getHostdate());
             account.setLastdayDpsamt(0.0);
             account.setLastdayTransamt(0.0);
             account.setOpendate(systemDateTime.getHostdate());
diff --git a/src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt b/src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt
new file mode 100644 (file)
index 0000000..a1bd2f0
--- /dev/null
@@ -0,0 +1,70 @@
+package com.supwisdom.dlpay
+
+import com.supwisdom.dlpay.api.dao.ShopdtlDao
+import com.supwisdom.dlpay.api.dao.TransactionMainDao
+import com.supwisdom.dlpay.api.repositories.ShopaccService
+import mu.KotlinLogging
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.scheduling.annotation.Async
+import org.springframework.scheduling.annotation.AsyncConfigurer
+import org.springframework.scheduling.annotation.EnableAsync
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
+import org.springframework.stereotype.Component
+import java.lang.reflect.Method
+import java.util.concurrent.Executor
+
+@Configuration
+@EnableAsync
+class SpringAsyncConfig : AsyncConfigurer {
+    @Bean("shopAccBalanceUpdater")
+    fun threadPoolExecutor(): Executor {
+        return ThreadPoolTaskExecutor().apply {
+            corePoolSize = 10
+            maxPoolSize = 30
+            setWaitForTasksToCompleteOnShutdown(true)
+        }
+    }
+
+    override fun getAsyncUncaughtExceptionHandler(): AsyncUncaughtExceptionHandler? {
+        return MyAsyncUncaughtExceptionHandler()
+    }
+}
+
+class MyAsyncUncaughtExceptionHandler : AsyncUncaughtExceptionHandler {
+    private val logger = KotlinLogging.logger { }
+    override fun handleUncaughtException(ex: Throwable, method: Method, vararg params: Any?) {
+        logger.error { "Async Task execute error: <${method.name}>, exception <${ex.message}>" }
+    }
+}
+
+
+@Component
+class ShopAccBalanceAsyncTask {
+    private val logger = KotlinLogging.logger { }
+
+    @Autowired
+    private lateinit var transactionMainDao: TransactionMainDao
+
+    @Autowired
+    lateinit var shopdltDao: ShopdtlDao
+
+    @Autowired
+    private lateinit var shopaccService: ShopaccService
+
+    @Async("shopAccBalanceUpdater")
+    fun updateShopBalance(shopdtlRefno: String) {
+        shopdltDao.findTShopdtlByRefno(shopdtlRefno)?.also {
+            if (it.updateBala) {
+                logger.warn { "shop balance update refno <$shopdtlRefno> has been updated" }
+                return
+            }
+        }?.also {
+            shopaccService.recalcShopBalance(it, it.amount, true)
+            it.updateBala = true
+            shopdltDao.save(it)
+        } ?: logger.warn { "shop balance updater refno<$shopdtlRefno> not found" }
+    }
+}
\ No newline at end of file
index d7f333b..ef9b194 100644 (file)
@@ -44,9 +44,6 @@ class ShopAPIController {
                         .data("shopaccno", it.shopaccno ?: "")
                         .success("注册成功"))
             }
-
-            return ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "商户注册失败"))
         } catch (ex: RequestParamCheckException) {
             return ResponseEntity.ok(ResponseBodyBuilder.create()
                     .requestException(ex, "请求参数错误"))
index 9622f61..b7b4604 100644 (file)
@@ -6,6 +6,8 @@ import com.supwisdom.dlpay.api.repositories.ShopaccService
 import com.supwisdom.dlpay.exception.TransactionProcessException
 import com.supwisdom.dlpay.framework.domain.TShopacc
 import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Repository
@@ -58,14 +60,25 @@ class AccountServiceImpl : AccountService {
                     doRecalcAccountBalance(dtl, account)
                     account.availbal += dtl.amount
                     account.balance += dtl.amount
-                    account.lasttransdate = dtl.accdate
+
+                    val sameDay = DateUtil.sameDay(account.lasttranstime,
+                            systemUtilServcie.sysdatetime.currentTimestamp) ?: false
+
+                    if (!sameDay) {
+                        account.lastdayTransamt = 0.0
+                        account.lastdayDpsamt = 0.0
+                    }
+                    if (dtl.tradeflag == TradeDict.TRADE_FLAG_OUT) {
+                        account.lastdayTransamt += amount
+                    } else {
+                        account.lastdayDpsamt += amount
+                    }
                     try {
                         entityManager.persist(account)
                     } catch (ex: OptimisticLockException) {
                         throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY,
                                 "个人账户被被更新")
                     }
-
                 } ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
                 "交易流水<${dtl.refno}>未找到指定个人账户")
     }
index ab253c0..17b45f0 100644 (file)
@@ -1,5 +1,6 @@
 package com.supwisdom.dlpay.api.service.impl
 
+import com.supwisdom.dlpay.ShopAccBalanceAsyncTask
 import com.supwisdom.dlpay.api.TransactionBuilder
 import com.supwisdom.dlpay.api.dao.PersondtlDao
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
@@ -46,6 +47,9 @@ class TransactionServiceImpl : TransactionService {
     @Autowired
     private lateinit var sourceTypeService: SourceTypeService
 
+    @Autowired
+    private lateinit var shopAccBalanceAsyncTask: ShopAccBalanceAsyncTask
+
     private fun preCheck(builder: TransactionBuilder) {
         builder.preCheck()
 
@@ -384,10 +388,11 @@ class TransactionServiceImpl : TransactionService {
                     transaction.shopDtl.shopaccno, Subject.SUBJNO_MACHANT_INCOME,
                     SHOP_BALANCE_FLAG, "both")
             if (amount.compareTo(0.0) != 0) {
-                transaction.shopDtl?.let {
-                    shopaccService.recalcShopBalance(it, it.amount, overdraft)
-                } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
-                        "商户流水<${transaction.refno}>不存在")
+//                transaction.shopDtl?.let {
+//                    shopaccService.recalcShopBalance(it, amount, overdraft)
+//                } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
+//                        "商户流水<${transaction.refno}>不存在")
+//                shopAccBalanceAsyncTask.updateShopBalance(transaction.shopDtl.refno)
             }
             transaction.shopDtl.status = TradeDict.DTL_STATUS_SUCCESS
             transaction.shopDtl.accdate = transaction.accdate
index 91fef26..1049c26 100644 (file)
@@ -69,7 +69,7 @@ class UserServiceImpl : UserService {
                 lowfreeLimit = lowfreeLimit
                 daylimit = daylimit
                 maxbal = systemUtilService.getSysparaValueAsDouble(SysparaUtil.SYSPARAID_NO1, SysparaUtil.SYSPARA_NO1_DEFAULT)
-                lasttransdate = systemdatetime.hostdate
+                lasttranstime = systemdatetime.currentTimestamp
                 lastdayTransamt = 0.0
                 lastdayDpsamt = 0.0
                 opendate = systemdatetime.hostdate
index 2475cf9..db0e644 100644 (file)
@@ -51,7 +51,7 @@
                     {field: 'availbal', title: '可用余额', width: 100,fixed: 'left', sort: true},
                     {field: 'balance', title: '总余额', width: 100,fixed: 'left', sort: true},
                     {field: 'frozebal', title: '冻结余额', width: 100,fixed: 'left', sort: true},
-                    {field: 'lasttransdate', title: '最后交易日期', width: 120,fixed: 'left', sort: true},
+                    {field: 'lasttranstime', title: '最后交易日期', width: 120,fixed: 'left', sort: true},
                     {field: 'opendate', title: '开户日期', width: 100,fixed: 'left', sort: true},
                     {
                         field: 'accno', align: 'center', title: '操作', fixed: 'right', templet: function (item) {