/** * Client HTTP per ar1-compiler (microservizio BFLOWS). * Il microservizio valida lo stesso JWT di GEPAFIN-BE (HS512 shared secret). * * Env var: REACT_APP_AR1_API_URL (es. http://78.46.41.91:18091) * * Pattern replicato 1:1 da rendicontazioneService.js. */ import { storeGet } from '../../../store'; const BASE_URL = process.env.REACT_APP_AR1_API_URL || ''; const buildHeaders = () => { const token = storeGet('getToken'); const h = { 'Content-Type': 'application/json' }; if (token) h['Authorization'] = `Bearer ${token}`; return h; }; const buildHeadersMultipart = () => { const token = storeGet('getToken'); const h = {}; if (token) h['Authorization'] = `Bearer ${token}`; return h; }; const handleResponse = async (response, onSuccess, onError) => { let body = null; try { body = await response.json(); } catch (e) { body = { detail: response.statusText }; } if (response.status >= 200 && response.status < 300) { if (onSuccess) onSuccess(body); } else { if (onError) onError({ status: response.status, ...body }); } }; const handleError = (err, onError) => { if (onError) onError({ status: 0, detail: err.message }); }; const Ar1Service = { // ---------- Status pubblico (per compliance modal) ---------- getStatusForCompany(companyId, onSuccess, onError) { fetch(`${BASE_URL}/public/ar1-status/${companyId}`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, // ---------- CRUD form beneficiario ---------- createDraft(companyId, variant, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms`, { method: 'POST', mode: 'cors', headers: buildHeaders(), body: JSON.stringify({ company_id: companyId, variant }) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, getForm(formId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, listFormsForCompany(companyId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/company/${companyId}`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, updateQuadri(formId, quadriPatch, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}/quadri`, { method: 'PUT', mode: 'cors', headers: buildHeaders(), body: JSON.stringify({ quadri: quadriPatch }) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, submitForSignature(formId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}/submit-for-signature`, { method: 'PUT', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, deleteForm(formId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}`, { method: 'DELETE', mode: 'cors', headers: buildHeaders() }).then(r => { if (r.status === 204) { if (onSuccess) onSuccess({}); } else handleResponse(r, onSuccess, onError); }).catch(e => handleError(e, onError)); }, // ---------- PDF ---------- generatePdf(formId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}/generate-pdf`, { method: 'POST', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, downloadPdfUnsigned(formId) { return fetch(`${BASE_URL}/api/ar1-forms/${formId}/pdf-unsigned`, { method: 'GET', mode: 'cors', headers: buildHeadersMultipart() }).then(r => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.blob(); }); }, downloadPdfSigned(formId) { return fetch(`${BASE_URL}/api/ar1-forms/${formId}/pdf-signed`, { method: 'GET', mode: 'cors', headers: buildHeadersMultipart() }).then(r => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.blob(); }); }, // ---------- Firma ---------- uploadSignature(formId, fileObject, onSuccess, onError) { const formData = new FormData(); formData.append('file', fileObject); fetch(`${BASE_URL}/api/ar1-forms/${formId}/upload-signature`, { method: 'POST', mode: 'cors', headers: buildHeadersMultipart(), body: formData }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, reVerifySignature(formId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}/verify`, { method: 'POST', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, archiveToCompanyDocument(formId, onSuccess, onError) { fetch(`${BASE_URL}/api/ar1-forms/${formId}/archive-to-company-document`, { method: 'POST', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, // ---------- ADMIN: templates ---------- listTemplates(onSuccess, onError, queryParams) { const qs = queryParams ? ('?' + new URLSearchParams(queryParams).toString()) : ''; fetch(`${BASE_URL}/admin/ar1-templates${qs}`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, getTemplateDetail(templateId, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-templates/${templateId}`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, updateTemplateLayout(templateId, layoutConfig, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-templates/${templateId}/layout-config`, { method: 'PUT', mode: 'cors', headers: buildHeaders(), body: JSON.stringify({ layout_config: layoutConfig }) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, createNewTemplateVersion(variant, payload, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-templates/${variant}/new-version`, { method: 'POST', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(payload) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, // ---------- ADMIN: policy ---------- getPolicy(onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-policy`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, updatePolicy(patch, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-policy`, { method: 'PUT', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(patch) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, // ---------- ADMIN: pec-schedule-config ---------- listPecSchedule(onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-pec-schedule-config`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, createPecRule(payload, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-pec-schedule-config`, { method: 'POST', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(payload) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, updatePecRule(ruleId, payload, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-pec-schedule-config/${ruleId}`, { method: 'PUT', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(payload) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, deletePecRule(ruleId, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-pec-schedule-config/${ruleId}`, { method: 'DELETE', mode: 'cors', headers: buildHeaders() }).then(r => { if (r.status === 204) { if (onSuccess) onSuccess({}); } else handleResponse(r, onSuccess, onError); }).catch(e => handleError(e, onError)); }, // ---------- ADMIN: bulk PEC ---------- bulkRequestRecompilation(payload, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-forms/bulk-request-recompilation`, { method: 'POST', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(payload) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, // ---------- ADMIN: document categories (per dropdown) ---------- previewTemplatePdf(templateId) { return fetch(`${BASE_URL}/admin/ar1-templates/${templateId}/preview-pdf`, { method: 'POST', mode: 'cors', headers: buildHeadersMultipart() }).then(r => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.blob(); }); }, listDocumentCategories(onSuccess, onError) { fetch(`${BASE_URL}/admin/document-categories`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, // ---------- ADMIN: email templates (Opzione 3 — tenant-agnostic, BE Gepafin pull) ---------- listEmailTemplates(onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-email-templates`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, getEmailTemplate(kind, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-email-templates/${kind}`, { method: 'GET', mode: 'cors', headers: buildHeaders() }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, updateEmailTemplate(kind, payload, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-email-templates/${kind}`, { method: 'PUT', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(payload) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, previewEmailTemplate(kind, mockVars, onSuccess, onError) { fetch(`${BASE_URL}/admin/ar1-email-templates/${kind}/preview`, { method: 'POST', mode: 'cors', headers: buildHeaders(), body: JSON.stringify(mockVars || {}) }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError)); }, }; export default Ar1Service;