Update maintenance Component for Skills
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"bamort/models"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// SkillWithCategories represents a skill with all its categories and difficulties
|
||||
type SkillWithCategories struct {
|
||||
models.Skill
|
||||
Categories []SkillCategoryInfo `json:"categories"`
|
||||
Difficulties []string `json:"difficulties"`
|
||||
}
|
||||
|
||||
// SkillCategoryInfo contains category details for a skill
|
||||
type SkillCategoryInfo struct {
|
||||
CategoryID uint `json:"category_id"`
|
||||
CategoryName string `json:"category_name"`
|
||||
DifficultyID uint `json:"difficulty_id"`
|
||||
DifficultyName string `json:"difficulty_name"`
|
||||
LearnCost int `json:"learn_cost"`
|
||||
}
|
||||
|
||||
// GetSkillWithCategories retrieves a skill with all its category-difficulty relationships
|
||||
func GetSkillWithCategories(skillID uint) (*SkillWithCategories, error) {
|
||||
var skill models.Skill
|
||||
if err := database.DB.First(&skill, skillID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get all category-difficulty relationships
|
||||
var scds []models.SkillCategoryDifficulty
|
||||
err := database.DB.Preload("SkillCategory").Preload("SkillDifficulty").
|
||||
Where("skill_id = ?", skillID).Find(&scds).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &SkillWithCategories{
|
||||
Skill: skill,
|
||||
Categories: make([]SkillCategoryInfo, len(scds)),
|
||||
Difficulties: make([]string, len(scds)),
|
||||
}
|
||||
|
||||
for i, scd := range scds {
|
||||
result.Categories[i] = SkillCategoryInfo{
|
||||
CategoryID: scd.SkillCategoryID,
|
||||
CategoryName: scd.SkillCategory.Name,
|
||||
DifficultyID: scd.SkillDifficultyID,
|
||||
DifficultyName: scd.SkillDifficulty.Name,
|
||||
LearnCost: scd.LearnCost,
|
||||
}
|
||||
result.Difficulties[i] = scd.SkillDifficulty.Name
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetAllSkillsWithCategories retrieves all skills with their categories
|
||||
func GetAllSkillsWithCategories() ([]SkillWithCategories, error) {
|
||||
var skills []models.Skill
|
||||
if err := database.DB.Find(&skills).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]SkillWithCategories, len(skills))
|
||||
for i, skill := range skills {
|
||||
skillWithCats, err := GetSkillWithCategories(skill.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[i] = *skillWithCats
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SkillUpdateRequest represents the request to update a skill with categories
|
||||
type SkillUpdateRequest struct {
|
||||
models.Skill
|
||||
CategoryDifficulties []CategoryDifficultyPair `json:"category_difficulties"`
|
||||
}
|
||||
|
||||
// CategoryDifficultyPair represents a category-difficulty mapping
|
||||
type CategoryDifficultyPair struct {
|
||||
CategoryID uint `json:"category_id"`
|
||||
DifficultyID uint `json:"difficulty_id"`
|
||||
LearnCost int `json:"learn_cost,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateSkillWithCategories updates a skill and its category-difficulty relationships
|
||||
func UpdateSkillWithCategories(skillID uint, req SkillUpdateRequest) error {
|
||||
// Start transaction
|
||||
return database.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// Update skill basic info
|
||||
if err := tx.Model(&models.Skill{}).Where("id = ?", skillID).Updates(req.Skill).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete existing category-difficulty relationships
|
||||
if err := tx.Where("skill_id = ?", skillID).Delete(&models.SkillCategoryDifficulty{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create new relationships
|
||||
for _, cd := range req.CategoryDifficulties {
|
||||
// Get category and difficulty names for denormalized fields
|
||||
var category models.SkillCategory
|
||||
if err := tx.First(&category, cd.CategoryID).Error; err != nil {
|
||||
return fmt.Errorf("category not found: %w", err)
|
||||
}
|
||||
|
||||
var difficulty models.SkillDifficulty
|
||||
if err := tx.First(&difficulty, cd.DifficultyID).Error; err != nil {
|
||||
return fmt.Errorf("difficulty not found: %w", err)
|
||||
}
|
||||
|
||||
learnCost := cd.LearnCost
|
||||
if learnCost == 0 {
|
||||
// Use default based on difficulty
|
||||
learnCost = getDefaultLearnCost(difficulty.Name)
|
||||
}
|
||||
|
||||
scd := models.SkillCategoryDifficulty{
|
||||
SkillID: skillID,
|
||||
SkillCategoryID: cd.CategoryID,
|
||||
SkillDifficultyID: cd.DifficultyID,
|
||||
LearnCost: learnCost,
|
||||
SCategory: category.Name,
|
||||
SDifficulty: difficulty.Name,
|
||||
}
|
||||
|
||||
if err := tx.Create(&scd).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// getDefaultLearnCost returns default LE cost based on difficulty
|
||||
func getDefaultLearnCost(difficulty string) int {
|
||||
switch strings.ToLower(difficulty) {
|
||||
case "leicht", "easy":
|
||||
return 5
|
||||
case "normal", "standard":
|
||||
return 10
|
||||
case "schwer", "hard":
|
||||
return 20
|
||||
case "sehr schwer", "very hard":
|
||||
return 30
|
||||
default:
|
||||
return 10
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Handler Functions =====
|
||||
|
||||
// GetEnhancedMDSkills returns skills with their full category/difficulty information
|
||||
func GetEnhancedMDSkills(c *gin.Context) {
|
||||
skills, err := GetAllSkillsWithCategories()
|
||||
if err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to retrieve skills: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Also get learning sources and difficulties for the dropdowns
|
||||
var sources []models.Source
|
||||
database.DB.Where("is_active = ?", true).Find(&sources)
|
||||
|
||||
var categories []models.SkillCategory
|
||||
database.DB.Find(&categories)
|
||||
|
||||
var difficulties []models.SkillDifficulty
|
||||
database.DB.Find(&difficulties)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"skills": skills,
|
||||
"sources": sources,
|
||||
"categories": categories,
|
||||
"difficulties": difficulties,
|
||||
})
|
||||
}
|
||||
|
||||
// GetEnhancedMDSkill returns a single skill with category/difficulty information
|
||||
func GetEnhancedMDSkill(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
respondWithError(c, http.StatusBadRequest, "Invalid ID")
|
||||
return
|
||||
}
|
||||
|
||||
skill, err := GetSkillWithCategories(uint(id))
|
||||
if err != nil {
|
||||
respondWithError(c, http.StatusNotFound, "Skill not found")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, skill)
|
||||
}
|
||||
|
||||
// UpdateEnhancedMDSkill updates a skill with its categories
|
||||
func UpdateEnhancedMDSkill(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
respondWithError(c, http.StatusBadRequest, "Invalid ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req SkillUpdateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
respondWithError(c, http.StatusBadRequest, "Invalid request: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the ID matches
|
||||
req.Skill.ID = uint(id)
|
||||
|
||||
if err := UpdateSkillWithCategories(uint(id), req); err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to update skill: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Return updated skill
|
||||
skill, err := GetSkillWithCategories(uint(id))
|
||||
if err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to retrieve updated skill")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, skill)
|
||||
}
|
||||
Reference in New Issue
Block a user