128 lines
4.2 KiB
Go
128 lines
4.2 KiB
Go
package document_service
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/XingfenD/yoresee_doc/internal/domain_event"
|
|
"github.com/XingfenD/yoresee_doc/internal/dto"
|
|
"github.com/XingfenD/yoresee_doc/internal/mapper/doc_container_mapper"
|
|
"github.com/XingfenD/yoresee_doc/internal/mapper/doc_type_mapper"
|
|
"github.com/XingfenD/yoresee_doc/internal/model"
|
|
"github.com/XingfenD/yoresee_doc/internal/status"
|
|
"github.com/XingfenD/yoresee_doc/internal/utils"
|
|
"github.com/sirupsen/logrus"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func (s *DocumentService) Create(ctx context.Context, req *dto.CreateDocumentRequest) (*dto.CreateDocumentResponse, error) {
|
|
if err := validateCreateDocumentReq(req); err != nil {
|
|
logrus.Errorf("[Service layer: DocumentService] validateCreateDocumentReq failed, err=%+v", err)
|
|
return nil, status.GenErrWithCustomMsg(err, "invalid create document request")
|
|
}
|
|
|
|
// TODO: redis support
|
|
docExternalID := utils.GenerateExternalID(utils.ExternalIDContextDocument)
|
|
err := utils.WithTransaction(s.db, func(tx *gorm.DB) error {
|
|
docModel := &model.Document{
|
|
ExternalID: docExternalID,
|
|
Title: req.Title,
|
|
Type: doc_type_mapper.ToModelType(req.Type),
|
|
ContainerType: doc_container_mapper.ToModelType(req.ContainerType),
|
|
Summary: "",
|
|
IsPublic: req.IsPublic,
|
|
Content: "",
|
|
Path: "0",
|
|
Depth: 0,
|
|
}
|
|
|
|
// query user_id
|
|
userID, err := s.userRepo.GetIDByExternalID(*req.CreatorExternalID).WithTx(tx).Exec()
|
|
if err != nil {
|
|
return status.StatusUserNotFound
|
|
}
|
|
|
|
docModel.UserID = userID
|
|
|
|
// query knowledge_id
|
|
if req.ContainerType == dto.ContainerType_KnowledgeBase {
|
|
kbID, err := s.kbRepo.GetIDByExternalID(*req.KnowledgeExternalID).WithTx(tx).Exec()
|
|
if err != nil {
|
|
return status.StatusKnowledgeBaseNotFound
|
|
}
|
|
docModel.KnowledgeID = &kbID
|
|
}
|
|
|
|
// TODO: permission check for knowledgebase
|
|
|
|
// query parent_id
|
|
if req.ParentExternalID != nil {
|
|
parentDocID, err := s.documentRepo.GetIDByExternalID(*req.ParentExternalID).WithTx(tx).Exec(ctx)
|
|
if err != nil {
|
|
return status.StatusDocumentNotFound
|
|
}
|
|
docModel.ParentID = parentDocID
|
|
}
|
|
|
|
// apply template content if provided
|
|
if req.TemplateID != nil && *req.TemplateID > 0 {
|
|
tpl, err := s.templateRepo.GetByID(*req.TemplateID).WithTx(tx).Exec()
|
|
if err != nil || tpl == nil {
|
|
logrus.Errorf("template not found: err:%+v", err)
|
|
return status.GenErrWithCustomMsg(status.StatusParamError, "template not found")
|
|
}
|
|
docModel.Content = tpl.Content
|
|
}
|
|
|
|
// create document meta
|
|
err = s.documentRepo.Create(docModel).WithTx(tx).Exec()
|
|
if err != nil {
|
|
status.GenErrWithCustomMsg(status.StatusWriteDBError, "create document meta failed")
|
|
return status.StatusWriteDBError
|
|
}
|
|
if err := s.documentRepo.UpdatePathDepth(docModel.ID, docModel.ParentID).WithTx(tx).Exec(); err != nil {
|
|
return status.GenErrWithCustomMsg(status.StatusWriteDBError, "update document path depth failed")
|
|
}
|
|
|
|
// create doc version
|
|
ver := &model.DocumentVersion{
|
|
DocumentID: docModel.ID,
|
|
Content: docModel.Content,
|
|
UserID: userID,
|
|
Title: docModel.Title,
|
|
ChangeSummary: "Create the document",
|
|
}
|
|
err = s.docVersionRepo.Create(ver).WithTx(tx).Exec()
|
|
if err != nil {
|
|
return status.GenErrWithCustomMsg(status.StatusWriteDBError, "create version failed")
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
logrus.Errorf("[Service layer: DocumentService] Create err: %+v", err)
|
|
return nil, status.StatusWriteDBError
|
|
}
|
|
|
|
if createdDoc, err := s.documentRepo.GetByExternalID(docExternalID).Exec(ctx); err == nil {
|
|
if err := s.documentRepo.BumpSubtreeVersionsByPath(ctx, createdDoc.Path); err != nil {
|
|
logrus.Warnf("bump subtree version failed: %v", err)
|
|
}
|
|
}
|
|
if req.TemplateID != nil && req.CreatorExternalID != nil && *req.CreatorExternalID != "" {
|
|
_ = s.CreateRecentTemplate(&dto.CreateRecentTemplateRequest{
|
|
UserExternalID: *req.CreatorExternalID,
|
|
TemplateID: *req.TemplateID,
|
|
AccessTime: time.Now(),
|
|
})
|
|
}
|
|
if err := domain_event.PublishDocumentUpsertEvent(ctx, docExternalID); err != nil {
|
|
logrus.Warnf("[Service layer: DocumentService] publish search sync event failed, external_id=%s, err=%+v", docExternalID, err)
|
|
}
|
|
|
|
return &dto.CreateDocumentResponse{
|
|
ExternalID: docExternalID,
|
|
}, nil
|
|
}
|