Export and Import of Game system master data
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# Master Data Export/Import
|
||||
|
||||
## Overview
|
||||
|
||||
The export/import mechanism allows exporting all master data from the `model_gsmaster` and `model_learning_costs` modules to JSON files and importing them back. The exported data is ID-independent, using natural keys (name + game_system) to identify records, making it suitable for:
|
||||
|
||||
- Migrating data between environments
|
||||
- Version controlling master data
|
||||
- Manually editing game data
|
||||
- Sharing/distributing game systems
|
||||
|
||||
## Supported Entities
|
||||
|
||||
### From `model_learning_costs.go`:
|
||||
- **Sources** (`learning_sources`) - Game books and source materials
|
||||
- **SkillCategories** (`learning_skill_categories`) - Skill classification categories
|
||||
- **SkillDifficulties** (`learning_skill_difficulties`) - Difficulty levels
|
||||
- **SkillCategoryDifficulties** (`learning_skill_category_difficulties`) - Relationship between skills, categories, and difficulties with learning costs
|
||||
|
||||
### From `model_gsmaster.go`:
|
||||
- **Skills** (`gsm_skills`) - Character skills
|
||||
- **Spells** (`gsm_spells`) - Magic spells
|
||||
|
||||
## Excluded Entities
|
||||
|
||||
The following are NOT exported/imported:
|
||||
- `AuditLogEntry` - Audit logs (transient data)
|
||||
- `BamortBase` - Base character data (character-specific)
|
||||
- `BamortCharTrait` - Character traits (character-specific)
|
||||
- `Magisch` - Character magic data (character-specific)
|
||||
- `LookupList` - System lookup lists (system config)
|
||||
|
||||
## File Format
|
||||
|
||||
All data is exported to JSON files with indentation for easy reading and editing:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "Skill Name",
|
||||
"game_system": "midgard",
|
||||
"source_code": "KOD",
|
||||
...
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Natural Keys
|
||||
|
||||
Instead of database IDs, the following natural keys are used to identify records:
|
||||
|
||||
| Entity | Natural Key |
|
||||
|--------|------------|
|
||||
| Source | `code` |
|
||||
| Skill | `name` + `game_system` |
|
||||
| Spell | `name` + `game_system` |
|
||||
| SkillCategory | `name` + `game_system` |
|
||||
| SkillDifficulty | `name` + `game_system` |
|
||||
| SkillCategoryDifficulty | `skill_name` + `skill_system` + `category_name` + `category_system` + `difficulty_name` + `difficulty_system` |
|
||||
|
||||
## Usage
|
||||
|
||||
### Export
|
||||
|
||||
```go
|
||||
import "bamort/gsmaster"
|
||||
|
||||
// Export specific entity types
|
||||
err := gsmaster.ExportSources("/path/to/output")
|
||||
err := gsmaster.ExportSkills("/path/to/output")
|
||||
err := gsmaster.ExportSpells("/path/to/output")
|
||||
err := gsmaster.ExportSkillCategories("/path/to/output")
|
||||
err := gsmaster.ExportSkillDifficulties("/path/to/output")
|
||||
err := gsmaster.ExportSkillCategoryDifficulties("/path/to/output")
|
||||
|
||||
// Export all master data at once
|
||||
err := gsmaster.ExportAll("/path/to/output")
|
||||
```
|
||||
|
||||
### Import
|
||||
|
||||
```go
|
||||
import "bamort/gsmaster"
|
||||
|
||||
// Import specific entity types
|
||||
err := gsmaster.ImportSources("/path/to/input")
|
||||
err := gsmaster.ImportSkills("/path/to/input")
|
||||
err := gsmaster.ImportSpells("/path/to/input")
|
||||
err := gsmaster.ImportSkillCategories("/path/to/input")
|
||||
err := gsmaster.ImportSkillDifficulties("/path/to/input")
|
||||
err := gsmaster.ImportSkillCategoryDifficulties("/path/to/input")
|
||||
|
||||
// Import all master data at once
|
||||
err := gsmaster.ImportAll("/path/to/input")
|
||||
```
|
||||
|
||||
## Import Behavior
|
||||
|
||||
The import mechanism follows an "upsert" pattern:
|
||||
|
||||
1. **Check if record exists** using natural keys
|
||||
2. If **not found**: Create new record
|
||||
3. If **found**: Update existing record with imported values
|
||||
|
||||
This allows for:
|
||||
- Importing new data
|
||||
- Updating existing data
|
||||
- Safe re-import of previously exported data
|
||||
|
||||
## Dependency Order
|
||||
|
||||
When using `ExportAll()` and `ImportAll()`, entities are processed in dependency order:
|
||||
|
||||
**Export/Import Order:**
|
||||
1. Sources (no dependencies)
|
||||
2. SkillCategories (depends on Sources)
|
||||
3. SkillDifficulties (no dependencies)
|
||||
4. Skills (depends on Sources)
|
||||
5. SkillCategoryDifficulties (depends on Skills, Categories, Difficulties)
|
||||
6. Spells (depends on Sources)
|
||||
|
||||
## File Names
|
||||
|
||||
Each entity type is exported to its own file:
|
||||
|
||||
| Entity | Filename |
|
||||
|--------|----------|
|
||||
| Sources | `sources.json` |
|
||||
| Skills | `skills.json` |
|
||||
| Spells | `spells.json` |
|
||||
| SkillCategories | `skill_categories.json` |
|
||||
| SkillDifficulties | `skill_difficulties.json` |
|
||||
| SkillCategoryDifficulties | `skill_category_difficulties.json` |
|
||||
|
||||
## Example Workflow
|
||||
|
||||
### Exporting Data
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bamort/gsmaster"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
outputDir := "./exported_data"
|
||||
|
||||
if err := gsmaster.ExportAll(outputDir); err != nil {
|
||||
log.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
log.Println("All master data exported to", outputDir)
|
||||
}
|
||||
```
|
||||
|
||||
### Editing Exported Data
|
||||
|
||||
```bash
|
||||
# Edit the JSON files manually
|
||||
vim exported_data/skills.json
|
||||
```
|
||||
|
||||
### Importing Modified Data
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bamort/gsmaster"
|
||||
"bamort/database"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize database connection
|
||||
database.InitDB()
|
||||
|
||||
inputDir := "./exported_data"
|
||||
|
||||
if err := gsmaster.ImportAll(inputDir); err != nil {
|
||||
log.Fatalf("Import failed: %v", err)
|
||||
}
|
||||
|
||||
log.Println("All master data imported from", inputDir)
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All export/import functions return errors that should be checked:
|
||||
|
||||
- **Export errors**: Usually file system issues (permissions, disk space)
|
||||
- **Import errors**: Can be:
|
||||
- File not found
|
||||
- Invalid JSON format
|
||||
- Missing dependencies (e.g., referenced source doesn't exist)
|
||||
- Database constraint violations
|
||||
|
||||
## Testing
|
||||
|
||||
The export/import mechanism is fully tested with TDD. See `gsmaster/export_import_test.go` for comprehensive test coverage including:
|
||||
|
||||
- Export creates valid JSON files
|
||||
- Import creates new records
|
||||
- Import updates existing records
|
||||
- Relationships are correctly restored using natural keys
|
||||
- Full export/import cycle works correctly
|
||||
|
||||
## Notes
|
||||
|
||||
- **No Handlers/Routes**: This functionality is intentionally not exposed as API endpoints. Use it programmatically or via CLI tools.
|
||||
- **ID Independence**: Exported data does not contain database IDs, making it portable across different database instances.
|
||||
- **Idempotent**: Import can be run multiple times safely - it will update existing records rather than creating duplicates.
|
||||
- **Transaction Safety**: Each import operation should ideally be wrapped in a database transaction for atomicity.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,687 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"bamort/models"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ExportSkillImprovementCosts exports all skill improvement costs to a JSON file
|
||||
func ExportSkillImprovementCosts(outputDir string) error {
|
||||
var costs []models.SkillImprovementCost
|
||||
if err := database.DB.Find(&costs).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch skill improvement costs: %w", err)
|
||||
}
|
||||
|
||||
// Build maps for skill category difficulties
|
||||
var scds []models.SkillCategoryDifficulty
|
||||
database.DB.Find(&scds)
|
||||
scdMap := make(map[uint]models.SkillCategoryDifficulty)
|
||||
for _, scd := range scds {
|
||||
scdMap[scd.ID] = scd
|
||||
}
|
||||
|
||||
// Get skills
|
||||
var skills []models.Skill
|
||||
database.DB.Find(&skills)
|
||||
skillMap := make(map[uint]models.Skill)
|
||||
for _, s := range skills {
|
||||
skillMap[s.ID] = s
|
||||
}
|
||||
|
||||
// Get categories
|
||||
var categories []models.SkillCategory
|
||||
database.DB.Find(&categories)
|
||||
categoryMap := make(map[uint]models.SkillCategory)
|
||||
for _, c := range categories {
|
||||
categoryMap[c.ID] = c
|
||||
}
|
||||
|
||||
// Get difficulties
|
||||
var difficulties []models.SkillDifficulty
|
||||
database.DB.Find(&difficulties)
|
||||
difficultyMap := make(map[uint]models.SkillDifficulty)
|
||||
for _, d := range difficulties {
|
||||
difficultyMap[d.ID] = d
|
||||
}
|
||||
|
||||
exportable := make([]ExportableSkillImprovementCost, len(costs))
|
||||
for i, cost := range costs {
|
||||
scd := scdMap[cost.SkillCategoryDifficultyID]
|
||||
skill := skillMap[scd.SkillID]
|
||||
category := categoryMap[scd.SkillCategoryID]
|
||||
difficulty := difficultyMap[scd.SkillDifficultyID]
|
||||
|
||||
exportable[i] = ExportableSkillImprovementCost{
|
||||
SkillName: skill.Name,
|
||||
SkillSystem: skill.GameSystem,
|
||||
CategoryName: category.Name,
|
||||
CategorySystem: category.GameSystem,
|
||||
DifficultyName: difficulty.Name,
|
||||
DifficultySystem: difficulty.GameSystem,
|
||||
CurrentLevel: cost.CurrentLevel,
|
||||
TERequired: cost.TERequired,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "skill_improvement_costs.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportSkillImprovementCosts imports skill improvement costs from a JSON file
|
||||
func ImportSkillImprovementCosts(inputDir string) error {
|
||||
var exportable []ExportableSkillImprovementCost
|
||||
if err := readJSON(filepath.Join(inputDir, "skill_improvement_costs.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
// Find skill
|
||||
var skill models.Skill
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", exp.SkillName, exp.SkillSystem).First(&skill).Error; err != nil {
|
||||
return fmt.Errorf("skill not found: %s: %w", exp.SkillName, err)
|
||||
}
|
||||
|
||||
// Find category
|
||||
var category models.SkillCategory
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", exp.CategoryName, exp.CategorySystem).First(&category).Error; err != nil {
|
||||
return fmt.Errorf("category not found: %s: %w", exp.CategoryName, err)
|
||||
}
|
||||
|
||||
// Find difficulty
|
||||
var difficulty models.SkillDifficulty
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", exp.DifficultyName, exp.DifficultySystem).First(&difficulty).Error; err != nil {
|
||||
return fmt.Errorf("difficulty not found: %s: %w", exp.DifficultyName, err)
|
||||
}
|
||||
|
||||
// Find SkillCategoryDifficulty
|
||||
var scd models.SkillCategoryDifficulty
|
||||
if err := database.DB.Where("skill_id = ? AND skill_category_id = ? AND skill_difficulty_id = ?",
|
||||
skill.ID, category.ID, difficulty.ID).First(&scd).Error; err != nil {
|
||||
return fmt.Errorf("skill category difficulty not found: %w", err)
|
||||
}
|
||||
|
||||
// Find or create SkillImprovementCost
|
||||
var cost models.SkillImprovementCost
|
||||
result := database.DB.Where("skill_category_difficulty_id = ? AND current_level = ?",
|
||||
scd.ID, exp.CurrentLevel).First(&cost)
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
cost = models.SkillImprovementCost{
|
||||
SkillCategoryDifficultyID: scd.ID,
|
||||
CurrentLevel: exp.CurrentLevel,
|
||||
TERequired: exp.TERequired,
|
||||
}
|
||||
if err := database.DB.Create(&cost).Error; err != nil {
|
||||
return fmt.Errorf("failed to create skill improvement cost: %w", err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query skill improvement cost: %w", result.Error)
|
||||
} else {
|
||||
cost.TERequired = exp.TERequired
|
||||
if err := database.DB.Save(&cost).Error; err != nil {
|
||||
return fmt.Errorf("failed to update skill improvement cost: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportWeaponSkills exports all weapon skills to a JSON file
|
||||
func ExportWeaponSkills(outputDir string) error {
|
||||
var skills []models.WeaponSkill
|
||||
if err := database.DB.Find(&skills).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch weapon skills: %w", err)
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[uint]string)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.ID] = s.Code
|
||||
}
|
||||
|
||||
exportable := make([]ExportableWeaponSkill, len(skills))
|
||||
for i, skill := range skills {
|
||||
exportable[i] = ExportableWeaponSkill{
|
||||
Name: skill.Name,
|
||||
GameSystem: skill.GameSystem,
|
||||
Beschreibung: skill.Beschreibung,
|
||||
SourceCode: sourceMap[skill.SourceID],
|
||||
PageNumber: skill.PageNumber,
|
||||
Initialwert: skill.Initialwert,
|
||||
BasisWert: skill.BasisWert,
|
||||
Bonuseigenschaft: skill.Bonuseigenschaft,
|
||||
Improvable: skill.Improvable,
|
||||
InnateSkill: skill.InnateSkill,
|
||||
Category: skill.Category,
|
||||
Difficulty: skill.Difficulty,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "weapon_skills.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportWeaponSkills imports weapon skills from a JSON file
|
||||
func ImportWeaponSkills(inputDir string) error {
|
||||
var exportable []ExportableWeaponSkill
|
||||
if err := readJSON(filepath.Join(inputDir, "weapon_skills.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[string]uint)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.Code] = s.ID
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
var skill models.WeaponSkill
|
||||
result := database.DB.Where("name = ? AND game_system = ?", exp.Name, exp.GameSystem).First(&skill)
|
||||
|
||||
sourceID := sourceMap[exp.SourceCode]
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
skill = models.WeaponSkill{
|
||||
Skill: models.Skill{
|
||||
Name: exp.Name,
|
||||
GameSystem: exp.GameSystem,
|
||||
Beschreibung: exp.Beschreibung,
|
||||
SourceID: sourceID,
|
||||
PageNumber: exp.PageNumber,
|
||||
Initialwert: exp.Initialwert,
|
||||
BasisWert: exp.BasisWert,
|
||||
Bonuseigenschaft: exp.Bonuseigenschaft,
|
||||
Improvable: exp.Improvable,
|
||||
InnateSkill: exp.InnateSkill,
|
||||
Category: exp.Category,
|
||||
Difficulty: exp.Difficulty,
|
||||
},
|
||||
}
|
||||
if err := database.DB.Create(&skill).Error; err != nil {
|
||||
return fmt.Errorf("failed to create weapon skill %s: %w", exp.Name, err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query weapon skill %s: %w", exp.Name, result.Error)
|
||||
} else {
|
||||
skill.Beschreibung = exp.Beschreibung
|
||||
skill.SourceID = sourceID
|
||||
skill.PageNumber = exp.PageNumber
|
||||
skill.Initialwert = exp.Initialwert
|
||||
skill.BasisWert = exp.BasisWert
|
||||
skill.Bonuseigenschaft = exp.Bonuseigenschaft
|
||||
skill.Improvable = exp.Improvable
|
||||
skill.InnateSkill = exp.InnateSkill
|
||||
skill.Category = exp.Category
|
||||
skill.Difficulty = exp.Difficulty
|
||||
|
||||
if err := database.DB.Save(&skill).Error; err != nil {
|
||||
return fmt.Errorf("failed to update weapon skill %s: %w", exp.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportEquipment exports all equipment to a JSON file
|
||||
func ExportEquipment(outputDir string) error {
|
||||
var equipment []models.Equipment
|
||||
if err := database.DB.Find(&equipment).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch equipment: %w", err)
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[uint]string)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.ID] = s.Code
|
||||
}
|
||||
|
||||
exportable := make([]ExportableEquipment, len(equipment))
|
||||
for i, eq := range equipment {
|
||||
exportable[i] = ExportableEquipment{
|
||||
Name: eq.Name,
|
||||
GameSystem: eq.GameSystem,
|
||||
Beschreibung: eq.Beschreibung,
|
||||
SourceCode: sourceMap[eq.SourceID],
|
||||
PageNumber: eq.PageNumber,
|
||||
Gewicht: eq.Gewicht,
|
||||
Wert: eq.Wert,
|
||||
PersonalItem: eq.PersonalItem,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "equipment.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportEquipment imports equipment from a JSON file
|
||||
func ImportEquipment(inputDir string) error {
|
||||
var exportable []ExportableEquipment
|
||||
if err := readJSON(filepath.Join(inputDir, "equipment.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[string]uint)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.Code] = s.ID
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
var eq models.Equipment
|
||||
result := database.DB.Where("name = ? AND game_system = ?", exp.Name, exp.GameSystem).First(&eq)
|
||||
|
||||
sourceID := sourceMap[exp.SourceCode]
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
eq = models.Equipment{
|
||||
Name: exp.Name,
|
||||
GameSystem: exp.GameSystem,
|
||||
Beschreibung: exp.Beschreibung,
|
||||
SourceID: sourceID,
|
||||
PageNumber: exp.PageNumber,
|
||||
Gewicht: exp.Gewicht,
|
||||
Wert: exp.Wert,
|
||||
PersonalItem: exp.PersonalItem,
|
||||
}
|
||||
if err := database.DB.Create(&eq).Error; err != nil {
|
||||
return fmt.Errorf("failed to create equipment %s: %w", exp.Name, err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query equipment %s: %w", exp.Name, result.Error)
|
||||
} else {
|
||||
eq.Beschreibung = exp.Beschreibung
|
||||
eq.SourceID = sourceID
|
||||
eq.PageNumber = exp.PageNumber
|
||||
eq.Gewicht = exp.Gewicht
|
||||
eq.Wert = exp.Wert
|
||||
eq.PersonalItem = exp.PersonalItem
|
||||
|
||||
if err := database.DB.Save(&eq).Error; err != nil {
|
||||
return fmt.Errorf("failed to update equipment %s: %w", exp.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportWeapons exports all weapons to a JSON file
|
||||
func ExportWeapons(outputDir string) error {
|
||||
var weapons []models.Weapon
|
||||
if err := database.DB.Find(&weapons).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch weapons: %w", err)
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[uint]string)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.ID] = s.Code
|
||||
}
|
||||
|
||||
exportable := make([]ExportableWeapon, len(weapons))
|
||||
for i, weapon := range weapons {
|
||||
exportable[i] = ExportableWeapon{
|
||||
Name: weapon.Name,
|
||||
GameSystem: weapon.GameSystem,
|
||||
Beschreibung: weapon.Beschreibung,
|
||||
SourceCode: sourceMap[weapon.SourceID],
|
||||
PageNumber: weapon.PageNumber,
|
||||
Gewicht: weapon.Gewicht,
|
||||
Wert: weapon.Wert,
|
||||
PersonalItem: weapon.PersonalItem,
|
||||
SkillRequired: weapon.SkillRequired,
|
||||
Damage: weapon.Damage,
|
||||
RangeNear: weapon.RangeNear,
|
||||
RangeMiddle: weapon.RangeMiddle,
|
||||
RangeFar: weapon.RangeFar,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "weapons.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportWeapons imports weapons from a JSON file
|
||||
func ImportWeapons(inputDir string) error {
|
||||
var exportable []ExportableWeapon
|
||||
if err := readJSON(filepath.Join(inputDir, "weapons.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[string]uint)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.Code] = s.ID
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
var weapon models.Weapon
|
||||
result := database.DB.Where("name = ? AND game_system = ?", exp.Name, exp.GameSystem).First(&weapon)
|
||||
|
||||
sourceID := sourceMap[exp.SourceCode]
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
weapon = models.Weapon{
|
||||
Equipment: models.Equipment{
|
||||
Name: exp.Name,
|
||||
GameSystem: exp.GameSystem,
|
||||
Beschreibung: exp.Beschreibung,
|
||||
SourceID: sourceID,
|
||||
PageNumber: exp.PageNumber,
|
||||
Gewicht: exp.Gewicht,
|
||||
Wert: exp.Wert,
|
||||
PersonalItem: exp.PersonalItem,
|
||||
},
|
||||
SkillRequired: exp.SkillRequired,
|
||||
Damage: exp.Damage,
|
||||
RangeNear: exp.RangeNear,
|
||||
RangeMiddle: exp.RangeMiddle,
|
||||
RangeFar: exp.RangeFar,
|
||||
}
|
||||
if err := database.DB.Create(&weapon).Error; err != nil {
|
||||
return fmt.Errorf("failed to create weapon %s: %w", exp.Name, err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query weapon %s: %w", exp.Name, result.Error)
|
||||
} else {
|
||||
weapon.Beschreibung = exp.Beschreibung
|
||||
weapon.SourceID = sourceID
|
||||
weapon.PageNumber = exp.PageNumber
|
||||
weapon.Gewicht = exp.Gewicht
|
||||
weapon.Wert = exp.Wert
|
||||
weapon.PersonalItem = exp.PersonalItem
|
||||
weapon.SkillRequired = exp.SkillRequired
|
||||
weapon.Damage = exp.Damage
|
||||
weapon.RangeNear = exp.RangeNear
|
||||
weapon.RangeMiddle = exp.RangeMiddle
|
||||
weapon.RangeFar = exp.RangeFar
|
||||
|
||||
if err := database.DB.Save(&weapon).Error; err != nil {
|
||||
return fmt.Errorf("failed to update weapon %s: %w", exp.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportContainers exports all containers to a JSON file
|
||||
func ExportContainers(outputDir string) error {
|
||||
var containers []models.Container
|
||||
if err := database.DB.Find(&containers).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch containers: %w", err)
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[uint]string)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.ID] = s.Code
|
||||
}
|
||||
|
||||
exportable := make([]ExportableContainer, len(containers))
|
||||
for i, container := range containers {
|
||||
exportable[i] = ExportableContainer{
|
||||
Name: container.Name,
|
||||
GameSystem: container.GameSystem,
|
||||
Beschreibung: container.Beschreibung,
|
||||
SourceCode: sourceMap[container.SourceID],
|
||||
PageNumber: container.PageNumber,
|
||||
Gewicht: container.Gewicht,
|
||||
Wert: container.Wert,
|
||||
PersonalItem: container.PersonalItem,
|
||||
Tragkraft: container.Tragkraft,
|
||||
Volumen: container.Volumen,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "containers.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportContainers imports containers from a JSON file
|
||||
func ImportContainers(inputDir string) error {
|
||||
var exportable []ExportableContainer
|
||||
if err := readJSON(filepath.Join(inputDir, "containers.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[string]uint)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.Code] = s.ID
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
var container models.Container
|
||||
result := database.DB.Where("name = ? AND game_system = ?", exp.Name, exp.GameSystem).First(&container)
|
||||
|
||||
sourceID := sourceMap[exp.SourceCode]
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
container = models.Container{
|
||||
Equipment: models.Equipment{
|
||||
Name: exp.Name,
|
||||
GameSystem: exp.GameSystem,
|
||||
Beschreibung: exp.Beschreibung,
|
||||
SourceID: sourceID,
|
||||
PageNumber: exp.PageNumber,
|
||||
Gewicht: exp.Gewicht,
|
||||
Wert: exp.Wert,
|
||||
PersonalItem: exp.PersonalItem,
|
||||
},
|
||||
Tragkraft: exp.Tragkraft,
|
||||
Volumen: exp.Volumen,
|
||||
}
|
||||
if err := database.DB.Create(&container).Error; err != nil {
|
||||
return fmt.Errorf("failed to create container %s: %w", exp.Name, err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query container %s: %w", exp.Name, result.Error)
|
||||
} else {
|
||||
container.Beschreibung = exp.Beschreibung
|
||||
container.SourceID = sourceID
|
||||
container.PageNumber = exp.PageNumber
|
||||
container.Gewicht = exp.Gewicht
|
||||
container.Wert = exp.Wert
|
||||
container.PersonalItem = exp.PersonalItem
|
||||
container.Tragkraft = exp.Tragkraft
|
||||
container.Volumen = exp.Volumen
|
||||
|
||||
if err := database.DB.Save(&container).Error; err != nil {
|
||||
return fmt.Errorf("failed to update container %s: %w", exp.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportTransportation exports all transportation to a JSON file
|
||||
func ExportTransportation(outputDir string) error {
|
||||
var transportation []models.Transportation
|
||||
if err := database.DB.Find(&transportation).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch transportation: %w", err)
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[uint]string)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.ID] = s.Code
|
||||
}
|
||||
|
||||
exportable := make([]ExportableTransportation, len(transportation))
|
||||
for i, trans := range transportation {
|
||||
exportable[i] = ExportableTransportation{
|
||||
Name: trans.Name,
|
||||
GameSystem: trans.GameSystem,
|
||||
Beschreibung: trans.Beschreibung,
|
||||
SourceCode: sourceMap[trans.SourceID],
|
||||
PageNumber: trans.PageNumber,
|
||||
Gewicht: trans.Gewicht,
|
||||
Wert: trans.Wert,
|
||||
PersonalItem: trans.PersonalItem,
|
||||
Tragkraft: trans.Tragkraft,
|
||||
Volumen: trans.Volumen,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "transportation.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportTransportation imports transportation from a JSON file
|
||||
func ImportTransportation(inputDir string) error {
|
||||
var exportable []ExportableTransportation
|
||||
if err := readJSON(filepath.Join(inputDir, "transportation.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[string]uint)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.Code] = s.ID
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
var trans models.Transportation
|
||||
result := database.DB.Where("name = ? AND game_system = ?", exp.Name, exp.GameSystem).First(&trans)
|
||||
|
||||
sourceID := sourceMap[exp.SourceCode]
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
trans = models.Transportation{
|
||||
Container: models.Container{
|
||||
Equipment: models.Equipment{
|
||||
Name: exp.Name,
|
||||
GameSystem: exp.GameSystem,
|
||||
Beschreibung: exp.Beschreibung,
|
||||
SourceID: sourceID,
|
||||
PageNumber: exp.PageNumber,
|
||||
Gewicht: exp.Gewicht,
|
||||
Wert: exp.Wert,
|
||||
PersonalItem: exp.PersonalItem,
|
||||
},
|
||||
Tragkraft: exp.Tragkraft,
|
||||
Volumen: exp.Volumen,
|
||||
},
|
||||
}
|
||||
if err := database.DB.Create(&trans).Error; err != nil {
|
||||
return fmt.Errorf("failed to create transportation %s: %w", exp.Name, err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query transportation %s: %w", exp.Name, result.Error)
|
||||
} else {
|
||||
trans.Beschreibung = exp.Beschreibung
|
||||
trans.SourceID = sourceID
|
||||
trans.PageNumber = exp.PageNumber
|
||||
trans.Gewicht = exp.Gewicht
|
||||
trans.Wert = exp.Wert
|
||||
trans.PersonalItem = exp.PersonalItem
|
||||
trans.Tragkraft = exp.Tragkraft
|
||||
trans.Volumen = exp.Volumen
|
||||
|
||||
if err := database.DB.Save(&trans).Error; err != nil {
|
||||
return fmt.Errorf("failed to update transportation %s: %w", exp.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExportBelieves exports all beliefs to a JSON file
|
||||
func ExportBelieves(outputDir string) error {
|
||||
var believes []models.Believe
|
||||
if err := database.DB.Find(&believes).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch believes: %w", err)
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[uint]string)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.ID] = s.Code
|
||||
}
|
||||
|
||||
exportable := make([]ExportableBelieve, len(believes))
|
||||
for i, believe := range believes {
|
||||
exportable[i] = ExportableBelieve{
|
||||
Name: believe.Name,
|
||||
GameSystem: believe.GameSystem,
|
||||
Beschreibung: believe.Beschreibung,
|
||||
SourceCode: sourceMap[believe.SourceID],
|
||||
PageNumber: believe.PageNumber,
|
||||
}
|
||||
}
|
||||
|
||||
return writeJSON(filepath.Join(outputDir, "believes.json"), exportable)
|
||||
}
|
||||
|
||||
// ImportBelieves imports believes from a JSON file
|
||||
func ImportBelieves(inputDir string) error {
|
||||
var exportable []ExportableBelieve
|
||||
if err := readJSON(filepath.Join(inputDir, "believes.json"), &exportable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get source map
|
||||
var sources []models.Source
|
||||
database.DB.Find(&sources)
|
||||
sourceMap := make(map[string]uint)
|
||||
for _, s := range sources {
|
||||
sourceMap[s.Code] = s.ID
|
||||
}
|
||||
|
||||
for _, exp := range exportable {
|
||||
var believe models.Believe
|
||||
result := database.DB.Where("name = ? AND game_system = ?", exp.Name, exp.GameSystem).First(&believe)
|
||||
|
||||
sourceID := sourceMap[exp.SourceCode]
|
||||
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
believe = models.Believe{
|
||||
Name: exp.Name,
|
||||
GameSystem: exp.GameSystem,
|
||||
Beschreibung: exp.Beschreibung,
|
||||
SourceID: sourceID,
|
||||
PageNumber: exp.PageNumber,
|
||||
}
|
||||
if err := database.DB.Create(&believe).Error; err != nil {
|
||||
return fmt.Errorf("failed to create believe %s: %w", exp.Name, err)
|
||||
}
|
||||
} else if result.Error != nil {
|
||||
return fmt.Errorf("failed to query believe %s: %w", exp.Name, result.Error)
|
||||
} else {
|
||||
believe.Beschreibung = exp.Beschreibung
|
||||
believe.SourceID = sourceID
|
||||
believe.PageNumber = exp.PageNumber
|
||||
|
||||
if err := database.DB.Save(&believe).Error; err != nil {
|
||||
return fmt.Errorf("failed to update believe %s: %w", exp.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,914 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"bamort/models"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestExportSkills(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test data
|
||||
source := getOrCreateSource("KOD", "Kodex")
|
||||
skill := models.Skill{
|
||||
Name: "Schwimmen",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Schwimmen im Wasser",
|
||||
Initialwert: 12,
|
||||
BasisWert: 0,
|
||||
Bonuseigenschaft: "Gw",
|
||||
Improvable: true,
|
||||
InnateSkill: false,
|
||||
SourceID: source.ID,
|
||||
PageNumber: 42,
|
||||
}
|
||||
database.DB.Create(&skill)
|
||||
|
||||
// Export skills
|
||||
tmpDir := t.TempDir()
|
||||
err := ExportSkills(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkills failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify file exists
|
||||
exportFile := filepath.Join(tmpDir, "skills.json")
|
||||
if _, err := os.Stat(exportFile); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", exportFile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportSkills(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create source that will be referenced
|
||||
source := getOrCreateSource("KOD", "Kodex")
|
||||
|
||||
// Export first
|
||||
tmpDir := t.TempDir()
|
||||
skill := models.Skill{
|
||||
Name: "Klettern",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Klettern an Wänden",
|
||||
Initialwert: 10,
|
||||
BasisWert: 0,
|
||||
Bonuseigenschaft: "Gw",
|
||||
Improvable: true,
|
||||
InnateSkill: false,
|
||||
SourceID: source.ID,
|
||||
PageNumber: 50,
|
||||
}
|
||||
database.DB.Create(&skill)
|
||||
|
||||
err := ExportSkills(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkills failed: %v", err)
|
||||
}
|
||||
|
||||
// Delete the skill
|
||||
database.DB.Delete(&skill)
|
||||
|
||||
// Import back
|
||||
err = ImportSkills(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSkills failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify skill was imported
|
||||
var importedSkill models.Skill
|
||||
err = database.DB.Where("name = ? AND game_system = ?", "Klettern", "midgard").First(&importedSkill).Error
|
||||
if err != nil {
|
||||
t.Fatalf("Imported skill not found: %v", err)
|
||||
}
|
||||
|
||||
if importedSkill.Beschreibung != "Klettern an Wänden" {
|
||||
t.Errorf("Expected beschreibung 'Klettern an Wänden', got '%s'", importedSkill.Beschreibung)
|
||||
}
|
||||
|
||||
if importedSkill.Initialwert != 10 {
|
||||
t.Errorf("Expected initialwert 10, got %d", importedSkill.Initialwert)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportSkillsUpdate(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("KOD", "Kodex")
|
||||
|
||||
// Create existing skill
|
||||
skill := models.Skill{
|
||||
Name: "Reiten",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Alte Beschreibung",
|
||||
Initialwert: 8,
|
||||
SourceID: source.ID,
|
||||
PageNumber: 30,
|
||||
}
|
||||
database.DB.Create(&skill)
|
||||
|
||||
// Export, modify, and re-import
|
||||
tmpDir := t.TempDir()
|
||||
err := ExportSkills(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkills failed: %v", err)
|
||||
}
|
||||
|
||||
// Update skill manually
|
||||
skill.Beschreibung = "Neue Beschreibung"
|
||||
skill.Initialwert = 12
|
||||
database.DB.Save(&skill)
|
||||
|
||||
// Export again with updated values
|
||||
err = ExportSkills(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkills failed: %v", err)
|
||||
}
|
||||
|
||||
// Reset to old values
|
||||
skill.Beschreibung = "Alte Beschreibung"
|
||||
skill.Initialwert = 8
|
||||
database.DB.Save(&skill)
|
||||
|
||||
// Import should update to exported values
|
||||
err = ImportSkills(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSkills failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify update
|
||||
var updatedSkill models.Skill
|
||||
err = database.DB.Where("name = ? AND game_system = ?", "Reiten", "midgard").First(&updatedSkill).Error
|
||||
if err != nil {
|
||||
t.Fatalf("Updated skill not found: %v", err)
|
||||
}
|
||||
|
||||
if updatedSkill.Beschreibung != "Neue Beschreibung" {
|
||||
t.Errorf("Expected updated beschreibung 'Neue Beschreibung', got '%s'", updatedSkill.Beschreibung)
|
||||
}
|
||||
|
||||
if updatedSkill.Initialwert != 12 {
|
||||
t.Errorf("Expected updated initialwert 12, got %d", updatedSkill.Initialwert)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportSources(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test source
|
||||
source := models.Source{
|
||||
Code: "ARK",
|
||||
Name: "Arkanum",
|
||||
GameSystem: "midgard",
|
||||
IsActive: true,
|
||||
}
|
||||
database.DB.Create(&source)
|
||||
|
||||
// Export
|
||||
tmpDir := t.TempDir()
|
||||
err := ExportSources(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSources failed: %v", err)
|
||||
}
|
||||
|
||||
// Delete
|
||||
database.DB.Delete(&source)
|
||||
|
||||
// Import
|
||||
err = ImportSources(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSources failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify
|
||||
var imported models.Source
|
||||
err = database.DB.Where("code = ?", "ARK").First(&imported).Error
|
||||
if err != nil {
|
||||
t.Fatalf("Imported source not found: %v", err)
|
||||
}
|
||||
|
||||
if imported.Name != "Arkanum" {
|
||||
t.Errorf("Expected name 'Arkanum', got '%s'", imported.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportSkillCategoryDifficulty(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create dependencies
|
||||
source := getOrCreateSource("KOD", "Kodex")
|
||||
skill := models.Skill{
|
||||
Name: "Tanzen",
|
||||
GameSystem: "midgard",
|
||||
SourceID: source.ID,
|
||||
}
|
||||
database.DB.Create(&skill)
|
||||
|
||||
category := getOrCreateCategory("Alltag", source.ID)
|
||||
difficulty := getOrCreateDifficulty("leicht")
|
||||
|
||||
// Create relationship
|
||||
scd := models.SkillCategoryDifficulty{
|
||||
SkillID: skill.ID,
|
||||
SkillCategoryID: category.ID,
|
||||
SkillDifficultyID: difficulty.ID,
|
||||
LearnCost: 5,
|
||||
SCategory: category.Name,
|
||||
SDifficulty: difficulty.Name,
|
||||
}
|
||||
database.DB.Create(&scd)
|
||||
|
||||
// Export
|
||||
tmpDir := t.TempDir()
|
||||
err := ExportSkillCategoryDifficulties(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkillCategoryDifficulties failed: %v", err)
|
||||
}
|
||||
|
||||
// Delete relationship
|
||||
database.DB.Delete(&scd)
|
||||
|
||||
// Import
|
||||
err = ImportSkillCategoryDifficulties(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSkillCategoryDifficulties failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify relationship was recreated
|
||||
var imported models.SkillCategoryDifficulty
|
||||
err = database.DB.Where("skill_id = ? AND skill_category_id = ?", skill.ID, category.ID).First(&imported).Error
|
||||
if err != nil {
|
||||
t.Fatalf("Imported relationship not found: %v", err)
|
||||
}
|
||||
|
||||
if imported.LearnCost != 5 {
|
||||
t.Errorf("Expected learn_cost 5, got %d", imported.LearnCost)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportSkillCategories(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test data
|
||||
source := getOrCreateSource("TEST_SC", "Test Source")
|
||||
category := models.SkillCategory{
|
||||
Name: "TestCategory",
|
||||
GameSystem: "midgard",
|
||||
SourceID: source.ID,
|
||||
}
|
||||
database.DB.Create(&category)
|
||||
|
||||
// Export
|
||||
tempDir := t.TempDir()
|
||||
err := ExportSkillCategories(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkillCategories failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify file was created
|
||||
filename := filepath.Join(tempDir, "skill_categories.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
// Delete the category
|
||||
database.DB.Unscoped().Delete(&category)
|
||||
|
||||
// Import
|
||||
err = ImportSkillCategories(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSkillCategories failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify the category was recreated
|
||||
var imported models.SkillCategory
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "TestCategory", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Category not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
if imported.SourceID != source.ID {
|
||||
t.Errorf("Expected SourceID %d, got %d", source.ID, imported.SourceID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportSkillDifficulties(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test data
|
||||
difficulty := models.SkillDifficulty{
|
||||
Name: "TestDifficulty",
|
||||
GameSystem: "midgard",
|
||||
}
|
||||
database.DB.Create(&difficulty)
|
||||
|
||||
// Export
|
||||
tempDir := t.TempDir()
|
||||
err := ExportSkillDifficulties(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkillDifficulties failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify file was created
|
||||
filename := filepath.Join(tempDir, "skill_difficulties.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
// Delete the difficulty
|
||||
database.DB.Unscoped().Delete(&difficulty)
|
||||
|
||||
// Import
|
||||
err = ImportSkillDifficulties(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSkillDifficulties failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify the difficulty was recreated
|
||||
var imported models.SkillDifficulty
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "TestDifficulty", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Difficulty not found after import: %v", result.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportSpells(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test data
|
||||
source := getOrCreateSource("TEST_SP", "Test Spell Source")
|
||||
spell := models.Spell{
|
||||
Name: "TestSpell",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Test description",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 42,
|
||||
Bonus: 5,
|
||||
Stufe: 3,
|
||||
AP: "2",
|
||||
Art: "Gestenzauber",
|
||||
Zauberdauer: "10 sec",
|
||||
Reichweite: "10m",
|
||||
Wirkungsziel: "Person",
|
||||
Wirkungsbereich: "1 Person",
|
||||
Wirkungsdauer: "1h",
|
||||
Ursprung: "Elben",
|
||||
Category: "normal",
|
||||
LearningCategory: "default",
|
||||
}
|
||||
database.DB.Create(&spell)
|
||||
|
||||
// Export
|
||||
tempDir := t.TempDir()
|
||||
err := ExportSpells(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSpells failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify file was created
|
||||
filename := filepath.Join(tempDir, "spells.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
// Modify the spell
|
||||
spell.Beschreibung = "Old description"
|
||||
spell.Bonus = 3
|
||||
database.DB.Save(&spell)
|
||||
|
||||
// Import (should update)
|
||||
err = ImportSpells(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSpells failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify the spell was updated
|
||||
var imported models.Spell
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "TestSpell", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Spell not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
if imported.Beschreibung != "Test description" {
|
||||
t.Errorf("Expected description 'Test description', got '%s'", imported.Beschreibung)
|
||||
}
|
||||
if imported.Bonus != 5 {
|
||||
t.Errorf("Expected bonus 5, got %d", imported.Bonus)
|
||||
}
|
||||
if imported.Stufe != 3 {
|
||||
t.Errorf("Expected level 3, got %d", imported.Stufe)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportAll(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test data
|
||||
source := getOrCreateSource("TEST_ALL", "Test All Source")
|
||||
|
||||
category := models.SkillCategory{Name: "AllCategory", GameSystem: "midgard", SourceID: source.ID}
|
||||
database.DB.Create(&category)
|
||||
|
||||
difficulty := models.SkillDifficulty{Name: "AllDifficulty", GameSystem: "midgard"}
|
||||
database.DB.Create(&difficulty)
|
||||
|
||||
skill := models.Skill{
|
||||
Name: "AllSkill",
|
||||
GameSystem: "midgard",
|
||||
SourceID: source.ID,
|
||||
Initialwert: 10,
|
||||
}
|
||||
database.DB.Create(&skill)
|
||||
|
||||
spell := models.Spell{
|
||||
Name: "AllSpell",
|
||||
GameSystem: "midgard",
|
||||
SourceID: source.ID,
|
||||
Stufe: 2,
|
||||
}
|
||||
database.DB.Create(&spell)
|
||||
|
||||
// Export all
|
||||
tempDir := t.TempDir()
|
||||
err := ExportAll(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportAll failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify all files were created
|
||||
files := []string{
|
||||
"sources.json",
|
||||
"character_classes.json",
|
||||
"skill_categories.json",
|
||||
"skill_difficulties.json",
|
||||
"spell_schools.json",
|
||||
"skills.json",
|
||||
"skill_category_difficulties.json",
|
||||
"spells.json",
|
||||
"class_category_ep_costs.json",
|
||||
"class_spell_school_ep_costs.json",
|
||||
"spell_level_le_costs.json",
|
||||
"skill_improvement_costs.json",
|
||||
"weapon_skills.json",
|
||||
"equipment.json",
|
||||
"weapons.json",
|
||||
"containers.json",
|
||||
"transportation.json",
|
||||
"believes.json",
|
||||
}
|
||||
for _, file := range files {
|
||||
filename := filepath.Join(tempDir, file)
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Errorf("Export file not created: %s", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all test data
|
||||
database.DB.Unscoped().Delete(&spell)
|
||||
database.DB.Unscoped().Delete(&skill)
|
||||
database.DB.Unscoped().Delete(&difficulty)
|
||||
database.DB.Unscoped().Delete(&category)
|
||||
// Don't delete source to avoid FK constraints
|
||||
|
||||
// Import all
|
||||
err = ImportAll(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportAll failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify all data was recreated
|
||||
var importedCategory models.SkillCategory
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", "AllCategory", "midgard").First(&importedCategory).Error; err != nil {
|
||||
t.Errorf("Category not found after import: %v", err)
|
||||
}
|
||||
|
||||
var importedDifficulty models.SkillDifficulty
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", "AllDifficulty", "midgard").First(&importedDifficulty).Error; err != nil {
|
||||
t.Errorf("Difficulty not found after import: %v", err)
|
||||
}
|
||||
|
||||
var importedSkill models.Skill
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", "AllSkill", "midgard").First(&importedSkill).Error; err != nil {
|
||||
t.Errorf("Skill not found after import: %v", err)
|
||||
}
|
||||
|
||||
var importedSpell models.Spell
|
||||
if err := database.DB.Where("name = ? AND game_system = ?", "AllSpell", "midgard").First(&importedSpell).Error; err != nil {
|
||||
t.Errorf("Spell not found after import: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportAll_live(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB(false)
|
||||
|
||||
// Export all
|
||||
tempDir := t.TempDir()
|
||||
err := ExportAll(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportAll failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify all files were created
|
||||
files := []string{"sources.json", "skill_categories.json", "skill_difficulties.json", "skills.json", "spells.json", "skill_category_difficulties.json"}
|
||||
for _, file := range files {
|
||||
filename := filepath.Join(tempDir, file)
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Errorf("Export file not created: %s", filename)
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, len(files), 6)
|
||||
|
||||
}
|
||||
|
||||
func TestExportImportWeaponSkills(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("TEST_WS", "Test Weapon Source")
|
||||
weaponSkill := models.WeaponSkill{
|
||||
Skill: models.Skill{
|
||||
Name: "Langschwert",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Langschwert Waffenfertigkeiten",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 50,
|
||||
Initialwert: 10,
|
||||
BasisWert: 5,
|
||||
Bonuseigenschaft: "St",
|
||||
Improvable: true,
|
||||
InnateSkill: false,
|
||||
Category: "Waffen",
|
||||
Difficulty: "normal",
|
||||
},
|
||||
}
|
||||
database.DB.Create(&weaponSkill)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err := ExportWeaponSkills(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportWeaponSkills failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "weapon_skills.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
database.DB.Unscoped().Delete(&weaponSkill)
|
||||
|
||||
err = ImportWeaponSkills(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportWeaponSkills failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.WeaponSkill
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "Langschwert", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Weapon skill not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
assert.Equal(t, "Langschwert Waffenfertigkeiten", imported.Beschreibung)
|
||||
assert.Equal(t, 10, imported.Initialwert)
|
||||
assert.Equal(t, 5, imported.BasisWert)
|
||||
}
|
||||
|
||||
func TestExportImportEquipment(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("TEST_EQ", "Test Equipment Source")
|
||||
equipment := models.Equipment{
|
||||
Name: "Seil",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "10m langes Hanfseil",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 75,
|
||||
Gewicht: 2.5,
|
||||
Wert: 15.0,
|
||||
PersonalItem: false,
|
||||
}
|
||||
database.DB.Create(&equipment)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err := ExportEquipment(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportEquipment failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "equipment.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
equipment.Wert = 10.0
|
||||
database.DB.Save(&equipment)
|
||||
|
||||
err = ImportEquipment(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportEquipment failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.Equipment
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "Seil", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Equipment not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
assert.Equal(t, 15.0, imported.Wert)
|
||||
assert.Equal(t, 2.5, imported.Gewicht)
|
||||
}
|
||||
|
||||
func TestExportImportWeapons(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("TEST_WP", "Test Weapon Source")
|
||||
weapon := models.Weapon{
|
||||
Equipment: models.Equipment{
|
||||
Name: "Kurzschwert",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Einhändiges Kurzschwert",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 80,
|
||||
Gewicht: 1.5,
|
||||
Wert: 50.0,
|
||||
PersonalItem: false,
|
||||
},
|
||||
SkillRequired: "Langschwert",
|
||||
Damage: "1W6+1",
|
||||
RangeNear: 0,
|
||||
RangeMiddle: 0,
|
||||
RangeFar: 0,
|
||||
}
|
||||
database.DB.Create(&weapon)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err := ExportWeapons(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportWeapons failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "weapons.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
weapon.Damage = "1W6"
|
||||
database.DB.Save(&weapon)
|
||||
|
||||
err = ImportWeapons(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportWeapons failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.Weapon
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "Kurzschwert", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Weapon not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
assert.Equal(t, "1W6+1", imported.Damage)
|
||||
assert.Equal(t, "Langschwert", imported.SkillRequired)
|
||||
}
|
||||
|
||||
func TestExportImportContainers(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("TEST_CT", "Test Container Source")
|
||||
container := models.Container{
|
||||
Equipment: models.Equipment{
|
||||
Name: "Rucksack",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Großer Lederrucksack",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 85,
|
||||
Gewicht: 1.0,
|
||||
Wert: 20.0,
|
||||
PersonalItem: false,
|
||||
},
|
||||
Tragkraft: 30.0,
|
||||
Volumen: 50.0,
|
||||
}
|
||||
database.DB.Create(&container)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err := ExportContainers(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportContainers failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "containers.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
container.Tragkraft = 25.0
|
||||
database.DB.Save(&container)
|
||||
|
||||
err = ImportContainers(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportContainers failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.Container
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "Rucksack", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Container not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
assert.Equal(t, 30.0, imported.Tragkraft)
|
||||
assert.Equal(t, 50.0, imported.Volumen)
|
||||
}
|
||||
|
||||
func TestExportImportTransportation(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("TEST_TR", "Test Transport Source")
|
||||
transportation := models.Transportation{
|
||||
Container: models.Container{
|
||||
Equipment: models.Equipment{
|
||||
Name: "Pferdewagen",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Zweirädriger Wagen",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 90,
|
||||
Gewicht: 100.0,
|
||||
Wert: 200.0,
|
||||
PersonalItem: false,
|
||||
},
|
||||
Tragkraft: 500.0,
|
||||
Volumen: 1000.0,
|
||||
},
|
||||
}
|
||||
database.DB.Create(&transportation)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err := ExportTransportation(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportTransportation failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "transportation.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
transportation.Tragkraft = 450.0
|
||||
database.DB.Save(&transportation)
|
||||
|
||||
err = ImportTransportation(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportTransportation failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.Transportation
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "Pferdewagen", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Transportation not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
assert.Equal(t, 500.0, imported.Tragkraft)
|
||||
assert.Equal(t, 1000.0, imported.Volumen)
|
||||
}
|
||||
|
||||
func TestExportImportBelieves(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
source := getOrCreateSource("TEST_BL", "Test Believe Source")
|
||||
believe := models.Believe{
|
||||
Name: "Kirche des Lichts",
|
||||
GameSystem: "midgard",
|
||||
Beschreibung: "Hauptreligion in Valian",
|
||||
SourceID: source.ID,
|
||||
PageNumber: 95,
|
||||
}
|
||||
database.DB.Create(&believe)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err := ExportBelieves(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportBelieves failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "believes.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
believe.Beschreibung = "Alte Beschreibung"
|
||||
database.DB.Save(&believe)
|
||||
|
||||
err = ImportBelieves(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportBelieves failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.Believe
|
||||
result := database.DB.Where("name = ? AND game_system = ?", "Kirche des Lichts", "midgard").First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("Believe not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
assert.Equal(t, "Hauptreligion in Valian", imported.Beschreibung)
|
||||
assert.Equal(t, 95, imported.PageNumber)
|
||||
}
|
||||
|
||||
func TestExportImportSkillImprovementCosts(t *testing.T) {
|
||||
setupTestEnvironment(t)
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create dependencies that already exist in test DB
|
||||
// Use existing skill, category, difficulty from test database
|
||||
var skill models.Skill
|
||||
if err := database.DB.Where("name = ?", "Abrichten").First(&skill).Error; err != nil {
|
||||
t.Skip("Test skill not found in database, skipping test")
|
||||
}
|
||||
|
||||
var category models.SkillCategory
|
||||
if err := database.DB.First(&category).Error; err != nil {
|
||||
t.Skip("No skill category found in database, skipping test")
|
||||
}
|
||||
|
||||
var difficulty models.SkillDifficulty
|
||||
if err := database.DB.First(&difficulty).Error; err != nil {
|
||||
t.Skip("No skill difficulty found in database, skipping test")
|
||||
}
|
||||
|
||||
// Find or create SkillCategoryDifficulty
|
||||
var scd models.SkillCategoryDifficulty
|
||||
err := database.DB.Where("skill_id = ? AND skill_category_id = ? AND skill_difficulty_id = ?",
|
||||
skill.ID, category.ID, difficulty.ID).First(&scd).Error
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
scd = models.SkillCategoryDifficulty{
|
||||
SkillID: skill.ID,
|
||||
SkillCategoryID: category.ID,
|
||||
SkillDifficultyID: difficulty.ID,
|
||||
LearnCost: 10,
|
||||
SCategory: category.Name,
|
||||
SDifficulty: difficulty.Name,
|
||||
}
|
||||
database.DB.Create(&scd)
|
||||
} else if err != nil {
|
||||
t.Fatalf("Failed to query SkillCategoryDifficulty: %v", err)
|
||||
}
|
||||
|
||||
// Create SkillImprovementCost
|
||||
improvementCost := models.SkillImprovementCost{
|
||||
SkillCategoryDifficultyID: scd.ID,
|
||||
CurrentLevel: 15, // Use unique level to avoid conflicts
|
||||
TERequired: 5,
|
||||
}
|
||||
database.DB.Create(&improvementCost)
|
||||
|
||||
// Export
|
||||
tempDir := t.TempDir()
|
||||
err = ExportSkillImprovementCosts(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ExportSkillImprovementCosts failed: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(tempDir, "skill_improvement_costs.json")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
t.Fatalf("Export file not created: %s", filename)
|
||||
}
|
||||
|
||||
// Modify the record
|
||||
improvementCost.TERequired = 7
|
||||
database.DB.Save(&improvementCost)
|
||||
|
||||
// Import should restore original value
|
||||
err = ImportSkillImprovementCosts(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ImportSkillImprovementCosts failed: %v", err)
|
||||
}
|
||||
|
||||
var imported models.SkillImprovementCost
|
||||
result := database.DB.Where("skill_category_difficulty_id = ? AND current_level = ?", scd.ID, 15).First(&imported)
|
||||
if result.Error != nil {
|
||||
t.Fatalf("SkillImprovementCost not found after import: %v", result.Error)
|
||||
}
|
||||
|
||||
// Should be restored to original value from export
|
||||
assert.Equal(t, 5, imported.TERequired)
|
||||
assert.Equal(t, 15, imported.CurrentLevel)
|
||||
}
|
||||
@@ -128,51 +128,6 @@ type Believe struct {
|
||||
PageNumber int `json:"page_number,omitempty"` // Seitenzahl im Quellenbuch
|
||||
}
|
||||
|
||||
/*
|
||||
func (object *LookupList) Create() error {
|
||||
gameSystem := "midgard"
|
||||
object.GameSystem = gameSystem
|
||||
err := database.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// Save the main character record
|
||||
if err := tx.Create(&object).Error; err != nil {
|
||||
return fmt.Errorf("failed to save Lookup: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (object *LookupList) First(value string) error {
|
||||
gameSystem := "midgard"
|
||||
err := database.DB.First(&object, "game_system=? AND name!='Placeholder' AND name = ?", gameSystem, value).Error
|
||||
if err != nil {
|
||||
// zauber found
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (object *LookupList) FirstId(value uint) error {
|
||||
gameSystem := "midgard"
|
||||
err := database.DB.First(&object, "game_system=? AND name!='Placeholder' AND id = ?", gameSystem, value).Error
|
||||
if err != nil {
|
||||
// zauber found
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (object *LookupList) Save() error {
|
||||
err := database.DB.Save(&object).Error
|
||||
if err != nil {
|
||||
// zauber found
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (object *Skill) TableName() string {
|
||||
dbPrefix := "gsm"
|
||||
return dbPrefix + "_" + "skills"
|
||||
|
||||
Reference in New Issue
Block a user