func (r *GormWorkItemRepository) Reorder(ctx context.Context, direction DirectionType, targetID *string, wi WorkItem, modifierID uuid.UUID) (*WorkItem, error) {
	var order float64
	res := WorkItemStorage{}

	id, err := strconv.ParseUint(wi.ID, 10, 64)
	if err != nil || id == 0 {
		return nil, errors.NewNotFoundError("work item", wi.ID)
	}

	tx := r.db.First(&res, id)
	if tx.RecordNotFound() {
		return nil, errors.NewNotFoundError("work item", wi.ID)
	}
	if err := tx.Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	if res.Version != wi.Version {
		return nil, errors.NewVersionConflictError("version conflict")
	}

	wiType, err := r.witr.LoadTypeFromDB(ctx, wi.Type)
	if err != nil {
		return nil, errors.NewBadParameterError("Type", wi.Type)
	}

	switch direction {
	case DirectionBelow:
		// if direction == "below", place the reorder item **below** the workitem having id equal to targetID
		aboveItemOrder, err := r.FindFirstItem(*targetID)
		if aboveItemOrder == nil || err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		belowItemId, belowItemOrder, err := r.FindSecondItem(aboveItemOrder, DirectionAbove)
		if err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		if *belowItemId == "0" {
			// Item is placed at last position
			belowItemOrder := float64(0)
			order = r.CalculateOrder(aboveItemOrder, &belowItemOrder)
		} else if *belowItemId == strconv.FormatUint(res.ID, 10) {
			// When same reorder request is made again
			order = wi.Fields[SystemOrder].(float64)
		} else {
			order = r.CalculateOrder(aboveItemOrder, belowItemOrder)
		}
	case DirectionAbove:
		// if direction == "above", place the reorder item **above** the workitem having id equal to targetID
		belowItemOrder, _ := r.FindFirstItem(*targetID)
		if belowItemOrder == nil || err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		aboveItemId, aboveItemOrder, err := r.FindSecondItem(belowItemOrder, DirectionBelow)
		if err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		if *aboveItemId == "0" {
			// Item is placed at first position
			order = *belowItemOrder + float64(orderValue)
		} else if *aboveItemId == strconv.FormatUint(res.ID, 10) {
			// When same reorder request is made again
			order = wi.Fields[SystemOrder].(float64)
		} else {
			order = r.CalculateOrder(aboveItemOrder, belowItemOrder)
		}
	case DirectionTop:
		// if direction == "top", place the reorder item at the topmost position. Now, the reorder item has the highest order in the whole list.
		res, err := r.LoadTopWorkitem(ctx)
		if err != nil {
			return nil, errs.Wrapf(err, "Failed to reorder")
		}
		if wi.ID == res.ID {
			// When same reorder request is made again
			order = wi.Fields[SystemOrder].(float64)
		} else {
			topItemOrder := res.Fields[SystemOrder].(float64)
			order = topItemOrder + orderValue
		}
	case DirectionBottom:
		// if direction == "bottom", place the reorder item at the bottom most position. Now, the reorder item has the lowest order in the whole list
		res, err := r.LoadBottomWorkitem(ctx)
		if err != nil {
			return nil, errs.Wrapf(err, "Failed to reorder")
		}
		if wi.ID == res.ID {
			// When same reorder request is made again
			order = wi.Fields[SystemOrder].(float64)
		} else {
			bottomItemOrder := res.Fields[SystemOrder].(float64)
			order = bottomItemOrder / 2
		}
	default:
		return &wi, nil
	}
	res.Version = res.Version + 1
	res.Type = wi.Type
	res.Fields = Fields{}

	res.ExecutionOrder = order

	for fieldName, fieldDef := range wiType.Fields {
		if fieldName == SystemCreatedAt || fieldName == SystemUpdatedAt || fieldName == SystemOrder {
			continue
		}
		fieldValue := wi.Fields[fieldName]
		var err error
		res.Fields[fieldName], err = fieldDef.ConvertToModel(fieldName, fieldValue)
		if err != nil {
			return nil, errors.NewBadParameterError(fieldName, fieldValue)
		}
	}
	tx = tx.Where("Version = ?", wi.Version).Save(&res)
	if err := tx.Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	if tx.RowsAffected == 0 {
		return nil, errors.NewVersionConflictError("version conflict")
	}
	// store a revision of the modified work item
	err = r.wirr.Create(context.Background(), modifierID, RevisionTypeUpdate, res)
	if err != nil {
		return nil, err
	}
	return ConvertWorkItemStorageToModel(wiType, &res)
}
// Reorder places the to-be-reordered workitem above the input workitem.
// The order of workitems are spaced by a factor of 1000.
// The new order of workitem := (order of previousitem + order of nextitem)/2
// Version must be the same as the one int the stored version
Reorder places the to-be-reordered workitem above the input workitem.
The order of workitems are spaced by a factor of 1000.
The new order of workitem := (order of previousitem + order of nextitem)/2
Version must be the same as the one int the stored version
// Reorder places the to - be - reordered workitem above the input workitem . // The order of workitems are spaced by a factor of 1000 . // The new order of workitem : = ( order of previousitem + order of nextitem ) / 2 // Version must be the same as the one int the stored version
func (r *GormWorkItemRepository) Reorder(ctx context.Context, direction DirectionType, targetID *string, wi WorkItem, modifierID uuid.UUID) (*WorkItem, error) {
	var order float64
	res := WorkItemStorage{}
	id, err := strconv.ParseUint(wi.ID, 10, 64)
	if err != nil || id == 0 {
		return nil, errors.NewNotFoundError("work item", wi.ID)
	}
	tx := r.db.First(&res, id)
	if tx.RecordNotFound() {
		return nil, errors.NewNotFoundError("work item", wi.ID)
	}
	if err := tx.Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	if res.Version != wi.Version {
		return nil, errors.NewVersionConflictError("version conflict")
	}
	wiType, err := r.witr.LoadTypeFromDB(ctx, wi.Type)
	if err != nil {
		return nil, errors.NewBadParameterError("Type", wi.Type)
	}
	switch direction {
	case DirectionBelow:
		aboveItemOrder, err := r.FindFirstItem(*targetID)
		if aboveItemOrder == nil || err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		belowItemId, belowItemOrder, err := r.FindSecondItem(aboveItemOrder, DirectionAbove)
		if err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		if *belowItemId == "0" {
			belowItemOrder := float64(0)
			order = r.CalculateOrder(aboveItemOrder, &belowItemOrder)
		} else if *belowItemId == strconv.FormatUint(res.ID, 10) {
			order = wi.Fields[SystemOrder].(float64)
		} else {
			order = r.CalculateOrder(aboveItemOrder, belowItemOrder)
		}
	case DirectionAbove:
		belowItemOrder, _ := r.FindFirstItem(*targetID)
		if belowItemOrder == nil || err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		aboveItemId, aboveItemOrder, err := r.FindSecondItem(belowItemOrder, DirectionBelow)
		if err != nil {
			return nil, errors.NewNotFoundError("work item", *targetID)
		}
		if *aboveItemId == "0" {
			order = *belowItemOrder + float64(orderValue)
		} else if *aboveItemId == strconv.FormatUint(res.ID, 10) {
			order = wi.Fields[SystemOrder].(float64)
		} else {
			order = r.CalculateOrder(aboveItemOrder, belowItemOrder)
		}
	case DirectionTop:
		res, err := r.LoadTopWorkitem(ctx)
		if err != nil {
			return nil, errs.Wrapf(err, "Failed to reorder")
		}
		if wi.ID == res.ID {
			order = wi.Fields[SystemOrder].(float64)
		} else {
			topItemOrder := res.Fields[SystemOrder].(float64)
			order = topItemOrder + orderValue
		}
	case DirectionBottom:
		res, err := r.LoadBottomWorkitem(ctx)
		if err != nil {
			return nil, errs.Wrapf(err, "Failed to reorder")
		}
		if wi.ID == res.ID {
			order = wi.Fields[SystemOrder].(float64)
		} else {
			bottomItemOrder := res.Fields[SystemOrder].(float64)
			order = bottomItemOrder / 2
		}
	default:
		return &wi, nil
	}
	res.Version = res.Version + 1
	res.Type = wi.Type
	res.Fields = Fields{}
	res.ExecutionOrder = order
	for fieldName, fieldDef := range wiType.Fields {
		if fieldName == SystemCreatedAt || fieldName == SystemUpdatedAt || fieldName == SystemOrder {
			continue
		}
		fieldValue := wi.Fields[fieldName]
		var err error
		res.Fields[fieldName], err = fieldDef.ConvertToModel(fieldName, fieldValue)
		if err != nil {
			return nil, errors.NewBadParameterError(fieldName, fieldValue)
		}
	}
	tx = tx.Where("Version = ?", wi.Version).Save(&res)
	if err := tx.Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	if tx.RowsAffected == 0 {
		return nil, errors.NewVersionConflictError("version conflict")
	}
	err = r.wirr.Create(context.Background(), modifierID, RevisionTypeUpdate, res)
	if err != nil {
		return nil, err
	}
	return ConvertWorkItemStorageToModel(wiType, &res)
}
func ( r * GormWorkItemRepository ) Reorder ( ctx context . Context , direction DirectionType , targetID * string , wi WorkItem , modifierID uuid . UUID ) ( * WorkItem , error ) { var order float64 res := WorkItemStorage { } id , err := strconv . ParseUint ( wi . ID , 10 , 64 ) if err != nil || id == 0 { return nil , errors . NewNotFoundError ( " " , wi . ID ) } tx := r . db . First ( & res , id ) if tx . RecordNotFound ( ) { return nil , errors . NewNotFoundError ( " " , wi . ID ) } if err := tx . Error ; err != nil { return nil , errors . NewInternalError ( err . Error ( ) ) } if res . Version != wi . Version { return nil , errors . NewVersionConflictError ( " " ) } wiType , err := r . witr . LoadTypeFromDB ( ctx , wi . Type ) if err != nil { return nil , errors . NewBadParameterError ( " " , wi . Type ) } switch direction { case DirectionBelow : aboveItemOrder , err := r . FindFirstItem ( * targetID ) if aboveItemOrder == nil || err != nil { return nil , errors . NewNotFoundError ( " " , * targetID ) } belowItemId , belowItemOrder , err := r . FindSecondItem ( aboveItemOrder , DirectionAbove ) if err != nil { return nil , errors . NewNotFoundError ( " " , * targetID ) } if * belowItemId == " " { belowItemOrder := float64 ( 0 ) order = r . CalculateOrder ( aboveItemOrder , & belowItemOrder ) } else if * belowItemId == strconv . FormatUint ( res . ID , 10 ) { order = wi . Fields [ SystemOrder ] . ( float64 ) } else { order = r . CalculateOrder ( aboveItemOrder , belowItemOrder ) } case DirectionAbove : belowItemOrder , _ := r . FindFirstItem ( * targetID ) if belowItemOrder == nil || err != nil { return nil , errors . NewNotFoundError ( " " , * targetID ) } aboveItemId , aboveItemOrder , err := r . FindSecondItem ( belowItemOrder , DirectionBelow ) if err != nil { return nil , errors . NewNotFoundError ( " " , * targetID ) } if * aboveItemId == " " { order = * belowItemOrder + float64 ( orderValue ) } else if * aboveItemId == strconv . FormatUint ( res . ID , 10 ) { order = wi . Fields [ SystemOrder ] . ( float64 ) } else { order = r . CalculateOrder ( aboveItemOrder , belowItemOrder ) } case DirectionTop : res , err := r . LoadTopWorkitem ( ctx ) if err != nil { return nil , errs . Wrapf ( err , " " ) } if wi . ID == res . ID { order = wi . Fields [ SystemOrder ] . ( float64 ) } else { topItemOrder := res . Fields [ SystemOrder ] . ( float64 ) order = topItemOrder + orderValue } case DirectionBottom : res , err := r . LoadBottomWorkitem ( ctx ) if err != nil { return nil , errs . Wrapf ( err , " " ) } if wi . ID == res . ID { order = wi . Fields [ SystemOrder ] . ( float64 ) } else { bottomItemOrder := res . Fields [ SystemOrder ] . ( float64 ) order = bottomItemOrder / 2 } default : return & wi , nil } res . Version = res . Version + 1 res . Type = wi . Type res . Fields = Fields { } res . ExecutionOrder = order for fieldName , fieldDef := range wiType . Fields { if fieldName == SystemCreatedAt || fieldName == SystemUpdatedAt || fieldName == SystemOrder { continue } fieldValue := wi . Fields [ fieldName ] var err error res . Fields [ fieldName ] , err = fieldDef . ConvertToModel ( fieldName , fieldValue ) if err != nil { return nil , errors . NewBadParameterError ( fieldName , fieldValue ) } } tx = tx . Where ( " " , wi . Version ) . Save ( & res ) if err := tx . Error ; err != nil { return nil , errors . NewInternalError ( err . Error ( ) ) } if tx . RowsAffected == 0 { return nil , errors . NewVersionConflictError ( " " ) } err = r . wirr . Create ( context . Background ( ) , modifierID , RevisionTypeUpdate , res ) if err != nil { return nil , err } return ConvertWorkItemStorageToModel ( wiType , & res ) }
Reorder places the to-be-reordered workitem above the input workitem.
Reorder places the to - be - reordered workitem above the input workitem .
// if direction == "below", place the reorder item **below** the workitem having id equal to targetID // Item is placed at last position // When same reorder request is made again // if direction == "above", place the reorder item **above** the workitem having id equal to targetID // Item is placed at first position // When same reorder request is made again // if direction == "top", place the reorder item at the topmost position. Now, the reorder item has the highest order in the whole list. // When same reorder request is made again // if direction == "bottom", place the reorder item at the bottom most position. Now, the reorder item has the lowest order in the whole list // When same reorder request is made again // store a revision of the modified work item