Compare commits
15 Commits
main
...
besure_bit
| Author | SHA1 | Date |
|---|---|---|
|
|
da79700989 | 2 weeks ago |
|
|
f16039eb5f | 2 weeks ago |
|
|
09dc3787b5 | 2 weeks ago |
|
|
cdbb749740 | 2 weeks ago |
|
|
db5603614f | 2 weeks ago |
|
|
15b2bc983b | 3 weeks ago |
|
|
af69388cbc | 3 weeks ago |
|
|
16f75d6659 | 3 weeks ago |
|
|
2680f3e5e2 | 3 weeks ago |
|
|
0eb71bb20f | 3 weeks ago |
|
|
095b4a19dc | 3 weeks ago |
|
|
14b8df60f6 | 3 weeks ago |
|
|
fd654978e0 | 3 weeks ago |
|
|
5987645a86 | 3 weeks ago |
|
|
9b313142a9 | 3 weeks ago |
@ -0,0 +1,436 @@
|
||||
-- BIT 样品仓储 v1.0
|
||||
-- Run against besure_bit_dev after review.
|
||||
|
||||
-- 样品基础字段
|
||||
SET @schema_name := DATABASE();
|
||||
|
||||
SET @column_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND column_name = 'is_sample'
|
||||
);
|
||||
SET @sql := IF(@column_exists = 0,
|
||||
'ALTER TABLE erp_product ADD COLUMN is_sample bit(1) NOT NULL DEFAULT b''0'' COMMENT ''是否样品'' AFTER bar_code',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @column_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND column_name = 'sample_category'
|
||||
);
|
||||
SET @sql := IF(@column_exists = 0,
|
||||
'ALTER TABLE erp_product ADD COLUMN sample_category varchar(64) NULL COMMENT ''样品分类'' AFTER is_sample',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @column_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND column_name = 'biz_unit'
|
||||
);
|
||||
SET @sql := IF(@column_exists = 0,
|
||||
'ALTER TABLE erp_product ADD COLUMN biz_unit varchar(64) NULL COMMENT ''所属事业部'' AFTER sample_category',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @column_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND column_name = 'customer_id'
|
||||
);
|
||||
SET @sql := IF(@column_exists = 0,
|
||||
'ALTER TABLE erp_product ADD COLUMN customer_id bigint NULL COMMENT ''客户ID'' AFTER biz_unit',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @column_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND column_name = 'customer_name'
|
||||
);
|
||||
SET @sql := IF(@column_exists = 0,
|
||||
'ALTER TABLE erp_product ADD COLUMN customer_name varchar(128) NULL COMMENT ''客户名称快照'' AFTER customer_id',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @index_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND index_name = 'idx_erp_product_sample'
|
||||
);
|
||||
SET @sql := IF(@index_exists = 0,
|
||||
'CREATE INDEX idx_erp_product_sample ON erp_product (is_sample, biz_unit, category_id, sub_category_id)',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @index_exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = @schema_name AND table_name = 'erp_product' AND index_name = 'idx_erp_product_customer'
|
||||
);
|
||||
SET @sql := IF(@index_exists = 0,
|
||||
'CREATE INDEX idx_erp_product_customer ON erp_product (customer_id)',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 字典:样品分类、出库原因
|
||||
INSERT INTO system_dict_type
|
||||
(name, type, status, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 'BIT样品分类', 'bit_sample_category', 0, 'BIT样品仓样品分类', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_type WHERE type = 'bit_sample_category');
|
||||
|
||||
INSERT INTO system_dict_type
|
||||
(name, type, status, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 'BIT样品出库原因', 'bit_sample_out_reason', 0, 'BIT样品仓出库原因', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_type WHERE type = 'bit_sample_out_reason');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 10, '客户样品', 'CUSTOMER_SAMPLE', 'bit_sample_category', 0, 'primary', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_category' AND value = 'CUSTOMER_SAMPLE');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 20, '内部样品', 'INTERNAL_SAMPLE', 'bit_sample_category', 0, 'success', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_category' AND value = 'INTERNAL_SAMPLE');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 30, '测试样品', 'TEST_SAMPLE', 'bit_sample_category', 0, 'warning', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_category' AND value = 'TEST_SAMPLE');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 10, '测试', 'TEST', 'bit_sample_out_reason', 0, 'warning', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_out_reason' AND value = 'TEST');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 20, '寄样', 'SEND_SAMPLE', 'bit_sample_out_reason', 0, 'primary', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_out_reason' AND value = 'SEND_SAMPLE');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 30, '领用', 'USE', 'bit_sample_out_reason', 0, 'success', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_out_reason' AND value = 'USE');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 40, '报废', 'SCRAP', 'bit_sample_out_reason', 0, 'danger', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_out_reason' AND value = 'SCRAP');
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 50, '其他', 'OTHER', 'bit_sample_out_reason', 0, 'info', '', '', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_type = 'bit_sample_out_reason' AND value = 'OTHER');
|
||||
|
||||
-- 编码规则:样品码、库位码,默认自动生成且后续可在系统中调整
|
||||
INSERT INTO erp_autocode_rule
|
||||
(rule_code, rule_name, rule_desc, max_length, is_padded, padded_char, padded_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 'BIT_SAMPLE_CODE', 'BIT样品码', 'BIT样品仓样品码默认规则', 18, 'N', '0', 'L', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM erp_autocode_rule WHERE rule_code = 'BIT_SAMPLE_CODE');
|
||||
|
||||
SET @bit_sample_rule_id := (SELECT id FROM erp_autocode_rule WHERE rule_code = 'BIT_SAMPLE_CODE' ORDER BY id LIMIT 1);
|
||||
|
||||
INSERT INTO erp_autocode_part
|
||||
(rule_id, part_index, part_type, part_code, part_name, part_length, datetime_format, input_character, fix_character, seria_start_no, seria_step, seria_now_no, cycle_flag, cycle_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_sample_rule_id, 1, 'FIXCHAR', 'BIT_SAMPLE_PREFIX', '固定前缀', 2, '', '', 'SP', NULL, NULL, NULL, 'N', 'OTHER', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_part WHERE rule_id = @bit_sample_rule_id AND part_code = 'BIT_SAMPLE_PREFIX');
|
||||
|
||||
INSERT INTO erp_autocode_part
|
||||
(rule_id, part_index, part_type, part_code, part_name, part_length, datetime_format, input_character, fix_character, seria_start_no, seria_step, seria_now_no, cycle_flag, cycle_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_sample_rule_id, 2, 'NOWDATE', 'BIT_SAMPLE_DATE', '年月日', 8, 'yyyyMMdd', '', '', NULL, NULL, NULL, 'N', 'OTHER', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_part WHERE rule_id = @bit_sample_rule_id AND part_code = 'BIT_SAMPLE_DATE');
|
||||
|
||||
INSERT INTO erp_autocode_part
|
||||
(rule_id, part_index, part_type, part_code, part_name, part_length, datetime_format, input_character, fix_character, seria_start_no, seria_step, seria_now_no, cycle_flag, cycle_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_sample_rule_id, 3, 'SERIALNO', 'BIT_SAMPLE_SERIAL', '流水号', 4, '', '', '', 1, 1, 0, 'Y', 'DAY', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_part WHERE rule_id = @bit_sample_rule_id AND part_code = 'BIT_SAMPLE_SERIAL');
|
||||
|
||||
INSERT INTO erp_autocode_record
|
||||
(rule_id, gen_date, gen_index, last_result, last_serial_no, last_input_char, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_sample_rule_id, DATE_FORMAT(NOW(), '%Y%m%d'), 0, '', 0, '', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_record WHERE rule_id = @bit_sample_rule_id);
|
||||
|
||||
INSERT INTO erp_autocode_rule
|
||||
(rule_code, rule_name, rule_desc, max_length, is_padded, padded_char, padded_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 'BIT_WAREHOUSE_LOCATION_CODE', 'BIT库位码', 'BIT样品仓库位码默认规则', 18, 'N', '0', 'L', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM erp_autocode_rule WHERE rule_code = 'BIT_WAREHOUSE_LOCATION_CODE');
|
||||
|
||||
SET @bit_location_rule_id := (SELECT id FROM erp_autocode_rule WHERE rule_code = 'BIT_WAREHOUSE_LOCATION_CODE' ORDER BY id LIMIT 1);
|
||||
|
||||
INSERT INTO erp_autocode_part
|
||||
(rule_id, part_index, part_type, part_code, part_name, part_length, datetime_format, input_character, fix_character, seria_start_no, seria_step, seria_now_no, cycle_flag, cycle_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_location_rule_id, 1, 'FIXCHAR', 'BIT_LOCATION_PREFIX', '固定前缀', 3, '', '', 'LOC', NULL, NULL, NULL, 'N', 'OTHER', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_location_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_part WHERE rule_id = @bit_location_rule_id AND part_code = 'BIT_LOCATION_PREFIX');
|
||||
|
||||
INSERT INTO erp_autocode_part
|
||||
(rule_id, part_index, part_type, part_code, part_name, part_length, datetime_format, input_character, fix_character, seria_start_no, seria_step, seria_now_no, cycle_flag, cycle_method, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_location_rule_id, 2, 'SERIALNO', 'BIT_LOCATION_SERIAL', '流水号', 5, '', '', '', 1, 1, 0, 'N', 'OTHER', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_location_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_part WHERE rule_id = @bit_location_rule_id AND part_code = 'BIT_LOCATION_SERIAL');
|
||||
|
||||
INSERT INTO erp_autocode_record
|
||||
(rule_id, gen_date, gen_index, last_result, last_serial_no, last_input_char, remark, is_enable, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @bit_location_rule_id, '', 0, '', 0, '', '', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_location_rule_id IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM erp_autocode_record WHERE rule_id = @bit_location_rule_id);
|
||||
|
||||
-- 菜单和按钮权限:后续 Web 页面与后端接口按这些权限标识实现
|
||||
SET @menu_seed := GREATEST((SELECT IFNULL(MAX(id), 0) FROM system_menu), 900000);
|
||||
|
||||
SET @erp_menu_id := (SELECT id FROM system_menu WHERE path = '/erp' AND parent_id = 0 AND deleted = b'0' ORDER BY id LIMIT 1);
|
||||
|
||||
SET @bit_wms_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @erp_menu_id AND path = 'bitwms' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, 'BIT样品仓', '', 1, 90, @erp_menu_id, 'bitwms', 'ep:box', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @erp_menu_id IS NOT NULL AND @bit_wms_id IS NULL;
|
||||
SET @bit_wms_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @erp_menu_id AND path = 'bitwms' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_sample_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'sample' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品信息', 'erp:bit-wms-sample:query', 2, 10, @bit_wms_id, 'sample', 'ep:goods', 'erp/bitwms/sample/index', 'ErpBitWmsSample', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_sample_menu_id IS NULL;
|
||||
SET @bit_sample_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'sample' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_location_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'location' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '库位信息', 'erp:bit-wms-location:query', 2, 20, @bit_wms_id, 'location', 'ep:coordinate', 'erp/bitwms/location/index', 'ErpBitWmsLocation', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_location_menu_id IS NULL;
|
||||
SET @bit_location_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'location' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_in_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'in' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品入库', 'erp:bit-wms-in:query', 2, 30, @bit_wms_id, 'in', 'ep:download', 'erp/bitwms/in/index', 'ErpBitWmsIn', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_in_menu_id IS NULL;
|
||||
SET @bit_in_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'in' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_out_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'out' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品出库', 'erp:bit-wms-out:query', 2, 40, @bit_wms_id, 'out', 'ep:upload', 'erp/bitwms/out/index', 'ErpBitWmsOut', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_out_menu_id IS NULL;
|
||||
SET @bit_out_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'out' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_move_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'move' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品移库', 'erp:bit-wms-move:query', 2, 50, @bit_wms_id, 'move', 'ep:sort', 'erp/bitwms/move/index', 'ErpBitWmsMove', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_move_menu_id IS NULL;
|
||||
SET @bit_move_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'move' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_stock_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'stock' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品库存', 'erp:bit-wms-stock:query', 2, 60, @bit_wms_id, 'stock', 'ep:grid', 'erp/bitwms/stock/index', 'ErpBitWmsStock', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_stock_menu_id IS NULL;
|
||||
SET @bit_stock_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'stock' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @bit_record_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'record' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '出入库明细', 'erp:bit-wms-record:query', 2, 70, @bit_wms_id, 'record', 'ep:document', 'erp/bitwms/record/index', 'ErpBitWmsRecord', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_wms_id IS NOT NULL AND @bit_record_menu_id IS NULL;
|
||||
SET @bit_record_menu_id := (
|
||||
SELECT id FROM system_menu
|
||||
WHERE parent_id = @bit_wms_id AND path = 'record' AND deleted = b'0'
|
||||
ORDER BY id LIMIT 1
|
||||
);
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品创建', 'erp:bit-wms-sample:create', 3, 10, @bit_sample_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-sample:create' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品更新', 'erp:bit-wms-sample:update', 3, 20, @bit_sample_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-sample:update' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '样品打印', 'erp:bit-wms-sample:print', 3, 30, @bit_sample_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_sample_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-sample:print' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '库位创建', 'erp:bit-wms-location:create', 3, 10, @bit_location_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_location_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-location:create' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '库位更新', 'erp:bit-wms-location:update', 3, 20, @bit_location_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_location_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-location:update' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '库位打印', 'erp:bit-wms-location:print', 3, 30, @bit_location_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_location_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-location:print' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '执行入库', 'erp:bit-wms-in:create', 3, 10, @bit_in_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_in_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-in:create' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '执行出库', 'erp:bit-wms-out:create', 3, 10, @bit_out_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_out_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-out:create' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '执行移库', 'erp:bit-wms-move:create', 3, 10, @bit_move_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_move_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-move:create' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '库存导出', 'erp:bit-wms-stock:export', 3, 20, @bit_stock_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_stock_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-stock:export' AND deleted = b'0');
|
||||
|
||||
SET @menu_seed := @menu_seed + 1;
|
||||
INSERT INTO system_menu
|
||||
(id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
|
||||
SELECT @menu_seed, '明细导出', 'erp:bit-wms-record:export', 3, 20, @bit_record_menu_id, '', '', '', NULL, 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE @bit_record_menu_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM system_menu WHERE permission = 'erp:bit-wms-record:export' AND deleted = b'0');
|
||||
|
||||
-- 5. 调拨项库区字段:支持 BIT 样品仓同仓不同库区移库
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'erp_stock_move_item' AND column_name = 'from_area_id') = 0,
|
||||
'ALTER TABLE erp_stock_move_item ADD COLUMN from_area_id bigint NULL COMMENT ''调出库区编号'' AFTER from_warehouse_id',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'erp_stock_move_item' AND column_name = 'from_area_name') = 0,
|
||||
'ALTER TABLE erp_stock_move_item ADD COLUMN from_area_name varchar(64) NULL COMMENT ''调出库区名称'' AFTER from_area_id',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'erp_stock_move_item' AND column_name = 'to_area_id') = 0,
|
||||
'ALTER TABLE erp_stock_move_item ADD COLUMN to_area_id bigint NULL COMMENT ''调入库区编号'' AFTER to_warehouse_id',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'erp_stock_move_item' AND column_name = 'to_area_name') = 0,
|
||||
'ALTER TABLE erp_stock_move_item ADD COLUMN to_area_name varchar(64) NULL COMMENT ''调入库区名称'' AFTER to_area_id',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@ -0,0 +1,29 @@
|
||||
-- BIT 样品仓打印模板类型补充 v3
|
||||
-- 说明:
|
||||
-- 1. 2026-06-22-bit-sample-wms.sql 已作为种子执行后,不再修改原文件。
|
||||
-- 2. 保留现有 print_template_type: 6 = 产线。
|
||||
-- 3. 本文件仅补充 BIT 样品标签、BIT 库位标签两个打印模板类型。
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 7, 'BIT样品标签', '7', 'print_template_type', 0, 'primary', '', 'qrcodeUrl,name,code,sampleCategory,customerName', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM system_dict_data
|
||||
WHERE dict_type = 'print_template_type' AND value = '7'
|
||||
);
|
||||
|
||||
UPDATE system_dict_data
|
||||
SET remark = 'qrcodeUrl,name,code,sampleCategory,customerName',
|
||||
updater = '1',
|
||||
update_time = NOW()
|
||||
WHERE dict_type = 'print_template_type'
|
||||
AND value = '7'
|
||||
AND deleted = b'0';
|
||||
|
||||
INSERT INTO system_dict_data
|
||||
(sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
SELECT 8, 'BIT库位标签', '8', 'print_template_type', 0, 'success', '', 'qrcodeUrl,name,code', '1', NOW(), '1', NOW(), b'0'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM system_dict_data
|
||||
WHERE dict_type = 'print_template_type' AND value = '8'
|
||||
);
|
||||
@ -0,0 +1,48 @@
|
||||
-- BIT 样品仓库位库存台账
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `erp_bit_wms_location_stock` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`product_id` bigint NOT NULL COMMENT '样品产品ID',
|
||||
`warehouse_id` bigint NOT NULL COMMENT '仓库ID',
|
||||
`area_id` bigint NULL COMMENT '库区ID',
|
||||
`location_id` bigint NOT NULL COMMENT '库位ID',
|
||||
`count` decimal(24, 6) NOT NULL DEFAULT 0.000000 COMMENT '当前库存数量',
|
||||
`unit_id` bigint NULL COMMENT '单位ID',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `uk_product_location` (`product_id`, `location_id`, `deleted`, `tenant_id`) USING BTREE,
|
||||
KEY `idx_location` (`location_id`) USING BTREE,
|
||||
KEY `idx_warehouse_area` (`warehouse_id`, `area_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BIT 样品库位库存';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `erp_bit_wms_location_stock_record` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`product_id` bigint NOT NULL COMMENT '样品产品ID',
|
||||
`warehouse_id` bigint NOT NULL COMMENT '仓库ID',
|
||||
`area_id` bigint NULL COMMENT '库区ID',
|
||||
`location_id` bigint NOT NULL COMMENT '库位ID',
|
||||
`count` decimal(24, 6) NOT NULL COMMENT '变动数量',
|
||||
`total_count` decimal(24, 6) NOT NULL COMMENT '变动后库位结存',
|
||||
`unit_id` bigint NULL COMMENT '单位ID',
|
||||
`biz_direction` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '业务方向',
|
||||
`biz_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '业务类型',
|
||||
`biz_id` bigint NULL COMMENT '业务单ID',
|
||||
`biz_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '业务单号',
|
||||
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '备注',
|
||||
`record_time` datetime NOT NULL COMMENT '操作时间',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `idx_product_location` (`product_id`, `location_id`) USING BTREE,
|
||||
KEY `idx_biz_no` (`biz_no`) USING BTREE,
|
||||
KEY `idx_record_time` (`record_time`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BIT 样品库位库存流水';
|
||||
@ -0,0 +1,85 @@
|
||||
package cn.iocoder.yudao.module.common.service.qrcordrecord;
|
||||
|
||||
import cn.iocoder.yudao.module.common.dal.dataobject.qrcoderecord.QrcodeRecordDO;
|
||||
import cn.iocoder.yudao.module.common.dal.mysql.qrcoderecord.QrcodeRecordMapper;
|
||||
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
|
||||
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class QrcodeRecordServiceImplTest {
|
||||
|
||||
private QrcodeRecordServiceImpl qrcodeRecordService;
|
||||
|
||||
@Mock
|
||||
private FileApi fileApi;
|
||||
@Mock
|
||||
private QrcodeRecordMapper qrcodeRecordMapper;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
qrcodeRecordService = new QrcodeRecordServiceImpl(Collections.emptyList());
|
||||
ReflectionTestUtils.setField(qrcodeRecordService, "fileApi", fileApi);
|
||||
ReflectionTestUtils.setField(qrcodeRecordService, "qrcodeRecordMapper", qrcodeRecordMapper);
|
||||
ReflectionTestUtils.setField(qrcodeRecordService, "width", 120);
|
||||
ReflectionTestUtils.setField(qrcodeRecordService, "height", 120);
|
||||
ReflectionTestUtils.setField(qrcodeRecordService, "defaultBucket", "common-qrcode");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateOrRefresh_whenQr_storesQrCodeType() throws Exception {
|
||||
Map<String, String> file = new HashMap<>();
|
||||
file.put("fileUrl", "https://file/qr.png");
|
||||
when(fileApi.createFile(any(), any(), any())).thenReturn(file);
|
||||
|
||||
qrcodeRecordService.generateOrRefresh(QrcodeBizTypeEnum.PRODUCT, 10L, "SP001", "DETAIL");
|
||||
|
||||
ArgumentCaptor<QrcodeRecordDO> recordCaptor = ArgumentCaptor.forClass(QrcodeRecordDO.class);
|
||||
verify(qrcodeRecordMapper).insert(recordCaptor.capture());
|
||||
assertEquals("QR", recordCaptor.getValue().getCodeType());
|
||||
}
|
||||
|
||||
@Test
|
||||
void selectQrcodeUrlByIdAndCodeAndType_filtersByCodeType() {
|
||||
QrcodeRecordDO qrRecord = new QrcodeRecordDO();
|
||||
qrRecord.setQrcodeFileUrl("https://file/qr.png");
|
||||
when(qrcodeRecordMapper.selectOne(any())).thenReturn(qrRecord);
|
||||
|
||||
String url = qrcodeRecordService.selectQrcodeUrlByIdAndCodeAndType(
|
||||
QrcodeBizTypeEnum.PRODUCT.getCode(), 10L, "SP001", CodeTypeEnum.QR);
|
||||
|
||||
assertEquals("https://file/qr.png", url);
|
||||
verify(qrcodeRecordMapper).selectOne(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void regenerateByCodeType_filtersExistingRecordByRequestedCodeType() throws Exception {
|
||||
Map<String, String> file = new HashMap<>();
|
||||
file.put("fileUrl", "https://file/qr.png");
|
||||
when(fileApi.createFile(any(), any(), any())).thenReturn(file);
|
||||
|
||||
qrcodeRecordService.regenerateByCodeType(QrcodeBizTypeEnum.PRODUCT, 10L, "SP001", "DETAIL", "QR");
|
||||
|
||||
verify(qrcodeRecordMapper).selectOne(any());
|
||||
|
||||
ArgumentCaptor<QrcodeRecordDO> recordCaptor = ArgumentCaptor.forClass(QrcodeRecordDO.class);
|
||||
verify(qrcodeRecordMapper).insert(recordCaptor.capture());
|
||||
assertEquals("QR", recordCaptor.getValue().getCodeType());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsInboundReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLabelRespVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRecordRespVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRespVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsMoveReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsOutboundReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsScanRespVO;
|
||||
import cn.iocoder.yudao.module.erp.service.bitwms.BitWmsService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - BIT 样品仓")
|
||||
@RestController
|
||||
@RequestMapping("/erp/bit-wms")
|
||||
@Validated
|
||||
public class BitWmsController {
|
||||
|
||||
@Resource
|
||||
private BitWmsService bitWmsService;
|
||||
|
||||
@PostMapping("/inbound")
|
||||
@Operation(summary = "BIT 样品入库")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-in:create')")
|
||||
public CommonResult<Long> inbound(@Valid @RequestBody BitWmsInboundReqVO reqVO) {
|
||||
return success(bitWmsService.inbound(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/outbound")
|
||||
@Operation(summary = "BIT 样品出库")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-out:create')")
|
||||
public CommonResult<Long> outbound(@Valid @RequestBody BitWmsOutboundReqVO reqVO) {
|
||||
return success(bitWmsService.outbound(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/move")
|
||||
@Operation(summary = "BIT 样品移库")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-move:create')")
|
||||
public CommonResult<Long> move(@Valid @RequestBody BitWmsMoveReqVO reqVO) {
|
||||
return success(bitWmsService.move(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/scan")
|
||||
@Operation(summary = "BIT 样品仓扫码")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-stock:query')")
|
||||
public CommonResult<BitWmsScanRespVO> scan(@RequestParam("code") String code) {
|
||||
return success(bitWmsService.scan(code));
|
||||
}
|
||||
|
||||
@GetMapping("/location-stock/page")
|
||||
@Operation(summary = "获得 BIT 样品库位库存分页")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-stock:query')")
|
||||
public CommonResult<PageResult<BitWmsLocationStockRespVO>> getLocationStockPage(
|
||||
@Valid BitWmsLocationStockPageReqVO pageReqVO) {
|
||||
return success(bitWmsService.getLocationStockPage(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/location-stock/count")
|
||||
@Operation(summary = "获得 BIT 样品当前库位库存")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-stock:query')")
|
||||
public CommonResult<BigDecimal> getLocationStockCount(@RequestParam("productId") Long productId,
|
||||
@RequestParam("locationId") Long locationId) {
|
||||
return success(bitWmsService.getLocationStockCount(productId, locationId));
|
||||
}
|
||||
|
||||
@GetMapping("/location-stock-record/page")
|
||||
@Operation(summary = "获得 BIT 样品库位流水分页")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-record:query')")
|
||||
public CommonResult<PageResult<BitWmsLocationStockRecordRespVO>> getLocationStockRecordPage(
|
||||
@Valid BitWmsLocationStockRecordPageReqVO pageReqVO) {
|
||||
return success(bitWmsService.getLocationStockRecordPage(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/sample-label")
|
||||
@Operation(summary = "获得样品标签打印数据")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-sample:print')")
|
||||
public CommonResult<BitWmsLabelRespVO> getSampleLabel(@RequestParam("productId") Long productId) {
|
||||
return success(bitWmsService.getSampleLabel(productId));
|
||||
}
|
||||
|
||||
@GetMapping("/location-label")
|
||||
@Operation(summary = "获得库位标签打印数据")
|
||||
@PreAuthorize("@ss.hasPermission('erp:bit-wms-location:print')")
|
||||
public CommonResult<BitWmsLabelRespVO> getLocationLabel(@RequestParam("locationId") Long locationId) {
|
||||
return success(bitWmsService.getLocationLabel(locationId));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品仓入库 Request VO")
|
||||
@Data
|
||||
public class BitWmsInboundReqVO {
|
||||
|
||||
@Schema(description = "样品产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "样品产品ID不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "仓库ID", example = "20")
|
||||
private Long warehouseId;
|
||||
|
||||
@Schema(description = "库区ID", example = "30")
|
||||
private Long areaId;
|
||||
|
||||
@Schema(description = "库位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "40")
|
||||
@NotNull(message = "库位不能为空")
|
||||
private Long locationId;
|
||||
|
||||
@Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "入库数量不能为空")
|
||||
@DecimalMin(value = "0.000001", message = "入库数量必须大于 0")
|
||||
private BigDecimal count;
|
||||
|
||||
@Schema(description = "单位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
|
||||
@NotNull(message = "单位不能为空")
|
||||
private Long unitId;
|
||||
|
||||
@Schema(description = "供应商ID", example = "1001")
|
||||
private Long supplierId;
|
||||
|
||||
@Schema(description = "备注", example = "first shelf")
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品库位库存分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BitWmsLocationStockPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "样品产品ID", example = "10")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "仓库ID", example = "20")
|
||||
private Long warehouseId;
|
||||
|
||||
@Schema(description = "库区ID", example = "30")
|
||||
private Long areaId;
|
||||
|
||||
@Schema(description = "库位ID", example = "40")
|
||||
private Long locationId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品库位流水分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BitWmsLocationStockRecordPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "样品产品ID", example = "10")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "仓库ID", example = "20")
|
||||
private Long warehouseId;
|
||||
|
||||
@Schema(description = "库区ID", example = "30")
|
||||
private Long areaId;
|
||||
|
||||
@Schema(description = "库位ID", example = "40")
|
||||
private Long locationId;
|
||||
|
||||
@Schema(description = "业务单号", example = "QTRK20260623001")
|
||||
private String bizNo;
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品库位流水 Response VO")
|
||||
@Data
|
||||
public class BitWmsLocationStockRecordRespVO {
|
||||
|
||||
private Long id;
|
||||
private Long productId;
|
||||
private String productName;
|
||||
private String barCode;
|
||||
private Long warehouseId;
|
||||
private String warehouseName;
|
||||
private Long areaId;
|
||||
private String areaName;
|
||||
private Long locationId;
|
||||
private String locationCode;
|
||||
private String locationName;
|
||||
private BigDecimal count;
|
||||
private BigDecimal totalCount;
|
||||
private Long unitId;
|
||||
private String unitName;
|
||||
private String bizDirection;
|
||||
private String bizType;
|
||||
private Long bizId;
|
||||
private String bizNo;
|
||||
private String remark;
|
||||
private String creator;
|
||||
private String creatorName;
|
||||
private LocalDateTime recordTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品库位库存 Response VO")
|
||||
@Data
|
||||
public class BitWmsLocationStockRespVO {
|
||||
|
||||
private Long id;
|
||||
private Long productId;
|
||||
private String productName;
|
||||
private String barCode;
|
||||
private String sampleCategory;
|
||||
private String customerName;
|
||||
private Long warehouseId;
|
||||
private String warehouseName;
|
||||
private Long areaId;
|
||||
private String areaName;
|
||||
private Long locationId;
|
||||
private String locationCode;
|
||||
private String locationName;
|
||||
private BigDecimal count;
|
||||
private Long unitId;
|
||||
private String unitName;
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品仓移库 Request VO")
|
||||
@Data
|
||||
public class BitWmsMoveReqVO {
|
||||
|
||||
@Schema(description = "样品产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "样品产品ID不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "调出库位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "40")
|
||||
@NotNull(message = "调出库位不能为空")
|
||||
private Long fromLocationId;
|
||||
|
||||
@Schema(description = "调入库位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "41")
|
||||
@NotNull(message = "调入库位不能为空")
|
||||
private Long toLocationId;
|
||||
|
||||
@Schema(description = "调出仓库ID", example = "20")
|
||||
private Long fromWarehouseId;
|
||||
|
||||
@Schema(description = "调出库区ID", example = "30")
|
||||
private Long fromAreaId;
|
||||
|
||||
@Schema(description = "调入仓库ID", example = "20")
|
||||
private Long toWarehouseId;
|
||||
|
||||
@Schema(description = "调入库区ID", example = "31")
|
||||
private Long toAreaId;
|
||||
|
||||
@Schema(description = "移库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "移库数量不能为空")
|
||||
@DecimalMin(value = "0.000001", message = "移库数量必须大于 0")
|
||||
private BigDecimal count;
|
||||
|
||||
@Schema(description = "备注", example = "上架调整")
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - BIT 样品仓出库 Request VO")
|
||||
@Data
|
||||
public class BitWmsOutboundReqVO {
|
||||
|
||||
@Schema(description = "样品产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "样品产品ID不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "仓库ID", example = "20")
|
||||
private Long warehouseId;
|
||||
|
||||
@Schema(description = "库区ID", example = "30")
|
||||
private Long areaId;
|
||||
|
||||
@Schema(description = "库位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "40")
|
||||
@NotNull(message = "库位不能为空")
|
||||
private Long locationId;
|
||||
|
||||
@Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "出库数量不能为空")
|
||||
@DecimalMin(value = "0.000001", message = "出库数量必须大于 0")
|
||||
private BigDecimal count;
|
||||
|
||||
@Schema(description = "出库原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "TEST")
|
||||
@NotBlank(message = "出库原因不能为空")
|
||||
private String outReason;
|
||||
|
||||
@Schema(description = "备注", example = "测试出库")
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package cn.iocoder.yudao.module.erp.dal.dataobject.bitwms;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* BIT 样品库位库存 DO
|
||||
*/
|
||||
@TableName("erp_bit_wms_location_stock")
|
||||
@KeySequence("erp_bit_wms_location_stock_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BitWmsLocationStockDO extends BaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private Long productId;
|
||||
|
||||
private Long warehouseId;
|
||||
|
||||
private Long areaId;
|
||||
|
||||
private Long locationId;
|
||||
|
||||
private BigDecimal count;
|
||||
|
||||
private Long unitId;
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.iocoder.yudao.module.erp.dal.dataobject.bitwms;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* BIT 样品库位库存流水 DO
|
||||
*/
|
||||
@TableName("erp_bit_wms_location_stock_record")
|
||||
@KeySequence("erp_bit_wms_location_stock_record_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BitWmsLocationStockRecordDO extends BaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private Long productId;
|
||||
|
||||
private Long warehouseId;
|
||||
|
||||
private Long areaId;
|
||||
|
||||
private Long locationId;
|
||||
|
||||
private BigDecimal count;
|
||||
|
||||
private BigDecimal totalCount;
|
||||
|
||||
private Long unitId;
|
||||
|
||||
private String bizDirection;
|
||||
|
||||
private String bizType;
|
||||
|
||||
private Long bizId;
|
||||
|
||||
private String bizNo;
|
||||
|
||||
private String remark;
|
||||
|
||||
private LocalDateTime recordTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package cn.iocoder.yudao.module.erp.dal.mysql.bitwms;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.bitwms.BitWmsLocationStockDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Mapper
|
||||
public interface BitWmsLocationStockMapper extends BaseMapperX<BitWmsLocationStockDO> {
|
||||
|
||||
default PageResult<BitWmsLocationStockDO> selectPage(BitWmsLocationStockPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BitWmsLocationStockDO>()
|
||||
.eqIfPresent(BitWmsLocationStockDO::getProductId, reqVO.getProductId())
|
||||
.eqIfPresent(BitWmsLocationStockDO::getWarehouseId, reqVO.getWarehouseId())
|
||||
.eqIfPresent(BitWmsLocationStockDO::getAreaId, reqVO.getAreaId())
|
||||
.eqIfPresent(BitWmsLocationStockDO::getLocationId, reqVO.getLocationId())
|
||||
.ne(BitWmsLocationStockDO::getCount, BigDecimal.ZERO)
|
||||
.orderByDesc(BitWmsLocationStockDO::getId));
|
||||
}
|
||||
|
||||
default BitWmsLocationStockDO selectByProductIdAndLocationId(Long productId, Long locationId) {
|
||||
return selectOne(new LambdaQueryWrapperX<BitWmsLocationStockDO>()
|
||||
.eq(BitWmsLocationStockDO::getProductId, productId)
|
||||
.eq(BitWmsLocationStockDO::getLocationId, locationId));
|
||||
}
|
||||
|
||||
default int updateCountIncrement(Long id, BigDecimal count, boolean negativeEnable) {
|
||||
if (count == null || count.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return 0;
|
||||
}
|
||||
LambdaUpdateWrapper<BitWmsLocationStockDO> updateWrapper = new LambdaUpdateWrapper<BitWmsLocationStockDO>()
|
||||
.eq(BitWmsLocationStockDO::getId, id);
|
||||
if (count.compareTo(BigDecimal.ZERO) > 0) {
|
||||
updateWrapper.setSql("count = count + " + count);
|
||||
} else {
|
||||
if (!negativeEnable) {
|
||||
updateWrapper.ge(BitWmsLocationStockDO::getCount, count.abs());
|
||||
}
|
||||
updateWrapper.setSql("count = count - " + count.abs());
|
||||
}
|
||||
return update(null, updateWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.erp.dal.mysql.bitwms;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.bitwms.BitWmsLocationStockRecordDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BitWmsLocationStockRecordMapper extends BaseMapperX<BitWmsLocationStockRecordDO> {
|
||||
|
||||
default PageResult<BitWmsLocationStockRecordDO> selectPage(BitWmsLocationStockRecordPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BitWmsLocationStockRecordDO>()
|
||||
.eqIfPresent(BitWmsLocationStockRecordDO::getProductId, reqVO.getProductId())
|
||||
.eqIfPresent(BitWmsLocationStockRecordDO::getWarehouseId, reqVO.getWarehouseId())
|
||||
.eqIfPresent(BitWmsLocationStockRecordDO::getAreaId, reqVO.getAreaId())
|
||||
.eqIfPresent(BitWmsLocationStockRecordDO::getLocationId, reqVO.getLocationId())
|
||||
.likeIfPresent(BitWmsLocationStockRecordDO::getBizNo, reqVO.getBizNo())
|
||||
.orderByDesc(BitWmsLocationStockRecordDO::getId));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.erp.handler;
|
||||
|
||||
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation.WarehouseLocationMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Component
|
||||
public class WarehouseLocationQrcodeBizHandler implements QrcodeBizHandler {
|
||||
|
||||
@Resource
|
||||
private WarehouseLocationMapper warehouseLocationMapper;
|
||||
|
||||
@Override
|
||||
public String getBizType() {
|
||||
return QrcodeBizTypeEnum.WAREHOUSE_LOCATION.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long id) {
|
||||
return warehouseLocationMapper.selectById(id) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildDeepLink(Long id) {
|
||||
return "besure://warehouse-location/detail?id=" + id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildH5Path(Long id) {
|
||||
return "/pages_function/pages/bitWms/stock?locationId=" + id;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.erp.service.bitwms;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsInboundReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLabelRespVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRecordRespVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsLocationStockRespVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsMoveReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsOutboundReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.bitwms.vo.BitWmsScanRespVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import javax.validation.Valid;
|
||||
|
||||
public interface BitWmsService {
|
||||
|
||||
Long inbound(@Valid BitWmsInboundReqVO reqVO);
|
||||
|
||||
Long outbound(@Valid BitWmsOutboundReqVO reqVO);
|
||||
|
||||
Long move(@Valid BitWmsMoveReqVO reqVO);
|
||||
|
||||
BitWmsScanRespVO scan(String code);
|
||||
|
||||
PageResult<BitWmsLocationStockRespVO> getLocationStockPage(@Valid BitWmsLocationStockPageReqVO pageReqVO);
|
||||
|
||||
PageResult<BitWmsLocationStockRecordRespVO> getLocationStockRecordPage(@Valid BitWmsLocationStockRecordPageReqVO pageReqVO);
|
||||
|
||||
BigDecimal getLocationStockCount(Long productId, Long locationId);
|
||||
|
||||
BitWmsLabelRespVO getSampleLabel(Long productId);
|
||||
|
||||
BitWmsLabelRespVO getLocationLabel(Long locationId);
|
||||
}
|
||||
@ -0,0 +1,151 @@
|
||||
package cn.iocoder.yudao.module.erp.service.product;
|
||||
|
||||
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
|
||||
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.productpackagingschemerel.ProductPackagingSchemeRelMapper;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.productsupplierrel.ProductSupplierRelMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* {@link ErpProductServiceImpl} 的单元测试类
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ErpProductServiceImplTest {
|
||||
|
||||
@InjectMocks
|
||||
private ErpProductServiceImpl productService;
|
||||
|
||||
@Mock
|
||||
private ErpProductMapper productMapper;
|
||||
@Mock
|
||||
private ErpProductCategoryMapper productCategoryMapper;
|
||||
@Mock
|
||||
private ErpProductUnitService productUnitService;
|
||||
@Mock
|
||||
private QrcodeRecordService qrcodeService;
|
||||
@Mock
|
||||
private AutoCodeUtil autoCodeUtil;
|
||||
@Mock
|
||||
private ProductPackagingSchemeRelMapper productPackagingSchemeRelMapper;
|
||||
@Mock
|
||||
private ProductSupplierRelMapper productSupplierRelMapper;
|
||||
|
||||
@Test
|
||||
void createProduct_whenBitSampleAndNoCode_generatesSampleCodeAndStoresMetadata() throws Exception {
|
||||
ProductSaveReqVO reqVO = new ProductSaveReqVO();
|
||||
reqVO.setName("BIT 样品");
|
||||
reqVO.setBarCode(null);
|
||||
reqVO.setIsSample(true);
|
||||
reqVO.setSampleCategory("CUSTOMER_SAMPLE");
|
||||
reqVO.setBizUnit("BIT");
|
||||
reqVO.setCustomerId(1001L);
|
||||
reqVO.setCustomerName("ACME HK");
|
||||
reqVO.setCategoryId(10L);
|
||||
reqVO.setUnitId(20L);
|
||||
reqVO.setStatus(0);
|
||||
reqVO.setStandard("STD-1");
|
||||
|
||||
ErpProductUnitDO unit = new ErpProductUnitDO();
|
||||
unit.setId(20L);
|
||||
unit.setName("PCS");
|
||||
when(productUnitService.getProductUnit(20L)).thenReturn(unit);
|
||||
|
||||
ErpProductCategoryDO category = new ErpProductCategoryDO();
|
||||
category.setId(10L);
|
||||
category.setName("测试分类");
|
||||
category.setCode("CAT");
|
||||
when(productCategoryMapper.selectById(10L)).thenReturn(category);
|
||||
|
||||
when(productMapper.selectProductExist(any(ErpProductDO.class))).thenReturn(false);
|
||||
when(autoCodeUtil.genSerialCode("BIT_SAMPLE_CODE", null)).thenReturn("SP202606220001");
|
||||
when(autoCodeUtil.queryCodeType("BIT_SAMPLE_CODE")).thenReturn(CodeTypeEnum.QR);
|
||||
when(productMapper.insert(any(ErpProductDO.class))).thenAnswer(invocation -> {
|
||||
ErpProductDO product = invocation.getArgument(0);
|
||||
product.setId(100L);
|
||||
return 1;
|
||||
});
|
||||
|
||||
Long id = productService.createProduct(reqVO);
|
||||
|
||||
assertEquals(100L, id);
|
||||
ArgumentCaptor<ErpProductDO> productCaptor = ArgumentCaptor.forClass(ErpProductDO.class);
|
||||
verify(productMapper).insert(productCaptor.capture());
|
||||
ErpProductDO product = productCaptor.getValue();
|
||||
assertTrue(product.getIsSample());
|
||||
assertEquals("CUSTOMER_SAMPLE", product.getSampleCategory());
|
||||
assertEquals("BIT", product.getBizUnit());
|
||||
assertEquals(1001L, product.getCustomerId());
|
||||
assertEquals("ACME HK", product.getCustomerName());
|
||||
assertEquals("SP202606220001", product.getBarCode());
|
||||
|
||||
verify(qrcodeService).generateOrRefresh(
|
||||
eq(QrcodeBizTypeEnum.PRODUCT),
|
||||
eq(100L),
|
||||
eq("SP202606220001"),
|
||||
eq("DETAIL"),
|
||||
eq(CodeTypeEnum.QR));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProduct_whenBitSampleRuleIsQr_returnsQrUrl() {
|
||||
ErpProductDO product = new ErpProductDO();
|
||||
product.setId(100L);
|
||||
product.setName("BIT 样品");
|
||||
product.setBarCode("SP202606220001");
|
||||
product.setIsSample(true);
|
||||
|
||||
when(productMapper.selectById(100L)).thenReturn(product);
|
||||
when(autoCodeUtil.queryCodeType("BIT_SAMPLE_CODE")).thenReturn(CodeTypeEnum.QR);
|
||||
when(qrcodeService.selectQrcodeUrlByIdAndCodeAndType(
|
||||
QrcodeBizTypeEnum.PRODUCT.getCode(), 100L, "SP202606220001", CodeTypeEnum.QR))
|
||||
.thenReturn("https://file/sample-qr.png");
|
||||
when(productMapper.selectDevicesByProductId(100L)).thenReturn(Collections.emptyList());
|
||||
when(productMapper.selectMoldsByProductId(100L)).thenReturn(Collections.emptyList());
|
||||
when(productPackagingSchemeRelMapper.selectListByProductId(100L)).thenReturn(Collections.emptyList());
|
||||
when(productSupplierRelMapper.selectListByProductId(100L)).thenReturn(Collections.emptyList());
|
||||
|
||||
assertEquals("https://file/sample-qr.png", productService.getProduct(100L).getQrcodeUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void regenerateCode_whenBitSampleRuleIsQr_regeneratesQr() throws Exception {
|
||||
ErpProductDO product = new ErpProductDO();
|
||||
product.setId(100L);
|
||||
product.setBarCode("SP202606220001");
|
||||
product.setIsSample(true);
|
||||
|
||||
when(productMapper.selectById(100L)).thenReturn(product);
|
||||
when(autoCodeUtil.queryCodeType("BIT_SAMPLE_CODE")).thenReturn(CodeTypeEnum.QR);
|
||||
|
||||
productService.regenerateCode(100L, "SP202606220001");
|
||||
|
||||
verify(qrcodeService).regenerateByCodeType(
|
||||
QrcodeBizTypeEnum.PRODUCT,
|
||||
100L,
|
||||
"SP202606220001",
|
||||
"DETAIL",
|
||||
CodeTypeEnum.QR.getCode());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.erp.service.warehouselocation;
|
||||
|
||||
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
|
||||
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.WarehouseLocationSaveReqVO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation.WarehouseLocationDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.warehousearea.WarehouseAreaMapper;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation.WarehouseLocationMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* {@link WarehouseLocationServiceImpl} 的单元测试类
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class WarehouseLocationServiceImplTest {
|
||||
|
||||
@InjectMocks
|
||||
private WarehouseLocationServiceImpl warehouseLocationService;
|
||||
|
||||
@Mock
|
||||
private WarehouseLocationMapper warehouseLocationMapper;
|
||||
@Mock
|
||||
private WarehouseAreaMapper warehouseAreaMapper;
|
||||
@Mock
|
||||
private AutoCodeUtil autoCodeUtil;
|
||||
@Mock
|
||||
private QrcodeRecordService qrcodeRecordService;
|
||||
|
||||
@Test
|
||||
void createWarehouseLocation_generatesQrcodeRecord() throws Exception {
|
||||
WarehouseLocationSaveReqVO reqVO = new WarehouseLocationSaveReqVO();
|
||||
reqVO.setCode("A1");
|
||||
reqVO.setName("A1");
|
||||
reqVO.setWarehouseId(1L);
|
||||
reqVO.setAreaId(1L);
|
||||
reqVO.setAllowProductMix(false);
|
||||
reqVO.setAllowBatchMix(false);
|
||||
reqVO.setStatus(0);
|
||||
|
||||
WarehouseAreaDO area = new WarehouseAreaDO();
|
||||
area.setId(1L);
|
||||
area.setWarehouseId(1L);
|
||||
when(warehouseAreaMapper.selectById(1L)).thenReturn(area);
|
||||
when(autoCodeUtil.queryCodeType("BIT_WAREHOUSE_LOCATION_CODE")).thenReturn(CodeTypeEnum.QR);
|
||||
when(warehouseLocationMapper.insert(any(WarehouseLocationDO.class))).thenAnswer(invocation -> {
|
||||
WarehouseLocationDO location = invocation.getArgument(0);
|
||||
location.setId(100L);
|
||||
return 1;
|
||||
});
|
||||
|
||||
Long id = warehouseLocationService.createWarehouseLocation(reqVO);
|
||||
|
||||
assertEquals(100L, id);
|
||||
verify(qrcodeRecordService).generateOrRefresh(
|
||||
eq(QrcodeBizTypeEnum.WAREHOUSE_LOCATION),
|
||||
eq(100L),
|
||||
eq("A1"),
|
||||
eq("DETAIL"),
|
||||
eq(CodeTypeEnum.QR));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue