560 lines
18 KiB
Go
560 lines
18 KiB
Go
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
package answer
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/apache/answer/internal/base/constant"
|
|
"github.com/apache/answer/internal/base/data"
|
|
"github.com/apache/answer/internal/base/handler"
|
|
"github.com/apache/answer/internal/base/pager"
|
|
"github.com/apache/answer/internal/base/reason"
|
|
"github.com/apache/answer/internal/entity"
|
|
"github.com/apache/answer/internal/schema"
|
|
"github.com/apache/answer/internal/service/activity_common"
|
|
answercommon "github.com/apache/answer/internal/service/answer_common"
|
|
"github.com/apache/answer/internal/service/rank"
|
|
"github.com/apache/answer/internal/service/unique"
|
|
"github.com/apache/answer/pkg/uid"
|
|
"github.com/apache/answer/plugin"
|
|
"github.com/segmentfault/pacman/errors"
|
|
"github.com/segmentfault/pacman/log"
|
|
)
|
|
|
|
// answerRepo answer repository
|
|
type answerRepo struct {
|
|
data *data.Data
|
|
uniqueIDRepo unique.UniqueIDRepo
|
|
userRankRepo rank.UserRankRepo
|
|
activityRepo activity_common.ActivityRepo
|
|
}
|
|
|
|
// NewAnswerRepo new repository
|
|
func NewAnswerRepo(
|
|
data *data.Data,
|
|
uniqueIDRepo unique.UniqueIDRepo,
|
|
userRankRepo rank.UserRankRepo,
|
|
activityRepo activity_common.ActivityRepo,
|
|
) answercommon.AnswerRepo {
|
|
return &answerRepo{
|
|
data: data,
|
|
uniqueIDRepo: uniqueIDRepo,
|
|
userRankRepo: userRankRepo,
|
|
activityRepo: activityRepo,
|
|
}
|
|
}
|
|
|
|
// AddAnswer add answer
|
|
func (ar *answerRepo) AddAnswer(ctx context.Context, answer *entity.Answer) (err error) {
|
|
answer.QuestionID = uid.DeShortID(answer.QuestionID)
|
|
ID, err := ar.uniqueIDRepo.GenUniqueIDStr(ctx, answer.TableName())
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
answer.ID = ID
|
|
_, err = ar.data.DB.Context(ctx).Insert(answer)
|
|
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
answer.ID = uid.EnShortID(answer.ID)
|
|
answer.QuestionID = uid.EnShortID(answer.QuestionID)
|
|
}
|
|
_ = ar.updateSearch(ctx, answer.ID)
|
|
return nil
|
|
}
|
|
|
|
// RemoveAnswer delete answer
|
|
func (ar *answerRepo) RemoveAnswer(ctx context.Context, answerID string) (err error) {
|
|
answerID = uid.DeShortID(answerID)
|
|
_, err = ar.data.DB.Context(ctx).ID(answerID).Cols("status").Update(&entity.Answer{
|
|
Status: entity.AnswerStatusDeleted,
|
|
})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
_ = ar.updateSearch(ctx, answerID)
|
|
return nil
|
|
}
|
|
|
|
// RecoverAnswer recover answer
|
|
func (ar *answerRepo) RecoverAnswer(ctx context.Context, answerID string) (err error) {
|
|
answerID = uid.DeShortID(answerID)
|
|
_, err = ar.data.DB.Context(ctx).ID(answerID).Cols("status").Update(&entity.Answer{
|
|
Status: entity.AnswerStatusAvailable,
|
|
})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
_ = ar.updateSearch(ctx, answerID)
|
|
return nil
|
|
}
|
|
|
|
// RemoveAllUserAnswer remove all user answer
|
|
func (ar *answerRepo) RemoveAllUserAnswer(ctx context.Context, userID string) (err error) {
|
|
// find all answer id that need to be deleted
|
|
answerIDs := make([]string, 0)
|
|
session := ar.data.DB.Context(ctx).Where("user_id = ?", userID)
|
|
session.Where("status != ?", entity.AnswerStatusDeleted)
|
|
err = session.Select("id").Table("answer").Find(&answerIDs)
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if len(answerIDs) == 0 {
|
|
return nil
|
|
}
|
|
|
|
log.Infof("find %d answers need to be deleted for user %s", len(answerIDs), userID)
|
|
|
|
// delete all question
|
|
session = ar.data.DB.Context(ctx).Where("user_id = ?", userID)
|
|
session.Where("status != ?", entity.AnswerStatusDeleted)
|
|
_, err = session.Cols("status", "updated_at").Update(&entity.Answer{
|
|
UpdatedAt: time.Now(),
|
|
Status: entity.AnswerStatusDeleted,
|
|
})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
|
|
// update search content
|
|
for _, id := range answerIDs {
|
|
_ = ar.updateSearch(ctx, id)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UpdateAnswer update answer
|
|
func (ar *answerRepo) UpdateAnswer(ctx context.Context, answer *entity.Answer, cols []string) (err error) {
|
|
answer.ID = uid.DeShortID(answer.ID)
|
|
answer.QuestionID = uid.DeShortID(answer.QuestionID)
|
|
_, err = ar.data.DB.Context(ctx).ID(answer.ID).Cols(cols...).Update(answer)
|
|
if err != nil {
|
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
_ = ar.updateSearch(ctx, answer.ID)
|
|
return err
|
|
}
|
|
|
|
func (ar *answerRepo) UpdateAnswerStatus(ctx context.Context, answerID string, status int) (err error) {
|
|
answerID = uid.DeShortID(answerID)
|
|
_, err = ar.data.DB.Context(ctx).ID(answerID).Cols("status").Update(&entity.Answer{Status: status})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
_ = ar.updateSearch(ctx, answerID)
|
|
return
|
|
}
|
|
|
|
// GetAnswer get answer one
|
|
func (ar *answerRepo) GetAnswer(ctx context.Context, id string) (
|
|
answer *entity.Answer, exist bool, err error,
|
|
) {
|
|
id = uid.DeShortID(id)
|
|
answer = &entity.Answer{}
|
|
exist, err = ar.data.DB.Context(ctx).ID(id).Get(answer)
|
|
if err != nil {
|
|
return nil, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
answer.ID = uid.EnShortID(answer.ID)
|
|
answer.QuestionID = uid.EnShortID(answer.QuestionID)
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetAnswerCount count answer
|
|
func (ar *answerRepo) GetAnswerCount(ctx context.Context) (count int64, err error) {
|
|
var resp = new(entity.Answer)
|
|
count, err = ar.data.DB.Context(ctx).Where("status = ?", entity.AnswerStatusAvailable).Count(resp)
|
|
if err != nil {
|
|
return count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetAnswerList get answer list all
|
|
func (ar *answerRepo) GetAnswerList(ctx context.Context, answer *entity.Answer) (answerList []*entity.Answer, err error) {
|
|
answerList = make([]*entity.Answer, 0)
|
|
if len(answer.ID) > 0 {
|
|
answer.ID = uid.DeShortID(answer.ID)
|
|
}
|
|
if len(answer.QuestionID) > 0 {
|
|
answer.QuestionID = uid.DeShortID(answer.QuestionID)
|
|
}
|
|
err = ar.data.DB.Context(ctx).Find(&answerList, answer)
|
|
if err != nil {
|
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
for _, item := range answerList {
|
|
item.ID = uid.EnShortID(item.ID)
|
|
item.QuestionID = uid.EnShortID(item.QuestionID)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetAnswerPage get answer page
|
|
func (ar *answerRepo) GetAnswerPage(ctx context.Context, page, pageSize int, answer *entity.Answer) (answerList []*entity.Answer, total int64, err error) {
|
|
answer.ID = uid.DeShortID(answer.ID)
|
|
answer.QuestionID = uid.DeShortID(answer.QuestionID)
|
|
answerList = make([]*entity.Answer, 0)
|
|
total, err = pager.Help(page, pageSize, &answerList, answer, ar.data.DB.Context(ctx))
|
|
if err != nil {
|
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
for _, item := range answerList {
|
|
item.ID = uid.EnShortID(item.ID)
|
|
item.QuestionID = uid.EnShortID(item.QuestionID)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// UpdateAcceptedStatus update all accepted status of this question's answers
|
|
func (ar *answerRepo) UpdateAcceptedStatus(ctx context.Context, acceptedAnswerID string, questionID string) error {
|
|
acceptedAnswerID = uid.DeShortID(acceptedAnswerID)
|
|
questionID = uid.DeShortID(questionID)
|
|
|
|
// update all this question's answer accepted status to false
|
|
_, err := ar.data.DB.Context(ctx).Where("question_id = ?", questionID).Cols("adopted").Update(&entity.Answer{
|
|
Accepted: schema.AnswerAcceptedFailed,
|
|
})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
|
|
// if acceptedAnswerID is not empty, update accepted status to true
|
|
if len(acceptedAnswerID) > 0 && acceptedAnswerID != "0" {
|
|
_, err = ar.data.DB.Context(ctx).Where("id = ?", acceptedAnswerID).Cols("adopted").Update(&entity.Answer{
|
|
Accepted: schema.AnswerAcceptedEnable,
|
|
})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
}
|
|
_ = ar.updateSearch(ctx, acceptedAnswerID)
|
|
return nil
|
|
}
|
|
|
|
// GetByID
|
|
func (ar *answerRepo) GetByID(ctx context.Context, answerID string) (*entity.Answer, bool, error) {
|
|
var resp entity.Answer
|
|
answerID = uid.DeShortID(answerID)
|
|
has, err := ar.data.DB.Context(ctx).ID(answerID).Get(&resp)
|
|
if err != nil {
|
|
return &resp, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
resp.ID = uid.EnShortID(resp.ID)
|
|
resp.QuestionID = uid.EnShortID(resp.QuestionID)
|
|
}
|
|
return &resp, has, nil
|
|
}
|
|
|
|
func (ar *answerRepo) GetByIDs(ctx context.Context, answerIDs ...string) ([]*entity.Answer, error) {
|
|
for idx, answerID := range answerIDs {
|
|
answerIDs[idx] = uid.DeShortID(answerID)
|
|
}
|
|
var resp = make([]*entity.Answer, 0)
|
|
err := ar.data.DB.Context(ctx).In("id", answerIDs).Find(&resp)
|
|
if err != nil {
|
|
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
for _, item := range resp {
|
|
item.ID = uid.EnShortID(item.ID)
|
|
item.QuestionID = uid.EnShortID(item.QuestionID)
|
|
}
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func (ar *answerRepo) GetCountByQuestionID(ctx context.Context, questionID string) (int64, error) {
|
|
questionID = uid.DeShortID(questionID)
|
|
var resp = new(entity.Answer)
|
|
count, err := ar.data.DB.Context(ctx).Where("question_id =? and status = ?", questionID, entity.AnswerStatusAvailable).Count(resp)
|
|
if err != nil {
|
|
return count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (ar *answerRepo) GetCountByUserID(ctx context.Context, userID string) (int64, error) {
|
|
var resp = new(entity.Answer)
|
|
count, err := ar.data.DB.Context(ctx).Where(" user_id = ? and status = ?", userID, entity.AnswerStatusAvailable).Count(resp)
|
|
if err != nil {
|
|
return count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (ar *answerRepo) GetIDsByUserIDAndQuestionID(ctx context.Context, userID string, questionID string) ([]string, error) {
|
|
questionID = uid.DeShortID(questionID)
|
|
var ids []string
|
|
resp := make([]string, 0)
|
|
err := ar.data.DB.Context(ctx).Table(entity.Answer{}.TableName()).Where("question_id =? and user_id = ? and status = ?", questionID, userID, entity.AnswerStatusAvailable).OrderBy("created_at ASC").Cols("id").Find(&ids)
|
|
if err != nil {
|
|
return resp, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
for _, id := range ids {
|
|
resp = append(resp, uid.EnShortID(id))
|
|
}
|
|
} else {
|
|
resp = ids
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// SearchList
|
|
func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearch) ([]*entity.Answer, int64, error) {
|
|
if search.QuestionID != "" {
|
|
search.QuestionID = uid.DeShortID(search.QuestionID)
|
|
}
|
|
search.ID = uid.DeShortID(search.ID)
|
|
var count int64
|
|
var err error
|
|
rows := make([]*entity.Answer, 0)
|
|
if search.Page > 0 {
|
|
search.Page--
|
|
} else {
|
|
search.Page = 0
|
|
}
|
|
if search.PageSize == 0 {
|
|
search.PageSize = constant.DefaultPageSize
|
|
}
|
|
offset := search.Page * search.PageSize
|
|
session := ar.data.DB.Context(ctx)
|
|
|
|
if search.QuestionID != "" {
|
|
session = session.And("question_id = ?", search.QuestionID)
|
|
}
|
|
if len(search.UserID) > 0 {
|
|
session = session.And("user_id = ?", search.UserID)
|
|
}
|
|
switch search.Order {
|
|
case entity.AnswerSearchOrderByTime:
|
|
session = session.OrderBy("created_at desc")
|
|
case entity.AnswerSearchOrderByTimeAsc:
|
|
session = session.OrderBy("created_at asc")
|
|
case entity.AnswerSearchOrderByVote:
|
|
session = session.OrderBy("vote_count desc")
|
|
default:
|
|
session = session.OrderBy("adopted desc,vote_count desc,created_at asc")
|
|
}
|
|
if !search.IncludeDeleted {
|
|
if search.LoginUserID == "" {
|
|
session = session.And("status = ? ", entity.AnswerStatusAvailable)
|
|
} else {
|
|
session = session.And("status = ? OR user_id = ?", entity.AnswerStatusAvailable, search.LoginUserID)
|
|
}
|
|
}
|
|
|
|
session = session.Limit(search.PageSize, offset)
|
|
count, err = session.FindAndCount(&rows)
|
|
if err != nil {
|
|
return rows, count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
for _, item := range rows {
|
|
item.ID = uid.EnShortID(item.ID)
|
|
item.QuestionID = uid.EnShortID(item.QuestionID)
|
|
}
|
|
}
|
|
return rows, count, nil
|
|
}
|
|
|
|
// GetPersonalAnswerPage personal answer page
|
|
func (ar *answerRepo) GetPersonalAnswerPage(ctx context.Context, req *entity.PersonalAnswerPageQueryCond) (
|
|
resp []*entity.Answer, total int64, err error) {
|
|
cond := &entity.Answer{
|
|
UserID: req.UserID,
|
|
}
|
|
session := ar.data.DB.Context(ctx)
|
|
switch req.Order {
|
|
case entity.AnswerSearchOrderByTime:
|
|
session = session.OrderBy("created_at desc")
|
|
case entity.AnswerSearchOrderByTimeAsc:
|
|
session = session.OrderBy("created_at asc")
|
|
case entity.AnswerSearchOrderByVote:
|
|
session = session.OrderBy("vote_count desc")
|
|
default:
|
|
session = session.OrderBy("adopted desc,vote_count desc,created_at asc")
|
|
}
|
|
if req.ShowPending {
|
|
session = session.And("status != ?", entity.AnswerStatusDeleted)
|
|
} else {
|
|
session = session.And("status = ?", entity.AnswerStatusAvailable)
|
|
}
|
|
resp = make([]*entity.Answer, 0)
|
|
total, err = pager.Help(req.Page, req.PageSize, &resp, cond, session)
|
|
if err != nil {
|
|
return nil, 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if handler.GetEnableShortID(ctx) {
|
|
for _, item := range resp {
|
|
item.ID = uid.EnShortID(item.ID)
|
|
item.QuestionID = uid.EnShortID(item.QuestionID)
|
|
}
|
|
}
|
|
return resp, total, nil
|
|
}
|
|
|
|
func (ar *answerRepo) AdminSearchList(ctx context.Context, req *schema.AdminAnswerPageReq) (
|
|
resp []*entity.Answer, total int64, err error) {
|
|
cond := &entity.Answer{}
|
|
session := ar.data.DB.Context(ctx)
|
|
if len(req.QuestionID) == 0 && len(req.AnswerID) == 0 {
|
|
session.Join("INNER", "question", "answer.question_id = question.id")
|
|
if len(req.QuestionTitle) > 0 {
|
|
session.Where("question.title like ?", "%"+req.QuestionTitle+"%")
|
|
}
|
|
}
|
|
if len(req.AnswerID) > 0 {
|
|
cond.ID = req.AnswerID
|
|
}
|
|
if len(req.QuestionID) > 0 {
|
|
session.Where("answer.question_id = ?", req.QuestionID)
|
|
}
|
|
if req.Status > 0 {
|
|
cond.Status = req.Status
|
|
}
|
|
session.Desc("answer.created_at")
|
|
|
|
resp = make([]*entity.Answer, 0)
|
|
total, err = pager.Help(req.Page, req.PageSize, &resp, cond, session)
|
|
if err != nil {
|
|
return nil, 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
return resp, total, nil
|
|
}
|
|
|
|
// SumVotesByQuestionID sum votes by question id
|
|
func (ar *answerRepo) SumVotesByQuestionID(ctx context.Context, questionID string) (float64, error) {
|
|
questionID = uid.DeShortID(questionID)
|
|
var resp entity.Answer
|
|
count, err := ar.data.DB.Context(ctx).Where("question_id = ? and status = ?", questionID, entity.AnswerStatusAvailable).Sum(&resp, "vote_count")
|
|
if err != nil {
|
|
return count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// updateSearch update search, if search plugin not enable, do nothing
|
|
func (ar *answerRepo) updateSearch(ctx context.Context, answerID string) (err error) {
|
|
answerID = uid.DeShortID(answerID)
|
|
// check search plugin
|
|
var (
|
|
s plugin.Search
|
|
)
|
|
_ = plugin.CallSearch(func(search plugin.Search) error {
|
|
s = search
|
|
return nil
|
|
})
|
|
if s == nil {
|
|
return
|
|
}
|
|
answer, exist, err := ar.GetAnswer(ctx, answerID)
|
|
if !exist {
|
|
return
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// get question
|
|
var (
|
|
question = new(entity.Question)
|
|
)
|
|
exist, err = ar.data.DB.Context(ctx).Where("id = ?", answer.QuestionID).Get(&question)
|
|
if err != nil {
|
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if !exist {
|
|
return
|
|
}
|
|
|
|
// get tags
|
|
var (
|
|
tagListList = make([]*entity.TagRel, 0)
|
|
tags = make([]string, 0)
|
|
)
|
|
st := ar.data.DB.Context(ctx).Where("object_id = ?", uid.DeShortID(question.ID))
|
|
st.Where("status = ?", entity.TagRelStatusAvailable)
|
|
err = st.Find(&tagListList)
|
|
if err != nil {
|
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
return
|
|
}
|
|
for _, tag := range tagListList {
|
|
tags = append(tags, tag.TagID)
|
|
}
|
|
|
|
content := &plugin.SearchContent{
|
|
ObjectID: answerID,
|
|
Title: question.Title,
|
|
Type: constant.AnswerObjectType,
|
|
Content: answer.OriginalText,
|
|
Answers: 0,
|
|
Status: plugin.SearchContentStatus(answer.Status),
|
|
Tags: tags,
|
|
QuestionID: answer.QuestionID,
|
|
UserID: answer.UserID,
|
|
Views: int64(question.ViewCount),
|
|
Created: answer.CreatedAt.Unix(),
|
|
Active: answer.UpdatedAt.Unix(),
|
|
Score: int64(answer.VoteCount),
|
|
HasAccepted: answer.Accepted == schema.AnswerAcceptedEnable,
|
|
}
|
|
err = s.UpdateContent(ctx, content)
|
|
return
|
|
}
|
|
|
|
func (ar *answerRepo) DeletePermanentlyAnswers(ctx context.Context) error {
|
|
// get all deleted answers ids
|
|
ids := make([]string, 0)
|
|
err := ar.data.DB.Context(ctx).Select("id").Table(new(entity.Answer).TableName()).
|
|
Where("status = ?", entity.AnswerStatusDeleted).Find(&ids)
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
if len(ids) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// delete all revisions permanently
|
|
_, err = ar.data.DB.Context(ctx).In("object_id", ids).Delete(&entity.Revision{})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
|
|
_, err = ar.data.DB.Context(ctx).Where("status = ?", entity.AnswerStatusDeleted).Delete(&entity.Answer{})
|
|
if err != nil {
|
|
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
}
|
|
return nil
|
|
}
|