Files
MealQuest/internal/db/shopping.sql.go
T
dev_agentandClaude Opus 5.5 6da5643f49
CI / ci (push) Successful in 5m4s
CI / ci (pull_request) Successful in 4m55s
Freeze ended weeks into the Supply archive and serve the archive API (Feature 17)
shopping.Freeze(weekStart) archives a week's Supply run once its week has
ended in the household's time zone, setting status archived and frozen_at;
it is idempotent, and a week not yet ended (ErrWeekNotEnded) or with no
list (ErrListNotFound) is an explicit error. A list still untitled is
titled first with archive_title and the same conditional write the
title_supply_run job uses; a failed title is logged and the list is
frozen untitled, keeping its week label.

GET /api/v1/shopping/archive?by=week|month|year returns the Supply runs
up to the household's current week, newest first, grouped by the
Monday's ISO week, month or year, each post with its week label, title or
null, dinner, item and on-hand counts, dinner names and current flag. Any
other by is 400 invalid_request. Frozen lists stay readable through
GET /shopping/{weekStart} and reject item PATCHes with 409 archived.

Maestro task 7ac36526-cb51-4dc7-bbad-6ebbee481942.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 07:10:06 -04:00

466 lines
12 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: shopping.sql
package db
import (
"context"
"database/sql"
)
const createShoppingGroup = `-- name: CreateShoppingGroup :exec
INSERT INTO shopping_groups (id, list_id, dinner_id, date, position, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`
type CreateShoppingGroupParams struct {
ID string
ListID string
DinnerID string
Date string
Position int64
CreatedAt string
UpdatedAt string
}
func (q *Queries) CreateShoppingGroup(ctx context.Context, arg CreateShoppingGroupParams) error {
_, err := q.db.ExecContext(ctx, createShoppingGroup,
arg.ID,
arg.ListID,
arg.DinnerID,
arg.Date,
arg.Position,
arg.CreatedAt,
arg.UpdatedAt,
)
return err
}
const createShoppingItem = `-- name: CreateShoppingItem :exec
INSERT INTO shopping_items (id, group_id, name, qty, needed, position, created_at, updated_at)
VALUES (?, ?, ?, ?, 1, ?, ?, ?)
`
type CreateShoppingItemParams struct {
ID string
GroupID string
Name string
Qty sql.NullString
Position int64
CreatedAt string
UpdatedAt string
}
// A new item is needed until the household marks it "have it".
func (q *Queries) CreateShoppingItem(ctx context.Context, arg CreateShoppingItemParams) error {
_, err := q.db.ExecContext(ctx, createShoppingItem,
arg.ID,
arg.GroupID,
arg.Name,
arg.Qty,
arg.Position,
arg.CreatedAt,
arg.UpdatedAt,
)
return err
}
const createShoppingList = `-- name: CreateShoppingList :exec
INSERT INTO shopping_lists (id, week_start, plan_id, status, created_at, updated_at)
VALUES (?, ?, ?, 'current', ?, ?)
`
type CreateShoppingListParams struct {
ID string
WeekStart string
PlanID string
CreatedAt string
UpdatedAt string
}
// A new, untitled Supply run: the title is written later, by the AI.
func (q *Queries) CreateShoppingList(ctx context.Context, arg CreateShoppingListParams) error {
_, err := q.db.ExecContext(ctx, createShoppingList,
arg.ID,
arg.WeekStart,
arg.PlanID,
arg.CreatedAt,
arg.UpdatedAt,
)
return err
}
const deleteShoppingGroup = `-- name: DeleteShoppingGroup :exec
DELETE FROM shopping_groups
WHERE id = ?
`
func (q *Queries) DeleteShoppingGroup(ctx context.Context, id string) error {
_, err := q.db.ExecContext(ctx, deleteShoppingGroup, id)
return err
}
const deleteShoppingItem = `-- name: DeleteShoppingItem :exec
DELETE FROM shopping_items
WHERE id = ?
`
func (q *Queries) DeleteShoppingItem(ctx context.Context, id string) error {
_, err := q.db.ExecContext(ctx, deleteShoppingItem, id)
return err
}
const freezeShoppingList = `-- name: FreezeShoppingList :execrows
UPDATE shopping_lists
SET status = 'archived', frozen_at = ?, updated_at = ?
WHERE id = ? AND frozen_at IS NULL
`
type FreezeShoppingListParams struct {
FrozenAt sql.NullString
UpdatedAt string
ID string
}
// Freezes list id into the Supply archive at frozen_at, unless it is
// frozen already.
func (q *Queries) FreezeShoppingList(ctx context.Context, arg FreezeShoppingListParams) (int64, error) {
result, err := q.db.ExecContext(ctx, freezeShoppingList, arg.FrozenAt, arg.UpdatedAt, arg.ID)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
const getShoppingItemList = `-- name: GetShoppingItemList :one
SELECT shopping_lists.id, shopping_lists.week_start, shopping_lists.plan_id, shopping_lists.title, shopping_lists.status, shopping_lists.sent_to_chat_at, shopping_lists.frozen_at, shopping_lists.created_at, shopping_lists.updated_at
FROM shopping_items
JOIN shopping_groups ON shopping_groups.id = shopping_items.group_id
JOIN shopping_lists ON shopping_lists.id = shopping_groups.list_id
WHERE shopping_items.id = ?
`
type GetShoppingItemListRow struct {
ShoppingList ShoppingList
}
// The Supply run holding item id. Returns sql.ErrNoRows when there is no
// such item.
func (q *Queries) GetShoppingItemList(ctx context.Context, id string) (GetShoppingItemListRow, error) {
row := q.db.QueryRowContext(ctx, getShoppingItemList, id)
var i GetShoppingItemListRow
err := row.Scan(
&i.ShoppingList.ID,
&i.ShoppingList.WeekStart,
&i.ShoppingList.PlanID,
&i.ShoppingList.Title,
&i.ShoppingList.Status,
&i.ShoppingList.SentToChatAt,
&i.ShoppingList.FrozenAt,
&i.ShoppingList.CreatedAt,
&i.ShoppingList.UpdatedAt,
)
return i, err
}
const getShoppingList = `-- name: GetShoppingList :one
SELECT id, week_start, plan_id, title, status, sent_to_chat_at, frozen_at, created_at, updated_at FROM shopping_lists
WHERE week_start = ?
`
// The Supply run of the week starting week_start. Returns sql.ErrNoRows
// when there is none.
func (q *Queries) GetShoppingList(ctx context.Context, weekStart string) (ShoppingList, error) {
row := q.db.QueryRowContext(ctx, getShoppingList, weekStart)
var i ShoppingList
err := row.Scan(
&i.ID,
&i.WeekStart,
&i.PlanID,
&i.Title,
&i.Status,
&i.SentToChatAt,
&i.FrozenAt,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const listShoppingGroupDinners = `-- name: ListShoppingGroupDinners :many
SELECT shopping_groups.id, shopping_groups.list_id, shopping_groups.dinner_id, shopping_groups.date, shopping_groups.position, shopping_groups.created_at, shopping_groups.updated_at, dinners.name AS dinner_name
FROM shopping_groups
JOIN dinners ON dinners.id = shopping_groups.dinner_id
WHERE shopping_groups.list_id = ?
ORDER BY shopping_groups.position, shopping_groups.id
`
type ListShoppingGroupDinnersRow struct {
ShoppingGroup ShoppingGroup
DinnerName string
}
// The groups of list list_id with their dinner's name, in list order.
func (q *Queries) ListShoppingGroupDinners(ctx context.Context, listID string) ([]ListShoppingGroupDinnersRow, error) {
rows, err := q.db.QueryContext(ctx, listShoppingGroupDinners, listID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListShoppingGroupDinnersRow
for rows.Next() {
var i ListShoppingGroupDinnersRow
if err := rows.Scan(
&i.ShoppingGroup.ID,
&i.ShoppingGroup.ListID,
&i.ShoppingGroup.DinnerID,
&i.ShoppingGroup.Date,
&i.ShoppingGroup.Position,
&i.ShoppingGroup.CreatedAt,
&i.ShoppingGroup.UpdatedAt,
&i.DinnerName,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listShoppingGroups = `-- name: ListShoppingGroups :many
SELECT id, list_id, dinner_id, date, position, created_at, updated_at FROM shopping_groups
WHERE list_id = ?
ORDER BY position, id
`
// The groups of list list_id, in list order.
func (q *Queries) ListShoppingGroups(ctx context.Context, listID string) ([]ShoppingGroup, error) {
rows, err := q.db.QueryContext(ctx, listShoppingGroups, listID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ShoppingGroup
for rows.Next() {
var i ShoppingGroup
if err := rows.Scan(
&i.ID,
&i.ListID,
&i.DinnerID,
&i.Date,
&i.Position,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listShoppingItems = `-- name: ListShoppingItems :many
SELECT shopping_items.id, shopping_items.group_id, shopping_items.name, shopping_items.qty, shopping_items.needed, shopping_items.position, shopping_items.created_at, shopping_items.updated_at, shopping_groups.dinner_id
FROM shopping_items
JOIN shopping_groups ON shopping_groups.id = shopping_items.group_id
WHERE shopping_groups.list_id = ?
ORDER BY shopping_groups.position, shopping_items.position, shopping_items.id
`
type ListShoppingItemsRow struct {
ShoppingItem ShoppingItem
DinnerID string
}
// The items of list list_id with their group's dinner, in list order: by
// group, then by item.
func (q *Queries) ListShoppingItems(ctx context.Context, listID string) ([]ListShoppingItemsRow, error) {
rows, err := q.db.QueryContext(ctx, listShoppingItems, listID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListShoppingItemsRow
for rows.Next() {
var i ListShoppingItemsRow
if err := rows.Scan(
&i.ShoppingItem.ID,
&i.ShoppingItem.GroupID,
&i.ShoppingItem.Name,
&i.ShoppingItem.Qty,
&i.ShoppingItem.Needed,
&i.ShoppingItem.Position,
&i.ShoppingItem.CreatedAt,
&i.ShoppingItem.UpdatedAt,
&i.DinnerID,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listShoppingListsThrough = `-- name: ListShoppingListsThrough :many
SELECT id, week_start, plan_id, title, status, sent_to_chat_at, frozen_at, created_at, updated_at FROM shopping_lists
WHERE week_start <= ?
ORDER BY week_start DESC
`
// The Supply runs of the weeks starting on or before week_start, newest
// week first.
func (q *Queries) ListShoppingListsThrough(ctx context.Context, weekStart string) ([]ShoppingList, error) {
rows, err := q.db.QueryContext(ctx, listShoppingListsThrough, weekStart)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ShoppingList
for rows.Next() {
var i ShoppingList
if err := rows.Scan(
&i.ID,
&i.WeekStart,
&i.PlanID,
&i.Title,
&i.Status,
&i.SentToChatAt,
&i.FrozenAt,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const moveShoppingGroup = `-- name: MoveShoppingGroup :exec
UPDATE shopping_groups
SET position = ?, updated_at = ?
WHERE id = ?
`
type MoveShoppingGroupParams struct {
Position int64
UpdatedAt string
ID string
}
func (q *Queries) MoveShoppingGroup(ctx context.Context, arg MoveShoppingGroupParams) error {
_, err := q.db.ExecContext(ctx, moveShoppingGroup, arg.Position, arg.UpdatedAt, arg.ID)
return err
}
const moveShoppingItem = `-- name: MoveShoppingItem :exec
UPDATE shopping_items
SET group_id = ?, qty = ?, position = ?, updated_at = ?
WHERE id = ?
`
type MoveShoppingItemParams struct {
GroupID string
Qty sql.NullString
Position int64
UpdatedAt string
ID string
}
// Places item id in group group_id at position with quantity qty; its
// name and needed flag are kept.
func (q *Queries) MoveShoppingItem(ctx context.Context, arg MoveShoppingItemParams) error {
_, err := q.db.ExecContext(ctx, moveShoppingItem,
arg.GroupID,
arg.Qty,
arg.Position,
arg.UpdatedAt,
arg.ID,
)
return err
}
const regenerateShoppingList = `-- name: RegenerateShoppingList :exec
UPDATE shopping_lists
SET plan_id = ?, updated_at = ?
WHERE id = ?
`
type RegenerateShoppingListParams struct {
PlanID string
UpdatedAt string
ID string
}
// Records a generation of list id from plan plan_id.
func (q *Queries) RegenerateShoppingList(ctx context.Context, arg RegenerateShoppingListParams) error {
_, err := q.db.ExecContext(ctx, regenerateShoppingList, arg.PlanID, arg.UpdatedAt, arg.ID)
return err
}
const setShoppingItemNeeded = `-- name: SetShoppingItemNeeded :exec
UPDATE shopping_items
SET needed = ?, updated_at = ?
WHERE id = ?
`
type SetShoppingItemNeededParams struct {
Needed int64
UpdatedAt string
ID string
}
// Marks item id needed (1) or "have it" (0).
func (q *Queries) SetShoppingItemNeeded(ctx context.Context, arg SetShoppingItemNeededParams) error {
_, err := q.db.ExecContext(ctx, setShoppingItemNeeded, arg.Needed, arg.UpdatedAt, arg.ID)
return err
}
const setShoppingListTitle = `-- name: SetShoppingListTitle :execrows
UPDATE shopping_lists
SET title = ?, updated_at = ?
WHERE id = ? AND title IS NULL AND status = 'current' AND frozen_at IS NULL
`
type SetShoppingListTitleParams struct {
Title sql.NullString
UpdatedAt string
ID string
}
// Titles list id, unless it has a title already or is frozen into the
// Supply archive.
func (q *Queries) SetShoppingListTitle(ctx context.Context, arg SetShoppingListTitleParams) (int64, error) {
result, err := q.db.ExecContext(ctx, setShoppingListTitle, arg.Title, arg.UpdatedAt, arg.ID)
if err != nil {
return 0, err
}
return result.RowsAffected()
}