From e3f6fa236d0edbfeef8e28d5b4f70c168900ce24 Mon Sep 17 00:00:00 2001 From: kae_mihara Date: Sun, 5 Jul 2026 08:06:28 +0900 Subject: [PATCH] feat:improve product yarn ratio workflow (#5) * feat: support product yarn batches * feat: improve product yarn ratio workflow * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- deploy/mysql/init.sql | 100 +- .../20260703_add_product_yarn_batch.sql | 174 ++ gateway/gateway.api | 139 +- .../inventory/product/exportProductHandler.go | 8 +- .../productbatch/createProductBatchHandler.go | 32 + .../productbatch/deleteProductBatchHandler.go | 28 + .../productbatch/listProductBatchHandler.go | 26 + .../productbatch/updateProductBatchHandler.go | 34 + .../inventory/yarn/createYarnHandler.go | 29 + .../inventory/yarn/deleteYarnHandler.go | 26 + .../handler/inventory/yarn/getYarnHandler.go | 26 + .../handler/inventory/yarn/listYarnHandler.go | 29 + .../inventory/yarn/updateYarnHandler.go | 32 + gateway/internal/handler/routes.go | 67 + .../inventory/panbolt/listPanViewLogic.go | 2 + .../inventory/product/createProductLogic.go | 32 +- .../inventory/product/exportProductLogic.go | 102 +- .../inventory/product/getColorDetailLogic.go | 3 + .../inventory/product/importProductLogic.go | 9 + .../logic/inventory/product/listPansLogic.go | 4 + .../inventory/product/listProductLogic.go | 2 + .../inventory/product/updateProductLogic.go | 1 + .../productbatch/createProductBatchLogic.go | 34 + .../productbatch/deleteProductBatchLogic.go | 31 + .../logic/inventory/productbatch/helpers.go | 36 + .../productbatch/listProductBatchLogic.go | 35 + .../productbatch/updateProductBatchLogic.go | 37 + .../logic/inventory/yarn/createYarnLogic.go | 37 + .../logic/inventory/yarn/deleteYarnLogic.go | 30 + .../logic/inventory/yarn/getYarnLogic.go | 32 + .../internal/logic/inventory/yarn/helpers.go | 26 + .../logic/inventory/yarn/listYarnLogic.go | 39 + .../logic/inventory/yarn/updateYarnLogic.go | 41 + gateway/internal/types/types.go | 125 +- go.mod | 1 + go.sum | 2 + model/invproductbatchmodel.go | 81 + model/invproductbatchmodel_gen.go | 100 + model/invproductboltmodel.go | 2 +- model/invproductmodel.go | 70 +- model/invproductmodel_gen.go | 39 +- model/invproductmodel_test.go | 110 +- model/invproductpanmodel.go | 23 +- model/invproductpanmodel_gen.go | 7 +- model/invyarnmodel.go | 82 + model/invyarnmodel_gen.go | 100 + pkg/excelparse/native.go | 86 + pkg/excelparse/parse.go | 1 + pkg/excelparse/types.go | 31 +- rpc/inventory/internal/logic/batch_helpers.go | 140 ++ .../internal/logic/batch_helpers_test.go | 56 + .../internal/logic/createproductbatchlogic.go | 56 + .../internal/logic/createproductlogic.go | 67 +- .../internal/logic/createyarnlogic.go | 68 + .../internal/logic/deleteproductbatchlogic.go | 46 + .../internal/logic/deleteyarnlogic.go | 35 + .../internal/logic/getproductlogic.go | 14 +- .../internal/logic/getproducttreelogic.go | 23 +- rpc/inventory/internal/logic/getyarnlogic.go | 36 + .../internal/logic/importproductslogic.go | 44 +- .../internal/logic/listcolordetaillogic.go | 3 + rpc/inventory/internal/logic/listpanslogic.go | 14 + .../internal/logic/listpanviewlogic.go | 2 + .../internal/logic/listproductbatchlogic.go | 40 + .../internal/logic/listproductlogic.go | 16 +- rpc/inventory/internal/logic/listyarnlogic.go | 42 + rpc/inventory/internal/logic/productcode.go | 101 + .../internal/logic/saveboltslogic.go | 10 + rpc/inventory/internal/logic/savepanslogic.go | 55 +- .../internal/logic/updateproductbatchlogic.go | 43 + .../internal/logic/updateproductlogic.go | 13 +- .../internal/logic/updateyarnlogic.go | 62 + rpc/inventory/internal/logic/yarn_helpers.go | 25 + .../internal/server/inventoryserviceserver.go | 47 + rpc/inventory/internal/svc/servicecontext.go | 6 + rpc/inventory/inventory.proto | 139 ++ .../inventoryservice/inventoryservice.go | 70 + rpc/inventory/pb/inventory.pb.go | 1713 +++++++++++++++-- rpc/inventory/pb/inventory_grpc.pb.go | 406 +++- 79 files changed, 5146 insertions(+), 389 deletions(-) create mode 100644 deploy/mysql/migrations/20260703_add_product_yarn_batch.sql create mode 100644 gateway/internal/handler/inventory/productbatch/createProductBatchHandler.go create mode 100644 gateway/internal/handler/inventory/productbatch/deleteProductBatchHandler.go create mode 100644 gateway/internal/handler/inventory/productbatch/listProductBatchHandler.go create mode 100644 gateway/internal/handler/inventory/productbatch/updateProductBatchHandler.go create mode 100644 gateway/internal/handler/inventory/yarn/createYarnHandler.go create mode 100644 gateway/internal/handler/inventory/yarn/deleteYarnHandler.go create mode 100644 gateway/internal/handler/inventory/yarn/getYarnHandler.go create mode 100644 gateway/internal/handler/inventory/yarn/listYarnHandler.go create mode 100644 gateway/internal/handler/inventory/yarn/updateYarnHandler.go create mode 100644 gateway/internal/logic/inventory/productbatch/createProductBatchLogic.go create mode 100644 gateway/internal/logic/inventory/productbatch/deleteProductBatchLogic.go create mode 100644 gateway/internal/logic/inventory/productbatch/helpers.go create mode 100644 gateway/internal/logic/inventory/productbatch/listProductBatchLogic.go create mode 100644 gateway/internal/logic/inventory/productbatch/updateProductBatchLogic.go create mode 100644 gateway/internal/logic/inventory/yarn/createYarnLogic.go create mode 100644 gateway/internal/logic/inventory/yarn/deleteYarnLogic.go create mode 100644 gateway/internal/logic/inventory/yarn/getYarnLogic.go create mode 100644 gateway/internal/logic/inventory/yarn/helpers.go create mode 100644 gateway/internal/logic/inventory/yarn/listYarnLogic.go create mode 100644 gateway/internal/logic/inventory/yarn/updateYarnLogic.go create mode 100644 model/invproductbatchmodel.go create mode 100644 model/invproductbatchmodel_gen.go create mode 100644 model/invyarnmodel.go create mode 100644 model/invyarnmodel_gen.go create mode 100644 pkg/excelparse/native.go create mode 100644 rpc/inventory/internal/logic/batch_helpers.go create mode 100644 rpc/inventory/internal/logic/batch_helpers_test.go create mode 100644 rpc/inventory/internal/logic/createproductbatchlogic.go create mode 100644 rpc/inventory/internal/logic/createyarnlogic.go create mode 100644 rpc/inventory/internal/logic/deleteproductbatchlogic.go create mode 100644 rpc/inventory/internal/logic/deleteyarnlogic.go create mode 100644 rpc/inventory/internal/logic/getyarnlogic.go create mode 100644 rpc/inventory/internal/logic/listproductbatchlogic.go create mode 100644 rpc/inventory/internal/logic/listyarnlogic.go create mode 100644 rpc/inventory/internal/logic/productcode.go create mode 100644 rpc/inventory/internal/logic/updateproductbatchlogic.go create mode 100644 rpc/inventory/internal/logic/updateyarnlogic.go create mode 100644 rpc/inventory/internal/logic/yarn_helpers.go diff --git a/deploy/mysql/init.sql b/deploy/mysql/init.sql index 1274625..04dc843 100644 --- a/deploy/mysql/init.sql +++ b/deploy/mysql/init.sql @@ -210,16 +210,14 @@ CREATE TABLE `crm_data_migration_log` ( CREATE TABLE `inv_product` ( `id` BIGINT NOT NULL AUTO_INCREMENT, + `tenant_id` VARCHAR(32) NOT NULL DEFAULT 't_default_001', `product_id` VARCHAR(32) NOT NULL, `product_name` VARCHAR(100) NOT NULL, `image_url` VARCHAR(255) NOT NULL DEFAULT '', `spec` VARCHAR(100) NOT NULL DEFAULT '', - `color` VARCHAR(50) NOT NULL DEFAULT '', - `unit_pieces` INT NOT NULL DEFAULT 0, - `unit_rolls` INT NOT NULL DEFAULT 0, - `stock_quantity` DECIMAL(10,2) NOT NULL DEFAULT 0.00, - `location` VARCHAR(100) NOT NULL DEFAULT '', - `cost_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `color` VARCHAR(50) NOT NULL DEFAULT '本色', + `color_no` VARCHAR(20) NOT NULL DEFAULT '', + `product_code` VARCHAR(50) NOT NULL DEFAULT '', `sales_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00, `remark` TEXT, `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled', @@ -228,12 +226,96 @@ CREATE TABLE `inv_product` ( `deleted_at` DATETIME DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_product_id` (`product_id`), - UNIQUE KEY `uk_product_name_spec_color` (`product_name`, `spec`, `color`), + UNIQUE KEY `uk_tenant_product_code` (`tenant_id`, `product_code`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_product_name_tenant` (`product_name`, `tenant_id`), KEY `idx_color` (`color`), - KEY `idx_location` (`location`), KEY `idx_status` (`status`), KEY `idx_deleted_at` (`deleted_at`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品档案'; + +CREATE TABLE `inv_yarn` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `yarn_id` VARCHAR(32) NOT NULL, + `tenant_id` VARCHAR(32) NOT NULL DEFAULT '', + `yarn_name` VARCHAR(100) NOT NULL, + `color` VARCHAR(50) NOT NULL DEFAULT '原纱本色', + `weight_g_m` DECIMAL(10,4) NOT NULL DEFAULT 0.0000, + `supplier_id` VARCHAR(32) NOT NULL DEFAULT '', + `dye_factory` VARCHAR(100) NOT NULL DEFAULT '无', + `image_url` VARCHAR(255) NOT NULL DEFAULT '', + `remark` TEXT, + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_yarn_id` (`yarn_id`), + UNIQUE KEY `uk_tenant_yarn_name_color_supplier` (`tenant_id`, `yarn_name`, `color`, `supplier_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_supplier_id` (`supplier_id`), + KEY `idx_status` (`status`), + KEY `idx_deleted_at` (`deleted_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='原料纱档案'; + +CREATE TABLE `inv_product_batch` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `batch_id` VARCHAR(32) NOT NULL, + `tenant_id` VARCHAR(32) NOT NULL DEFAULT '', + `product_id` VARCHAR(32) NOT NULL, + `batch_no` VARCHAR(64) NOT NULL DEFAULT '', + `yarn_ratio` JSON DEFAULT NULL, + `warp_weight_g_m` DECIMAL(10,4) NOT NULL DEFAULT 0.0000, + `weft_weight_g_m` DECIMAL(10,4) NOT NULL DEFAULT 0.0000, + `production_process` TEXT, + `remark` TEXT, + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_batch_id` (`batch_id`), + UNIQUE KEY `uk_tenant_batch_no` (`tenant_id`, `batch_no`), + KEY `idx_product_id` (`product_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_status` (`status`), + KEY `idx_deleted_at` (`deleted_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品批次表'; + +CREATE TABLE `inv_product_pan` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `pan_id` VARCHAR(32) NOT NULL, + `product_id` VARCHAR(32) NOT NULL, + `batch_id` VARCHAR(32) NOT NULL DEFAULT '', + `name` VARCHAR(50) NOT NULL DEFAULT '', + `position` VARCHAR(100) NOT NULL DEFAULT '', + `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_batch_id` (`batch_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_position` (`position`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品盘库存'; + +CREATE TABLE `inv_product_bolt` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `bolt_id` VARCHAR(32) NOT NULL, + `pan_id` VARCHAR(32) NOT NULL, + `length_m` DECIMAL(10,2) NOT NULL DEFAULT 0.00, + `color` VARCHAR(50) NOT NULL DEFAULT '', + `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 COMMENT='产品匹库存'; CREATE TABLE `inv_stock_import_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT, diff --git a/deploy/mysql/migrations/20260703_add_product_yarn_batch.sql b/deploy/mysql/migrations/20260703_add_product_yarn_batch.sql new file mode 100644 index 0000000..b1582e9 --- /dev/null +++ b/deploy/mysql/migrations/20260703_add_product_yarn_batch.sql @@ -0,0 +1,174 @@ +-- Product/yarn/batch model migration. +-- Adds yarn master data, product batches, frozen product codes, and pan batch ownership. +-- Run after the pan/bolt and purchase-management migrations. + +SET @db = DATABASE(); + +CREATE TABLE IF NOT EXISTS `inv_yarn` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `yarn_id` VARCHAR(32) NOT NULL COMMENT 'business key, UUID', + `tenant_id` VARCHAR(32) NOT NULL DEFAULT '', + `yarn_name` VARCHAR(100) NOT NULL, + `color` VARCHAR(50) NOT NULL DEFAULT '原纱本色', + `weight_g_m` DECIMAL(10,4) NOT NULL DEFAULT 0.0000 COMMENT 'yarn weight (g/m)', + `supplier_id` VARCHAR(32) NOT NULL DEFAULT '', + `dye_factory` VARCHAR(100) NOT NULL DEFAULT '无', + `image_url` VARCHAR(255) NOT NULL DEFAULT '', + `remark` TEXT, + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_yarn_id` (`yarn_id`), + UNIQUE KEY `uk_tenant_yarn_name_color_supplier` (`tenant_id`, `yarn_name`, `color`, `supplier_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_supplier_id` (`supplier_id`), + KEY `idx_status` (`status`), + KEY `idx_deleted_at` (`deleted_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='原料纱档案'; + +CREATE TABLE IF NOT EXISTS `inv_product_batch` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `batch_id` VARCHAR(32) NOT NULL COMMENT 'business key, UUID', + `tenant_id` VARCHAR(32) NOT NULL DEFAULT '', + `product_id` VARCHAR(32) NOT NULL, + `batch_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'format: {product_code}-B001', + `yarn_ratio` JSON DEFAULT NULL, + `warp_weight_g_m` DECIMAL(10,4) NOT NULL DEFAULT 0.0000, + `weft_weight_g_m` DECIMAL(10,4) NOT NULL DEFAULT 0.0000, + `production_process` TEXT, + `remark` TEXT, + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_batch_id` (`batch_id`), + UNIQUE KEY `uk_tenant_batch_no` (`tenant_id`, `batch_no`), + KEY `idx_product_id` (`product_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_status` (`status`), + KEY `idx_deleted_at` (`deleted_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品批次表'; + +-- inv_product.color_no +SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='color_no'); +SET @s = IF(@c=0, 'ALTER TABLE `inv_product` ADD COLUMN `color_no` VARCHAR(20) NOT NULL DEFAULT '''' COMMENT ''色号'' AFTER `color`', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- inv_product.product_code +SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND COLUMN_NAME='product_code'); +SET @s = IF(@c=0, 'ALTER TABLE `inv_product` ADD COLUMN `product_code` VARCHAR(50) NOT NULL DEFAULT '''' COMMENT ''产品码,创建后冻结'' AFTER `color_no`', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- inv_product_pan.batch_id +SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product_pan' AND COLUMN_NAME='batch_id'); +SET @s = IF(@c=0, 'ALTER TABLE `inv_product_pan` ADD COLUMN `batch_id` VARCHAR(32) NOT NULL DEFAULT '''' COMMENT ''FK inv_product_batch.batch_id'' AFTER `product_id`', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @i = (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product_pan' AND INDEX_NAME='idx_batch_id'); +SET @s = IF(@i=0, 'ALTER TABLE `inv_product_pan` ADD KEY `idx_batch_id` (`batch_id`)', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- Align older pan/bolt installations with the current model. +SET @c = (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product_bolt' AND COLUMN_NAME='color'); +SET @s = IF(@c=0, 'ALTER TABLE `inv_product_bolt` ADD COLUMN `color` VARCHAR(50) NOT NULL DEFAULT '''' AFTER `length_m`', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- Backfill product defaults. +UPDATE `inv_product` +SET `color` = '本色' +WHERE `deleted_at` IS NULL AND TRIM(COALESCE(`color`, '')) = ''; + +UPDATE `inv_product` p +JOIN ( + SELECT id, LPAD(ROW_NUMBER() OVER (PARTITION BY tenant_id, product_name ORDER BY created_at, id), 2, '0') AS generated_color_no + FROM `inv_product` + WHERE `deleted_at` IS NULL +) x ON x.id = p.id +SET p.`color_no` = x.generated_color_no +WHERE TRIM(COALESCE(p.`color_no`, '')) = ''; + +-- Historical SQL cannot reliably derive pinyin initials. For migrated rows with +-- non-latin product names, use a stable P{id} prefix; new writes use backend pinyin. +UPDATE `inv_product` p +JOIN ( + SELECT id, + UPPER(CONCAT( + CASE + WHEN REGEXP_REPLACE(product_name, '[^0-9A-Za-z]', '') = '' THEN CONCAT('P', id) + ELSE REGEXP_REPLACE(product_name, '[^0-9A-Za-z]', '') + END, + color_no + )) AS raw_code + FROM `inv_product` + WHERE `deleted_at` IS NULL +) b ON b.id = p.id +SET p.`product_code` = LEFT(b.raw_code, 50) +WHERE TRIM(COALESCE(p.`product_code`, '')) = ''; + +UPDATE `inv_product` p +JOIN ( + SELECT id, + CASE + WHEN rn = 1 THEN raw_code + ELSE LEFT(CONCAT(raw_code, '-', id), 50) + END AS unique_code + FROM ( + SELECT id, tenant_id, product_code AS raw_code, + ROW_NUMBER() OVER (PARTITION BY tenant_id, product_code ORDER BY id) AS rn + FROM `inv_product` + WHERE `deleted_at` IS NULL + ) d +) u ON u.id = p.id +SET p.`product_code` = u.unique_code; + +-- Default B001 batch for every historical product. +INSERT INTO `inv_product_batch` ( + `batch_id`, `tenant_id`, `product_id`, `batch_no`, + `yarn_ratio`, `warp_weight_g_m`, `weft_weight_g_m`, + `production_process`, `remark`, `status` +) +SELECT + MD5(CONCAT('B001:', p.`tenant_id`, ':', p.`product_id`)), + p.`tenant_id`, + p.`product_id`, + CONCAT(p.`product_code`, '-B001'), + NULL, + 0.0000, + 0.0000, + '无', + NULL, + 1 +FROM `inv_product` p +WHERE p.`deleted_at` IS NULL + AND NOT EXISTS ( + SELECT 1 FROM `inv_product_batch` b + WHERE b.`tenant_id` = p.`tenant_id` + AND b.`product_id` = p.`product_id` + AND b.`batch_no` = CONCAT(p.`product_code`, '-B001') + ); + +UPDATE `inv_product_pan` pan +JOIN `inv_product` p ON p.`product_id` = pan.`product_id` +JOIN `inv_product_batch` b ON b.`product_id` = p.`product_id` + AND b.`tenant_id` = p.`tenant_id` + AND b.`batch_no` = CONCAT(p.`product_code`, '-B001') +SET pan.`batch_id` = b.`batch_id` +WHERE TRIM(COALESCE(pan.`batch_id`, '')) = ''; + +-- Replace the old natural key after product_code has been populated. +SET @i = (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND INDEX_NAME='uk_product_name_spec_color'); +SET @s = IF(@i>0, 'ALTER TABLE `inv_product` DROP INDEX `uk_product_name_spec_color`', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @i = (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='inv_product' AND INDEX_NAME='uk_tenant_product_code'); +SET @s = IF(@i=0, 'ALTER TABLE `inv_product` ADD UNIQUE KEY `uk_tenant_product_code` (`tenant_id`, `product_code`)', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- Verification queries for release runbooks: +-- SELECT COUNT(*) AS empty_product_code FROM inv_product WHERE deleted_at IS NULL AND product_code = ''; +-- SELECT tenant_id, product_code, COUNT(*) FROM inv_product WHERE deleted_at IS NULL GROUP BY tenant_id, product_code HAVING COUNT(*) > 1; +-- SELECT p.product_id FROM inv_product p LEFT JOIN inv_product_batch b ON b.product_id = p.product_id AND b.batch_no = CONCAT(p.product_code, '-B001') WHERE p.deleted_at IS NULL AND b.batch_id IS NULL; +-- SELECT pan.pan_id FROM inv_product_pan pan WHERE pan.batch_id = ''; diff --git a/gateway/gateway.api b/gateway/gateway.api index 9084e0a..5ddf5d7 100644 --- a/gateway/gateway.api +++ b/gateway/gateway.api @@ -224,6 +224,8 @@ type ( ImageUrl string `json:"imageUrl"` Spec string `json:"spec"` Color string `json:"color"` + ColorNo string `json:"colorNo"` + ProductCode string `json:"productCode"` SalesPrice string `json:"salesPrice"` Remark string `json:"remark"` Status int64 `json:"status"` @@ -235,15 +237,19 @@ type ( ImageUrl string `json:"imageUrl,optional"` Spec string `json:"spec,optional"` Color string `json:"color,optional"` + ColorNo string `json:"colorNo,optional"` + ProductCode string `json:"productCode,optional"` SalesPrice string `json:"salesPrice,optional"` Remark string `json:"remark,optional"` Pans []PanInput `json:"pans,optional"` + InitialBatch ProductBatchInput `json:"initialBatch,optional"` } UpdateProductReq { ProductName string `json:"productName,optional"` ImageUrl string `json:"imageUrl,optional"` Spec string `json:"spec,optional"` Color string `json:"color,optional"` + ColorNo string `json:"colorNo,optional"` SalesPrice string `json:"salesPrice,optional"` Remark string `json:"remark,optional"` } @@ -253,6 +259,8 @@ type ( ProductName string `form:"productName,optional"` Spec string `form:"spec,optional"` Color string `form:"color,optional"` + ColorNo string `form:"colorNo,optional"` + ProductCode string `form:"productCode,optional"` Status int64 `form:"status,optional,default=-1"` } ListProductResp { @@ -279,6 +287,8 @@ type ( PanInfo { PanId string `json:"panId"` ProductId string `json:"productId"` + BatchId string `json:"batchId"` + BatchNo string `json:"batchNo"` Name string `json:"name"` Position string `json:"position"` SortOrder int64 `json:"sortOrder"` @@ -290,6 +300,7 @@ type ( Name string `json:"name"` Position string `json:"position,optional"` BoltLengths []string `json:"boltLengths,optional"` + BatchId string `json:"batchId,optional"` } ListPanResp { List []PanInfo `json:"list"` @@ -331,6 +342,8 @@ type ( ProductId string `json:"productId"` ProductName string `json:"productName"` Color string `json:"color"` + ColorNo string `json:"colorNo"` + ProductCode string `json:"productCode"` Spec string `json:"spec"` ImageUrl string `json:"imageUrl"` PanCount int64 `json:"panCount"` @@ -338,6 +351,7 @@ type ( TotalLengthM string `json:"totalLengthM"` Locations string `json:"locations"` SalesPrice string `json:"salesPrice"` + BatchCount int64 `json:"batchCount"` } ListColorDetailReq { ProductName string `form:"productName"` @@ -347,6 +361,85 @@ type ( } ) +// ==================== Yarn & Batch Types ==================== +type ( + YarnInfo { + YarnId string `json:"yarnId"` + YarnName string `json:"yarnName"` + Color string `json:"color"` + WeightGM string `json:"weightGM"` + SupplierId string `json:"supplierId"` + SupplierName string `json:"supplierName"` + DyeFactory string `json:"dyeFactory"` + ImageUrl string `json:"imageUrl"` + Remark string `json:"remark"` + Status int64 `json:"status"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` + } + CreateYarnReq { + YarnName string `json:"yarnName"` + Color string `json:"color,optional"` + WeightGM string `json:"weightGM"` + SupplierId string `json:"supplierId"` + DyeFactory string `json:"dyeFactory,optional"` + ImageUrl string `json:"imageUrl,optional"` + Remark string `json:"remark,optional"` + } + UpdateYarnReq { + YarnName string `json:"yarnName,optional"` + Color string `json:"color,optional"` + WeightGM string `json:"weightGM,optional"` + SupplierId string `json:"supplierId,optional"` + DyeFactory string `json:"dyeFactory,optional"` + ImageUrl string `json:"imageUrl,optional"` + Remark string `json:"remark,optional"` + Status int64 `json:"status,optional,default=1"` + } + ListYarnReq { + Page int64 `form:"page,default=1"` + PageSize int64 `form:"pageSize,default=20"` + YarnName string `form:"yarnName,optional"` + SupplierId string `form:"supplierId,optional"` + Status int64 `form:"status,optional,default=-1"` + } + ListYarnResp { + Total int64 `json:"total"` + List []YarnInfo `json:"list"` + } + ProductBatchInput { + BatchNo string `json:"batchNo,optional"` + YarnRatio string `json:"yarnRatio,optional"` + WarpWeightGM string `json:"warpWeightGM,optional"` + WeftWeightGM string `json:"weftWeightGM,optional"` + ProductionProcess string `json:"productionProcess,optional"` + Remark string `json:"remark,optional"` + } + ProductBatchInfo { + BatchId string `json:"batchId"` + ProductId string `json:"productId"` + BatchNo string `json:"batchNo"` + YarnRatio string `json:"yarnRatio"` + WarpWeightGM string `json:"warpWeightGM"` + WeftWeightGM string `json:"weftWeightGM"` + ProductionProcess string `json:"productionProcess"` + Remark string `json:"remark"` + Status int64 `json:"status"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` + } + CreateProductBatchReq { + Batch ProductBatchInput `json:"batch"` + } + UpdateProductBatchReq { + Batch ProductBatchInput `json:"batch"` + Status int64 `json:"status,optional,default=1"` + } + ListProductBatchResp { + List []ProductBatchInfo `json:"list"` + } +) + // ==================== Stock Statistics Types ==================== type ( StockSummaryResp { @@ -725,6 +818,51 @@ service gateway-api { put /products/:id/pans (SavePansReq) returns (IdResp) } +// Inventory - Yarn Management +@server ( + prefix: /api/v1/inventory + group: inventory/yarn + jwt: Auth + middleware: AuthorityMiddleware +) +service gateway-api { + @handler ListYarnHandler + get /yarns (ListYarnReq) returns (ListYarnResp) + + @handler GetYarnHandler + get /yarns/:id returns (YarnInfo) + + @handler CreateYarnHandler + post /yarns (CreateYarnReq) returns (IdResp) + + @handler UpdateYarnHandler + put /yarns/:id (UpdateYarnReq) returns (IdResp) + + @handler DeleteYarnHandler + delete /yarns/:id returns (IdResp) +} + +// Inventory - Product Batch Management +@server ( + prefix: /api/v1/inventory + group: inventory/productbatch + jwt: Auth + middleware: AuthorityMiddleware +) +service gateway-api { + @handler ListProductBatchHandler + get /products/:id/batches returns (ListProductBatchResp) + + @handler CreateProductBatchHandler + post /products/:id/batches (CreateProductBatchReq) returns (IdResp) + + @handler UpdateProductBatchHandler + put /products/:id/batches/:batchId (UpdateProductBatchReq) returns (IdResp) + + @handler DeleteProductBatchHandler + delete /products/:id/batches/:batchId returns (IdResp) +} + // Inventory - Pan/Bolt Management @server ( prefix: /api/v1/inventory @@ -805,4 +943,3 @@ service gateway-api { @handler ApproveStockAdjustHandler post /adjusts/:id/approve (ApproveStockAdjustReq) returns (IdResp) } - diff --git a/gateway/internal/handler/inventory/product/exportProductHandler.go b/gateway/internal/handler/inventory/product/exportProductHandler.go index 1c046f7..a15c8ae 100644 --- a/gateway/internal/handler/inventory/product/exportProductHandler.go +++ b/gateway/internal/handler/inventory/product/exportProductHandler.go @@ -5,6 +5,7 @@ package product import ( "net/http" + "net/url" "github.com/zeromicro/go-zero/rest/httpx" "muyu-apiserver/gateway/internal/logic/inventory/product" @@ -14,11 +15,14 @@ import ( func ExportProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := product.NewExportProductLogic(r.Context(), svcCtx) - err := l.ExportProduct() + data, filename, err := l.ExportProduct() if err != nil { httpx.ErrorCtx(r.Context(), w, err) } else { - httpx.Ok(w) + w.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + w.Header().Set("Content-Disposition", "attachment; filename*=UTF-8''"+url.PathEscape(filename)) + w.WriteHeader(http.StatusOK) + _, _ = w.Write(data) } } } diff --git a/gateway/internal/handler/inventory/productbatch/createProductBatchHandler.go b/gateway/internal/handler/inventory/productbatch/createProductBatchHandler.go new file mode 100644 index 0000000..f36777e --- /dev/null +++ b/gateway/internal/handler/inventory/productbatch/createProductBatchHandler.go @@ -0,0 +1,32 @@ +// Code scaffolded by goctl. Safe to edit. + +package productbatch + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/productbatch" + "muyu-apiserver/gateway/internal/svc" + "muyu-apiserver/gateway/internal/types" +) + +func CreateProductBatchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.CreateProductBatchReq + 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 := productbatch.NewCreateProductBatchLogic(ctx, svcCtx) + resp, err := l.CreateProductBatch(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/productbatch/deleteProductBatchHandler.go b/gateway/internal/handler/inventory/productbatch/deleteProductBatchHandler.go new file mode 100644 index 0000000..9e21bd0 --- /dev/null +++ b/gateway/internal/handler/inventory/productbatch/deleteProductBatchHandler.go @@ -0,0 +1,28 @@ +// Code scaffolded by goctl. Safe to edit. + +package productbatch + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/productbatch" + "muyu-apiserver/gateway/internal/svc" +) + +func DeleteProductBatchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := pathvar.Vars(r) + ctx := context.WithValue(r.Context(), "pathId", vars["id"]) + ctx = context.WithValue(ctx, "batchId", vars["batchId"]) + l := productbatch.NewDeleteProductBatchLogic(ctx, svcCtx) + resp, err := l.DeleteProductBatch() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/productbatch/listProductBatchHandler.go b/gateway/internal/handler/inventory/productbatch/listProductBatchHandler.go new file mode 100644 index 0000000..6a1a4a0 --- /dev/null +++ b/gateway/internal/handler/inventory/productbatch/listProductBatchHandler.go @@ -0,0 +1,26 @@ +// Code scaffolded by goctl. Safe to edit. + +package productbatch + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/productbatch" + "muyu-apiserver/gateway/internal/svc" +) + +func ListProductBatchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"]) + l := productbatch.NewListProductBatchLogic(ctx, svcCtx) + resp, err := l.ListProductBatch() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/productbatch/updateProductBatchHandler.go b/gateway/internal/handler/inventory/productbatch/updateProductBatchHandler.go new file mode 100644 index 0000000..c412024 --- /dev/null +++ b/gateway/internal/handler/inventory/productbatch/updateProductBatchHandler.go @@ -0,0 +1,34 @@ +// Code scaffolded by goctl. Safe to edit. + +package productbatch + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/productbatch" + "muyu-apiserver/gateway/internal/svc" + "muyu-apiserver/gateway/internal/types" +) + +func UpdateProductBatchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.UpdateProductBatchReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + vars := pathvar.Vars(r) + ctx := context.WithValue(r.Context(), "pathId", vars["id"]) + ctx = context.WithValue(ctx, "batchId", vars["batchId"]) + l := productbatch.NewUpdateProductBatchLogic(ctx, svcCtx) + resp, err := l.UpdateProductBatch(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/yarn/createYarnHandler.go b/gateway/internal/handler/inventory/yarn/createYarnHandler.go new file mode 100644 index 0000000..2ebc584 --- /dev/null +++ b/gateway/internal/handler/inventory/yarn/createYarnHandler.go @@ -0,0 +1,29 @@ +// Code scaffolded by goctl. Safe to edit. + +package yarn + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "muyu-apiserver/gateway/internal/logic/inventory/yarn" + "muyu-apiserver/gateway/internal/svc" + "muyu-apiserver/gateway/internal/types" +) + +func CreateYarnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.CreateYarnReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + l := yarn.NewCreateYarnLogic(r.Context(), svcCtx) + resp, err := l.CreateYarn(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/yarn/deleteYarnHandler.go b/gateway/internal/handler/inventory/yarn/deleteYarnHandler.go new file mode 100644 index 0000000..25d6928 --- /dev/null +++ b/gateway/internal/handler/inventory/yarn/deleteYarnHandler.go @@ -0,0 +1,26 @@ +// Code scaffolded by goctl. Safe to edit. + +package yarn + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/yarn" + "muyu-apiserver/gateway/internal/svc" +) + +func DeleteYarnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"]) + l := yarn.NewDeleteYarnLogic(ctx, svcCtx) + resp, err := l.DeleteYarn() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/yarn/getYarnHandler.go b/gateway/internal/handler/inventory/yarn/getYarnHandler.go new file mode 100644 index 0000000..8a70c27 --- /dev/null +++ b/gateway/internal/handler/inventory/yarn/getYarnHandler.go @@ -0,0 +1,26 @@ +// Code scaffolded by goctl. Safe to edit. + +package yarn + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/yarn" + "muyu-apiserver/gateway/internal/svc" +) + +func GetYarnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"]) + l := yarn.NewGetYarnLogic(ctx, svcCtx) + resp, err := l.GetYarn() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/yarn/listYarnHandler.go b/gateway/internal/handler/inventory/yarn/listYarnHandler.go new file mode 100644 index 0000000..bd4a592 --- /dev/null +++ b/gateway/internal/handler/inventory/yarn/listYarnHandler.go @@ -0,0 +1,29 @@ +// Code scaffolded by goctl. Safe to edit. + +package yarn + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "muyu-apiserver/gateway/internal/logic/inventory/yarn" + "muyu-apiserver/gateway/internal/svc" + "muyu-apiserver/gateway/internal/types" +) + +func ListYarnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.ListYarnReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + l := yarn.NewListYarnLogic(r.Context(), svcCtx) + resp, err := l.ListYarn(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/inventory/yarn/updateYarnHandler.go b/gateway/internal/handler/inventory/yarn/updateYarnHandler.go new file mode 100644 index 0000000..c23be29 --- /dev/null +++ b/gateway/internal/handler/inventory/yarn/updateYarnHandler.go @@ -0,0 +1,32 @@ +// Code scaffolded by goctl. Safe to edit. + +package yarn + +import ( + "context" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "github.com/zeromicro/go-zero/rest/pathvar" + "muyu-apiserver/gateway/internal/logic/inventory/yarn" + "muyu-apiserver/gateway/internal/svc" + "muyu-apiserver/gateway/internal/types" +) + +func UpdateYarnHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.UpdateYarnReq + 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 := yarn.NewUpdateYarnLogic(ctx, svcCtx) + resp, err := l.UpdateYarn(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/gateway/internal/handler/routes.go b/gateway/internal/handler/routes.go index f0b2379..8a41cc3 100644 --- a/gateway/internal/handler/routes.go +++ b/gateway/internal/handler/routes.go @@ -13,7 +13,9 @@ import ( inventorylog "muyu-apiserver/gateway/internal/handler/inventory/log" inventorypanbolt "muyu-apiserver/gateway/internal/handler/inventory/panbolt" inventoryproduct "muyu-apiserver/gateway/internal/handler/inventory/product" + inventoryproductbatch "muyu-apiserver/gateway/internal/handler/inventory/productbatch" inventorystock "muyu-apiserver/gateway/internal/handler/inventory/stock" + inventoryyarn "muyu-apiserver/gateway/internal/handler/inventory/yarn" productioninbound "muyu-apiserver/gateway/internal/handler/production/inbound" productionplan "muyu-apiserver/gateway/internal/handler/production/plan" productionprocess "muyu-apiserver/gateway/internal/handler/production/process" @@ -148,6 +150,71 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { rest.WithPrefix("/api/v1/inventory"), ) + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.AuthorityMiddleware}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/yarns", + Handler: inventoryyarn.ListYarnHandler(serverCtx), + }, + { + Method: http.MethodGet, + Path: "/yarns/:id", + Handler: inventoryyarn.GetYarnHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/yarns", + Handler: inventoryyarn.CreateYarnHandler(serverCtx), + }, + { + Method: http.MethodPut, + Path: "/yarns/:id", + Handler: inventoryyarn.UpdateYarnHandler(serverCtx), + }, + { + Method: http.MethodDelete, + Path: "/yarns/:id", + Handler: inventoryyarn.DeleteYarnHandler(serverCtx), + }, + }..., + ), + rest.WithJwt(serverCtx.Config.Auth.AccessSecret), + rest.WithPrefix("/api/v1/inventory"), + ) + + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.AuthorityMiddleware}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/products/:id/batches", + Handler: inventoryproductbatch.ListProductBatchHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/products/:id/batches", + Handler: inventoryproductbatch.CreateProductBatchHandler(serverCtx), + }, + { + Method: http.MethodPut, + Path: "/products/:id/batches/:batchId", + Handler: inventoryproductbatch.UpdateProductBatchHandler(serverCtx), + }, + { + Method: http.MethodDelete, + Path: "/products/:id/batches/:batchId", + Handler: inventoryproductbatch.DeleteProductBatchHandler(serverCtx), + }, + }..., + ), + rest.WithJwt(serverCtx.Config.Auth.AccessSecret), + rest.WithPrefix("/api/v1/inventory"), + ) + server.AddRoutes( rest.WithMiddlewares( []rest.Middleware{serverCtx.AuthorityMiddleware}, diff --git a/gateway/internal/logic/inventory/panbolt/listPanViewLogic.go b/gateway/internal/logic/inventory/panbolt/listPanViewLogic.go index 71cec33..3d25a46 100644 --- a/gateway/internal/logic/inventory/panbolt/listPanViewLogic.go +++ b/gateway/internal/logic/inventory/panbolt/listPanViewLogic.go @@ -40,6 +40,8 @@ func (l *ListPanViewLogic) ListPanView(req *types.ListPanViewReq) (resp *types.L list = append(list, types.PanListItem{ PanId: item.PanId, ProductId: item.ProductId, + BatchId: item.BatchId, + BatchNo: item.BatchNo, Name: item.Name, Position: item.Position, ProductName: item.ProductName, diff --git a/gateway/internal/logic/inventory/product/createProductLogic.go b/gateway/internal/logic/inventory/product/createProductLogic.go index ea36d5a..c430b69 100644 --- a/gateway/internal/logic/inventory/product/createProductLogic.go +++ b/gateway/internal/logic/inventory/product/createProductLogic.go @@ -26,13 +26,16 @@ func NewCreateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Cre func (l *CreateProductLogic) CreateProduct(req *types.CreateProductReq) (resp *types.IdResp, err error) { rpcResp, err := l.svcCtx.InventoryRpc.CreateProduct(l.ctx, &pb.CreateProductReq{ - ProductName: req.ProductName, - ImageUrl: req.ImageUrl, - Spec: req.Spec, - Color: req.Color, - SalesPrice: req.SalesPrice, - Remark: req.Remark, - Pans: panInputsToPb(req.Pans), + ProductName: req.ProductName, + ImageUrl: req.ImageUrl, + Spec: req.Spec, + Color: req.Color, + ColorNo: req.ColorNo, + ProductCode: req.ProductCode, + SalesPrice: req.SalesPrice, + Remark: req.Remark, + Pans: panInputsToPb(req.Pans), + InitialBatch: productBatchInputToPb(req.InitialBatch), }) if err != nil { return nil, err @@ -51,7 +54,22 @@ func panInputsToPb(pans []types.PanInput) []*pb.PanInput { Name: p.Name, Position: p.Position, BoltLengths: p.BoltLengths, + BatchId: p.BatchId, }) } return out } + +func productBatchInputToPb(input types.ProductBatchInput) *pb.ProductBatchInput { + if input == (types.ProductBatchInput{}) { + return nil + } + return &pb.ProductBatchInput{ + BatchNo: input.BatchNo, + YarnRatio: input.YarnRatio, + WarpWeightGM: input.WarpWeightGM, + WeftWeightGM: input.WeftWeightGM, + ProductionProcess: input.ProductionProcess, + Remark: input.Remark, + } +} diff --git a/gateway/internal/logic/inventory/product/exportProductLogic.go b/gateway/internal/logic/inventory/product/exportProductLogic.go index ee46068..1811e49 100644 --- a/gateway/internal/logic/inventory/product/exportProductLogic.go +++ b/gateway/internal/logic/inventory/product/exportProductLogic.go @@ -2,10 +2,13 @@ package product import ( "context" - "errors" + "fmt" + "time" "muyu-apiserver/gateway/internal/svc" + "muyu-apiserver/rpc/inventory/pb" + "github.com/xuri/excelize/v2" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,6 +26,99 @@ func NewExportProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Exp } } -func (l *ExportProductLogic) ExportProduct() error { - return errors.New("export product requires response writer, will be implemented in handler layer") +func (l *ExportProductLogic) ExportProduct() ([]byte, string, error) { + products, err := l.listAllProducts() + if err != nil { + return nil, "", err + } + + f := excelize.NewFile() + defer f.Close() + + sheet := "产品" + if err := f.SetSheetName("Sheet1", sheet); err != nil { + return nil, "", err + } + headers := []interface{}{"产品名称", "规格型号", "颜色", "色号", "产品码", "销售价", "批次号", "纱线配比", "经线克重(g/m)", "纬线克重(g/m)", "生产工艺", "备注"} + if err := f.SetSheetRow(sheet, "A1", &headers); err != nil { + return nil, "", err + } + + row := 2 + for _, product := range products { + batchResp, err := l.svcCtx.InventoryRpc.ListProductBatch(l.ctx, &pb.ListProductBatchReq{ProductId: product.ProductId}) + if err != nil { + return nil, "", err + } + if len(batchResp.List) == 0 { + if err := setProductExportRow(f, sheet, row, product, nil); err != nil { + return nil, "", err + } + row++ + continue + } + for _, batch := range batchResp.List { + if err := setProductExportRow(f, sheet, row, product, batch); err != nil { + return nil, "", err + } + row++ + } + } + + if err := f.SetColWidth(sheet, "A", "L", 18); err != nil { + return nil, "", err + } + buf, err := f.WriteToBuffer() + if err != nil { + return nil, "", err + } + filename := fmt.Sprintf("products-%s.xlsx", time.Now().Format("20060102150405")) + return buf.Bytes(), filename, nil +} + +func (l *ExportProductLogic) listAllProducts() ([]*pb.ProductInfo, error) { + const pageSize int64 = 500 + var all []*pb.ProductInfo + for page := int64(1); ; page++ { + resp, err := l.svcCtx.InventoryRpc.ListProduct(l.ctx, &pb.ListProductReq{Page: page, PageSize: pageSize, Status: -1}) + if err != nil { + return nil, err + } + all = append(all, resp.List...) + if int64(len(all)) >= resp.Total || len(resp.List) == 0 { + return all, nil + } + } +} + +func setProductExportRow(f *excelize.File, sheet string, row int, product *pb.ProductInfo, batch *pb.ProductBatchInfo) error { + values := []interface{}{ + product.ProductName, + product.Spec, + product.Color, + product.ColorNo, + product.ProductCode, + product.SalesPrice, + "", + "", + "", + "", + "", + product.Remark, + } + if batch != nil { + values[6] = batch.BatchNo + values[7] = batch.YarnRatio + values[8] = batch.WarpWeightGM + values[9] = batch.WeftWeightGM + values[10] = batch.ProductionProcess + if batch.Remark != "" { + values[11] = batch.Remark + } + } + cell, err := excelize.CoordinatesToCellName(1, row) + if err != nil { + return err + } + return f.SetSheetRow(sheet, cell, &values) } diff --git a/gateway/internal/logic/inventory/product/getColorDetailLogic.go b/gateway/internal/logic/inventory/product/getColorDetailLogic.go index 6c2e715..fb5a4fe 100644 --- a/gateway/internal/logic/inventory/product/getColorDetailLogic.go +++ b/gateway/internal/logic/inventory/product/getColorDetailLogic.go @@ -37,6 +37,8 @@ func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (res ProductId: it.ProductId, ProductName: it.ProductName, Color: it.Color, + ColorNo: it.ColorNo, + ProductCode: it.ProductCode, Spec: it.Spec, ImageUrl: it.ImageUrl, PanCount: it.PanCount, @@ -44,6 +46,7 @@ func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (res TotalLengthM: it.TotalLengthM, Locations: it.Locations, SalesPrice: it.SalesPrice, + BatchCount: it.BatchCount, }) } return &types.ColorDetailResp{List: list}, nil diff --git a/gateway/internal/logic/inventory/product/importProductLogic.go b/gateway/internal/logic/inventory/product/importProductLogic.go index 406ac0b..a162054 100644 --- a/gateway/internal/logic/inventory/product/importProductLogic.go +++ b/gateway/internal/logic/inventory/product/importProductLogic.go @@ -42,8 +42,17 @@ func (l *ImportProductLogic) ImportProduct(filePath, fileName string) (resp *typ ProductName: p.ProductName, Spec: p.Spec, Color: p.Color, + ColorNo: p.ColorNo, + ProductCode: p.ProductCode, SalesPrice: p.SalesPrice, Remark: p.Remark, + InitialBatch: &pb.ProductBatchInput{ + BatchNo: p.BatchNo, + YarnRatio: p.YarnRatio, + WarpWeightGM: p.WarpWeightGM, + WeftWeightGM: p.WeftWeightGM, + ProductionProcess: p.ProductionProcess, + }, }) } diff --git a/gateway/internal/logic/inventory/product/listPansLogic.go b/gateway/internal/logic/inventory/product/listPansLogic.go index 0426f48..3396ffe 100644 --- a/gateway/internal/logic/inventory/product/listPansLogic.go +++ b/gateway/internal/logic/inventory/product/listPansLogic.go @@ -57,6 +57,8 @@ func panInfoFromPB(p *pb.PanInfo) types.PanInfo { return types.PanInfo{ PanId: p.PanId, ProductId: p.ProductId, + BatchId: p.BatchId, + BatchNo: p.BatchNo, Name: p.Name, Position: p.Position, SortOrder: p.SortOrder, @@ -76,6 +78,8 @@ func productInfoFromPB(p *pb.ProductInfo) types.ProductInfo { ImageUrl: p.ImageUrl, Spec: p.Spec, Color: p.Color, + ColorNo: p.ColorNo, + ProductCode: p.ProductCode, SalesPrice: p.SalesPrice, Remark: p.Remark, Status: p.Status, diff --git a/gateway/internal/logic/inventory/product/listProductLogic.go b/gateway/internal/logic/inventory/product/listProductLogic.go index 3ce85b7..22225ee 100644 --- a/gateway/internal/logic/inventory/product/listProductLogic.go +++ b/gateway/internal/logic/inventory/product/listProductLogic.go @@ -31,6 +31,8 @@ func (l *ListProductLogic) ListProduct(req *types.ListProductReq) (resp *types.L ProductName: req.ProductName, Spec: req.Spec, Color: req.Color, + ColorNo: req.ColorNo, + ProductCode: req.ProductCode, Status: req.Status, }) if err != nil { diff --git a/gateway/internal/logic/inventory/product/updateProductLogic.go b/gateway/internal/logic/inventory/product/updateProductLogic.go index d5b4e59..322bce7 100644 --- a/gateway/internal/logic/inventory/product/updateProductLogic.go +++ b/gateway/internal/logic/inventory/product/updateProductLogic.go @@ -34,6 +34,7 @@ func (l *UpdateProductLogic) UpdateProduct(req *types.UpdateProductReq) (resp *t ImageUrl: req.ImageUrl, Spec: req.Spec, Color: req.Color, + ColorNo: req.ColorNo, SalesPrice: req.SalesPrice, Remark: req.Remark, }) diff --git a/gateway/internal/logic/inventory/productbatch/createProductBatchLogic.go b/gateway/internal/logic/inventory/productbatch/createProductBatchLogic.go new file mode 100644 index 0000000..c5c7968 --- /dev/null +++ b/gateway/internal/logic/inventory/productbatch/createProductBatchLogic.go @@ -0,0 +1,34 @@ +package productbatch + +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 CreateProductBatchLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateProductBatchLogic { + return &CreateProductBatchLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *CreateProductBatchLogic) CreateProductBatch(req *types.CreateProductBatchReq) (*types.IdResp, error) { + productId := ctxdata.GetPathId(l.ctx) + resp, err := l.svcCtx.InventoryRpc.CreateProductBatch(l.ctx, &pb.CreateProductBatchReq{ + ProductId: productId, + Batch: batchInputToPB(req.Batch), + }) + if err != nil { + return nil, err + } + return &types.IdResp{Id: resp.Id}, nil +} diff --git a/gateway/internal/logic/inventory/productbatch/deleteProductBatchLogic.go b/gateway/internal/logic/inventory/productbatch/deleteProductBatchLogic.go new file mode 100644 index 0000000..4d78f1a --- /dev/null +++ b/gateway/internal/logic/inventory/productbatch/deleteProductBatchLogic.go @@ -0,0 +1,31 @@ +package productbatch + +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 DeleteProductBatchLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDeleteProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductBatchLogic { + return &DeleteProductBatchLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *DeleteProductBatchLogic) DeleteProductBatch() (*types.IdResp, error) { + productId := ctxdata.GetPathId(l.ctx) + batchId, _ := l.ctx.Value("batchId").(string) + if _, err := l.svcCtx.InventoryRpc.DeleteProductBatch(l.ctx, &pb.DeleteProductBatchReq{ProductId: productId, BatchId: batchId}); err != nil { + return nil, err + } + return &types.IdResp{Id: batchId}, nil +} diff --git a/gateway/internal/logic/inventory/productbatch/helpers.go b/gateway/internal/logic/inventory/productbatch/helpers.go new file mode 100644 index 0000000..895aa3a --- /dev/null +++ b/gateway/internal/logic/inventory/productbatch/helpers.go @@ -0,0 +1,36 @@ +package productbatch + +import ( + "muyu-apiserver/gateway/internal/types" + "muyu-apiserver/rpc/inventory/pb" +) + +func batchInputToPB(input types.ProductBatchInput) *pb.ProductBatchInput { + return &pb.ProductBatchInput{ + BatchNo: input.BatchNo, + YarnRatio: input.YarnRatio, + WarpWeightGM: input.WarpWeightGM, + WeftWeightGM: input.WeftWeightGM, + ProductionProcess: input.ProductionProcess, + Remark: input.Remark, + } +} + +func batchInfoFromPB(b *pb.ProductBatchInfo) types.ProductBatchInfo { + if b == nil { + return types.ProductBatchInfo{} + } + return types.ProductBatchInfo{ + BatchId: b.BatchId, + ProductId: b.ProductId, + BatchNo: b.BatchNo, + YarnRatio: b.YarnRatio, + WarpWeightGM: b.WarpWeightGM, + WeftWeightGM: b.WeftWeightGM, + ProductionProcess: b.ProductionProcess, + Remark: b.Remark, + Status: b.Status, + CreatedAt: b.CreatedAt, + UpdatedAt: b.UpdatedAt, + } +} diff --git a/gateway/internal/logic/inventory/productbatch/listProductBatchLogic.go b/gateway/internal/logic/inventory/productbatch/listProductBatchLogic.go new file mode 100644 index 0000000..d0df751 --- /dev/null +++ b/gateway/internal/logic/inventory/productbatch/listProductBatchLogic.go @@ -0,0 +1,35 @@ +package productbatch + +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 ListProductBatchLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewListProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListProductBatchLogic { + return &ListProductBatchLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *ListProductBatchLogic) ListProductBatch() (*types.ListProductBatchResp, error) { + productId := ctxdata.GetPathId(l.ctx) + resp, err := l.svcCtx.InventoryRpc.ListProductBatch(l.ctx, &pb.ListProductBatchReq{ProductId: productId}) + if err != nil { + return nil, err + } + list := make([]types.ProductBatchInfo, 0, len(resp.List)) + for _, item := range resp.List { + list = append(list, batchInfoFromPB(item)) + } + return &types.ListProductBatchResp{List: list}, nil +} diff --git a/gateway/internal/logic/inventory/productbatch/updateProductBatchLogic.go b/gateway/internal/logic/inventory/productbatch/updateProductBatchLogic.go new file mode 100644 index 0000000..8a11ebb --- /dev/null +++ b/gateway/internal/logic/inventory/productbatch/updateProductBatchLogic.go @@ -0,0 +1,37 @@ +package productbatch + +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 UpdateProductBatchLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewUpdateProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateProductBatchLogic { + return &UpdateProductBatchLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *UpdateProductBatchLogic) UpdateProductBatch(req *types.UpdateProductBatchReq) (*types.IdResp, error) { + productId := ctxdata.GetPathId(l.ctx) + batchId, _ := l.ctx.Value("batchId").(string) + _, err := l.svcCtx.InventoryRpc.UpdateProductBatch(l.ctx, &pb.UpdateProductBatchReq{ + ProductId: productId, + BatchId: batchId, + Batch: batchInputToPB(req.Batch), + Status: req.Status, + }) + if err != nil { + return nil, err + } + return &types.IdResp{Id: batchId}, nil +} diff --git a/gateway/internal/logic/inventory/yarn/createYarnLogic.go b/gateway/internal/logic/inventory/yarn/createYarnLogic.go new file mode 100644 index 0000000..74d28f8 --- /dev/null +++ b/gateway/internal/logic/inventory/yarn/createYarnLogic.go @@ -0,0 +1,37 @@ +package yarn + +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 CreateYarnLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateYarnLogic { + return &CreateYarnLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *CreateYarnLogic) CreateYarn(req *types.CreateYarnReq) (*types.IdResp, error) { + resp, err := l.svcCtx.InventoryRpc.CreateYarn(l.ctx, &pb.CreateYarnReq{ + YarnName: req.YarnName, + Color: req.Color, + WeightGM: req.WeightGM, + SupplierId: req.SupplierId, + DyeFactory: req.DyeFactory, + ImageUrl: req.ImageUrl, + Remark: req.Remark, + }) + if err != nil { + return nil, err + } + return &types.IdResp{Id: resp.Id}, nil +} diff --git a/gateway/internal/logic/inventory/yarn/deleteYarnLogic.go b/gateway/internal/logic/inventory/yarn/deleteYarnLogic.go new file mode 100644 index 0000000..ec6f14e --- /dev/null +++ b/gateway/internal/logic/inventory/yarn/deleteYarnLogic.go @@ -0,0 +1,30 @@ +package yarn + +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 DeleteYarnLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDeleteYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteYarnLogic { + return &DeleteYarnLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *DeleteYarnLogic) DeleteYarn() (*types.IdResp, error) { + id := ctxdata.GetPathId(l.ctx) + if _, err := l.svcCtx.InventoryRpc.DeleteYarn(l.ctx, &pb.DeleteYarnReq{YarnId: id}); err != nil { + return nil, err + } + return &types.IdResp{Id: id}, nil +} diff --git a/gateway/internal/logic/inventory/yarn/getYarnLogic.go b/gateway/internal/logic/inventory/yarn/getYarnLogic.go new file mode 100644 index 0000000..0100f2c --- /dev/null +++ b/gateway/internal/logic/inventory/yarn/getYarnLogic.go @@ -0,0 +1,32 @@ +package yarn + +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 GetYarnLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetYarnLogic { + return &GetYarnLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *GetYarnLogic) GetYarn() (*types.YarnInfo, error) { + id := ctxdata.GetPathId(l.ctx) + resp, err := l.svcCtx.InventoryRpc.GetYarn(l.ctx, &pb.GetYarnReq{YarnId: id}) + if err != nil { + return nil, err + } + out := yarnInfoFromPB(resp) + return &out, nil +} diff --git a/gateway/internal/logic/inventory/yarn/helpers.go b/gateway/internal/logic/inventory/yarn/helpers.go new file mode 100644 index 0000000..c1f6122 --- /dev/null +++ b/gateway/internal/logic/inventory/yarn/helpers.go @@ -0,0 +1,26 @@ +package yarn + +import ( + "muyu-apiserver/gateway/internal/types" + "muyu-apiserver/rpc/inventory/pb" +) + +func yarnInfoFromPB(y *pb.YarnInfo) types.YarnInfo { + if y == nil { + return types.YarnInfo{} + } + return types.YarnInfo{ + YarnId: y.YarnId, + YarnName: y.YarnName, + Color: y.Color, + WeightGM: y.WeightGM, + SupplierId: y.SupplierId, + SupplierName: y.SupplierName, + DyeFactory: y.DyeFactory, + ImageUrl: y.ImageUrl, + Remark: y.Remark, + Status: y.Status, + CreatedAt: y.CreatedAt, + UpdatedAt: y.UpdatedAt, + } +} diff --git a/gateway/internal/logic/inventory/yarn/listYarnLogic.go b/gateway/internal/logic/inventory/yarn/listYarnLogic.go new file mode 100644 index 0000000..67be2cd --- /dev/null +++ b/gateway/internal/logic/inventory/yarn/listYarnLogic.go @@ -0,0 +1,39 @@ +package yarn + +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 ListYarnLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewListYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListYarnLogic { + return &ListYarnLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *ListYarnLogic) ListYarn(req *types.ListYarnReq) (*types.ListYarnResp, error) { + resp, err := l.svcCtx.InventoryRpc.ListYarn(l.ctx, &pb.ListYarnReq{ + Page: req.Page, + PageSize: req.PageSize, + YarnName: req.YarnName, + SupplierId: req.SupplierId, + Status: req.Status, + }) + if err != nil { + return nil, err + } + list := make([]types.YarnInfo, 0, len(resp.List)) + for _, item := range resp.List { + list = append(list, yarnInfoFromPB(item)) + } + return &types.ListYarnResp{Total: resp.Total, List: list}, nil +} diff --git a/gateway/internal/logic/inventory/yarn/updateYarnLogic.go b/gateway/internal/logic/inventory/yarn/updateYarnLogic.go new file mode 100644 index 0000000..dc4cc74 --- /dev/null +++ b/gateway/internal/logic/inventory/yarn/updateYarnLogic.go @@ -0,0 +1,41 @@ +package yarn + +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 UpdateYarnLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewUpdateYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateYarnLogic { + return &UpdateYarnLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} +} + +func (l *UpdateYarnLogic) UpdateYarn(req *types.UpdateYarnReq) (*types.IdResp, error) { + id := ctxdata.GetPathId(l.ctx) + _, err := l.svcCtx.InventoryRpc.UpdateYarn(l.ctx, &pb.UpdateYarnReq{ + YarnId: id, + YarnName: req.YarnName, + Color: req.Color, + WeightGM: req.WeightGM, + SupplierId: req.SupplierId, + DyeFactory: req.DyeFactory, + ImageUrl: req.ImageUrl, + Remark: req.Remark, + Status: req.Status, + }) + if err != nil { + return nil, err + } + return &types.IdResp{Id: id}, nil +} diff --git a/gateway/internal/types/types.go b/gateway/internal/types/types.go index 77e0e87..8d7e813 100644 --- a/gateway/internal/types/types.go +++ b/gateway/internal/types/types.go @@ -34,13 +34,16 @@ type CreateMenuReq struct { } type CreateProductReq struct { - ProductName string `json:"productName"` - ImageUrl string `json:"imageUrl,optional"` - Spec string `json:"spec,optional"` - Color string `json:"color,optional"` - SalesPrice string `json:"salesPrice,optional"` - Remark string `json:"remark,optional"` - Pans []PanInput `json:"pans,optional"` + ProductName string `json:"productName"` + ImageUrl string `json:"imageUrl,optional"` + Spec string `json:"spec,optional"` + Color string `json:"color,optional"` + ColorNo string `json:"colorNo,optional"` + ProductCode string `json:"productCode,optional"` + SalesPrice string `json:"salesPrice,optional"` + Remark string `json:"remark,optional"` + Pans []PanInput `json:"pans,optional"` + InitialBatch ProductBatchInput `json:"initialBatch,optional"` } type CreateRoleReq struct { @@ -114,6 +117,8 @@ type ListProductReq struct { ProductName string `form:"productName,optional"` Spec string `form:"spec,optional"` Color string `form:"color,optional"` + ColorNo string `form:"colorNo,optional"` + ProductCode string `form:"productCode,optional"` Status int64 `form:"status,optional,default=-1"` } @@ -230,6 +235,8 @@ type ProductInfo struct { ImageUrl string `json:"imageUrl"` Spec string `json:"spec"` Color string `json:"color"` + ColorNo string `json:"colorNo"` + ProductCode string `json:"productCode"` SalesPrice string `json:"salesPrice"` Remark string `json:"remark"` Status int64 `json:"status"` @@ -247,6 +254,8 @@ type BoltInfo struct { type PanInfo struct { PanId string `json:"panId"` ProductId string `json:"productId"` + BatchId string `json:"batchId"` + BatchNo string `json:"batchNo"` Name string `json:"name"` Position string `json:"position"` SortOrder int64 `json:"sortOrder"` @@ -259,6 +268,7 @@ type PanInput struct { Name string `json:"name"` Position string `json:"position,optional"` BoltLengths []string `json:"boltLengths,optional"` + BatchId string `json:"batchId,optional"` } type ListPanResp struct { @@ -304,6 +314,8 @@ type ColorDetailItem struct { ProductId string `json:"productId"` ProductName string `json:"productName"` Color string `json:"color"` + ColorNo string `json:"colorNo"` + ProductCode string `json:"productCode"` Spec string `json:"spec"` ImageUrl string `json:"imageUrl"` PanCount int64 `json:"panCount"` @@ -311,6 +323,7 @@ type ColorDetailItem struct { TotalLengthM string `json:"totalLengthM"` Locations string `json:"locations"` SalesPrice string `json:"salesPrice"` + BatchCount int64 `json:"batchCount"` } type ListColorDetailReq struct { @@ -321,9 +334,96 @@ type ColorDetailResp struct { List []ColorDetailItem `json:"list"` } +type YarnInfo struct { + YarnId string `json:"yarnId"` + YarnName string `json:"yarnName"` + Color string `json:"color"` + WeightGM string `json:"weightGM"` + SupplierId string `json:"supplierId"` + SupplierName string `json:"supplierName"` + DyeFactory string `json:"dyeFactory"` + ImageUrl string `json:"imageUrl"` + Remark string `json:"remark"` + Status int64 `json:"status"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +type CreateYarnReq struct { + YarnName string `json:"yarnName"` + Color string `json:"color,optional"` + WeightGM string `json:"weightGM"` + SupplierId string `json:"supplierId"` + DyeFactory string `json:"dyeFactory,optional"` + ImageUrl string `json:"imageUrl,optional"` + Remark string `json:"remark,optional"` +} + +type UpdateYarnReq struct { + YarnName string `json:"yarnName"` + Color string `json:"color,optional"` + WeightGM string `json:"weightGM"` + SupplierId string `json:"supplierId"` + DyeFactory string `json:"dyeFactory,optional"` + ImageUrl string `json:"imageUrl,optional"` + Remark string `json:"remark,optional"` + Status int64 `json:"status,optional,default=1"` +} + +type ListYarnReq struct { + Page int64 `form:"page,default=1"` + PageSize int64 `form:"pageSize,default=20"` + YarnName string `form:"yarnName,optional"` + SupplierId string `form:"supplierId,optional"` + Status int64 `form:"status,optional,default=-1"` +} + +type ListYarnResp struct { + Total int64 `json:"total"` + List []YarnInfo `json:"list"` +} + +type ProductBatchInput struct { + BatchNo string `json:"batchNo,optional"` + YarnRatio string `json:"yarnRatio,optional"` + WarpWeightGM string `json:"warpWeightGM,optional"` + WeftWeightGM string `json:"weftWeightGM,optional"` + ProductionProcess string `json:"productionProcess,optional"` + Remark string `json:"remark,optional"` +} + +type ProductBatchInfo struct { + BatchId string `json:"batchId"` + ProductId string `json:"productId"` + BatchNo string `json:"batchNo"` + YarnRatio string `json:"yarnRatio"` + WarpWeightGM string `json:"warpWeightGM"` + WeftWeightGM string `json:"weftWeightGM"` + ProductionProcess string `json:"productionProcess"` + Remark string `json:"remark"` + Status int64 `json:"status"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +type CreateProductBatchReq struct { + Batch ProductBatchInput `json:"batch"` +} + +type UpdateProductBatchReq struct { + Batch ProductBatchInput `json:"batch"` + Status int64 `json:"status,optional,default=1"` +} + +type ListProductBatchResp struct { + List []ProductBatchInfo `json:"list"` +} + type PanListItem struct { PanId string `json:"panId"` ProductId string `json:"productId"` + BatchId string `json:"batchId"` + BatchNo string `json:"batchNo"` Name string `json:"name"` Position string `json:"position"` ProductName string `json:"productName"` @@ -484,6 +584,7 @@ type UpdateProductReq struct { ImageUrl string `json:"imageUrl,optional"` Spec string `json:"spec,optional"` Color string `json:"color,optional"` + ColorNo string `json:"colorNo,optional"` SalesPrice string `json:"salesPrice,optional"` Remark string `json:"remark,optional"` } @@ -702,12 +803,12 @@ type ListPurchaseOrderResp struct { // ─── Purchase Receipt ──────────────────────────────────────────────────────── type PurchaseReceiptDetailInfo struct { - DetailId string `json:"detailId"` + DetailId string `json:"detailId"` OrderDetailId string `json:"orderDetailId"` - ProductId string `json:"productId"` - ActualQty string `json:"actualQty"` - UnitCost string `json:"unitCost"` - Remark string `json:"remark"` + ProductId string `json:"productId"` + ActualQty string `json:"actualQty"` + UnitCost string `json:"unitCost"` + Remark string `json:"remark"` } type PurchaseReceiptDetailReq struct { diff --git a/go.mod b/go.mod index 0434468..390e5b6 100644 --- a/go.mod +++ b/go.mod @@ -66,6 +66,7 @@ require ( github.com/microsoft/go-mssqldb v1.9.5 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mozillazg/go-pinyin v0.21.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect diff --git a/go.sum b/go.sum index 21fbc2f..9b184dd 100644 --- a/go.sum +++ b/go.sum @@ -189,6 +189,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/mozillazg/go-pinyin v0.21.0 h1:Wo8/NT45z7P3er/9YSLHA3/kjZzbLz5hR7i+jGeIGao= +github.com/mozillazg/go-pinyin v0.21.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= diff --git a/model/invproductbatchmodel.go b/model/invproductbatchmodel.go new file mode 100644 index 0000000..31f33fa --- /dev/null +++ b/model/invproductbatchmodel.go @@ -0,0 +1,81 @@ +package model + +import ( + "context" + "fmt" + "time" + + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ InvProductBatchModel = (*customInvProductBatchModel)(nil) + +type ( + InvProductBatchModel interface { + invProductBatchModel + FindByProductId(ctx context.Context, tenantId, productId string) ([]*InvProductBatch, error) + FindLatestByProductId(ctx context.Context, tenantId, productId string) (*InvProductBatch, error) + FindOneByProductAndBatchId(ctx context.Context, tenantId, productId, batchId string) (*InvProductBatch, error) + NextBatchNo(ctx context.Context, tenantId, productCode string) (string, error) + SoftDeleteByBatchId(ctx context.Context, batchId string) error + } + + customInvProductBatchModel struct { + *defaultInvProductBatchModel + } +) + +func NewInvProductBatchModel(conn sqlx.SqlConn) InvProductBatchModel { + return &customInvProductBatchModel{ + defaultInvProductBatchModel: newInvProductBatchModel(conn), + } +} + +func (m *customInvProductBatchModel) FindByProductId(ctx context.Context, tenantId, productId string) ([]*InvProductBatch, error) { + var list []*InvProductBatch + query := fmt.Sprintf("SELECT %s FROM %s WHERE tenant_id = ? AND product_id = ? AND deleted_at IS NULL ORDER BY batch_no", invProductBatchRows, m.table) + if err := m.conn.QueryRowsCtx(ctx, &list, query, tenantId, productId); err != nil { + return nil, err + } + return list, nil +} + +func (m *customInvProductBatchModel) FindLatestByProductId(ctx context.Context, tenantId, productId string) (*InvProductBatch, error) { + var resp InvProductBatch + query := fmt.Sprintf("SELECT %s FROM %s WHERE tenant_id = ? AND product_id = ? AND deleted_at IS NULL AND status = 1 ORDER BY batch_no DESC LIMIT 1", invProductBatchRows, m.table) + if err := m.conn.QueryRowCtx(ctx, &resp, query, tenantId, productId); err != nil { + return nil, err + } + return &resp, nil +} + +func (m *customInvProductBatchModel) FindOneByProductAndBatchId(ctx context.Context, tenantId, productId, batchId string) (*InvProductBatch, error) { + var resp InvProductBatch + query := fmt.Sprintf("SELECT %s FROM %s WHERE tenant_id = ? AND product_id = ? AND batch_id = ? AND deleted_at IS NULL LIMIT 1", invProductBatchRows, m.table) + if err := m.conn.QueryRowCtx(ctx, &resp, query, tenantId, productId, batchId); err != nil { + return nil, err + } + return &resp, nil +} + +func (m *customInvProductBatchModel) NextBatchNo(ctx context.Context, tenantId, productCode string) (string, error) { + var next int64 + query := fmt.Sprintf(`SELECT COALESCE(MAX(CAST(SUBSTRING(batch_no, CHAR_LENGTH(?) + 3) AS UNSIGNED)), 0) + 1 + FROM %s + WHERE tenant_id = ? AND batch_no LIKE CONCAT(?, '-B%%')`, m.table) + if err := m.conn.QueryRowCtx(ctx, &next, query, productCode, tenantId, productCode); err != nil { + return "", err + } + return fmt.Sprintf("%s-B%03d", productCode, next), nil +} + +func (m *customInvProductBatchModel) SoftDeleteByBatchId(ctx context.Context, batchId string) error { + batch, err := m.FindOneByBatchId(ctx, batchId) + if err != nil { + return err + } + batch.Status = 0 + batch.DeletedAt.Time = time.Now() + batch.DeletedAt.Valid = true + return m.Update(ctx, batch) +} diff --git a/model/invproductbatchmodel_gen.go b/model/invproductbatchmodel_gen.go new file mode 100644 index 0000000..fe0c911 --- /dev/null +++ b/model/invproductbatchmodel_gen.go @@ -0,0 +1,100 @@ +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 ( + invProductBatchFieldNames = builder.RawFieldNames(&InvProductBatch{}) + invProductBatchRows = strings.Join(invProductBatchFieldNames, ",") + invProductBatchRowsExpectAutoSet = strings.Join(stringx.Remove(invProductBatchFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + invProductBatchRowsWithPlaceHolder = strings.Join(stringx.Remove(invProductBatchFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + invProductBatchModel interface { + Insert(ctx context.Context, data *InvProductBatch) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*InvProductBatch, error) + FindOneByBatchId(ctx context.Context, batchId string) (*InvProductBatch, error) + Update(ctx context.Context, data *InvProductBatch) error + Delete(ctx context.Context, id int64) error + } + + defaultInvProductBatchModel struct { + conn sqlx.SqlConn + table string + } + + InvProductBatch struct { + Id int64 `db:"id"` + BatchId string `db:"batch_id"` + TenantId string `db:"tenant_id"` + ProductId string `db:"product_id"` + BatchNo string `db:"batch_no"` + YarnRatio sql.NullString `db:"yarn_ratio"` + WarpWeightGM float64 `db:"warp_weight_g_m"` + WeftWeightGM float64 `db:"weft_weight_g_m"` + ProductionProcess sql.NullString `db:"production_process"` + Remark sql.NullString `db:"remark"` + Status int64 `db:"status"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + DeletedAt sql.NullTime `db:"deleted_at"` + } +) + +func newInvProductBatchModel(conn sqlx.SqlConn) *defaultInvProductBatchModel { + return &defaultInvProductBatchModel{ + conn: conn, + table: "`inv_product_batch`", + } +} + +func (m *defaultInvProductBatchModel) Insert(ctx context.Context, data *InvProductBatch) (sql.Result, error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invProductBatchRowsExpectAutoSet) + return m.conn.ExecCtx(ctx, query, data.BatchId, data.TenantId, data.ProductId, data.BatchNo, data.YarnRatio, data.WarpWeightGM, data.WeftWeightGM, data.ProductionProcess, data.Remark, data.Status, data.DeletedAt) +} + +func (m *defaultInvProductBatchModel) FindOne(ctx context.Context, id int64) (*InvProductBatch, error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? LIMIT 1", invProductBatchRows, m.table) + var resp InvProductBatch + err := m.conn.QueryRowCtx(ctx, &resp, query, id) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (m *defaultInvProductBatchModel) FindOneByBatchId(ctx context.Context, batchId string) (*InvProductBatch, error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `batch_id` = ? AND `deleted_at` IS NULL LIMIT 1", invProductBatchRows, m.table) + var resp InvProductBatch + err := m.conn.QueryRowCtx(ctx, &resp, query, batchId) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (m *defaultInvProductBatchModel) Update(ctx context.Context, data *InvProductBatch) error { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, invProductBatchRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, data.BatchId, data.TenantId, data.ProductId, data.BatchNo, data.YarnRatio, data.WarpWeightGM, data.WeftWeightGM, data.ProductionProcess, data.Remark, data.Status, data.DeletedAt, data.Id) + return err +} + +func (m *defaultInvProductBatchModel) 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 *defaultInvProductBatchModel) tableName() string { + return m.table +} diff --git a/model/invproductboltmodel.go b/model/invproductboltmodel.go index 71c62c3..ddad91c 100644 --- a/model/invproductboltmodel.go +++ b/model/invproductboltmodel.go @@ -59,7 +59,7 @@ func (m *customInvProductBoltModel) FindByPanId(ctx context.Context, panId strin 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` "+ + "SELECT b.`id`, b.`bolt_id`, b.`pan_id`, b.`length_m`, b.`color`, 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) diff --git a/model/invproductmodel.go b/model/invproductmodel.go index 2284083..809ec48 100755 --- a/model/invproductmodel.go +++ b/model/invproductmodel.go @@ -19,25 +19,28 @@ type StockGroupResult struct { } 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"` + 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"` + ColorNo string `db:"color_no"` + ProductCode string `db:"product_code"` Spec string `db:"spec"` ImageUrl string `db:"image_url"` SalesPrice float64 `db:"sales_price"` PanCount int64 `db:"pan_count"` BoltCount int64 `db:"bolt_count"` + BatchCount int64 `db:"batch_count"` TotalLengthM float64 `db:"total_length_m"` Locations string `db:"locations"` } @@ -45,11 +48,13 @@ type ColorDetail struct { type ( InvProductModel interface { invProductModel - FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color string, status int64) ([]*InvProduct, int64, error) + FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color, colorNo, productCode string, status int64) ([]*InvProduct, int64, error) FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error) FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, error) + FindOneByTenantProductCode(ctx context.Context, tenantId, productCode string) (*InvProduct, error) FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error) FindGroupByLocation(ctx context.Context, tenantId string) ([]StockGroupResult, error) + NextColorNo(ctx context.Context, tenantId, productName string) (string, error) BulkInsert(ctx context.Context, products []*InvProduct) (int64, error) } @@ -79,15 +84,16 @@ func (m *customInvProductModel) BulkInsert(ctx context.Context, products []*InvP } batch := products[i:end] - placeholder := "(" + strings.Repeat("?,", 9) + "?)" + placeholder := "(" + strings.Repeat("?,", 11) + "?)" placeholders := make([]string, len(batch)) - args := make([]interface{}, 0, len(batch)*10) + args := make([]interface{}, 0, len(batch)*12) 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, + p.ColorNo, p.ProductCode, p.SalesPrice, p.Remark, p.Status, + p.TenantId, p.DeletedAt, ) } @@ -105,7 +111,7 @@ func (m *customInvProductModel) BulkInsert(ctx context.Context, products []*InvP return totalAffected, nil } -func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color string, status int64) ([]*InvProduct, int64, error) { +func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color, colorNo, productCode string, status int64) ([]*InvProduct, int64, error) { where := "WHERE deleted_at IS NULL AND tenant_id = ?" args := []interface{}{tenantId} @@ -121,6 +127,14 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p where += " AND color = ?" args = append(args, color) } + if colorNo != "" { + where += " AND color_no LIKE ?" + args = append(args, "%"+colorNo+"%") + } + if productCode != "" { + where += " AND product_code LIKE ?" + args = append(args, "%"+productCode+"%") + } if status >= 0 { where += " AND status = ?" args = append(args, status) @@ -144,6 +158,27 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p return list, total, nil } +func (m *customInvProductModel) FindOneByTenantProductCode(ctx context.Context, tenantId, productCode string) (*InvProduct, error) { + var resp InvProduct + query := fmt.Sprintf("SELECT %s FROM %s WHERE tenant_id = ? AND product_code = ? AND deleted_at IS NULL LIMIT 1", invProductRows, m.table) + err := m.QueryRowNoCacheCtx(ctx, &resp, query, tenantId, productCode) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (m *customInvProductModel) NextColorNo(ctx context.Context, tenantId, productName string) (string, error) { + var next int64 + query := fmt.Sprintf(`SELECT COALESCE(MAX(CAST(color_no AS UNSIGNED)), 0) + 1 + FROM %s + WHERE tenant_id = ? AND product_name = ? AND deleted_at IS NULL AND color_no REGEXP '^[0-9]+$'`, m.table) + if err := m.QueryRowNoCacheCtx(ctx, &next, query, tenantId, productName); err != nil { + return "", err + } + return fmt.Sprintf("%02d", next), nil +} + func (m *customInvProductModel) FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error) { var list []*ProductSummary query := `SELECT p.product_name, p.spec, @@ -200,9 +235,16 @@ func (m *customInvProductModel) FindGroupByLocation(ctx context.Context, tenantI 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, + query := `SELECT p.product_id, p.product_name, p.color, p.color_no, p.product_code, p.spec, p.image_url, p.sales_price, COUNT(DISTINCT pan.pan_id) AS pan_count, COUNT(bolt.bolt_id) AS bolt_count, + ( + SELECT COUNT(DISTINCT batch.batch_id) + FROM ` + "`inv_product_batch`" + ` batch + WHERE batch.product_id = p.product_id + AND batch.tenant_id = p.tenant_id + AND batch.deleted_at IS NULL + ) AS batch_count, COALESCE(SUM(bolt.length_m), 0) AS total_length_m, COALESCE(GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position), '') AS locations FROM ` + m.table + ` p diff --git a/model/invproductmodel_gen.go b/model/invproductmodel_gen.go index 7fefa7c..68bbc1c 100755 --- a/model/invproductmodel_gen.go +++ b/model/invproductmodel_gen.go @@ -27,6 +27,7 @@ var ( cacheInvProductIdPrefix = "cache:invProduct:id:" cacheInvProductProductIdPrefix = "cache:invProduct:productId:" cacheInvProductProductNamePrefix = "cache:invProduct:productName:" + cacheInvProductProductCodePrefix = "cache:invProduct:productCode:" ) type ( @@ -35,6 +36,7 @@ type ( FindOne(ctx context.Context, id int64) (*InvProduct, error) FindOneByProductId(ctx context.Context, productId string) (*InvProduct, error) FindOneByProductName(ctx context.Context, productName string) (*InvProduct, error) + FindOneByProductCode(ctx context.Context, productCode string) (*InvProduct, error) Update(ctx context.Context, data *InvProduct) error Delete(ctx context.Context, id int64) error } @@ -51,6 +53,8 @@ type ( ImageUrl string `db:"image_url"` Spec string `db:"spec"` Color string `db:"color"` + ColorNo string `db:"color_no"` + ProductCode string `db:"product_code"` SalesPrice float64 `db:"sales_price"` Remark sql.NullString `db:"remark"` Status int64 `db:"status"` @@ -77,10 +81,11 @@ func (m *defaultInvProductModel) Delete(ctx context.Context, id int64) error { invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, id) invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId) invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName) + invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode) _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { query := fmt.Sprintf("delete from %s where `id` = ?", m.table) return conn.ExecCtx(ctx, query, id) - }, invProductIdKey, invProductProductIdKey, invProductProductNameKey) + }, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey) return err } @@ -121,6 +126,26 @@ func (m *defaultInvProductModel) FindOneByProductId(ctx context.Context, product } } +func (m *defaultInvProductModel) FindOneByProductCode(ctx context.Context, productCode string) (*InvProduct, error) { + invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, productCode) + var resp InvProduct + err := m.QueryRowIndexCtx(ctx, &resp, invProductProductCodeKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `product_code` = ? limit 1", invProductRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, productCode); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + func (m *defaultInvProductModel) FindOneByProductName(ctx context.Context, productName string) (*InvProduct, error) { invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, productName) var resp InvProduct @@ -145,10 +170,11 @@ func (m *defaultInvProductModel) Insert(ctx context.Context, data *InvProduct) ( invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id) invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId) invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName) + invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode) 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) - 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) + 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.ColorNo, data.ProductCode, data.SalesPrice, data.Remark, data.Status, data.TenantId, data.DeletedAt) + }, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey) return ret, err } @@ -161,10 +187,11 @@ func (m *defaultInvProductModel) Update(ctx context.Context, newData *InvProduct invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id) invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId) invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName) + invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode) _, 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) - 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) + return conn.ExecCtx(ctx, query, newData.ProductId, newData.ProductName, newData.ImageUrl, newData.Spec, newData.Color, newData.ColorNo, newData.ProductCode, newData.SalesPrice, newData.Remark, newData.Status, newData.TenantId, newData.DeletedAt, newData.Id) + }, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey) return err } diff --git a/model/invproductmodel_test.go b/model/invproductmodel_test.go index 190fb7b..5ae2ce2 100644 --- a/model/invproductmodel_test.go +++ b/model/invproductmodel_test.go @@ -49,6 +49,8 @@ func TestInvProductInsert(t *testing.T) { ImageUrl: "", Spec: "100cm", Color: "red", + ColorNo: "01", + ProductCode: uniqueID("TPC"), SalesPrice: 99.9, Remark: sql.NullString{String: "test remark", Valid: true}, Status: 1, @@ -83,6 +85,8 @@ func TestInvProductFindOne(t *testing.T) { ProductName: uniqueID("test_product"), Spec: "200cm", Color: "blue", + ColorNo: "01", + ProductCode: uniqueID("TPC"), SalesPrice: 49.5, Status: 1, TenantId: "t_default_001", @@ -121,6 +125,8 @@ func TestInvProductUpdate(t *testing.T) { ProductName: uniqueID("test_product"), Spec: "50cm", Color: "green", + ColorNo: "01", + ProductCode: uniqueID("TPC"), SalesPrice: 10.0, Status: 1, TenantId: "t_default_001", @@ -172,6 +178,8 @@ func TestInvProductBulkInsert(t *testing.T) { ProductName: uniqueID(fmt.Sprintf("bulk_product_%d", i)), Spec: "10cm", Color: "white", + ColorNo: fmt.Sprintf("%02d", i+1), + ProductCode: uniqueID(fmt.Sprintf("BTPC%d", i)), SalesPrice: float64(i+1) * 5.0, Status: 1, TenantId: "t_default_001", @@ -229,7 +237,8 @@ func TestInvProductSchemaColumns(t *testing.T) { // Columns that the InvProduct struct declares (via db tags). structCols := []string{ "id", "product_id", "product_name", "image_url", "spec", "color", - "sales_price", "remark", "status", "tenant_id", "created_at", "updated_at", "deleted_at", + "color_no", "product_code", "sales_price", "remark", "status", "tenant_id", + "created_at", "updated_at", "deleted_at", } for _, col := range structCols { @@ -253,7 +262,7 @@ func TestInvProductSchemaColumns(t *testing.T) { // TestFindProductSummaryNoPans guards against the GROUP_CONCAT NULL scan bug: // when a product has no pans, the LEFT JOIN produces NULL for pan.position and // GROUP_CONCAT over all-NULL values returns NULL, which cannot be scanned into a -// Go string. The fix wraps both GROUP_CONCAT calls with COALESCE(..., ''). +// Go string. The fix wraps both GROUP_CONCAT calls with COALESCE(..., ''). func TestFindProductSummaryNoPans(t *testing.T) { if testing.Short() { t.Skip("skipping integration test in short mode") @@ -267,6 +276,8 @@ func TestFindProductSummaryNoPans(t *testing.T) { ProductName: uniqueID("nopan_product"), Spec: "50cm", Color: "red", + ColorNo: "01", + ProductCode: uniqueID("TPC"), SalesPrice: 99.0, Status: 1, TenantId: "t_default_001", @@ -318,6 +329,8 @@ func TestFindColorDetailNoPans(t *testing.T) { ProductName: uniqueID("color_nopan_product"), Spec: "80cm", Color: "blue", + ColorNo: "01", + ProductCode: uniqueID("TPC"), SalesPrice: 50.0, Status: 1, TenantId: "t_default_001", @@ -343,3 +356,96 @@ func TestFindColorDetailNoPans(t *testing.T) { t.Errorf("Locations: got %q, want empty string", list[0].Locations) } } + +func TestFindColorDetailBatchCountDoesNotDuplicateStock(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test in short mode") + } + + conn := sqlx.NewMysql(testDSN) + m := newTestProductModel(t) + panM := newInvProductPanModel(conn) + boltM := newInvProductBoltModel(conn) + batchM := newInvProductBatchModel(conn) + ctx := context.Background() + + productId := uniqueID("pcb") + p := &InvProduct{ + ProductId: productId, + ProductName: uniqueID("color_batch_product"), + Spec: "120cm", + Color: "natural", + ColorNo: "01", + ProductCode: uniqueID("TPC"), + SalesPrice: 20.0, + Status: 1, + TenantId: "t_default_001", + } + res, err := m.Insert(ctx, p) + if err != nil { + t.Fatalf("Insert product: %v", err) + } + productRowId, _ := res.LastInsertId() + t.Cleanup(func() { _ = m.Delete(ctx, productRowId) }) + + batchAId := uniqueID("b1") + batchBId := uniqueID("b2") + for _, batch := range []*InvProductBatch{ + {BatchId: batchAId, TenantId: p.TenantId, ProductId: productId, BatchNo: p.ProductCode + "-B001", Status: 1}, + {BatchId: batchBId, TenantId: p.TenantId, ProductId: productId, BatchNo: p.ProductCode + "-B002", Status: 1}, + } { + res, err := batchM.Insert(ctx, batch) + if err != nil { + t.Fatalf("Insert batch: %v", err) + } + id, _ := res.LastInsertId() + t.Cleanup(func() { _ = batchM.Delete(ctx, id) }) + } + + pans := []*InvProductPan{ + {PanId: uniqueID("pa"), ProductId: productId, BatchId: batchAId, Name: "A", Position: "A-01", SortOrder: 1, TenantId: p.TenantId}, + {PanId: uniqueID("pb"), ProductId: productId, BatchId: batchBId, Name: "B", Position: "B-02", SortOrder: 2, TenantId: p.TenantId}, + } + for _, pan := range pans { + res, err := panM.Insert(ctx, pan) + if err != nil { + t.Fatalf("Insert pan: %v", err) + } + id, _ := res.LastInsertId() + t.Cleanup(func() { _ = panM.Delete(ctx, id) }) + } + + for _, bolt := range []*InvProductBolt{ + {BoltId: uniqueID("ba1"), PanId: pans[0].PanId, LengthM: 10.5, Color: p.Color, SortOrder: 1, TenantId: p.TenantId}, + {BoltId: uniqueID("ba2"), PanId: pans[0].PanId, LengthM: 11.5, Color: p.Color, SortOrder: 2, TenantId: p.TenantId}, + {BoltId: uniqueID("bb1"), PanId: pans[1].PanId, LengthM: 12.0, Color: p.Color, SortOrder: 1, TenantId: p.TenantId}, + } { + res, err := boltM.Insert(ctx, bolt) + if err != nil { + t.Fatalf("Insert bolt: %v", err) + } + id, _ := res.LastInsertId() + t.Cleanup(func() { _ = boltM.Delete(ctx, id) }) + } + + list, err := m.FindColorDetail(ctx, p.TenantId, p.ProductName) + if err != nil { + t.Fatalf("FindColorDetail: %v", err) + } + if len(list) != 1 { + t.Fatalf("expected 1 color detail row, got %d", len(list)) + } + got := list[0] + if got.PanCount != 2 { + t.Errorf("PanCount: got %d, want 2", got.PanCount) + } + if got.BoltCount != 3 { + t.Errorf("BoltCount: got %d, want 3", got.BoltCount) + } + if got.BatchCount != 2 { + t.Errorf("BatchCount: got %d, want 2", got.BatchCount) + } + if got.TotalLengthM != 34.0 { + t.Errorf("TotalLengthM: got %.2f, want 34.00", got.TotalLengthM) + } +} diff --git a/model/invproductpanmodel.go b/model/invproductpanmodel.go index 00cdcd3..f8ae656 100644 --- a/model/invproductpanmodel.go +++ b/model/invproductpanmodel.go @@ -15,6 +15,8 @@ var _ InvProductPanModel = (*customInvProductPanModel)(nil) type PanListItem struct { PanId string `db:"pan_id"` ProductId string `db:"product_id"` + BatchId string `db:"batch_id"` + BatchNo string `db:"batch_no"` Name string `db:"name"` Position string `db:"position"` ProductName string `db:"product_name"` @@ -30,6 +32,7 @@ type ( 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) + CountByBatchId(ctx context.Context, batchId string) (int64, error) } customInvProductPanModel struct { @@ -79,13 +82,14 @@ func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId str return nil, 0, err } - query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.name, pan.position, - p.product_name, + query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.batch_id, COALESCE(batch.batch_no, '') AS batch_no, + 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_batch batch ON batch.batch_id = pan.batch_id AND batch.deleted_at IS NULL LEFT JOIN inv_product_bolt b ON b.pan_id = pan.pan_id %s GROUP BY pan.pan_id @@ -100,6 +104,15 @@ func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId str return list, total, nil } +func (m *customInvProductPanModel) CountByBatchId(ctx context.Context, batchId string) (int64, error) { + var total int64 + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `batch_id` = ?", m.table) + if err := m.conn.QueryRowCtx(ctx, &total, query, batchId); err != nil { + return 0, err + } + return 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) @@ -109,12 +122,12 @@ func (m *customInvProductPanModel) BulkReplace(ctx context.Context, productId, t if len(pans) == 0 { return nil } - placeholder := "(?, ?, ?, ?, ?, ?)" + placeholder := "(?, ?, ?, ?, ?, ?, ?)" placeholders := make([]string, len(pans)) - args := make([]interface{}, 0, len(pans)*6) + args := make([]interface{}, 0, len(pans)*7) for i, p := range pans { placeholders[i] = placeholder - args = append(args, p.PanId, productId, p.Name, p.Position, p.SortOrder, tenantId) + args = append(args, p.PanId, productId, p.BatchId, 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...) diff --git a/model/invproductpanmodel_gen.go b/model/invproductpanmodel_gen.go index 8d6dc01..a11066b 100644 --- a/model/invproductpanmodel_gen.go +++ b/model/invproductpanmodel_gen.go @@ -37,6 +37,7 @@ type ( Id int64 `db:"id"` PanId string `db:"pan_id"` ProductId string `db:"product_id"` + BatchId string `db:"batch_id"` Name string `db:"name"` Position string `db:"position"` SortOrder int64 `db:"sort_order"` @@ -54,8 +55,8 @@ func newInvProductPanModel(conn sqlx.SqlConn) *defaultInvProductPanModel { } 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) + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?)", m.table, invProductPanRowsExpectAutoSet) + return m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.BatchId, data.Name, data.Position, data.SortOrder, data.TenantId) } func (m *defaultInvProductPanModel) FindOne(ctx context.Context, id int64) (*InvProductPan, error) { @@ -80,7 +81,7 @@ func (m *defaultInvProductPanModel) FindOneByPanId(ctx context.Context, panId st 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) + _, err := m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.BatchId, data.Name, data.Position, data.SortOrder, data.TenantId, data.Id) return err } diff --git a/model/invyarnmodel.go b/model/invyarnmodel.go new file mode 100644 index 0000000..c8419ec --- /dev/null +++ b/model/invyarnmodel.go @@ -0,0 +1,82 @@ +package model + +import ( + "context" + "fmt" + "time" + + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ InvYarnModel = (*customInvYarnModel)(nil) + +type ( + InvYarnModel interface { + invYarnModel + FindList(ctx context.Context, tenantId string, page, pageSize int64, yarnName, supplierId string, status int64) ([]*InvYarn, int64, error) + FindOneByUnique(ctx context.Context, tenantId, yarnName, color, supplierId string) (*InvYarn, error) + SoftDeleteByYarnId(ctx context.Context, yarnId string) error + } + + customInvYarnModel struct { + *defaultInvYarnModel + } +) + +func NewInvYarnModel(conn sqlx.SqlConn) InvYarnModel { + return &customInvYarnModel{ + defaultInvYarnModel: newInvYarnModel(conn), + } +} + +func (m *customInvYarnModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, yarnName, supplierId string, status int64) ([]*InvYarn, int64, error) { + where := "WHERE tenant_id = ? AND deleted_at IS NULL" + args := []interface{}{tenantId} + + if yarnName != "" { + where += " AND yarn_name LIKE ?" + args = append(args, "%"+yarnName+"%") + } + if supplierId != "" { + where += " AND supplier_id = ?" + args = append(args, supplierId) + } + if status >= 0 { + where += " AND status = ?" + args = append(args, status) + } + + var total int64 + countQuery := fmt.Sprintf("SELECT COUNT(*) FROM %s %s", m.table, where) + if err := m.conn.QueryRowCtx(ctx, &total, countQuery, args...); err != nil { + return nil, 0, err + } + + var list []*InvYarn + query := fmt.Sprintf("SELECT %s FROM %s %s ORDER BY created_at DESC LIMIT ? OFFSET ?", invYarnRows, m.table, where) + args = append(args, pageSize, (page-1)*pageSize) + if err := m.conn.QueryRowsCtx(ctx, &list, query, args...); err != nil { + return nil, 0, err + } + return list, total, nil +} + +func (m *customInvYarnModel) FindOneByUnique(ctx context.Context, tenantId, yarnName, color, supplierId string) (*InvYarn, error) { + var resp InvYarn + query := fmt.Sprintf("SELECT %s FROM %s WHERE tenant_id = ? AND yarn_name = ? AND color = ? AND supplier_id = ? AND deleted_at IS NULL LIMIT 1", invYarnRows, m.table) + if err := m.conn.QueryRowCtx(ctx, &resp, query, tenantId, yarnName, color, supplierId); err != nil { + return nil, err + } + return &resp, nil +} + +func (m *customInvYarnModel) SoftDeleteByYarnId(ctx context.Context, yarnId string) error { + yarn, err := m.FindOneByYarnId(ctx, yarnId) + if err != nil { + return err + } + yarn.Status = 0 + yarn.DeletedAt.Time = time.Now() + yarn.DeletedAt.Valid = true + return m.Update(ctx, yarn) +} diff --git a/model/invyarnmodel_gen.go b/model/invyarnmodel_gen.go new file mode 100644 index 0000000..131d39f --- /dev/null +++ b/model/invyarnmodel_gen.go @@ -0,0 +1,100 @@ +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 ( + invYarnFieldNames = builder.RawFieldNames(&InvYarn{}) + invYarnRows = strings.Join(invYarnFieldNames, ",") + invYarnRowsExpectAutoSet = strings.Join(stringx.Remove(invYarnFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + invYarnRowsWithPlaceHolder = strings.Join(stringx.Remove(invYarnFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + invYarnModel interface { + Insert(ctx context.Context, data *InvYarn) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*InvYarn, error) + FindOneByYarnId(ctx context.Context, yarnId string) (*InvYarn, error) + Update(ctx context.Context, data *InvYarn) error + Delete(ctx context.Context, id int64) error + } + + defaultInvYarnModel struct { + conn sqlx.SqlConn + table string + } + + InvYarn struct { + Id int64 `db:"id"` + YarnId string `db:"yarn_id"` + TenantId string `db:"tenant_id"` + YarnName string `db:"yarn_name"` + Color string `db:"color"` + WeightGM float64 `db:"weight_g_m"` + SupplierId string `db:"supplier_id"` + DyeFactory string `db:"dye_factory"` + ImageUrl string `db:"image_url"` + Remark sql.NullString `db:"remark"` + Status int64 `db:"status"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + DeletedAt sql.NullTime `db:"deleted_at"` + } +) + +func newInvYarnModel(conn sqlx.SqlConn) *defaultInvYarnModel { + return &defaultInvYarnModel{ + conn: conn, + table: "`inv_yarn`", + } +} + +func (m *defaultInvYarnModel) Insert(ctx context.Context, data *InvYarn) (sql.Result, error) { + query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invYarnRowsExpectAutoSet) + return m.conn.ExecCtx(ctx, query, data.YarnId, data.TenantId, data.YarnName, data.Color, data.WeightGM, data.SupplierId, data.DyeFactory, data.ImageUrl, data.Remark, data.Status, data.DeletedAt) +} + +func (m *defaultInvYarnModel) FindOne(ctx context.Context, id int64) (*InvYarn, error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? LIMIT 1", invYarnRows, m.table) + var resp InvYarn + err := m.conn.QueryRowCtx(ctx, &resp, query, id) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (m *defaultInvYarnModel) FindOneByYarnId(ctx context.Context, yarnId string) (*InvYarn, error) { + query := fmt.Sprintf("SELECT %s FROM %s WHERE `yarn_id` = ? AND `deleted_at` IS NULL LIMIT 1", invYarnRows, m.table) + var resp InvYarn + err := m.conn.QueryRowCtx(ctx, &resp, query, yarnId) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (m *defaultInvYarnModel) Update(ctx context.Context, data *InvYarn) error { + query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, invYarnRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, data.YarnId, data.TenantId, data.YarnName, data.Color, data.WeightGM, data.SupplierId, data.DyeFactory, data.ImageUrl, data.Remark, data.Status, data.DeletedAt, data.Id) + return err +} + +func (m *defaultInvYarnModel) 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 *defaultInvYarnModel) tableName() string { + return m.table +} diff --git a/pkg/excelparse/native.go b/pkg/excelparse/native.go new file mode 100644 index 0000000..0b2cf37 --- /dev/null +++ b/pkg/excelparse/native.go @@ -0,0 +1,86 @@ +package excelparse + +import "strings" + +// NativeProductParser handles the MuYu product import template and product exports. +type NativeProductParser struct{} + +func (p *NativeProductParser) Name() string { return "木语产品模板" } + +func (p *NativeProductParser) Match(headers []string) bool { + idx := buildIndex(headers) + if !hasAny(idx, "产品名称", "名称") { + return false + } + return hasAny(idx, "产品码", "色号", "批次号", "纱线配比", "生产工艺") +} + +func (p *NativeProductParser) ParseRows(headers []string, rows [][]string) (*ParseResult, error) { + idx := buildIndex(headers) + seen := make(map[string]struct{}, len(rows)) + products := make([]ParsedProduct, 0, len(rows)) + skipped := 0 + + for _, row := range rows { + name := firstCol(row, idx, "产品名称", "名称") + if name == "" { + skipped++ + continue + } + + productCode := firstCol(row, idx, "产品码", "Product Code", "product_code") + key := productCode + if key == "" { + key = strings.Join([]string{ + name, + firstCol(row, idx, "规格型号", "规格"), + firstCol(row, idx, "颜色"), + firstCol(row, idx, "色号"), + }, "\x00") + } + if _, ok := seen[key]; ok { + skipped++ + continue + } + seen[key] = struct{}{} + + products = append(products, ParsedProduct{ + ProductName: name, + Spec: firstCol(row, idx, "规格型号", "规格"), + Color: firstCol(row, idx, "颜色"), + ColorNo: firstCol(row, idx, "色号"), + ProductCode: productCode, + SalesPrice: stripCurrency(firstCol(row, idx, "销售价", "参考售价")), + BatchNo: firstCol(row, idx, "批次号"), + YarnRatio: firstCol(row, idx, "纱线配比"), + WarpWeightGM: stripUnit(firstCol(row, idx, "经线克重(g/m)", "经线克重", "经纱克重")), + WeftWeightGM: stripUnit(firstCol(row, idx, "纬线克重(g/m)", "纬线克重", "纬纱克重")), + ProductionProcess: firstCol(row, idx, "生产工艺"), + Remark: firstCol(row, idx, "备注"), + }) + } + + return &ParseResult{Products: products, SkippedRows: skipped}, nil +} + +func hasAny(idx map[string]int, names ...string) bool { + for _, name := range names { + if _, ok := idx[name]; ok { + return true + } + } + return false +} + +func firstCol(row []string, idx map[string]int, names ...string) string { + for _, name := range names { + col, ok := idx[name] + if !ok { + continue + } + if val := colVal(row, col); val != "" { + return val + } + } + return "" +} diff --git a/pkg/excelparse/parse.go b/pkg/excelparse/parse.go index 9a88089..e8f1f7c 100644 --- a/pkg/excelparse/parse.go +++ b/pkg/excelparse/parse.go @@ -17,6 +17,7 @@ import ( var parsers []FormatParser func init() { + parsers = append(parsers, &NativeProductParser{}) parsers = append(parsers, &MiaozhangParser{}) } diff --git a/pkg/excelparse/types.go b/pkg/excelparse/types.go index e962ce3..61165f2 100644 --- a/pkg/excelparse/types.go +++ b/pkg/excelparse/types.go @@ -3,25 +3,32 @@ package excelparse import "errors" var ( - ErrUnknownFormat = errors.New("unrecognized excel format; supported: 秒账, 领星") - ErrEmptyFile = errors.New("excel file has no data rows") + 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 + ProductName string + Spec string + Color string + ColorNo string + ProductCode string + UnitRolls int64 + StockQuantity string + CostPrice string + SalesPrice string + BatchNo string + YarnRatio string + WarpWeightGM string + WeftWeightGM string + ProductionProcess string + Remark string } type ParseResult struct { - Products []ParsedProduct - ParserName string + Products []ParsedProduct + ParserName string SkippedRows int } diff --git a/rpc/inventory/internal/logic/batch_helpers.go b/rpc/inventory/internal/logic/batch_helpers.go new file mode 100644 index 0000000..3d09e1f --- /dev/null +++ b/rpc/inventory/internal/logic/batch_helpers.go @@ -0,0 +1,140 @@ +package logic + +import ( + "database/sql" + "encoding/json" + "fmt" + "math" + "strconv" + "strings" + + "muyu-apiserver/model" + "muyu-apiserver/rpc/inventory/pb" +) + +func nullString(v string) sql.NullString { + return sql.NullString{String: v, Valid: v != ""} +} + +func nullableJSON(v string) sql.NullString { + v = strings.TrimSpace(v) + return sql.NullString{String: v, Valid: v != ""} +} + +func parseDecimalString(v string) float64 { + n, _ := strconv.ParseFloat(strings.TrimSpace(v), 64) + return n +} + +type yarnRatioPayload struct { + Warp []yarnRatioItem `json:"warp"` + Weft []yarnRatioItem `json:"weft"` +} + +type yarnRatioItem struct { + YarnID string `json:"yarn_id"` + YarnId string `json:"yarnId"` + Ratio float64 `json:"ratio"` +} + +func (i yarnRatioItem) yarnID() string { + if i.YarnID != "" { + return i.YarnID + } + return i.YarnId +} + +func validateProductBatchInput(batch *pb.ProductBatchInput) error { + if batch == nil { + return nil + } + return validateYarnRatio(batch.YarnRatio) +} + +func validateYarnRatio(raw string) error { + raw = strings.TrimSpace(raw) + if raw == "" { + return nil + } + var payload yarnRatioPayload + if err := json.Unmarshal([]byte(raw), &payload); err != nil { + return fmt.Errorf("纱线配比格式无效") + } + if err := validateYarnRatioSide("经线", payload.Warp); err != nil { + return err + } + return validateYarnRatioSide("纬线", payload.Weft) +} + +func validateYarnRatioSide(label string, items []yarnRatioItem) error { + if len(items) == 0 { + return nil + } + total := 0 + for _, item := range items { + if strings.TrimSpace(item.yarnID()) == "" { + return fmt.Errorf("%s纱线不能为空", label) + } + if item.Ratio < 1 || item.Ratio > 10 || math.Trunc(item.Ratio) != item.Ratio { + return fmt.Errorf("%s使用配比必须为 1-10 的整数", label) + } + total += int(item.Ratio) + } + if total != 10 { + return fmt.Errorf("%s配比合计必须为 10,当前为 %d", label, total) + } + return nil +} + +func batchInputToModelFields(batch *pb.ProductBatchInput, target *model.InvProductBatch) error { + if batch == nil { + target.ProductionProcess = nullString(defaultProcess) + return nil + } + if err := validateProductBatchInput(batch); err != nil { + return err + } + target.YarnRatio = nullableJSON(batch.YarnRatio) + target.WarpWeightGM = parseDecimalString(batch.WarpWeightGM) + target.WeftWeightGM = parseDecimalString(batch.WeftWeightGM) + process := strings.TrimSpace(batch.ProductionProcess) + if process == "" { + process = defaultProcess + } + target.ProductionProcess = nullString(process) + target.Remark = nullString(batch.Remark) + return nil +} + +func batchToPb(batch *model.InvProductBatch) *pb.ProductBatchInfo { + return &pb.ProductBatchInfo{ + BatchId: batch.BatchId, + ProductId: batch.ProductId, + BatchNo: batch.BatchNo, + YarnRatio: batch.YarnRatio.String, + WarpWeightGM: fmt.Sprintf("%.4f", batch.WarpWeightGM), + WeftWeightGM: fmt.Sprintf("%.4f", batch.WeftWeightGM), + ProductionProcess: batch.ProductionProcess.String, + Remark: batch.Remark.String, + Status: batch.Status, + CreatedAt: batch.CreatedAt.Format("2006-01-02 15:04:05"), + UpdatedAt: batch.UpdatedAt.Format("2006-01-02 15:04:05"), + } +} + +func productToPb(product *model.InvProduct) *pb.ProductInfo { + return &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"), + ColorNo: product.ColorNo, + ProductCode: product.ProductCode, + } +} diff --git a/rpc/inventory/internal/logic/batch_helpers_test.go b/rpc/inventory/internal/logic/batch_helpers_test.go new file mode 100644 index 0000000..e634368 --- /dev/null +++ b/rpc/inventory/internal/logic/batch_helpers_test.go @@ -0,0 +1,56 @@ +package logic + +import "testing" + +func TestValidateYarnRatio(t *testing.T) { + tests := []struct { + name string + raw string + wantErr bool + }{ + { + name: "empty ratio is valid", + raw: "", + wantErr: false, + }, + { + name: "both sides add up to ten", + raw: `{"warp":[{"yarn_id":"y1","ratio":6},{"yarn_id":"y2","ratio":4}],"weft":[{"yarn_id":"y3","ratio":10}]}`, + wantErr: false, + }, + { + name: "one empty side is valid", + raw: `{"warp":[{"yarn_id":"y1","ratio":10}],"weft":[]}`, + wantErr: false, + }, + { + name: "side with yarn must add up to ten", + raw: `{"warp":[{"yarn_id":"y1","ratio":9}],"weft":[]}`, + wantErr: true, + }, + { + name: "ratio must be integer", + raw: `{"warp":[{"yarn_id":"y1","ratio":9.5}],"weft":[]}`, + wantErr: true, + }, + { + name: "yarn id is required", + raw: `{"warp":[{"ratio":10}],"weft":[]}`, + wantErr: true, + }, + { + name: "invalid json is rejected", + raw: `{warp}`, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validateYarnRatio(tt.raw) + if (err != nil) != tt.wantErr { + t.Fatalf("validateYarnRatio() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/rpc/inventory/internal/logic/createproductbatchlogic.go b/rpc/inventory/internal/logic/createproductbatchlogic.go new file mode 100644 index 0000000..f9f4f87 --- /dev/null +++ b/rpc/inventory/internal/logic/createproductbatchlogic.go @@ -0,0 +1,56 @@ +package logic + +import ( + "context" + "strings" + + "muyu-apiserver/model" + "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 CreateProductBatchLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewCreateProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateProductBatchLogic { + return &CreateProductBatchLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *CreateProductBatchLogic) CreateProductBatch(in *pb.CreateProductBatchReq) (*pb.IdResp, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, in.ProductId) + if err != nil || product.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "product not found") + } + batchNo, err := l.svcCtx.ProductBatchModel.NextBatchNo(l.ctx, tenantId, product.ProductCode) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + if requestedBatchNo := strings.TrimSpace(in.Batch.GetBatchNo()); requestedBatchNo != "" { + batchNo = requestedBatchNo + } + batchId := uid.Generate() + batch := &model.InvProductBatch{ + BatchId: batchId, + TenantId: tenantId, + ProductId: product.ProductId, + BatchNo: batchNo, + Status: 1, + } + if err := batchInputToModelFields(in.Batch, batch); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + if _, err := l.svcCtx.ProductBatchModel.Insert(l.ctx, batch); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &pb.IdResp{Id: batchId}, nil +} diff --git a/rpc/inventory/internal/logic/createproductlogic.go b/rpc/inventory/internal/logic/createproductlogic.go index d300353..036cc77 100644 --- a/rpc/inventory/internal/logic/createproductlogic.go +++ b/rpc/inventory/internal/logic/createproductlogic.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "strconv" + "strings" "muyu-apiserver/model" "muyu-apiserver/pkg/metrics" @@ -35,23 +36,64 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp, tenantId := tenantctx.ExtractTenantId(l.ctx) productId := uid.Generate() salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64) + productName := strings.TrimSpace(in.ProductName) + if productName == "" { + return nil, status.Error(codes.InvalidArgument, "产品名称不能为空") + } + color := normalizeProductColor(in.Color) + colorNo, err := resolveColorNo(l.ctx, l.svcCtx.ProductModel, tenantId, productName, in.ColorNo) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + productCode := strings.ToUpper(strings.TrimSpace(in.ProductCode)) + if productCode == "" { + productCode = generateProductCode(productName, colorNo) + } + if err := ensureProductCodeAvailable(l.ctx, l.svcCtx.ProductModel, tenantId, productCode); err != nil { + return nil, status.Error(codes.AlreadyExists, err.Error()) + } + if err := validateProductBatchInput(in.InitialBatch); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } product := &model.InvProduct{ ProductId: productId, TenantId: tenantId, - ProductName: in.ProductName, + ProductName: productName, ImageUrl: in.ImageUrl, Spec: in.Spec, - Color: in.Color, + Color: color, + ColorNo: colorNo, + ProductCode: productCode, 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) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } + + firstBatchNo := productCode + "-B001" + if batchNo := strings.TrimSpace(in.InitialBatch.GetBatchNo()); batchNo != "" { + firstBatchNo = batchNo + } + + firstBatch := &model.InvProductBatch{ + BatchId: uid.Generate(), + TenantId: tenantId, + ProductId: productId, + BatchNo: firstBatchNo, + Status: 1, + } + if err := batchInputToModelFields(in.InitialBatch, firstBatch); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + if _, err := l.svcCtx.ProductBatchModel.Insert(l.ctx, firstBatch); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + var totalLengthM float64 var totalBolts int @@ -59,12 +101,21 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp, pans := make([]*model.InvProductPan, 0, len(in.Pans)) for i, panInput := range in.Pans { panId := uid.Generate() + batchId := panInput.BatchId + if batchId == "" { + batchId = firstBatch.BatchId + } + if _, err := l.svcCtx.ProductBatchModel.FindOneByProductAndBatchId(l.ctx, tenantId, productId, batchId); err != nil { + return nil, status.Error(codes.InvalidArgument, "批次不存在或不属于该产品") + } pans = append(pans, &model.InvProductPan{ PanId: panId, ProductId: productId, + BatchId: batchId, Name: panInput.Name, Position: panInput.Position, SortOrder: int64(i + 1), + TenantId: tenantId, }) if len(panInput.BoltLengths) > 0 { @@ -76,23 +127,25 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp, BoltId: uid.Generate(), PanId: panId, LengthM: lengthM, + Color: color, SortOrder: int64(j + 1), + TenantId: tenantId, }) } totalBolts += len(panInput.BoltLengths) - if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, panId, "", bolts); err != nil { + if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, panId, tenantId, 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 { + if err := l.svcCtx.PanModel.BulkReplace(l.ctx, productId, tenantId, 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() + metrics.ProductCreatedTotal.WithLabelValues(tenantId, productName, in.Spec, color).Inc() if totalLengthM > 0 { - metrics.InboundLengthMetersTotal.WithLabelValues(tenantId, in.ProductName, in.Color, "create").Add(totalLengthM) + metrics.InboundLengthMetersTotal.WithLabelValues(tenantId, productName, color, "create").Add(totalLengthM) } if totalBolts > 0 { metrics.InboundBoltsTotal.WithLabelValues(tenantId, "create").Add(float64(totalBolts)) diff --git a/rpc/inventory/internal/logic/createyarnlogic.go b/rpc/inventory/internal/logic/createyarnlogic.go new file mode 100644 index 0000000..7d8f9f6 --- /dev/null +++ b/rpc/inventory/internal/logic/createyarnlogic.go @@ -0,0 +1,68 @@ +package logic + +import ( + "context" + "database/sql" + "errors" + "strings" + + "muyu-apiserver/model" + "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 CreateYarnLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewCreateYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateYarnLogic { + return &CreateYarnLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *CreateYarnLogic) CreateYarn(in *pb.CreateYarnReq) (*pb.IdResp, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + yarnName := strings.TrimSpace(in.YarnName) + if yarnName == "" { + return nil, status.Error(codes.InvalidArgument, "纱线名称不能为空") + } + if strings.TrimSpace(in.SupplierId) == "" { + return nil, status.Error(codes.InvalidArgument, "供应商不能为空") + } + supplier, err := l.svcCtx.SupplierModel.FindOneBySupplierId(l.ctx, in.SupplierId) + if err != nil || supplier.TenantId != tenantId { + return nil, status.Error(codes.InvalidArgument, "供应商不存在") + } + + color := normalizeYarnColor(in.Color) + if _, err := l.svcCtx.YarnModel.FindOneByUnique(l.ctx, tenantId, yarnName, color, in.SupplierId); err == nil { + return nil, status.Error(codes.AlreadyExists, "纱线已存在") + } else if !errors.Is(err, model.ErrNotFound) { + return nil, status.Error(codes.Internal, err.Error()) + } + + yarnId := uid.Generate() + yarn := &model.InvYarn{ + YarnId: yarnId, + TenantId: tenantId, + YarnName: yarnName, + Color: color, + WeightGM: parseDecimalString(in.WeightGM), + SupplierId: in.SupplierId, + DyeFactory: normalizeDyeFactory(in.DyeFactory), + ImageUrl: in.ImageUrl, + Remark: sql.NullString{String: in.Remark, Valid: in.Remark != ""}, + Status: 1, + } + if _, err := l.svcCtx.YarnModel.Insert(l.ctx, yarn); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &pb.IdResp{Id: yarnId}, nil +} diff --git a/rpc/inventory/internal/logic/deleteproductbatchlogic.go b/rpc/inventory/internal/logic/deleteproductbatchlogic.go new file mode 100644 index 0000000..acacd72 --- /dev/null +++ b/rpc/inventory/internal/logic/deleteproductbatchlogic.go @@ -0,0 +1,46 @@ +package logic + +import ( + "context" + "strings" + + "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 DeleteProductBatchLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewDeleteProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductBatchLogic { + return &DeleteProductBatchLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *DeleteProductBatchLogic) DeleteProductBatch(in *pb.DeleteProductBatchReq) (*pb.Empty, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + batch, err := l.svcCtx.ProductBatchModel.FindOneByProductAndBatchId(l.ctx, tenantId, in.ProductId, in.BatchId) + if err != nil { + return nil, status.Error(codes.NotFound, "批次不存在") + } + if strings.HasSuffix(batch.BatchNo, "-B001") { + return nil, status.Error(codes.FailedPrecondition, "B001 批次不可删除") + } + count, err := l.svcCtx.PanModel.CountByBatchId(l.ctx, in.BatchId) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + if count > 0 { + return nil, status.Error(codes.FailedPrecondition, "批次已有库存引用,不能删除") + } + if err := l.svcCtx.ProductBatchModel.SoftDeleteByBatchId(l.ctx, in.BatchId); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &pb.Empty{}, nil +} diff --git a/rpc/inventory/internal/logic/deleteyarnlogic.go b/rpc/inventory/internal/logic/deleteyarnlogic.go new file mode 100644 index 0000000..20c8c44 --- /dev/null +++ b/rpc/inventory/internal/logic/deleteyarnlogic.go @@ -0,0 +1,35 @@ +package logic + +import ( + "context" + + "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 DeleteYarnLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewDeleteYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteYarnLogic { + return &DeleteYarnLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *DeleteYarnLogic) DeleteYarn(in *pb.DeleteYarnReq) (*pb.Empty, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + yarn, err := l.svcCtx.YarnModel.FindOneByYarnId(l.ctx, in.YarnId) + if err != nil || yarn.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "纱线不存在") + } + if err := l.svcCtx.YarnModel.SoftDeleteByYarnId(l.ctx, in.YarnId); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &pb.Empty{}, nil +} diff --git a/rpc/inventory/internal/logic/getproductlogic.go b/rpc/inventory/internal/logic/getproductlogic.go index 20e12a1..a96fb11 100644 --- a/rpc/inventory/internal/logic/getproductlogic.go +++ b/rpc/inventory/internal/logic/getproductlogic.go @@ -2,7 +2,6 @@ package logic import ( "context" - "fmt" "muyu-apiserver/rpc/inventory/internal/svc" "muyu-apiserver/rpc/inventory/pb" @@ -32,16 +31,5 @@ func (l *GetProductLogic) GetProduct(in *pb.GetProductReq) (*pb.ProductInfo, err return nil, status.Error(codes.NotFound, "product not found") } - return &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"), - }, nil + return productToPb(product), nil } diff --git a/rpc/inventory/internal/logic/getproducttreelogic.go b/rpc/inventory/internal/logic/getproducttreelogic.go index d8d4fe8..4edf98f 100644 --- a/rpc/inventory/internal/logic/getproducttreelogic.go +++ b/rpc/inventory/internal/logic/getproducttreelogic.go @@ -36,6 +36,14 @@ func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductT if err != nil { return nil, status.Error(codes.Internal, err.Error()) } + batches, err := l.svcCtx.ProductBatchModel.FindByProductId(l.ctx, product.TenantId, in.ProductId) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + batchNoById := make(map[string]string, len(batches)) + for _, b := range batches { + batchNoById[b.BatchId] = b.BatchNo + } var totalBoltCount int64 var totalLengthM float64 @@ -65,6 +73,8 @@ func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductT pbPans = append(pbPans, &pb.PanInfo{ PanId: pan.PanId, ProductId: pan.ProductId, + BatchId: pan.BatchId, + BatchNo: batchNoById[pan.BatchId], Name: pan.Name, Position: pan.Position, SortOrder: pan.SortOrder, @@ -75,18 +85,7 @@ func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductT } 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"), - }, + Product: productToPb(product), Pans: pbPans, TotalPanCount: int64(len(pans)), TotalBoltCount: totalBoltCount, diff --git a/rpc/inventory/internal/logic/getyarnlogic.go b/rpc/inventory/internal/logic/getyarnlogic.go new file mode 100644 index 0000000..a4634b1 --- /dev/null +++ b/rpc/inventory/internal/logic/getyarnlogic.go @@ -0,0 +1,36 @@ +package logic + +import ( + "context" + + "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 GetYarnLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewGetYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetYarnLogic { + return &GetYarnLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *GetYarnLogic) GetYarn(in *pb.GetYarnReq) (*pb.YarnInfo, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + yarn, err := l.svcCtx.YarnModel.FindOneByYarnId(l.ctx, in.YarnId) + if err != nil || yarn.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "纱线不存在") + } + supplierName := "" + if supplier, err := l.svcCtx.SupplierModel.FindOneBySupplierId(l.ctx, yarn.SupplierId); err == nil { + supplierName = supplier.SupplierName + } + return yarnToPb(yarn, supplierName), nil +} diff --git a/rpc/inventory/internal/logic/importproductslogic.go b/rpc/inventory/internal/logic/importproductslogic.go index f4bab8f..9203b60 100644 --- a/rpc/inventory/internal/logic/importproductslogic.go +++ b/rpc/inventory/internal/logic/importproductslogic.go @@ -3,7 +3,7 @@ package logic import ( "context" "database/sql" - "strconv" + "fmt" "strings" "muyu-apiserver/model" @@ -33,33 +33,20 @@ func NewImportProductsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Im } func (l *ImportProductsLogic) ImportProducts(in *pb.ImportProductReq) (*pb.ImportProductResp, error) { - products := make([]*model.InvProduct, 0, len(in.Products)) + totalCount := int64(len(in.Products)) + var successCount int64 + errs := make([]string, 0) + creator := NewCreateProductLogic(l.ctx, l.svcCtx) - for _, p := range in.Products { - salesPrice, _ := strconv.ParseFloat(p.SalesPrice, 64) - - products = append(products, &model.InvProduct{ - ProductId: uid.Generate(), - ProductName: p.ProductName, - ImageUrl: p.ImageUrl, - Spec: p.Spec, - Color: p.Color, - SalesPrice: salesPrice, - Remark: sql.NullString{String: p.Remark, Valid: p.Remark != ""}, - Status: 1, - }) - } - - totalCount := int64(len(products)) - affected, err := l.svcCtx.ProductModel.BulkInsert(l.ctx, products) - - var errorMsg string - successCount := affected - failCount := totalCount - affected - if err != nil { - errorMsg = err.Error() - l.Errorf("bulk insert partial failure: %v", err) + for i, p := range in.Products { + if _, err := creator.CreateProduct(p); err != nil { + errs = append(errs, fmt.Sprintf("第%d行: %v", i+1, err)) + continue + } + successCount++ } + failCount := totalCount - successCount + errorMsg := strings.Join(errs, "; ") importId := uid.Generate() importLog := &model.InvStockImportLog{ @@ -74,7 +61,7 @@ func (l *ImportProductsLogic) ImportProducts(in *pb.ImportProductReq) (*pb.Impor if _, logErr := l.svcCtx.ImportLogModel.Insert(l.ctx, importLog); logErr != nil { l.Errorf("save import log failed: %v", logErr) - if err != nil { + if errorMsg != "" { return nil, status.Error(codes.Internal, strings.Join([]string{errorMsg, logErr.Error()}, "; ")) } return nil, status.Error(codes.Internal, logErr.Error()) @@ -87,9 +74,6 @@ func (l *ImportProductsLogic) ImportProducts(in *pb.ImportProductReq) (*pb.Impor 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{ TotalCount: totalCount, diff --git a/rpc/inventory/internal/logic/listcolordetaillogic.go b/rpc/inventory/internal/logic/listcolordetaillogic.go index ca0c3a1..f9ca53d 100644 --- a/rpc/inventory/internal/logic/listcolordetaillogic.go +++ b/rpc/inventory/internal/logic/listcolordetaillogic.go @@ -40,10 +40,13 @@ func (l *ListColorDetailLogic) ListColorDetail(in *pb.ListColorDetailReq) (*pb.L ProductId: d.ProductId, ProductName: d.ProductName, Color: d.Color, + ColorNo: d.ColorNo, + ProductCode: d.ProductCode, Spec: d.Spec, ImageUrl: d.ImageUrl, PanCount: d.PanCount, BoltCount: d.BoltCount, + BatchCount: d.BatchCount, TotalLengthM: fmt.Sprintf("%.2f", d.TotalLengthM), Locations: d.Locations, SalesPrice: fmt.Sprintf("%.2f", d.SalesPrice), diff --git a/rpc/inventory/internal/logic/listpanslogic.go b/rpc/inventory/internal/logic/listpanslogic.go index f574fb7..b538ce0 100644 --- a/rpc/inventory/internal/logic/listpanslogic.go +++ b/rpc/inventory/internal/logic/listpanslogic.go @@ -27,10 +27,22 @@ func NewListPansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPans } func (l *ListPansLogic) ListPans(in *pb.ListPanReq) (*pb.ListPanResp, 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()) } + batches, err := l.svcCtx.ProductBatchModel.FindByProductId(l.ctx, product.TenantId, in.ProductId) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + batchNoById := make(map[string]string, len(batches)) + for _, b := range batches { + batchNoById[b.BatchId] = b.BatchNo + } pbPans := make([]*pb.PanInfo, 0, len(pans)) for _, pan := range pans { @@ -52,6 +64,8 @@ func (l *ListPansLogic) ListPans(in *pb.ListPanReq) (*pb.ListPanResp, error) { pbPans = append(pbPans, &pb.PanInfo{ PanId: pan.PanId, ProductId: pan.ProductId, + BatchId: pan.BatchId, + BatchNo: batchNoById[pan.BatchId], Name: pan.Name, Position: pan.Position, SortOrder: pan.SortOrder, diff --git a/rpc/inventory/internal/logic/listpanviewlogic.go b/rpc/inventory/internal/logic/listpanviewlogic.go index 588e946..c19890d 100644 --- a/rpc/inventory/internal/logic/listpanviewlogic.go +++ b/rpc/inventory/internal/logic/listpanviewlogic.go @@ -39,6 +39,8 @@ func (l *ListPanViewLogic) ListPanView(in *pb.ListPanViewReq) (*pb.ListPanViewRe pbList = append(pbList, &pb.PanListItem{ PanId: item.PanId, ProductId: item.ProductId, + BatchId: item.BatchId, + BatchNo: item.BatchNo, Name: item.Name, Position: item.Position, ProductName: item.ProductName, diff --git a/rpc/inventory/internal/logic/listproductbatchlogic.go b/rpc/inventory/internal/logic/listproductbatchlogic.go new file mode 100644 index 0000000..e17915e --- /dev/null +++ b/rpc/inventory/internal/logic/listproductbatchlogic.go @@ -0,0 +1,40 @@ +package logic + +import ( + "context" + + "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 ListProductBatchLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewListProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListProductBatchLogic { + return &ListProductBatchLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *ListProductBatchLogic) ListProductBatch(in *pb.ListProductBatchReq) (*pb.ListProductBatchResp, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, in.ProductId) + if err != nil || product.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "product not found") + } + list, err := l.svcCtx.ProductBatchModel.FindByProductId(l.ctx, tenantId, in.ProductId) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + pbList := make([]*pb.ProductBatchInfo, 0, len(list)) + for _, b := range list { + pbList = append(pbList, batchToPb(b)) + } + return &pb.ListProductBatchResp{List: pbList}, nil +} diff --git a/rpc/inventory/internal/logic/listproductlogic.go b/rpc/inventory/internal/logic/listproductlogic.go index 59b4ae6..1d1ab36 100644 --- a/rpc/inventory/internal/logic/listproductlogic.go +++ b/rpc/inventory/internal/logic/listproductlogic.go @@ -2,7 +2,6 @@ package logic import ( "context" - "fmt" "muyu-apiserver/pkg/tenantctx" "muyu-apiserver/rpc/inventory/internal/svc" @@ -29,25 +28,14 @@ func NewListProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListP func (l *ListProductLogic) ListProduct(in *pb.ListProductReq) (*pb.ListProductResp, error) { 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.Status) + list, total, err := l.svcCtx.ProductModel.FindList(l.ctx, tenantId, in.Page, in.PageSize, in.ProductName, in.Spec, in.Color, in.ColorNo, in.ProductCode, in.Status) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } pbList := make([]*pb.ProductInfo, 0, len(list)) for _, p := range list { - pbList = append(pbList, &pb.ProductInfo{ - ProductId: p.ProductId, - ProductName: p.ProductName, - ImageUrl: p.ImageUrl, - Spec: p.Spec, - Color: p.Color, - 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"), - }) + pbList = append(pbList, productToPb(p)) } return &pb.ListProductResp{ diff --git a/rpc/inventory/internal/logic/listyarnlogic.go b/rpc/inventory/internal/logic/listyarnlogic.go new file mode 100644 index 0000000..3db058c --- /dev/null +++ b/rpc/inventory/internal/logic/listyarnlogic.go @@ -0,0 +1,42 @@ +package logic + +import ( + "context" + + "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 ListYarnLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewListYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListYarnLogic { + return &ListYarnLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *ListYarnLogic) ListYarn(in *pb.ListYarnReq) (*pb.ListYarnResp, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + list, total, err := l.svcCtx.YarnModel.FindList(l.ctx, tenantId, in.Page, in.PageSize, in.YarnName, in.SupplierId, in.Status) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + pbList := make([]*pb.YarnInfo, 0, len(list)) + for _, y := range list { + supplierName := "" + if supplier, err := l.svcCtx.SupplierModel.FindOneBySupplierId(l.ctx, y.SupplierId); err == nil { + supplierName = supplier.SupplierName + } + pbList = append(pbList, yarnToPb(y, supplierName)) + } + + return &pb.ListYarnResp{Total: total, List: pbList}, nil +} diff --git a/rpc/inventory/internal/logic/productcode.go b/rpc/inventory/internal/logic/productcode.go new file mode 100644 index 0000000..15f0ca0 --- /dev/null +++ b/rpc/inventory/internal/logic/productcode.go @@ -0,0 +1,101 @@ +package logic + +import ( + "context" + "errors" + "strings" + "unicode" + + "muyu-apiserver/model" + + "github.com/mozillazg/go-pinyin" +) + +const ( + defaultProductColor = "本色" + defaultYarnColor = "原纱本色" + defaultDyeFactory = "无" + defaultProcess = "无" +) + +func normalizeColorNo(colorNo string) string { + return strings.ToUpper(strings.TrimSpace(colorNo)) +} + +func normalizeProductColor(color string) string { + color = strings.TrimSpace(color) + if color == "" { + return defaultProductColor + } + return color +} + +func normalizeYarnColor(color string) string { + color = strings.TrimSpace(color) + if color == "" { + return defaultYarnColor + } + return color +} + +func normalizeDyeFactory(factory string) string { + factory = strings.TrimSpace(factory) + if factory == "" { + return defaultDyeFactory + } + return factory +} + +func productNameCodePrefix(productName string) string { + args := pinyin.NewArgs() + args.Style = pinyin.Normal + var b strings.Builder + + for _, r := range productName { + switch { + case r >= 'a' && r <= 'z': + b.WriteRune(unicode.ToUpper(r)) + case r >= 'A' && r <= 'Z': + b.WriteRune(r) + case r >= '0' && r <= '9': + b.WriteRune(r) + case unicode.Is(unicode.Han, r): + py := pinyin.Pinyin(string(r), args) + if len(py) > 0 && len(py[0]) > 0 && py[0][0] != "" { + first := []rune(py[0][0]) + if len(first) > 0 { + b.WriteRune(unicode.ToUpper(first[0])) + } + } + } + } + + code := b.String() + if code == "" { + return "P" + } + return code +} + +func generateProductCode(productName, colorNo string) string { + return productNameCodePrefix(productName) + normalizeColorNo(colorNo) +} + +func resolveColorNo(ctx context.Context, productModel model.InvProductModel, tenantId, productName, colorNo string) (string, error) { + colorNo = normalizeColorNo(colorNo) + if colorNo != "" { + return colorNo, nil + } + return productModel.NextColorNo(ctx, tenantId, productName) +} + +func ensureProductCodeAvailable(ctx context.Context, productModel model.InvProductModel, tenantId, productCode string) error { + _, err := productModel.FindOneByTenantProductCode(ctx, tenantId, productCode) + if err == nil { + return errors.New("产品码已存在") + } + if errors.Is(err, model.ErrNotFound) { + return nil + } + return err +} diff --git a/rpc/inventory/internal/logic/saveboltslogic.go b/rpc/inventory/internal/logic/saveboltslogic.go index 80c3fd1..2b5982b 100644 --- a/rpc/inventory/internal/logic/saveboltslogic.go +++ b/rpc/inventory/internal/logic/saveboltslogic.go @@ -32,6 +32,14 @@ func NewSaveBoltsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveBol func (l *SaveBoltsLogic) SaveBolts(in *pb.SaveBoltsReq) (*pb.Empty, error) { tenantId := tenantctx.ExtractTenantId(l.ctx) + pan, err := l.svcCtx.PanModel.FindOneByPanId(l.ctx, in.PanId) + if err != nil || pan.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "pan not found") + } + product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, pan.ProductId) + if err != nil || product.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "product not found") + } var totalLengthM float64 bolts := make([]*model.InvProductBolt, 0, len(in.Lengths)) @@ -42,7 +50,9 @@ func (l *SaveBoltsLogic) SaveBolts(in *pb.SaveBoltsReq) (*pb.Empty, error) { BoltId: uid.Generate(), PanId: in.PanId, LengthM: lengthM, + Color: product.Color, SortOrder: int64(i + 1), + TenantId: tenantId, }) } diff --git a/rpc/inventory/internal/logic/savepanslogic.go b/rpc/inventory/internal/logic/savepanslogic.go index e3e07bb..8c518c4 100644 --- a/rpc/inventory/internal/logic/savepanslogic.go +++ b/rpc/inventory/internal/logic/savepanslogic.go @@ -2,6 +2,7 @@ package logic import ( "context" + "errors" "strconv" "muyu-apiserver/model" @@ -33,19 +34,53 @@ func NewSavePansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SavePans 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()) + product, err := l.svcCtx.ProductModel.FindOneByProductId(l.ctx, in.ProductId) + if err != nil || product.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "product not found") + } + + defaultBatch, err := l.svcCtx.ProductBatchModel.FindLatestByProductId(l.ctx, tenantId, in.ProductId) + if err != nil { + if !errors.Is(err, model.ErrNotFound) { + return nil, status.Error(codes.Internal, err.Error()) + } + defaultBatch = &model.InvProductBatch{ + BatchId: uid.Generate(), + TenantId: tenantId, + ProductId: in.ProductId, + BatchNo: product.ProductCode + "-B001", + Status: 1, + } + if err := batchInputToModelFields(nil, defaultBatch); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + if _, err := l.svcCtx.ProductBatchModel.Insert(l.ctx, defaultBatch); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } } var totalLengthM float64 var totalBolts int + type panBoltSet struct { + panId string + bolts []*model.InvProductBolt + } + boltsByPan := make([]panBoltSet, 0, len(in.Pans)) pans := make([]*model.InvProductPan, 0, len(in.Pans)) for i, panInput := range in.Pans { panId := uid.Generate() + batchId := panInput.BatchId + if batchId == "" { + batchId = defaultBatch.BatchId + } + if _, err := l.svcCtx.ProductBatchModel.FindOneByProductAndBatchId(l.ctx, tenantId, in.ProductId, batchId); err != nil { + return nil, status.Error(codes.InvalidArgument, "批次不存在或不属于该产品") + } pans = append(pans, &model.InvProductPan{ PanId: panId, ProductId: in.ProductId, + BatchId: batchId, Name: panInput.Name, Position: panInput.Position, SortOrder: int64(i + 1), @@ -61,20 +96,30 @@ func (l *SavePansLogic) SavePans(in *pb.SavePansReq) (*pb.Empty, error) { BoltId: uid.Generate(), PanId: panId, LengthM: lengthM, + Color: product.Color, SortOrder: int64(j + 1), + TenantId: tenantId, }) } 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()) - } + boltsByPan = append(boltsByPan, panBoltSet{panId: panId, bolts: bolts}) } } + if err := l.svcCtx.BoltModel.DeleteByProductId(l.ctx, in.ProductId); 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()) } + for _, item := range boltsByPan { + if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, item.panId, tenantId, item.bolts); 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) diff --git a/rpc/inventory/internal/logic/updateproductbatchlogic.go b/rpc/inventory/internal/logic/updateproductbatchlogic.go new file mode 100644 index 0000000..2a083d8 --- /dev/null +++ b/rpc/inventory/internal/logic/updateproductbatchlogic.go @@ -0,0 +1,43 @@ +package logic + +import ( + "context" + + "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 UpdateProductBatchLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewUpdateProductBatchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateProductBatchLogic { + return &UpdateProductBatchLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *UpdateProductBatchLogic) UpdateProductBatch(in *pb.UpdateProductBatchReq) (*pb.Empty, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + batch, err := l.svcCtx.ProductBatchModel.FindOneByProductAndBatchId(l.ctx, tenantId, in.ProductId, in.BatchId) + if err != nil { + return nil, status.Error(codes.NotFound, "批次不存在") + } + if err := batchInputToModelFields(in.Batch, batch); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + if in.Status == 0 { + batch.Status = 0 + } else { + batch.Status = 1 + } + if err := l.svcCtx.ProductBatchModel.Update(l.ctx, batch); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &pb.Empty{}, nil +} diff --git a/rpc/inventory/internal/logic/updateproductlogic.go b/rpc/inventory/internal/logic/updateproductlogic.go index 0dc2df9..fbf05fc 100644 --- a/rpc/inventory/internal/logic/updateproductlogic.go +++ b/rpc/inventory/internal/logic/updateproductlogic.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "strconv" + "strings" "muyu-apiserver/rpc/inventory/internal/svc" "muyu-apiserver/rpc/inventory/pb" @@ -35,10 +36,18 @@ func (l *UpdateProductLogic) UpdateProduct(in *pb.UpdateProductReq) (*pb.Empty, salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64) - product.ProductName = in.ProductName + productName := strings.TrimSpace(in.ProductName) + if productName == "" { + return nil, status.Error(codes.InvalidArgument, "产品名称不能为空") + } + + product.ProductName = productName product.ImageUrl = in.ImageUrl product.Spec = in.Spec - product.Color = in.Color + product.Color = normalizeProductColor(in.Color) + if strings.TrimSpace(in.ColorNo) != "" { + product.ColorNo = normalizeColorNo(in.ColorNo) + } product.SalesPrice = salesPrice product.Remark = sql.NullString{String: in.Remark, Valid: in.Remark != ""} diff --git a/rpc/inventory/internal/logic/updateyarnlogic.go b/rpc/inventory/internal/logic/updateyarnlogic.go new file mode 100644 index 0000000..bacac6d --- /dev/null +++ b/rpc/inventory/internal/logic/updateyarnlogic.go @@ -0,0 +1,62 @@ +package logic + +import ( + "context" + "database/sql" + "strings" + + "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 UpdateYarnLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewUpdateYarnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateYarnLogic { + return &UpdateYarnLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} +} + +func (l *UpdateYarnLogic) UpdateYarn(in *pb.UpdateYarnReq) (*pb.Empty, error) { + tenantId := tenantctx.ExtractTenantId(l.ctx) + yarn, err := l.svcCtx.YarnModel.FindOneByYarnId(l.ctx, in.YarnId) + if err != nil || yarn.TenantId != tenantId { + return nil, status.Error(codes.NotFound, "纱线不存在") + } + yarnName := strings.TrimSpace(in.YarnName) + if yarnName == "" { + return nil, status.Error(codes.InvalidArgument, "纱线名称不能为空") + } + if strings.TrimSpace(in.SupplierId) == "" { + return nil, status.Error(codes.InvalidArgument, "供应商不能为空") + } + supplier, err := l.svcCtx.SupplierModel.FindOneBySupplierId(l.ctx, in.SupplierId) + if err != nil || supplier.TenantId != tenantId { + return nil, status.Error(codes.InvalidArgument, "供应商不存在") + } + + yarn.YarnName = yarnName + yarn.Color = normalizeYarnColor(in.Color) + yarn.WeightGM = parseDecimalString(in.WeightGM) + yarn.SupplierId = in.SupplierId + yarn.DyeFactory = normalizeDyeFactory(in.DyeFactory) + yarn.ImageUrl = in.ImageUrl + yarn.Remark = sql.NullString{String: in.Remark, Valid: in.Remark != ""} + if in.Status == 0 { + yarn.Status = 0 + } else { + yarn.Status = 1 + } + + if err := l.svcCtx.YarnModel.Update(l.ctx, yarn); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &pb.Empty{}, nil +} diff --git a/rpc/inventory/internal/logic/yarn_helpers.go b/rpc/inventory/internal/logic/yarn_helpers.go new file mode 100644 index 0000000..35dd4f9 --- /dev/null +++ b/rpc/inventory/internal/logic/yarn_helpers.go @@ -0,0 +1,25 @@ +package logic + +import ( + "fmt" + + "muyu-apiserver/model" + "muyu-apiserver/rpc/inventory/pb" +) + +func yarnToPb(yarn *model.InvYarn, supplierName string) *pb.YarnInfo { + return &pb.YarnInfo{ + YarnId: yarn.YarnId, + YarnName: yarn.YarnName, + Color: yarn.Color, + WeightGM: fmt.Sprintf("%.4f", yarn.WeightGM), + SupplierId: yarn.SupplierId, + SupplierName: supplierName, + DyeFactory: yarn.DyeFactory, + ImageUrl: yarn.ImageUrl, + Remark: yarn.Remark.String, + Status: yarn.Status, + CreatedAt: yarn.CreatedAt.Format("2006-01-02 15:04:05"), + UpdatedAt: yarn.UpdatedAt.Format("2006-01-02 15:04:05"), + } +} diff --git a/rpc/inventory/internal/server/inventoryserviceserver.go b/rpc/inventory/internal/server/inventoryserviceserver.go index 75043a4..438b57d 100644 --- a/rpc/inventory/internal/server/inventoryserviceserver.go +++ b/rpc/inventory/internal/server/inventoryserviceserver.go @@ -67,6 +67,53 @@ func (s *InventoryServiceServer) ListColorDetail(ctx context.Context, in *pb.Lis return l.ListColorDetail(in) } +// Yarn CRUD +func (s *InventoryServiceServer) CreateYarn(ctx context.Context, in *pb.CreateYarnReq) (*pb.IdResp, error) { + l := logic.NewCreateYarnLogic(ctx, s.svcCtx) + return l.CreateYarn(in) +} + +func (s *InventoryServiceServer) UpdateYarn(ctx context.Context, in *pb.UpdateYarnReq) (*pb.Empty, error) { + l := logic.NewUpdateYarnLogic(ctx, s.svcCtx) + return l.UpdateYarn(in) +} + +func (s *InventoryServiceServer) DeleteYarn(ctx context.Context, in *pb.DeleteYarnReq) (*pb.Empty, error) { + l := logic.NewDeleteYarnLogic(ctx, s.svcCtx) + return l.DeleteYarn(in) +} + +func (s *InventoryServiceServer) GetYarn(ctx context.Context, in *pb.GetYarnReq) (*pb.YarnInfo, error) { + l := logic.NewGetYarnLogic(ctx, s.svcCtx) + return l.GetYarn(in) +} + +func (s *InventoryServiceServer) ListYarn(ctx context.Context, in *pb.ListYarnReq) (*pb.ListYarnResp, error) { + l := logic.NewListYarnLogic(ctx, s.svcCtx) + return l.ListYarn(in) +} + +// Product Batch CRUD +func (s *InventoryServiceServer) CreateProductBatch(ctx context.Context, in *pb.CreateProductBatchReq) (*pb.IdResp, error) { + l := logic.NewCreateProductBatchLogic(ctx, s.svcCtx) + return l.CreateProductBatch(in) +} + +func (s *InventoryServiceServer) UpdateProductBatch(ctx context.Context, in *pb.UpdateProductBatchReq) (*pb.Empty, error) { + l := logic.NewUpdateProductBatchLogic(ctx, s.svcCtx) + return l.UpdateProductBatch(in) +} + +func (s *InventoryServiceServer) DeleteProductBatch(ctx context.Context, in *pb.DeleteProductBatchReq) (*pb.Empty, error) { + l := logic.NewDeleteProductBatchLogic(ctx, s.svcCtx) + return l.DeleteProductBatch(in) +} + +func (s *InventoryServiceServer) ListProductBatch(ctx context.Context, in *pb.ListProductBatchReq) (*pb.ListProductBatchResp, error) { + l := logic.NewListProductBatchLogic(ctx, s.svcCtx) + return l.ListProductBatch(in) +} + // Pan / Bolt list views func (s *InventoryServiceServer) ListPanView(ctx context.Context, in *pb.ListPanViewReq) (*pb.ListPanViewResp, error) { l := logic.NewListPanViewLogic(ctx, s.svcCtx) diff --git a/rpc/inventory/internal/svc/servicecontext.go b/rpc/inventory/internal/svc/servicecontext.go index a38e99f..eb92f5a 100644 --- a/rpc/inventory/internal/svc/servicecontext.go +++ b/rpc/inventory/internal/svc/servicecontext.go @@ -10,8 +10,11 @@ import ( type ServiceContext struct { Config config.Config ProductModel model.InvProductModel + YarnModel model.InvYarnModel + ProductBatchModel model.InvProductBatchModel PanModel model.InvProductPanModel BoltModel model.InvProductBoltModel + SupplierModel model.PurSupplierModel ImportLogModel model.InvStockImportLogModel StockCheckModel model.InvStockCheckModel CheckDetailModel model.InvStockCheckDetailModel @@ -24,8 +27,11 @@ func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ Config: c, ProductModel: model.NewInvProductModel(conn, c.Cache), + YarnModel: model.NewInvYarnModel(conn), + ProductBatchModel: model.NewInvProductBatchModel(conn), PanModel: model.NewInvProductPanModel(conn), BoltModel: model.NewInvProductBoltModel(conn), + SupplierModel: model.NewPurSupplierModel(conn, c.Cache), ImportLogModel: model.NewInvStockImportLogModel(conn, c.Cache), StockCheckModel: model.NewInvStockCheckModel(conn, c.Cache), CheckDetailModel: model.NewInvStockCheckDetailModel(conn, c.Cache), diff --git a/rpc/inventory/inventory.proto b/rpc/inventory/inventory.proto index f81bcf1..53e2c97 100644 --- a/rpc/inventory/inventory.proto +++ b/rpc/inventory/inventory.proto @@ -17,6 +17,8 @@ message ProductInfo { int64 status = 8; string created_at = 9; string updated_at = 10; + string color_no = 11; + string product_code = 12; } message CreateProductReq { @@ -27,6 +29,9 @@ message CreateProductReq { string sales_price = 5; string remark = 6; repeated PanInput pans = 7; + string color_no = 8; + ProductBatchInput initial_batch = 9; + string product_code = 10; } message UpdateProductReq { @@ -37,6 +42,7 @@ message UpdateProductReq { string color = 5; string sales_price = 6; string remark = 7; + string color_no = 8; } message DeleteProductReq { @@ -54,6 +60,8 @@ message ListProductReq { string spec = 4; string color = 5; int64 status = 6; + string color_no = 7; + string product_code = 8; } message ListProductResp { @@ -72,12 +80,15 @@ message PanInfo { repeated BoltInfo bolts = 6; int64 bolt_count = 7; string total_length = 8; + string batch_id = 9; + string batch_no = 10; } message PanInput { string name = 1; string position = 2; repeated string bolt_lengths = 3; + string batch_id = 4; } message ListPanReq { @@ -157,6 +168,9 @@ message ColorDetailItem { string total_length_m = 8; string locations = 9; string sales_price = 10; + string color_no = 11; + string product_code = 12; + int64 batch_count = 13; } message ListColorDetailReq { @@ -178,6 +192,8 @@ message PanListItem { string colors = 6; // aggregated from bolt.color, no spec int64 bolt_count = 7; string total_length_m = 8; + string batch_id = 9; + string batch_no = 10; } message ListPanViewReq { @@ -242,6 +258,116 @@ message ListImportLogResp { repeated ImportLogInfo list = 2; } +// ==================== Yarn ==================== + +message YarnInfo { + string yarn_id = 1; + string yarn_name = 2; + string color = 3; + string weight_g_m = 4; + string supplier_id = 5; + string supplier_name = 6; + string dye_factory = 7; + string image_url = 8; + string remark = 9; + int64 status = 10; + string created_at = 11; + string updated_at = 12; +} + +message CreateYarnReq { + string yarn_name = 1; + string color = 2; + string weight_g_m = 3; + string supplier_id = 4; + string dye_factory = 5; + string image_url = 6; + string remark = 7; +} + +message UpdateYarnReq { + string yarn_id = 1; + string yarn_name = 2; + string color = 3; + string weight_g_m = 4; + string supplier_id = 5; + string dye_factory = 6; + string image_url = 7; + string remark = 8; + int64 status = 9; +} + +message DeleteYarnReq { + string yarn_id = 1; +} + +message GetYarnReq { + string yarn_id = 1; +} + +message ListYarnReq { + int64 page = 1; + int64 page_size = 2; + string yarn_name = 3; + string supplier_id = 4; + int64 status = 5; +} + +message ListYarnResp { + int64 total = 1; + repeated YarnInfo list = 2; +} + +// ==================== Product Batch ==================== + +message ProductBatchInput { + string yarn_ratio = 1; + string warp_weight_g_m = 2; + string weft_weight_g_m = 3; + string production_process = 4; + string remark = 5; + string batch_no = 6; +} + +message ProductBatchInfo { + string batch_id = 1; + string product_id = 2; + string batch_no = 3; + string yarn_ratio = 4; + string warp_weight_g_m = 5; + string weft_weight_g_m = 6; + string production_process = 7; + string remark = 8; + int64 status = 9; + string created_at = 10; + string updated_at = 11; +} + +message CreateProductBatchReq { + string product_id = 1; + ProductBatchInput batch = 2; +} + +message UpdateProductBatchReq { + string product_id = 1; + string batch_id = 2; + ProductBatchInput batch = 3; + int64 status = 4; +} + +message DeleteProductBatchReq { + string product_id = 1; + string batch_id = 2; +} + +message ListProductBatchReq { + string product_id = 1; +} + +message ListProductBatchResp { + repeated ProductBatchInfo list = 1; +} + message ImportLogInfo { string import_id = 1; string file_name = 2; @@ -440,6 +566,19 @@ service InventoryService { // Color Detail (panel 2) rpc ListColorDetail(ListColorDetailReq) returns (ListColorDetailResp); + // Yarn CRUD + rpc CreateYarn(CreateYarnReq) returns (IdResp); + rpc UpdateYarn(UpdateYarnReq) returns (Empty); + rpc DeleteYarn(DeleteYarnReq) returns (Empty); + rpc GetYarn(GetYarnReq) returns (YarnInfo); + rpc ListYarn(ListYarnReq) returns (ListYarnResp); + + // Product Batch CRUD + rpc CreateProductBatch(CreateProductBatchReq) returns (IdResp); + rpc UpdateProductBatch(UpdateProductBatchReq) returns (Empty); + rpc DeleteProductBatch(DeleteProductBatchReq) returns (Empty); + rpc ListProductBatch(ListProductBatchReq) returns (ListProductBatchResp); + // Pan / Bolt list views (dimension panels) rpc ListPanView(ListPanViewReq) returns (ListPanViewResp); rpc ListBoltView(ListBoltViewReq) returns (ListBoltViewResp); diff --git a/rpc/inventory/inventoryservice/inventoryservice.go b/rpc/inventory/inventoryservice/inventoryservice.go index 2407740..c718b17 100644 --- a/rpc/inventory/inventoryservice/inventoryservice.go +++ b/rpc/inventory/inventoryservice/inventoryservice.go @@ -20,13 +20,18 @@ type ( ColorDetailItem = pb.ColorDetailItem ConfirmStockCheckReq = pb.ConfirmStockCheckReq CreateProductReq = pb.CreateProductReq + CreateProductBatchReq = pb.CreateProductBatchReq CreateStockAdjustReq = pb.CreateStockAdjustReq CreateStockCheckReq = pb.CreateStockCheckReq + CreateYarnReq = pb.CreateYarnReq + DeleteProductBatchReq = pb.DeleteProductBatchReq DeleteProductReq = pb.DeleteProductReq + DeleteYarnReq = pb.DeleteYarnReq Empty = pb.Empty GetProductReq = pb.GetProductReq GetStockAdjustReq = pb.GetStockAdjustReq GetStockCheckReq = pb.GetStockCheckReq + GetYarnReq = pb.GetYarnReq IdResp = pb.IdResp ImportLogInfo = pb.ImportLogInfo ImportProductReq = pb.ImportProductReq @@ -44,6 +49,8 @@ type ( ListImportLogResp = pb.ListImportLogResp ListPanReq = pb.ListPanReq ListPanResp = pb.ListPanResp + ListProductBatchReq = pb.ListProductBatchReq + ListProductBatchResp = pb.ListProductBatchResp ListProductReq = pb.ListProductReq ListProductResp = pb.ListProductResp ListProductSummaryReq = pb.ListProductSummaryReq @@ -52,8 +59,12 @@ type ( ListStockAdjustResp = pb.ListStockAdjustResp ListStockCheckReq = pb.ListStockCheckReq ListStockCheckResp = pb.ListStockCheckResp + ListYarnReq = pb.ListYarnReq + ListYarnResp = pb.ListYarnResp PanInfo = pb.PanInfo PanInput = pb.PanInput + ProductBatchInfo = pb.ProductBatchInfo + ProductBatchInput = pb.ProductBatchInput ProductInfo = pb.ProductInfo ProductSummaryItem = pb.ProductSummaryItem ProductTreeResp = pb.ProductTreeResp @@ -70,8 +81,11 @@ type ( StockGroupResp = pb.StockGroupResp StockSummaryReq = pb.StockSummaryReq StockSummaryResp = pb.StockSummaryResp + UpdateProductBatchReq = pb.UpdateProductBatchReq UpdateProductReq = pb.UpdateProductReq UpdateStockCheckReq = pb.UpdateStockCheckReq + UpdateYarnReq = pb.UpdateYarnReq + YarnInfo = pb.YarnInfo InventoryService interface { // Product CRUD @@ -86,6 +100,17 @@ type ( 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) + // Yarn CRUD + CreateYarn(ctx context.Context, in *CreateYarnReq, opts ...grpc.CallOption) (*IdResp, error) + UpdateYarn(ctx context.Context, in *UpdateYarnReq, opts ...grpc.CallOption) (*Empty, error) + DeleteYarn(ctx context.Context, in *DeleteYarnReq, opts ...grpc.CallOption) (*Empty, error) + GetYarn(ctx context.Context, in *GetYarnReq, opts ...grpc.CallOption) (*YarnInfo, error) + ListYarn(ctx context.Context, in *ListYarnReq, opts ...grpc.CallOption) (*ListYarnResp, error) + // Product Batch CRUD + CreateProductBatch(ctx context.Context, in *CreateProductBatchReq, opts ...grpc.CallOption) (*IdResp, error) + UpdateProductBatch(ctx context.Context, in *UpdateProductBatchReq, opts ...grpc.CallOption) (*Empty, error) + DeleteProductBatch(ctx context.Context, in *DeleteProductBatchReq, opts ...grpc.CallOption) (*Empty, error) + ListProductBatch(ctx context.Context, in *ListProductBatchReq, opts ...grpc.CallOption) (*ListProductBatchResp, 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) @@ -166,6 +191,51 @@ func (m *defaultInventoryService) ListColorDetail(ctx context.Context, in *ListC return client.ListColorDetail(ctx, in, opts...) } +func (m *defaultInventoryService) CreateYarn(ctx context.Context, in *CreateYarnReq, opts ...grpc.CallOption) (*IdResp, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.CreateYarn(ctx, in, opts...) +} + +func (m *defaultInventoryService) UpdateYarn(ctx context.Context, in *UpdateYarnReq, opts ...grpc.CallOption) (*Empty, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.UpdateYarn(ctx, in, opts...) +} + +func (m *defaultInventoryService) DeleteYarn(ctx context.Context, in *DeleteYarnReq, opts ...grpc.CallOption) (*Empty, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.DeleteYarn(ctx, in, opts...) +} + +func (m *defaultInventoryService) GetYarn(ctx context.Context, in *GetYarnReq, opts ...grpc.CallOption) (*YarnInfo, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.GetYarn(ctx, in, opts...) +} + +func (m *defaultInventoryService) ListYarn(ctx context.Context, in *ListYarnReq, opts ...grpc.CallOption) (*ListYarnResp, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.ListYarn(ctx, in, opts...) +} + +func (m *defaultInventoryService) CreateProductBatch(ctx context.Context, in *CreateProductBatchReq, opts ...grpc.CallOption) (*IdResp, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.CreateProductBatch(ctx, in, opts...) +} + +func (m *defaultInventoryService) UpdateProductBatch(ctx context.Context, in *UpdateProductBatchReq, opts ...grpc.CallOption) (*Empty, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.UpdateProductBatch(ctx, in, opts...) +} + +func (m *defaultInventoryService) DeleteProductBatch(ctx context.Context, in *DeleteProductBatchReq, opts ...grpc.CallOption) (*Empty, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.DeleteProductBatch(ctx, in, opts...) +} + +func (m *defaultInventoryService) ListProductBatch(ctx context.Context, in *ListProductBatchReq, opts ...grpc.CallOption) (*ListProductBatchResp, error) { + client := pb.NewInventoryServiceClient(m.cli.Conn()) + return client.ListProductBatch(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...) diff --git a/rpc/inventory/pb/inventory.pb.go b/rpc/inventory/pb/inventory.pb.go index e838666..0b63c68 100644 --- a/rpc/inventory/pb/inventory.pb.go +++ b/rpc/inventory/pb/inventory.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.3 +// protoc v7.34.1 // source: inventory.proto package pb @@ -33,6 +33,8 @@ type ProductInfo struct { Status int64 `protobuf:"varint,8,opt,name=status,proto3" json:"status,omitempty"` CreatedAt string `protobuf:"bytes,9,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` UpdatedAt string `protobuf:"bytes,10,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + ColorNo string `protobuf:"bytes,11,opt,name=color_no,json=colorNo,proto3" json:"color_no,omitempty"` + ProductCode string `protobuf:"bytes,12,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -137,6 +139,20 @@ func (x *ProductInfo) GetUpdatedAt() string { return "" } +func (x *ProductInfo) GetColorNo() string { + if x != nil { + return x.ColorNo + } + return "" +} + +func (x *ProductInfo) GetProductCode() string { + if x != nil { + return x.ProductCode + } + return "" +} + type CreateProductReq struct { state protoimpl.MessageState `protogen:"open.v1"` ProductName string `protobuf:"bytes,1,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` @@ -146,6 +162,9 @@ type CreateProductReq struct { SalesPrice string `protobuf:"bytes,5,opt,name=sales_price,json=salesPrice,proto3" json:"sales_price,omitempty"` Remark string `protobuf:"bytes,6,opt,name=remark,proto3" json:"remark,omitempty"` Pans []*PanInput `protobuf:"bytes,7,rep,name=pans,proto3" json:"pans,omitempty"` + ColorNo string `protobuf:"bytes,8,opt,name=color_no,json=colorNo,proto3" json:"color_no,omitempty"` + InitialBatch *ProductBatchInput `protobuf:"bytes,9,opt,name=initial_batch,json=initialBatch,proto3" json:"initial_batch,omitempty"` + ProductCode string `protobuf:"bytes,10,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -229,6 +248,27 @@ func (x *CreateProductReq) GetPans() []*PanInput { return nil } +func (x *CreateProductReq) GetColorNo() string { + if x != nil { + return x.ColorNo + } + return "" +} + +func (x *CreateProductReq) GetInitialBatch() *ProductBatchInput { + if x != nil { + return x.InitialBatch + } + return nil +} + +func (x *CreateProductReq) GetProductCode() string { + if x != nil { + return x.ProductCode + } + return "" +} + type UpdateProductReq struct { state protoimpl.MessageState `protogen:"open.v1"` ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` @@ -238,6 +278,7 @@ type UpdateProductReq struct { Color string `protobuf:"bytes,5,opt,name=color,proto3" json:"color,omitempty"` SalesPrice string `protobuf:"bytes,6,opt,name=sales_price,json=salesPrice,proto3" json:"sales_price,omitempty"` Remark string `protobuf:"bytes,7,opt,name=remark,proto3" json:"remark,omitempty"` + ColorNo string `protobuf:"bytes,8,opt,name=color_no,json=colorNo,proto3" json:"color_no,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -321,6 +362,13 @@ func (x *UpdateProductReq) GetRemark() string { return "" } +func (x *UpdateProductReq) GetColorNo() string { + if x != nil { + return x.ColorNo + } + return "" +} + type DeleteProductReq struct { state protoimpl.MessageState `protogen:"open.v1"` ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` @@ -417,6 +465,8 @@ type ListProductReq struct { Spec string `protobuf:"bytes,4,opt,name=spec,proto3" json:"spec,omitempty"` Color string `protobuf:"bytes,5,opt,name=color,proto3" json:"color,omitempty"` Status int64 `protobuf:"varint,6,opt,name=status,proto3" json:"status,omitempty"` + ColorNo string `protobuf:"bytes,7,opt,name=color_no,json=colorNo,proto3" json:"color_no,omitempty"` + ProductCode string `protobuf:"bytes,8,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -493,6 +543,20 @@ func (x *ListProductReq) GetStatus() int64 { return 0 } +func (x *ListProductReq) GetColorNo() string { + if x != nil { + return x.ColorNo + } + return "" +} + +func (x *ListProductReq) GetProductCode() string { + if x != nil { + return x.ProductCode + } + return "" +} + type ListProductResp struct { state protoimpl.MessageState `protogen:"open.v1"` Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` @@ -555,6 +619,8 @@ type PanInfo struct { Bolts []*BoltInfo `protobuf:"bytes,6,rep,name=bolts,proto3" json:"bolts,omitempty"` BoltCount int64 `protobuf:"varint,7,opt,name=bolt_count,json=boltCount,proto3" json:"bolt_count,omitempty"` TotalLength string `protobuf:"bytes,8,opt,name=total_length,json=totalLength,proto3" json:"total_length,omitempty"` + BatchId string `protobuf:"bytes,9,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` + BatchNo string `protobuf:"bytes,10,opt,name=batch_no,json=batchNo,proto3" json:"batch_no,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -645,11 +711,26 @@ func (x *PanInfo) GetTotalLength() string { return "" } +func (x *PanInfo) GetBatchId() string { + if x != nil { + return x.BatchId + } + return "" +} + +func (x *PanInfo) GetBatchNo() string { + if x != nil { + return x.BatchNo + } + return "" +} + type PanInput struct { state protoimpl.MessageState `protogen:"open.v1"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Position string `protobuf:"bytes,2,opt,name=position,proto3" json:"position,omitempty"` BoltLengths []string `protobuf:"bytes,3,rep,name=bolt_lengths,json=boltLengths,proto3" json:"bolt_lengths,omitempty"` + BatchId string `protobuf:"bytes,4,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -705,6 +786,13 @@ func (x *PanInput) GetBoltLengths() []string { return nil } +func (x *PanInput) GetBatchId() string { + if x != nil { + return x.BatchId + } + return "" +} + type ListPanReq struct { state protoimpl.MessageState `protogen:"open.v1"` ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` @@ -1321,6 +1409,9 @@ type ColorDetailItem struct { TotalLengthM string `protobuf:"bytes,8,opt,name=total_length_m,json=totalLengthM,proto3" json:"total_length_m,omitempty"` Locations string `protobuf:"bytes,9,opt,name=locations,proto3" json:"locations,omitempty"` SalesPrice string `protobuf:"bytes,10,opt,name=sales_price,json=salesPrice,proto3" json:"sales_price,omitempty"` + ColorNo string `protobuf:"bytes,11,opt,name=color_no,json=colorNo,proto3" json:"color_no,omitempty"` + ProductCode string `protobuf:"bytes,12,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` + BatchCount int64 `protobuf:"varint,13,opt,name=batch_count,json=batchCount,proto3" json:"batch_count,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1425,6 +1516,27 @@ func (x *ColorDetailItem) GetSalesPrice() string { return "" } +func (x *ColorDetailItem) GetColorNo() string { + if x != nil { + return x.ColorNo + } + return "" +} + +func (x *ColorDetailItem) GetProductCode() string { + if x != nil { + return x.ProductCode + } + return "" +} + +func (x *ColorDetailItem) GetBatchCount() int64 { + if x != nil { + return x.BatchCount + } + return 0 +} + type ListColorDetailReq struct { state protoimpl.MessageState `protogen:"open.v1"` ProductName string `protobuf:"bytes,1,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` @@ -1523,6 +1635,8 @@ type PanListItem struct { Colors string `protobuf:"bytes,6,opt,name=colors,proto3" json:"colors,omitempty"` // aggregated from bolt.color, no spec BoltCount int64 `protobuf:"varint,7,opt,name=bolt_count,json=boltCount,proto3" json:"bolt_count,omitempty"` TotalLengthM string `protobuf:"bytes,8,opt,name=total_length_m,json=totalLengthM,proto3" json:"total_length_m,omitempty"` + BatchId string `protobuf:"bytes,9,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` + BatchNo string `protobuf:"bytes,10,opt,name=batch_no,json=batchNo,proto3" json:"batch_no,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1613,6 +1727,20 @@ func (x *PanListItem) GetTotalLengthM() string { return "" } +func (x *PanListItem) GetBatchId() string { + if x != nil { + return x.BatchId + } + return "" +} + +func (x *PanListItem) GetBatchNo() string { + if x != nil { + return x.BatchNo + } + return "" +} + type ListPanViewReq struct { state protoimpl.MessageState `protogen:"open.v1"` Page int64 `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"` @@ -2201,6 +2329,1022 @@ func (x *ListImportLogResp) GetList() []*ImportLogInfo { return nil } +type YarnInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + YarnId string `protobuf:"bytes,1,opt,name=yarn_id,json=yarnId,proto3" json:"yarn_id,omitempty"` + YarnName string `protobuf:"bytes,2,opt,name=yarn_name,json=yarnName,proto3" json:"yarn_name,omitempty"` + Color string `protobuf:"bytes,3,opt,name=color,proto3" json:"color,omitempty"` + WeightGM string `protobuf:"bytes,4,opt,name=weight_g_m,json=weightGM,proto3" json:"weight_g_m,omitempty"` + SupplierId string `protobuf:"bytes,5,opt,name=supplier_id,json=supplierId,proto3" json:"supplier_id,omitempty"` + SupplierName string `protobuf:"bytes,6,opt,name=supplier_name,json=supplierName,proto3" json:"supplier_name,omitempty"` + DyeFactory string `protobuf:"bytes,7,opt,name=dye_factory,json=dyeFactory,proto3" json:"dye_factory,omitempty"` + ImageUrl string `protobuf:"bytes,8,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` + Remark string `protobuf:"bytes,9,opt,name=remark,proto3" json:"remark,omitempty"` + Status int64 `protobuf:"varint,10,opt,name=status,proto3" json:"status,omitempty"` + CreatedAt string `protobuf:"bytes,11,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + UpdatedAt string `protobuf:"bytes,12,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *YarnInfo) Reset() { + *x = YarnInfo{} + mi := &file_inventory_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *YarnInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*YarnInfo) ProtoMessage() {} + +func (x *YarnInfo) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[33] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use YarnInfo.ProtoReflect.Descriptor instead. +func (*YarnInfo) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{33} +} + +func (x *YarnInfo) GetYarnId() string { + if x != nil { + return x.YarnId + } + return "" +} + +func (x *YarnInfo) GetYarnName() string { + if x != nil { + return x.YarnName + } + return "" +} + +func (x *YarnInfo) GetColor() string { + if x != nil { + return x.Color + } + return "" +} + +func (x *YarnInfo) GetWeightGM() string { + if x != nil { + return x.WeightGM + } + return "" +} + +func (x *YarnInfo) GetSupplierId() string { + if x != nil { + return x.SupplierId + } + return "" +} + +func (x *YarnInfo) GetSupplierName() string { + if x != nil { + return x.SupplierName + } + return "" +} + +func (x *YarnInfo) GetDyeFactory() string { + if x != nil { + return x.DyeFactory + } + return "" +} + +func (x *YarnInfo) GetImageUrl() string { + if x != nil { + return x.ImageUrl + } + return "" +} + +func (x *YarnInfo) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +func (x *YarnInfo) GetStatus() int64 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *YarnInfo) GetCreatedAt() string { + if x != nil { + return x.CreatedAt + } + return "" +} + +func (x *YarnInfo) GetUpdatedAt() string { + if x != nil { + return x.UpdatedAt + } + return "" +} + +type CreateYarnReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + YarnName string `protobuf:"bytes,1,opt,name=yarn_name,json=yarnName,proto3" json:"yarn_name,omitempty"` + Color string `protobuf:"bytes,2,opt,name=color,proto3" json:"color,omitempty"` + WeightGM string `protobuf:"bytes,3,opt,name=weight_g_m,json=weightGM,proto3" json:"weight_g_m,omitempty"` + SupplierId string `protobuf:"bytes,4,opt,name=supplier_id,json=supplierId,proto3" json:"supplier_id,omitempty"` + DyeFactory string `protobuf:"bytes,5,opt,name=dye_factory,json=dyeFactory,proto3" json:"dye_factory,omitempty"` + ImageUrl string `protobuf:"bytes,6,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` + Remark string `protobuf:"bytes,7,opt,name=remark,proto3" json:"remark,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateYarnReq) Reset() { + *x = CreateYarnReq{} + mi := &file_inventory_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateYarnReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateYarnReq) ProtoMessage() {} + +func (x *CreateYarnReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[34] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateYarnReq.ProtoReflect.Descriptor instead. +func (*CreateYarnReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{34} +} + +func (x *CreateYarnReq) GetYarnName() string { + if x != nil { + return x.YarnName + } + return "" +} + +func (x *CreateYarnReq) GetColor() string { + if x != nil { + return x.Color + } + return "" +} + +func (x *CreateYarnReq) GetWeightGM() string { + if x != nil { + return x.WeightGM + } + return "" +} + +func (x *CreateYarnReq) GetSupplierId() string { + if x != nil { + return x.SupplierId + } + return "" +} + +func (x *CreateYarnReq) GetDyeFactory() string { + if x != nil { + return x.DyeFactory + } + return "" +} + +func (x *CreateYarnReq) GetImageUrl() string { + if x != nil { + return x.ImageUrl + } + return "" +} + +func (x *CreateYarnReq) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +type UpdateYarnReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + YarnId string `protobuf:"bytes,1,opt,name=yarn_id,json=yarnId,proto3" json:"yarn_id,omitempty"` + YarnName string `protobuf:"bytes,2,opt,name=yarn_name,json=yarnName,proto3" json:"yarn_name,omitempty"` + Color string `protobuf:"bytes,3,opt,name=color,proto3" json:"color,omitempty"` + WeightGM string `protobuf:"bytes,4,opt,name=weight_g_m,json=weightGM,proto3" json:"weight_g_m,omitempty"` + SupplierId string `protobuf:"bytes,5,opt,name=supplier_id,json=supplierId,proto3" json:"supplier_id,omitempty"` + DyeFactory string `protobuf:"bytes,6,opt,name=dye_factory,json=dyeFactory,proto3" json:"dye_factory,omitempty"` + ImageUrl string `protobuf:"bytes,7,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` + Remark string `protobuf:"bytes,8,opt,name=remark,proto3" json:"remark,omitempty"` + Status int64 `protobuf:"varint,9,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateYarnReq) Reset() { + *x = UpdateYarnReq{} + mi := &file_inventory_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateYarnReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateYarnReq) ProtoMessage() {} + +func (x *UpdateYarnReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[35] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateYarnReq.ProtoReflect.Descriptor instead. +func (*UpdateYarnReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{35} +} + +func (x *UpdateYarnReq) GetYarnId() string { + if x != nil { + return x.YarnId + } + return "" +} + +func (x *UpdateYarnReq) GetYarnName() string { + if x != nil { + return x.YarnName + } + return "" +} + +func (x *UpdateYarnReq) GetColor() string { + if x != nil { + return x.Color + } + return "" +} + +func (x *UpdateYarnReq) GetWeightGM() string { + if x != nil { + return x.WeightGM + } + return "" +} + +func (x *UpdateYarnReq) GetSupplierId() string { + if x != nil { + return x.SupplierId + } + return "" +} + +func (x *UpdateYarnReq) GetDyeFactory() string { + if x != nil { + return x.DyeFactory + } + return "" +} + +func (x *UpdateYarnReq) GetImageUrl() string { + if x != nil { + return x.ImageUrl + } + return "" +} + +func (x *UpdateYarnReq) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +func (x *UpdateYarnReq) GetStatus() int64 { + if x != nil { + return x.Status + } + return 0 +} + +type DeleteYarnReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + YarnId string `protobuf:"bytes,1,opt,name=yarn_id,json=yarnId,proto3" json:"yarn_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteYarnReq) Reset() { + *x = DeleteYarnReq{} + mi := &file_inventory_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteYarnReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteYarnReq) ProtoMessage() {} + +func (x *DeleteYarnReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[36] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteYarnReq.ProtoReflect.Descriptor instead. +func (*DeleteYarnReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{36} +} + +func (x *DeleteYarnReq) GetYarnId() string { + if x != nil { + return x.YarnId + } + return "" +} + +type GetYarnReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + YarnId string `protobuf:"bytes,1,opt,name=yarn_id,json=yarnId,proto3" json:"yarn_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetYarnReq) Reset() { + *x = GetYarnReq{} + mi := &file_inventory_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetYarnReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetYarnReq) ProtoMessage() {} + +func (x *GetYarnReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[37] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetYarnReq.ProtoReflect.Descriptor instead. +func (*GetYarnReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{37} +} + +func (x *GetYarnReq) GetYarnId() string { + if x != nil { + return x.YarnId + } + return "" +} + +type ListYarnReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Page int64 `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"` + PageSize int64 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + YarnName string `protobuf:"bytes,3,opt,name=yarn_name,json=yarnName,proto3" json:"yarn_name,omitempty"` + SupplierId string `protobuf:"bytes,4,opt,name=supplier_id,json=supplierId,proto3" json:"supplier_id,omitempty"` + Status int64 `protobuf:"varint,5,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListYarnReq) Reset() { + *x = ListYarnReq{} + mi := &file_inventory_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListYarnReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListYarnReq) ProtoMessage() {} + +func (x *ListYarnReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[38] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListYarnReq.ProtoReflect.Descriptor instead. +func (*ListYarnReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{38} +} + +func (x *ListYarnReq) GetPage() int64 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *ListYarnReq) GetPageSize() int64 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListYarnReq) GetYarnName() string { + if x != nil { + return x.YarnName + } + return "" +} + +func (x *ListYarnReq) GetSupplierId() string { + if x != nil { + return x.SupplierId + } + return "" +} + +func (x *ListYarnReq) GetStatus() int64 { + if x != nil { + return x.Status + } + return 0 +} + +type ListYarnResp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + List []*YarnInfo `protobuf:"bytes,2,rep,name=list,proto3" json:"list,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListYarnResp) Reset() { + *x = ListYarnResp{} + mi := &file_inventory_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListYarnResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListYarnResp) ProtoMessage() {} + +func (x *ListYarnResp) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[39] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListYarnResp.ProtoReflect.Descriptor instead. +func (*ListYarnResp) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{39} +} + +func (x *ListYarnResp) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *ListYarnResp) GetList() []*YarnInfo { + if x != nil { + return x.List + } + return nil +} + +type ProductBatchInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + YarnRatio string `protobuf:"bytes,1,opt,name=yarn_ratio,json=yarnRatio,proto3" json:"yarn_ratio,omitempty"` + WarpWeightGM string `protobuf:"bytes,2,opt,name=warp_weight_g_m,json=warpWeightGM,proto3" json:"warp_weight_g_m,omitempty"` + WeftWeightGM string `protobuf:"bytes,3,opt,name=weft_weight_g_m,json=weftWeightGM,proto3" json:"weft_weight_g_m,omitempty"` + ProductionProcess string `protobuf:"bytes,4,opt,name=production_process,json=productionProcess,proto3" json:"production_process,omitempty"` + Remark string `protobuf:"bytes,5,opt,name=remark,proto3" json:"remark,omitempty"` + BatchNo string `protobuf:"bytes,6,opt,name=batch_no,json=batchNo,proto3" json:"batch_no,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProductBatchInput) Reset() { + *x = ProductBatchInput{} + mi := &file_inventory_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProductBatchInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProductBatchInput) ProtoMessage() {} + +func (x *ProductBatchInput) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[40] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProductBatchInput.ProtoReflect.Descriptor instead. +func (*ProductBatchInput) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{40} +} + +func (x *ProductBatchInput) GetYarnRatio() string { + if x != nil { + return x.YarnRatio + } + return "" +} + +func (x *ProductBatchInput) GetWarpWeightGM() string { + if x != nil { + return x.WarpWeightGM + } + return "" +} + +func (x *ProductBatchInput) GetWeftWeightGM() string { + if x != nil { + return x.WeftWeightGM + } + return "" +} + +func (x *ProductBatchInput) GetProductionProcess() string { + if x != nil { + return x.ProductionProcess + } + return "" +} + +func (x *ProductBatchInput) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +func (x *ProductBatchInput) GetBatchNo() string { + if x != nil { + return x.BatchNo + } + return "" +} + +type ProductBatchInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + BatchId string `protobuf:"bytes,1,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` + ProductId string `protobuf:"bytes,2,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + BatchNo string `protobuf:"bytes,3,opt,name=batch_no,json=batchNo,proto3" json:"batch_no,omitempty"` + YarnRatio string `protobuf:"bytes,4,opt,name=yarn_ratio,json=yarnRatio,proto3" json:"yarn_ratio,omitempty"` + WarpWeightGM string `protobuf:"bytes,5,opt,name=warp_weight_g_m,json=warpWeightGM,proto3" json:"warp_weight_g_m,omitempty"` + WeftWeightGM string `protobuf:"bytes,6,opt,name=weft_weight_g_m,json=weftWeightGM,proto3" json:"weft_weight_g_m,omitempty"` + ProductionProcess string `protobuf:"bytes,7,opt,name=production_process,json=productionProcess,proto3" json:"production_process,omitempty"` + Remark string `protobuf:"bytes,8,opt,name=remark,proto3" json:"remark,omitempty"` + Status int64 `protobuf:"varint,9,opt,name=status,proto3" json:"status,omitempty"` + CreatedAt string `protobuf:"bytes,10,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + UpdatedAt string `protobuf:"bytes,11,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProductBatchInfo) Reset() { + *x = ProductBatchInfo{} + mi := &file_inventory_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProductBatchInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProductBatchInfo) ProtoMessage() {} + +func (x *ProductBatchInfo) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[41] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProductBatchInfo.ProtoReflect.Descriptor instead. +func (*ProductBatchInfo) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{41} +} + +func (x *ProductBatchInfo) GetBatchId() string { + if x != nil { + return x.BatchId + } + return "" +} + +func (x *ProductBatchInfo) GetProductId() string { + if x != nil { + return x.ProductId + } + return "" +} + +func (x *ProductBatchInfo) GetBatchNo() string { + if x != nil { + return x.BatchNo + } + return "" +} + +func (x *ProductBatchInfo) GetYarnRatio() string { + if x != nil { + return x.YarnRatio + } + return "" +} + +func (x *ProductBatchInfo) GetWarpWeightGM() string { + if x != nil { + return x.WarpWeightGM + } + return "" +} + +func (x *ProductBatchInfo) GetWeftWeightGM() string { + if x != nil { + return x.WeftWeightGM + } + return "" +} + +func (x *ProductBatchInfo) GetProductionProcess() string { + if x != nil { + return x.ProductionProcess + } + return "" +} + +func (x *ProductBatchInfo) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +func (x *ProductBatchInfo) GetStatus() int64 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *ProductBatchInfo) GetCreatedAt() string { + if x != nil { + return x.CreatedAt + } + return "" +} + +func (x *ProductBatchInfo) GetUpdatedAt() string { + if x != nil { + return x.UpdatedAt + } + return "" +} + +type CreateProductBatchReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + Batch *ProductBatchInput `protobuf:"bytes,2,opt,name=batch,proto3" json:"batch,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateProductBatchReq) Reset() { + *x = CreateProductBatchReq{} + mi := &file_inventory_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateProductBatchReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateProductBatchReq) ProtoMessage() {} + +func (x *CreateProductBatchReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[42] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateProductBatchReq.ProtoReflect.Descriptor instead. +func (*CreateProductBatchReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{42} +} + +func (x *CreateProductBatchReq) GetProductId() string { + if x != nil { + return x.ProductId + } + return "" +} + +func (x *CreateProductBatchReq) GetBatch() *ProductBatchInput { + if x != nil { + return x.Batch + } + return nil +} + +type UpdateProductBatchReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + BatchId string `protobuf:"bytes,2,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` + Batch *ProductBatchInput `protobuf:"bytes,3,opt,name=batch,proto3" json:"batch,omitempty"` + Status int64 `protobuf:"varint,4,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateProductBatchReq) Reset() { + *x = UpdateProductBatchReq{} + mi := &file_inventory_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateProductBatchReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateProductBatchReq) ProtoMessage() {} + +func (x *UpdateProductBatchReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[43] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateProductBatchReq.ProtoReflect.Descriptor instead. +func (*UpdateProductBatchReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{43} +} + +func (x *UpdateProductBatchReq) GetProductId() string { + if x != nil { + return x.ProductId + } + return "" +} + +func (x *UpdateProductBatchReq) GetBatchId() string { + if x != nil { + return x.BatchId + } + return "" +} + +func (x *UpdateProductBatchReq) GetBatch() *ProductBatchInput { + if x != nil { + return x.Batch + } + return nil +} + +func (x *UpdateProductBatchReq) GetStatus() int64 { + if x != nil { + return x.Status + } + return 0 +} + +type DeleteProductBatchReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + BatchId string `protobuf:"bytes,2,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteProductBatchReq) Reset() { + *x = DeleteProductBatchReq{} + mi := &file_inventory_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteProductBatchReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteProductBatchReq) ProtoMessage() {} + +func (x *DeleteProductBatchReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[44] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteProductBatchReq.ProtoReflect.Descriptor instead. +func (*DeleteProductBatchReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{44} +} + +func (x *DeleteProductBatchReq) GetProductId() string { + if x != nil { + return x.ProductId + } + return "" +} + +func (x *DeleteProductBatchReq) GetBatchId() string { + if x != nil { + return x.BatchId + } + return "" +} + +type ListProductBatchReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListProductBatchReq) Reset() { + *x = ListProductBatchReq{} + mi := &file_inventory_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListProductBatchReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListProductBatchReq) ProtoMessage() {} + +func (x *ListProductBatchReq) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[45] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListProductBatchReq.ProtoReflect.Descriptor instead. +func (*ListProductBatchReq) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{45} +} + +func (x *ListProductBatchReq) GetProductId() string { + if x != nil { + return x.ProductId + } + return "" +} + +type ListProductBatchResp struct { + state protoimpl.MessageState `protogen:"open.v1"` + List []*ProductBatchInfo `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListProductBatchResp) Reset() { + *x = ListProductBatchResp{} + mi := &file_inventory_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListProductBatchResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListProductBatchResp) ProtoMessage() {} + +func (x *ListProductBatchResp) ProtoReflect() protoreflect.Message { + mi := &file_inventory_proto_msgTypes[46] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListProductBatchResp.ProtoReflect.Descriptor instead. +func (*ListProductBatchResp) Descriptor() ([]byte, []int) { + return file_inventory_proto_rawDescGZIP(), []int{46} +} + +func (x *ListProductBatchResp) GetList() []*ProductBatchInfo { + if x != nil { + return x.List + } + return nil +} + type ImportLogInfo struct { state protoimpl.MessageState `protogen:"open.v1"` ImportId string `protobuf:"bytes,1,opt,name=import_id,json=importId,proto3" json:"import_id,omitempty"` @@ -2217,7 +3361,7 @@ type ImportLogInfo struct { func (x *ImportLogInfo) Reset() { *x = ImportLogInfo{} - mi := &file_inventory_proto_msgTypes[33] + mi := &file_inventory_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2229,7 +3373,7 @@ func (x *ImportLogInfo) String() string { func (*ImportLogInfo) ProtoMessage() {} func (x *ImportLogInfo) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[33] + mi := &file_inventory_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2242,7 +3386,7 @@ func (x *ImportLogInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportLogInfo.ProtoReflect.Descriptor instead. func (*ImportLogInfo) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{33} + return file_inventory_proto_rawDescGZIP(), []int{47} } func (x *ImportLogInfo) GetImportId() string { @@ -2309,7 +3453,7 @@ type StockSummaryReq struct { func (x *StockSummaryReq) Reset() { *x = StockSummaryReq{} - mi := &file_inventory_proto_msgTypes[34] + mi := &file_inventory_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2321,7 +3465,7 @@ func (x *StockSummaryReq) String() string { func (*StockSummaryReq) ProtoMessage() {} func (x *StockSummaryReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[34] + mi := &file_inventory_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2334,7 +3478,7 @@ func (x *StockSummaryReq) ProtoReflect() protoreflect.Message { // Deprecated: Use StockSummaryReq.ProtoReflect.Descriptor instead. func (*StockSummaryReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{34} + return file_inventory_proto_rawDescGZIP(), []int{48} } type StockSummaryResp struct { @@ -2350,7 +3494,7 @@ type StockSummaryResp struct { func (x *StockSummaryResp) Reset() { *x = StockSummaryResp{} - mi := &file_inventory_proto_msgTypes[35] + mi := &file_inventory_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2362,7 +3506,7 @@ func (x *StockSummaryResp) String() string { func (*StockSummaryResp) ProtoMessage() {} func (x *StockSummaryResp) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[35] + mi := &file_inventory_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2375,7 +3519,7 @@ func (x *StockSummaryResp) ProtoReflect() protoreflect.Message { // Deprecated: Use StockSummaryResp.ProtoReflect.Descriptor instead. func (*StockSummaryResp) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{35} + return file_inventory_proto_rawDescGZIP(), []int{49} } func (x *StockSummaryResp) GetProductCount() int64 { @@ -2422,7 +3566,7 @@ type StockGroupReq struct { func (x *StockGroupReq) Reset() { *x = StockGroupReq{} - mi := &file_inventory_proto_msgTypes[36] + mi := &file_inventory_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2434,7 +3578,7 @@ func (x *StockGroupReq) String() string { func (*StockGroupReq) ProtoMessage() {} func (x *StockGroupReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[36] + mi := &file_inventory_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2447,7 +3591,7 @@ func (x *StockGroupReq) ProtoReflect() protoreflect.Message { // Deprecated: Use StockGroupReq.ProtoReflect.Descriptor instead. func (*StockGroupReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{36} + return file_inventory_proto_rawDescGZIP(), []int{50} } func (x *StockGroupReq) GetGroupBy() string { @@ -2468,7 +3612,7 @@ type StockGroupItem struct { func (x *StockGroupItem) Reset() { *x = StockGroupItem{} - mi := &file_inventory_proto_msgTypes[37] + mi := &file_inventory_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2480,7 +3624,7 @@ func (x *StockGroupItem) String() string { func (*StockGroupItem) ProtoMessage() {} func (x *StockGroupItem) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[37] + mi := &file_inventory_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2493,7 +3637,7 @@ func (x *StockGroupItem) ProtoReflect() protoreflect.Message { // Deprecated: Use StockGroupItem.ProtoReflect.Descriptor instead. func (*StockGroupItem) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{37} + return file_inventory_proto_rawDescGZIP(), []int{51} } func (x *StockGroupItem) GetName() string { @@ -2526,7 +3670,7 @@ type StockGroupResp struct { func (x *StockGroupResp) Reset() { *x = StockGroupResp{} - mi := &file_inventory_proto_msgTypes[38] + mi := &file_inventory_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2538,7 +3682,7 @@ func (x *StockGroupResp) String() string { func (*StockGroupResp) ProtoMessage() {} func (x *StockGroupResp) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[38] + mi := &file_inventory_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2551,7 +3695,7 @@ func (x *StockGroupResp) ProtoReflect() protoreflect.Message { // Deprecated: Use StockGroupResp.ProtoReflect.Descriptor instead. func (*StockGroupResp) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{38} + return file_inventory_proto_rawDescGZIP(), []int{52} } func (x *StockGroupResp) GetList() []*StockGroupItem { @@ -2578,7 +3722,7 @@ type StockCheckInfo struct { func (x *StockCheckInfo) Reset() { *x = StockCheckInfo{} - mi := &file_inventory_proto_msgTypes[39] + mi := &file_inventory_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2590,7 +3734,7 @@ func (x *StockCheckInfo) String() string { func (*StockCheckInfo) ProtoMessage() {} func (x *StockCheckInfo) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[39] + mi := &file_inventory_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2603,7 +3747,7 @@ func (x *StockCheckInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use StockCheckInfo.ProtoReflect.Descriptor instead. func (*StockCheckInfo) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{39} + return file_inventory_proto_rawDescGZIP(), []int{53} } func (x *StockCheckInfo) GetCheckId() string { @@ -2686,7 +3830,7 @@ type StockCheckDetailInfo struct { func (x *StockCheckDetailInfo) Reset() { *x = StockCheckDetailInfo{} - mi := &file_inventory_proto_msgTypes[40] + mi := &file_inventory_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2698,7 +3842,7 @@ func (x *StockCheckDetailInfo) String() string { func (*StockCheckDetailInfo) ProtoMessage() {} func (x *StockCheckDetailInfo) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[40] + mi := &file_inventory_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2711,7 +3855,7 @@ func (x *StockCheckDetailInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use StockCheckDetailInfo.ProtoReflect.Descriptor instead. func (*StockCheckDetailInfo) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{40} + return file_inventory_proto_rawDescGZIP(), []int{54} } func (x *StockCheckDetailInfo) GetDetailId() string { @@ -2789,7 +3933,7 @@ type CreateStockCheckReq struct { func (x *CreateStockCheckReq) Reset() { *x = CreateStockCheckReq{} - mi := &file_inventory_proto_msgTypes[41] + mi := &file_inventory_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2801,7 +3945,7 @@ func (x *CreateStockCheckReq) String() string { func (*CreateStockCheckReq) ProtoMessage() {} func (x *CreateStockCheckReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[41] + mi := &file_inventory_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2814,7 +3958,7 @@ func (x *CreateStockCheckReq) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateStockCheckReq.ProtoReflect.Descriptor instead. func (*CreateStockCheckReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{41} + return file_inventory_proto_rawDescGZIP(), []int{55} } func (x *CreateStockCheckReq) GetCheckDate() string { @@ -2856,7 +4000,7 @@ type StockCheckDetailReq struct { func (x *StockCheckDetailReq) Reset() { *x = StockCheckDetailReq{} - mi := &file_inventory_proto_msgTypes[42] + mi := &file_inventory_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2868,7 +4012,7 @@ func (x *StockCheckDetailReq) String() string { func (*StockCheckDetailReq) ProtoMessage() {} func (x *StockCheckDetailReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[42] + mi := &file_inventory_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2881,7 +4025,7 @@ func (x *StockCheckDetailReq) ProtoReflect() protoreflect.Message { // Deprecated: Use StockCheckDetailReq.ProtoReflect.Descriptor instead. func (*StockCheckDetailReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{42} + return file_inventory_proto_rawDescGZIP(), []int{56} } func (x *StockCheckDetailReq) GetProductId() string { @@ -2916,7 +4060,7 @@ type UpdateStockCheckReq struct { func (x *UpdateStockCheckReq) Reset() { *x = UpdateStockCheckReq{} - mi := &file_inventory_proto_msgTypes[43] + mi := &file_inventory_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2928,7 +4072,7 @@ func (x *UpdateStockCheckReq) String() string { func (*UpdateStockCheckReq) ProtoMessage() {} func (x *UpdateStockCheckReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[43] + mi := &file_inventory_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2941,7 +4085,7 @@ func (x *UpdateStockCheckReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateStockCheckReq.ProtoReflect.Descriptor instead. func (*UpdateStockCheckReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{43} + return file_inventory_proto_rawDescGZIP(), []int{57} } func (x *UpdateStockCheckReq) GetCheckId() string { @@ -2975,7 +4119,7 @@ type ConfirmStockCheckReq struct { func (x *ConfirmStockCheckReq) Reset() { *x = ConfirmStockCheckReq{} - mi := &file_inventory_proto_msgTypes[44] + mi := &file_inventory_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2987,7 +4131,7 @@ func (x *ConfirmStockCheckReq) String() string { func (*ConfirmStockCheckReq) ProtoMessage() {} func (x *ConfirmStockCheckReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[44] + mi := &file_inventory_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3000,7 +4144,7 @@ func (x *ConfirmStockCheckReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmStockCheckReq.ProtoReflect.Descriptor instead. func (*ConfirmStockCheckReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{44} + return file_inventory_proto_rawDescGZIP(), []int{58} } func (x *ConfirmStockCheckReq) GetCheckId() string { @@ -3026,7 +4170,7 @@ type GetStockCheckReq struct { func (x *GetStockCheckReq) Reset() { *x = GetStockCheckReq{} - mi := &file_inventory_proto_msgTypes[45] + mi := &file_inventory_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3038,7 +4182,7 @@ func (x *GetStockCheckReq) String() string { func (*GetStockCheckReq) ProtoMessage() {} func (x *GetStockCheckReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[45] + mi := &file_inventory_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3051,7 +4195,7 @@ func (x *GetStockCheckReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStockCheckReq.ProtoReflect.Descriptor instead. func (*GetStockCheckReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{45} + return file_inventory_proto_rawDescGZIP(), []int{59} } func (x *GetStockCheckReq) GetCheckId() string { @@ -3075,7 +4219,7 @@ type ListStockCheckReq struct { func (x *ListStockCheckReq) Reset() { *x = ListStockCheckReq{} - mi := &file_inventory_proto_msgTypes[46] + mi := &file_inventory_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3087,7 +4231,7 @@ func (x *ListStockCheckReq) String() string { func (*ListStockCheckReq) ProtoMessage() {} func (x *ListStockCheckReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[46] + mi := &file_inventory_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3100,7 +4244,7 @@ func (x *ListStockCheckReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStockCheckReq.ProtoReflect.Descriptor instead. func (*ListStockCheckReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{46} + return file_inventory_proto_rawDescGZIP(), []int{60} } func (x *ListStockCheckReq) GetPage() int64 { @@ -3155,7 +4299,7 @@ type ListStockCheckResp struct { func (x *ListStockCheckResp) Reset() { *x = ListStockCheckResp{} - mi := &file_inventory_proto_msgTypes[47] + mi := &file_inventory_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3167,7 +4311,7 @@ func (x *ListStockCheckResp) String() string { func (*ListStockCheckResp) ProtoMessage() {} func (x *ListStockCheckResp) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[47] + mi := &file_inventory_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3180,7 +4324,7 @@ func (x *ListStockCheckResp) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStockCheckResp.ProtoReflect.Descriptor instead. func (*ListStockCheckResp) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{47} + return file_inventory_proto_rawDescGZIP(), []int{61} } func (x *ListStockCheckResp) GetTotal() int64 { @@ -3216,7 +4360,7 @@ type StockAdjustInfo struct { func (x *StockAdjustInfo) Reset() { *x = StockAdjustInfo{} - mi := &file_inventory_proto_msgTypes[48] + mi := &file_inventory_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3228,7 +4372,7 @@ func (x *StockAdjustInfo) String() string { func (*StockAdjustInfo) ProtoMessage() {} func (x *StockAdjustInfo) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[48] + mi := &file_inventory_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3241,7 +4385,7 @@ func (x *StockAdjustInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use StockAdjustInfo.ProtoReflect.Descriptor instead. func (*StockAdjustInfo) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{48} + return file_inventory_proto_rawDescGZIP(), []int{62} } func (x *StockAdjustInfo) GetAdjustId() string { @@ -3337,7 +4481,7 @@ type StockAdjustDetailInfo struct { func (x *StockAdjustDetailInfo) Reset() { *x = StockAdjustDetailInfo{} - mi := &file_inventory_proto_msgTypes[49] + mi := &file_inventory_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3349,7 +4493,7 @@ func (x *StockAdjustDetailInfo) String() string { func (*StockAdjustDetailInfo) ProtoMessage() {} func (x *StockAdjustDetailInfo) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[49] + mi := &file_inventory_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3362,7 +4506,7 @@ func (x *StockAdjustDetailInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use StockAdjustDetailInfo.ProtoReflect.Descriptor instead. func (*StockAdjustDetailInfo) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{49} + return file_inventory_proto_rawDescGZIP(), []int{63} } func (x *StockAdjustDetailInfo) GetDetailId() string { @@ -3434,7 +4578,7 @@ type CreateStockAdjustReq struct { func (x *CreateStockAdjustReq) Reset() { *x = CreateStockAdjustReq{} - mi := &file_inventory_proto_msgTypes[50] + mi := &file_inventory_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3446,7 +4590,7 @@ func (x *CreateStockAdjustReq) String() string { func (*CreateStockAdjustReq) ProtoMessage() {} func (x *CreateStockAdjustReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[50] + mi := &file_inventory_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3459,7 +4603,7 @@ func (x *CreateStockAdjustReq) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateStockAdjustReq.ProtoReflect.Descriptor instead. func (*CreateStockAdjustReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{50} + return file_inventory_proto_rawDescGZIP(), []int{64} } func (x *CreateStockAdjustReq) GetAdjustDate() string { @@ -3508,7 +4652,7 @@ type StockAdjustDetailReq struct { func (x *StockAdjustDetailReq) Reset() { *x = StockAdjustDetailReq{} - mi := &file_inventory_proto_msgTypes[51] + mi := &file_inventory_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3520,7 +4664,7 @@ func (x *StockAdjustDetailReq) String() string { func (*StockAdjustDetailReq) ProtoMessage() {} func (x *StockAdjustDetailReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[51] + mi := &file_inventory_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3533,7 +4677,7 @@ func (x *StockAdjustDetailReq) ProtoReflect() protoreflect.Message { // Deprecated: Use StockAdjustDetailReq.ProtoReflect.Descriptor instead. func (*StockAdjustDetailReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{51} + return file_inventory_proto_rawDescGZIP(), []int{65} } func (x *StockAdjustDetailReq) GetProductId() string { @@ -3568,7 +4712,7 @@ type ApproveStockAdjustReq struct { func (x *ApproveStockAdjustReq) Reset() { *x = ApproveStockAdjustReq{} - mi := &file_inventory_proto_msgTypes[52] + mi := &file_inventory_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3580,7 +4724,7 @@ func (x *ApproveStockAdjustReq) String() string { func (*ApproveStockAdjustReq) ProtoMessage() {} func (x *ApproveStockAdjustReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[52] + mi := &file_inventory_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3593,7 +4737,7 @@ func (x *ApproveStockAdjustReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveStockAdjustReq.ProtoReflect.Descriptor instead. func (*ApproveStockAdjustReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{52} + return file_inventory_proto_rawDescGZIP(), []int{66} } func (x *ApproveStockAdjustReq) GetAdjustId() string { @@ -3626,7 +4770,7 @@ type GetStockAdjustReq struct { func (x *GetStockAdjustReq) Reset() { *x = GetStockAdjustReq{} - mi := &file_inventory_proto_msgTypes[53] + mi := &file_inventory_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3638,7 +4782,7 @@ func (x *GetStockAdjustReq) String() string { func (*GetStockAdjustReq) ProtoMessage() {} func (x *GetStockAdjustReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[53] + mi := &file_inventory_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3651,7 +4795,7 @@ func (x *GetStockAdjustReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStockAdjustReq.ProtoReflect.Descriptor instead. func (*GetStockAdjustReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{53} + return file_inventory_proto_rawDescGZIP(), []int{67} } func (x *GetStockAdjustReq) GetAdjustId() string { @@ -3676,7 +4820,7 @@ type ListStockAdjustReq struct { func (x *ListStockAdjustReq) Reset() { *x = ListStockAdjustReq{} - mi := &file_inventory_proto_msgTypes[54] + mi := &file_inventory_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3688,7 +4832,7 @@ func (x *ListStockAdjustReq) String() string { func (*ListStockAdjustReq) ProtoMessage() {} func (x *ListStockAdjustReq) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[54] + mi := &file_inventory_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3701,7 +4845,7 @@ func (x *ListStockAdjustReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStockAdjustReq.ProtoReflect.Descriptor instead. func (*ListStockAdjustReq) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{54} + return file_inventory_proto_rawDescGZIP(), []int{68} } func (x *ListStockAdjustReq) GetPage() int64 { @@ -3763,7 +4907,7 @@ type ListStockAdjustResp struct { func (x *ListStockAdjustResp) Reset() { *x = ListStockAdjustResp{} - mi := &file_inventory_proto_msgTypes[55] + mi := &file_inventory_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3775,7 +4919,7 @@ func (x *ListStockAdjustResp) String() string { func (*ListStockAdjustResp) ProtoMessage() {} func (x *ListStockAdjustResp) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[55] + mi := &file_inventory_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3788,7 +4932,7 @@ func (x *ListStockAdjustResp) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStockAdjustResp.ProtoReflect.Descriptor instead. func (*ListStockAdjustResp) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{55} + return file_inventory_proto_rawDescGZIP(), []int{69} } func (x *ListStockAdjustResp) GetTotal() int64 { @@ -3814,7 +4958,7 @@ type IdResp struct { func (x *IdResp) Reset() { *x = IdResp{} - mi := &file_inventory_proto_msgTypes[56] + mi := &file_inventory_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3826,7 +4970,7 @@ func (x *IdResp) String() string { func (*IdResp) ProtoMessage() {} func (x *IdResp) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[56] + mi := &file_inventory_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3839,7 +4983,7 @@ func (x *IdResp) ProtoReflect() protoreflect.Message { // Deprecated: Use IdResp.ProtoReflect.Descriptor instead. func (*IdResp) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{56} + return file_inventory_proto_rawDescGZIP(), []int{70} } func (x *IdResp) GetId() string { @@ -3857,7 +5001,7 @@ type Empty struct { func (x *Empty) Reset() { *x = Empty{} - mi := &file_inventory_proto_msgTypes[57] + mi := &file_inventory_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3869,7 +5013,7 @@ func (x *Empty) String() string { func (*Empty) ProtoMessage() {} func (x *Empty) ProtoReflect() protoreflect.Message { - mi := &file_inventory_proto_msgTypes[57] + mi := &file_inventory_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3882,14 +5026,14 @@ func (x *Empty) ProtoReflect() protoreflect.Message { // Deprecated: Use Empty.ProtoReflect.Descriptor instead. func (*Empty) Descriptor() ([]byte, []int) { - return file_inventory_proto_rawDescGZIP(), []int{57} + return file_inventory_proto_rawDescGZIP(), []int{71} } var File_inventory_proto protoreflect.FileDescriptor const file_inventory_proto_rawDesc = "" + "\n" + - "\x0finventory.proto\x12\tinventory\"\xa5\x02\n" + + "\x0finventory.proto\x12\tinventory\"\xe3\x02\n" + "\vProductInfo\x12\x1d\n" + "\n" + "product_id\x18\x01 \x01(\tR\tproductId\x12!\n" + @@ -3905,7 +5049,9 @@ const file_inventory_proto_rawDesc = "" + "created_at\x18\t \x01(\tR\tcreatedAt\x12\x1d\n" + "\n" + "updated_at\x18\n" + - " \x01(\tR\tupdatedAt\"\xde\x01\n" + + " \x01(\tR\tupdatedAt\x12\x19\n" + + "\bcolor_no\x18\v \x01(\tR\acolorNo\x12!\n" + + "\fproduct_code\x18\f \x01(\tR\vproductCode\"\xdf\x02\n" + "\x10CreateProductReq\x12!\n" + "\fproduct_name\x18\x01 \x01(\tR\vproductName\x12\x1b\n" + "\timage_url\x18\x02 \x01(\tR\bimageUrl\x12\x12\n" + @@ -3914,7 +5060,11 @@ const file_inventory_proto_rawDesc = "" + "\vsales_price\x18\x05 \x01(\tR\n" + "salesPrice\x12\x16\n" + "\x06remark\x18\x06 \x01(\tR\x06remark\x12'\n" + - "\x04pans\x18\a \x03(\v2\x13.inventory.PanInputR\x04pans\"\xd4\x01\n" + + "\x04pans\x18\a \x03(\v2\x13.inventory.PanInputR\x04pans\x12\x19\n" + + "\bcolor_no\x18\b \x01(\tR\acolorNo\x12A\n" + + "\rinitial_batch\x18\t \x01(\v2\x1c.inventory.ProductBatchInputR\finitialBatch\x12!\n" + + "\fproduct_code\x18\n" + + " \x01(\tR\vproductCode\"\xef\x01\n" + "\x10UpdateProductReq\x12\x1d\n" + "\n" + "product_id\x18\x01 \x01(\tR\tproductId\x12!\n" + @@ -3924,23 +5074,26 @@ const file_inventory_proto_rawDesc = "" + "\x05color\x18\x05 \x01(\tR\x05color\x12\x1f\n" + "\vsales_price\x18\x06 \x01(\tR\n" + "salesPrice\x12\x16\n" + - "\x06remark\x18\a \x01(\tR\x06remark\"1\n" + + "\x06remark\x18\a \x01(\tR\x06remark\x12\x19\n" + + "\bcolor_no\x18\b \x01(\tR\acolorNo\"1\n" + "\x10DeleteProductReq\x12\x1d\n" + "\n" + "product_id\x18\x01 \x01(\tR\tproductId\".\n" + "\rGetProductReq\x12\x1d\n" + "\n" + - "product_id\x18\x01 \x01(\tR\tproductId\"\xa6\x01\n" + + "product_id\x18\x01 \x01(\tR\tproductId\"\xe4\x01\n" + "\x0eListProductReq\x12\x12\n" + "\x04page\x18\x01 \x01(\x03R\x04page\x12\x1b\n" + "\tpage_size\x18\x02 \x01(\x03R\bpageSize\x12!\n" + "\fproduct_name\x18\x03 \x01(\tR\vproductName\x12\x12\n" + "\x04spec\x18\x04 \x01(\tR\x04spec\x12\x14\n" + "\x05color\x18\x05 \x01(\tR\x05color\x12\x16\n" + - "\x06status\x18\x06 \x01(\x03R\x06status\"S\n" + + "\x06status\x18\x06 \x01(\x03R\x06status\x12\x19\n" + + "\bcolor_no\x18\a \x01(\tR\acolorNo\x12!\n" + + "\fproduct_code\x18\b \x01(\tR\vproductCode\"S\n" + "\x0fListProductResp\x12\x14\n" + "\x05total\x18\x01 \x01(\x03R\x05total\x12*\n" + - "\x04list\x18\x02 \x03(\v2\x16.inventory.ProductInfoR\x04list\"\xfb\x01\n" + + "\x04list\x18\x02 \x03(\v2\x16.inventory.ProductInfoR\x04list\"\xb1\x02\n" + "\aPanInfo\x12\x15\n" + "\x06pan_id\x18\x01 \x01(\tR\x05panId\x12\x1d\n" + "\n" + @@ -3952,11 +5105,15 @@ const file_inventory_proto_rawDesc = "" + "\x05bolts\x18\x06 \x03(\v2\x13.inventory.BoltInfoR\x05bolts\x12\x1d\n" + "\n" + "bolt_count\x18\a \x01(\x03R\tboltCount\x12!\n" + - "\ftotal_length\x18\b \x01(\tR\vtotalLength\"]\n" + + "\ftotal_length\x18\b \x01(\tR\vtotalLength\x12\x19\n" + + "\bbatch_id\x18\t \x01(\tR\abatchId\x12\x19\n" + + "\bbatch_no\x18\n" + + " \x01(\tR\abatchNo\"x\n" + "\bPanInput\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1a\n" + "\bposition\x18\x02 \x01(\tR\bposition\x12!\n" + - "\fbolt_lengths\x18\x03 \x03(\tR\vboltLengths\"+\n" + + "\fbolt_lengths\x18\x03 \x03(\tR\vboltLengths\x12\x19\n" + + "\bbatch_id\x18\x04 \x01(\tR\abatchId\"+\n" + "\n" + "ListPanReq\x12\x1d\n" + "\n" + @@ -3998,7 +5155,7 @@ const file_inventory_proto_rawDesc = "" + "\tlocations\x18\b \x01(\tR\tlocations\"\x17\n" + "\x15ListProductSummaryReq\"K\n" + "\x16ListProductSummaryResp\x121\n" + - "\x04list\x18\x01 \x03(\v2\x1d.inventory.ProductSummaryItemR\x04list\"\xbb\x02\n" + + "\x04list\x18\x01 \x03(\v2\x1d.inventory.ProductSummaryItemR\x04list\"\x9a\x03\n" + "\x0fColorDetailItem\x12\x1d\n" + "\n" + "product_id\x18\x01 \x01(\tR\tproductId\x12!\n" + @@ -4013,11 +5170,15 @@ const file_inventory_proto_rawDesc = "" + "\tlocations\x18\t \x01(\tR\tlocations\x12\x1f\n" + "\vsales_price\x18\n" + " \x01(\tR\n" + - "salesPrice\"7\n" + + "salesPrice\x12\x19\n" + + "\bcolor_no\x18\v \x01(\tR\acolorNo\x12!\n" + + "\fproduct_code\x18\f \x01(\tR\vproductCode\x12\x1f\n" + + "\vbatch_count\x18\r \x01(\x03R\n" + + "batchCount\"7\n" + "\x12ListColorDetailReq\x12!\n" + "\fproduct_name\x18\x01 \x01(\tR\vproductName\"E\n" + "\x13ListColorDetailResp\x12.\n" + - "\x04list\x18\x01 \x03(\v2\x1a.inventory.ColorDetailItemR\x04list\"\xf3\x01\n" + + "\x04list\x18\x01 \x03(\v2\x1a.inventory.ColorDetailItemR\x04list\"\xa9\x02\n" + "\vPanListItem\x12\x15\n" + "\x06pan_id\x18\x01 \x01(\tR\x05panId\x12\x1d\n" + "\n" + @@ -4028,7 +5189,10 @@ const file_inventory_proto_rawDesc = "" + "\x06colors\x18\x06 \x01(\tR\x06colors\x12\x1d\n" + "\n" + "bolt_count\x18\a \x01(\x03R\tboltCount\x12$\n" + - "\x0etotal_length_m\x18\b \x01(\tR\ftotalLengthM\"\x80\x01\n" + + "\x0etotal_length_m\x18\b \x01(\tR\ftotalLengthM\x12\x19\n" + + "\bbatch_id\x18\t \x01(\tR\abatchId\x12\x19\n" + + "\bbatch_no\x18\n" + + " \x01(\tR\abatchNo\"\x80\x01\n" + "\x0eListPanViewReq\x12\x12\n" + "\x04page\x18\x01 \x01(\x03R\x04page\x12\x1b\n" + "\tpage_size\x18\x02 \x01(\x03R\bpageSize\x12!\n" + @@ -4074,7 +5238,109 @@ const file_inventory_proto_rawDesc = "" + "\tpage_size\x18\x02 \x01(\x03R\bpageSize\"W\n" + "\x11ListImportLogResp\x12\x14\n" + "\x05total\x18\x01 \x01(\x03R\x05total\x12,\n" + - "\x04list\x18\x02 \x03(\v2\x18.inventory.ImportLogInfoR\x04list\"\x86\x02\n" + + "\x04list\x18\x02 \x03(\v2\x18.inventory.ImportLogInfoR\x04list\"\xe6\x02\n" + + "\bYarnInfo\x12\x17\n" + + "\ayarn_id\x18\x01 \x01(\tR\x06yarnId\x12\x1b\n" + + "\tyarn_name\x18\x02 \x01(\tR\byarnName\x12\x14\n" + + "\x05color\x18\x03 \x01(\tR\x05color\x12\x1c\n" + + "\n" + + "weight_g_m\x18\x04 \x01(\tR\bweightGM\x12\x1f\n" + + "\vsupplier_id\x18\x05 \x01(\tR\n" + + "supplierId\x12#\n" + + "\rsupplier_name\x18\x06 \x01(\tR\fsupplierName\x12\x1f\n" + + "\vdye_factory\x18\a \x01(\tR\n" + + "dyeFactory\x12\x1b\n" + + "\timage_url\x18\b \x01(\tR\bimageUrl\x12\x16\n" + + "\x06remark\x18\t \x01(\tR\x06remark\x12\x16\n" + + "\x06status\x18\n" + + " \x01(\x03R\x06status\x12\x1d\n" + + "\n" + + "created_at\x18\v \x01(\tR\tcreatedAt\x12\x1d\n" + + "\n" + + "updated_at\x18\f \x01(\tR\tupdatedAt\"\xd7\x01\n" + + "\rCreateYarnReq\x12\x1b\n" + + "\tyarn_name\x18\x01 \x01(\tR\byarnName\x12\x14\n" + + "\x05color\x18\x02 \x01(\tR\x05color\x12\x1c\n" + + "\n" + + "weight_g_m\x18\x03 \x01(\tR\bweightGM\x12\x1f\n" + + "\vsupplier_id\x18\x04 \x01(\tR\n" + + "supplierId\x12\x1f\n" + + "\vdye_factory\x18\x05 \x01(\tR\n" + + "dyeFactory\x12\x1b\n" + + "\timage_url\x18\x06 \x01(\tR\bimageUrl\x12\x16\n" + + "\x06remark\x18\a \x01(\tR\x06remark\"\x88\x02\n" + + "\rUpdateYarnReq\x12\x17\n" + + "\ayarn_id\x18\x01 \x01(\tR\x06yarnId\x12\x1b\n" + + "\tyarn_name\x18\x02 \x01(\tR\byarnName\x12\x14\n" + + "\x05color\x18\x03 \x01(\tR\x05color\x12\x1c\n" + + "\n" + + "weight_g_m\x18\x04 \x01(\tR\bweightGM\x12\x1f\n" + + "\vsupplier_id\x18\x05 \x01(\tR\n" + + "supplierId\x12\x1f\n" + + "\vdye_factory\x18\x06 \x01(\tR\n" + + "dyeFactory\x12\x1b\n" + + "\timage_url\x18\a \x01(\tR\bimageUrl\x12\x16\n" + + "\x06remark\x18\b \x01(\tR\x06remark\x12\x16\n" + + "\x06status\x18\t \x01(\x03R\x06status\"(\n" + + "\rDeleteYarnReq\x12\x17\n" + + "\ayarn_id\x18\x01 \x01(\tR\x06yarnId\"%\n" + + "\n" + + "GetYarnReq\x12\x17\n" + + "\ayarn_id\x18\x01 \x01(\tR\x06yarnId\"\x94\x01\n" + + "\vListYarnReq\x12\x12\n" + + "\x04page\x18\x01 \x01(\x03R\x04page\x12\x1b\n" + + "\tpage_size\x18\x02 \x01(\x03R\bpageSize\x12\x1b\n" + + "\tyarn_name\x18\x03 \x01(\tR\byarnName\x12\x1f\n" + + "\vsupplier_id\x18\x04 \x01(\tR\n" + + "supplierId\x12\x16\n" + + "\x06status\x18\x05 \x01(\x03R\x06status\"M\n" + + "\fListYarnResp\x12\x14\n" + + "\x05total\x18\x01 \x01(\x03R\x05total\x12'\n" + + "\x04list\x18\x02 \x03(\v2\x13.inventory.YarnInfoR\x04list\"\xe2\x01\n" + + "\x11ProductBatchInput\x12\x1d\n" + + "\n" + + "yarn_ratio\x18\x01 \x01(\tR\tyarnRatio\x12%\n" + + "\x0fwarp_weight_g_m\x18\x02 \x01(\tR\fwarpWeightGM\x12%\n" + + "\x0fweft_weight_g_m\x18\x03 \x01(\tR\fweftWeightGM\x12-\n" + + "\x12production_process\x18\x04 \x01(\tR\x11productionProcess\x12\x16\n" + + "\x06remark\x18\x05 \x01(\tR\x06remark\x12\x19\n" + + "\bbatch_no\x18\x06 \x01(\tR\abatchNo\"\xf1\x02\n" + + "\x10ProductBatchInfo\x12\x19\n" + + "\bbatch_id\x18\x01 \x01(\tR\abatchId\x12\x1d\n" + + "\n" + + "product_id\x18\x02 \x01(\tR\tproductId\x12\x19\n" + + "\bbatch_no\x18\x03 \x01(\tR\abatchNo\x12\x1d\n" + + "\n" + + "yarn_ratio\x18\x04 \x01(\tR\tyarnRatio\x12%\n" + + "\x0fwarp_weight_g_m\x18\x05 \x01(\tR\fwarpWeightGM\x12%\n" + + "\x0fweft_weight_g_m\x18\x06 \x01(\tR\fweftWeightGM\x12-\n" + + "\x12production_process\x18\a \x01(\tR\x11productionProcess\x12\x16\n" + + "\x06remark\x18\b \x01(\tR\x06remark\x12\x16\n" + + "\x06status\x18\t \x01(\x03R\x06status\x12\x1d\n" + + "\n" + + "created_at\x18\n" + + " \x01(\tR\tcreatedAt\x12\x1d\n" + + "\n" + + "updated_at\x18\v \x01(\tR\tupdatedAt\"j\n" + + "\x15CreateProductBatchReq\x12\x1d\n" + + "\n" + + "product_id\x18\x01 \x01(\tR\tproductId\x122\n" + + "\x05batch\x18\x02 \x01(\v2\x1c.inventory.ProductBatchInputR\x05batch\"\x9d\x01\n" + + "\x15UpdateProductBatchReq\x12\x1d\n" + + "\n" + + "product_id\x18\x01 \x01(\tR\tproductId\x12\x19\n" + + "\bbatch_id\x18\x02 \x01(\tR\abatchId\x122\n" + + "\x05batch\x18\x03 \x01(\v2\x1c.inventory.ProductBatchInputR\x05batch\x12\x16\n" + + "\x06status\x18\x04 \x01(\x03R\x06status\"Q\n" + + "\x15DeleteProductBatchReq\x12\x1d\n" + + "\n" + + "product_id\x18\x01 \x01(\tR\tproductId\x12\x19\n" + + "\bbatch_id\x18\x02 \x01(\tR\abatchId\"4\n" + + "\x13ListProductBatchReq\x12\x1d\n" + + "\n" + + "product_id\x18\x01 \x01(\tR\tproductId\"G\n" + + "\x14ListProductBatchResp\x12/\n" + + "\x04list\x18\x01 \x03(\v2\x1b.inventory.ProductBatchInfoR\x04list\"\x86\x02\n" + "\rImportLogInfo\x12\x1b\n" + "\timport_id\x18\x01 \x01(\tR\bimportId\x12\x1b\n" + "\tfile_name\x18\x02 \x01(\tR\bfileName\x12\x1f\n" + @@ -4217,7 +5483,7 @@ const file_inventory_proto_rawDesc = "" + "\x04list\x18\x02 \x03(\v2\x1a.inventory.StockAdjustInfoR\x04list\"\x18\n" + "\x06IdResp\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\"\a\n" + - "\x05Empty2\x8d\x0f\n" + + "\x05Empty2\xe4\x13\n" + "\x10InventoryService\x12?\n" + "\rCreateProduct\x12\x1b.inventory.CreateProductReq\x1a\x11.inventory.IdResp\x12>\n" + "\rUpdateProduct\x12\x1b.inventory.UpdateProductReq\x1a\x10.inventory.Empty\x12>\n" + @@ -4227,7 +5493,19 @@ const file_inventory_proto_rawDesc = "" + "\vListProduct\x12\x19.inventory.ListProductReq\x1a\x1a.inventory.ListProductResp\x12F\n" + "\x0eGetProductTree\x12\x18.inventory.GetProductReq\x1a\x1a.inventory.ProductTreeResp\x12Y\n" + "\x12ListProductSummary\x12 .inventory.ListProductSummaryReq\x1a!.inventory.ListProductSummaryResp\x12P\n" + - "\x0fListColorDetail\x12\x1d.inventory.ListColorDetailReq\x1a\x1e.inventory.ListColorDetailResp\x12D\n" + + "\x0fListColorDetail\x12\x1d.inventory.ListColorDetailReq\x1a\x1e.inventory.ListColorDetailResp\x129\n" + + "\n" + + "CreateYarn\x12\x18.inventory.CreateYarnReq\x1a\x11.inventory.IdResp\x128\n" + + "\n" + + "UpdateYarn\x12\x18.inventory.UpdateYarnReq\x1a\x10.inventory.Empty\x128\n" + + "\n" + + "DeleteYarn\x12\x18.inventory.DeleteYarnReq\x1a\x10.inventory.Empty\x125\n" + + "\aGetYarn\x12\x15.inventory.GetYarnReq\x1a\x13.inventory.YarnInfo\x12;\n" + + "\bListYarn\x12\x16.inventory.ListYarnReq\x1a\x17.inventory.ListYarnResp\x12I\n" + + "\x12CreateProductBatch\x12 .inventory.CreateProductBatchReq\x1a\x11.inventory.IdResp\x12H\n" + + "\x12UpdateProductBatch\x12 .inventory.UpdateProductBatchReq\x1a\x10.inventory.Empty\x12H\n" + + "\x12DeleteProductBatch\x12 .inventory.DeleteProductBatchReq\x1a\x10.inventory.Empty\x12S\n" + + "\x10ListProductBatch\x12\x1e.inventory.ListProductBatchReq\x1a\x1f.inventory.ListProductBatchResp\x12D\n" + "\vListPanView\x12\x19.inventory.ListPanViewReq\x1a\x1a.inventory.ListPanViewResp\x12G\n" + "\fListBoltView\x12\x1a.inventory.ListBoltViewReq\x1a\x1b.inventory.ListBoltViewResp\x129\n" + "\bListPans\x12\x15.inventory.ListPanReq\x1a\x16.inventory.ListPanResp\x124\n" + @@ -4260,7 +5538,7 @@ func file_inventory_proto_rawDescGZIP() []byte { return file_inventory_proto_rawDescData } -var file_inventory_proto_msgTypes = make([]protoimpl.MessageInfo, 58) +var file_inventory_proto_msgTypes = make([]protoimpl.MessageInfo, 72) var file_inventory_proto_goTypes = []any{ (*ProductInfo)(nil), // 0: inventory.ProductInfo (*CreateProductReq)(nil), // 1: inventory.CreateProductReq @@ -4295,114 +5573,151 @@ var file_inventory_proto_goTypes = []any{ (*ImportProductResp)(nil), // 30: inventory.ImportProductResp (*ListImportLogReq)(nil), // 31: inventory.ListImportLogReq (*ListImportLogResp)(nil), // 32: inventory.ListImportLogResp - (*ImportLogInfo)(nil), // 33: inventory.ImportLogInfo - (*StockSummaryReq)(nil), // 34: inventory.StockSummaryReq - (*StockSummaryResp)(nil), // 35: inventory.StockSummaryResp - (*StockGroupReq)(nil), // 36: inventory.StockGroupReq - (*StockGroupItem)(nil), // 37: inventory.StockGroupItem - (*StockGroupResp)(nil), // 38: inventory.StockGroupResp - (*StockCheckInfo)(nil), // 39: inventory.StockCheckInfo - (*StockCheckDetailInfo)(nil), // 40: inventory.StockCheckDetailInfo - (*CreateStockCheckReq)(nil), // 41: inventory.CreateStockCheckReq - (*StockCheckDetailReq)(nil), // 42: inventory.StockCheckDetailReq - (*UpdateStockCheckReq)(nil), // 43: inventory.UpdateStockCheckReq - (*ConfirmStockCheckReq)(nil), // 44: inventory.ConfirmStockCheckReq - (*GetStockCheckReq)(nil), // 45: inventory.GetStockCheckReq - (*ListStockCheckReq)(nil), // 46: inventory.ListStockCheckReq - (*ListStockCheckResp)(nil), // 47: inventory.ListStockCheckResp - (*StockAdjustInfo)(nil), // 48: inventory.StockAdjustInfo - (*StockAdjustDetailInfo)(nil), // 49: inventory.StockAdjustDetailInfo - (*CreateStockAdjustReq)(nil), // 50: inventory.CreateStockAdjustReq - (*StockAdjustDetailReq)(nil), // 51: inventory.StockAdjustDetailReq - (*ApproveStockAdjustReq)(nil), // 52: inventory.ApproveStockAdjustReq - (*GetStockAdjustReq)(nil), // 53: inventory.GetStockAdjustReq - (*ListStockAdjustReq)(nil), // 54: inventory.ListStockAdjustReq - (*ListStockAdjustResp)(nil), // 55: inventory.ListStockAdjustResp - (*IdResp)(nil), // 56: inventory.IdResp - (*Empty)(nil), // 57: inventory.Empty + (*YarnInfo)(nil), // 33: inventory.YarnInfo + (*CreateYarnReq)(nil), // 34: inventory.CreateYarnReq + (*UpdateYarnReq)(nil), // 35: inventory.UpdateYarnReq + (*DeleteYarnReq)(nil), // 36: inventory.DeleteYarnReq + (*GetYarnReq)(nil), // 37: inventory.GetYarnReq + (*ListYarnReq)(nil), // 38: inventory.ListYarnReq + (*ListYarnResp)(nil), // 39: inventory.ListYarnResp + (*ProductBatchInput)(nil), // 40: inventory.ProductBatchInput + (*ProductBatchInfo)(nil), // 41: inventory.ProductBatchInfo + (*CreateProductBatchReq)(nil), // 42: inventory.CreateProductBatchReq + (*UpdateProductBatchReq)(nil), // 43: inventory.UpdateProductBatchReq + (*DeleteProductBatchReq)(nil), // 44: inventory.DeleteProductBatchReq + (*ListProductBatchReq)(nil), // 45: inventory.ListProductBatchReq + (*ListProductBatchResp)(nil), // 46: inventory.ListProductBatchResp + (*ImportLogInfo)(nil), // 47: inventory.ImportLogInfo + (*StockSummaryReq)(nil), // 48: inventory.StockSummaryReq + (*StockSummaryResp)(nil), // 49: inventory.StockSummaryResp + (*StockGroupReq)(nil), // 50: inventory.StockGroupReq + (*StockGroupItem)(nil), // 51: inventory.StockGroupItem + (*StockGroupResp)(nil), // 52: inventory.StockGroupResp + (*StockCheckInfo)(nil), // 53: inventory.StockCheckInfo + (*StockCheckDetailInfo)(nil), // 54: inventory.StockCheckDetailInfo + (*CreateStockCheckReq)(nil), // 55: inventory.CreateStockCheckReq + (*StockCheckDetailReq)(nil), // 56: inventory.StockCheckDetailReq + (*UpdateStockCheckReq)(nil), // 57: inventory.UpdateStockCheckReq + (*ConfirmStockCheckReq)(nil), // 58: inventory.ConfirmStockCheckReq + (*GetStockCheckReq)(nil), // 59: inventory.GetStockCheckReq + (*ListStockCheckReq)(nil), // 60: inventory.ListStockCheckReq + (*ListStockCheckResp)(nil), // 61: inventory.ListStockCheckResp + (*StockAdjustInfo)(nil), // 62: inventory.StockAdjustInfo + (*StockAdjustDetailInfo)(nil), // 63: inventory.StockAdjustDetailInfo + (*CreateStockAdjustReq)(nil), // 64: inventory.CreateStockAdjustReq + (*StockAdjustDetailReq)(nil), // 65: inventory.StockAdjustDetailReq + (*ApproveStockAdjustReq)(nil), // 66: inventory.ApproveStockAdjustReq + (*GetStockAdjustReq)(nil), // 67: inventory.GetStockAdjustReq + (*ListStockAdjustReq)(nil), // 68: inventory.ListStockAdjustReq + (*ListStockAdjustResp)(nil), // 69: inventory.ListStockAdjustResp + (*IdResp)(nil), // 70: inventory.IdResp + (*Empty)(nil), // 71: inventory.Empty } var file_inventory_proto_depIdxs = []int32{ 8, // 0: inventory.CreateProductReq.pans:type_name -> inventory.PanInput - 0, // 1: inventory.ListProductResp.list:type_name -> inventory.ProductInfo - 12, // 2: inventory.PanInfo.bolts:type_name -> inventory.BoltInfo - 7, // 3: inventory.ListPanResp.list:type_name -> inventory.PanInfo - 8, // 4: inventory.SavePansReq.pans:type_name -> inventory.PanInput - 12, // 5: inventory.ListBoltResp.list:type_name -> inventory.BoltInfo - 0, // 6: inventory.ProductTreeResp.product:type_name -> inventory.ProductInfo - 7, // 7: inventory.ProductTreeResp.pans:type_name -> inventory.PanInfo - 17, // 8: inventory.ListProductSummaryResp.list:type_name -> inventory.ProductSummaryItem - 20, // 9: inventory.ListColorDetailResp.list:type_name -> inventory.ColorDetailItem - 23, // 10: inventory.ListPanViewResp.list:type_name -> inventory.PanListItem - 26, // 11: inventory.ListBoltViewResp.list:type_name -> inventory.BoltListItem - 1, // 12: inventory.ImportProductReq.products:type_name -> inventory.CreateProductReq - 33, // 13: inventory.ListImportLogResp.list:type_name -> inventory.ImportLogInfo - 37, // 14: inventory.StockGroupResp.list:type_name -> inventory.StockGroupItem - 40, // 15: inventory.StockCheckInfo.details:type_name -> inventory.StockCheckDetailInfo - 42, // 16: inventory.CreateStockCheckReq.details:type_name -> inventory.StockCheckDetailReq - 42, // 17: inventory.UpdateStockCheckReq.details:type_name -> inventory.StockCheckDetailReq - 39, // 18: inventory.ListStockCheckResp.list:type_name -> inventory.StockCheckInfo - 49, // 19: inventory.StockAdjustInfo.details:type_name -> inventory.StockAdjustDetailInfo - 51, // 20: inventory.CreateStockAdjustReq.details:type_name -> inventory.StockAdjustDetailReq - 48, // 21: inventory.ListStockAdjustResp.list:type_name -> inventory.StockAdjustInfo - 1, // 22: inventory.InventoryService.CreateProduct:input_type -> inventory.CreateProductReq - 2, // 23: inventory.InventoryService.UpdateProduct:input_type -> inventory.UpdateProductReq - 3, // 24: inventory.InventoryService.DeleteProduct:input_type -> inventory.DeleteProductReq - 4, // 25: inventory.InventoryService.GetProduct:input_type -> inventory.GetProductReq - 5, // 26: inventory.InventoryService.ListProduct:input_type -> inventory.ListProductReq - 4, // 27: inventory.InventoryService.GetProductTree:input_type -> inventory.GetProductReq - 18, // 28: inventory.InventoryService.ListProductSummary:input_type -> inventory.ListProductSummaryReq - 21, // 29: inventory.InventoryService.ListColorDetail:input_type -> inventory.ListColorDetailReq - 24, // 30: inventory.InventoryService.ListPanView:input_type -> inventory.ListPanViewReq - 27, // 31: inventory.InventoryService.ListBoltView:input_type -> inventory.ListBoltViewReq - 9, // 32: inventory.InventoryService.ListPans:input_type -> inventory.ListPanReq - 11, // 33: inventory.InventoryService.SavePans:input_type -> inventory.SavePansReq - 13, // 34: inventory.InventoryService.ListBolts:input_type -> inventory.ListBoltReq - 15, // 35: inventory.InventoryService.SaveBolts:input_type -> inventory.SaveBoltsReq - 29, // 36: inventory.InventoryService.ImportProducts:input_type -> inventory.ImportProductReq - 31, // 37: inventory.InventoryService.ListImportLog:input_type -> inventory.ListImportLogReq - 34, // 38: inventory.InventoryService.GetStockSummary:input_type -> inventory.StockSummaryReq - 36, // 39: inventory.InventoryService.GetStockGroup:input_type -> inventory.StockGroupReq - 41, // 40: inventory.InventoryService.CreateStockCheck:input_type -> inventory.CreateStockCheckReq - 43, // 41: inventory.InventoryService.UpdateStockCheck:input_type -> inventory.UpdateStockCheckReq - 44, // 42: inventory.InventoryService.ConfirmStockCheck:input_type -> inventory.ConfirmStockCheckReq - 45, // 43: inventory.InventoryService.GetStockCheck:input_type -> inventory.GetStockCheckReq - 46, // 44: inventory.InventoryService.ListStockCheck:input_type -> inventory.ListStockCheckReq - 50, // 45: inventory.InventoryService.CreateStockAdjust:input_type -> inventory.CreateStockAdjustReq - 52, // 46: inventory.InventoryService.ApproveStockAdjust:input_type -> inventory.ApproveStockAdjustReq - 53, // 47: inventory.InventoryService.GetStockAdjust:input_type -> inventory.GetStockAdjustReq - 54, // 48: inventory.InventoryService.ListStockAdjust:input_type -> inventory.ListStockAdjustReq - 56, // 49: inventory.InventoryService.CreateProduct:output_type -> inventory.IdResp - 57, // 50: inventory.InventoryService.UpdateProduct:output_type -> inventory.Empty - 57, // 51: inventory.InventoryService.DeleteProduct:output_type -> inventory.Empty - 0, // 52: inventory.InventoryService.GetProduct:output_type -> inventory.ProductInfo - 6, // 53: inventory.InventoryService.ListProduct:output_type -> inventory.ListProductResp - 16, // 54: inventory.InventoryService.GetProductTree:output_type -> inventory.ProductTreeResp - 19, // 55: inventory.InventoryService.ListProductSummary:output_type -> inventory.ListProductSummaryResp - 22, // 56: inventory.InventoryService.ListColorDetail:output_type -> inventory.ListColorDetailResp - 25, // 57: inventory.InventoryService.ListPanView:output_type -> inventory.ListPanViewResp - 28, // 58: inventory.InventoryService.ListBoltView:output_type -> inventory.ListBoltViewResp - 10, // 59: inventory.InventoryService.ListPans:output_type -> inventory.ListPanResp - 57, // 60: inventory.InventoryService.SavePans:output_type -> inventory.Empty - 14, // 61: inventory.InventoryService.ListBolts:output_type -> inventory.ListBoltResp - 57, // 62: inventory.InventoryService.SaveBolts:output_type -> inventory.Empty - 30, // 63: inventory.InventoryService.ImportProducts:output_type -> inventory.ImportProductResp - 32, // 64: inventory.InventoryService.ListImportLog:output_type -> inventory.ListImportLogResp - 35, // 65: inventory.InventoryService.GetStockSummary:output_type -> inventory.StockSummaryResp - 38, // 66: inventory.InventoryService.GetStockGroup:output_type -> inventory.StockGroupResp - 56, // 67: inventory.InventoryService.CreateStockCheck:output_type -> inventory.IdResp - 57, // 68: inventory.InventoryService.UpdateStockCheck:output_type -> inventory.Empty - 57, // 69: inventory.InventoryService.ConfirmStockCheck:output_type -> inventory.Empty - 39, // 70: inventory.InventoryService.GetStockCheck:output_type -> inventory.StockCheckInfo - 47, // 71: inventory.InventoryService.ListStockCheck:output_type -> inventory.ListStockCheckResp - 56, // 72: inventory.InventoryService.CreateStockAdjust:output_type -> inventory.IdResp - 57, // 73: inventory.InventoryService.ApproveStockAdjust:output_type -> inventory.Empty - 48, // 74: inventory.InventoryService.GetStockAdjust:output_type -> inventory.StockAdjustInfo - 55, // 75: inventory.InventoryService.ListStockAdjust:output_type -> inventory.ListStockAdjustResp - 49, // [49:76] is the sub-list for method output_type - 22, // [22:49] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 40, // 1: inventory.CreateProductReq.initial_batch:type_name -> inventory.ProductBatchInput + 0, // 2: inventory.ListProductResp.list:type_name -> inventory.ProductInfo + 12, // 3: inventory.PanInfo.bolts:type_name -> inventory.BoltInfo + 7, // 4: inventory.ListPanResp.list:type_name -> inventory.PanInfo + 8, // 5: inventory.SavePansReq.pans:type_name -> inventory.PanInput + 12, // 6: inventory.ListBoltResp.list:type_name -> inventory.BoltInfo + 0, // 7: inventory.ProductTreeResp.product:type_name -> inventory.ProductInfo + 7, // 8: inventory.ProductTreeResp.pans:type_name -> inventory.PanInfo + 17, // 9: inventory.ListProductSummaryResp.list:type_name -> inventory.ProductSummaryItem + 20, // 10: inventory.ListColorDetailResp.list:type_name -> inventory.ColorDetailItem + 23, // 11: inventory.ListPanViewResp.list:type_name -> inventory.PanListItem + 26, // 12: inventory.ListBoltViewResp.list:type_name -> inventory.BoltListItem + 1, // 13: inventory.ImportProductReq.products:type_name -> inventory.CreateProductReq + 47, // 14: inventory.ListImportLogResp.list:type_name -> inventory.ImportLogInfo + 33, // 15: inventory.ListYarnResp.list:type_name -> inventory.YarnInfo + 40, // 16: inventory.CreateProductBatchReq.batch:type_name -> inventory.ProductBatchInput + 40, // 17: inventory.UpdateProductBatchReq.batch:type_name -> inventory.ProductBatchInput + 41, // 18: inventory.ListProductBatchResp.list:type_name -> inventory.ProductBatchInfo + 51, // 19: inventory.StockGroupResp.list:type_name -> inventory.StockGroupItem + 54, // 20: inventory.StockCheckInfo.details:type_name -> inventory.StockCheckDetailInfo + 56, // 21: inventory.CreateStockCheckReq.details:type_name -> inventory.StockCheckDetailReq + 56, // 22: inventory.UpdateStockCheckReq.details:type_name -> inventory.StockCheckDetailReq + 53, // 23: inventory.ListStockCheckResp.list:type_name -> inventory.StockCheckInfo + 63, // 24: inventory.StockAdjustInfo.details:type_name -> inventory.StockAdjustDetailInfo + 65, // 25: inventory.CreateStockAdjustReq.details:type_name -> inventory.StockAdjustDetailReq + 62, // 26: inventory.ListStockAdjustResp.list:type_name -> inventory.StockAdjustInfo + 1, // 27: inventory.InventoryService.CreateProduct:input_type -> inventory.CreateProductReq + 2, // 28: inventory.InventoryService.UpdateProduct:input_type -> inventory.UpdateProductReq + 3, // 29: inventory.InventoryService.DeleteProduct:input_type -> inventory.DeleteProductReq + 4, // 30: inventory.InventoryService.GetProduct:input_type -> inventory.GetProductReq + 5, // 31: inventory.InventoryService.ListProduct:input_type -> inventory.ListProductReq + 4, // 32: inventory.InventoryService.GetProductTree:input_type -> inventory.GetProductReq + 18, // 33: inventory.InventoryService.ListProductSummary:input_type -> inventory.ListProductSummaryReq + 21, // 34: inventory.InventoryService.ListColorDetail:input_type -> inventory.ListColorDetailReq + 34, // 35: inventory.InventoryService.CreateYarn:input_type -> inventory.CreateYarnReq + 35, // 36: inventory.InventoryService.UpdateYarn:input_type -> inventory.UpdateYarnReq + 36, // 37: inventory.InventoryService.DeleteYarn:input_type -> inventory.DeleteYarnReq + 37, // 38: inventory.InventoryService.GetYarn:input_type -> inventory.GetYarnReq + 38, // 39: inventory.InventoryService.ListYarn:input_type -> inventory.ListYarnReq + 42, // 40: inventory.InventoryService.CreateProductBatch:input_type -> inventory.CreateProductBatchReq + 43, // 41: inventory.InventoryService.UpdateProductBatch:input_type -> inventory.UpdateProductBatchReq + 44, // 42: inventory.InventoryService.DeleteProductBatch:input_type -> inventory.DeleteProductBatchReq + 45, // 43: inventory.InventoryService.ListProductBatch:input_type -> inventory.ListProductBatchReq + 24, // 44: inventory.InventoryService.ListPanView:input_type -> inventory.ListPanViewReq + 27, // 45: inventory.InventoryService.ListBoltView:input_type -> inventory.ListBoltViewReq + 9, // 46: inventory.InventoryService.ListPans:input_type -> inventory.ListPanReq + 11, // 47: inventory.InventoryService.SavePans:input_type -> inventory.SavePansReq + 13, // 48: inventory.InventoryService.ListBolts:input_type -> inventory.ListBoltReq + 15, // 49: inventory.InventoryService.SaveBolts:input_type -> inventory.SaveBoltsReq + 29, // 50: inventory.InventoryService.ImportProducts:input_type -> inventory.ImportProductReq + 31, // 51: inventory.InventoryService.ListImportLog:input_type -> inventory.ListImportLogReq + 48, // 52: inventory.InventoryService.GetStockSummary:input_type -> inventory.StockSummaryReq + 50, // 53: inventory.InventoryService.GetStockGroup:input_type -> inventory.StockGroupReq + 55, // 54: inventory.InventoryService.CreateStockCheck:input_type -> inventory.CreateStockCheckReq + 57, // 55: inventory.InventoryService.UpdateStockCheck:input_type -> inventory.UpdateStockCheckReq + 58, // 56: inventory.InventoryService.ConfirmStockCheck:input_type -> inventory.ConfirmStockCheckReq + 59, // 57: inventory.InventoryService.GetStockCheck:input_type -> inventory.GetStockCheckReq + 60, // 58: inventory.InventoryService.ListStockCheck:input_type -> inventory.ListStockCheckReq + 64, // 59: inventory.InventoryService.CreateStockAdjust:input_type -> inventory.CreateStockAdjustReq + 66, // 60: inventory.InventoryService.ApproveStockAdjust:input_type -> inventory.ApproveStockAdjustReq + 67, // 61: inventory.InventoryService.GetStockAdjust:input_type -> inventory.GetStockAdjustReq + 68, // 62: inventory.InventoryService.ListStockAdjust:input_type -> inventory.ListStockAdjustReq + 70, // 63: inventory.InventoryService.CreateProduct:output_type -> inventory.IdResp + 71, // 64: inventory.InventoryService.UpdateProduct:output_type -> inventory.Empty + 71, // 65: inventory.InventoryService.DeleteProduct:output_type -> inventory.Empty + 0, // 66: inventory.InventoryService.GetProduct:output_type -> inventory.ProductInfo + 6, // 67: inventory.InventoryService.ListProduct:output_type -> inventory.ListProductResp + 16, // 68: inventory.InventoryService.GetProductTree:output_type -> inventory.ProductTreeResp + 19, // 69: inventory.InventoryService.ListProductSummary:output_type -> inventory.ListProductSummaryResp + 22, // 70: inventory.InventoryService.ListColorDetail:output_type -> inventory.ListColorDetailResp + 70, // 71: inventory.InventoryService.CreateYarn:output_type -> inventory.IdResp + 71, // 72: inventory.InventoryService.UpdateYarn:output_type -> inventory.Empty + 71, // 73: inventory.InventoryService.DeleteYarn:output_type -> inventory.Empty + 33, // 74: inventory.InventoryService.GetYarn:output_type -> inventory.YarnInfo + 39, // 75: inventory.InventoryService.ListYarn:output_type -> inventory.ListYarnResp + 70, // 76: inventory.InventoryService.CreateProductBatch:output_type -> inventory.IdResp + 71, // 77: inventory.InventoryService.UpdateProductBatch:output_type -> inventory.Empty + 71, // 78: inventory.InventoryService.DeleteProductBatch:output_type -> inventory.Empty + 46, // 79: inventory.InventoryService.ListProductBatch:output_type -> inventory.ListProductBatchResp + 25, // 80: inventory.InventoryService.ListPanView:output_type -> inventory.ListPanViewResp + 28, // 81: inventory.InventoryService.ListBoltView:output_type -> inventory.ListBoltViewResp + 10, // 82: inventory.InventoryService.ListPans:output_type -> inventory.ListPanResp + 71, // 83: inventory.InventoryService.SavePans:output_type -> inventory.Empty + 14, // 84: inventory.InventoryService.ListBolts:output_type -> inventory.ListBoltResp + 71, // 85: inventory.InventoryService.SaveBolts:output_type -> inventory.Empty + 30, // 86: inventory.InventoryService.ImportProducts:output_type -> inventory.ImportProductResp + 32, // 87: inventory.InventoryService.ListImportLog:output_type -> inventory.ListImportLogResp + 49, // 88: inventory.InventoryService.GetStockSummary:output_type -> inventory.StockSummaryResp + 52, // 89: inventory.InventoryService.GetStockGroup:output_type -> inventory.StockGroupResp + 70, // 90: inventory.InventoryService.CreateStockCheck:output_type -> inventory.IdResp + 71, // 91: inventory.InventoryService.UpdateStockCheck:output_type -> inventory.Empty + 71, // 92: inventory.InventoryService.ConfirmStockCheck:output_type -> inventory.Empty + 53, // 93: inventory.InventoryService.GetStockCheck:output_type -> inventory.StockCheckInfo + 61, // 94: inventory.InventoryService.ListStockCheck:output_type -> inventory.ListStockCheckResp + 70, // 95: inventory.InventoryService.CreateStockAdjust:output_type -> inventory.IdResp + 71, // 96: inventory.InventoryService.ApproveStockAdjust:output_type -> inventory.Empty + 62, // 97: inventory.InventoryService.GetStockAdjust:output_type -> inventory.StockAdjustInfo + 69, // 98: inventory.InventoryService.ListStockAdjust:output_type -> inventory.ListStockAdjustResp + 63, // [63:99] is the sub-list for method output_type + 27, // [27:63] is the sub-list for method input_type + 27, // [27:27] is the sub-list for extension type_name + 27, // [27:27] is the sub-list for extension extendee + 0, // [0:27] is the sub-list for field type_name } func init() { file_inventory_proto_init() } @@ -4416,7 +5731,7 @@ func file_inventory_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_inventory_proto_rawDesc), len(file_inventory_proto_rawDesc)), NumEnums: 0, - NumMessages: 58, + NumMessages: 72, NumExtensions: 0, NumServices: 1, }, diff --git a/rpc/inventory/pb/inventory_grpc.pb.go b/rpc/inventory/pb/inventory_grpc.pb.go index 4afbe23..53b285b 100644 --- a/rpc/inventory/pb/inventory_grpc.pb.go +++ b/rpc/inventory/pb/inventory_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.29.3 +// - protoc-gen-go-grpc v1.6.2 +// - protoc v7.34.1 // source: inventory.proto package pb @@ -27,6 +27,15 @@ const ( InventoryService_GetProductTree_FullMethodName = "/inventory.InventoryService/GetProductTree" InventoryService_ListProductSummary_FullMethodName = "/inventory.InventoryService/ListProductSummary" InventoryService_ListColorDetail_FullMethodName = "/inventory.InventoryService/ListColorDetail" + InventoryService_CreateYarn_FullMethodName = "/inventory.InventoryService/CreateYarn" + InventoryService_UpdateYarn_FullMethodName = "/inventory.InventoryService/UpdateYarn" + InventoryService_DeleteYarn_FullMethodName = "/inventory.InventoryService/DeleteYarn" + InventoryService_GetYarn_FullMethodName = "/inventory.InventoryService/GetYarn" + InventoryService_ListYarn_FullMethodName = "/inventory.InventoryService/ListYarn" + InventoryService_CreateProductBatch_FullMethodName = "/inventory.InventoryService/CreateProductBatch" + InventoryService_UpdateProductBatch_FullMethodName = "/inventory.InventoryService/UpdateProductBatch" + InventoryService_DeleteProductBatch_FullMethodName = "/inventory.InventoryService/DeleteProductBatch" + InventoryService_ListProductBatch_FullMethodName = "/inventory.InventoryService/ListProductBatch" InventoryService_ListPanView_FullMethodName = "/inventory.InventoryService/ListPanView" InventoryService_ListBoltView_FullMethodName = "/inventory.InventoryService/ListBoltView" InventoryService_ListPans_FullMethodName = "/inventory.InventoryService/ListPans" @@ -64,6 +73,17 @@ type InventoryServiceClient interface { 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) + // Yarn CRUD + CreateYarn(ctx context.Context, in *CreateYarnReq, opts ...grpc.CallOption) (*IdResp, error) + UpdateYarn(ctx context.Context, in *UpdateYarnReq, opts ...grpc.CallOption) (*Empty, error) + DeleteYarn(ctx context.Context, in *DeleteYarnReq, opts ...grpc.CallOption) (*Empty, error) + GetYarn(ctx context.Context, in *GetYarnReq, opts ...grpc.CallOption) (*YarnInfo, error) + ListYarn(ctx context.Context, in *ListYarnReq, opts ...grpc.CallOption) (*ListYarnResp, error) + // Product Batch CRUD + CreateProductBatch(ctx context.Context, in *CreateProductBatchReq, opts ...grpc.CallOption) (*IdResp, error) + UpdateProductBatch(ctx context.Context, in *UpdateProductBatchReq, opts ...grpc.CallOption) (*Empty, error) + DeleteProductBatch(ctx context.Context, in *DeleteProductBatchReq, opts ...grpc.CallOption) (*Empty, error) + ListProductBatch(ctx context.Context, in *ListProductBatchReq, opts ...grpc.CallOption) (*ListProductBatchResp, 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) @@ -180,6 +200,96 @@ func (c *inventoryServiceClient) ListColorDetail(ctx context.Context, in *ListCo return out, nil } +func (c *inventoryServiceClient) CreateYarn(ctx context.Context, in *CreateYarnReq, opts ...grpc.CallOption) (*IdResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(IdResp) + err := c.cc.Invoke(ctx, InventoryService_CreateYarn_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) UpdateYarn(ctx context.Context, in *UpdateYarnReq, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, InventoryService_UpdateYarn_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) DeleteYarn(ctx context.Context, in *DeleteYarnReq, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, InventoryService_DeleteYarn_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) GetYarn(ctx context.Context, in *GetYarnReq, opts ...grpc.CallOption) (*YarnInfo, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(YarnInfo) + err := c.cc.Invoke(ctx, InventoryService_GetYarn_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) ListYarn(ctx context.Context, in *ListYarnReq, opts ...grpc.CallOption) (*ListYarnResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListYarnResp) + err := c.cc.Invoke(ctx, InventoryService_ListYarn_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) CreateProductBatch(ctx context.Context, in *CreateProductBatchReq, opts ...grpc.CallOption) (*IdResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(IdResp) + err := c.cc.Invoke(ctx, InventoryService_CreateProductBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) UpdateProductBatch(ctx context.Context, in *UpdateProductBatchReq, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, InventoryService_UpdateProductBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) DeleteProductBatch(ctx context.Context, in *DeleteProductBatchReq, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, InventoryService_DeleteProductBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) ListProductBatch(ctx context.Context, in *ListProductBatchReq, opts ...grpc.CallOption) (*ListProductBatchResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListProductBatchResp) + err := c.cc.Invoke(ctx, InventoryService_ListProductBatch_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) @@ -386,6 +496,17 @@ type InventoryServiceServer interface { ListProductSummary(context.Context, *ListProductSummaryReq) (*ListProductSummaryResp, error) // Color Detail (panel 2) ListColorDetail(context.Context, *ListColorDetailReq) (*ListColorDetailResp, error) + // Yarn CRUD + CreateYarn(context.Context, *CreateYarnReq) (*IdResp, error) + UpdateYarn(context.Context, *UpdateYarnReq) (*Empty, error) + DeleteYarn(context.Context, *DeleteYarnReq) (*Empty, error) + GetYarn(context.Context, *GetYarnReq) (*YarnInfo, error) + ListYarn(context.Context, *ListYarnReq) (*ListYarnResp, error) + // Product Batch CRUD + CreateProductBatch(context.Context, *CreateProductBatchReq) (*IdResp, error) + UpdateProductBatch(context.Context, *UpdateProductBatchReq) (*Empty, error) + DeleteProductBatch(context.Context, *DeleteProductBatchReq) (*Empty, error) + ListProductBatch(context.Context, *ListProductBatchReq) (*ListProductBatchResp, error) // Pan / Bolt list views (dimension panels) ListPanView(context.Context, *ListPanViewReq) (*ListPanViewResp, error) ListBoltView(context.Context, *ListBoltViewReq) (*ListBoltViewResp, error) @@ -423,85 +544,112 @@ type InventoryServiceServer interface { type UnimplementedInventoryServiceServer struct{} func (UnimplementedInventoryServiceServer) CreateProduct(context.Context, *CreateProductReq) (*IdResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateProduct not implemented") + return nil, status.Error(codes.Unimplemented, "method CreateProduct not implemented") } func (UnimplementedInventoryServiceServer) UpdateProduct(context.Context, *UpdateProductReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateProduct not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateProduct not implemented") } func (UnimplementedInventoryServiceServer) DeleteProduct(context.Context, *DeleteProductReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteProduct not implemented") + return nil, status.Error(codes.Unimplemented, "method DeleteProduct not implemented") } func (UnimplementedInventoryServiceServer) GetProduct(context.Context, *GetProductReq) (*ProductInfo, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetProduct not implemented") + return nil, status.Error(codes.Unimplemented, "method GetProduct not implemented") } func (UnimplementedInventoryServiceServer) ListProduct(context.Context, *ListProductReq) (*ListProductResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListProduct not implemented") + return nil, status.Error(codes.Unimplemented, "method ListProduct not implemented") } func (UnimplementedInventoryServiceServer) GetProductTree(context.Context, *GetProductReq) (*ProductTreeResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetProductTree not implemented") + return nil, status.Error(codes.Unimplemented, "method GetProductTree not implemented") } func (UnimplementedInventoryServiceServer) ListProductSummary(context.Context, *ListProductSummaryReq) (*ListProductSummaryResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListProductSummary not implemented") + return nil, status.Error(codes.Unimplemented, "method ListProductSummary not implemented") } func (UnimplementedInventoryServiceServer) ListColorDetail(context.Context, *ListColorDetailReq) (*ListColorDetailResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListColorDetail not implemented") + return nil, status.Error(codes.Unimplemented, "method ListColorDetail not implemented") +} +func (UnimplementedInventoryServiceServer) CreateYarn(context.Context, *CreateYarnReq) (*IdResp, error) { + return nil, status.Error(codes.Unimplemented, "method CreateYarn not implemented") +} +func (UnimplementedInventoryServiceServer) UpdateYarn(context.Context, *UpdateYarnReq) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateYarn not implemented") +} +func (UnimplementedInventoryServiceServer) DeleteYarn(context.Context, *DeleteYarnReq) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteYarn not implemented") +} +func (UnimplementedInventoryServiceServer) GetYarn(context.Context, *GetYarnReq) (*YarnInfo, error) { + return nil, status.Error(codes.Unimplemented, "method GetYarn not implemented") +} +func (UnimplementedInventoryServiceServer) ListYarn(context.Context, *ListYarnReq) (*ListYarnResp, error) { + return nil, status.Error(codes.Unimplemented, "method ListYarn not implemented") +} +func (UnimplementedInventoryServiceServer) CreateProductBatch(context.Context, *CreateProductBatchReq) (*IdResp, error) { + return nil, status.Error(codes.Unimplemented, "method CreateProductBatch not implemented") +} +func (UnimplementedInventoryServiceServer) UpdateProductBatch(context.Context, *UpdateProductBatchReq) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateProductBatch not implemented") +} +func (UnimplementedInventoryServiceServer) DeleteProductBatch(context.Context, *DeleteProductBatchReq) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteProductBatch not implemented") +} +func (UnimplementedInventoryServiceServer) ListProductBatch(context.Context, *ListProductBatchReq) (*ListProductBatchResp, error) { + return nil, status.Error(codes.Unimplemented, "method ListProductBatch not implemented") } func (UnimplementedInventoryServiceServer) ListPanView(context.Context, *ListPanViewReq) (*ListPanViewResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListPanView not implemented") + return nil, status.Error(codes.Unimplemented, "method ListPanView not implemented") } func (UnimplementedInventoryServiceServer) ListBoltView(context.Context, *ListBoltViewReq) (*ListBoltViewResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListBoltView not implemented") + return nil, status.Error(codes.Unimplemented, "method ListBoltView not implemented") } func (UnimplementedInventoryServiceServer) ListPans(context.Context, *ListPanReq) (*ListPanResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListPans not implemented") + return nil, status.Error(codes.Unimplemented, "method ListPans not implemented") } func (UnimplementedInventoryServiceServer) SavePans(context.Context, *SavePansReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method SavePans not implemented") + return nil, status.Error(codes.Unimplemented, "method SavePans not implemented") } func (UnimplementedInventoryServiceServer) ListBolts(context.Context, *ListBoltReq) (*ListBoltResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListBolts not implemented") + return nil, status.Error(codes.Unimplemented, "method ListBolts not implemented") } func (UnimplementedInventoryServiceServer) SaveBolts(context.Context, *SaveBoltsReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method SaveBolts not implemented") + return nil, status.Error(codes.Unimplemented, "method SaveBolts not implemented") } func (UnimplementedInventoryServiceServer) ImportProducts(context.Context, *ImportProductReq) (*ImportProductResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ImportProducts not implemented") + return nil, status.Error(codes.Unimplemented, "method ImportProducts not implemented") } func (UnimplementedInventoryServiceServer) ListImportLog(context.Context, *ListImportLogReq) (*ListImportLogResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListImportLog not implemented") + return nil, status.Error(codes.Unimplemented, "method ListImportLog not implemented") } func (UnimplementedInventoryServiceServer) GetStockSummary(context.Context, *StockSummaryReq) (*StockSummaryResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetStockSummary not implemented") + return nil, status.Error(codes.Unimplemented, "method GetStockSummary not implemented") } func (UnimplementedInventoryServiceServer) GetStockGroup(context.Context, *StockGroupReq) (*StockGroupResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetStockGroup not implemented") + return nil, status.Error(codes.Unimplemented, "method GetStockGroup not implemented") } func (UnimplementedInventoryServiceServer) CreateStockCheck(context.Context, *CreateStockCheckReq) (*IdResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateStockCheck not implemented") + return nil, status.Error(codes.Unimplemented, "method CreateStockCheck not implemented") } func (UnimplementedInventoryServiceServer) UpdateStockCheck(context.Context, *UpdateStockCheckReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateStockCheck not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateStockCheck not implemented") } func (UnimplementedInventoryServiceServer) ConfirmStockCheck(context.Context, *ConfirmStockCheckReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConfirmStockCheck not implemented") + return nil, status.Error(codes.Unimplemented, "method ConfirmStockCheck not implemented") } func (UnimplementedInventoryServiceServer) GetStockCheck(context.Context, *GetStockCheckReq) (*StockCheckInfo, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetStockCheck not implemented") + return nil, status.Error(codes.Unimplemented, "method GetStockCheck not implemented") } func (UnimplementedInventoryServiceServer) ListStockCheck(context.Context, *ListStockCheckReq) (*ListStockCheckResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListStockCheck not implemented") + return nil, status.Error(codes.Unimplemented, "method ListStockCheck not implemented") } func (UnimplementedInventoryServiceServer) CreateStockAdjust(context.Context, *CreateStockAdjustReq) (*IdResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateStockAdjust not implemented") + return nil, status.Error(codes.Unimplemented, "method CreateStockAdjust not implemented") } func (UnimplementedInventoryServiceServer) ApproveStockAdjust(context.Context, *ApproveStockAdjustReq) (*Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method ApproveStockAdjust not implemented") + return nil, status.Error(codes.Unimplemented, "method ApproveStockAdjust not implemented") } func (UnimplementedInventoryServiceServer) GetStockAdjust(context.Context, *GetStockAdjustReq) (*StockAdjustInfo, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetStockAdjust not implemented") + return nil, status.Error(codes.Unimplemented, "method GetStockAdjust not implemented") } func (UnimplementedInventoryServiceServer) ListStockAdjust(context.Context, *ListStockAdjustReq) (*ListStockAdjustResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListStockAdjust not implemented") + return nil, status.Error(codes.Unimplemented, "method ListStockAdjust not implemented") } func (UnimplementedInventoryServiceServer) mustEmbedUnimplementedInventoryServiceServer() {} func (UnimplementedInventoryServiceServer) testEmbeddedByValue() {} @@ -514,7 +662,7 @@ type UnsafeInventoryServiceServer interface { } func RegisterInventoryServiceServer(s grpc.ServiceRegistrar, srv InventoryServiceServer) { - // If the following call pancis, it indicates UnimplementedInventoryServiceServer was + // If the following call panics, 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. @@ -668,6 +816,168 @@ func _InventoryService_ListColorDetail_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } +func _InventoryService_CreateYarn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateYarnReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).CreateYarn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_CreateYarn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).CreateYarn(ctx, req.(*CreateYarnReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_UpdateYarn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateYarnReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).UpdateYarn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_UpdateYarn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).UpdateYarn(ctx, req.(*UpdateYarnReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_DeleteYarn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteYarnReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).DeleteYarn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_DeleteYarn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).DeleteYarn(ctx, req.(*DeleteYarnReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_GetYarn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetYarnReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).GetYarn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_GetYarn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).GetYarn(ctx, req.(*GetYarnReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_ListYarn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListYarnReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).ListYarn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_ListYarn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).ListYarn(ctx, req.(*ListYarnReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_CreateProductBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateProductBatchReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).CreateProductBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_CreateProductBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).CreateProductBatch(ctx, req.(*CreateProductBatchReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_UpdateProductBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateProductBatchReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).UpdateProductBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_UpdateProductBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).UpdateProductBatch(ctx, req.(*UpdateProductBatchReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_DeleteProductBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteProductBatchReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).DeleteProductBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_DeleteProductBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).DeleteProductBatch(ctx, req.(*DeleteProductBatchReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_ListProductBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListProductBatchReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).ListProductBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_ListProductBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).ListProductBatch(ctx, req.(*ListProductBatchReq)) + } + 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 { @@ -1049,6 +1359,42 @@ var InventoryService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListColorDetail", Handler: _InventoryService_ListColorDetail_Handler, }, + { + MethodName: "CreateYarn", + Handler: _InventoryService_CreateYarn_Handler, + }, + { + MethodName: "UpdateYarn", + Handler: _InventoryService_UpdateYarn_Handler, + }, + { + MethodName: "DeleteYarn", + Handler: _InventoryService_DeleteYarn_Handler, + }, + { + MethodName: "GetYarn", + Handler: _InventoryService_GetYarn_Handler, + }, + { + MethodName: "ListYarn", + Handler: _InventoryService_ListYarn_Handler, + }, + { + MethodName: "CreateProductBatch", + Handler: _InventoryService_CreateProductBatch_Handler, + }, + { + MethodName: "UpdateProductBatch", + Handler: _InventoryService_UpdateProductBatch_Handler, + }, + { + MethodName: "DeleteProductBatch", + Handler: _InventoryService_DeleteProductBatch_Handler, + }, + { + MethodName: "ListProductBatch", + Handler: _InventoryService_ListProductBatch_Handler, + }, { MethodName: "ListPanView", Handler: _InventoryService_ListPanView_Handler,