# Demo branch setup (`debrand`) This branch is a white-label demo. `fpsms_demo` is a full copy of the live database `fpsmsdb`, then rewritten in place. People, shops, and copied order codes change. Item codes, lot numbers, warehouse codes, and floors stay. The three most recent delivery and purchase arrival dates move to today, tomorrow, and the day after. Lot expiry dates move forward by the same gap, so stock that was usable on the newest delivery day stays usable. Line prices become 1. It must not read or write `fpsmsdb`, and it must not call the live M18 system. Check out `debrand` in both repositories: - `FPSMS-backend` - `FPSMS-frontend` Do not merge this branch. Do not start it with `db-local`, `prod`, or `db-toa`. ## What you get | | | | -------------- | --------------------------------------------------------------- | | Site | Frontend on port 3000, API on port 8090 | | Spring profile | `db-demo` | | Database | `fpsms_demo` on `127.0.0.1:3306` | | App login | `demo` / `Demo2026!` | | Also | `demo.stock` / `Demo2026!` (倉務), `demo.prod` / `Demo2026!` (出品) | `demo` is an existing admin user, renamed. Every copied password is reset to `Demo2026!`. `demo.stock` and `demo.prod` are renamed only when a stock-only user and a production-only user already exist. Floors stay `1/F`, `2/F`, `3/F`, and `4/F`. Item codes and lot numbers stay. Shop codes look like `S12`. Names lose the substrings `TOA` and `平記`. ## 1. Stop anything already on port 8090 The frontend on this branch calls `http://localhost:8090/api`. If a normal backend is already listening there, it is the live database. Stop that process before starting the demo. ## 2. Copy production into `fpsms_demo`, then replace identifying values Liquibase changesets in this repo name the schema `fpsmsdb`. Do not run them against the live database. Use the local `root` account from `application-db-local.yml` only for this copy. Load structure and rows, including Liquibase history, then run the anonymize script. The script updates existing rows. It does not delete them. It refuses to run unless the current database is `fpsms_demo`, and it refuses to run again after `settings.name = DEMO.anonymized.v1` is set. A mysqldump often starts with `USE fpsmsdb`; change that line to `USE fpsms_demo` before import so the live schema is not overwritten. ```bash mysql -h127.0.0.1 -P3306 -uroot -p -e \ "DROP DATABASE IF EXISTS fpsms_demo; CREATE DATABASE fpsms_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" mysqldump --routines --triggers -h127.0.0.1 -P3306 -uroot -p fpsmsdb \ > /tmp/fpsms_demo_copy.sql mysql -h127.0.0.1 -P3306 -uroot -p fpsms_demo < /tmp/fpsms_demo_copy.sql mysql -h127.0.0.1 -P3306 -uroot -p fpsms_demo \ < scripts/anonymize_demo_copy.sql ``` In MySQL Workbench the default query timeout is 30 seconds. A full copy takes longer, and Workbench then reports error 2013 even though the server may still be working. Before running the script: **MySQL Workbench → Settings → SQL Editor → DBMS connection read timeout interval** = `3600`. Reconnect, select `fpsms_demo`, and run the whole file. Dropping `fpsms_demo` removes a previous demo copy only. Do not point that `DROP` at `fpsmsdb`. After the script, `items.code` and `inventory_lot.lotNo` still match the copy, `shop.code` looks like `S12`, `user.username` is `demo` or `USER-{id}`, and floor `store_id` is still `2/F` or `4/F`. `SELECT COUNT(*)` on those tables should match the production copy. Every user password is `Demo2026!`. Purchase and delivery line `price` and `up` are `1`. `DEMO.dateAnchor` is the calendar day the script ran. Opening the backend does not move dates. On a later demo day, run `scripts/refresh_demo_dates.sql` against `fpsms_demo` before starting. It adds the days since `DEMO.dateAnchor` to lot expiry dates and to delivery and purchase arrival dates, then sets the anchor to that day. The same orders and the same usable lots remain. Running it again on the same day changes nothing. ## 3. Create a login that cannot see `fpsmsdb` `application-db-demo.yml` connects as `fpsms_demo` / `FpsmsDemoOnly2026`. That account is allowed to use `fpsms_demo` only. ```bash mysql -h127.0.0.1 -P3306 -uroot -p <<'SQL' CREATE USER IF NOT EXISTS 'fpsms_demo'@'127.0.0.1' IDENTIFIED BY 'FpsmsDemoOnly2026'; CREATE USER IF NOT EXISTS 'fpsms_demo'@'localhost' IDENTIFIED BY 'FpsmsDemoOnly2026'; ALTER USER 'fpsms_demo'@'127.0.0.1' IDENTIFIED BY 'FpsmsDemoOnly2026'; ALTER USER 'fpsms_demo'@'localhost' IDENTIFIED BY 'FpsmsDemoOnly2026'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON fpsms_demo.* TO 'fpsms_demo'@'127.0.0.1'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON fpsms_demo.* TO 'fpsms_demo'@'localhost'; FLUSH PRIVILEGES; SQL ``` Confirm the wall before starting the app. The first command must fail with MySQL error 1142. The second must succeed. ```bash mysql -h127.0.0.1 -P3306 -ufpsms_demo -pFpsmsDemoOnly2026 -e "SELECT COUNT(*) FROM fpsmsdb.user;" mysql -h127.0.0.1 -P3306 -ufpsms_demo -pFpsmsDemoOnly2026 -D fpsms_demo -e "SELECT COUNT(*) FROM user;" ``` Do not put `root` back into `application-db-demo.yml`. If this login can read `fpsmsdb`, the demo profile refuses to start. That refusal is the point. ## 4. Start the backend JDK 17. From `FPSMS-backend`, on branch `debrand`: ```bash ./gradlew bootRun --args='--spring.profiles.active=db-demo' ``` Startup does not insert sample rows and does not change dates. It refuses to start unless `DEMO.anonymized.v1` is present, so a raw production copy cannot be served. In the log, expect: `Demo database login cannot read live schema fpsmsdb (MySQL error 1142).` Do not expect `Token updated`. That line means the process asked the live M18 server for a token. M18 screens are hidden. Calling them directly returns 403, for example `GET /api/m18/test/po-by-code`. ## 5. Start the frontend From `FPSMS-frontend`, on branch `debrand`: ```bash npm install npm run dev ``` Open `http://localhost:3000`. `.env.development` and `.env.production` on this branch both point at port 8090 on this machine. Do not point `NEXT_PUBLIC_API_URL` at `10.10.0.81` or any other live server. Sign in as `demo` / `Demo2026!`. ## If startup fails | Log | What to do | | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | Can read live schema `fpsmsdb` | The datasource user is too powerful. Recreate `fpsms_demo` as in step 3. Do not bypass the check. | | Access denied for `fpsms_demo` | The user or password does not match `application-db-demo.yml`, or the grants were not flushed. | | Liquibase tries to alter `fpsmsdb` | The changelog tables were not copied into `fpsms_demo`. Repeat step 2. With the restricted login this should fail closed, not change live data. | | has not been anonymized | Run `scripts/anonymize_demo_copy.sql` against `fpsms_demo`. Do not start the app on the raw copy. | | Port 8090 already in use | Stop the other backend. Do not point the demo frontend at it. |