From c757bc8a7f24788c0512d98afc865aadd420440d Mon Sep 17 00:00:00 2001
From: "Fabien F."
Date: Tue, 4 Aug 2026 16:39:28 +0200
Subject: [PATCH 1/3] fix(web): nommer le seuil par ce qu'il montre, pas par la
puce qu'il donne
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
« Tuiles minimum pour donner sa puce à une catégorie » demandait au lecteur de
savoir ce qu'est une puce avant de comprendre le réglage. La phrase d'aide juste
en dessous l'explique déjà, et c'est sa place.
Deux fichiers parce que la barre de refus nomme le champ sans le panneau qui le
surmonte : fields.ts est la seule source de ce nom-là, l'étiquette de la page en
est la copie sous son propre titre.
---
web/src/admin/lib/fields.ts | 2 +-
web/src/admin/pages/Catalog.svelte | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/web/src/admin/lib/fields.ts b/web/src/admin/lib/fields.ts
index 5f28d1a..b4d733a 100644
--- a/web/src/admin/lib/fields.ts
+++ b/web/src/admin/lib/fields.ts
@@ -29,7 +29,7 @@ export const FIELD_LABELS: Readonly> = {
'ui.show_grid_prices': 'Afficher les prix sur les tuiles',
'ui.show_by_unit_products': 'Afficher les produits vendus à l’unité',
'ui.grid_columns': 'Colonnes de la grille',
- 'ui.min_products_for_chip': 'Tuiles minimum pour donner sa puce à une catégorie',
+ 'ui.min_products_for_chip': 'Articles minimum pour afficher une catégorie',
'scale.type': 'Protocole de la balance',
'scale.present': 'Ce poste a une balance',
diff --git a/web/src/admin/pages/Catalog.svelte b/web/src/admin/pages/Catalog.svelte
index 3711596..deff45a 100644
--- a/web/src/admin/pages/Catalog.svelte
+++ b/web/src/admin/pages/Catalog.svelte
@@ -879,7 +879,7 @@
Date: Tue, 4 Aug 2026 16:39:54 +0200
Subject: [PATCH 2/3] =?UTF-8?q?fix(catalog):=20un=20code-barres=20mang?=
=?UTF-8?q?=C3=A9=20par=20un=20tableur=20le=20dit,=20au=20lieu=20de=20comp?=
=?UTF-8?q?ter=20ses=20caract=C3=A8res?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signalé depuis le poste, sur le plan de travail « à corriger dans Odoo » :
« Corriger le code-barres « 3,70015E+12 » : il compte 11 caractères au lieu de
13. Un scanner de caisse le refusera. »
La phrase est vraie et ne sert à rien. Onze est bien la longueur de cette
chaîne — c'est d'ailleurs ce qui prouve que le fichier la porte telle quelle,
et que rien ne s'affiche mal ici. Un tableur a lu la colonne comme un nombre en
enregistrant l'export : 3700147202196 en ressort à six chiffres significatifs,
sept chiffres perdus pour de bon. Personne ne peut retaper ce que le fichier ne
porte plus, et la fiche Odoo, elle, est très probablement intacte : le travail
demandé n'est pas dans Odoo, il est de produire le fichier à nouveau.
Le motif reste INVALID_BARCODE — c'en est un, et le code de signalement voyage
jusqu'au schéma, aux couleurs du rapport et à l'arbre de §10.3. Seule la phrase
change, sur le seul cas que la notation scientifique désigne sans ambiguïté :
un vrai code-barres n'est que des chiffres, donc aucun ne peut porter d'exposant.
Un code réellement court garde son décompte, et le test l'épingle : là, le
nombre de caractères EST la faute, et quelqu'un le retape dans Odoo.
Non couvert : un tableur peut aussi manger le zéro de tête d'un 049…, qui
ressort à douze chiffres et retombe donc sur le décompte. Même cause, message
encore trompeur, mais rien ne le distingue d'une vraie saisie courte sans
regarder le fichier entier.
---
internal/catalog/findings.go | 28 +++++++++++++++++++++++++--
internal/catalog/qualify_test.go | 33 ++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/internal/catalog/findings.go b/internal/catalog/findings.go
index a72ce4a..0f72a12 100644
--- a/internal/catalog/findings.go
+++ b/internal/catalog/findings.go
@@ -2,6 +2,7 @@ package catalog
import (
"fmt"
+ "regexp"
"strings"
"openscale/internal/domain"
@@ -86,13 +87,16 @@ func noBarcode(r Row) domain.Finding {
}
}
-// invalidBarcode reports thirteen characters that are not a readable EAN-13.
+// invalidBarcode reports a code the till could not read as an EAN-13.
//
// It NAMES the check digit that was expected, because that is the difference between
// « code-barres invalide » and a correction somebody can type: six of the seven
// offending codes of flv_1.csv are one digit away from being right.
+//
+// A code a spreadsheet turned into a number gets its OWN sentence, and that is not
+// cosmetic: the work it asks for is not in Odoo at all (see spreadsheetNumber).
func invalidBarcode(r Row) domain.Finding {
- return domain.Finding{
+ f := domain.Finding{
CSVLine: r.Line,
ProductID: r.ID,
ProductName: r.Name,
@@ -102,8 +106,28 @@ func invalidBarcode(r Row) domain.Finding {
Message: fmt.Sprintf("Corriger le code-barres « %s » : %s. "+
"Un scanner de caisse le refusera.", r.Barcode, whyNotEAN13(r.Barcode)),
}
+ if spreadsheetNumber.MatchString(r.Barcode) {
+ f.Message = fmt.Sprintf("Réexporter le catalogue depuis Odoo sans ouvrir le "+
+ "fichier dans un tableur : « %s » n'est pas un code-barres mais un nombre en "+
+ "notation scientifique, ce qu'un tableur fait d'une colonne de treize "+
+ "chiffres dès qu'il l'enregistre. Les chiffres perdus ne se devinent pas, et "+
+ "les autres codes du fichier sont sans doute dans le même état.", r.Barcode)
+ }
+ return f
}
+// spreadsheetNumber recognises a code that went through a spreadsheet on its way here.
+//
+// Opening the export in Excel or LibreOffice and saving it back reads a column of
+// thirteen digits as a NUMBER: 3700147202196 comes out « 3,70015E+12 », six significant
+// figures and seven digits gone for good. Saying it counts eleven characters instead of
+// thirteen is true and useless — nobody can retype what the file no longer carries, the
+// record in Odoo is very probably intact, and the fix is to produce the file again.
+//
+// No genuine barcode can match: a barcode is digits and nothing else, and this pattern
+// requires an exponent.
+var spreadsheetNumber = regexp.MustCompile(`^[0-9]+([.,][0-9]+)?[eE][+-]?[0-9]+$`)
+
// whyNotEAN13 says, in French, which of the two faults a code carries.
//
// The two lead to different work: a wrong check digit is a typing mistake to fix at
diff --git a/internal/catalog/qualify_test.go b/internal/catalog/qualify_test.go
index e301c2f..eb8516b 100644
--- a/internal/catalog/qualify_test.go
+++ b/internal/catalog/qualify_test.go
@@ -356,6 +356,39 @@ func TestTheReservedZoneMessageNamesTheDigitsAndTheValue(t *testing.T) {
}
}
+// TestASpreadsheetNumberIsNamedForWhatItIs covers the one invalid barcode nobody can
+// fix in Odoo, because Odoo is not where it broke.
+//
+// « 3,70015E+12 » is what a spreadsheet leaves of 3700147202196 after opening the
+// export and saving it back: thirteen digits read as a number, kept to six significant
+// figures. Counting its eleven characters is TRUE and worth nothing — the digits are
+// gone, they cannot be typed back from the report, and every other code of the file is
+// in the same state. The only usable instruction is to export again.
+func TestASpreadsheetNumberIsNamedForWhatItIs(t *testing.T) {
+ for _, mangled := range []string{"3,70015E+12", "3.70015E+12", "3,70015e+12", "4,93E+11"} {
+ _, findings, _ := catalog.Qualify(row(func(r *catalog.Row) { r.Barcode = mangled }))
+ if len(findings) != 1 || findings[0].Code != domain.FindingInvalidBarcode {
+ t.Fatalf("%s : signalements %v, attendu INVALID_BARCODE", mangled, codes(findings))
+ }
+ message := findings[0].Message
+ if strings.Contains(message, "caractères au lieu de 13") {
+ t.Errorf("%s : le message compte les caractères d'un nombre : %s", mangled, message)
+ }
+ for _, expected := range []string{mangled, "Réexporter", "tableur"} {
+ if !strings.Contains(message, expected) {
+ t.Errorf("le message ne contient pas %q : %s", expected, message)
+ }
+ }
+ }
+
+ // A code that really is a short string of digits keeps the count: there, the number
+ // of characters IS the fault, and someone retypes it in Odoo.
+ _, findings, _ := catalog.Qualify(row(func(r *catalog.Row) { r.Barcode = "049302100000" }))
+ if !strings.Contains(findings[0].Message, "12 caractères au lieu de 13") {
+ t.Errorf("un code court a perdu son décompte : %s", findings[0].Message)
+ }
+}
+
// codes lists the codes of a slice of findings, for a failure message.
func codes(findings []domain.Finding) []string {
out := make([]string, 0, len(findings))
From 3b5507ba19e2490967d1d4b6427b7a00cc067d8e Mon Sep 17 00:00:00 2001
From: "Fabien F."
Date: Tue, 4 Aug 2026 16:40:04 +0200
Subject: [PATCH 3/3] =?UTF-8?q?build(web):=20r=C3=A9g=C3=A9n=C3=A8re=20le?=
=?UTF-8?q?=20front=20embarqu=C3=A9=20avec=20le=20nouveau=20libell=C3=A9?=
=?UTF-8?q?=20du=20seuil?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
internal/web/dist/admin.html | 4 ++--
internal/web/dist/assets/admin-DEu9sOlj.js | 1 -
internal/web/dist/assets/admin-tZr91ixu.js | 1 +
.../web/dist/assets/{index-BoOKWXIu.js => index-DPFlyzED.js} | 4 ++--
.../web/dist/assets/{mount-D3UhzFzr.js => mount-1OvlPcKC.js} | 4 ++--
internal/web/dist/index.html | 2 +-
6 files changed, 8 insertions(+), 8 deletions(-)
delete mode 100644 internal/web/dist/assets/admin-DEu9sOlj.js
create mode 100644 internal/web/dist/assets/admin-tZr91ixu.js
rename internal/web/dist/assets/{index-BoOKWXIu.js => index-DPFlyzED.js} (99%)
rename internal/web/dist/assets/{mount-D3UhzFzr.js => mount-1OvlPcKC.js} (94%)
diff --git a/internal/web/dist/admin.html b/internal/web/dist/admin.html
index 7e6fcba..d1a5580 100644
--- a/internal/web/dist/admin.html
+++ b/internal/web/dist/admin.html
@@ -5,9 +5,9 @@
Administration
-
+
-
+
diff --git a/internal/web/dist/assets/admin-DEu9sOlj.js b/internal/web/dist/assets/admin-DEu9sOlj.js
deleted file mode 100644
index aba8cec..0000000
--- a/internal/web/dist/assets/admin-DEu9sOlj.js
+++ /dev/null
@@ -1 +0,0 @@
-import"./app-BaRSXv80.js";import{mountAdmin as m}from"./mount-D3UhzFzr.js";m(document.getElementById("app"));
diff --git a/internal/web/dist/assets/admin-tZr91ixu.js b/internal/web/dist/assets/admin-tZr91ixu.js
new file mode 100644
index 0000000..d59f2ee
--- /dev/null
+++ b/internal/web/dist/assets/admin-tZr91ixu.js
@@ -0,0 +1 @@
+import"./app-BaRSXv80.js";import{mountAdmin as m}from"./mount-1OvlPcKC.js";m(document.getElementById("app"));
diff --git a/internal/web/dist/assets/index-BoOKWXIu.js b/internal/web/dist/assets/index-DPFlyzED.js
similarity index 99%
rename from internal/web/dist/assets/index-BoOKWXIu.js
rename to internal/web/dist/assets/index-DPFlyzED.js
index 9872a39..8a75d0d 100644
--- a/internal/web/dist/assets/index-BoOKWXIu.js
+++ b/internal/web/dist/assets/index-DPFlyzED.js
@@ -1,2 +1,2 @@
-const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/mount-D3UhzFzr.js","assets/app-BaRSXv80.js","assets/app-Cfxw4Luj.css","assets/mount-MmpjwdB2.css"])))=>i.map(i=>d[i]);
-import{e as Ie,u as je,d as re,p as Y,a as q,i as W,I as ee,t as z,b as N,c as w,f as Z,g as E,h as t,s as h,j as ae,k as te,l as se,m as T,n as v,o as u,q as Pe,r as fe,w as De,v as Te,x as ne,y as Ce,R as Re,z as b,A as D,B as qe,T as Le,C as Ne,N as Oe,D as Me,E as We,F as Be,G as Fe,H as ze,M as He,J as Ue,K as Ve,L as Ge,O as Xe,P as Ke,Q as Je,S as Qe,U as Ye,V as Ze,W as $e,X as et}from"./app-BaRSXv80.js";class be{#e=new WeakMap;#t;#n;static entries=new WeakMap;constructor(e){this.#n=e}observe(e,n){var r=this.#e.get(e)||new Set;return r.add(n),this.#e.set(e,r),this.#s().observe(e,this.#n),()=>{var l=this.#e.get(e);l.delete(n),l.size===0&&(this.#e.delete(e),this.#t.unobserve(e))}}#s(){return this.#t??(this.#t=new ResizeObserver(e=>{for(var n of e){be.entries.set(n.target,n);for(var r of this.#e.get(n.target)||[])r(n)}}))}}var tt=new be({box:"border-box"});function he(s,e,n){var r=tt.observe(s,()=>n(s[e]));Ie(()=>(je(()=>n(s[e])),r))}const nt="modulepreload",at=function(s){return"/"+s},ye={},st=function(e,n,r){let l=Promise.resolve();if(n&&n.length>0){let _=function(o){return Promise.all(o.map(i=>Promise.resolve(i).then(y=>({status:"fulfilled",value:y}),y=>({status:"rejected",reason:y}))))};document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),d=c?.nonce||c?.getAttribute("nonce");l=_(n.map(o=>{if(o=at(o),o in ye)return;ye[o]=!0;const i=o.endsWith(".css"),y=i?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${y}`))return;const k=document.createElement("link");if(k.rel=i?"stylesheet":nt,i||(k.as="script"),k.crossOrigin="",k.href=o,d&&k.setAttribute("nonce",d),document.head.appendChild(k),i)return new Promise((m,I)=>{k.addEventListener("load",m),k.addEventListener("error",()=>I(new Error(`Unable to preload CSS for ${o}`)))})}))}function f(c){const d=new Event("vite:preloadError",{cancelable:!0});if(d.payload=c,window.dispatchEvent(d),!d.defaultPrevented)throw c}return l.then(c=>{for(const d of c||[])d.status==="rejected"&&f(d.reason);return e().catch(f)})};var rt=E('
');function Ot(s,e){Y(e,!0);const n=["1","2","3","4","5","6","7","8","9","0"];var r=Nt(),l=u(r),f=h(u(l),2),c=u(f),d=h(l,2);fe(d,20,()=>n,m=>m,(m,I)=>{var g=Lt(),P=u(g);z(()=>T(P,I)),N("click",g,()=>e.ondigit(I)),w(m,g)});var _=h(d,2),o=u(_),i=h(o,2),y=h(i,2),k=u(y);ee(k,{name:"check",size:"1.5rem"}),z(()=>T(c,e.grams===""?"0":e.grams)),N("click",o,function(...m){e.onclear?.apply(this,m)}),N("click",i,function(...m){e.oncancel?.apply(this,m)}),N("click",y,function(...m){e.onconfirm?.apply(this,m)}),w(s,r),Z()}re(["click"]);function Mt(s){return s===null||s.state==="initializing"?!1:s.scale.connected&&s.printer.health!=="faulted"}const Ee=1500,Wt=2e3,ke=5e3;function Bt(s,e){return e?s>=ke?{showWeight:!1,banner:"Poids indisponible",mustReconnect:!0}:s>=Wt?{showWeight:!1,banner:"Poids indisponible",mustReconnect:!1}:s>=Ee?{showWeight:!1,banner:"",mustReconnect:!1}:{showWeight:!0,banner:"",mustReconnect:!1}:{showWeight:s=ke}}const Ft=250,Ht={show_grid_prices:!0,idle_timeout_s:45,reprint_window_s:60,sound:!0,show_by_unit_products:!1,grid_columns:0,min_products_for_chip:He};class Ut{#e=D(null);get state(){return t(this.#e)}set state(e){b(this.#e,e,!0)}#t=D(null);get catalog(){return t(this.#t)}set catalog(e){b(this.#t,e,!0)}#n=D(ze({showWeight:!0,banner:"",mustReconnect:!1}));get link(){return t(this.#n)}set link(e){b(this.#n,e,!0)}#s=D("");get catalogError(){return t(this.#s)}set catalogError(e){b(this.#s,e,!0)}#r=null;#i=null;#l=Date.now();#a=!1;#o=!1;get presentation(){return this.catalog?.presentation??Ht}start(){this.#u(),this.#c(),this.#i=setInterval(()=>this.#v(),Ft)}stop(){this.#i!==null&&clearInterval(this.#i),this.#i=null,this.#r?.close(),this.#r=null,this.#a=!1}#c(){const e=new EventSource("/api/v1/stream");this.#r=e,e.onopen=()=>{this.#a=!0,this.#l=Date.now()},e.addEventListener("state",n=>this.#d(n)),e.onerror=()=>{this.#a=!1}}#d(e){this.#l=Date.now(),this.#a=!0;const n=JSON.parse(e.data),r=this.state;if(this.state=n,this.catalog===null)return;const l=n.catalog_count!==this.catalog.product_count,f=r!==null&&n.presentation_digest!==r.presentation_digest;(l||f)&&this.#u()}#v(){const e=Bt(Date.now()-this.#l,this.#a);this.link=e,e.mustReconnect&&(this.#r?.close(),this.#l=Date.now(),this.#c())}async#u(){if(!this.#o){this.#o=!0;try{this.catalog=await Ue(),this.catalogError=""}catch{this.catalog===null&&(this.catalogError="Catalogue indisponible. Prévenez un responsable.")}finally{this.#o=!1}}}}const xe="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function Ae(){let s=Date.now();const e=new Array(26);for(let r=9;r>=0;r--)e[r]=xe[s%32],s=Math.floor(s/32);const n=new Uint8Array(16);crypto.getRandomValues(n);for(let r=0;r<16;r++)e[10+r]=xe[n[r]%32];return e.join("")}var Vt=E('');function Gt(s,e){Y(e,!0);const n=new Ut;let r=D(ze(Ve)),l=D(""),f=D(!1);const c=v(()=>t(l)!==""||t(f));let d=D(null),_=D(-1),o=D(null);const i=v(()=>n.catalog),y=v(()=>t(i)===null?[]:Qe(t(i))),k=v(()=>t(i)===null?[]:Ke(t(i))),m=v(()=>Xe(t(y),t(r),t(l))),I=v(()=>{const a={};for(const S of t(i)?.categories??[])a[S.code]=S.color;return a}),g=v(()=>n.state),P=v(()=>n.presentation),B=v(()=>Mt(t(g))),R=v(()=>{if(n.catalogError!=="")return{message:n.catalogError,hint:"Le poste réessaie tout seul."};if(t(y).length>0)return{message:"Aucun produit ne correspond.",hint:"Effacez des lettres ou changez de rayon."};if(t(i)!==null&&t(i).products.length>0)return{message:t(i).products.every(U=>U.mode==="by_unit")&&!t(P).show_by_unit_products?"Aucun produit à montrer : ce poste masque les produits vendus à l’unité, et le catalogue reçu ne contient que ceux-là.":"Aucun produit à montrer : les réglages d’affichage de ce poste masquent tout ce qu’il a reçu.",hint:"Le fichier est bien arrivé : prévenez un responsable, c’est un réglage de ce poste qui vide la grille."};const a=t(g)?.station??0;return{message:a>0?`Catalogue vide. En attente du fichier flv_${a}.csv.`:"Catalogue vide. En attente du fichier du poste.",hint:"Prévenez un responsable : aucun produit ne peut être pesé."}}),H=v(()=>t(g)?.state==="rejected"?t(g).product?.id??null:null),V=v(()=>t(g)?.state==="faulted"||t(g)?.state==="out_of_service"),A=["product_armed","weight_present","weight_stable","awaiting_stability","validating","printing"],O=v(()=>t(g)!==null&&A.includes(t(g).state)?t(g).product?.id??null:null),G=v(()=>Pt(t(i)?.updated_at??""));ne(()=>(n.start(),()=>n.stop())),ne(()=>{const a=n.state?.revision??-1;t(d)!==null&&a>t(_)&&(b(d,null),b(_,-1))});async function X(a){if(t(d)===null){b(d,a.id,!0),b(_,n.state?.revision??-1,!0);try{await Ge({product_id:a.id,tare_g:n.state?.weight.tare_g??0,units:1,manual_weight_g:0,seen_weight_g:n.state?.weight.gross_g??0,measurement_seq:n.state?.weight.seq??0,key:Ae()})}catch{b(d,null)}}}async function K(){const a=n.state?.reprint.job_id;a===void 0||a===""||await Je(a,Ae())}function F(){b(l,""),b(f,!1)}function p(){b(f,!0)}function C(){const a=t(m).length===1?t(m)[0]:void 0;a!==void 0&&X(a)}function M(a){if(!(a.metaKey||a.ctrlKey||a.altKey)&&!(a.target instanceof HTMLElement&&a.target.tagName==="INPUT")&&!(t(o)!==null||t(V))){if(a.key==="Escape"){a.preventDefault(),F();return}if(a.key==="Backspace"){a.preventDefault(),b(l,t(l).slice(0,-1),!0);return}if(a.key==="Enter"){C();return}a.key.length===1&&/[a-zA-Z0-9 ]/.test(a.key)&&(a.key===" "&&t(l)===""||(a.preventDefault(),b(l,t(l)+a.key)))}}ne(()=>(window.addEventListener("keydown",M),()=>window.removeEventListener("keydown",M)));async function $(){(await st(()=>import("./mount-D3UhzFzr.js"),__vite__mapDeps([0,1,2,3]))).mountAdmin(document.body)}var ie=Vt(),oe=u(ie);{let a=v(()=>t(o)!==null);ot(oe,{get snapshot(){return t(g)},get showWeight(){return n.link.showWeight},get linkBanner(){return n.link.banner},get taring(){return t(a)},ontare:()=>b(o,"")})}var J=h(oe,2);{var ce=a=>{Ot(a,{get grams(){return t(o)},ondigit:S=>b(o,(t(o)??"")+S),onclear:()=>b(o,""),oncancel:()=>b(o,null),onconfirm:()=>b(o,null)})};W(J,a=>{t(o)!==null&&a(ce)})}var le=h(J,2);{let a=v(()=>t(i)?.pricing.primary_code??""),S=v(()=>Object.fromEntries((t(i)?.pricing.tiers??[]).map(Q=>[Q.code,Q.abbrev]))),U=v(()=>t(i)===null&&n.catalogError==="");Et(le,{get products(){return t(m)},get colors(){return t(I)},get primaryCode(){return t(a)},get tierAbbrev(){return t(S)},get selectedID(){return t(O)},get rejectedID(){return t(H)},get busyID(){return t(d)},get showPrices(){return t(P).show_grid_prices},get gridColumns(){return t(P).grid_columns},get loading(){return t(U)},get emptyMessage(){return t(R).message},get emptyHint(){return t(R).hint},onpick:X})}var ue=h(le,2);{var pe=a=>{At(a,{get query(){return t(l)},onquery:S=>b(l,S,!0),onclose:F,onenter:C})};W(ue,a=>{t(c)&&a(pe)})}var de=h(ue,2);dt(de,{get chips(){return t(k)},get active(){return t(r)},get searchFieldOpen(){return t(c)},onselect:a=>b(r,a,!0),onopensearch:p});var ve=h(de,2);{let a=v(()=>t(g)?.last_label??null),S=v(()=>t(g)?.reprint.available??!1),U=v(()=>t(i)?.app_version??"");qt(ve,{get label(){return t(a)},get available(){return t(S)},get catalogAt(){return t(G)},get productCount(){return t(y).length},get appVersion(){return t(U)},get healthy(){return t(B)},onreprint:K,onadmin:$})}var x=h(ve,2);{var L=a=>{{let S=v(()=>t(g).message?.text??"Prévenez un responsable.");we(a,{title:"Poste indisponible",get detail(){return t(S)},get code(){return t(g).fault_code},action:{label:"J’ai compris",run:()=>{Ye()}}})}},j=a=>{we(a,{title:"Poste hors service",detail:"Ce poste ne peut pas peser. Prévenez un responsable.",get code(){return t(g).fault_code}})};W(x,a=>{t(g)?.state==="faulted"?a(L):t(g)?.state==="out_of_service"&&a(j,1)})}w(s,ie),Z()}const Xt=5,Kt="ResizeObserver loop";function Jt(){let s=!1,e=!1;const n=(c,d)=>{s||(s=!0,$e(c,d),Qt(),setTimeout(()=>location.reload(),Xt*1e3))},r=c=>{e||(e=!0,Ze(c))},l=c=>{if((c.error===void 0||c.error===null)&&c.message.startsWith(Kt)){r(c.message);return}n(c.message,c.error?.stack??"")},f=c=>{n(String(c.reason),c.reason?.stack??"")};return window.addEventListener("error",l),window.addEventListener("unhandledrejection",f),()=>{window.removeEventListener("error",l),window.removeEventListener("unhandledrejection",f)}}function Qt(){const s=document.createElement("div");s.className="fatal",s.append(me("h1","Une erreur est survenue"),me("p","L’écran va se recharger tout seul."),me("p","ERR-UI-01","code")),document.body.appendChild(s)}function me(s,e,n=""){const r=document.createElement(s);return r.textContent=e,n!==""&&(r.className=n),r}Jt();document.addEventListener("contextmenu",s=>{Yt(s.target)||s.preventDefault()});document.addEventListener("dragstart",s=>s.preventDefault());et(Gt,{target:document.getElementById("app")});function Yt(s){return s instanceof Element&&s.closest("[data-admin]")!==null}
+const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/mount-1OvlPcKC.js","assets/app-BaRSXv80.js","assets/app-Cfxw4Luj.css","assets/mount-MmpjwdB2.css"])))=>i.map(i=>d[i]);
+import{e as Ie,u as je,d as re,p as Y,a as q,i as W,I as ee,t as z,b as N,c as w,f as Z,g as E,h as t,s as h,j as ae,k as te,l as se,m as T,n as v,o as u,q as Pe,r as fe,w as De,v as Te,x as ne,y as Ce,R as Re,z as b,A as D,B as qe,T as Le,C as Ne,N as Oe,D as Me,E as We,F as Be,G as Fe,H as ze,M as He,J as Ue,K as Ve,L as Ge,O as Xe,P as Ke,Q as Je,S as Qe,U as Ye,V as Ze,W as $e,X as et}from"./app-BaRSXv80.js";class be{#e=new WeakMap;#t;#n;static entries=new WeakMap;constructor(e){this.#n=e}observe(e,n){var r=this.#e.get(e)||new Set;return r.add(n),this.#e.set(e,r),this.#s().observe(e,this.#n),()=>{var l=this.#e.get(e);l.delete(n),l.size===0&&(this.#e.delete(e),this.#t.unobserve(e))}}#s(){return this.#t??(this.#t=new ResizeObserver(e=>{for(var n of e){be.entries.set(n.target,n);for(var r of this.#e.get(n.target)||[])r(n)}}))}}var tt=new be({box:"border-box"});function he(s,e,n){var r=tt.observe(s,()=>n(s[e]));Ie(()=>(je(()=>n(s[e])),r))}const nt="modulepreload",at=function(s){return"/"+s},ye={},st=function(e,n,r){let l=Promise.resolve();if(n&&n.length>0){let _=function(o){return Promise.all(o.map(i=>Promise.resolve(i).then(y=>({status:"fulfilled",value:y}),y=>({status:"rejected",reason:y}))))};document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),d=c?.nonce||c?.getAttribute("nonce");l=_(n.map(o=>{if(o=at(o),o in ye)return;ye[o]=!0;const i=o.endsWith(".css"),y=i?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${y}`))return;const k=document.createElement("link");if(k.rel=i?"stylesheet":nt,i||(k.as="script"),k.crossOrigin="",k.href=o,d&&k.setAttribute("nonce",d),document.head.appendChild(k),i)return new Promise((m,I)=>{k.addEventListener("load",m),k.addEventListener("error",()=>I(new Error(`Unable to preload CSS for ${o}`)))})}))}function f(c){const d=new Event("vite:preloadError",{cancelable:!0});if(d.payload=c,window.dispatchEvent(d),!d.defaultPrevented)throw c}return l.then(c=>{for(const d of c||[])d.status==="rejected"&&f(d.reason);return e().catch(f)})};var rt=E('
');function Ot(s,e){Y(e,!0);const n=["1","2","3","4","5","6","7","8","9","0"];var r=Nt(),l=u(r),f=h(u(l),2),c=u(f),d=h(l,2);fe(d,20,()=>n,m=>m,(m,I)=>{var g=Lt(),P=u(g);z(()=>T(P,I)),N("click",g,()=>e.ondigit(I)),w(m,g)});var _=h(d,2),o=u(_),i=h(o,2),y=h(i,2),k=u(y);ee(k,{name:"check",size:"1.5rem"}),z(()=>T(c,e.grams===""?"0":e.grams)),N("click",o,function(...m){e.onclear?.apply(this,m)}),N("click",i,function(...m){e.oncancel?.apply(this,m)}),N("click",y,function(...m){e.onconfirm?.apply(this,m)}),w(s,r),Z()}re(["click"]);function Mt(s){return s===null||s.state==="initializing"?!1:s.scale.connected&&s.printer.health!=="faulted"}const Ee=1500,Wt=2e3,ke=5e3;function Bt(s,e){return e?s>=ke?{showWeight:!1,banner:"Poids indisponible",mustReconnect:!0}:s>=Wt?{showWeight:!1,banner:"Poids indisponible",mustReconnect:!1}:s>=Ee?{showWeight:!1,banner:"",mustReconnect:!1}:{showWeight:!0,banner:"",mustReconnect:!1}:{showWeight:s=ke}}const Ft=250,Ht={show_grid_prices:!0,idle_timeout_s:45,reprint_window_s:60,sound:!0,show_by_unit_products:!1,grid_columns:0,min_products_for_chip:He};class Ut{#e=D(null);get state(){return t(this.#e)}set state(e){b(this.#e,e,!0)}#t=D(null);get catalog(){return t(this.#t)}set catalog(e){b(this.#t,e,!0)}#n=D(ze({showWeight:!0,banner:"",mustReconnect:!1}));get link(){return t(this.#n)}set link(e){b(this.#n,e,!0)}#s=D("");get catalogError(){return t(this.#s)}set catalogError(e){b(this.#s,e,!0)}#r=null;#i=null;#l=Date.now();#a=!1;#o=!1;get presentation(){return this.catalog?.presentation??Ht}start(){this.#u(),this.#c(),this.#i=setInterval(()=>this.#v(),Ft)}stop(){this.#i!==null&&clearInterval(this.#i),this.#i=null,this.#r?.close(),this.#r=null,this.#a=!1}#c(){const e=new EventSource("/api/v1/stream");this.#r=e,e.onopen=()=>{this.#a=!0,this.#l=Date.now()},e.addEventListener("state",n=>this.#d(n)),e.onerror=()=>{this.#a=!1}}#d(e){this.#l=Date.now(),this.#a=!0;const n=JSON.parse(e.data),r=this.state;if(this.state=n,this.catalog===null)return;const l=n.catalog_count!==this.catalog.product_count,f=r!==null&&n.presentation_digest!==r.presentation_digest;(l||f)&&this.#u()}#v(){const e=Bt(Date.now()-this.#l,this.#a);this.link=e,e.mustReconnect&&(this.#r?.close(),this.#l=Date.now(),this.#c())}async#u(){if(!this.#o){this.#o=!0;try{this.catalog=await Ue(),this.catalogError=""}catch{this.catalog===null&&(this.catalogError="Catalogue indisponible. Prévenez un responsable.")}finally{this.#o=!1}}}}const xe="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function Ae(){let s=Date.now();const e=new Array(26);for(let r=9;r>=0;r--)e[r]=xe[s%32],s=Math.floor(s/32);const n=new Uint8Array(16);crypto.getRandomValues(n);for(let r=0;r<16;r++)e[10+r]=xe[n[r]%32];return e.join("")}var Vt=E('');function Gt(s,e){Y(e,!0);const n=new Ut;let r=D(ze(Ve)),l=D(""),f=D(!1);const c=v(()=>t(l)!==""||t(f));let d=D(null),_=D(-1),o=D(null);const i=v(()=>n.catalog),y=v(()=>t(i)===null?[]:Qe(t(i))),k=v(()=>t(i)===null?[]:Ke(t(i))),m=v(()=>Xe(t(y),t(r),t(l))),I=v(()=>{const a={};for(const S of t(i)?.categories??[])a[S.code]=S.color;return a}),g=v(()=>n.state),P=v(()=>n.presentation),B=v(()=>Mt(t(g))),R=v(()=>{if(n.catalogError!=="")return{message:n.catalogError,hint:"Le poste réessaie tout seul."};if(t(y).length>0)return{message:"Aucun produit ne correspond.",hint:"Effacez des lettres ou changez de rayon."};if(t(i)!==null&&t(i).products.length>0)return{message:t(i).products.every(U=>U.mode==="by_unit")&&!t(P).show_by_unit_products?"Aucun produit à montrer : ce poste masque les produits vendus à l’unité, et le catalogue reçu ne contient que ceux-là.":"Aucun produit à montrer : les réglages d’affichage de ce poste masquent tout ce qu’il a reçu.",hint:"Le fichier est bien arrivé : prévenez un responsable, c’est un réglage de ce poste qui vide la grille."};const a=t(g)?.station??0;return{message:a>0?`Catalogue vide. En attente du fichier flv_${a}.csv.`:"Catalogue vide. En attente du fichier du poste.",hint:"Prévenez un responsable : aucun produit ne peut être pesé."}}),H=v(()=>t(g)?.state==="rejected"?t(g).product?.id??null:null),V=v(()=>t(g)?.state==="faulted"||t(g)?.state==="out_of_service"),A=["product_armed","weight_present","weight_stable","awaiting_stability","validating","printing"],O=v(()=>t(g)!==null&&A.includes(t(g).state)?t(g).product?.id??null:null),G=v(()=>Pt(t(i)?.updated_at??""));ne(()=>(n.start(),()=>n.stop())),ne(()=>{const a=n.state?.revision??-1;t(d)!==null&&a>t(_)&&(b(d,null),b(_,-1))});async function X(a){if(t(d)===null){b(d,a.id,!0),b(_,n.state?.revision??-1,!0);try{await Ge({product_id:a.id,tare_g:n.state?.weight.tare_g??0,units:1,manual_weight_g:0,seen_weight_g:n.state?.weight.gross_g??0,measurement_seq:n.state?.weight.seq??0,key:Ae()})}catch{b(d,null)}}}async function K(){const a=n.state?.reprint.job_id;a===void 0||a===""||await Je(a,Ae())}function F(){b(l,""),b(f,!1)}function p(){b(f,!0)}function C(){const a=t(m).length===1?t(m)[0]:void 0;a!==void 0&&X(a)}function M(a){if(!(a.metaKey||a.ctrlKey||a.altKey)&&!(a.target instanceof HTMLElement&&a.target.tagName==="INPUT")&&!(t(o)!==null||t(V))){if(a.key==="Escape"){a.preventDefault(),F();return}if(a.key==="Backspace"){a.preventDefault(),b(l,t(l).slice(0,-1),!0);return}if(a.key==="Enter"){C();return}a.key.length===1&&/[a-zA-Z0-9 ]/.test(a.key)&&(a.key===" "&&t(l)===""||(a.preventDefault(),b(l,t(l)+a.key)))}}ne(()=>(window.addEventListener("keydown",M),()=>window.removeEventListener("keydown",M)));async function $(){(await st(()=>import("./mount-1OvlPcKC.js"),__vite__mapDeps([0,1,2,3]))).mountAdmin(document.body)}var ie=Vt(),oe=u(ie);{let a=v(()=>t(o)!==null);ot(oe,{get snapshot(){return t(g)},get showWeight(){return n.link.showWeight},get linkBanner(){return n.link.banner},get taring(){return t(a)},ontare:()=>b(o,"")})}var J=h(oe,2);{var ce=a=>{Ot(a,{get grams(){return t(o)},ondigit:S=>b(o,(t(o)??"")+S),onclear:()=>b(o,""),oncancel:()=>b(o,null),onconfirm:()=>b(o,null)})};W(J,a=>{t(o)!==null&&a(ce)})}var le=h(J,2);{let a=v(()=>t(i)?.pricing.primary_code??""),S=v(()=>Object.fromEntries((t(i)?.pricing.tiers??[]).map(Q=>[Q.code,Q.abbrev]))),U=v(()=>t(i)===null&&n.catalogError==="");Et(le,{get products(){return t(m)},get colors(){return t(I)},get primaryCode(){return t(a)},get tierAbbrev(){return t(S)},get selectedID(){return t(O)},get rejectedID(){return t(H)},get busyID(){return t(d)},get showPrices(){return t(P).show_grid_prices},get gridColumns(){return t(P).grid_columns},get loading(){return t(U)},get emptyMessage(){return t(R).message},get emptyHint(){return t(R).hint},onpick:X})}var ue=h(le,2);{var pe=a=>{At(a,{get query(){return t(l)},onquery:S=>b(l,S,!0),onclose:F,onenter:C})};W(ue,a=>{t(c)&&a(pe)})}var de=h(ue,2);dt(de,{get chips(){return t(k)},get active(){return t(r)},get searchFieldOpen(){return t(c)},onselect:a=>b(r,a,!0),onopensearch:p});var ve=h(de,2);{let a=v(()=>t(g)?.last_label??null),S=v(()=>t(g)?.reprint.available??!1),U=v(()=>t(i)?.app_version??"");qt(ve,{get label(){return t(a)},get available(){return t(S)},get catalogAt(){return t(G)},get productCount(){return t(y).length},get appVersion(){return t(U)},get healthy(){return t(B)},onreprint:K,onadmin:$})}var x=h(ve,2);{var L=a=>{{let S=v(()=>t(g).message?.text??"Prévenez un responsable.");we(a,{title:"Poste indisponible",get detail(){return t(S)},get code(){return t(g).fault_code},action:{label:"J’ai compris",run:()=>{Ye()}}})}},j=a=>{we(a,{title:"Poste hors service",detail:"Ce poste ne peut pas peser. Prévenez un responsable.",get code(){return t(g).fault_code}})};W(x,a=>{t(g)?.state==="faulted"?a(L):t(g)?.state==="out_of_service"&&a(j,1)})}w(s,ie),Z()}const Xt=5,Kt="ResizeObserver loop";function Jt(){let s=!1,e=!1;const n=(c,d)=>{s||(s=!0,$e(c,d),Qt(),setTimeout(()=>location.reload(),Xt*1e3))},r=c=>{e||(e=!0,Ze(c))},l=c=>{if((c.error===void 0||c.error===null)&&c.message.startsWith(Kt)){r(c.message);return}n(c.message,c.error?.stack??"")},f=c=>{n(String(c.reason),c.reason?.stack??"")};return window.addEventListener("error",l),window.addEventListener("unhandledrejection",f),()=>{window.removeEventListener("error",l),window.removeEventListener("unhandledrejection",f)}}function Qt(){const s=document.createElement("div");s.className="fatal",s.append(me("h1","Une erreur est survenue"),me("p","L’écran va se recharger tout seul."),me("p","ERR-UI-01","code")),document.body.appendChild(s)}function me(s,e,n=""){const r=document.createElement(s);return r.textContent=e,n!==""&&(r.className=n),r}Jt();document.addEventListener("contextmenu",s=>{Yt(s.target)||s.preventDefault()});document.addEventListener("dragstart",s=>s.preventDefault());et(Gt,{target:document.getElementById("app")});function Yt(s){return s instanceof Element&&s.closest("[data-admin]")!==null}
diff --git a/internal/web/dist/assets/mount-D3UhzFzr.js b/internal/web/dist/assets/mount-1OvlPcKC.js
similarity index 94%
rename from internal/web/dist/assets/mount-D3UhzFzr.js
rename to internal/web/dist/assets/mount-1OvlPcKC.js
index 3f6541e..7800b83 100644
--- a/internal/web/dist/assets/mount-D3UhzFzr.js
+++ b/internal/web/dist/assets/mount-1OvlPcKC.js
@@ -1,4 +1,4 @@
-import{Y as Tr,Z as zr,_ as jr,$ as Ea,a0 as Vt,e as Rr,a1 as or,a2 as Or,a3 as Ar,a4 as Nr,u as ma,a5 as Ca,a6 as Ir,a7 as ur,x as wt,A as B,h as e,z as v,H as vt,d as ot,a as Be,s as n,i as _,t as f,l as Nt,j as be,m as o,b as Ce,c as l,o as s,g as c,p as Ue,I as Dr,f as Me,n as u,q as ae,a8 as Ia,r as ze,G as Gt,a9 as ea,aa as Tt,B as da,ab as lt,ac as Xt,ad as ka,C as Fr,J as cr,y as sa,T as Ur,ae as Ht,F as Mr,E as Wr,D as Br,O as Vr,K as Gr,X as Hr,af as Jr}from"./app-BaRSXv80.js";function dr(a){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Kr(a,t,...r){var i=new jr(a);Tr(()=>{const d=t()??null;i.ensure(d,d&&(p=>d(p,...r)))},zr)}function Pa(a,t,r=!1){if(a.multiple){if(t==null)return;if(!Or(t))return Ar();for(var i of a.options)i.selected=t.includes(la(i));return}for(i of a.options){var d=la(i);if(Nr(d,t)){i.selected=!0;return}}(!r||t!==void 0)&&(a.selectedIndex=-1)}function vr(a){var t=new MutationObserver(()=>{"__value"in a&&Pa(a,a.__value)});t.observe(a,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),or(()=>{t.disconnect()})}function $r(a,t,r=t){var i=new WeakSet,d=!0;Ea(a,"change",p=>{var y=p?"[selected]":":checked",z;if(a.multiple)z=[].map.call(a.querySelectorAll(y),la);else{var m=a.querySelector(y)??a.querySelector("option:not([disabled])");z=m&&la(m)}r(z),a.__value=z,Vt!==null&&i.add(Vt)}),Rr(()=>{var p=t();if(a===document.activeElement){var y=Vt;if(i.has(y))return}if(Pa(a,p,d),d&&p===void 0){var z=a.querySelector(":checked");z!==null&&(p=la(z),r(p))}a.__value=p,d=!1}),vr(a)}function la(a){return"__value"in a?a.__value:a.value}function ia(a,t,r=t){var i=new WeakSet;Ea(a,"input",async d=>{var p=d?a.defaultValue:a.value;if(p=ba(a)?wa(p):p,r(p),Vt!==null&&i.add(Vt),await Ir(),p!==(p=t())){var y=a.selectionStart,z=a.selectionEnd,m=a.value.length;if(a.value=p??"",z!==null){var j=a.value.length;y===z&&z===m&&j>m?(a.selectionStart=j,a.selectionEnd=j):(a.selectionStart=y,a.selectionEnd=Math.min(z,j))}}}),ma(t)==null&&a.value&&(r(ba(a)?wa(a.value):a.value),Vt!==null&&i.add(Vt)),Ca(()=>{var d=t();if(a===document.activeElement){var p=Vt;if(i.has(p))return}ba(a)&&d===wa(a.value)||a.type==="date"&&!d&&!a.value||d!==a.value&&(a.value=d??"")})}function Da(a,t,r=t){Ea(a,"change",i=>{var d=i?a.defaultChecked:a.checked;r(d)}),ma(t)==null&&r(a.checked),Ca(()=>{var i=t();a.checked=!!i})}function ba(a){var t=a.type;return t==="number"||t==="range"}function wa(a){return a===""?null:+a}function Fa(a,t,r,i,d){var p=()=>{i(r[a])};r.addEventListener(t,p),d?Ca(()=>{r[a]=d()}):p(),(r===document.body||r===window||r===document)&&or(()=>{r.removeEventListener(t,p)})}function Ta(a){ur===null&&dr(),wt(()=>{const t=ma(a);if(typeof t=="function")return t})}function Yr(a){ur===null&&dr(),Ta(()=>()=>ma(a))}const Xr="ERR-CFG-02";class Pt extends Error{constructor(t,r,i="",d=[]){super(r),this.status=t,this.code=i,this.faults=d,this.name="AdminError"}status;code;faults;get needsPassword(){return this.status===401}get needsFirstPassword(){return this.status===409&&this.code===Xr}get needsCredentials(){return this.needsPassword||this.needsFirstPassword}}function fa(a){return a instanceof Pt&&a.needsCredentials}function Qr(){return It("/admin/api/health")}function Zr(){return He("/admin/api/troubleshooting/reprint",{})}function en(){return He("/admin/api/troubleshooting/reload-catalog",{})}function tn(a){return He("/admin/api/troubleshooting/manual-entry",{on:a})}function an(){return He("/admin/api/troubleshooting/roll-changed",{})}function rn(a){return He("/admin/api/troubleshooting/fallback-printer",{on:a})}function nn(){return He("/admin/api/troubleshooting/test-scale",{})}function sn(){return He("/admin/api/troubleshooting/test-printer",{})}function ln(){return He("/admin/api/troubleshooting/test-label",{})}async function pr(a){const t=new FormData;t.append("file",a,a.name);const r=await fetch("/admin/api/catalog/import",{method:"POST",body:t});return Ra(r,"POST /admin/api/catalog/import")}const on="/admin/api/diagnostic.zip";function un(a){return He("/admin/api/session",{password:a})}async function cn(){await fetch("/admin/api/session",{method:"DELETE"})}function dn(a,t){return He("/admin/api/session/recovery",{code:a,password:t})}function za(){return It("/admin/api/config")}function vn(a){return ja("PUT","/admin/api/config",a)}function pn(){return He("/admin/api/config/reload",{})}function fn(){return He("/admin/api/restart",{})}function gn(){return He("/admin/api/reboot",{})}function mn(){return ja("DELETE","/admin/api/reboot",{})}function hn(){return He("/admin/api/config/confirm",{})}async function _n(){return(await It("/admin/api/config/versions")).versions}function bn(a){return He("/admin/api/config/restore",{version:a})}async function wn(){return(await It("/admin/api/ports")).ports}async function yn(){return(await It("/admin/api/printers")).printers}async function xn(){return(await He("/admin/api/printers/discover",{})).printers}function kn(a){return He("/admin/api/scale/detect",{port:a})}async function Ua(a,t){return(await He("/admin/api/scale/capture",{port:a,seconds:t})).frames}function fr(a){return He("/admin/api/printer/test?what="+a,{})}function qn(a,t,r,i){const d=new URLSearchParams({template:a,demo:t?"1":"0",dual:r?"1":"0"});return d.set("t",String(i)),"/admin/api/label/preview.png?"+d.toString()}async function Sn(a){const t=new URLSearchParams(a);return(await It("/admin/api/journal?"+t)).weighings}function Ln(a){return"/admin/api/journal/export.csv?"+new URLSearchParams(a).toString()}async function En(a){const t=new URLSearchParams(a);return(await It("/admin/api/technical?"+t)).entries}function Cn(a){const t=a===void 0?"":"?id="+String(a);return It("/admin/api/imports"+t)}function Pn(){return He("/admin/api/catalog/reload",{})}function Tn(){return He("/admin/api/catalog/forget-quarantine",{})}function Ma(a,t){return He("/admin/api/products/"+encodeURIComponent(a)+"/decision",t)}function zn(a){return He("/admin/api/replay",{frame:a})}async function It(a){const t=await fetch(a,{headers:{accept:"application/json"}});return Ra(t,"GET "+a)}function He(a,t){return ja("POST",a,t)}async function ja(a,t,r){const i=await fetch(t,{method:a,headers:{"content-type":"application/json"},body:JSON.stringify(r)});return Ra(i,a+" "+t)}async function Ra(a,t){const r=await a.text();if(!a.ok){const i=gr(r);throw new Pt(a.status,Rn(r,t,a.status)+jn(a),i?.code??"",i?.faults??[])}if(r!=="")return JSON.parse(r)}function jn(a){if(a.status!==429)return"";const t=Number(a.headers.get("Retry-After")??"");if(!Number.isFinite(t)||t<=0)return"";const r=Math.ceil(t/60);return r>1?` Réessayez dans ${String(r)} minutes.`:" Réessayez dans une minute."}function Rn(a,t,r){const i=gr(a);return i?.message!==void 0&&i.message!==""?i.message:`${t} a répondu ${String(r)}.`}function gr(a){try{return JSON.parse(a)}catch{return null}}function On(){return It("/admin/api/update")}function An(){return He("/admin/api/update/check",{})}function Nn(a){return He("/admin/api/update/apply",{version:a})}class In{constructor(t){this.admin=t}admin;#t=B(null);get config(){return e(this.#t)}set config(t){v(this.#t,t,!0)}#r=B("");get fingerprint(){return e(this.#r)}set fingerprint(t){v(this.#r,t,!0)}#a=B(vt([]));get retired(){return e(this.#a)}set retired(t){v(this.#a,t,!0)}#e=B(null);get pending(){return e(this.#e)}set pending(t){v(this.#e,t,!0)}#n=B(vt([]));get faults(){return e(this.#n)}set faults(t){v(this.#n,t,!0)}#l=B(!1);get dirty(){return e(this.#l)}set dirty(t){v(this.#l,t,!0)}async load(){const t=await this.admin.load(()=>za());t!==null&&(this.config=t.config,this.fingerprint=t.config_fingerprint,this.retired=t.retired_keys??[],this.pending=t.pending_confirmation,this.faults=[],this.dirty=!1)}value(t){let r=this.config;for(const i of t.split(".")){if(r===null||typeof r!="object")return;r=r[i]}return r}text(t){const r=this.value(t);return r==null?"":String(r)}number(t){const r=this.value(t);return typeof r=="number"?r:Number(r??0)}flag(t){return this.value(t)===!0}set(t,r){if(this.config===null)return;const i=t.split("."),d=i.pop();if(d===void 0)return;let p=this.config;for(const y of i){const z=p[y];(z===null||typeof z!="object")&&(p[y]={}),p=p[y]}p[d]=r,this.dirty=!0}unset(t){const r=t.split("."),i=r.pop();if(i===void 0||this.config===null)return!1;let d=this.config;for(const p of r){if(d===null||typeof d!="object")return!1;d=d[p]}return d===null||typeof d!="object"?!1:(delete d[i],this.dirty=!0,!0)}async save(){if(this.config===null)return!1;this.faults=[];const t=this.config;let r;try{r=await vn(t)}catch(i){if(fa(i))throw i;return this.admin.report(i),this.faults=Dn(this.admin),!1}return this.config=r.config,this.fingerprint=r.config_fingerprint,this.retired=r.retired_keys??[],this.pending=r.pending_confirmation,this.dirty=!1,!0}async confirm(){try{await hn()}catch(t){if(fa(t))throw t;this.admin.report(t);return}this.admin.notice="La configuration est confirmée.",this.pending=null,await this.admin.refresh()}dropRetired(t){if(t.includes("[")){this.admin.actionError=`« ${t} » est logée dans un tableau : cet écran ne sait pas la retirer de là. Modifiez le fichier de configuration lui-même.`;return}this.unset(t)&&(this.retired=this.retired.filter(r=>r!==t))}}function Dn(a){return a.lastFaults}const Fn={"station.number":"Numéro du poste","station.name":"Nom du poste","station.coop":"Nom de la coopérative","network.listen":"Adresse d’écoute","network.admin_on_lan":"Administration accessible depuis le réseau","ui.language":"Langue","ui.sound":"Son","ui.idle_timeout_s":"Retour à l’accueil après (secondes)","ui.reprint_window_s":"Réimpression possible pendant (secondes)","ui.show_grid_prices":"Afficher les prix sur les tuiles","ui.show_by_unit_products":"Afficher les produits vendus à l’unité","ui.grid_columns":"Colonnes de la grille","ui.min_products_for_chip":"Tuiles minimum pour donner sa puce à une catégorie","scale.type":"Protocole de la balance","scale.present":"Ce poste a une balance","scale.manual_entry_allowed":"Saisie manuelle autorisée","scale.degrade_after_s":"Passer en mode dégradé après (secondes)","scale.options.port":"Port série","scale.options.baud":"Vitesse (bauds)","scale.options.bits":"Bits de données","scale.options.parity":"Parité","scale.options.stop":"Bits d’arrêt","scale.options.backoff_min_ms":"Attente minimale avant réessai (ms)","scale.options.backoff_max_ms":"Attente maximale avant réessai (ms)","printer.type":"Pilote d’impression","printer.template":"Gabarit d’étiquette","printer.options.transport":"Transport","printer.options.queue":"File d’impression","printer.options.path":"Fichier de périphérique","printer.options.address":"Adresse réseau","printer.options.darkness":"Noircissement","printer.options.speed":"Vitesse d’impression","printer.options.offset_x":"Décalage horizontal (dots)","printer.options.offset_y":"Décalage vertical (dots)","printer.options.invert_bits":"Inverser les points","printer.options.copies":"Exemplaires","printer.options.roll_capacity":"Étiquettes par rouleau","pricing.amount_rounding":"Arrondi du montant","pricing.unit_price_rounding":"Arrondi du prix au kilo","pricing.primary_code":"Tarif principal","pricing.reference_code":"Tarif de référence","barcode.verify_reference_check_digit":"Vérifier la clé de contrôle","limits.empty_max_g":"Plateau considéré vide en dessous de (g)","limits.basket_check_enabled":"Vérifier la présence du panier","limits.basket_min_g":"Poids du panier, borne basse (g)","limits.basket_max_g":"Poids du panier, borne haute (g)","limits.min_weight_g":"Poids minimum accepté","limits.max_weight_g":"Poids maximum accepté","limits.max_tare_g":"Tare maximale","limits.min_units":"Unités minimum","limits.max_units":"Unités maximum","limits.max_amount_cents":"Montant maximum (centimes)","stability.mode":"Exigence de stabilité","stability.min_duration_ms":"Durée de stabilité (ms)","stability.tolerance_g":"Tolérance de stabilité (g)","stability.timeout_ms":"Délai d’attente de stabilité (ms)","stability.on_timeout":"Au bout du délai","stability.min_latch_rate":"Taux d’accroche minimal","stability.latch_rate_window_ms":"Fenêtre de mesure du taux (ms)","stability.expiry_floor_ms":"Péremption, plancher (ms)","stability.expiry_ceiling_ms":"Péremption, plafond (ms)","stability.expiry_factor":"Péremption, facteur","catalog.type":"Où le poste va chercher le catalogue","catalog.options.directory":"Répertoire surveillé","catalog.options.url":"Adresse du serveur","catalog.options.username":"Compte","catalog.options.password":"Mot de passe","catalog.options.separator":"Séparateur du CSV","catalog.options.poll_interval_s":"Vérifier toutes les (secondes)","catalog.options.stable_polls":"Vérifications avant lecture","catalog.options.max_file_size_mb":"Taille maximale du fichier (Mo)","catalog.options.max_image_size_kb":"Taille maximale d’une image (Ko)","catalog.options.min_readable_ratio":"Part minimale de lignes lisibles","catalog.options.max_weighable_drop":"Baisse maximale des produits pesables","catalog.options.max_archives":"Archives conservées","catalog.options.archive_days":"Archives conservées (jours)","catalog.options.failures_before_reject":"Échecs avant mise en quarantaine","catalog.images.source":"Origine des photos","catalog.images.path":"Répertoire des photos","catalog.fallback_category":"Rayon par défaut","journal.max_rows":"Pesées conservées","journal.max_days":"Pesées conservées (jours)","journal.max_technical":"Événements techniques conservés","admin.session_minutes":"Durée d’une session (minutes)","admin.attempts_per_minute":"Tentatives par minute","maintenance.weekly_integrity_check":"Contrôle d’intégrité hebdomadaire","maintenance.disk_alert_mb":"Alerte disque en dessous de (Mo)"};function qt(a){return Fn[a]??a}const Un={station:"l’identité du poste",network:"le réseau",ui:"l’écran client",scale:"la balance",printer:"l’imprimante",pricing:"les tarifs",barcode:"le code-barres",limits:"les garde-fous",stability:"la stabilité",catalog:"le catalogue",journal:"le journal",maintenance:"la maintenance"};function Mn(a){return Un[a]??a}const Wn={scale:"balance",printer:"imprimante",catalog:"catalogue",ui:"écran",config:"configuration",http:"réseau",system:"système"};function mr(a){return Wn[a]??"origine inconnue"}const qa="openscale.admin.preferences",hr="technical";class Bn{#t=B(vt(Vn()));get showTechnicalNames(){return e(this.#t)}set showTechnicalNames(t){v(this.#t,t,!0)}toggleTechnicalNames(){this.showTechnicalNames=!this.showTechnicalNames,Gn(this.showTechnicalNames)}}function Vn(){try{return globalThis.localStorage?.getItem(qa)===hr}catch{return!1}}function Gn(a){try{a?globalThis.localStorage?.setItem(qa,hr):globalThis.localStorage?.removeItem(qa)}catch{}}const St=new Bn,Hn=3e3,Jn=["hardware","label","rules","catalog","journal","station","update"];function Wa(a){return Jn.includes(a)}function Kn(a){return a instanceof Pt&&a.needsCredentials}class $n{constructor(t=Hn){this.periodMs=t}periodMs;#t=B(null);get health(){return e(this.#t)}set health(t){v(this.#t,t,!0)}#r=B("dashboard");get page(){return e(this.#r)}set page(t){v(this.#r,t,!0)}#a=B(!1);get expert(){return e(this.#a)}set expert(t){v(this.#a,t,!0)}#e=B("");get linkError(){return e(this.#e)}set linkError(t){v(this.#e,t,!0)}#n=B("");get actionError(){return e(this.#n)}set actionError(t){v(this.#n,t,!0)}#l=B(!1);get needsFirstPassword(){return e(this.#l)}set needsFirstPassword(t){v(this.#l,t,!0)}#d=B("");get notice(){return e(this.#d)}set notice(t){v(this.#d,t,!0)}#v=B(!1);get busy(){return e(this.#v)}set busy(t){v(this.#v,t,!0)}#p=B(vt([]));get lastFaults(){return e(this.#p)}set lastFaults(t){v(this.#p,t,!0)}#f=B(null);get pending(){return e(this.#f)}set pending(t){v(this.#f,t,!0)}#i=null;#o=null;start(){this.refresh(),this.#i=setInterval(()=>{this.refresh()},this.periodMs)}stop(){this.#i!==null&&clearInterval(this.#i),this.#i=null}async refresh(){try{this.health=await Qr(),this.linkError=""}catch(t){this.linkError=Ba(t)}}#u(){this.busy=!0,this.notice="",this.actionError="",this.needsFirstPassword=!1}#s(t){this.actionError=Ba(t),this.needsFirstPassword=t instanceof Pt&&t.needsFirstPassword,this.#m(t)}async run(t){this.#u();let r=null;try{r=await t(),this.notice=r.message}catch(i){this.#s(i)}finally{this.busy=!1}return await this.refresh(),r}async login(t){this.#u();try{return await un(t),this.expert=!0,this.notice="Session d’administration ouverte.",!0}catch(r){return this.expert=!1,this.#s(r),!1}finally{this.busy=!1}}async recover(t,r){this.#u();try{const i=await dn(t,r);return this.expert=!0,this.notice=i.warning??"Le mot de passe est remplacé et la session est ouverte.",!0}catch(i){return this.#s(i),!1}finally{this.busy=!1}}async protect(t){try{return await t()}catch(r){if(!Kn(r))return this.#s(r),null;if(!await this.#g(r))return null;try{return await t()}catch(i){return this.#s(i),null}}}#g(t){return this.pending={kind:t.needsFirstPassword?"first-password":"password",message:t.message},new Promise(r=>{this.#o=r})}async answerPassword(t){await this.login(t)&&this.#c(!0)}async answerRecovery(t,r){await this.recover(t,r)&&this.#c(!0)}cancelPassword(){this.#c(!1)}#c(t){this.pending=null,this.notice="";const r=this.#o;this.#o=null,r?.(t)}async logout(){await cn(),this.expert=!1,this.page="dashboard",this.notice="Session d’administration fermée."}open(t){this.actionError="",this.notice="",this.needsFirstPassword=!1,this.page=t}async load(t){try{const r=await t();return this.actionError="",this.lastFaults=[],r}catch(r){return this.lastFaults=r instanceof Pt?r.faults:[],this.#s(r),null}}report(t){this.lastFaults=t instanceof Pt?t.faults:[],this.#s(t)}#m(t){t instanceof Pt&&t.needsPassword&&(this.expert=!1)}}function Ba(a){return a instanceof Pt?a.message:a instanceof Error?"Le poste n’a pas répondu : "+a.message:"Le poste n’a pas répondu."}var Yn=c('clé'),Xn=c('');function Te(a,t){const r=Be(t,"kind",3,"read"),i=Be(t,"busy",3,!1),d=Be(t,"disabled",3,!1),p=Be(t,"protected",3,!1),y=Be(t,"act",3,void 0);var z=Xn();let m;var j=s(z),S=n(j);{var A=L=>{var W=Yn();l(L,W)};_(S,L=>{p()&&L(A)})}f(()=>{m=Nt(z,1,`act ${r()??""}`,"svelte-5tpq0o",m,{"touch-target":r()==="destructive",busy:i()}),be(z,"data-kind",r()),be(z,"data-act",y()),z.disabled=d()||i(),o(j,`${(i()?"En cours…":t.label)??""} `)}),Ce("click",z,function(...L){t.onrun?.apply(this,L)}),l(a,z)}ot(["click"]);var Qn=c(`
Le code de secours a été tiré à l’installation de ce poste et imprimé
+import{Y as Tr,Z as zr,_ as jr,$ as Ea,a0 as Vt,e as Rr,a1 as or,a2 as Or,a3 as Ar,a4 as Nr,u as ma,a5 as Ca,a6 as Ir,a7 as ur,x as wt,A as B,h as e,z as v,H as vt,d as ot,a as Be,s as n,i as _,t as f,l as Nt,j as be,m as o,b as Ce,c as l,o as s,g as c,p as Ue,I as Dr,f as Me,n as u,q as ae,a8 as Ia,r as ze,G as Gt,a9 as ea,aa as Tt,B as da,ab as lt,ac as Xt,ad as ka,C as Fr,J as cr,y as sa,T as Ur,ae as Ht,F as Mr,E as Wr,D as Br,O as Vr,K as Gr,X as Hr,af as Jr}from"./app-BaRSXv80.js";function dr(a){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Kr(a,t,...r){var i=new jr(a);Tr(()=>{const d=t()??null;i.ensure(d,d&&(p=>d(p,...r)))},zr)}function Pa(a,t,r=!1){if(a.multiple){if(t==null)return;if(!Or(t))return Ar();for(var i of a.options)i.selected=t.includes(la(i));return}for(i of a.options){var d=la(i);if(Nr(d,t)){i.selected=!0;return}}(!r||t!==void 0)&&(a.selectedIndex=-1)}function vr(a){var t=new MutationObserver(()=>{"__value"in a&&Pa(a,a.__value)});t.observe(a,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),or(()=>{t.disconnect()})}function $r(a,t,r=t){var i=new WeakSet,d=!0;Ea(a,"change",p=>{var y=p?"[selected]":":checked",z;if(a.multiple)z=[].map.call(a.querySelectorAll(y),la);else{var m=a.querySelector(y)??a.querySelector("option:not([disabled])");z=m&&la(m)}r(z),a.__value=z,Vt!==null&&i.add(Vt)}),Rr(()=>{var p=t();if(a===document.activeElement){var y=Vt;if(i.has(y))return}if(Pa(a,p,d),d&&p===void 0){var z=a.querySelector(":checked");z!==null&&(p=la(z),r(p))}a.__value=p,d=!1}),vr(a)}function la(a){return"__value"in a?a.__value:a.value}function ia(a,t,r=t){var i=new WeakSet;Ea(a,"input",async d=>{var p=d?a.defaultValue:a.value;if(p=ba(a)?wa(p):p,r(p),Vt!==null&&i.add(Vt),await Ir(),p!==(p=t())){var y=a.selectionStart,z=a.selectionEnd,m=a.value.length;if(a.value=p??"",z!==null){var j=a.value.length;y===z&&z===m&&j>m?(a.selectionStart=j,a.selectionEnd=j):(a.selectionStart=y,a.selectionEnd=Math.min(z,j))}}}),ma(t)==null&&a.value&&(r(ba(a)?wa(a.value):a.value),Vt!==null&&i.add(Vt)),Ca(()=>{var d=t();if(a===document.activeElement){var p=Vt;if(i.has(p))return}ba(a)&&d===wa(a.value)||a.type==="date"&&!d&&!a.value||d!==a.value&&(a.value=d??"")})}function Da(a,t,r=t){Ea(a,"change",i=>{var d=i?a.defaultChecked:a.checked;r(d)}),ma(t)==null&&r(a.checked),Ca(()=>{var i=t();a.checked=!!i})}function ba(a){var t=a.type;return t==="number"||t==="range"}function wa(a){return a===""?null:+a}function Fa(a,t,r,i,d){var p=()=>{i(r[a])};r.addEventListener(t,p),d?Ca(()=>{r[a]=d()}):p(),(r===document.body||r===window||r===document)&&or(()=>{r.removeEventListener(t,p)})}function Ta(a){ur===null&&dr(),wt(()=>{const t=ma(a);if(typeof t=="function")return t})}function Yr(a){ur===null&&dr(),Ta(()=>()=>ma(a))}const Xr="ERR-CFG-02";class Pt extends Error{constructor(t,r,i="",d=[]){super(r),this.status=t,this.code=i,this.faults=d,this.name="AdminError"}status;code;faults;get needsPassword(){return this.status===401}get needsFirstPassword(){return this.status===409&&this.code===Xr}get needsCredentials(){return this.needsPassword||this.needsFirstPassword}}function fa(a){return a instanceof Pt&&a.needsCredentials}function Qr(){return It("/admin/api/health")}function Zr(){return He("/admin/api/troubleshooting/reprint",{})}function en(){return He("/admin/api/troubleshooting/reload-catalog",{})}function tn(a){return He("/admin/api/troubleshooting/manual-entry",{on:a})}function an(){return He("/admin/api/troubleshooting/roll-changed",{})}function rn(a){return He("/admin/api/troubleshooting/fallback-printer",{on:a})}function nn(){return He("/admin/api/troubleshooting/test-scale",{})}function sn(){return He("/admin/api/troubleshooting/test-printer",{})}function ln(){return He("/admin/api/troubleshooting/test-label",{})}async function pr(a){const t=new FormData;t.append("file",a,a.name);const r=await fetch("/admin/api/catalog/import",{method:"POST",body:t});return Ra(r,"POST /admin/api/catalog/import")}const on="/admin/api/diagnostic.zip";function un(a){return He("/admin/api/session",{password:a})}async function cn(){await fetch("/admin/api/session",{method:"DELETE"})}function dn(a,t){return He("/admin/api/session/recovery",{code:a,password:t})}function za(){return It("/admin/api/config")}function vn(a){return ja("PUT","/admin/api/config",a)}function pn(){return He("/admin/api/config/reload",{})}function fn(){return He("/admin/api/restart",{})}function gn(){return He("/admin/api/reboot",{})}function mn(){return ja("DELETE","/admin/api/reboot",{})}function hn(){return He("/admin/api/config/confirm",{})}async function _n(){return(await It("/admin/api/config/versions")).versions}function bn(a){return He("/admin/api/config/restore",{version:a})}async function wn(){return(await It("/admin/api/ports")).ports}async function yn(){return(await It("/admin/api/printers")).printers}async function xn(){return(await He("/admin/api/printers/discover",{})).printers}function kn(a){return He("/admin/api/scale/detect",{port:a})}async function Ua(a,t){return(await He("/admin/api/scale/capture",{port:a,seconds:t})).frames}function fr(a){return He("/admin/api/printer/test?what="+a,{})}function qn(a,t,r,i){const d=new URLSearchParams({template:a,demo:t?"1":"0",dual:r?"1":"0"});return d.set("t",String(i)),"/admin/api/label/preview.png?"+d.toString()}async function Sn(a){const t=new URLSearchParams(a);return(await It("/admin/api/journal?"+t)).weighings}function Ln(a){return"/admin/api/journal/export.csv?"+new URLSearchParams(a).toString()}async function En(a){const t=new URLSearchParams(a);return(await It("/admin/api/technical?"+t)).entries}function Cn(a){const t=a===void 0?"":"?id="+String(a);return It("/admin/api/imports"+t)}function Pn(){return He("/admin/api/catalog/reload",{})}function Tn(){return He("/admin/api/catalog/forget-quarantine",{})}function Ma(a,t){return He("/admin/api/products/"+encodeURIComponent(a)+"/decision",t)}function zn(a){return He("/admin/api/replay",{frame:a})}async function It(a){const t=await fetch(a,{headers:{accept:"application/json"}});return Ra(t,"GET "+a)}function He(a,t){return ja("POST",a,t)}async function ja(a,t,r){const i=await fetch(t,{method:a,headers:{"content-type":"application/json"},body:JSON.stringify(r)});return Ra(i,a+" "+t)}async function Ra(a,t){const r=await a.text();if(!a.ok){const i=gr(r);throw new Pt(a.status,Rn(r,t,a.status)+jn(a),i?.code??"",i?.faults??[])}if(r!=="")return JSON.parse(r)}function jn(a){if(a.status!==429)return"";const t=Number(a.headers.get("Retry-After")??"");if(!Number.isFinite(t)||t<=0)return"";const r=Math.ceil(t/60);return r>1?` Réessayez dans ${String(r)} minutes.`:" Réessayez dans une minute."}function Rn(a,t,r){const i=gr(a);return i?.message!==void 0&&i.message!==""?i.message:`${t} a répondu ${String(r)}.`}function gr(a){try{return JSON.parse(a)}catch{return null}}function On(){return It("/admin/api/update")}function An(){return He("/admin/api/update/check",{})}function Nn(a){return He("/admin/api/update/apply",{version:a})}class In{constructor(t){this.admin=t}admin;#t=B(null);get config(){return e(this.#t)}set config(t){v(this.#t,t,!0)}#r=B("");get fingerprint(){return e(this.#r)}set fingerprint(t){v(this.#r,t,!0)}#a=B(vt([]));get retired(){return e(this.#a)}set retired(t){v(this.#a,t,!0)}#e=B(null);get pending(){return e(this.#e)}set pending(t){v(this.#e,t,!0)}#n=B(vt([]));get faults(){return e(this.#n)}set faults(t){v(this.#n,t,!0)}#l=B(!1);get dirty(){return e(this.#l)}set dirty(t){v(this.#l,t,!0)}async load(){const t=await this.admin.load(()=>za());t!==null&&(this.config=t.config,this.fingerprint=t.config_fingerprint,this.retired=t.retired_keys??[],this.pending=t.pending_confirmation,this.faults=[],this.dirty=!1)}value(t){let r=this.config;for(const i of t.split(".")){if(r===null||typeof r!="object")return;r=r[i]}return r}text(t){const r=this.value(t);return r==null?"":String(r)}number(t){const r=this.value(t);return typeof r=="number"?r:Number(r??0)}flag(t){return this.value(t)===!0}set(t,r){if(this.config===null)return;const i=t.split("."),d=i.pop();if(d===void 0)return;let p=this.config;for(const y of i){const z=p[y];(z===null||typeof z!="object")&&(p[y]={}),p=p[y]}p[d]=r,this.dirty=!0}unset(t){const r=t.split("."),i=r.pop();if(i===void 0||this.config===null)return!1;let d=this.config;for(const p of r){if(d===null||typeof d!="object")return!1;d=d[p]}return d===null||typeof d!="object"?!1:(delete d[i],this.dirty=!0,!0)}async save(){if(this.config===null)return!1;this.faults=[];const t=this.config;let r;try{r=await vn(t)}catch(i){if(fa(i))throw i;return this.admin.report(i),this.faults=Dn(this.admin),!1}return this.config=r.config,this.fingerprint=r.config_fingerprint,this.retired=r.retired_keys??[],this.pending=r.pending_confirmation,this.dirty=!1,!0}async confirm(){try{await hn()}catch(t){if(fa(t))throw t;this.admin.report(t);return}this.admin.notice="La configuration est confirmée.",this.pending=null,await this.admin.refresh()}dropRetired(t){if(t.includes("[")){this.admin.actionError=`« ${t} » est logée dans un tableau : cet écran ne sait pas la retirer de là. Modifiez le fichier de configuration lui-même.`;return}this.unset(t)&&(this.retired=this.retired.filter(r=>r!==t))}}function Dn(a){return a.lastFaults}const Fn={"station.number":"Numéro du poste","station.name":"Nom du poste","station.coop":"Nom de la coopérative","network.listen":"Adresse d’écoute","network.admin_on_lan":"Administration accessible depuis le réseau","ui.language":"Langue","ui.sound":"Son","ui.idle_timeout_s":"Retour à l’accueil après (secondes)","ui.reprint_window_s":"Réimpression possible pendant (secondes)","ui.show_grid_prices":"Afficher les prix sur les tuiles","ui.show_by_unit_products":"Afficher les produits vendus à l’unité","ui.grid_columns":"Colonnes de la grille","ui.min_products_for_chip":"Articles minimum pour afficher une catégorie","scale.type":"Protocole de la balance","scale.present":"Ce poste a une balance","scale.manual_entry_allowed":"Saisie manuelle autorisée","scale.degrade_after_s":"Passer en mode dégradé après (secondes)","scale.options.port":"Port série","scale.options.baud":"Vitesse (bauds)","scale.options.bits":"Bits de données","scale.options.parity":"Parité","scale.options.stop":"Bits d’arrêt","scale.options.backoff_min_ms":"Attente minimale avant réessai (ms)","scale.options.backoff_max_ms":"Attente maximale avant réessai (ms)","printer.type":"Pilote d’impression","printer.template":"Gabarit d’étiquette","printer.options.transport":"Transport","printer.options.queue":"File d’impression","printer.options.path":"Fichier de périphérique","printer.options.address":"Adresse réseau","printer.options.darkness":"Noircissement","printer.options.speed":"Vitesse d’impression","printer.options.offset_x":"Décalage horizontal (dots)","printer.options.offset_y":"Décalage vertical (dots)","printer.options.invert_bits":"Inverser les points","printer.options.copies":"Exemplaires","printer.options.roll_capacity":"Étiquettes par rouleau","pricing.amount_rounding":"Arrondi du montant","pricing.unit_price_rounding":"Arrondi du prix au kilo","pricing.primary_code":"Tarif principal","pricing.reference_code":"Tarif de référence","barcode.verify_reference_check_digit":"Vérifier la clé de contrôle","limits.empty_max_g":"Plateau considéré vide en dessous de (g)","limits.basket_check_enabled":"Vérifier la présence du panier","limits.basket_min_g":"Poids du panier, borne basse (g)","limits.basket_max_g":"Poids du panier, borne haute (g)","limits.min_weight_g":"Poids minimum accepté","limits.max_weight_g":"Poids maximum accepté","limits.max_tare_g":"Tare maximale","limits.min_units":"Unités minimum","limits.max_units":"Unités maximum","limits.max_amount_cents":"Montant maximum (centimes)","stability.mode":"Exigence de stabilité","stability.min_duration_ms":"Durée de stabilité (ms)","stability.tolerance_g":"Tolérance de stabilité (g)","stability.timeout_ms":"Délai d’attente de stabilité (ms)","stability.on_timeout":"Au bout du délai","stability.min_latch_rate":"Taux d’accroche minimal","stability.latch_rate_window_ms":"Fenêtre de mesure du taux (ms)","stability.expiry_floor_ms":"Péremption, plancher (ms)","stability.expiry_ceiling_ms":"Péremption, plafond (ms)","stability.expiry_factor":"Péremption, facteur","catalog.type":"Où le poste va chercher le catalogue","catalog.options.directory":"Répertoire surveillé","catalog.options.url":"Adresse du serveur","catalog.options.username":"Compte","catalog.options.password":"Mot de passe","catalog.options.separator":"Séparateur du CSV","catalog.options.poll_interval_s":"Vérifier toutes les (secondes)","catalog.options.stable_polls":"Vérifications avant lecture","catalog.options.max_file_size_mb":"Taille maximale du fichier (Mo)","catalog.options.max_image_size_kb":"Taille maximale d’une image (Ko)","catalog.options.min_readable_ratio":"Part minimale de lignes lisibles","catalog.options.max_weighable_drop":"Baisse maximale des produits pesables","catalog.options.max_archives":"Archives conservées","catalog.options.archive_days":"Archives conservées (jours)","catalog.options.failures_before_reject":"Échecs avant mise en quarantaine","catalog.images.source":"Origine des photos","catalog.images.path":"Répertoire des photos","catalog.fallback_category":"Rayon par défaut","journal.max_rows":"Pesées conservées","journal.max_days":"Pesées conservées (jours)","journal.max_technical":"Événements techniques conservés","admin.session_minutes":"Durée d’une session (minutes)","admin.attempts_per_minute":"Tentatives par minute","maintenance.weekly_integrity_check":"Contrôle d’intégrité hebdomadaire","maintenance.disk_alert_mb":"Alerte disque en dessous de (Mo)"};function qt(a){return Fn[a]??a}const Un={station:"l’identité du poste",network:"le réseau",ui:"l’écran client",scale:"la balance",printer:"l’imprimante",pricing:"les tarifs",barcode:"le code-barres",limits:"les garde-fous",stability:"la stabilité",catalog:"le catalogue",journal:"le journal",maintenance:"la maintenance"};function Mn(a){return Un[a]??a}const Wn={scale:"balance",printer:"imprimante",catalog:"catalogue",ui:"écran",config:"configuration",http:"réseau",system:"système"};function mr(a){return Wn[a]??"origine inconnue"}const qa="openscale.admin.preferences",hr="technical";class Bn{#t=B(vt(Vn()));get showTechnicalNames(){return e(this.#t)}set showTechnicalNames(t){v(this.#t,t,!0)}toggleTechnicalNames(){this.showTechnicalNames=!this.showTechnicalNames,Gn(this.showTechnicalNames)}}function Vn(){try{return globalThis.localStorage?.getItem(qa)===hr}catch{return!1}}function Gn(a){try{a?globalThis.localStorage?.setItem(qa,hr):globalThis.localStorage?.removeItem(qa)}catch{}}const St=new Bn,Hn=3e3,Jn=["hardware","label","rules","catalog","journal","station","update"];function Wa(a){return Jn.includes(a)}function Kn(a){return a instanceof Pt&&a.needsCredentials}class $n{constructor(t=Hn){this.periodMs=t}periodMs;#t=B(null);get health(){return e(this.#t)}set health(t){v(this.#t,t,!0)}#r=B("dashboard");get page(){return e(this.#r)}set page(t){v(this.#r,t,!0)}#a=B(!1);get expert(){return e(this.#a)}set expert(t){v(this.#a,t,!0)}#e=B("");get linkError(){return e(this.#e)}set linkError(t){v(this.#e,t,!0)}#n=B("");get actionError(){return e(this.#n)}set actionError(t){v(this.#n,t,!0)}#l=B(!1);get needsFirstPassword(){return e(this.#l)}set needsFirstPassword(t){v(this.#l,t,!0)}#d=B("");get notice(){return e(this.#d)}set notice(t){v(this.#d,t,!0)}#v=B(!1);get busy(){return e(this.#v)}set busy(t){v(this.#v,t,!0)}#p=B(vt([]));get lastFaults(){return e(this.#p)}set lastFaults(t){v(this.#p,t,!0)}#f=B(null);get pending(){return e(this.#f)}set pending(t){v(this.#f,t,!0)}#i=null;#o=null;start(){this.refresh(),this.#i=setInterval(()=>{this.refresh()},this.periodMs)}stop(){this.#i!==null&&clearInterval(this.#i),this.#i=null}async refresh(){try{this.health=await Qr(),this.linkError=""}catch(t){this.linkError=Ba(t)}}#u(){this.busy=!0,this.notice="",this.actionError="",this.needsFirstPassword=!1}#s(t){this.actionError=Ba(t),this.needsFirstPassword=t instanceof Pt&&t.needsFirstPassword,this.#m(t)}async run(t){this.#u();let r=null;try{r=await t(),this.notice=r.message}catch(i){this.#s(i)}finally{this.busy=!1}return await this.refresh(),r}async login(t){this.#u();try{return await un(t),this.expert=!0,this.notice="Session d’administration ouverte.",!0}catch(r){return this.expert=!1,this.#s(r),!1}finally{this.busy=!1}}async recover(t,r){this.#u();try{const i=await dn(t,r);return this.expert=!0,this.notice=i.warning??"Le mot de passe est remplacé et la session est ouverte.",!0}catch(i){return this.#s(i),!1}finally{this.busy=!1}}async protect(t){try{return await t()}catch(r){if(!Kn(r))return this.#s(r),null;if(!await this.#g(r))return null;try{return await t()}catch(i){return this.#s(i),null}}}#g(t){return this.pending={kind:t.needsFirstPassword?"first-password":"password",message:t.message},new Promise(r=>{this.#o=r})}async answerPassword(t){await this.login(t)&&this.#c(!0)}async answerRecovery(t,r){await this.recover(t,r)&&this.#c(!0)}cancelPassword(){this.#c(!1)}#c(t){this.pending=null,this.notice="";const r=this.#o;this.#o=null,r?.(t)}async logout(){await cn(),this.expert=!1,this.page="dashboard",this.notice="Session d’administration fermée."}open(t){this.actionError="",this.notice="",this.needsFirstPassword=!1,this.page=t}async load(t){try{const r=await t();return this.actionError="",this.lastFaults=[],r}catch(r){return this.lastFaults=r instanceof Pt?r.faults:[],this.#s(r),null}}report(t){this.lastFaults=t instanceof Pt?t.faults:[],this.#s(t)}#m(t){t instanceof Pt&&t.needsPassword&&(this.expert=!1)}}function Ba(a){return a instanceof Pt?a.message:a instanceof Error?"Le poste n’a pas répondu : "+a.message:"Le poste n’a pas répondu."}var Yn=c('clé'),Xn=c('');function Te(a,t){const r=Be(t,"kind",3,"read"),i=Be(t,"busy",3,!1),d=Be(t,"disabled",3,!1),p=Be(t,"protected",3,!1),y=Be(t,"act",3,void 0);var z=Xn();let m;var j=s(z),S=n(j);{var A=L=>{var W=Yn();l(L,W)};_(S,L=>{p()&&L(A)})}f(()=>{m=Nt(z,1,`act ${r()??""}`,"svelte-5tpq0o",m,{"touch-target":r()==="destructive",busy:i()}),be(z,"data-kind",r()),be(z,"data-act",y()),z.disabled=d()||i(),o(j,`${(i()?"En cours…":t.label)??""} `)}),Ce("click",z,function(...L){t.onrun?.apply(this,L)}),l(a,z)}ot(["click"]);var Qn=c(`
Le code de secours a été tiré à l’installation de ce poste et imprimé
sur sa fiche, rangée dans le classeur du magasin. Il n’existe nulle part ailleurs.
`,1),Zn=c(`
Oublié ? Le code de secours de la fiche d’installation en repose un.
Un responsable peut aussi le faire en ligne de commande, avec openscale config password.
`,1),es=c('
'),ts=c('
');function as(a,t){Ue(t,!0);const r=u(()=>t.admin.pending?.kind==="first-password");let i=B(""),d=B("");const p=8,y=u(()=>e(r)?e(d).trim().length>0&&e(i).length>=p:e(i).length>0);async function z(){!e(y)||t.admin.busy||(e(r)?await t.admin.answerRecovery(e(d),e(i)):await t.admin.answerPassword(e(i)),v(i,""),v(d,""))}var m=ts(),j=s(m),S=s(j),A=s(S),L=s(A);Dr(L,{name:"settings",size:"1.5rem"});var W=n(A,2),O=s(W),C=n(S,2),K=s(C),U=n(C,2);{var E=T=>{var w=Qn(),k=n(ae(w),2),R=n(s(k),2);Ia(R);var F=n(k,2),h=s(F);h.textContent="Nouveau mot de passe — 8 caractères au moins";var G=n(h,2);Ce("keydown",R,Y=>Y.key==="Enter"&&void z()),ia(R,()=>e(d),Y=>v(d,Y)),Ce("keydown",G,Y=>Y.key==="Enter"&&void z()),ia(G,()=>e(i),Y=>v(i,Y)),l(T,w)},x=T=>{var w=Zn(),k=ae(w),R=n(s(k),2);Ia(R),Ce("keydown",R,F=>F.key==="Enter"&&void z()),ia(R,()=>e(i),F=>v(i,F)),l(T,w)};_(U,T=>{e(r)?T(E):T(x,-1)})}var g=n(U,2);{var D=T=>{var w=es(),k=s(w);f(()=>o(k,t.admin.actionError)),l(T,w)};_(g,T=>{t.admin.actionError!==""&&T(D)})}var H=n(g,2),V=s(H);Te(V,{label:"Annuler",onrun:()=>t.admin.cancelPassword()});var $=n(V,2);{let T=u(()=>e(r)?"Poser ce mot de passe":"Continuer"),w=u(()=>!e(y)||t.admin.busy);Te($,{kind:"write",get label(){return e(T)},get disabled(){return e(w)},onrun:()=>{z()}})}f(()=>{o(O,e(r)?"Ce poste n’a pas encore de mot de passe":"Mot de passe d’administration"),o(K,t.admin.pending?.message??"")}),l(a,m),Me()}ot(["keydown"]);var rs=c(''),ns=c(""),ss=c(''),ls=c(''),is=c(""),os=c(""),us=c('
Le poste y cherche le fichier , et le supprime
une fois lu : c’est ce qui dit au producteur que la livraison est prise.
`,1),hs=c(`
Sur un serveur WebDAV, le dépôt d’un fichier CSV depuis cet écran n’est plus
@@ -7,7 +7,7 @@ import{Y as Tr,Z as zr,_ as jr,$ as Ea,a0 as Vt,e as Rr,a1 as or,a2 as Or,a3 as
chercher aucun catalogue.
`),bs=c('
',1);function ws(a,t){Ue(t,!0);const r={local_drop:["catalog.options.directory"],webdav:["catalog.options.url","catalog.options.username","catalog.options.password"]},i=u(()=>t.draft.text("catalog.type"));function d(p){t.draft.set("catalog.type",p);for(const[y,z]of Object.entries(r))if(y!==p)for(const m of z)t.draft.unset(m)}Oe(a,{title:"Où le poste va chercher le catalogue",children:(p,y)=>{var z=bs(),m=ae(z),j=s(m),S=s(j),A=n(j,2),L=s(A),W=n(m,2);{var O=E=>{var x=gs();l(E,x)},C=E=>{var x=ms(),g=ae(x);{let $=u(()=>qt("catalog.options.directory")),T=u(()=>t.draft.text("catalog.options.directory")),w=u(()=>$e(t.draft,"catalog.options.directory"));at(g,{get label(){return e($)},path:"catalog.options.directory",get value(){return e(T)},hint:"Laissez vide pour le répertoire du poste, celui que le service crée lui-même. Un répertoire nommé ici doit exister : le poste ne le crée pas.",get fault(){return e(w)},onchange:k=>t.draft.set("catalog.options.directory",k)})}var D=n(g,2),H=n(s(D)),V=s(H);f(()=>o(V,`flv_${t.station??""}.csv`)),l(E,x)},K=E=>{var x=hs(),g=ae(x);{let V=u(()=>qt("catalog.options.url")),$=u(()=>t.draft.text("catalog.options.url")),T=u(()=>$e(t.draft,"catalog.options.url"));at(g,{get label(){return e(V)},path:"catalog.options.url",get value(){return e($)},get fault(){return e(T)},onchange:w=>t.draft.set("catalog.options.url",w)})}var D=n(g,2);{let V=u(()=>qt("catalog.options.username")),$=u(()=>t.draft.text("catalog.options.username")),T=u(()=>$e(t.draft,"catalog.options.username"));at(D,{get label(){return e(V)},path:"catalog.options.username",get value(){return e($)},get fault(){return e(T)},onchange:w=>t.draft.set("catalog.options.username",w)})}var H=n(D,2);{let V=u(()=>qt("catalog.options.password")),$=u(()=>$e(t.draft,"catalog.options.password"));at(H,{get label(){return e(V)},path:"catalog.options.password",kind:"password",value:"",hint:"Laissez vide : le mot de passe actuel est conservé.",get fault(){return e($)},onchange:T=>t.draft.set("catalog.options.password",T)})}l(E,x)},U=E=>{var x=_s();l(E,x)};_(W,E=>{t.draft.config===null?E(O):e(i)==="local_drop"?E(C,1):e(i)==="webdav"?E(K,2):E(U,-1)})}f(()=>{ea(S,e(i)==="local_drop"),ea(L,e(i)==="webdav")}),Ce("change",S,()=>d("local_drop")),Ce("change",L,()=>d("webdav")),l(p,z)},$$slots:{default:!0}}),Me()}ot(["change"]);const Va=1e3;function va(a){const t=Oa(a);return t===null?"":[Zt(t.getDate()),Zt(t.getMonth()+1),String(t.getFullYear())].join("/")}function Lt(a){const t=Oa(a);return t===null?"":`${va(a)} à ${Zt(t.getHours())}:${Zt(t.getMinutes())}`}function ys(a){const t=Oa(a);return t===null?"":[Zt(t.getHours()),Zt(t.getMinutes()),Zt(t.getSeconds())].join(":")}function Sa(a){const t=a/1e6;return t<1e3?`${Math.round(t)} Mo`:`${_r(t/1e3)} Go`}function se(a){const t=String(Math.abs(Math.trunc(a))),r=[];for(let i=t.length;i>0;i-=3)r.unshift(t.slice(Math.max(0,i-3),i));return(a<0?"-":"")+r.join(" ")}function ua(a){return a0}function qs(a){const t=a.motive!=="";return{canWithdraw:t||!pa(!1,a.waiverInForce),canOfferAgain:t||!pa(!0,a.waiverInForce),canSaveWaiver:ks(a.typedWaiver)&&(t||!pa(a.offeredInForce,a.typedWaiver)),canDropWaiver:t||!pa(a.offeredInForce,null)}}function br(a){const t=[];return a.offered||t.push("retiré de la grille"),a.min_weight_g!==null&&t.push(`peut peser à partir de ${se(a.min_weight_g)} g`),t.length===0?"aucune restriction":t.join(" · ")}function ca(a,t,r,i){const d=t>1?i:r;return a>=t?`${se(t)} ${d}.`:`${se(a)} lignes affichées sur ${se(t)} ${d}.`}function Ss(a,t){return t>a?`${se(a)} produits affichés sur ${se(t)} trouvés — précisez votre recherche.`:`${se(t)} ${t>1?"produits trouvés":"produit trouvé"}.`}function Ls(a){return`${se(a)} ${a>1?"imports affichés":"import affiché"} : le poste n’en publie jamais plus de vingt.`}function ya(a,t,r,i){const d=`${se(r)} ${r>1?t:a}`;return r<=i?d+".":`${d} — seules les ${se(i)} premières lignes sont affichées.`}function Es(a,t){const r=`${se(a)} ${a>1?"produits retirés":"produit retiré"}`;return t===""?r+".":`${r} depuis l’import du ${Lt(t)}.`}var Cs=c('
Aucune décision locale : la grille est celle du fichier.
'),Ps=c('
'),Ts=c('
',1);function zs(a,t){Ue(t,!0);const r=20,i=u(()=>t.decisions.slice(0,r));Oe(a,{title:"Décisions en vigueur",note:"Ce qu’un humain a décidé, produit par produit. C’est ici que se reprend un produit retiré de la grille.",children:(d,p)=>{var y=Tt(),z=ae(y);{var m=S=>{var A=Cs();l(S,A)},j=S=>{var A=Ts(),L=ae(A),W=s(L),O=n(L,2),C=s(O);ze(C,21,()=>e(i),K=>K.product_id,(K,U)=>{var E=Ps(),x=s(E),g=n(x,2),D=s(g),H=n(g,2),V=s(H),$=n(H,2),T=s($),w=n($,2),k=s(w),R=n(w,2),F=s(R);f((h,G,Y)=>{o(D,h),o(V,e(U).product_id),o(T,G),o(k,e(U).reason),o(F,Y)},[()=>t.nameOf(e(U).product_id),()=>br(e(U)),()=>va(e(U).decided_at)]),Ce("click",x,()=>t.onchoose(e(U).product_id)),l(K,E)}),f(K=>o(W,K),[()=>ca(e(i).length,t.decisions.length,"décision en vigueur","décisions en vigueur")]),l(S,A)};_(z,S=>{t.decisions.length===0?S(m):S(j,-1)})}l(d,y)},$$slots:{default:!0}}),Me()}ot(["click"]);function js(a){return a==="loading"?"Lecture des signalements du dernier import…":"Les signalements du dernier import n’ont pas pu être lus : cet écran ne sait pas ce qu’ils disent."}function Rs(a){return a==="loading"?"Lecture de l’historique des imports…":"L’historique des imports n’a pas pu être lu : cet écran ne sait pas ce qu’il contient."}function Aa(a,t,r){return a!==void 0?a:t==="loading"?"Lecture du nom…":t==="unread"?r:"Produit absent du catalogue en service"}var Ga=c('
'),Os=c(''),As=c('
'),Ns=c('
',1);function xa(a,t){Ue(t,!0);const r=Be(t,"remedy",3,""),i=50,d=u(()=>t.findings.slice(0,i)),p=u(()=>t.findings.length>e(d).length);Oe(a,{get title(){return t.title},get note(){return t.note},children:(y,z)=>{var m=Tt(),j=ae(m);{var S=W=>{var O=Ga(),C=s(O);f(K=>{be(O,"data-unread",t.list),o(C,K)},[()=>js(t.state)]),l(W,O)},A=W=>{var O=Ga(),C=s(O);f(()=>o(C,t.none)),l(W,O)},L=W=>{var O=Ns(),C=ae(O),K=s(C),U=n(K);{var E=D=>{var H=lt();f(()=>o(H,r())),l(D,H)};_(U,D=>{e(p)&&r()!==""&&D(E)})}var x=n(C,2),g=s(x);ze(g,21,()=>e(d),da,(D,H)=>{var V=As(),$=s(V),T=s($),w=n($,2);{var k=M=>{var b=Os(),N=s(b);f(()=>o(N,e(H).product_name)),l(M,b)};_(w,M=>{e(H).product_name!==""&&M(k)})}var R=n(w,2),F=s(R),h=n(R,2),G=s(h),Y=n(h,2),ne=s(Y);f(M=>{o(T,`ligne ${M??""}`),o(F,e(H).product_id),o(G,e(H).value),o(ne,e(H).message)},[()=>se(e(H).csv_line)]),l(D,V)}),f(D=>{be(C,"data-tally",t.list),o(K,`${D??""} `),be(x,"data-rows",t.list)},[()=>ca(e(d).length,t.findings.length,t.singular,t.plural)]),l(W,O)};_(j,W=>{t.state!=="read"?W(S):t.findings.length===0?W(A,1):W(L,-1)})}l(y,m)},$$slots:{default:!0}}),Me()}function wr(a,t){const r=a.rows_read_count,i=a.images_decoded_count,d=r-i,p=[{count:_t(a.weighable_count),label:"pesables",note:`(${_t(i)} avec photo, ${_t(d)} sans)`,link:""},{count:_t(a.not_weighable_count),label:"non pesables",note:Bs(t),link:""}];if(a.anomalies_count>0&&p.push({count:_t(a.anomalies_count),label:"anomalies",note:"à corriger dans Odoo",link:Ha(a.anomalies_count)}),a.unit_mismatches_count>0){const y=a.unit_mismatches_count;p.push({count:"+ "+_t(y),label:y===1?"unité divergente":"unités divergentes",note:"pesable, unité à corriger",link:Ha(y)})}return{headline:`Catalogue du ${va(a.occurred_at)} — ${_t(r)} produits reçus`,lines:p,oneLine:Is(a)}}function Is(a){const t=[`${_t(a.rows_read_count)} reçus`,`${_t(a.weighable_count)} pesables`,`${_t(a.not_weighable_count)} non pesables`,`${_t(a.anomalies_count)} anomalies`],r=a.unit_mismatches_count;return r>0&&t.push(`${_t(r)} ${r===1?"unité divergente":"unités divergentes"}`),t.join(" · ")}const Ds={applied:"appliqué",unchanged:"identique au précédent",rejected:"refusé",failed:"échec"},Fs={local_drop:"dépôt local",webdav:"WebDAV",manual:"déposé sur l’écran"};function ha(a){return Ds[a]??"résultat inconnu"}function yr(a){return Fs[a]??"source inconnue"}function Us(a,t){const r=[a.file_name===""?"Le dernier fichier":a.file_name,ha(a.result)],i=Lt(a.occurred_at);i!==""&&r.push("le "+i),r.push("via "+yr(a.source));const d=a.reason===""?"":" "+a.reason;return`${r.join(" ")} — ${wr(a,t).oneLine}.${d}`}function Ms(a){return a===""?"Aucun nouvel import enregistré à cet instant, et ce poste ne publie pas ce qu’il surveille.":"Aucun nouvel import enregistré à cet instant. Le poste surveille "+a+" : le fichier n’y était pas, ou il n’a pas encore fini d’arriver."}function Ws(a){return"Ce poste n’a pas de journal : il ne pourra rien dire de l’issue de cette relecture."+(a===""?"":" Le poste surveille "+a+".")}function Ha(a){return a===1?"voir la ligne":`voir les ${_t(a)} lignes`}function Bs(a){return a.map(t=>`${Vs(t)} (${_t(t.count)})`).join(", ")}function Vs(a){switch(a.code){case"PREPACKAGED_PRODUCT":return"préemballés";case"INTERNAL_CODE_NOT_WEIGHABLE":return a.value===""?"code interne":"code interne "+a.value;case"NO_BARCODE":return"sans code-barres";default:return a.code}}function _t(a){return String(a)}var Gs=c('
');function xr(a,t){Ue(t,!0);const r=u(()=>wr(t.record,t.motives));var i=Zs(),d=s(i),p=s(d),y=n(d,2);ze(y,21,()=>e(r).lines,j=>j.label,(j,S)=>{var A=Qs(),L=s(A),W=s(L),O=n(L,2),C=s(O),K=s(C),U=n(C,2);{var E=D=>{var H=Ys(),V=s(H);f(()=>o(V,e(S).note)),l(D,H)};_(U,D=>{e(S).note!==""&&D(E)})}var x=n(U,2);{var g=D=>{var H=Xs(),V=s(H);f(()=>o(V,e(S).link)),Ce("click",H,()=>t.onshowrows(e(S).label==="anomalies"?"anomalies":"units")),l(D,H)};_(x,D=>{e(S).link!==""&&t.onshowrows!==void 0&&D(g)})}f(()=>{be(A,"data-row",e(S).label),o(W,e(S).count),o(K,e(S).label)}),l(j,A)});var z=n(y,2),m=s(z);f(()=>{o(p,e(r).headline),o(m,e(r).oneLine)}),l(a,i),Me()}ot(["click"]);var el=c(""),tl=c(''),al=c('');function Na(a,t){Ue(t,!0);const r=Be(t,"hint",3,"");var i=al(),d=s(i),p=n(d,2),y=s(p),z=s(y),m=n(y,2);{var j=L=>{var W=el(),O=s(W);f(()=>o(O,t.path)),l(L,W)};_(m,L=>{St.showTechnicalNames&&L(j)})}var S=n(m,2);{var A=L=>{var W=tl(),O=s(W);f(()=>o(O,r())),l(L,W)};_(S,L=>{r()!==""&&L(A)})}f(L=>{be(i,"data-flag",t.path),be(i,"data-on",L),ea(d,t.on),o(z,t.label)},[()=>String(t.on)]),Ce("change",d,L=>t.onchange(L.currentTarget.checked)),l(a,i),Me()}ot(["change"]);function Ja(a){const t=`${se(a.columns)} ${a.columns>1?"colonnes":"colonne"}`,r=`${se(a.rows)} ${a.rows>1?"rangées":"rangée"}`;return`${t} × ${r}`}function rl(a){const t=a.layout,r=[];if(a.columns===Xt)return r.push(t===null?"Automatique : la grille suit la largeur de l’écran. Un écran plus large en montre davantage sans qu’on y revienne.":`Automatique : ${Ja(t)} sur cet écran. Un écran plus large en montrera davantage sans qu’on y revienne.`),r;if(t===null)return r.push(`${se(a.columns)} ${a.columns>1?"colonnes":"colonne"} sur tous les écrans. Cet écran ne sait pas dire combien de rangées cela fait ici.`),r;const i=t.columns*t.rows;if(r.push(`${Ja(t)} — ${se(i)} ${i>1?"tuiles":"tuile"} d’un coup, sur cet écran (${String(a.viewport.width)} × ${String(a.viewport.height)}).`),a.tileCount>0){const p=Math.ceil(a.tileCount/i);r.push(a.tileCount>1?`Les ${se(a.tileCount)} tuiles de la grille tiennent en ${se(p)} ${p>1?"écrans":"écran"}.`:"La seule tuile de la grille tient en un écran.")}const d=a.floor;if(d!==null&&d.names>0){const p=d.names>1;r.push(`${se(d.names)} ${p?"noms":"nom"} sur ${se(a.tileCount)} ${p?"atteignent":"atteint"} le plancher de ${se(ka)} px : `+(d.rows>1?`leurs ${se(d.rows)} rangées peuvent être plus hautes que les autres.`:"leur rangée peut être plus haute que les autres."))}return r}function nl(a,t,r){if(a==="loading")return"Lecture du catalogue en service…";if(a==="unread")return"Le catalogue en service n’a pas pu être lu : cet écran ne sait pas combien de produits se vendent à l’unité.";if(t===0)return"Aucun produit vendu à l’unité dans le catalogue en service.";const i=t>1,d=i?"produits vendus à l’unité sont":"produit vendu à l’unité est",p=r?`${i?"montrés":"montré"} dans la grille de ce poste`:`${i?"masqués":"masqué"} sur ce poste`;return`${se(t)} ${d} ${p}.`}function sl(a){return["localhost","127.0.0.1"].includes(a)?"":"Cet écran n’est pas celui du poste : ce compte vaut pour l’écran que vous lisez."}const ll=-1,il=10;class kr{#t=B("");get sentence(){return e(this.#t)}set sentence(t){v(this.#t,t,!0)}#r=0;#a="";#e=0;begin(t){this.sentence="",this.#r=t.last_import_id,this.#a=t.watched,this.#e=il}forget(){this.sentence="",this.#e=0}observe(t){if(this.#e===0)return;if(t.counters.journal_rows_count===ll){this.#n(Ws(this.#a));return}const r=t.catalog;if(r!==null&&r.id!==this.#r){this.#n(Us(r,t.catalog_motives));return}this.#e-=1,this.#e===0&&(this.sentence=Ms(this.#a))}#n(t){this.sentence=t,this.#e=0}}var ol=c('
Aucun import enregistré sur ce poste.
'),ul=c('
'),cl=c(`
« Oublier la quarantaine » fait relire un fichier que le poste avait écarté : c’est le
seul geste de cette page qui puisse remettre en service un catalogue refusé.
`,1),Ka=c(""),dl=c(''),vl=c('
'),pl=c('
'),fl=c(''),gl=c(`
Un produit masqué reste vendable : la caisse lit toujours son code-barres, et une
étiquette déjà imprimée reste valable. Ce réglage ne fait que retirer sa tuile.
Colonnes de la grille
Se tromper ne coûte rien d’autre que de revenir ici : le réglage ne change ni le
- fichier reçu, ni les étiquettes déjà imprimées.
En dessous de ce nombre, la catégorie n’a pas de puce dans la barre du bas. Ses
+ fichier reçu, ni les étiquettes déjà imprimées.
En dessous de ce nombre, la catégorie n’a pas de puce dans la barre du bas. Ses
produits restent dans « Tout » et à la recherche : ce réglage ne retire aucune
tuile. Pour ne plus montrer une catégorie du tout, c’est sa case « visible » qu’il
faut décocher.
`,1),ml=c('
'),hl=c(`
Déposez ici le fichier clé
Ce dépôt remplace toute la grille par le fichier apporté : il change ce que le poste
diff --git a/internal/web/dist/index.html b/internal/web/dist/index.html
index 1f104c9..6dcfac1 100644
--- a/internal/web/dist/index.html
+++ b/internal/web/dist/index.html
@@ -6,7 +6,7 @@