From 97eb15c8bd80157a113cf8ffc341e7e9ce85557f Mon Sep 17 00:00:00 2001 From: Tang Cheng Date: Tue, 18 Jun 2019 15:53:17 +0800 Subject: [PATCH] =?utf8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=95=86=E6=88=B7?= =?utf8?q?=E4=BD=99=E9=A2=9D=E5=BC=82=E6=AD=A5=E6=9B=B4=E6=96=B0=E6=9C=BA?= =?utf8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../supwisdom/dlpay/api/dao/ShopdtlDao.java | 4 ++ .../api/repositories/ShopaccService.java | 8 +++ .../dlpay/framework/domain/TShopacc.java | 14 +----- .../dlpay/framework/util/TradeErrorCode.java | 5 ++ .../supwisdom/dlpay/account_process_async.kt | 20 ++------ .../api/controller/consume_api_controller.kt | 12 ++--- .../com/supwisdom/dlpay/api/scheduler_task.kt | 27 ++++++++++ .../api/service/impl/account_service_impl.kt | 25 ++++++++-- .../service/impl/transaction_service_impl.kt | 39 ++++++--------- .../dlpay/api/service/transaction_service.kt | 49 ++++++++++++++++++- .../dlpay/api/transaction_builder.kt | 9 ++-- 11 files changed, 141 insertions(+), 71 deletions(-) create mode 100644 src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt diff --git a/src/main/java/com/supwisdom/dlpay/api/dao/ShopdtlDao.java b/src/main/java/com/supwisdom/dlpay/api/dao/ShopdtlDao.java index 611d3cb1..0e49580d 100644 --- a/src/main/java/com/supwisdom/dlpay/api/dao/ShopdtlDao.java +++ b/src/main/java/com/supwisdom/dlpay/api/dao/ShopdtlDao.java @@ -7,9 +7,13 @@ import org.springframework.data.jpa.repository.Lock; import org.springframework.stereotype.Repository; import javax.persistence.LockModeType; +import java.util.List; @Repository public interface ShopdtlDao extends JpaRepository, JpaSpecificationExecutor { @Lock(LockModeType.OPTIMISTIC) TShopdtl findTShopdtlByRefno(String refno); + + @Lock(LockModeType.OPTIMISTIC) + List findAllByStatusAndUpdateBala(String status, Boolean flag); } diff --git a/src/main/java/com/supwisdom/dlpay/api/repositories/ShopaccService.java b/src/main/java/com/supwisdom/dlpay/api/repositories/ShopaccService.java index cea6e084..2d8ebcf1 100644 --- a/src/main/java/com/supwisdom/dlpay/api/repositories/ShopaccService.java +++ b/src/main/java/com/supwisdom/dlpay/api/repositories/ShopaccService.java @@ -4,7 +4,15 @@ import com.supwisdom.dlpay.api.domain.TShopdtl; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + public interface ShopaccService { @Transactional(isolation = Isolation.READ_COMMITTED) void recalcShopBalance(TShopdtl dtl, Double amount, boolean overdraft); + + @Transactional(isolation = Isolation.READ_COMMITTED) + void recalcShopBalance(String refno, boolean overdraft); + + @Transactional + List findUnupdatedShopDtl(int maxCount); } diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java b/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java index 9d8b8b4c..b7df8d22 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java +++ b/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java @@ -1,9 +1,6 @@ package com.supwisdom.dlpay.framework.domain; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; +import javax.persistence.*; import java.sql.Timestamp; @Entity @@ -34,9 +31,7 @@ public class TShopacc { @Column(name = "BALANCE", length = 15, precision = 2) private Double balance = 0.0; - @Column(name = "VERSION") - private Long version = 1L; - + @Version @Column(name = "LASTUPDATE") private Timestamp lastUpdate = new Timestamp(System.currentTimeMillis()); @@ -107,10 +102,6 @@ public class TShopacc { return balance; } - public Long getVersion() { - return this.version; - } - public String getMac() { return mac; } @@ -122,7 +113,6 @@ public class TShopacc { public void incrOrDecrBalance(Double amount) { this.balance += amount; this.lastUpdate = new Timestamp(System.currentTimeMillis()); - this.version++; } } diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java b/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java index 71df1391..08bf26fa 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java +++ b/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java @@ -35,6 +35,11 @@ public class TradeErrorCode { */ public static final int TRANSACTION_IS_FINISHED = 10005; + /** + * 交易状态错误,正在处理 + */ + public static final int TRANSACTION_HAS_BEEN_PROCESS = 100030; + /** * 交易已冲正 */ diff --git a/src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt b/src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt index a1bd2f02..3e3918f7 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/account_process_async.kt @@ -13,6 +13,8 @@ import org.springframework.scheduling.annotation.AsyncConfigurer import org.springframework.scheduling.annotation.EnableAsync import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor import org.springframework.stereotype.Component +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional import java.lang.reflect.Method import java.util.concurrent.Executor @@ -45,26 +47,12 @@ class MyAsyncUncaughtExceptionHandler : AsyncUncaughtExceptionHandler { 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") + @Transactional 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" } + shopaccService.recalcShopBalance(shopdtlRefno, true) } } \ No newline at end of file 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 1214889a..12cb97d3 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 @@ -7,10 +7,7 @@ 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 -import com.supwisdom.dlpay.api.service.TransactionService -import com.supwisdom.dlpay.api.service.UserService +import com.supwisdom.dlpay.api.service.* import com.supwisdom.dlpay.exception.RequestParamCheckException import com.supwisdom.dlpay.exception.TransactionCheckException import com.supwisdom.dlpay.exception.TransactionException @@ -47,10 +44,7 @@ class ConsumeAPIController { lateinit var transactionMainDao: TransactionMainDao @Autowired - lateinit var transactionService: TransactionService - - @Autowired - private lateinit var shopAccBalanceAsyncTask: ShopAccBalanceAsyncTask + lateinit var transactionService: TransactionServiceProxy /** * 流水结果查询统一接口 @@ -181,7 +175,7 @@ class ConsumeAPIController { } }.init(transactionService) - transactionService.success(dtl.refno, "") + transactionService.success(dtl.refno) return ResponseEntity.ok(ResponseBodyBuilder.create() .data("refno", dtl.refno) diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt b/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt new file mode 100644 index 00000000..a0379df1 --- /dev/null +++ b/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt @@ -0,0 +1,27 @@ +package com.supwisdom.dlpay.api + +import com.supwisdom.dlpay.api.dao.ShopdtlDao +import com.supwisdom.dlpay.api.domain.TShopdtl +import com.supwisdom.dlpay.api.repositories.ShopaccService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class MySchedulerTask { + @Autowired + private lateinit var shopaccService: ShopaccService + + fun doShopBlanceUpdate(dtl: TShopdtl) { + shopaccService.recalcShopBalance(dtl.refno, true) + } + + @Scheduled(fixedRate = 5000) + @Transactional + fun dealShopUnupdatedDtl() { + shopaccService.findUnupdatedShopDtl(100).forEach { + doShopBlanceUpdate(it) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt index b7b4604f..6e72082a 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/account_service_impl.kt @@ -8,6 +8,7 @@ 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.TradeDict.* import com.supwisdom.dlpay.framework.util.TradeErrorCode import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Repository @@ -68,7 +69,7 @@ class AccountServiceImpl : AccountService { account.lastdayTransamt = 0.0 account.lastdayDpsamt = 0.0 } - if (dtl.tradeflag == TradeDict.TRADE_FLAG_OUT) { + if (dtl.tradeflag == TRADE_FLAG_OUT) { account.lastdayTransamt += amount } else { account.lastdayDpsamt += amount @@ -93,14 +94,32 @@ class ShopaccServiceImpl : ShopaccService { override fun recalcShopBalance(dtl: TShopdtl, amount: Double, overdraft: Boolean) { val shopacc = entityManager.find(TShopacc::class.java, dtl.shopaccno, LockModeType.OPTIMISTIC) ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, - "交易流水<${dtl.refno}>商户账户不存在") + "商户账户<${dtl.shopaccno}>不存在") shopacc.balance += amount if (shopacc.balance < 0.0 && !overdraft) { throw TransactionProcessException(TradeErrorCode.SHORT_BALANCE_ERROR, "商户账户余额不足") } - entityManager.persist(shopacc) } + + override fun recalcShopBalance(refno: String, overdraft: Boolean) { + val shopdtl = entityManager.find(TShopdtl::class.java, refno, LockModeType.PESSIMISTIC_WRITE) + ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, + "商户流水<$refno>不存在") + if (shopdtl.updateBala) { + return + } + recalcShopBalance(shopdtl, shopdtl.amount, overdraft) + shopdtl.updateBala = true + entityManager.persist(shopdtl) + } + + override fun findUnupdatedShopDtl(maxCount: Int): List { + return entityManager.createQuery(""" + SELECT p FROM TShopdtl p + WHERE p.status='$DTL_STATUS_SUCCESS' and p.updateBala=false + ORDER BY p.refno""", TShopdtl::class.java).setMaxResults(maxCount).resultList + } } \ No newline at end of file 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 05b57b24..3c8b3a6f 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 @@ -17,8 +17,11 @@ 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.Service +import org.springframework.transaction.annotation.Propagation +import org.springframework.transaction.annotation.Transactional import java.sql.SQLException import java.sql.Timestamp +import kotlin.math.absoluteValue @Service @@ -44,9 +47,6 @@ class TransactionServiceImpl : TransactionService { @Autowired private lateinit var sourceTypeService: SourceTypeService - @Autowired - private lateinit var shopAccBalanceAsyncTask: ShopAccBalanceAsyncTask - private fun preCheck(builder: TransactionBuilder) { builder.preCheck() @@ -100,8 +100,7 @@ class TransactionServiceImpl : TransactionService { remark = builder.person().remark this.status = status }.also { - // save persondtl - persondtlDao.save(it) + // persondtlDao.save(it) transaction.personDtl = it transaction.person = true } @@ -130,6 +129,7 @@ class TransactionServiceImpl : TransactionService { this.oppositeAccName = builder.shop().opposite.getAccountName() this.remark = builder.shop().remark this.reverseFlag = TradeDict.REVERSE_FLAG_NONE + this.updateBala = false this.status = status }.also { // save shopdtl @@ -315,14 +315,6 @@ class TransactionServiceImpl : TransactionService { } override fun success(refno: String, remark: String): TTransactionMain { - val transaction = successOnAccount(refno, remark) - if (transaction.status == TradeDict.DTL_STATUS_SUCCESS) { - shopAccBalanceAsyncTask.updateShopBalance(transaction.refno) - } - return transaction - } - - override fun successOnAccount(refno: String, remark: String): TTransactionMain { val transaction = transactionMainDao.findByRefnoForUpdate(refno) ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>参考号错误") @@ -377,7 +369,7 @@ class TransactionServiceImpl : TransactionService { val amount = transaction.sumAmountByAccno( transaction.personDtl.accountNo, Subject.SUBJNO_PERSONAL_DEPOSIT, PERSON_BALANCE_FLAG, "both") - if (amount.compareTo(0.0) != 0) { + if (amount.absoluteValue.compareTo(0.0) != 0) { transaction.personDtl?.let { accountService.recalcAccountBalance(it, amount, overdraft) transaction.personDtl.accdate = transaction.accdate @@ -389,16 +381,13 @@ class TransactionServiceImpl : TransactionService { } if (transaction.shop) { // update shop balance - val amount = transaction.sumAmountByAccno( - transaction.shopDtl.shopaccno, Subject.SUBJNO_MACHANT_INCOME, - SHOP_BALANCE_FLAG, "both") - if (amount.compareTo(0.0) != 0) { -// transaction.shopDtl?.let { -// shopaccService.recalcShopBalance(it, amount, overdraft) -// } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, -// "商户流水<${transaction.refno}>不存在") -// shopAccBalanceAsyncTask.updateShopBalance(transaction.shopDtl.refno) - } +// val amount = transaction.sumAmountByAccno( +// transaction.shopDtl.shopaccno, Subject.SUBJNO_MACHANT_INCOME, +// SHOP_BALANCE_FLAG, "both") +// if (amount.absoluteValue.compareTo(0.0) != 0) { +// +// } + transaction.shopDtl.updateBala = false transaction.shopDtl.status = TradeDict.DTL_STATUS_SUCCESS transaction.shopDtl.accdate = transaction.accdate transaction.shopDtl.remark = remark @@ -428,4 +417,4 @@ class TransactionServiceImpl : TransactionService { transactionMainDao.save(transaction) return transaction } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt index c2b942a1..223a12bc 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt @@ -1,7 +1,10 @@ package com.supwisdom.dlpay.api.service +import com.supwisdom.dlpay.ShopAccBalanceAsyncTask import com.supwisdom.dlpay.api.TransactionBuilder import com.supwisdom.dlpay.api.domain.TTransactionMain +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Propagation import org.springframework.transaction.annotation.Transactional @@ -22,9 +25,9 @@ interface TransactionService { fun fail(refno: String, remark: String): TTransactionMain @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class]) - fun successOnAccount(refno: String, remark: String): TTransactionMain - fun success(refno: String, remark: String): TTransactionMain + + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class]) fun success(refno: String): TTransactionMain // 撤销接口冲正类接口 @@ -58,3 +61,45 @@ interface TransactionService { @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class]) fun repair(refno: String, remark: String): TTransactionMain } + +@Component +class TransactionServiceProxy { + @Autowired + private lateinit var transactionService: TransactionService + + @Autowired + private lateinit var shopAccBalanceAsyncTask: ShopAccBalanceAsyncTask + + + fun init(builder: TransactionBuilder): TTransactionMain { + return transactionService.init(builder) + } + + fun wip(refno: String): TTransactionMain { + return transactionService.wip(refno) + } + + fun wip(builder: TransactionBuilder): TTransactionMain { + return transactionService.wip(builder) + } + + fun fail(refno: String): TTransactionMain { + return transactionService.fail(refno) + } + + fun fail(refno: String, remark: String): TTransactionMain { + return transactionService.fail(refno, remark) + } + + fun success(refno: String, remark: String): TTransactionMain { + return transactionService.success(refno, remark).also { + if (it.shop) { + shopAccBalanceAsyncTask.updateShopBalance(it.refno) + } + } + } + + fun success(refno: String): TTransactionMain { + return success(refno, "") + } +} \ No newline at end of file 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 9dc29acf..74f77fda 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt @@ -3,6 +3,7 @@ package com.supwisdom.dlpay.api import com.supwisdom.dlpay.api.domain.TAccount import com.supwisdom.dlpay.api.domain.TTransactionMain import com.supwisdom.dlpay.api.service.TransactionService +import com.supwisdom.dlpay.api.service.TransactionServiceProxy import com.supwisdom.dlpay.exception.TransactionCheckException import com.supwisdom.dlpay.framework.domain.TShopacc import com.supwisdom.dlpay.framework.domain.TSubject @@ -337,19 +338,19 @@ class TransactionBuilder { } } - fun init(transactionService: TransactionService): TTransactionMain { + fun init(transactionService: TransactionServiceProxy): TTransactionMain { return transactionService.init(this) } - fun wip(transactionService: TransactionService): TTransactionMain { + fun wip(transactionService: TransactionServiceProxy): TTransactionMain { return transactionService.wip(this) } - fun cancel(transactionService: TransactionService, originRefno: String): TTransactionMain { + fun cancel(transactionService: TransactionServiceProxy, originRefno: String): TTransactionMain { TODO("not implement") } - fun reverse(transactionService: TransactionService, originRefno: String, amount: Double): TTransactionMain { + fun reverse(transactionService: TransactionServiceProxy, originRefno: String, amount: Double): TTransactionMain { TODO("not implement") } } -- 2.17.1