Преглед на файлове

Lighten demo anonymize: keep item/lot/floor codes and refresh dates by script.

debrand
kelvin.yau преди 3 седмици
родител
ревизия
314507d567
променени са 5 файла, в които са добавени 303 реда и са изтрити 664 реда
  1. +7
    -5
      docs/DEMO_BRANCH_SETUP.md
  2. +189
    -641
      scripts/anonymize_demo_copy.sql
  3. +87
    -0
      scripts/refresh_demo_dates.sql
  4. +17
    -16
      src/main/java/com/ffii/fpsms/modules/common/demo/DemoFloors.kt
  5. +3
    -2
      src/main/java/com/ffii/fpsms/modules/common/demo/DemoSandboxSeeder.kt

+ 7
- 5
docs/DEMO_BRANCH_SETUP.md Целия файл

@@ -1,6 +1,6 @@
# 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 so names, codes, and other identifying values become placeholders. Row counts, ids, statuses, quantities, and dates stay. It must not read or write `fpsmsdb`, and it must not call the live M18 system.
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:

@@ -21,7 +21,7 @@ Do not merge this branch. Do not start it with `db-local`, `prod`, or `db-toa`.
| 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 are `A/F` (was 2/F) and `B/F` (was 4/F). Item codes look like `ITEM-12`, shops like `SHOP-3`, lots like `LOT-9`.
`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

@@ -31,7 +31,7 @@ The frontend on this branch calls `http://localhost:8090/api`. If a normal backe

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.
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 \
@@ -50,7 +50,9 @@ In MySQL Workbench the default query timeout is 30 seconds. A full copy takes lo

Dropping `fpsms_demo` removes a previous demo copy only. Do not point that `DROP` at `fpsmsdb`.

After the script, a sample of `items.code`, `shop.name`, `inventory_lot.lotNo`, `user.username`, and floor `store_id` values should be placeholders, and `SELECT COUNT(*)` on those tables should match the production copy. Every user password is `Demo2026!`.
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`

@@ -91,7 +93,7 @@ JDK 17. From `FPSMS-backend`, on branch `debrand`:
./gradlew bootRun --args='--spring.profiles.active=db-demo'
```

Startup does not insert sample rows. It refuses to start unless `DEMO.anonymized.v1` is present, so a raw production copy cannot be served. Dates stay on the days they had in the copy.
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:



+ 189
- 641
scripts/anonymize_demo_copy.sql Целия файл

@@ -1,5 +1,15 @@
-- Rewrite identifying values in fpsms_demo. Does not delete rows.
-- Ids, foreign keys, statuses, quantities stay.
-- Item codes, lot numbers, warehouse codes, and floors (1/F–4/F) stay.
-- Shop codes, delivery-order codes, and purchase-order codes are rewritten
-- and the same old string is updated everywhere it was copied.
-- The three most recent delivery and purchase arrival dates move to
-- today, tomorrow, and the day after. Today is the real calendar day
-- in UTC+8. Lot expiry dates move forward by the same number of days
-- as the newest delivery arrival day, so usable stock stays usable.
-- settings DEMO.dateAnchor stores that day. Line prices become 1.
-- Opening the backend does not move dates. On a later demo day, run
-- scripts/refresh_demo_dates.sql.
--
-- Run only against a disposable full copy of production:
-- mysql -h127.0.0.1 -P3306 -uroot -p fpsms_demo < scripts/anonymize_demo_copy.sql
@@ -13,8 +23,12 @@
-- Reconnect, select fpsms_demo, then run this whole file.

SET NAMES utf8mb4;
SET SESSION time_zone = '+08:00';
SET SESSION sql_safe_updates = 0;
SET SESSION group_concat_max_len = 1000000;
SET SESSION net_read_timeout = 7200;
SET SESSION net_write_timeout = 7200;
SET SESSION wait_timeout = 28800;

DROP PROCEDURE IF EXISTS demo_exec_if_table;
DROP PROCEDURE IF EXISTS demo_apply_map;
@@ -30,23 +44,12 @@ DELIMITER $$

CREATE PROCEDURE demo_drop_maps()
BEGIN
DROP TABLE IF EXISTS _demo_map_item;
DROP TABLE IF EXISTS _demo_map_shop;
DROP TABLE IF EXISTS _demo_map_lot;
DROP TABLE IF EXISTS _demo_map_loc;
DROP TABLE IF EXISTS _demo_map_truck;
DROP TABLE IF EXISTS _demo_map_do;
DROP TABLE IF EXISTS _demo_map_po;
DROP TABLE IF EXISTS _demo_map_jo;
DROP TABLE IF EXISTS _demo_map_pk;
DROP TABLE IF EXISTS _demo_map_si;
DROP TABLE IF EXISTS _demo_map_st;
DROP TABLE IF EXISTS _demo_map_pp;
DROP TABLE IF EXISTS _demo_map_user;
DROP TABLE IF EXISTS _demo_map_username;
DROP TABLE IF EXISTS _demo_map_person;
DROP TABLE IF EXISTS _demo_map_equip;
DROP TABLE IF EXISTS _demo_map_stage;
END$$

CREATE PROCEDURE demo_exec_if_table(IN p_table VARCHAR(64), IN p_sql TEXT)
@@ -112,197 +115,6 @@ BEGIN
END IF;
END$$

CREATE PROCEDURE demo_add_missing(
IN p_map VARCHAR(64),
IN p_table VARCHAR(64),
IN p_column VARCHAR(64),
IN p_prefix VARCHAR(24)
)
demo_add_missing_body: BEGIN
DECLARE n INT DEFAULT 0;
SELECT COUNT(*) INTO n
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = p_table
AND column_name = p_column;
IF n = 0 THEN
LEAVE demo_add_missing_body;
END IF;

DELETE FROM _demo_map_stage;
SET @demo_sql = CONCAT(
'INSERT IGNORE INTO _demo_map_stage (old_value) ',
'SELECT DISTINCT `', p_column, '` FROM `', p_table, '` ',
'WHERE `', p_column, '` IS NOT NULL AND `', p_column, '` <> '''''
);
PREPARE demo_stmt FROM @demo_sql;
EXECUTE demo_stmt;
DEALLOCATE PREPARE demo_stmt;

SET @demo_sql = CONCAT(
'DELETE s FROM _demo_map_stage s INNER JOIN `', p_map, '` m ',
'ON m.old_value = s.old_value'
);
PREPARE demo_stmt FROM @demo_sql;
EXECUTE demo_stmt;
DEALLOCATE PREPARE demo_stmt;

SET @demo_sql = CONCAT(
'INSERT INTO `', p_map, '` (old_value, new_value) ',
'SELECT old_value, CONCAT(''', p_prefix, ''', rn) FROM (',
' SELECT old_value, ROW_NUMBER() OVER (ORDER BY old_value) AS rn FROM _demo_map_stage',
') numbered'
);
PREPARE demo_stmt FROM @demo_sql;
EXECUTE demo_stmt;
DEALLOCATE PREPARE demo_stmt;
END$$

CREATE PROCEDURE demo_blank_columns()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE tname VARCHAR(64);
DECLARE cname VARCHAR(64);
DECLARE cur CURSOR FOR
SELECT table_name, column_name
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND data_type IN ('varchar', 'char', 'text', 'tinytext', 'mediumtext', 'longtext')
AND table_name NOT LIKE '\_demo\_map\_%'
AND table_name NOT IN ('settings', 'DATABASECHANGELOG', 'DATABASECHANGELOGLOCK', 'authority', 'uom_conversion', 'currency')
AND LOWER(column_name) IN (
'remarks', 'remark', 'reason', 'issue_remark', 'errormessage',
'addr1', 'addr2', 'addr3', 'addr4',
'contactno', 'contactemail', 'contactname', 'brno', 'district',
'phone1', 'phone2', 'staffno', 'department', 'title',
'sendermail', 'tomail', 'subject', 'content',
'districtreference', 'countryoforigin',
'dnno', 'invoiceno',
'subjectcht', 'subjecteng', 'contentcht', 'contenteng'
);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN cur;
blank_loop: LOOP
FETCH cur INTO tname, cname;
IF done = 1 THEN
LEAVE blank_loop;
END IF;
SET @demo_sql = CONCAT(
'UPDATE `', tname, '` SET `', cname, '` = '''' WHERE `', cname, '` IS NOT NULL AND `', cname, '` <> '''''
);
PREPARE demo_stmt FROM @demo_sql;
EXECUTE demo_stmt;
DEALLOCATE PREPARE demo_stmt;
END LOOP;
CLOSE cur;
END$$

CREATE PROCEDURE demo_replace_floors()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE tname VARCHAR(64);
DECLARE cname VARCHAR(64);
DECLARE cset VARCHAR(64);
DECLARE bincol VARCHAR(64);
DECLARE cur CURSOR FOR
SELECT table_name, column_name, character_set_name
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND data_type IN ('varchar', 'char', 'text', 'tinytext', 'mediumtext', 'longtext')
AND table_name NOT LIKE '\_demo\_map\_%'
AND table_name NOT IN ('DATABASECHANGELOG', 'DATABASECHANGELOGLOCK', 'authority');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN cur;
floor_loop: LOOP
FETCH cur INTO tname, cname, cset;
IF done = 1 THEN
LEAVE floor_loop;
END IF;
SET bincol = IF(cset = 'utf8mb4', 'utf8mb4_bin', 'utf8mb3_bin');

SET @demo_sql = CONCAT(
'UPDATE `', tname, '` SET `', cname, '` = CASE ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''2/F'' THEN ''A/F'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''4/F'' THEN ''B/F'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''1/F'' THEN ''C/F'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''3/F'' THEN ''D/F'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''2F'' THEN ''AF'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''4F'' THEN ''BF'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''1F'' THEN ''CF'' ',
'WHEN UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' = ''3F'' THEN ''DF'' ',
'ELSE `', cname, '` END ',
'WHERE UPPER(TRIM(`', cname, '`)) COLLATE ', bincol, ' IN (''2/F'',''4/F'',''1/F'',''3/F'',''2F'',''4F'',''1F'',''3F'')'
);
PREPARE demo_stmt FROM @demo_sql;
EXECUTE demo_stmt;
DEALLOCATE PREPARE demo_stmt;

SET @demo_sql = CONCAT(
'UPDATE `', tname, '` SET `', cname, '` = ',
'REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(`', cname, '`, ',
'''-2F-'', ''-AF-''), ''-4F-'', ''-BF-''), ''-1F-'', ''-CF-''), ''-3F-'', ''-DF-''), ',
'''-2/F-'', ''-A/F-''), ''-4/F-'', ''-B/F-''), ''-1/F-'', ''-C/F-''), ''-3/F-'', ''-D/F-'') ',
'WHERE `', cname, '` COLLATE ', bincol, ' LIKE ''%-2F-%'' OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-4F-%'' ',
'OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-1F-%'' OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-3F-%'' ',
'OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-2/F-%'' OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-4/F-%'' ',
'OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-1/F-%'' OR `', cname, '` COLLATE ', bincol, ' LIKE ''%-3/F-%'''
);
PREPARE demo_stmt FROM @demo_sql;
EXECUTE demo_stmt;
DEALLOCATE PREPARE demo_stmt;
END LOOP;
CLOSE cur;
END$$

CREATE PROCEDURE demo_remap_shop_csv(IN p_setting VARCHAR(255))
demo_remap_shop_csv_body: BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v LONGTEXT;
DECLARE oldv VARCHAR(255);
DECLARE newv VARCHAR(255);
DECLARE setting_rows INT DEFAULT 0;
DECLARE cur CURSOR FOR
SELECT old_value, new_value
FROM _demo_map_shop
ORDER BY CHAR_LENGTH(old_value) DESC, old_value;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

SELECT COUNT(*) INTO setting_rows
FROM settings
WHERE name = p_setting COLLATE utf8mb4_0900_ai_ci;
IF setting_rows = 0 THEN
LEAVE demo_remap_shop_csv_body;
END IF;
SELECT IFNULL(value, '') INTO v
FROM settings
WHERE name = p_setting COLLATE utf8mb4_0900_ai_ci
LIMIT 1;
IF v IS NULL OR v COLLATE utf8mb4_0900_ai_ci = '' THEN
LEAVE demo_remap_shop_csv_body;
END IF;

SET v = CONCAT(',', REPLACE(v, ' ', ''), ',');
OPEN cur;
shop_csv_loop: LOOP
FETCH cur INTO oldv, newv;
IF done = 1 THEN
LEAVE shop_csv_loop;
END IF;
SET v = REPLACE(
v COLLATE utf8mb4_bin,
CONCAT(',', oldv COLLATE utf8mb4_bin, ','),
CONCAT(',', newv COLLATE utf8mb4_bin, ',')
);
END LOOP;
CLOSE cur;
SET v = TRIM(BOTH ',' FROM v);
UPDATE settings
SET value = IFNULL(v, '')
WHERE name = p_setting COLLATE utf8mb4_0900_ai_ci;
END$$

CREATE PROCEDURE anonymize_demo_copy()
BEGIN
DECLARE marker_count INT DEFAULT 0;
@@ -310,6 +122,7 @@ BEGIN
DECLARE stock_id BIGINT DEFAULT NULL;
DECLARE prod_id BIGINT DEFAULT NULL;
DECLARE pwd_hash VARCHAR(80) DEFAULT '$2a$10$9eqxnNGtxFADAW9AbbjRIevr8YWgBqkLr//23U6qYOWs5U9figE2u';
DECLARE expiry_delta INT DEFAULT NULL;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET demo_id = demo_id;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
@@ -332,18 +145,6 @@ BEGIN

CALL demo_drop_maps();

CREATE TABLE _demo_map_stage (
old_value VARCHAR(512) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_item (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(255) NOT NULL,
new_name VARCHAR(255) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_shop (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(255) NOT NULL,
@@ -351,69 +152,15 @@ BEGIN
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_lot (
old_value VARCHAR(512) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_loc (
old_value VARCHAR(512) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_truck (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_do (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
new_value VARCHAR(255) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_po (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_jo (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_pk (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_si (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_st (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_pp (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE _demo_map_equip (
old_value VARCHAR(255) NOT NULL,
new_value VARCHAR(64) NOT NULL,
new_value VARCHAR(255) NOT NULL,
PRIMARY KEY (old_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

@@ -513,169 +260,113 @@ BEGIN
WHERE old_name IS NOT NULL
GROUP BY old_name;

INSERT INTO _demo_map_item (old_value, new_value, new_name)
SELECT code, CONCAT('ITEM-', MIN(id)), CONCAT('Item ', MIN(id))
FROM items
WHERE code IS NOT NULL AND code <> ''
GROUP BY code;

INSERT INTO _demo_map_shop (old_value, new_value, new_name)
SELECT code, CONCAT('SHOP-', MIN(id)), CONCAT('Shop ', MIN(id))
SELECT code, CONCAT('S', MIN(id)), CONCAT('Shop ', MIN(id))
FROM shop
WHERE code IS NOT NULL AND code <> ''
GROUP BY code;

INSERT INTO _demo_map_lot (old_value, new_value)
SELECT lotNo, CONCAT('LOT-', MIN(id))
FROM inventory_lot
WHERE lotNo IS NOT NULL AND lotNo <> ''
GROUP BY lotNo;

CALL demo_add_missing('_demo_map_lot', 'stock_in_line', 'lotNo', 'LOT-S');
CALL demo_add_missing('_demo_map_lot', 'stock_in_line', 'productLotNo', 'LOT-P');
CALL demo_add_missing('_demo_map_lot', 'delivery_order_line', 'm18Lot', 'LOT-M');
CALL demo_add_missing('_demo_map_lot', 'stocktakerecord', 'lotNo', 'LOT-T');
CALL demo_add_missing('_demo_map_lot', 'stock_adjustment_record', 'lotNo', 'LOT-A');
CALL demo_add_missing('_demo_map_lot', 'stock_transfer_record', 'lotNo', 'LOT-R');
CALL demo_add_missing('_demo_map_lot', 'item_lot_trace_log', 'lotNo', 'LOT-L');
CALL demo_add_missing('_demo_map_lot', 'bag_lot_line', 'lotNo', 'LOT-B');
CALL demo_add_missing('_demo_map_lot', 'pick_execution_issue', 'lot_no', 'LOT-I');

INSERT INTO _demo_map_loc (old_value, new_value)
INSERT INTO _demo_map_do (old_value, new_value)
SELECT code,
CASE code
WHEN '2F-W202-01-00' THEN 'LOC-HOLD'
WHEN '2F-W200-#A-00' THEN 'LOC-WIP'
ELSE CONCAT('LOC-', MIN(id))
CASE
WHEN stripped = '' THEN CONCAT('DO-', min_id)
WHEN dup_count > 1 THEN CONCAT(stripped, '-', min_id)
ELSE stripped
END
FROM warehouse
WHERE code IS NOT NULL AND code <> ''
AND UPPER(REPLACE(code, ' ', '')) NOT IN ('2/F', '2F', '4/F', '4F', '1/F', '1F', '3/F', '3F')
GROUP BY code;

CALL demo_add_missing('_demo_map_loc', 'items', 'LocationCode', 'LOC-I');
CALL demo_add_missing('_demo_map_loc', 'stock_transfer_record', 'startLocation', 'LOC-S');
CALL demo_add_missing('_demo_map_loc', 'stock_transfer_record', 'targetLocation', 'LOC-T');
CALL demo_add_missing('_demo_map_loc', 'pick_execution_issue', 'store_location', 'LOC-P');

DELETE FROM _demo_map_loc
WHERE UPPER(REPLACE(old_value, ' ', '')) IN ('2/F', '2F', '4/F', '4F', '1/F', '1F', '3/F', '3F');

INSERT INTO _demo_map_loc (old_value, new_value) VALUES
('2F-W202-01-00', 'LOC-HOLD'),
('2F-W200-#A-00', 'LOC-WIP'),
('4F-W402-01-00', 'LOC-X01'),
('4F-W402-02-00', 'LOC-X02'),
('4F-W402-03-00', 'LOC-X03'),
('4F-W402-04-00', 'LOC-X04'),
('4F-W402-05-00', 'LOC-X05'),
('4F-W402-#A-00', 'LOC-X06'),
('4F-W402-#B-00', 'LOC-X07'),
('4F-W402-#C-00', 'LOC-X08'),
('4F-W402-#D-00', 'LOC-X09'),
('4F-W402-#E-00', 'LOC-X10'),
('4F-W402-#F-00', 'LOC-X11'),
('4F-W402-#G-00', 'LOC-X12'),
('4F-W402-#H-00', 'LOC-X13'),
('4F-W402-#I-00', 'LOC-X14'),
('4F-W402-#J-00', 'LOC-X15'),
('4F-W402-#K-00', 'LOC-X16'),
('4F-W402-#L-00', 'LOC-X17'),
('4F-W402-#M-00', 'LOC-X18'),
('4F-W402-#N-00', 'LOC-X19'),
('4F-W402-#O-00', 'LOC-X20'),
('4F-W402-#P-00', 'LOC-X21'),
('4F-W402-#Q-00', 'LOC-X22'),
('4F-W402-#R-00', 'LOC-X23'),
('4F-W402-#S-00', 'LOC-X24')
ON DUPLICATE KEY UPDATE new_value = VALUES(new_value);

INSERT INTO _demo_map_truck (old_value, new_value)
SELECT TruckLanceCode, CONCAT('TRUCK-', MIN(id))
FROM truck
WHERE TruckLanceCode IS NOT NULL AND TruckLanceCode <> ''
GROUP BY TruckLanceCode;

CALL demo_add_missing('_demo_map_truck', 'truck_lane_version', 'truckLanceCode', 'TRUCK-V');
CALL demo_add_missing('_demo_map_truck', 'truck_lane_version_line', 'truckLanceCode', 'TRUCK-L');
CALL demo_add_missing('_demo_map_truck', 'truck_lane_schedule_line', 'fromTruckLanceCode', 'TRUCK-F');
CALL demo_add_missing('_demo_map_truck', 'truck_lane_schedule_line', 'toTruckLanceCode', 'TRUCK-T');
CALL demo_add_missing('_demo_map_truck', 'delivery_order_pick_order', 'truckLanceCode', 'TRUCK-D');
CALL demo_add_missing('_demo_map_truck', 'do_pick_order', 'TruckLanceCode', 'TRUCK-O');
CALL demo_add_missing('_demo_map_truck', 'do_pick_order_record', 'TruckLanceCode', 'TRUCK-R');
CALL demo_add_missing('_demo_map_truck', 'do_replenishment', 'truckLaneCode', 'TRUCK-P');

INSERT INTO _demo_map_do (old_value, new_value)
SELECT code, CONCAT('DO-', MIN(id)) FROM delivery_order
WHERE code IS NOT NULL AND code <> '' GROUP BY code;
FROM (
SELECT g.code,
g.stripped,
g.min_id,
COUNT(*) OVER (PARTITION BY g.stripped) AS dup_count
FROM (
SELECT code,
REPLACE(code, 'TO', '') AS stripped,
MIN(id) AS min_id
FROM delivery_order
WHERE code IS NOT NULL AND code <> ''
GROUP BY code
) g
) numbered;

INSERT INTO _demo_map_po (old_value, new_value)
SELECT code, CONCAT('PO-', MIN(id)) FROM purchase_order
WHERE code IS NOT NULL AND code <> '' GROUP BY code;

INSERT INTO _demo_map_jo (old_value, new_value)
SELECT code, CONCAT('JO-', MIN(id)) FROM job_order
WHERE code IS NOT NULL AND code <> '' GROUP BY code;

INSERT INTO _demo_map_pk (old_value, new_value)
SELECT code, CONCAT('PK-', MIN(id)) FROM pick_order
WHERE code IS NOT NULL AND code <> '' GROUP BY code;
SELECT code,
CASE
WHEN stripped = '' THEN CONCAT('PO-', min_id)
WHEN dup_count > 1 THEN CONCAT(stripped, '-', min_id)
ELSE stripped
END
FROM (
SELECT g.code,
g.stripped,
g.min_id,
COUNT(*) OVER (PARTITION BY g.stripped) AS dup_count
FROM (
SELECT code,
REPLACE(REPLACE(code, 'PF', ''), 'PP', '') AS stripped,
MIN(id) AS min_id
FROM purchase_order
WHERE code IS NOT NULL AND code <> ''
GROUP BY code
) g
) numbered;

INSERT INTO _demo_map_si (old_value, new_value)
SELECT code, CONCAT('SI-', MIN(id)) FROM stock_in
WHERE code IS NOT NULL AND code <> '' GROUP BY code;
START TRANSACTION;

INSERT INTO _demo_map_st (old_value, new_value)
SELECT code, CONCAT('ST-', MIN(id)) FROM stock_take
WHERE code IS NOT NULL AND code <> '' GROUP BY code;
UPDATE `user` u
JOIN _demo_map_user m ON m.user_id = u.id
SET u.username = CONCAT('~u', u.id);

INSERT INTO _demo_map_pp (old_value, new_value)
SELECT productprocesscode, CONCAT('PP-', MIN(id)) FROM productprocess
WHERE productprocesscode IS NOT NULL AND productprocesscode <> ''
GROUP BY productprocesscode;
UPDATE `user` u
JOIN _demo_map_user m ON m.user_id = u.id
SET u.username = m.new_username,
u.password = pwd_hash,
u.name = m.new_name,
u.fullname = m.new_name,
u.firstname = 'User',
u.lastname = CAST(u.id AS CHAR),
u.email = CASE m.new_username
WHEN 'demo' THEN '[email protected]'
WHEN 'demo.stock' THEN '[email protected]'
WHEN 'demo.prod' THEN '[email protected]'
ELSE CONCAT('user', u.id, '@example.com')
END,
u.phone1 = '',
u.phone2 = '',
u.department = '',
u.title = '',
u.remarks = '',
u.staffNo = '';

INSERT INTO _demo_map_equip (old_value, new_value)
SELECT code, CONCAT('EQ-', MIN(id)) FROM equipment
WHERE code IS NOT NULL AND code <> ''
GROUP BY code;
CALL demo_apply_map('item_lot_trace_log', 'username', '_demo_map_username');
CALL demo_apply_map('stocktakerecord', 'createdBy', '_demo_map_username');
CALL demo_apply_map('pick_execution_issue', 'createdBy', '_demo_map_username');
CALL demo_apply_map('pick_execution_issue', 'modifiedBy', '_demo_map_username');
CALL demo_apply_map('pick_execution_issue', 'handled_by', '_demo_map_username');
CALL demo_apply_map('do_pick_order', 'createdBy', '_demo_map_username');
CALL demo_apply_map('do_pick_order', 'modifiedBy', '_demo_map_username');
CALL demo_apply_map('do_pick_order_record', 'createdBy', '_demo_map_username');
CALL demo_apply_map('do_pick_order_record', 'modifiedBy', '_demo_map_username');
CALL demo_apply_map('delivery_order_pick_order', 'createdBy', '_demo_map_username');
CALL demo_apply_map('delivery_order_pick_order', 'modifiedBy', '_demo_map_username');

START TRANSACTION;
CALL demo_apply_map('stocktakerecord', 'approverName', '_demo_map_person');
CALL demo_apply_map('stocktakerecord', 'stockTakerName', '_demo_map_person');
CALL demo_apply_map('do_pick_order', 'handler_name', '_demo_map_person');
CALL demo_apply_map('do_pick_order_record', 'handler_name', '_demo_map_person');
CALL demo_apply_map('delivery_order_pick_order', 'handlerName', '_demo_map_person');
CALL demo_apply_map('pick_execution_issue', 'picker_name', '_demo_map_person');

UPDATE items i
LEFT JOIN _demo_map_item m ON i.code COLLATE utf8mb4_unicode_ci = m.old_value
SET i.code = COALESCE(m.new_value, CONCAT('ITEM-', i.id)),
i.name = COALESCE(m.new_name, CONCAT('Item ', i.id)),
i.description = COALESCE(m.new_name, CONCAT('Item ', i.id)),
i.remarks = '',
i.countryOfOrigin = '';

UPDATE shop s
JOIN _demo_map_shop m ON s.code COLLATE utf8mb4_unicode_ci = m.old_value
SET s.code = m.new_value,
s.name = m.new_name,
s.brNo = '',
s.contactNo = '',
s.contactEmail = '',
s.contactName = '',
s.addr1 = '',
s.addr2 = '',
s.addr3 = '',
s.addr4 = '',
s.district = '';
UPDATE items
SET name = REPLACE(REPLACE(IFNULL(name, ''), 'TOA', ''), '平記', ''),
description = REPLACE(REPLACE(IFNULL(description, ''), 'TOA', ''), '平記', '');

UPDATE shop
SET code = CONCAT('SHOP-', id),
SET code = CONCAT('S', id),
name = CONCAT('Shop ', id),
brNo = '',
contactNo = '',
contactEmail = '',
contactName = '',
addr1 = '',
addr2 = '',
addr3 = '',
addr4 = '',
district = ''
WHERE code IS NULL OR code = '';
contactNo = '88888888',
addr1 = CONCAT('Addr row 1 ', id),
addr2 = CONCAT('Addr row 2 ', id),
addr3 = '香港';

CALL demo_apply_pair('truck', 'ShopCode', 'ShopName', '_demo_map_shop');
CALL demo_apply_pair('truck_lane_schedule_line', 'shopCode', 'shopName', '_demo_map_shop');
@@ -687,78 +378,6 @@ BEGIN
CALL demo_apply_map('truck', 'ShopCode', '_demo_map_shop');
CALL demo_apply_map('do_replenishment', 'shopCode', '_demo_map_shop');

CALL demo_apply_pair('do_replenishment', 'itemNo', 'itemName', '_demo_map_item');
CALL demo_apply_pair('stock_transfer_record', 'itemCode', 'itemName', '_demo_map_item');
CALL demo_apply_pair('stocktakerecord', 'itemCode', 'itemName', '_demo_map_item');
CALL demo_apply_pair('bag', 'itemCode', 'itemName', '_demo_map_item');
CALL demo_apply_map('purchase_order_line', 'itemNo', '_demo_map_item');
CALL demo_apply_map('delivery_order_line', 'itemNo', '_demo_map_item');
CALL demo_apply_map('stock_in_line', 'itemNo', '_demo_map_item');
CALL demo_apply_map('do_replenishment', 'itemNo', '_demo_map_item');
CALL demo_apply_map('stock_ledger', 'itemCode', '_demo_map_item');
CALL demo_apply_map('stocktakerecord', 'itemCode', '_demo_map_item');
CALL demo_apply_map('stock_adjustment_record', 'itemCode', '_demo_map_item');
CALL demo_apply_map('stock_transfer_record', 'itemCode', '_demo_map_item');
CALL demo_apply_map('item_lot_trace_log', 'itemCode', '_demo_map_item');
CALL demo_apply_map('item_default_shelf_life', 'itemCode', '_demo_map_item');
CALL demo_apply_map('coffee_or_tea', 'itemCode', '_demo_map_item');
CALL demo_apply_map('onpack_template_file', 'itemCode', '_demo_map_item');
CALL demo_apply_map('onpack_expiry_item_code', 'itemCode', '_demo_map_item');
CALL demo_apply_map('bag', 'itemCode', '_demo_map_item');
CALL demo_apply_map('jo_pick_order', 'itemCode', '_demo_map_item');
CALL demo_apply_map('jo_pick_order_record', 'itemCode', '_demo_map_item');
CALL demo_apply_map('pick_execution_issue', 'item_code', '_demo_map_item');
CALL demo_apply_map('m18_cunit', 'itemNo', '_demo_map_item');

CALL demo_apply_map('inventory_lot', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('stock_in_line', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('stock_in_line', 'productLotNo', '_demo_map_lot');
CALL demo_apply_map('delivery_order_line', 'm18Lot', '_demo_map_lot');
CALL demo_apply_map('stocktakerecord', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('stock_adjustment_record', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('stock_transfer_record', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('item_lot_trace_log', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('bag_lot_line', 'lotNo', '_demo_map_lot');
CALL demo_apply_map('pick_execution_issue', 'lot_no', '_demo_map_lot');

UPDATE warehouse w
LEFT JOIN _demo_map_loc m ON w.code COLLATE utf8mb4_unicode_ci = m.old_value
SET w.code = COALESCE(m.new_value, CONCAT('LOC-', w.id)),
w.name = LEFT(COALESCE(m.new_value, CONCAT('LOC-', w.id)), 30),
w.description = LEFT(COALESCE(m.new_value, CONCAT('LOC-', w.id)), 30),
w.warehouse = NULL,
w.area = NULL,
w.slot = NULL,
w.stockTakeSection = NULL,
w.stockTakeSectionDescription = NULL;

CALL demo_apply_map('items', 'LocationCode', '_demo_map_loc');
CALL demo_apply_map('stock_transfer_record', 'startLocation', '_demo_map_loc');
CALL demo_apply_map('stock_transfer_record', 'targetLocation', '_demo_map_loc');
CALL demo_apply_map('pick_execution_issue', 'store_location', '_demo_map_loc');

UPDATE items
SET warehouse = NULL, area = NULL, slot = NULL;

UPDATE warehouse
SET `order` = CASE
WHEN `order` REGEXP '^2F-[0-9]+$' THEN CONCAT('AF-', SUBSTRING(`order`, 4))
WHEN `order` REGEXP '^4F-[0-9]+$' THEN CONCAT('BF-', SUBSTRING(`order`, 4))
WHEN `order` REGEXP '^1F-[0-9]+$' THEN CONCAT('CF-', SUBSTRING(`order`, 4))
WHEN `order` REGEXP '^3F-[0-9]+$' THEN CONCAT('DF-', SUBSTRING(`order`, 4))
ELSE `order`
END;

CALL demo_apply_map('truck', 'TruckLanceCode', '_demo_map_truck');
CALL demo_apply_map('truck_lane_version', 'truckLanceCode', '_demo_map_truck');
CALL demo_apply_map('truck_lane_version_line', 'truckLanceCode', '_demo_map_truck');
CALL demo_apply_map('truck_lane_schedule_line', 'fromTruckLanceCode', '_demo_map_truck');
CALL demo_apply_map('truck_lane_schedule_line', 'toTruckLanceCode', '_demo_map_truck');
CALL demo_apply_map('delivery_order_pick_order', 'truckLanceCode', '_demo_map_truck');
CALL demo_apply_map('do_pick_order', 'TruckLanceCode', '_demo_map_truck');
CALL demo_apply_map('do_pick_order_record', 'TruckLanceCode', '_demo_map_truck');
CALL demo_apply_map('do_replenishment', 'truckLaneCode', '_demo_map_truck');

CALL demo_apply_map('delivery_order', 'code', '_demo_map_do');
CALL demo_apply_map('do_pick_order', 'delivery_order_code', '_demo_map_do');
CALL demo_apply_map('do_pick_order_record', 'delivery_order_code', '_demo_map_do');
@@ -769,163 +388,95 @@ BEGIN
CALL demo_apply_map('do_replenishment', 'targetDoCode', '_demo_map_do');

CALL demo_apply_map('purchase_order', 'code', '_demo_map_po');
CALL demo_apply_map('job_order', 'code', '_demo_map_jo');
CALL demo_apply_map('jo_pick_order', 'jobOrderCode', '_demo_map_jo');
CALL demo_apply_map('jo_pick_order_record', 'jobOrderCode', '_demo_map_jo');
CALL demo_apply_map('jo_bag_consumption', 'jobOrderCode', '_demo_map_jo');

CALL demo_apply_map('pick_order', 'code', '_demo_map_pk');
CALL demo_apply_map('do_pick_order', 'pick_order_code', '_demo_map_pk');
CALL demo_apply_map('do_pick_order_record', 'pick_order_code', '_demo_map_pk');
CALL demo_apply_map('do_pick_order_line', 'pick_order_code', '_demo_map_pk');
CALL demo_apply_map('do_pick_order_line_record', 'pick_order_code', '_demo_map_pk');
CALL demo_apply_map('jo_pick_order', 'pickOrderCode', '_demo_map_pk');
CALL demo_apply_map('jo_pick_order_record', 'pickOrderCode', '_demo_map_pk');
CALL demo_apply_map('pick_execution_issue', 'pick_order_code', '_demo_map_pk');
CALL demo_apply_map('stock_out', 'consoPickOrderCode', '_demo_map_pk');

CALL demo_apply_map('stock_in', 'code', '_demo_map_si');
CALL demo_apply_map('stock_take', 'code', '_demo_map_st');
CALL demo_apply_map('productprocess', 'productprocesscode', '_demo_map_pp');

UPDATE pick_order
SET consoCode = CONCAT('CS-', id)
WHERE consoCode IS NOT NULL AND consoCode <> '';

UPDATE do_replenishment
SET code = CONCAT('DR-', id)
WHERE code IS NOT NULL AND code <> '';

UPDATE do_pick_order_record
SET deliveryNoteCode = CONCAT('DN-', id)
WHERE deliveryNoteCode IS NOT NULL AND deliveryNoteCode <> '';

UPDATE delivery_order_pick_order
SET deliveryNoteCode = CONCAT('DN-P', id)
WHERE deliveryNoteCode IS NOT NULL AND deliveryNoteCode <> '';

CALL demo_exec_if_table('purchase_quotation',
'UPDATE purchase_quotation SET code = CONCAT(''PQ-'', id) WHERE code IS NOT NULL');
CALL demo_exec_if_table('purchase_quotation_line',
'UPDATE purchase_quotation_line SET code = CONCAT(''PQL-'', id) WHERE code IS NOT NULL');

UPDATE bom
SET code = CONCAT('BOM-', id),
name = CONCAT('Bom ', id),
description = CONCAT('Bom ', id);

CALL demo_exec_if_table('company',
'UPDATE company SET code = CONCAT(''CO-'', id), name = CONCAT(''Company '', id), brNo = '''', contactNo = '''', email = '''', addr1 = '''', addr2 = '''', addr3 = '''', addr4 = ''''');
CALL demo_exec_if_table('process',
'UPDATE `process` SET code = CONCAT(''PROC-'', id), name = LEFT(CONCAT(''Process '', id), 30), description = LEFT(CONCAT(''Process '', id), 30), remarks = ''''');
CALL demo_exec_if_table('equipment',
'UPDATE equipment SET code = CONCAT(''EQ-'', id), name = LEFT(CONCAT(''Equip '', id), 30), description = CONCAT(''Equip '', id)');
CALL demo_apply_map('equipment_detail', 'equipmentCode', '_demo_map_equip');
CALL demo_exec_if_table('equipment_detail',
'UPDATE equipment_detail SET code = CONCAT(''EQD-'', id), name = CONCAT(''Equip '', id), repairAndMaintenanceRemarks = ''''');
CALL demo_exec_if_table('item_category',
'UPDATE item_category SET code = CONCAT(''CAT-'', id), parent = '''', sub = ''''');
CALL demo_exec_if_table('qc_item',
'UPDATE qc_item SET code = CONCAT(''QC-'', id), name = CONCAT(''Qc '', id), description = ''''');
CALL demo_exec_if_table('qc_category',
'UPDATE qc_category SET code = CONCAT(''QCC-'', id), name = CONCAT(''Qc '', id), description = CONCAT(''Qc '', id)');
CALL demo_exec_if_table('pick_order_group',
'UPDATE pick_order_group SET name = CONCAT(''POG-'', id)');
CALL demo_exec_if_table('printer',
'UPDATE printer SET code = CONCAT(''PRINTER-'', id), name = CASE name WHEN ''Label機 2F A+B'' THEN ''LABEL-A'' WHEN ''Label機 4F 乾貨 C, D'' THEN ''LABEL-B'' ELSE CONCAT(''Printer '', id) END, description = '''', brand = '''', ip = ''''');
CALL demo_exec_if_table('logistic',
'UPDATE logistic SET logisticName = CONCAT(''Logistic '', id), carPlate = CONCAT(''PLATE-'', id), driverName = CONCAT(''Driver '', id), driverNumber = id');
CALL demo_exec_if_table('group',
'UPDATE `group` SET name = CONCAT(''~g'', id)');
CALL demo_exec_if_table('group',
'UPDATE `group` SET name = CONCAT(''GROUP-'', id), description = ''''');

CALL demo_exec_if_table('onpack_template_file',
'UPDATE onpack_template_file SET fileName = CONCAT(''file-'', id)');
CALL demo_exec_if_table('onpack_expiry_item_code',
'UPDATE onpack_expiry_item_code SET printName = itemCode');

CALL demo_exec_if_table('m18_data_log',
'UPDATE m18_data_log SET dataLog = JSON_OBJECT()');
CALL demo_exec_if_table('grn_send_log',
'UPDATE grn_send_log SET data = JSON_OBJECT()');
CALL demo_exec_if_table('m18_goods_receipt_note_log',
'UPDATE m18_goods_receipt_note_log SET grn_code = CONCAT(''GRN-'', id)');
CALL demo_exec_if_table('mail_template',
'UPDATE mail_template SET `to` = '''', cc = '''', description = CONCAT(''Template '', id), subjectCht = '''', subjectEng = '''', contentCht = '''', contentEng = ''''');
CALL demo_exec_if_table('mail_send_log',
'UPDATE mail_send_log SET senderMail = '''', subject = '''', content = '''', tempDesc = ''Mail'', errorMessage = ''''');
CALL demo_exec_if_table('mail_send_log_line',
'UPDATE mail_send_log_line SET toMail = '''', errorMessage = ''''');

CALL demo_apply_map('item_lot_trace_log', 'username', '_demo_map_username');
CALL demo_apply_map('stocktakerecord', 'createdBy', '_demo_map_username');
CALL demo_apply_map('pick_execution_issue', 'createdBy', '_demo_map_username');
CALL demo_apply_map('pick_execution_issue', 'modifiedBy', '_demo_map_username');
CALL demo_apply_map('pick_execution_issue', 'handled_by', '_demo_map_username');
CALL demo_apply_map('do_pick_order', 'createdBy', '_demo_map_username');
CALL demo_apply_map('do_pick_order', 'modifiedBy', '_demo_map_username');
CALL demo_apply_map('do_pick_order_record', 'createdBy', '_demo_map_username');
CALL demo_apply_map('do_pick_order_record', 'modifiedBy', '_demo_map_username');
CALL demo_apply_map('delivery_order_pick_order', 'createdBy', '_demo_map_username');
CALL demo_apply_map('delivery_order_pick_order', 'modifiedBy', '_demo_map_username');

CALL demo_apply_map('stocktakerecord', 'approverName', '_demo_map_person');
CALL demo_apply_map('stocktakerecord', 'stockTakerName', '_demo_map_person');
CALL demo_apply_map('do_pick_order', 'handler_name', '_demo_map_person');
CALL demo_apply_map('do_pick_order_record', 'handler_name', '_demo_map_person');
CALL demo_apply_map('delivery_order_pick_order', 'handlerName', '_demo_map_person');
CALL demo_apply_map('pick_execution_issue', 'picker_name', '_demo_map_person');
CALL demo_exec_if_table('pick_execution_issue',
'UPDATE pick_execution_issue SET item_description = ''''');

UPDATE `user` u
JOIN _demo_map_user m ON m.user_id = u.id
SET u.username = CONCAT('~u', u.id);

UPDATE `user` u
JOIN _demo_map_user m ON m.user_id = u.id
SET u.username = m.new_username,
u.password = pwd_hash,
u.name = m.new_name,
u.fullname = m.new_name,
u.firstname = 'User',
u.lastname = CAST(u.id AS CHAR),
u.email = CASE m.new_username
WHEN 'demo' THEN '[email protected]'
WHEN 'demo.stock' THEN '[email protected]'
WHEN 'demo.prod' THEN '[email protected]'
ELSE CONCAT('user', u.id, '@example.com')
END,
u.phone1 = '',
u.phone2 = '',
u.department = '',
u.title = '',
u.remarks = '',
u.staffNo = '';

CALL demo_blank_columns();
UPDATE truck
SET TruckLanceCode = REPLACE(TruckLanceCode, 'P06B', 'AA'),
remark = REPLACE(remark, 'P06B', 'AA');
CALL demo_exec_if_table('truck_lane_version',
'UPDATE truck_lane_version SET truckLanceCode = REPLACE(truckLanceCode, ''P06B'', ''AA'')');
CALL demo_exec_if_table('truck_lane_version_line',
'UPDATE truck_lane_version_line SET truckLanceCode = REPLACE(truckLanceCode, ''P06B'', ''AA'')');
CALL demo_exec_if_table('truck_lane_schedule_line',
'UPDATE truck_lane_schedule_line SET fromTruckLanceCode = REPLACE(fromTruckLanceCode, ''P06B'', ''AA''), toTruckLanceCode = REPLACE(toTruckLanceCode, ''P06B'', ''AA'')');
CALL demo_exec_if_table('delivery_order_pick_order',
'UPDATE delivery_order_pick_order SET truckLanceCode = REPLACE(truckLanceCode, ''P06B'', ''AA'')');
CALL demo_exec_if_table('do_pick_order',
'UPDATE do_pick_order SET TruckLanceCode = REPLACE(TruckLanceCode, ''P06B'', ''AA'')');
CALL demo_exec_if_table('do_pick_order_record',
'UPDATE do_pick_order_record SET TruckLanceCode = REPLACE(TruckLanceCode, ''P06B'', ''AA'')');
CALL demo_exec_if_table('do_replenishment',
'UPDATE do_replenishment SET truckLaneCode = REPLACE(truckLaneCode, ''P06B'', ''AA'')');

UPDATE purchase_order_line SET price = 1, up = 1;
UPDATE delivery_order_line SET price = 1, up = 1;

SELECT DATEDIFF(CURDATE(), MAX(DATE(estimatedArrivalDate)))
INTO expiry_delta
FROM delivery_order
WHERE deleted = 0 AND estimatedArrivalDate IS NOT NULL;

IF expiry_delta IS NOT NULL AND expiry_delta > 0 THEN
UPDATE inventory_lot
SET expiryDate = DATE_ADD(expiryDate, INTERVAL expiry_delta DAY)
WHERE expiryDate IS NOT NULL;
END IF;

UPDATE settings SET name = 'DO.floor.suppliers.AF' WHERE name = 'DO.floor.suppliers.2F';
UPDATE settings SET name = 'DO.floor.suppliers.BF' WHERE name = 'DO.floor.suppliers.4F';
CALL demo_remap_shop_csv('DO.floor.suppliers.AF');
CALL demo_remap_shop_csv('DO.floor.suppliers.BF');
UPDATE delivery_order d
JOIN (
SELECT eta_day, rn
FROM (
SELECT
DATE(estimatedArrivalDate) AS eta_day,
ROW_NUMBER() OVER (ORDER BY DATE(estimatedArrivalDate) DESC) AS rn
FROM delivery_order
WHERE deleted = 0 AND estimatedArrivalDate IS NOT NULL
GROUP BY DATE(estimatedArrivalDate)
) t
WHERE rn <= 3
) m ON DATE(d.estimatedArrivalDate) = m.eta_day
SET d.estimatedArrivalDate = TIMESTAMP(
DATE_ADD(CURDATE(), INTERVAL (m.rn - 1) DAY),
TIME(d.estimatedArrivalDate)
)
WHERE d.deleted = 0;

UPDATE purchase_order p
JOIN (
SELECT eta_day, rn
FROM (
SELECT
DATE(estimatedArrivalDate) AS eta_day,
ROW_NUMBER() OVER (ORDER BY DATE(estimatedArrivalDate) DESC) AS rn
FROM purchase_order
WHERE deleted = 0 AND estimatedArrivalDate IS NOT NULL
GROUP BY DATE(estimatedArrivalDate)
) t
WHERE rn <= 3
) m ON DATE(p.estimatedArrivalDate) = m.eta_day
SET p.estimatedArrivalDate = TIMESTAMP(
DATE_ADD(CURDATE(), INTERVAL (m.rn - 1) DAY),
TIME(p.estimatedArrivalDate)
)
WHERE p.deleted = 0;

UPDATE settings
SET value = ''
WHERE name IN (
'LASER_PRINT.host',
'LASER_PRINT.itemCodes',
'LASER_PRINT.lastReceiveSuccess'
)
OR name LIKE 'MAIL.smtp.%'
OR name LIKE 'REPORT.dailyMaint.recipients%';

CALL demo_replace_floors();
SET value = (
SELECT GROUP_CONCAT(DISTINCT s.code ORDER BY s.code SEPARATOR ',')
FROM delivery_order d
JOIN shop s ON s.id = d.supplierId AND s.deleted = 0
WHERE d.deleted = 0
AND d.estimatedArrivalDate IS NOT NULL
AND DATE(d.estimatedArrivalDate) BETWEEN CURDATE()
AND DATE_ADD(CURDATE(), INTERVAL 2 DAY)
)
WHERE name IN ('DO.floor.suppliers.2F', 'DO.floor.suppliers.4F');

INSERT INTO settings (name, value, category, type)
VALUES ('DEMO.anonymized.v1', '1', 'DEMO', 'string');

INSERT INTO settings (name, value, category, type)
VALUES ('DEMO.dateAnchor', DATE_FORMAT(CURDATE(), '%Y-%m-%d'), 'DEMO', 'string');

COMMIT;
CALL demo_drop_maps();
END$$
@@ -937,11 +488,7 @@ CALL anonymize_demo_copy();
DROP PROCEDURE IF EXISTS demo_exec_if_table;
DROP PROCEDURE IF EXISTS demo_apply_map;
DROP PROCEDURE IF EXISTS demo_apply_pair;
DROP PROCEDURE IF EXISTS demo_add_missing;
DROP PROCEDURE IF EXISTS demo_blank_columns;
DROP PROCEDURE IF EXISTS demo_replace_floors;
DROP PROCEDURE IF EXISTS demo_remap_shop_csv;
DROP PROCEDURE IF EXISTS demo_drop_maps;
DROP PROCEDURE IF EXISTS anonymize_demo_copy;

SELECT name, value FROM settings WHERE name = 'DEMO.anonymized.v1';
SELECT name, value FROM settings WHERE name IN ('DEMO.anonymized.v1', 'DEMO.dateAnchor');

+ 87
- 0
scripts/refresh_demo_dates.sql Целия файл

@@ -0,0 +1,87 @@
-- Move demo dates forward to the real UTC+8 today.
-- Run this on the morning of a demo when that day is later than
-- settings DEMO.dateAnchor. Safe to run again on the same day.
--
-- Adds the same number of days to:
-- inventory_lot.expiryDate
-- delivery_order.estimatedArrivalDate
-- purchase_order.estimatedArrivalDate
-- Quantities, statuses, and lot numbers stay. Already-expired lots stay expired.
--
-- Does not anonymize. Run scripts/anonymize_demo_copy.sql once first.
-- Only updates when DATABASE() is fpsms_demo and the guards below are ok.
--
-- Workbench: select fpsms_demo, File → Open SQL Script, run the whole file.
-- No DELIMITER / procedure (Workbench File → Run friendly).
--
-- mysql -h127.0.0.1 -P3306 -uroot -p fpsms_demo < scripts/refresh_demo_dates.sql

SET NAMES utf8mb4;
SET SESSION time_zone = '+08:00';
SET SESSION sql_safe_updates = 0;
SET SESSION net_read_timeout = 7200;
SET SESSION net_write_timeout = 7200;
SET SESSION wait_timeout = 28800;

SELECT CASE
WHEN DATABASE() IS NULL OR DATABASE() <> 'fpsms_demo'
THEN CONCAT('FAIL: current database is ', IFNULL(DATABASE(), 'NULL'), ' — select fpsms_demo')
WHEN (SELECT COUNT(*) FROM settings WHERE name = 'DEMO.anonymized.v1') = 0
THEN 'FAIL: run anonymize_demo_copy.sql first'
WHEN (SELECT COUNT(*) FROM settings WHERE name = 'DEMO.dateAnchor') <> 1
THEN 'FAIL: DEMO.dateAnchor must exist exactly once'
WHEN (
SELECT STR_TO_DATE(value, '%Y-%m-%d')
FROM settings
WHERE name = 'DEMO.dateAnchor'
) IS NULL
THEN 'FAIL: DEMO.dateAnchor is not YYYY-MM-DD'
ELSE 'ok'
END AS refresh_guard
INTO @refresh_guard;

SET @day_delta = IF(
@refresh_guard = 'ok',
(
SELECT DATEDIFF(CURDATE(), STR_TO_DATE(value, '%Y-%m-%d'))
FROM settings
WHERE name = 'DEMO.dateAnchor'
),
NULL
);

START TRANSACTION;

UPDATE inventory_lot
SET expiryDate = DATE_ADD(expiryDate, INTERVAL @day_delta DAY)
WHERE @refresh_guard = 'ok'
AND @day_delta > 0
AND expiryDate IS NOT NULL;

UPDATE delivery_order
SET estimatedArrivalDate = DATE_ADD(estimatedArrivalDate, INTERVAL @day_delta DAY)
WHERE @refresh_guard = 'ok'
AND @day_delta > 0
AND estimatedArrivalDate IS NOT NULL;

UPDATE purchase_order
SET estimatedArrivalDate = DATE_ADD(estimatedArrivalDate, INTERVAL @day_delta DAY)
WHERE @refresh_guard = 'ok'
AND @day_delta > 0
AND estimatedArrivalDate IS NOT NULL;

UPDATE settings
SET value = DATE_FORMAT(CURDATE(), '%Y-%m-%d')
WHERE @refresh_guard = 'ok'
AND @day_delta > 0
AND name = 'DEMO.dateAnchor';

COMMIT;

SELECT
@refresh_guard AS refresh_guard,
@day_delta AS days_added,
name,
value
FROM settings
WHERE name = 'DEMO.dateAnchor';

+ 17
- 16
src/main/java/com/ffii/fpsms/modules/common/demo/DemoFloors.kt Целия файл

@@ -1,26 +1,27 @@
package com.ffii.fpsms.modules.common.demo

/**
* Floor and bin labels stored in the anonymized demo database.
* A/F was 2/F, B/F was 4/F, C/F was 1/F, D/F was 3/F.
* Floor and bin labels kept from the production copy.
* Display uses 1/F–4/F. Setting keys and store keys use 1F–4F.
* Hold and WIP bins stay the real warehouse codes.
*/
object DemoFloors {
const val FLOOR_A = "A/F"
const val FLOOR_A_KEY = "AF"
const val FLOOR_B = "B/F"
const val FLOOR_B_KEY = "BF"
const val FLOOR_C = "C/F"
const val FLOOR_C_KEY = "CF"
const val FLOOR_D = "D/F"
const val FLOOR_D_KEY = "DF"
const val FLOOR_A = "2/F"
const val FLOOR_A_KEY = "2F"
const val FLOOR_B = "4/F"
const val FLOOR_B_KEY = "4F"
const val FLOOR_C = "1/F"
const val FLOOR_C_KEY = "1F"
const val FLOOR_D = "3/F"
const val FLOOR_D_KEY = "3F"

const val LOC_HOLD = "LOC-HOLD"
const val LOC_WIP = "LOC-WIP"
const val LOC_HOLD = "2F-W202-01-00"
const val LOC_WIP = "2F-W200-#A-00"
const val LOC_PREFIX = "LOC-"

const val LABEL_A = "LABEL-A"
const val LABEL_B = "LABEL-B"
const val LABEL_A = "Label機 2F A+B"
const val LABEL_B = "Label機 4F 乾貨 C, D"

const val SETTING_SUPPLIERS_A = "DO.floor.suppliers.AF"
const val SETTING_SUPPLIERS_B = "DO.floor.suppliers.BF"
const val SETTING_SUPPLIERS_A = "DO.floor.suppliers.2F"
const val SETTING_SUPPLIERS_B = "DO.floor.suppliers.4F"
}

+ 3
- 2
src/main/java/com/ffii/fpsms/modules/common/demo/DemoSandboxSeeder.kt Целия файл

@@ -14,7 +14,8 @@ import javax.sql.DataSource

/**
* Startup guard for the db-demo profile.
* The database must already be an anonymized copy of production. This does not insert rows.
* The database must already be an anonymized copy of production. This does not insert or rewrite rows.
* Dates, including lot expiry, are moved only by scripts/anonymize_demo_copy.sql and scripts/refresh_demo_dates.sql.
*/
@Component
@Profile("db-demo")
@@ -51,7 +52,7 @@ class DemoSandboxSeeder(
"Demo profile refused to start. $DEMO_DATABASE has not been anonymized. Run scripts/anonymize_demo_copy.sql before starting.",
)
}
log.info("Demo database {} is anonymized ({}).", DEMO_DATABASE, ANONYMIZED_MARKER)
log.info("Demo database {} is anonymized ({}). Dates are not moved at startup.", DEMO_DATABASE, ANONYMIZED_MARKER)
}

/**


Зареждане…
Отказ
Запис