chore: upload parte 1 - logica
DevSecOps Enterprise Pipeline / security-gate-and-deploy (push) Failing after 41s
DevSecOps Enterprise Pipeline / security-gate-and-deploy (push) Failing after 41s
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { getDb } from "@/lib/db";
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const sql = getDb();
|
||||
const { searchParams } = new URL(request.url);
|
||||
const componentId = searchParams.get("componentId");
|
||||
const search = searchParams.get("search");
|
||||
const type = searchParams.get("type");
|
||||
const limit = Math.min(Number(searchParams.get("limit") || 50), 200);
|
||||
const offset = Number(searchParams.get("offset") || 0);
|
||||
|
||||
let query = `
|
||||
SELECT
|
||||
st.*,
|
||||
c.name AS component_name,
|
||||
c.part_number,
|
||||
cat.name AS category_name
|
||||
FROM stock_transactions st
|
||||
JOIN components c ON st.component_id = c.id
|
||||
LEFT JOIN categories cat ON c.category_id = cat.id
|
||||
WHERE 1=1
|
||||
`;
|
||||
const params: (string | number)[] = [];
|
||||
let paramIdx = 1;
|
||||
|
||||
if (componentId) {
|
||||
query += ` AND st.component_id = $${paramIdx++}`;
|
||||
params.push(Number(componentId));
|
||||
}
|
||||
|
||||
if (search) {
|
||||
query += ` AND (c.name ILIKE $${paramIdx} OR c.part_number ILIKE $${paramIdx})`;
|
||||
params.push(`%${search}%`);
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
if (type && type !== "all") {
|
||||
query += ` AND st.transaction_type = $${paramIdx++}`;
|
||||
params.push(type);
|
||||
}
|
||||
|
||||
query += ` ORDER BY st.created_at DESC LIMIT $${paramIdx++} OFFSET $${paramIdx++}`;
|
||||
params.push(limit, offset);
|
||||
|
||||
const rows = await sql(query, params);
|
||||
|
||||
// Also get total count for pagination
|
||||
let countQuery = `
|
||||
SELECT COUNT(*) as total
|
||||
FROM stock_transactions st
|
||||
JOIN components c ON st.component_id = c.id
|
||||
WHERE 1=1
|
||||
`;
|
||||
const countParams: (string | number)[] = [];
|
||||
let countIdx = 1;
|
||||
|
||||
if (componentId) {
|
||||
countQuery += ` AND st.component_id = $${countIdx++}`;
|
||||
countParams.push(Number(componentId));
|
||||
}
|
||||
if (search) {
|
||||
countQuery += ` AND (c.name ILIKE $${countIdx} OR c.part_number ILIKE $${countIdx})`;
|
||||
countParams.push(`%${search}%`);
|
||||
countIdx++;
|
||||
}
|
||||
if (type && type !== "all") {
|
||||
countQuery += ` AND st.transaction_type = $${countIdx++}`;
|
||||
countParams.push(type);
|
||||
}
|
||||
|
||||
const countResult = await sql(countQuery, countParams);
|
||||
|
||||
return NextResponse.json({
|
||||
transactions: rows,
|
||||
total: Number(countResult[0].total),
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const sql = getDb();
|
||||
const body = await request.json();
|
||||
const {
|
||||
component_id,
|
||||
transaction_type,
|
||||
quantity,
|
||||
unit_cost,
|
||||
supplier,
|
||||
supplier_order_ref,
|
||||
notes,
|
||||
} = body;
|
||||
|
||||
if (!component_id || !transaction_type || !quantity) {
|
||||
return NextResponse.json(
|
||||
{ error: "component_id, transaction_type, and quantity are required" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Validate supplier_order_ref if provided - must match an existing PO
|
||||
if (supplier_order_ref && supplier_order_ref.trim()) {
|
||||
const poCheck = await sql(
|
||||
`SELECT id FROM supplier_pos WHERE po_number = $1`,
|
||||
[supplier_order_ref.trim()]
|
||||
);
|
||||
if (poCheck.length === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: `Purchase order "${supplier_order_ref}" not found. Please select a valid PO or leave the field empty.` },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const total_cost = unit_cost ? Number(unit_cost) * Number(quantity) : null;
|
||||
|
||||
// Insert the stock transaction record
|
||||
const insertParams = [
|
||||
component_id,
|
||||
transaction_type,
|
||||
Number(quantity),
|
||||
unit_cost ? Number(unit_cost) : null,
|
||||
total_cost,
|
||||
supplier || null,
|
||||
supplier_order_ref || null,
|
||||
notes || null,
|
||||
];
|
||||
const rows = await sql(
|
||||
`INSERT INTO stock_transactions (component_id, transaction_type, quantity, unit_cost, total_cost, supplier, supplier_order_ref, notes)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING *`,
|
||||
insertParams
|
||||
);
|
||||
|
||||
// Update the component's stock_quantity
|
||||
const qtyChange =
|
||||
transaction_type === "consumption"
|
||||
? -Math.abs(Number(quantity))
|
||||
: Math.abs(Number(quantity));
|
||||
|
||||
await sql(
|
||||
`UPDATE components SET stock_quantity = stock_quantity + $1, updated_at = NOW() WHERE id = $2`,
|
||||
[qtyChange, component_id]
|
||||
);
|
||||
|
||||
return NextResponse.json(rows[0], { status: 201 });
|
||||
}
|
||||
Reference in New Issue
Block a user