gigafibre-fsm/apps/ops/src/api/reports.js
louispaulb 512c4a5f1b feat(ops): dispatch auto complet + perf Boîte/rapports + fix session
Planificateur « Suggérer » : 4 stratégies (smart / meilleurs d'abord / équilibré /
juste ce qu'il faut), compétences+niveaux par tech (édition inline), niveau requis
par compétence + par job, carte des tournées (1 couleur/tech, domicile→arrêts,
sélecteur de jour), fenêtre de dispatch auj.+demain (dates sélectionnées), règle
week-end + placeholder « en attente du quart », clustering + lasso + filtre-date
sur la carte, accès rapide « À assigner » (badge).

Boîte : liste /conversations allégée (45 Mo → ~1 Mo, 17×) + messages chargés à
l'ouverture. Rapports : cache SWR sur revenue-explorer (22×). Session : keep-alive
+ timeout fetch global + authFetch durci → fin des rechargements manuels.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 08:49:35 -04:00

114 lines
4.3 KiB
JavaScript

/**
* Report API — calls targo-hub /reports/* endpoints
* (hub proxies to ERPNext GL Entry / Sales Invoice)
*/
import { HUB_URL as HUB } from 'src/config/hub'
async function hubFetch (path) {
const res = await fetch(HUB + path)
if (!res.ok) throw new Error('Report API error: ' + res.status)
return res.json()
}
/**
* Per-address provider lookup (Québec IHV open data) for a batch of addresses.
* @param {Array<{key,address1,city,zip}>} items (max 80 per call)
* @returns {Promise<{results: Record<string, {matched,etat_label,providers,cogeco}>}>}
*/
export async function lookupServiceabilityBatch (items) {
const res = await fetch(HUB + '/serviceability/lookup-batch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items }),
})
if (!res.ok) throw new Error('Serviceability API error: ' + res.status)
return res.json()
}
/**
* Revenue report — GL entries grouped by Income account and month
* @param {string} start YYYY-MM-DD
* @param {string} end YYYY-MM-DD
*/
export function fetchRevenueReport (start, end, { mode = 'gl', filter = '' } = {}) {
let url = `/reports/revenue?start=${start}&end=${end}&mode=${mode}`
if (filter) url += `&filter=${encodeURIComponent(filter)}`
return hubFetch(url)
}
/**
* Sales report — Sales Invoices with TPS/TVQ breakdown
*/
export function fetchSalesReport (start, end) {
return hubFetch(`/reports/sales?start=${start}&end=${end}`)
}
/**
* Tax report — TPS/TVQ collected vs paid per period
* @param {string} period 'monthly' | 'quarterly'
*/
export function fetchTaxReport (start, end, period = 'monthly') {
return hubFetch(`/reports/taxes?start=${start}&end=${end}&period=${period}`)
}
/**
* Accounts Receivable aging report
*/
export function fetchARReport (asOf) {
return hubFetch(`/reports/ar?as_of=${asOf}`)
}
/**
* Fetch accounts list
*/
export function fetchAccounts (type = 'Income') {
return hubFetch(`/reports/accounts?type=${type}`)
}
// ── Legacy MariaDB analytical reports ──────────────────────────────────────
/**
* Overpriced-Internet report — residential/commercial service addresses whose
* net MONTHLY Internet bill (plan + recurring discounts, annual plans
* normalized /12) exceeds a threshold. Queries the legacy gestionclient DB.
*
* @param {object} opts
* @param {number} opts.threshold $ floor (default 90)
* @param {string} opts.segment 'residential' | 'commercial' | 'all'
* @param {boolean} opts.addons include IP fixe / extra download / point-to-point
*/
export function fetchOverpricedInternet ({ threshold = 90, segment = 'residential', addons = true, limit = 2000 } = {}) {
const qs = new URLSearchParams({
threshold: String(threshold), segment, addons: addons ? '1' : '0', limit: String(limit),
})
return hubFetch(`/reports/legacy/overpriced-internet?${qs}`)
}
/** Direct CSV download URL for the same report (browser <a download>). */
export function overpricedInternetCsvUrl ({ threshold = 90, segment = 'residential', addons = true } = {}) {
const qs = new URLSearchParams({
threshold: String(threshold), segment, addons: addons ? '1' : '0',
})
return `${HUB}/reports/legacy/overpriced-internet.csv?${qs}`
}
/**
* Explorateur de revenus — MRR net récurrent regroupé par DIMENSION (un seul rapport,
* critères ajoutables). Remplace les rapports F fixes (par service / code postal / ville / segment).
* @param {object} opts { dimension:'category|zip|city|segment|plan', segment, type:'internet|tv|phone|all', active, threshold, limit }
*/
export function fetchRevenueExplorer ({ dimension = 'category', segment = 'all', type = 'all', active = true, threshold = 0, limit = 300 } = {}) {
const qs = new URLSearchParams({
dimension, segment, type, active: active ? '1' : '0', threshold: String(threshold), limit: String(limit),
})
return hubFetch(`/reports/legacy/revenue-explorer?${qs}`)
}
/** URL CSV directe pour l'explorateur de revenus (mêmes critères). */
export function revenueExplorerCsvUrl ({ dimension = 'category', segment = 'all', type = 'all', active = true, threshold = 0 } = {}) {
const qs = new URLSearchParams({
dimension, segment, type, active: active ? '1' : '0', threshold: String(threshold),
})
return `${HUB}/reports/legacy/revenue-explorer.csv?${qs}`
}