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);
}
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",
@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; //最后一天消费金额
@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;
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;
this.lowfreeLimit = lowfreeLimit;
this.daylimit = daylimit;
this.maxbal = maxbal;
- this.lasttransdate = lasttransdate;
+ this.lasttranstime = lasttranstime;
this.lastdayTransamt = lastdayTransamt;
this.lastdayDpsamt = lastdayDpsamt;
this.tac = tac;
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() {
this.person = person;
}
- public Long getVersion() {
- return version;
- }
-
- public void setVersion(Long version) {
- this.version = version;
- }
}
@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)
@Column(name = "STATUS", length = 20)
private String status;
+ @Column(name = "updatebala")
+ private Boolean updateBala;
+
@Column(name = "OPPOSITEACCNO", length = 64)
private String oppositeAccNo;
public void setRemark(String remark) {
this.remark = remark;
}
+
+ public Boolean getUpdateBala() {
+ return updateBala;
+ }
+
+ public void setUpdateBala(Boolean updateBala) {
+ this.updateBala = updateBala;
+ }
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
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);
+ }
}
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());
--- /dev/null
+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
.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, "请求参数错误"))
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
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}>未找到指定个人账户")
}
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
@Autowired
private lateinit var sourceTypeService: SourceTypeService
+ @Autowired
+ private lateinit var shopAccBalanceAsyncTask: ShopAccBalanceAsyncTask
+
private fun preCheck(builder: TransactionBuilder) {
builder.preCheck()
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
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
{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) {