← back to Omega Watches 2

src/app/api/alerts/route.ts

123 lines

import { NextRequest, NextResponse } from "next/server";
import { query } from "@/lib/db";
import { getSession } from "@/lib/auth";

export const dynamic = "force-dynamic";

export async function GET(request: NextRequest) {
  const session = await getSession(request);
  if (!session) {
    return NextResponse.json(
      { success: false, error: { code: "UNAUTHORIZED", message: "Login required" } },
      { status: 401 }
    );
  }

  const rules = await query(`
    SELECT par.*, wr.reference_number, wr.collection, wr.model_name,
           (SELECT AVG(me.price_usd)::NUMERIC(14,2)
            FROM market_event me
            WHERE me.reference_id = par.reference_id
              AND NOT me.is_quarantined AND me.price_usd > 0
              AND me.sale_date > CURRENT_DATE - 30
           ) as current_avg_price
    FROM price_alert_rule par
    JOIN watch_reference wr ON par.reference_id = wr.id
    ORDER BY par.is_active DESC, par.created_at DESC
  `);

  // Check which rules are currently triggered
  const enriched = rules.map((r: any) => {
    const avg = parseFloat(r.current_avg_price) || 0;
    let triggered = false;
    if (r.alert_type === "price_below" && avg > 0 && avg < parseFloat(r.threshold)) triggered = true;
    if (r.alert_type === "price_above" && avg > 0 && avg > parseFloat(r.threshold)) triggered = true;
    return { ...r, is_triggered: triggered };
  });

  return NextResponse.json({
    success: true,
    data: {
      rules: enriched,
      summary: {
        total: rules.length,
        active: rules.filter((r: any) => r.is_active).length,
        triggered: enriched.filter((r: any) => r.is_triggered).length,
      },
    },
  });
}

export async function POST(request: NextRequest) {
  const session = await getSession(request);
  if (!session) {
    return NextResponse.json(
      { success: false, error: { code: "UNAUTHORIZED", message: "Login required" } },
      { status: 401 }
    );
  }

  if (session.role !== "admin" && session.role !== "operator") {
    return NextResponse.json(
      { success: false, error: { code: "FORBIDDEN", message: "Admin or operator role required" } },
      { status: 403 }
    );
  }

  const { reference_number, alert_type, threshold, notes } = await request.json();

  if (!reference_number || !alert_type || !threshold) {
    return NextResponse.json(
      { success: false, error: { code: "MISSING_PARAMS", message: "reference_number, alert_type, and threshold required" } },
      { status: 400 }
    );
  }

  const ref = await query(
    "SELECT id FROM watch_reference WHERE reference_number = $1",
    [reference_number]
  );

  if (ref.length === 0) {
    return NextResponse.json(
      { success: false, error: { code: "NOT_FOUND", message: "Reference not found" } },
      { status: 404 }
    );
  }

  const result = await query(
    `INSERT INTO price_alert_rule (reference_id, alert_type, threshold, notes, created_by)
     VALUES ($1, $2, $3, $4, $5)
     RETURNING *`,
    [ref[0].id, alert_type, threshold, notes || null, session.username]
  );

  return NextResponse.json({ success: true, data: result[0] });
}

export async function PUT(request: NextRequest) {
  const session = await getSession(request);
  if (!session) {
    return NextResponse.json(
      { success: false, error: { code: "UNAUTHORIZED", message: "Login required" } },
      { status: 401 }
    );
  }

  const { id, is_active } = await request.json();

  if (!id || is_active === undefined) {
    return NextResponse.json(
      { success: false, error: { code: "MISSING_PARAMS", message: "id and is_active required" } },
      { status: 400 }
    );
  }

  await query(
    "UPDATE price_alert_rule SET is_active = $1 WHERE id = $2",
    [is_active, id]
  );

  return NextResponse.json({ success: true, data: { id, is_active } });
}