瀏覽代碼

fix:edit batch_msg API

jimmyyem 8 月之前
父節點
當前提交
dcd6458b04

+ 15 - 13
crontask/send_msg.go

@@ -30,12 +30,6 @@ func (l *CronTask) sendMsg() {
 		l.Logger.Info("batch start: ", batch.BatchNo)
 		// 如果 批次 status 为 0,则先产生待发送消息
 		if batch.Status == 0 {
-
-			// 如果是设定了发送时间,且还没到则应该忽略该条内容
-			if !batch.SendTime.IsZero() && time.Now().Before(batch.SendTime) {
-				continue
-			}
-
 			userlist := make([]*ent.Contact, 0)
 			if batch.Tag == "all" {
 				// 获取 contact 表中  wx_wxid 等于 req.Fromwxid 的 type 为1或2的数据
@@ -108,11 +102,25 @@ func (l *CronTask) sendMsg() {
 			}
 
 			if len(msgs) > 0 {
-				_, err = l.svcCtx.DB.Msg.CreateBulk(msgs...).Save(l.ctx)
+				// 加事务,批量操作一条 batch_msg 和 一堆 msg 信息
+				tx, err := l.svcCtx.DB.Tx(l.ctx)
 				if err != nil {
+					l.Logger.Errorf("start db transaction err: %v", err)
+					continue
+				}
+				_, err = tx.BatchMsg.UpdateOneID(batch.ID).Where(batchmsg.StatusNEQ(1)).SetStatus(1).Save(l.ctx)
+				if err != nil {
+					_ = tx.Rollback()
+					l.Logger.Errorf("batchmsg update err: %v", err)
+					continue
+				}
+				_, err = tx.Msg.CreateBulk(msgs...).Save(l.ctx)
+				if err != nil {
+					_ = tx.Rollback()
 					l.Logger.Errorf("msg CreateBulk err: %v", err)
 					continue
 				}
+				_ = tx.Commit()
 			} else {
 				// 如果没有消息,直接更新批次状态为已发送
 				_, err = l.svcCtx.DB.BatchMsg.UpdateOneID(batch.ID).
@@ -126,12 +134,6 @@ func (l *CronTask) sendMsg() {
 				}
 				continue
 			}
-
-			_, err = l.svcCtx.DB.BatchMsg.UpdateOneID(batch.ID).Where(batchmsg.StatusNEQ(1)).SetStatus(1).Save(l.ctx)
-			if err != nil {
-				l.Logger.Errorf("batchmsg update err: %v", err)
-				continue
-			}
 		}
 
 		// 获取当前批次的所有待发送消息

+ 4 - 4
desc/wechat/batch_msg.api

@@ -40,10 +40,6 @@ type (
         // 结束时间 
         StopTime  *int64 `json:"stopTime,optional"`
 
-		// 发送时间
-		SendTime  *int64 `json:"sendTime,optional"`
-		SendTimeStr *string `json:"sendTimeStr,optional"`
-
         // 标签列表
         Labels  []string `json:"labels,optional"`
 
@@ -122,4 +118,8 @@ service Wechat {
     // Get batch msg by ID | 通过ID获取BatchMsg
     @handler getBatchMsgById
     post /batch_msg (IDReq) returns (BatchMsgInfoResp)
+
+	// Stop batch_msg by ID | 通过ID停止BatchMsg
+	@handler stopBatchMsg
+	post /batch_msg/stop (IDReq) returns (BaseMsgResp)
 }

+ 15 - 15
ent/batchmsg.go

@@ -45,11 +45,11 @@ type BatchMsg struct {
 	StartTime time.Time `json:"start_time,omitempty"`
 	// 结束时间
 	StopTime time.Time `json:"stop_time,omitempty"`
-	// 发送时间
-	SendTime time.Time `json:"send_time,omitempty"`
 	// 发送类型 1-群发消息 2-群发朋友圈
-	Type         int32 `json:"type,omitempty"`
-	selectValues sql.SelectValues
+	Type int32 `json:"type,omitempty"`
+	// organization_id | 租户ID
+	OrganizationID uint64 `json:"organization_id,omitempty"`
+	selectValues   sql.SelectValues
 }
 
 // scanValues returns the types for scanning values from sql.Rows.
@@ -57,11 +57,11 @@ func (*BatchMsg) scanValues(columns []string) ([]any, error) {
 	values := make([]any, len(columns))
 	for i := range columns {
 		switch columns[i] {
-		case batchmsg.FieldID, batchmsg.FieldStatus, batchmsg.FieldTotal, batchmsg.FieldSuccess, batchmsg.FieldFail, batchmsg.FieldType:
+		case batchmsg.FieldID, batchmsg.FieldStatus, batchmsg.FieldTotal, batchmsg.FieldSuccess, batchmsg.FieldFail, batchmsg.FieldType, batchmsg.FieldOrganizationID:
 			values[i] = new(sql.NullInt64)
 		case batchmsg.FieldBatchNo, batchmsg.FieldTaskName, batchmsg.FieldFromwxid, batchmsg.FieldMsg, batchmsg.FieldTag:
 			values[i] = new(sql.NullString)
-		case batchmsg.FieldCreatedAt, batchmsg.FieldUpdatedAt, batchmsg.FieldDeletedAt, batchmsg.FieldStartTime, batchmsg.FieldStopTime, batchmsg.FieldSendTime:
+		case batchmsg.FieldCreatedAt, batchmsg.FieldUpdatedAt, batchmsg.FieldDeletedAt, batchmsg.FieldStartTime, batchmsg.FieldStopTime:
 			values[i] = new(sql.NullTime)
 		default:
 			values[i] = new(sql.UnknownType)
@@ -168,18 +168,18 @@ func (bm *BatchMsg) assignValues(columns []string, values []any) error {
 			} else if value.Valid {
 				bm.StopTime = value.Time
 			}
-		case batchmsg.FieldSendTime:
-			if value, ok := values[i].(*sql.NullTime); !ok {
-				return fmt.Errorf("unexpected type %T for field send_time", values[i])
-			} else if value.Valid {
-				bm.SendTime = value.Time
-			}
 		case batchmsg.FieldType:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field type", values[i])
 			} else if value.Valid {
 				bm.Type = int32(value.Int64)
 			}
+		case batchmsg.FieldOrganizationID:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field organization_id", values[i])
+			} else if value.Valid {
+				bm.OrganizationID = uint64(value.Int64)
+			}
 		default:
 			bm.selectValues.Set(columns[i], values[i])
 		}
@@ -258,11 +258,11 @@ func (bm *BatchMsg) String() string {
 	builder.WriteString("stop_time=")
 	builder.WriteString(bm.StopTime.Format(time.ANSIC))
 	builder.WriteString(", ")
-	builder.WriteString("send_time=")
-	builder.WriteString(bm.SendTime.Format(time.ANSIC))
-	builder.WriteString(", ")
 	builder.WriteString("type=")
 	builder.WriteString(fmt.Sprintf("%v", bm.Type))
+	builder.WriteString(", ")
+	builder.WriteString("organization_id=")
+	builder.WriteString(fmt.Sprintf("%v", bm.OrganizationID))
 	builder.WriteByte(')')
 	return builder.String()
 }

+ 10 - 8
ent/batchmsg/batchmsg.go

@@ -42,10 +42,10 @@ const (
 	FieldStartTime = "start_time"
 	// FieldStopTime holds the string denoting the stop_time field in the database.
 	FieldStopTime = "stop_time"
-	// FieldSendTime holds the string denoting the send_time field in the database.
-	FieldSendTime = "send_time"
 	// FieldType holds the string denoting the type field in the database.
 	FieldType = "type"
+	// FieldOrganizationID holds the string denoting the organization_id field in the database.
+	FieldOrganizationID = "organization_id"
 	// Table holds the table name of the batchmsg in the database.
 	Table = "batch_msg"
 )
@@ -67,8 +67,8 @@ var Columns = []string{
 	FieldFail,
 	FieldStartTime,
 	FieldStopTime,
-	FieldSendTime,
 	FieldType,
+	FieldOrganizationID,
 }
 
 // ValidColumn reports if the column name is valid (part of the table columns).
@@ -97,6 +97,8 @@ var (
 	UpdateDefaultUpdatedAt func() time.Time
 	// DefaultTaskName holds the default value on creation for the "task_name" field.
 	DefaultTaskName string
+	// OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
+	OrganizationIDValidator func(uint64) error
 )
 
 // OrderOption defines the ordering options for the BatchMsg queries.
@@ -177,12 +179,12 @@ func ByStopTime(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldStopTime, opts...).ToFunc()
 }
 
-// BySendTime orders the results by the send_time field.
-func BySendTime(opts ...sql.OrderTermOption) OrderOption {
-	return sql.OrderByField(FieldSendTime, opts...).ToFunc()
-}
-
 // ByType orders the results by the type field.
 func ByType(opts ...sql.OrderTermOption) OrderOption {
 	return sql.OrderByField(FieldType, opts...).ToFunc()
 }
+
+// ByOrganizationID orders the results by the organization_id field.
+func ByOrganizationID(opts ...sql.OrderTermOption) OrderOption {
+	return sql.OrderByField(FieldOrganizationID, opts...).ToFunc()
+}

+ 45 - 55
ent/batchmsg/where.go

@@ -124,16 +124,16 @@ func StopTime(v time.Time) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldStopTime, v))
 }
 
-// SendTime applies equality check predicate on the "send_time" field. It's identical to SendTimeEQ.
-func SendTime(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldEQ(FieldSendTime, v))
-}
-
 // Type applies equality check predicate on the "type" field. It's identical to TypeEQ.
 func Type(v int32) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldType, v))
 }
 
+// OrganizationID applies equality check predicate on the "organization_id" field. It's identical to OrganizationIDEQ.
+func OrganizationID(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEQ(FieldOrganizationID, v))
+}
+
 // CreatedAtEQ applies the EQ predicate on the "created_at" field.
 func CreatedAtEQ(v time.Time) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldCreatedAt, v))
@@ -939,56 +939,6 @@ func StopTimeNotNil() predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldNotNull(FieldStopTime))
 }
 
-// SendTimeEQ applies the EQ predicate on the "send_time" field.
-func SendTimeEQ(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldEQ(FieldSendTime, v))
-}
-
-// SendTimeNEQ applies the NEQ predicate on the "send_time" field.
-func SendTimeNEQ(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldNEQ(FieldSendTime, v))
-}
-
-// SendTimeIn applies the In predicate on the "send_time" field.
-func SendTimeIn(vs ...time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldIn(FieldSendTime, vs...))
-}
-
-// SendTimeNotIn applies the NotIn predicate on the "send_time" field.
-func SendTimeNotIn(vs ...time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldNotIn(FieldSendTime, vs...))
-}
-
-// SendTimeGT applies the GT predicate on the "send_time" field.
-func SendTimeGT(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldGT(FieldSendTime, v))
-}
-
-// SendTimeGTE applies the GTE predicate on the "send_time" field.
-func SendTimeGTE(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldGTE(FieldSendTime, v))
-}
-
-// SendTimeLT applies the LT predicate on the "send_time" field.
-func SendTimeLT(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldLT(FieldSendTime, v))
-}
-
-// SendTimeLTE applies the LTE predicate on the "send_time" field.
-func SendTimeLTE(v time.Time) predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldLTE(FieldSendTime, v))
-}
-
-// SendTimeIsNil applies the IsNil predicate on the "send_time" field.
-func SendTimeIsNil() predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldIsNull(FieldSendTime))
-}
-
-// SendTimeNotNil applies the NotNil predicate on the "send_time" field.
-func SendTimeNotNil() predicate.BatchMsg {
-	return predicate.BatchMsg(sql.FieldNotNull(FieldSendTime))
-}
-
 // TypeEQ applies the EQ predicate on the "type" field.
 func TypeEQ(v int32) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldEQ(FieldType, v))
@@ -1039,6 +989,46 @@ func TypeNotNil() predicate.BatchMsg {
 	return predicate.BatchMsg(sql.FieldNotNull(FieldType))
 }
 
+// OrganizationIDEQ applies the EQ predicate on the "organization_id" field.
+func OrganizationIDEQ(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDNEQ applies the NEQ predicate on the "organization_id" field.
+func OrganizationIDNEQ(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNEQ(FieldOrganizationID, v))
+}
+
+// OrganizationIDIn applies the In predicate on the "organization_id" field.
+func OrganizationIDIn(vs ...uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDNotIn applies the NotIn predicate on the "organization_id" field.
+func OrganizationIDNotIn(vs ...uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldNotIn(FieldOrganizationID, vs...))
+}
+
+// OrganizationIDGT applies the GT predicate on the "organization_id" field.
+func OrganizationIDGT(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldGT(FieldOrganizationID, v))
+}
+
+// OrganizationIDGTE applies the GTE predicate on the "organization_id" field.
+func OrganizationIDGTE(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldGTE(FieldOrganizationID, v))
+}
+
+// OrganizationIDLT applies the LT predicate on the "organization_id" field.
+func OrganizationIDLT(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldLT(FieldOrganizationID, v))
+}
+
+// OrganizationIDLTE applies the LTE predicate on the "organization_id" field.
+func OrganizationIDLTE(v uint64) predicate.BatchMsg {
+	return predicate.BatchMsg(sql.FieldLTE(FieldOrganizationID, v))
+}
+
 // And groups predicates with the AND operator between them.
 func And(predicates ...predicate.BatchMsg) predicate.BatchMsg {
 	return predicate.BatchMsg(sql.AndPredicates(predicates...))

+ 78 - 78
ent/batchmsg_create.go

@@ -218,20 +218,6 @@ func (bmc *BatchMsgCreate) SetNillableStopTime(t *time.Time) *BatchMsgCreate {
 	return bmc
 }
 
-// SetSendTime sets the "send_time" field.
-func (bmc *BatchMsgCreate) SetSendTime(t time.Time) *BatchMsgCreate {
-	bmc.mutation.SetSendTime(t)
-	return bmc
-}
-
-// SetNillableSendTime sets the "send_time" field if the given value is not nil.
-func (bmc *BatchMsgCreate) SetNillableSendTime(t *time.Time) *BatchMsgCreate {
-	if t != nil {
-		bmc.SetSendTime(*t)
-	}
-	return bmc
-}
-
 // SetType sets the "type" field.
 func (bmc *BatchMsgCreate) SetType(i int32) *BatchMsgCreate {
 	bmc.mutation.SetType(i)
@@ -246,6 +232,12 @@ func (bmc *BatchMsgCreate) SetNillableType(i *int32) *BatchMsgCreate {
 	return bmc
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (bmc *BatchMsgCreate) SetOrganizationID(u uint64) *BatchMsgCreate {
+	bmc.mutation.SetOrganizationID(u)
+	return bmc
+}
+
 // SetID sets the "id" field.
 func (bmc *BatchMsgCreate) SetID(u uint64) *BatchMsgCreate {
 	bmc.mutation.SetID(u)
@@ -318,6 +310,14 @@ func (bmc *BatchMsgCreate) check() error {
 	if _, ok := bmc.mutation.UpdatedAt(); !ok {
 		return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "BatchMsg.updated_at"`)}
 	}
+	if _, ok := bmc.mutation.OrganizationID(); !ok {
+		return &ValidationError{Name: "organization_id", err: errors.New(`ent: missing required field "BatchMsg.organization_id"`)}
+	}
+	if v, ok := bmc.mutation.OrganizationID(); ok {
+		if err := batchmsg.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "BatchMsg.organization_id": %w`, err)}
+		}
+	}
 	return nil
 }
 
@@ -407,14 +407,14 @@ func (bmc *BatchMsgCreate) createSpec() (*BatchMsg, *sqlgraph.CreateSpec) {
 		_spec.SetField(batchmsg.FieldStopTime, field.TypeTime, value)
 		_node.StopTime = value
 	}
-	if value, ok := bmc.mutation.SendTime(); ok {
-		_spec.SetField(batchmsg.FieldSendTime, field.TypeTime, value)
-		_node.SendTime = value
-	}
 	if value, ok := bmc.mutation.GetType(); ok {
 		_spec.SetField(batchmsg.FieldType, field.TypeInt32, value)
 		_node.Type = value
 	}
+	if value, ok := bmc.mutation.OrganizationID(); ok {
+		_spec.SetField(batchmsg.FieldOrganizationID, field.TypeUint64, value)
+		_node.OrganizationID = value
+	}
 	return _node, _spec
 }
 
@@ -719,24 +719,6 @@ func (u *BatchMsgUpsert) ClearStopTime() *BatchMsgUpsert {
 	return u
 }
 
-// SetSendTime sets the "send_time" field.
-func (u *BatchMsgUpsert) SetSendTime(v time.Time) *BatchMsgUpsert {
-	u.Set(batchmsg.FieldSendTime, v)
-	return u
-}
-
-// UpdateSendTime sets the "send_time" field to the value that was provided on create.
-func (u *BatchMsgUpsert) UpdateSendTime() *BatchMsgUpsert {
-	u.SetExcluded(batchmsg.FieldSendTime)
-	return u
-}
-
-// ClearSendTime clears the value of the "send_time" field.
-func (u *BatchMsgUpsert) ClearSendTime() *BatchMsgUpsert {
-	u.SetNull(batchmsg.FieldSendTime)
-	return u
-}
-
 // SetType sets the "type" field.
 func (u *BatchMsgUpsert) SetType(v int32) *BatchMsgUpsert {
 	u.Set(batchmsg.FieldType, v)
@@ -761,6 +743,24 @@ func (u *BatchMsgUpsert) ClearType() *BatchMsgUpsert {
 	return u
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (u *BatchMsgUpsert) SetOrganizationID(v uint64) *BatchMsgUpsert {
+	u.Set(batchmsg.FieldOrganizationID, v)
+	return u
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *BatchMsgUpsert) UpdateOrganizationID() *BatchMsgUpsert {
+	u.SetExcluded(batchmsg.FieldOrganizationID)
+	return u
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *BatchMsgUpsert) AddOrganizationID(v uint64) *BatchMsgUpsert {
+	u.Add(batchmsg.FieldOrganizationID, v)
+	return u
+}
+
 // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
 // Using this option is equivalent to using:
 //
@@ -1106,27 +1106,6 @@ func (u *BatchMsgUpsertOne) ClearStopTime() *BatchMsgUpsertOne {
 	})
 }
 
-// SetSendTime sets the "send_time" field.
-func (u *BatchMsgUpsertOne) SetSendTime(v time.Time) *BatchMsgUpsertOne {
-	return u.Update(func(s *BatchMsgUpsert) {
-		s.SetSendTime(v)
-	})
-}
-
-// UpdateSendTime sets the "send_time" field to the value that was provided on create.
-func (u *BatchMsgUpsertOne) UpdateSendTime() *BatchMsgUpsertOne {
-	return u.Update(func(s *BatchMsgUpsert) {
-		s.UpdateSendTime()
-	})
-}
-
-// ClearSendTime clears the value of the "send_time" field.
-func (u *BatchMsgUpsertOne) ClearSendTime() *BatchMsgUpsertOne {
-	return u.Update(func(s *BatchMsgUpsert) {
-		s.ClearSendTime()
-	})
-}
-
 // SetType sets the "type" field.
 func (u *BatchMsgUpsertOne) SetType(v int32) *BatchMsgUpsertOne {
 	return u.Update(func(s *BatchMsgUpsert) {
@@ -1155,6 +1134,27 @@ func (u *BatchMsgUpsertOne) ClearType() *BatchMsgUpsertOne {
 	})
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (u *BatchMsgUpsertOne) SetOrganizationID(v uint64) *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *BatchMsgUpsertOne) AddOrganizationID(v uint64) *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *BatchMsgUpsertOne) UpdateOrganizationID() *BatchMsgUpsertOne {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
 // Exec executes the query.
 func (u *BatchMsgUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -1666,27 +1666,6 @@ func (u *BatchMsgUpsertBulk) ClearStopTime() *BatchMsgUpsertBulk {
 	})
 }
 
-// SetSendTime sets the "send_time" field.
-func (u *BatchMsgUpsertBulk) SetSendTime(v time.Time) *BatchMsgUpsertBulk {
-	return u.Update(func(s *BatchMsgUpsert) {
-		s.SetSendTime(v)
-	})
-}
-
-// UpdateSendTime sets the "send_time" field to the value that was provided on create.
-func (u *BatchMsgUpsertBulk) UpdateSendTime() *BatchMsgUpsertBulk {
-	return u.Update(func(s *BatchMsgUpsert) {
-		s.UpdateSendTime()
-	})
-}
-
-// ClearSendTime clears the value of the "send_time" field.
-func (u *BatchMsgUpsertBulk) ClearSendTime() *BatchMsgUpsertBulk {
-	return u.Update(func(s *BatchMsgUpsert) {
-		s.ClearSendTime()
-	})
-}
-
 // SetType sets the "type" field.
 func (u *BatchMsgUpsertBulk) SetType(v int32) *BatchMsgUpsertBulk {
 	return u.Update(func(s *BatchMsgUpsert) {
@@ -1715,6 +1694,27 @@ func (u *BatchMsgUpsertBulk) ClearType() *BatchMsgUpsertBulk {
 	})
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (u *BatchMsgUpsertBulk) SetOrganizationID(v uint64) *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.SetOrganizationID(v)
+	})
+}
+
+// AddOrganizationID adds v to the "organization_id" field.
+func (u *BatchMsgUpsertBulk) AddOrganizationID(v uint64) *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.AddOrganizationID(v)
+	})
+}
+
+// UpdateOrganizationID sets the "organization_id" field to the value that was provided on create.
+func (u *BatchMsgUpsertBulk) UpdateOrganizationID() *BatchMsgUpsertBulk {
+	return u.Update(func(s *BatchMsgUpsert) {
+		s.UpdateOrganizationID()
+	})
+}
+
 // Exec executes the query.
 func (u *BatchMsgUpsertBulk) Exec(ctx context.Context) error {
 	if u.create.err != nil {

+ 80 - 52
ent/batchmsg_update.go

@@ -302,26 +302,6 @@ func (bmu *BatchMsgUpdate) ClearStopTime() *BatchMsgUpdate {
 	return bmu
 }
 
-// SetSendTime sets the "send_time" field.
-func (bmu *BatchMsgUpdate) SetSendTime(t time.Time) *BatchMsgUpdate {
-	bmu.mutation.SetSendTime(t)
-	return bmu
-}
-
-// SetNillableSendTime sets the "send_time" field if the given value is not nil.
-func (bmu *BatchMsgUpdate) SetNillableSendTime(t *time.Time) *BatchMsgUpdate {
-	if t != nil {
-		bmu.SetSendTime(*t)
-	}
-	return bmu
-}
-
-// ClearSendTime clears the value of the "send_time" field.
-func (bmu *BatchMsgUpdate) ClearSendTime() *BatchMsgUpdate {
-	bmu.mutation.ClearSendTime()
-	return bmu
-}
-
 // SetType sets the "type" field.
 func (bmu *BatchMsgUpdate) SetType(i int32) *BatchMsgUpdate {
 	bmu.mutation.ResetType()
@@ -349,6 +329,27 @@ func (bmu *BatchMsgUpdate) ClearType() *BatchMsgUpdate {
 	return bmu
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (bmu *BatchMsgUpdate) SetOrganizationID(u uint64) *BatchMsgUpdate {
+	bmu.mutation.ResetOrganizationID()
+	bmu.mutation.SetOrganizationID(u)
+	return bmu
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (bmu *BatchMsgUpdate) SetNillableOrganizationID(u *uint64) *BatchMsgUpdate {
+	if u != nil {
+		bmu.SetOrganizationID(*u)
+	}
+	return bmu
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (bmu *BatchMsgUpdate) AddOrganizationID(u int64) *BatchMsgUpdate {
+	bmu.mutation.AddOrganizationID(u)
+	return bmu
+}
+
 // Mutation returns the BatchMsgMutation object of the builder.
 func (bmu *BatchMsgUpdate) Mutation() *BatchMsgMutation {
 	return bmu.mutation
@@ -396,7 +397,20 @@ func (bmu *BatchMsgUpdate) defaults() error {
 	return nil
 }
 
+// check runs all checks and user-defined validators on the builder.
+func (bmu *BatchMsgUpdate) check() error {
+	if v, ok := bmu.mutation.OrganizationID(); ok {
+		if err := batchmsg.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "BatchMsg.organization_id": %w`, err)}
+		}
+	}
+	return nil
+}
+
 func (bmu *BatchMsgUpdate) sqlSave(ctx context.Context) (n int, err error) {
+	if err := bmu.check(); err != nil {
+		return n, err
+	}
 	_spec := sqlgraph.NewUpdateSpec(batchmsg.Table, batchmsg.Columns, sqlgraph.NewFieldSpec(batchmsg.FieldID, field.TypeUint64))
 	if ps := bmu.mutation.predicates; len(ps) > 0 {
 		_spec.Predicate = func(selector *sql.Selector) {
@@ -492,12 +506,6 @@ func (bmu *BatchMsgUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if bmu.mutation.StopTimeCleared() {
 		_spec.ClearField(batchmsg.FieldStopTime, field.TypeTime)
 	}
-	if value, ok := bmu.mutation.SendTime(); ok {
-		_spec.SetField(batchmsg.FieldSendTime, field.TypeTime, value)
-	}
-	if bmu.mutation.SendTimeCleared() {
-		_spec.ClearField(batchmsg.FieldSendTime, field.TypeTime)
-	}
 	if value, ok := bmu.mutation.GetType(); ok {
 		_spec.SetField(batchmsg.FieldType, field.TypeInt32, value)
 	}
@@ -507,6 +515,12 @@ func (bmu *BatchMsgUpdate) sqlSave(ctx context.Context) (n int, err error) {
 	if bmu.mutation.TypeCleared() {
 		_spec.ClearField(batchmsg.FieldType, field.TypeInt32)
 	}
+	if value, ok := bmu.mutation.OrganizationID(); ok {
+		_spec.SetField(batchmsg.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := bmu.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(batchmsg.FieldOrganizationID, field.TypeUint64, value)
+	}
 	if n, err = sqlgraph.UpdateNodes(ctx, bmu.driver, _spec); err != nil {
 		if _, ok := err.(*sqlgraph.NotFoundError); ok {
 			err = &NotFoundError{batchmsg.Label}
@@ -801,26 +815,6 @@ func (bmuo *BatchMsgUpdateOne) ClearStopTime() *BatchMsgUpdateOne {
 	return bmuo
 }
 
-// SetSendTime sets the "send_time" field.
-func (bmuo *BatchMsgUpdateOne) SetSendTime(t time.Time) *BatchMsgUpdateOne {
-	bmuo.mutation.SetSendTime(t)
-	return bmuo
-}
-
-// SetNillableSendTime sets the "send_time" field if the given value is not nil.
-func (bmuo *BatchMsgUpdateOne) SetNillableSendTime(t *time.Time) *BatchMsgUpdateOne {
-	if t != nil {
-		bmuo.SetSendTime(*t)
-	}
-	return bmuo
-}
-
-// ClearSendTime clears the value of the "send_time" field.
-func (bmuo *BatchMsgUpdateOne) ClearSendTime() *BatchMsgUpdateOne {
-	bmuo.mutation.ClearSendTime()
-	return bmuo
-}
-
 // SetType sets the "type" field.
 func (bmuo *BatchMsgUpdateOne) SetType(i int32) *BatchMsgUpdateOne {
 	bmuo.mutation.ResetType()
@@ -848,6 +842,27 @@ func (bmuo *BatchMsgUpdateOne) ClearType() *BatchMsgUpdateOne {
 	return bmuo
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (bmuo *BatchMsgUpdateOne) SetOrganizationID(u uint64) *BatchMsgUpdateOne {
+	bmuo.mutation.ResetOrganizationID()
+	bmuo.mutation.SetOrganizationID(u)
+	return bmuo
+}
+
+// SetNillableOrganizationID sets the "organization_id" field if the given value is not nil.
+func (bmuo *BatchMsgUpdateOne) SetNillableOrganizationID(u *uint64) *BatchMsgUpdateOne {
+	if u != nil {
+		bmuo.SetOrganizationID(*u)
+	}
+	return bmuo
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (bmuo *BatchMsgUpdateOne) AddOrganizationID(u int64) *BatchMsgUpdateOne {
+	bmuo.mutation.AddOrganizationID(u)
+	return bmuo
+}
+
 // Mutation returns the BatchMsgMutation object of the builder.
 func (bmuo *BatchMsgUpdateOne) Mutation() *BatchMsgMutation {
 	return bmuo.mutation
@@ -908,7 +923,20 @@ func (bmuo *BatchMsgUpdateOne) defaults() error {
 	return nil
 }
 
+// check runs all checks and user-defined validators on the builder.
+func (bmuo *BatchMsgUpdateOne) check() error {
+	if v, ok := bmuo.mutation.OrganizationID(); ok {
+		if err := batchmsg.OrganizationIDValidator(v); err != nil {
+			return &ValidationError{Name: "organization_id", err: fmt.Errorf(`ent: validator failed for field "BatchMsg.organization_id": %w`, err)}
+		}
+	}
+	return nil
+}
+
 func (bmuo *BatchMsgUpdateOne) sqlSave(ctx context.Context) (_node *BatchMsg, err error) {
+	if err := bmuo.check(); err != nil {
+		return _node, err
+	}
 	_spec := sqlgraph.NewUpdateSpec(batchmsg.Table, batchmsg.Columns, sqlgraph.NewFieldSpec(batchmsg.FieldID, field.TypeUint64))
 	id, ok := bmuo.mutation.ID()
 	if !ok {
@@ -1021,12 +1049,6 @@ func (bmuo *BatchMsgUpdateOne) sqlSave(ctx context.Context) (_node *BatchMsg, er
 	if bmuo.mutation.StopTimeCleared() {
 		_spec.ClearField(batchmsg.FieldStopTime, field.TypeTime)
 	}
-	if value, ok := bmuo.mutation.SendTime(); ok {
-		_spec.SetField(batchmsg.FieldSendTime, field.TypeTime, value)
-	}
-	if bmuo.mutation.SendTimeCleared() {
-		_spec.ClearField(batchmsg.FieldSendTime, field.TypeTime)
-	}
 	if value, ok := bmuo.mutation.GetType(); ok {
 		_spec.SetField(batchmsg.FieldType, field.TypeInt32, value)
 	}
@@ -1036,6 +1058,12 @@ func (bmuo *BatchMsgUpdateOne) sqlSave(ctx context.Context) (_node *BatchMsg, er
 	if bmuo.mutation.TypeCleared() {
 		_spec.ClearField(batchmsg.FieldType, field.TypeInt32)
 	}
+	if value, ok := bmuo.mutation.OrganizationID(); ok {
+		_spec.SetField(batchmsg.FieldOrganizationID, field.TypeUint64, value)
+	}
+	if value, ok := bmuo.mutation.AddedOrganizationID(); ok {
+		_spec.AddField(batchmsg.FieldOrganizationID, field.TypeUint64, value)
+	}
 	_node = &BatchMsg{config: bmuo.config}
 	_spec.Assign = _node.assignValues
 	_spec.ScanValues = _node.scanValues

+ 2 - 2
ent/migrate/schema.go

@@ -52,8 +52,8 @@ var (
 		{Name: "fail", Type: field.TypeInt32, Nullable: true, Comment: "失败数量"},
 		{Name: "start_time", Type: field.TypeTime, Nullable: true, Comment: "开始时间"},
 		{Name: "stop_time", Type: field.TypeTime, Nullable: true, Comment: "结束时间"},
-		{Name: "send_time", Type: field.TypeTime, Nullable: true, Comment: "发送时间"},
 		{Name: "type", Type: field.TypeInt32, Nullable: true, Comment: "发送类型 1-群发消息 2-群发朋友圈"},
+		{Name: "organization_id", Type: field.TypeUint64, Comment: "organization_id | 租户ID"},
 	}
 	// BatchMsgTable holds the schema information for the "batch_msg" table.
 	BatchMsgTable = &schema.Table{
@@ -69,7 +69,7 @@ var (
 			{
 				Name:    "batchmsg_type",
 				Unique:  false,
-				Columns: []*schema.Column{BatchMsgColumns[16]},
+				Columns: []*schema.Column{BatchMsgColumns[15]},
 			},
 		},
 	}

+ 113 - 99
ent/mutation.go

@@ -1069,34 +1069,35 @@ func (m *AgentMutation) ResetEdge(name string) error {
 // BatchMsgMutation represents an operation that mutates the BatchMsg nodes in the graph.
 type BatchMsgMutation struct {
 	config
-	op            Op
-	typ           string
-	id            *uint64
-	created_at    *time.Time
-	updated_at    *time.Time
-	deleted_at    *time.Time
-	status        *uint8
-	addstatus     *int8
-	batch_no      *string
-	task_name     *string
-	fromwxid      *string
-	msg           *string
-	tag           *string
-	total         *int32
-	addtotal      *int32
-	success       *int32
-	addsuccess    *int32
-	fail          *int32
-	addfail       *int32
-	start_time    *time.Time
-	stop_time     *time.Time
-	send_time     *time.Time
-	_type         *int32
-	add_type      *int32
-	clearedFields map[string]struct{}
-	done          bool
-	oldValue      func(context.Context) (*BatchMsg, error)
-	predicates    []predicate.BatchMsg
+	op                 Op
+	typ                string
+	id                 *uint64
+	created_at         *time.Time
+	updated_at         *time.Time
+	deleted_at         *time.Time
+	status             *uint8
+	addstatus          *int8
+	batch_no           *string
+	task_name          *string
+	fromwxid           *string
+	msg                *string
+	tag                *string
+	total              *int32
+	addtotal           *int32
+	success            *int32
+	addsuccess         *int32
+	fail               *int32
+	addfail            *int32
+	start_time         *time.Time
+	stop_time          *time.Time
+	_type              *int32
+	add_type           *int32
+	organization_id    *uint64
+	addorganization_id *int64
+	clearedFields      map[string]struct{}
+	done               bool
+	oldValue           func(context.Context) (*BatchMsg, error)
+	predicates         []predicate.BatchMsg
 }
 
 var _ ent.Mutation = (*BatchMsgMutation)(nil)
@@ -1947,55 +1948,6 @@ func (m *BatchMsgMutation) ResetStopTime() {
 	delete(m.clearedFields, batchmsg.FieldStopTime)
 }
 
-// SetSendTime sets the "send_time" field.
-func (m *BatchMsgMutation) SetSendTime(t time.Time) {
-	m.send_time = &t
-}
-
-// SendTime returns the value of the "send_time" field in the mutation.
-func (m *BatchMsgMutation) SendTime() (r time.Time, exists bool) {
-	v := m.send_time
-	if v == nil {
-		return
-	}
-	return *v, true
-}
-
-// OldSendTime returns the old "send_time" field's value of the BatchMsg entity.
-// If the BatchMsg object wasn't provided to the builder, the object is fetched from the database.
-// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
-func (m *BatchMsgMutation) OldSendTime(ctx context.Context) (v time.Time, err error) {
-	if !m.op.Is(OpUpdateOne) {
-		return v, errors.New("OldSendTime is only allowed on UpdateOne operations")
-	}
-	if m.id == nil || m.oldValue == nil {
-		return v, errors.New("OldSendTime requires an ID field in the mutation")
-	}
-	oldValue, err := m.oldValue(ctx)
-	if err != nil {
-		return v, fmt.Errorf("querying old value for OldSendTime: %w", err)
-	}
-	return oldValue.SendTime, nil
-}
-
-// ClearSendTime clears the value of the "send_time" field.
-func (m *BatchMsgMutation) ClearSendTime() {
-	m.send_time = nil
-	m.clearedFields[batchmsg.FieldSendTime] = struct{}{}
-}
-
-// SendTimeCleared returns if the "send_time" field was cleared in this mutation.
-func (m *BatchMsgMutation) SendTimeCleared() bool {
-	_, ok := m.clearedFields[batchmsg.FieldSendTime]
-	return ok
-}
-
-// ResetSendTime resets all changes to the "send_time" field.
-func (m *BatchMsgMutation) ResetSendTime() {
-	m.send_time = nil
-	delete(m.clearedFields, batchmsg.FieldSendTime)
-}
-
 // SetType sets the "type" field.
 func (m *BatchMsgMutation) SetType(i int32) {
 	m._type = &i
@@ -2066,6 +2018,62 @@ func (m *BatchMsgMutation) ResetType() {
 	delete(m.clearedFields, batchmsg.FieldType)
 }
 
+// SetOrganizationID sets the "organization_id" field.
+func (m *BatchMsgMutation) SetOrganizationID(u uint64) {
+	m.organization_id = &u
+	m.addorganization_id = nil
+}
+
+// OrganizationID returns the value of the "organization_id" field in the mutation.
+func (m *BatchMsgMutation) OrganizationID() (r uint64, exists bool) {
+	v := m.organization_id
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldOrganizationID returns the old "organization_id" field's value of the BatchMsg entity.
+// If the BatchMsg object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *BatchMsgMutation) OldOrganizationID(ctx context.Context) (v uint64, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldOrganizationID is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldOrganizationID requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldOrganizationID: %w", err)
+	}
+	return oldValue.OrganizationID, nil
+}
+
+// AddOrganizationID adds u to the "organization_id" field.
+func (m *BatchMsgMutation) AddOrganizationID(u int64) {
+	if m.addorganization_id != nil {
+		*m.addorganization_id += u
+	} else {
+		m.addorganization_id = &u
+	}
+}
+
+// AddedOrganizationID returns the value that was added to the "organization_id" field in this mutation.
+func (m *BatchMsgMutation) AddedOrganizationID() (r int64, exists bool) {
+	v := m.addorganization_id
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// ResetOrganizationID resets all changes to the "organization_id" field.
+func (m *BatchMsgMutation) ResetOrganizationID() {
+	m.organization_id = nil
+	m.addorganization_id = nil
+}
+
 // Where appends a list predicates to the BatchMsgMutation builder.
 func (m *BatchMsgMutation) Where(ps ...predicate.BatchMsg) {
 	m.predicates = append(m.predicates, ps...)
@@ -2143,12 +2151,12 @@ func (m *BatchMsgMutation) Fields() []string {
 	if m.stop_time != nil {
 		fields = append(fields, batchmsg.FieldStopTime)
 	}
-	if m.send_time != nil {
-		fields = append(fields, batchmsg.FieldSendTime)
-	}
 	if m._type != nil {
 		fields = append(fields, batchmsg.FieldType)
 	}
+	if m.organization_id != nil {
+		fields = append(fields, batchmsg.FieldOrganizationID)
+	}
 	return fields
 }
 
@@ -2185,10 +2193,10 @@ func (m *BatchMsgMutation) Field(name string) (ent.Value, bool) {
 		return m.StartTime()
 	case batchmsg.FieldStopTime:
 		return m.StopTime()
-	case batchmsg.FieldSendTime:
-		return m.SendTime()
 	case batchmsg.FieldType:
 		return m.GetType()
+	case batchmsg.FieldOrganizationID:
+		return m.OrganizationID()
 	}
 	return nil, false
 }
@@ -2226,10 +2234,10 @@ func (m *BatchMsgMutation) OldField(ctx context.Context, name string) (ent.Value
 		return m.OldStartTime(ctx)
 	case batchmsg.FieldStopTime:
 		return m.OldStopTime(ctx)
-	case batchmsg.FieldSendTime:
-		return m.OldSendTime(ctx)
 	case batchmsg.FieldType:
 		return m.OldType(ctx)
+	case batchmsg.FieldOrganizationID:
+		return m.OldOrganizationID(ctx)
 	}
 	return nil, fmt.Errorf("unknown BatchMsg field %s", name)
 }
@@ -2337,19 +2345,19 @@ func (m *BatchMsgMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetStopTime(v)
 		return nil
-	case batchmsg.FieldSendTime:
-		v, ok := value.(time.Time)
+	case batchmsg.FieldType:
+		v, ok := value.(int32)
 		if !ok {
 			return fmt.Errorf("unexpected type %T for field %s", value, name)
 		}
-		m.SetSendTime(v)
+		m.SetType(v)
 		return nil
-	case batchmsg.FieldType:
-		v, ok := value.(int32)
+	case batchmsg.FieldOrganizationID:
+		v, ok := value.(uint64)
 		if !ok {
 			return fmt.Errorf("unexpected type %T for field %s", value, name)
 		}
-		m.SetType(v)
+		m.SetOrganizationID(v)
 		return nil
 	}
 	return fmt.Errorf("unknown BatchMsg field %s", name)
@@ -2374,6 +2382,9 @@ func (m *BatchMsgMutation) AddedFields() []string {
 	if m.add_type != nil {
 		fields = append(fields, batchmsg.FieldType)
 	}
+	if m.addorganization_id != nil {
+		fields = append(fields, batchmsg.FieldOrganizationID)
+	}
 	return fields
 }
 
@@ -2392,6 +2403,8 @@ func (m *BatchMsgMutation) AddedField(name string) (ent.Value, bool) {
 		return m.AddedFail()
 	case batchmsg.FieldType:
 		return m.AddedType()
+	case batchmsg.FieldOrganizationID:
+		return m.AddedOrganizationID()
 	}
 	return nil, false
 }
@@ -2436,6 +2449,13 @@ func (m *BatchMsgMutation) AddField(name string, value ent.Value) error {
 		}
 		m.AddType(v)
 		return nil
+	case batchmsg.FieldOrganizationID:
+		v, ok := value.(int64)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.AddOrganizationID(v)
+		return nil
 	}
 	return fmt.Errorf("unknown BatchMsg numeric field %s", name)
 }
@@ -2480,9 +2500,6 @@ func (m *BatchMsgMutation) ClearedFields() []string {
 	if m.FieldCleared(batchmsg.FieldStopTime) {
 		fields = append(fields, batchmsg.FieldStopTime)
 	}
-	if m.FieldCleared(batchmsg.FieldSendTime) {
-		fields = append(fields, batchmsg.FieldSendTime)
-	}
 	if m.FieldCleared(batchmsg.FieldType) {
 		fields = append(fields, batchmsg.FieldType)
 	}
@@ -2536,9 +2553,6 @@ func (m *BatchMsgMutation) ClearField(name string) error {
 	case batchmsg.FieldStopTime:
 		m.ClearStopTime()
 		return nil
-	case batchmsg.FieldSendTime:
-		m.ClearSendTime()
-		return nil
 	case batchmsg.FieldType:
 		m.ClearType()
 		return nil
@@ -2592,12 +2606,12 @@ func (m *BatchMsgMutation) ResetField(name string) error {
 	case batchmsg.FieldStopTime:
 		m.ResetStopTime()
 		return nil
-	case batchmsg.FieldSendTime:
-		m.ResetSendTime()
-		return nil
 	case batchmsg.FieldType:
 		m.ResetType()
 		return nil
+	case batchmsg.FieldOrganizationID:
+		m.ResetOrganizationID()
+		return nil
 	}
 	return fmt.Errorf("unknown BatchMsg field %s", name)
 }

+ 4 - 0
ent/runtime/runtime.go

@@ -100,6 +100,10 @@ func init() {
 	batchmsgDescTaskName := batchmsgFields[2].Descriptor()
 	// batchmsg.DefaultTaskName holds the default value on creation for the task_name field.
 	batchmsg.DefaultTaskName = batchmsgDescTaskName.Default.(string)
+	// batchmsgDescOrganizationID is the schema descriptor for organization_id field.
+	batchmsgDescOrganizationID := batchmsgFields[12].Descriptor()
+	// batchmsg.OrganizationIDValidator is a validator for the "organization_id" field. It is called by the builders before save.
+	batchmsg.OrganizationIDValidator = batchmsgDescOrganizationID.Validators[0].(func(uint64) error)
 	contactMixin := schema.Contact{}.Mixin()
 	contactMixinHooks2 := contactMixin[2].Hooks()
 	contact.Hooks[0] = contactMixinHooks2[0]

+ 1 - 1
ent/schema/batch_msg.go

@@ -28,8 +28,8 @@ func (BatchMsg) Fields() []ent.Field {
 		field.Int32("fail").Optional().Comment("失败数量"),
 		field.Time("start_time").Optional().Comment("开始时间"),
 		field.Time("stop_time").Optional().Comment("结束时间"),
-		field.Time("send_time").Optional().Default(nil).Comment("发送时间"),
 		field.Int32("type").Optional().Comment("发送类型 1-群发消息 2-群发朋友圈"),
+		field.Uint64("organization_id").Positive().Comment("organization_id | 租户ID"),
 	}
 }
 func (BatchMsg) Mixin() []ent.Mixin {

+ 12 - 12
ent/set_not_nil.go

@@ -512,49 +512,49 @@ func (bm *BatchMsgCreate) SetNotNilStopTime(value *time.Time) *BatchMsgCreate {
 }
 
 // set field if value's pointer is not nil.
-func (bm *BatchMsgUpdate) SetNotNilSendTime(value *time.Time) *BatchMsgUpdate {
+func (bm *BatchMsgUpdate) SetNotNilType(value *int32) *BatchMsgUpdate {
 	if value != nil {
-		return bm.SetSendTime(*value)
+		return bm.SetType(*value)
 	}
 	return bm
 }
 
 // set field if value's pointer is not nil.
-func (bm *BatchMsgUpdateOne) SetNotNilSendTime(value *time.Time) *BatchMsgUpdateOne {
+func (bm *BatchMsgUpdateOne) SetNotNilType(value *int32) *BatchMsgUpdateOne {
 	if value != nil {
-		return bm.SetSendTime(*value)
+		return bm.SetType(*value)
 	}
 	return bm
 }
 
 // set field if value's pointer is not nil.
-func (bm *BatchMsgCreate) SetNotNilSendTime(value *time.Time) *BatchMsgCreate {
+func (bm *BatchMsgCreate) SetNotNilType(value *int32) *BatchMsgCreate {
 	if value != nil {
-		return bm.SetSendTime(*value)
+		return bm.SetType(*value)
 	}
 	return bm
 }
 
 // set field if value's pointer is not nil.
-func (bm *BatchMsgUpdate) SetNotNilType(value *int32) *BatchMsgUpdate {
+func (bm *BatchMsgUpdate) SetNotNilOrganizationID(value *uint64) *BatchMsgUpdate {
 	if value != nil {
-		return bm.SetType(*value)
+		return bm.SetOrganizationID(*value)
 	}
 	return bm
 }
 
 // set field if value's pointer is not nil.
-func (bm *BatchMsgUpdateOne) SetNotNilType(value *int32) *BatchMsgUpdateOne {
+func (bm *BatchMsgUpdateOne) SetNotNilOrganizationID(value *uint64) *BatchMsgUpdateOne {
 	if value != nil {
-		return bm.SetType(*value)
+		return bm.SetOrganizationID(*value)
 	}
 	return bm
 }
 
 // set field if value's pointer is not nil.
-func (bm *BatchMsgCreate) SetNotNilType(value *int32) *BatchMsgCreate {
+func (bm *BatchMsgCreate) SetNotNilOrganizationID(value *uint64) *BatchMsgCreate {
 	if value != nil {
-		return bm.SetType(*value)
+		return bm.SetOrganizationID(*value)
 	}
 	return bm
 }

+ 44 - 0
internal/handler/batch_msg/stop_batch_msg_handler.go

@@ -0,0 +1,44 @@
+package batch_msg
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/batch_msg"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /batch_msg/stop batch_msg StopBatchMsg
+//
+// Stop batch_msg by ID | 通过ID停止BatchMsg
+//
+// Stop batch_msg by ID | 通过ID停止BatchMsg
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func StopBatchMsgHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := batch_msg.NewStopBatchMsgLogic(r.Context(), svcCtx)
+		resp, err := l.StopBatchMsg(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 5 - 0
internal/handler/routes.go

@@ -592,6 +592,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/batch_msg",
 					Handler: batch_msg.GetBatchMsgByIdHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/batch_msg/stop",
+					Handler: batch_msg.StopBatchMsgHandler(serverCtx),
+				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),

+ 6 - 54
internal/logic/batch_msg/create_batch_msg_logic.go

@@ -36,9 +36,10 @@ func NewCreateBatchMsgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cr
 }
 
 func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.BaseMsgResp, error) {
-	var err error
 	organizationId := l.ctx.Value("organizationId").(uint64)
 
+	var err error
+
 	all := false
 	for _, labelName := range req.Labels {
 		if strings.EqualFold(labelName, "all") || strings.EqualFold(labelName, "全部") {
@@ -48,8 +49,6 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 		}
 	}
 
-	l.Logger.Infof("CreateBatchMsgLogic: %v", *req)
-
 	startTime := time.Now()
 	// req.StartTimeStr 不为nil并且不为空
 	if req.StartTimeStr != nil && *req.StartTimeStr != "" {
@@ -62,18 +61,6 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 		}
 	}
 
-	// 定时发送时间
-	var sendTime *time.Time
-	if req.SendTimeStr != nil && *req.SendTimeStr != "" {
-		sendTimeParse, err := time.Parse("2006-01-02 15:04:05", *req.SendTimeStr)
-		if err != nil {
-			// 处理错误,例如打印错误并返回
-			l.Logger.Errorf("时间字符串转换错误: %v", err)
-			return nil, err
-		}
-		sendTime = &sendTimeParse
-	}
-
 	// 把 req.Msg 字符串的内容 json_decode 到 msgArray
 	// 然后再把每一条信息都给所有指定的用户记录到 message_records 表
 	var msgArray []custom_types.Action
@@ -145,7 +132,8 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 			//l.Logger.Infof("CreateBatchMsgLogic userlist= %v", userlist)
 		}
 	}
-	total := int32(len(userlist))
+	// 这里是根据userlist 和 批量消息数 获得最终待发送消息总数
+	total := int32(len(userlist)) * int32(len(msgActionList))
 
 	if total == 0 {
 		return &types.BaseMsgResp{Msg: errormsg.TargetNotFound}, nil
@@ -154,13 +142,7 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 	uuid := uuidx.NewUUID()
 	batchNo := uuid.String()
 
-	// 开始事务
-	tx, err := l.svcCtx.DB.Tx(context.Background())
-	if err != nil {
-		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-	}
-
-	batchMsg, err := l.svcCtx.DB.BatchMsg.Create().
+	_, err = l.svcCtx.DB.BatchMsg.Create().
 		SetNotNilBatchNo(&batchNo).
 		SetNotNilFromwxid(req.Fromwxid).
 		SetNotNilMsg(req.Msg).
@@ -168,43 +150,13 @@ func (l *CreateBatchMsgLogic) CreateBatchMsg(req *types.BatchMsgInfo) (*types.Ba
 		SetTotal(total).
 		SetNotNilTaskName(req.TaskName).
 		SetNotNilStartTime(&startTime).
-		SetNotNilSendTime(sendTime).
 		SetNotNilType(req.Type).
+		SetNotNilOrganizationID(&organizationId).
 		Save(l.ctx)
 
 	if err != nil {
-		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
-	// 批量记录信息到 message_records 表里
-	for _, user := range userlist {
-		// 每个用户的所有 信息 组合到一个数组里然后批量插入,减少DB的压力
-		bulkCreate := make([]*ent.MessageRecordsCreate, 0)
-		for idx, msg := range msgActionList {
-			bulkCreate = append(bulkCreate, l.svcCtx.DB.MessageRecords.Create().
-				SetStatus(1).
-				SetNotNilBotWxid(req.Fromwxid).
-				SetNotNilContactID(&user.ID).
-				SetNotNilContactType(&user.Type).
-				SetNotNilContentType(&msg.Type).
-				SetNotNilContent(&msg.Content).
-				SetNotNilMeta(msg.Meta).
-				SetNotNilSendTime(sendTime).
-				SetNotNilContactWxid(&user.Wxid). //接收方wxid
-				SetSourceType(2).                 // 2:批量消息
-				SetSourceID(batchMsg.ID).         // 批量消息ID,batch_msg 表主键
-				SetSubSourceID(uint64(idx)).      // 用索引作为 sub_source_id
-				SetOrganizationID(organizationId),
-			)
-		}
-		err = tx.MessageRecords.CreateBulk(bulkCreate...).Exec(l.ctx)
-		if err != nil {
-			_ = tx.Rollback()
-			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
-		}
-	}
-	_ = tx.Commit()
-
 	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
 }

+ 22 - 15
internal/logic/batch_msg/get_batch_msg_by_id_logic.go

@@ -2,6 +2,9 @@ package batch_msg
 
 import (
 	"context"
+	"github.com/zeromicro/go-zero/core/errorx"
+	"wechat-api/ent"
+	"wechat-api/ent/batchmsg"
 
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -28,8 +31,13 @@ func NewGetBatchMsgByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G
 }
 
 func (l *GetBatchMsgByIdLogic) GetBatchMsgById(req *types.IDReq) (*types.BatchMsgInfoResp, error) {
-	data, err := l.svcCtx.DB.BatchMsg.Get(l.ctx, req.Id)
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
+	data, err := l.svcCtx.DB.BatchMsg.Query().Where(batchmsg.ID(req.Id), batchmsg.OrganizationID(organizationId)).First(l.ctx)
 	if err != nil {
+		if ent.IsNotFound(err) {
+			return nil, errorx.NewInvalidArgumentError("群发消息不存在")
+		}
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
@@ -44,20 +52,19 @@ func (l *GetBatchMsgByIdLogic) GetBatchMsgById(req *types.IDReq) (*types.BatchMs
 				CreatedAt: pointy.GetPointer(data.CreatedAt.UnixMilli()),
 				UpdatedAt: pointy.GetPointer(data.UpdatedAt.UnixMilli()),
 			},
-			Status:      &data.Status,
-			BatchNo:     &data.BatchNo,
-			TaskName:    &data.TaskName,
-			Fromwxid:    &data.Fromwxid,
-			Msg:         &data.Msg,
-			Tag:         &data.Tag,
-			Total:       &data.Total,
-			Success:     &data.Success,
-			Fail:        &data.Fail,
-			Type:        &data.Type,
-			StartTime:   pointy.GetUnixMilliPointer(data.StartTime.UnixMilli()),
-			StopTime:    pointy.GetUnixMilliPointer(data.StopTime.UnixMilli()),
-			SendTime:    pointy.GetUnixMilliPointer(data.SendTime.UnixMilli()),
-			SendTimeStr: pointy.GetPointer(data.SendTime.Format("2006-01-02 15:04:05")),
+			Status:       &data.Status,
+			BatchNo:      &data.BatchNo,
+			TaskName:     &data.TaskName,
+			Fromwxid:     &data.Fromwxid,
+			Msg:          &data.Msg,
+			Tag:          &data.Tag,
+			Total:        &data.Total,
+			Success:      &data.Success,
+			Fail:         &data.Fail,
+			Type:         &data.Type,
+			StartTime:    pointy.GetUnixMilliPointer(data.StartTime.UnixMilli()),
+			StopTime:     pointy.GetUnixMilliPointer(data.StopTime.UnixMilli()),
+			StartTimeStr: pointy.GetPointer(data.StartTime.Format("2006-01-02 15:04:05")),
 		},
 	}, nil
 }

+ 16 - 14
internal/logic/batch_msg/get_batch_msg_list_logic.go

@@ -30,8 +30,11 @@ func NewGetBatchMsgListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G
 }
 
 func (l *GetBatchMsgListLogic) GetBatchMsgList(req *types.BatchMsgListReq) (*types.BatchMsgListResp, error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+
 	var predicates []predicate.BatchMsg
 	predicates = append(predicates, batchmsg.Type(*req.Type))
+	predicates = append(predicates, batchmsg.OrganizationIDEQ(organizationId))
 	if req.BatchNo != nil {
 		predicates = append(predicates, batchmsg.BatchNoContains(*req.BatchNo))
 	}
@@ -62,20 +65,19 @@ func (l *GetBatchMsgListLogic) GetBatchMsgList(req *types.BatchMsgListReq) (*typ
 					CreatedAt: pointy.GetPointer(v.CreatedAt.UnixMilli()),
 					UpdatedAt: pointy.GetPointer(v.UpdatedAt.UnixMilli()),
 				},
-				Status:      &v.Status,
-				BatchNo:     &v.BatchNo,
-				TaskName:    &v.TaskName,
-				Fromwxid:    &v.Fromwxid,
-				Msg:         &v.Msg,
-				Tag:         &v.Tag,
-				Total:       &v.Total,
-				Success:     &v.Success,
-				Fail:        &v.Fail,
-				Type:        &v.Type,
-				StartTime:   pointy.GetUnixMilliPointer(v.StartTime.UnixMilli()),
-				StopTime:    pointy.GetUnixMilliPointer(v.StopTime.UnixMilli()),
-				SendTime:    pointy.GetUnixMilliPointer(v.SendTime.UnixMilli()),
-				SendTimeStr: pointy.GetPointer(v.SendTime.Format("2006-01-02 15:04:05")),
+				Status:       &v.Status,
+				BatchNo:      &v.BatchNo,
+				TaskName:     &v.TaskName,
+				Fromwxid:     &v.Fromwxid,
+				Msg:          &v.Msg,
+				Tag:          &v.Tag,
+				Total:        &v.Total,
+				Success:      &v.Success,
+				Fail:         &v.Fail,
+				Type:         &v.Type,
+				StartTime:    pointy.GetUnixMilliPointer(v.StartTime.UnixMilli()),
+				StopTime:     pointy.GetUnixMilliPointer(v.StopTime.UnixMilli()),
+				StartTimeStr: pointy.GetPointer(v.StartTime.Format("2006-01-02 15:04:05")),
 			})
 	}
 

+ 55 - 0
internal/logic/batch_msg/stop_batch_msg_logic.go

@@ -0,0 +1,55 @@
+package batch_msg
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/errorx"
+	"wechat-api/ent"
+	"wechat-api/ent/batchmsg"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type StopBatchMsgLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewStopBatchMsgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StopBatchMsgLogic {
+	return &StopBatchMsgLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *StopBatchMsgLogic) StopBatchMsg(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
+	organizationId := l.ctx.Value("organizationId").(uint64)
+	batchMsg, err := l.svcCtx.DB.BatchMsg.Query().Where(batchmsg.ID(req.Id), batchmsg.OrganizationID(organizationId)).First(l.ctx)
+	if err != nil {
+		if ent.IsNotFound(err) {
+			return nil, errorx.NewInvalidArgumentError("群发消息不存在")
+		}
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	if batchMsg.Status == 0 {
+		// 设置状态为3,代表已停止
+		err = l.svcCtx.DB.BatchMsg.UpdateOneID(batchMsg.ID).SetStatus(3).Exec(l.ctx)
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+	} else if batchMsg.Status == 3 {
+		return nil, errorx.NewInvalidArgumentError("群发消息已停止")
+	} else if batchMsg.Status == 2 {
+		return nil, errorx.NewInvalidArgumentError("群发消息已发送完毕,无法停止")
+	} else if batchMsg.Status == 1 {
+		return nil, errorx.NewInvalidArgumentError("群发消息正在发送中,无法停止")
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 0 - 3
internal/types/types.go

@@ -1235,9 +1235,6 @@ type BatchMsgInfo struct {
 	StartTimeStr *string `json:"startTimeStr,optional"`
 	// 结束时间
 	StopTime *int64 `json:"stopTime,optional"`
-	// 发送时间
-	SendTime    *int64  `json:"sendTime,optional"`
-	SendTimeStr *string `json:"sendTimeStr,optional"`
 	// 标签列表
 	Labels []string `json:"labels,optional"`
 	// 标签列表