init push
This commit is contained in:
289
internal/service/air_rescuer_checklist_service.go
Normal file
289
internal/service/air_rescuer_checklist_service.go
Normal file
@@ -0,0 +1,289 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
airrescuechecklist "wucher/internal/domain/air_rescue_checklist"
|
||||
)
|
||||
|
||||
type AirRescuerChecklistService struct {
|
||||
repo airrescuechecklist.Repository
|
||||
}
|
||||
|
||||
func NewAirRescuerChecklistService(repo airrescuechecklist.Repository) *AirRescuerChecklistService {
|
||||
return &AirRescuerChecklistService{repo: repo}
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) CreateBulk(ctx context.Context, rows []airrescuechecklist.ChecklistCreateInput) error {
|
||||
if len(rows) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
for i := range rows {
|
||||
header := &rows[i].Checklist
|
||||
if header.Position <= 0 {
|
||||
nextPos, err := txRepo.NextChecklistPosition(ctx, header.HEMSBaseID, header.ScopeCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Position = nextPos
|
||||
}
|
||||
if err := txRepo.CreateChecklist(ctx, header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var nextItemPos int
|
||||
itemNextInitialized := false
|
||||
for j := range rows[i].Items {
|
||||
item := &rows[i].Items[j]
|
||||
item.ChecklistID = append([]byte(nil), header.ID...)
|
||||
if item.Position <= 0 {
|
||||
if !itemNextInitialized {
|
||||
pos, err := txRepo.NextChecklistItemPosition(ctx, header.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nextItemPos = pos
|
||||
itemNextInitialized = true
|
||||
}
|
||||
item.Position = nextItemPos
|
||||
nextItemPos++
|
||||
}
|
||||
if err := txRepo.CreateChecklistItem(ctx, item); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) UpdateChecklist(ctx context.Context, row *airrescuechecklist.AirRescuerChecklist) error {
|
||||
if row == nil {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
row.Position = normalizeChecklistPosition(row.Position)
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistByID(ctx, row.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return txRepo.UpdateChecklist(ctx, row)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) UpdateChecklistWithNewItems(
|
||||
ctx context.Context,
|
||||
row *airrescuechecklist.AirRescuerChecklist,
|
||||
newItems []airrescuechecklist.AirRescuerChecklistItem,
|
||||
) error {
|
||||
if row == nil && len(newItems) == 0 {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
|
||||
checklistID := []byte(nil)
|
||||
if row != nil {
|
||||
row.Position = normalizeChecklistPosition(row.Position)
|
||||
checklistID = append([]byte(nil), row.ID...)
|
||||
}
|
||||
if len(checklistID) == 0 && len(newItems) > 0 {
|
||||
checklistID = append([]byte(nil), newItems[0].ChecklistID...)
|
||||
}
|
||||
if len(checklistID) == 0 {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistByID(ctx, checklistID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if row != nil {
|
||||
if err := txRepo.UpdateChecklist(ctx, row); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(newItems) == 0 {
|
||||
return nil
|
||||
}
|
||||
nextItemPos := 0
|
||||
itemNextInitialized := false
|
||||
for i := range newItems {
|
||||
newItems[i].ChecklistID = append([]byte(nil), checklistID...)
|
||||
if newItems[i].Position <= 0 {
|
||||
if !itemNextInitialized {
|
||||
pos, err := txRepo.NextChecklistItemPosition(ctx, checklistID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nextItemPos = pos
|
||||
itemNextInitialized = true
|
||||
}
|
||||
newItems[i].Position = nextItemPos
|
||||
nextItemPos++
|
||||
}
|
||||
}
|
||||
return txRepo.CreateChecklistItems(ctx, newItems)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) DeleteChecklist(ctx context.Context, id []byte, deletedBy []byte) error {
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistByID(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := txRepo.SoftDeleteChecklist(ctx, id, deletedBy); err != nil {
|
||||
return err
|
||||
}
|
||||
return txRepo.SoftDeleteItemsByChecklistID(ctx, id, deletedBy)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) CreateChecklistItem(ctx context.Context, row *airrescuechecklist.AirRescuerChecklistItem) error {
|
||||
if row == nil {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistByID(ctx, row.ChecklistID); err != nil {
|
||||
return err
|
||||
}
|
||||
if row.Position <= 0 {
|
||||
nextPos, err := txRepo.NextChecklistItemPosition(ctx, row.ChecklistID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
row.Position = nextPos
|
||||
}
|
||||
return txRepo.CreateChecklistItem(ctx, row)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) CreateChecklistItems(ctx context.Context, checklistID []byte, rows []airrescuechecklist.AirRescuerChecklistItem) error {
|
||||
if len(rows) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistByID(ctx, checklistID); err != nil {
|
||||
return err
|
||||
}
|
||||
nextItemPos := 0
|
||||
itemNextInitialized := false
|
||||
for i := range rows {
|
||||
rows[i].ChecklistID = append([]byte(nil), checklistID...)
|
||||
if rows[i].Position <= 0 {
|
||||
if !itemNextInitialized {
|
||||
pos, err := txRepo.NextChecklistItemPosition(ctx, checklistID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nextItemPos = pos
|
||||
itemNextInitialized = true
|
||||
}
|
||||
rows[i].Position = nextItemPos
|
||||
nextItemPos++
|
||||
}
|
||||
}
|
||||
return txRepo.CreateChecklistItems(ctx, rows)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) ReorderChecklistItems(
|
||||
ctx context.Context,
|
||||
checklistID []byte,
|
||||
rows []airrescuechecklist.ChecklistItemReorderInput,
|
||||
updatedBy []byte,
|
||||
) error {
|
||||
if len(rows) == 0 {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistByID(ctx, checklistID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
seenItemIDs := make(map[string]struct{}, len(rows))
|
||||
for i := range rows {
|
||||
itemID := rows[i].ID
|
||||
if len(itemID) == 0 {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
itemKey := string(itemID)
|
||||
if _, exists := seenItemIDs[itemKey]; exists {
|
||||
return errors.New("duplicate item_uuid in reorder payload")
|
||||
}
|
||||
seenItemIDs[itemKey] = struct{}{}
|
||||
|
||||
current, err := txRepo.LockChecklistItemByID(ctx, itemID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(current.ChecklistID, checklistID) {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
if err := txRepo.UpdateChecklistItem(ctx, &airrescuechecklist.AirRescuerChecklistItem{
|
||||
ID: append([]byte(nil), itemID...),
|
||||
Name: current.Name,
|
||||
Position: normalizeChecklistPosition(rows[i].Position),
|
||||
UpdatedBy: append([]byte(nil), updatedBy...),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) UpdateChecklistItem(ctx context.Context, row *airrescuechecklist.AirRescuerChecklistItem) error {
|
||||
if row == nil {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
row.Position = normalizeChecklistPosition(row.Position)
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistItemByID(ctx, row.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return txRepo.UpdateChecklistItem(ctx, row)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) DeleteChecklistItem(ctx context.Context, id []byte, deletedBy []byte) error {
|
||||
return s.repo.InTx(ctx, func(txRepo airrescuechecklist.TxRepository) error {
|
||||
if _, err := txRepo.LockChecklistItemByID(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return txRepo.SoftDeleteChecklistItem(ctx, id, deletedBy)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) GetChecklistByID(ctx context.Context, id []byte) (*airrescuechecklist.ChecklistHeaderView, error) {
|
||||
return s.repo.GetChecklistByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) GetChecklistItemByID(ctx context.Context, id []byte) (*airrescuechecklist.ChecklistItemView, error) {
|
||||
return s.repo.GetChecklistItemByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) ListChecklistHeaders(ctx context.Context, filter airrescuechecklist.ChecklistHeaderFilter) ([]airrescuechecklist.ChecklistHeaderView, error) {
|
||||
return s.repo.ListChecklistHeaders(ctx, filter)
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) ListChecklistItemsByChecklistIDs(ctx context.Context, checklistIDs [][]byte) ([]airrescuechecklist.ChecklistItemView, error) {
|
||||
return s.repo.ListChecklistItemsByChecklistIDs(ctx, checklistIDs)
|
||||
}
|
||||
|
||||
func (s *AirRescuerChecklistService) ListHEMSBases(ctx context.Context, filter airrescuechecklist.HEMSBaseFilter) ([]airrescuechecklist.HEMSBaseView, error) {
|
||||
return s.repo.ListHEMSBases(ctx, filter)
|
||||
}
|
||||
|
||||
func normalizeChecklistPosition(v int) int {
|
||||
if v <= 0 {
|
||||
return 1
|
||||
}
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user