refactor: expiry 模块按 handler/model/service 分层
This commit is contained in:
@@ -0,0 +1,133 @@
|
|||||||
|
package expiry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
expiryhandler "wx_service/internal/expiry/handler"
|
||||||
|
expirymodel "wx_service/internal/expiry/model"
|
||||||
|
expiryrepo "wx_service/internal/expiry/repository"
|
||||||
|
expiryservice "wx_service/internal/expiry/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CategoryFood = expirymodel.CategoryFood
|
||||||
|
CategoryMedicine = expirymodel.CategoryMedicine
|
||||||
|
CategoryCosmetic = expirymodel.CategoryCosmetic
|
||||||
|
CategoryOther = expirymodel.CategoryOther
|
||||||
|
|
||||||
|
StatusNormal = expirymodel.StatusNormal
|
||||||
|
StatusExpiring = expirymodel.StatusExpiring
|
||||||
|
StatusExpired = expirymodel.StatusExpired
|
||||||
|
StatusUsed = expirymodel.StatusUsed
|
||||||
|
StatusDiscarded = expirymodel.StatusDiscarded
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultRemindDays = expirymodel.DefaultRemindDays
|
||||||
|
|
||||||
|
type ExpiryItem = expirymodel.ExpiryItem
|
||||||
|
type ExpiryUserSettings = expirymodel.ExpiryUserSettings
|
||||||
|
|
||||||
|
type Repository = expiryrepo.Repository
|
||||||
|
type Service = expiryservice.Service
|
||||||
|
type Handler = expiryhandler.Handler
|
||||||
|
type SummaryCache = expiryservice.SummaryCache
|
||||||
|
|
||||||
|
type CreateItemRequest = expiryservice.CreateItemRequest
|
||||||
|
type UpdateItemRequest = expiryservice.UpdateItemRequest
|
||||||
|
type ItemFilters = expiryservice.ItemFilters
|
||||||
|
type ItemView = expiryservice.ItemView
|
||||||
|
type ItemListResponse = expiryservice.ItemListResponse
|
||||||
|
type SummaryResponse = expiryservice.SummaryResponse
|
||||||
|
type SettingsResponse = expiryservice.SettingsResponse
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrExpiryItemNotFound = expiryrepo.ErrExpiryItemNotFound
|
||||||
|
|
||||||
|
ErrExpiryNameInvalid = expiryservice.ErrExpiryNameInvalid
|
||||||
|
ErrExpiryCategoryInvalid = expiryservice.ErrExpiryCategoryInvalid
|
||||||
|
ErrExpiryMiniProgramRequired = expiryservice.ErrExpiryMiniProgramRequired
|
||||||
|
ErrExpiryQuantityInvalid = expiryservice.ErrExpiryQuantityInvalid
|
||||||
|
ErrExpiryLocationTooLong = expiryservice.ErrExpiryLocationTooLong
|
||||||
|
ErrExpiryRemarkTooLong = expiryservice.ErrExpiryRemarkTooLong
|
||||||
|
ErrExpiryDateRequired = expiryservice.ErrExpiryDateRequired
|
||||||
|
ErrExpiryShelfLifeDaysInvalid = expiryservice.ErrExpiryShelfLifeDaysInvalid
|
||||||
|
ErrExpiryFilterStatusInvalid = expiryservice.ErrExpiryFilterStatusInvalid
|
||||||
|
ErrExpiryFilterCategoryInvalid = expiryservice.ErrExpiryFilterCategoryInvalid
|
||||||
|
ErrExpiryFilterSortInvalid = expiryservice.ErrExpiryFilterSortInvalid
|
||||||
|
ErrExpiryStatusInvalid = expiryservice.ErrExpiryStatusInvalid
|
||||||
|
ErrExpiryRemindDaysInvalid = expiryservice.ErrExpiryRemindDaysInvalid
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRepository(db *gorm.DB) *Repository {
|
||||||
|
return expiryrepo.NewRepository(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewService(repo *Repository) *Service {
|
||||||
|
return expiryservice.NewService(repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(service *Service) *Handler {
|
||||||
|
return expiryhandler.NewHandler(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSummaryCache(rc *redis.Client, keyPrefix string, ttl time.Duration) *SummaryCache {
|
||||||
|
return expiryservice.NewSummaryCache(rc, keyPrefix, ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dateOnly(t time.Time) time.Time {
|
||||||
|
return expirymodel.DateOnly(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeFilters(filters ItemFilters) ItemFilters {
|
||||||
|
return expiryservice.NormalizeFilters(filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateFilters(filters ItemFilters) error {
|
||||||
|
return expiryservice.ValidateFilters(filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateBaseFields(name, category string, quantity int, location, remark string) error {
|
||||||
|
return expiryservice.ValidateBaseFields(name, category, quantity, location, remark)
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyExpiryDate(item *ExpiryItem, expiryDate *time.Time, shelfLifeDays *int) error {
|
||||||
|
return expiryservice.ApplyExpiryDate(item, expiryDate, shelfLifeDays)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidCategory(category string) bool {
|
||||||
|
return expiryservice.IsValidCategory(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRemindDays(days []int) ([]int, error) {
|
||||||
|
return expiryservice.ValidateRemindDays(days)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toItemView(item ExpiryItem) ItemView {
|
||||||
|
return expiryservice.ToItemView(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeExpirySuccess(c *gin.Context, message string, data interface{}) {
|
||||||
|
resp := gin.H{
|
||||||
|
"code": 0,
|
||||||
|
"message": message,
|
||||||
|
}
|
||||||
|
if data != nil {
|
||||||
|
resp["data"] = data
|
||||||
|
}
|
||||||
|
c.JSON(200, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeExpiryError(c *gin.Context, code int, message string) {
|
||||||
|
c.JSON(code, gin.H{
|
||||||
|
"code": code,
|
||||||
|
"message": message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeExpiryServerError(c *gin.Context) {
|
||||||
|
writeExpiryError(c, 500, "服务器错误")
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package expiry
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -10,15 +10,17 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
expiryrepo "wx_service/internal/expiry/repository"
|
||||||
|
expiryservice "wx_service/internal/expiry/service"
|
||||||
"wx_service/internal/middleware"
|
"wx_service/internal/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler 负责 HTTP 层处理。
|
// Handler 负责 HTTP 层处理。
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
service *Service
|
service *expiryservice.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(service *Service) *Handler {
|
func NewHandler(service *expiryservice.Service) *Handler {
|
||||||
return &Handler{service: service}
|
return &Handler{service: service}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +74,7 @@ func (h *Handler) GetItems(c *gin.Context) {
|
|||||||
|
|
||||||
page := parseIntWithDefault(c.Query("page"), 1)
|
page := parseIntWithDefault(c.Query("page"), 1)
|
||||||
pageSize := parseIntWithDefault(c.Query("page_size"), 20)
|
pageSize := parseIntWithDefault(c.Query("page_size"), 20)
|
||||||
filters := ItemFilters{
|
filters := expiryservice.ItemFilters{
|
||||||
Status: strings.TrimSpace(c.DefaultQuery("status", "all")),
|
Status: strings.TrimSpace(c.DefaultQuery("status", "all")),
|
||||||
Category: strings.TrimSpace(c.DefaultQuery("category", "all")),
|
Category: strings.TrimSpace(c.DefaultQuery("category", "all")),
|
||||||
Sort: strings.TrimSpace(c.DefaultQuery("sort", "expiry_date")),
|
Sort: strings.TrimSpace(c.DefaultQuery("sort", "expiry_date")),
|
||||||
@@ -119,7 +121,7 @@ func (h *Handler) CreateItem(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
writeExpirySuccess(c, "添加成功", toItemView(*item))
|
writeExpirySuccess(c, "添加成功", expiryservice.ToItemView(*item))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateItem 更新物品。
|
// UpdateItem 更新物品。
|
||||||
@@ -144,7 +146,7 @@ func (h *Handler) UpdateItem(c *gin.Context) {
|
|||||||
|
|
||||||
item, err := h.service.UpdateItem(id, user.ID, serviceReq)
|
item, err := h.service.UpdateItem(id, user.ID, serviceReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrExpiryItemNotFound) {
|
if errors.Is(err, expiryrepo.ErrExpiryItemNotFound) {
|
||||||
writeExpiryError(c, http.StatusNotFound, "物品不存在")
|
writeExpiryError(c, http.StatusNotFound, "物品不存在")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -156,7 +158,7 @@ func (h *Handler) UpdateItem(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
writeExpirySuccess(c, "更新成功", toItemView(*item))
|
writeExpirySuccess(c, "更新成功", expiryservice.ToItemView(*item))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteItem 删除物品。
|
// DeleteItem 删除物品。
|
||||||
@@ -169,7 +171,7 @@ func (h *Handler) DeleteItem(c *gin.Context) {
|
|||||||
|
|
||||||
err := h.service.DeleteItem(id, user.ID)
|
err := h.service.DeleteItem(id, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrExpiryItemNotFound) {
|
if errors.Is(err, expiryrepo.ErrExpiryItemNotFound) {
|
||||||
writeExpiryError(c, http.StatusNotFound, "物品不存在")
|
writeExpiryError(c, http.StatusNotFound, "物品不存在")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -195,7 +197,7 @@ func (h *Handler) UpdateStatus(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := h.service.UpdateItemStatus(id, user.ID, strings.TrimSpace(req.Status)); err != nil {
|
if err := h.service.UpdateItemStatus(id, user.ID, strings.TrimSpace(req.Status)); err != nil {
|
||||||
if errors.Is(err, ErrExpiryItemNotFound) {
|
if errors.Is(err, expiryrepo.ErrExpiryItemNotFound) {
|
||||||
writeExpiryError(c, http.StatusNotFound, "物品不存在")
|
writeExpiryError(c, http.StatusNotFound, "物品不存在")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -256,15 +258,15 @@ func (h *Handler) UpdateSettings(c *gin.Context) {
|
|||||||
writeExpirySuccess(c, "更新成功", resp)
|
writeExpirySuccess(c, "更新成功", resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) toCreateItemRequest(miniProgramID uint, req createOrUpdateItemRequest) (CreateItemRequest, error) {
|
func (h *Handler) toCreateItemRequest(miniProgramID uint, req createOrUpdateItemRequest) (expiryservice.CreateItemRequest, error) {
|
||||||
productionDate, err := parseDateString(req.ProductionDate)
|
productionDate, err := parseDateString(req.ProductionDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CreateItemRequest{}, errors.New("production_date 格式错误,应为 YYYY-MM-DD")
|
return expiryservice.CreateItemRequest{}, errors.New("production_date 格式错误,应为 YYYY-MM-DD")
|
||||||
}
|
}
|
||||||
|
|
||||||
expiryDate, err := parseDateString(req.ExpiryDate)
|
expiryDate, err := parseDateString(req.ExpiryDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CreateItemRequest{}, errors.New("expiry_date 格式错误,应为 YYYY-MM-DD")
|
return expiryservice.CreateItemRequest{}, errors.New("expiry_date 格式错误,应为 YYYY-MM-DD")
|
||||||
}
|
}
|
||||||
|
|
||||||
quantity := 1
|
quantity := 1
|
||||||
@@ -272,7 +274,7 @@ func (h *Handler) toCreateItemRequest(miniProgramID uint, req createOrUpdateItem
|
|||||||
quantity = *req.Quantity
|
quantity = *req.Quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateItemRequest{
|
return expiryservice.CreateItemRequest{
|
||||||
MiniProgramID: miniProgramID,
|
MiniProgramID: miniProgramID,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Category: req.Category,
|
Category: req.Category,
|
||||||
@@ -318,19 +320,19 @@ func parseItemID(c *gin.Context) (uint, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isExpiryBadRequestError(err error) bool {
|
func isExpiryBadRequestError(err error) bool {
|
||||||
return errors.Is(err, ErrExpiryNameInvalid) ||
|
return errors.Is(err, expiryservice.ErrExpiryNameInvalid) ||
|
||||||
errors.Is(err, ErrExpiryCategoryInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryCategoryInvalid) ||
|
||||||
errors.Is(err, ErrExpiryMiniProgramRequired) ||
|
errors.Is(err, expiryservice.ErrExpiryMiniProgramRequired) ||
|
||||||
errors.Is(err, ErrExpiryQuantityInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryQuantityInvalid) ||
|
||||||
errors.Is(err, ErrExpiryLocationTooLong) ||
|
errors.Is(err, expiryservice.ErrExpiryLocationTooLong) ||
|
||||||
errors.Is(err, ErrExpiryRemarkTooLong) ||
|
errors.Is(err, expiryservice.ErrExpiryRemarkTooLong) ||
|
||||||
errors.Is(err, ErrExpiryDateRequired) ||
|
errors.Is(err, expiryservice.ErrExpiryDateRequired) ||
|
||||||
errors.Is(err, ErrExpiryShelfLifeDaysInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryShelfLifeDaysInvalid) ||
|
||||||
errors.Is(err, ErrExpiryFilterStatusInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryFilterStatusInvalid) ||
|
||||||
errors.Is(err, ErrExpiryFilterCategoryInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryFilterCategoryInvalid) ||
|
||||||
errors.Is(err, ErrExpiryFilterSortInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryFilterSortInvalid) ||
|
||||||
errors.Is(err, ErrExpiryStatusInvalid) ||
|
errors.Is(err, expiryservice.ErrExpiryStatusInvalid) ||
|
||||||
errors.Is(err, ErrExpiryRemindDaysInvalid)
|
errors.Is(err, expiryservice.ErrExpiryRemindDaysInvalid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeExpirySuccess(c *gin.Context, message string, data interface{}) {
|
func writeExpirySuccess(c *gin.Context, message string, data interface{}) {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package expiry
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
@@ -23,7 +23,7 @@ const (
|
|||||||
StatusDiscarded = "discarded"
|
StatusDiscarded = "discarded"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultRemindDays = []int{7, 3, 1}
|
var DefaultRemindDays = []int{7, 3, 1}
|
||||||
|
|
||||||
// ExpiryItem 表示保质期物品数据模型。
|
// ExpiryItem 表示保质期物品数据模型。
|
||||||
type ExpiryItem struct {
|
type ExpiryItem struct {
|
||||||
@@ -50,8 +50,8 @@ func (ExpiryItem) TableName() string {
|
|||||||
|
|
||||||
// CalculateDaysLeft 计算当前日期与过期日期之间的天数差。
|
// CalculateDaysLeft 计算当前日期与过期日期之间的天数差。
|
||||||
func (item *ExpiryItem) CalculateDaysLeft() int {
|
func (item *ExpiryItem) CalculateDaysLeft() int {
|
||||||
now := dateOnly(time.Now())
|
now := DateOnly(time.Now())
|
||||||
expiry := dateOnly(item.ExpiryDate)
|
expiry := DateOnly(item.ExpiryDate)
|
||||||
return int(expiry.Sub(now).Hours() / 24)
|
return int(expiry.Sub(now).Hours() / 24)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ func (ExpiryUserSettings) TableName() string {
|
|||||||
return "expiry_user_settings"
|
return "expiry_user_settings"
|
||||||
}
|
}
|
||||||
|
|
||||||
func dateOnly(t time.Time) time.Time {
|
func DateOnly(t time.Time) time.Time {
|
||||||
year, month, day := t.In(time.Local).Date()
|
year, month, day := t.In(time.Local).Date()
|
||||||
return time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
return time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package expiry
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
expirymodel "wx_service/internal/expiry/model"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ func NewRepository(db *gorm.DB) *Repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create 创建物品。
|
// Create 创建物品。
|
||||||
func (r *Repository) Create(item *ExpiryItem) error {
|
func (r *Repository) Create(item *expirymodel.ExpiryItem) error {
|
||||||
if err := r.db.Create(item).Error; err != nil {
|
if err := r.db.Create(item).Error; err != nil {
|
||||||
return fmt.Errorf("create expiry item: %w", err)
|
return fmt.Errorf("create expiry item: %w", err)
|
||||||
}
|
}
|
||||||
@@ -30,7 +32,7 @@ func (r *Repository) Create(item *ExpiryItem) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update 更新物品。
|
// Update 更新物品。
|
||||||
func (r *Repository) Update(item *ExpiryItem) error {
|
func (r *Repository) Update(item *expirymodel.ExpiryItem) error {
|
||||||
updates := map[string]interface{}{
|
updates := map[string]interface{}{
|
||||||
"mini_program_id": item.MiniProgramID,
|
"mini_program_id": item.MiniProgramID,
|
||||||
"name": item.Name,
|
"name": item.Name,
|
||||||
@@ -44,7 +46,7 @@ func (r *Repository) Update(item *ExpiryItem) error {
|
|||||||
"status": item.Status,
|
"status": item.Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := r.db.Model(&ExpiryItem{}).
|
tx := r.db.Model(&expirymodel.ExpiryItem{}).
|
||||||
Where("id = ? AND user_id = ?", item.ID, item.UserID).
|
Where("id = ? AND user_id = ?", item.ID, item.UserID).
|
||||||
Updates(updates)
|
Updates(updates)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
@@ -58,7 +60,7 @@ func (r *Repository) Update(item *ExpiryItem) error {
|
|||||||
|
|
||||||
// Delete 软删除物品。
|
// Delete 软删除物品。
|
||||||
func (r *Repository) Delete(id, userID uint) error {
|
func (r *Repository) Delete(id, userID uint) error {
|
||||||
tx := r.db.Where("id = ? AND user_id = ?", id, userID).Delete(&ExpiryItem{})
|
tx := r.db.Where("id = ? AND user_id = ?", id, userID).Delete(&expirymodel.ExpiryItem{})
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return fmt.Errorf("delete expiry item: %w", tx.Error)
|
return fmt.Errorf("delete expiry item: %w", tx.Error)
|
||||||
}
|
}
|
||||||
@@ -69,8 +71,8 @@ func (r *Repository) Delete(id, userID uint) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindByID 根据 ID 查询单个物品。
|
// FindByID 根据 ID 查询单个物品。
|
||||||
func (r *Repository) FindByID(id, userID uint) (*ExpiryItem, error) {
|
func (r *Repository) FindByID(id, userID uint) (*expirymodel.ExpiryItem, error) {
|
||||||
var item ExpiryItem
|
var item expirymodel.ExpiryItem
|
||||||
err := r.db.Where("id = ? AND user_id = ?", id, userID).First(&item).Error
|
err := r.db.Where("id = ? AND user_id = ?", id, userID).First(&item).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -86,7 +88,7 @@ func (r *Repository) FindByUser(
|
|||||||
userID uint,
|
userID uint,
|
||||||
filters map[string]interface{},
|
filters map[string]interface{},
|
||||||
page, pageSize int,
|
page, pageSize int,
|
||||||
) ([]ExpiryItem, int64, error) {
|
) ([]expirymodel.ExpiryItem, int64, error) {
|
||||||
if page <= 0 {
|
if page <= 0 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
@@ -97,22 +99,22 @@ func (r *Repository) FindByUser(
|
|||||||
pageSize = 100
|
pageSize = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
query := r.db.Model(&ExpiryItem{}).Where("user_id = ?", userID)
|
query := r.db.Model(&expirymodel.ExpiryItem{}).Where("user_id = ?", userID)
|
||||||
now := dateOnly(time.Now())
|
now := expirymodel.DateOnly(time.Now())
|
||||||
sevenDaysLater := now.AddDate(0, 0, 7)
|
sevenDaysLater := now.AddDate(0, 0, 7)
|
||||||
|
|
||||||
if status, ok := filters["status"].(string); ok && status != "" && status != "all" {
|
if status, ok := filters["status"].(string); ok && status != "" && status != "all" {
|
||||||
switch status {
|
switch status {
|
||||||
case StatusExpiring:
|
case expirymodel.StatusExpiring:
|
||||||
query = query.Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}).
|
query = query.Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}).
|
||||||
Where("expiry_date BETWEEN ? AND ?", now, sevenDaysLater)
|
Where("expiry_date BETWEEN ? AND ?", now, sevenDaysLater)
|
||||||
case StatusExpired:
|
case expirymodel.StatusExpired:
|
||||||
query = query.Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}).
|
query = query.Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}).
|
||||||
Where("expiry_date < ?", now)
|
Where("expiry_date < ?", now)
|
||||||
case StatusNormal:
|
case expirymodel.StatusNormal:
|
||||||
query = query.Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}).
|
query = query.Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}).
|
||||||
Where("expiry_date > ?", sevenDaysLater)
|
Where("expiry_date > ?", sevenDaysLater)
|
||||||
case StatusUsed, StatusDiscarded:
|
case expirymodel.StatusUsed, expirymodel.StatusDiscarded:
|
||||||
query = query.Where("status = ?", status)
|
query = query.Where("status = ?", status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +139,7 @@ func (r *Repository) FindByUser(
|
|||||||
return nil, 0, fmt.Errorf("count expiry items: %w", err)
|
return nil, 0, fmt.Errorf("count expiry items: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var items []ExpiryItem
|
var items []expirymodel.ExpiryItem
|
||||||
offset := (page - 1) * pageSize
|
offset := (page - 1) * pageSize
|
||||||
if err := query.Offset(offset).Limit(pageSize).Find(&items).Error; err != nil {
|
if err := query.Offset(offset).Limit(pageSize).Find(&items).Error; err != nil {
|
||||||
return nil, 0, fmt.Errorf("list expiry items: %w", err)
|
return nil, 0, fmt.Errorf("list expiry items: %w", err)
|
||||||
@@ -148,11 +150,11 @@ func (r *Repository) FindByUser(
|
|||||||
|
|
||||||
// GetSummary 获取首页汇总统计数据。
|
// GetSummary 获取首页汇总统计数据。
|
||||||
func (r *Repository) GetSummary(userID uint) (map[string]int, error) {
|
func (r *Repository) GetSummary(userID uint) (map[string]int, error) {
|
||||||
now := dateOnly(time.Now())
|
now := expirymodel.DateOnly(time.Now())
|
||||||
sevenDaysLater := now.AddDate(0, 0, 7)
|
sevenDaysLater := now.AddDate(0, 0, 7)
|
||||||
|
|
||||||
base := func() *gorm.DB {
|
base := func() *gorm.DB {
|
||||||
return r.db.Model(&ExpiryItem{}).Where("user_id = ?", userID)
|
return r.db.Model(&expirymodel.ExpiryItem{}).Where("user_id = ?", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
count := func(tx *gorm.DB) (int64, error) {
|
count := func(tx *gorm.DB) (int64, error) {
|
||||||
@@ -163,35 +165,35 @@ func (r *Repository) GetSummary(userID uint) (map[string]int, error) {
|
|||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
totalItems, err := count(base().Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}))
|
totalItems, err := count(base().Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("count total items: %w", err)
|
return nil, fmt.Errorf("count total items: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expiringSoon, err := count(base().Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}).
|
expiringSoon, err := count(base().Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}).
|
||||||
Where("expiry_date BETWEEN ? AND ?", now, sevenDaysLater))
|
Where("expiry_date BETWEEN ? AND ?", now, sevenDaysLater))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("count expiring items: %w", err)
|
return nil, fmt.Errorf("count expiring items: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expired, err := count(base().Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}).
|
expired, err := count(base().Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}).
|
||||||
Where("expiry_date < ?", now))
|
Where("expiry_date < ?", now))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("count expired items: %w", err)
|
return nil, fmt.Errorf("count expired items: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
normal, err := count(base().Where("status NOT IN ?", []string{StatusUsed, StatusDiscarded}).
|
normal, err := count(base().Where("status NOT IN ?", []string{expirymodel.StatusUsed, expirymodel.StatusDiscarded}).
|
||||||
Where("expiry_date > ?", sevenDaysLater))
|
Where("expiry_date > ?", sevenDaysLater))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("count normal items: %w", err)
|
return nil, fmt.Errorf("count normal items: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
used, err := count(base().Where("status = ?", StatusUsed))
|
used, err := count(base().Where("status = ?", expirymodel.StatusUsed))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("count used items: %w", err)
|
return nil, fmt.Errorf("count used items: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
discarded, err := count(base().Where("status = ?", StatusDiscarded))
|
discarded, err := count(base().Where("status = ?", expirymodel.StatusDiscarded))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("count discarded items: %w", err)
|
return nil, fmt.Errorf("count discarded items: %w", err)
|
||||||
}
|
}
|
||||||
@@ -208,7 +210,7 @@ func (r *Repository) GetSummary(userID uint) (map[string]int, error) {
|
|||||||
|
|
||||||
// UpdateStatus 更新物品状态(used/discarded)。
|
// UpdateStatus 更新物品状态(used/discarded)。
|
||||||
func (r *Repository) UpdateStatus(id, userID uint, status string) error {
|
func (r *Repository) UpdateStatus(id, userID uint, status string) error {
|
||||||
tx := r.db.Model(&ExpiryItem{}).
|
tx := r.db.Model(&expirymodel.ExpiryItem{}).
|
||||||
Where("id = ? AND user_id = ?", id, userID).
|
Where("id = ? AND user_id = ?", id, userID).
|
||||||
Update("status", status)
|
Update("status", status)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
@@ -221,8 +223,8 @@ func (r *Repository) UpdateStatus(id, userID uint, status string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetSettings 查询用户提醒设置。
|
// GetSettings 查询用户提醒设置。
|
||||||
func (r *Repository) GetSettings(userID uint) (*ExpiryUserSettings, error) {
|
func (r *Repository) GetSettings(userID uint) (*expirymodel.ExpiryUserSettings, error) {
|
||||||
var settings ExpiryUserSettings
|
var settings expirymodel.ExpiryUserSettings
|
||||||
err := r.db.Where("user_id = ?", userID).First(&settings).Error
|
err := r.db.Where("user_id = ?", userID).First(&settings).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -234,14 +236,14 @@ func (r *Repository) GetSettings(userID uint) (*ExpiryUserSettings, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSettings 更新用户提醒设置(不存在则创建)。
|
// UpdateSettings 更新用户提醒设置(不存在则创建)。
|
||||||
func (r *Repository) UpdateSettings(userID uint, remindDays []int) (*ExpiryUserSettings, error) {
|
func (r *Repository) UpdateSettings(userID uint, remindDays []int) (*expirymodel.ExpiryUserSettings, error) {
|
||||||
settings, err := r.GetSettings(userID)
|
settings, err := r.GetSettings(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if settings == nil {
|
if settings == nil {
|
||||||
settings = &ExpiryUserSettings{
|
settings = &expirymodel.ExpiryUserSettings{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
RemindDays: copyIntSlice(remindDays),
|
RemindDays: copyIntSlice(remindDays),
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package expiry
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package expiry
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
expirymodel "wx_service/internal/expiry/model"
|
||||||
|
expiryrepo "wx_service/internal/expiry/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -25,7 +28,7 @@ var (
|
|||||||
|
|
||||||
// Service 封装保质期模块业务逻辑。
|
// Service 封装保质期模块业务逻辑。
|
||||||
type Service struct {
|
type Service struct {
|
||||||
repo *Repository
|
repo *expiryrepo.Repository
|
||||||
summaryCache *SummaryCache
|
summaryCache *SummaryCache
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +97,7 @@ type SettingsResponse struct {
|
|||||||
RemindDays []int `json:"remind_days"`
|
RemindDays []int `json:"remind_days"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(repo *Repository) *Service {
|
func NewService(repo *expiryrepo.Repository) *Service {
|
||||||
return &Service{repo: repo}
|
return &Service{repo: repo}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +107,7 @@ func (s *Service) BindSummaryCache(cache *SummaryCache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateItem 创建物品,并处理过期日期自动计算。
|
// CreateItem 创建物品,并处理过期日期自动计算。
|
||||||
func (s *Service) CreateItem(userID uint, req CreateItemRequest) (*ExpiryItem, error) {
|
func (s *Service) CreateItem(userID uint, req CreateItemRequest) (*expirymodel.ExpiryItem, error) {
|
||||||
if req.MiniProgramID == 0 {
|
if req.MiniProgramID == 0 {
|
||||||
return nil, ErrExpiryMiniProgramRequired
|
return nil, ErrExpiryMiniProgramRequired
|
||||||
}
|
}
|
||||||
@@ -115,7 +118,7 @@ func (s *Service) CreateItem(userID uint, req CreateItemRequest) (*ExpiryItem, e
|
|||||||
return nil, ErrExpiryShelfLifeDaysInvalid
|
return nil, ErrExpiryShelfLifeDaysInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
item := &ExpiryItem{
|
item := &expirymodel.ExpiryItem{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
MiniProgramID: req.MiniProgramID,
|
MiniProgramID: req.MiniProgramID,
|
||||||
Name: strings.TrimSpace(req.Name),
|
Name: strings.TrimSpace(req.Name),
|
||||||
@@ -123,7 +126,7 @@ func (s *Service) CreateItem(userID uint, req CreateItemRequest) (*ExpiryItem, e
|
|||||||
Quantity: req.Quantity,
|
Quantity: req.Quantity,
|
||||||
Location: strings.TrimSpace(req.Location),
|
Location: strings.TrimSpace(req.Location),
|
||||||
Remark: strings.TrimSpace(req.Remark),
|
Remark: strings.TrimSpace(req.Remark),
|
||||||
Status: StatusNormal,
|
Status: expirymodel.StatusNormal,
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.Quantity == 0 {
|
if item.Quantity == 0 {
|
||||||
@@ -131,7 +134,7 @@ func (s *Service) CreateItem(userID uint, req CreateItemRequest) (*ExpiryItem, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.ProductionDate != nil {
|
if req.ProductionDate != nil {
|
||||||
pd := dateOnly(*req.ProductionDate)
|
pd := expirymodel.DateOnly(*req.ProductionDate)
|
||||||
item.ProductionDate = &pd
|
item.ProductionDate = &pd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +152,7 @@ func (s *Service) CreateItem(userID uint, req CreateItemRequest) (*ExpiryItem, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateItem 更新物品。
|
// UpdateItem 更新物品。
|
||||||
func (s *Service) UpdateItem(id, userID uint, req UpdateItemRequest) (*ExpiryItem, error) {
|
func (s *Service) UpdateItem(id, userID uint, req UpdateItemRequest) (*expirymodel.ExpiryItem, error) {
|
||||||
item, err := s.repo.FindByID(id, userID)
|
item, err := s.repo.FindByID(id, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -178,7 +181,7 @@ func (s *Service) UpdateItem(id, userID uint, req UpdateItemRequest) (*ExpiryIte
|
|||||||
item.Quantity = 1
|
item.Quantity = 1
|
||||||
}
|
}
|
||||||
if req.ProductionDate != nil {
|
if req.ProductionDate != nil {
|
||||||
pd := dateOnly(*req.ProductionDate)
|
pd := expirymodel.DateOnly(*req.ProductionDate)
|
||||||
item.ProductionDate = &pd
|
item.ProductionDate = &pd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,8 +190,8 @@ func (s *Service) UpdateItem(id, userID uint, req UpdateItemRequest) (*ExpiryIte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 已标记为 used/discarded 的物品保留状态,其余回归可计算状态。
|
// 已标记为 used/discarded 的物品保留状态,其余回归可计算状态。
|
||||||
if item.Status != StatusUsed && item.Status != StatusDiscarded {
|
if item.Status != expirymodel.StatusUsed && item.Status != expirymodel.StatusDiscarded {
|
||||||
item.Status = StatusNormal
|
item.Status = expirymodel.StatusNormal
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.repo.Update(item); err != nil {
|
if err := s.repo.Update(item); err != nil {
|
||||||
@@ -210,7 +213,7 @@ func (s *Service) DeleteItem(id, userID uint) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetItem 获取单个物品。
|
// GetItem 获取单个物品。
|
||||||
func (s *Service) GetItem(id, userID uint) (*ExpiryItem, error) {
|
func (s *Service) GetItem(id, userID uint) (*expirymodel.ExpiryItem, error) {
|
||||||
item, err := s.repo.FindByID(id, userID)
|
item, err := s.repo.FindByID(id, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -237,7 +240,7 @@ func (s *Service) GetItems(userID uint, filters ItemFilters) (*ItemListResponse,
|
|||||||
|
|
||||||
result := make([]ItemView, 0, len(items))
|
result := make([]ItemView, 0, len(items))
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
result = append(result, toItemView(item))
|
result = append(result, ToItemView(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ItemListResponse{
|
return &ItemListResponse{
|
||||||
@@ -275,7 +278,7 @@ func (s *Service) GetSummary(userID uint) (*SummaryResponse, error) {
|
|||||||
// UpdateItemStatus 标记物品状态。
|
// UpdateItemStatus 标记物品状态。
|
||||||
func (s *Service) UpdateItemStatus(id, userID uint, status string) error {
|
func (s *Service) UpdateItemStatus(id, userID uint, status string) error {
|
||||||
status = strings.TrimSpace(status)
|
status = strings.TrimSpace(status)
|
||||||
if status != StatusUsed && status != StatusDiscarded {
|
if status != expirymodel.StatusUsed && status != expirymodel.StatusDiscarded {
|
||||||
return ErrExpiryStatusInvalid
|
return ErrExpiryStatusInvalid
|
||||||
}
|
}
|
||||||
if err := s.repo.UpdateStatus(id, userID, status); err != nil {
|
if err := s.repo.UpdateStatus(id, userID, status); err != nil {
|
||||||
@@ -294,7 +297,7 @@ func (s *Service) GetSettings(userID uint) (*SettingsResponse, error) {
|
|||||||
|
|
||||||
if settings == nil || len(settings.RemindDays) == 0 {
|
if settings == nil || len(settings.RemindDays) == 0 {
|
||||||
return &SettingsResponse{
|
return &SettingsResponse{
|
||||||
RemindDays: copyIntSlice(defaultRemindDays),
|
RemindDays: copyIntSlice(expirymodel.DefaultRemindDays),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,16 +347,16 @@ func validateBaseFields(name, category string, quantity int, location, remark st
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyExpiryDate(item *ExpiryItem, expiryDate *time.Time, shelfLifeDays *int) error {
|
func applyExpiryDate(item *expirymodel.ExpiryItem, expiryDate *time.Time, shelfLifeDays *int) error {
|
||||||
// 若提供生产日期 + 保质期,优先自动计算过期日期。
|
// 若提供生产日期 + 保质期,优先自动计算过期日期。
|
||||||
if item.ProductionDate != nil && shelfLifeDays != nil {
|
if item.ProductionDate != nil && shelfLifeDays != nil {
|
||||||
item.ShelfLifeDays = shelfLifeDays
|
item.ShelfLifeDays = shelfLifeDays
|
||||||
item.ExpiryDate = dateOnly(item.ProductionDate.AddDate(0, 0, *shelfLifeDays))
|
item.ExpiryDate = expirymodel.DateOnly(item.ProductionDate.AddDate(0, 0, *shelfLifeDays))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if expiryDate != nil {
|
if expiryDate != nil {
|
||||||
item.ExpiryDate = dateOnly(*expiryDate)
|
item.ExpiryDate = expirymodel.DateOnly(*expiryDate)
|
||||||
item.ShelfLifeDays = shelfLifeDays
|
item.ShelfLifeDays = shelfLifeDays
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -385,13 +388,13 @@ func normalizeFilters(filters ItemFilters) ItemFilters {
|
|||||||
|
|
||||||
func validateFilters(filters ItemFilters) error {
|
func validateFilters(filters ItemFilters) error {
|
||||||
switch filters.Status {
|
switch filters.Status {
|
||||||
case "all", StatusExpiring, StatusExpired, StatusNormal, StatusUsed, StatusDiscarded:
|
case "all", expirymodel.StatusExpiring, expirymodel.StatusExpired, expirymodel.StatusNormal, expirymodel.StatusUsed, expirymodel.StatusDiscarded:
|
||||||
default:
|
default:
|
||||||
return ErrExpiryFilterStatusInvalid
|
return ErrExpiryFilterStatusInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
switch filters.Category {
|
switch filters.Category {
|
||||||
case "all", CategoryFood, CategoryMedicine, CategoryCosmetic, CategoryOther:
|
case "all", expirymodel.CategoryFood, expirymodel.CategoryMedicine, expirymodel.CategoryCosmetic, expirymodel.CategoryOther:
|
||||||
default:
|
default:
|
||||||
return ErrExpiryFilterCategoryInvalid
|
return ErrExpiryFilterCategoryInvalid
|
||||||
}
|
}
|
||||||
@@ -407,14 +410,14 @@ func validateFilters(filters ItemFilters) error {
|
|||||||
|
|
||||||
func isValidCategory(category string) bool {
|
func isValidCategory(category string) bool {
|
||||||
switch category {
|
switch category {
|
||||||
case CategoryFood, CategoryMedicine, CategoryCosmetic, CategoryOther:
|
case expirymodel.CategoryFood, expirymodel.CategoryMedicine, expirymodel.CategoryCosmetic, expirymodel.CategoryOther:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toItemView(item ExpiryItem) ItemView {
|
func ToItemView(item expirymodel.ExpiryItem) ItemView {
|
||||||
calculatedStatus := item.CalculateStatus()
|
calculatedStatus := item.CalculateStatus()
|
||||||
return ItemView{
|
return ItemView{
|
||||||
ID: item.ID,
|
ID: item.ID,
|
||||||
@@ -482,3 +485,36 @@ func (s *Service) invalidateSummaryCache(userID uint) {
|
|||||||
}
|
}
|
||||||
_ = s.summaryCache.Delete(context.Background(), userID)
|
_ = s.summaryCache.Delete(context.Background(), userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyIntSlice(values []int) []int {
|
||||||
|
if len(values) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
copied := make([]int, len(values))
|
||||||
|
copy(copied, values)
|
||||||
|
return copied
|
||||||
|
}
|
||||||
|
|
||||||
|
func NormalizeFilters(filters ItemFilters) ItemFilters {
|
||||||
|
return normalizeFilters(filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateFilters(filters ItemFilters) error {
|
||||||
|
return validateFilters(filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateBaseFields(name, category string, quantity int, location, remark string) error {
|
||||||
|
return validateBaseFields(name, category, quantity, location, remark)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ApplyExpiryDate(item *expirymodel.ExpiryItem, expiryDate *time.Time, shelfLifeDays *int) error {
|
||||||
|
return applyExpiryDate(item, expiryDate, shelfLifeDays)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsValidCategory(category string) bool {
|
||||||
|
return isValidCategory(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateRemindDays(days []int) ([]int, error) {
|
||||||
|
return validateRemindDays(days)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user