feat: 매도 시 같은 그룹 2계좌 동시 매도 (카드 1장+PIN 1개, 선택 팝업)
- orders/handler.py: propose_trade_multi (레그별 독립 검증, 같은 소유자 그룹만, SELL+LIMIT/MARKET 한정) + submit_with_pin multi 분기 _submit_multi_legs (레그 독립 제출·독립 fill_watcher, 한 레그 실패해도 나머지 시도) - orders/card.py: format_card_multi (레그별 계좌·수량·예상회수 + 합계) - behive_web.py: POST /api/order/propose_multi (PIN은 iMessage '매도(2계좌)'), sell-choice-modal (두 계좌 모두 / 선택 계좌만 / 취소), doPropose SELL 분기 (accStatus로 sibling 보유 감지 → 팝업, sibling 수량은 보유 전량) - fix: /api/order/cancel 응답이 dict를 PendingCard로 취급해 매번 500 나던 기존 버그 (취소 자체는 동작, 응답만 깨짐) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -153,6 +153,47 @@ def format_card(request: dict, market_data: dict, card_id: str,
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def format_card_multi(legs: list, side: str, symbol: str, symbol_name: str,
|
||||
order_type: str, price: Optional[int], card_id: str,
|
||||
state_warning: Optional[str] = None) -> str:
|
||||
"""복수 계좌 동시 주문 카드 — 레그별 계좌·수량·예상회수 나열.
|
||||
|
||||
legs: [{'account': str, 'qty': int, 'position_qty': int?}, ...]
|
||||
"""
|
||||
cfg = _limits()['card']
|
||||
side_word = '매수' if side == 'BUY' else '매도'
|
||||
side_emoji = cfg['buy_emoji'] if side == 'BUY' else cfg['sell_emoji']
|
||||
marker = cfg['highlight_marker']
|
||||
spouse_marker = ' 🔐 가희 계좌' if any(_is_spouse(l['account']) for l in legs) else ''
|
||||
type_marker = f' {cfg["warning_emoji"]} 시장가' if order_type == 'MARKET' else ''
|
||||
|
||||
lines = [f'{side_emoji} {_md_bold(side_word + " 미리보기")} [#{card_id}]{type_marker}{spouse_marker}'
|
||||
f' · 계좌 {len(legs)}개 동시', '']
|
||||
lines.append(f'{marker} {_md_bold(side_word)}')
|
||||
lines.append(f'{marker} 종목: {_md_bold(symbol_name)} ({symbol})')
|
||||
if state_warning:
|
||||
lines.append(state_warning)
|
||||
if order_type == 'LIMIT':
|
||||
lines.append(f'{marker} 가격: {_md_bold(_money(price))}')
|
||||
else:
|
||||
lines.append(f'{marker} 가격: {_md_bold("시장가")}')
|
||||
lines.append('')
|
||||
total = 0
|
||||
for l in legs:
|
||||
part = f'{marker} {_md_bold(_account_display(l["account"]))}: {l["qty"]:,}주'
|
||||
if l.get('position_qty'):
|
||||
part += f' (보유 {l["position_qty"]:,}주)'
|
||||
if order_type == 'LIMIT' and price:
|
||||
part += f' → {_money(price * l["qty"])}'
|
||||
total += price * l['qty']
|
||||
lines.append(part)
|
||||
if order_type == 'LIMIT' and price:
|
||||
money_label = '예상 금액 합계' if side == 'BUY' else '예상 회수 합계'
|
||||
lines.append(f'{money_label}: {_money(total)}')
|
||||
lines.append(f'{_limits()["pin"]["expiry_seconds"]}초 후 만료')
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def format_pin_message(pin: str) -> str:
|
||||
return pin
|
||||
|
||||
|
||||
Reference in New Issue
Block a user