Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions internal/catalog/findings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package catalog

import (
"fmt"
"regexp"
"strings"

"openscale/internal/domain"
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down
33 changes: 33 additions & 0 deletions internal/catalog/qualify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions internal/web/dist/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light" />
<title>Administration</title>
<script type="module" crossorigin src="/assets/admin-DEu9sOlj.js"></script>
<script type="module" crossorigin src="/assets/admin-tZr91ixu.js"></script>
<link rel="modulepreload" crossorigin href="/assets/app-BaRSXv80.js">
<link rel="modulepreload" crossorigin href="/assets/mount-D3UhzFzr.js">
<link rel="modulepreload" crossorigin href="/assets/mount-1OvlPcKC.js">
<link rel="stylesheet" crossorigin href="/assets/app-Cfxw4Luj.css">
<link rel="stylesheet" crossorigin href="/assets/mount-MmpjwdB2.css">
</head>
Expand Down
1 change: 0 additions & 1 deletion internal/web/dist/assets/admin-DEu9sOlj.js

This file was deleted.

1 change: 1 addition & 0 deletions internal/web/dist/assets/admin-tZr91ixu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import"./app-BaRSXv80.js";import{mountAdmin as m}from"./mount-1OvlPcKC.js";m(document.getElementById("app"));

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion internal/web/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="color-scheme" content="light" />
<title>Pesée</title>
<script type="module" crossorigin src="/assets/index-BoOKWXIu.js"></script>
<script type="module" crossorigin src="/assets/index-DPFlyzED.js"></script>
<link rel="modulepreload" crossorigin href="/assets/app-BaRSXv80.js">
<link rel="stylesheet" crossorigin href="/assets/app-Cfxw4Luj.css">
<link rel="stylesheet" crossorigin href="/assets/index-BqkwrTvW.css">
Expand Down
2 changes: 1 addition & 1 deletion web/src/admin/lib/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const FIELD_LABELS: Readonly<Record<string, string>> = {
'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',
Expand Down
2 changes: 1 addition & 1 deletion web/src/admin/pages/Catalog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@
</p>

<p class="columns-label">
<label for="chip-threshold">Tuiles minimum pour donner sa puce à une catégorie</label>
<label for="chip-threshold">Articles minimum pour afficher une catégorie</label>
{#if preferences.showTechnicalNames}<code>{CHIP_THRESHOLD_PATH}</code>{/if}
</p>
<input
Expand Down