From abb8e09ceb1330052259e9a08378a5642a6a7170 Mon Sep 17 00:00:00 2001 From: shouta0715 Date: Tue, 28 Nov 2023 15:27:00 +0900 Subject: [PATCH 1/4] add cities table --- .../db/migration/000002_add_city.down.sql | 5 +++++ .../db/migration/000002_add_city.up.sql | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 app/infrastructure/db/migration/000002_add_city.down.sql create mode 100644 app/infrastructure/db/migration/000002_add_city.up.sql diff --git a/app/infrastructure/db/migration/000002_add_city.down.sql b/app/infrastructure/db/migration/000002_add_city.down.sql new file mode 100644 index 0000000..1e63cd3 --- /dev/null +++ b/app/infrastructure/db/migration/000002_add_city.down.sql @@ -0,0 +1,5 @@ +ALTER TABLE menus DROP CONSTRAINT `menus_city_code_offers_at_unique`; + +ALTER TABLE menus DROP COLUMN `city_code`; + +DROP TABLE cities; \ No newline at end of file diff --git a/app/infrastructure/db/migration/000002_add_city.up.sql b/app/infrastructure/db/migration/000002_add_city.up.sql new file mode 100644 index 0000000..f5d24a6 --- /dev/null +++ b/app/infrastructure/db/migration/000002_add_city.up.sql @@ -0,0 +1,13 @@ +CREATE TABLE cities ( + city_code INT PRIMARY KEY, + city_name VARCHAR(100) NOT NULL, + prefecture_code INT NOT NULL, + prefecture_name VARCHAR(100) NOT NULL, + school_lunch_info_available boolean NOT NULL DEFAULT FALSE +); + +ALTER TABLE menus +ADD COLUMN `city_code` INT NOT NULL DEFAULT 0; + +ALTER TABLE menus +ADD CONSTRAINT `menus_city_code_offers_at_unique` UNIQUE (`city_code`, `offered_at`); \ No newline at end of file From 1e5582350ae2ee77decc30b6e969ff2f9cd2d2d8 Mon Sep 17 00:00:00 2001 From: shouta0715 Date: Wed, 29 Nov 2023 11:20:35 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix:=E5=9E=8B=E3=81=AE=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=82=84user,cities=E8=BF=BD=E5=8A=A0=E3=81=AA=E3=81=A9?= =?UTF-8?q?=E3=80=82=E3=81=BB=E3=81=BC=E3=81=99=E3=81=B9=E3=81=A6=E3=81=AE?= =?UTF-8?q?=E3=83=86=E3=83=BC=E3=83=96=E3=83=AB=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/migration/000001_init_schema.down.sql | 7 -- .../db/migration/000001_init_schema.up.sql | 33 -------- .../migration/000001_new_migration.down.sql | 35 ++++++++ .../db/migration/000001_new_migration.up.sql | 79 +++++++++++++++++++ .../db/migration/000002_add_city.down.sql | 5 -- .../db/migration/000002_add_city.up.sql | 13 --- 6 files changed, 114 insertions(+), 58 deletions(-) delete mode 100644 app/infrastructure/db/migration/000001_init_schema.down.sql delete mode 100644 app/infrastructure/db/migration/000001_init_schema.up.sql create mode 100644 app/infrastructure/db/migration/000001_new_migration.down.sql create mode 100644 app/infrastructure/db/migration/000001_new_migration.up.sql delete mode 100644 app/infrastructure/db/migration/000002_add_city.down.sql delete mode 100644 app/infrastructure/db/migration/000002_add_city.up.sql diff --git a/app/infrastructure/db/migration/000001_init_schema.down.sql b/app/infrastructure/db/migration/000001_init_schema.down.sql deleted file mode 100644 index 5e07cc2..0000000 --- a/app/infrastructure/db/migration/000001_init_schema.down.sql +++ /dev/null @@ -1,7 +0,0 @@ -DROP TABLE IF EXISTS `menus`; - -DROP TABLE IF EXISTS `dishes`; - -DROP TABLE IF EXISTS `allergens`; - -DROP TABLE IF EXISTS `dishes_allergens`; \ No newline at end of file diff --git a/app/infrastructure/db/migration/000001_init_schema.up.sql b/app/infrastructure/db/migration/000001_init_schema.up.sql deleted file mode 100644 index 0483cab..0000000 --- a/app/infrastructure/db/migration/000001_init_schema.up.sql +++ /dev/null @@ -1,33 +0,0 @@ -CREATE TABLE `menus` ( - `id` varchar(255) PRIMARY KEY, - `offered_at` DATE NOT NULL COMMENT '給食の提供日', - `photo_url` varchar(255) NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP), - `elementary_school_calories` int NOT NULL DEFAULT 0 COMMENT '小学校のカロリー', - `junior_high_school_calories` int NOT NULL DEFAULT 0 COMMENT '中学校のカロリー' -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; - -CREATE TABLE `dishes` ( - `id` varchar(255) PRIMARY KEY, - `menu_id` varchar(255) NOT NULL, - `name` varchar(255) UNIQUE NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; - -CREATE TABLE `allergens` ( - `id` SMALLINT PRIMARY KEY AUTO_INCREMENT, - `name` varchar(255) UNIQUE NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; - -CREATE TABLE `dishes_allergens` ( - `allergen_id` SMALLINT NOT NULL, - `dish_id` varchar(255) NOT NULL, - PRIMARY KEY (`dish_id`, `allergen_id`) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; - -CREATE INDEX `menus_index_0` ON `menus` (`offered_at`); - -CREATE INDEX `dishes_index_2` ON `dishes` (`menu_id`); - -CREATE INDEX `dishes_index_3` ON `dishes` (`name`); \ No newline at end of file diff --git a/app/infrastructure/db/migration/000001_new_migration.down.sql b/app/infrastructure/db/migration/000001_new_migration.down.sql new file mode 100644 index 0000000..0f07eaf --- /dev/null +++ b/app/infrastructure/db/migration/000001_new_migration.down.sql @@ -0,0 +1,35 @@ +DROP INDEX `idx_users_city_code` ON `users`; + +DROP INDEX `idx_users_username` ON `users`; + +DROP INDEX `idx_external_data_sources_year_status` ON `external_data_sources`; + +DROP INDEX `idx_external_data_sources_city_code_status` ON `external_data_sources`; + +DROP INDEX `idx_external_data_sources_city_code` ON `external_data_sources`; + +DROP INDEX `idx_external_data_sources_dataset_id` ON `external_data_sources`; + +DROP INDEX `idx_cities_city_name` ON `cities`; + +DROP INDEX `idx_dishes_name` ON `dishes`; + +DROP INDEX `idx_dishes_menu_id` ON `dishes`; + +DROP INDEX `idx_menus_offered_at` ON `menus`; + +DROP INDEX `idx_menus_city_code_offered_at` ON `menus`; + +DROP TABLE `users`; + +DROP TABLE `external_data_sources`; + +DROP TABLE `cities`; + +DROP TABLE `dishes_allergens`; + +DROP TABLE `allergens`; + +DROP TABLE `dishes`; + +DROP TABLE `menus`; \ No newline at end of file diff --git a/app/infrastructure/db/migration/000001_new_migration.up.sql b/app/infrastructure/db/migration/000001_new_migration.up.sql new file mode 100644 index 0000000..271d1e3 --- /dev/null +++ b/app/infrastructure/db/migration/000001_new_migration.up.sql @@ -0,0 +1,79 @@ +CREATE TABLE `menus` ( + `id` varchar(255) PRIMARY KEY, + `offered_at` DATE NOT NULL COMMENT '給食の提供日', + `photo_url` varchar(255), + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `elementary_school_calories` int NOT NULL DEFAULT 0, + `junior_high_school_calories` int NOT NULL DEFAULT 0, + `city_code` SMALLINT NOT NULL +); + +CREATE TABLE `dishes` ( + `id` varchar(255) PRIMARY KEY, + `menu_id` varchar(255) NOT NULL, + `name` varchar(255) UNIQUE NOT NULL, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE `allergens` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `name` varchar(255) UNIQUE NOT NULL, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE `dishes_allergens` ( + `allergen_id` INT NOT NULL, + `dish_id` varchar(255) NOT NULL, + PRIMARY KEY (`dish_id`, `allergen_id`) +); + +CREATE TABLE `cities` ( + `city_code` SMALLINT PRIMARY KEY, + `city_name` VARCHAR(100) NOT NULL, + `prefecture_code` SMALLINT NOT NULL, + `prefecture_name` VARCHAR(100) NOT NULL, + `school_lunch_info_available` boolean NOT NULL DEFAULT FALSE COMMENT '給食のデータが登録されているかどうか' +); + +CREATE TABLE `external_data_sources` ( + `source_id` INT PRIMARY KEY AUTO_INCREMENT, + `city_code` INT NOT NULL, + `dataset_id` VARCHAR(255) UNIQUE NOT NULL COMMENT 'linkedDataのdatasetのURL', + `year` INT NOT NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `status` VARCHAR(50) NOT NULL DEFAULT "Inactive" COMMENT 'Status of the data source: Active (currently in use), Inactive (not in use), Updating (currently being updated), Error (an error has occurred)', + `category` varchar(50) NOT NULL DEFAULT "menu" COMMENT 'menu or dish or allergens', + `description` TEXT +); + +CREATE TABLE `users` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `username` VARCHAR(50) UNIQUE NOT NULL, + `hashed_password` VARCHAR(255) NOT NULL, + `email` VARCHAR(100) UNIQUE NOT NULL, + `role` VARCHAR(50) NOT NULL DEFAULT "guest" COMMENT 'User roles: municipality (for municipal staff), admin (for system administrators), guest (for general users)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `city_code` SMALLINT NOT NULL DEFAULT 0 +); + +CREATE INDEX `idx_menus_offered_at` ON `menus` (`offered_at`); + +CREATE UNIQUE INDEX `idx_menus_city_code_offered_at` ON `menus` (`city_code`, `offered_at`); + +CREATE INDEX `idx_dishes_menu_id` ON `dishes` (`menu_id`); + +CREATE INDEX `idx_dishes_name` ON `dishes` (`name`); + +CREATE INDEX `idx_cities_city_name` ON `cities` (`city_name`); + +CREATE UNIQUE INDEX `idx_external_data_sources_dataset_id` ON `external_data_sources` (`dataset_id`); + +CREATE INDEX `idx_external_data_sources_city_code` ON `external_data_sources` (`city_code`); + +CREATE INDEX `idx_external_data_sources_city_code_status` ON `external_data_sources` (`city_code`, `status`); + +CREATE INDEX `idx_external_data_sources_year_status` ON `external_data_sources` (`year`, `status`); + +CREATE UNIQUE INDEX `idx_users_username` ON `users` (`username`); + +CREATE INDEX `idx_users_city_code` ON `users` (`city_code`); \ No newline at end of file diff --git a/app/infrastructure/db/migration/000002_add_city.down.sql b/app/infrastructure/db/migration/000002_add_city.down.sql deleted file mode 100644 index 1e63cd3..0000000 --- a/app/infrastructure/db/migration/000002_add_city.down.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE menus DROP CONSTRAINT `menus_city_code_offers_at_unique`; - -ALTER TABLE menus DROP COLUMN `city_code`; - -DROP TABLE cities; \ No newline at end of file diff --git a/app/infrastructure/db/migration/000002_add_city.up.sql b/app/infrastructure/db/migration/000002_add_city.up.sql deleted file mode 100644 index f5d24a6..0000000 --- a/app/infrastructure/db/migration/000002_add_city.up.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE TABLE cities ( - city_code INT PRIMARY KEY, - city_name VARCHAR(100) NOT NULL, - prefecture_code INT NOT NULL, - prefecture_name VARCHAR(100) NOT NULL, - school_lunch_info_available boolean NOT NULL DEFAULT FALSE -); - -ALTER TABLE menus -ADD COLUMN `city_code` INT NOT NULL DEFAULT 0; - -ALTER TABLE menus -ADD CONSTRAINT `menus_city_code_offers_at_unique` UNIQUE (`city_code`, `offered_at`); \ No newline at end of file From 6b2d0b05f272c55932efa786d0fdedbe72a41e28 Mon Sep 17 00:00:00 2001 From: shouta0715 Date: Wed, 29 Nov 2023 11:20:58 +0900 Subject: [PATCH 3/4] =?UTF-8?q?cities=E3=81=AE=E7=99=BB=E9=8C=B2=E3=81=AB?= =?UTF-8?q?=E4=BC=B4=E3=81=84=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/domain/menu_domain.go | 56 ++++++---- app/domain/mocks/menu_domain.go | 128 +++++++++++----------- app/infrastructure/db/query/menu.sql | 18 ++- app/infrastructure/db/sqlc/menu.sql.go | 127 +++++++++++++++------ app/infrastructure/db/sqlc/menu_test.go | 58 ++++++++-- app/infrastructure/db/sqlc/mocks/query.go | 33 +++--- app/infrastructure/db/sqlc/models.go | 46 +++++++- app/infrastructure/db/sqlc/querier.go | 9 +- app/util/random.go | 12 ++ 9 files changed, 321 insertions(+), 166 deletions(-) diff --git a/app/domain/menu_domain.go b/app/domain/menu_domain.go index 1b4550d..3308cc3 100644 --- a/app/domain/menu_domain.go +++ b/app/domain/menu_domain.go @@ -2,17 +2,19 @@ package domain import ( "context" + "database/sql" "time" "github.com/ogurilab/school-lunch-api/util" ) type Menu struct { - ID string `json:"id"` - OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` - ElementarySchoolCalories int32 `json:"elementary_school_calories"` - JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + ID string `json:"id"` + OfferedAt time.Time `json:"offered_at"` + PhotoUrl sql.NullString `json:"photo_url"` + ElementarySchoolCalories int32 `json:"elementary_school_calories"` + JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` } type MenuWithDishes struct { @@ -22,38 +24,39 @@ type MenuWithDishes struct { type MenuRepository interface { Create(ctx context.Context, menu *Menu) error - GetByID(ctx context.Context, id string) (*Menu, error) - Fetch(ctx context.Context, limit int32, offset int32) ([]*Menu, error) - GetByDate(ctx context.Context, offeredAt time.Time) (*Menu, error) - FetchByRangeDate(ctx context.Context, start, end time.Time) ([]*Menu, error) + GetByID(ctx context.Context, id string, city int32) (*Menu, error) + Fetch(ctx context.Context, limit int32, offset int32, city int32) ([]*Menu, error) + GetByDate(ctx context.Context, offeredAt time.Time, city int32) (*Menu, error) + FetchByRangeDate(ctx context.Context, start, end time.Time, city int32) ([]*Menu, error) // MenuWithDishes - GetByIDWithDishes(ctx context.Context, id string) (*MenuWithDishes, error) - FetchWithDishes(ctx context.Context, limit int32, offset int32) ([]*MenuWithDishes, error) - GetByDateWithDishes(ctx context.Context, offeredAt time.Time) (*MenuWithDishes, error) - FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time) ([]*MenuWithDishes, error) + GetByIDWithDishes(ctx context.Context, id string, city int32) (*MenuWithDishes, error) + FetchWithDishes(ctx context.Context, limit int32, offset int32, city int32) ([]*MenuWithDishes, error) + GetByDateWithDishes(ctx context.Context, offeredAt time.Time, city int32) (*MenuWithDishes, error) + FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time, city int32) ([]*MenuWithDishes, error) } type MenuUsecase interface { Create(ctx context.Context, menu *Menu) error - GetByID(ctx context.Context, id string) (*Menu, error) - Fetch(ctx context.Context, limit int32, offset int32) ([]*Menu, error) - GetByDate(ctx context.Context, offeredAt time.Time) (*Menu, error) - FetchByRangeDate(ctx context.Context, start, end time.Time) ([]*Menu, error) + GetByID(ctx context.Context, id string, city int32) (*Menu, error) + Fetch(ctx context.Context, limit int32, offset int32, city int32) ([]*Menu, error) + GetByDate(ctx context.Context, offeredAt time.Time, city int32) (*Menu, error) + FetchByRangeDate(ctx context.Context, start, end time.Time, city int32) ([]*Menu, error) // MenuWithDishes - GetByIDWithDishes(ctx context.Context, id string) (*MenuWithDishes, error) - FetchWithDishes(ctx context.Context, limit int32, offset int32) ([]*MenuWithDishes, error) - GetByDateWithDishes(ctx context.Context, offeredAt time.Time) (*MenuWithDishes, error) - FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time) ([]*MenuWithDishes, error) + GetByIDWithDishes(ctx context.Context, id string, city int32) (*MenuWithDishes, error) + FetchWithDishes(ctx context.Context, limit int32, offset int32, city int32) ([]*MenuWithDishes, error) + GetByDateWithDishes(ctx context.Context, offeredAt time.Time, city int32) (*MenuWithDishes, error) + FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time, city int32) ([]*MenuWithDishes, error) } func newMenu( id string, offeredAt time.Time, - photoUrl string, + photoUrl sql.NullString, elementarySchoolCalories int32, juniorHighSchoolCalories int32, + cityCode int32, ) (*Menu, error) { if _, err := util.ParseUlid(id); err != nil { @@ -66,15 +69,17 @@ func newMenu( PhotoUrl: photoUrl, ElementarySchoolCalories: elementarySchoolCalories, JuniorHighSchoolCalories: juniorHighSchoolCalories, + CityCode: cityCode, }, nil } func ReNewMenu( id string, offeredAt time.Time, - photoUrl string, + photoUrl sql.NullString, elementarySchoolCalories int32, juniorHighSchoolCalories int32, + cityCode int32, ) (*Menu, error) { return newMenu( id, @@ -82,14 +87,16 @@ func ReNewMenu( photoUrl, elementarySchoolCalories, juniorHighSchoolCalories, + cityCode, ) } func NewMenu( offeredAt time.Time, - photoUrl string, + photoUrl sql.NullString, elementarySchoolCalories int32, juniorHighSchoolCalories int32, + cityCode int32, ) (*Menu, error) { id := util.NewUlid() return newMenu( @@ -98,5 +105,6 @@ func NewMenu( photoUrl, elementarySchoolCalories, juniorHighSchoolCalories, + cityCode, ) } diff --git a/app/domain/mocks/menu_domain.go b/app/domain/mocks/menu_domain.go index eea9b44..b29521f 100644 --- a/app/domain/mocks/menu_domain.go +++ b/app/domain/mocks/menu_domain.go @@ -55,123 +55,123 @@ func (mr *MockMenuRepositoryMockRecorder) Create(ctx, menu any) *gomock.Call { } // Fetch mocks base method. -func (m *MockMenuRepository) Fetch(ctx context.Context, limit, offset int32) ([]*domain.Menu, error) { +func (m *MockMenuRepository) Fetch(ctx context.Context, limit, offset, city int32) ([]*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Fetch", ctx, limit, offset) + ret := m.ctrl.Call(m, "Fetch", ctx, limit, offset, city) ret0, _ := ret[0].([]*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // Fetch indicates an expected call of Fetch. -func (mr *MockMenuRepositoryMockRecorder) Fetch(ctx, limit, offset any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) Fetch(ctx, limit, offset, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockMenuRepository)(nil).Fetch), ctx, limit, offset) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockMenuRepository)(nil).Fetch), ctx, limit, offset, city) } // FetchByRangeDate mocks base method. -func (m *MockMenuRepository) FetchByRangeDate(ctx context.Context, start, end time.Time) ([]*domain.Menu, error) { +func (m *MockMenuRepository) FetchByRangeDate(ctx context.Context, start, end time.Time, city int32) ([]*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchByRangeDate", ctx, start, end) + ret := m.ctrl.Call(m, "FetchByRangeDate", ctx, start, end, city) ret0, _ := ret[0].([]*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchByRangeDate indicates an expected call of FetchByRangeDate. -func (mr *MockMenuRepositoryMockRecorder) FetchByRangeDate(ctx, start, end any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) FetchByRangeDate(ctx, start, end, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDate", reflect.TypeOf((*MockMenuRepository)(nil).FetchByRangeDate), ctx, start, end) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDate", reflect.TypeOf((*MockMenuRepository)(nil).FetchByRangeDate), ctx, start, end, city) } // FetchByRangeDateWithDishes mocks base method. -func (m *MockMenuRepository) FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time) ([]*domain.MenuWithDishes, error) { +func (m *MockMenuRepository) FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time, city int32) ([]*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchByRangeDateWithDishes", ctx, start, end) + ret := m.ctrl.Call(m, "FetchByRangeDateWithDishes", ctx, start, end, city) ret0, _ := ret[0].([]*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchByRangeDateWithDishes indicates an expected call of FetchByRangeDateWithDishes. -func (mr *MockMenuRepositoryMockRecorder) FetchByRangeDateWithDishes(ctx, start, end any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) FetchByRangeDateWithDishes(ctx, start, end, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDateWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).FetchByRangeDateWithDishes), ctx, start, end) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDateWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).FetchByRangeDateWithDishes), ctx, start, end, city) } // FetchWithDishes mocks base method. -func (m *MockMenuRepository) FetchWithDishes(ctx context.Context, limit, offset int32) ([]*domain.MenuWithDishes, error) { +func (m *MockMenuRepository) FetchWithDishes(ctx context.Context, limit, offset, city int32) ([]*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchWithDishes", ctx, limit, offset) + ret := m.ctrl.Call(m, "FetchWithDishes", ctx, limit, offset, city) ret0, _ := ret[0].([]*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchWithDishes indicates an expected call of FetchWithDishes. -func (mr *MockMenuRepositoryMockRecorder) FetchWithDishes(ctx, limit, offset any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) FetchWithDishes(ctx, limit, offset, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).FetchWithDishes), ctx, limit, offset) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).FetchWithDishes), ctx, limit, offset, city) } // GetByDate mocks base method. -func (m *MockMenuRepository) GetByDate(ctx context.Context, offeredAt time.Time) (*domain.Menu, error) { +func (m *MockMenuRepository) GetByDate(ctx context.Context, offeredAt time.Time, city int32) (*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByDate", ctx, offeredAt) + ret := m.ctrl.Call(m, "GetByDate", ctx, offeredAt, city) ret0, _ := ret[0].(*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByDate indicates an expected call of GetByDate. -func (mr *MockMenuRepositoryMockRecorder) GetByDate(ctx, offeredAt any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) GetByDate(ctx, offeredAt, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDate", reflect.TypeOf((*MockMenuRepository)(nil).GetByDate), ctx, offeredAt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDate", reflect.TypeOf((*MockMenuRepository)(nil).GetByDate), ctx, offeredAt, city) } // GetByDateWithDishes mocks base method. -func (m *MockMenuRepository) GetByDateWithDishes(ctx context.Context, offeredAt time.Time) (*domain.MenuWithDishes, error) { +func (m *MockMenuRepository) GetByDateWithDishes(ctx context.Context, offeredAt time.Time, city int32) (*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByDateWithDishes", ctx, offeredAt) + ret := m.ctrl.Call(m, "GetByDateWithDishes", ctx, offeredAt, city) ret0, _ := ret[0].(*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByDateWithDishes indicates an expected call of GetByDateWithDishes. -func (mr *MockMenuRepositoryMockRecorder) GetByDateWithDishes(ctx, offeredAt any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) GetByDateWithDishes(ctx, offeredAt, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDateWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).GetByDateWithDishes), ctx, offeredAt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDateWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).GetByDateWithDishes), ctx, offeredAt, city) } // GetByID mocks base method. -func (m *MockMenuRepository) GetByID(ctx context.Context, id string) (*domain.Menu, error) { +func (m *MockMenuRepository) GetByID(ctx context.Context, id string, city int32) (*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByID", ctx, id) + ret := m.ctrl.Call(m, "GetByID", ctx, id, city) ret0, _ := ret[0].(*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByID indicates an expected call of GetByID. -func (mr *MockMenuRepositoryMockRecorder) GetByID(ctx, id any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) GetByID(ctx, id, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockMenuRepository)(nil).GetByID), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockMenuRepository)(nil).GetByID), ctx, id, city) } // GetByIDWithDishes mocks base method. -func (m *MockMenuRepository) GetByIDWithDishes(ctx context.Context, id string) (*domain.MenuWithDishes, error) { +func (m *MockMenuRepository) GetByIDWithDishes(ctx context.Context, id string, city int32) (*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByIDWithDishes", ctx, id) + ret := m.ctrl.Call(m, "GetByIDWithDishes", ctx, id, city) ret0, _ := ret[0].(*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByIDWithDishes indicates an expected call of GetByIDWithDishes. -func (mr *MockMenuRepositoryMockRecorder) GetByIDWithDishes(ctx, id any) *gomock.Call { +func (mr *MockMenuRepositoryMockRecorder) GetByIDWithDishes(ctx, id, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIDWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).GetByIDWithDishes), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIDWithDishes", reflect.TypeOf((*MockMenuRepository)(nil).GetByIDWithDishes), ctx, id, city) } // MockMenuUsecase is a mock of MenuUsecase interface. @@ -212,121 +212,121 @@ func (mr *MockMenuUsecaseMockRecorder) Create(ctx, menu any) *gomock.Call { } // Fetch mocks base method. -func (m *MockMenuUsecase) Fetch(ctx context.Context, limit, offset int32) ([]*domain.Menu, error) { +func (m *MockMenuUsecase) Fetch(ctx context.Context, limit, offset, city int32) ([]*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Fetch", ctx, limit, offset) + ret := m.ctrl.Call(m, "Fetch", ctx, limit, offset, city) ret0, _ := ret[0].([]*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // Fetch indicates an expected call of Fetch. -func (mr *MockMenuUsecaseMockRecorder) Fetch(ctx, limit, offset any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) Fetch(ctx, limit, offset, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockMenuUsecase)(nil).Fetch), ctx, limit, offset) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockMenuUsecase)(nil).Fetch), ctx, limit, offset, city) } // FetchByRangeDate mocks base method. -func (m *MockMenuUsecase) FetchByRangeDate(ctx context.Context, start, end time.Time) ([]*domain.Menu, error) { +func (m *MockMenuUsecase) FetchByRangeDate(ctx context.Context, start, end time.Time, city int32) ([]*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchByRangeDate", ctx, start, end) + ret := m.ctrl.Call(m, "FetchByRangeDate", ctx, start, end, city) ret0, _ := ret[0].([]*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchByRangeDate indicates an expected call of FetchByRangeDate. -func (mr *MockMenuUsecaseMockRecorder) FetchByRangeDate(ctx, start, end any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) FetchByRangeDate(ctx, start, end, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDate", reflect.TypeOf((*MockMenuUsecase)(nil).FetchByRangeDate), ctx, start, end) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDate", reflect.TypeOf((*MockMenuUsecase)(nil).FetchByRangeDate), ctx, start, end, city) } // FetchByRangeDateWithDishes mocks base method. -func (m *MockMenuUsecase) FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time) ([]*domain.MenuWithDishes, error) { +func (m *MockMenuUsecase) FetchByRangeDateWithDishes(ctx context.Context, start, end time.Time, city int32) ([]*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchByRangeDateWithDishes", ctx, start, end) + ret := m.ctrl.Call(m, "FetchByRangeDateWithDishes", ctx, start, end, city) ret0, _ := ret[0].([]*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchByRangeDateWithDishes indicates an expected call of FetchByRangeDateWithDishes. -func (mr *MockMenuUsecaseMockRecorder) FetchByRangeDateWithDishes(ctx, start, end any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) FetchByRangeDateWithDishes(ctx, start, end, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDateWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).FetchByRangeDateWithDishes), ctx, start, end) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchByRangeDateWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).FetchByRangeDateWithDishes), ctx, start, end, city) } // FetchWithDishes mocks base method. -func (m *MockMenuUsecase) FetchWithDishes(ctx context.Context, limit, offset int32) ([]*domain.MenuWithDishes, error) { +func (m *MockMenuUsecase) FetchWithDishes(ctx context.Context, limit, offset, city int32) ([]*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchWithDishes", ctx, limit, offset) + ret := m.ctrl.Call(m, "FetchWithDishes", ctx, limit, offset, city) ret0, _ := ret[0].([]*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchWithDishes indicates an expected call of FetchWithDishes. -func (mr *MockMenuUsecaseMockRecorder) FetchWithDishes(ctx, limit, offset any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) FetchWithDishes(ctx, limit, offset, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).FetchWithDishes), ctx, limit, offset) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).FetchWithDishes), ctx, limit, offset, city) } // GetByDate mocks base method. -func (m *MockMenuUsecase) GetByDate(ctx context.Context, offeredAt time.Time) (*domain.Menu, error) { +func (m *MockMenuUsecase) GetByDate(ctx context.Context, offeredAt time.Time, city int32) (*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByDate", ctx, offeredAt) + ret := m.ctrl.Call(m, "GetByDate", ctx, offeredAt, city) ret0, _ := ret[0].(*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByDate indicates an expected call of GetByDate. -func (mr *MockMenuUsecaseMockRecorder) GetByDate(ctx, offeredAt any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) GetByDate(ctx, offeredAt, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDate", reflect.TypeOf((*MockMenuUsecase)(nil).GetByDate), ctx, offeredAt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDate", reflect.TypeOf((*MockMenuUsecase)(nil).GetByDate), ctx, offeredAt, city) } // GetByDateWithDishes mocks base method. -func (m *MockMenuUsecase) GetByDateWithDishes(ctx context.Context, offeredAt time.Time) (*domain.MenuWithDishes, error) { +func (m *MockMenuUsecase) GetByDateWithDishes(ctx context.Context, offeredAt time.Time, city int32) (*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByDateWithDishes", ctx, offeredAt) + ret := m.ctrl.Call(m, "GetByDateWithDishes", ctx, offeredAt, city) ret0, _ := ret[0].(*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByDateWithDishes indicates an expected call of GetByDateWithDishes. -func (mr *MockMenuUsecaseMockRecorder) GetByDateWithDishes(ctx, offeredAt any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) GetByDateWithDishes(ctx, offeredAt, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDateWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).GetByDateWithDishes), ctx, offeredAt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByDateWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).GetByDateWithDishes), ctx, offeredAt, city) } // GetByID mocks base method. -func (m *MockMenuUsecase) GetByID(ctx context.Context, id string) (*domain.Menu, error) { +func (m *MockMenuUsecase) GetByID(ctx context.Context, id string, city int32) (*domain.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByID", ctx, id) + ret := m.ctrl.Call(m, "GetByID", ctx, id, city) ret0, _ := ret[0].(*domain.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByID indicates an expected call of GetByID. -func (mr *MockMenuUsecaseMockRecorder) GetByID(ctx, id any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) GetByID(ctx, id, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockMenuUsecase)(nil).GetByID), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockMenuUsecase)(nil).GetByID), ctx, id, city) } // GetByIDWithDishes mocks base method. -func (m *MockMenuUsecase) GetByIDWithDishes(ctx context.Context, id string) (*domain.MenuWithDishes, error) { +func (m *MockMenuUsecase) GetByIDWithDishes(ctx context.Context, id string, city int32) (*domain.MenuWithDishes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetByIDWithDishes", ctx, id) + ret := m.ctrl.Call(m, "GetByIDWithDishes", ctx, id, city) ret0, _ := ret[0].(*domain.MenuWithDishes) ret1, _ := ret[1].(error) return ret0, ret1 } // GetByIDWithDishes indicates an expected call of GetByIDWithDishes. -func (mr *MockMenuUsecaseMockRecorder) GetByIDWithDishes(ctx, id any) *gomock.Call { +func (mr *MockMenuUsecaseMockRecorder) GetByIDWithDishes(ctx, id, city any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIDWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).GetByIDWithDishes), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIDWithDishes", reflect.TypeOf((*MockMenuUsecase)(nil).GetByIDWithDishes), ctx, id, city) } diff --git a/app/infrastructure/db/query/menu.sql b/app/infrastructure/db/query/menu.sql index 65fc79a..2a9cb34 100644 --- a/app/infrastructure/db/query/menu.sql +++ b/app/infrastructure/db/query/menu.sql @@ -4,24 +4,28 @@ INSERT INTO menus ( offered_at, photo_url, elementary_school_calories, - junior_high_school_calories + junior_high_school_calories, + city_code ) VALUES ( sqlc.arg(id), sqlc.arg(offered_at), sqlc.arg(photo_url), sqlc.arg(elementary_school_calories), - sqlc.arg(junior_high_school_calories) + sqlc.arg(junior_high_school_calories), + sqlc.arg(city_code) ); -- name: GetMenu :one SELECT * FROM menus -WHERE id = sqlc.arg(id); +WHERE id = sqlc.arg(id) + AND city_code = sqlc.arg(city_code); -- name: ListMenus :many SELECT * FROM menus AS m +WHERE city_code = sqlc.arg(city_code) ORDER BY offered_at LIMIT ? OFFSET ?; @@ -30,13 +34,15 @@ SELECT * FROM menus WHERE offered_at >= sqlc.arg(start_offered_at) AND offered_at < sqlc.arg(end_offered_at) + AND city_code = sqlc.arg(city_code) ORDER BY offered_at LIMIT ?; -- name: GetMenuByOfferedAt :one SELECT * FROM menus -WHERE offered_at = sqlc.arg(offered_at); +WHERE offered_at = sqlc.arg(offered_at) + AND city_code = sqlc.arg(city_code); -- name: GetMenuWithDishes :one SELECT m.*, @@ -53,6 +59,7 @@ SELECT m.*, FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id WHERE m.id = sqlc.arg(id) + AND m.city_code = sqlc.arg(city_code) GROUP BY m.id; -- name: ListMenuWithDishes :many @@ -69,6 +76,7 @@ SELECT m.*, ) AS dishes FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id +WHERE m.city_code = sqlc.arg(city_code) GROUP BY m.id ORDER BY offered_at LIMIT ? OFFSET ?; @@ -88,6 +96,7 @@ SELECT m.*, FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id WHERE m.offered_at = sqlc.arg(offered_at) + AND m.city_code = sqlc.arg(city_code) GROUP BY m.id; -- name: ListMenuWithDishesByOfferedAt :many @@ -106,6 +115,7 @@ FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id WHERE m.offered_at >= sqlc.arg(start_offered_at) AND m.offered_at <= sqlc.arg(end_offered_at) + AND m.city_code = sqlc.arg(city_code) GROUP BY m.id ORDER BY offered_at LIMIT ?; \ No newline at end of file diff --git a/app/infrastructure/db/sqlc/menu.sql.go b/app/infrastructure/db/sqlc/menu.sql.go index 91ac1e7..6ec4a86 100644 --- a/app/infrastructure/db/sqlc/menu.sql.go +++ b/app/infrastructure/db/sqlc/menu.sql.go @@ -7,6 +7,7 @@ package db import ( "context" + "database/sql" "encoding/json" "time" ) @@ -17,23 +18,26 @@ INSERT INTO menus ( offered_at, photo_url, elementary_school_calories, - junior_high_school_calories + junior_high_school_calories, + city_code ) VALUES ( ?, ?, ?, ?, + ?, ? ) ` type CreateMenuParams struct { - ID string `json:"id"` - OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` - ElementarySchoolCalories int32 `json:"elementary_school_calories"` - JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + ID string `json:"id"` + OfferedAt time.Time `json:"offered_at"` + PhotoUrl sql.NullString `json:"photo_url"` + ElementarySchoolCalories int32 `json:"elementary_school_calories"` + JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` } func (q *Queries) CreateMenu(ctx context.Context, arg CreateMenuParams) error { @@ -43,18 +47,25 @@ func (q *Queries) CreateMenu(ctx context.Context, arg CreateMenuParams) error { arg.PhotoUrl, arg.ElementarySchoolCalories, arg.JuniorHighSchoolCalories, + arg.CityCode, ) return err } const getMenu = `-- name: GetMenu :one -SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories +SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories, city_code FROM menus WHERE id = ? + AND city_code = ? ` -func (q *Queries) GetMenu(ctx context.Context, id string) (Menu, error) { - row := q.db.QueryRowContext(ctx, getMenu, id) +type GetMenuParams struct { + ID string `json:"id"` + CityCode int32 `json:"city_code"` +} + +func (q *Queries) GetMenu(ctx context.Context, arg GetMenuParams) (Menu, error) { + row := q.db.QueryRowContext(ctx, getMenu, arg.ID, arg.CityCode) var i Menu err := row.Scan( &i.ID, @@ -63,18 +74,25 @@ func (q *Queries) GetMenu(ctx context.Context, id string) (Menu, error) { &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, ) return i, err } const getMenuByOfferedAt = `-- name: GetMenuByOfferedAt :one -SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories +SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories, city_code FROM menus WHERE offered_at = ? + AND city_code = ? ` -func (q *Queries) GetMenuByOfferedAt(ctx context.Context, offeredAt time.Time) (Menu, error) { - row := q.db.QueryRowContext(ctx, getMenuByOfferedAt, offeredAt) +type GetMenuByOfferedAtParams struct { + OfferedAt time.Time `json:"offered_at"` + CityCode int32 `json:"city_code"` +} + +func (q *Queries) GetMenuByOfferedAt(ctx context.Context, arg GetMenuByOfferedAtParams) (Menu, error) { + row := q.db.QueryRowContext(ctx, getMenuByOfferedAt, arg.OfferedAt, arg.CityCode) var i Menu err := row.Scan( &i.ID, @@ -83,12 +101,13 @@ func (q *Queries) GetMenuByOfferedAt(ctx context.Context, offeredAt time.Time) ( &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, ) return i, err } const getMenuWithDishes = `-- name: GetMenuWithDishes :one -SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, +SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, m.city_code, JSON_ARRAYAGG( JSON_OBJECT( 'id', @@ -102,21 +121,28 @@ SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calori FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id WHERE m.id = ? + AND m.city_code = ? GROUP BY m.id ` +type GetMenuWithDishesParams struct { + ID string `json:"id"` + CityCode int32 `json:"city_code"` +} + type GetMenuWithDishesRow struct { ID string `json:"id"` OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` + PhotoUrl sql.NullString `json:"photo_url"` CreatedAt time.Time `json:"created_at"` ElementarySchoolCalories int32 `json:"elementary_school_calories"` JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` Dishes json.RawMessage `json:"dishes"` } -func (q *Queries) GetMenuWithDishes(ctx context.Context, id string) (GetMenuWithDishesRow, error) { - row := q.db.QueryRowContext(ctx, getMenuWithDishes, id) +func (q *Queries) GetMenuWithDishes(ctx context.Context, arg GetMenuWithDishesParams) (GetMenuWithDishesRow, error) { + row := q.db.QueryRowContext(ctx, getMenuWithDishes, arg.ID, arg.CityCode) var i GetMenuWithDishesRow err := row.Scan( &i.ID, @@ -125,13 +151,14 @@ func (q *Queries) GetMenuWithDishes(ctx context.Context, id string) (GetMenuWith &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, &i.Dishes, ) return i, err } const getMenuWithDishesByOfferedAt = `-- name: GetMenuWithDishesByOfferedAt :one -SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, +SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, m.city_code, JSON_ARRAYAGG( JSON_OBJECT( 'id', @@ -145,21 +172,28 @@ SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calori FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id WHERE m.offered_at = ? + AND m.city_code = ? GROUP BY m.id ` +type GetMenuWithDishesByOfferedAtParams struct { + OfferedAt time.Time `json:"offered_at"` + CityCode int32 `json:"city_code"` +} + type GetMenuWithDishesByOfferedAtRow struct { ID string `json:"id"` OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` + PhotoUrl sql.NullString `json:"photo_url"` CreatedAt time.Time `json:"created_at"` ElementarySchoolCalories int32 `json:"elementary_school_calories"` JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` Dishes json.RawMessage `json:"dishes"` } -func (q *Queries) GetMenuWithDishesByOfferedAt(ctx context.Context, offeredAt time.Time) (GetMenuWithDishesByOfferedAtRow, error) { - row := q.db.QueryRowContext(ctx, getMenuWithDishesByOfferedAt, offeredAt) +func (q *Queries) GetMenuWithDishesByOfferedAt(ctx context.Context, arg GetMenuWithDishesByOfferedAtParams) (GetMenuWithDishesByOfferedAtRow, error) { + row := q.db.QueryRowContext(ctx, getMenuWithDishesByOfferedAt, arg.OfferedAt, arg.CityCode) var i GetMenuWithDishesByOfferedAtRow err := row.Scan( &i.ID, @@ -168,13 +202,14 @@ func (q *Queries) GetMenuWithDishesByOfferedAt(ctx context.Context, offeredAt ti &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, &i.Dishes, ) return i, err } const listMenuWithDishes = `-- name: ListMenuWithDishes :many -SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, +SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, m.city_code, JSON_ARRAYAGG( JSON_OBJECT( 'id', @@ -187,28 +222,31 @@ SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calori ) AS dishes FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id +WHERE m.city_code = ? GROUP BY m.id ORDER BY offered_at LIMIT ? OFFSET ? ` type ListMenuWithDishesParams struct { - Limit int32 `json:"limit"` - Offset int32 `json:"offset"` + CityCode int32 `json:"city_code"` + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` } type ListMenuWithDishesRow struct { ID string `json:"id"` OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` + PhotoUrl sql.NullString `json:"photo_url"` CreatedAt time.Time `json:"created_at"` ElementarySchoolCalories int32 `json:"elementary_school_calories"` JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` Dishes json.RawMessage `json:"dishes"` } func (q *Queries) ListMenuWithDishes(ctx context.Context, arg ListMenuWithDishesParams) ([]ListMenuWithDishesRow, error) { - rows, err := q.db.QueryContext(ctx, listMenuWithDishes, arg.Limit, arg.Offset) + rows, err := q.db.QueryContext(ctx, listMenuWithDishes, arg.CityCode, arg.Limit, arg.Offset) if err != nil { return nil, err } @@ -223,6 +261,7 @@ func (q *Queries) ListMenuWithDishes(ctx context.Context, arg ListMenuWithDishes &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, &i.Dishes, ); err != nil { return nil, err @@ -239,7 +278,7 @@ func (q *Queries) ListMenuWithDishes(ctx context.Context, arg ListMenuWithDishes } const listMenuWithDishesByOfferedAt = `-- name: ListMenuWithDishesByOfferedAt :many -SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, +SELECT m.id, m.offered_at, m.photo_url, m.created_at, m.elementary_school_calories, m.junior_high_school_calories, m.city_code, JSON_ARRAYAGG( JSON_OBJECT( 'id', @@ -254,6 +293,7 @@ FROM menus AS m LEFT JOIN dishes AS d ON m.id = d.menu_id WHERE m.offered_at >= ? AND m.offered_at <= ? + AND m.city_code = ? GROUP BY m.id ORDER BY offered_at LIMIT ? @@ -262,21 +302,28 @@ LIMIT ? type ListMenuWithDishesByOfferedAtParams struct { StartOfferedAt time.Time `json:"start_offered_at"` EndOfferedAt time.Time `json:"end_offered_at"` + CityCode int32 `json:"city_code"` Limit int32 `json:"limit"` } type ListMenuWithDishesByOfferedAtRow struct { ID string `json:"id"` OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` + PhotoUrl sql.NullString `json:"photo_url"` CreatedAt time.Time `json:"created_at"` ElementarySchoolCalories int32 `json:"elementary_school_calories"` JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` Dishes json.RawMessage `json:"dishes"` } func (q *Queries) ListMenuWithDishesByOfferedAt(ctx context.Context, arg ListMenuWithDishesByOfferedAtParams) ([]ListMenuWithDishesByOfferedAtRow, error) { - rows, err := q.db.QueryContext(ctx, listMenuWithDishesByOfferedAt, arg.StartOfferedAt, arg.EndOfferedAt, arg.Limit) + rows, err := q.db.QueryContext(ctx, listMenuWithDishesByOfferedAt, + arg.StartOfferedAt, + arg.EndOfferedAt, + arg.CityCode, + arg.Limit, + ) if err != nil { return nil, err } @@ -291,6 +338,7 @@ func (q *Queries) ListMenuWithDishesByOfferedAt(ctx context.Context, arg ListMen &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, &i.Dishes, ); err != nil { return nil, err @@ -307,19 +355,21 @@ func (q *Queries) ListMenuWithDishesByOfferedAt(ctx context.Context, arg ListMen } const listMenus = `-- name: ListMenus :many -SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories +SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories, city_code FROM menus AS m +WHERE city_code = ? ORDER BY offered_at LIMIT ? OFFSET ? ` type ListMenusParams struct { - Limit int32 `json:"limit"` - Offset int32 `json:"offset"` + CityCode int32 `json:"city_code"` + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` } func (q *Queries) ListMenus(ctx context.Context, arg ListMenusParams) ([]Menu, error) { - rows, err := q.db.QueryContext(ctx, listMenus, arg.Limit, arg.Offset) + rows, err := q.db.QueryContext(ctx, listMenus, arg.CityCode, arg.Limit, arg.Offset) if err != nil { return nil, err } @@ -334,6 +384,7 @@ func (q *Queries) ListMenus(ctx context.Context, arg ListMenusParams) ([]Menu, e &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, ); err != nil { return nil, err } @@ -349,10 +400,11 @@ func (q *Queries) ListMenus(ctx context.Context, arg ListMenusParams) ([]Menu, e } const listMenusByOfferedAt = `-- name: ListMenusByOfferedAt :many -SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories +SELECT id, offered_at, photo_url, created_at, elementary_school_calories, junior_high_school_calories, city_code FROM menus WHERE offered_at >= ? AND offered_at < ? + AND city_code = ? ORDER BY offered_at LIMIT ? ` @@ -360,11 +412,17 @@ LIMIT ? type ListMenusByOfferedAtParams struct { StartOfferedAt time.Time `json:"start_offered_at"` EndOfferedAt time.Time `json:"end_offered_at"` + CityCode int32 `json:"city_code"` Limit int32 `json:"limit"` } func (q *Queries) ListMenusByOfferedAt(ctx context.Context, arg ListMenusByOfferedAtParams) ([]Menu, error) { - rows, err := q.db.QueryContext(ctx, listMenusByOfferedAt, arg.StartOfferedAt, arg.EndOfferedAt, arg.Limit) + rows, err := q.db.QueryContext(ctx, listMenusByOfferedAt, + arg.StartOfferedAt, + arg.EndOfferedAt, + arg.CityCode, + arg.Limit, + ) if err != nil { return nil, err } @@ -379,6 +437,7 @@ func (q *Queries) ListMenusByOfferedAt(ctx context.Context, arg ListMenusByOffer &i.CreatedAt, &i.ElementarySchoolCalories, &i.JuniorHighSchoolCalories, + &i.CityCode, ); err != nil { return nil, err } diff --git a/app/infrastructure/db/sqlc/menu_test.go b/app/infrastructure/db/sqlc/menu_test.go index ed7a3cd..dc7e885 100644 --- a/app/infrastructure/db/sqlc/menu_test.go +++ b/app/infrastructure/db/sqlc/menu_test.go @@ -12,13 +12,20 @@ import ( "github.com/stretchr/testify/require" ) +var cityCode = util.RandomCityCode() + func TestCreateMenu(t *testing.T) { createRandomMenu(t) } func TestGetMenu(t *testing.T) { menu1 := createRandomMenu(t) - menu2, err := testQuery.GetMenu(context.Background(), menu1.ID) + arg := GetMenuParams{ + ID: menu1.ID, + CityCode: menu1.CityCode, + } + + menu2, err := testQuery.GetMenu(context.Background(), arg) require.NoError(t, err) require.NotEmpty(t, menu2) @@ -38,8 +45,9 @@ func TestFetchMenus(t *testing.T) { } arg := ListMenusParams{ - Limit: 5, - Offset: 5, + Limit: 5, + Offset: 5, + CityCode: cityCode, } menus, err := testQuery.ListMenus(context.Background(), arg) @@ -61,7 +69,12 @@ func TestFetchMenus(t *testing.T) { func TestGetMenuByOfferedAt(t *testing.T) { menu := createRandomMenu(t) - result, err := testQuery.GetMenuByOfferedAt(context.Background(), menu.OfferedAt) + arg := GetMenuByOfferedAtParams{ + OfferedAt: menu.OfferedAt, + CityCode: menu.CityCode, + } + + result, err := testQuery.GetMenuByOfferedAt(context.Background(), arg) require.NoError(t, err) require.NotEmpty(t, result) @@ -81,6 +94,7 @@ func TestFetchMenusByOfferedAt(t *testing.T) { for i := 0; i < 10; i++ { menu := createRandomMenu(t) offeredAts = append(offeredAts, menu.OfferedAt) + } sort.Slice(offeredAts, func(i, j int) bool { @@ -91,6 +105,7 @@ func TestFetchMenusByOfferedAt(t *testing.T) { StartOfferedAt: offeredAts[0], EndOfferedAt: offeredAts[5], Limit: 5, + CityCode: cityCode, } menus, err := testQuery.ListMenusByOfferedAt(context.Background(), arg) @@ -124,7 +139,12 @@ func TestGetWithDishes(t *testing.T) { require.Len(t, mockDishes, 10) - result, err := testQuery.GetMenuWithDishes(context.Background(), menu.ID) + arg := GetMenuWithDishesParams{ + ID: menu.ID, + CityCode: menu.CityCode, + } + + result, err := testQuery.GetMenuWithDishes(context.Background(), arg) require.NoError(t, err) @@ -155,8 +175,9 @@ func TestFetchMenuWithDishes(t *testing.T) { } arg := ListMenuWithDishesParams{ - Limit: 5, - Offset: 5, + Limit: 5, + Offset: 5, + CityCode: cityCode, } results, err := testQuery.ListMenuWithDishes(context.Background(), arg) @@ -183,7 +204,12 @@ func TestGetMenuWithDishesByOfferedAt(t *testing.T) { require.Len(t, mockDishes, 10) - result, err := testQuery.GetMenuWithDishesByOfferedAt(context.Background(), menu.OfferedAt) + arg := GetMenuWithDishesByOfferedAtParams{ + OfferedAt: menu.OfferedAt, + CityCode: menu.CityCode, + } + + result, err := testQuery.GetMenuWithDishesByOfferedAt(context.Background(), arg) require.NoError(t, err) @@ -228,6 +254,7 @@ func TestFetchMenuWithDishesByOfferedAt(t *testing.T) { StartOfferedAt: offeredAts[0], EndOfferedAt: offeredAts[5], Limit: 5, + CityCode: cityCode, } results, err := testQuery.ListMenuWithDishesByOfferedAt(context.Background(), arg) @@ -244,21 +271,27 @@ func TestFetchMenuWithDishesByOfferedAt(t *testing.T) { } func createRandomMenu(t *testing.T) *domain.Menu { - ID := util.RandomUlid() + id := util.RandomUlid() args := CreateMenuParams{ - ID: ID, + ID: id, OfferedAt: util.RandomDate(), - PhotoUrl: util.RandomURL(), + PhotoUrl: util.RandomNullURL(), ElementarySchoolCalories: util.RandomInt32(), JuniorHighSchoolCalories: util.RandomInt32(), + CityCode: cityCode, } err := testQuery.CreateMenu(context.Background(), args) require.NoError(t, err) - menu, err := testQuery.GetMenu(context.Background(), ID) + getArg := GetMenuParams{ + ID: id, + CityCode: cityCode, + } + + menu, err := testQuery.GetMenu(context.Background(), getArg) require.NoError(t, err) require.NotEmpty(t, menu) @@ -276,6 +309,7 @@ func createRandomMenu(t *testing.T) *domain.Menu { menu.PhotoUrl, menu.ElementarySchoolCalories, menu.JuniorHighSchoolCalories, + menu.CityCode, ) require.NoError(t, err) diff --git a/app/infrastructure/db/sqlc/mocks/query.go b/app/infrastructure/db/sqlc/mocks/query.go index 1e657c7..60552af 100644 --- a/app/infrastructure/db/sqlc/mocks/query.go +++ b/app/infrastructure/db/sqlc/mocks/query.go @@ -11,7 +11,6 @@ package mocks import ( context "context" reflect "reflect" - time "time" db "github.com/ogurilab/school-lunch-api/infrastructure/db/sqlc" gomock "go.uber.org/mock/gomock" @@ -99,63 +98,63 @@ func (mr *MockQueryMockRecorder) GetDishByNames(ctx, arg any) *gomock.Call { } // GetMenu mocks base method. -func (m *MockQuery) GetMenu(ctx context.Context, id string) (db.Menu, error) { +func (m *MockQuery) GetMenu(ctx context.Context, arg db.GetMenuParams) (db.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMenu", ctx, id) + ret := m.ctrl.Call(m, "GetMenu", ctx, arg) ret0, _ := ret[0].(db.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // GetMenu indicates an expected call of GetMenu. -func (mr *MockQueryMockRecorder) GetMenu(ctx, id any) *gomock.Call { +func (mr *MockQueryMockRecorder) GetMenu(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenu", reflect.TypeOf((*MockQuery)(nil).GetMenu), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenu", reflect.TypeOf((*MockQuery)(nil).GetMenu), ctx, arg) } // GetMenuByOfferedAt mocks base method. -func (m *MockQuery) GetMenuByOfferedAt(ctx context.Context, offeredAt time.Time) (db.Menu, error) { +func (m *MockQuery) GetMenuByOfferedAt(ctx context.Context, arg db.GetMenuByOfferedAtParams) (db.Menu, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMenuByOfferedAt", ctx, offeredAt) + ret := m.ctrl.Call(m, "GetMenuByOfferedAt", ctx, arg) ret0, _ := ret[0].(db.Menu) ret1, _ := ret[1].(error) return ret0, ret1 } // GetMenuByOfferedAt indicates an expected call of GetMenuByOfferedAt. -func (mr *MockQueryMockRecorder) GetMenuByOfferedAt(ctx, offeredAt any) *gomock.Call { +func (mr *MockQueryMockRecorder) GetMenuByOfferedAt(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenuByOfferedAt", reflect.TypeOf((*MockQuery)(nil).GetMenuByOfferedAt), ctx, offeredAt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenuByOfferedAt", reflect.TypeOf((*MockQuery)(nil).GetMenuByOfferedAt), ctx, arg) } // GetMenuWithDishes mocks base method. -func (m *MockQuery) GetMenuWithDishes(ctx context.Context, id string) (db.GetMenuWithDishesRow, error) { +func (m *MockQuery) GetMenuWithDishes(ctx context.Context, arg db.GetMenuWithDishesParams) (db.GetMenuWithDishesRow, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMenuWithDishes", ctx, id) + ret := m.ctrl.Call(m, "GetMenuWithDishes", ctx, arg) ret0, _ := ret[0].(db.GetMenuWithDishesRow) ret1, _ := ret[1].(error) return ret0, ret1 } // GetMenuWithDishes indicates an expected call of GetMenuWithDishes. -func (mr *MockQueryMockRecorder) GetMenuWithDishes(ctx, id any) *gomock.Call { +func (mr *MockQueryMockRecorder) GetMenuWithDishes(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenuWithDishes", reflect.TypeOf((*MockQuery)(nil).GetMenuWithDishes), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenuWithDishes", reflect.TypeOf((*MockQuery)(nil).GetMenuWithDishes), ctx, arg) } // GetMenuWithDishesByOfferedAt mocks base method. -func (m *MockQuery) GetMenuWithDishesByOfferedAt(ctx context.Context, offeredAt time.Time) (db.GetMenuWithDishesByOfferedAtRow, error) { +func (m *MockQuery) GetMenuWithDishesByOfferedAt(ctx context.Context, arg db.GetMenuWithDishesByOfferedAtParams) (db.GetMenuWithDishesByOfferedAtRow, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMenuWithDishesByOfferedAt", ctx, offeredAt) + ret := m.ctrl.Call(m, "GetMenuWithDishesByOfferedAt", ctx, arg) ret0, _ := ret[0].(db.GetMenuWithDishesByOfferedAtRow) ret1, _ := ret[1].(error) return ret0, ret1 } // GetMenuWithDishesByOfferedAt indicates an expected call of GetMenuWithDishesByOfferedAt. -func (mr *MockQueryMockRecorder) GetMenuWithDishesByOfferedAt(ctx, offeredAt any) *gomock.Call { +func (mr *MockQueryMockRecorder) GetMenuWithDishesByOfferedAt(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenuWithDishesByOfferedAt", reflect.TypeOf((*MockQuery)(nil).GetMenuWithDishesByOfferedAt), ctx, offeredAt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMenuWithDishesByOfferedAt", reflect.TypeOf((*MockQuery)(nil).GetMenuWithDishesByOfferedAt), ctx, arg) } // ListDishes mocks base method. diff --git a/app/infrastructure/db/sqlc/models.go b/app/infrastructure/db/sqlc/models.go index 6fea096..6909b73 100644 --- a/app/infrastructure/db/sqlc/models.go +++ b/app/infrastructure/db/sqlc/models.go @@ -5,6 +5,7 @@ package db import ( + "database/sql" "time" ) @@ -14,6 +15,15 @@ type Allergen struct { CreatedAt time.Time `json:"created_at"` } +type City struct { + CityCode int32 `json:"city_code"` + CityName string `json:"city_name"` + PrefectureCode int32 `json:"prefecture_code"` + PrefectureName string `json:"prefecture_name"` + // 給食のデータが登録されているかどうか + SchoolLunchInfoAvailable bool `json:"school_lunch_info_available"` +} + type Dish struct { ID string `json:"id"` MenuID string `json:"menu_id"` @@ -26,14 +36,38 @@ type DishesAllergen struct { DishID string `json:"dish_id"` } +type ExternalDataSource struct { + SourceID int32 `json:"source_id"` + CityCode int32 `json:"city_code"` + // linkedDataのdatasetのURL + DatasetID string `json:"dataset_id"` + Year int32 `json:"year"` + UpdatedAt time.Time `json:"updated_at"` + // Status of the data source: Active (currently in use), Inactive (not in use), Updating (currently being updated), Error (an error has occurred) + Status string `json:"status"` + // menu or dish or allergens + Category string `json:"category"` + Description sql.NullString `json:"description"` +} + type Menu struct { ID string `json:"id"` // 給食の提供日 - OfferedAt time.Time `json:"offered_at"` - PhotoUrl string `json:"photo_url"` + OfferedAt time.Time `json:"offered_at"` + PhotoUrl sql.NullString `json:"photo_url"` + CreatedAt time.Time `json:"created_at"` + ElementarySchoolCalories int32 `json:"elementary_school_calories"` + JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` +} + +type User struct { + ID int32 `json:"id"` + Username string `json:"username"` + HashedPassword string `json:"hashed_password"` + Email string `json:"email"` + // User roles: municipality (for municipal staff), admin (for system administrators), guest (for general users) + Role string `json:"role"` CreatedAt time.Time `json:"created_at"` - // 小学校のカロリー - ElementarySchoolCalories int32 `json:"elementary_school_calories"` - // 中学校のカロリー - JuniorHighSchoolCalories int32 `json:"junior_high_school_calories"` + CityCode int32 `json:"city_code"` } diff --git a/app/infrastructure/db/sqlc/querier.go b/app/infrastructure/db/sqlc/querier.go index 68bad94..b5f3426 100644 --- a/app/infrastructure/db/sqlc/querier.go +++ b/app/infrastructure/db/sqlc/querier.go @@ -6,7 +6,6 @@ package db import ( "context" - "time" ) type Querier interface { @@ -14,10 +13,10 @@ type Querier interface { CreateMenu(ctx context.Context, arg CreateMenuParams) error GetDish(ctx context.Context, id string) (Dish, error) GetDishByNames(ctx context.Context, arg GetDishByNamesParams) ([]Dish, error) - GetMenu(ctx context.Context, id string) (Menu, error) - GetMenuByOfferedAt(ctx context.Context, offeredAt time.Time) (Menu, error) - GetMenuWithDishes(ctx context.Context, id string) (GetMenuWithDishesRow, error) - GetMenuWithDishesByOfferedAt(ctx context.Context, offeredAt time.Time) (GetMenuWithDishesByOfferedAtRow, error) + GetMenu(ctx context.Context, arg GetMenuParams) (Menu, error) + GetMenuByOfferedAt(ctx context.Context, arg GetMenuByOfferedAtParams) (Menu, error) + GetMenuWithDishes(ctx context.Context, arg GetMenuWithDishesParams) (GetMenuWithDishesRow, error) + GetMenuWithDishesByOfferedAt(ctx context.Context, arg GetMenuWithDishesByOfferedAtParams) (GetMenuWithDishesByOfferedAtRow, error) ListDishes(ctx context.Context, menuID string) ([]Dish, error) ListMenuWithDishes(ctx context.Context, arg ListMenuWithDishesParams) ([]ListMenuWithDishesRow, error) ListMenuWithDishesByOfferedAt(ctx context.Context, arg ListMenuWithDishesByOfferedAtParams) ([]ListMenuWithDishesByOfferedAtRow, error) diff --git a/app/util/random.go b/app/util/random.go index 2a37e69..979072a 100644 --- a/app/util/random.go +++ b/app/util/random.go @@ -1,6 +1,7 @@ package util import ( + "database/sql" "fmt" "math/rand" "strings" @@ -47,6 +48,17 @@ func RandomURL() string { return fmt.Sprintf("https://%s.com", RandomString(10)) } +func RandomNullURL() sql.NullString { + return sql.NullString{ + String: RandomURL(), + Valid: true, + } +} + func RandomInt32() int32 { return int32(RandomInt(0, 100)) } + +func RandomCityCode() int32 { + return int32(RandomInt(0, 4713)) +} From fcfd2856e94476a2f1fa321dd7d3801e0d0e5733 Mon Sep 17 00:00:00 2001 From: shouta0715 Date: Wed, 29 Nov 2023 11:37:32 +0900 Subject: [PATCH 4/4] =?UTF-8?q?test=E6=99=82=E3=81=AB=E3=82=AD=E3=83=A3?= =?UTF-8?q?=E3=82=B7=E3=83=A5=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 61de103..1a165c4 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ sqlc: test: - cd ${APP_PATH} && DB_SOURCE="${TEST_DB_URL}" go test -v -short -cover ./... + cd ${APP_PATH} && DB_SOURCE="${TEST_DB_URL}" go test -count=1 -v -short -cover ./... .PHONY: up down start prod prod_stop migrateup migratedown new_migration sqlc test \ No newline at end of file