迁移合作订单完整能力,并统一 AppRoleCode 角色权限与首页菜单展示。
新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -61,6 +61,11 @@ struct OrderEntity: Decodable, Identifiable, Equatable, Hashable {
|
||||
let photoTravel: OrderPhotoTravel?
|
||||
let isNeedEdit: Bool
|
||||
let isRefined: Int
|
||||
let canBindReferral: Int
|
||||
let showOrderSource: Int
|
||||
let referralOrderNo: String
|
||||
let referralSalerName: String
|
||||
let referralOrder: BoundReferralOrder?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case photogUid = "photog_uid"
|
||||
@ -89,6 +94,11 @@ struct OrderEntity: Decodable, Identifiable, Equatable, Hashable {
|
||||
case photoTravel = "photo_travel"
|
||||
case isNeedEdit
|
||||
case isRefined = "is_refined"
|
||||
case canBindReferral = "can_bind_referral"
|
||||
case showOrderSource = "show_order_source"
|
||||
case referralOrderNo = "referral_order_no"
|
||||
case referralSalerName = "referral_saler_name"
|
||||
case referralOrder = "referral_order"
|
||||
}
|
||||
|
||||
/// 宽松解码订单字段,兼容后端数字和字符串混用。
|
||||
@ -120,6 +130,11 @@ struct OrderEntity: Decodable, Identifiable, Equatable, Hashable {
|
||||
photoTravel = try container.decodeIfPresent(OrderPhotoTravel.self, forKey: .photoTravel)
|
||||
isNeedEdit = try container.decodeLossyBool(forKey: .isNeedEdit) ?? true
|
||||
isRefined = try container.decodeLossyInt(forKey: .isRefined) ?? 0
|
||||
canBindReferral = try container.decodeLossyInt(forKey: .canBindReferral) ?? 0
|
||||
showOrderSource = try container.decodeLossyInt(forKey: .showOrderSource) ?? 0
|
||||
referralOrderNo = try container.decodeLossyString(forKey: .referralOrderNo)
|
||||
referralSalerName = try container.decodeLossyString(forKey: .referralSalerName)
|
||||
referralOrder = try container.decodeIfPresent(BoundReferralOrder.self, forKey: .referralOrder)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
106
suixinkan/Features/Orders/Models/OrderSourceModels.swift
Normal file
106
suixinkan/Features/Orders/Models/OrderSourceModels.swift
Normal file
@ -0,0 +1,106 @@
|
||||
import Foundation
|
||||
|
||||
struct OrderSourcePerson: Identifiable, Hashable {
|
||||
let key: String
|
||||
let name: String
|
||||
let phone: String
|
||||
|
||||
var id: String { key }
|
||||
}
|
||||
|
||||
struct OrderSourceLead: Identifiable, Hashable {
|
||||
let key: String
|
||||
let userPhone: String
|
||||
let remark: String
|
||||
let images: [String]
|
||||
|
||||
var id: String { key }
|
||||
}
|
||||
|
||||
struct OrderSourceSelection: Hashable {
|
||||
let person: OrderSourcePerson
|
||||
let lead: OrderSourceLead
|
||||
}
|
||||
|
||||
extension CooperativeSaler {
|
||||
func toOrderSourcePerson() -> OrderSourcePerson {
|
||||
OrderSourcePerson(
|
||||
key: "\(displayId)",
|
||||
name: displayName,
|
||||
phone: displayPhone
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension ReferralOrder {
|
||||
func toOrderSourceLead() -> OrderSourceLead {
|
||||
let remarkText: String
|
||||
if !remark.isEmpty {
|
||||
remarkText = remark
|
||||
} else if !statusLabel.isEmpty {
|
||||
remarkText = statusLabel
|
||||
} else {
|
||||
remarkText = "带客单 \(displayReferralOrderNo)"
|
||||
}
|
||||
return OrderSourceLead(
|
||||
key: displayReferralOrderNo,
|
||||
userPhone: userMobile,
|
||||
remark: remarkText,
|
||||
images: images
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension BoundReferralOrder {
|
||||
func toOrderSourceSelection(fallbackSalerName: String = "") -> OrderSourceSelection? {
|
||||
let referralNo = orderNo.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !referralNo.isEmpty else { return nil }
|
||||
let personName = salerName.isEmpty
|
||||
? (fallbackSalerName.isEmpty ? "—" : fallbackSalerName)
|
||||
: salerName
|
||||
let remarkText: String
|
||||
if !remark.isEmpty {
|
||||
remarkText = remark
|
||||
} else if !displayText.isEmpty {
|
||||
remarkText = displayText
|
||||
} else {
|
||||
remarkText = "带客单号 \(referralNo)"
|
||||
}
|
||||
return OrderSourceSelection(
|
||||
person: OrderSourcePerson(
|
||||
key: saleUserId > 0 ? "\(saleUserId)" : "",
|
||||
name: personName,
|
||||
phone: salerPhone
|
||||
),
|
||||
lead: OrderSourceLead(
|
||||
key: referralNo,
|
||||
userPhone: userMobile,
|
||||
remark: remarkText,
|
||||
images: []
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension OrderEntity {
|
||||
func toBoundOrderSourceSelection() -> OrderSourceSelection? {
|
||||
if let referralOrder,
|
||||
let selection = referralOrder.toOrderSourceSelection(fallbackSalerName: referralSalerName) {
|
||||
return selection
|
||||
}
|
||||
guard !referralOrderNo.isEmpty else { return nil }
|
||||
return OrderSourceSelection(
|
||||
person: OrderSourcePerson(
|
||||
key: "",
|
||||
name: referralSalerName.isEmpty ? "—" : referralSalerName,
|
||||
phone: ""
|
||||
),
|
||||
lead: OrderSourceLead(
|
||||
key: referralOrderNo,
|
||||
userPhone: phone,
|
||||
remark: "带客单号 \(referralOrderNo)",
|
||||
images: []
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user