25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 

588 satır
21 KiB

  1. -- Rewrite identifying values in fpsms_demo. Does not delete rows.
  2. -- Ids, foreign keys, statuses, quantities stay.
  3. -- Item codes, lot numbers, warehouse codes, and floors (1/F–4/F) stay.
  4. -- Shop codes, delivery-order codes, and purchase-order codes are rewritten
  5. -- and the same old string is updated everywhere it was copied.
  6. -- The three most recent delivery and purchase arrival dates move to
  7. -- today, tomorrow, and the day after. Today is the real calendar day
  8. -- in UTC+8. Lot expiry dates move forward by the same number of days
  9. -- as the newest delivery arrival day, so usable stock stays usable.
  10. -- settings DEMO.dateAnchor stores that day. Line prices become 1.
  11. -- Tops up demo hero stock (MG1757, PP2236, PP2237): every lot line gets
  12. -- >=20 available units, status=available, hold cleared, and Hold bin
  13. -- 2F-W202-01-00 → 2F-W201-#J-01 so JO 提料 / DO 執貨 can use them.
  14. -- Stocktake section ST-012 keeps only PP2220/PP2074/PP2126/PP2326;
  15. -- other items in those bins are stocked out (net qty → 0).
  16. -- DO.floor.suppliers.2F / 4F keep production split; shop codes expand to
  17. -- all matching S{id} (do not copy the same CSV into both floors).
  18. -- Opening the backend does not move dates. On a later demo day, run
  19. -- scripts/refresh_demo_dates.sql.
  20. --
  21. -- Run only against a disposable full copy of production:
  22. -- mysql -h127.0.0.1 -P3306 -uroot -p fpsms_demo < scripts/anonymize_demo_copy.sql
  23. --
  24. -- Refuses to run unless the current database is fpsms_demo.
  25. -- Refuses to run again once settings.name = DEMO.anonymized.v1 exists.
  26. -- Password for every user, including demo / demo.stock / demo.prod, is Demo2026!.
  27. -- staffNo is set for JO production scan: demo=STAFF001, demo.stock=STAFF002,
  28. -- demo.prod=STAFF003, others=STAFF{id}.
  29. --
  30. -- MySQL Workbench stops a query after 30 seconds and reports error 2013.
  31. -- Before running: Preferences, SQL Editor, DBMS connection read timeout = 3600.
  32. -- Reconnect, select fpsms_demo, then run this whole file.
  33. SET NAMES utf8mb4;
  34. SET SESSION time_zone = '+08:00';
  35. SET SESSION sql_safe_updates = 0;
  36. SET SESSION group_concat_max_len = 1000000;
  37. SET SESSION net_read_timeout = 7200;
  38. SET SESSION net_write_timeout = 7200;
  39. SET SESSION wait_timeout = 28800;
  40. DROP PROCEDURE IF EXISTS demo_exec_if_table;
  41. DROP PROCEDURE IF EXISTS demo_apply_map;
  42. DROP PROCEDURE IF EXISTS demo_apply_pair;
  43. DROP PROCEDURE IF EXISTS demo_add_missing;
  44. DROP PROCEDURE IF EXISTS demo_blank_columns;
  45. DROP PROCEDURE IF EXISTS demo_replace_floors;
  46. DROP PROCEDURE IF EXISTS demo_remap_shop_csv;
  47. DROP PROCEDURE IF EXISTS demo_drop_maps;
  48. DROP PROCEDURE IF EXISTS anonymize_demo_copy;
  49. DELIMITER $$
  50. CREATE PROCEDURE demo_drop_maps()
  51. BEGIN
  52. DROP TABLE IF EXISTS _demo_map_shop;
  53. DROP TABLE IF EXISTS _demo_map_do;
  54. DROP TABLE IF EXISTS _demo_map_po;
  55. DROP TABLE IF EXISTS _demo_map_user;
  56. DROP TABLE IF EXISTS _demo_map_username;
  57. DROP TABLE IF EXISTS _demo_map_person;
  58. END$$
  59. CREATE PROCEDURE demo_exec_if_table(IN p_table VARCHAR(64), IN p_sql TEXT)
  60. BEGIN
  61. DECLARE n INT DEFAULT 0;
  62. SELECT COUNT(*) INTO n
  63. FROM information_schema.tables
  64. WHERE table_schema = DATABASE() AND table_name = p_table;
  65. IF n > 0 THEN
  66. SET @demo_sql = p_sql;
  67. PREPARE demo_stmt FROM @demo_sql;
  68. EXECUTE demo_stmt;
  69. DEALLOCATE PREPARE demo_stmt;
  70. END IF;
  71. END$$
  72. CREATE PROCEDURE demo_apply_map(IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_map VARCHAR(64))
  73. BEGIN
  74. DECLARE n INT DEFAULT 0;
  75. SELECT COUNT(*) INTO n
  76. FROM information_schema.columns
  77. WHERE table_schema = DATABASE()
  78. AND table_name = p_table
  79. AND column_name = p_column;
  80. IF n > 0 THEN
  81. SET @demo_sql = CONCAT(
  82. 'UPDATE `', p_table, '` t INNER JOIN `', p_map, '` m ',
  83. 'ON t.`', p_column, '` COLLATE utf8mb4_unicode_ci = m.old_value ',
  84. 'SET t.`', p_column, '` = m.new_value'
  85. );
  86. PREPARE demo_stmt FROM @demo_sql;
  87. EXECUTE demo_stmt;
  88. DEALLOCATE PREPARE demo_stmt;
  89. END IF;
  90. END$$
  91. CREATE PROCEDURE demo_apply_pair(
  92. IN p_table VARCHAR(64),
  93. IN p_code VARCHAR(64),
  94. IN p_name VARCHAR(64),
  95. IN p_map VARCHAR(64)
  96. )
  97. BEGIN
  98. DECLARE ncode INT DEFAULT 0;
  99. DECLARE nname INT DEFAULT 0;
  100. SELECT COUNT(*) INTO ncode
  101. FROM information_schema.columns
  102. WHERE table_schema = DATABASE() AND table_name = p_table AND column_name = p_code;
  103. SELECT COUNT(*) INTO nname
  104. FROM information_schema.columns
  105. WHERE table_schema = DATABASE() AND table_name = p_table AND column_name = p_name;
  106. IF ncode > 0 AND nname > 0 THEN
  107. SET @demo_sql = CONCAT(
  108. 'UPDATE `', p_table, '` t INNER JOIN `', p_map, '` m ',
  109. 'ON t.`', p_code, '` COLLATE utf8mb4_unicode_ci = m.old_value ',
  110. 'SET t.`', p_code, '` = m.new_value, t.`', p_name, '` = m.new_name'
  111. );
  112. PREPARE demo_stmt FROM @demo_sql;
  113. EXECUTE demo_stmt;
  114. DEALLOCATE PREPARE demo_stmt;
  115. ELSEIF ncode > 0 THEN
  116. CALL demo_apply_map(p_table, p_code, p_map);
  117. END IF;
  118. END$$
  119. CREATE PROCEDURE anonymize_demo_copy()
  120. BEGIN
  121. DECLARE marker_count INT DEFAULT 0;
  122. DECLARE demo_id BIGINT DEFAULT NULL;
  123. DECLARE stock_id BIGINT DEFAULT NULL;
  124. DECLARE prod_id BIGINT DEFAULT NULL;
  125. DECLARE pwd_hash VARCHAR(80) DEFAULT '$2a$10$9eqxnNGtxFADAW9AbbjRIevr8YWgBqkLr//23U6qYOWs5U9figE2u';
  126. DECLARE expiry_delta INT DEFAULT NULL;
  127. DECLARE CONTINUE HANDLER FOR NOT FOUND SET demo_id = demo_id;
  128. DECLARE EXIT HANDLER FOR SQLEXCEPTION
  129. BEGIN
  130. ROLLBACK;
  131. CALL demo_drop_maps();
  132. RESIGNAL;
  133. END;
  134. IF DATABASE() IS NULL OR DATABASE() <> 'fpsms_demo' THEN
  135. SIGNAL SQLSTATE '45000'
  136. SET MESSAGE_TEXT = 'Refusing to anonymize: current database is not fpsms_demo';
  137. END IF;
  138. SELECT COUNT(*) INTO marker_count FROM settings WHERE name = 'DEMO.anonymized.v1';
  139. IF marker_count > 0 THEN
  140. SIGNAL SQLSTATE '45000'
  141. SET MESSAGE_TEXT = 'Refusing to anonymize: DEMO.anonymized.v1 already exists';
  142. END IF;
  143. CALL demo_drop_maps();
  144. CREATE TABLE _demo_map_shop (
  145. old_value VARCHAR(255) NOT NULL,
  146. new_value VARCHAR(255) NOT NULL,
  147. new_name VARCHAR(255) NOT NULL,
  148. PRIMARY KEY (old_value)
  149. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  150. CREATE TABLE _demo_map_do (
  151. old_value VARCHAR(255) NOT NULL,
  152. new_value VARCHAR(255) NOT NULL,
  153. PRIMARY KEY (old_value)
  154. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  155. CREATE TABLE _demo_map_po (
  156. old_value VARCHAR(255) NOT NULL,
  157. new_value VARCHAR(255) NOT NULL,
  158. PRIMARY KEY (old_value)
  159. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  160. CREATE TABLE _demo_map_user (
  161. user_id BIGINT NOT NULL,
  162. old_username VARCHAR(255) NULL,
  163. new_username VARCHAR(255) NOT NULL,
  164. old_name VARCHAR(255) NULL,
  165. new_name VARCHAR(255) NOT NULL,
  166. PRIMARY KEY (user_id)
  167. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  168. CREATE TABLE _demo_map_username (
  169. old_value VARCHAR(255) NOT NULL,
  170. new_value VARCHAR(255) NOT NULL,
  171. PRIMARY KEY (old_value)
  172. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  173. CREATE TABLE _demo_map_person (
  174. old_value VARCHAR(255) NOT NULL,
  175. new_value VARCHAR(255) NOT NULL,
  176. PRIMARY KEY (old_value)
  177. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  178. SELECT u.id INTO demo_id
  179. FROM `user` u
  180. JOIN user_authority ua ON ua.userId = u.id
  181. JOIN authority a ON a.id = ua.authId
  182. WHERE a.authority = 'ADMIN'
  183. ORDER BY u.deleted, u.id
  184. LIMIT 1;
  185. IF demo_id IS NULL THEN
  186. SELECT id INTO demo_id FROM `user` ORDER BY deleted, id LIMIT 1;
  187. END IF;
  188. SELECT u.id INTO stock_id
  189. FROM `user` u
  190. WHERE u.id <> IFNULL(demo_id, -1)
  191. AND EXISTS (
  192. SELECT 1 FROM user_authority ua
  193. JOIN authority a ON a.id = ua.authId
  194. WHERE ua.userId = u.id AND a.authority = 'STOCK'
  195. )
  196. AND NOT EXISTS (
  197. SELECT 1 FROM user_authority ua
  198. JOIN authority a ON a.id = ua.authId
  199. WHERE ua.userId = u.id AND a.authority = 'ADMIN'
  200. )
  201. ORDER BY u.deleted, u.id
  202. LIMIT 1;
  203. SELECT u.id INTO prod_id
  204. FROM `user` u
  205. WHERE u.id <> IFNULL(demo_id, -1)
  206. AND u.id <> IFNULL(stock_id, -1)
  207. AND EXISTS (
  208. SELECT 1 FROM user_authority ua
  209. JOIN authority a ON a.id = ua.authId
  210. WHERE ua.userId = u.id AND a.authority = 'PROD'
  211. )
  212. AND NOT EXISTS (
  213. SELECT 1 FROM user_authority ua
  214. JOIN authority a ON a.id = ua.authId
  215. WHERE ua.userId = u.id AND a.authority = 'ADMIN'
  216. )
  217. ORDER BY u.deleted, u.id
  218. LIMIT 1;
  219. INSERT INTO _demo_map_user (user_id, old_username, new_username, old_name, new_name)
  220. SELECT id,
  221. NULLIF(username, ''),
  222. CASE
  223. WHEN id = demo_id THEN 'demo'
  224. WHEN id = stock_id THEN 'demo.stock'
  225. WHEN id = prod_id THEN 'demo.prod'
  226. ELSE CONCAT('USER-', id)
  227. END,
  228. NULLIF(name, ''),
  229. CASE
  230. WHEN id = demo_id THEN 'Demo'
  231. WHEN id = stock_id THEN 'Demo Stock'
  232. WHEN id = prod_id THEN 'Demo Prod'
  233. ELSE CONCAT('User ', id)
  234. END
  235. FROM `user`;
  236. INSERT INTO _demo_map_username (old_value, new_value)
  237. SELECT old_username, MIN(new_username)
  238. FROM _demo_map_user
  239. WHERE old_username IS NOT NULL
  240. GROUP BY old_username;
  241. INSERT INTO _demo_map_person (old_value, new_value)
  242. SELECT old_name, MIN(new_name)
  243. FROM _demo_map_user
  244. WHERE old_name IS NOT NULL
  245. GROUP BY old_name;
  246. INSERT INTO _demo_map_shop (old_value, new_value, new_name)
  247. SELECT code, CONCAT('S', MIN(id)), CONCAT('Shop ', MIN(id))
  248. FROM shop
  249. WHERE code IS NOT NULL AND code <> ''
  250. GROUP BY code;
  251. INSERT INTO _demo_map_do (old_value, new_value)
  252. SELECT code,
  253. CASE
  254. WHEN stripped = '' THEN CONCAT('DO-', min_id)
  255. WHEN dup_count > 1 THEN CONCAT(stripped, '-', min_id)
  256. ELSE stripped
  257. END
  258. FROM (
  259. SELECT g.code,
  260. g.stripped,
  261. g.min_id,
  262. COUNT(*) OVER (PARTITION BY g.stripped) AS dup_count
  263. FROM (
  264. SELECT code,
  265. REPLACE(code, 'TO', '') AS stripped,
  266. MIN(id) AS min_id
  267. FROM delivery_order
  268. WHERE code IS NOT NULL AND code <> ''
  269. GROUP BY code
  270. ) g
  271. ) numbered;
  272. INSERT INTO _demo_map_po (old_value, new_value)
  273. SELECT code,
  274. CASE
  275. WHEN stripped = '' THEN CONCAT('PO-', min_id)
  276. WHEN dup_count > 1 THEN CONCAT(stripped, '-', min_id)
  277. ELSE stripped
  278. END
  279. FROM (
  280. SELECT g.code,
  281. g.stripped,
  282. g.min_id,
  283. COUNT(*) OVER (PARTITION BY g.stripped) AS dup_count
  284. FROM (
  285. SELECT code,
  286. REPLACE(REPLACE(code, 'PF', ''), 'PP', '') AS stripped,
  287. MIN(id) AS min_id
  288. FROM purchase_order
  289. WHERE code IS NOT NULL AND code <> ''
  290. GROUP BY code
  291. ) g
  292. ) numbered;
  293. START TRANSACTION;
  294. UPDATE `user` u
  295. JOIN _demo_map_user m ON m.user_id = u.id
  296. SET u.username = CONCAT('~u', u.id);
  297. UPDATE `user` u
  298. JOIN _demo_map_user m ON m.user_id = u.id
  299. SET u.username = m.new_username,
  300. u.password = pwd_hash,
  301. u.name = m.new_name,
  302. u.fullname = m.new_name,
  303. u.firstname = 'User',
  304. u.lastname = CAST(u.id AS CHAR),
  305. u.email = CASE m.new_username
  306. WHEN 'demo' THEN '[email protected]'
  307. WHEN 'demo.stock' THEN '[email protected]'
  308. WHEN 'demo.prod' THEN '[email protected]'
  309. ELSE CONCAT('user', u.id, '@example.com')
  310. END,
  311. u.phone1 = '',
  312. u.phone2 = '',
  313. u.department = '',
  314. u.title = '',
  315. u.remarks = '',
  316. -- Keep scannable staffNo for JO production (findByStaffNo).
  317. -- Prefix STAFF so camera/keyboard plain-text scan is accepted by FE.
  318. u.staffNo = CASE m.new_username
  319. WHEN 'demo' THEN 'STAFF001'
  320. WHEN 'demo.stock' THEN 'STAFF002'
  321. WHEN 'demo.prod' THEN 'STAFF003'
  322. ELSE CONCAT('STAFF', u.id)
  323. END;
  324. CALL demo_apply_map('item_lot_trace_log', 'username', '_demo_map_username');
  325. CALL demo_apply_map('stocktakerecord', 'createdBy', '_demo_map_username');
  326. CALL demo_apply_map('pick_execution_issue', 'createdBy', '_demo_map_username');
  327. CALL demo_apply_map('pick_execution_issue', 'modifiedBy', '_demo_map_username');
  328. CALL demo_apply_map('pick_execution_issue', 'handled_by', '_demo_map_username');
  329. CALL demo_apply_map('do_pick_order', 'createdBy', '_demo_map_username');
  330. CALL demo_apply_map('do_pick_order', 'modifiedBy', '_demo_map_username');
  331. CALL demo_apply_map('do_pick_order_record', 'createdBy', '_demo_map_username');
  332. CALL demo_apply_map('do_pick_order_record', 'modifiedBy', '_demo_map_username');
  333. CALL demo_apply_map('delivery_order_pick_order', 'createdBy', '_demo_map_username');
  334. CALL demo_apply_map('delivery_order_pick_order', 'modifiedBy', '_demo_map_username');
  335. CALL demo_apply_map('stocktakerecord', 'approverName', '_demo_map_person');
  336. CALL demo_apply_map('stocktakerecord', 'stockTakerName', '_demo_map_person');
  337. CALL demo_apply_map('do_pick_order', 'handler_name', '_demo_map_person');
  338. CALL demo_apply_map('do_pick_order_record', 'handler_name', '_demo_map_person');
  339. CALL demo_apply_map('delivery_order_pick_order', 'handlerName', '_demo_map_person');
  340. CALL demo_apply_map('pick_execution_issue', 'picker_name', '_demo_map_person');
  341. UPDATE items
  342. SET name = REPLACE(REPLACE(IFNULL(name, ''), 'TOA', ''), '平記', ''),
  343. description = REPLACE(REPLACE(IFNULL(description, ''), 'TOA', ''), '平記', '');
  344. -- Remap floor supplier CSVs while shop.code is still the production code.
  345. -- Expand each listed code to every shop row with that code → S{id}, so DO
  346. -- supplierId rows keep matching after shop codes become unique.
  347. SELECT IFNULL(value, '') INTO @demo_floor_2f
  348. FROM settings WHERE name = 'DO.floor.suppliers.2F' LIMIT 1;
  349. SELECT IFNULL(value, '') INTO @demo_floor_4f
  350. FROM settings WHERE name = 'DO.floor.suppliers.4F' LIMIT 1;
  351. UPDATE settings
  352. SET value = IFNULL((
  353. SELECT GROUP_CONCAT(DISTINCT CONCAT('S', s.id) ORDER BY s.id SEPARATOR ',')
  354. FROM shop s
  355. WHERE IFNULL(s.deleted, 0) = 0
  356. AND @demo_floor_2f <> ''
  357. AND FIND_IN_SET(s.code, REPLACE(@demo_floor_2f, ' ', ''))
  358. ), '')
  359. WHERE name = 'DO.floor.suppliers.2F';
  360. UPDATE settings
  361. SET value = IFNULL((
  362. SELECT GROUP_CONCAT(DISTINCT CONCAT('S', s.id) ORDER BY s.id SEPARATOR ',')
  363. FROM shop s
  364. WHERE IFNULL(s.deleted, 0) = 0
  365. AND @demo_floor_4f <> ''
  366. AND FIND_IN_SET(s.code, REPLACE(@demo_floor_4f, ' ', ''))
  367. ), '')
  368. WHERE name = 'DO.floor.suppliers.4F';
  369. UPDATE shop
  370. SET code = CONCAT('S', id),
  371. name = CONCAT('Shop ', id),
  372. contactNo = '88888888',
  373. addr1 = CONCAT('Addr row 1 ', id),
  374. addr2 = CONCAT('Addr row 2 ', id),
  375. addr3 = '香港';
  376. CALL demo_apply_pair('truck', 'ShopCode', 'ShopName', '_demo_map_shop');
  377. CALL demo_apply_pair('truck_lane_schedule_line', 'shopCode', 'shopName', '_demo_map_shop');
  378. CALL demo_apply_pair('delivery_order_pick_order', 'shopCode', 'shopName', '_demo_map_shop');
  379. CALL demo_apply_pair('do_pick_order', 'ShopCode', 'ShopName', '_demo_map_shop');
  380. CALL demo_apply_pair('do_pick_order_record', 'ShopCode', 'ShopName', '_demo_map_shop');
  381. CALL demo_apply_pair('do_replenishment', 'shopCode', 'shopName', '_demo_map_shop');
  382. CALL demo_apply_pair('truck_lane_version_line', 'shopCode', 'branchName', '_demo_map_shop');
  383. CALL demo_apply_map('truck', 'ShopCode', '_demo_map_shop');
  384. CALL demo_apply_map('do_replenishment', 'shopCode', '_demo_map_shop');
  385. CALL demo_apply_map('delivery_order', 'code', '_demo_map_do');
  386. CALL demo_apply_map('do_pick_order', 'delivery_order_code', '_demo_map_do');
  387. CALL demo_apply_map('do_pick_order_record', 'delivery_order_code', '_demo_map_do');
  388. CALL demo_apply_map('do_pick_order_line', 'delivery_order_code', '_demo_map_do');
  389. CALL demo_apply_map('do_pick_order_line_record', 'delivery_order_code', '_demo_map_do');
  390. CALL demo_apply_map('stock_out', 'deliveryOrderCode', '_demo_map_do');
  391. CALL demo_apply_map('do_replenishment', 'sourceDoCode', '_demo_map_do');
  392. CALL demo_apply_map('do_replenishment', 'targetDoCode', '_demo_map_do');
  393. CALL demo_apply_map('purchase_order', 'code', '_demo_map_po');
  394. UPDATE truck
  395. SET TruckLanceCode = REPLACE(TruckLanceCode, 'P06B', 'AA'),
  396. remark = REPLACE(remark, 'P06B', 'AA');
  397. CALL demo_exec_if_table('truck_lane_version',
  398. 'UPDATE truck_lane_version SET truckLanceCode = REPLACE(truckLanceCode, ''P06B'', ''AA'')');
  399. CALL demo_exec_if_table('truck_lane_version_line',
  400. 'UPDATE truck_lane_version_line SET truckLanceCode = REPLACE(truckLanceCode, ''P06B'', ''AA'')');
  401. CALL demo_exec_if_table('truck_lane_schedule_line',
  402. 'UPDATE truck_lane_schedule_line SET fromTruckLanceCode = REPLACE(fromTruckLanceCode, ''P06B'', ''AA''), toTruckLanceCode = REPLACE(toTruckLanceCode, ''P06B'', ''AA'')');
  403. CALL demo_exec_if_table('delivery_order_pick_order',
  404. 'UPDATE delivery_order_pick_order SET truckLanceCode = REPLACE(truckLanceCode, ''P06B'', ''AA'')');
  405. CALL demo_exec_if_table('do_pick_order',
  406. 'UPDATE do_pick_order SET TruckLanceCode = REPLACE(TruckLanceCode, ''P06B'', ''AA'')');
  407. CALL demo_exec_if_table('do_pick_order_record',
  408. 'UPDATE do_pick_order_record SET TruckLanceCode = REPLACE(TruckLanceCode, ''P06B'', ''AA'')');
  409. CALL demo_exec_if_table('do_replenishment',
  410. 'UPDATE do_replenishment SET truckLaneCode = REPLACE(truckLaneCode, ''P06B'', ''AA'')');
  411. UPDATE purchase_order_line SET price = 1, up = 1;
  412. UPDATE delivery_order_line SET price = 1, up = 1;
  413. SELECT DATEDIFF(CURDATE(), MAX(DATE(estimatedArrivalDate)))
  414. INTO expiry_delta
  415. FROM delivery_order
  416. WHERE deleted = 0 AND estimatedArrivalDate IS NOT NULL;
  417. IF expiry_delta IS NOT NULL AND expiry_delta > 0 THEN
  418. -- Clamp at DATE max so sentinel 9999-12-31 lots do not Error 1441.
  419. UPDATE inventory_lot
  420. SET expiryDate = IF(
  421. expiryDate > DATE_SUB('9999-12-31', INTERVAL expiry_delta DAY),
  422. '9999-12-31',
  423. DATE_ADD(expiryDate, INTERVAL expiry_delta DAY)
  424. )
  425. WHERE expiryDate IS NOT NULL;
  426. END IF;
  427. UPDATE delivery_order d
  428. JOIN (
  429. SELECT eta_day, rn
  430. FROM (
  431. SELECT
  432. DATE(estimatedArrivalDate) AS eta_day,
  433. ROW_NUMBER() OVER (ORDER BY DATE(estimatedArrivalDate) DESC) AS rn
  434. FROM delivery_order
  435. WHERE deleted = 0 AND estimatedArrivalDate IS NOT NULL
  436. GROUP BY DATE(estimatedArrivalDate)
  437. ) t
  438. WHERE rn <= 3
  439. ) m ON DATE(d.estimatedArrivalDate) = m.eta_day
  440. SET d.estimatedArrivalDate = TIMESTAMP(
  441. DATE_ADD(CURDATE(), INTERVAL (m.rn - 1) DAY),
  442. TIME(d.estimatedArrivalDate)
  443. )
  444. WHERE d.deleted = 0;
  445. UPDATE purchase_order p
  446. JOIN (
  447. SELECT eta_day, rn
  448. FROM (
  449. SELECT
  450. DATE(estimatedArrivalDate) AS eta_day,
  451. ROW_NUMBER() OVER (ORDER BY DATE(estimatedArrivalDate) DESC) AS rn
  452. FROM purchase_order
  453. WHERE deleted = 0 AND estimatedArrivalDate IS NOT NULL
  454. GROUP BY DATE(estimatedArrivalDate)
  455. ) t
  456. WHERE rn <= 3
  457. ) m ON DATE(p.estimatedArrivalDate) = m.eta_day
  458. SET p.estimatedArrivalDate = TIMESTAMP(
  459. DATE_ADD(CURDATE(), INTERVAL (m.rn - 1) DAY),
  460. TIME(p.estimatedArrivalDate)
  461. )
  462. WHERE p.deleted = 0;
  463. -- Demo hero stock: MG1757 (PP2220 JO 提料) + PP2236/PP2237 (DO 執貨).
  464. -- Production copy often leaves these depleted and/or status=unavailable
  465. -- (and on Hold). Every lot line: >=20 net qty, status=available,
  466. -- holdQty=0, Hold bin → 2F-W201-#J-01. Trigger syncs inventory.
  467. UPDATE inventory_lot_line ill
  468. JOIN inventory_lot l
  469. ON l.id = ill.inventoryLotId AND IFNULL(l.deleted, 0) = 0
  470. JOIN items i
  471. ON i.id = l.itemId
  472. AND i.code IN ('MG1757', 'PP2236', 'PP2237')
  473. AND IFNULL(i.deleted, 0) = 0
  474. LEFT JOIN warehouse w
  475. ON w.id = ill.warehouseId
  476. LEFT JOIN warehouse w_pick
  477. ON w_pick.code = '2F-W201-#J-01'
  478. AND IFNULL(w_pick.deleted, 0) = 0
  479. SET ill.inQty = IF(
  480. (
  481. IFNULL(ill.inQty, 0)
  482. - IFNULL(ill.outQty, 0)
  483. - IFNULL(ill.holdQty, 0)
  484. ) < 20,
  485. IFNULL(ill.outQty, 0) + 20,
  486. ill.inQty
  487. ),
  488. ill.holdQty = 0,
  489. ill.status = 'available',
  490. ill.warehouseId = IF(
  491. w.code = '2F-W202-01-00' AND w_pick.id IS NOT NULL,
  492. w_pick.id,
  493. ill.warehouseId
  494. )
  495. WHERE IFNULL(ill.deleted, 0) = 0;
  496. -- Demo stocktake ST-012 (2F 麵包餡): only keep PP2220 / PP2074 / PP2126 /
  497. -- PP2326. Zero every other item in those bins so 盤點 shows a short list.
  498. UPDATE inventory_lot_line ill
  499. JOIN inventory_lot l
  500. ON l.id = ill.inventoryLotId AND IFNULL(l.deleted, 0) = 0
  501. JOIN items i
  502. ON i.id = l.itemId
  503. AND IFNULL(i.deleted, 0) = 0
  504. AND i.code NOT IN ('PP2220', 'PP2074', 'PP2126', 'PP2326')
  505. JOIN warehouse w
  506. ON w.id = ill.warehouseId
  507. AND IFNULL(w.deleted, 0) = 0
  508. AND w.stockTakeSection = 'ST-012'
  509. SET ill.outQty = IFNULL(ill.inQty, 0),
  510. ill.holdQty = 0
  511. WHERE IFNULL(ill.deleted, 0) = 0
  512. AND (
  513. IFNULL(ill.inQty, 0)
  514. - IFNULL(ill.outQty, 0)
  515. - IFNULL(ill.holdQty, 0)
  516. ) <> 0;
  517. INSERT INTO settings (name, value, category, type)
  518. VALUES ('DEMO.anonymized.v1', '1', 'DEMO', 'string');
  519. INSERT INTO settings (name, value, category, type)
  520. VALUES ('DEMO.dateAnchor', DATE_FORMAT(CURDATE(), '%Y-%m-%d'), 'DEMO', 'string');
  521. COMMIT;
  522. CALL demo_drop_maps();
  523. END$$
  524. DELIMITER ;
  525. CALL anonymize_demo_copy();
  526. DROP PROCEDURE IF EXISTS demo_exec_if_table;
  527. DROP PROCEDURE IF EXISTS demo_apply_map;
  528. DROP PROCEDURE IF EXISTS demo_apply_pair;
  529. DROP PROCEDURE IF EXISTS demo_drop_maps;
  530. DROP PROCEDURE IF EXISTS anonymize_demo_copy;
  531. SELECT name, value FROM settings WHERE name IN ('DEMO.anonymized.v1', 'DEMO.dateAnchor');