chore: upload parte 1 - logica
DevSecOps Enterprise Pipeline / security-gate-and-deploy (push) Failing after 41s

This commit is contained in:
2026-06-01 15:35:53 +01:00
parent a63625d228
commit 9c14a19a87
127 changed files with 22255 additions and 0 deletions
+146
View File
@@ -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 });
}