Merge pull request #2 from R0m1k3/feat/artcentrale-api
feat(articles): expose and filter code centrale (artcentrale)
This commit is contained in:
3 files changed
+30
-5
No files matched your search
+10
-1
@@ -32,9 +32,17 @@ GET /api/articles
|
||||
| `ean` | string | EAN / GTIN | — |
|
||||
| `codefou` | string | Code fournisseur (partiel) | — |
|
||||
| `actif` | `1`/`0`| `1` = actif, `0` = suspendu | — |
|
||||
| `artcentrale` | string | Code centrale (partiel) | — |
|
||||
| `has_artcentrale` | `1`/`0` | `1` = référencé centrale, `0` = non référencé | — |
|
||||
| `page` | int | Numéro de page | 1 |
|
||||
| `limit` | int | Lignes par page (max 500) | 50 |
|
||||
|
||||
> **Code centrale** (`artcentrale`) : identifiant LaFoir'Fouille sur 11 chiffres, préfixe `1000x`
|
||||
> (ex. `10000137005`). Seuls les produits référencés par la centrale en possèdent un —
|
||||
> environ 355 800 articles sur 427 700. Pour les autres, le champ vaut `null`.
|
||||
> `has_artcentrale=1` ne retient que les codes conformes : quelques valeurs parasites
|
||||
> (`10000`, `10000192289P`) ont le bon préfixe mais pas la bonne longueur, et sont exclues.
|
||||
|
||||
**Réponse** :
|
||||
```json
|
||||
{
|
||||
@@ -54,6 +62,7 @@ GET /api/articles
|
||||
"suspendu": null,
|
||||
"suividatecreation": "2020-01-15T00:00:00.000Z",
|
||||
"suividatemodif": "2024-06-01T00:00:00.000Z",
|
||||
"artcentrale": "10000137005",
|
||||
"prix_vente_mini": 15.00,
|
||||
"prix_vente_maxi": 25.00,
|
||||
"eco_ttc": 0.10,
|
||||
@@ -85,7 +94,7 @@ GET /api/articles/:id
|
||||
**Réponse** :
|
||||
```json
|
||||
{
|
||||
"article": { "no_id": 12345, "codein": "...", "libelle1": "...", "pa": 10.50, "..." : "..." },
|
||||
"article": { "no_id": 12345, "codein": "...", "libelle1": "...", "artcentrale": "10000137005", "pa": 10.50, "..." : "..." },
|
||||
"gtins": [
|
||||
{ "gtin": "3760000000001", "preferentiel": 1 }
|
||||
],
|
||||
|
||||
+19
-3
@@ -2,11 +2,12 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
const { getPool } = require('../config/database');
|
||||
|
||||
// GET /api/articles?search=&codein=&ean=&actif=&codefou=&page=&limit=
|
||||
// GET /api/articles?search=&codein=&ean=&actif=&codefou=&artcentrale=&has_artcentrale=&page=&limit=
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const pool = getPool();
|
||||
const { search = '', codein = '', ean = '', actif = '', codefou = '', page = 1, limit = 50 } = req.query;
|
||||
const { search = '', codein = '', ean = '', actif = '', codefou = '',
|
||||
artcentrale = '', has_artcentrale = '', page = 1, limit = 50 } = req.query;
|
||||
const pageNum = Math.max(1, parseInt(page) || 1);
|
||||
const limitNum = Math.max(1, Math.min(parseInt(limit) || 50, 500));
|
||||
const offsetNum = (pageNum - 1) * limitNum;
|
||||
@@ -16,6 +17,7 @@ router.get('/', async (req, res) => {
|
||||
a.NO_ID, a.CODEIN, a.LIBELLE1, a.LIBELLE2, a.LIB_TICKET,
|
||||
a.TAX_CODE, a.ACH_CODE, a.UTILISABLE, a.ACTIF, a.SUSPENDU,
|
||||
a.SUIVIDATECREATION, a.SUIVIDATEMODIF,
|
||||
NULLIF(TRIM(a.ARTCENTRALE), '') AS ARTCENTRALE,
|
||||
ai.PRIX_VENTE_MINI, ai.PRIX_VENTE_MAXI, ai.ECO_TTC,
|
||||
ai.ON_WEB, ai.INTERDIT_REMISE, ai.NOMPHOTO,
|
||||
ai.DATEDEBVENTE, ai.DATEFINVENTE,
|
||||
@@ -50,9 +52,22 @@ router.get('/', async (req, res) => {
|
||||
AND ($4 = '%%' OR EXISTS (
|
||||
SELECT 1 FROM ARTFOU1 f WHERE f.ART_NO_ID = a.NO_ID AND f.CODE LIKE $4
|
||||
))
|
||||
AND ($6 = '%%' OR TRIM(a.ARTCENTRALE) LIKE $6)
|
||||
-- code centrale LaFoir'Fouille : préfixe 1000x sur 11 chiffres.
|
||||
-- COALESCE car les articles non référencés valent '' ou NULL.
|
||||
AND ($7 = '' OR (
|
||||
$7 = '1' AND TRIM(COALESCE(a.ARTCENTRALE, '')) LIKE '1000%'
|
||||
AND LENGTH(TRIM(COALESCE(a.ARTCENTRALE, ''))) = 11
|
||||
) OR (
|
||||
$7 = '0' AND NOT (
|
||||
TRIM(COALESCE(a.ARTCENTRALE, '')) LIKE '1000%'
|
||||
AND LENGTH(TRIM(COALESCE(a.ARTCENTRALE, ''))) = 11
|
||||
)
|
||||
))
|
||||
ORDER BY a.LIBELLE1
|
||||
LIMIT ${limitNum} OFFSET ${offsetNum}
|
||||
`, [`%${search}%`, `%${codein}%`, `%${ean}%`, `%${codefou}%`, actif]);
|
||||
`, [`%${search}%`, `%${codein}%`, `%${ean}%`, `%${codefou}%`, actif,
|
||||
`%${artcentrale}%`, has_artcentrale]);
|
||||
|
||||
const articles = result.rows.map(a => {
|
||||
const photoCode = a.nomphoto ? a.nomphoto.replace(/\.[^.]+$/, '') : null;
|
||||
@@ -123,6 +138,7 @@ router.get('/:id', async (req, res) => {
|
||||
res.json({
|
||||
article: {
|
||||
...art,
|
||||
artcentrale: art.artcentrale?.trim() || null,
|
||||
photo_url: photoCode ? `/api/articles/${req.params.id}/photo` : null,
|
||||
photo_url_large: photoCode ? `/api/articles/${req.params.id}/photo?size=large` : null,
|
||||
},
|
||||
|
||||
@@ -44,7 +44,7 @@ async function syncArticles(force) {
|
||||
suividatecreation: r.SUIVIDATECREATION,
|
||||
suividatemodif: r.SUIVIDATEMODIF,
|
||||
nom_no_id: r.NOM_NO_ID,
|
||||
artcentrale: r.ARTCENTRALE ?? null,
|
||||
artcentrale: safeStr(r.ARTCENTRALE),
|
||||
}));
|
||||
|
||||
const count = await batchUpsert(pg, 'articles', rows, ['no_id'], ARTICLES_COLS);
|
||||
|
||||
Reference in new issue
Block a user