Browse Source

cow: 解决冲突

Yi 6 months ago
parent
commit
3e944552e3

+ 8 - 6
cmd/crontab.go

@@ -1,12 +1,10 @@
 package cmd
 
 import (
-	"context"
-	"fmt"
+	"kpt-pasture/config"
 	"kpt-pasture/dep"
 
-	"gitee.com/xuyiping_admin/pkg/cmd"
-	"gitee.com/xuyiping_admin/pkg/xerr"
+	"gitee.com/xuyiping_admin/pkg/svcutil"
 	"github.com/spf13/cobra"
 )
 
@@ -15,11 +13,14 @@ var CrontabCmd = &cobra.Command{
 	Use:   "crontab",
 	Short: "计划任务",
 	Run: func(cmd *cobra.Command, args []string) {
-		fmt.Println("crontab called")
+		svcutil.WaitFor(config.Options().HTTPServerAddr, func(stop <-chan struct{}) error {
+			dep.DICrontabService().Run(stop)
+			return nil
+		})
 	},
 }
 
-func init() {
+/*func init() {
 	// 每日零点更新牛只日龄脚本
 	cmd.Instant(JobCmd, "update:cowAge", UpdateCowDayAge, "更新牛只日龄")
 	cmd.Instant(JobCmd, "gen:cowAge", GenerateWorkOrder, "创建每天的工单")
@@ -40,3 +41,4 @@ func GenerateWorkOrder(ctx context.Context, args []string) error {
 	}
 	return nil
 }
+*/

+ 5 - 1
config/app.develop.yaml

@@ -32,4 +32,8 @@ side_work_setting:
     queues:
       workflow: 20
       low: 10
-      default: 5
+      default: 5
+cron:
+  crontab_start_run: false
+  update_cow_dayAge: "0 */1 * * * ?"
+  generate_work_order: "0 0 22 * * ?"

+ 10 - 0
config/app.go

@@ -41,6 +41,16 @@ type AppConfig struct {
 
 	// asynq 相关配置
 	SideWorkSetting SideWorkSetting `yaml:"side_work_setting"`
+
+	CronSetting CronSetting `json:"cron_setting" yaml:"cron"`
+}
+
+type CronSetting struct {
+	// 是否启动任务时先跑一次
+	CrontabStartRun bool `yaml:"crontab_start_run"`
+	// CRONTAB 表达式
+	UpdateCowDayAge   string `yaml:"update_cow_dayAge"`
+	GenerateWorkOrder string `yaml:"generate_work_order"`
 }
 
 type JwtTokenKeyConfig struct {

+ 4 - 0
config/app.test.yaml

@@ -32,3 +32,7 @@ side_work_setting:
       workflow: 20
       low: 10
       default: 5
+cron:
+  crontab_start_run: false
+  update_cow_dayAge: "0 */1 * * * ?"
+  generate_work_order: "0 0 22 * * ?"

+ 47 - 7
dep/di_crontab.go

@@ -1,14 +1,54 @@
 package dep
 
-import "kpt-pasture/module/crontab"
+import (
+	"kpt-pasture/config"
+	"kpt-pasture/module/crontab"
 
-func DICrontabService() crontab.Crontab {
-	var out crontab.Crontab
-	if err := DI().Invoke(func(in crontab.Crontab) {
-		out = in
-	}); err != nil {
+	"go.uber.org/dig"
+
+	"gitee.com/xuyiping_admin/pkg/cron"
+	prom "github.com/prometheus/client_golang/prometheus"
+)
+
+var DataCenterCrontabCounterVec = prom.NewCounterVec(
+	prom.CounterOpts{
+		Namespace: "kpt-pasture",
+		Subsystem: "crontab",
+		Name:      "crontab",
+	},
+	[]string{"name"},
+)
+
+func DICrontabService() (out *cron.Crontab) {
+	container := DI()
+	if err := container.Provide(EntryCrontab); err != nil {
+		panic(err)
+	}
+	if err := container.Invoke(func(c *cron.Crontab) { out = c }); err != nil {
+		panic(err)
+	}
+	return
+}
+
+// CrontabDependency 依赖注入结构体
+type CrontabDependency struct {
+	dig.In
+
+	CrontabHub crontab.Crontab // 定时任务
+}
+
+func EntryCrontab(dependency CrontabDependency) *cron.Crontab {
+	cfg := config.Options()
+	cs := cfg.CronSetting
+	newCrontab := cron.NewCrontab(DataCenterCrontabCounterVec)
+	err := newCrontab.Bind("UpdateCowDayAge", cs.UpdateCowDayAge, dependency.CrontabHub.UpdateCowInfo)
+	if err != nil {
+		panic(err)
+	}
+	err = newCrontab.Bind("GenerateWorkOrder", cs.GenerateWorkOrder, dependency.CrontabHub.GenerateAsynqWorkOrder)
+	if err != nil {
 		panic(err)
 	}
 
-	return out
+	return newCrontab
 }

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20240903091812-dfb3f5f46972
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20240905100333-97e1bcf51bd3
 	gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eko/gocache v1.1.0

+ 12 - 0
go.sum

@@ -56,6 +56,18 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20240903085608-021437ccc8db h1:eF1rpNr5
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240903085608-021437ccc8db/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240903091812-dfb3f5f46972 h1:UvNVKnlH2AU0sSELWxNC3NP822VJ/5vn1lVoepo8Wp0=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240903091812-dfb3f5f46972/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240904074804-21d4cb43dda8 h1:QYpogX3+y6/W8WIv/QoqUg/x69MIuWgEkNturvioV4c=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240904074804-21d4cb43dda8/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905015138-86162dede551 h1:2VOWlximGeR3X2llS4vSvE08YDsAonuRTElTowiD0rA=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905015138-86162dede551/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905023855-2b00583fae76 h1:ErVpREHmwqZLQI9ILsJtqtM25k8Yi2CqbiswjlIVa8A=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905023855-2b00583fae76/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905024709-477a20f21d1e h1:YnUaLh7OfaRdp75etn+8iz18U7mArP4BKFw7ReTrPqo=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905024709-477a20f21d1e/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905070443-31141edfb80d h1:YXjVQZuGK1J36FKPYh0rYxIyjm79tOnikkYG68O1rck=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905070443-31141edfb80d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905100333-97e1bcf51bd3 h1:hNO95yUSYiSGfDKRper22iC+UdZFlgfLuwPigAy1WM0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240905100333-97e1bcf51bd3/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015 h1:dfb5dRd57L2HKjdwLT93UFmPYFPOmEl56gtZmqcNnaE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015/go.mod h1:Fk4GYI/v0IK3XFrm1Gn+VkgCz5Y7mfswD5hsTJYOG6A=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 26 - 6
http/handler/pasture/seme_time.go

@@ -3,6 +3,7 @@ package pasture
 import (
 	"kpt-pasture/http/middleware"
 	"net/http"
+	"strconv"
 
 	"gitee.com/xuyiping_admin/pkg/xerr"
 
@@ -14,8 +15,8 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
-// SemeTimeCreated 同期策略添加
-func SemeTimeCreated(c *gin.Context) {
+// SameTimeCreatedOrUpdate 同期策略添加或者更新
+func SameTimeCreatedOrUpdate(c *gin.Context) {
 	var req pasturePb.SearchSameTimeList
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
@@ -43,7 +44,7 @@ func SemeTimeCreated(c *gin.Context) {
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.CreateOrUpdateSemeTime(c, &req); err != nil {
+	if err := middleware.BackendOperation(c).OpsService.CreateOrUpdateSameTime(c, &req); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
@@ -55,8 +56,8 @@ func SemeTimeCreated(c *gin.Context) {
 	})
 }
 
-// SemeTimeList 同步策略列表
-func SemeTimeList(c *gin.Context) {
+// SameTimeList 同步策略列表
+func SameTimeList(c *gin.Context) {
 	var req pasturePb.SearchNameRequest
 	if err := ginutil.BindProto(c, &req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
@@ -69,10 +70,29 @@ func SemeTimeList(c *gin.Context) {
 		PageOffset: int32(c.GetInt(middleware.PageOffset)),
 	}
 
-	res, err := middleware.BackendOperation(c).OpsService.SearchSemeTimeList(c, &req, pagination)
+	res, err := middleware.BackendOperation(c).OpsService.SearchSameTimeList(c, &req, pagination)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
 	ginutil.JSONResp(c, res)
 }
+
+func SameTimeIsShow(c *gin.Context) {
+	sameTimeIdStr := c.Param("id")
+	sameTimeId, _ := strconv.Atoi(sameTimeIdStr)
+
+	if err := valid.Validate(sameTimeId, valid.Required, valid.Min(1)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	if err := middleware.BackendOperation(c).OpsService.SameTimeIsShow(c, int64(sameTimeId)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}

+ 3 - 2
http/route/pasture_api.go

@@ -46,7 +46,8 @@ func PastureManageAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		pastureRoute.PUT("/immunization/is_show/:id", pasture.ImmunizationIsShow)
 
 		// 同期相关
-		pastureRoute.POST("/seme/time/create", pasture.SemeTimeCreated)
-		pastureRoute.POST("/seme/time/list", pasture.SemeTimeList)
+		pastureRoute.POST("/same/time/createOrUpdate", pasture.SameTimeCreatedOrUpdate)
+		pastureRoute.POST("/same/time/list", pasture.SameTimeList)
+		pastureRoute.PUT("/same/time/is_show/:id", pasture.SameTimeIsShow)
 	}
 }

+ 2 - 2
model/cow.go

@@ -79,7 +79,7 @@ func NewCow(req *pasturePb.SearchEnterData) *Cow {
 	}
 }
 
-func NewCalfCow(motherId, fatherId int64, calf *EventCalvingCalf) *Cow {
+func NewCalfCow(motherId, fatherId int64, calf *CalvingCalf) *Cow {
 	return &Cow{
 		Sex:         calf.Sex,
 		EarNumber:   calf.EarNumber,
@@ -87,7 +87,7 @@ func NewCalfCow(motherId, fatherId int64, calf *EventCalvingCalf) *Cow {
 		CowType:     pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
 		BreedStatus: pasturePb.BreedStatus_UnBreed,    // 未配
 		CowKind:     calf.CowKind,                     // 牛只品种
-		BirthWeight: calf.Weight,
+		BirthWeight: calf.BrithWeight,
 		SourceId:    pasturePb.CowSource_Calving, // 产犊方式
 		FatherId:    fatherId,
 		MotherId:    motherId,

+ 2 - 2
model/event_calving.go

@@ -51,7 +51,7 @@ type EventCalvingList struct {
 
 type EventCalvingListSlice []*EventCalvingList
 
-func (e EventCalvingListSlice) ToPB(req []*EventCalvingCalf) []*pasturePb.SearchLavingList {
+func (e EventCalvingListSlice) ToPB(req []*CalvingCalf) []*pasturePb.SearchLavingList {
 	var list []*pasturePb.SearchLavingList
 	for _, item := range e {
 		CalfItemList := make([]*pasturePb.CalfItem, 0)
@@ -62,7 +62,7 @@ func (e EventCalvingListSlice) ToPB(req []*EventCalvingCalf) []*pasturePb.Search
 			CalfItemList = append(CalfItemList, &pasturePb.CalfItem{
 				EarNumber:  v.EarNumber,
 				Sex:        v.Sex,
-				Weight:     float32(v.Weight) / 100,
+				Weight:     float32(v.BrithWeight) / 1000,
 				IsAdoption: v.IsAdoption,
 				IsLive:     v.IsLive,
 				CreatedAt:  int32(v.CreatedAt),

+ 15 - 3
model/same_time.go

@@ -3,6 +3,9 @@ package model
 import (
 	"encoding/json"
 
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"go.uber.org/zap"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
@@ -15,7 +18,7 @@ type SameTime struct {
 	IsDelete            pasturePb.IsShow_Kind  `json:"isDelete"`
 	PostpartumDaysStart int32                  `json:"postpartumDaysStart"`
 	PostpartumDaysEnd   int32                  `json:"postpartumDaysEnd"`
-	SameTimeDetails     string                 `json:"sameTimeDetails"`
+	CollateNodes        string                 `json:"collateNodes"`
 	Remarks             string                 `json:"remarks"`
 	OperationId         int64                  `json:"operationId"`
 	CreatedAt           int64                  `json:"createdAt"`
@@ -27,7 +30,10 @@ func (e *SameTime) TableName() string {
 }
 
 func NewSameTime(currentUser *SystemUser, req *pasturePb.SearchSameTimeList) *SameTime {
-	sameTimeDetails, _ := json.Marshal(req.CollateNodes)
+	var collateNodes []byte
+	if len(req.CollateNodes) > 0 {
+		collateNodes, _ = json.Marshal(req.CollateNodes)
+	}
 	return &SameTime{
 		Name:                req.Name,
 		WeekType:            req.WeekType,
@@ -36,7 +42,7 @@ func NewSameTime(currentUser *SystemUser, req *pasturePb.SearchSameTimeList) *Sa
 		IsDelete:            pasturePb.IsShow_Ok,
 		PostpartumDaysStart: req.PostpartumDaysStart,
 		PostpartumDaysEnd:   req.PostpartumDaysEnd,
-		SameTimeDetails:     string(sameTimeDetails),
+		CollateNodes:        string(collateNodes),
 		Remarks:             req.Remarks,
 		OperationId:         currentUser.Id,
 	}
@@ -58,6 +64,11 @@ func (e SameTimeSlice) ToPB(
 			}
 			operationName = u.Name
 		}
+
+		collectionNodes := make([]*pasturePb.CollateNode, 0)
+		if err := json.Unmarshal([]byte(v.CollateNodes), &collectionNodes); err != nil {
+			zaplog.Error("json.Unmarshal SameTimeSlice.ToPB error", zap.Any("err", err))
+		}
 		res[i] = &pasturePb.SearchSameTimeList{
 			Id:                  int32(v.Id),
 			Name:                v.Name,
@@ -68,6 +79,7 @@ func (e SameTimeSlice) ToPB(
 			IsShow:              v.IsShow,
 			PostpartumDaysStart: v.PostpartumDaysStart,
 			PostpartumDaysEnd:   v.PostpartumDaysEnd,
+			CollateNodes:        collectionNodes,
 			Remarks:             v.Remarks,
 			OperationId:         int32(v.OperationId),
 			OperationName:       operationName,

+ 14 - 0
model/same_time_cow.go

@@ -0,0 +1,14 @@
+package model
+
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
+type SameTimeCow struct {
+	Id         int64                 `json:"id"`
+	CowId      int64                 `json:"cowId"`
+	SameTimeId int64                 `json:"sameTimeId"`
+	Status     pasturePb.IsShow_Kind `json:"status"`
+	StartAt    int64                 `json:"startAt"`
+	EndAt      int64                 `json:"endAt"`
+	CreatedAt  int64                 `json:"createdAt"`
+	UpdatedAt  int64                 `json:"updatedAt"`
+}

+ 5 - 2
model/work_order_master.go

@@ -3,6 +3,8 @@ package model
 import (
 	"encoding/json"
 	"fmt"
+
+	"kpt-pasture/config"
 	"kpt-pasture/http/util"
 	"strconv"
 	"strings"
@@ -106,12 +108,13 @@ func NewTaskWorkOrderOption(processAt int64) []asynq.Option {
 	}
 }
 
-func NewTaskWorkOrderPayload(farmName string, id int64, execTime time.Duration) *asynq.Task {
+func NewTaskWorkOrderPayload(id int64, execTime time.Duration) *asynq.Task {
 	payload, _ := json.Marshal(TaskWorkOrderPayload{
 		WorkOrderId: id,
 	})
 	processAt := time.Now().Add(execTime).Unix()
-	return asynq.NewTask(fmt.Sprintf("%s:%s", farmName, TaskWorkOrder), payload, NewTaskWorkOrderOption(processAt)...)
+
+	return asynq.NewTask(fmt.Sprintf("%s:%s", config.Options().FarmName, TaskWorkOrder), payload, NewTaskWorkOrderOption(processAt)...)
 }
 
 type WorkOrderMasterSlice []*WorkOrderMaster

+ 7 - 7
module/backend/config_data.go

@@ -177,10 +177,6 @@ func (s *StoreEntry) SemeTimeCowTypeEnumList() []*pasturePb.ConfigOptionsList {
 		Value:    int32(pasturePb.CowType_Breeding_Calf),
 		Label:    "种母牛",
 		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_Empty),
-		Label:    "空怀",
-		Disabled: true,
 	})
 	return cowTypeList
 }
@@ -188,12 +184,16 @@ func (s *StoreEntry) SemeTimeCowTypeEnumList() []*pasturePb.ConfigOptionsList {
 func (s *StoreEntry) SameTimeTypeEnumList() []*pasturePb.ConfigOptionsList {
 	cowTypeList := make([]*pasturePb.ConfigOptionsList, 0)
 	cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeType_PG),
-		Label:    "PG",
+		Value:    int32(pasturePb.SameTimeType_PGBJ),
+		Label:    "PG保健",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.SameTimeType_PGTQ),
+		Label:    "PG同期",
 		Disabled: true,
 	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.SameTimeType_RnGH),
-		Label:    "RnGH",
+		Label:    "RnGh",
 		Disabled: true,
 	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.SameTimeType_TAI),

+ 3 - 2
module/backend/interface.go

@@ -111,8 +111,9 @@ type PastureManageService interface {
 	SearchCowSourceList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error)
 	CreateOrUpdateCowSource(ctx context.Context, req *pasturePb.SearchBaseConfigList) error
 
-	CreateOrUpdateSemeTime(ctx context.Context, req *pasturePb.SearchSameTimeList) error
-	SearchSemeTimeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SameTimeResponse, error)
+	CreateOrUpdateSameTime(ctx context.Context, req *pasturePb.SearchSameTimeList) error
+	SearchSameTimeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SameTimeResponse, error)
+	SameTimeIsShow(ctx context.Context, id int64) error
 
 	SearchDiseaseTypeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error)
 	CreateOrUpdateDiseaseType(ctx context.Context, req *pasturePb.SearchBaseConfigList) error

+ 24 - 5
module/backend/prescription.go

@@ -14,7 +14,7 @@ import (
 	"gorm.io/gorm"
 )
 
-func (s *StoreEntry) CreateOrUpdateSemeTime(ctx context.Context, req *pasturePb.SearchSameTimeList) error {
+func (s *StoreEntry) CreateOrUpdateSameTime(ctx context.Context, req *pasturePb.SearchSameTimeList) error {
 	currentUser, _ := s.GetCurrentSystemUser(ctx)
 	semeTime := model.NewSameTime(currentUser, req)
 	if req.Id > 0 {
@@ -24,7 +24,7 @@ func (s *StoreEntry) CreateOrUpdateSemeTime(ctx context.Context, req *pasturePb.
 			"cow_type":              semeTime.CowType,
 			"postpartum_days_start": semeTime.PostpartumDaysStart,
 			"postpartum_days_end":   semeTime.PostpartumDaysEnd,
-			"same_time_details":     semeTime.SameTimeDetails,
+			"collate_nodes":         semeTime.CollateNodes,
 			"is_show":               semeTime.IsShow,
 			"remarks":               semeTime.Remarks,
 		}).Error; err != nil {
@@ -38,11 +38,10 @@ func (s *StoreEntry) CreateOrUpdateSemeTime(ctx context.Context, req *pasturePb.
 	return nil
 }
 
-func (s *StoreEntry) SearchSemeTimeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SameTimeResponse, error) {
+func (s *StoreEntry) SearchSameTimeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SameTimeResponse, error) {
 	semeTimeList := make([]*model.SameTime, 0)
 	var count int64 = 0
-	pref := s.DB.Model(new(model.SameTime)).
-		Where("is_delete = ?", pasturePb.IsShow_Ok)
+	pref := s.DB.Model(new(model.SameTime))
 	if req.Name != "" {
 		pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))
 	}
@@ -67,6 +66,26 @@ func (s *StoreEntry) SearchSemeTimeList(ctx context.Context, req *pasturePb.Sear
 	}, nil
 }
 
+func (s *StoreEntry) SameTimeIsShow(ctx context.Context, id int64) error {
+	sameTime := &model.SameTime{
+		Id: id,
+	}
+	if err := s.DB.First(sameTime).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return xerr.Custom("该同期数据不存在")
+		}
+		return xerr.WithStack(err)
+	}
+	isShow := pasturePb.IsShow_No
+	if sameTime.IsShow == pasturePb.IsShow_No {
+		isShow = pasturePb.IsShow_Ok
+	}
+
+	if err := s.DB.Model(sameTime).Update("is_show", isShow).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
 func (s *StoreEntry) SearchDiseaseList(ctx context.Context, req *pasturePb.SearchDiseaseRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchDiseaseResponse, error) {
 	diseaseList := make([]*model.Disease, 0)
 	var count int64 = 0

+ 1 - 1
module/backend/work.go

@@ -229,7 +229,7 @@ func (s *StoreEntry) SendAsynqWorkOrder(ctx context.Context, workOrder *model.Wo
 	}
 
 	execTime := time.Now().Unix() - timeUnix
-	if _, err := s.AsynqClient.CtxEnqueue(ctx, model.NewTaskWorkOrderPayload(s.Cfg.FarmName, workOrder.Id, time.Duration(execTime)*time.Second)); err != nil {
+	if _, err := s.AsynqClient.CtxEnqueue(ctx, model.NewTaskWorkOrderPayload(workOrder.Id, time.Duration(execTime)*time.Second)); err != nil {
 		zaplog.Error("PushMessage CtxEnqueue", zap.Any("Err", err))
 	}
 }

+ 68 - 2
module/crontab/crontab.go

@@ -2,6 +2,7 @@ package crontab
 
 import (
 	"context"
+	"errors"
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"time"
@@ -52,9 +53,10 @@ func (e *Entry) GenerateAsynqWorkOrder() error {
 			continue
 		}
 		execTime := time.Now().Unix() - timeUnix
-		if _, err := e.AsynqClient.CtxEnqueue(
+
+		if _, err = e.AsynqClient.CtxEnqueue(
 			context.Background(),
-			model.NewTaskWorkOrderPayload(e.Cfg.FarmName, workOrder.Id, time.Duration(execTime)*time.Second),
+			model.NewTaskWorkOrderPayload(workOrder.Id, time.Duration(execTime)*time.Second),
 		); err != nil {
 			zaplog.Error("PushMessage CtxEnqueue", zap.Any("Err", err))
 		}
@@ -108,6 +110,47 @@ func (e *Entry) ImmunizationPlan() error {
 
 // SameTimePlan 同期计划,生成工作单
 func (e *Entry) SameTimePlan() error {
+	sameTimeList := make([]*model.SameTime, 0)
+	if err := e.DB.Where("is_show = ?", pasturePb.IsShow_Ok).Find(&sameTimeList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	cowSameTimeList := make([]*model.SameTimeCow, 0)
+	if err := e.DB.Select("cow_id").Where("status = ?", pasturePb.IsShow_Ok).Find(&cowSameTimeList).Error; err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			return xerr.WithStack(err)
+		}
+	}
+	cowIds := make([]int64, 0)
+	if len(cowSameTimeList) > 0 {
+		for _, cowSameTime := range cowSameTimeList {
+			cowIds = append(cowIds, cowSameTime.CowId)
+		}
+	}
+
+	for _, plan := range sameTimeList {
+		cowList := make([]*model.Cow, 0)
+		pref := e.DB.Select("id").
+			Where("is_remove = ?", pasturePb.IsShow_Ok).
+			Where("is_pregnant = ?", pasturePb.IsShow_No).
+			Where("calving_age >= ?", plan.PostpartumDaysStart).
+			Where("calving_age <= ?", plan.PostpartumDaysEnd)
+		if len(cowIds) > 0 {
+			pref.Where("id NOT IN ?", cowIds)
+		}
+
+		if err := pref.Find(&cowList); err != nil {
+			zaplog.Error("crontab", zap.Any("SameTimePlan", err), zap.Any("plan", plan))
+			continue
+		}
+		if len(cowList) <= 0 {
+			continue
+		}
+		if err := e.GenerateCalendarBySameTimePlan(cowList, plan); err != nil {
+			zaplog.Error("crontab", zap.Any("GenerateCalendarBySameTimePlan", err), zap.Any("cowList", cowList), zap.Any("plan", plan))
+			continue
+		}
+	}
 	return nil
 }
 
@@ -165,6 +208,29 @@ func (e *Entry) GenerateCalendarByImmunization(cowList []*model.Cow, name string
 	return nil
 }
 
+func (e *Entry) GenerateCalendarBySameTimePlan(cowList []*model.Cow, sameTime *model.SameTime) error {
+	if len(cowList) <= 0 {
+		return nil
+	}
+
+	cowSameTimeList := make([]*model.SameTimeCow, 0)
+	for _, cow := range cowList {
+		cowSameTimeList = append(cowSameTimeList, &model.SameTimeCow{
+			CowId:      cow.Id,
+			SameTimeId: sameTime.Id,
+			Status:     pasturePb.IsShow_Ok,
+			StartAt:    time.Now().Unix(),
+			EndAt:      0,
+		})
+	}
+
+	if err := e.DB.Create(cowSameTimeList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	return nil
+}
+
 func (e *Entry) getWorkOrderCalendar(name string) []*model.WorkOrderCalendar {
 	res := make([]*model.WorkOrderCalendar, 0)
 	if err := e.DB.Where("name = ?", name).