package gas import ( "bytes" "encoding/json" "io" "reflect" "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" platformgasorder "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/platform/gasorder" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) func rewriteJSON(ctx *gin.Context, mutate func(map[string]any) bool) bool { body, err := io.ReadAll(ctx.Request.Body) if err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return false } var values map[string]any if err := json.Unmarshal(body, &values); err != nil || !mutate(values) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return false } body, err = json.Marshal(values) if err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return false } ctx.Request.Body = io.NopCloser(bytes.NewReader(body)) return true } func scopedContract(ctx *gin.Context, identity string, gasID uint64) (models.GasorderContract, bool) { var contract models.GasorderContract if err := common.ActiveRecords(impl.DBService).Where("identity = ? AND gas_basic_id = ?", identity, gasID).First(&contract).Error; err != nil { common.RespondRecordError(ctx, err) return contract, false } return contract, true } func scopedOrder(ctx *gin.Context, identity string, gasID uint64) (models.GasorderBasic, bool) { var order models.GasorderBasic if err := common.ActiveRecords(impl.DBService).Where("identity = ? AND gas_basic_id = ?", identity, gasID).First(&order).Error; err != nil { common.RespondRecordError(ctx, err) return order, false } return order, true } func ListGasorderContract(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } listScoped(ctx, &models.GasorderContract{}, common.ActiveRecords(impl.DBService.Model(&models.GasorderContract{})). Where("gas_basic_id = ?", station.ID), "gasorder_contract.created_at desc") } func GetGasorderContract(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } if _, ok := scopedContract(ctx, ctx.Param("identity"), station.ID); ok { platformgasorder.GetGasorderContract(ctx) } } func CreateGasorderContract(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } if !rewriteJSON(ctx, func(values map[string]any) bool { userIdentity, _ := values["user_account_identity"].(string) if _, _, valid := requireUser(ctx, userIdentity, station.ID); !valid { return false } if deliveryIdentity, _ := values["delivery_basic_identity"].(string); deliveryIdentity != "" { if _, valid := requireDelivery(ctx, deliveryIdentity, station.ID); !valid { return false } } values["gas_basic_identity"] = station.Identity return true }) { return } platformgasorder.CreateGasorderContract(ctx) } func withContract(ctx *gin.Context, handler gin.HandlerFunc) { station, ok := currentGas(ctx) if !ok { return } if _, ok := scopedContract(ctx, ctx.Param("identity"), station.ID); ok { handler(ctx) } } func UpdateGasorderContract(ctx *gin.Context) { withContract(ctx, platformgasorder.UpdateGasorderContract) } func ActivateGasorderContract(ctx *gin.Context) { withContract(ctx, platformgasorder.ActivateGasorderContract) } func RenewGasorderContract(ctx *gin.Context) { withContract(ctx, platformgasorder.RenewGasorderContract) } func TerminateGasorderContract(ctx *gin.Context) { withContract(ctx, platformgasorder.TerminateGasorderContract) } func BindGasorderContractProduct(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } if !rewriteJSON(ctx, func(values map[string]any) bool { identity, _ := values["gasorder_contract_identity"].(string) _, valid := scopedContract(ctx, identity, station.ID) return valid }) { return } platformgasorder.BindGasorderContractProduct(ctx) } func UnbindGasorderContractProduct(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } var binding models.GasorderContractProduct err := common.ActiveRecords(impl.DBService.Model(&models.GasorderContractProduct{})). Select("gasorder_contract_product.*"). Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_product.gasorder_contract_id"). Where("gasorder_contract_product.identity = ? AND gasorder_contract.gas_basic_id = ?", ctx.Param("identity"), station.ID). First(&binding).Error if err != nil { common.RespondRecordError(ctx, err) return } platformgasorder.UnbindGasorderContractProduct(ctx) } func ListGasorderContractProduct(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } query := common.ActiveRecords(impl.DBService.Model(&models.GasorderContractProduct{})). Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_product.gasorder_contract_id"). Where("gasorder_contract.gas_basic_id = ?", station.ID) listScoped(ctx, &models.GasorderContractProduct{}, query, "gasorder_contract_product.created_at desc") } // ListContractProductCandidate 仅返回当前气站服务用户名下可用于合同绑定的气瓶。 func ListContractProductCandidate(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } query := common.ActiveRecords(impl.DBService.Model(&models.ProductInfo{})). Joins("JOIN user_service_relation ON user_service_relation.user_account_id = product_info.user_account_id AND user_service_relation.status <> ?", common.StatusArchived). Where("user_service_relation.gas_basic_id = ?", station.ID) listScoped(ctx, &models.ProductInfo{}, query, "product_info.created_at desc") } func ListGasorderContractRevision(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } query := common.ActiveRecords(impl.DBService.Model(&models.GasorderContractRevision{})). Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_revision.gasorder_contract_id"). Where("gasorder_contract.gas_basic_id = ?", station.ID) listScoped(ctx, &models.GasorderContractRevision{}, query, "gasorder_contract_revision.created_at desc") } func ListGasorderBasic(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } listScoped(ctx, &models.GasorderBasic{}, common.ActiveRecords(impl.DBService.Model(&models.GasorderBasic{})). Where("gas_basic_id = ?", station.ID), "gasorder_basic.created_at desc") } func GetGasorderBasic(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } if _, ok := scopedOrder(ctx, ctx.Param("identity"), station.ID); ok { platformgasorder.GetGasorderBasic(ctx) } } func CreateGasorderBasic(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } if !rewriteJSON(ctx, func(values map[string]any) bool { contractIdentity, _ := values["gasorder_contract_identity"].(string) if _, valid := scopedContract(ctx, contractIdentity, station.ID); !valid { return false } values["creator_type"] = "gas" values["creator_identity"] = station.Identity return true }) { return } platformgasorder.CreateGasorderBasic(ctx) } func withOrder(ctx *gin.Context, handler gin.HandlerFunc) { station, ok := currentGas(ctx) if !ok { return } if _, ok := scopedOrder(ctx, ctx.Param("identity"), station.ID); ok { handler(ctx) } } func AssignGasorderBasic(ctx *gin.Context) { station, ok := currentGas(ctx) if !ok { return } if _, ok := scopedOrder(ctx, ctx.Param("identity"), station.ID); !ok { return } if !rewriteJSON(ctx, func(values map[string]any) bool { deliveryIdentity, _ := values["delivery_basic_identity"].(string) staffIdentity, _ := values["staff_account_identity"].(string) _, deliveryOK := requireDelivery(ctx, deliveryIdentity, station.ID) _, staffOK := requireStaff(ctx, staffIdentity, station.ID) return deliveryOK && staffOK }) { return } platformgasorder.AssignGasorderBasic(ctx) } func GasorderStartFilling(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderStartFilling) } func GasorderReady(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderReady) } func GasorderException(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderException) } func GasorderRecover(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderRecover) } func GasorderCancel(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderCancel) } func listScoped(ctx *gin.Context, model any, query *gorm.DB, order string) { page, size := common.PageSize(ctx) var total int64 if err := common.ApplyKeywordFilter(ctx, query, model).Count(&total).Error; err != nil { infra.Response.Error(ctx, err) return } list := sliceForModel(model) if err := common.ApplyKeywordFilter(ctx, query, model).Order(order).Offset((page - 1) * size).Limit(size).Find(list).Error; err != nil { infra.Response.Error(ctx, err) return } respondList(ctx, list, total) } func sliceForModel(model any) any { return reflect.New(reflect.SliceOf(reflect.TypeOf(model).Elem())).Interface() }