fix(migration): enable insert from structure work recursively

This commit is contained in:
kolaente 2023-01-13 18:33:20 +01:00
parent c3a099d71b
commit 2260688c3b
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
2 changed files with 243 additions and 206 deletions

View File

@ -50,74 +50,107 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
log.Debugf("[creating structure] Creating %d projects", len(str))
labels := make(map[string]*models.Label)
archivedProjects := []int64{}
// Create all projects
for _, p := range str {
p.ID = 0
err = p.Create(s, user)
err = createProjectWithChildren(s, p, 0, &archivedProjects, labels, user)
if err != nil {
return
return err
}
}
log.Debugf("[creating structure] Created project %d", p.ID)
log.Debugf("[creating structure] Creating %d projects", len(p.ChildProjects))
if len(archivedProjects) > 0 {
_, err = s.
Cols("is_archived").
In("id", archivedProjects).
Update(&models.Project{IsArchived: true})
if err != nil {
return err
}
}
log.Debugf("[creating structure] Done inserting new task structure")
return nil
}
func createProjectWithChildren(s *xorm.Session, project *models.ProjectWithTasksAndBuckets, parentProjectID int64, archivedProjectIDs *[]int64, labels map[string]*models.Label, user *user.User) (err error) {
err = createProjectWithEverything(s, project, parentProjectID, archivedProjectIDs, labels, user)
if err != nil {
return err
}
log.Debugf("[creating structure] Created project %d", project.ID)
if len(project.ChildProjects) > 0 {
log.Debugf("[creating structure] Creating %d projects", len(project.ChildProjects))
// Create all projects
for _, l := range p.ChildProjects {
// The tasks and bucket slices are going to be reset during the creation of the project so we rescue it here
for _, cp := range project.ChildProjects {
err = createProjectWithChildren(s, cp, project.ID, archivedProjectIDs, labels, user)
if err != nil {
return err
}
}
}
return
}
func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTasksAndBuckets, parentProjectID int64, archivedProjects *[]int64, labels map[string]*models.Label, user *user.User) (err error) {
// The tasks and bucket slices are going to be reset during the creation of the project, so we rescue it here
// to be able to still loop over them aftere the project was created.
tasks := l.Tasks
originalBuckets := l.Buckets
originalBackgroundInformation := l.BackgroundInformation
tasks := project.Tasks
originalBuckets := project.Buckets
originalBackgroundInformation := project.BackgroundInformation
needsDefaultBucket := false
// Saving the archived status to archive the project again after creating it
var wasArchived bool
if l.IsArchived {
if project.IsArchived {
wasArchived = true
l.IsArchived = false
project.IsArchived = false
}
l.ParentProjectID = p.ID
l.ID = 0
err = l.Create(s, user)
project.ParentProjectID = parentProjectID
project.ID = 0
err = project.Create(s, user)
if err != nil {
return
}
if wasArchived {
archivedProjects = append(archivedProjects, l.ID)
*archivedProjects = append(*archivedProjects, project.ID)
}
log.Debugf("[creating structure] Created project %d", l.ID)
log.Debugf("[creating structure] Created project %d", project.ID)
bf, is := originalBackgroundInformation.(*bytes.Buffer)
if is {
backgroundFile := bytes.NewReader(bf.Bytes())
log.Debugf("[creating structure] Creating a background file for project %d", l.ID)
log.Debugf("[creating structure] Creating a background file for project %d", project.ID)
err = handler.SaveBackgroundFile(s, user, &l.Project, backgroundFile, "", uint64(backgroundFile.Len()))
err = handler.SaveBackgroundFile(s, user, &project.Project, backgroundFile, "", uint64(backgroundFile.Len()))
if err != nil {
return err
}
log.Debugf("[creating structure] Created a background file for project %d", l.ID)
log.Debugf("[creating structure] Created a background file for project %d", project.ID)
}
// Create all buckets
buckets := make(map[int64]*models.Bucket) // old bucket id is the key
if len(l.Buckets) > 0 {
log.Debugf("[creating structure] Creating %d buckets", len(l.Buckets))
if len(project.Buckets) > 0 {
log.Debugf("[creating structure] Creating %d buckets", len(project.Buckets))
}
for _, bucket := range originalBuckets {
oldID := bucket.ID
bucket.ID = 0 // We want a new id
bucket.ProjectID = l.ID
bucket.ProjectID = project.ID
err = bucket.Create(s, user)
if err != nil {
return
@ -145,7 +178,7 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
for _, t := range tasks {
setBucketOrDefault(&t.Task)
t.ProjectID = l.ID
t.ProjectID = project.ID
err = t.Create(s, user)
if err != nil {
return
@ -238,6 +271,7 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
for _, comment := range t.Comments {
comment.TaskID = t.ID
comment.ID = 0
err = comment.Create(s, user)
if err != nil {
return
@ -248,34 +282,27 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
// All tasks brought their own bucket with them, therefore the newly created default bucket is just extra space
if !needsDefaultBucket {
b := &models.Bucket{ProjectID: l.ID}
b := &models.Bucket{ProjectID: project.ID}
bucketsIn, _, _, err := b.ReadAll(s, user, "", 1, 1)
if err != nil {
return err
}
buckets := bucketsIn.([]*models.Bucket)
err = buckets[0].Delete(s, user)
var newBacklogBucket *models.Bucket
for _, b := range buckets {
if b.Title == "Backlog" {
newBacklogBucket = b
break
}
}
err = newBacklogBucket.Delete(s, user)
if err != nil && !models.IsErrCannotRemoveLastBucket(err) {
return err
}
}
l.Tasks = tasks
l.Buckets = originalBuckets
}
}
if len(archivedProjects) > 0 {
_, err = s.
Cols("is_archived").
In("id", archivedProjects).
Update(&models.Project{IsArchived: true})
if err != nil {
return err
}
}
log.Debugf("[creating structure] Done inserting new task structure")
project.Tasks = tasks
project.Buckets = originalBuckets
return nil
}

View File

@ -38,6 +38,13 @@ func TestInsertFromStructure(t *testing.T) {
Title: "Test1",
Description: "Lorem Ipsum",
},
Tasks: []*models.TaskWithComments{
{
Task: models.Task{
Title: "Task on parent",
},
},
},
ChildProjects: []*models.ProjectWithTasksAndBuckets{
{
Project: models.Project{
@ -141,6 +148,9 @@ func TestInsertFromStructure(t *testing.T) {
"title": testStructure[0].ChildProjects[0].Tasks[6].Title,
"bucket_id": 1111, // No task with that bucket should exist
})
db.AssertExists(t, "tasks", map[string]interface{}{
"title": testStructure[0].Tasks[0].Title,
}, false)
assert.NotEqual(t, 0, testStructure[0].ChildProjects[0].Tasks[0].BucketID) // Should get the default bucket
assert.NotEqual(t, 0, testStructure[0].ChildProjects[0].Tasks[6].BucketID) // Should get the default bucket
})