Skip to content

セクション D: batch-jobs (Go) をモノレポ配下へ取り込み#4

Merged
kantacky merged 68 commits into
mainfrom
feat/d-batch-jobs
May 10, 2026
Merged

セクション D: batch-jobs (Go) をモノレポ配下へ取り込み#4
kantacky merged 68 commits into
mainfrom
feat/d-batch-jobs

Conversation

@kantacky

@kantacky kantacky commented May 9, 2026

Copy link
Copy Markdown
Member

やったこと

Notion 計画 §7-D に沿って、fun-dotto/batch-jobs の Go 部分 (旧 fun-dotto/schedule-scripts モジュール名) を cmd/{build-class-change-notifications-job,dispatch-notifications-job}/ + internal/modules/batch-jobs/ として git filter-repo で履歴ごと取り込む。Python スクレイパー (src/, Dockerfile.scraper, pyproject.toml, uv.lock) は対象外。

  • batch-jobs (Go 部分) の取り込み (履歴保全)
    • git filter-repo --invert-paths で Python 部分 (src/, pyproject.toml, uv.lock, Dockerfile.scraper) と terraform/ を除外
    • あわせて internal/database/database.go (shared-go と重複する Connect 実装)、go.mod / mise.toml / Dockerfile 等の競合トップレベルファイル、.claude / .codex / .github / .dockerignore / README.md / .gitignore も同時に除外
    • --path-rename internal/internal/modules/batch-jobs/cmd/build-class-change-notifications/cmd/build-class-change-notifications-job/cmd/dispatch-notifications/cmd/dispatch-notifications-job/ で再配置
    • git merge --allow-unrelated-histories でブランチに合流 (.mcp.json は merge 中の競合回避のため一時退避)
  • import path を一括書き換え
    • github.com/fun-dotto/schedule-scripts/internal/<pkg>internal/modules/batch-jobs/<pkg>
    • github.com/fun-dotto/shared-go/db/modelinternal/shared/model
  • cmd エントリの整理
    • DB 接続を internal/shared/db.ConnectWithConnectorIAMAuthN に切り替え (academic と同様)。変数名は db パッケージとの衝突回避のため conn に統一
    • repository wiring の引数も conn に置換
    • -dry-run フラグや CLI 引数の扱いは変更せず、Cloud Run Job 側の args は §F で受け止める前提を維持
  • 依存整理
    • firebase.google.com/go/v4 とその間接依存を go.mod に追加し go mod tidy

確認したこと

  • mise exec -- go build ./... がリポジトリ全体で成功
  • mise exec -- go test ./... が成功 (academic / batch-jobs ともテスト Pass)
  • cmd/{build-class-change-notifications-job,dispatch-notifications-job}/main.go から旧 database.ConnectWithConnectorIAMAuthN 呼び出しが消え、shared/db に切り替わっていることを確認

メモ

  • internal/database/ の処理は §C と同じ理由で database.go のみ除外し、ToDomain 等の変換ヘルパを含む model ファイル群は internal/modules/batch-jobs/database/ として保持。internal/shared/model への一本化は §E で atlas schema diff を踏まえて検討
  • batch-jobs リポジトリの Python 部分削除は §H (cutover) のタスクとして別途実施
  • ベースブランチは §C スタックの feat/c-academic-api

masaya-osuga and others added 22 commits April 17, 2026 22:48
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 決定的 UUID + ON CONFLICT DO NOTHING で再実行安全な Upsert を追加
- 休講・補講・教室変更から前日 18:00 JST の通知を生成
- 通知対象は course_registrations から引く授業履修者
- 不要になった Notification の Create 層は削除

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
これまでは新しいtarget_userの追加のみで、対象外になったユーザーの行が残留していた。
uniqueIDsが空のときは全削除、そうでないときは新リストに含まれないユーザーを削除してから
OnConflict DoNothingでinsertするよう変更し、冪等なupsertにした。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- ListUpcomingの比較を date > ? から date >= ? に変更し、引数をfrom.Format("2006-01-02")で
  日付文字列化。type:dateカラムと整合させ、意図(明日以降)を命名と条件の両方で表現した
- 呼び出し側をtodayStartからtomorrowに変更し、対象日が明日以降であることを明確化
- periodJaを(string, bool)に変更。未知のPeriod値は警告ログを出しつつ、時限抜きの文面に
  フォールバックしてユーザー向け通知に内部enum文字列を漏らさないようにした

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
repository の ListUpcoming を ListByDate にリネームし、WHERE 句を
date >= ? から date = ? に変更。翌カレンダー日(JST)に該当する
休講・補講・教室変更のみを通知テーブルに入れるようにする。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
通知ごとに is_notified を即時更新し、500件超バッチの部分失敗時も sent > 0 を成功扱いとして重複送信を防ぐ。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ications

DB接続と通知書き込み層を追加(user-api 準拠)
これまでリポジトリ直下の classification_result.csv と
faculty_rooms_data/ 配下に散らばっていた静的データを
data/ 直下にフラット化し、参照箇所を併せて更新した。

- classification_result.csv と faculties_*.csv / rooms.csv を data/ 直下へ移動
- lesson_ids.py のデフォルトパスを data/classification_result.csv に変更
- scripts/insert_faculty_rooms.py の CSV_DIR を data/ に変更
- README のディレクトリ説明と取り込みスクリプトのパス記載を更新
- .dockerignore のパターンを data/**/*.{json,csv} に変更し、
  移動後も Docker ビルドコンテキストから除外され続けるようにした

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: pyproject.toml と uv.lock を追加

requirements.txt の内容を pyproject.toml に移植し、uv で依存を厳密にロックする。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(mise): Python 管理を uv に委譲して uv 自体をピン留め

Python のバージョンは pyproject.toml の requires-python と uv.lock で
管理するため、mise からは python を外して uv 0.11.8 を追加する。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(docker): uv ベースイメージに移行

ghcr.io/astral-sh/uv:0.11.8-debian-slim をベースに、
依存と本体を 2 段階 COPY して uv sync --frozen でインストールする。
ビルドキャッシュが効きやすくなり、再現性も uv.lock に統一される。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: ローカル実行手順を uv 前提に更新し requirements.txt を削除

uv sync / uv run でローカル開発を完結させる手順に書き換え、
役目を終えた requirements.txt を削除する。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* コードを src/dotto_batch_jobs/ 配下の単一パッケージに再配置

スクレイピングと教員居室取り込みの 2 ジョブを scrape_class_changes /
insert_faculty_rooms サブパッケージに分け、共有 DB レイヤを db/ に集約。
旧パス(main.py, lesson_ids.py, db/, scrapers/, scripts/)を削除し、
モジュール内の相対 import を dotto_batch_jobs.* の絶対 import に統一する。
本コミットはコード再配置と import 書き換えに限定し、振る舞いは変更しない。

* pyproject を hatchling ベースの単一パッケージ化し console_scripts を追加

uv ワークスペース構成の検討から、依存と配布が単純な単一パッケージ構成に
方針を変更。pyproject.toml に hatchling を build-backend として設定し、
依存(requests / beautifulsoup4 / sqlalchemy / cloud-sql-python-connector /
pg8000 / python-dotenv)をトップに集約する。
2 つのジョブのエントリポイントを [project.scripts] に登録し、
scrape-class-changes と insert-faculty-rooms コマンドで起動できるようにする。
uv.lock も新しい単一パッケージ構成に合わせて再生成する。

* Dockerfile を新しい console_script エントリポイントに合わせて更新

単一パッケージ化に伴い、ソースコピー後にプロジェクト本体も
uv sync してインストールし、CMD を python main.py から
scrape-class-changes コマンド起動に切り替える。

* README をパッケージ再配置と新コマンドに合わせて更新

エントリポイント表とディレクトリ構成、ローカル実行手順、運用フローを
src/dotto_batch_jobs/ レイアウトと scrape-class-changes /
insert-faculty-rooms コマンド呼び出しに更新する。

* リポジトリルート算出を src 配下の新パッケージ階層に合わせて修正

src/dotto_batch_jobs/ 配下への再配置でファイル深さが 1 段増えたが、
ROOT を Path(__file__).resolve().parents[4] のままにしていたため
リポジトリ外(~/Developer 直下)を指してしまい、
data/classification_result.csv が見つからず lessonId 照合がスキップされていた。
parents[3] に修正してリポジトリルートを正しく解決する。

* 休講・補講スクレイプ結果の最新スナップショットを反映

scrape-class-changes 実行で取得した最新の休講・補講データを反映する。
休講に 4/30 ロボットの科学技術、5/1 情報機器概論、7/10 自律システムを追加し、
補講は 7/10 自律システム休講分(7/24)を最新内容に差し替えた。

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Notification ドメイン/DB スキーマを per-user 通知済み管理 + FCM 拡張ペイロードへ更新

通知済みフラグを Notification.IsNotified から
NotificationTargetUser.NotifiedAt に移し、ユーザー単位での配信管理を可能にする。
あわせて Title/Body 以外の FCM オプション (ImageURL, AnalyticsLabel,
APNs, Android, Webpush) をスキーマ・ドメインに追加し、Message を Body に改名。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Notification リポジトリを per-user notified_at 管理に切り替え

MarkAsDispatched (通知単位の is_notified 更新) を
MarkUsersAsNotified (target_users.notified_at 更新) に置き換える。
ListPendingNotifications は notified_at IS NULL のユーザーが残っている
通知だけを返し、未通知ユーザーのみを TargetUsers として詰めるように変更。
UpsertNotification は TargetUsers の差集合同期と既存 notified_at の保持を
両立させ (OnConflict DoNothing)、util に uniqueTargetUsers ヘルパーを追加。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 通知配信サービスを per-user 管理 + FCM 拡張ペイロードに対応

dispatch-notifications を、成功した user だけ MarkUsersAsNotified で
通知済みにする per-user 配信に変更。FCM トークン未登録ユーザーや、
multicast 応答で個別失敗したユーザーを区別して扱うようにし、
全件一括の MarkAsDispatched 呼び出しを撤廃。
配信メッセージは Title/Body に加え APNs / Android / Webpush 等の
拡張オプションを反映できるようにし、enqueue 側では class change 通知に
APNsSound=default をセット。dry-run のフラグ説明も notified_at 表記に更新。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 通知配信ループ内で都度 MarkUsersAsNotified を呼んでクラッシュ時の重複配信を抑止

ループ末尾でまとめてフラッシュしていたため、途中でプロセスが落ちると
FCM 送信済みでも notified_at が未更新のまま残り、次回ディスパッチで
重複配信される恐れがあった。通知1件ごとに即時永続化するよう変更。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* TotalFCMSent をトークン成功送信数に統一

dry-run では len(tokens)、本実行では len(successUserIDs) を加算しており、
1ユーザー複数トークン時に値の意味が乖離していた。sendToTokens に
成功トークン数を返させて dry-run と意味を揃え、フィールド名 TotalFCMSent
の示す内容と一致させる。部分失敗ログもトークン単位の内訳を併記。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Python 出力データ data/*.json を追跡対象から除外

Python プログラムが生成する成果物のため、リポジトリで管理する必要がない。
追跡済みの 6 ファイルを削除し、.gitignore に data/*.json を追加して
今後再び追跡されないようにした。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* insert-faculty-rooms の入力 CSV と年度を CLI 引数化

faculties CSV パスと対象年度をコード内にハードコードしていたため、
追加年度の取り込みや別パス指定のたびに編集が必要だった。
--faculties YEAR=PATH 形式の必須引数(複数指定可)に置き換え、
ヘルプに必須カラム (name, email, room_name) と CSV 形式も明記した。
README の実行例も新しい呼び出し方に更新している。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 入力 CSV (rooms / faculties_2025 / faculties_2026) をリポジトリから削除

insert-faculty-rooms が CSV パスを CLI 引数で受け取るようになり、
リポジトリ内に固定パスで CSV を抱える必要が無くなった。
rooms.csv も含めて入力データはリポジトリ外で管理する方針へ寄せ、
追跡対象から削除する。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* lessonId 照合のソースを CSV から subjects テーブルへ移行

classification_result.csv で持っていた (syllabus_id, name) は
subjects テーブルに同等情報があり、CSV を別管理する必要がない。
load_name_maps を Engine 受け取りに変更して DB から名前マップを構築し、
fill_lesson_ids_in_records は複数レコード呼び出しでもクエリを 1 回に
抑えられるよう、マップを引数で受け取る形にした。
main.py は DB エンジン取得後に lessonId 照合を行う流れへ変更し、
不要になった CSV パスヘルパと data/classification_result.csv を削除した。
README の data/ 説明も併せて更新している。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* JSON 出力先を data/ から output/ に変更し追跡対象から除外

入力データの置き場である data/ にスクレイピング結果の JSON を混在させて
いたが、入力 CSV 群を整理した結果 data/ を使う必要がなくなったため、
出力専用の output/ ディレクトリへ分離する。
.gitignore は data/*.json を output/ に置き換え、ディレクトリごと
追跡対象外とした。
README の構成図と実行結果の説明も output/ に揃えている。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: 入力 CSV のパス例をプレースホルダ化

data/ 配下を前提とした例から <path-to-data-directory>/... に書き換え、
入力 CSV の置き場が任意であることを README とヘルプ文の双方で揃える。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scrape-class-changes): subjects 取得結果を syllabus_id, name で並べ替えて決定的にする

ORDER BY が無いと DB の返却順に依存し、同一 name の重複がある場合に
load_name_maps() の「先勝ち」結果が非決定になる。実行ごとに同じ
マッピングへ収束するよう ORDER BY syllabus_id, name を付与する。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(scrape-class-changes): fuzzy_pick_id の docstring を subjects 由来の表現に更新

CSV からの取り込みを廃止し subjects テーブルへ移行したのに合わせ、
「CSV 側キー」という残存表現を「subjects 由来のキー」に直す。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(insert-faculty-rooms): 必須カラムを email, room_name に統一しヘッダ検証を追加

実装で参照していない name を必須カラムから外し、README/ヘルプ/description を
実装と整合させる。あわせて CSV ヘッダ行に email / room_name が含まれていない
場合は INSERT 前に中断するよう存在チェックを追加し、ヘッダ欠落で全行未一致に
なる事故を早期に検知する。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(insert-faculty-rooms): BOM 付き CSV を扱えるよう utf-8-sig で開く

* fix(scrape-class-changes): syllabus_id の int 変換失敗時に stderr に警告を出す

* fix(scrape-class-changes): lessonId 照合の例外捕捉を SQLAlchemyError に絞り traceback を出力する

* docs(readme): 構成表の insert-faculty-rooms 説明を CLI 引数指定に合わせる

* fix(insert-faculty-rooms): CSV パスのオープン失敗時に stderr へメッセージを出して終了コード 1 で中断する

* fix(insert-faculty-rooms): CSV を newline="" で開いて環境差による空行混入を防ぐ

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
git filter-repo で配置した internal/modules/batch-jobs/ 配下の import を
新リポジトリのパスに揃える (Notion 計画 §7-D)。
- github.com/fun-dotto/schedule-scripts/internal/<pkg> →
  github.com/fun-dotto/server/internal/modules/batch-jobs/<pkg>
- github.com/fun-dotto/shared-go/db/model →
  github.com/fun-dotto/server/internal/shared/model

cmd 側の wiring 変更や DB 接続の差し替えは別コミットで扱い、
本コミットは internal/modules/batch-jobs/ 内のパッケージ参照だけを
書き換える純粋な機械的置換に留める。
build-class-change-notifications-job / dispatch-notifications-job の
DB 接続を internal/shared/db.ConnectWithConnectorIAMAuthN へ集約し、
shared 層をモノレポ全体の単一接続ソースとして扱う方針 (Notion 計画 §7-D)
を batch-jobs 側にも適用する。
- パッケージ名 db との衝突回避のため変数名は conn に統一
- repository wiring の引数も conn に置換
- バイナリ名 /bin/build-class-change-notifications-job、
  /bin/dispatch-notifications-job の対応を維持
batch-jobs (旧 fun-dotto/schedule-scripts) の repository / service が
要求する firebase.google.com/go/v4 とその間接依存を go.mod に追加し、
go mod tidy で整理した。go test ./... も通ることを確認した上で確定する。
@kantacky kantacky self-assigned this May 9, 2026
@kantacky kantacky marked this pull request as ready for review May 9, 2026 13:23
Copilot AI review requested due to automatic review settings May 9, 2026 13:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

fun-dotto/batch-jobs(旧 schedule-scripts の Go 部分)をモノレポ配下へ履歴ごと取り込み、クラス変更通知の生成ジョブと通知配信ジョブ(FCM)を cmd/*-jobinternal/modules/batch-jobs として動かせるようにする PR です。

Changes:

  • internal/modules/batch-jobs/ に domain/database/repository/service を追加し、通知の enqueue と dispatch ロジックを実装
  • cmd/build-class-change-notifications-job / cmd/dispatch-notifications-job のエントリポイントを追加し、共通 DB 接続ヘルパ(internal/shared/db)へ接続を統一
  • Firebase Admin SDK 追加に伴う依存(go.mod / go.sum)更新

Reviewed changes

Copilot reviewed 36 out of 37 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/modules/batch-jobs/service/notification_dispatch.go 未配信通知を取得し、FCM multicast で配信・配信済み更新するサービスを追加
internal/modules/batch-jobs/service/class_change_notification.go 休講/補講/教室変更から通知を組み立てるサービスの骨組みを追加
internal/modules/batch-jobs/service/class_change_notification_enqueue.go 翌日分のクラス変更を通知テーブルへ enqueue する処理を追加
internal/modules/batch-jobs/repository/util.go 重複排除ユーティリティを追加
internal/modules/batch-jobs/repository/room_change.go RoomChangeRepository の器を追加
internal/modules/batch-jobs/repository/room_change_list_by_date.go 日付指定で教室変更を取得するクエリを追加
internal/modules/batch-jobs/repository/notification.go NotificationRepository の器を追加
internal/modules/batch-jobs/repository/notification_upsert.go 通知とターゲットユーザーの upsert/同期処理を追加
internal/modules/batch-jobs/repository/notification_mark_notified.go 配信済み(notified_at)更新処理を追加
internal/modules/batch-jobs/repository/notification_list_pending.go 配信ウィンドウ内かつ未配信ユーザーがいる通知の取得処理を追加
internal/modules/batch-jobs/repository/makeup_class.go MakeupClassRepository の器を追加
internal/modules/batch-jobs/repository/makeup_class_list_by_date.go 日付指定で補講を取得するクエリを追加
internal/modules/batch-jobs/repository/fcm_token.go FCM トークン一覧取得(フィルタ付き)を追加
internal/modules/batch-jobs/repository/course_registration.go CourseRegistrationRepository の器を追加
internal/modules/batch-jobs/repository/course_registration_list_user_ids_by_subject.go 科目IDから受講ユーザーID一覧を取得するクエリを追加
internal/modules/batch-jobs/repository/cancelled_class.go CancelledClassRepository の器を追加
internal/modules/batch-jobs/repository/cancelled_class_list_by_date.go 日付指定で休講を取得するクエリを追加
internal/modules/batch-jobs/domain/subject.go Subject ドメインモデルを追加
internal/modules/batch-jobs/domain/room.go Room ドメインモデルを追加
internal/modules/batch-jobs/domain/room_change.go RoomChange ドメインモデルを追加
internal/modules/batch-jobs/domain/notification.go Notification / NotificationTargetUser ドメインモデルを追加
internal/modules/batch-jobs/domain/makeup_class.go MakeupClass ドメインモデルを追加
internal/modules/batch-jobs/domain/fcm_token.go FCMToken とフィルタ型を追加
internal/modules/batch-jobs/domain/cancelled_class.go CancelledClass ドメインモデルを追加
internal/modules/batch-jobs/database/subject.go subjects テーブル相当の GORM モデルと ToDomain を追加
internal/modules/batch-jobs/database/room.go rooms テーブル相当の GORM モデルと ToDomain を追加
internal/modules/batch-jobs/database/room_change.go room_changes テーブル相当の GORM モデルと ToDomain を追加
internal/modules/batch-jobs/database/notification.go notifications テーブル相当の GORM モデルと From/ToDomain を追加
internal/modules/batch-jobs/database/notification_target_user.go notification_target_users テーブル相当の GORM モデルを追加
internal/modules/batch-jobs/database/makeup_class.go makeup_classes テーブル相当の GORM モデルと ToDomain を追加
internal/modules/batch-jobs/database/fcm_token.go fcm_tokens テーブル相当の GORM モデルと ToDomain を追加
internal/modules/batch-jobs/database/course_registration.go course_registrations テーブル相当の GORM モデルを追加
internal/modules/batch-jobs/database/cancelled_class.go cancelled_classes テーブル相当の GORM モデルと ToDomain を追加
cmd/dispatch-notifications-job/main.go 通知配信ジョブ(Firebase Messaging + DB)エントリポイントを追加
cmd/build-class-change-notifications-job/main.go クラス変更通知 enqueue ジョブ(DB)エントリポイントを追加
go.mod Firebase Admin SDK 追加に伴う依存関係を更新
go.sum 依存追加に伴うチェックサムを更新

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +35 to +42
firebaseApp, err := firebase.NewApp(ctx, nil)
if err != nil {
log.Fatalf("Failed to initialize Firebase app: %v", err)
}
messagingClient, err := firebaseApp.Messaging(ctx)
if err != nil {
log.Fatalf("Failed to initialize Firebase Messaging client: %v", err)
}
Comment on lines +22 to +26
// ID 衝突時は本文を更新しない (再通知・重複配信を防ぐため)。target_users の増減のみ下で同期する。
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoNothing: true,
}).Create(&dbNotification).Error; err != nil {
Base automatically changed from feat/c-academic-api to main May 10, 2026 04:25
@kantacky kantacky merged commit 242635f into main May 10, 2026
4 checks passed
@kantacky kantacky deleted the feat/d-batch-jobs branch May 10, 2026 04:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants