# Catalog import implementation report

Date: 12 August 2026

## Outcome

The existing Node.js application now has a live MySQL/MariaDB catalog database, a transactional and resumable Excel importer, real catalog APIs, and live admin/storefront catalog screens. The supplied workbook passed preflight and the complete catalog was imported into the local XAMPP database.

## Database verification

| Check | Actual | Expected | Result |
|---|---:|---:|---|
| Products | 3,083 | 3,083 | Pass |
| Categories | 47 | 47 | Pass |
| Authors | 1,072 | 1,072 | Pass |
| Publishers | 300 | 300 | Pass |
| Custom attributes | 23,166 | 23,166 | Pass |
| Product text parts | 6,060 | 6,060 | Pass |
| Catalogue records/PDF URLs | 43 | 43 | Pass |
| Product image URLs | 3,115 | 3,115 | Pass |
| Products without categories | 0 | 0 | Pass |
| Duplicate operational SKUs | 0 | 0 | Pass |

There are 3,080 enabled and 3 disabled products, matching the workbook status values.

Source fingerprint: `4d775a976933a98e12c6d10a64c67d4080f3d4a7d00ed6f28e554482b95c7c4b`

## Runtime repair

- Replaced the browser-side `localhost:5000` API default with same-origin `/api/v1` requests.
- Added Next.js development rewrites to the Express backend, matching the existing nginx production routing.
- Added central `.env` loading for the API and importer.
- Corrected the local database URL to the XAMPP MySQL/MariaDB database.
- Recovered XAMPP after its first large Prisma migration attempt, applied the generated schema through the native client, and registered the migration.
- Added support for the existing `?subject=` storefront URL parameter as an alias for the category filter.
- Reduced catalog-import concurrency for XAMPP/MariaDB and verified resumable recovery from seven transient deadlocks.
- Removed query-by-query Prisma logging unless `PRISMA_QUERY_LOG=true`.

## Live page verification

The storefront proxy, catalog API, category metadata, image link, and product page were tested through the LAN address. The `Material Science` subject URL selects that category and returns its one matching product, **Isocyanide Chemistry: Applications in Synthesis and Material Science**, with no browser console errors.

The host LAN address can change with DHCP. Because API traffic is now same-origin, the storefront continues to work through the current address without rebuilding `NEXT_PUBLIC_API_URL`.

## Source-data handling

- 59 repeated ISBN groups are preserved because ISBN remains text and is not forced unique.
- 59 repeated source-SKU groups retain their original `sourceSku`; deterministic unique operational SKUs are generated.
- 69 repeated source-slug groups and 8 blank slugs retain the source value while receiving deterministic public slugs.
- 1 missing price, 4 invalid stock values, and 8 discounts above price are recorded as warnings.
- 1 product has no image URL; 128 have no plain description; 1,920 have no author; and 2,050 have no publisher. Blank relationships remain null rather than creating fabricated records.

## Remaining explicit mapping decision

All 43 catalogue records and PDF URLs are present and openable from the Catalogue panel. The workbook has no product/category-to-catalogue key, so `BookCatalogue` contains no guessed relationships. Product-level PDF links require an owner-approved catalogue/category mapping JSON as documented in the runbook.
