livrare lot 2
This commit is contained in:
commit
8ecc78e729
763 changed files with 164593 additions and 0 deletions
|
|
@ -0,0 +1,359 @@
|
|||
/**
|
||||
* Validation Rules Routes - FULL CRUD
|
||||
*
|
||||
* Validation rules are leaf nodes - no children, can be deleted directly
|
||||
* technique -> technique_validation_rule
|
||||
*/
|
||||
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { query, queryOne, transaction } from '../config/database';
|
||||
import { TechniqueValidationRule, ApiResponse } from '../types';
|
||||
import { PoolClient } from 'pg';
|
||||
import { internalError } from '../config/error-response';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Parameter type for validation rules
|
||||
const PARAMETER_TYPE_VALIDATION_RULE = 5;
|
||||
|
||||
// Helper: Create parameter entry
|
||||
const createParameter = async (client: PoolClient): Promise<number> => {
|
||||
const maxResult = await client.query('SELECT COALESCE(MAX(parameter_id), 0) + 1 as next_id FROM parameter');
|
||||
const nextParamId = maxResult.rows[0].next_id;
|
||||
|
||||
await client.query(`
|
||||
INSERT INTO parameter (parameter_id, parameter_type, valid_from, valid_to, created_date, updated_date)
|
||||
VALUES ($1, $2, '2026-01-01', '2999-01-01', CURRENT_DATE, CURRENT_DATE)
|
||||
`, [nextParamId, PARAMETER_TYPE_VALIDATION_RULE]);
|
||||
|
||||
return nextParamId;
|
||||
};
|
||||
|
||||
// Helper: Get next rule_id
|
||||
const getNextRuleId = async (client: PoolClient): Promise<number> => {
|
||||
const result = await client.query('SELECT COALESCE(MAX(technique_valid_rule_id), 0) + 1 as next_id FROM technique_validation_rule');
|
||||
return result.rows[0].next_id;
|
||||
};
|
||||
|
||||
// GET all validation rules
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const rules = await query<TechniqueValidationRule>(
|
||||
'SELECT * FROM technique_validation_rule ORDER BY technique_id, technique_valid_rule_id'
|
||||
);
|
||||
res.json({
|
||||
success: true,
|
||||
data: rules,
|
||||
count: rules.length
|
||||
} as ApiResponse<TechniqueValidationRule[]>);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
} as ApiResponse<never>);
|
||||
}
|
||||
});
|
||||
|
||||
// GET validation rules with technique info
|
||||
router.get('/with-techniques', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const rules = await query<TechniqueValidationRule & { technique_name: string }>(`
|
||||
SELECT r.*, t.technique_name
|
||||
FROM technique_validation_rule r
|
||||
JOIN technique t ON r.technique_id = t.technique_id
|
||||
ORDER BY r.technique_id, r.technique_valid_rule_id
|
||||
`);
|
||||
res.json({
|
||||
success: true,
|
||||
data: rules,
|
||||
count: rules.length
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// GET validation rules by technique_id
|
||||
router.get('/by-technique/:techniqueId', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const rules = await query<TechniqueValidationRule>(
|
||||
'SELECT * FROM technique_validation_rule WHERE technique_id = $1 ORDER BY technique_valid_rule_id',
|
||||
[req.params.techniqueId]
|
||||
);
|
||||
res.json({
|
||||
success: true,
|
||||
data: rules,
|
||||
count: rules.length
|
||||
} as ApiResponse<TechniqueValidationRule[]>);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
} as ApiResponse<never>);
|
||||
}
|
||||
});
|
||||
|
||||
// GET stats — declarat înainte de '/:id', altfel 'stats' e capturat ca :id
|
||||
router.get('/stats', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const stats = await query<any>(`
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM technique) as total_techniques,
|
||||
(SELECT COUNT(DISTINCT technique_id) FROM technique_validation_rule) as techniques_with_rules,
|
||||
(SELECT COUNT(*) FROM technique_validation_rule) as total_rules,
|
||||
(SELECT COUNT(*) FROM technique WHERE technique_id NOT IN (SELECT DISTINCT technique_id FROM technique_validation_rule)) as techniques_missing_rules
|
||||
`);
|
||||
res.json({
|
||||
success: true,
|
||||
data: stats[0]
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// GET single validation rule by ID
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const rule = await queryOne<TechniqueValidationRule>(
|
||||
'SELECT * FROM technique_validation_rule WHERE technique_valid_rule_id = $1',
|
||||
[req.params.id]
|
||||
);
|
||||
|
||||
if (!rule) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Regula de validare nu a fost găsită'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: rule
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// POST - Create single validation rule
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { technique_id, rule_name, rule_value, description } = req.body;
|
||||
|
||||
// Validation
|
||||
if (!technique_id || !rule_name || !rule_value) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Câmpuri obligatorii: technique_id, rule_name, rule_value'
|
||||
});
|
||||
}
|
||||
|
||||
// Verify technique exists
|
||||
const technique = await queryOne('SELECT technique_id FROM technique WHERE technique_id = $1', [technique_id]);
|
||||
if (!technique) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Tehnica specificată nu există'
|
||||
});
|
||||
}
|
||||
|
||||
const result = await transaction(async (client) => {
|
||||
// Create parameter entry
|
||||
const parameterId = await createParameter(client);
|
||||
|
||||
// Get next rule ID
|
||||
const ruleId = await getNextRuleId(client);
|
||||
|
||||
// Insert rule
|
||||
const insertResult = await client.query(`
|
||||
INSERT INTO technique_validation_rule (technique_valid_rule_id, technique_id, rule_name, rule_value, description, parameter_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *
|
||||
`, [ruleId, technique_id, rule_name, rule_value, description || '', parameterId]);
|
||||
|
||||
return insertResult.rows[0];
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
data: result,
|
||||
message: 'Regula de validare a fost creată cu succes'
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// POST /bulk-for-technique - Create multiple rules for a single technique
|
||||
router.post('/bulk-for-technique/:techniqueId', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const techniqueId = parseInt(req.params.techniqueId);
|
||||
const { rules } = req.body;
|
||||
|
||||
if (!rules || !Array.isArray(rules) || rules.length === 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Câmp obligatoriu: rules (array de {rule_name, rule_value, description})'
|
||||
});
|
||||
}
|
||||
|
||||
// Verify technique exists
|
||||
const technique = await queryOne('SELECT technique_id FROM technique WHERE technique_id = $1', [techniqueId]);
|
||||
if (!technique) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Tehnica specificată nu există'
|
||||
});
|
||||
}
|
||||
|
||||
const result = await transaction(async (client) => {
|
||||
const created: any[] = [];
|
||||
|
||||
for (const rule of rules) {
|
||||
if (!rule.rule_name || !rule.rule_value) {
|
||||
throw new Error(`Regulă invalidă: ${JSON.stringify(rule)}. Obligatoriu: rule_name, rule_value`);
|
||||
}
|
||||
|
||||
// Create parameter entry
|
||||
const parameterId = await createParameter(client);
|
||||
|
||||
// Get next rule ID
|
||||
const ruleId = await getNextRuleId(client);
|
||||
|
||||
// Insert rule
|
||||
const insertResult = await client.query(`
|
||||
INSERT INTO technique_validation_rule (technique_valid_rule_id, technique_id, rule_name, rule_value, description, parameter_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *
|
||||
`, [ruleId, techniqueId, rule.rule_name, rule.rule_value, rule.description || '', parameterId]);
|
||||
|
||||
created.push(insertResult.rows[0]);
|
||||
}
|
||||
|
||||
return created;
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
data: result,
|
||||
count: result.length,
|
||||
message: `${result.length} reguli de validare au fost create cu succes`
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// PUT - Update validation rule
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
const { technique_id, rule_name, rule_value, description } = req.body;
|
||||
|
||||
// Check if rule exists
|
||||
const existing = await queryOne<TechniqueValidationRule>(
|
||||
'SELECT * FROM technique_validation_rule WHERE technique_valid_rule_id = $1',
|
||||
[id]
|
||||
);
|
||||
|
||||
if (!existing) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Regula de validare nu a fost găsită'
|
||||
});
|
||||
}
|
||||
|
||||
// If changing technique_id, verify it exists
|
||||
if (technique_id) {
|
||||
const technique = await queryOne('SELECT technique_id FROM technique WHERE technique_id = $1', [technique_id]);
|
||||
if (!technique) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Tehnica specificată nu există'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const result = await queryOne<TechniqueValidationRule>(`
|
||||
UPDATE technique_validation_rule
|
||||
SET technique_id = COALESCE($1, technique_id),
|
||||
rule_name = COALESCE($2, rule_name),
|
||||
rule_value = COALESCE($3, rule_value),
|
||||
description = COALESCE($4, description)
|
||||
WHERE technique_valid_rule_id = $5
|
||||
RETURNING *
|
||||
`, [technique_id, rule_name, rule_value, description, id]);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
message: 'Regula de validare a fost actualizată cu succes'
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE - Delete single validation rule
|
||||
router.delete('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
|
||||
// Check if rule exists
|
||||
const existing = await queryOne<TechniqueValidationRule>(
|
||||
'SELECT * FROM technique_validation_rule WHERE technique_valid_rule_id = $1',
|
||||
[id]
|
||||
);
|
||||
|
||||
if (!existing) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Regula de validare nu a fost găsită'
|
||||
});
|
||||
}
|
||||
|
||||
// Delete (leaf node - no children to check)
|
||||
await query('DELETE FROM technique_validation_rule WHERE technique_valid_rule_id = $1', [id]);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Regula de validare a fost ștearsă cu succes',
|
||||
deleted: true
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE all validation rules for a technique
|
||||
router.delete('/by-technique/:techniqueId', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const techniqueId = req.params.techniqueId;
|
||||
|
||||
// Verify technique exists
|
||||
const technique = await queryOne('SELECT technique_id FROM technique WHERE technique_id = $1', [techniqueId]);
|
||||
if (!technique) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Tehnica specificată nu există'
|
||||
});
|
||||
}
|
||||
|
||||
const result = await query<TechniqueValidationRule>(
|
||||
'DELETE FROM technique_validation_rule WHERE technique_id = $1 RETURNING *',
|
||||
[techniqueId]
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
count: result.length,
|
||||
message: `${result.length} reguli de validare au fost șterse pentru tehnica ${techniqueId}`
|
||||
});
|
||||
} catch (error) {
|
||||
internalError(res, error);
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue