Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

予約確定機能 追加 #17

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions controller/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,14 @@ func (ec *eventController) CreateAnswer(c echo.Context) error {
if err != nil {
return err
}

if event.UserAnswersCount == event.NumberOfParticipants {
if err := util.SendMail(event.ID, event.ConfirmationEmail); err != nil {
return apperror.NewUnknownError(fmt.Errorf("failed to send confirmation email: %w", err), nil)
}
}
eventRes := eventToEventResponse(event, user)

i := slices.IndexFunc(eventRes.UserAnswers, func(answer entity.UserEventAnswerResponse) bool {
return answer.IsYourAnswer
})
Expand All @@ -146,6 +153,7 @@ func (ec *eventController) RetrieveUserAnswer(c echo.Context) error {
if err != nil {
return err
}

eventRes := eventToEventResponse(event, user)
i := slices.IndexFunc(eventRes.UserAnswers, func(answer entity.UserEventAnswerResponse) bool {
return answer.IsYourAnswer
Expand Down
51 changes: 38 additions & 13 deletions entity/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,31 @@ import (
)

type Event struct {
ID ulid.ULID `json:"id"`
OwnerID ulid.ULID `json:"ownerId"`
Name string `json:"name"`
Description string `json:"description"`
DurationAbout string `json:"durationAbout"`
UnitSeconds int `json:"unitSeconds"`
Units []EventTimeUnit `json:"units"`
UserAnswers []UserEventAnswer `json:"userAnswers"`
ID ulid.ULID `json:"id"`
OwnerID ulid.ULID `json:"ownerId"`
Name string `json:"name"`
Description string `json:"description"`
DurationAbout string `json:"durationAbout"`
UnitSeconds int `json:"unitSeconds"`
Units []EventTimeUnit `json:"units"`
UserAnswers []UserEventAnswer `json:"userAnswers"`
UserAnswersCount int `json:"userAnswersCount"`
NotifyByEmail bool `json:"notifyByEmail"`
NumberOfParticipants int `json:"numberOfParticipants"`
ConfirmationEmail string `json:"confirmationEmail"`
}

type EventRequest struct {
Name string `json:"name"`
Description string `json:"description"`
DurationAbout string `json:"durationAbout"`
UnitSeconds int `json:"unitDuration"`
Units []EventTimeUnitRequest `json:"units"`
Name string `json:"name"`
Description string `json:"description"`
DurationAbout string `json:"durationAbout"`
UnitSeconds int `json:"unitDuration"`
Units []EventTimeUnitRequest `json:"units"`
NotifyByEmail bool `json:"notifyByEmail"`
NumberOfParticipants int `json:"numberOfParticipants"`
ConfirmationEmail string `json:"confirmationEmail"`
}

type EventResponse struct {
ID string `json:"id"`
OwnerID string `json:"ownerId"`
Expand All @@ -48,3 +57,19 @@ type EventTimeUnitResponse struct {
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
}

type Confirm struct {
ID ulid.ULID `json:"id"`
EventID ulid.ULID `json:"-"`
NotifyByEmail bool `json:"notifyByEmail"`
NumberOfParticipants int `json:"numberOfParticipants"`
ConfirmationEmail string `json:"confirmationEmail"`
}

type EventNotifyReservation struct {
ID ulid.ULID `json:"id"`
EventID ulid.ULID `json:"-"`
NotifyByEmail bool `json:"notifyByEmail"`
NumberOfParticipants int `json:"numberOfParticipants"`
ConfirmationEmail string `json:"confirmationEmail"`
}
21 changes: 19 additions & 2 deletions repository/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ type EventRepository interface {
FetchEventAnswersWithUnits(ctx context.Context, tx *sql.Tx, eventId ulid.ULID) ([]entity.UserEventAnswer, error)
// イベントの指定ユーザー回答(Unit無し)を取得する
FetchEventAnswer(ctx context.Context, tx *sql.Tx, eventId ulid.ULID, userId ulid.ULID) (entity.UserEventAnswer, error)

// 回答したユーザーの数を取得する
FetchUserAnswerCount(ctx context.Context, tx *sql.Tx, eventId ulid.ULID) (int, error)
// イベント参加回答更新
UpdateEventAnswer(ctx context.Context, tx *sql.Tx, answer entity.UserEventAnswer) (entity.UserEventAnswer, error)
// イベント参加回答時間単位を登録する
RegisterAnswerUnits(ctx context.Context, tx *sql.Tx, answer []entity.UserEventAnswerUnit) ([]entity.UserEventAnswerUnit, error)

// // イベントとイベント単位を取得する
// FetchEventAndUnits(ctx context.Context, tx *sql.Tx, eventId ulid.ULID) (entity.Event, error)
// // イベントの全情報を取得する
Expand Down Expand Up @@ -164,6 +164,7 @@ func (er *eventRepository) FetchEventTimeUnits(ctx context.Context, tx *sql.Tx,
return etus, nil
}

// イベントの全ユーザー回答(Unit付き)を取得する
// FetchEventAnswersWithUnits implements EventRepository.
func (er *eventRepository) FetchEventAnswersWithUnits(ctx context.Context, tx *sql.Tx, eventId ulid.ULID) ([]entity.UserEventAnswer, error) {
// panic("unimplemented")
Expand Down Expand Up @@ -259,6 +260,22 @@ func (er *eventRepository) FetchEventAnswer(ctx context.Context, tx *sql.Tx, eve
}, nil
}

// FetchUserAnswerCount implements EventRepository.
func (er *eventRepository) FetchUserAnswerCount(ctx context.Context, tx *sql.Tx, eventId ulid.ULID) (int, error) {
var exc boil.ContextExecutor = tx
if tx == nil {
exc = er.db
}

count, err := models.UserEventAnswers(
models.UserEventAnswerWhere.EventID.EQ(util.ULIDToString(eventId)),
).Count(ctx, exc)
if err != nil {
return 0, err
}
return int(count), nil
}

// UpdateEventAnswer implements EventRepository.
func (er *eventRepository) UpdateEventAnswer(ctx context.Context, tx *sql.Tx, answer entity.UserEventAnswer) (entity.UserEventAnswer, error) {
var exc boil.ContextExecutor = tx
Expand Down
6 changes: 6 additions & 0 deletions usecase/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ func (eu *eventUsecase) CreateUserAnswer(ctx context.Context, eventId ulid.ULID,
}
newAnswer.Units = ansUnits

// ユーザーの回答数を数える
userAnswerCount, err := eu.er.FetchUserAnswerCount(ctx, tx, eventId)
if userAnswerCount != 0 {
return entity.UserEventAnswer{}, err
}

// commit!
err = tx.Commit()
if err != nil {
Expand Down
25 changes: 25 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package util
import (
"context"
"crypto/rand"
"fmt"
"log"
"net/http"
"net/smtp"
"strings"
"time"

Expand Down Expand Up @@ -115,3 +118,25 @@ func MakeRandomStr(digit int) (string, error) {
}
return result, nil
}

func SendMail(id ulid.ULID, password, targetAddrs string) error {
hostname := "smtp.gmail.com" // SMTPサーバーのホスト名
port := 587 // SMTPサーバーのポート番号
from := "[email protected]" // 送信元のメールアドレス
recipients := []string{targetAddrs} // 送信先のメールアドレス
title := "magische 全員回答完了のお知らせ" // メールのタイトル
body := ("全員が回答しました!\n" +
"確認してください!\n") // メールの本文

auth := smtp.PlainAuth("", targetAddrs, password, hostname)
msg := []byte(strings.ReplaceAll(fmt.Sprintf(
"To: %s\nSubject: %s\n\n%s", strings.Join(recipients, ","), title, body),
"\n", "\r\n"))

// メール送信
err := smtp.SendMail(fmt.Sprintf("%s:%d", hostname, port), auth, from, recipients, msg)
if err != nil {
log.Fatal(err)
}
return nil
}