完善订单交接结账流程留痕

This commit is contained in:
yml2213
2026-08-28 23:48:32 +08:00
parent a9a9127076
commit c87883cc65
27 changed files with 915 additions and 5 deletions
+25 -2
View File
@@ -6,6 +6,7 @@ import (
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/notification"
"hfb_sys/backend/internal/processlog"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -31,9 +32,12 @@ func (r *Repository) SubmitCheckout(ctx context.Context, userID uint64, orderID
if hasOpen {
return ErrCheckoutCannotSubmit
}
before := orderState(order)
checkoutToUserID := order.OwnerID
checkoutTargetType := processlog.ActorUser
if isPlatformSettlementOrder(order) && platformManagedAdminID(order) > 0 {
checkoutToUserID = platformManagedAdminID(order)
checkoutTargetType = processlog.ActorAdmin
}
record := model.HandoffRecord{
OrderID: order.ID,
@@ -61,6 +65,9 @@ func (r *Repository) SubmitCheckout(ctx context.Context, userID uint64, orderID
order.SettlementStatus = settlementStatusPending
now := time.Now()
order.HandoffStartedAt = &now
if err := appendOrderEvent(tx, order, "checkout", "checkout_submitted", processlog.ActorUser, userID, checkoutTargetType, &checkoutToUserID, req.Content, "", checkoutEventPayload(checkout), before, req.EvidenceURLS); err != nil {
return err
}
orderID := order.ID
if isPlatformSettlementOrder(order) {
if err := appendManagedAdminNotification(tx, order, "checkout", "代管订单待确认结账", "租客已发起结账,请检查账号状态和消耗明细后确认。"); err != nil {
@@ -108,6 +115,7 @@ func (r *Repository) ConfirmCheckout(ctx context.Context, userID uint64, orderID
if order.Status != orderStatusPendingCheckoutConfirm || order.HandoffStatus != handoffStatusPendingOwnerCheckout {
return ErrCheckoutCannotConfirm
}
before := orderState(order)
checkout, err := lockOpenCheckout(tx, order.ID)
if err != nil {
return err
@@ -128,7 +136,10 @@ func (r *Repository) ConfirmCheckout(ctx context.Context, userID uint64, orderID
checkout.OwnerAdjustedAt = &now
action, err := r.finalizeCheckout(tx, &order, checkout, "号主已确认结账,订单完成。")
refund = action
return err
if err != nil {
return err
}
return appendOrderEvent(tx, order, "checkout", "checkout_confirmed", processlog.ActorUser, userID, processlog.ActorUser, &order.RenterID, "号主确认当前结账方案,订单完成。", "", checkoutEventPayload(*checkout), before, decodeStringList(checkout.EvidenceURLS))
})
if err != nil {
return err
@@ -154,6 +165,7 @@ func (r *Repository) CounterCheckout(ctx context.Context, userID uint64, orderID
if order.Status != orderStatusPendingCheckoutConfirm && order.Status != orderStatusPendingCheckoutAccept {
return ErrCheckoutCannotCounter
}
before := orderState(order)
checkout, err := lockOpenCheckout(tx, order.ID)
if err != nil {
return err
@@ -221,6 +233,13 @@ func (r *Repository) CounterCheckout(ctx context.Context, userID uint64, orderID
if err := tx.Save(&order).Error; err != nil {
return err
}
targetID := order.OwnerID
if isOwner {
targetID = order.RenterID
}
if err := appendOrderEvent(tx, order, "checkout", "checkout_countered", processlog.ActorUser, userID, processlog.ActorUser, &targetID, "", req.Reason, checkoutEventPayload(*checkout), before, req.EvidenceURLS); err != nil {
return err
}
if err := tx.Save(checkout).Error; err != nil {
return err
}
@@ -285,6 +304,7 @@ func (r *Repository) AcceptCheckout(ctx context.Context, userID uint64, orderID
if order.Status != orderStatusPendingCheckoutAccept || order.HandoffStatus != handoffStatusPendingRenterCheckout {
return ErrCheckoutCannotConfirm
}
before := orderState(order)
checkout, err := lockOpenCheckout(tx, order.ID)
if err != nil {
return err
@@ -300,7 +320,10 @@ func (r *Repository) AcceptCheckout(ctx context.Context, userID uint64, orderID
checkout.RenterConfirmedAt = &now
action, err := r.finalizeCheckout(tx, &order, checkout, "租客已确认结账协商,订单完成。")
refund = action
return err
if err != nil {
return err
}
return appendOrderEvent(tx, order, "checkout", "checkout_accepted", processlog.ActorUser, userID, processlog.ActorUser, &order.OwnerID, "租客接受当前结账方案,订单完成。", "", checkoutEventPayload(*checkout), before, decodeStringList(checkout.EvidenceURLS))
})
if err != nil {
return err
@@ -5,6 +5,7 @@ import (
"time"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/processlog"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -23,6 +24,7 @@ func (r *Repository) AdminHoldDeposit(ctx context.Context, adminID uint64, order
if !canHoldDeposit(order) {
return ErrDepositCannotHold
}
before := orderState(order)
beforeStatus := order.DepositHoldStatus
now := time.Now()
order.DepositHoldStatus = depositHoldStatusHeld
@@ -30,6 +32,9 @@ func (r *Repository) AdminHoldDeposit(ctx context.Context, adminID uint64, order
order.DepositHeldBy = &adminID
order.DepositHeldAt = &now
order.DepositHoldReleasedAt = nil
if err := appendOrderEvent(tx, order, "settlement", "deposit_held", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, "客服暂扣订单押金。", req.Reason, map[string]any{"deposit_amount_cent": order.DepositAmountCent}, before, nil); err != nil {
return err
}
if err := appendAuditLog(tx, adminID, "order.deposit_hold", "order", order.ID, meta, map[string]any{
"order_id": order.ID,
"order_no": order.OrderNo,
@@ -61,9 +66,13 @@ func (r *Repository) AdminReleaseDeposit(ctx context.Context, adminID uint64, or
if holdAmountCent <= 0 {
return ErrDepositHoldAmountEmpty
}
before := orderState(order)
now := time.Now()
order.DepositHoldStatus = depositHoldStatusReleased
order.DepositHoldReleasedAt = &now
if err := appendOrderEvent(tx, order, "settlement", "deposit_released", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, "客服归还已暂扣的押金。", req.Reason, map[string]any{"deposit_hold_amount_cent": holdAmountCent}, before, nil); err != nil {
return err
}
action, err := r.prepareRefund(&order, holdAmountCent, refundBizDeposit, "暂扣押金归还原路退回")
if err != nil {
return err
+24
View File
@@ -51,6 +51,8 @@ type OrderDTO struct {
GrowthPointsAwarded int64 `json:"growth_points_awarded,omitempty"`
GrowthPointsAwardedAt *time.Time `json:"growth_points_awarded_at,omitempty"`
AccountSnapshot datatypes.JSON `json:"account_snapshot"`
AccountSource string `json:"account_source"`
SourceChannel string `json:"source_channel,omitempty"`
Status string `json:"status"`
HandoffStatus string `json:"handoff_status"`
HandoffMode string `json:"handoff_mode"`
@@ -190,6 +192,28 @@ type HandoffRecordDTO struct {
CreatedAt time.Time `json:"created_at"`
}
// ProcessEventDTO 是后台交易时间线中的一条不可变过程记录。
type ProcessEventDTO struct {
ID uint64 `json:"id"`
BusinessType string `json:"business_type"`
BusinessID uint64 `json:"business_id"`
Stage string `json:"stage"`
Action string `json:"action"`
ActorType string `json:"actor_type"`
ActorID uint64 `json:"actor_id"`
ActorName string `json:"actor_name"`
TargetType string `json:"target_type"`
TargetID *uint64 `json:"target_id,omitempty"`
TargetName string `json:"target_name"`
Content string `json:"content"`
Reason string `json:"reason"`
Payload datatypes.JSON `json:"payload"`
AttachmentURLs []string `json:"attachment_urls"`
StateBefore datatypes.JSON `json:"state_before"`
StateAfter datatypes.JSON `json:"state_after"`
CreatedAt time.Time `json:"created_at"`
}
type CheckoutDTO struct {
ID uint64 `json:"id"`
OrderID uint64 `json:"order_id"`
@@ -7,6 +7,7 @@ import (
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/notification"
"hfb_sys/backend/internal/processlog"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -51,6 +52,7 @@ func (r *Repository) AdminForceHandoff(ctx context.Context, adminID uint64, orde
if !canAdminForceHandoff(order) || strings.TrimSpace(req.Reason) == "" {
return ErrOrderCannotForceHandoff
}
before := orderState(order)
if order.RefundStatus == refundStatusPending || order.RefundStatus == refundStatusPendingReview {
return ErrOrderCannotForceHandoff
}
@@ -100,6 +102,9 @@ func (r *Repository) AdminForceHandoff(ctx context.Context, adminID uint64, orde
order.HandoffStatus = handoffStatusReceived
order.EstimatedDurationHours = estimateOrderDurationHours(order.AccountSnapshot)
order.RentedAt = &now
if err := appendOrderEvent(tx, order, "handoff", "admin_force_handoff", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, content, req.Reason, nil, before, nil); err != nil {
return err
}
orderID := order.ID
if err := notification.Append(tx,
notification.Entry{
@@ -60,6 +60,19 @@ func (h *Handler) AdminHandoffRecords(c *gin.Context) {
response.OK(c, gin.H{"items": items})
}
func (h *Handler) AdminProcessEvents(c *gin.Context) {
id, ok := parseID(c)
if !ok {
return
}
items, err := h.service.ProcessEventsAdmin(c.Request.Context(), id)
if err != nil {
writeOrderError(c, err)
return
}
response.OK(c, gin.H{"items": items})
}
func (h *Handler) AdminClose(c *gin.Context) {
h.adminAction(c, h.service.AdminClose, gin.H{"closed": true})
}
@@ -5,6 +5,7 @@ import (
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/notification"
"hfb_sys/backend/internal/processlog"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -20,6 +21,7 @@ func (r *Repository) SubmitHandoff(ctx context.Context, userID uint64, orderID u
if order.OwnerID != userID {
return ErrPermissionDenied
}
before := orderState(order)
// 号主交接超时(owner_timeout)后仍允许补提交,避免临时延误导致订单卡死。
if order.Status != orderStatusPendingHandoff ||
(order.HandoffStatus != handoffStatusPendingOwner && order.HandoffStatus != handoffStatusOwnerTimeout) {
@@ -37,6 +39,9 @@ func (r *Repository) SubmitHandoff(ctx context.Context, userID uint64, orderID u
return err
}
order.HandoffStatus = handoffStatusPendingRenterConfirm
if err := appendOrderEvent(tx, order, "handoff", "owner_handoff_submitted", processlog.ActorUser, userID, processlog.ActorUser, &order.RenterID, req.Content, "", nil, before, nil); err != nil {
return err
}
orderID := order.ID
renterContent := "请查看交接记录,确认账号可正常登录后点击确认收号。"
if lateSubmit {
@@ -9,6 +9,7 @@ import (
"hfb_sys/backend/internal/modules/chat"
"hfb_sys/backend/internal/modules/notification"
"hfb_sys/backend/internal/modules/rentergrowth"
"hfb_sys/backend/internal/processlog"
"gorm.io/datatypes"
"gorm.io/gorm"
@@ -44,6 +45,10 @@ func (r *Repository) Create(ctx context.Context, renterID uint64, req CreateRequ
if err != nil {
return err
}
accountSource, sourceChannel, err := orderAccountSourceSnapshot(tx, listing.ID)
if err != nil {
return err
}
orderNo, err := newOrderNo()
if err != nil {
return err
@@ -89,6 +94,8 @@ func (r *Repository) Create(ctx context.Context, renterID uint64, req CreateRequ
RenterGrowthLevelName: growthSnapshot.LevelName,
RenterDiscountBps: growthSnapshot.DiscountBps,
AccountSnapshot: snapshot,
AccountSource: accountSource,
SourceChannel: sourceChannel,
Status: orderStatusPendingPayment,
HandoffStatus: handoffStatusNone,
HandoffMode: listingHandoffMode(listing),
@@ -126,6 +133,18 @@ func (r *Repository) Create(ctx context.Context, renterID uint64, req CreateRequ
return r.FindForUser(ctx, renterID, createdID)
}
func orderAccountSourceSnapshot(tx *gorm.DB, listingID uint64) (string, string, error) {
var upload model.ListingUpload
err := tx.Where("listing_id = ?", listingID).Order("id DESC").First(&upload).Error
if err == gorm.ErrRecordNotFound {
return "internal", "", nil
}
if err != nil {
return "", "", err
}
return "external", upload.SourceChannel, nil
}
func listingHandoffMode(listing model.RentalListing) string {
if listing.HandoffMode != "" {
return listing.HandoffMode
@@ -421,6 +440,7 @@ func (r *Repository) ConfirmReceive(ctx context.Context, userID uint64, orderID
if order.Status != orderStatusPendingHandoff || order.HandoffStatus != handoffStatusPendingRenterConfirm {
return ErrOrderCannotReceive
}
before := orderState(order)
now := time.Now()
if err := tx.Model(&model.HandoffRecord{}).
Where("order_id = ? AND type IN ?", order.ID, []string{"owner_handoff", "platform_handoff"}).
@@ -431,6 +451,9 @@ func (r *Repository) ConfirmReceive(ctx context.Context, userID uint64, orderID
order.HandoffStatus = handoffStatusReceived
order.EstimatedDurationHours = estimateOrderDurationHours(order.AccountSnapshot)
order.RentedAt = &now
if err := appendOrderEvent(tx, order, "handoff", "renter_received_confirmed", processlog.ActorUser, userID, processlog.ActorUser, &order.OwnerID, "租客确认已收号,订单开始租用。", "", nil, before, nil); err != nil {
return err
}
orderID := order.ID
if isPlatformHandoffOrder(order) {
if err := appendManagedAdminNotification(tx, order, "handoff", "租客已确认收号", "代管订单已进入使用中。"); err != nil {
@@ -7,6 +7,7 @@ import (
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/adminnotification"
"hfb_sys/backend/internal/modules/notification"
"hfb_sys/backend/internal/processlog"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@@ -81,6 +82,7 @@ func (r *Repository) AdminPlatformHandoff(ctx context.Context, adminID uint64, o
if !canAdminPlatformHandoff(order) {
return ErrOrderCannotHandoff
}
before := orderState(order)
beforeHandoffStatus := order.HandoffStatus
if order.ManagedAdminID == nil {
order.ManagedAdminID = &adminID
@@ -98,6 +100,9 @@ func (r *Repository) AdminPlatformHandoff(ctx context.Context, adminID uint64, o
now := time.Now()
order.HandoffStatus = handoffStatusPendingRenterConfirm
order.HandoffStartedAt = &now
if err := appendOrderEvent(tx, order, "handoff", "platform_handoff_submitted", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, req.Content, req.Reason, nil, before, nil); err != nil {
return err
}
orderID := order.ID
content := "客服已提交交接说明,请查看交接记录,确认账号可正常登录后点击确认收号。"
if beforeHandoffStatus == handoffStatusOwnerTimeout {
@@ -146,6 +151,7 @@ func (r *Repository) AdminPlatformCheckoutConfirm(ctx context.Context, adminID u
if !canAdminPlatformCheckoutConfirm(order) {
return ErrCheckoutCannotConfirm
}
before := orderState(order)
checkout, err := lockOpenCheckout(tx, order.ID)
if err != nil {
return err
@@ -175,6 +181,9 @@ func (r *Repository) AdminPlatformCheckoutConfirm(ctx context.Context, adminID u
if err != nil {
return err
}
if err := appendOrderEvent(tx, order, "checkout", "platform_checkout_confirmed", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, "客服确认当前结账方案,订单完成。", req.Reason, checkoutEventPayload(*checkout), before, decodeStringList(checkout.EvidenceURLS)); err != nil {
return err
}
return appendAuditLog(tx, adminID, "order.platform_checkout_confirm", "order", order.ID, meta, map[string]any{
"order_id": order.ID,
"order_no": order.OrderNo,
@@ -207,6 +216,7 @@ func (r *Repository) AdminPlatformCheckoutCounter(ctx context.Context, adminID u
if !canAdminPlatformCheckoutConfirm(order) {
return ErrCheckoutCannotCounter
}
before := orderState(order)
if order.ManagedAdminID == nil {
order.ManagedAdminID = &adminID
}
@@ -259,6 +269,9 @@ func (r *Repository) AdminPlatformCheckoutCounter(ctx context.Context, adminID u
if err := tx.Create(&record).Error; err != nil {
return err
}
if err := appendOrderEvent(tx, order, "checkout", "platform_checkout_countered", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, "", req.Reason, checkoutEventPayload(*checkout), before, req.EvidenceURLS); err != nil {
return err
}
if err := appendAuditLog(tx, adminID, "order.platform_checkout_counter", "order", order.ID, meta, map[string]any{
"order_id": order.ID,
"order_no": order.OrderNo,
@@ -308,6 +321,7 @@ func (r *Repository) AdminPlatformCheckoutDispute(ctx context.Context, adminID u
if !canAdminPlatformCheckoutConfirm(order) {
return ErrCheckoutCannotCounter
}
before := orderState(order)
if order.ManagedAdminID == nil {
order.ManagedAdminID = &adminID
}
@@ -369,6 +383,9 @@ func (r *Repository) AdminPlatformCheckoutDispute(ctx context.Context, adminID u
if err := tx.Create(&record).Error; err != nil {
return err
}
if err := appendOrderEvent(tx, order, "dispute", "platform_checkout_dispute_opened", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.RenterID, "客服发起结账争议。", req.Reason, map[string]any{"checkout_id": checkout.ID, "dispute_id": row.ID}, before, nil); err != nil {
return err
}
disputeID := row.ID
orderID := order.ID
if err := notification.Append(tx, notification.Entry{
@@ -415,6 +432,7 @@ func (r *Repository) AdminMarkOfflineSettlement(ctx context.Context, adminID uin
if !canAdminMarkOfflineSettlement(order) {
return ErrOfflineSettlementCannotMark
}
before := orderState(order)
beforeStatus := order.OfflineSettlementStatus
now := time.Now()
order.OfflineSettlementStatus = offlineSettlementStatusSettled
@@ -422,6 +440,9 @@ func (r *Repository) AdminMarkOfflineSettlement(ctx context.Context, adminID uin
order.OfflineSettledBy = &adminID
order.OfflineSettledAt = &now
order.OwnerSettledAt = &now
if err := appendOrderEvent(tx, order, "settlement", "offline_settlement_confirmed", processlog.ActorAdmin, adminID, processlog.ActorUser, &order.OwnerID, "确认已完成线下结算。", req.Remark, map[string]any{"offline_settlement_amount_cent": order.OfflineSettlementAmountCent}, before, nil); err != nil {
return err
}
if err := appendAuditLog(tx, adminID, "order.offline_settlement", "order", order.ID, meta, map[string]any{
"order_id": order.ID,
"order_no": order.OrderNo,
@@ -107,6 +107,8 @@ func (row orderRow) toAdminDTO() OrderDTO {
GrowthPointsAwarded: row.GrowthPointsAwarded,
GrowthPointsAwardedAt: row.GrowthPointsAwardedAt,
AccountSnapshot: row.AccountSnapshot,
AccountSource: effectiveAccountSource(row.RentalOrder),
SourceChannel: row.SourceChannel,
Status: row.Status,
HandoffStatus: row.HandoffStatus,
HandoffMode: effectiveHandoffMode(row.RentalOrder),
@@ -131,6 +133,13 @@ func (row orderRow) toAdminDTO() OrderDTO {
}
}
func effectiveAccountSource(order model.RentalOrder) string {
if order.AccountSource != "" {
return order.AccountSource
}
return "internal"
}
func (row orderRow) toDTOForUser(userID uint64) OrderDTO {
dto := row.toAdminDTO()
dto.AdminActions = nil
@@ -146,6 +155,9 @@ func (row orderRow) toDTOForUser(userID uint64) OrderDTO {
dto.OfflineSettlementRemark = ""
dto.OfflineSettledBy = nil
dto.OfflineSettledAt = nil
// 外部来源渠道属于后台经营信息,仅在管理员订单详情展示。
dto.AccountSource = ""
dto.SourceChannel = ""
applyOrderPriceView(&dto, row.RentalOrder, userID)
return dto
}
@@ -0,0 +1,64 @@
package order
import (
"context"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/processlog"
"gorm.io/gorm"
)
const processBusinessOrder = "order"
func orderState(order model.RentalOrder) map[string]any {
return map[string]any{
"order_status": order.Status, "handoff_status": order.HandoffStatus,
"settlement_status": order.SettlementStatus,
"offline_settlement_status": effectiveOfflineSettlementStatus(order),
}
}
func checkoutEventPayload(checkout model.OrderCheckout) map[string]any {
return map[string]any{
"checkout_id": checkout.ID, "round": checkout.RoundCount, "turn": normalizeCheckoutTurn(&checkout),
"proposed_by": checkout.ProposedBy, "rent_amount_cent": checkout.RentAmountCent,
"owner_rent_amount_cent": checkout.OwnerRentAmountCent, "platform_fee_cent": checkout.PlatformFeeCent,
"deposit_amount_cent": checkout.DepositAmountCent, "consumable_amount_cent": checkout.ConsumableAmountCent,
"coin_consumed_m": checkout.CoinConsumedM, "deposit_deduct_amount_cent": checkout.DepositDeductAmountCent,
"renter_refund_amount_cent": checkout.RenterRefundAmountCent, "owner_income_amount_cent": checkout.OwnerIncomeAmountCent,
"shortfall_cent": checkout.ShortfallCent, "overshoot_amount_cent": checkout.OvershootAmountCent,
}
}
func appendOrderEvent(tx *gorm.DB, order model.RentalOrder, stage, action, actorType string, actorID uint64, targetType string, targetID *uint64, content, reason string, payload, before map[string]any, attachments []string) error {
return processlog.Append(tx, processlog.Entry{
BusinessType: processBusinessOrder, BusinessID: order.ID, Stage: stage, Action: action,
ActorType: actorType, ActorID: actorID, TargetType: targetType, TargetID: targetID,
Content: content, Reason: reason, Payload: payload, Attachments: attachments,
StateBefore: before, StateAfter: orderState(order),
})
}
func (r *Repository) ProcessEventsAdmin(ctx context.Context, orderID uint64) ([]ProcessEventDTO, error) {
var order model.RentalOrder
if err := r.db.WithContext(ctx).First(&order, orderID).Error; err != nil {
return nil, err
}
rows, err := processlog.List(r.db.WithContext(ctx), processBusinessOrder, orderID)
if err != nil {
return nil, err
}
items := make([]ProcessEventDTO, 0, len(rows))
for _, row := range rows {
items = append(items, ProcessEventDTO{
ID: row.ID, BusinessType: row.BusinessType, BusinessID: row.BusinessID, Stage: row.Stage,
Action: row.Action, ActorType: row.ActorType, ActorID: row.ActorID, ActorName: row.ActorName,
TargetType: row.TargetType, TargetID: row.TargetID, TargetName: row.TargetName,
Content: row.Content, Reason: row.Reason, Payload: row.Payload,
AttachmentURLs: decodeStringList(row.AttachmentURLs), StateBefore: row.StateBefore,
StateAfter: row.StateAfter, CreatedAt: row.CreatedAt,
})
}
return items, nil
}
@@ -184,6 +184,13 @@ func (s *Service) HandoffRecordsAdmin(ctx context.Context, orderID uint64) ([]Ha
return s.repo.HandoffRecordsAdmin(ctx, orderID)
}
func (s *Service) ProcessEventsAdmin(ctx context.Context, orderID uint64) ([]ProcessEventDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.ProcessEventsAdmin(ctx, orderID)
}
func (s *Service) AdminClose(ctx context.Context, adminID uint64, orderID uint64, req AdminActionRequest, meta AuditMeta) error {
if s.repo == nil {
return ErrDependencyUnavailable