Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
71a300f
Add API for IA summaries of amendments and related configurations
remikelpro Apr 25, 2026
b90f0d7
Add API for IA summaries of amendments and related configurations
remikelpro Apr 25, 2026
4249d75
Implement API for IA summaries of amendments and add filtering option…
remikelpro Apr 30, 2026
f2f8122
Remove .claude/settings.json from tracking
remikelpro May 4, 2026
a2fdf2d
Remove .claude/settings.local.json (already in .gitignore)
remikelpro May 4, 2026
266fd1d
Restore security settings and admin/api-keys routes lost during cherr…
remikelpro May 4, 2026
c875798
Change directory amendements_ia
awenig May 5, 2026
81fae35
Add review functionality for amendments and enhance API integration
remikelpro May 13, 2026
b19a629
Only keep decrypt in csrf_exclude_uris
awenig May 17, 2026
9395db1
Re-put amendements/review
awenig May 17, 2026
c487d15
Move function in another model
awenig May 17, 2026
88f870d
Same : move function in admin_model
awenig May 17, 2026
43b4020
Update Admin.php
awenig May 17, 2026
cccff00
small fixes
remikelpro May 18, 2026
99316c2
Remove because no longer with politicanalysis
awenig May 18, 2026
1ca56e7
Add data table
awenig May 18, 2026
90939a0
Improve design of table
awenig May 18, 2026
516952a
Sorting already dealt with with datatable
awenig May 18, 2026
20af245
Don't display amendments already decrypted
awenig May 18, 2026
ff7b195
Clean view
awenig May 18, 2026
f588cea
amendements_batch_summaries no longer used
awenig May 18, 2026
3571639
amendements_decrypt no longer used
awenig May 18, 2026
382c348
Seem useless to me now?
awenig May 18, 2026
cf1083e
Update .env.dist
awenig May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.git
.claude
3 changes: 2 additions & 1 deletion .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ BASE_URL=http://dev-datan.fr
API_KEY_NOBG=
API_KEY_MAILJET=
API_KEY_SECRETE_MAILJET=
COMPOSER_AUTOLOAD=application/config/autoload.php
COMPOSER_AUTOLOAD=application/config/autoload.php
POLITIC_ANALYSIS_PUBLIC_URL=
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ application/logs/*
#custom config
application/config/custom_config.php

#claude code
.claude/

#root folder
node_modules
/test
Expand Down
2 changes: 1 addition & 1 deletion application/config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
$config['csrf_exclude_uris'] = array('upload/image', 'api/.*');
$config['csrf_exclude_uris'] = array('upload/image', 'api/.*', 'admin/amendements/review');

/*
|--------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions application/config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@

// ADMIN
$route['admin'] = 'admin/index';
$route['admin/amendements'] = 'admin/amendements';
$route['admin/amendements/review'] = 'admin/amendements_review';
$route['admin/votes'] = 'admin/votes';
$route['admin/elections/modifications-mps'] = 'admin/election_modifications_mps';
$route['admin/elections/(:any)'] = 'admin/election_candidates/$1';
Expand Down Expand Up @@ -211,6 +213,8 @@
$route['api/non_decrypted_votes'] = 'api/non_decrypted_votes/index';
$route['api/non_decrypted_votes/meta'] = 'api/non_decrypted_votes/meta';
$route['api/non_decrypted_votes/(:any)'] = 'api/non_decrypted_votes/index/$1';
// Résumés IA des amendements (écriture depuis PoliticAnalysis)
$route['api/amendements_ia'] = 'api/amendements_ia/index';
// Exposés des motifs
$route['api/exposes'] = 'api/exposes/index';
$route['api/exposes/meta'] = 'api/exposes/meta';
Expand Down
81 changes: 80 additions & 1 deletion application/controllers/Admin.php
Comment thread
awenig marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
class Admin extends Auth_Controller {
class Admin extends Auth_Controller{

public function __construct() {
parent::__construct();
Expand Down Expand Up @@ -963,5 +963,84 @@ public function api_keys_revoke($id)
$this->session->set_flashdata('success', 'Clé API révoquée avec succès');
redirect('admin/api-keys');
}

public function amendements()
{
$data = $this->data;

$sort = $this->input->get('sort') ?: 'date';
$direction = $this->input->get('direction') ?: 'DESC';

$period = $this->input->get('period');
$date_start = $this->input->get('date_start');
$date_end = $this->input->get('date_end');
$hide_reviewed = filter_var($this->input->get('hide_reviewed'), FILTER_VALIDATE_BOOLEAN);

$allowed_periods = array('all', '7', '30', '90', '180', '365');
if (!in_array($period, $allowed_periods, true)) {
$period = 'all';
}

$valid_date = function ($d) {
return $d && preg_match('/^\d{4}-\d{2}-\d{2}$/', $d);
};
$date_start = $valid_date($date_start) ? $date_start : '';
$date_end = $valid_date($date_end) ? $date_end : '';

$filters = array(
'period' => $period,
'date_start' => $date_start,
'date_end' => $date_end,
'hide_reviewed' => $hide_reviewed,
);

$data['amendements'] = $this->admin_model->get_amendements_list($sort, $direction, $filters);
$data['sort'] = $sort;
$data['direction'] = $direction;
$data['period'] = $period;
$data['date_start'] = $date_start;
$data['date_end'] = $date_end;
$data['hide_reviewed'] = $hide_reviewed;
$data['title'] = 'Liste des amendements';
$data['pa_public_url'] = rtrim($_SERVER['POLITIC_ANALYSIS_PUBLIC_URL'] ?? '', '/');

$data['title_meta'] = 'Amendements - Dashboard | Datan';
$data['breadcrumb'] = array(
array('name' => 'Dashboard', 'url' => base_url() . 'admin', 'active' => FALSE),
array('name' => 'Amendements', 'url' => base_url() . 'admin/amendements', 'active' => TRUE),
);

$this->load->view('dashboard/header', $data);
$this->load->view('dashboard-mp/amendements/index', $data);
$this->load->view('dashboard/footer');
}

public function amendements_review()
{
if ($this->input->method(TRUE) !== 'POST') {
show_404();
}

$legislature = (int) $this->input->post('legislature');
$voteNumero = (string)$this->input->post('voteNumero');
$reviewed = filter_var($this->input->post('reviewed'), FILTER_VALIDATE_BOOLEAN);

if (!$legislature || !$voteNumero) {
$this->output->set_status_header(400)->set_content_type('application/json')
->set_output(json_encode(['error' => 'legislature et voteNumero sont requis']));
return;
}

$ok = $this->admin_model->set_amendement_reviewed($legislature, $voteNumero, $reviewed);

if (!$ok) {
$this->output->set_status_header(500)->set_content_type('application/json')
->set_output(json_encode(['error' => "Échec de l'enregistrement (vérifier que la table amendements_ia et sa clé unique uk_leg_vote existent)"]));
return;
}

$this->output->set_status_header(200)->set_content_type('application/json')
->set_output(json_encode(['success' => true, 'reviewed' => $reviewed ? 1 : 0]));
}
}
?>
126 changes: 126 additions & 0 deletions application/models/Admin_model.php
Comment thread
awenig marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,130 @@ public function table_changes($table, $toInsert){
);
$this->db->insert('table_changes', $data);
}

/**
* Liste les votes de type amendement de la dernière législature,
* avec résumé IA, score de simplicité et statut de décryptage.
*
* @param string $sort Colonne de tri : 'date'|'votants'|'disparite'|'simplicite'|'decrypte'
* @param string $direction 'ASC'|'DESC'
* @param array $filters ['period' => '7'|'30'|'90'|'180'|'365'|'all',
* 'date_start' => 'YYYY-MM-DD',
* 'date_end' => 'YYYY-MM-DD']
*/
public function get_amendements_list($sort = 'date', $direction = 'DESC', $filters = array())
{
$allowed_sorts = array(
'date' => 'vi.dateScrutin',
'votants' => 'vi.nombreVotants',
'disparite' => 'disparite',
'interet' => 'interet',
'simplicite' => 'aia.simplicite_ia',
'decrypte' => 'decrypte',
);

$order_col = isset($allowed_sorts[$sort]) ? $allowed_sorts[$sort] : 'vi.dateScrutin';
$direction = strtoupper($direction) === 'ASC' ? 'ASC' : 'DESC';

// Dernière législature disponible
$last_leg = $this->db->query('SELECT MAX(legislature) AS leg FROM votes_info')->row_array();
$legislature = $last_leg['leg'] ?? 17;

// Filtres date
$where_date = '';
$params = array($legislature);

$period = isset($filters['period']) ? (string)$filters['period'] : 'all';
$date_start = isset($filters['date_start']) ? (string)$filters['date_start'] : '';
$date_end = isset($filters['date_end']) ? (string)$filters['date_end'] : '';

$is_valid_date = function ($d) {
return $d && preg_match('/^\d{4}-\d{2}-\d{2}$/', $d);
};

if ($is_valid_date($date_start) || $is_valid_date($date_end)) {
if ($is_valid_date($date_start)) {
$where_date .= ' AND vi.dateScrutin >= ?';
$params[] = $date_start;
}
if ($is_valid_date($date_end)) {
$where_date .= ' AND vi.dateScrutin <= ?';
$params[] = $date_end;
}
} elseif (in_array($period, array('7', '30', '90', '180', '365'), true)) {
$where_date = ' AND vi.dateScrutin >= DATE_SUB(CURDATE(), INTERVAL ? DAY)';
$params[] = (int)$period;
}

// Filtre "cacher les reviewed"
$where_reviewed = '';
if (!empty($filters['hide_reviewed'])) {
$where_reviewed = ' AND COALESCE(aia.reviewed, 0) = 0';
}

$sql = "
SELECT
vi.voteNumero,
vi.legislature,
vi.dateScrutin,
date_format(vi.dateScrutin, '%d/%m/%Y') AS dateScrutinFR,
vi.nombreVotants,
vi.decomptePour AS pour,
vi.decompteContre AS contre,
vi.decompteAbs AS abstention,
CASE
WHEN vi.nombreVotants > 0
THEN ROUND(ABS(vi.decomptePour - vi.decompteContre) * 100 / vi.nombreVotants, 1)
ELSE 0
END AS disparite,
CASE
WHEN vi.nombreVotants > 0
THEN ROUND(
LEAST(vi.nombreVotants / 250, 1)
* (1 - ABS(vi.decomptePour - vi.decompteContre) / vi.nombreVotants)
* 100, 1)
ELSE 0
END AS interet,
aia.titre_ia,
aia.resume_ia,
aia.simplicite_ia,
COALESCE(aia.reviewed, 0) AS reviewed,
COALESCE(vd.title, vi.titre, vi.seanceRef) AS titre
FROM votes_info vi
LEFT JOIN amendements_ia aia
ON aia.voteNumero = vi.voteNumero AND aia.legislature = vi.legislature
LEFT JOIN votes_datan vd
ON vd.voteNumero = vi.voteNumero AND vd.legislature = vi.legislature
WHERE vi.voteType IN ('amendement', 'les amen')
AND vi.legislature = ?
AND vd.id IS NULL
$where_date
$where_reviewed
ORDER BY $order_col $direction
";

return $this->db->query($sql, $params)->result_array();
}

/**
* Marque un amendement comme reviewed (ou non).
* Crée la ligne dans amendements_ia si elle n'existe pas encore.
*
* @return bool true si la requête a réussi, false en cas d'erreur SQL
*/
public function set_amendement_reviewed($legislature, $voteNumero, $reviewed)
{
$legislature = (int) $legislature;
$voteNumero = (string) $voteNumero;
$reviewed = $reviewed ? 1 : 0;

$ok = $this->db->query(
"INSERT INTO amendements_ia (legislature, voteNumero, reviewed)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE reviewed = VALUES(reviewed), updated_at = NOW()",
array($legislature, $voteNumero, $reviewed)
);

return $ok !== FALSE;
}
}
4 changes: 4 additions & 0 deletions application/models/Api_key_model.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public function get_available_endpoints()
'/api/non_decrypted_votes' => array(
'GET' => 'Lister les votes non décryptés'
),
// Résumés IA des amendements (écriture depuis PoliticAnalysis)
'/api/amendements_ia' => array(
'POST' => "Créer/mettre à jour un résumé IA d'amendement"
),
// Exposés des motifs
'/api/exposes' => array(
'GET' => 'Lister les exposés',
Expand Down
1 change: 0 additions & 1 deletion application/models/DashboardMP_model.php
Comment thread
awenig marked this conversation as resolved.
Comment thread
awenig marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public function get_votes_explained($mpId, $published = NULL){
}

public function get_vote_explained($mpId, $legislature, $voteNumero){
echo $voteNumero;
$sql = 'SELECT e.id, e.voteNumero, e.legislature, e.text AS explication, vd.title AS vote_titre,
CASE WHEN e.state = 1 THEN "publié" ELSE "brouillon" END AS state,
CASE
Expand Down
Loading