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>
This commit is contained in:
parent
bb212aff36
commit
e3f6fa236d
@ -210,16 +210,14 @@ CREATE TABLE `crm_data_migration_log` (
|
|||||||
|
|
||||||
CREATE TABLE `inv_product` (
|
CREATE TABLE `inv_product` (
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`tenant_id` VARCHAR(32) NOT NULL DEFAULT 't_default_001',
|
||||||
`product_id` VARCHAR(32) NOT NULL,
|
`product_id` VARCHAR(32) NOT NULL,
|
||||||
`product_name` VARCHAR(100) NOT NULL,
|
`product_name` VARCHAR(100) NOT NULL,
|
||||||
`image_url` VARCHAR(255) NOT NULL DEFAULT '',
|
`image_url` VARCHAR(255) NOT NULL DEFAULT '',
|
||||||
`spec` VARCHAR(100) NOT NULL DEFAULT '',
|
`spec` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
`color` VARCHAR(50) NOT NULL DEFAULT '',
|
`color` VARCHAR(50) NOT NULL DEFAULT '本色',
|
||||||
`unit_pieces` INT NOT NULL DEFAULT 0,
|
`color_no` VARCHAR(20) NOT NULL DEFAULT '',
|
||||||
`unit_rolls` INT NOT NULL DEFAULT 0,
|
`product_code` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
`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,
|
|
||||||
`sales_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
`sales_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||||
`remark` TEXT,
|
`remark` TEXT,
|
||||||
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled',
|
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled',
|
||||||
@ -228,12 +226,96 @@ CREATE TABLE `inv_product` (
|
|||||||
`deleted_at` DATETIME DEFAULT NULL,
|
`deleted_at` DATETIME DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `uk_product_id` (`product_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_color` (`color`),
|
||||||
KEY `idx_location` (`location`),
|
|
||||||
KEY `idx_status` (`status`),
|
KEY `idx_status` (`status`),
|
||||||
KEY `idx_deleted_at` (`deleted_at`)
|
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` (
|
CREATE TABLE `inv_stock_import_log` (
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
|||||||
174
deploy/mysql/migrations/20260703_add_product_yarn_batch.sql
Normal file
174
deploy/mysql/migrations/20260703_add_product_yarn_batch.sql
Normal file
@ -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 = '';
|
||||||
@ -224,6 +224,8 @@ type (
|
|||||||
ImageUrl string `json:"imageUrl"`
|
ImageUrl string `json:"imageUrl"`
|
||||||
Spec string `json:"spec"`
|
Spec string `json:"spec"`
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
|
ColorNo string `json:"colorNo"`
|
||||||
|
ProductCode string `json:"productCode"`
|
||||||
SalesPrice string `json:"salesPrice"`
|
SalesPrice string `json:"salesPrice"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
Status int64 `json:"status"`
|
Status int64 `json:"status"`
|
||||||
@ -235,15 +237,19 @@ type (
|
|||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
|
ColorNo string `json:"colorNo,optional"`
|
||||||
|
ProductCode string `json:"productCode,optional"`
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
Remark string `json:"remark,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
Pans []PanInput `json:"pans,optional"`
|
Pans []PanInput `json:"pans,optional"`
|
||||||
|
InitialBatch ProductBatchInput `json:"initialBatch,optional"`
|
||||||
}
|
}
|
||||||
UpdateProductReq {
|
UpdateProductReq {
|
||||||
ProductName string `json:"productName,optional"`
|
ProductName string `json:"productName,optional"`
|
||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
|
ColorNo string `json:"colorNo,optional"`
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
Remark string `json:"remark,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
}
|
}
|
||||||
@ -253,6 +259,8 @@ type (
|
|||||||
ProductName string `form:"productName,optional"`
|
ProductName string `form:"productName,optional"`
|
||||||
Spec string `form:"spec,optional"`
|
Spec string `form:"spec,optional"`
|
||||||
Color string `form:"color,optional"`
|
Color string `form:"color,optional"`
|
||||||
|
ColorNo string `form:"colorNo,optional"`
|
||||||
|
ProductCode string `form:"productCode,optional"`
|
||||||
Status int64 `form:"status,optional,default=-1"`
|
Status int64 `form:"status,optional,default=-1"`
|
||||||
}
|
}
|
||||||
ListProductResp {
|
ListProductResp {
|
||||||
@ -279,6 +287,8 @@ type (
|
|||||||
PanInfo {
|
PanInfo {
|
||||||
PanId string `json:"panId"`
|
PanId string `json:"panId"`
|
||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
|
BatchId string `json:"batchId"`
|
||||||
|
BatchNo string `json:"batchNo"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Position string `json:"position"`
|
Position string `json:"position"`
|
||||||
SortOrder int64 `json:"sortOrder"`
|
SortOrder int64 `json:"sortOrder"`
|
||||||
@ -290,6 +300,7 @@ type (
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Position string `json:"position,optional"`
|
Position string `json:"position,optional"`
|
||||||
BoltLengths []string `json:"boltLengths,optional"`
|
BoltLengths []string `json:"boltLengths,optional"`
|
||||||
|
BatchId string `json:"batchId,optional"`
|
||||||
}
|
}
|
||||||
ListPanResp {
|
ListPanResp {
|
||||||
List []PanInfo `json:"list"`
|
List []PanInfo `json:"list"`
|
||||||
@ -331,6 +342,8 @@ type (
|
|||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
|
ColorNo string `json:"colorNo"`
|
||||||
|
ProductCode string `json:"productCode"`
|
||||||
Spec string `json:"spec"`
|
Spec string `json:"spec"`
|
||||||
ImageUrl string `json:"imageUrl"`
|
ImageUrl string `json:"imageUrl"`
|
||||||
PanCount int64 `json:"panCount"`
|
PanCount int64 `json:"panCount"`
|
||||||
@ -338,6 +351,7 @@ type (
|
|||||||
TotalLengthM string `json:"totalLengthM"`
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
Locations string `json:"locations"`
|
Locations string `json:"locations"`
|
||||||
SalesPrice string `json:"salesPrice"`
|
SalesPrice string `json:"salesPrice"`
|
||||||
|
BatchCount int64 `json:"batchCount"`
|
||||||
}
|
}
|
||||||
ListColorDetailReq {
|
ListColorDetailReq {
|
||||||
ProductName string `form:"productName"`
|
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 ====================
|
// ==================== Stock Statistics Types ====================
|
||||||
type (
|
type (
|
||||||
StockSummaryResp {
|
StockSummaryResp {
|
||||||
@ -725,6 +818,51 @@ service gateway-api {
|
|||||||
put /products/:id/pans (SavePansReq) returns (IdResp)
|
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
|
// Inventory - Pan/Bolt Management
|
||||||
@server (
|
@server (
|
||||||
prefix: /api/v1/inventory
|
prefix: /api/v1/inventory
|
||||||
@ -805,4 +943,3 @@ service gateway-api {
|
|||||||
@handler ApproveStockAdjustHandler
|
@handler ApproveStockAdjustHandler
|
||||||
post /adjusts/:id/approve (ApproveStockAdjustReq) returns (IdResp)
|
post /adjusts/:id/approve (ApproveStockAdjustReq) returns (IdResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ package product
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
"muyu-apiserver/gateway/internal/logic/inventory/product"
|
"muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||||
@ -14,11 +15,14 @@ import (
|
|||||||
func ExportProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func ExportProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
l := product.NewExportProductLogic(r.Context(), svcCtx)
|
l := product.NewExportProductLogic(r.Context(), svcCtx)
|
||||||
err := l.ExportProduct()
|
data, filename, err := l.ExportProduct()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpx.ErrorCtx(r.Context(), w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
} else {
|
} 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
gateway/internal/handler/inventory/yarn/createYarnHandler.go
Normal file
29
gateway/internal/handler/inventory/yarn/createYarnHandler.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
gateway/internal/handler/inventory/yarn/deleteYarnHandler.go
Normal file
26
gateway/internal/handler/inventory/yarn/deleteYarnHandler.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
gateway/internal/handler/inventory/yarn/getYarnHandler.go
Normal file
26
gateway/internal/handler/inventory/yarn/getYarnHandler.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
gateway/internal/handler/inventory/yarn/listYarnHandler.go
Normal file
29
gateway/internal/handler/inventory/yarn/listYarnHandler.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
gateway/internal/handler/inventory/yarn/updateYarnHandler.go
Normal file
32
gateway/internal/handler/inventory/yarn/updateYarnHandler.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,9 @@ import (
|
|||||||
inventorylog "muyu-apiserver/gateway/internal/handler/inventory/log"
|
inventorylog "muyu-apiserver/gateway/internal/handler/inventory/log"
|
||||||
inventorypanbolt "muyu-apiserver/gateway/internal/handler/inventory/panbolt"
|
inventorypanbolt "muyu-apiserver/gateway/internal/handler/inventory/panbolt"
|
||||||
inventoryproduct "muyu-apiserver/gateway/internal/handler/inventory/product"
|
inventoryproduct "muyu-apiserver/gateway/internal/handler/inventory/product"
|
||||||
|
inventoryproductbatch "muyu-apiserver/gateway/internal/handler/inventory/productbatch"
|
||||||
inventorystock "muyu-apiserver/gateway/internal/handler/inventory/stock"
|
inventorystock "muyu-apiserver/gateway/internal/handler/inventory/stock"
|
||||||
|
inventoryyarn "muyu-apiserver/gateway/internal/handler/inventory/yarn"
|
||||||
productioninbound "muyu-apiserver/gateway/internal/handler/production/inbound"
|
productioninbound "muyu-apiserver/gateway/internal/handler/production/inbound"
|
||||||
productionplan "muyu-apiserver/gateway/internal/handler/production/plan"
|
productionplan "muyu-apiserver/gateway/internal/handler/production/plan"
|
||||||
productionprocess "muyu-apiserver/gateway/internal/handler/production/process"
|
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"),
|
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(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||||
|
|||||||
@ -40,6 +40,8 @@ func (l *ListPanViewLogic) ListPanView(req *types.ListPanViewReq) (resp *types.L
|
|||||||
list = append(list, types.PanListItem{
|
list = append(list, types.PanListItem{
|
||||||
PanId: item.PanId,
|
PanId: item.PanId,
|
||||||
ProductId: item.ProductId,
|
ProductId: item.ProductId,
|
||||||
|
BatchId: item.BatchId,
|
||||||
|
BatchNo: item.BatchNo,
|
||||||
Name: item.Name,
|
Name: item.Name,
|
||||||
Position: item.Position,
|
Position: item.Position,
|
||||||
ProductName: item.ProductName,
|
ProductName: item.ProductName,
|
||||||
|
|||||||
@ -30,9 +30,12 @@ func (l *CreateProductLogic) CreateProduct(req *types.CreateProductReq) (resp *t
|
|||||||
ImageUrl: req.ImageUrl,
|
ImageUrl: req.ImageUrl,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
|
ColorNo: req.ColorNo,
|
||||||
|
ProductCode: req.ProductCode,
|
||||||
SalesPrice: req.SalesPrice,
|
SalesPrice: req.SalesPrice,
|
||||||
Remark: req.Remark,
|
Remark: req.Remark,
|
||||||
Pans: panInputsToPb(req.Pans),
|
Pans: panInputsToPb(req.Pans),
|
||||||
|
InitialBatch: productBatchInputToPb(req.InitialBatch),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -51,7 +54,22 @@ func panInputsToPb(pans []types.PanInput) []*pb.PanInput {
|
|||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
Position: p.Position,
|
Position: p.Position,
|
||||||
BoltLengths: p.BoltLengths,
|
BoltLengths: p.BoltLengths,
|
||||||
|
BatchId: p.BatchId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return out
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2,10 +2,13 @@ package product
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"muyu-apiserver/gateway/internal/svc"
|
"muyu-apiserver/gateway/internal/svc"
|
||||||
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
|
|
||||||
|
"github.com/xuri/excelize/v2"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"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 {
|
func (l *ExportProductLogic) ExportProduct() ([]byte, string, error) {
|
||||||
return errors.New("export product requires response writer, will be implemented in handler layer")
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,8 @@ func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (res
|
|||||||
ProductId: it.ProductId,
|
ProductId: it.ProductId,
|
||||||
ProductName: it.ProductName,
|
ProductName: it.ProductName,
|
||||||
Color: it.Color,
|
Color: it.Color,
|
||||||
|
ColorNo: it.ColorNo,
|
||||||
|
ProductCode: it.ProductCode,
|
||||||
Spec: it.Spec,
|
Spec: it.Spec,
|
||||||
ImageUrl: it.ImageUrl,
|
ImageUrl: it.ImageUrl,
|
||||||
PanCount: it.PanCount,
|
PanCount: it.PanCount,
|
||||||
@ -44,6 +46,7 @@ func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (res
|
|||||||
TotalLengthM: it.TotalLengthM,
|
TotalLengthM: it.TotalLengthM,
|
||||||
Locations: it.Locations,
|
Locations: it.Locations,
|
||||||
SalesPrice: it.SalesPrice,
|
SalesPrice: it.SalesPrice,
|
||||||
|
BatchCount: it.BatchCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return &types.ColorDetailResp{List: list}, nil
|
return &types.ColorDetailResp{List: list}, nil
|
||||||
|
|||||||
@ -42,8 +42,17 @@ func (l *ImportProductLogic) ImportProduct(filePath, fileName string) (resp *typ
|
|||||||
ProductName: p.ProductName,
|
ProductName: p.ProductName,
|
||||||
Spec: p.Spec,
|
Spec: p.Spec,
|
||||||
Color: p.Color,
|
Color: p.Color,
|
||||||
|
ColorNo: p.ColorNo,
|
||||||
|
ProductCode: p.ProductCode,
|
||||||
SalesPrice: p.SalesPrice,
|
SalesPrice: p.SalesPrice,
|
||||||
Remark: p.Remark,
|
Remark: p.Remark,
|
||||||
|
InitialBatch: &pb.ProductBatchInput{
|
||||||
|
BatchNo: p.BatchNo,
|
||||||
|
YarnRatio: p.YarnRatio,
|
||||||
|
WarpWeightGM: p.WarpWeightGM,
|
||||||
|
WeftWeightGM: p.WeftWeightGM,
|
||||||
|
ProductionProcess: p.ProductionProcess,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,8 @@ func panInfoFromPB(p *pb.PanInfo) types.PanInfo {
|
|||||||
return types.PanInfo{
|
return types.PanInfo{
|
||||||
PanId: p.PanId,
|
PanId: p.PanId,
|
||||||
ProductId: p.ProductId,
|
ProductId: p.ProductId,
|
||||||
|
BatchId: p.BatchId,
|
||||||
|
BatchNo: p.BatchNo,
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
Position: p.Position,
|
Position: p.Position,
|
||||||
SortOrder: p.SortOrder,
|
SortOrder: p.SortOrder,
|
||||||
@ -76,6 +78,8 @@ func productInfoFromPB(p *pb.ProductInfo) types.ProductInfo {
|
|||||||
ImageUrl: p.ImageUrl,
|
ImageUrl: p.ImageUrl,
|
||||||
Spec: p.Spec,
|
Spec: p.Spec,
|
||||||
Color: p.Color,
|
Color: p.Color,
|
||||||
|
ColorNo: p.ColorNo,
|
||||||
|
ProductCode: p.ProductCode,
|
||||||
SalesPrice: p.SalesPrice,
|
SalesPrice: p.SalesPrice,
|
||||||
Remark: p.Remark,
|
Remark: p.Remark,
|
||||||
Status: p.Status,
|
Status: p.Status,
|
||||||
|
|||||||
@ -31,6 +31,8 @@ func (l *ListProductLogic) ListProduct(req *types.ListProductReq) (resp *types.L
|
|||||||
ProductName: req.ProductName,
|
ProductName: req.ProductName,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
|
ColorNo: req.ColorNo,
|
||||||
|
ProductCode: req.ProductCode,
|
||||||
Status: req.Status,
|
Status: req.Status,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -34,6 +34,7 @@ func (l *UpdateProductLogic) UpdateProduct(req *types.UpdateProductReq) (resp *t
|
|||||||
ImageUrl: req.ImageUrl,
|
ImageUrl: req.ImageUrl,
|
||||||
Spec: req.Spec,
|
Spec: req.Spec,
|
||||||
Color: req.Color,
|
Color: req.Color,
|
||||||
|
ColorNo: req.ColorNo,
|
||||||
SalesPrice: req.SalesPrice,
|
SalesPrice: req.SalesPrice,
|
||||||
Remark: req.Remark,
|
Remark: req.Remark,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
36
gateway/internal/logic/inventory/productbatch/helpers.go
Normal file
36
gateway/internal/logic/inventory/productbatch/helpers.go
Normal file
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
37
gateway/internal/logic/inventory/yarn/createYarnLogic.go
Normal file
37
gateway/internal/logic/inventory/yarn/createYarnLogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
30
gateway/internal/logic/inventory/yarn/deleteYarnLogic.go
Normal file
30
gateway/internal/logic/inventory/yarn/deleteYarnLogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
32
gateway/internal/logic/inventory/yarn/getYarnLogic.go
Normal file
32
gateway/internal/logic/inventory/yarn/getYarnLogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
26
gateway/internal/logic/inventory/yarn/helpers.go
Normal file
26
gateway/internal/logic/inventory/yarn/helpers.go
Normal file
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
39
gateway/internal/logic/inventory/yarn/listYarnLogic.go
Normal file
39
gateway/internal/logic/inventory/yarn/listYarnLogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
41
gateway/internal/logic/inventory/yarn/updateYarnLogic.go
Normal file
41
gateway/internal/logic/inventory/yarn/updateYarnLogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -38,9 +38,12 @@ type CreateProductReq struct {
|
|||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
|
ColorNo string `json:"colorNo,optional"`
|
||||||
|
ProductCode string `json:"productCode,optional"`
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
Remark string `json:"remark,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
Pans []PanInput `json:"pans,optional"`
|
Pans []PanInput `json:"pans,optional"`
|
||||||
|
InitialBatch ProductBatchInput `json:"initialBatch,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateRoleReq struct {
|
type CreateRoleReq struct {
|
||||||
@ -114,6 +117,8 @@ type ListProductReq struct {
|
|||||||
ProductName string `form:"productName,optional"`
|
ProductName string `form:"productName,optional"`
|
||||||
Spec string `form:"spec,optional"`
|
Spec string `form:"spec,optional"`
|
||||||
Color string `form:"color,optional"`
|
Color string `form:"color,optional"`
|
||||||
|
ColorNo string `form:"colorNo,optional"`
|
||||||
|
ProductCode string `form:"productCode,optional"`
|
||||||
Status int64 `form:"status,optional,default=-1"`
|
Status int64 `form:"status,optional,default=-1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +235,8 @@ type ProductInfo struct {
|
|||||||
ImageUrl string `json:"imageUrl"`
|
ImageUrl string `json:"imageUrl"`
|
||||||
Spec string `json:"spec"`
|
Spec string `json:"spec"`
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
|
ColorNo string `json:"colorNo"`
|
||||||
|
ProductCode string `json:"productCode"`
|
||||||
SalesPrice string `json:"salesPrice"`
|
SalesPrice string `json:"salesPrice"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
Status int64 `json:"status"`
|
Status int64 `json:"status"`
|
||||||
@ -247,6 +254,8 @@ type BoltInfo struct {
|
|||||||
type PanInfo struct {
|
type PanInfo struct {
|
||||||
PanId string `json:"panId"`
|
PanId string `json:"panId"`
|
||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
|
BatchId string `json:"batchId"`
|
||||||
|
BatchNo string `json:"batchNo"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Position string `json:"position"`
|
Position string `json:"position"`
|
||||||
SortOrder int64 `json:"sortOrder"`
|
SortOrder int64 `json:"sortOrder"`
|
||||||
@ -259,6 +268,7 @@ type PanInput struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Position string `json:"position,optional"`
|
Position string `json:"position,optional"`
|
||||||
BoltLengths []string `json:"boltLengths,optional"`
|
BoltLengths []string `json:"boltLengths,optional"`
|
||||||
|
BatchId string `json:"batchId,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListPanResp struct {
|
type ListPanResp struct {
|
||||||
@ -304,6 +314,8 @@ type ColorDetailItem struct {
|
|||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
|
ColorNo string `json:"colorNo"`
|
||||||
|
ProductCode string `json:"productCode"`
|
||||||
Spec string `json:"spec"`
|
Spec string `json:"spec"`
|
||||||
ImageUrl string `json:"imageUrl"`
|
ImageUrl string `json:"imageUrl"`
|
||||||
PanCount int64 `json:"panCount"`
|
PanCount int64 `json:"panCount"`
|
||||||
@ -311,6 +323,7 @@ type ColorDetailItem struct {
|
|||||||
TotalLengthM string `json:"totalLengthM"`
|
TotalLengthM string `json:"totalLengthM"`
|
||||||
Locations string `json:"locations"`
|
Locations string `json:"locations"`
|
||||||
SalesPrice string `json:"salesPrice"`
|
SalesPrice string `json:"salesPrice"`
|
||||||
|
BatchCount int64 `json:"batchCount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListColorDetailReq struct {
|
type ListColorDetailReq struct {
|
||||||
@ -321,9 +334,96 @@ type ColorDetailResp struct {
|
|||||||
List []ColorDetailItem `json:"list"`
|
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 {
|
type PanListItem struct {
|
||||||
PanId string `json:"panId"`
|
PanId string `json:"panId"`
|
||||||
ProductId string `json:"productId"`
|
ProductId string `json:"productId"`
|
||||||
|
BatchId string `json:"batchId"`
|
||||||
|
BatchNo string `json:"batchNo"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Position string `json:"position"`
|
Position string `json:"position"`
|
||||||
ProductName string `json:"productName"`
|
ProductName string `json:"productName"`
|
||||||
@ -484,6 +584,7 @@ type UpdateProductReq struct {
|
|||||||
ImageUrl string `json:"imageUrl,optional"`
|
ImageUrl string `json:"imageUrl,optional"`
|
||||||
Spec string `json:"spec,optional"`
|
Spec string `json:"spec,optional"`
|
||||||
Color string `json:"color,optional"`
|
Color string `json:"color,optional"`
|
||||||
|
ColorNo string `json:"colorNo,optional"`
|
||||||
SalesPrice string `json:"salesPrice,optional"`
|
SalesPrice string `json:"salesPrice,optional"`
|
||||||
Remark string `json:"remark,optional"`
|
Remark string `json:"remark,optional"`
|
||||||
}
|
}
|
||||||
|
|||||||
1
go.mod
1
go.mod
@ -66,6 +66,7 @@ require (
|
|||||||
github.com/microsoft/go-mssqldb v1.9.5 // indirect
|
github.com/microsoft/go-mssqldb v1.9.5 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||||
|
|||||||
2
go.sum
2
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/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/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/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 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
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=
|
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||||
|
|||||||
81
model/invproductbatchmodel.go
Normal file
81
model/invproductbatchmodel.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
100
model/invproductbatchmodel_gen.go
Normal file
100
model/invproductbatchmodel_gen.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -59,7 +59,7 @@ func (m *customInvProductBoltModel) FindByPanId(ctx context.Context, panId strin
|
|||||||
func (m *customInvProductBoltModel) FindByProductId(ctx context.Context, productId string) ([]*InvProductBolt, error) {
|
func (m *customInvProductBoltModel) FindByProductId(ctx context.Context, productId string) ([]*InvProductBolt, error) {
|
||||||
var list []*InvProductBolt
|
var list []*InvProductBolt
|
||||||
query := fmt.Sprintf(
|
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` "+
|
"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)
|
"WHERE p.`product_id` = ? ORDER BY p.`sort_order`, b.`sort_order`", m.table)
|
||||||
err := m.conn.QueryRowsCtx(ctx, &list, query, productId)
|
err := m.conn.QueryRowsCtx(ctx, &list, query, productId)
|
||||||
|
|||||||
@ -33,11 +33,14 @@ type ColorDetail struct {
|
|||||||
ProductId string `db:"product_id"`
|
ProductId string `db:"product_id"`
|
||||||
ProductName string `db:"product_name"`
|
ProductName string `db:"product_name"`
|
||||||
Color string `db:"color"`
|
Color string `db:"color"`
|
||||||
|
ColorNo string `db:"color_no"`
|
||||||
|
ProductCode string `db:"product_code"`
|
||||||
Spec string `db:"spec"`
|
Spec string `db:"spec"`
|
||||||
ImageUrl string `db:"image_url"`
|
ImageUrl string `db:"image_url"`
|
||||||
SalesPrice float64 `db:"sales_price"`
|
SalesPrice float64 `db:"sales_price"`
|
||||||
PanCount int64 `db:"pan_count"`
|
PanCount int64 `db:"pan_count"`
|
||||||
BoltCount int64 `db:"bolt_count"`
|
BoltCount int64 `db:"bolt_count"`
|
||||||
|
BatchCount int64 `db:"batch_count"`
|
||||||
TotalLengthM float64 `db:"total_length_m"`
|
TotalLengthM float64 `db:"total_length_m"`
|
||||||
Locations string `db:"locations"`
|
Locations string `db:"locations"`
|
||||||
}
|
}
|
||||||
@ -45,11 +48,13 @@ type ColorDetail struct {
|
|||||||
type (
|
type (
|
||||||
InvProductModel interface {
|
InvProductModel interface {
|
||||||
invProductModel
|
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)
|
FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error)
|
||||||
FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, 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)
|
FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
||||||
FindGroupByLocation(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)
|
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]
|
batch := products[i:end]
|
||||||
|
|
||||||
placeholder := "(" + strings.Repeat("?,", 9) + "?)"
|
placeholder := "(" + strings.Repeat("?,", 11) + "?)"
|
||||||
placeholders := make([]string, len(batch))
|
placeholders := make([]string, len(batch))
|
||||||
args := make([]interface{}, 0, len(batch)*10)
|
args := make([]interface{}, 0, len(batch)*12)
|
||||||
|
|
||||||
for j, p := range batch {
|
for j, p := range batch {
|
||||||
placeholders[j] = placeholder
|
placeholders[j] = placeholder
|
||||||
args = append(args,
|
args = append(args,
|
||||||
p.ProductId, p.ProductName, p.ImageUrl, p.Spec, p.Color,
|
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
|
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 = ?"
|
where := "WHERE deleted_at IS NULL AND tenant_id = ?"
|
||||||
args := []interface{}{tenantId}
|
args := []interface{}{tenantId}
|
||||||
|
|
||||||
@ -121,6 +127,14 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p
|
|||||||
where += " AND color = ?"
|
where += " AND color = ?"
|
||||||
args = append(args, color)
|
args = append(args, color)
|
||||||
}
|
}
|
||||||
|
if colorNo != "" {
|
||||||
|
where += " AND color_no LIKE ?"
|
||||||
|
args = append(args, "%"+colorNo+"%")
|
||||||
|
}
|
||||||
|
if productCode != "" {
|
||||||
|
where += " AND product_code LIKE ?"
|
||||||
|
args = append(args, "%"+productCode+"%")
|
||||||
|
}
|
||||||
if status >= 0 {
|
if status >= 0 {
|
||||||
where += " AND status = ?"
|
where += " AND status = ?"
|
||||||
args = append(args, status)
|
args = append(args, status)
|
||||||
@ -144,6 +158,27 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p
|
|||||||
return list, total, nil
|
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) {
|
func (m *customInvProductModel) FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error) {
|
||||||
var list []*ProductSummary
|
var list []*ProductSummary
|
||||||
query := `SELECT p.product_name, p.spec,
|
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) {
|
func (m *customInvProductModel) FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, error) {
|
||||||
var list []*ColorDetail
|
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(DISTINCT pan.pan_id) AS pan_count,
|
||||||
COUNT(bolt.bolt_id) AS bolt_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(SUM(bolt.length_m), 0) AS total_length_m,
|
||||||
COALESCE(GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position), '') AS locations
|
COALESCE(GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position), '') AS locations
|
||||||
FROM ` + m.table + ` p
|
FROM ` + m.table + ` p
|
||||||
|
|||||||
@ -27,6 +27,7 @@ var (
|
|||||||
cacheInvProductIdPrefix = "cache:invProduct:id:"
|
cacheInvProductIdPrefix = "cache:invProduct:id:"
|
||||||
cacheInvProductProductIdPrefix = "cache:invProduct:productId:"
|
cacheInvProductProductIdPrefix = "cache:invProduct:productId:"
|
||||||
cacheInvProductProductNamePrefix = "cache:invProduct:productName:"
|
cacheInvProductProductNamePrefix = "cache:invProduct:productName:"
|
||||||
|
cacheInvProductProductCodePrefix = "cache:invProduct:productCode:"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -35,6 +36,7 @@ type (
|
|||||||
FindOne(ctx context.Context, id int64) (*InvProduct, error)
|
FindOne(ctx context.Context, id int64) (*InvProduct, error)
|
||||||
FindOneByProductId(ctx context.Context, productId string) (*InvProduct, error)
|
FindOneByProductId(ctx context.Context, productId string) (*InvProduct, error)
|
||||||
FindOneByProductName(ctx context.Context, productName 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
|
Update(ctx context.Context, data *InvProduct) error
|
||||||
Delete(ctx context.Context, id int64) error
|
Delete(ctx context.Context, id int64) error
|
||||||
}
|
}
|
||||||
@ -51,6 +53,8 @@ type (
|
|||||||
ImageUrl string `db:"image_url"`
|
ImageUrl string `db:"image_url"`
|
||||||
Spec string `db:"spec"`
|
Spec string `db:"spec"`
|
||||||
Color string `db:"color"`
|
Color string `db:"color"`
|
||||||
|
ColorNo string `db:"color_no"`
|
||||||
|
ProductCode string `db:"product_code"`
|
||||||
SalesPrice float64 `db:"sales_price"`
|
SalesPrice float64 `db:"sales_price"`
|
||||||
Remark sql.NullString `db:"remark"`
|
Remark sql.NullString `db:"remark"`
|
||||||
Status int64 `db:"status"`
|
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)
|
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, id)
|
||||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||||
|
invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode)
|
||||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
return conn.ExecCtx(ctx, query, id)
|
return conn.ExecCtx(ctx, query, id)
|
||||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey)
|
||||||
return err
|
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) {
|
func (m *defaultInvProductModel) FindOneByProductName(ctx context.Context, productName string) (*InvProduct, error) {
|
||||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, productName)
|
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, productName)
|
||||||
var resp InvProduct
|
var resp InvProduct
|
||||||
@ -145,10 +170,11 @@ func (m *defaultInvProductModel) Insert(ctx context.Context, data *InvProduct) (
|
|||||||
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id)
|
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id)
|
||||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||||
|
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) {
|
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invProductRowsExpectAutoSet)
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invProductRowsExpectAutoSet)
|
||||||
return conn.ExecCtx(ctx, query, data.ProductId, data.ProductName, data.ImageUrl, data.Spec, data.Color, data.SalesPrice, data.Remark, data.Status, data.TenantId, data.DeletedAt)
|
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)
|
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,10 +187,11 @@ func (m *defaultInvProductModel) Update(ctx context.Context, newData *InvProduct
|
|||||||
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id)
|
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id)
|
||||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||||
|
invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode)
|
||||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, invProductRowsWithPlaceHolder)
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, invProductRowsWithPlaceHolder)
|
||||||
return conn.ExecCtx(ctx, query, newData.ProductId, newData.ProductName, newData.ImageUrl, newData.Spec, newData.Color, newData.SalesPrice, newData.Remark, newData.Status, newData.TenantId, newData.DeletedAt, newData.Id)
|
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)
|
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,8 @@ func TestInvProductInsert(t *testing.T) {
|
|||||||
ImageUrl: "",
|
ImageUrl: "",
|
||||||
Spec: "100cm",
|
Spec: "100cm",
|
||||||
Color: "red",
|
Color: "red",
|
||||||
|
ColorNo: "01",
|
||||||
|
ProductCode: uniqueID("TPC"),
|
||||||
SalesPrice: 99.9,
|
SalesPrice: 99.9,
|
||||||
Remark: sql.NullString{String: "test remark", Valid: true},
|
Remark: sql.NullString{String: "test remark", Valid: true},
|
||||||
Status: 1,
|
Status: 1,
|
||||||
@ -83,6 +85,8 @@ func TestInvProductFindOne(t *testing.T) {
|
|||||||
ProductName: uniqueID("test_product"),
|
ProductName: uniqueID("test_product"),
|
||||||
Spec: "200cm",
|
Spec: "200cm",
|
||||||
Color: "blue",
|
Color: "blue",
|
||||||
|
ColorNo: "01",
|
||||||
|
ProductCode: uniqueID("TPC"),
|
||||||
SalesPrice: 49.5,
|
SalesPrice: 49.5,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
TenantId: "t_default_001",
|
TenantId: "t_default_001",
|
||||||
@ -121,6 +125,8 @@ func TestInvProductUpdate(t *testing.T) {
|
|||||||
ProductName: uniqueID("test_product"),
|
ProductName: uniqueID("test_product"),
|
||||||
Spec: "50cm",
|
Spec: "50cm",
|
||||||
Color: "green",
|
Color: "green",
|
||||||
|
ColorNo: "01",
|
||||||
|
ProductCode: uniqueID("TPC"),
|
||||||
SalesPrice: 10.0,
|
SalesPrice: 10.0,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
TenantId: "t_default_001",
|
TenantId: "t_default_001",
|
||||||
@ -172,6 +178,8 @@ func TestInvProductBulkInsert(t *testing.T) {
|
|||||||
ProductName: uniqueID(fmt.Sprintf("bulk_product_%d", i)),
|
ProductName: uniqueID(fmt.Sprintf("bulk_product_%d", i)),
|
||||||
Spec: "10cm",
|
Spec: "10cm",
|
||||||
Color: "white",
|
Color: "white",
|
||||||
|
ColorNo: fmt.Sprintf("%02d", i+1),
|
||||||
|
ProductCode: uniqueID(fmt.Sprintf("BTPC%d", i)),
|
||||||
SalesPrice: float64(i+1) * 5.0,
|
SalesPrice: float64(i+1) * 5.0,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
TenantId: "t_default_001",
|
TenantId: "t_default_001",
|
||||||
@ -229,7 +237,8 @@ func TestInvProductSchemaColumns(t *testing.T) {
|
|||||||
// Columns that the InvProduct struct declares (via db tags).
|
// Columns that the InvProduct struct declares (via db tags).
|
||||||
structCols := []string{
|
structCols := []string{
|
||||||
"id", "product_id", "product_name", "image_url", "spec", "color",
|
"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 {
|
for _, col := range structCols {
|
||||||
@ -267,6 +276,8 @@ func TestFindProductSummaryNoPans(t *testing.T) {
|
|||||||
ProductName: uniqueID("nopan_product"),
|
ProductName: uniqueID("nopan_product"),
|
||||||
Spec: "50cm",
|
Spec: "50cm",
|
||||||
Color: "red",
|
Color: "red",
|
||||||
|
ColorNo: "01",
|
||||||
|
ProductCode: uniqueID("TPC"),
|
||||||
SalesPrice: 99.0,
|
SalesPrice: 99.0,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
TenantId: "t_default_001",
|
TenantId: "t_default_001",
|
||||||
@ -318,6 +329,8 @@ func TestFindColorDetailNoPans(t *testing.T) {
|
|||||||
ProductName: uniqueID("color_nopan_product"),
|
ProductName: uniqueID("color_nopan_product"),
|
||||||
Spec: "80cm",
|
Spec: "80cm",
|
||||||
Color: "blue",
|
Color: "blue",
|
||||||
|
ColorNo: "01",
|
||||||
|
ProductCode: uniqueID("TPC"),
|
||||||
SalesPrice: 50.0,
|
SalesPrice: 50.0,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
TenantId: "t_default_001",
|
TenantId: "t_default_001",
|
||||||
@ -343,3 +356,96 @@ func TestFindColorDetailNoPans(t *testing.T) {
|
|||||||
t.Errorf("Locations: got %q, want empty string", list[0].Locations)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -15,6 +15,8 @@ var _ InvProductPanModel = (*customInvProductPanModel)(nil)
|
|||||||
type PanListItem struct {
|
type PanListItem struct {
|
||||||
PanId string `db:"pan_id"`
|
PanId string `db:"pan_id"`
|
||||||
ProductId string `db:"product_id"`
|
ProductId string `db:"product_id"`
|
||||||
|
BatchId string `db:"batch_id"`
|
||||||
|
BatchNo string `db:"batch_no"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
Position string `db:"position"`
|
Position string `db:"position"`
|
||||||
ProductName string `db:"product_name"`
|
ProductName string `db:"product_name"`
|
||||||
@ -30,6 +32,7 @@ type (
|
|||||||
DeleteByProductId(ctx context.Context, productId string) error
|
DeleteByProductId(ctx context.Context, productId string) error
|
||||||
BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) 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)
|
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 {
|
customInvProductPanModel struct {
|
||||||
@ -79,13 +82,14 @@ func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId str
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.name, pan.position,
|
query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.batch_id, COALESCE(batch.batch_no, '') AS batch_no,
|
||||||
p.product_name,
|
pan.name, pan.position, p.product_name,
|
||||||
COALESCE(GROUP_CONCAT(DISTINCT b.color ORDER BY b.color SEPARATOR ', '), '') AS colors,
|
COALESCE(GROUP_CONCAT(DISTINCT b.color ORDER BY b.color SEPARATOR ', '), '') AS colors,
|
||||||
COUNT(b.bolt_id) AS bolt_count,
|
COUNT(b.bolt_id) AS bolt_count,
|
||||||
COALESCE(SUM(b.length_m), 0) AS total_length_m
|
COALESCE(SUM(b.length_m), 0) AS total_length_m
|
||||||
FROM %s pan
|
FROM %s pan
|
||||||
JOIN inv_product p ON p.product_id = pan.product_id
|
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
|
LEFT JOIN inv_product_bolt b ON b.pan_id = pan.pan_id
|
||||||
%s
|
%s
|
||||||
GROUP BY pan.pan_id
|
GROUP BY pan.pan_id
|
||||||
@ -100,6 +104,15 @@ func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId str
|
|||||||
return list, total, nil
|
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 {
|
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 {
|
return m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
delQuery := fmt.Sprintf("DELETE FROM %s WHERE `product_id` = ?", m.table)
|
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 {
|
if len(pans) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
placeholder := "(?, ?, ?, ?, ?, ?)"
|
placeholder := "(?, ?, ?, ?, ?, ?, ?)"
|
||||||
placeholders := make([]string, len(pans))
|
placeholders := make([]string, len(pans))
|
||||||
args := make([]interface{}, 0, len(pans)*6)
|
args := make([]interface{}, 0, len(pans)*7)
|
||||||
for i, p := range pans {
|
for i, p := range pans {
|
||||||
placeholders[i] = placeholder
|
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, ","))
|
insQuery := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", m.table, invProductPanRowsExpectAutoSet, strings.Join(placeholders, ","))
|
||||||
_, err := session.ExecCtx(ctx, insQuery, args...)
|
_, err := session.ExecCtx(ctx, insQuery, args...)
|
||||||
|
|||||||
@ -37,6 +37,7 @@ type (
|
|||||||
Id int64 `db:"id"`
|
Id int64 `db:"id"`
|
||||||
PanId string `db:"pan_id"`
|
PanId string `db:"pan_id"`
|
||||||
ProductId string `db:"product_id"`
|
ProductId string `db:"product_id"`
|
||||||
|
BatchId string `db:"batch_id"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
Position string `db:"position"`
|
Position string `db:"position"`
|
||||||
SortOrder int64 `db:"sort_order"`
|
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) {
|
func (m *defaultInvProductPanModel) Insert(ctx context.Context, data *InvProductPan) (sql.Result, error) {
|
||||||
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?)", m.table, invProductPanRowsExpectAutoSet)
|
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)
|
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) {
|
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 {
|
func (m *defaultInvProductPanModel) Update(ctx context.Context, data *InvProductPan) error {
|
||||||
query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, invProductPanRowsWithPlaceHolder)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
82
model/invyarnmodel.go
Normal file
82
model/invyarnmodel.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
100
model/invyarnmodel_gen.go
Normal file
100
model/invyarnmodel_gen.go
Normal file
@ -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
|
||||||
|
}
|
||||||
86
pkg/excelparse/native.go
Normal file
86
pkg/excelparse/native.go
Normal file
@ -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 ""
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ import (
|
|||||||
var parsers []FormatParser
|
var parsers []FormatParser
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
parsers = append(parsers, &NativeProductParser{})
|
||||||
parsers = append(parsers, &MiaozhangParser{})
|
parsers = append(parsers, &MiaozhangParser{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,10 +12,17 @@ type ParsedProduct struct {
|
|||||||
ProductName string
|
ProductName string
|
||||||
Spec string
|
Spec string
|
||||||
Color string
|
Color string
|
||||||
|
ColorNo string
|
||||||
|
ProductCode string
|
||||||
UnitRolls int64
|
UnitRolls int64
|
||||||
StockQuantity string
|
StockQuantity string
|
||||||
CostPrice string
|
CostPrice string
|
||||||
SalesPrice string
|
SalesPrice string
|
||||||
|
BatchNo string
|
||||||
|
YarnRatio string
|
||||||
|
WarpWeightGM string
|
||||||
|
WeftWeightGM string
|
||||||
|
ProductionProcess string
|
||||||
Remark string
|
Remark string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
140
rpc/inventory/internal/logic/batch_helpers.go
Normal file
140
rpc/inventory/internal/logic/batch_helpers.go
Normal file
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
56
rpc/inventory/internal/logic/batch_helpers_test.go
Normal file
56
rpc/inventory/internal/logic/batch_helpers_test.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
56
rpc/inventory/internal/logic/createproductbatchlogic.go
Normal file
56
rpc/inventory/internal/logic/createproductbatchlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"muyu-apiserver/model"
|
||||||
"muyu-apiserver/pkg/metrics"
|
"muyu-apiserver/pkg/metrics"
|
||||||
@ -35,23 +36,64 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp,
|
|||||||
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
productId := uid.Generate()
|
productId := uid.Generate()
|
||||||
salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64)
|
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{
|
product := &model.InvProduct{
|
||||||
ProductId: productId,
|
ProductId: productId,
|
||||||
TenantId: tenantId,
|
TenantId: tenantId,
|
||||||
ProductName: in.ProductName,
|
ProductName: productName,
|
||||||
ImageUrl: in.ImageUrl,
|
ImageUrl: in.ImageUrl,
|
||||||
Spec: in.Spec,
|
Spec: in.Spec,
|
||||||
Color: in.Color,
|
Color: color,
|
||||||
|
ColorNo: colorNo,
|
||||||
|
ProductCode: productCode,
|
||||||
SalesPrice: salesPrice,
|
SalesPrice: salesPrice,
|
||||||
Remark: sql.NullString{String: in.Remark, Valid: in.Remark != ""},
|
Remark: sql.NullString{String: in.Remark, Valid: in.Remark != ""},
|
||||||
Status: 1,
|
Status: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := l.svcCtx.ProductModel.Insert(l.ctx, product)
|
_, err = l.svcCtx.ProductModel.Insert(l.ctx, product)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
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 totalLengthM float64
|
||||||
var totalBolts int
|
var totalBolts int
|
||||||
|
|
||||||
@ -59,12 +101,21 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp,
|
|||||||
pans := make([]*model.InvProductPan, 0, len(in.Pans))
|
pans := make([]*model.InvProductPan, 0, len(in.Pans))
|
||||||
for i, panInput := range in.Pans {
|
for i, panInput := range in.Pans {
|
||||||
panId := uid.Generate()
|
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{
|
pans = append(pans, &model.InvProductPan{
|
||||||
PanId: panId,
|
PanId: panId,
|
||||||
ProductId: productId,
|
ProductId: productId,
|
||||||
|
BatchId: batchId,
|
||||||
Name: panInput.Name,
|
Name: panInput.Name,
|
||||||
Position: panInput.Position,
|
Position: panInput.Position,
|
||||||
SortOrder: int64(i + 1),
|
SortOrder: int64(i + 1),
|
||||||
|
TenantId: tenantId,
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(panInput.BoltLengths) > 0 {
|
if len(panInput.BoltLengths) > 0 {
|
||||||
@ -76,23 +127,25 @@ func (l *CreateProductLogic) CreateProduct(in *pb.CreateProductReq) (*pb.IdResp,
|
|||||||
BoltId: uid.Generate(),
|
BoltId: uid.Generate(),
|
||||||
PanId: panId,
|
PanId: panId,
|
||||||
LengthM: lengthM,
|
LengthM: lengthM,
|
||||||
|
Color: color,
|
||||||
SortOrder: int64(j + 1),
|
SortOrder: int64(j + 1),
|
||||||
|
TenantId: tenantId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
totalBolts += len(panInput.BoltLengths)
|
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)
|
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)
|
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 {
|
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 {
|
if totalBolts > 0 {
|
||||||
metrics.InboundBoltsTotal.WithLabelValues(tenantId, "create").Add(float64(totalBolts))
|
metrics.InboundBoltsTotal.WithLabelValues(tenantId, "create").Add(float64(totalBolts))
|
||||||
|
|||||||
68
rpc/inventory/internal/logic/createyarnlogic.go
Normal file
68
rpc/inventory/internal/logic/createyarnlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
46
rpc/inventory/internal/logic/deleteproductbatchlogic.go
Normal file
46
rpc/inventory/internal/logic/deleteproductbatchlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
35
rpc/inventory/internal/logic/deleteyarnlogic.go
Normal file
35
rpc/inventory/internal/logic/deleteyarnlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ package logic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"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 nil, status.Error(codes.NotFound, "product not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.ProductInfo{
|
return productToPb(product), nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,14 @@ func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductT
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
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 totalBoltCount int64
|
||||||
var totalLengthM float64
|
var totalLengthM float64
|
||||||
@ -65,6 +73,8 @@ func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductT
|
|||||||
pbPans = append(pbPans, &pb.PanInfo{
|
pbPans = append(pbPans, &pb.PanInfo{
|
||||||
PanId: pan.PanId,
|
PanId: pan.PanId,
|
||||||
ProductId: pan.ProductId,
|
ProductId: pan.ProductId,
|
||||||
|
BatchId: pan.BatchId,
|
||||||
|
BatchNo: batchNoById[pan.BatchId],
|
||||||
Name: pan.Name,
|
Name: pan.Name,
|
||||||
Position: pan.Position,
|
Position: pan.Position,
|
||||||
SortOrder: pan.SortOrder,
|
SortOrder: pan.SortOrder,
|
||||||
@ -75,18 +85,7 @@ func (l *GetProductTreeLogic) GetProductTree(in *pb.GetProductReq) (*pb.ProductT
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &pb.ProductTreeResp{
|
return &pb.ProductTreeResp{
|
||||||
Product: &pb.ProductInfo{
|
Product: productToPb(product),
|
||||||
ProductId: product.ProductId,
|
|
||||||
ProductName: product.ProductName,
|
|
||||||
ImageUrl: product.ImageUrl,
|
|
||||||
Spec: product.Spec,
|
|
||||||
Color: product.Color,
|
|
||||||
SalesPrice: fmt.Sprintf("%.2f", product.SalesPrice),
|
|
||||||
Remark: product.Remark.String,
|
|
||||||
Status: product.Status,
|
|
||||||
CreatedAt: product.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
||||||
UpdatedAt: product.UpdatedAt.Format("2006-01-02 15:04:05"),
|
|
||||||
},
|
|
||||||
Pans: pbPans,
|
Pans: pbPans,
|
||||||
TotalPanCount: int64(len(pans)),
|
TotalPanCount: int64(len(pans)),
|
||||||
TotalBoltCount: totalBoltCount,
|
TotalBoltCount: totalBoltCount,
|
||||||
|
|||||||
36
rpc/inventory/internal/logic/getyarnlogic.go
Normal file
36
rpc/inventory/internal/logic/getyarnlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@ package logic
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"strconv"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"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) {
|
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 {
|
for i, p := range in.Products {
|
||||||
salesPrice, _ := strconv.ParseFloat(p.SalesPrice, 64)
|
if _, err := creator.CreateProduct(p); err != nil {
|
||||||
|
errs = append(errs, fmt.Sprintf("第%d行: %v", i+1, err))
|
||||||
products = append(products, &model.InvProduct{
|
continue
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
successCount++
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
failCount := totalCount - successCount
|
||||||
|
errorMsg := strings.Join(errs, "; ")
|
||||||
|
|
||||||
importId := uid.Generate()
|
importId := uid.Generate()
|
||||||
importLog := &model.InvStockImportLog{
|
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 {
|
if _, logErr := l.svcCtx.ImportLogModel.Insert(l.ctx, importLog); logErr != nil {
|
||||||
l.Errorf("save import log failed: %v", logErr)
|
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, strings.Join([]string{errorMsg, logErr.Error()}, "; "))
|
||||||
}
|
}
|
||||||
return nil, status.Error(codes.Internal, 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.ImportProductsTotal.WithLabelValues(tenantId, "fail").Add(float64(failCount))
|
||||||
}
|
}
|
||||||
metrics.ImportBatchSize.WithLabelValues(tenantId).Observe(float64(totalCount))
|
metrics.ImportBatchSize.WithLabelValues(tenantId).Observe(float64(totalCount))
|
||||||
for _, p := range in.Products {
|
|
||||||
metrics.ProductCreatedTotal.WithLabelValues(tenantId, p.ProductName, p.Spec, p.Color).Inc()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pb.ImportProductResp{
|
return &pb.ImportProductResp{
|
||||||
TotalCount: totalCount,
|
TotalCount: totalCount,
|
||||||
|
|||||||
@ -40,10 +40,13 @@ func (l *ListColorDetailLogic) ListColorDetail(in *pb.ListColorDetailReq) (*pb.L
|
|||||||
ProductId: d.ProductId,
|
ProductId: d.ProductId,
|
||||||
ProductName: d.ProductName,
|
ProductName: d.ProductName,
|
||||||
Color: d.Color,
|
Color: d.Color,
|
||||||
|
ColorNo: d.ColorNo,
|
||||||
|
ProductCode: d.ProductCode,
|
||||||
Spec: d.Spec,
|
Spec: d.Spec,
|
||||||
ImageUrl: d.ImageUrl,
|
ImageUrl: d.ImageUrl,
|
||||||
PanCount: d.PanCount,
|
PanCount: d.PanCount,
|
||||||
BoltCount: d.BoltCount,
|
BoltCount: d.BoltCount,
|
||||||
|
BatchCount: d.BatchCount,
|
||||||
TotalLengthM: fmt.Sprintf("%.2f", d.TotalLengthM),
|
TotalLengthM: fmt.Sprintf("%.2f", d.TotalLengthM),
|
||||||
Locations: d.Locations,
|
Locations: d.Locations,
|
||||||
SalesPrice: fmt.Sprintf("%.2f", d.SalesPrice),
|
SalesPrice: fmt.Sprintf("%.2f", d.SalesPrice),
|
||||||
|
|||||||
@ -27,10 +27,22 @@ func NewListPansLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPans
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *ListPansLogic) ListPans(in *pb.ListPanReq) (*pb.ListPanResp, error) {
|
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)
|
pans, err := l.svcCtx.PanModel.FindByProductId(l.ctx, in.ProductId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
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))
|
pbPans := make([]*pb.PanInfo, 0, len(pans))
|
||||||
for _, pan := range pans {
|
for _, pan := range pans {
|
||||||
@ -52,6 +64,8 @@ func (l *ListPansLogic) ListPans(in *pb.ListPanReq) (*pb.ListPanResp, error) {
|
|||||||
pbPans = append(pbPans, &pb.PanInfo{
|
pbPans = append(pbPans, &pb.PanInfo{
|
||||||
PanId: pan.PanId,
|
PanId: pan.PanId,
|
||||||
ProductId: pan.ProductId,
|
ProductId: pan.ProductId,
|
||||||
|
BatchId: pan.BatchId,
|
||||||
|
BatchNo: batchNoById[pan.BatchId],
|
||||||
Name: pan.Name,
|
Name: pan.Name,
|
||||||
Position: pan.Position,
|
Position: pan.Position,
|
||||||
SortOrder: pan.SortOrder,
|
SortOrder: pan.SortOrder,
|
||||||
|
|||||||
@ -39,6 +39,8 @@ func (l *ListPanViewLogic) ListPanView(in *pb.ListPanViewReq) (*pb.ListPanViewRe
|
|||||||
pbList = append(pbList, &pb.PanListItem{
|
pbList = append(pbList, &pb.PanListItem{
|
||||||
PanId: item.PanId,
|
PanId: item.PanId,
|
||||||
ProductId: item.ProductId,
|
ProductId: item.ProductId,
|
||||||
|
BatchId: item.BatchId,
|
||||||
|
BatchNo: item.BatchNo,
|
||||||
Name: item.Name,
|
Name: item.Name,
|
||||||
Position: item.Position,
|
Position: item.Position,
|
||||||
ProductName: item.ProductName,
|
ProductName: item.ProductName,
|
||||||
|
|||||||
40
rpc/inventory/internal/logic/listproductbatchlogic.go
Normal file
40
rpc/inventory/internal/logic/listproductbatchlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ package logic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"muyu-apiserver/pkg/tenantctx"
|
"muyu-apiserver/pkg/tenantctx"
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"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) {
|
func (l *ListProductLogic) ListProduct(in *pb.ListProductReq) (*pb.ListProductResp, error) {
|
||||||
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
list, total, err := l.svcCtx.ProductModel.FindList(l.ctx, tenantId, in.Page, in.PageSize, in.ProductName, in.Spec, in.Color, in.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 {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
pbList := make([]*pb.ProductInfo, 0, len(list))
|
pbList := make([]*pb.ProductInfo, 0, len(list))
|
||||||
for _, p := range list {
|
for _, p := range list {
|
||||||
pbList = append(pbList, &pb.ProductInfo{
|
pbList = append(pbList, productToPb(p))
|
||||||
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"),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.ListProductResp{
|
return &pb.ListProductResp{
|
||||||
|
|||||||
42
rpc/inventory/internal/logic/listyarnlogic.go
Normal file
42
rpc/inventory/internal/logic/listyarnlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
101
rpc/inventory/internal/logic/productcode.go
Normal file
101
rpc/inventory/internal/logic/productcode.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -32,6 +32,14 @@ func NewSaveBoltsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveBol
|
|||||||
|
|
||||||
func (l *SaveBoltsLogic) SaveBolts(in *pb.SaveBoltsReq) (*pb.Empty, error) {
|
func (l *SaveBoltsLogic) SaveBolts(in *pb.SaveBoltsReq) (*pb.Empty, error) {
|
||||||
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
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
|
var totalLengthM float64
|
||||||
bolts := make([]*model.InvProductBolt, 0, len(in.Lengths))
|
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(),
|
BoltId: uid.Generate(),
|
||||||
PanId: in.PanId,
|
PanId: in.PanId,
|
||||||
LengthM: lengthM,
|
LengthM: lengthM,
|
||||||
|
Color: product.Color,
|
||||||
SortOrder: int64(i + 1),
|
SortOrder: int64(i + 1),
|
||||||
|
TenantId: tenantId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package logic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"muyu-apiserver/model"
|
"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) {
|
func (l *SavePansLogic) SavePans(in *pb.SavePansReq) (*pb.Empty, error) {
|
||||||
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
tenantId := tenantctx.ExtractTenantId(l.ctx)
|
||||||
|
|
||||||
if err := l.svcCtx.BoltModel.DeleteByProductId(l.ctx, in.ProductId); err != nil {
|
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())
|
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 totalLengthM float64
|
||||||
var totalBolts int
|
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))
|
pans := make([]*model.InvProductPan, 0, len(in.Pans))
|
||||||
for i, panInput := range in.Pans {
|
for i, panInput := range in.Pans {
|
||||||
panId := uid.Generate()
|
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{
|
pans = append(pans, &model.InvProductPan{
|
||||||
PanId: panId,
|
PanId: panId,
|
||||||
ProductId: in.ProductId,
|
ProductId: in.ProductId,
|
||||||
|
BatchId: batchId,
|
||||||
Name: panInput.Name,
|
Name: panInput.Name,
|
||||||
Position: panInput.Position,
|
Position: panInput.Position,
|
||||||
SortOrder: int64(i + 1),
|
SortOrder: int64(i + 1),
|
||||||
@ -61,20 +96,30 @@ func (l *SavePansLogic) SavePans(in *pb.SavePansReq) (*pb.Empty, error) {
|
|||||||
BoltId: uid.Generate(),
|
BoltId: uid.Generate(),
|
||||||
PanId: panId,
|
PanId: panId,
|
||||||
LengthM: lengthM,
|
LengthM: lengthM,
|
||||||
|
Color: product.Color,
|
||||||
SortOrder: int64(j + 1),
|
SortOrder: int64(j + 1),
|
||||||
|
TenantId: tenantId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
totalBolts += len(panInput.BoltLengths)
|
totalBolts += len(panInput.BoltLengths)
|
||||||
if err := l.svcCtx.BoltModel.BulkReplace(l.ctx, panId, tenantId, bolts); err != nil {
|
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())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := l.svcCtx.PanModel.BulkReplace(l.ctx, in.ProductId, tenantId, pans); err != nil {
|
if err := l.svcCtx.PanModel.BulkReplace(l.ctx, in.ProductId, tenantId, pans); err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
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()
|
metrics.PansSavedTotal.WithLabelValues(tenantId, in.ProductId).Inc()
|
||||||
if totalLengthM > 0 {
|
if totalLengthM > 0 {
|
||||||
productName := l.resolveProductName(in.ProductId)
|
productName := l.resolveProductName(in.ProductId)
|
||||||
|
|||||||
43
rpc/inventory/internal/logic/updateproductbatchlogic.go
Normal file
43
rpc/inventory/internal/logic/updateproductbatchlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"muyu-apiserver/rpc/inventory/internal/svc"
|
"muyu-apiserver/rpc/inventory/internal/svc"
|
||||||
"muyu-apiserver/rpc/inventory/pb"
|
"muyu-apiserver/rpc/inventory/pb"
|
||||||
@ -35,10 +36,18 @@ func (l *UpdateProductLogic) UpdateProduct(in *pb.UpdateProductReq) (*pb.Empty,
|
|||||||
|
|
||||||
salesPrice, _ := strconv.ParseFloat(in.SalesPrice, 64)
|
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.ImageUrl = in.ImageUrl
|
||||||
product.Spec = in.Spec
|
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.SalesPrice = salesPrice
|
||||||
product.Remark = sql.NullString{String: in.Remark, Valid: in.Remark != ""}
|
product.Remark = sql.NullString{String: in.Remark, Valid: in.Remark != ""}
|
||||||
|
|
||||||
|
|||||||
62
rpc/inventory/internal/logic/updateyarnlogic.go
Normal file
62
rpc/inventory/internal/logic/updateyarnlogic.go
Normal file
@ -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
|
||||||
|
}
|
||||||
25
rpc/inventory/internal/logic/yarn_helpers.go
Normal file
25
rpc/inventory/internal/logic/yarn_helpers.go
Normal file
@ -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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -67,6 +67,53 @@ func (s *InventoryServiceServer) ListColorDetail(ctx context.Context, in *pb.Lis
|
|||||||
return l.ListColorDetail(in)
|
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
|
// Pan / Bolt list views
|
||||||
func (s *InventoryServiceServer) ListPanView(ctx context.Context, in *pb.ListPanViewReq) (*pb.ListPanViewResp, error) {
|
func (s *InventoryServiceServer) ListPanView(ctx context.Context, in *pb.ListPanViewReq) (*pb.ListPanViewResp, error) {
|
||||||
l := logic.NewListPanViewLogic(ctx, s.svcCtx)
|
l := logic.NewListPanViewLogic(ctx, s.svcCtx)
|
||||||
|
|||||||
@ -10,8 +10,11 @@ import (
|
|||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
ProductModel model.InvProductModel
|
ProductModel model.InvProductModel
|
||||||
|
YarnModel model.InvYarnModel
|
||||||
|
ProductBatchModel model.InvProductBatchModel
|
||||||
PanModel model.InvProductPanModel
|
PanModel model.InvProductPanModel
|
||||||
BoltModel model.InvProductBoltModel
|
BoltModel model.InvProductBoltModel
|
||||||
|
SupplierModel model.PurSupplierModel
|
||||||
ImportLogModel model.InvStockImportLogModel
|
ImportLogModel model.InvStockImportLogModel
|
||||||
StockCheckModel model.InvStockCheckModel
|
StockCheckModel model.InvStockCheckModel
|
||||||
CheckDetailModel model.InvStockCheckDetailModel
|
CheckDetailModel model.InvStockCheckDetailModel
|
||||||
@ -24,8 +27,11 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
ProductModel: model.NewInvProductModel(conn, c.Cache),
|
ProductModel: model.NewInvProductModel(conn, c.Cache),
|
||||||
|
YarnModel: model.NewInvYarnModel(conn),
|
||||||
|
ProductBatchModel: model.NewInvProductBatchModel(conn),
|
||||||
PanModel: model.NewInvProductPanModel(conn),
|
PanModel: model.NewInvProductPanModel(conn),
|
||||||
BoltModel: model.NewInvProductBoltModel(conn),
|
BoltModel: model.NewInvProductBoltModel(conn),
|
||||||
|
SupplierModel: model.NewPurSupplierModel(conn, c.Cache),
|
||||||
ImportLogModel: model.NewInvStockImportLogModel(conn, c.Cache),
|
ImportLogModel: model.NewInvStockImportLogModel(conn, c.Cache),
|
||||||
StockCheckModel: model.NewInvStockCheckModel(conn, c.Cache),
|
StockCheckModel: model.NewInvStockCheckModel(conn, c.Cache),
|
||||||
CheckDetailModel: model.NewInvStockCheckDetailModel(conn, c.Cache),
|
CheckDetailModel: model.NewInvStockCheckDetailModel(conn, c.Cache),
|
||||||
|
|||||||
@ -17,6 +17,8 @@ message ProductInfo {
|
|||||||
int64 status = 8;
|
int64 status = 8;
|
||||||
string created_at = 9;
|
string created_at = 9;
|
||||||
string updated_at = 10;
|
string updated_at = 10;
|
||||||
|
string color_no = 11;
|
||||||
|
string product_code = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateProductReq {
|
message CreateProductReq {
|
||||||
@ -27,6 +29,9 @@ message CreateProductReq {
|
|||||||
string sales_price = 5;
|
string sales_price = 5;
|
||||||
string remark = 6;
|
string remark = 6;
|
||||||
repeated PanInput pans = 7;
|
repeated PanInput pans = 7;
|
||||||
|
string color_no = 8;
|
||||||
|
ProductBatchInput initial_batch = 9;
|
||||||
|
string product_code = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateProductReq {
|
message UpdateProductReq {
|
||||||
@ -37,6 +42,7 @@ message UpdateProductReq {
|
|||||||
string color = 5;
|
string color = 5;
|
||||||
string sales_price = 6;
|
string sales_price = 6;
|
||||||
string remark = 7;
|
string remark = 7;
|
||||||
|
string color_no = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeleteProductReq {
|
message DeleteProductReq {
|
||||||
@ -54,6 +60,8 @@ message ListProductReq {
|
|||||||
string spec = 4;
|
string spec = 4;
|
||||||
string color = 5;
|
string color = 5;
|
||||||
int64 status = 6;
|
int64 status = 6;
|
||||||
|
string color_no = 7;
|
||||||
|
string product_code = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListProductResp {
|
message ListProductResp {
|
||||||
@ -72,12 +80,15 @@ message PanInfo {
|
|||||||
repeated BoltInfo bolts = 6;
|
repeated BoltInfo bolts = 6;
|
||||||
int64 bolt_count = 7;
|
int64 bolt_count = 7;
|
||||||
string total_length = 8;
|
string total_length = 8;
|
||||||
|
string batch_id = 9;
|
||||||
|
string batch_no = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PanInput {
|
message PanInput {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
string position = 2;
|
string position = 2;
|
||||||
repeated string bolt_lengths = 3;
|
repeated string bolt_lengths = 3;
|
||||||
|
string batch_id = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListPanReq {
|
message ListPanReq {
|
||||||
@ -157,6 +168,9 @@ message ColorDetailItem {
|
|||||||
string total_length_m = 8;
|
string total_length_m = 8;
|
||||||
string locations = 9;
|
string locations = 9;
|
||||||
string sales_price = 10;
|
string sales_price = 10;
|
||||||
|
string color_no = 11;
|
||||||
|
string product_code = 12;
|
||||||
|
int64 batch_count = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListColorDetailReq {
|
message ListColorDetailReq {
|
||||||
@ -178,6 +192,8 @@ message PanListItem {
|
|||||||
string colors = 6; // aggregated from bolt.color, no spec
|
string colors = 6; // aggregated from bolt.color, no spec
|
||||||
int64 bolt_count = 7;
|
int64 bolt_count = 7;
|
||||||
string total_length_m = 8;
|
string total_length_m = 8;
|
||||||
|
string batch_id = 9;
|
||||||
|
string batch_no = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListPanViewReq {
|
message ListPanViewReq {
|
||||||
@ -242,6 +258,116 @@ message ListImportLogResp {
|
|||||||
repeated ImportLogInfo list = 2;
|
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 {
|
message ImportLogInfo {
|
||||||
string import_id = 1;
|
string import_id = 1;
|
||||||
string file_name = 2;
|
string file_name = 2;
|
||||||
@ -440,6 +566,19 @@ service InventoryService {
|
|||||||
// Color Detail (panel 2)
|
// Color Detail (panel 2)
|
||||||
rpc ListColorDetail(ListColorDetailReq) returns (ListColorDetailResp);
|
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)
|
// Pan / Bolt list views (dimension panels)
|
||||||
rpc ListPanView(ListPanViewReq) returns (ListPanViewResp);
|
rpc ListPanView(ListPanViewReq) returns (ListPanViewResp);
|
||||||
rpc ListBoltView(ListBoltViewReq) returns (ListBoltViewResp);
|
rpc ListBoltView(ListBoltViewReq) returns (ListBoltViewResp);
|
||||||
|
|||||||
@ -20,13 +20,18 @@ type (
|
|||||||
ColorDetailItem = pb.ColorDetailItem
|
ColorDetailItem = pb.ColorDetailItem
|
||||||
ConfirmStockCheckReq = pb.ConfirmStockCheckReq
|
ConfirmStockCheckReq = pb.ConfirmStockCheckReq
|
||||||
CreateProductReq = pb.CreateProductReq
|
CreateProductReq = pb.CreateProductReq
|
||||||
|
CreateProductBatchReq = pb.CreateProductBatchReq
|
||||||
CreateStockAdjustReq = pb.CreateStockAdjustReq
|
CreateStockAdjustReq = pb.CreateStockAdjustReq
|
||||||
CreateStockCheckReq = pb.CreateStockCheckReq
|
CreateStockCheckReq = pb.CreateStockCheckReq
|
||||||
|
CreateYarnReq = pb.CreateYarnReq
|
||||||
|
DeleteProductBatchReq = pb.DeleteProductBatchReq
|
||||||
DeleteProductReq = pb.DeleteProductReq
|
DeleteProductReq = pb.DeleteProductReq
|
||||||
|
DeleteYarnReq = pb.DeleteYarnReq
|
||||||
Empty = pb.Empty
|
Empty = pb.Empty
|
||||||
GetProductReq = pb.GetProductReq
|
GetProductReq = pb.GetProductReq
|
||||||
GetStockAdjustReq = pb.GetStockAdjustReq
|
GetStockAdjustReq = pb.GetStockAdjustReq
|
||||||
GetStockCheckReq = pb.GetStockCheckReq
|
GetStockCheckReq = pb.GetStockCheckReq
|
||||||
|
GetYarnReq = pb.GetYarnReq
|
||||||
IdResp = pb.IdResp
|
IdResp = pb.IdResp
|
||||||
ImportLogInfo = pb.ImportLogInfo
|
ImportLogInfo = pb.ImportLogInfo
|
||||||
ImportProductReq = pb.ImportProductReq
|
ImportProductReq = pb.ImportProductReq
|
||||||
@ -44,6 +49,8 @@ type (
|
|||||||
ListImportLogResp = pb.ListImportLogResp
|
ListImportLogResp = pb.ListImportLogResp
|
||||||
ListPanReq = pb.ListPanReq
|
ListPanReq = pb.ListPanReq
|
||||||
ListPanResp = pb.ListPanResp
|
ListPanResp = pb.ListPanResp
|
||||||
|
ListProductBatchReq = pb.ListProductBatchReq
|
||||||
|
ListProductBatchResp = pb.ListProductBatchResp
|
||||||
ListProductReq = pb.ListProductReq
|
ListProductReq = pb.ListProductReq
|
||||||
ListProductResp = pb.ListProductResp
|
ListProductResp = pb.ListProductResp
|
||||||
ListProductSummaryReq = pb.ListProductSummaryReq
|
ListProductSummaryReq = pb.ListProductSummaryReq
|
||||||
@ -52,8 +59,12 @@ type (
|
|||||||
ListStockAdjustResp = pb.ListStockAdjustResp
|
ListStockAdjustResp = pb.ListStockAdjustResp
|
||||||
ListStockCheckReq = pb.ListStockCheckReq
|
ListStockCheckReq = pb.ListStockCheckReq
|
||||||
ListStockCheckResp = pb.ListStockCheckResp
|
ListStockCheckResp = pb.ListStockCheckResp
|
||||||
|
ListYarnReq = pb.ListYarnReq
|
||||||
|
ListYarnResp = pb.ListYarnResp
|
||||||
PanInfo = pb.PanInfo
|
PanInfo = pb.PanInfo
|
||||||
PanInput = pb.PanInput
|
PanInput = pb.PanInput
|
||||||
|
ProductBatchInfo = pb.ProductBatchInfo
|
||||||
|
ProductBatchInput = pb.ProductBatchInput
|
||||||
ProductInfo = pb.ProductInfo
|
ProductInfo = pb.ProductInfo
|
||||||
ProductSummaryItem = pb.ProductSummaryItem
|
ProductSummaryItem = pb.ProductSummaryItem
|
||||||
ProductTreeResp = pb.ProductTreeResp
|
ProductTreeResp = pb.ProductTreeResp
|
||||||
@ -70,8 +81,11 @@ type (
|
|||||||
StockGroupResp = pb.StockGroupResp
|
StockGroupResp = pb.StockGroupResp
|
||||||
StockSummaryReq = pb.StockSummaryReq
|
StockSummaryReq = pb.StockSummaryReq
|
||||||
StockSummaryResp = pb.StockSummaryResp
|
StockSummaryResp = pb.StockSummaryResp
|
||||||
|
UpdateProductBatchReq = pb.UpdateProductBatchReq
|
||||||
UpdateProductReq = pb.UpdateProductReq
|
UpdateProductReq = pb.UpdateProductReq
|
||||||
UpdateStockCheckReq = pb.UpdateStockCheckReq
|
UpdateStockCheckReq = pb.UpdateStockCheckReq
|
||||||
|
UpdateYarnReq = pb.UpdateYarnReq
|
||||||
|
YarnInfo = pb.YarnInfo
|
||||||
|
|
||||||
InventoryService interface {
|
InventoryService interface {
|
||||||
// Product CRUD
|
// Product CRUD
|
||||||
@ -86,6 +100,17 @@ type (
|
|||||||
ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error)
|
ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error)
|
||||||
// Color Detail (panel 2)
|
// Color Detail (panel 2)
|
||||||
ListColorDetail(ctx context.Context, in *ListColorDetailReq, opts ...grpc.CallOption) (*ListColorDetailResp, error)
|
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
|
// Pan / Bolt list views
|
||||||
ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error)
|
ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error)
|
||||||
ListBoltView(ctx context.Context, in *ListBoltViewReq, opts ...grpc.CallOption) (*ListBoltViewResp, 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...)
|
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) {
|
func (m *defaultInventoryService) ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error) {
|
||||||
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
client := pb.NewInventoryServiceClient(m.cli.Conn())
|
||||||
return client.ListPanView(ctx, in, opts...)
|
return client.ListPanView(ctx, in, opts...)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.5.1
|
// - protoc-gen-go-grpc v1.6.2
|
||||||
// - protoc v5.29.3
|
// - protoc v7.34.1
|
||||||
// source: inventory.proto
|
// source: inventory.proto
|
||||||
|
|
||||||
package pb
|
package pb
|
||||||
@ -27,6 +27,15 @@ const (
|
|||||||
InventoryService_GetProductTree_FullMethodName = "/inventory.InventoryService/GetProductTree"
|
InventoryService_GetProductTree_FullMethodName = "/inventory.InventoryService/GetProductTree"
|
||||||
InventoryService_ListProductSummary_FullMethodName = "/inventory.InventoryService/ListProductSummary"
|
InventoryService_ListProductSummary_FullMethodName = "/inventory.InventoryService/ListProductSummary"
|
||||||
InventoryService_ListColorDetail_FullMethodName = "/inventory.InventoryService/ListColorDetail"
|
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_ListPanView_FullMethodName = "/inventory.InventoryService/ListPanView"
|
||||||
InventoryService_ListBoltView_FullMethodName = "/inventory.InventoryService/ListBoltView"
|
InventoryService_ListBoltView_FullMethodName = "/inventory.InventoryService/ListBoltView"
|
||||||
InventoryService_ListPans_FullMethodName = "/inventory.InventoryService/ListPans"
|
InventoryService_ListPans_FullMethodName = "/inventory.InventoryService/ListPans"
|
||||||
@ -64,6 +73,17 @@ type InventoryServiceClient interface {
|
|||||||
ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error)
|
ListProductSummary(ctx context.Context, in *ListProductSummaryReq, opts ...grpc.CallOption) (*ListProductSummaryResp, error)
|
||||||
// Color Detail (panel 2)
|
// Color Detail (panel 2)
|
||||||
ListColorDetail(ctx context.Context, in *ListColorDetailReq, opts ...grpc.CallOption) (*ListColorDetailResp, error)
|
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)
|
// Pan / Bolt list views (dimension panels)
|
||||||
ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error)
|
ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error)
|
||||||
ListBoltView(ctx context.Context, in *ListBoltViewReq, opts ...grpc.CallOption) (*ListBoltViewResp, 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
|
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) {
|
func (c *inventoryServiceClient) ListPanView(ctx context.Context, in *ListPanViewReq, opts ...grpc.CallOption) (*ListPanViewResp, error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListPanViewResp)
|
out := new(ListPanViewResp)
|
||||||
@ -386,6 +496,17 @@ type InventoryServiceServer interface {
|
|||||||
ListProductSummary(context.Context, *ListProductSummaryReq) (*ListProductSummaryResp, error)
|
ListProductSummary(context.Context, *ListProductSummaryReq) (*ListProductSummaryResp, error)
|
||||||
// Color Detail (panel 2)
|
// Color Detail (panel 2)
|
||||||
ListColorDetail(context.Context, *ListColorDetailReq) (*ListColorDetailResp, error)
|
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)
|
// Pan / Bolt list views (dimension panels)
|
||||||
ListPanView(context.Context, *ListPanViewReq) (*ListPanViewResp, error)
|
ListPanView(context.Context, *ListPanViewReq) (*ListPanViewResp, error)
|
||||||
ListBoltView(context.Context, *ListBoltViewReq) (*ListBoltViewResp, error)
|
ListBoltView(context.Context, *ListBoltViewReq) (*ListBoltViewResp, error)
|
||||||
@ -423,85 +544,112 @@ type InventoryServiceServer interface {
|
|||||||
type UnimplementedInventoryServiceServer struct{}
|
type UnimplementedInventoryServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedInventoryServiceServer) CreateProduct(context.Context, *CreateProductReq) (*IdResp, error) {
|
func (UnimplementedInventoryServiceServer) CreateProduct(context.Context, *CreateProductReq) (*IdResp, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CreateProduct not implemented")
|
return nil, status.Error(codes.Unimplemented, "method CreateProduct not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedInventoryServiceServer) UpdateProduct(context.Context, *UpdateProductReq) (*Empty, error) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) mustEmbedUnimplementedInventoryServiceServer() {}
|
||||||
func (UnimplementedInventoryServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedInventoryServiceServer) testEmbeddedByValue() {}
|
||||||
@ -514,7 +662,7 @@ type UnsafeInventoryServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterInventoryServiceServer(s grpc.ServiceRegistrar, srv InventoryServiceServer) {
|
func RegisterInventoryServiceServer(s grpc.ServiceRegistrar, srv InventoryServiceServer) {
|
||||||
// If the following call pancis, it indicates UnimplementedInventoryServiceServer was
|
// If the following call panics, it indicates UnimplementedInventoryServiceServer was
|
||||||
// embedded by pointer and is nil. This will cause panics if an
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
// unimplemented method is ever invoked, so we test this at initialization
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
// time to prevent it from happening at runtime later due to I/O.
|
// 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)
|
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) {
|
func _InventoryService_ListPanView_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(ListPanViewReq)
|
in := new(ListPanViewReq)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@ -1049,6 +1359,42 @@ var InventoryService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "ListColorDetail",
|
MethodName: "ListColorDetail",
|
||||||
Handler: _InventoryService_ListColorDetail_Handler,
|
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",
|
MethodName: "ListPanView",
|
||||||
Handler: _InventoryService_ListPanView_Handler,
|
Handler: _InventoryService_ListPanView_Handler,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user