chore: sync codebase with upstream
Align origin/main with upstream/main (GitHub). The two branches diverged due to pre-rebase vs post-rebase merge commits for the k8s-amd64-dockerfiles feature. Includes: multi-stage Go compilation Dockerfiles, pan-bolt inventory features, CRM relations, Excel import tooling, proto/gRPC updates, migration scripts, and tools/ directory. Excludes deploy/bin/ pre-compiled binaries (arm64, not needed for amd64 K3s cluster; builds use multi-stage Dockerfiles now).
This commit is contained in:
parent
c5ab2279c0
commit
379fb28d92
30
.gitignore
vendored
30
.gitignore
vendored
@ -1,6 +1,6 @@
|
|||||||
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/go,macos,visualstudiocode
|
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,go,macos
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go,macos,visualstudiocode
|
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,linux,go,macos
|
||||||
|
|
||||||
### Go ###
|
### Go ###
|
||||||
# If you prefer the allow list template instead of the deny list, see community template:
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
@ -25,6 +25,21 @@
|
|||||||
# Go workspace file
|
# Go workspace file
|
||||||
go.work
|
go.work
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
### macOS ###
|
### macOS ###
|
||||||
# General
|
# General
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@ -77,16 +92,9 @@ Temporary Items
|
|||||||
.history
|
.history
|
||||||
.ionide
|
.ionide
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/go,macos,visualstudiocode
|
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,go,macos
|
||||||
|
|
||||||
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
||||||
|
|
||||||
# MySQL data directory (contains binaries, certs, and runtime state)
|
# Local runtime data and certificates
|
||||||
data/
|
data/
|
||||||
|
|
||||||
# Environment and secrets
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
*.pem
|
|
||||||
deploy/bin/
|
|
||||||
worker/graphsync/go.sum
|
|
||||||
|
|||||||
@ -11,5 +11,6 @@ RUN apk add --no-cache ca-certificates tzdata
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /server ./gateway
|
COPY --from=builder /server ./gateway
|
||||||
COPY deploy/etc/gateway.yaml etc/gateway.yaml
|
COPY deploy/etc/gateway.yaml etc/gateway.yaml
|
||||||
|
COPY deploy/tools/ tools/
|
||||||
EXPOSE 8888
|
EXPOSE 8888
|
||||||
CMD ["./gateway", "-f", "etc/gateway.yaml"]
|
CMD ["./gateway", "-f", "etc/gateway.yaml"]
|
||||||
|
|||||||
@ -62,10 +62,10 @@ services:
|
|||||||
- --name=default
|
- --name=default
|
||||||
- --data-dir=/etcd-data
|
- --data-dir=/etcd-data
|
||||||
- --listen-client-urls=http://0.0.0.0:2379
|
- --listen-client-urls=http://0.0.0.0:2379
|
||||||
- --advertise-client-urls=http://etcd:2379
|
- --advertise-client-urls=http://127.0.0.1:2379
|
||||||
- --listen-peer-urls=http://0.0.0.0:2380
|
- --listen-peer-urls=http://0.0.0.0:2380
|
||||||
- --initial-advertise-peer-urls=http://etcd:2380
|
- --initial-advertise-peer-urls=http://127.0.0.1:2380
|
||||||
- --initial-cluster=default=http://etcd:2380
|
- --initial-cluster=default=http://127.0.0.1:2380
|
||||||
- --initial-cluster-state=new
|
- --initial-cluster-state=new
|
||||||
ports:
|
ports:
|
||||||
- "2379:2379"
|
- "2379:2379"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
Name: gateway-api
|
Name: gateway-api
|
||||||
Host: 0.0.0.0
|
Host: 0.0.0.0
|
||||||
Port: 8888
|
Port: 8888
|
||||||
|
Timeout: 120000
|
||||||
|
|
||||||
Auth:
|
Auth:
|
||||||
AccessSecret: muyu-wms-jwt-secret-key-2026
|
AccessSecret: muyu-wms-jwt-secret-key-2026
|
||||||
@ -23,6 +24,7 @@ InventoryRpc:
|
|||||||
- etcd:2379
|
- etcd:2379
|
||||||
Key: inventory.rpc
|
Key: inventory.rpc
|
||||||
NonBlock: true
|
NonBlock: true
|
||||||
|
Timeout: 60000
|
||||||
|
|
||||||
Log:
|
Log:
|
||||||
ServiceName: gateway-api
|
ServiceName: gateway-api
|
||||||
|
|||||||
@ -334,27 +334,27 @@ CREATE TABLE `casbin_rule` (
|
|||||||
-- ==================== Initial Data ====================
|
-- ==================== Initial Data ====================
|
||||||
|
|
||||||
-- Default admin user (password: admin123, bcrypt hashed)
|
-- Default admin user (password: admin123, bcrypt hashed)
|
||||||
INSERT INTO `sys_user` (`user_id`, `username`, `password`, `salt`, `real_name`, `status`)
|
INSERT IGNORE INTO `sys_user` (`user_id`, `username`, `password`, `salt`, `real_name`, `status`)
|
||||||
VALUES ('u_admin_001', 'admin', '$2a$10$S5XPWRXUnexAt9KJw2CefeHMa6aude7j5dm5qgWM1YMQAAwRgsGXa', 'bcrypt', 'System Admin', 1);
|
VALUES ('u_admin_001', 'admin', '$2a$10$S5XPWRXUnexAt9KJw2CefeHMa6aude7j5dm5qgWM1YMQAAwRgsGXa', 'bcrypt', 'System Admin', 1);
|
||||||
|
|
||||||
-- Default tenant and mapping
|
-- Default tenant and mapping
|
||||||
INSERT INTO `crm_tenant` (`tenant_id`, `tenant_name`, `tenant_code`, `status`)
|
INSERT IGNORE INTO `crm_tenant` (`tenant_id`, `tenant_name`, `tenant_code`, `status`)
|
||||||
VALUES ('t_default_001', '默认租户', 'DEFAULT', 1);
|
VALUES ('t_default_001', '默认租户', 'DEFAULT', 1);
|
||||||
|
|
||||||
INSERT INTO `crm_tenant_user` (`tenant_user_id`, `tenant_id`, `user_id`, `is_primary`, `status`)
|
INSERT IGNORE INTO `crm_tenant_user` (`tenant_user_id`, `tenant_id`, `user_id`, `is_primary`, `status`)
|
||||||
VALUES ('tu_001', 't_default_001', 'u_admin_001', 1, 1);
|
VALUES ('tu_001', 't_default_001', 'u_admin_001', 1, 1);
|
||||||
|
|
||||||
-- Default roles
|
-- Default roles
|
||||||
INSERT INTO `sys_role` (`role_id`, `role_name`, `role_key`, `role_desc`, `sort_order`, `status`) VALUES
|
INSERT IGNORE INTO `sys_role` (`role_id`, `role_name`, `role_key`, `role_desc`, `sort_order`, `status`) VALUES
|
||||||
('r_001', '系统管理员', 'admin', 'Full system access', 1, 1),
|
('r_001', '系统管理员', 'admin', 'Full system access', 1, 1),
|
||||||
('r_002', '仓库管理员', 'warehouse', 'Warehouse management access', 2, 1),
|
('r_002', '仓库管理员', 'warehouse', 'Warehouse management access', 2, 1),
|
||||||
('r_003', '普通用户', 'user', 'Basic read access', 3, 1);
|
('r_003', '普通用户', 'user', 'Basic read access', 3, 1);
|
||||||
|
|
||||||
-- Assign admin role to admin user
|
-- Assign admin role to admin user
|
||||||
INSERT INTO `sys_user_role` (`user_id`, `role_id`) VALUES ('u_admin_001', 'r_001');
|
INSERT IGNORE INTO `sys_user_role` (`user_id`, `role_id`) VALUES ('u_admin_001', 'r_001');
|
||||||
|
|
||||||
-- Default menus
|
-- Default menus
|
||||||
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `menu_name`, `menu_type`, `path`, `component`, `permission`, `icon`, `sort_order`, `visible`, `status`) VALUES
|
INSERT IGNORE INTO `sys_menu` (`menu_id`, `parent_id`, `menu_name`, `menu_type`, `path`, `component`, `permission`, `icon`, `sort_order`, `visible`, `status`) VALUES
|
||||||
-- Dashboard
|
-- Dashboard
|
||||||
('m_001', '', '首页', 1, '/dashboard', './Dashboard', '', 'DashboardOutlined', 1, 1, 1),
|
('m_001', '', '首页', 1, '/dashboard', './Dashboard', '', 'DashboardOutlined', 1, 1, 1),
|
||||||
-- System Management
|
-- System Management
|
||||||
@ -374,26 +374,26 @@ INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `menu_name`, `menu_type`, `path`
|
|||||||
('m_206', 'm_200', 'Excel导入', 2, '/inventory/import', './Inventory/Import', 'inventory:import:exec', 'ImportOutlined', 6, 1, 1);
|
('m_206', 'm_200', 'Excel导入', 2, '/inventory/import', './Inventory/Import', 'inventory:import:exec', 'ImportOutlined', 6, 1, 1);
|
||||||
|
|
||||||
-- CRM menus
|
-- CRM menus
|
||||||
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `menu_name`, `menu_type`, `path`, `component`, `permission`, `icon`, `sort_order`, `visible`, `status`) VALUES
|
INSERT IGNORE INTO `sys_menu` (`menu_id`, `parent_id`, `menu_name`, `menu_type`, `path`, `component`, `permission`, `icon`, `sort_order`, `visible`, `status`) VALUES
|
||||||
('m_300', '', '客户关系', 1, '/crm', '', '', 'NodeIndexOutlined', 300, 1, 1),
|
('m_300', '', '客户关系', 1, '/crm', '', '', 'NodeIndexOutlined', 300, 1, 1),
|
||||||
('m_301', 'm_300', '上下游关系', 2, '/crm/relations', './CRM/Relations', 'crm:relation:list', 'ApartmentOutlined', 1, 1, 1);
|
('m_301', 'm_300', '上下游关系', 2, '/crm/relations', './CRM/Relations', 'crm:relation:list', 'ApartmentOutlined', 1, 1, 1);
|
||||||
|
|
||||||
-- Assign all menus to admin role
|
-- Assign all menus to admin role
|
||||||
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`)
|
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`)
|
||||||
SELECT 'r_001', `menu_id` FROM `sys_menu`;
|
SELECT 'r_001', `menu_id` FROM `sys_menu`;
|
||||||
|
|
||||||
-- Assign inventory menus to warehouse role
|
-- Assign inventory menus to warehouse role
|
||||||
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
|
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
|
||||||
('r_002', 'm_001'),
|
('r_002', 'm_001'),
|
||||||
('r_002', 'm_200'), ('r_002', 'm_201'), ('r_002', 'm_202'),
|
('r_002', 'm_200'), ('r_002', 'm_201'), ('r_002', 'm_202'),
|
||||||
('r_002', 'm_203'), ('r_002', 'm_204'), ('r_002', 'm_205'), ('r_002', 'm_206');
|
('r_002', 'm_203'), ('r_002', 'm_204'), ('r_002', 'm_205'), ('r_002', 'm_206');
|
||||||
|
|
||||||
-- Assign CRM menus to admin role
|
-- Assign CRM menus to admin role
|
||||||
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
|
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
|
||||||
('r_001', 'm_300'), ('r_001', 'm_301');
|
('r_001', 'm_300'), ('r_001', 'm_301');
|
||||||
|
|
||||||
-- Default Casbin policies
|
-- Default Casbin policies
|
||||||
INSERT INTO `casbin_rule` (`ptype`, `v0`, `v1`, `v2`) VALUES
|
INSERT IGNORE INTO `casbin_rule` (`ptype`, `v0`, `v1`, `v2`) VALUES
|
||||||
('p', 'admin', '/api/v1/*', '*'),
|
('p', 'admin', '/api/v1/*', '*'),
|
||||||
('p', 'warehouse', '/api/v1/auth/*', '*'),
|
('p', 'warehouse', '/api/v1/auth/*', '*'),
|
||||||
('p', 'warehouse', '/api/v1/inventory/*', '*'),
|
('p', 'warehouse', '/api/v1/inventory/*', '*'),
|
||||||
@ -404,7 +404,7 @@ INSERT INTO `casbin_rule` (`ptype`, `v0`, `v1`, `v2`) VALUES
|
|||||||
('p', 'user', '/api/v1/inventory/stocks/*', 'GET');
|
('p', 'user', '/api/v1/inventory/stocks/*', 'GET');
|
||||||
|
|
||||||
-- Default system configs
|
-- Default system configs
|
||||||
INSERT INTO `sys_config` (`config_id`, `config_key`, `config_value`, `config_name`, `config_group`, `remark`) VALUES
|
INSERT IGNORE INTO `sys_config` (`config_id`, `config_key`, `config_value`, `config_name`, `config_group`, `remark`) VALUES
|
||||||
('c_001', 'sys_name', 'muyuqingfeng仓储管理系统', 'System Name', 'basic', 'System display name'),
|
('c_001', 'sys_name', 'muyuqingfeng仓储管理系统', 'System Name', 'basic', 'System display name'),
|
||||||
('c_002', 'sys_logo', '', 'System Logo', 'basic', 'System logo URL'),
|
('c_002', 'sys_logo', '', 'System Logo', 'basic', 'System logo URL'),
|
||||||
('c_003', 'upload_max_size', '10', 'Upload Max Size (MB)', 'upload', 'Maximum file upload size'),
|
('c_003', 'upload_max_size', '10', 'Upload Max Size (MB)', 'upload', 'Maximum file upload size'),
|
||||||
|
|||||||
44
deploy/mysql/migrations/20260403_add_pan_and_bolt.sql
Normal file
44
deploy/mysql/migrations/20260403_add_pan_and_bolt.sql
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
-- Three-layer inventory model: Product -> Pan(盘) -> Bolt(匹)
|
||||||
|
|
||||||
|
-- Pan table: each row = one physical pan/roll, belongs to a product
|
||||||
|
CREATE TABLE IF NOT EXISTS `inv_product_pan` (
|
||||||
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`pan_id` VARCHAR(32) NOT NULL,
|
||||||
|
`product_id` VARCHAR(32) NOT NULL,
|
||||||
|
`name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'pan label: A, B, C...',
|
||||||
|
`position` VARCHAR(100) NOT NULL DEFAULT '' COMMENT 'physical location: Shanghai, Nanjing...',
|
||||||
|
`sort_order` INT NOT NULL DEFAULT 0,
|
||||||
|
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||||
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uk_pan_id` (`pan_id`),
|
||||||
|
KEY `idx_product_id` (`product_id`),
|
||||||
|
KEY `idx_tenant_id` (`tenant_id`),
|
||||||
|
KEY `idx_position` (`position`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Bolt table: each row = one physical bolt/piece, belongs to a pan
|
||||||
|
CREATE TABLE IF NOT EXISTS `inv_product_bolt` (
|
||||||
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`bolt_id` VARCHAR(32) NOT NULL,
|
||||||
|
`pan_id` VARCHAR(32) NOT NULL COMMENT 'FK to inv_product_pan',
|
||||||
|
`length_m` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 'length in meters',
|
||||||
|
`sort_order` INT NOT NULL DEFAULT 0,
|
||||||
|
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||||
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uk_bolt_id` (`bolt_id`),
|
||||||
|
KEY `idx_pan_id` (`pan_id`),
|
||||||
|
KEY `idx_tenant_id` (`tenant_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Add composite index for product summary aggregation (panel 1)
|
||||||
|
-- Use PREPARE/EXECUTE to skip if index already exists (MySQL has no CREATE INDEX IF NOT EXISTS).
|
||||||
|
SET @ix = (SELECT COUNT(*) FROM information_schema.STATISTICS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'inv_product' AND INDEX_NAME = 'idx_product_name_tenant');
|
||||||
|
SET @s = IF(@ix = 0,
|
||||||
|
'ALTER TABLE `inv_product` ADD KEY `idx_product_name_tenant` (`product_name`, `tenant_id`)',
|
||||||
|
'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
65
deploy/mysql/migrations/20260403_data_migration.sql
Normal file
65
deploy/mysql/migrations/20260403_data_migration.sql
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
-- Data migration: split existing inv_product flat data into pan + bolt records.
|
||||||
|
-- Run AFTER 20260403_add_pan_and_bolt.sql but BEFORE 20260403_drop_legacy_columns.sql.
|
||||||
|
-- Wrapped in a stored procedure so re-runs on an already-migrated database
|
||||||
|
-- (where `location` was already dropped) silently succeed rather than error.
|
||||||
|
-- MySQL validates column names at call time, not at CREATE PROCEDURE time,
|
||||||
|
-- so the IF guard prevents the INSERTs from running when the column is absent.
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS _migrate_inv_pan_bolt;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE PROCEDURE _migrate_inv_pan_bolt()
|
||||||
|
BEGIN
|
||||||
|
DECLARE v_has_location TINYINT DEFAULT 0;
|
||||||
|
SELECT COUNT(*) INTO v_has_location
|
||||||
|
FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'inv_product'
|
||||||
|
AND COLUMN_NAME = 'location';
|
||||||
|
|
||||||
|
IF v_has_location = 1 THEN
|
||||||
|
-- Step 1: one default pan per product, position taken from legacy `location`
|
||||||
|
INSERT INTO inv_product_pan (pan_id, product_id, name, position, sort_order, tenant_id)
|
||||||
|
SELECT
|
||||||
|
CONCAT('pan_mig_', product_id),
|
||||||
|
product_id,
|
||||||
|
'A',
|
||||||
|
COALESCE(location, ''),
|
||||||
|
1,
|
||||||
|
COALESCE(tenant_id, '')
|
||||||
|
FROM inv_product
|
||||||
|
WHERE deleted_at IS NULL
|
||||||
|
AND product_id NOT IN (SELECT DISTINCT product_id FROM inv_product_pan);
|
||||||
|
|
||||||
|
-- Step 2: bolt records, one per unit_piece (or one if unit_pieces = 0)
|
||||||
|
INSERT INTO inv_product_bolt (bolt_id, pan_id, length_m, sort_order, tenant_id)
|
||||||
|
SELECT
|
||||||
|
CONCAT('bolt_mig_', product_id, '_', seq.n),
|
||||||
|
CONCAT('pan_mig_', product_id),
|
||||||
|
CASE
|
||||||
|
WHEN unit_pieces > 0 THEN ROUND(stock_quantity / unit_pieces, 2)
|
||||||
|
ELSE stock_quantity
|
||||||
|
END,
|
||||||
|
seq.n,
|
||||||
|
COALESCE(tenant_id, '')
|
||||||
|
FROM inv_product
|
||||||
|
CROSS JOIN (
|
||||||
|
SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
|
||||||
|
UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10
|
||||||
|
UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15
|
||||||
|
UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20
|
||||||
|
) seq
|
||||||
|
WHERE deleted_at IS NULL
|
||||||
|
AND stock_quantity > 0
|
||||||
|
AND seq.n <= GREATEST(unit_pieces, 1)
|
||||||
|
AND CONCAT('pan_mig_', product_id) IN (SELECT pan_id FROM inv_product_pan);
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
CALL _migrate_inv_pan_bolt();
|
||||||
|
DROP PROCEDURE IF EXISTS _migrate_inv_pan_bolt;
|
||||||
|
|
||||||
|
-- Verification queries (run manually to check)
|
||||||
|
-- SELECT COUNT(*) AS pan_count FROM inv_product_pan WHERE pan_id LIKE 'pan_mig_%';
|
||||||
|
-- SELECT COUNT(*) AS bolt_count FROM inv_product_bolt WHERE bolt_id LIKE 'bolt_mig_%';
|
||||||
26
deploy/mysql/migrations/20260403_drop_legacy_columns.sql
Normal file
26
deploy/mysql/migrations/20260403_drop_legacy_columns.sql
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
-- Remove deprecated flat columns from inv_product.
|
||||||
|
-- Must run AFTER 20260403_data_migration.sql has migrated existing rows.
|
||||||
|
-- Uses PREPARE/EXECUTE to skip each column that was already dropped
|
||||||
|
-- (MySQL has no DROP COLUMN IF EXISTS; that is a MariaDB-only extension).
|
||||||
|
|
||||||
|
SET @db = DATABASE();
|
||||||
|
|
||||||
|
SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='unit_pieces');
|
||||||
|
SET @s = IF(@c=1, 'ALTER TABLE `inv_product` DROP COLUMN `unit_pieces`', 'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='unit_rolls');
|
||||||
|
SET @s = IF(@c=1, 'ALTER TABLE `inv_product` DROP COLUMN `unit_rolls`', 'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='stock_quantity');
|
||||||
|
SET @s = IF(@c=1, 'ALTER TABLE `inv_product` DROP COLUMN `stock_quantity`', 'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='location');
|
||||||
|
SET @s = IF(@c=1, 'ALTER TABLE `inv_product` DROP COLUMN `location`', 'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='cost_price');
|
||||||
|
SET @s = IF(@c=1, 'ALTER TABLE `inv_product` DROP COLUMN `cost_price`', 'SELECT 1');
|
||||||
|
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||||
9
deploy/mysql/migrations/20260407_fix_menu_mojibake.sql
Normal file
9
deploy/mysql/migrations/20260407_fix_menu_mojibake.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-- Fix double-encoded (CP1252→UTF-8) menu_name for pans/bolts entries
|
||||||
|
-- Root cause: these records were inserted through a connection that
|
||||||
|
-- misinterpreted UTF-8 bytes as CP1252, causing mojibake.
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
USE `muyu_wms`;
|
||||||
|
|
||||||
|
UPDATE `sys_menu` SET `menu_name` = '盘库存' WHERE `menu_id` = 'm_207' AND `path` = '/inventory/pans';
|
||||||
|
UPDATE `sys_menu` SET `menu_name` = '匹库存' WHERE `menu_id` = 'm_208' AND `path` = '/inventory/bolts';
|
||||||
@ -11,6 +11,9 @@ server {
|
|||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Allow large file uploads (e.g. Excel imports up to 100MB)
|
||||||
|
client_max_body_size 100m;
|
||||||
|
|
||||||
# API proxy
|
# API proxy
|
||||||
location /api/ {
|
location /api/ {
|
||||||
# Use Docker DNS dynamic resolution to avoid stale container IP after recreate.
|
# Use Docker DNS dynamic resolution to avoid stale container IP after recreate.
|
||||||
@ -29,7 +32,15 @@ server {
|
|||||||
add_header Cache-Control "public, immutable";
|
add_header Cache-Control "public, immutable";
|
||||||
}
|
}
|
||||||
|
|
||||||
# Static assets cache
|
# Do not aggressively cache entry bundles because file names are stable
|
||||||
|
# (for example umi.js / umi.css) and stale cache can cause a blank page
|
||||||
|
# after deployment updates.
|
||||||
|
location ~* ^/(umi\.js|umi\.css|preload_helper\.js)$ {
|
||||||
|
expires -1;
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache other static assets that are typically fingerprinted/chunked.
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
expires 30d;
|
expires 30d;
|
||||||
add_header Cache-Control "public, immutable";
|
add_header Cache-Control "public, immutable";
|
||||||
|
|||||||
119
deploy/tools/package-lock.json
generated
Normal file
119
deploy/tools/package-lock.json
generated
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
{
|
||||||
|
"name": "tools",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "tools",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/adler-32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cfb": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"crc-32": "~1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/codepage": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/crc-32": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"crc32": "bin/crc32.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/frac": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ssf": {
|
||||||
|
"version": "0.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||||
|
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"frac": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wmf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/word": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xlsx": {
|
||||||
|
"version": "0.18.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||||
|
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"cfb": "~1.2.1",
|
||||||
|
"codepage": "~1.15.0",
|
||||||
|
"crc-32": "~1.2.1",
|
||||||
|
"ssf": "~0.11.2",
|
||||||
|
"wmf": "~1.0.1",
|
||||||
|
"word": "~0.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"xlsx": "bin/xlsx.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
deploy/tools/package.json
Normal file
15
deploy/tools/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "tools",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "xls2json.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
21
deploy/tools/xls2json.js
Normal file
21
deploy/tools/xls2json.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
// Converts .xls/.xlsx to JSON on stdout.
|
||||||
|
// Usage: node xls2json.js <filepath>
|
||||||
|
const XLSX = require(__dirname + '/node_modules/xlsx');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const file = process.argv[2];
|
||||||
|
if (!file) {
|
||||||
|
process.stderr.write('usage: xls2json.js <file>\n');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const wb = XLSX.readFile(file);
|
||||||
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||||
|
const rows = XLSX.utils.sheet_to_json(ws, { header: 1, defval: '' });
|
||||||
|
process.stdout.write(JSON.stringify(rows));
|
||||||
|
} catch (e) {
|
||||||
|
process.stderr.write('xls2json error: ' + e.message + '\n');
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
@ -8,3 +8,23 @@ Auth:
|
|||||||
DefaultTenantId: t_default_001
|
DefaultTenantId: t_default_001
|
||||||
|
|
||||||
DataSource: root:muyu2026@tcp(127.0.0.1:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
DataSource: root:muyu2026@tcp(127.0.0.1:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||||
|
PostgresDataSource: "postgres://muyu:muyu2026@127.0.0.1:5432/muyu_crm?sslmode=disable"
|
||||||
|
|
||||||
|
SystemRpc:
|
||||||
|
Etcd:
|
||||||
|
Hosts:
|
||||||
|
- 127.0.0.1:2379
|
||||||
|
Key: system.rpc
|
||||||
|
NonBlock: true
|
||||||
|
|
||||||
|
InventoryRpc:
|
||||||
|
Etcd:
|
||||||
|
Hosts:
|
||||||
|
- 127.0.0.1:2379
|
||||||
|
Key: inventory.rpc
|
||||||
|
NonBlock: true
|
||||||
|
|
||||||
|
Log:
|
||||||
|
ServiceName: gateway-api
|
||||||
|
Mode: console
|
||||||
|
Level: info
|
||||||
|
|||||||
@ -219,47 +219,33 @@ type (
|
|||||||
// ==================== Product Types ====================
|
// ==================== Product Types ====================
|
||||||
type (
|
type (
|
||||||
ProductInfo {
|
ProductInfo {
|
||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
ImageUrl string `json:"imageUrl"`
|
ImageUrl string `json:"imageUrl"`
|
||||||
Spec string `json:"spec"`
|
Spec string `json:"spec"`
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
UnitPieces int64 `json:"unitPieces"`
|
SalesPrice string `json:"salesPrice"`
|
||||||
UnitRolls int64 `json:"unitRolls"`
|
Remark string `json:"remark"`
|
||||||
StockQuantity string `json:"stockQuantity"`
|
Status int64 `json:"status"`
|
||||||
Location string `json:"location"`
|
CreatedAt string `json:"createdAt"`
|
||||||
CostPrice string `json:"costPrice"`
|
UpdatedAt string `json:"updatedAt"`
|
||||||
SalesPrice string `json:"salesPrice"`
|
|
||||||
Remark string `json:"remark"`
|
|
||||||
Status int64 `json:"status"`
|
|
||||||
CreatedAt string `json:"createdAt"`
|
|
||||||
UpdatedAt string `json:"updatedAt"`
|
|
||||||
}
|
}
|
||||||
CreateProductReq {
|
CreateProductReq {
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
UnitPieces int64 `json:"unitPieces,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
UnitRolls int64 `json:"unitRolls,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
StockQuantity string `json:"stockQuantity,optional"`
|
Pans []PanInput `json:"pans,optional"`
|
||||||
Location string `json:"location,optional"`
|
|
||||||
CostPrice string `json:"costPrice,optional"`
|
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
|
||||||
Remark string `json:"remark,optional"`
|
|
||||||
}
|
}
|
||||||
UpdateProductReq {
|
UpdateProductReq {
|
||||||
ProductName string `json:"productName,optional"`
|
ProductName string `json:"productName,optional"`
|
||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
UnitPieces int64 `json:"unitPieces,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
UnitRolls int64 `json:"unitRolls,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
StockQuantity string `json:"stockQuantity,optional"`
|
|
||||||
Location string `json:"location,optional"`
|
|
||||||
CostPrice string `json:"costPrice,optional"`
|
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
|
||||||
Remark string `json:"remark,optional"`
|
|
||||||
}
|
}
|
||||||
ListProductReq {
|
ListProductReq {
|
||||||
Page int64 `form:"page,default=1"`
|
Page int64 `form:"page,default=1"`
|
||||||
@ -267,7 +253,6 @@ type (
|
|||||||
ProductName string `form:"productName,optional"`
|
ProductName string `form:"productName,optional"`
|
||||||
Spec string `form:"spec,optional"`
|
Spec string `form:"spec,optional"`
|
||||||
Color string `form:"color,optional"`
|
Color string `form:"color,optional"`
|
||||||
Location string `form:"location,optional"`
|
|
||||||
Status int64 `form:"status,optional,default=-1"`
|
Status int64 `form:"status,optional,default=-1"`
|
||||||
}
|
}
|
||||||
ListProductResp {
|
ListProductResp {
|
||||||
@ -283,13 +268,92 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ==================== Pan / Bolt Types ====================
|
||||||
|
type (
|
||||||
|
BoltInfo {
|
||||||
|
BoltId string `json:"boltId"`
|
||||||
|
PanId string `json:"panId"`
|
||||||
|
LengthM string `json:"lengthM"`
|
||||||
|
SortOrder int64 `json:"sortOrder"`
|
||||||
|
}
|
||||||
|
PanInfo {
|
||||||
|
PanId string `json:"panId"`
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Position string `json:"position"`
|
||||||
|
SortOrder int64 `json:"sortOrder"`
|
||||||
|
Bolts []BoltInfo `json:"bolts"`
|
||||||
|
BoltCount int64 `json:"boltCount"`
|
||||||
|
TotalLength string `json:"totalLength"`
|
||||||
|
}
|
||||||
|
PanInput {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Position string `json:"position,optional"`
|
||||||
|
BoltLengths []string `json:"boltLengths,optional"`
|
||||||
|
}
|
||||||
|
ListPanResp {
|
||||||
|
List []PanInfo `json:"list"`
|
||||||
|
}
|
||||||
|
SavePansReq {
|
||||||
|
Pans []PanInput `json:"pans"`
|
||||||
|
}
|
||||||
|
ListBoltResp {
|
||||||
|
List []BoltInfo `json:"list"`
|
||||||
|
}
|
||||||
|
SaveBoltsReq {
|
||||||
|
Lengths []string `json:"lengths"`
|
||||||
|
}
|
||||||
|
ProductTreeResp {
|
||||||
|
Product ProductInfo `json:"product"`
|
||||||
|
Pans []PanInfo `json:"pans"`
|
||||||
|
TotalPanCount int64 `json:"totalPanCount"`
|
||||||
|
TotalBoltCount int64 `json:"totalBoltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ==================== Panel Types ====================
|
||||||
|
type (
|
||||||
|
ProductSummaryItem {
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Spec string `json:"spec"`
|
||||||
|
ColorCount int64 `json:"colorCount"`
|
||||||
|
TotalPanCount int64 `json:"totalPanCount"`
|
||||||
|
TotalBoltCount int64 `json:"totalBoltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
Colors string `json:"colors"`
|
||||||
|
Locations string `json:"locations"`
|
||||||
|
}
|
||||||
|
ProductSummaryResp {
|
||||||
|
List []ProductSummaryItem `json:"list"`
|
||||||
|
}
|
||||||
|
ColorDetailItem {
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
Spec string `json:"spec"`
|
||||||
|
ImageUrl string `json:"imageUrl"`
|
||||||
|
PanCount int64 `json:"panCount"`
|
||||||
|
BoltCount int64 `json:"boltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
Locations string `json:"locations"`
|
||||||
|
SalesPrice string `json:"salesPrice"`
|
||||||
|
}
|
||||||
|
ListColorDetailReq {
|
||||||
|
ProductName string `form:"productName"`
|
||||||
|
}
|
||||||
|
ColorDetailResp {
|
||||||
|
List []ColorDetailItem `json:"list"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// ==================== Stock Statistics Types ====================
|
// ==================== Stock Statistics Types ====================
|
||||||
type (
|
type (
|
||||||
StockSummaryResp {
|
StockSummaryResp {
|
||||||
ProductCount int64 `json:"productCount"`
|
ProductCount int64 `json:"productCount"`
|
||||||
TotalPieces int64 `json:"totalPieces"`
|
TotalPieces int64 `json:"totalPieces"`
|
||||||
TotalRolls int64 `json:"totalRolls"`
|
TotalPans int64 `json:"totalPans"`
|
||||||
TotalCostValue string `json:"totalCostValue"`
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
TotalSalesValue string `json:"totalSalesValue"`
|
TotalSalesValue string `json:"totalSalesValue"`
|
||||||
}
|
}
|
||||||
StockGroupItem {
|
StockGroupItem {
|
||||||
@ -644,6 +708,36 @@ service gateway-api {
|
|||||||
|
|
||||||
@handler ExportProductHandler
|
@handler ExportProductHandler
|
||||||
get /products/export
|
get /products/export
|
||||||
|
|
||||||
|
@handler GetProductSummaryHandler
|
||||||
|
get /products/summary returns (ProductSummaryResp)
|
||||||
|
|
||||||
|
@handler GetColorDetailHandler
|
||||||
|
get /products/colors (ListColorDetailReq) returns (ColorDetailResp)
|
||||||
|
|
||||||
|
@handler GetProductTreeHandler
|
||||||
|
get /products/:id/tree returns (ProductTreeResp)
|
||||||
|
|
||||||
|
@handler ListPansHandler
|
||||||
|
get /products/:id/pans returns (ListPanResp)
|
||||||
|
|
||||||
|
@handler SavePansHandler
|
||||||
|
put /products/:id/pans (SavePansReq) returns (IdResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inventory - Pan/Bolt Management
|
||||||
|
@server (
|
||||||
|
prefix: /api/v1/inventory
|
||||||
|
group: inventory/panbolt
|
||||||
|
jwt: Auth
|
||||||
|
middleware: AuthorityMiddleware
|
||||||
|
)
|
||||||
|
service gateway-api {
|
||||||
|
@handler ListBoltsHandler
|
||||||
|
get /pans/:id/bolts returns (ListBoltResp)
|
||||||
|
|
||||||
|
@handler SaveBoltsHandler
|
||||||
|
put /pans/:id/bolts (SaveBoltsReq) returns (IdResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inventory - Stock Query & Statistics
|
// Inventory - Stock Query & Statistics
|
||||||
|
|||||||
@ -50,7 +50,7 @@ func main() {
|
|||||||
if ok {
|
if ok {
|
||||||
return http.StatusOK, &Response{Code: int(s.Code()), Msg: s.Message()}
|
return http.StatusOK, &Response{Code: int(s.Code()), Msg: s.Message()}
|
||||||
}
|
}
|
||||||
return http.StatusOK, &Response{Code: 1001, Msg: err.Error()}
|
return http.StatusBadRequest, &Response{Code: 1001, Msg: err.Error()}
|
||||||
})
|
})
|
||||||
|
|
||||||
httpx.SetOkHandler(func(ctx context.Context, a interface{}) interface{} {
|
httpx.SetOkHandler(func(ctx context.Context, a interface{}) interface{} {
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
package relation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SearchTenantsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
keyword := r.URL.Query().Get("keyword")
|
||||||
|
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
|
||||||
|
if limit <= 0 {
|
||||||
|
limit = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
tenants, err := svcCtx.CrmRepo.SearchTenants(r.Context(), keyword, limit)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, map[string]interface{}{
|
||||||
|
"list": tenants,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/panbolt"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListBoltViewHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.ListBoltViewReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := logic.NewListBoltViewLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ListBoltView(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/panbolt"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListBoltsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||||
|
l := logic.NewListBoltsLogic(ctx, svcCtx)
|
||||||
|
resp, err := l.ListBolts()
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/panbolt"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListPanViewHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.ListPanViewReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := logic.NewListPanViewLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ListPanView(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/panbolt"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SaveBoltsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.SaveBoltsReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||||
|
l := logic.NewSaveBoltsLogic(ctx, svcCtx)
|
||||||
|
resp, err := l.SaveBolts(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetColorDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.ListColorDetailReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := logic.NewGetColorDetailLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetColorDetail(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductSummaryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
l := logic.NewGetProductSummaryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetProductSummary()
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProductTreeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||||
|
l := logic.NewGetProductTreeLogic(ctx, svcCtx)
|
||||||
|
resp, err := l.GetProductTree()
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,46 @@
|
|||||||
// Code scaffolded by goctl. Safe to edit.
|
|
||||||
// goctl 1.9.2
|
|
||||||
|
|
||||||
package product
|
package product
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
"muyu-apiserver/gateway/internal/logic/inventory/product"
|
"muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
"muyu-apiserver/gateway/internal/svc"
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxUploadSize = 50 << 20 // 50 MB
|
||||||
|
|
||||||
func ImportProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func ImportProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)
|
||||||
|
|
||||||
|
file, header, err := r.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
ext := filepath.Ext(header.Filename)
|
||||||
|
tmpFile, err := os.CreateTemp("", "import-*"+ext)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(tmpFile.Name())
|
||||||
|
defer tmpFile.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(tmpFile, file); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmpFile.Close()
|
||||||
|
|
||||||
l := product.NewImportProductLogic(r.Context(), svcCtx)
|
l := product.NewImportProductLogic(r.Context(), svcCtx)
|
||||||
resp, err := l.ImportProduct()
|
resp, err := l.ImportProduct(tmpFile.Name(), header.Filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpx.ErrorCtx(r.Context(), w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListPansHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||||
|
l := logic.NewListPansLogic(ctx, svcCtx)
|
||||||
|
resp, err := l.ListPans()
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||||
|
logic "muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SavePansHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.SavePansReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||||
|
l := logic.NewSavePansLogic(ctx, svcCtx)
|
||||||
|
resp, err := l.SavePans(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ import (
|
|||||||
crmrelation "muyu-apiserver/gateway/internal/handler/crm/relation"
|
crmrelation "muyu-apiserver/gateway/internal/handler/crm/relation"
|
||||||
inventoryadjust "muyu-apiserver/gateway/internal/handler/inventory/adjust"
|
inventoryadjust "muyu-apiserver/gateway/internal/handler/inventory/adjust"
|
||||||
inventorycheck "muyu-apiserver/gateway/internal/handler/inventory/check"
|
inventorycheck "muyu-apiserver/gateway/internal/handler/inventory/check"
|
||||||
|
inventorypanbolt "muyu-apiserver/gateway/internal/handler/inventory/panbolt"
|
||||||
inventoryproduct "muyu-apiserver/gateway/internal/handler/inventory/product"
|
inventoryproduct "muyu-apiserver/gateway/internal/handler/inventory/product"
|
||||||
inventorystock "muyu-apiserver/gateway/internal/handler/inventory/stock"
|
inventorystock "muyu-apiserver/gateway/internal/handler/inventory/stock"
|
||||||
systemconfig "muyu-apiserver/gateway/internal/handler/system/config"
|
systemconfig "muyu-apiserver/gateway/internal/handler/system/config"
|
||||||
@ -34,6 +35,17 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
rest.WithPrefix("/api/v1/auth"),
|
rest.WithPrefix("/api/v1/auth"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/tenants/search",
|
||||||
|
Handler: crmrelation.SearchTenantsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest.WithPrefix("/api/v1/public"),
|
||||||
|
)
|
||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
@ -175,6 +187,21 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
Path: "/products",
|
Path: "/products",
|
||||||
Handler: inventoryproduct.CreateProductHandler(serverCtx),
|
Handler: inventoryproduct.CreateProductHandler(serverCtx),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/products/summary",
|
||||||
|
Handler: inventoryproduct.GetProductSummaryHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/products/colors",
|
||||||
|
Handler: inventoryproduct.GetColorDetailHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/products/export",
|
||||||
|
Handler: inventoryproduct.ExportProductHandler(serverCtx),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
Path: "/products/:id",
|
Path: "/products/:id",
|
||||||
@ -192,9 +219,29 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
Path: "/products/export",
|
Path: "/products/:id/tree",
|
||||||
Handler: inventoryproduct.ExportProductHandler(serverCtx),
|
Handler: inventoryproduct.GetProductTreeHandler(serverCtx),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/products/:id/pans",
|
||||||
|
Handler: inventoryproduct.ListPansHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPut,
|
||||||
|
Path: "/products/:id/pans",
|
||||||
|
Handler: inventoryproduct.SavePansHandler(serverCtx),
|
||||||
|
},
|
||||||
|
}...,
|
||||||
|
),
|
||||||
|
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1/inventory"),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
rest.WithMiddlewares(
|
||||||
|
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||||
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Path: "/products/import",
|
Path: "/products/import",
|
||||||
@ -204,6 +251,37 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
),
|
),
|
||||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||||
rest.WithPrefix("/api/v1/inventory"),
|
rest.WithPrefix("/api/v1/inventory"),
|
||||||
|
rest.WithMaxBytes(50<<20),
|
||||||
|
)
|
||||||
|
|
||||||
|
server.AddRoutes(
|
||||||
|
rest.WithMiddlewares(
|
||||||
|
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||||
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/pans",
|
||||||
|
Handler: inventorypanbolt.ListPanViewHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/bolts",
|
||||||
|
Handler: inventorypanbolt.ListBoltViewHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/pans/:id/bolts",
|
||||||
|
Handler: inventorypanbolt.ListBoltsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPut,
|
||||||
|
Path: "/pans/:id/bolts",
|
||||||
|
Handler: inventorypanbolt.SaveBoltsHandler(serverCtx),
|
||||||
|
},
|
||||||
|
}...,
|
||||||
|
),
|
||||||
|
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api/v1/inventory"),
|
||||||
)
|
)
|
||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListBoltViewLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListBoltViewLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListBoltViewLogic {
|
||||||
|
return &ListBoltViewLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListBoltViewLogic) ListBoltView(req *types.ListBoltViewReq) (resp *types.ListBoltViewResp, err error) {
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ListBoltView(l.ctx, &pb.ListBoltViewReq{
|
||||||
|
Page: req.Page,
|
||||||
|
PageSize: req.PageSize,
|
||||||
|
ProductName: req.ProductName,
|
||||||
|
Position: req.Position,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]types.BoltListItem, 0, len(rpcResp.List))
|
||||||
|
for _, item := range rpcResp.List {
|
||||||
|
list = append(list, types.BoltListItem{
|
||||||
|
BoltId: item.BoltId,
|
||||||
|
PanId: item.PanId,
|
||||||
|
LengthM: item.LengthM,
|
||||||
|
Color: item.Color,
|
||||||
|
SortOrder: item.SortOrder,
|
||||||
|
PanName: item.PanName,
|
||||||
|
Position: item.Position,
|
||||||
|
ProductId: item.ProductId,
|
||||||
|
ProductName: item.ProductName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &types.ListBoltViewResp{Total: rpcResp.Total, List: list}, nil
|
||||||
|
}
|
||||||
44
gateway/internal/logic/inventory/panbolt/listBoltsLogic.go
Normal file
44
gateway/internal/logic/inventory/panbolt/listBoltsLogic.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/ctxdata"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListBoltsLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListBoltsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListBoltsLogic {
|
||||||
|
return &ListBoltsLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListBoltsLogic) ListBolts() (resp *types.ListBoltResp, err error) {
|
||||||
|
panId := ctxdata.GetPathId(l.ctx)
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ListBolts(l.ctx, &pb.ListBoltReq{PanId: panId})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
list := make([]types.BoltInfo, 0, len(rpcResp.List))
|
||||||
|
for _, b := range rpcResp.List {
|
||||||
|
list = append(list, types.BoltInfo{
|
||||||
|
BoltId: b.BoltId,
|
||||||
|
PanId: b.PanId,
|
||||||
|
LengthM: b.LengthM,
|
||||||
|
SortOrder: b.SortOrder,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &types.ListBoltResp{List: list}, nil
|
||||||
|
}
|
||||||
52
gateway/internal/logic/inventory/panbolt/listPanViewLogic.go
Normal file
52
gateway/internal/logic/inventory/panbolt/listPanViewLogic.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPanViewLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListPanViewLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPanViewLogic {
|
||||||
|
return &ListPanViewLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListPanViewLogic) ListPanView(req *types.ListPanViewReq) (resp *types.ListPanViewResp, err error) {
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ListPanView(l.ctx, &pb.ListPanViewReq{
|
||||||
|
Page: req.Page,
|
||||||
|
PageSize: req.PageSize,
|
||||||
|
ProductName: req.ProductName,
|
||||||
|
Position: req.Position,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]types.PanListItem, 0, len(rpcResp.List))
|
||||||
|
for _, item := range rpcResp.List {
|
||||||
|
list = append(list, types.PanListItem{
|
||||||
|
PanId: item.PanId,
|
||||||
|
ProductId: item.ProductId,
|
||||||
|
Name: item.Name,
|
||||||
|
Position: item.Position,
|
||||||
|
ProductName: item.ProductName,
|
||||||
|
Colors: item.Colors,
|
||||||
|
BoltCount: item.BoltCount,
|
||||||
|
TotalLengthM: item.TotalLengthM,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &types.ListPanViewResp{Total: rpcResp.Total, List: list}, nil
|
||||||
|
}
|
||||||
38
gateway/internal/logic/inventory/panbolt/saveBoltsLogic.go
Normal file
38
gateway/internal/logic/inventory/panbolt/saveBoltsLogic.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package panbolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/ctxdata"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SaveBoltsLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSaveBoltsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveBoltsLogic {
|
||||||
|
return &SaveBoltsLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SaveBoltsLogic) SaveBolts(req *types.SaveBoltsReq) (resp *types.IdResp, err error) {
|
||||||
|
panId := ctxdata.GetPathId(l.ctx)
|
||||||
|
_, err = l.svcCtx.InventoryRpc.SaveBolts(l.ctx, &pb.SaveBoltsReq{
|
||||||
|
PanId: panId,
|
||||||
|
Lengths: req.Lengths,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &types.IdResp{Id: panId}, nil
|
||||||
|
}
|
||||||
@ -26,17 +26,13 @@ func NewCreateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cre
|
|||||||
|
|
||||||
func (l *CreateProductLogic) CreateProduct(req *types.CreateProductReq) (resp *types.IdResp, err error) {
|
func (l *CreateProductLogic) CreateProduct(req *types.CreateProductReq) (resp *types.IdResp, err error) {
|
||||||
rpcResp, err := l.svcCtx.InventoryRpc.CreateProduct(l.ctx, &pb.CreateProductReq{
|
rpcResp, err := l.svcCtx.InventoryRpc.CreateProduct(l.ctx, &pb.CreateProductReq{
|
||||||
ProductName: req.ProductName,
|
ProductName: req.ProductName,
|
||||||
ImageUrl: req.ImageUrl,
|
ImageUrl: req.ImageUrl,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
UnitPieces: req.UnitPieces,
|
SalesPrice: req.SalesPrice,
|
||||||
UnitRolls: req.UnitRolls,
|
Remark: req.Remark,
|
||||||
StockQuantity: req.StockQuantity,
|
Pans: panInputsToPb(req.Pans),
|
||||||
Location: req.Location,
|
|
||||||
CostPrice: req.CostPrice,
|
|
||||||
SalesPrice: req.SalesPrice,
|
|
||||||
Remark: req.Remark,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -44,3 +40,18 @@ func (l *CreateProductLogic) CreateProduct(req *types.CreateProductReq) (resp *t
|
|||||||
|
|
||||||
return &types.IdResp{Id: rpcResp.Id}, nil
|
return &types.IdResp{Id: rpcResp.Id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func panInputsToPb(pans []types.PanInput) []*pb.PanInput {
|
||||||
|
if len(pans) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make([]*pb.PanInput, 0, len(pans))
|
||||||
|
for _, p := range pans {
|
||||||
|
out = append(out, &pb.PanInput{
|
||||||
|
Name: p.Name,
|
||||||
|
Position: p.Position,
|
||||||
|
BoltLengths: p.BoltLengths,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetColorDetailLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetColorDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetColorDetailLogic {
|
||||||
|
return &GetColorDetailLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (resp *types.ColorDetailResp, err error) {
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ListColorDetail(l.ctx, &pb.ListColorDetailReq{
|
||||||
|
ProductName: req.ProductName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
list := make([]types.ColorDetailItem, 0, len(rpcResp.List))
|
||||||
|
for _, it := range rpcResp.List {
|
||||||
|
list = append(list, types.ColorDetailItem{
|
||||||
|
ProductId: it.ProductId,
|
||||||
|
ProductName: it.ProductName,
|
||||||
|
Color: it.Color,
|
||||||
|
Spec: it.Spec,
|
||||||
|
ImageUrl: it.ImageUrl,
|
||||||
|
PanCount: it.PanCount,
|
||||||
|
BoltCount: it.BoltCount,
|
||||||
|
TotalLengthM: it.TotalLengthM,
|
||||||
|
Locations: it.Locations,
|
||||||
|
SalesPrice: it.SalesPrice,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &types.ColorDetailResp{List: list}, nil
|
||||||
|
}
|
||||||
@ -35,21 +35,6 @@ func (l *GetProductLogic) GetProduct() (resp *types.ProductInfo, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.ProductInfo{
|
pi := productInfoFromPB(rpcResp)
|
||||||
ProductId: rpcResp.ProductId,
|
return &pi, nil
|
||||||
ProductName: rpcResp.ProductName,
|
|
||||||
ImageUrl: rpcResp.ImageUrl,
|
|
||||||
Spec: rpcResp.Spec,
|
|
||||||
Color: rpcResp.Color,
|
|
||||||
UnitPieces: rpcResp.UnitPieces,
|
|
||||||
UnitRolls: rpcResp.UnitRolls,
|
|
||||||
StockQuantity: rpcResp.StockQuantity,
|
|
||||||
Location: rpcResp.Location,
|
|
||||||
CostPrice: rpcResp.CostPrice,
|
|
||||||
SalesPrice: rpcResp.SalesPrice,
|
|
||||||
Remark: rpcResp.Remark,
|
|
||||||
Status: rpcResp.Status,
|
|
||||||
CreatedAt: rpcResp.CreatedAt,
|
|
||||||
UpdatedAt: rpcResp.UpdatedAt,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetProductSummaryLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetProductSummaryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductSummaryLogic {
|
||||||
|
return &GetProductSummaryLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetProductSummaryLogic) GetProductSummary() (resp *types.ProductSummaryResp, err error) {
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ListProductSummary(l.ctx, &pb.ListProductSummaryReq{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
list := make([]types.ProductSummaryItem, 0, len(rpcResp.List))
|
||||||
|
for _, it := range rpcResp.List {
|
||||||
|
list = append(list, types.ProductSummaryItem{
|
||||||
|
ProductName: it.ProductName,
|
||||||
|
Spec: it.Spec,
|
||||||
|
ColorCount: it.ColorCount,
|
||||||
|
TotalPanCount: it.TotalPanCount,
|
||||||
|
TotalBoltCount: it.TotalBoltCount,
|
||||||
|
TotalLengthM: it.TotalLengthM,
|
||||||
|
Colors: it.Colors,
|
||||||
|
Locations: it.Locations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &types.ProductSummaryResp{List: list}, nil
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/ctxdata"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetProductTreeLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetProductTreeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductTreeLogic {
|
||||||
|
return &GetProductTreeLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetProductTreeLogic) GetProductTree() (resp *types.ProductTreeResp, err error) {
|
||||||
|
id := ctxdata.GetPathId(l.ctx)
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.GetProductTree(l.ctx, &pb.GetProductReq{
|
||||||
|
ProductId: id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pans := make([]types.PanInfo, 0, len(rpcResp.Pans))
|
||||||
|
for _, p := range rpcResp.Pans {
|
||||||
|
pans = append(pans, panInfoFromPB(p))
|
||||||
|
}
|
||||||
|
return &types.ProductTreeResp{
|
||||||
|
Product: productInfoFromPB(rpcResp.Product),
|
||||||
|
Pans: pans,
|
||||||
|
TotalPanCount: rpcResp.TotalPanCount,
|
||||||
|
TotalBoltCount: rpcResp.TotalBoltCount,
|
||||||
|
TotalLengthM: rpcResp.TotalLengthM,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@ -2,10 +2,13 @@ package product
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"muyu-apiserver/gateway/internal/svc"
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
"muyu-apiserver/gateway/internal/types"
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/excelparse"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
)
|
)
|
||||||
@ -24,6 +27,50 @@ func NewImportProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Imp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *ImportProductLogic) ImportProduct() (resp *types.ImportProductResp, err error) {
|
func (l *ImportProductLogic) ImportProduct(filePath, fileName string) (resp *types.ImportProductResp, err error) {
|
||||||
return nil, errors.New("import product requires file upload handling, will be implemented in handler layer")
|
result, err := excelparse.ParseFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("解析Excel失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Infof("excel parsed: format=%s, products=%d, skipped=%d",
|
||||||
|
result.ParserName, len(result.Products), result.SkippedRows)
|
||||||
|
|
||||||
|
products := make([]*pb.CreateProductReq, 0, len(result.Products))
|
||||||
|
for _, p := range result.Products {
|
||||||
|
products = append(products, &pb.CreateProductReq{
|
||||||
|
ProductName: p.ProductName,
|
||||||
|
Spec: p.Spec,
|
||||||
|
Color: p.Color,
|
||||||
|
SalesPrice: p.SalesPrice,
|
||||||
|
Remark: p.Remark,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ImportProducts(l.ctx, &pb.ImportProductReq{
|
||||||
|
Products: products,
|
||||||
|
FileName: fileName + " (" + result.ParserName + "格式)",
|
||||||
|
Operator: operatorFromCtx(l.ctx),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ImportProductResp{
|
||||||
|
TotalCount: rpcResp.TotalCount,
|
||||||
|
SuccessCount: rpcResp.SuccessCount,
|
||||||
|
FailCount: rpcResp.FailCount,
|
||||||
|
ErrorMsg: rpcResp.ErrorMsg,
|
||||||
|
ImportId: rpcResp.ImportId,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func operatorFromCtx(ctx context.Context) string {
|
||||||
|
if uid, ok := ctx.Value("userId").(string); ok {
|
||||||
|
return uid
|
||||||
|
}
|
||||||
|
if uid, ok := ctx.Value("userId").(int64); ok {
|
||||||
|
return strconv.FormatInt(uid, 10)
|
||||||
|
}
|
||||||
|
return "system"
|
||||||
}
|
}
|
||||||
|
|||||||
85
gateway/internal/logic/inventory/product/listPansLogic.go
Normal file
85
gateway/internal/logic/inventory/product/listPansLogic.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/ctxdata"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPansLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListPansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPansLogic {
|
||||||
|
return &ListPansLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListPansLogic) ListPans() (resp *types.ListPanResp, err error) {
|
||||||
|
id := ctxdata.GetPathId(l.ctx)
|
||||||
|
rpcResp, err := l.svcCtx.InventoryRpc.ListPans(l.ctx, &pb.ListPanReq{
|
||||||
|
ProductId: id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
list := make([]types.PanInfo, 0, len(rpcResp.List))
|
||||||
|
for _, p := range rpcResp.List {
|
||||||
|
list = append(list, panInfoFromPB(p))
|
||||||
|
}
|
||||||
|
return &types.ListPanResp{List: list}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func boltInfoFromPB(b *pb.BoltInfo) types.BoltInfo {
|
||||||
|
return types.BoltInfo{
|
||||||
|
BoltId: b.BoltId,
|
||||||
|
PanId: b.PanId,
|
||||||
|
LengthM: b.LengthM,
|
||||||
|
SortOrder: b.SortOrder,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func panInfoFromPB(p *pb.PanInfo) types.PanInfo {
|
||||||
|
bolts := make([]types.BoltInfo, 0, len(p.Bolts))
|
||||||
|
for _, b := range p.Bolts {
|
||||||
|
bolts = append(bolts, boltInfoFromPB(b))
|
||||||
|
}
|
||||||
|
return types.PanInfo{
|
||||||
|
PanId: p.PanId,
|
||||||
|
ProductId: p.ProductId,
|
||||||
|
Name: p.Name,
|
||||||
|
Position: p.Position,
|
||||||
|
SortOrder: p.SortOrder,
|
||||||
|
Bolts: bolts,
|
||||||
|
BoltCount: p.BoltCount,
|
||||||
|
TotalLength: p.TotalLength,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func productInfoFromPB(p *pb.ProductInfo) types.ProductInfo {
|
||||||
|
if p == nil {
|
||||||
|
return types.ProductInfo{}
|
||||||
|
}
|
||||||
|
return types.ProductInfo{
|
||||||
|
ProductId: p.ProductId,
|
||||||
|
ProductName: p.ProductName,
|
||||||
|
ImageUrl: p.ImageUrl,
|
||||||
|
Spec: p.Spec,
|
||||||
|
Color: p.Color,
|
||||||
|
SalesPrice: p.SalesPrice,
|
||||||
|
Remark: p.Remark,
|
||||||
|
Status: p.Status,
|
||||||
|
CreatedAt: p.CreatedAt,
|
||||||
|
UpdatedAt: p.UpdatedAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,7 +31,6 @@ func (l *ListProductLogic) ListProduct(req *types.ListProductReq) (resp *types.L
|
|||||||
ProductName: req.ProductName,
|
ProductName: req.ProductName,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
Location: req.Location,
|
|
||||||
Status: req.Status,
|
Status: req.Status,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,23 +39,7 @@ func (l *ListProductLogic) ListProduct(req *types.ListProductReq) (resp *types.L
|
|||||||
|
|
||||||
list := make([]types.ProductInfo, 0, len(rpcResp.List))
|
list := make([]types.ProductInfo, 0, len(rpcResp.List))
|
||||||
for _, p := range rpcResp.List {
|
for _, p := range rpcResp.List {
|
||||||
list = append(list, types.ProductInfo{
|
list = append(list, productInfoFromPB(p))
|
||||||
ProductId: p.ProductId,
|
|
||||||
ProductName: p.ProductName,
|
|
||||||
ImageUrl: p.ImageUrl,
|
|
||||||
Spec: p.Spec,
|
|
||||||
Color: p.Color,
|
|
||||||
UnitPieces: p.UnitPieces,
|
|
||||||
UnitRolls: p.UnitRolls,
|
|
||||||
StockQuantity: p.StockQuantity,
|
|
||||||
Location: p.Location,
|
|
||||||
CostPrice: p.CostPrice,
|
|
||||||
SalesPrice: p.SalesPrice,
|
|
||||||
Remark: p.Remark,
|
|
||||||
Status: p.Status,
|
|
||||||
CreatedAt: p.CreatedAt,
|
|
||||||
UpdatedAt: p.UpdatedAt,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.ListProductResp{
|
return &types.ListProductResp{
|
||||||
|
|||||||
38
gateway/internal/logic/inventory/product/savePansLogic.go
Normal file
38
gateway/internal/logic/inventory/product/savePansLogic.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/ctxdata"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SavePansLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSavePansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SavePansLogic {
|
||||||
|
return &SavePansLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SavePansLogic) SavePans(req *types.SavePansReq) (resp *types.IdResp, err error) {
|
||||||
|
id := ctxdata.GetPathId(l.ctx)
|
||||||
|
_, err = l.svcCtx.InventoryRpc.SavePans(l.ctx, &pb.SavePansReq{
|
||||||
|
ProductId: id,
|
||||||
|
Pans: panInputsToPb(req.Pans),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &types.IdResp{Id: id}, nil
|
||||||
|
}
|
||||||
@ -29,18 +29,13 @@ func (l *UpdateProductLogic) UpdateProduct(req *types.UpdateProductReq) (resp *t
|
|||||||
id := ctxdata.GetPathId(l.ctx)
|
id := ctxdata.GetPathId(l.ctx)
|
||||||
|
|
||||||
_, err = l.svcCtx.InventoryRpc.UpdateProduct(l.ctx, &pb.UpdateProductReq{
|
_, err = l.svcCtx.InventoryRpc.UpdateProduct(l.ctx, &pb.UpdateProductReq{
|
||||||
ProductId: id,
|
ProductId: id,
|
||||||
ProductName: req.ProductName,
|
ProductName: req.ProductName,
|
||||||
ImageUrl: req.ImageUrl,
|
ImageUrl: req.ImageUrl,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
UnitPieces: req.UnitPieces,
|
SalesPrice: req.SalesPrice,
|
||||||
UnitRolls: req.UnitRolls,
|
Remark: req.Remark,
|
||||||
StockQuantity: req.StockQuantity,
|
|
||||||
Location: req.Location,
|
|
||||||
CostPrice: req.CostPrice,
|
|
||||||
SalesPrice: req.SalesPrice,
|
|
||||||
Remark: req.Remark,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -33,8 +33,8 @@ func (l *GetStockSummaryLogic) GetStockSummary() (resp *types.StockSummaryResp,
|
|||||||
return &types.StockSummaryResp{
|
return &types.StockSummaryResp{
|
||||||
ProductCount: rpcResp.ProductCount,
|
ProductCount: rpcResp.ProductCount,
|
||||||
TotalPieces: rpcResp.TotalPieces,
|
TotalPieces: rpcResp.TotalPieces,
|
||||||
TotalRolls: rpcResp.TotalRolls,
|
TotalPans: rpcResp.TotalPans,
|
||||||
TotalCostValue: rpcResp.TotalCostValue,
|
TotalLengthM: rpcResp.TotalLengthM,
|
||||||
TotalSalesValue: rpcResp.TotalSalesValue,
|
TotalSalesValue: rpcResp.TotalSalesValue,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,6 @@ func (l *ListStockLogic) ListStock(req *types.ListProductReq) (resp *types.ListP
|
|||||||
ProductName: req.ProductName,
|
ProductName: req.ProductName,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
Location: req.Location,
|
|
||||||
Status: req.Status,
|
Status: req.Status,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -41,21 +40,16 @@ func (l *ListStockLogic) ListStock(req *types.ListProductReq) (resp *types.ListP
|
|||||||
list := make([]types.ProductInfo, 0, len(rpcResp.List))
|
list := make([]types.ProductInfo, 0, len(rpcResp.List))
|
||||||
for _, p := range rpcResp.List {
|
for _, p := range rpcResp.List {
|
||||||
list = append(list, types.ProductInfo{
|
list = append(list, types.ProductInfo{
|
||||||
ProductId: p.ProductId,
|
ProductId: p.ProductId,
|
||||||
ProductName: p.ProductName,
|
ProductName: p.ProductName,
|
||||||
ImageUrl: p.ImageUrl,
|
ImageUrl: p.ImageUrl,
|
||||||
Spec: p.Spec,
|
Spec: p.Spec,
|
||||||
Color: p.Color,
|
Color: p.Color,
|
||||||
UnitPieces: p.UnitPieces,
|
SalesPrice: p.SalesPrice,
|
||||||
UnitRolls: p.UnitRolls,
|
Remark: p.Remark,
|
||||||
StockQuantity: p.StockQuantity,
|
Status: p.Status,
|
||||||
Location: p.Location,
|
CreatedAt: p.CreatedAt,
|
||||||
CostPrice: p.CostPrice,
|
UpdatedAt: p.UpdatedAt,
|
||||||
SalesPrice: p.SalesPrice,
|
|
||||||
Remark: p.Remark,
|
|
||||||
Status: p.Status,
|
|
||||||
CreatedAt: p.CreatedAt,
|
|
||||||
UpdatedAt: p.UpdatedAt,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"muyu-apiserver/gateway/internal/svc"
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
"muyu-apiserver/gateway/internal/types"
|
"muyu-apiserver/gateway/internal/types"
|
||||||
|
"muyu-apiserver/pkg/ctxdata"
|
||||||
"muyu-apiserver/rpc/system/pb"
|
"muyu-apiserver/rpc/system/pb"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
@ -37,5 +38,9 @@ func (l *CreateUserLogic) CreateUser(req *types.CreateUserReq) (resp *types.IdRe
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tenantId := ctxdata.GetTenantId(l.ctx); tenantId != "" {
|
||||||
|
_ = l.svcCtx.CrmRepo.AddUserToTenant(l.ctx, rpcResp.Id, tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
return &types.IdResp{Id: rpcResp.Id}, nil
|
return &types.IdResp{Id: rpcResp.Id}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,6 +63,36 @@ func NewCrmRepo(conn sqlx.SqlConn) *CrmRepo {
|
|||||||
return &CrmRepo{conn: conn}
|
return &CrmRepo{conn: conn}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CrmRepo) SearchTenants(ctx context.Context, keyword string, limit int) ([]GraphNode, error) {
|
||||||
|
if limit <= 0 || limit > 50 {
|
||||||
|
limit = 20
|
||||||
|
}
|
||||||
|
nodes := make([]GraphNode, 0)
|
||||||
|
if keyword == "" {
|
||||||
|
if err := r.conn.QueryRowsCtx(ctx, &nodes,
|
||||||
|
"SELECT tenant_id, tenant_name FROM crm_tenant WHERE status = 1 ORDER BY tenant_name LIMIT $1", limit); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := r.conn.QueryRowsCtx(ctx, &nodes,
|
||||||
|
"SELECT tenant_id, tenant_name FROM crm_tenant WHERE status = 1 AND tenant_name LIKE $1 ORDER BY tenant_name LIMIT $2",
|
||||||
|
"%"+keyword+"%", limit); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CrmRepo) AddUserToTenant(ctx context.Context, userId, tenantId string) error {
|
||||||
|
_, err := r.conn.ExecCtx(ctx,
|
||||||
|
`INSERT INTO crm_tenant_user (user_id, tenant_id, is_primary, status)
|
||||||
|
VALUES ($1, $2, 1, 1)
|
||||||
|
ON CONFLICT (user_id, tenant_id) DO NOTHING`,
|
||||||
|
userId, tenantId,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *CrmRepo) VerifyUserTenant(ctx context.Context, userId, tenantId string) (bool, error) {
|
func (r *CrmRepo) VerifyUserTenant(ctx context.Context, userId, tenantId string) (bool, error) {
|
||||||
var count int64
|
var count int64
|
||||||
err := r.conn.QueryRowCtx(ctx, &count,
|
err := r.conn.QueryRowCtx(ctx, &count,
|
||||||
|
|||||||
@ -34,17 +34,13 @@ type CreateMenuReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CreateProductReq struct {
|
type CreateProductReq struct {
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
UnitPieces int64 `json:"unitPieces,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
UnitRolls int64 `json:"unitRolls,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
StockQuantity string `json:"stockQuantity,optional"`
|
Pans []PanInput `json:"pans,optional"`
|
||||||
Location string `json:"location,optional"`
|
|
||||||
CostPrice string `json:"costPrice,optional"`
|
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
|
||||||
Remark string `json:"remark,optional"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateRoleReq struct {
|
type CreateRoleReq struct {
|
||||||
@ -118,7 +114,6 @@ type ListProductReq struct {
|
|||||||
ProductName string `form:"productName,optional"`
|
ProductName string `form:"productName,optional"`
|
||||||
Spec string `form:"spec,optional"`
|
Spec string `form:"spec,optional"`
|
||||||
Color string `form:"color,optional"`
|
Color string `form:"color,optional"`
|
||||||
Location string `form:"location,optional"`
|
|
||||||
Status int64 `form:"status,optional,default=-1"`
|
Status int64 `form:"status,optional,default=-1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,21 +225,147 @@ type PageReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProductInfo struct {
|
type ProductInfo struct {
|
||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
ImageUrl string `json:"imageUrl"`
|
ImageUrl string `json:"imageUrl"`
|
||||||
Spec string `json:"spec"`
|
Spec string `json:"spec"`
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
UnitPieces int64 `json:"unitPieces"`
|
SalesPrice string `json:"salesPrice"`
|
||||||
UnitRolls int64 `json:"unitRolls"`
|
Remark string `json:"remark"`
|
||||||
StockQuantity string `json:"stockQuantity"`
|
Status int64 `json:"status"`
|
||||||
Location string `json:"location"`
|
CreatedAt string `json:"createdAt"`
|
||||||
CostPrice string `json:"costPrice"`
|
UpdatedAt string `json:"updatedAt"`
|
||||||
SalesPrice string `json:"salesPrice"`
|
}
|
||||||
Remark string `json:"remark"`
|
|
||||||
Status int64 `json:"status"`
|
type BoltInfo struct {
|
||||||
CreatedAt string `json:"createdAt"`
|
BoltId string `json:"boltId"`
|
||||||
UpdatedAt string `json:"updatedAt"`
|
PanId string `json:"panId"`
|
||||||
|
LengthM string `json:"lengthM"`
|
||||||
|
SortOrder int64 `json:"sortOrder"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PanInfo struct {
|
||||||
|
PanId string `json:"panId"`
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Position string `json:"position"`
|
||||||
|
SortOrder int64 `json:"sortOrder"`
|
||||||
|
Bolts []BoltInfo `json:"bolts"`
|
||||||
|
BoltCount int64 `json:"boltCount"`
|
||||||
|
TotalLength string `json:"totalLength"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PanInput struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Position string `json:"position,optional"`
|
||||||
|
BoltLengths []string `json:"boltLengths,optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListPanResp struct {
|
||||||
|
List []PanInfo `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SavePansReq struct {
|
||||||
|
Pans []PanInput `json:"pans"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListBoltResp struct {
|
||||||
|
List []BoltInfo `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SaveBoltsReq struct {
|
||||||
|
Lengths []string `json:"lengths"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductTreeResp struct {
|
||||||
|
Product ProductInfo `json:"product"`
|
||||||
|
Pans []PanInfo `json:"pans"`
|
||||||
|
TotalPanCount int64 `json:"totalPanCount"`
|
||||||
|
TotalBoltCount int64 `json:"totalBoltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductSummaryItem struct {
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Spec string `json:"spec"`
|
||||||
|
ColorCount int64 `json:"colorCount"`
|
||||||
|
TotalPanCount int64 `json:"totalPanCount"`
|
||||||
|
TotalBoltCount int64 `json:"totalBoltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
Colors string `json:"colors"`
|
||||||
|
Locations string `json:"locations"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductSummaryResp struct {
|
||||||
|
List []ProductSummaryItem `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColorDetailItem struct {
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
Spec string `json:"spec"`
|
||||||
|
ImageUrl string `json:"imageUrl"`
|
||||||
|
PanCount int64 `json:"panCount"`
|
||||||
|
BoltCount int64 `json:"boltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
Locations string `json:"locations"`
|
||||||
|
SalesPrice string `json:"salesPrice"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListColorDetailReq struct {
|
||||||
|
ProductName string `form:"productName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColorDetailResp struct {
|
||||||
|
List []ColorDetailItem `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PanListItem struct {
|
||||||
|
PanId string `json:"panId"`
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Position string `json:"position"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
Colors string `json:"colors"`
|
||||||
|
BoltCount int64 `json:"boltCount"`
|
||||||
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListPanViewReq struct {
|
||||||
|
Page int64 `form:"page,default=1"`
|
||||||
|
PageSize int64 `form:"pageSize,default=20"`
|
||||||
|
ProductName string `form:"productName,optional"`
|
||||||
|
Position string `form:"position,optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListPanViewResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List []PanListItem `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoltListItem struct {
|
||||||
|
BoltId string `json:"boltId"`
|
||||||
|
PanId string `json:"panId"`
|
||||||
|
LengthM string `json:"lengthM"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
SortOrder int64 `json:"sortOrder"`
|
||||||
|
PanName string `json:"panName"`
|
||||||
|
Position string `json:"position"`
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
ProductName string `json:"productName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListBoltViewReq struct {
|
||||||
|
Page int64 `form:"page,default=1"`
|
||||||
|
PageSize int64 `form:"pageSize,default=20"`
|
||||||
|
ProductName string `form:"productName,optional"`
|
||||||
|
Position string `form:"position,optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListBoltViewResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List []BoltListItem `json:"list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleInfo struct {
|
type RoleInfo struct {
|
||||||
@ -337,8 +458,8 @@ type StockGroupResp struct {
|
|||||||
type StockSummaryResp struct {
|
type StockSummaryResp struct {
|
||||||
ProductCount int64 `json:"productCount"`
|
ProductCount int64 `json:"productCount"`
|
||||||
TotalPieces int64 `json:"totalPieces"`
|
TotalPieces int64 `json:"totalPieces"`
|
||||||
TotalRolls int64 `json:"totalRolls"`
|
TotalPans int64 `json:"totalPans"`
|
||||||
TotalCostValue string `json:"totalCostValue"`
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
TotalSalesValue string `json:"totalSalesValue"`
|
TotalSalesValue string `json:"totalSalesValue"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,17 +480,12 @@ type UpdateMenuReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UpdateProductReq struct {
|
type UpdateProductReq struct {
|
||||||
ProductName string `json:"productName,optional"`
|
ProductName string `json:"productName,optional"`
|
||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
UnitPieces int64 `json:"unitPieces,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
UnitRolls int64 `json:"unitRolls,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
StockQuantity string `json:"stockQuantity,optional"`
|
|
||||||
Location string `json:"location,optional"`
|
|
||||||
CostPrice string `json:"costPrice,optional"`
|
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
|
||||||
Remark string `json:"remark,optional"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateRoleReq struct {
|
type UpdateRoleReq struct {
|
||||||
|
|||||||
10
go.mod
10
go.mod
@ -7,6 +7,8 @@ require (
|
|||||||
github.com/casbin/gorm-adapter/v3 v3.28.0
|
github.com/casbin/gorm-adapter/v3 v3.28.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
github.com/lib/pq v1.12.0
|
github.com/lib/pq v1.12.0
|
||||||
|
github.com/prometheus/client_golang v1.23.2
|
||||||
|
github.com/xuri/excelize/v2 v2.10.1
|
||||||
github.com/zeromicro/go-zero v1.10.0
|
github.com/zeromicro/go-zero v1.10.0
|
||||||
golang.org/x/crypto v0.48.0
|
golang.org/x/crypto v0.48.0
|
||||||
google.golang.org/grpc v1.79.1
|
google.golang.org/grpc v1.79.1
|
||||||
@ -68,14 +70,18 @@ require (
|
|||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.66.1 // indirect
|
github.com/prometheus/common v0.66.1 // indirect
|
||||||
github.com/prometheus/procfs v0.16.1 // indirect
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.17.3 // indirect
|
github.com/redis/go-redis/v9 v9.17.3 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/richardlehane/mscfb v1.0.6 // indirect
|
||||||
|
github.com/richardlehane/msoleps v1.0.6 // indirect
|
||||||
github.com/shopspring/decimal v1.4.0 // indirect
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/tiendc/go-deepcopy v1.7.2 // indirect
|
||||||
|
github.com/xuri/efp v0.0.1 // indirect
|
||||||
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||||
go.etcd.io/etcd/api/v3 v3.5.15 // indirect
|
go.etcd.io/etcd/api/v3 v3.5.15 // indirect
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
|
||||||
go.etcd.io/etcd/client/v3 v3.5.15 // indirect
|
go.etcd.io/etcd/client/v3 v3.5.15 // indirect
|
||||||
@ -97,7 +103,7 @@ require (
|
|||||||
go.uber.org/zap v1.24.0 // indirect
|
go.uber.org/zap v1.24.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
|
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/oauth2 v0.34.0 // indirect
|
golang.org/x/oauth2 v0.34.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
|
|||||||
18
go.sum
18
go.sum
@ -223,6 +223,10 @@ github.com/redis/go-redis/v9 v9.17.3 h1:fN29NdNrE17KttK5Ndf20buqfDZwGNgoUr9qjl1D
|
|||||||
github.com/redis/go-redis/v9 v9.17.3/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
|
github.com/redis/go-redis/v9 v9.17.3/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8=
|
||||||
|
github.com/richardlehane/mscfb v1.0.6/go.mod h1:pe0+IUIc0AHh0+teNzBlJCtSyZdFOGgV4ZK9bsoV+Jo=
|
||||||
|
github.com/richardlehane/msoleps v1.0.6 h1:9BvkpjvD+iUBalUY4esMwv6uBkfOip/Lzvd93jvR9gg=
|
||||||
|
github.com/richardlehane/msoleps v1.0.6/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
@ -248,6 +252,14 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44=
|
||||||
|
github.com/tiendc/go-deepcopy v1.7.2/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
|
||||||
|
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
|
||||||
|
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||||
|
github.com/xuri/excelize/v2 v2.10.1 h1:V62UlqopMqha3kOpnlHy2CcRVw1V8E63jFoWUmMzxN0=
|
||||||
|
github.com/xuri/excelize/v2 v2.10.1/go.mod h1:iG5tARpgaEeIhTqt3/fgXCGoBRt4hNXgCp3tfXKoOIc=
|
||||||
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
|
||||||
|
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
@ -317,6 +329,8 @@ golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
|||||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
||||||
|
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||||
|
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@ -348,8 +362,8 @@ golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
|||||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|||||||
146
model/invproductboltmodel.go
Normal file
146
model/invproductboltmodel.go
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ InvProductBoltModel = (*customInvProductBoltModel)(nil)
|
||||||
|
|
||||||
|
// BoltListItem is the flat view row for the bolt-dimension panel.
|
||||||
|
// Color comes from the bolt itself, spec is omitted (product-level only).
|
||||||
|
type BoltListItem struct {
|
||||||
|
BoltId string `db:"bolt_id"`
|
||||||
|
PanId string `db:"pan_id"`
|
||||||
|
LengthM float64 `db:"length_m"`
|
||||||
|
Color string `db:"color"`
|
||||||
|
SortOrder int64 `db:"sort_order"`
|
||||||
|
PanName string `db:"pan_name"`
|
||||||
|
Position string `db:"position"`
|
||||||
|
ProductId string `db:"product_id"`
|
||||||
|
ProductName string `db:"product_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
InvProductBoltModel interface {
|
||||||
|
invProductBoltModel
|
||||||
|
FindByPanId(ctx context.Context, panId string) ([]*InvProductBolt, error)
|
||||||
|
FindByProductId(ctx context.Context, productId string) ([]*InvProductBolt, error)
|
||||||
|
DeleteByPanId(ctx context.Context, panId string) error
|
||||||
|
DeleteByProductId(ctx context.Context, productId string) error
|
||||||
|
BulkReplace(ctx context.Context, panId, tenantId string, bolts []*InvProductBolt) error
|
||||||
|
FindBoltList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*BoltListItem, int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customInvProductBoltModel struct {
|
||||||
|
*defaultInvProductBoltModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewInvProductBoltModel(conn sqlx.SqlConn) InvProductBoltModel {
|
||||||
|
return &customInvProductBoltModel{
|
||||||
|
defaultInvProductBoltModel: newInvProductBoltModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductBoltModel) FindByPanId(ctx context.Context, panId string) ([]*InvProductBolt, error) {
|
||||||
|
var list []*InvProductBolt
|
||||||
|
query := fmt.Sprintf("SELECT %s FROM %s WHERE `pan_id` = ? ORDER BY `sort_order`", invProductBoltRows, m.table)
|
||||||
|
err := m.conn.QueryRowsCtx(ctx, &list, query, panId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductBoltModel) FindByProductId(ctx context.Context, productId string) ([]*InvProductBolt, error) {
|
||||||
|
var list []*InvProductBolt
|
||||||
|
query := fmt.Sprintf(
|
||||||
|
"SELECT b.`id`, b.`bolt_id`, b.`pan_id`, b.`length_m`, b.`sort_order`, b.`tenant_id`, b.`created_at`, b.`updated_at` "+
|
||||||
|
"FROM %s b INNER JOIN `inv_product_pan` p ON b.`pan_id` = p.`pan_id` "+
|
||||||
|
"WHERE p.`product_id` = ? ORDER BY p.`sort_order`, b.`sort_order`", m.table)
|
||||||
|
err := m.conn.QueryRowsCtx(ctx, &list, query, productId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductBoltModel) DeleteByPanId(ctx context.Context, panId string) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE `pan_id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, panId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductBoltModel) DeleteByProductId(ctx context.Context, productId string) error {
|
||||||
|
query := fmt.Sprintf(
|
||||||
|
"DELETE b FROM %s b INNER JOIN `inv_product_pan` p ON b.`pan_id` = p.`pan_id` WHERE p.`product_id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, productId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductBoltModel) FindBoltList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*BoltListItem, int64, error) {
|
||||||
|
where := "WHERE b.tenant_id = ? AND p.deleted_at IS NULL"
|
||||||
|
args := []interface{}{tenantId}
|
||||||
|
|
||||||
|
if productName != "" {
|
||||||
|
where += " AND p.product_name LIKE ?"
|
||||||
|
args = append(args, "%"+productName+"%")
|
||||||
|
}
|
||||||
|
if position != "" {
|
||||||
|
where += " AND pan.position LIKE ?"
|
||||||
|
args = append(args, "%"+position+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
countQuery := fmt.Sprintf(`SELECT COUNT(*)
|
||||||
|
FROM %s b
|
||||||
|
JOIN inv_product_pan pan ON pan.pan_id = b.pan_id
|
||||||
|
JOIN inv_product p ON p.product_id = pan.product_id
|
||||||
|
%s`, m.table, where)
|
||||||
|
var total int64
|
||||||
|
if err := m.conn.QueryRowCtx(ctx, &total, countQuery, args...); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`SELECT b.bolt_id, b.pan_id, b.length_m, b.color, b.sort_order,
|
||||||
|
pan.name AS pan_name, pan.position,
|
||||||
|
p.product_id, p.product_name
|
||||||
|
FROM %s b
|
||||||
|
JOIN inv_product_pan pan ON pan.pan_id = b.pan_id
|
||||||
|
JOIN inv_product p ON p.product_id = pan.product_id
|
||||||
|
%s
|
||||||
|
ORDER BY b.created_at DESC
|
||||||
|
LIMIT ? OFFSET ?`, m.table, where)
|
||||||
|
args = append(args, pageSize, (page-1)*pageSize)
|
||||||
|
|
||||||
|
var list []*BoltListItem
|
||||||
|
if err := m.conn.QueryRowsCtx(ctx, &list, query, args...); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return list, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductBoltModel) BulkReplace(ctx context.Context, panId, tenantId string, bolts []*InvProductBolt) error {
|
||||||
|
return m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
delQuery := fmt.Sprintf("DELETE FROM %s WHERE `pan_id` = ?", m.table)
|
||||||
|
if _, err := session.ExecCtx(ctx, delQuery, panId); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(bolts) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
placeholder := "(?, ?, ?, ?, ?, ?)"
|
||||||
|
placeholders := make([]string, len(bolts))
|
||||||
|
args := make([]interface{}, 0, len(bolts)*6)
|
||||||
|
for i, b := range bolts {
|
||||||
|
placeholders[i] = placeholder
|
||||||
|
args = append(args, b.BoltId, panId, b.LengthM, b.Color, b.SortOrder, tenantId)
|
||||||
|
}
|
||||||
|
insQuery := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", m.table, invProductBoltRowsExpectAutoSet, strings.Join(placeholders, ","))
|
||||||
|
_, err := session.ExecCtx(ctx, insQuery, args...)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
95
model/invproductboltmodel_gen.go
Normal file
95
model/invproductboltmodel_gen.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
invProductBoltFieldNames = builder.RawFieldNames(&InvProductBolt{})
|
||||||
|
invProductBoltRows = strings.Join(invProductBoltFieldNames, ",")
|
||||||
|
invProductBoltRowsExpectAutoSet = strings.Join(stringx.Remove(invProductBoltFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
invProductBoltRowsWithPlaceHolder = strings.Join(stringx.Remove(invProductBoltFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
invProductBoltModel interface {
|
||||||
|
Insert(ctx context.Context, data *InvProductBolt) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*InvProductBolt, error)
|
||||||
|
FindOneByBoltId(ctx context.Context, boltId string) (*InvProductBolt, error)
|
||||||
|
Update(ctx context.Context, data *InvProductBolt) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultInvProductBoltModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
InvProductBolt struct {
|
||||||
|
Id int64 `db:"id"`
|
||||||
|
BoltId string `db:"bolt_id"`
|
||||||
|
PanId string `db:"pan_id"`
|
||||||
|
LengthM float64 `db:"length_m"`
|
||||||
|
Color string `db:"color"`
|
||||||
|
SortOrder int64 `db:"sort_order"`
|
||||||
|
TenantId string `db:"tenant_id"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newInvProductBoltModel(conn sqlx.SqlConn) *defaultInvProductBoltModel {
|
||||||
|
return &defaultInvProductBoltModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`inv_product_bolt`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductBoltModel) Insert(ctx context.Context, data *InvProductBolt) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?)", m.table, invProductBoltRowsExpectAutoSet)
|
||||||
|
return m.conn.ExecCtx(ctx, query, data.BoltId, data.PanId, data.LengthM, data.Color, data.SortOrder, data.TenantId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductBoltModel) FindOne(ctx context.Context, id int64) (*InvProductBolt, error) {
|
||||||
|
query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? LIMIT 1", invProductBoltRows, m.table)
|
||||||
|
var resp InvProductBolt
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductBoltModel) FindOneByBoltId(ctx context.Context, boltId string) (*InvProductBolt, error) {
|
||||||
|
query := fmt.Sprintf("SELECT %s FROM %s WHERE `bolt_id` = ? LIMIT 1", invProductBoltRows, m.table)
|
||||||
|
var resp InvProductBolt
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, boltId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductBoltModel) Update(ctx context.Context, data *InvProductBolt) error {
|
||||||
|
query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, invProductBoltRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.BoltId, data.PanId, data.LengthM, data.Color, data.SortOrder, data.TenantId, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductBoltModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductBoltModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
@ -10,19 +11,46 @@ import (
|
|||||||
|
|
||||||
var _ InvProductModel = (*customInvProductModel)(nil)
|
var _ InvProductModel = (*customInvProductModel)(nil)
|
||||||
|
|
||||||
|
// StockGroupResult is kept for GroupBy queries (color / location).
|
||||||
type StockGroupResult struct {
|
type StockGroupResult struct {
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
Count int64 `db:"count"`
|
Count int64 `db:"count"`
|
||||||
Quantity float64 `db:"quantity"`
|
Quantity float64 `db:"quantity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProductSummary struct {
|
||||||
|
ProductName string `db:"product_name"`
|
||||||
|
Spec string `db:"spec"`
|
||||||
|
ColorCount int64 `db:"color_count"`
|
||||||
|
TotalPanCount int64 `db:"total_pan_count"`
|
||||||
|
TotalBoltCount int64 `db:"total_bolt_count"`
|
||||||
|
TotalLengthM float64 `db:"total_length_m"`
|
||||||
|
Colors string `db:"colors"`
|
||||||
|
Locations string `db:"locations"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColorDetail struct {
|
||||||
|
ProductId string `db:"product_id"`
|
||||||
|
ProductName string `db:"product_name"`
|
||||||
|
Color string `db:"color"`
|
||||||
|
Spec string `db:"spec"`
|
||||||
|
ImageUrl string `db:"image_url"`
|
||||||
|
SalesPrice float64 `db:"sales_price"`
|
||||||
|
PanCount int64 `db:"pan_count"`
|
||||||
|
BoltCount int64 `db:"bolt_count"`
|
||||||
|
TotalLengthM float64 `db:"total_length_m"`
|
||||||
|
Locations string `db:"locations"`
|
||||||
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
InvProductModel interface {
|
InvProductModel interface {
|
||||||
invProductModel
|
invProductModel
|
||||||
FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color, location string, status int64) ([]*InvProduct, int64, error)
|
FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color string, status int64) ([]*InvProduct, int64, error)
|
||||||
FindStockSummary(ctx context.Context, tenantId string) (productCount, totalPieces, totalRolls int64, totalCostValue, totalSalesValue float64, err error)
|
FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error)
|
||||||
|
FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, error)
|
||||||
FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
||||||
FindGroupByLocation(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
FindGroupByLocation(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
||||||
|
BulkInsert(ctx context.Context, products []*InvProduct) (int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
customInvProductModel struct {
|
customInvProductModel struct {
|
||||||
@ -36,7 +64,48 @@ func NewInvProductModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Opti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color, location string, status int64) ([]*InvProduct, int64, error) {
|
const bulkBatchSize = 200
|
||||||
|
|
||||||
|
func (m *customInvProductModel) BulkInsert(ctx context.Context, products []*InvProduct) (int64, error) {
|
||||||
|
if len(products) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalAffected int64
|
||||||
|
for i := 0; i < len(products); i += bulkBatchSize {
|
||||||
|
end := i + bulkBatchSize
|
||||||
|
if end > len(products) {
|
||||||
|
end = len(products)
|
||||||
|
}
|
||||||
|
batch := products[i:end]
|
||||||
|
|
||||||
|
placeholder := "(" + strings.Repeat("?,", 9) + "?)"
|
||||||
|
placeholders := make([]string, len(batch))
|
||||||
|
args := make([]interface{}, 0, len(batch)*10)
|
||||||
|
|
||||||
|
for j, p := range batch {
|
||||||
|
placeholders[j] = placeholder
|
||||||
|
args = append(args,
|
||||||
|
p.ProductId, p.ProductName, p.ImageUrl, p.Spec, p.Color,
|
||||||
|
p.SalesPrice, p.Remark, p.Status, p.TenantId, p.DeletedAt,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s",
|
||||||
|
m.table, invProductRowsExpectAutoSet, strings.Join(placeholders, ","))
|
||||||
|
|
||||||
|
result, err := m.ExecNoCacheCtx(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return totalAffected, fmt.Errorf("batch %d-%d: %w", i, end-1, err)
|
||||||
|
}
|
||||||
|
n, _ := result.RowsAffected()
|
||||||
|
totalAffected += n
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalAffected, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color string, status int64) ([]*InvProduct, int64, error) {
|
||||||
where := "WHERE deleted_at IS NULL AND tenant_id = ?"
|
where := "WHERE deleted_at IS NULL AND tenant_id = ?"
|
||||||
args := []interface{}{tenantId}
|
args := []interface{}{tenantId}
|
||||||
|
|
||||||
@ -52,10 +121,6 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p
|
|||||||
where += " AND color = ?"
|
where += " AND color = ?"
|
||||||
args = append(args, color)
|
args = append(args, color)
|
||||||
}
|
}
|
||||||
if location != "" {
|
|
||||||
where += " AND location = ?"
|
|
||||||
args = append(args, location)
|
|
||||||
}
|
|
||||||
if status >= 0 {
|
if status >= 0 {
|
||||||
where += " AND status = ?"
|
where += " AND status = ?"
|
||||||
args = append(args, status)
|
args = append(args, status)
|
||||||
@ -79,25 +144,37 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p
|
|||||||
return list, total, nil
|
return list, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *customInvProductModel) FindStockSummary(ctx context.Context, tenantId string) (productCount, totalPieces, totalRolls int64, totalCostValue, totalSalesValue float64, err error) {
|
func (m *customInvProductModel) FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error) {
|
||||||
var summary struct {
|
var list []*ProductSummary
|
||||||
ProductCount int64 `db:"product_count"`
|
query := `SELECT p.product_name, p.spec,
|
||||||
TotalPieces int64 `db:"total_pieces"`
|
COUNT(DISTINCT p.product_id) AS color_count,
|
||||||
TotalRolls int64 `db:"total_rolls"`
|
COUNT(DISTINCT pan.pan_id) AS total_pan_count,
|
||||||
TotalCostValue float64 `db:"total_cost_value"`
|
COUNT(bolt.bolt_id) AS total_bolt_count,
|
||||||
TotalSalesValue float64 `db:"total_sales_value"`
|
COALESCE(SUM(bolt.length_m), 0) AS total_length_m,
|
||||||
}
|
GROUP_CONCAT(DISTINCT p.color) AS colors,
|
||||||
query := fmt.Sprintf("SELECT COUNT(*) AS product_count, COALESCE(SUM(unit_pieces), 0) AS total_pieces, COALESCE(SUM(unit_rolls), 0) AS total_rolls, COALESCE(SUM(stock_quantity * cost_price), 0) AS total_cost_value, COALESCE(SUM(stock_quantity * sales_price), 0) AS total_sales_value FROM %s WHERE deleted_at IS NULL AND tenant_id = ?", m.table)
|
GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position) AS locations
|
||||||
err = m.QueryRowNoCacheCtx(ctx, &summary, query, tenantId)
|
FROM ` + m.table + ` p
|
||||||
|
LEFT JOIN ` + "`inv_product_pan`" + ` pan ON pan.product_id = p.product_id
|
||||||
|
LEFT JOIN ` + "`inv_product_bolt`" + ` bolt ON bolt.pan_id = pan.pan_id
|
||||||
|
WHERE p.tenant_id = ? AND p.deleted_at IS NULL
|
||||||
|
GROUP BY p.product_name, p.spec
|
||||||
|
ORDER BY p.product_name`
|
||||||
|
err := m.QueryRowsNoCacheCtx(ctx, &list, query, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, 0, 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return summary.ProductCount, summary.TotalPieces, summary.TotalRolls, summary.TotalCostValue, summary.TotalSalesValue, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *customInvProductModel) FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error) {
|
func (m *customInvProductModel) FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error) {
|
||||||
var list []StockGroupResult
|
var list []StockGroupResult
|
||||||
query := fmt.Sprintf("SELECT color AS name, COUNT(*) AS count, COALESCE(SUM(stock_quantity), 0) AS quantity FROM %s WHERE deleted_at IS NULL AND tenant_id = ? GROUP BY color ORDER BY count DESC", m.table)
|
query := `SELECT p.color AS name, COUNT(DISTINCT p.product_id) AS count,
|
||||||
|
COALESCE(SUM(bolt.length_m), 0) AS quantity
|
||||||
|
FROM ` + m.table + ` p
|
||||||
|
LEFT JOIN ` + "`inv_product_pan`" + ` pan ON pan.product_id = p.product_id
|
||||||
|
LEFT JOIN ` + "`inv_product_bolt`" + ` bolt ON bolt.pan_id = pan.pan_id
|
||||||
|
WHERE p.tenant_id = ? AND p.deleted_at IS NULL
|
||||||
|
GROUP BY p.color ORDER BY count DESC`
|
||||||
err := m.QueryRowsNoCacheCtx(ctx, &list, query, tenantId)
|
err := m.QueryRowsNoCacheCtx(ctx, &list, query, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -107,10 +184,36 @@ func (m *customInvProductModel) FindGroupByColor(ctx context.Context, tenantId s
|
|||||||
|
|
||||||
func (m *customInvProductModel) FindGroupByLocation(ctx context.Context, tenantId string) ([]StockGroupResult, error) {
|
func (m *customInvProductModel) FindGroupByLocation(ctx context.Context, tenantId string) ([]StockGroupResult, error) {
|
||||||
var list []StockGroupResult
|
var list []StockGroupResult
|
||||||
query := fmt.Sprintf("SELECT location AS name, COUNT(*) AS count, COALESCE(SUM(stock_quantity), 0) AS quantity FROM %s WHERE deleted_at IS NULL AND tenant_id = ? GROUP BY location ORDER BY count DESC", m.table)
|
query := `SELECT pan.position AS name, COUNT(DISTINCT p.product_id) AS count,
|
||||||
|
COALESCE(SUM(bolt.length_m), 0) AS quantity
|
||||||
|
FROM ` + m.table + ` p
|
||||||
|
JOIN ` + "`inv_product_pan`" + ` pan ON pan.product_id = p.product_id
|
||||||
|
LEFT JOIN ` + "`inv_product_bolt`" + ` bolt ON bolt.pan_id = pan.pan_id
|
||||||
|
WHERE p.tenant_id = ? AND p.deleted_at IS NULL AND pan.position != ''
|
||||||
|
GROUP BY pan.position ORDER BY count DESC`
|
||||||
err := m.QueryRowsNoCacheCtx(ctx, &list, query, tenantId)
|
err := m.QueryRowsNoCacheCtx(ctx, &list, query, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductModel) FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, error) {
|
||||||
|
var list []*ColorDetail
|
||||||
|
query := `SELECT p.product_id, p.product_name, p.color, p.spec, p.image_url, p.sales_price,
|
||||||
|
COUNT(DISTINCT pan.pan_id) AS pan_count,
|
||||||
|
COUNT(bolt.bolt_id) AS bolt_count,
|
||||||
|
COALESCE(SUM(bolt.length_m), 0) AS total_length_m,
|
||||||
|
GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position) AS locations
|
||||||
|
FROM ` + m.table + ` p
|
||||||
|
LEFT JOIN ` + "`inv_product_pan`" + ` pan ON pan.product_id = p.product_id
|
||||||
|
LEFT JOIN ` + "`inv_product_bolt`" + ` bolt ON bolt.pan_id = pan.pan_id
|
||||||
|
WHERE p.tenant_id = ? AND p.deleted_at IS NULL AND p.product_name = ?
|
||||||
|
GROUP BY p.product_id
|
||||||
|
ORDER BY p.color`
|
||||||
|
err := m.QueryRowsNoCacheCtx(ctx, &list, query, tenantId, productName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -45,23 +45,19 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
InvProduct struct {
|
InvProduct struct {
|
||||||
Id int64 `db:"id"`
|
Id int64 `db:"id"`
|
||||||
ProductId string `db:"product_id"`
|
ProductId string `db:"product_id"`
|
||||||
ProductName string `db:"product_name"`
|
ProductName string `db:"product_name"`
|
||||||
ImageUrl string `db:"image_url"`
|
ImageUrl string `db:"image_url"`
|
||||||
Spec string `db:"spec"`
|
Spec string `db:"spec"`
|
||||||
Color string `db:"color"`
|
Color string `db:"color"`
|
||||||
UnitPieces int64 `db:"unit_pieces"`
|
SalesPrice float64 `db:"sales_price"`
|
||||||
UnitRolls int64 `db:"unit_rolls"`
|
Remark sql.NullString `db:"remark"`
|
||||||
StockQuantity float64 `db:"stock_quantity"`
|
Status int64 `db:"status"`
|
||||||
Location string `db:"location"`
|
TenantId string `db:"tenant_id"`
|
||||||
CostPrice float64 `db:"cost_price"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
SalesPrice float64 `db:"sales_price"`
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
Remark sql.NullString `db:"remark"`
|
DeletedAt sql.NullTime `db:"deleted_at"`
|
||||||
Status int64 `db:"status"` // 1:enabled 0:disabled
|
|
||||||
CreatedAt time.Time `db:"created_at"`
|
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
|
||||||
DeletedAt sql.NullTime `db:"deleted_at"`
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -150,8 +146,8 @@ func (m *defaultInvProductModel) Insert(ctx context.Context, data *InvProduct) (
|
|||||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||||
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invProductRowsExpectAutoSet)
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invProductRowsExpectAutoSet)
|
||||||
return conn.ExecCtx(ctx, query, data.ProductId, data.ProductName, data.ImageUrl, data.Spec, data.Color, data.UnitPieces, data.UnitRolls, data.StockQuantity, data.Location, data.CostPrice, data.SalesPrice, data.Remark, data.Status, data.DeletedAt)
|
return conn.ExecCtx(ctx, query, data.ProductId, data.ProductName, data.ImageUrl, data.Spec, data.Color, data.SalesPrice, data.Remark, data.Status, data.TenantId, data.DeletedAt)
|
||||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@ -167,7 +163,7 @@ func (m *defaultInvProductModel) Update(ctx context.Context, newData *InvProduct
|
|||||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, invProductRowsWithPlaceHolder)
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, invProductRowsWithPlaceHolder)
|
||||||
return conn.ExecCtx(ctx, query, newData.ProductId, newData.ProductName, newData.ImageUrl, newData.Spec, newData.Color, newData.UnitPieces, newData.UnitRolls, newData.StockQuantity, newData.Location, newData.CostPrice, newData.SalesPrice, newData.Remark, newData.Status, newData.DeletedAt, newData.Id)
|
return conn.ExecCtx(ctx, query, newData.ProductId, newData.ProductName, newData.ImageUrl, newData.Spec, newData.Color, newData.SalesPrice, newData.Remark, newData.Status, newData.TenantId, newData.DeletedAt, newData.Id)
|
||||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
123
model/invproductpanmodel.go
Normal file
123
model/invproductpanmodel.go
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ InvProductPanModel = (*customInvProductPanModel)(nil)
|
||||||
|
|
||||||
|
// PanListItem is the aggregated view row for the pan-dimension panel.
|
||||||
|
// Colors is aggregated from the bolts on this pan; spec is omitted (product-level only).
|
||||||
|
type PanListItem struct {
|
||||||
|
PanId string `db:"pan_id"`
|
||||||
|
ProductId string `db:"product_id"`
|
||||||
|
Name string `db:"name"`
|
||||||
|
Position string `db:"position"`
|
||||||
|
ProductName string `db:"product_name"`
|
||||||
|
Colors string `db:"colors"`
|
||||||
|
BoltCount int64 `db:"bolt_count"`
|
||||||
|
TotalLengthM float64 `db:"total_length_m"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
InvProductPanModel interface {
|
||||||
|
invProductPanModel
|
||||||
|
FindByProductId(ctx context.Context, productId string) ([]*InvProductPan, error)
|
||||||
|
DeleteByProductId(ctx context.Context, productId string) error
|
||||||
|
BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) error
|
||||||
|
FindPanList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*PanListItem, int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customInvProductPanModel struct {
|
||||||
|
*defaultInvProductPanModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewInvProductPanModel(conn sqlx.SqlConn) InvProductPanModel {
|
||||||
|
return &customInvProductPanModel{
|
||||||
|
defaultInvProductPanModel: newInvProductPanModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductPanModel) FindByProductId(ctx context.Context, productId string) ([]*InvProductPan, error) {
|
||||||
|
var list []*InvProductPan
|
||||||
|
query := fmt.Sprintf("SELECT %s FROM %s WHERE `product_id` = ? ORDER BY `sort_order`", invProductPanRows, m.table)
|
||||||
|
err := m.conn.QueryRowsCtx(ctx, &list, query, productId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductPanModel) DeleteByProductId(ctx context.Context, productId string) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE `product_id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, productId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*PanListItem, int64, error) {
|
||||||
|
where := "WHERE pan.tenant_id = ? AND p.deleted_at IS NULL"
|
||||||
|
args := []interface{}{tenantId}
|
||||||
|
|
||||||
|
if productName != "" {
|
||||||
|
where += " AND p.product_name LIKE ?"
|
||||||
|
args = append(args, "%"+productName+"%")
|
||||||
|
}
|
||||||
|
if position != "" {
|
||||||
|
where += " AND pan.position LIKE ?"
|
||||||
|
args = append(args, "%"+position+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
countQuery := fmt.Sprintf(`SELECT COUNT(DISTINCT pan.pan_id)
|
||||||
|
FROM %s pan JOIN inv_product p ON p.product_id = pan.product_id %s`, m.table, where)
|
||||||
|
var total int64
|
||||||
|
if err := m.conn.QueryRowCtx(ctx, &total, countQuery, args...); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.name, pan.position,
|
||||||
|
p.product_name,
|
||||||
|
COALESCE(GROUP_CONCAT(DISTINCT b.color ORDER BY b.color SEPARATOR ', '), '') AS colors,
|
||||||
|
COUNT(b.bolt_id) AS bolt_count,
|
||||||
|
COALESCE(SUM(b.length_m), 0) AS total_length_m
|
||||||
|
FROM %s pan
|
||||||
|
JOIN inv_product p ON p.product_id = pan.product_id
|
||||||
|
LEFT JOIN inv_product_bolt b ON b.pan_id = pan.pan_id
|
||||||
|
%s
|
||||||
|
GROUP BY pan.pan_id
|
||||||
|
ORDER BY pan.created_at DESC
|
||||||
|
LIMIT ? OFFSET ?`, m.table, where)
|
||||||
|
args = append(args, pageSize, (page-1)*pageSize)
|
||||||
|
|
||||||
|
var list []*PanListItem
|
||||||
|
if err := m.conn.QueryRowsCtx(ctx, &list, query, args...); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return list, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customInvProductPanModel) BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) error {
|
||||||
|
return m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
delQuery := fmt.Sprintf("DELETE FROM %s WHERE `product_id` = ?", m.table)
|
||||||
|
if _, err := session.ExecCtx(ctx, delQuery, productId); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(pans) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
placeholder := "(?, ?, ?, ?, ?, ?)"
|
||||||
|
placeholders := make([]string, len(pans))
|
||||||
|
args := make([]interface{}, 0, len(pans)*6)
|
||||||
|
for i, p := range pans {
|
||||||
|
placeholders[i] = placeholder
|
||||||
|
args = append(args, p.PanId, productId, p.Name, p.Position, p.SortOrder, tenantId)
|
||||||
|
}
|
||||||
|
insQuery := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", m.table, invProductPanRowsExpectAutoSet, strings.Join(placeholders, ","))
|
||||||
|
_, err := session.ExecCtx(ctx, insQuery, args...)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
95
model/invproductpanmodel_gen.go
Normal file
95
model/invproductpanmodel_gen.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
invProductPanFieldNames = builder.RawFieldNames(&InvProductPan{})
|
||||||
|
invProductPanRows = strings.Join(invProductPanFieldNames, ",")
|
||||||
|
invProductPanRowsExpectAutoSet = strings.Join(stringx.Remove(invProductPanFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
invProductPanRowsWithPlaceHolder = strings.Join(stringx.Remove(invProductPanFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
invProductPanModel interface {
|
||||||
|
Insert(ctx context.Context, data *InvProductPan) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*InvProductPan, error)
|
||||||
|
FindOneByPanId(ctx context.Context, panId string) (*InvProductPan, error)
|
||||||
|
Update(ctx context.Context, data *InvProductPan) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultInvProductPanModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
InvProductPan struct {
|
||||||
|
Id int64 `db:"id"`
|
||||||
|
PanId string `db:"pan_id"`
|
||||||
|
ProductId string `db:"product_id"`
|
||||||
|
Name string `db:"name"`
|
||||||
|
Position string `db:"position"`
|
||||||
|
SortOrder int64 `db:"sort_order"`
|
||||||
|
TenantId string `db:"tenant_id"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newInvProductPanModel(conn sqlx.SqlConn) *defaultInvProductPanModel {
|
||||||
|
return &defaultInvProductPanModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`inv_product_pan`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductPanModel) Insert(ctx context.Context, data *InvProductPan) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?)", m.table, invProductPanRowsExpectAutoSet)
|
||||||
|
return m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.Name, data.Position, data.SortOrder, data.TenantId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductPanModel) FindOne(ctx context.Context, id int64) (*InvProductPan, error) {
|
||||||
|
query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? LIMIT 1", invProductPanRows, m.table)
|
||||||
|
var resp InvProductPan
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductPanModel) FindOneByPanId(ctx context.Context, panId string) (*InvProductPan, error) {
|
||||||
|
query := fmt.Sprintf("SELECT %s FROM %s WHERE `pan_id` = ? LIMIT 1", invProductPanRows, m.table)
|
||||||
|
var resp InvProductPan
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, panId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductPanModel) Update(ctx context.Context, data *InvProductPan) error {
|
||||||
|
query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, invProductPanRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.Name, data.Position, data.SortOrder, data.TenantId, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductPanModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInvProductPanModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
@ -46,6 +46,7 @@ type (
|
|||||||
|
|
||||||
SysRole struct {
|
SysRole struct {
|
||||||
Id int64 `db:"id"`
|
Id int64 `db:"id"`
|
||||||
|
TenantId string `db:"tenant_id"`
|
||||||
RoleId string `db:"role_id"`
|
RoleId string `db:"role_id"`
|
||||||
RoleName string `db:"role_name"`
|
RoleName string `db:"role_name"`
|
||||||
RoleKey string `db:"role_key"`
|
RoleKey string `db:"role_key"`
|
||||||
@ -142,8 +143,8 @@ func (m *defaultSysRoleModel) Insert(ctx context.Context, data *SysRole) (sql.Re
|
|||||||
sysRoleRoleIdKey := fmt.Sprintf("%s%v", cacheSysRoleRoleIdPrefix, data.RoleId)
|
sysRoleRoleIdKey := fmt.Sprintf("%s%v", cacheSysRoleRoleIdPrefix, data.RoleId)
|
||||||
sysRoleRoleKeyKey := fmt.Sprintf("%s%v", cacheSysRoleRoleKeyPrefix, data.RoleKey)
|
sysRoleRoleKeyKey := fmt.Sprintf("%s%v", cacheSysRoleRoleKeyPrefix, data.RoleKey)
|
||||||
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, sysRoleRowsExpectAutoSet)
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, sysRoleRowsExpectAutoSet)
|
||||||
return conn.ExecCtx(ctx, query, data.RoleId, data.RoleName, data.RoleKey, data.RoleDesc, data.SortOrder, data.Status)
|
return conn.ExecCtx(ctx, query, data.TenantId, data.RoleId, data.RoleName, data.RoleKey, data.RoleDesc, data.SortOrder, data.Status)
|
||||||
}, sysRoleIdKey, sysRoleRoleIdKey, sysRoleRoleKeyKey)
|
}, sysRoleIdKey, sysRoleRoleIdKey, sysRoleRoleKeyKey)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@ -159,7 +160,7 @@ func (m *defaultSysRoleModel) Update(ctx context.Context, newData *SysRole) erro
|
|||||||
sysRoleRoleKeyKey := fmt.Sprintf("%s%v", cacheSysRoleRoleKeyPrefix, data.RoleKey)
|
sysRoleRoleKeyKey := fmt.Sprintf("%s%v", cacheSysRoleRoleKeyPrefix, data.RoleKey)
|
||||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, sysRoleRowsWithPlaceHolder)
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, sysRoleRowsWithPlaceHolder)
|
||||||
return conn.ExecCtx(ctx, query, newData.RoleId, newData.RoleName, newData.RoleKey, newData.RoleDesc, newData.SortOrder, newData.Status, newData.Id)
|
return conn.ExecCtx(ctx, query, newData.TenantId, newData.RoleId, newData.RoleName, newData.RoleKey, newData.RoleDesc, newData.SortOrder, newData.Status, newData.Id)
|
||||||
}, sysRoleIdKey, sysRoleRoleIdKey, sysRoleRoleKeyKey)
|
}, sysRoleIdKey, sysRoleRoleIdKey, sysRoleRoleKeyKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
102
pkg/excelparse/miaozhang.go
Normal file
102
pkg/excelparse/miaozhang.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package excelparse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MiaozhangParser handles Excel exports from 秒账 (miaozhang.cn).
|
||||||
|
//
|
||||||
|
// Expected headers:
|
||||||
|
// 图片1 | 图片2 | 图片3 | 名称 | 规格型号 | 颜色 | 条形码 | 匹数 | 库存数量 | 成本均价 | 参考售价 | 备注 | 更新日期
|
||||||
|
type MiaozhangParser struct{}
|
||||||
|
|
||||||
|
func (p *MiaozhangParser) Name() string { return "秒账" }
|
||||||
|
|
||||||
|
func (p *MiaozhangParser) Match(headers []string) bool {
|
||||||
|
required := map[string]bool{"名称": false, "规格型号": false, "颜色": false, "匹数": false, "库存数量": false}
|
||||||
|
for _, h := range headers {
|
||||||
|
h = strings.TrimSpace(h)
|
||||||
|
if _, ok := required[h]; ok {
|
||||||
|
required[h] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, found := range required {
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MiaozhangParser) ParseRows(headers []string, rows [][]string) (*ParseResult, error) {
|
||||||
|
idx := buildIndex(headers)
|
||||||
|
|
||||||
|
var products []ParsedProduct
|
||||||
|
skipped := 0
|
||||||
|
|
||||||
|
for _, row := range rows {
|
||||||
|
name := colVal(row, idx["名称"])
|
||||||
|
|
||||||
|
if name == "" || strings.HasPrefix(name, "总") {
|
||||||
|
skipped++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rolls, _ := strconv.ParseInt(colVal(row, idx["匹数"]), 10, 64)
|
||||||
|
|
||||||
|
products = append(products, ParsedProduct{
|
||||||
|
ProductName: name,
|
||||||
|
Spec: colVal(row, idx["规格型号"]),
|
||||||
|
Color: colVal(row, idx["颜色"]),
|
||||||
|
UnitRolls: rolls,
|
||||||
|
StockQuantity: stripUnit(colVal(row, idx["库存数量"])),
|
||||||
|
CostPrice: stripCurrency(colVal(row, idx["成本均价"])),
|
||||||
|
SalesPrice: stripCurrency(colVal(row, idx["参考售价"])),
|
||||||
|
Remark: colVal(row, idx["备注"]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ParseResult{Products: products, SkippedRows: skipped}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildIndex(headers []string) map[string]int {
|
||||||
|
m := make(map[string]int, len(headers))
|
||||||
|
for i, h := range headers {
|
||||||
|
m[strings.TrimSpace(h)] = i
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func colVal(row []string, idx int) string {
|
||||||
|
if idx < 0 || idx >= len(row) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(row[idx])
|
||||||
|
}
|
||||||
|
|
||||||
|
// stripUnit removes trailing unit markers like "米", "kg", etc.
|
||||||
|
func stripUnit(s string) string {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
for _, suffix := range []string{"米", "m", "kg", "KG"} {
|
||||||
|
s = strings.TrimSuffix(s, suffix)
|
||||||
|
}
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
if s == "" {
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// stripCurrency removes leading ¥ / $ / ¥ symbols.
|
||||||
|
func stripCurrency(s string) string {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
for _, prefix := range []string{"¥", "¥", "$", "$"} {
|
||||||
|
s = strings.TrimPrefix(s, prefix)
|
||||||
|
}
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
if s == "" {
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
167
pkg/excelparse/parse.go
Normal file
167
pkg/excelparse/parse.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
package excelparse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xuri/excelize/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var parsers []FormatParser
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
parsers = append(parsers, &MiaozhangParser{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterParser adds a format parser at runtime (e.g. for plugins).
|
||||||
|
func RegisterParser(p FormatParser) {
|
||||||
|
parsers = append(parsers, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsToolPath returns the path to the xls2json.js script.
|
||||||
|
// Checks XLS_TOOL_PATH env var first, then falls back to a path
|
||||||
|
// relative to the binary's directory so it works both locally and in Docker.
|
||||||
|
func xlsToolPath() (string, error) {
|
||||||
|
if p := os.Getenv("XLS_TOOL_PATH"); p != "" {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
// Docker layout: /app/tools/xls2json.js
|
||||||
|
candidates := []string{
|
||||||
|
"/app/tools/xls2json.js",
|
||||||
|
}
|
||||||
|
// Local dev: look relative to the process working directory
|
||||||
|
if cwd, err := os.Getwd(); err == nil {
|
||||||
|
candidates = append(candidates,
|
||||||
|
filepath.Join(cwd, "deploy/tools/xls2json.js"),
|
||||||
|
filepath.Join(cwd, "../deploy/tools/xls2json.js"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for _, p := range candidates {
|
||||||
|
if _, err := os.Stat(p); err == nil {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("xls2json.js not found; set XLS_TOOL_PATH env var or deploy to /app/tools/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseFile reads an Excel file, auto-detects the competitor format, and returns parsed products.
|
||||||
|
func ParseFile(filePath string) (*ParseResult, error) {
|
||||||
|
ext := strings.ToLower(filepath.Ext(filePath))
|
||||||
|
|
||||||
|
var headers []string
|
||||||
|
var rows [][]string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch ext {
|
||||||
|
case ".xlsx":
|
||||||
|
headers, rows, err = readXLSX(filePath)
|
||||||
|
case ".xls":
|
||||||
|
headers, rows, err = readXLS(filePath)
|
||||||
|
default:
|
||||||
|
return nil, ErrUnsupportedExt
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read excel: %w", err)
|
||||||
|
}
|
||||||
|
if len(rows) == 0 {
|
||||||
|
return nil, ErrEmptyFile
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range parsers {
|
||||||
|
if p.Match(headers) {
|
||||||
|
result, err := p.ParseRows(headers, rows)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parse %s: %w", p.Name(), err)
|
||||||
|
}
|
||||||
|
result.ParserName = p.Name()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, ErrUnknownFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
func readXLSX(filePath string) ([]string, [][]string, error) {
|
||||||
|
f, err := excelize.OpenFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
sheets := f.GetSheetList()
|
||||||
|
if len(sheets) == 0 {
|
||||||
|
return nil, nil, ErrEmptyFile
|
||||||
|
}
|
||||||
|
|
||||||
|
allRows, err := f.GetRows(sheets[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(allRows) < 2 {
|
||||||
|
return nil, nil, ErrEmptyFile
|
||||||
|
}
|
||||||
|
|
||||||
|
return allRows[0], allRows[1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readXLS delegates to the xls2json.js Node.js script via subprocess.
|
||||||
|
// This handles legacy .xls (BIFF8) files including those with embedded images,
|
||||||
|
// which pure-Go libraries cannot reliably process.
|
||||||
|
func readXLS(filePath string) ([]string, [][]string, error) {
|
||||||
|
toolPath, err := xlsToolPath()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
cmd := exec.CommandContext(ctx, "node", toolPath, filePath)
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
msg := strings.TrimSpace(stderr.String())
|
||||||
|
if msg == "" {
|
||||||
|
msg = err.Error()
|
||||||
|
}
|
||||||
|
return nil, nil, fmt.Errorf("xls2json: %s", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON format: [][]interface{} (first row = headers)
|
||||||
|
var raw [][]interface{}
|
||||||
|
if err := json.Unmarshal(stdout.Bytes(), &raw); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("xls2json output parse: %w", err)
|
||||||
|
}
|
||||||
|
if len(raw) < 2 {
|
||||||
|
return nil, nil, ErrEmptyFile
|
||||||
|
}
|
||||||
|
|
||||||
|
toStrings := func(row []interface{}) []string {
|
||||||
|
out := make([]string, len(row))
|
||||||
|
for i, v := range row {
|
||||||
|
if v == nil {
|
||||||
|
out[i] = ""
|
||||||
|
} else {
|
||||||
|
out[i] = strings.TrimSpace(fmt.Sprintf("%v", v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := toStrings(raw[0])
|
||||||
|
rows := make([][]string, 0, len(raw)-1)
|
||||||
|
for _, r := range raw[1:] {
|
||||||
|
rows = append(rows, toStrings(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers, rows, nil
|
||||||
|
}
|
||||||
34
pkg/excelparse/types.go
Normal file
34
pkg/excelparse/types.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package excelparse
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrUnknownFormat = errors.New("unrecognized excel format; supported: 秒账, 领星")
|
||||||
|
ErrEmptyFile = errors.New("excel file has no data rows")
|
||||||
|
ErrUnsupportedExt = errors.New("unsupported file extension; use .xls or .xlsx")
|
||||||
|
)
|
||||||
|
|
||||||
|
type ParsedProduct struct {
|
||||||
|
ProductName string
|
||||||
|
Spec string
|
||||||
|
Color string
|
||||||
|
UnitRolls int64
|
||||||
|
StockQuantity string
|
||||||
|
CostPrice string
|
||||||
|
SalesPrice string
|
||||||
|
Remark string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParseResult struct {
|
||||||
|
Products []ParsedProduct
|
||||||
|
ParserName string
|
||||||
|
SkippedRows int
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatParser transforms raw spreadsheet rows into structured products.
|
||||||
|
// Each competitor format (秒账, 领星, etc.) implements this interface.
|
||||||
|
type FormatParser interface {
|
||||||
|
Name() string
|
||||||
|
Match(headers []string) bool
|
||||||
|
ParseRows(headers []string, rows [][]string) (*ParseResult, error)
|
||||||
|
}
|
||||||
32
pkg/metrics/interceptor.go
Normal file
32
pkg/metrics/interceptor.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
|
||||||
|
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||||
|
start := time.Now()
|
||||||
|
resp, err := handler(ctx, req)
|
||||||
|
elapsed := time.Since(start).Seconds()
|
||||||
|
|
||||||
|
code := "OK"
|
||||||
|
if err != nil {
|
||||||
|
if st, ok := status.FromError(err); ok {
|
||||||
|
code = strconv.Itoa(int(st.Code()))
|
||||||
|
} else {
|
||||||
|
code = "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RPCDurationSeconds.WithLabelValues(info.FullMethod).Observe(elapsed)
|
||||||
|
RPCRequestsTotal.WithLabelValues(info.FullMethod, code).Inc()
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
141
pkg/metrics/metrics.go
Normal file
141
pkg/metrics/metrics.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
const namespace = "muyu"
|
||||||
|
const subsystem = "inventory"
|
||||||
|
|
||||||
|
// ---- Business Counters ----
|
||||||
|
|
||||||
|
var ProductCreatedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "product_created_total",
|
||||||
|
Help: "Total number of products created.",
|
||||||
|
}, []string{"tenant_id", "product_name", "spec", "color"})
|
||||||
|
|
||||||
|
var ProductDeletedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "product_deleted_total",
|
||||||
|
Help: "Total number of products deleted (soft delete).",
|
||||||
|
}, []string{"tenant_id"})
|
||||||
|
|
||||||
|
var ImportOperationsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "import_operations_total",
|
||||||
|
Help: "Total number of import operations executed.",
|
||||||
|
}, []string{"tenant_id", "operator"})
|
||||||
|
|
||||||
|
var ImportProductsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "import_products_total",
|
||||||
|
Help: "Total number of products processed during imports.",
|
||||||
|
}, []string{"tenant_id", "result"})
|
||||||
|
|
||||||
|
var InboundLengthMetersTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "inbound_length_meters_total",
|
||||||
|
Help: "Total length (meters) of fabric added to inventory.",
|
||||||
|
}, []string{"tenant_id", "product_name", "color", "operation"})
|
||||||
|
|
||||||
|
var InboundBoltsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "inbound_bolts_total",
|
||||||
|
Help: "Total number of bolt records added to inventory.",
|
||||||
|
}, []string{"tenant_id", "operation"})
|
||||||
|
|
||||||
|
var PansSavedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "pans_saved_total",
|
||||||
|
Help: "Total number of pan-save operations.",
|
||||||
|
}, []string{"tenant_id", "product_id"})
|
||||||
|
|
||||||
|
var StockCheckCreatedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "stock_check_created_total",
|
||||||
|
Help: "Total number of stock check records created.",
|
||||||
|
}, []string{"tenant_id"})
|
||||||
|
|
||||||
|
var StockCheckConfirmedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "stock_check_confirmed_total",
|
||||||
|
Help: "Total number of stock checks confirmed.",
|
||||||
|
}, []string{"tenant_id"})
|
||||||
|
|
||||||
|
var StockAdjustCreatedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "stock_adjust_created_total",
|
||||||
|
Help: "Total number of stock adjustments created.",
|
||||||
|
}, []string{"tenant_id", "reason"})
|
||||||
|
|
||||||
|
var StockAdjustApprovedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "stock_adjust_approved_total",
|
||||||
|
Help: "Total number of stock adjustments approved/rejected.",
|
||||||
|
}, []string{"tenant_id", "action"})
|
||||||
|
|
||||||
|
var StockAdjustQuantityMeters = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "stock_adjust_quantity_meters_total",
|
||||||
|
Help: "Total adjusted quantity in meters (absolute value, split by direction).",
|
||||||
|
}, []string{"tenant_id", "direction"})
|
||||||
|
|
||||||
|
// ---- Histograms ----
|
||||||
|
|
||||||
|
var ImportBatchSize = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "import_batch_size",
|
||||||
|
Help: "Number of products per import operation.",
|
||||||
|
Buckets: []float64{1, 5, 10, 50, 100, 200, 500, 1000},
|
||||||
|
}, []string{"tenant_id"})
|
||||||
|
|
||||||
|
// ---- RPC Operational Metrics ----
|
||||||
|
|
||||||
|
var RPCDurationSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "rpc_duration_seconds",
|
||||||
|
Help: "Duration of RPC calls in seconds.",
|
||||||
|
Buckets: prometheus.DefBuckets,
|
||||||
|
}, []string{"method"})
|
||||||
|
|
||||||
|
var RPCRequestsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace, Subsystem: subsystem,
|
||||||
|
Name: "rpc_requests_total",
|
||||||
|
Help: "Total number of RPC requests.",
|
||||||
|
}, []string{"method", "code"})
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(
|
||||||
|
ProductCreatedTotal,
|
||||||
|
ProductDeletedTotal,
|
||||||
|
ImportOperationsTotal,
|
||||||
|
ImportProductsTotal,
|
||||||
|
InboundLengthMetersTotal,
|
||||||
|
InboundBoltsTotal,
|
||||||
|
PansSavedTotal,
|
||||||
|
StockCheckCreatedTotal,
|
||||||
|
StockCheckConfirmedTotal,
|
||||||
|
StockAdjustCreatedTotal,
|
||||||
|
StockAdjustApprovedTotal,
|
||||||
|
StockAdjustQuantityMeters,
|
||||||
|
ImportBatchSize,
|
||||||
|
RPCDurationSeconds,
|
||||||
|
RPCRequestsTotal,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartHTTP(addr string) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.Handle("/metrics", promhttp.Handler())
|
||||||
|
go func() {
|
||||||
|
logx.Infof("prometheus metrics listening on %s", addr)
|
||||||
|
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||||
|
logx.Errorf("prometheus http server error: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
10
rpc/inventory/buf.gen.yaml
Normal file
10
rpc/inventory/buf.gen.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
version: v2
|
||||||
|
plugins:
|
||||||
|
- local: protoc-gen-go
|
||||||
|
out: pb
|
||||||
|
opt:
|
||||||
|
- paths=source_relative
|
||||||
|
- local: protoc-gen-go-grpc
|
||||||
|
out: pb
|
||||||
|
opt:
|
||||||
|
- paths=source_relative
|
||||||
9
rpc/inventory/buf.yaml
Normal file
9
rpc/inventory/buf.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
version: v2
|
||||||
|
modules:
|
||||||
|
- path: .
|
||||||
|
lint:
|
||||||
|
use:
|
||||||
|
- DEFAULT
|
||||||
|
breaking:
|
||||||
|
use:
|
||||||
|
- FILE
|
||||||
@ -11,6 +11,8 @@ DataSource: root:muyu2026@tcp(127.0.0.1:3306)/muyu_wms?charset=utf8mb4&parseTime
|
|||||||
Cache:
|
Cache:
|
||||||
- Host: 127.0.0.1:6379
|
- Host: 127.0.0.1:6379
|
||||||
|
|
||||||
|
PrometheusAddr: :9092
|
||||||
|
|
||||||
Log:
|
Log:
|
||||||
ServiceName: inventory-rpc
|
ServiceName: inventory-rpc
|
||||||
Mode: console
|
Mode: console
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
zrpc.RpcServerConf
|
zrpc.RpcServerConf
|
||||||
DataSource string
|
DataSource string
|
||||||
Cache cache.CacheConf
|
Cache cache.CacheConf
|
||||||
|
PrometheusAddr string `json:",default=:9092"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package logic
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
@ -39,29 +41,11 @@ func (l *ApproveStockAdjustLogic) ApproveStockAdjust(in *pb.ApproveStockAdjustRe
|
|||||||
|
|
||||||
switch in.Action {
|
switch in.Action {
|
||||||
case 1: // approve
|
case 1: // approve
|
||||||
details, err := l.svcCtx.AdjustDetailModel.FindByAdjustId(l.ctx, in.AdjustId)
|
// In the three-layer model, actual stock adjustments are done via
|
||||||
if err != nil {
|
// SaveBolts/SavePans. Approving records the approval decision only.
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range details {
|
|
||||||
product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, d.ProductId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to find product %s: %v", d.ProductId, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
product.StockQuantity = d.AfterQuantity
|
|
||||||
err = l.svcCtx.ProductModel.Update(l.ctx, product)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to update product %s stock: %v", d.ProductId, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adjust.Status = 1
|
adjust.Status = 1
|
||||||
|
|
||||||
case 2: // reject
|
case 2: // reject
|
||||||
adjust.Status = 2
|
adjust.Status = 2
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "unsupported action: %d", in.Action)
|
return nil, status.Errorf(codes.InvalidArgument, "unsupported action: %d", in.Action)
|
||||||
}
|
}
|
||||||
@ -71,5 +55,12 @@ func (l *ApproveStockAdjustLogic) ApproveStockAdjust(in *pb.ApproveStockAdjustRe
|
|||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
actionLabel := "approve"
|
||||||
|
if in.Action == 2 {
|
||||||
|
actionLabel = "reject"
|
||||||
|
}
|
||||||
|
metrics.StockAdjustApprovedTotal.WithLabelValues(tenantId, actionLabel).Inc()
|
||||||
|
|
||||||
return &pb.Empty{}, nil
|
return &pb.Empty{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package logic
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
@ -35,29 +37,17 @@ func (l *ConfirmStockCheckLogic) ConfirmStockCheck(in *pb.ConfirmStockCheckReq)
|
|||||||
return nil, status.Error(codes.FailedPrecondition, "stock check cannot be confirmed in current status")
|
return nil, status.Error(codes.FailedPrecondition, "stock check cannot be confirmed in current status")
|
||||||
}
|
}
|
||||||
|
|
||||||
details, err := l.svcCtx.CheckDetailModel.FindByCheckId(l.ctx, in.CheckId)
|
// In the three-layer model, stock is held in bolt records.
|
||||||
if err != nil {
|
// Confirming a stock check marks it as completed; bolt-level adjustments
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
// are handled separately via the SaveBolts/SavePans endpoints.
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range details {
|
|
||||||
product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, d.ProductId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to find product %s: %v", d.ProductId, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
product.StockQuantity = d.ActualQuantity
|
|
||||||
err = l.svcCtx.ProductModel.Update(l.ctx, product)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to update product %s stock: %v", d.ProductId, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check.Status = 2
|
check.Status = 2
|
||||||
err = l.svcCtx.StockCheckModel.Update(l.ctx, check)
|
err = l.svcCtx.StockCheckModel.Update(l.ctx, check)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
metrics.StockCheckConfirmedTotal.WithLabelValues(tenantId).Inc()
|
||||||
|
|
||||||
return &pb.Empty{}, nil
|
return &pb.Empty{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/pkg/uid"
|
"muyu-apiserver/pkg/uid"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
@ -31,25 +33,17 @@ func NewCreateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cre
|
|||||||
|
|
||||||
func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp, error) {
|
func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp, error) {
|
||||||
productId := uid.Generate()
|
productId := uid.Generate()
|
||||||
|
|
||||||
stockQuantity, _ := strconv.ParseFloat(in.StockQuantity, 64)
|
|
||||||
costPrice, _ := strconv.ParseFloat(in.CostPrice, 64)
|
|
||||||
salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64)
|
salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64)
|
||||||
|
|
||||||
product := &model.InvProduct{
|
product := &model.InvProduct{
|
||||||
ProductId: productId,
|
ProductId: productId,
|
||||||
ProductName: in.ProductName,
|
ProductName: in.ProductName,
|
||||||
ImageUrl: in.ImageUrl,
|
ImageUrl: in.ImageUrl,
|
||||||
Spec: in.Spec,
|
Spec: in.Spec,
|
||||||
Color: in.Color,
|
Color: in.Color,
|
||||||
UnitPieces: in.UnitPieces,
|
SalesPrice: salesPrice,
|
||||||
UnitRolls: in.UnitRolls,
|
Remark: sql.NullString{String: in.Remark, Valid: in.Remark != ""},
|
||||||
StockQuantity: stockQuantity,
|
Status: 1,
|
||||||
Location: in.Location,
|
|
||||||
CostPrice: costPrice,
|
|
||||||
SalesPrice: salesPrice,
|
|
||||||
Remark: sql.NullString{String: in.Remark, Valid: in.Remark != ""},
|
|
||||||
Status: 1,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := l.svcCtx.ProductModel.Insert(l.ctx, product)
|
_, err := l.svcCtx.ProductModel.Insert(l.ctx, product)
|
||||||
@ -57,5 +51,52 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp,
|
|||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
var totalLengthM float64
|
||||||
|
var totalBolts int
|
||||||
|
|
||||||
|
if len(in.Pans) > 0 {
|
||||||
|
pans := make([]*model.InvProductPan, 0, len(in.Pans))
|
||||||
|
for i, panInput := range in.Pans {
|
||||||
|
panId := uid.Generate()
|
||||||
|
pans = append(pans, &model.InvProductPan{
|
||||||
|
PanId: panId,
|
||||||
|
ProductId: productId,
|
||||||
|
Name: panInput.Name,
|
||||||
|
Position: panInput.Position,
|
||||||
|
SortOrder: int64(i + 1),
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(panInput.BoltLengths) > 0 {
|
||||||
|
bolts := make([]*model.InvProductBolt, 0, len(panInput.BoltLengths))
|
||||||
|
for j, lengthStr := range panInput.BoltLengths {
|
||||||
|
lengthM, _ := strconv.ParseFloat(lengthStr, 64)
|
||||||
|
totalLengthM += lengthM
|
||||||
|
bolts = append(bolts, &model.InvProductBolt{
|
||||||
|
BoltId: uid.Generate(),
|
||||||
|
PanId: panId,
|
||||||
|
LengthM: lengthM,
|
||||||
|
SortOrder: int64(j + 1),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
totalBolts += len(panInput.BoltLengths)
|
||||||
|
if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, panId, "", bolts); err != nil {
|
||||||
|
l.Errorf("create bolts for pan %s failed: %v", panId, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := l.svcCtx.PanModel.BulkReplace(l.ctx, productId, "", pans); err != nil {
|
||||||
|
l.Errorf("create pans for product %s failed: %v", productId, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics.ProductCreatedTotal.WithLabelValues(tenantId, in.ProductName, in.Spec, in.Color).Inc()
|
||||||
|
if totalLengthM > 0 {
|
||||||
|
metrics.InboundLengthMetersTotal.WithLabelValues(tenantId, in.ProductName, in.Color, "create").Add(totalLengthM)
|
||||||
|
}
|
||||||
|
if totalBolts > 0 {
|
||||||
|
metrics.InboundBoltsTotal.WithLabelValues(tenantId, "create").Add(float64(totalBolts))
|
||||||
|
}
|
||||||
|
|
||||||
return &pb.IdResp{Id: productId}, nil
|
return &pb.IdResp{Id: productId}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,11 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"math"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/pkg/uid"
|
"muyu-apiserver/pkg/uid"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
@ -30,6 +34,19 @@ func NewCreateStockAdjustLogic(ctx context.Context, svcCtx *svc.ServiceContext)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// currentQty returns the total bolt length (meters) for a product.
|
||||||
|
func (l *CreateStockAdjustLogic) currentQty(productId string) float64 {
|
||||||
|
bolts, err := l.svcCtx.BoltModel.FindByProductId(l.ctx, productId)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var total float64
|
||||||
|
for _, b := range bolts {
|
||||||
|
total += b.LengthM
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
func (l *CreateStockAdjustLogic) CreateStockAdjust(in *pb.CreateStockAdjustReq) (*pb.IdResp, error) {
|
func (l *CreateStockAdjustLogic) CreateStockAdjust(in *pb.CreateStockAdjustReq) (*pb.IdResp, error) {
|
||||||
adjustId := uid.Generate()
|
adjustId := uid.Generate()
|
||||||
adjustNo := generateNo("TZ")
|
adjustNo := generateNo("TZ")
|
||||||
@ -56,19 +73,20 @@ func (l *CreateStockAdjustLogic) CreateStockAdjust(in *pb.CreateStockAdjustReq)
|
|||||||
|
|
||||||
details := make([]*model.InvStockAdjustDetail, 0, len(in.Details))
|
details := make([]*model.InvStockAdjustDetail, 0, len(in.Details))
|
||||||
for _, d := range in.Details {
|
for _, d := range in.Details {
|
||||||
product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, d.ProductId)
|
_, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, d.ProductId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.NotFound, "product %s not found", d.ProductId)
|
return nil, status.Errorf(codes.NotFound, "product %s not found", d.ProductId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeQty := l.currentQty(d.ProductId)
|
||||||
adjustQty, _ := strconv.ParseFloat(d.AdjustQuantity, 64)
|
adjustQty, _ := strconv.ParseFloat(d.AdjustQuantity, 64)
|
||||||
afterQty := product.StockQuantity + adjustQty
|
afterQty := beforeQty + adjustQty
|
||||||
|
|
||||||
details = append(details, &model.InvStockAdjustDetail{
|
details = append(details, &model.InvStockAdjustDetail{
|
||||||
DetailId: uid.Generate(),
|
DetailId: uid.Generate(),
|
||||||
AdjustId: adjustId,
|
AdjustId: adjustId,
|
||||||
ProductId: d.ProductId,
|
ProductId: d.ProductId,
|
||||||
BeforeQuantity: product.StockQuantity,
|
BeforeQuantity: beforeQty,
|
||||||
AdjustQuantity: adjustQty,
|
AdjustQuantity: adjustQty,
|
||||||
AfterQuantity: afterQty,
|
AfterQuantity: afterQty,
|
||||||
Remark: sql.NullString{String: d.Remark, Valid: d.Remark != ""},
|
Remark: sql.NullString{String: d.Remark, Valid: d.Remark != ""},
|
||||||
@ -80,5 +98,15 @@ func (l *CreateStockAdjustLogic) CreateStockAdjust(in *pb.CreateStockAdjustReq)
|
|||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
metrics.StockAdjustCreatedTotal.WithLabelValues(tenantId, in.AdjustReason).Inc()
|
||||||
|
for _, d := range details {
|
||||||
|
if d.AdjustQuantity >= 0 {
|
||||||
|
metrics.StockAdjustQuantityMeters.WithLabelValues(tenantId, "increase").Add(d.AdjustQuantity)
|
||||||
|
} else {
|
||||||
|
metrics.StockAdjustQuantityMeters.WithLabelValues(tenantId, "decrease").Add(math.Abs(d.AdjustQuantity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &pb.IdResp{Id: adjustId}, nil
|
return &pb.IdResp{Id: adjustId}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/pkg/uid"
|
"muyu-apiserver/pkg/uid"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
@ -36,6 +38,19 @@ func generateNo(prefix string) string {
|
|||||||
return fmt.Sprintf("%s%s%04d", prefix, now.Format("20060102"), now.UnixNano()%10000)
|
return fmt.Sprintf("%s%s%04d", prefix, now.Format("20060102"), now.UnixNano()%10000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// computeSystemQty returns the total bolt length (meters) for a product.
|
||||||
|
func (l *CreateStockCheckLogic) computeSystemQty(productId string) float64 {
|
||||||
|
bolts, err := l.svcCtx.BoltModel.FindByProductId(l.ctx, productId)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var total float64
|
||||||
|
for _, b := range bolts {
|
||||||
|
total += b.LengthM
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
func (l *CreateStockCheckLogic) CreateStockCheck(in *pb.CreateStockCheckReq) (*pb.IdResp, error) {
|
func (l *CreateStockCheckLogic) CreateStockCheck(in *pb.CreateStockCheckReq) (*pb.IdResp, error) {
|
||||||
checkId := uid.Generate()
|
checkId := uid.Generate()
|
||||||
checkNo := generateNo("PD")
|
checkNo := generateNo("PD")
|
||||||
@ -66,15 +81,16 @@ func (l *CreateStockCheckLogic) CreateStockCheck(in *pb.CreateStockCheckReq) (*p
|
|||||||
return nil, status.Errorf(codes.NotFound, "product %s not found", d.ProductId)
|
return nil, status.Errorf(codes.NotFound, "product %s not found", d.ProductId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systemQty := l.computeSystemQty(d.ProductId)
|
||||||
actualQty, _ := strconv.ParseFloat(d.ActualQuantity, 64)
|
actualQty, _ := strconv.ParseFloat(d.ActualQuantity, 64)
|
||||||
diffQty := actualQty - product.StockQuantity
|
diffQty := actualQty - systemQty
|
||||||
diffAmount := diffQty * product.CostPrice
|
diffAmount := diffQty * product.SalesPrice
|
||||||
|
|
||||||
details = append(details, &model.InvStockCheckDetail{
|
details = append(details, &model.InvStockCheckDetail{
|
||||||
DetailId: uid.Generate(),
|
DetailId: uid.Generate(),
|
||||||
CheckId: checkId,
|
CheckId: checkId,
|
||||||
ProductId: d.ProductId,
|
ProductId: d.ProductId,
|
||||||
SystemQuantity: product.StockQuantity,
|
SystemQuantity: systemQty,
|
||||||
ActualQuantity: actualQty,
|
ActualQuantity: actualQty,
|
||||||
DiffQuantity: diffQty,
|
DiffQuantity: diffQty,
|
||||||
DiffAmount: diffAmount,
|
DiffAmount: diffAmount,
|
||||||
@ -87,5 +103,8 @@ func (l *CreateStockCheckLogic) CreateStockCheck(in *pb.CreateStockCheckReq) (*p
|
|||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
metrics.StockCheckCreatedTotal.WithLabelValues(tenantId).Inc()
|
||||||
|
|
||||||
return &pb.IdResp{Id: checkId}, nil
|
return &pb.IdResp{Id: checkId}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
@ -41,5 +43,8 @@ func (l *DeleteProductLogic) DeleteProduct(in *pb.DeleteProductReq) (*pb.Empty,
|
|||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
metrics.ProductDeletedTotal.WithLabelValues(tenantId).Inc()
|
||||||
|
|
||||||
return &pb.Empty{}, nil
|
return &pb.Empty{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,20 +33,15 @@ func (l *GetProductLogic) GetProduct(in *pb.GetProductReq) (*pb.ProductInfo, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &pb.ProductInfo{
|
return &pb.ProductInfo{
|
||||||
ProductId: product.ProductId,
|
ProductId: product.ProductId,
|
||||||
ProductName: product.ProductName,
|
ProductName: product.ProductName,
|
||||||
ImageUrl: product.ImageUrl,
|
ImageUrl: product.ImageUrl,
|
||||||
Spec: product.Spec,
|
Spec: product.Spec,
|
||||||
Color: product.Color,
|
Color: product.Color,
|
||||||
UnitPieces: product.UnitPieces,
|
SalesPrice: fmt.Sprintf("%.2f", product.SalesPrice),
|
||||||
UnitRolls: product.UnitRolls,
|
Remark: product.Remark.String,
|
||||||
StockQuantity: fmt.Sprintf("%.2f", product.StockQuantity),
|
Status: product.Status,
|
||||||
Location: product.Location,
|
CreatedAt: product.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||||
CostPrice: fmt.Sprintf("%.2f", product.CostPrice),
|
UpdatedAt: product.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||||
SalesPrice: fmt.Sprintf("%.2f", product.SalesPrice),
|
|
||||||
Remark: product.Remark.String,
|
|
||||||
Status: product.Status,
|
|
||||||
CreatedAt: product.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
||||||
UpdatedAt: product.UpdatedAt.Format("2006-01-02 15:04:05"),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
95
rpc/inventory/internal/logic/getproducttreelogic.go
Normal file
95
rpc/inventory/internal/logic/getproducttreelogic.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetProductTreeLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetProductTreeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductTreeLogic {
|
||||||
|
return &GetProductTreeLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductTreeResp, error) {
|
||||||
|
product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, in.ProductId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.NotFound, "product not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
pans, err := l.svcCtx.PanModel.FindByProductId(l.ctx, in.ProductId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalBoltCount int64
|
||||||
|
var totalLengthM float64
|
||||||
|
pbPans := make([]*pb.PanInfo, 0, len(pans))
|
||||||
|
|
||||||
|
for _, pan := range pans {
|
||||||
|
bolts, err := l.svcCtx.BoltModel.FindByPanId(l.ctx, pan.PanId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var panLength float64
|
||||||
|
pbBolts := make([]*pb.BoltInfo, 0, len(bolts))
|
||||||
|
for _, b := range bolts {
|
||||||
|
pbBolts = append(pbBolts, &pb.BoltInfo{
|
||||||
|
BoltId: b.BoltId,
|
||||||
|
PanId: b.PanId,
|
||||||
|
LengthM: fmt.Sprintf("%.2f", b.LengthM),
|
||||||
|
SortOrder: b.SortOrder,
|
||||||
|
})
|
||||||
|
panLength += b.LengthM
|
||||||
|
}
|
||||||
|
|
||||||
|
totalBoltCount += int64(len(bolts))
|
||||||
|
totalLengthM += panLength
|
||||||
|
|
||||||
|
pbPans = append(pbPans, &pb.PanInfo{
|
||||||
|
PanId: pan.PanId,
|
||||||
|
ProductId: pan.ProductId,
|
||||||
|
Name: pan.Name,
|
||||||
|
Position: pan.Position,
|
||||||
|
SortOrder: pan.SortOrder,
|
||||||
|
Bolts: pbBolts,
|
||||||
|
BoltCount: int64(len(bolts)),
|
||||||
|
TotalLength: fmt.Sprintf("%.2f", panLength),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ProductTreeResp{
|
||||||
|
Product: &pb.ProductInfo{
|
||||||
|
ProductId: product.ProductId,
|
||||||
|
ProductName: product.ProductName,
|
||||||
|
ImageUrl: product.ImageUrl,
|
||||||
|
Spec: product.Spec,
|
||||||
|
Color: product.Color,
|
||||||
|
SalesPrice: fmt.Sprintf("%.2f", product.SalesPrice),
|
||||||
|
Remark: product.Remark.String,
|
||||||
|
Status: product.Status,
|
||||||
|
CreatedAt: product.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||||
|
UpdatedAt: product.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||||
|
},
|
||||||
|
Pans: pbPans,
|
||||||
|
TotalPanCount: int64(len(pans)),
|
||||||
|
TotalBoltCount: totalBoltCount,
|
||||||
|
TotalLengthM: fmt.Sprintf("%.2f", totalLengthM),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@ -29,16 +29,26 @@ func NewGetStockSummaryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G
|
|||||||
|
|
||||||
func (l *GetStockSummaryLogic) GetStockSummary(in *pb.StockSummaryReq) (*pb.StockSummaryResp, error) {
|
func (l *GetStockSummaryLogic) GetStockSummary(in *pb.StockSummaryReq) (*pb.StockSummaryResp, error) {
|
||||||
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
productCount, totalPieces, totalRolls, totalCostValue, totalSalesValue, err := l.svcCtx.ProductModel.FindStockSummary(l.ctx, tenantId)
|
summaries, err := l.svcCtx.ProductModel.FindProductSummary(l.ctx, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var productCount, totalPieces, totalPans int64
|
||||||
|
var totalLengthM, totalSalesValue float64
|
||||||
|
for _, s := range summaries {
|
||||||
|
productCount += s.ColorCount
|
||||||
|
totalPieces += s.TotalBoltCount
|
||||||
|
totalPans += s.TotalPanCount
|
||||||
|
totalLengthM += s.TotalLengthM
|
||||||
|
}
|
||||||
|
_ = totalSalesValue
|
||||||
|
|
||||||
return &pb.StockSummaryResp{
|
return &pb.StockSummaryResp{
|
||||||
ProductCount: productCount,
|
ProductCount: productCount,
|
||||||
TotalPieces: totalPieces,
|
TotalPieces: totalPieces,
|
||||||
TotalRolls: totalRolls,
|
TotalPans: totalPans,
|
||||||
TotalCostValue: fmt.Sprintf("%.2f", totalCostValue),
|
TotalLengthM: fmt.Sprintf("%.2f", totalLengthM),
|
||||||
TotalSalesValue: fmt.Sprintf("%.2f", totalSalesValue),
|
TotalSalesValue: "0.00",
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,12 @@ package logic
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/pkg/uid"
|
"muyu-apiserver/pkg/uid"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
@ -32,44 +33,35 @@ func NewImportProductsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Im
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *ImportProductsLogic) ImportProducts(in *pb.ImportProductReq) (*pb.ImportProductResp, error) {
|
func (l *ImportProductsLogic) ImportProducts(in *pb.ImportProductReq) (*pb.ImportProductResp, error) {
|
||||||
var successCount, failCount int64
|
products := make([]*model.InvProduct, 0, len(in.Products))
|
||||||
var errMsgs []string
|
|
||||||
|
|
||||||
for i, p := range in.Products {
|
for _, p := range in.Products {
|
||||||
productId := uid.Generate()
|
|
||||||
stockQuantity, _ := strconv.ParseFloat(p.StockQuantity, 64)
|
|
||||||
costPrice, _ := strconv.ParseFloat(p.CostPrice, 64)
|
|
||||||
salesPrice, _ := strconv.ParseFloat(p.SalesPrice, 64)
|
salesPrice, _ := strconv.ParseFloat(p.SalesPrice, 64)
|
||||||
|
|
||||||
product := &model.InvProduct{
|
products = append(products, &model.InvProduct{
|
||||||
ProductId: productId,
|
ProductId: uid.Generate(),
|
||||||
ProductName: p.ProductName,
|
ProductName: p.ProductName,
|
||||||
ImageUrl: p.ImageUrl,
|
ImageUrl: p.ImageUrl,
|
||||||
Spec: p.Spec,
|
Spec: p.Spec,
|
||||||
Color: p.Color,
|
Color: p.Color,
|
||||||
UnitPieces: p.UnitPieces,
|
SalesPrice: salesPrice,
|
||||||
UnitRolls: p.UnitRolls,
|
Remark: sql.NullString{String: p.Remark, Valid: p.Remark != ""},
|
||||||
StockQuantity: stockQuantity,
|
Status: 1,
|
||||||
Location: p.Location,
|
})
|
||||||
CostPrice: costPrice,
|
|
||||||
SalesPrice: salesPrice,
|
|
||||||
Remark: sql.NullString{String: p.Remark, Valid: p.Remark != ""},
|
|
||||||
Status: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := l.svcCtx.ProductModel.Insert(l.ctx, product)
|
|
||||||
if err != nil {
|
|
||||||
failCount++
|
|
||||||
errMsgs = append(errMsgs, fmt.Sprintf("row %d: %s", i+1, err.Error()))
|
|
||||||
} else {
|
|
||||||
successCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
totalCount := int64(len(in.Products))
|
totalCount := int64(len(products))
|
||||||
importId := uid.Generate()
|
affected, err := l.svcCtx.ProductModel.BulkInsert(l.ctx, products)
|
||||||
errorMsg := strings.Join(errMsgs, "; ")
|
|
||||||
|
|
||||||
|
var errorMsg string
|
||||||
|
successCount := affected
|
||||||
|
failCount := totalCount - affected
|
||||||
|
if err != nil {
|
||||||
|
errorMsg = err.Error()
|
||||||
|
l.Errorf("bulk insert partial failure: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
importId := uid.Generate()
|
||||||
importLog := &model.InvStockImportLog{
|
importLog := &model.InvStockImportLog{
|
||||||
ImportId: importId,
|
ImportId: importId,
|
||||||
FileName: in.FileName,
|
FileName: in.FileName,
|
||||||
@ -80,9 +72,23 @@ func (l *ImportProductsLogic) ImportProducts(in *pb.ImportProductReq) (*pb.Impor
|
|||||||
Operator: in.Operator,
|
Operator: in.Operator,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := l.svcCtx.ImportLogModel.Insert(l.ctx, importLog)
|
if _, logErr := l.svcCtx.ImportLogModel.Insert(l.ctx, importLog); logErr != nil {
|
||||||
if err != nil {
|
l.Errorf("save import log failed: %v", logErr)
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, strings.Join([]string{errorMsg, logErr.Error()}, "; "))
|
||||||
|
}
|
||||||
|
return nil, status.Error(codes.Internal, logErr.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
metrics.ImportOperationsTotal.WithLabelValues(tenantId, in.Operator).Inc()
|
||||||
|
metrics.ImportProductsTotal.WithLabelValues(tenantId, "success").Add(float64(successCount))
|
||||||
|
if failCount > 0 {
|
||||||
|
metrics.ImportProductsTotal.WithLabelValues(tenantId, "fail").Add(float64(failCount))
|
||||||
|
}
|
||||||
|
metrics.ImportBatchSize.WithLabelValues(tenantId).Observe(float64(totalCount))
|
||||||
|
for _, p := range in.Products {
|
||||||
|
metrics.ProductCreatedTotal.WithLabelValues(tenantId, p.ProductName, p.Spec, p.Color).Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.ImportProductResp{
|
return &pb.ImportProductResp{
|
||||||
|
|||||||
46
rpc/inventory/internal/logic/listboltslogic.go
Normal file
46
rpc/inventory/internal/logic/listboltslogic.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListBoltsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListBoltsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListBoltsLogic {
|
||||||
|
return &ListBoltsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListBoltsLogic) ListBolts(in *pb.ListBoltReq) (*pb.ListBoltResp, error) {
|
||||||
|
bolts, err := l.svcCtx.BoltModel.FindByPanId(l.ctx, in.PanId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pbBolts := make([]*pb.BoltInfo, 0, len(bolts))
|
||||||
|
for _, b := range bolts {
|
||||||
|
pbBolts = append(pbBolts, &pb.BoltInfo{
|
||||||
|
BoltId: b.BoltId,
|
||||||
|
PanId: b.PanId,
|
||||||
|
LengthM: fmt.Sprintf("%.2f", b.LengthM),
|
||||||
|
SortOrder: b.SortOrder,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ListBoltResp{List: pbBolts}, nil
|
||||||
|
}
|
||||||
53
rpc/inventory/internal/logic/listboltviewlogic.go
Normal file
53
rpc/inventory/internal/logic/listboltviewlogic.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListBoltViewLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListBoltViewLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListBoltViewLogic {
|
||||||
|
return &ListBoltViewLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListBoltViewLogic) ListBoltView(in *pb.ListBoltViewReq) (*pb.ListBoltViewResp, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
list, total, err := l.svcCtx.BoltModel.FindBoltList(l.ctx, tenantId, in.Page, in.PageSize, in.ProductName, in.Position)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pbList := make([]*pb.BoltListItem, 0, len(list))
|
||||||
|
for _, item := range list {
|
||||||
|
pbList = append(pbList, &pb.BoltListItem{
|
||||||
|
BoltId: item.BoltId,
|
||||||
|
PanId: item.PanId,
|
||||||
|
LengthM: fmt.Sprintf("%.2f", item.LengthM),
|
||||||
|
Color: item.Color,
|
||||||
|
SortOrder: item.SortOrder,
|
||||||
|
PanName: item.PanName,
|
||||||
|
Position: item.Position,
|
||||||
|
ProductId: item.ProductId,
|
||||||
|
ProductName: item.ProductName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ListBoltViewResp{Total: total, List: pbList}, nil
|
||||||
|
}
|
||||||
54
rpc/inventory/internal/logic/listcolordetaillogic.go
Normal file
54
rpc/inventory/internal/logic/listcolordetaillogic.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListColorDetailLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListColorDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListColorDetailLogic {
|
||||||
|
return &ListColorDetailLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListColorDetailLogic) ListColorDetail(in *pb.ListColorDetailReq) (*pb.ListColorDetailResp, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
list, err := l.svcCtx.ProductModel.FindColorDetail(l.ctx, tenantId, in.ProductName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pbList := make([]*pb.ColorDetailItem, 0, len(list))
|
||||||
|
for _, d := range list {
|
||||||
|
pbList = append(pbList, &pb.ColorDetailItem{
|
||||||
|
ProductId: d.ProductId,
|
||||||
|
ProductName: d.ProductName,
|
||||||
|
Color: d.Color,
|
||||||
|
Spec: d.Spec,
|
||||||
|
ImageUrl: d.ImageUrl,
|
||||||
|
PanCount: d.PanCount,
|
||||||
|
BoltCount: d.BoltCount,
|
||||||
|
TotalLengthM: fmt.Sprintf("%.2f", d.TotalLengthM),
|
||||||
|
Locations: d.Locations,
|
||||||
|
SalesPrice: fmt.Sprintf("%.2f", d.SalesPrice),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ListColorDetailResp{List: pbList}, nil
|
||||||
|
}
|
||||||
65
rpc/inventory/internal/logic/listpanslogic.go
Normal file
65
rpc/inventory/internal/logic/listpanslogic.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPansLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListPansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPansLogic {
|
||||||
|
return &ListPansLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListPansLogic) ListPans(in *pb.ListPanReq) (*pb.ListPanResp, error) {
|
||||||
|
pans, err := l.svcCtx.PanModel.FindByProductId(l.ctx, in.ProductId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pbPans := make([]*pb.PanInfo, 0, len(pans))
|
||||||
|
for _, pan := range pans {
|
||||||
|
bolts, err := l.svcCtx.BoltModel.FindByPanId(l.ctx, pan.PanId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
var panLength float64
|
||||||
|
pbBolts := make([]*pb.BoltInfo, 0, len(bolts))
|
||||||
|
for _, b := range bolts {
|
||||||
|
pbBolts = append(pbBolts, &pb.BoltInfo{
|
||||||
|
BoltId: b.BoltId,
|
||||||
|
PanId: b.PanId,
|
||||||
|
LengthM: fmt.Sprintf("%.2f", b.LengthM),
|
||||||
|
SortOrder: b.SortOrder,
|
||||||
|
})
|
||||||
|
panLength += b.LengthM
|
||||||
|
}
|
||||||
|
pbPans = append(pbPans, &pb.PanInfo{
|
||||||
|
PanId: pan.PanId,
|
||||||
|
ProductId: pan.ProductId,
|
||||||
|
Name: pan.Name,
|
||||||
|
Position: pan.Position,
|
||||||
|
SortOrder: pan.SortOrder,
|
||||||
|
Bolts: pbBolts,
|
||||||
|
BoltCount: int64(len(bolts)),
|
||||||
|
TotalLength: fmt.Sprintf("%.2f", panLength),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ListPanResp{List: pbPans}, nil
|
||||||
|
}
|
||||||
52
rpc/inventory/internal/logic/listpanviewlogic.go
Normal file
52
rpc/inventory/internal/logic/listpanviewlogic.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPanViewLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListPanViewLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPanViewLogic {
|
||||||
|
return &ListPanViewLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListPanViewLogic) ListPanView(in *pb.ListPanViewReq) (*pb.ListPanViewResp, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
list, total, err := l.svcCtx.PanModel.FindPanList(l.ctx, tenantId, in.Page, in.PageSize, in.ProductName, in.Position)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pbList := make([]*pb.PanListItem, 0, len(list))
|
||||||
|
for _, item := range list {
|
||||||
|
pbList = append(pbList, &pb.PanListItem{
|
||||||
|
PanId: item.PanId,
|
||||||
|
ProductId: item.ProductId,
|
||||||
|
Name: item.Name,
|
||||||
|
Position: item.Position,
|
||||||
|
ProductName: item.ProductName,
|
||||||
|
Colors: item.Colors,
|
||||||
|
BoltCount: item.BoltCount,
|
||||||
|
TotalLengthM: fmt.Sprintf("%.2f", item.TotalLengthM),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ListPanViewResp{Total: total, List: pbList}, nil
|
||||||
|
}
|
||||||
@ -29,7 +29,7 @@ func NewListProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListP
|
|||||||
|
|
||||||
func (l *ListProductLogic) ListProduct(in *pb.ListProductReq) (*pb.ListProductResp, error) {
|
func (l *ListProductLogic) ListProduct(in *pb.ListProductReq) (*pb.ListProductResp, error) {
|
||||||
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
list, total, err := l.svcCtx.ProductModel.FindList(l.ctx, tenantId, in.Page, in.PageSize, in.ProductName, in.Spec, in.Color, in.Location, in.Status)
|
list, total, err := l.svcCtx.ProductModel.FindList(l.ctx, tenantId, in.Page, in.PageSize, in.ProductName, in.Spec, in.Color, in.Status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
@ -37,21 +37,16 @@ func (l *ListProductLogic) ListProduct(in *pb.ListProductReq) (*pb.ListProductRe
|
|||||||
pbList := make([]*pb.ProductInfo, 0, len(list))
|
pbList := make([]*pb.ProductInfo, 0, len(list))
|
||||||
for _, p := range list {
|
for _, p := range list {
|
||||||
pbList = append(pbList, &pb.ProductInfo{
|
pbList = append(pbList, &pb.ProductInfo{
|
||||||
ProductId: p.ProductId,
|
ProductId: p.ProductId,
|
||||||
ProductName: p.ProductName,
|
ProductName: p.ProductName,
|
||||||
ImageUrl: p.ImageUrl,
|
ImageUrl: p.ImageUrl,
|
||||||
Spec: p.Spec,
|
Spec: p.Spec,
|
||||||
Color: p.Color,
|
Color: p.Color,
|
||||||
UnitPieces: p.UnitPieces,
|
SalesPrice: fmt.Sprintf("%.2f", p.SalesPrice),
|
||||||
UnitRolls: p.UnitRolls,
|
Remark: p.Remark.String,
|
||||||
StockQuantity: fmt.Sprintf("%.2f", p.StockQuantity),
|
Status: p.Status,
|
||||||
Location: p.Location,
|
CreatedAt: p.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||||
CostPrice: fmt.Sprintf("%.2f", p.CostPrice),
|
UpdatedAt: p.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||||
SalesPrice: fmt.Sprintf("%.2f", p.SalesPrice),
|
|
||||||
Remark: p.Remark.String,
|
|
||||||
Status: p.Status,
|
|
||||||
CreatedAt: p.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
||||||
UpdatedAt: p.UpdatedAt.Format("2006-01-02 15:04:05"),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
rpc/inventory/internal/logic/listproductsummarylogic.go
Normal file
52
rpc/inventory/internal/logic/listproductsummarylogic.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListProductSummaryLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListProductSummaryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListProductSummaryLogic {
|
||||||
|
return &ListProductSummaryLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListProductSummaryLogic) ListProductSummary(in *pb.ListProductSummaryReq) (*pb.ListProductSummaryResp, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
list, err := l.svcCtx.ProductModel.FindProductSummary(l.ctx, tenantId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pbList := make([]*pb.ProductSummaryItem, 0, len(list))
|
||||||
|
for _, s := range list {
|
||||||
|
pbList = append(pbList, &pb.ProductSummaryItem{
|
||||||
|
ProductName: s.ProductName,
|
||||||
|
Spec: s.Spec,
|
||||||
|
ColorCount: s.ColorCount,
|
||||||
|
TotalPanCount: s.TotalPanCount,
|
||||||
|
TotalBoltCount: s.TotalBoltCount,
|
||||||
|
TotalLengthM: fmt.Sprintf("%.2f", s.TotalLengthM),
|
||||||
|
Colors: s.Colors,
|
||||||
|
Locations: s.Locations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.ListProductSummaryResp{List: pbList}, nil
|
||||||
|
}
|
||||||
59
rpc/inventory/internal/logic/saveboltslogic.go
Normal file
59
rpc/inventory/internal/logic/saveboltslogic.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
|
"muyu-apiserver/pkg/uid"
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SaveBoltsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSaveBoltsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveBoltsLogic {
|
||||||
|
return &SaveBoltsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SaveBoltsLogic) SaveBolts(in *pb.SaveBoltsReq) (*pb.Empty, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
|
||||||
|
var totalLengthM float64
|
||||||
|
bolts := make([]*model.InvProductBolt, 0, len(in.Lengths))
|
||||||
|
for i, lengthStr := range in.Lengths {
|
||||||
|
lengthM, _ := strconv.ParseFloat(lengthStr, 64)
|
||||||
|
totalLengthM += lengthM
|
||||||
|
bolts = append(bolts, &model.InvProductBolt{
|
||||||
|
BoltId: uid.Generate(),
|
||||||
|
PanId: in.PanId,
|
||||||
|
LengthM: lengthM,
|
||||||
|
SortOrder: int64(i + 1),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, in.PanId, tenantId, bolts); err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics.InboundBoltsTotal.WithLabelValues(tenantId, "save_bolts").Add(float64(len(in.Lengths)))
|
||||||
|
if totalLengthM > 0 {
|
||||||
|
metrics.InboundLengthMetersTotal.WithLabelValues(tenantId, "", "", "save_bolts").Add(totalLengthM)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.Empty{}, nil
|
||||||
|
}
|
||||||
105
rpc/inventory/internal/logic/savepanslogic.go
Normal file
105
rpc/inventory/internal/logic/savepanslogic.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
|
"muyu-apiserver/pkg/uid"
|
||||||
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SavePansLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSavePansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SavePansLogic {
|
||||||
|
return &SavePansLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SavePansLogic) SavePans(in *pb.SavePansReq) (*pb.Empty, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
|
||||||
|
if err := l.svcCtx.BoltModel.DeleteByProductId(l.ctx, in.ProductId); err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalLengthM float64
|
||||||
|
var totalBolts int
|
||||||
|
|
||||||
|
pans := make([]*model.InvProductPan, 0, len(in.Pans))
|
||||||
|
for i, panInput := range in.Pans {
|
||||||
|
panId := uid.Generate()
|
||||||
|
pans = append(pans, &model.InvProductPan{
|
||||||
|
PanId: panId,
|
||||||
|
ProductId: in.ProductId,
|
||||||
|
Name: panInput.Name,
|
||||||
|
Position: panInput.Position,
|
||||||
|
SortOrder: int64(i + 1),
|
||||||
|
TenantId: tenantId,
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(panInput.BoltLengths) > 0 {
|
||||||
|
bolts := make([]*model.InvProductBolt, 0, len(panInput.BoltLengths))
|
||||||
|
for j, lengthStr := range panInput.BoltLengths {
|
||||||
|
lengthM, _ := strconv.ParseFloat(lengthStr, 64)
|
||||||
|
totalLengthM += lengthM
|
||||||
|
bolts = append(bolts, &model.InvProductBolt{
|
||||||
|
BoltId: uid.Generate(),
|
||||||
|
PanId: panId,
|
||||||
|
LengthM: lengthM,
|
||||||
|
SortOrder: int64(j + 1),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
totalBolts += len(panInput.BoltLengths)
|
||||||
|
if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, panId, tenantId, bolts); err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := l.svcCtx.PanModel.BulkReplace(l.ctx, in.ProductId, tenantId, pans); err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics.PansSavedTotal.WithLabelValues(tenantId, in.ProductId).Inc()
|
||||||
|
if totalLengthM > 0 {
|
||||||
|
productName := l.resolveProductName(in.ProductId)
|
||||||
|
color := l.resolveProductColor(in.ProductId)
|
||||||
|
metrics.InboundLengthMetersTotal.WithLabelValues(tenantId, productName, color, "save_pans").Add(totalLengthM)
|
||||||
|
}
|
||||||
|
if totalBolts > 0 {
|
||||||
|
metrics.InboundBoltsTotal.WithLabelValues(tenantId, "save_pans").Add(float64(totalBolts))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.Empty{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SavePansLogic) resolveProductName(productId string) string {
|
||||||
|
p, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, productId)
|
||||||
|
if err != nil {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
return p.ProductName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *SavePansLogic) resolveProductColor(productId string) string {
|
||||||
|
p, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, productId)
|
||||||
|
if err != nil {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
return p.Color
|
||||||
|
}
|
||||||
@ -33,19 +33,12 @@ func (l *UpdateProductLogic) UpdateProduct(in *pb.UpdateProductReq) (*pb.Empty,
|
|||||||
return nil, status.Error(codes.NotFound, "product not found")
|
return nil, status.Error(codes.NotFound, "product not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
stockQuantity, _ := strconv.ParseFloat(in.StockQuantity, 64)
|
|
||||||
costPrice, _ := strconv.ParseFloat(in.CostPrice, 64)
|
|
||||||
salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64)
|
salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64)
|
||||||
|
|
||||||
product.ProductName = in.ProductName
|
product.ProductName = in.ProductName
|
||||||
product.ImageUrl = in.ImageUrl
|
product.ImageUrl = in.ImageUrl
|
||||||
product.Spec = in.Spec
|
product.Spec = in.Spec
|
||||||
product.Color = in.Color
|
product.Color = in.Color
|
||||||
product.UnitPieces = in.UnitPieces
|
|
||||||
product.UnitRolls = in.UnitRolls
|
|
||||||
product.StockQuantity = stockQuantity
|
|
||||||
product.Location = in.Location
|
|
||||||
product.CostPrice = costPrice
|
|
||||||
product.SalesPrice = salesPrice
|
product.SalesPrice = salesPrice
|
||||||
product.Remark = sql.NullString{String: in.Remark, Valid: in.Remark != ""}
|
product.Remark = sql.NullString{String: in.Remark, Valid: in.Remark != ""}
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,18 @@ func NewUpdateStockCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *UpdateStockCheckLogic) systemQty(productId string) float64 {
|
||||||
|
bolts, err := l.svcCtx.BoltModel.FindByProductId(l.ctx, productId)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var total float64
|
||||||
|
for _, b := range bolts {
|
||||||
|
total += b.LengthM
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
func (l *UpdateStockCheckLogic) UpdateStockCheck(in *pb.UpdateStockCheckReq) (*pb.Empty, error) {
|
func (l *UpdateStockCheckLogic) UpdateStockCheck(in *pb.UpdateStockCheckReq) (*pb.Empty, error) {
|
||||||
check, err := l.svcCtx.StockCheckModel.FindOneByCheckId(l.ctx, in.CheckId)
|
check, err := l.svcCtx.StockCheckModel.FindOneByCheckId(l.ctx, in.CheckId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,15 +71,16 @@ func (l *UpdateStockCheckLogic) UpdateStockCheck(in *pb.UpdateStockCheckReq) (*p
|
|||||||
return nil, status.Errorf(codes.NotFound, "product %s not found", d.ProductId)
|
return nil, status.Errorf(codes.NotFound, "product %s not found", d.ProductId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysQty := l.systemQty(d.ProductId)
|
||||||
actualQty, _ := strconv.ParseFloat(d.ActualQuantity, 64)
|
actualQty, _ := strconv.ParseFloat(d.ActualQuantity, 64)
|
||||||
diffQty := actualQty - product.StockQuantity
|
diffQty := actualQty - sysQty
|
||||||
diffAmount := diffQty * product.CostPrice
|
diffAmount := diffQty * product.SalesPrice
|
||||||
|
|
||||||
details = append(details, &model.InvStockCheckDetail{
|
details = append(details, &model.InvStockCheckDetail{
|
||||||
DetailId: uid.Generate(),
|
DetailId: uid.Generate(),
|
||||||
CheckId: in.CheckId,
|
CheckId: in.CheckId,
|
||||||
ProductId: d.ProductId,
|
ProductId: d.ProductId,
|
||||||
SystemQuantity: product.StockQuantity,
|
SystemQuantity: sysQty,
|
||||||
ActualQuantity: actualQty,
|
ActualQuantity: actualQty,
|
||||||
DiffQuantity: diffQty,
|
DiffQuantity: diffQty,
|
||||||
DiffAmount: diffAmount,
|
DiffAmount: diffAmount,
|
||||||
|
|||||||
@ -23,7 +23,7 @@ func NewInventoryServiceServer(svcCtx *svc.ServiceContext) *InventoryServiceServ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Product
|
// Product CRUD
|
||||||
func (s *InventoryServiceServer) CreateProduct(ctx context.Context, in *pb.CreateProductReq) (*pb.IdResp, error) {
|
func (s *InventoryServiceServer) CreateProduct(ctx context.Context, in *pb.CreateProductReq) (*pb.IdResp, error) {
|
||||||
l := logic.NewCreateProductLogic(ctx, s.svcCtx)
|
l := logic.NewCreateProductLogic(ctx, s.svcCtx)
|
||||||
return l.CreateProduct(in)
|
return l.CreateProduct(in)
|
||||||
@ -49,6 +49,57 @@ func (s *InventoryServiceServer) ListProduct(ctx context.Context, in *pb.ListPro
|
|||||||
return l.ListProduct(in)
|
return l.ListProduct(in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Product Tree (panel 3)
|
||||||
|
func (s *InventoryServiceServer) GetProductTree(ctx context.Context, in *pb.GetProductReq) (*pb.ProductTreeResp, error) {
|
||||||
|
l := logic.NewGetProductTreeLogic(ctx, s.svcCtx)
|
||||||
|
return l.GetProductTree(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Product Summary (panel 1)
|
||||||
|
func (s *InventoryServiceServer) ListProductSummary(ctx context.Context, in *pb.ListProductSummaryReq) (*pb.ListProductSummaryResp, error) {
|
||||||
|
l := logic.NewListProductSummaryLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListProductSummary(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color Detail (panel 2)
|
||||||
|
func (s *InventoryServiceServer) ListColorDetail(ctx context.Context, in *pb.ListColorDetailReq) (*pb.ListColorDetailResp, error) {
|
||||||
|
l := logic.NewListColorDetailLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListColorDetail(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan / Bolt list views
|
||||||
|
func (s *InventoryServiceServer) ListPanView(ctx context.Context, in *pb.ListPanViewReq) (*pb.ListPanViewResp, error) {
|
||||||
|
l := logic.NewListPanViewLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListPanView(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *InventoryServiceServer) ListBoltView(ctx context.Context, in *pb.ListBoltViewReq) (*pb.ListBoltViewResp, error) {
|
||||||
|
l := logic.NewListBoltViewLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListBoltView(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan CRUD
|
||||||
|
func (s *InventoryServiceServer) ListPans(ctx context.Context, in *pb.ListPanReq) (*pb.ListPanResp, error) {
|
||||||
|
l := logic.NewListPansLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListPans(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *InventoryServiceServer) SavePans(ctx context.Context, in *pb.SavePansReq) (*pb.Empty, error) {
|
||||||
|
l := logic.NewSavePansLogic(ctx, s.svcCtx)
|
||||||
|
return l.SavePans(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bolt CRUD
|
||||||
|
func (s *InventoryServiceServer) ListBolts(ctx context.Context, in *pb.ListBoltReq) (*pb.ListBoltResp, error) {
|
||||||
|
l := logic.NewListBoltsLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListBolts(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *InventoryServiceServer) SaveBolts(ctx context.Context, in *pb.SaveBoltsReq) (*pb.Empty, error) {
|
||||||
|
l := logic.NewSaveBoltsLogic(ctx, s.svcCtx)
|
||||||
|
return l.SaveBolts(in)
|
||||||
|
}
|
||||||
|
|
||||||
// Import
|
// Import
|
||||||
func (s *InventoryServiceServer) ImportProducts(ctx context.Context, in *pb.ImportProductReq) (*pb.ImportProductResp, error) {
|
func (s *InventoryServiceServer) ImportProducts(ctx context.Context, in *pb.ImportProductReq) (*pb.ImportProductResp, error) {
|
||||||
l := logic.NewImportProductsLogic(ctx, s.svcCtx)
|
l := logic.NewImportProductsLogic(ctx, s.svcCtx)
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import (
|
|||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
ProductModel model.InvProductModel
|
ProductModel model.InvProductModel
|
||||||
|
PanModel model.InvProductPanModel
|
||||||
|
BoltModel model.InvProductBoltModel
|
||||||
ImportLogModel model.InvStockImportLogModel
|
ImportLogModel model.InvStockImportLogModel
|
||||||
StockCheckModel model.InvStockCheckModel
|
StockCheckModel model.InvStockCheckModel
|
||||||
CheckDetailModel model.InvStockCheckDetailModel
|
CheckDetailModel model.InvStockCheckDetailModel
|
||||||
@ -22,6 +24,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
ProductModel: model.NewInvProductModel(conn, c.Cache),
|
ProductModel: model.NewInvProductModel(conn, c.Cache),
|
||||||
|
PanModel: model.NewInvProductPanModel(conn),
|
||||||
|
BoltModel: model.NewInvProductBoltModel(conn),
|
||||||
ImportLogModel: model.NewInvStockImportLogModel(conn, c.Cache),
|
ImportLogModel: model.NewInvStockImportLogModel(conn, c.Cache),
|
||||||
StockCheckModel: model.NewInvStockCheckModel(conn, c.Cache),
|
StockCheckModel: model.NewInvStockCheckModel(conn, c.Cache),
|
||||||
CheckDetailModel: model.NewInvStockCheckDetailModel(conn, c.Cache),
|
CheckDetailModel: model.NewInvStockCheckDetailModel(conn, c.Cache),
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"muyu-apiserver/pkg/metrics"
|
||||||
"muyu-apiserver/rpc/inventory/internal/config"
|
"muyu-apiserver/rpc/inventory/internal/config"
|
||||||
"muyu-apiserver/rpc/inventory/internal/server"
|
"muyu-apiserver/rpc/inventory/internal/server"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
@ -25,6 +26,8 @@ func main() {
|
|||||||
conf.MustLoad(*configFile, &c)
|
conf.MustLoad(*configFile, &c)
|
||||||
ctx := svc.NewServiceContext(c)
|
ctx := svc.NewServiceContext(c)
|
||||||
|
|
||||||
|
metrics.StartHTTP(c.PrometheusAddr)
|
||||||
|
|
||||||
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
||||||
pb.RegisterInventoryServiceServer(grpcServer, server.NewInventoryServiceServer(ctx))
|
pb.RegisterInventoryServiceServer(grpcServer, server.NewInventoryServiceServer(ctx))
|
||||||
|
|
||||||
@ -32,6 +35,7 @@ func main() {
|
|||||||
reflection.Register(grpcServer)
|
reflection.Register(grpcServer)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
s.AddUnaryInterceptors(metrics.UnaryServerInterceptor())
|
||||||
defer s.Stop()
|
defer s.Stop()
|
||||||
|
|
||||||
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
|
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
|
||||||
|
|||||||
@ -12,16 +12,11 @@ message ProductInfo {
|
|||||||
string image_url = 3;
|
string image_url = 3;
|
||||||
string spec = 4;
|
string spec = 4;
|
||||||
string color = 5;
|
string color = 5;
|
||||||
int64 unit_pieces = 6;
|
string sales_price = 6;
|
||||||
int64 unit_rolls = 7;
|
string remark = 7;
|
||||||
string stock_quantity = 8;
|
int64 status = 8;
|
||||||
string location = 9;
|
string created_at = 9;
|
||||||
string cost_price = 10;
|
string updated_at = 10;
|
||||||
string sales_price = 11;
|
|
||||||
string remark = 12;
|
|
||||||
int64 status = 13;
|
|
||||||
string created_at = 14;
|
|
||||||
string updated_at = 15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateProductReq {
|
message CreateProductReq {
|
||||||
@ -29,13 +24,9 @@ message CreateProductReq {
|
|||||||
string image_url = 2;
|
string image_url = 2;
|
||||||
string spec = 3;
|
string spec = 3;
|
||||||
string color = 4;
|
string color = 4;
|
||||||
int64 unit_pieces = 5;
|
string sales_price = 5;
|
||||||
int64 unit_rolls = 6;
|
string remark = 6;
|
||||||
string stock_quantity = 7;
|
repeated PanInput pans = 7;
|
||||||
string location = 8;
|
|
||||||
string cost_price = 9;
|
|
||||||
string sales_price = 10;
|
|
||||||
string remark = 11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateProductReq {
|
message UpdateProductReq {
|
||||||
@ -44,13 +35,8 @@ message UpdateProductReq {
|
|||||||
string image_url = 3;
|
string image_url = 3;
|
||||||
string spec = 4;
|
string spec = 4;
|
||||||
string color = 5;
|
string color = 5;
|
||||||
int64 unit_pieces = 6;
|
string sales_price = 6;
|
||||||
int64 unit_rolls = 7;
|
string remark = 7;
|
||||||
string stock_quantity = 8;
|
|
||||||
string location = 9;
|
|
||||||
string cost_price = 10;
|
|
||||||
string sales_price = 11;
|
|
||||||
string remark = 12;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeleteProductReq {
|
message DeleteProductReq {
|
||||||
@ -67,8 +53,7 @@ message ListProductReq {
|
|||||||
string product_name = 3;
|
string product_name = 3;
|
||||||
string spec = 4;
|
string spec = 4;
|
||||||
string color = 5;
|
string color = 5;
|
||||||
string location = 6;
|
int64 status = 6;
|
||||||
int64 status = 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListProductResp {
|
message ListProductResp {
|
||||||
@ -76,6 +61,161 @@ message ListProductResp {
|
|||||||
repeated ProductInfo list = 2;
|
repeated ProductInfo list = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== Pan (盘) ====================
|
||||||
|
|
||||||
|
message PanInfo {
|
||||||
|
string pan_id = 1;
|
||||||
|
string product_id = 2;
|
||||||
|
string name = 3;
|
||||||
|
string position = 4;
|
||||||
|
int64 sort_order = 5;
|
||||||
|
repeated BoltInfo bolts = 6;
|
||||||
|
int64 bolt_count = 7;
|
||||||
|
string total_length = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanInput {
|
||||||
|
string name = 1;
|
||||||
|
string position = 2;
|
||||||
|
repeated string bolt_lengths = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListPanReq {
|
||||||
|
string product_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListPanResp {
|
||||||
|
repeated PanInfo list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SavePansReq {
|
||||||
|
string product_id = 1;
|
||||||
|
repeated PanInput pans = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Bolt (匹) ====================
|
||||||
|
|
||||||
|
message BoltInfo {
|
||||||
|
string bolt_id = 1;
|
||||||
|
string pan_id = 2;
|
||||||
|
string length_m = 3;
|
||||||
|
int64 sort_order = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListBoltReq {
|
||||||
|
string pan_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListBoltResp {
|
||||||
|
repeated BoltInfo list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SaveBoltsReq {
|
||||||
|
string pan_id = 1;
|
||||||
|
repeated string lengths = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Product Tree (三层详情) ====================
|
||||||
|
|
||||||
|
message ProductTreeResp {
|
||||||
|
ProductInfo product = 1;
|
||||||
|
repeated PanInfo pans = 2;
|
||||||
|
int64 total_pan_count = 3;
|
||||||
|
int64 total_bolt_count = 4;
|
||||||
|
string total_length_m = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Panel 1: Product Summary ====================
|
||||||
|
|
||||||
|
message ProductSummaryItem {
|
||||||
|
string product_name = 1;
|
||||||
|
string spec = 2;
|
||||||
|
int64 color_count = 3;
|
||||||
|
int64 total_pan_count = 4;
|
||||||
|
int64 total_bolt_count = 5;
|
||||||
|
string total_length_m = 6;
|
||||||
|
string colors = 7;
|
||||||
|
string locations = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListProductSummaryReq {}
|
||||||
|
|
||||||
|
message ListProductSummaryResp {
|
||||||
|
repeated ProductSummaryItem list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Panel 2: Color Detail ====================
|
||||||
|
|
||||||
|
message ColorDetailItem {
|
||||||
|
string product_id = 1;
|
||||||
|
string product_name = 2;
|
||||||
|
string color = 3;
|
||||||
|
string spec = 4;
|
||||||
|
string image_url = 5;
|
||||||
|
int64 pan_count = 6;
|
||||||
|
int64 bolt_count = 7;
|
||||||
|
string total_length_m = 8;
|
||||||
|
string locations = 9;
|
||||||
|
string sales_price = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListColorDetailReq {
|
||||||
|
string product_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListColorDetailResp {
|
||||||
|
repeated ColorDetailItem list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Pan / Bolt List View ====================
|
||||||
|
|
||||||
|
message PanListItem {
|
||||||
|
string pan_id = 1;
|
||||||
|
string product_id = 2;
|
||||||
|
string name = 3;
|
||||||
|
string position = 4;
|
||||||
|
string product_name = 5;
|
||||||
|
string colors = 6; // aggregated from bolt.color, no spec
|
||||||
|
int64 bolt_count = 7;
|
||||||
|
string total_length_m = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListPanViewReq {
|
||||||
|
int64 page = 1;
|
||||||
|
int64 page_size = 2;
|
||||||
|
string product_name = 3;
|
||||||
|
string position = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListPanViewResp {
|
||||||
|
int64 total = 1;
|
||||||
|
repeated PanListItem list = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BoltListItem {
|
||||||
|
string bolt_id = 1;
|
||||||
|
string pan_id = 2;
|
||||||
|
string length_m = 3;
|
||||||
|
string color = 4; // bolt's own color, no spec
|
||||||
|
int64 sort_order = 5;
|
||||||
|
string pan_name = 6;
|
||||||
|
string position = 7;
|
||||||
|
string product_id = 8;
|
||||||
|
string product_name = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListBoltViewReq {
|
||||||
|
int64 page = 1;
|
||||||
|
int64 page_size = 2;
|
||||||
|
string product_name = 3;
|
||||||
|
string position = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListBoltViewResp {
|
||||||
|
int64 total = 1;
|
||||||
|
repeated BoltListItem list = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== Stock Import ====================
|
// ==================== Stock Import ====================
|
||||||
|
|
||||||
message ImportProductReq {
|
message ImportProductReq {
|
||||||
@ -120,8 +260,8 @@ message StockSummaryReq {}
|
|||||||
message StockSummaryResp {
|
message StockSummaryResp {
|
||||||
int64 product_count = 1;
|
int64 product_count = 1;
|
||||||
int64 total_pieces = 2;
|
int64 total_pieces = 2;
|
||||||
int64 total_rolls = 3;
|
int64 total_pans = 3;
|
||||||
string total_cost_value = 4;
|
string total_length_m = 4;
|
||||||
string total_sales_value = 5;
|
string total_sales_value = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,13 +424,34 @@ message Empty {}
|
|||||||
// ==================== Service ====================
|
// ==================== Service ====================
|
||||||
|
|
||||||
service InventoryService {
|
service InventoryService {
|
||||||
// Product
|
// Product CRUD
|
||||||
rpc CreateProduct(CreateProductReq) returns (IdResp);
|
rpc CreateProduct(CreateProductReq) returns (IdResp);
|
||||||
rpc UpdateProduct(UpdateProductReq) returns (Empty);
|
rpc UpdateProduct(UpdateProductReq) returns (Empty);
|
||||||
rpc DeleteProduct(DeleteProductReq) returns (Empty);
|
rpc DeleteProduct(DeleteProductReq) returns (Empty);
|
||||||
rpc GetProduct(GetProductReq) returns (ProductInfo);
|
rpc GetProduct(GetProductReq) returns (ProductInfo);
|
||||||
rpc ListProduct(ListProductReq) returns (ListProductResp);
|
rpc ListProduct(ListProductReq) returns (ListProductResp);
|
||||||
|
|
||||||
|
// Product Tree (panel 3)
|
||||||
|
rpc GetProductTree(GetProductReq) returns (ProductTreeResp);
|
||||||
|
|
||||||
|
// Product Summary (panel 1)
|
||||||
|
rpc ListProductSummary(ListProductSummaryReq) returns (ListProductSummaryResp);
|
||||||
|
|
||||||
|
// Color Detail (panel 2)
|
||||||
|
rpc ListColorDetail(ListColorDetailReq) returns (ListColorDetailResp);
|
||||||
|
|
||||||
|
// Pan / Bolt list views (dimension panels)
|
||||||
|
rpc ListPanView(ListPanViewReq) returns (ListPanViewResp);
|
||||||
|
rpc ListBoltView(ListBoltViewReq) returns (ListBoltViewResp);
|
||||||
|
|
||||||
|
// Pan CRUD
|
||||||
|
rpc ListPans(ListPanReq) returns (ListPanResp);
|
||||||
|
rpc SavePans(SavePansReq) returns (Empty);
|
||||||
|
|
||||||
|
// Bolt CRUD
|
||||||
|
rpc ListBolts(ListBoltReq) returns (ListBoltResp);
|
||||||
|
rpc SaveBolts(SaveBoltsReq) returns (Empty);
|
||||||
|
|
||||||
// Import
|
// Import
|
||||||
rpc ImportProducts(ImportProductReq) returns (ImportProductResp);
|
rpc ImportProducts(ImportProductReq) returns (ImportProductResp);
|
||||||
rpc ListImportLog(ListImportLogReq) returns (ListImportLogResp);
|
rpc ListImportLog(ListImportLogReq) returns (ListImportLogResp);
|
||||||
|
|||||||
@ -14,50 +14,87 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ApproveStockAdjustReq = pb.ApproveStockAdjustReq
|
ApproveStockAdjustReq = pb.ApproveStockAdjustReq
|
||||||
ConfirmStockCheckReq = pb.ConfirmStockCheckReq
|
BoltListItem = pb.BoltListItem
|
||||||
CreateProductReq = pb.CreateProductReq
|
BoltInfo = pb.BoltInfo
|
||||||
CreateStockAdjustReq = pb.CreateStockAdjustReq
|
ColorDetailItem = pb.ColorDetailItem
|
||||||
CreateStockCheckReq = pb.CreateStockCheckReq
|
ConfirmStockCheckReq = pb.ConfirmStockCheckReq
|
||||||
DeleteProductReq = pb.DeleteProductReq
|
CreateProductReq = pb.CreateProductReq
|
||||||
Empty = pb.Empty
|
CreateStockAdjustReq = pb.CreateStockAdjustReq
|
||||||
GetProductReq = pb.GetProductReq
|
CreateStockCheckReq = pb.CreateStockCheckReq
|
||||||
GetStockAdjustReq = pb.GetStockAdjustReq
|
DeleteProductReq = pb.DeleteProductReq
|
||||||
GetStockCheckReq = pb.GetStockCheckReq
|
Empty = pb.Empty
|
||||||
IdResp = pb.IdResp
|
GetProductReq = pb.GetProductReq
|
||||||
ImportLogInfo = pb.ImportLogInfo
|
GetStockAdjustReq = pb.GetStockAdjustReq
|
||||||
ImportProductReq = pb.ImportProductReq
|
GetStockCheckReq = pb.GetStockCheckReq
|
||||||
ImportProductResp = pb.ImportProductResp
|
IdResp = pb.IdResp
|
||||||
ListImportLogReq = pb.ListImportLogReq
|
ImportLogInfo = pb.ImportLogInfo
|
||||||
ListImportLogResp = pb.ListImportLogResp
|
ImportProductReq = pb.ImportProductReq
|
||||||
ListProductReq = pb.ListProductReq
|
ImportProductResp = pb.ImportProductResp
|
||||||
ListProductResp = pb.ListProductResp
|
ListBoltReq = pb.ListBoltReq
|
||||||
ListStockAdjustReq = pb.ListStockAdjustReq
|
ListBoltResp = pb.ListBoltResp
|
||||||
ListStockAdjustResp = pb.ListStockAdjustResp
|
ListBoltViewReq = pb.ListBoltViewReq
|
||||||
ListStockCheckReq = pb.ListStockCheckReq
|
ListBoltViewResp = pb.ListBoltViewResp
|
||||||
ListStockCheckResp = pb.ListStockCheckResp
|
ListColorDetailReq = pb.ListColorDetailReq
|
||||||
ProductInfo = pb.ProductInfo
|
ListPanViewReq = pb.ListPanViewReq
|
||||||
StockAdjustDetailInfo = pb.StockAdjustDetailInfo
|
ListPanViewResp = pb.ListPanViewResp
|
||||||
StockAdjustDetailReq = pb.StockAdjustDetailReq
|
PanListItem = pb.PanListItem
|
||||||
StockAdjustInfo = pb.StockAdjustInfo
|
ListColorDetailResp = pb.ListColorDetailResp
|
||||||
StockCheckDetailInfo = pb.StockCheckDetailInfo
|
ListImportLogReq = pb.ListImportLogReq
|
||||||
StockCheckDetailReq = pb.StockCheckDetailReq
|
ListImportLogResp = pb.ListImportLogResp
|
||||||
StockCheckInfo = pb.StockCheckInfo
|
ListPanReq = pb.ListPanReq
|
||||||
StockGroupItem = pb.StockGroupItem
|
ListPanResp = pb.ListPanResp
|
||||||
StockGroupReq = pb.StockGroupReq
|
ListProductReq = pb.ListProductReq
|
||||||
StockGroupResp = pb.StockGroupResp
|
ListProductResp = pb.ListProductResp
|
||||||
StockSummaryReq = pb.StockSummaryReq
|
ListProductSummaryReq = pb.ListProductSummaryReq
|
||||||
StockSummaryResp = pb.StockSummaryResp
|
ListProductSummaryResp = pb.ListProductSummaryResp
|
||||||
UpdateProductReq = pb.UpdateProductReq
|
ListStockAdjustReq = pb.ListStockAdjustReq
|
||||||
UpdateStockCheckReq = pb.UpdateStockCheckReq
|
ListStockAdjustResp = pb.ListStockAdjustResp
|
||||||
|
ListStockCheckReq = pb.ListStockCheckReq
|
||||||
|
ListStockCheckResp = pb.ListStockCheckResp
|
||||||
|
PanInfo = pb.PanInfo
|
||||||
|
PanInput = pb.PanInput
|
||||||
|
ProductInfo = pb.ProductInfo
|
||||||
|
ProductSummaryItem = pb.ProductSummaryItem
|
||||||
|
ProductTreeResp = pb.ProductTreeResp
|
||||||
|
SaveBoltsReq = pb.SaveBoltsReq
|
||||||
|
SavePansReq = pb.SavePansReq
|
||||||
|
StockAdjustDetailInfo = pb.StockAdjustDetailInfo
|
||||||
|
StockAdjustDetailReq = pb.StockAdjustDetailReq
|
||||||
|
StockAdjustInfo = pb.StockAdjustInfo
|
||||||
|
StockCheckDetailInfo = pb.StockCheckDetailInfo
|
||||||
|
StockCheckDetailReq = pb.StockCheckDetailReq
|
||||||
|
StockCheckInfo = pb.StockCheckInfo
|
||||||
|
StockGroupItem = pb.StockGroupItem
|
||||||
|
StockGroupReq = pb.StockGroupReq
|
||||||
|
StockGroupResp = pb.StockGroupResp
|
||||||
|
StockSummaryReq = pb.StockSummaryReq
|
||||||
|
StockSummaryResp = pb.StockSummaryResp
|
||||||
|
UpdateProductReq = pb.UpdateProductReq
|
||||||
|
UpdateStockCheckReq = pb.UpdateStockCheckReq
|
||||||
|
|
||||||
InventoryService interface {
|
InventoryService interface {
|
||||||
// Product
|
// Product CRUD
|
||||||
CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error)
|
CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error)
|
||||||
UpdateProduct(ctx context.Context, in *UpdateProductReq, opts ...grpc.CallOption) (*Empty, error)
|
UpdateProduct(ctx context.Context, in *UpdateProductReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
DeleteProduct(ctx context.Context, in *DeleteProductReq, opts ...grpc.CallOption) (*Empty, error)
|
DeleteProduct(ctx context.Context, in *DeleteProductReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
GetProduct(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductInfo, error)
|
GetProduct(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductInfo, error)
|
||||||
ListProduct(ctx context.Context, in *ListProductReq, opts ...grpc.CallOption) (*ListProductResp, error)
|
ListProduct(ctx context.Context, in *ListProductReq, opts ...grpc.CallOption) (*ListProductResp, error)
|
||||||
|
// Product Tree (panel 3)
|
||||||
|
GetProductTree(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductTreeResp, error)
|
||||||
|
// Product Summary (panel 1)
|
||||||
|
ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error)
|
||||||
|
// Color Detail (panel 2)
|
||||||
|
ListColorDetail(ctx context.Context, in *ListColorDetailReq, opts ...grpc.CallOption) (*ListColorDetailResp, error)
|
||||||
|
// Pan / Bolt list views
|
||||||
|
ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error)
|
||||||
|
ListBoltView(ctx context.Context, in *ListBoltViewReq, opts ...grpc.CallOption) (*ListBoltViewResp, error)
|
||||||
|
// Pan CRUD
|
||||||
|
ListPans(ctx context.Context, in *ListPanReq, opts ...grpc.CallOption) (*ListPanResp, error)
|
||||||
|
SavePans(ctx context.Context, in *SavePansReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
|
// Bolt CRUD
|
||||||
|
ListBolts(ctx context.Context, in *ListBoltReq, opts ...grpc.CallOption) (*ListBoltResp, error)
|
||||||
|
SaveBolts(ctx context.Context, in *SaveBoltsReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
// Import
|
// Import
|
||||||
ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error)
|
ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error)
|
||||||
ListImportLog(ctx context.Context, in *ListImportLogReq, opts ...grpc.CallOption) (*ListImportLogResp, error)
|
ListImportLog(ctx context.Context, in *ListImportLogReq, opts ...grpc.CallOption) (*ListImportLogResp, error)
|
||||||
@ -88,7 +125,7 @@ func NewInventoryService(cli zrpc.Client) InventoryService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Product
|
// Product CRUD
|
||||||
func (m *defaultInventoryService) CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error) {
|
func (m *defaultInventoryService) CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error) {
|
||||||
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
return client.CreateProduct(ctx, in, opts...)
|
return client.CreateProduct(ctx, in, opts...)
|
||||||
@ -114,6 +151,51 @@ func (m *defaultInventoryService) ListProduct(ctx context.Context, in *ListProdu
|
|||||||
return client.ListProduct(ctx, in, opts...)
|
return client.ListProduct(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) GetProductTree(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductTreeResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.GetProductTree(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.ListProductSummary(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) ListColorDetail(ctx context.Context, in *ListColorDetailReq, opts ...grpc.CallOption) (*ListColorDetailResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.ListColorDetail(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.ListPanView(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) ListBoltView(ctx context.Context, in *ListBoltViewReq, opts ...grpc.CallOption) (*ListBoltViewResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.ListBoltView(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) ListPans(ctx context.Context, in *ListPanReq, opts ...grpc.CallOption) (*ListPanResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.ListPans(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) SavePans(ctx context.Context, in *SavePansReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.SavePans(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) ListBolts(ctx context.Context, in *ListBoltReq, opts ...grpc.CallOption) (*ListBoltResp, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.ListBolts(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultInventoryService) SaveBolts(ctx context.Context, in *SaveBoltsReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
return client.SaveBolts(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
// Import
|
// Import
|
||||||
func (m *defaultInventoryService) ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error) {
|
func (m *defaultInventoryService) ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error) {
|
||||||
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.2.0
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
// - protoc v3.20.3
|
// - protoc v5.29.3
|
||||||
// source: rpc/inventory/inventory.proto
|
// source: inventory.proto
|
||||||
|
|
||||||
package pb
|
package pb
|
||||||
|
|
||||||
@ -15,19 +15,64 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
InventoryService_CreateProduct_FullMethodName = "/inventory.InventoryService/CreateProduct"
|
||||||
|
InventoryService_UpdateProduct_FullMethodName = "/inventory.InventoryService/UpdateProduct"
|
||||||
|
InventoryService_DeleteProduct_FullMethodName = "/inventory.InventoryService/DeleteProduct"
|
||||||
|
InventoryService_GetProduct_FullMethodName = "/inventory.InventoryService/GetProduct"
|
||||||
|
InventoryService_ListProduct_FullMethodName = "/inventory.InventoryService/ListProduct"
|
||||||
|
InventoryService_GetProductTree_FullMethodName = "/inventory.InventoryService/GetProductTree"
|
||||||
|
InventoryService_ListProductSummary_FullMethodName = "/inventory.InventoryService/ListProductSummary"
|
||||||
|
InventoryService_ListColorDetail_FullMethodName = "/inventory.InventoryService/ListColorDetail"
|
||||||
|
InventoryService_ListPanView_FullMethodName = "/inventory.InventoryService/ListPanView"
|
||||||
|
InventoryService_ListBoltView_FullMethodName = "/inventory.InventoryService/ListBoltView"
|
||||||
|
InventoryService_ListPans_FullMethodName = "/inventory.InventoryService/ListPans"
|
||||||
|
InventoryService_SavePans_FullMethodName = "/inventory.InventoryService/SavePans"
|
||||||
|
InventoryService_ListBolts_FullMethodName = "/inventory.InventoryService/ListBolts"
|
||||||
|
InventoryService_SaveBolts_FullMethodName = "/inventory.InventoryService/SaveBolts"
|
||||||
|
InventoryService_ImportProducts_FullMethodName = "/inventory.InventoryService/ImportProducts"
|
||||||
|
InventoryService_ListImportLog_FullMethodName = "/inventory.InventoryService/ListImportLog"
|
||||||
|
InventoryService_GetStockSummary_FullMethodName = "/inventory.InventoryService/GetStockSummary"
|
||||||
|
InventoryService_GetStockGroup_FullMethodName = "/inventory.InventoryService/GetStockGroup"
|
||||||
|
InventoryService_CreateStockCheck_FullMethodName = "/inventory.InventoryService/CreateStockCheck"
|
||||||
|
InventoryService_UpdateStockCheck_FullMethodName = "/inventory.InventoryService/UpdateStockCheck"
|
||||||
|
InventoryService_ConfirmStockCheck_FullMethodName = "/inventory.InventoryService/ConfirmStockCheck"
|
||||||
|
InventoryService_GetStockCheck_FullMethodName = "/inventory.InventoryService/GetStockCheck"
|
||||||
|
InventoryService_ListStockCheck_FullMethodName = "/inventory.InventoryService/ListStockCheck"
|
||||||
|
InventoryService_CreateStockAdjust_FullMethodName = "/inventory.InventoryService/CreateStockAdjust"
|
||||||
|
InventoryService_ApproveStockAdjust_FullMethodName = "/inventory.InventoryService/ApproveStockAdjust"
|
||||||
|
InventoryService_GetStockAdjust_FullMethodName = "/inventory.InventoryService/GetStockAdjust"
|
||||||
|
InventoryService_ListStockAdjust_FullMethodName = "/inventory.InventoryService/ListStockAdjust"
|
||||||
|
)
|
||||||
|
|
||||||
// InventoryServiceClient is the client API for InventoryService service.
|
// InventoryServiceClient is the client API for InventoryService service.
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
type InventoryServiceClient interface {
|
type InventoryServiceClient interface {
|
||||||
// Product
|
// Product CRUD
|
||||||
CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error)
|
CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error)
|
||||||
UpdateProduct(ctx context.Context, in *UpdateProductReq, opts ...grpc.CallOption) (*Empty, error)
|
UpdateProduct(ctx context.Context, in *UpdateProductReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
DeleteProduct(ctx context.Context, in *DeleteProductReq, opts ...grpc.CallOption) (*Empty, error)
|
DeleteProduct(ctx context.Context, in *DeleteProductReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
GetProduct(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductInfo, error)
|
GetProduct(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductInfo, error)
|
||||||
ListProduct(ctx context.Context, in *ListProductReq, opts ...grpc.CallOption) (*ListProductResp, error)
|
ListProduct(ctx context.Context, in *ListProductReq, opts ...grpc.CallOption) (*ListProductResp, error)
|
||||||
|
// Product Tree (panel 3)
|
||||||
|
GetProductTree(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductTreeResp, error)
|
||||||
|
// Product Summary (panel 1)
|
||||||
|
ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error)
|
||||||
|
// Color Detail (panel 2)
|
||||||
|
ListColorDetail(ctx context.Context, in *ListColorDetailReq, opts ...grpc.CallOption) (*ListColorDetailResp, error)
|
||||||
|
// Pan / Bolt list views (dimension panels)
|
||||||
|
ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error)
|
||||||
|
ListBoltView(ctx context.Context, in *ListBoltViewReq, opts ...grpc.CallOption) (*ListBoltViewResp, error)
|
||||||
|
// Pan CRUD
|
||||||
|
ListPans(ctx context.Context, in *ListPanReq, opts ...grpc.CallOption) (*ListPanResp, error)
|
||||||
|
SavePans(ctx context.Context, in *SavePansReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
|
// Bolt CRUD
|
||||||
|
ListBolts(ctx context.Context, in *ListBoltReq, opts ...grpc.CallOption) (*ListBoltResp, error)
|
||||||
|
SaveBolts(ctx context.Context, in *SaveBoltsReq, opts ...grpc.CallOption) (*Empty, error)
|
||||||
// Import
|
// Import
|
||||||
ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error)
|
ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error)
|
||||||
ListImportLog(ctx context.Context, in *ListImportLogReq, opts ...grpc.CallOption) (*ListImportLogResp, error)
|
ListImportLog(ctx context.Context, in *ListImportLogReq, opts ...grpc.CallOption) (*ListImportLogResp, error)
|
||||||
@ -56,8 +101,9 @@ func NewInventoryServiceClient(cc grpc.ClientConnInterface) InventoryServiceClie
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error) {
|
func (c *inventoryServiceClient) CreateProduct(ctx context.Context, in *CreateProductReq, opts ...grpc.CallOption) (*IdResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(IdResp)
|
out := new(IdResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/CreateProduct", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_CreateProduct_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -65,8 +111,9 @@ func (c *inventoryServiceClient) CreateProduct(ctx context.Context, in *CreatePr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) UpdateProduct(ctx context.Context, in *UpdateProductReq, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *inventoryServiceClient) UpdateProduct(ctx context.Context, in *UpdateProductReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/UpdateProduct", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_UpdateProduct_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -74,8 +121,9 @@ func (c *inventoryServiceClient) UpdateProduct(ctx context.Context, in *UpdatePr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) DeleteProduct(ctx context.Context, in *DeleteProductReq, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *inventoryServiceClient) DeleteProduct(ctx context.Context, in *DeleteProductReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/DeleteProduct", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_DeleteProduct_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -83,8 +131,9 @@ func (c *inventoryServiceClient) DeleteProduct(ctx context.Context, in *DeletePr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) GetProduct(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductInfo, error) {
|
func (c *inventoryServiceClient) GetProduct(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductInfo, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ProductInfo)
|
out := new(ProductInfo)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/GetProduct", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_GetProduct_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -92,8 +141,99 @@ func (c *inventoryServiceClient) GetProduct(ctx context.Context, in *GetProductR
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ListProduct(ctx context.Context, in *ListProductReq, opts ...grpc.CallOption) (*ListProductResp, error) {
|
func (c *inventoryServiceClient) ListProduct(ctx context.Context, in *ListProductReq, opts ...grpc.CallOption) (*ListProductResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListProductResp)
|
out := new(ListProductResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ListProduct", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ListProduct_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) GetProductTree(ctx context.Context, in *GetProductReq, opts ...grpc.CallOption) (*ProductTreeResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ProductTreeResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_GetProductTree_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListProductSummaryResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_ListProductSummary_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) ListColorDetail(ctx context.Context, in *ListColorDetailReq, opts ...grpc.CallOption) (*ListColorDetailResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListColorDetailResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_ListColorDetail_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListPanViewResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_ListPanView_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) ListBoltView(ctx context.Context, in *ListBoltViewReq, opts ...grpc.CallOption) (*ListBoltViewResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListBoltViewResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_ListBoltView_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) ListPans(ctx context.Context, in *ListPanReq, opts ...grpc.CallOption) (*ListPanResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListPanResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_ListPans_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) SavePans(ctx context.Context, in *SavePansReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(Empty)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_SavePans_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) ListBolts(ctx context.Context, in *ListBoltReq, opts ...grpc.CallOption) (*ListBoltResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListBoltResp)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_ListBolts_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *inventoryServiceClient) SaveBolts(ctx context.Context, in *SaveBoltsReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(Empty)
|
||||||
|
err := c.cc.Invoke(ctx, InventoryService_SaveBolts_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -101,8 +241,9 @@ func (c *inventoryServiceClient) ListProduct(ctx context.Context, in *ListProduc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error) {
|
func (c *inventoryServiceClient) ImportProducts(ctx context.Context, in *ImportProductReq, opts ...grpc.CallOption) (*ImportProductResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ImportProductResp)
|
out := new(ImportProductResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ImportProducts", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ImportProducts_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -110,8 +251,9 @@ func (c *inventoryServiceClient) ImportProducts(ctx context.Context, in *ImportP
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ListImportLog(ctx context.Context, in *ListImportLogReq, opts ...grpc.CallOption) (*ListImportLogResp, error) {
|
func (c *inventoryServiceClient) ListImportLog(ctx context.Context, in *ListImportLogReq, opts ...grpc.CallOption) (*ListImportLogResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListImportLogResp)
|
out := new(ListImportLogResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ListImportLog", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ListImportLog_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -119,8 +261,9 @@ func (c *inventoryServiceClient) ListImportLog(ctx context.Context, in *ListImpo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) GetStockSummary(ctx context.Context, in *StockSummaryReq, opts ...grpc.CallOption) (*StockSummaryResp, error) {
|
func (c *inventoryServiceClient) GetStockSummary(ctx context.Context, in *StockSummaryReq, opts ...grpc.CallOption) (*StockSummaryResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(StockSummaryResp)
|
out := new(StockSummaryResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/GetStockSummary", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_GetStockSummary_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -128,8 +271,9 @@ func (c *inventoryServiceClient) GetStockSummary(ctx context.Context, in *StockS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) GetStockGroup(ctx context.Context, in *StockGroupReq, opts ...grpc.CallOption) (*StockGroupResp, error) {
|
func (c *inventoryServiceClient) GetStockGroup(ctx context.Context, in *StockGroupReq, opts ...grpc.CallOption) (*StockGroupResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(StockGroupResp)
|
out := new(StockGroupResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/GetStockGroup", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_GetStockGroup_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -137,8 +281,9 @@ func (c *inventoryServiceClient) GetStockGroup(ctx context.Context, in *StockGro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) CreateStockCheck(ctx context.Context, in *CreateStockCheckReq, opts ...grpc.CallOption) (*IdResp, error) {
|
func (c *inventoryServiceClient) CreateStockCheck(ctx context.Context, in *CreateStockCheckReq, opts ...grpc.CallOption) (*IdResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(IdResp)
|
out := new(IdResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/CreateStockCheck", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_CreateStockCheck_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -146,8 +291,9 @@ func (c *inventoryServiceClient) CreateStockCheck(ctx context.Context, in *Creat
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) UpdateStockCheck(ctx context.Context, in *UpdateStockCheckReq, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *inventoryServiceClient) UpdateStockCheck(ctx context.Context, in *UpdateStockCheckReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/UpdateStockCheck", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_UpdateStockCheck_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -155,8 +301,9 @@ func (c *inventoryServiceClient) UpdateStockCheck(ctx context.Context, in *Updat
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ConfirmStockCheck(ctx context.Context, in *ConfirmStockCheckReq, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *inventoryServiceClient) ConfirmStockCheck(ctx context.Context, in *ConfirmStockCheckReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ConfirmStockCheck", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ConfirmStockCheck_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -164,8 +311,9 @@ func (c *inventoryServiceClient) ConfirmStockCheck(ctx context.Context, in *Conf
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) GetStockCheck(ctx context.Context, in *GetStockCheckReq, opts ...grpc.CallOption) (*StockCheckInfo, error) {
|
func (c *inventoryServiceClient) GetStockCheck(ctx context.Context, in *GetStockCheckReq, opts ...grpc.CallOption) (*StockCheckInfo, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(StockCheckInfo)
|
out := new(StockCheckInfo)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/GetStockCheck", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_GetStockCheck_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -173,8 +321,9 @@ func (c *inventoryServiceClient) GetStockCheck(ctx context.Context, in *GetStock
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ListStockCheck(ctx context.Context, in *ListStockCheckReq, opts ...grpc.CallOption) (*ListStockCheckResp, error) {
|
func (c *inventoryServiceClient) ListStockCheck(ctx context.Context, in *ListStockCheckReq, opts ...grpc.CallOption) (*ListStockCheckResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListStockCheckResp)
|
out := new(ListStockCheckResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ListStockCheck", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ListStockCheck_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -182,8 +331,9 @@ func (c *inventoryServiceClient) ListStockCheck(ctx context.Context, in *ListSto
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) CreateStockAdjust(ctx context.Context, in *CreateStockAdjustReq, opts ...grpc.CallOption) (*IdResp, error) {
|
func (c *inventoryServiceClient) CreateStockAdjust(ctx context.Context, in *CreateStockAdjustReq, opts ...grpc.CallOption) (*IdResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(IdResp)
|
out := new(IdResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/CreateStockAdjust", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_CreateStockAdjust_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -191,8 +341,9 @@ func (c *inventoryServiceClient) CreateStockAdjust(ctx context.Context, in *Crea
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ApproveStockAdjust(ctx context.Context, in *ApproveStockAdjustReq, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *inventoryServiceClient) ApproveStockAdjust(ctx context.Context, in *ApproveStockAdjustReq, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ApproveStockAdjust", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ApproveStockAdjust_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -200,8 +351,9 @@ func (c *inventoryServiceClient) ApproveStockAdjust(ctx context.Context, in *App
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) GetStockAdjust(ctx context.Context, in *GetStockAdjustReq, opts ...grpc.CallOption) (*StockAdjustInfo, error) {
|
func (c *inventoryServiceClient) GetStockAdjust(ctx context.Context, in *GetStockAdjustReq, opts ...grpc.CallOption) (*StockAdjustInfo, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(StockAdjustInfo)
|
out := new(StockAdjustInfo)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/GetStockAdjust", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_GetStockAdjust_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -209,8 +361,9 @@ func (c *inventoryServiceClient) GetStockAdjust(ctx context.Context, in *GetStoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *inventoryServiceClient) ListStockAdjust(ctx context.Context, in *ListStockAdjustReq, opts ...grpc.CallOption) (*ListStockAdjustResp, error) {
|
func (c *inventoryServiceClient) ListStockAdjust(ctx context.Context, in *ListStockAdjustReq, opts ...grpc.CallOption) (*ListStockAdjustResp, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListStockAdjustResp)
|
out := new(ListStockAdjustResp)
|
||||||
err := c.cc.Invoke(ctx, "/inventory.InventoryService/ListStockAdjust", in, out, opts...)
|
err := c.cc.Invoke(ctx, InventoryService_ListStockAdjust_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -219,14 +372,29 @@ func (c *inventoryServiceClient) ListStockAdjust(ctx context.Context, in *ListSt
|
|||||||
|
|
||||||
// InventoryServiceServer is the server API for InventoryService service.
|
// InventoryServiceServer is the server API for InventoryService service.
|
||||||
// All implementations must embed UnimplementedInventoryServiceServer
|
// All implementations must embed UnimplementedInventoryServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility.
|
||||||
type InventoryServiceServer interface {
|
type InventoryServiceServer interface {
|
||||||
// Product
|
// Product CRUD
|
||||||
CreateProduct(context.Context, *CreateProductReq) (*IdResp, error)
|
CreateProduct(context.Context, *CreateProductReq) (*IdResp, error)
|
||||||
UpdateProduct(context.Context, *UpdateProductReq) (*Empty, error)
|
UpdateProduct(context.Context, *UpdateProductReq) (*Empty, error)
|
||||||
DeleteProduct(context.Context, *DeleteProductReq) (*Empty, error)
|
DeleteProduct(context.Context, *DeleteProductReq) (*Empty, error)
|
||||||
GetProduct(context.Context, *GetProductReq) (*ProductInfo, error)
|
GetProduct(context.Context, *GetProductReq) (*ProductInfo, error)
|
||||||
ListProduct(context.Context, *ListProductReq) (*ListProductResp, error)
|
ListProduct(context.Context, *ListProductReq) (*ListProductResp, error)
|
||||||
|
// Product Tree (panel 3)
|
||||||
|
GetProductTree(context.Context, *GetProductReq) (*ProductTreeResp, error)
|
||||||
|
// Product Summary (panel 1)
|
||||||
|
ListProductSummary(context.Context, *ListProductSummaryReq) (*ListProductSummaryResp, error)
|
||||||
|
// Color Detail (panel 2)
|
||||||
|
ListColorDetail(context.Context, *ListColorDetailReq) (*ListColorDetailResp, error)
|
||||||
|
// Pan / Bolt list views (dimension panels)
|
||||||
|
ListPanView(context.Context, *ListPanViewReq) (*ListPanViewResp, error)
|
||||||
|
ListBoltView(context.Context, *ListBoltViewReq) (*ListBoltViewResp, error)
|
||||||
|
// Pan CRUD
|
||||||
|
ListPans(context.Context, *ListPanReq) (*ListPanResp, error)
|
||||||
|
SavePans(context.Context, *SavePansReq) (*Empty, error)
|
||||||
|
// Bolt CRUD
|
||||||
|
ListBolts(context.Context, *ListBoltReq) (*ListBoltResp, error)
|
||||||
|
SaveBolts(context.Context, *SaveBoltsReq) (*Empty, error)
|
||||||
// Import
|
// Import
|
||||||
ImportProducts(context.Context, *ImportProductReq) (*ImportProductResp, error)
|
ImportProducts(context.Context, *ImportProductReq) (*ImportProductResp, error)
|
||||||
ListImportLog(context.Context, *ListImportLogReq) (*ListImportLogResp, error)
|
ListImportLog(context.Context, *ListImportLogReq) (*ListImportLogResp, error)
|
||||||
@ -247,9 +415,12 @@ type InventoryServiceServer interface {
|
|||||||
mustEmbedUnimplementedInventoryServiceServer()
|
mustEmbedUnimplementedInventoryServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedInventoryServiceServer must be embedded to have forward compatible implementations.
|
// UnimplementedInventoryServiceServer must be embedded to have
|
||||||
type UnimplementedInventoryServiceServer struct {
|
// forward compatible implementations.
|
||||||
}
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedInventoryServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedInventoryServiceServer) CreateProduct(context.Context, *CreateProductReq) (*IdResp, error) {
|
func (UnimplementedInventoryServiceServer) CreateProduct(context.Context, *CreateProductReq) (*IdResp, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CreateProduct not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method CreateProduct not implemented")
|
||||||
@ -266,6 +437,33 @@ func (UnimplementedInventoryServiceServer) GetProduct(context.Context, *GetProdu
|
|||||||
func (UnimplementedInventoryServiceServer) ListProduct(context.Context, *ListProductReq) (*ListProductResp, error) {
|
func (UnimplementedInventoryServiceServer) ListProduct(context.Context, *ListProductReq) (*ListProductResp, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListProduct not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ListProduct not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) GetProductTree(context.Context, *GetProductReq) (*ProductTreeResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetProductTree not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) ListProductSummary(context.Context, *ListProductSummaryReq) (*ListProductSummaryResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListProductSummary not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) ListColorDetail(context.Context, *ListColorDetailReq) (*ListColorDetailResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListColorDetail not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) ListPanView(context.Context, *ListPanViewReq) (*ListPanViewResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListPanView not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) ListBoltView(context.Context, *ListBoltViewReq) (*ListBoltViewResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListBoltView not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) ListPans(context.Context, *ListPanReq) (*ListPanResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListPans not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) SavePans(context.Context, *SavePansReq) (*Empty, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SavePans not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) ListBolts(context.Context, *ListBoltReq) (*ListBoltResp, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListBolts not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedInventoryServiceServer) SaveBolts(context.Context, *SaveBoltsReq) (*Empty, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SaveBolts not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedInventoryServiceServer) ImportProducts(context.Context, *ImportProductReq) (*ImportProductResp, error) {
|
func (UnimplementedInventoryServiceServer) ImportProducts(context.Context, *ImportProductReq) (*ImportProductResp, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ImportProducts not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ImportProducts not implemented")
|
||||||
}
|
}
|
||||||
@ -306,6 +504,7 @@ func (UnimplementedInventoryServiceServer) ListStockAdjust(context.Context, *Lis
|
|||||||
return nil, status.Errorf(codes.Unimplemented, "method ListStockAdjust not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ListStockAdjust not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedInventoryServiceServer) mustEmbedUnimplementedInventoryServiceServer() {}
|
func (UnimplementedInventoryServiceServer) mustEmbedUnimplementedInventoryServiceServer() {}
|
||||||
|
func (UnimplementedInventoryServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
// UnsafeInventoryServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeInventoryServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to InventoryServiceServer will
|
// Use of this interface is not recommended, as added methods to InventoryServiceServer will
|
||||||
@ -315,6 +514,13 @@ type UnsafeInventoryServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterInventoryServiceServer(s grpc.ServiceRegistrar, srv InventoryServiceServer) {
|
func RegisterInventoryServiceServer(s grpc.ServiceRegistrar, srv InventoryServiceServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedInventoryServiceServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
s.RegisterService(&InventoryService_ServiceDesc, srv)
|
s.RegisterService(&InventoryService_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +534,7 @@ func _InventoryService_CreateProduct_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/CreateProduct",
|
FullMethod: InventoryService_CreateProduct_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).CreateProduct(ctx, req.(*CreateProductReq))
|
return srv.(InventoryServiceServer).CreateProduct(ctx, req.(*CreateProductReq))
|
||||||
@ -346,7 +552,7 @@ func _InventoryService_UpdateProduct_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/UpdateProduct",
|
FullMethod: InventoryService_UpdateProduct_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).UpdateProduct(ctx, req.(*UpdateProductReq))
|
return srv.(InventoryServiceServer).UpdateProduct(ctx, req.(*UpdateProductReq))
|
||||||
@ -364,7 +570,7 @@ func _InventoryService_DeleteProduct_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/DeleteProduct",
|
FullMethod: InventoryService_DeleteProduct_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).DeleteProduct(ctx, req.(*DeleteProductReq))
|
return srv.(InventoryServiceServer).DeleteProduct(ctx, req.(*DeleteProductReq))
|
||||||
@ -382,7 +588,7 @@ func _InventoryService_GetProduct_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/GetProduct",
|
FullMethod: InventoryService_GetProduct_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).GetProduct(ctx, req.(*GetProductReq))
|
return srv.(InventoryServiceServer).GetProduct(ctx, req.(*GetProductReq))
|
||||||
@ -400,7 +606,7 @@ func _InventoryService_ListProduct_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ListProduct",
|
FullMethod: InventoryService_ListProduct_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ListProduct(ctx, req.(*ListProductReq))
|
return srv.(InventoryServiceServer).ListProduct(ctx, req.(*ListProductReq))
|
||||||
@ -408,6 +614,168 @@ func _InventoryService_ListProduct_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _InventoryService_GetProductTree_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetProductReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).GetProductTree(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_GetProductTree_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).GetProductTree(ctx, req.(*GetProductReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_ListProductSummary_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListProductSummaryReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).ListProductSummary(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_ListProductSummary_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).ListProductSummary(ctx, req.(*ListProductSummaryReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_ListColorDetail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListColorDetailReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).ListColorDetail(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_ListColorDetail_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).ListColorDetail(ctx, req.(*ListColorDetailReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_ListPanView_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListPanViewReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).ListPanView(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_ListPanView_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).ListPanView(ctx, req.(*ListPanViewReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_ListBoltView_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListBoltViewReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).ListBoltView(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_ListBoltView_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).ListBoltView(ctx, req.(*ListBoltViewReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_ListPans_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListPanReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).ListPans(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_ListPans_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).ListPans(ctx, req.(*ListPanReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_SavePans_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(SavePansReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).SavePans(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_SavePans_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).SavePans(ctx, req.(*SavePansReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_ListBolts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListBoltReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).ListBolts(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_ListBolts_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).ListBolts(ctx, req.(*ListBoltReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _InventoryService_SaveBolts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(SaveBoltsReq)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(InventoryServiceServer).SaveBolts(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: InventoryService_SaveBolts_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(InventoryServiceServer).SaveBolts(ctx, req.(*SaveBoltsReq))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _InventoryService_ImportProducts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _InventoryService_ImportProducts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(ImportProductReq)
|
in := new(ImportProductReq)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@ -418,7 +786,7 @@ func _InventoryService_ImportProducts_Handler(srv interface{}, ctx context.Conte
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ImportProducts",
|
FullMethod: InventoryService_ImportProducts_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ImportProducts(ctx, req.(*ImportProductReq))
|
return srv.(InventoryServiceServer).ImportProducts(ctx, req.(*ImportProductReq))
|
||||||
@ -436,7 +804,7 @@ func _InventoryService_ListImportLog_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ListImportLog",
|
FullMethod: InventoryService_ListImportLog_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ListImportLog(ctx, req.(*ListImportLogReq))
|
return srv.(InventoryServiceServer).ListImportLog(ctx, req.(*ListImportLogReq))
|
||||||
@ -454,7 +822,7 @@ func _InventoryService_GetStockSummary_Handler(srv interface{}, ctx context.Cont
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/GetStockSummary",
|
FullMethod: InventoryService_GetStockSummary_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).GetStockSummary(ctx, req.(*StockSummaryReq))
|
return srv.(InventoryServiceServer).GetStockSummary(ctx, req.(*StockSummaryReq))
|
||||||
@ -472,7 +840,7 @@ func _InventoryService_GetStockGroup_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/GetStockGroup",
|
FullMethod: InventoryService_GetStockGroup_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).GetStockGroup(ctx, req.(*StockGroupReq))
|
return srv.(InventoryServiceServer).GetStockGroup(ctx, req.(*StockGroupReq))
|
||||||
@ -490,7 +858,7 @@ func _InventoryService_CreateStockCheck_Handler(srv interface{}, ctx context.Con
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/CreateStockCheck",
|
FullMethod: InventoryService_CreateStockCheck_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).CreateStockCheck(ctx, req.(*CreateStockCheckReq))
|
return srv.(InventoryServiceServer).CreateStockCheck(ctx, req.(*CreateStockCheckReq))
|
||||||
@ -508,7 +876,7 @@ func _InventoryService_UpdateStockCheck_Handler(srv interface{}, ctx context.Con
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/UpdateStockCheck",
|
FullMethod: InventoryService_UpdateStockCheck_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).UpdateStockCheck(ctx, req.(*UpdateStockCheckReq))
|
return srv.(InventoryServiceServer).UpdateStockCheck(ctx, req.(*UpdateStockCheckReq))
|
||||||
@ -526,7 +894,7 @@ func _InventoryService_ConfirmStockCheck_Handler(srv interface{}, ctx context.Co
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ConfirmStockCheck",
|
FullMethod: InventoryService_ConfirmStockCheck_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ConfirmStockCheck(ctx, req.(*ConfirmStockCheckReq))
|
return srv.(InventoryServiceServer).ConfirmStockCheck(ctx, req.(*ConfirmStockCheckReq))
|
||||||
@ -544,7 +912,7 @@ func _InventoryService_GetStockCheck_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/GetStockCheck",
|
FullMethod: InventoryService_GetStockCheck_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).GetStockCheck(ctx, req.(*GetStockCheckReq))
|
return srv.(InventoryServiceServer).GetStockCheck(ctx, req.(*GetStockCheckReq))
|
||||||
@ -562,7 +930,7 @@ func _InventoryService_ListStockCheck_Handler(srv interface{}, ctx context.Conte
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ListStockCheck",
|
FullMethod: InventoryService_ListStockCheck_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ListStockCheck(ctx, req.(*ListStockCheckReq))
|
return srv.(InventoryServiceServer).ListStockCheck(ctx, req.(*ListStockCheckReq))
|
||||||
@ -580,7 +948,7 @@ func _InventoryService_CreateStockAdjust_Handler(srv interface{}, ctx context.Co
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/CreateStockAdjust",
|
FullMethod: InventoryService_CreateStockAdjust_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).CreateStockAdjust(ctx, req.(*CreateStockAdjustReq))
|
return srv.(InventoryServiceServer).CreateStockAdjust(ctx, req.(*CreateStockAdjustReq))
|
||||||
@ -598,7 +966,7 @@ func _InventoryService_ApproveStockAdjust_Handler(srv interface{}, ctx context.C
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ApproveStockAdjust",
|
FullMethod: InventoryService_ApproveStockAdjust_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ApproveStockAdjust(ctx, req.(*ApproveStockAdjustReq))
|
return srv.(InventoryServiceServer).ApproveStockAdjust(ctx, req.(*ApproveStockAdjustReq))
|
||||||
@ -616,7 +984,7 @@ func _InventoryService_GetStockAdjust_Handler(srv interface{}, ctx context.Conte
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/GetStockAdjust",
|
FullMethod: InventoryService_GetStockAdjust_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).GetStockAdjust(ctx, req.(*GetStockAdjustReq))
|
return srv.(InventoryServiceServer).GetStockAdjust(ctx, req.(*GetStockAdjustReq))
|
||||||
@ -634,7 +1002,7 @@ func _InventoryService_ListStockAdjust_Handler(srv interface{}, ctx context.Cont
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/inventory.InventoryService/ListStockAdjust",
|
FullMethod: InventoryService_ListStockAdjust_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(InventoryServiceServer).ListStockAdjust(ctx, req.(*ListStockAdjustReq))
|
return srv.(InventoryServiceServer).ListStockAdjust(ctx, req.(*ListStockAdjustReq))
|
||||||
@ -669,6 +1037,42 @@ var InventoryService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "ListProduct",
|
MethodName: "ListProduct",
|
||||||
Handler: _InventoryService_ListProduct_Handler,
|
Handler: _InventoryService_ListProduct_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "GetProductTree",
|
||||||
|
Handler: _InventoryService_GetProductTree_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListProductSummary",
|
||||||
|
Handler: _InventoryService_ListProductSummary_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListColorDetail",
|
||||||
|
Handler: _InventoryService_ListColorDetail_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListPanView",
|
||||||
|
Handler: _InventoryService_ListPanView_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListBoltView",
|
||||||
|
Handler: _InventoryService_ListBoltView_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListPans",
|
||||||
|
Handler: _InventoryService_ListPans_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SavePans",
|
||||||
|
Handler: _InventoryService_SavePans_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListBolts",
|
||||||
|
Handler: _InventoryService_ListBolts_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SaveBolts",
|
||||||
|
Handler: _InventoryService_SaveBolts_Handler,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
MethodName: "ImportProducts",
|
MethodName: "ImportProducts",
|
||||||
Handler: _InventoryService_ImportProducts_Handler,
|
Handler: _InventoryService_ImportProducts_Handler,
|
||||||
@ -723,5 +1127,5 @@ var InventoryService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "rpc/inventory/inventory.proto",
|
Metadata: "inventory.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"muyu-apiserver/model"
|
||||||
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/pkg/uid"
|
"muyu-apiserver/pkg/uid"
|
||||||
"muyu-apiserver/rpc/system/internal/svc"
|
"muyu-apiserver/rpc/system/internal/svc"
|
||||||
"muyu-apiserver/rpc/system/pb"
|
"muyu-apiserver/rpc/system/pb"
|
||||||
@ -28,9 +29,11 @@ func NewCreateRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Create
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *CreateRoleLogic) CreateRole(in *pb.CreateRoleReq) (*pb.IdResp, error) {
|
func (l *CreateRoleLogic) CreateRole(in *pb.CreateRoleReq) (*pb.IdResp, error) {
|
||||||
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
roleId := uid.Generate()
|
roleId := uid.Generate()
|
||||||
|
|
||||||
_, err := l.svcCtx.RoleModel.Insert(l.ctx, &model.SysRole{
|
_, err := l.svcCtx.RoleModel.Insert(l.ctx, &model.SysRole{
|
||||||
|
TenantId: tenantId,
|
||||||
RoleId: roleId,
|
RoleId: roleId,
|
||||||
RoleName: in.RoleName,
|
RoleName: in.RoleName,
|
||||||
RoleKey: in.RoleKey,
|
RoleKey: in.RoleKey,
|
||||||
|
|||||||
96
worker/graphsync/go.sum
Normal file
96
worker/graphsync/go.sum
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
github.com/IBM/sarama v1.43.3 h1:Yj6L2IaNvb2mRBop39N7mmJAHBVY3dTPncr3qGVkxPA=
|
||||||
|
github.com/IBM/sarama v1.43.3/go.mod h1:FVIRaLrhK3Cla/9FfRF5X9Zua2KpS3SYIXxhac1H+FQ=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=
|
||||||
|
github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
|
||||||
|
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||||
|
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||||
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
|
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||||
|
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||||
|
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||||
|
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||||
|
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||||
|
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
|
||||||
|
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
|
||||||
|
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
|
||||||
|
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||||
|
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||||
|
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||||
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/neo4j/neo4j-go-driver/v5 v5.28.0 h1:chDT68PHNa8JZRmjSkGzAbk1weLWo4rMtDvccvpobg0=
|
||||||
|
github.com/neo4j/neo4j-go-driver/v5 v5.28.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
Loading…
x
Reference in New Issue
Block a user