Refine stock import UX with suggestions, ignore rules, and inline mapping controls
This commit is contained in:
@@ -997,6 +997,8 @@ func (h *PricingHandler) ImportStockLog(c *gin.Context) {
|
||||
"conflicts": result.Conflicts,
|
||||
"fallback_matches": result.FallbackMatches,
|
||||
"parse_errors": result.ParseErrors,
|
||||
"ignored": result.Ignored,
|
||||
"mapping_suggestions": result.MappingSuggestions,
|
||||
"import_date": result.ImportDate.Format("2006-01-02"),
|
||||
"warehouse_pricelist_id": result.WarehousePLID,
|
||||
"warehouse_pricelist_version": result.WarehousePLVer,
|
||||
@@ -1029,6 +1031,8 @@ func (h *PricingHandler) ImportStockLog(c *gin.Context) {
|
||||
"conflicts": p.Conflicts,
|
||||
"fallback_matches": p.FallbackMatches,
|
||||
"parse_errors": p.ParseErrors,
|
||||
"ignored": p.Ignored,
|
||||
"mapping_suggestions": p.MappingSuggestions,
|
||||
"import_date": p.ImportDate,
|
||||
"warehouse_pricelist_id": p.PricelistID,
|
||||
"warehouse_pricelist_version": p.PricelistVer,
|
||||
@@ -1078,7 +1082,7 @@ func (h *PricingHandler) UpsertStockMapping(c *gin.Context) {
|
||||
|
||||
var req struct {
|
||||
Partnumber string `json:"partnumber" binding:"required"`
|
||||
LotName string `json:"lot_name" binding:"required"`
|
||||
LotName string `json:"lot_name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -1109,3 +1113,107 @@ func (h *PricingHandler) DeleteStockMapping(c *gin.Context) {
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"deleted": deleted})
|
||||
}
|
||||
|
||||
func (h *PricingHandler) ListStockIgnoreRules(c *gin.Context) {
|
||||
if h.stockImportService == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"error": "Правила игнорирования доступны только в онлайн режиме",
|
||||
"offline": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "50"))
|
||||
rows, total, err := h.stockImportService.ListIgnoreRules(page, perPage)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"items": rows,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"per_page": perPage,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *PricingHandler) UpsertStockIgnoreRule(c *gin.Context) {
|
||||
if h.stockImportService == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"error": "Правила игнорирования доступны только в онлайн режиме",
|
||||
"offline": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
Target string `json:"target" binding:"required"`
|
||||
MatchType string `json:"match_type" binding:"required"`
|
||||
Pattern string `json:"pattern" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if err := h.stockImportService.UpsertIgnoreRule(req.Target, req.MatchType, req.Pattern); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "ignore rule saved"})
|
||||
}
|
||||
|
||||
func (h *PricingHandler) DeleteStockIgnoreRule(c *gin.Context) {
|
||||
if h.stockImportService == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"error": "Правила игнорирования доступны только в онлайн режиме",
|
||||
"offline": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
|
||||
return
|
||||
}
|
||||
deleted, err := h.stockImportService.DeleteIgnoreRule(uint(id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"deleted": deleted})
|
||||
}
|
||||
|
||||
func (h *PricingHandler) ListLots(c *gin.Context) {
|
||||
if h.db == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"error": "Список LOT доступен только в онлайн режиме",
|
||||
"offline": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "500"))
|
||||
if perPage < 1 {
|
||||
perPage = 500
|
||||
}
|
||||
if perPage > 5000 {
|
||||
perPage = 5000
|
||||
}
|
||||
search := strings.TrimSpace(c.Query("search"))
|
||||
query := h.db.Model(&models.Lot{}).Select("lot_name")
|
||||
if search != "" {
|
||||
query = query.Where("lot_name LIKE ?", "%"+search+"%")
|
||||
}
|
||||
var lots []models.Lot
|
||||
if err := query.Order("lot_name ASC").Limit(perPage).Find(&lots).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
items := make([]string, 0, len(lots))
|
||||
for _, lot := range lots {
|
||||
if strings.TrimSpace(lot.LotName) == "" {
|
||||
continue
|
||||
}
|
||||
items = append(items, lot.LotName)
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user