From 030e1d50c1f643137220f1ecf1d90ce39174204a Mon Sep 17 00:00:00 2001
From: dd <gitluke@outlook.com>
Date: Sat, 30 May 2026 01:58:54 +0800
Subject: [PATCH] 1

---
 trading-order-service/src/main/java/com/yami/trading/service/contract/ContractApplyOrderService.java |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractApplyOrderService.java b/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractApplyOrderService.java
index 7edae99..2d12389 100644
--- a/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractApplyOrderService.java
+++ b/trading-order-service/src/main/java/com/yami/trading/service/contract/ContractApplyOrderService.java
@@ -201,9 +201,17 @@
      */
     public void open(ContractApplyOrder order) {
         Item item = this.itemService.findBySymbol(order.getSymbol());
+        //虚拟币新币
+        if (!itemService.isContractTrading(item)) {
+            throw new YamiShopBindException("未开放合约交易");
+        }
+        /*if (itemService.isSuspended(item.getSymbol())) {
+            throw new YamiShopBindException("停牌禁止交易");
+        }*/
+
         List<ItemLeverageDTO> levers = itemLeverageService.findByItemId(item.getUuid());
         log.info("{}  --- order --- {}  --- {}", order.getSymbol(), item.getUuid(), levers.size());
-        checkLever(order, levers);
+        //checkLever(order, levers);
 
         order.setOrderNo(DateUtil.getToday("yyMMddHHmmss") + RandomUtil.getRandomNum(8));
 
@@ -229,11 +237,11 @@
         }
 
         Wallet wallet = this.walletService.findByUserId(order.getPartyId());
-        BigDecimal amountBefore = wallet.getMoney();
-        BigDecimal totalAmountCost = order.getDeposit().add(order.getFee());
+        BigDecimal totalAmountCost = order.getDeposit().add(order.getFee() != null ? order.getFee() : BigDecimal.ZERO);
+        BigDecimal available = getAvailableOpenMargin(order.getPartyId(), null);
 
-        if (amountBefore.compareTo(totalAmountCost) < 0) {
-            throw new YamiShopBindException("余额不足");
+        if (available.compareTo(totalAmountCost) < 0) {
+            throw new YamiShopBindException("not sufficient funds");
         }
 
         //如果是限价单先扣钱
@@ -247,6 +255,48 @@
             );
         }
         save(order);
+
+        // 市价单同步成交,避免异步撮合失败时长期挂单
+        if (ContractApplyOrder.ORDER_PRICE_TYPE_OPPONENT.equals(order.getOrderPriceType())) {
+            executeOpenImmediately(order);
+        }
+    }
+
+    /**
+     * 市价开仓立即撮合;失败则向上抛出,由事务回滚委托单。
+     */
+    private void executeOpenImmediately(ContractApplyOrder order) {
+        List<Realtime> realtimes = dataService.realtime(order.getSymbol());
+        if (CollectionUtil.isEmpty(realtimes)) {
+            return;
+        }
+        contractOrderService.saveOpen(order, realtimes.get(0));
+    }
+
+    /**
+     * 可用于新开仓的余额(双向持仓下多空各自占用保证金,需扣除未成交市价委托预留额)。
+     *
+     * @param excludeOrderNo 正在成交的委托单号,不计入预留
+     */
+    public BigDecimal getAvailableOpenMargin(String partyId, String excludeOrderNo) {
+        Wallet wallet = walletService.findByUserId(partyId);
+        if (wallet == null || wallet.getMoney() == null) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal available = wallet.getMoney();
+        List<ContractApplyOrder> pendingOpens = findSubmitted(partyId, null, ContractApplyOrder.OFFSET_OPEN, null);
+        for (ContractApplyOrder pending : pendingOpens) {
+            if (excludeOrderNo != null && excludeOrderNo.equals(pending.getOrderNo())) {
+                continue;
+            }
+            if (!ContractApplyOrder.ORDER_PRICE_TYPE_OPPONENT.equals(pending.getOrderPriceType())) {
+                continue;
+            }
+            BigDecimal deposit = pending.getDeposit() != null ? pending.getDeposit() : BigDecimal.ZERO;
+            BigDecimal fee = pending.getFee() != null ? pending.getFee() : BigDecimal.ZERO;
+            available = available.subtract(deposit).subtract(fee);
+        }
+        return available.max(BigDecimal.ZERO);
     }
 
     /**

--
Gitblit v1.9.3