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>
114 lines
4.3 KiB
JavaScript
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}`
|
|
}
|