init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

View 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
}