122 lines
5.0 KiB
Go
122 lines
5.0 KiB
Go
|
|
// 功能描述:向用户本人提供隐私化配送轨迹与履约时间线;版本:1.0.0。
|
|||
|
|
package user
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"math"
|
|||
|
|
"strconv"
|
|||
|
|
|
|||
|
|
"git.apinb.com/bsm-sdk/core/infra"
|
|||
|
|
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
|||
|
|
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
|||
|
|
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
|||
|
|
"github.com/gin-gonic/gin"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// GetGasOrderDeliveryTrack 先限定本人订单,再将定位点约化到约百米精度后下发。
|
|||
|
|
func GetGasOrderDeliveryTrack(ctx *gin.Context) {
|
|||
|
|
account, ok := common.UserAccount(ctx)
|
|||
|
|
if !ok {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
var order models.GasorderBasic
|
|||
|
|
if err := impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", ctx.Param("identity"), account.ID, common.StatusArchived).First(&order).Error; err != nil {
|
|||
|
|
gasDetailError(ctx, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
var station models.GasBasic
|
|||
|
|
if order.GasBasicID != 0 {
|
|||
|
|
if err := impl.DBService.Where("id = ? AND status = ?", order.GasBasicID, common.StatusEnable).Find(&station).Error; err != nil {
|
|||
|
|
gasDetailError(ctx, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
var staff models.StaffAccount
|
|||
|
|
if order.StaffAccountID != 0 {
|
|||
|
|
if err := impl.DBService.Where("id = ? AND role_code = ? AND status = ?", order.StaffAccountID, "delivery", common.StatusEnable).Find(&staff).Error; err != nil {
|
|||
|
|
gasDetailError(ctx, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
var track models.GasorderTrack
|
|||
|
|
if err := impl.DBService.Where("gasorder_basic_id = ? AND status <> ?", order.ID, common.StatusArchived).Order("attempt_no desc, id desc").Limit(1).Find(&track).Error; err != nil {
|
|||
|
|
gasDetailError(ctx, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
var points []models.GasorderTrackPoint
|
|||
|
|
if track.ID != 0 {
|
|||
|
|
if err := impl.DBService.Where("gasorder_track_id = ? AND status = ?", track.ID, common.StatusEnable).Order("occurred_at asc, id asc").Limit(200).Find(&points).Error; err != nil {
|
|||
|
|
gasDetailError(ctx, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
var histories []models.GasorderStatus
|
|||
|
|
if err := impl.DBService.Where("gasorder_basic_id = ? AND status <> ?", order.ID, common.StatusArchived).Order("occurred_at asc, id asc").Find(&histories).Error; err != nil {
|
|||
|
|
gasDetailError(ctx, err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
publicPoints := make([]gin.H, 0, len(points))
|
|||
|
|
for _, point := range points {
|
|||
|
|
longitude, longitudeOK := approximateCoordinate(point.Longitude, -180, 180)
|
|||
|
|
latitude, latitudeOK := approximateCoordinate(point.Latitude, -90, 90)
|
|||
|
|
if longitudeOK && latitudeOK {
|
|||
|
|
publicPoints = append(publicPoints, gin.H{"longitude": longitude, "latitude": latitude, "occurred_at": point.OccurredAt})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
publicTimeline := make([]gin.H, 0, len(histories))
|
|||
|
|
for _, history := range histories {
|
|||
|
|
if title, detail, visible := deliveryTimelineText(history.ToStatus, station.Name); visible {
|
|||
|
|
publicTimeline = append(publicTimeline, gin.H{
|
|||
|
|
"status_code": history.ToStatus, "title": title, "detail": detail, "occurred_at": history.OccurredAt,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
destinationLongitude, destinationLongitudeOK := approximateCoordinate(order.Longitude, -180, 180)
|
|||
|
|
destinationLatitude, destinationLatitudeOK := approximateCoordinate(order.Latitude, -90, 90)
|
|||
|
|
infra.Response.Success(ctx, gin.H{
|
|||
|
|
"identity": order.Identity, "status_code": order.OrderStatus, "status_name": gasOrderStatusName(order.OrderStatus),
|
|||
|
|
"status_message": deliveryStatusMessage(order.OrderStatus), "appointment_at": order.AppointmentAt,
|
|||
|
|
"updated_at": nullableTrackTime(track.ID != 0, track.UpdatedAt), "station_name": station.Name,
|
|||
|
|
"staff_name": staff.Name, "staff_avatar": "", "staff_phone_masked": common.MaskPhone(staff.Phone),
|
|||
|
|
"controlled_call_available": false, "route_available": len(publicPoints) > 0,
|
|||
|
|
"destination_available": destinationLongitudeOK && destinationLatitudeOK,
|
|||
|
|
"destination_longitude": destinationLongitude, "destination_latitude": destinationLatitude,
|
|||
|
|
"points": publicPoints, "timeline": publicTimeline,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// approximateCoordinate 仅返回三位小数,避免用户接口暴露服务人员的精确实时位置。
|
|||
|
|
func approximateCoordinate(value string, min, max float64) (float64, bool) {
|
|||
|
|
parsed, err := strconv.ParseFloat(value, 64)
|
|||
|
|
if err != nil || parsed < min || parsed > max {
|
|||
|
|
return 0, false
|
|||
|
|
}
|
|||
|
|
return math.Round(parsed*1000) / 1000, true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// deliveryTimelineText 将不可变订单状态转换为用户可理解的履约节点。
|
|||
|
|
func deliveryTimelineText(status int, stationName string) (string, string, bool) {
|
|||
|
|
switch status {
|
|||
|
|
case 18:
|
|||
|
|
return "气站已接单", namedStation(stationName) + "已接收您的订单", true
|
|||
|
|
case 20:
|
|||
|
|
return "商品装车完成", "商品已装车,准备出发", true
|
|||
|
|
case 33:
|
|||
|
|
return "配送员已出发", "配送员已从" + namedStation(stationName) + "出发", true
|
|||
|
|
case 34:
|
|||
|
|
return "商品已送达", "请核对商品并确认签收", true
|
|||
|
|
case 23:
|
|||
|
|
return "配送已完成", "本次配送已完成", true
|
|||
|
|
case 21:
|
|||
|
|
return "配送出现异常", "平台正在处理本次配送异常", true
|
|||
|
|
default:
|
|||
|
|
return "", "", false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func namedStation(name string) string {
|
|||
|
|
if name == "" {
|
|||
|
|
return "供气站"
|
|||
|
|
}
|
|||
|
|
return name
|
|||
|
|
}
|