Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
7 changes: 7 additions & 0 deletions cmd/atlas-loader/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import (
func main() {
stmts, err := gormschema.New("postgres").Load(
&model.Announcement{},
&model.Calendar{},
&model.CalendarDate{},
Comment thread
hikaru-0602 marked this conversation as resolved.
&model.CancelledClass{},
&model.CourseRegistration{},
&model.FareRule{},
&model.FCMToken{},
&model.Faculty{},
&model.FacultyRoom{},
Expand All @@ -22,13 +25,17 @@ func main() {
&model.NotificationTargetUser{},
&model.Room{},
&model.RoomChange{},
&model.Route{},
&model.Stop{},
&model.StopTime{},
&model.Subject{},
&model.SubjectEligibleAttribute{},
&model.SubjectFaculty{},
&model.SubjectRequirement{},
&model.Syllabus{},
&model.TimetableItem{},
&model.TimetableItemRoom{},
&model.Trip{},
&model.User{},
)
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions internal/shared/model/calendar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package model

type Calendar struct {
Common

ServiceID string `gorm:"not null;uniqueIndex"`
Monday int `gorm:"not null"`
Tuesday int `gorm:"not null"`
Wednesday int `gorm:"not null"`
Thursday int `gorm:"not null"`
Friday int `gorm:"not null"`
Saturday int `gorm:"not null"`
Sunday int `gorm:"not null"`
StartDate string `gorm:"not null"`
EndDate string `gorm:"not null"`
}
10 changes: 10 additions & 0 deletions internal/shared/model/calendar_date.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package model

type CalendarDate struct {
Common

ServiceID string `gorm:"not null;index"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceIDがCalendarへのNOT NULL FKになっていますが、GTFS仕様上はcalendar.txtにservice_idが存在せず、calendar_dates.txtのみで運行日を定義するケースも許容されています。そのケースの取り込み時にFK制約違反になる可能性があるため、Calendar側の存在を前提にしてよいか確認したいです。

Calendar *Calendar `gorm:"belongsTo;foreignKey:ServiceID;references:ServiceID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

belongsTo はgormの公式タグとして存在しないキーです。既存コード(例: room_change.go)は gorm:"foreignKey:XxxID;constraint:..." のみを使っており、belongsTo は無効な値として単に無視されます。削除をお願いします。

@hikaru-0602 hikaru-0602 Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

公式にはタグはないけどライブラリ自体には存在してる
https://github.com/go-gorm/gorm/blob/master/schema/relationship.go

これないとHasOne判定になってマイグレーション失敗するからタグ残すことにした
これでも問題はないけど,削除した方が良いなら対応します

Date string `gorm:"not null;index"`
ExceptionType int `gorm:"not null"`
}
13 changes: 13 additions & 0 deletions internal/shared/model/fare_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package model

type FareRule struct {
Common

RouteID string `gorm:"not null;index"`
Route *Route `gorm:"belongsTo;foreignKey:RouteID;references:RouteID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
OriginID string `gorm:"not null;index"`
Origin *Stop `gorm:"belongsTo;foreignKey:OriginID;references:StopID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
DestinationID string `gorm:"not null;index"`
Destination *Stop `gorm:"belongsTo;foreignKey:DestinationID;references:StopID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
Price float64 `gorm:"not null"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GTFS標準のfare_rules.txtにはprice列は存在せず、price/currency_typeはfare_attributes.txt側(fare_idで紐付け)の責務です。このモデルはfare_attributes相当を作らずpriceを直接埋め込んでおり、正規化されたGTFSモデルから逸脱しています。同一fare_idを複数ルールで共有するケースやcurrency_type等の拡張に対応できなくなるため、設計意図を確認したいです。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本来は,子どもと大人で料金が異なる場合とかを想定してテーブル分かれてるんだけど,実データ見たところ一律料金だったため,テーブルを分ける必要は無いと判断.
将来子ども料金とか作られたら対応は必要になる.

}
8 changes: 8 additions & 0 deletions internal/shared/model/route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package model

type Route struct {
Common

RouteID string `gorm:"not null;uniqueIndex"`
RouteShortName string `gorm:"not null"`
}
8 changes: 8 additions & 0 deletions internal/shared/model/stop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package model

type Stop struct {
Common

StopID string `gorm:"not null;uniqueIndex"`
StopName string `gorm:"not null"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GTFS仕様上 stop_lat/stop_lon(緯度経度)はConditionally Requiredで、経路探索・地図表示に実質必須のフィールドです。現状StopIDとStopNameのみで位置情報が完全に欠落しており、機能上致命的な漏れの可能性があります。意図的な省略でなければ追加をお願いします。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

今回の仕様には緯度経度は必要ないと判断.
もし,現在地から一番近いバス停を自動選択といった機能を追加するならその際に対応が必要

}
13 changes: 13 additions & 0 deletions internal/shared/model/stop_time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package model

type StopTime struct {
Common

TripID string `gorm:"not null;index"`
Trip *Trip `gorm:"belongsTo;foreignKey:TripID;references:TripID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
Outdated
ArrivalTime string `gorm:"not null"`
DepartureTime string `gorm:"not null"`
StopID string `gorm:"not null;index"`
Stop *Stop `gorm:"belongsTo;foreignKey:StopID;references:StopID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
StopSequence int `gorm:"not null"`
}
12 changes: 12 additions & 0 deletions internal/shared/model/trip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package model

type Trip struct {
Common

TripID string `gorm:"not null;uniqueIndex"`
RouteID string `gorm:"not null;index"`
Route *Route `gorm:"belongsTo;foreignKey:RouteID;references:RouteID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
Outdated
ServiceID string `gorm:"not null;index"`
Calendar *Calendar `gorm:"belongsTo;foreignKey:ServiceID;references:ServiceID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Comment thread
hikaru-0602 marked this conversation as resolved.
Outdated
DirectionID int `gorm:"not null"`
}
113 changes: 113 additions & 0 deletions migrations/20260820171158_add_gtfs.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
-- Create "calendars" table
CREATE TABLE "public"."calendars" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"service_id" text NOT NULL,
"monday" bigint NOT NULL,
"tuesday" bigint NOT NULL,
"wednesday" bigint NOT NULL,
"thursday" bigint NOT NULL,
"friday" bigint NOT NULL,
"saturday" bigint NOT NULL,
"sunday" bigint NOT NULL,
"start_date" text NOT NULL,
"end_date" text NOT NULL,
PRIMARY KEY ("id")
);
-- Create index "idx_calendars_service_id" to table: "calendars"
CREATE UNIQUE INDEX "idx_calendars_service_id" ON "public"."calendars" ("service_id");
-- Create "calendar_dates" table
CREATE TABLE "public"."calendar_dates" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"service_id" text NOT NULL,
"date" text NOT NULL,
"exception_type" bigint NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "fk_calendar_dates_calendar" FOREIGN KEY ("service_id") REFERENCES "public"."calendars" ("service_id") ON UPDATE CASCADE ON DELETE CASCADE
);
-- Create index "idx_calendar_dates_date" to table: "calendar_dates"
CREATE INDEX "idx_calendar_dates_date" ON "public"."calendar_dates" ("date");
-- Create index "idx_calendar_dates_service_id" to table: "calendar_dates"
CREATE INDEX "idx_calendar_dates_service_id" ON "public"."calendar_dates" ("service_id");
-- Create "stops" table
CREATE TABLE "public"."stops" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"stop_id" text NOT NULL,
"stop_name" text NOT NULL,
PRIMARY KEY ("id")
);
-- Create index "idx_stops_stop_id" to table: "stops"
CREATE UNIQUE INDEX "idx_stops_stop_id" ON "public"."stops" ("stop_id");
-- Create "routes" table
CREATE TABLE "public"."routes" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"route_id" text NOT NULL,
"route_short_name" text NOT NULL,
PRIMARY KEY ("id")
);
-- Create index "idx_routes_route_id" to table: "routes"
CREATE UNIQUE INDEX "idx_routes_route_id" ON "public"."routes" ("route_id");
-- Create "fare_rules" table
CREATE TABLE "public"."fare_rules" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"route_id" text NOT NULL,
"origin_id" text NOT NULL,
"destination_id" text NOT NULL,
"price" numeric NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "fk_fare_rules_destination" FOREIGN KEY ("destination_id") REFERENCES "public"."stops" ("stop_id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "fk_fare_rules_origin" FOREIGN KEY ("origin_id") REFERENCES "public"."stops" ("stop_id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "fk_fare_rules_route" FOREIGN KEY ("route_id") REFERENCES "public"."routes" ("route_id") ON UPDATE CASCADE ON DELETE CASCADE
);
-- Create index "idx_fare_rules_destination_id" to table: "fare_rules"
CREATE INDEX "idx_fare_rules_destination_id" ON "public"."fare_rules" ("destination_id");
-- Create index "idx_fare_rules_origin_id" to table: "fare_rules"
CREATE INDEX "idx_fare_rules_origin_id" ON "public"."fare_rules" ("origin_id");
-- Create index "idx_fare_rules_route_id" to table: "fare_rules"
CREATE INDEX "idx_fare_rules_route_id" ON "public"."fare_rules" ("route_id");
-- Create "trips" table
CREATE TABLE "public"."trips" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"trip_id" text NOT NULL,
"route_id" text NOT NULL,
"service_id" text NOT NULL,
"direction_id" bigint NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "fk_trips_calendar" FOREIGN KEY ("service_id") REFERENCES "public"."calendars" ("service_id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "fk_trips_route" FOREIGN KEY ("route_id") REFERENCES "public"."routes" ("route_id") ON UPDATE CASCADE ON DELETE CASCADE
);
-- Create index "idx_trips_route_id" to table: "trips"
CREATE INDEX "idx_trips_route_id" ON "public"."trips" ("route_id");
-- Create index "idx_trips_service_id" to table: "trips"
CREATE INDEX "idx_trips_service_id" ON "public"."trips" ("service_id");
-- Create index "idx_trips_trip_id" to table: "trips"
CREATE UNIQUE INDEX "idx_trips_trip_id" ON "public"."trips" ("trip_id");
-- Create "stop_times" table
CREATE TABLE "public"."stop_times" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"created_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
"trip_id" text NOT NULL,
"arrival_time" text NOT NULL,
"departure_time" text NOT NULL,
"stop_id" text NOT NULL,
"stop_sequence" bigint NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "fk_stop_times_stop" FOREIGN KEY ("stop_id") REFERENCES "public"."stops" ("stop_id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "fk_stop_times_trip" FOREIGN KEY ("trip_id") REFERENCES "public"."trips" ("trip_id") ON UPDATE CASCADE ON DELETE CASCADE
);
-- Create index "idx_stop_times_stop_id" to table: "stop_times"
CREATE INDEX "idx_stop_times_stop_id" ON "public"."stop_times" ("stop_id");
-- Create index "idx_stop_times_trip_id" to table: "stop_times"
CREATE INDEX "idx_stop_times_trip_id" ON "public"."stop_times" ("trip_id");
3 changes: 2 additions & 1 deletion migrations/atlas.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
h1:mQA8+6XzgUFnR6Z3XZPxHD6GVSUJkrzddFL0jnGEnxs=
h1:D5+i7UkpjX21CwSfHPnweaD2G/XBWhvNtDxh558HwkY=
20260510075358_baseline.sql h1:S1fQ5KJJJ/pulk/6WuV0GWMpC7jrMdg8uFGScIAr18A=
20260510085829.sql h1:Jo1Alddu/vC51J4L/XttheZYY7FERVzLgRQLPStkHwk=
20260716124002.sql h1:QVA3ZUNeL5M7ohqzdf7ZQ6RefAuQ5UGD1/SKZIje0OU=
20260820171158_add_gtfs.sql h1:bqlu65oO9vfinAtbIXE7Mg5j3bbm9npUAPk9po9kRc0=