Compare commits
No commits in common. "e3f6fa236d0edbfeef8e28d5b4f70c168900ce24" and "7a8df1f0d492814aef21944432cfa44c5c4d8db7" have entirely different histories.
e3f6fa236d
...
7a8df1f0d4
8
.gitignore
vendored
8
.gitignore
vendored
@ -99,11 +99,3 @@ Temporary Items
|
||||
# Local runtime data and certificates
|
||||
data/
|
||||
deploy/bin/
|
||||
|
||||
# Node modules — install via `cd deploy/tools && npm ci`
|
||||
node_modules/
|
||||
|
||||
# Environment secrets
|
||||
.env
|
||||
deploy/.env
|
||||
!deploy/.env.example
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
stages:
|
||||
- build-1
|
||||
- build-2
|
||||
- build-3
|
||||
|
||||
variables:
|
||||
HARBOR_REGISTRY: harbor-in-k3s.cheverjohn.me
|
||||
@ -14,8 +13,7 @@ variables:
|
||||
.build-template: &build-template
|
||||
image: docker:27
|
||||
services:
|
||||
- name: docker:27-dind
|
||||
command: ["--dns", "10.43.0.10", "--dns", "223.5.5.5"]
|
||||
- docker:27-dind
|
||||
retry: 2
|
||||
before_script:
|
||||
- until docker info >/dev/null 2>&1; do echo "Waiting for Docker daemon..."; sleep 2; done
|
||||
@ -24,18 +22,14 @@ variables:
|
||||
- |
|
||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||
TAG="$CI_COMMIT_TAG"
|
||||
elif [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
||||
TAG="main-${CI_COMMIT_SHORT_SHA}"
|
||||
else
|
||||
TAG="feat-${CI_COMMIT_SHORT_SHA}"
|
||||
TAG="main-${CI_COMMIT_SHORT_SHA}"
|
||||
fi
|
||||
- docker build --network host -t $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$TAG -f $DOCKERFILE_PATH .
|
||||
- docker build -t $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$TAG -f $DOCKERFILE_PATH .
|
||||
- docker push $HARBOR_REGISTRY/$HARBOR_PROJECT/$IMAGE_NAME:$TAG
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
- if: $CI_COMMIT_TAG =~ /^v/
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
- if: $CI_COMMIT_BRANCH =~ /^feat\//
|
||||
|
||||
build-muyu-gateway:
|
||||
<<: *build-template
|
||||
@ -57,17 +51,3 @@ build-muyu-inventory-rpc:
|
||||
variables:
|
||||
IMAGE_NAME: muyu-inventory-rpc
|
||||
DOCKERFILE_PATH: deploy/Dockerfile.inventory
|
||||
|
||||
build-muyu-purchase-rpc:
|
||||
<<: *build-template
|
||||
stage: build-2
|
||||
variables:
|
||||
IMAGE_NAME: muyu-purchase-rpc
|
||||
DOCKERFILE_PATH: deploy/Dockerfile.purchase
|
||||
|
||||
build-muyu-production-rpc:
|
||||
<<: *build-template
|
||||
stage: build-3
|
||||
variables:
|
||||
IMAGE_NAME: muyu-production-rpc
|
||||
DOCKERFILE_PATH: deploy/Dockerfile.production
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
# Copy this file to .env and fill in real values
|
||||
# NEVER commit .env to git
|
||||
|
||||
# Database passwords (REQUIRED)
|
||||
MYSQL_ROOT_PASSWORD=your_mysql_password_here
|
||||
POSTGRES_PASSWORD=your_postgres_password_here
|
||||
|
||||
# JWT secret for gateway auth (REQUIRED)
|
||||
ACCESS_SECRET=your_jwt_secret_here
|
||||
|
||||
# Neo4j (only needed for graph stack: docker-compose.graph.yaml)
|
||||
NEO4J_AUTH=neo4j/your_neo4j_password_here
|
||||
NEO4J_PASS=your_neo4j_password_here
|
||||
@ -11,12 +11,10 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./gateway/gateway.
|
||||
|
||||
FROM ${BASE_REGISTRY}/alpine:3.20
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache ca-certificates tzdata gettext
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY --from=builder /server ./gateway
|
||||
COPY deploy/etc/gateway.yaml etc/gateway.yaml
|
||||
COPY deploy/tools/ tools/
|
||||
COPY deploy/entrypoint.sh /entrypoint.sh
|
||||
EXPOSE 8888
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["./gateway", "-f", "etc/gateway.yaml"]
|
||||
|
||||
@ -11,11 +11,9 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./rpc/inventory/in
|
||||
|
||||
FROM ${BASE_REGISTRY}/alpine:3.20
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache ca-certificates tzdata gettext
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY --from=builder /server ./inventory
|
||||
COPY deploy/etc/inventory.yaml etc/inventory.yaml
|
||||
COPY deploy/entrypoint.sh /entrypoint.sh
|
||||
EXPOSE 9002
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["./inventory", "-f", "etc/inventory.yaml"]
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
ARG BASE_REGISTRY=harbor-in-k3s.cheverjohn.me/library
|
||||
FROM ${BASE_REGISTRY}/golang:1.24-alpine AS builder
|
||||
ENV GOPROXY=https://goproxy.cn,direct
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache git
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./rpc/production/production.go
|
||||
|
||||
FROM ${BASE_REGISTRY}/alpine:3.20
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache ca-certificates tzdata gettext
|
||||
WORKDIR /app
|
||||
COPY --from=builder /server ./production
|
||||
COPY deploy/etc/production.yaml etc/production.yaml
|
||||
COPY deploy/entrypoint.sh /entrypoint.sh
|
||||
EXPOSE 9004
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["./production", "-f", "etc/production.yaml"]
|
||||
@ -1,21 +1,7 @@
|
||||
ARG BASE_REGISTRY=harbor-in-k3s.cheverjohn.me/library
|
||||
FROM ${BASE_REGISTRY}/golang:1.24-alpine AS builder
|
||||
ENV GOPROXY=https://goproxy.cn,direct
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache git
|
||||
FROM alpine:3.19
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./rpc/purchase/purchase.go
|
||||
|
||||
FROM ${BASE_REGISTRY}/alpine:3.20
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache ca-certificates tzdata gettext
|
||||
WORKDIR /app
|
||||
COPY --from=builder /server ./purchase
|
||||
COPY deploy/bin/purchase .
|
||||
COPY deploy/etc/purchase.yaml etc/purchase.yaml
|
||||
COPY deploy/entrypoint.sh /entrypoint.sh
|
||||
EXPOSE 9003
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["./purchase", "-f", "etc/purchase.yaml"]
|
||||
|
||||
@ -11,11 +11,9 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./rpc/system/syste
|
||||
|
||||
FROM ${BASE_REGISTRY}/alpine:3.20
|
||||
RUN sed -i "s|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g" /etc/apk/repositories
|
||||
RUN apk add --no-cache ca-certificates tzdata gettext
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
COPY --from=builder /server ./system
|
||||
COPY deploy/etc/system.yaml etc/system.yaml
|
||||
COPY deploy/entrypoint.sh /entrypoint.sh
|
||||
EXPOSE 9001
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["./system", "-f", "etc/system.yaml"]
|
||||
|
||||
@ -5,7 +5,7 @@ services:
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: muyu
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
|
||||
POSTGRES_PASSWORD: muyu2026
|
||||
POSTGRES_DB: muyu_crm
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
@ -70,7 +70,7 @@ services:
|
||||
container_name: muyu-neo4j
|
||||
restart: always
|
||||
environment:
|
||||
NEO4J_AUTH: ${NEO4J_AUTH:?Set NEO4J_AUTH in .env (e.g. neo4j/yourpassword)}
|
||||
NEO4J_AUTH: neo4j/muyu2026
|
||||
NEO4J_server_memory_heap_initial__size: 512m
|
||||
NEO4J_server_memory_heap_max__size: 1024m
|
||||
NEO4J_server_default__listen__address: 0.0.0.0
|
||||
@ -103,7 +103,7 @@ services:
|
||||
KAFKA_GROUP: graphsync
|
||||
NEO4J_URI: bolt://neo4j:7687
|
||||
NEO4J_USER: neo4j
|
||||
NEO4J_PASS: ${NEO4J_PASS:?Set NEO4J_PASS in .env}
|
||||
NEO4J_PASS: muyu2026
|
||||
TZ: Asia/Shanghai
|
||||
|
||||
kafka-ui:
|
||||
|
||||
@ -4,7 +4,7 @@ services:
|
||||
container_name: muyu-mysql
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?Set MYSQL_ROOT_PASSWORD in .env}
|
||||
MYSQL_ROOT_PASSWORD: muyu2026
|
||||
MYSQL_DATABASE: muyu_wms
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
@ -39,7 +39,7 @@ services:
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: muyu
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
|
||||
POSTGRES_PASSWORD: muyu2026
|
||||
POSTGRES_DB: muyu_crm
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
@ -90,7 +90,6 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
MYSQL_DSN: "root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
|
||||
|
||||
inventory-rpc:
|
||||
build:
|
||||
@ -107,7 +106,6 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
MYSQL_DSN: "root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
|
||||
|
||||
purchase-rpc:
|
||||
build:
|
||||
@ -124,28 +122,6 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
MYSQL_DSN: "root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
|
||||
|
||||
production-rpc:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/Dockerfile.production
|
||||
container_name: muyu-production-rpc
|
||||
restart: always
|
||||
ports:
|
||||
- "9004:9004"
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
etcd:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./etc/production.yaml:/etc/muyu/production.yaml
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
MYSQL_DSN: "root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
|
||||
|
||||
gateway:
|
||||
build:
|
||||
@ -162,15 +138,10 @@ services:
|
||||
condition: service_started
|
||||
purchase-rpc:
|
||||
condition: service_started
|
||||
production-rpc:
|
||||
condition: service_started
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
MYSQL_DSN: "root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
|
||||
POSTGRES_DSN: "postgres://muyu:${POSTGRES_PASSWORD}@postgres:5432/muyu_crm?sslmode=disable"
|
||||
ACCESS_SECRET: ${ACCESS_SECRET:?Set ACCESS_SECRET in .env}
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Substitute environment variables in YAML config templates before starting the service.
|
||||
# Usage: entrypoint.sh <binary> -f <config.yaml>
|
||||
#
|
||||
# The YAML file is treated as a template with ${VAR} placeholders.
|
||||
# envsubst replaces them with actual environment variable values at container start time.
|
||||
# The rendered config is written to /tmp to avoid read-only filesystem issues (e.g. ConfigMap mounts).
|
||||
|
||||
set -e
|
||||
|
||||
BINARY="$1"
|
||||
shift
|
||||
|
||||
# Scan args for -f <config> and render to /tmp
|
||||
ARGS=""
|
||||
PREV=""
|
||||
for arg in "$@"; do
|
||||
if [ "$PREV" = "-f" ] && [ -f "$arg" ]; then
|
||||
RENDERED="/tmp/$(basename "$arg")"
|
||||
envsubst < "$arg" > "$RENDERED"
|
||||
ARGS="$ARGS $RENDERED"
|
||||
else
|
||||
ARGS="$ARGS $arg"
|
||||
fi
|
||||
PREV="$arg"
|
||||
done
|
||||
|
||||
exec "$BINARY" $ARGS
|
||||
@ -4,12 +4,12 @@ Port: 8888
|
||||
Timeout: 120000
|
||||
|
||||
Auth:
|
||||
AccessSecret: ${ACCESS_SECRET}
|
||||
AccessSecret: muyu-wms-jwt-secret-key-2026
|
||||
AccessExpire: 7200
|
||||
DefaultTenantId: t_default_001
|
||||
|
||||
DataSource: ${MYSQL_DSN}
|
||||
PostgresDataSource: ${POSTGRES_DSN}
|
||||
DataSource: root:muyu2026@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
PostgresDataSource: "postgres://muyu:muyu2026@postgres:5432/muyu_crm?sslmode=disable"
|
||||
|
||||
SystemRpc:
|
||||
Etcd:
|
||||
@ -34,14 +34,6 @@ PurchaseRpc:
|
||||
NonBlock: true
|
||||
Timeout: 60000
|
||||
|
||||
ProductionRpc:
|
||||
Etcd:
|
||||
Hosts:
|
||||
- etcd:2379
|
||||
Key: production.rpc
|
||||
NonBlock: true
|
||||
Timeout: 60000
|
||||
|
||||
Log:
|
||||
ServiceName: gateway-api
|
||||
Mode: console
|
||||
|
||||
@ -6,7 +6,7 @@ Etcd:
|
||||
- etcd:2379
|
||||
Key: inventory.rpc
|
||||
|
||||
DataSource: ${MYSQL_DSN}
|
||||
DataSource: root:muyu2026@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
|
||||
Cache:
|
||||
- Host: redis:6379
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
Name: production.rpc
|
||||
ListenOn: 0.0.0.0:9004
|
||||
|
||||
Etcd:
|
||||
Hosts:
|
||||
- etcd:2379
|
||||
Key: production.rpc
|
||||
|
||||
DataSource: ${MYSQL_DSN}
|
||||
|
||||
Cache:
|
||||
- Host: redis:6379
|
||||
|
||||
Log:
|
||||
ServiceName: production-rpc
|
||||
Mode: console
|
||||
Level: info
|
||||
@ -6,7 +6,7 @@ Etcd:
|
||||
- etcd:2379
|
||||
Key: purchase.rpc
|
||||
|
||||
DataSource: ${MYSQL_DSN}
|
||||
DataSource: root:muyu2026@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
|
||||
Cache:
|
||||
- Host: redis:6379
|
||||
|
||||
@ -6,7 +6,7 @@ Etcd:
|
||||
- etcd:2379
|
||||
Key: system.rpc
|
||||
|
||||
DataSource: ${MYSQL_DSN}
|
||||
DataSource: root:muyu2026@tcp(mysql:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
|
||||
Cache:
|
||||
- Host: redis:6379
|
||||
|
||||
@ -210,14 +210,16 @@ CREATE TABLE `crm_data_migration_log` (
|
||||
|
||||
CREATE TABLE `inv_product` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT 't_default_001',
|
||||
`product_id` VARCHAR(32) NOT NULL,
|
||||
`product_name` VARCHAR(100) NOT NULL,
|
||||
`image_url` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`spec` VARCHAR(100) NOT NULL DEFAULT '',
|
||||
`color` VARCHAR(50) NOT NULL DEFAULT '本色',
|
||||
`color_no` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
`product_code` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`color` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`unit_pieces` INT NOT NULL DEFAULT 0,
|
||||
`unit_rolls` INT NOT NULL DEFAULT 0,
|
||||
`stock_quantity` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`location` VARCHAR(100) NOT NULL DEFAULT '',
|
||||
`cost_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`sales_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`remark` TEXT,
|
||||
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '1:enabled 0:disabled',
|
||||
@ -226,96 +228,12 @@ CREATE TABLE `inv_product` (
|
||||
`deleted_at` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_product_id` (`product_id`),
|
||||
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`),
|
||||
UNIQUE KEY `uk_product_name_spec_color` (`product_name`, `spec`, `color`),
|
||||
KEY `idx_color` (`color`),
|
||||
KEY `idx_location` (`location`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_deleted_at` (`deleted_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 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='产品匹库存';
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE `inv_stock_import_log` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
-- End-to-End Validation Queries for Production Plan Collaboration
|
||||
-- Run these after testing the full flow to verify data consistency
|
||||
|
||||
-- 1. Verify production plan exists and has correct structure
|
||||
SELECT p.plan_id, p.plan_code, p.product_name, p.target_quantity,
|
||||
p.completed_quantity, p.status,
|
||||
ROUND(p.completed_quantity * 100.0 / NULLIF(p.target_quantity, 0), 1) as progress_pct
|
||||
FROM pro_production_plan p
|
||||
WHERE p.tenant_id = 'TEST_TENANT'
|
||||
ORDER BY p.created_at DESC LIMIT 5;
|
||||
|
||||
-- 2. Verify yarn ratios sum to 100%
|
||||
SELECT yr.plan_id,
|
||||
COUNT(*) as ratio_count,
|
||||
SUM(yr.ratio) as total_ratio,
|
||||
CASE WHEN ABS(SUM(yr.ratio) - 1.0) < 0.01 THEN 'OK' ELSE 'MISMATCH' END as check_result
|
||||
FROM pro_plan_yarn_ratio yr
|
||||
GROUP BY yr.plan_id;
|
||||
|
||||
-- 3. Verify process steps — each plan should have exactly 5 steps
|
||||
SELECT ps.plan_id,
|
||||
COUNT(*) as step_count,
|
||||
SUM(CASE WHEN ps.status = 2 THEN 1 ELSE 0 END) as completed_steps,
|
||||
CASE WHEN COUNT(*) = 5 THEN 'OK' ELSE 'MISSING_STEPS' END as check_result
|
||||
FROM pro_plan_process_step ps
|
||||
GROUP BY ps.plan_id;
|
||||
|
||||
-- 4. Verify share link lifecycle
|
||||
SELECT sl.short_code, sl.status, sl.click_count,
|
||||
sl.expires_at, NOW() as current_time,
|
||||
CASE WHEN sl.expires_at > NOW() THEN 'VALID' ELSE 'EXPIRED' END as expiry_check,
|
||||
pf.factory_tenant_id
|
||||
FROM pro_share_link sl
|
||||
LEFT JOIN pro_plan_factory pf ON pf.plan_id = sl.plan_id
|
||||
ORDER BY sl.created_at DESC LIMIT 5;
|
||||
|
||||
-- 5. CRITICAL: Verify data consistency — completed_quantity must equal SUM(inbound)
|
||||
SELECT p.plan_id, p.plan_code,
|
||||
p.completed_quantity as plan_completed,
|
||||
COALESCE(SUM(ir.quantity), 0) as inbound_sum,
|
||||
CASE
|
||||
WHEN ABS(p.completed_quantity - COALESCE(SUM(ir.quantity), 0)) < 0.01 THEN 'CONSISTENT'
|
||||
ELSE 'DRIFT_DETECTED'
|
||||
END as consistency_check
|
||||
FROM pro_production_plan p
|
||||
LEFT JOIN pro_inbound_record ir ON ir.plan_id = p.plan_id
|
||||
GROUP BY p.plan_id, p.plan_code, p.completed_quantity;
|
||||
|
||||
-- 6. Verify auto-completion: plans with completed_quantity >= target_quantity should be status=3
|
||||
SELECT p.plan_id, p.plan_code,
|
||||
p.target_quantity, p.completed_quantity, p.status,
|
||||
CASE
|
||||
WHEN p.completed_quantity >= p.target_quantity AND p.status != 3 THEN 'SHOULD_BE_COMPLETED'
|
||||
WHEN p.completed_quantity < p.target_quantity AND p.status = 3 THEN 'PREMATURE_COMPLETION'
|
||||
ELSE 'OK'
|
||||
END as auto_complete_check
|
||||
FROM pro_production_plan p
|
||||
WHERE p.status IN (2, 3);
|
||||
|
||||
-- 7. Verify inventory logs match inbound records
|
||||
SELECT ir.record_id, ir.quantity,
|
||||
il.change_qty, il.ref_type, il.ref_id,
|
||||
CASE
|
||||
WHEN il.log_id IS NULL THEN 'MISSING_LOG'
|
||||
WHEN ABS(ir.quantity - il.change_qty) < 0.01 THEN 'OK'
|
||||
ELSE 'QUANTITY_MISMATCH'
|
||||
END as log_check
|
||||
FROM pro_inbound_record ir
|
||||
LEFT JOIN inv_inventory_log il ON il.ref_id = ir.record_id AND il.ref_type = 'PRODUCTION';
|
||||
|
||||
-- 8. Summary report
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM pro_production_plan) as total_plans,
|
||||
(SELECT COUNT(*) FROM pro_production_plan WHERE status = 3) as completed_plans,
|
||||
(SELECT COUNT(*) FROM pro_share_link) as total_links,
|
||||
(SELECT COUNT(*) FROM pro_share_link WHERE status = 2) as confirmed_links,
|
||||
(SELECT COUNT(*) FROM pro_inbound_record) as total_inbound_records,
|
||||
(SELECT COALESCE(SUM(quantity), 0) FROM pro_inbound_record) as total_inbound_meters,
|
||||
(SELECT COUNT(*) FROM inv_inventory_log WHERE ref_type = 'PRODUCTION') as production_inv_logs;
|
||||
@ -1,133 +0,0 @@
|
||||
-- Phase 3: Production Plan Collaboration + Batch Inbound
|
||||
|
||||
-- ==================== Production Plan ====================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pro_production_plan` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`plan_id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`plan_code` VARCHAR(32) NOT NULL COMMENT 'PP-YYYYMMDD-XXXX',
|
||||
`product_id` VARCHAR(32) NOT NULL,
|
||||
`product_name` VARCHAR(100) NOT NULL DEFAULT '',
|
||||
`color` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`fabric_code` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`color_code` VARCHAR(20) NOT NULL DEFAULT '',
|
||||
`target_quantity` DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT 'target meters',
|
||||
`completed_quantity` DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT 'completed meters = SUM(inbound)',
|
||||
`yarn_usage_per_meter` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 'grams per meter',
|
||||
`production_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 'yuan per meter',
|
||||
`supplier_id` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'pur_supplier.supplier_id as textile factory',
|
||||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0:draft 1:pending 2:producing 3:completed 4:cancelled',
|
||||
`remark` TEXT,
|
||||
`start_time` DATETIME DEFAULT NULL,
|
||||
`creator` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`operator` 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_plan_id` (`plan_id`),
|
||||
UNIQUE KEY `uk_plan_code_tenant` (`plan_code`, `tenant_id`),
|
||||
KEY `idx_tenant_status` (`tenant_id`, `status`),
|
||||
KEY `idx_product` (`product_id`),
|
||||
KEY `idx_supplier` (`supplier_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='生产计划';
|
||||
|
||||
-- ==================== Yarn Ratio ====================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pro_plan_yarn_ratio` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`ratio_id` VARCHAR(32) NOT NULL,
|
||||
`plan_id` VARCHAR(32) NOT NULL,
|
||||
`yarn_name` VARCHAR(100) NOT NULL DEFAULT '',
|
||||
`ratio` DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT '0.00-1.00',
|
||||
`amount_per_meter` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 'grams',
|
||||
`total_amount` DECIMAL(14,2) NOT NULL DEFAULT 0.00 COMMENT 'grams',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_ratio_id` (`ratio_id`),
|
||||
KEY `idx_plan` (`plan_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='纱线配比';
|
||||
|
||||
-- ==================== Process Step ====================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pro_plan_process_step` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`step_id` VARCHAR(32) NOT NULL,
|
||||
`plan_id` VARCHAR(32) NOT NULL,
|
||||
`step_type` VARCHAR(30) NOT NULL COMMENT 'confirm|yarn_purchase|dyeing|machine_start|fabric_warehouse',
|
||||
`step_order` TINYINT NOT NULL DEFAULT 0,
|
||||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0:pending 1:in_progress 2:completed',
|
||||
`operator_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`completed_at` DATETIME DEFAULT NULL,
|
||||
`remark` TEXT,
|
||||
`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_step_id` (`step_id`),
|
||||
UNIQUE KEY `uk_plan_step` (`plan_id`, `step_type`),
|
||||
KEY `idx_plan` (`plan_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='生产流程节点';
|
||||
|
||||
-- ==================== Share Link ====================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pro_share_link` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`link_id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`plan_id` VARCHAR(32) NOT NULL,
|
||||
`short_code` VARCHAR(16) NOT NULL,
|
||||
`token` VARCHAR(512) NOT NULL DEFAULT '',
|
||||
`factory_type` VARCHAR(20) NOT NULL DEFAULT 'textile',
|
||||
`hide_sensitive` TINYINT NOT NULL DEFAULT 0,
|
||||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0:pending 1:clicked 2:confirmed 3:rejected 4:expired',
|
||||
`click_count` INT NOT NULL DEFAULT 0,
|
||||
`clicked_at` DATETIME DEFAULT NULL,
|
||||
`responded_at` DATETIME DEFAULT NULL,
|
||||
`reject_reason` VARCHAR(500) NOT NULL DEFAULT '',
|
||||
`expires_at` DATETIME NOT NULL,
|
||||
`created_by` 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_link_id` (`link_id`),
|
||||
UNIQUE KEY `uk_short_code` (`short_code`),
|
||||
KEY `idx_plan` (`plan_id`),
|
||||
KEY `idx_tenant` (`tenant_id`),
|
||||
KEY `idx_status_expires` (`status`, `expires_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='分享链接';
|
||||
|
||||
-- ==================== Plan Factory ====================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pro_plan_factory` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`plan_id` VARCHAR(32) NOT NULL,
|
||||
`factory_tenant_id` VARCHAR(32) NOT NULL,
|
||||
`factory_type` VARCHAR(20) NOT NULL DEFAULT 'textile',
|
||||
`share_link_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_plan_factory` (`plan_id`, `factory_tenant_id`),
|
||||
KEY `idx_factory` (`factory_tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计划-工厂关联';
|
||||
|
||||
-- ==================== Inbound Record ====================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pro_inbound_record` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`record_id` VARCHAR(32) NOT NULL,
|
||||
`tenant_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`plan_id` VARCHAR(32) NOT NULL,
|
||||
`product_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`batch_no` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`quantity` DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT 'meters',
|
||||
`rolls` INT NOT NULL DEFAULT 0,
|
||||
`price_per_meter` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
`operator_id` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`remark` TEXT,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_record_id` (`record_id`),
|
||||
KEY `idx_plan` (`plan_id`),
|
||||
KEY `idx_tenant` (`tenant_id`),
|
||||
KEY `idx_product` (`product_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='按计划分批入库';
|
||||
@ -1,174 +0,0 @@
|
||||
-- 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 = '';
|
||||
@ -1,15 +1,14 @@
|
||||
# Local development config — fill in credentials before running locally.
|
||||
Name: gateway-api
|
||||
Host: 0.0.0.0
|
||||
Port: 8888
|
||||
|
||||
Auth:
|
||||
AccessSecret: your_jwt_secret_here
|
||||
AccessSecret: muyu-wms-jwt-secret-key-2026
|
||||
AccessExpire: 7200
|
||||
DefaultTenantId: t_default_001
|
||||
|
||||
DataSource: root:your_password@tcp(127.0.0.1:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
PostgresDataSource: "postgres://muyu:your_password@127.0.0.1:5432/muyu_crm?sslmode=disable"
|
||||
DataSource: root:muyu2026@tcp(127.0.0.1:3306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
PostgresDataSource: "postgres://muyu:muyu2026@127.0.0.1:5432/muyu_crm?sslmode=disable"
|
||||
|
||||
SystemRpc:
|
||||
Etcd:
|
||||
|
||||
@ -224,8 +224,6 @@ type (
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
Spec string `json:"spec"`
|
||||
Color string `json:"color"`
|
||||
ColorNo string `json:"colorNo"`
|
||||
ProductCode string `json:"productCode"`
|
||||
SalesPrice string `json:"salesPrice"`
|
||||
Remark string `json:"remark"`
|
||||
Status int64 `json:"status"`
|
||||
@ -237,19 +235,15 @@ type (
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Spec string `json:"spec,optional"`
|
||||
Color string `json:"color,optional"`
|
||||
ColorNo string `json:"colorNo,optional"`
|
||||
ProductCode string `json:"productCode,optional"`
|
||||
SalesPrice string `json:"salesPrice,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
Pans []PanInput `json:"pans,optional"`
|
||||
InitialBatch ProductBatchInput `json:"initialBatch,optional"`
|
||||
}
|
||||
UpdateProductReq {
|
||||
ProductName string `json:"productName,optional"`
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Spec string `json:"spec,optional"`
|
||||
Color string `json:"color,optional"`
|
||||
ColorNo string `json:"colorNo,optional"`
|
||||
SalesPrice string `json:"salesPrice,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
@ -259,8 +253,6 @@ type (
|
||||
ProductName string `form:"productName,optional"`
|
||||
Spec string `form:"spec,optional"`
|
||||
Color string `form:"color,optional"`
|
||||
ColorNo string `form:"colorNo,optional"`
|
||||
ProductCode string `form:"productCode,optional"`
|
||||
Status int64 `form:"status,optional,default=-1"`
|
||||
}
|
||||
ListProductResp {
|
||||
@ -287,8 +279,6 @@ type (
|
||||
PanInfo {
|
||||
PanId string `json:"panId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchId string `json:"batchId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
Name string `json:"name"`
|
||||
Position string `json:"position"`
|
||||
SortOrder int64 `json:"sortOrder"`
|
||||
@ -300,7 +290,6 @@ type (
|
||||
Name string `json:"name"`
|
||||
Position string `json:"position,optional"`
|
||||
BoltLengths []string `json:"boltLengths,optional"`
|
||||
BatchId string `json:"batchId,optional"`
|
||||
}
|
||||
ListPanResp {
|
||||
List []PanInfo `json:"list"`
|
||||
@ -342,8 +331,6 @@ type (
|
||||
ProductId string `json:"productId"`
|
||||
ProductName string `json:"productName"`
|
||||
Color string `json:"color"`
|
||||
ColorNo string `json:"colorNo"`
|
||||
ProductCode string `json:"productCode"`
|
||||
Spec string `json:"spec"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
PanCount int64 `json:"panCount"`
|
||||
@ -351,7 +338,6 @@ type (
|
||||
TotalLengthM string `json:"totalLengthM"`
|
||||
Locations string `json:"locations"`
|
||||
SalesPrice string `json:"salesPrice"`
|
||||
BatchCount int64 `json:"batchCount"`
|
||||
}
|
||||
ListColorDetailReq {
|
||||
ProductName string `form:"productName"`
|
||||
@ -361,85 +347,6 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// ==================== Yarn & Batch Types ====================
|
||||
type (
|
||||
YarnInfo {
|
||||
YarnId string `json:"yarnId"`
|
||||
YarnName string `json:"yarnName"`
|
||||
Color string `json:"color"`
|
||||
WeightGM string `json:"weightGM"`
|
||||
SupplierId string `json:"supplierId"`
|
||||
SupplierName string `json:"supplierName"`
|
||||
DyeFactory string `json:"dyeFactory"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
Remark string `json:"remark"`
|
||||
Status int64 `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
CreateYarnReq {
|
||||
YarnName string `json:"yarnName"`
|
||||
Color string `json:"color,optional"`
|
||||
WeightGM string `json:"weightGM"`
|
||||
SupplierId string `json:"supplierId"`
|
||||
DyeFactory string `json:"dyeFactory,optional"`
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
UpdateYarnReq {
|
||||
YarnName string `json:"yarnName,optional"`
|
||||
Color string `json:"color,optional"`
|
||||
WeightGM string `json:"weightGM,optional"`
|
||||
SupplierId string `json:"supplierId,optional"`
|
||||
DyeFactory string `json:"dyeFactory,optional"`
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
Status int64 `json:"status,optional,default=1"`
|
||||
}
|
||||
ListYarnReq {
|
||||
Page int64 `form:"page,default=1"`
|
||||
PageSize int64 `form:"pageSize,default=20"`
|
||||
YarnName string `form:"yarnName,optional"`
|
||||
SupplierId string `form:"supplierId,optional"`
|
||||
Status int64 `form:"status,optional,default=-1"`
|
||||
}
|
||||
ListYarnResp {
|
||||
Total int64 `json:"total"`
|
||||
List []YarnInfo `json:"list"`
|
||||
}
|
||||
ProductBatchInput {
|
||||
BatchNo string `json:"batchNo,optional"`
|
||||
YarnRatio string `json:"yarnRatio,optional"`
|
||||
WarpWeightGM string `json:"warpWeightGM,optional"`
|
||||
WeftWeightGM string `json:"weftWeightGM,optional"`
|
||||
ProductionProcess string `json:"productionProcess,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
ProductBatchInfo {
|
||||
BatchId string `json:"batchId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
YarnRatio string `json:"yarnRatio"`
|
||||
WarpWeightGM string `json:"warpWeightGM"`
|
||||
WeftWeightGM string `json:"weftWeightGM"`
|
||||
ProductionProcess string `json:"productionProcess"`
|
||||
Remark string `json:"remark"`
|
||||
Status int64 `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
CreateProductBatchReq {
|
||||
Batch ProductBatchInput `json:"batch"`
|
||||
}
|
||||
UpdateProductBatchReq {
|
||||
Batch ProductBatchInput `json:"batch"`
|
||||
Status int64 `json:"status,optional,default=1"`
|
||||
}
|
||||
ListProductBatchResp {
|
||||
List []ProductBatchInfo `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
// ==================== Stock Statistics Types ====================
|
||||
type (
|
||||
StockSummaryResp {
|
||||
@ -818,51 +725,6 @@ service gateway-api {
|
||||
put /products/:id/pans (SavePansReq) returns (IdResp)
|
||||
}
|
||||
|
||||
// Inventory - Yarn Management
|
||||
@server (
|
||||
prefix: /api/v1/inventory
|
||||
group: inventory/yarn
|
||||
jwt: Auth
|
||||
middleware: AuthorityMiddleware
|
||||
)
|
||||
service gateway-api {
|
||||
@handler ListYarnHandler
|
||||
get /yarns (ListYarnReq) returns (ListYarnResp)
|
||||
|
||||
@handler GetYarnHandler
|
||||
get /yarns/:id returns (YarnInfo)
|
||||
|
||||
@handler CreateYarnHandler
|
||||
post /yarns (CreateYarnReq) returns (IdResp)
|
||||
|
||||
@handler UpdateYarnHandler
|
||||
put /yarns/:id (UpdateYarnReq) returns (IdResp)
|
||||
|
||||
@handler DeleteYarnHandler
|
||||
delete /yarns/:id returns (IdResp)
|
||||
}
|
||||
|
||||
// Inventory - Product Batch Management
|
||||
@server (
|
||||
prefix: /api/v1/inventory
|
||||
group: inventory/productbatch
|
||||
jwt: Auth
|
||||
middleware: AuthorityMiddleware
|
||||
)
|
||||
service gateway-api {
|
||||
@handler ListProductBatchHandler
|
||||
get /products/:id/batches returns (ListProductBatchResp)
|
||||
|
||||
@handler CreateProductBatchHandler
|
||||
post /products/:id/batches (CreateProductBatchReq) returns (IdResp)
|
||||
|
||||
@handler UpdateProductBatchHandler
|
||||
put /products/:id/batches/:batchId (UpdateProductBatchReq) returns (IdResp)
|
||||
|
||||
@handler DeleteProductBatchHandler
|
||||
delete /products/:id/batches/:batchId returns (IdResp)
|
||||
}
|
||||
|
||||
// Inventory - Pan/Bolt Management
|
||||
@server (
|
||||
prefix: /api/v1/inventory
|
||||
@ -943,3 +805,4 @@ service gateway-api {
|
||||
@handler ApproveStockAdjustHandler
|
||||
post /adjusts/:id/approve (ApproveStockAdjustReq) returns (IdResp)
|
||||
}
|
||||
|
||||
|
||||
@ -20,5 +20,4 @@ type Config struct {
|
||||
SystemRpc zrpc.RpcClientConf
|
||||
InventoryRpc zrpc.RpcClientConf
|
||||
PurchaseRpc zrpc.RpcClientConf
|
||||
ProductionRpc zrpc.RpcClientConf
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ package product
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/inventory/product"
|
||||
@ -15,14 +14,11 @@ import (
|
||||
func ExportProductHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
l := product.NewExportProductLogic(r.Context(), svcCtx)
|
||||
data, filename, err := l.ExportProduct()
|
||||
err := l.ExportProduct()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
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)
|
||||
httpx.Ok(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/inbound"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func CreateInboundHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayCreateInboundReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := inbound.NewCreateInboundLogic(r.Context(), svcCtx)
|
||||
resp, err := l.CreateInbound(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/inbound"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func ListInboundHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayListInboundReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := inbound.NewListInboundLogic(r.Context(), svcCtx)
|
||||
resp, err := l.ListInbound(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/plan"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func ConfirmPlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.ConfirmPlanReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := plan.NewConfirmPlanLogic(r.Context(), svcCtx)
|
||||
err := l.ConfirmPlan(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, types.IdResp{})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/plan"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func CreateProductionPlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.CreateProductionPlanReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := plan.NewCreateProductionPlanLogic(r.Context(), svcCtx)
|
||||
resp, err := l.CreateProductionPlan(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/production/plan"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func GetProductionPlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["planId"])
|
||||
l := plan.NewGetProductionPlanLogic(ctx, svcCtx)
|
||||
resp, err := l.GetProductionPlan()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/plan"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func ListProductionPlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.ListProductionPlanReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := plan.NewListProductionPlanLogic(r.Context(), svcCtx)
|
||||
resp, err := l.ListProductionPlan(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/process"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func CompleteStepHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayCompleteStepReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := process.NewCompleteStepLogic(r.Context(), svcCtx)
|
||||
err := l.CompleteStep(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, types.IdResp{})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/share"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func ClickShareLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayClickShareLinkReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := share.NewClickShareLinkLogic(r.Context(), svcCtx)
|
||||
err := l.ClickShareLink(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, types.IdResp{})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/share"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func ConfirmShareLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayConfirmShareLinkReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := share.NewConfirmShareLinkLogic(r.Context(), svcCtx)
|
||||
err := l.ConfirmShareLink(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, types.IdResp{})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/share"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func CreateShareLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayCreateShareLinkReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := share.NewCreateShareLinkLogic(r.Context(), svcCtx)
|
||||
resp, err := l.CreateShareLink(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/production/share"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func GetShareLinkPlanViewHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["shortCode"])
|
||||
l := share.NewGetShareLinkPlanViewLogic(ctx, svcCtx)
|
||||
resp, err := l.GetShareLinkPlanView()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"muyu-apiserver/gateway/internal/logic/production/share"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
)
|
||||
|
||||
func RejectShareLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GatewayRejectShareLinkReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := share.NewRejectShareLinkLogic(r.Context(), svcCtx)
|
||||
err := l.RejectShareLink(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, types.IdResp{})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,16 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/order"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func CancelPurchaseOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := order.NewCancelPurchaseOrderLogic(ctx, svcCtx)
|
||||
l := order.NewCancelPurchaseOrderLogic(r.Context(), svcCtx)
|
||||
err := l.CancelPurchaseOrder()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/order"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func ConfirmPurchaseOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := order.NewConfirmPurchaseOrderLogic(ctx, svcCtx)
|
||||
l := order.NewConfirmPurchaseOrderLogic(r.Context(), svcCtx)
|
||||
err := l.ConfirmPurchaseOrder()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/order"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func GetPurchaseOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := order.NewGetPurchaseOrderLogic(ctx, svcCtx)
|
||||
l := order.NewGetPurchaseOrderLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetPurchaseOrder()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/order"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
@ -19,8 +17,7 @@ func UpdatePurchaseOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := order.NewUpdatePurchaseOrderLogic(ctx, svcCtx)
|
||||
l := order.NewUpdatePurchaseOrderLogic(r.Context(), svcCtx)
|
||||
err := l.UpdatePurchaseOrder(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
package receipt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/receipt"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func ConfirmPurchaseReceiptHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := receipt.NewConfirmPurchaseReceiptLogic(ctx, svcCtx)
|
||||
l := receipt.NewConfirmPurchaseReceiptLogic(r.Context(), svcCtx)
|
||||
err := l.ConfirmPurchaseReceipt()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
package receipt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/receipt"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func GetPurchaseReceiptHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := receipt.NewGetPurchaseReceiptLogic(ctx, svcCtx)
|
||||
l := receipt.NewGetPurchaseReceiptLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetPurchaseReceipt()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
package supplier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/supplier"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func DeleteSupplierHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := supplier.NewDeleteSupplierLogic(ctx, svcCtx)
|
||||
l := supplier.NewDeleteSupplierLogic(r.Context(), svcCtx)
|
||||
err := l.DeleteSupplier()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
package supplier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/supplier"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
)
|
||||
|
||||
func GetSupplierHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := supplier.NewGetSupplierLogic(ctx, svcCtx)
|
||||
l := supplier.NewGetSupplierLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetSupplier()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
package supplier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"github.com/zeromicro/go-zero/rest/pathvar"
|
||||
"muyu-apiserver/gateway/internal/logic/purchase/supplier"
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
@ -19,8 +17,7 @@ func UpdateSupplierHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), "pathId", pathvar.Vars(r)["id"])
|
||||
l := supplier.NewUpdateSupplierLogic(ctx, svcCtx)
|
||||
l := supplier.NewUpdateSupplierLogic(r.Context(), svcCtx)
|
||||
err := l.UpdateSupplier(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
|
||||
@ -13,13 +13,7 @@ import (
|
||||
inventorylog "muyu-apiserver/gateway/internal/handler/inventory/log"
|
||||
inventorypanbolt "muyu-apiserver/gateway/internal/handler/inventory/panbolt"
|
||||
inventoryproduct "muyu-apiserver/gateway/internal/handler/inventory/product"
|
||||
inventoryproductbatch "muyu-apiserver/gateway/internal/handler/inventory/productbatch"
|
||||
inventorystock "muyu-apiserver/gateway/internal/handler/inventory/stock"
|
||||
inventoryyarn "muyu-apiserver/gateway/internal/handler/inventory/yarn"
|
||||
productioninbound "muyu-apiserver/gateway/internal/handler/production/inbound"
|
||||
productionplan "muyu-apiserver/gateway/internal/handler/production/plan"
|
||||
productionprocess "muyu-apiserver/gateway/internal/handler/production/process"
|
||||
productionshare "muyu-apiserver/gateway/internal/handler/production/share"
|
||||
purchaseorder "muyu-apiserver/gateway/internal/handler/purchase/order"
|
||||
purchasepayment "muyu-apiserver/gateway/internal/handler/purchase/payment"
|
||||
purchasereceipt "muyu-apiserver/gateway/internal/handler/purchase/receipt"
|
||||
@ -150,71 +144,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
rest.WithPrefix("/api/v1/inventory"),
|
||||
)
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/yarns",
|
||||
Handler: inventoryyarn.ListYarnHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/yarns/:id",
|
||||
Handler: inventoryyarn.GetYarnHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/yarns",
|
||||
Handler: inventoryyarn.CreateYarnHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPut,
|
||||
Path: "/yarns/:id",
|
||||
Handler: inventoryyarn.UpdateYarnHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodDelete,
|
||||
Path: "/yarns/:id",
|
||||
Handler: inventoryyarn.DeleteYarnHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/inventory"),
|
||||
)
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/products/:id/batches",
|
||||
Handler: inventoryproductbatch.ListProductBatchHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/products/:id/batches",
|
||||
Handler: inventoryproductbatch.CreateProductBatchHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPut,
|
||||
Path: "/products/:id/batches/:batchId",
|
||||
Handler: inventoryproductbatch.UpdateProductBatchHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodDelete,
|
||||
Path: "/products/:id/batches/:batchId",
|
||||
Handler: inventoryproductbatch.DeleteProductBatchHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/inventory"),
|
||||
)
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
@ -705,120 +634,4 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/inventory"),
|
||||
)
|
||||
|
||||
// ─── Production Plan (JWT + Authority) ──────────────────────────────────
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/plan",
|
||||
Handler: productionplan.CreateProductionPlanHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/plan",
|
||||
Handler: productionplan.ListProductionPlanHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/plan/:planId",
|
||||
Handler: productionplan.GetProductionPlanHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/plan/confirm",
|
||||
Handler: productionplan.ConfirmPlanHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/production"),
|
||||
)
|
||||
|
||||
// ─── Production Share (JWT + Authority) ─────────────────────────────────
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/share",
|
||||
Handler: productionshare.CreateShareLinkHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/share/confirm",
|
||||
Handler: productionshare.ConfirmShareLinkHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/share/reject",
|
||||
Handler: productionshare.RejectShareLinkHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/production"),
|
||||
)
|
||||
|
||||
// ─── Production Process (JWT + Authority) ───────────────────────────────
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/process/step",
|
||||
Handler: productionprocess.CompleteStepHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/production"),
|
||||
)
|
||||
|
||||
// ─── Production Inbound (JWT + Authority) ───────────────────────────────
|
||||
|
||||
server.AddRoutes(
|
||||
rest.WithMiddlewares(
|
||||
[]rest.Middleware{serverCtx.AuthorityMiddleware},
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/inbound",
|
||||
Handler: productioninbound.CreateInboundHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/inbound",
|
||||
Handler: productioninbound.ListInboundHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/v1/production"),
|
||||
)
|
||||
|
||||
// ─── Production Public Share (NO JWT) ───────────────────────────────────
|
||||
|
||||
server.AddRoutes(
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/share/:shortCode",
|
||||
Handler: productionshare.GetShareLinkPlanViewHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/share/click",
|
||||
Handler: productionshare.ClickShareLinkHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
rest.WithPrefix("/api/v1/public/production"),
|
||||
)
|
||||
}
|
||||
|
||||
@ -40,8 +40,6 @@ func (l *ListPanViewLogic) ListPanView(req *types.ListPanViewReq) (resp *types.L
|
||||
list = append(list, types.PanListItem{
|
||||
PanId: item.PanId,
|
||||
ProductId: item.ProductId,
|
||||
BatchId: item.BatchId,
|
||||
BatchNo: item.BatchNo,
|
||||
Name: item.Name,
|
||||
Position: item.Position,
|
||||
ProductName: item.ProductName,
|
||||
|
||||
@ -30,12 +30,9 @@ func (l *CreateProductLogic) CreateProduct(req *types.CreateProductReq) (resp *t
|
||||
ImageUrl: req.ImageUrl,
|
||||
Spec: req.Spec,
|
||||
Color: req.Color,
|
||||
ColorNo: req.ColorNo,
|
||||
ProductCode: req.ProductCode,
|
||||
SalesPrice: req.SalesPrice,
|
||||
Remark: req.Remark,
|
||||
Pans: panInputsToPb(req.Pans),
|
||||
InitialBatch: productBatchInputToPb(req.InitialBatch),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -54,22 +51,7 @@ func panInputsToPb(pans []types.PanInput) []*pb.PanInput {
|
||||
Name: p.Name,
|
||||
Position: p.Position,
|
||||
BoltLengths: p.BoltLengths,
|
||||
BatchId: p.BatchId,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func productBatchInputToPb(input types.ProductBatchInput) *pb.ProductBatchInput {
|
||||
if input == (types.ProductBatchInput{}) {
|
||||
return nil
|
||||
}
|
||||
return &pb.ProductBatchInput{
|
||||
BatchNo: input.BatchNo,
|
||||
YarnRatio: input.YarnRatio,
|
||||
WarpWeightGM: input.WarpWeightGM,
|
||||
WeftWeightGM: input.WeftWeightGM,
|
||||
ProductionProcess: input.ProductionProcess,
|
||||
Remark: input.Remark,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,13 +2,10 @@ package product
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"errors"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/rpc/inventory/pb"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
@ -26,99 +23,6 @@ func NewExportProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Exp
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ExportProductLogic) ExportProduct() ([]byte, string, error) {
|
||||
products, err := l.listAllProducts()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
f := excelize.NewFile()
|
||||
defer f.Close()
|
||||
|
||||
sheet := "产品"
|
||||
if err := f.SetSheetName("Sheet1", sheet); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
headers := []interface{}{"产品名称", "规格型号", "颜色", "色号", "产品码", "销售价", "批次号", "纱线配比", "经线克重(g/m)", "纬线克重(g/m)", "生产工艺", "备注"}
|
||||
if err := f.SetSheetRow(sheet, "A1", &headers); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
row := 2
|
||||
for _, product := range products {
|
||||
batchResp, err := l.svcCtx.InventoryRpc.ListProductBatch(l.ctx, &pb.ListProductBatchReq{ProductId: product.ProductId})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if len(batchResp.List) == 0 {
|
||||
if err := setProductExportRow(f, sheet, row, product, nil); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
row++
|
||||
continue
|
||||
}
|
||||
for _, batch := range batchResp.List {
|
||||
if err := setProductExportRow(f, sheet, row, product, batch); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
row++
|
||||
}
|
||||
}
|
||||
|
||||
if err := f.SetColWidth(sheet, "A", "L", 18); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
buf, err := f.WriteToBuffer()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
filename := fmt.Sprintf("products-%s.xlsx", time.Now().Format("20060102150405"))
|
||||
return buf.Bytes(), filename, nil
|
||||
}
|
||||
|
||||
func (l *ExportProductLogic) listAllProducts() ([]*pb.ProductInfo, error) {
|
||||
const pageSize int64 = 500
|
||||
var all []*pb.ProductInfo
|
||||
for page := int64(1); ; page++ {
|
||||
resp, err := l.svcCtx.InventoryRpc.ListProduct(l.ctx, &pb.ListProductReq{Page: page, PageSize: pageSize, Status: -1})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
all = append(all, resp.List...)
|
||||
if int64(len(all)) >= resp.Total || len(resp.List) == 0 {
|
||||
return all, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setProductExportRow(f *excelize.File, sheet string, row int, product *pb.ProductInfo, batch *pb.ProductBatchInfo) error {
|
||||
values := []interface{}{
|
||||
product.ProductName,
|
||||
product.Spec,
|
||||
product.Color,
|
||||
product.ColorNo,
|
||||
product.ProductCode,
|
||||
product.SalesPrice,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
product.Remark,
|
||||
}
|
||||
if batch != nil {
|
||||
values[6] = batch.BatchNo
|
||||
values[7] = batch.YarnRatio
|
||||
values[8] = batch.WarpWeightGM
|
||||
values[9] = batch.WeftWeightGM
|
||||
values[10] = batch.ProductionProcess
|
||||
if batch.Remark != "" {
|
||||
values[11] = batch.Remark
|
||||
}
|
||||
}
|
||||
cell, err := excelize.CoordinatesToCellName(1, row)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SetSheetRow(sheet, cell, &values)
|
||||
func (l *ExportProductLogic) ExportProduct() error {
|
||||
return errors.New("export product requires response writer, will be implemented in handler layer")
|
||||
}
|
||||
|
||||
@ -37,8 +37,6 @@ func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (res
|
||||
ProductId: it.ProductId,
|
||||
ProductName: it.ProductName,
|
||||
Color: it.Color,
|
||||
ColorNo: it.ColorNo,
|
||||
ProductCode: it.ProductCode,
|
||||
Spec: it.Spec,
|
||||
ImageUrl: it.ImageUrl,
|
||||
PanCount: it.PanCount,
|
||||
@ -46,7 +44,6 @@ func (l *GetColorDetailLogic) GetColorDetail(req *types.ListColorDetailReq) (res
|
||||
TotalLengthM: it.TotalLengthM,
|
||||
Locations: it.Locations,
|
||||
SalesPrice: it.SalesPrice,
|
||||
BatchCount: it.BatchCount,
|
||||
})
|
||||
}
|
||||
return &types.ColorDetailResp{List: list}, nil
|
||||
|
||||
@ -42,17 +42,8 @@ func (l *ImportProductLogic) ImportProduct(filePath, fileName string) (resp *typ
|
||||
ProductName: p.ProductName,
|
||||
Spec: p.Spec,
|
||||
Color: p.Color,
|
||||
ColorNo: p.ColorNo,
|
||||
ProductCode: p.ProductCode,
|
||||
SalesPrice: p.SalesPrice,
|
||||
Remark: p.Remark,
|
||||
InitialBatch: &pb.ProductBatchInput{
|
||||
BatchNo: p.BatchNo,
|
||||
YarnRatio: p.YarnRatio,
|
||||
WarpWeightGM: p.WarpWeightGM,
|
||||
WeftWeightGM: p.WeftWeightGM,
|
||||
ProductionProcess: p.ProductionProcess,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -57,8 +57,6 @@ func panInfoFromPB(p *pb.PanInfo) types.PanInfo {
|
||||
return types.PanInfo{
|
||||
PanId: p.PanId,
|
||||
ProductId: p.ProductId,
|
||||
BatchId: p.BatchId,
|
||||
BatchNo: p.BatchNo,
|
||||
Name: p.Name,
|
||||
Position: p.Position,
|
||||
SortOrder: p.SortOrder,
|
||||
@ -78,8 +76,6 @@ func productInfoFromPB(p *pb.ProductInfo) types.ProductInfo {
|
||||
ImageUrl: p.ImageUrl,
|
||||
Spec: p.Spec,
|
||||
Color: p.Color,
|
||||
ColorNo: p.ColorNo,
|
||||
ProductCode: p.ProductCode,
|
||||
SalesPrice: p.SalesPrice,
|
||||
Remark: p.Remark,
|
||||
Status: p.Status,
|
||||
|
||||
@ -31,8 +31,6 @@ func (l *ListProductLogic) ListProduct(req *types.ListProductReq) (resp *types.L
|
||||
ProductName: req.ProductName,
|
||||
Spec: req.Spec,
|
||||
Color: req.Color,
|
||||
ColorNo: req.ColorNo,
|
||||
ProductCode: req.ProductCode,
|
||||
Status: req.Status,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@ -34,7 +34,6 @@ func (l *UpdateProductLogic) UpdateProduct(req *types.UpdateProductReq) (resp *t
|
||||
ImageUrl: req.ImageUrl,
|
||||
Spec: req.Spec,
|
||||
Color: req.Color,
|
||||
ColorNo: req.ColorNo,
|
||||
SalesPrice: req.SalesPrice,
|
||||
Remark: req.Remark,
|
||||
})
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
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
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CreateInboundLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateInboundLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateInboundLogic {
|
||||
return &CreateInboundLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateInboundLogic) CreateInbound(req *types.GatewayCreateInboundReq) (*types.IdResp, error) {
|
||||
resp, err := l.svcCtx.ProductionRpc.CreateInbound(l.ctx, &productionservice.CreateInboundReq{
|
||||
PlanId: req.PlanId,
|
||||
ProductId: req.ProductId,
|
||||
BatchNo: req.BatchNo,
|
||||
Quantity: req.Quantity,
|
||||
Rolls: req.Rolls,
|
||||
PricePerMeter: req.PricePerMeter,
|
||||
OperatorId: ctxdata.GetUserId(l.ctx),
|
||||
Remark: req.Remark,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.IdResp{Id: resp.Id}, nil
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ListInboundLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewListInboundLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListInboundLogic {
|
||||
return &ListInboundLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ListInboundLogic) ListInbound(req *types.GatewayListInboundReq) (*types.ListInboundResp, error) {
|
||||
rpcResp, err := l.svcCtx.ProductionRpc.ListInbound(l.ctx, &productionservice.ListInboundReq{
|
||||
PlanId: req.PlanId,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := make([]types.InboundRecordInfo, 0, len(rpcResp.List))
|
||||
for _, ir := range rpcResp.List {
|
||||
list = append(list, types.InboundRecordInfo{
|
||||
RecordId: ir.RecordId,
|
||||
TenantId: ir.TenantId,
|
||||
PlanId: ir.PlanId,
|
||||
ProductId: ir.ProductId,
|
||||
BatchNo: ir.BatchNo,
|
||||
Quantity: ir.Quantity,
|
||||
Rolls: ir.Rolls,
|
||||
PricePerMeter: ir.PricePerMeter,
|
||||
OperatorId: ir.OperatorId,
|
||||
Remark: ir.Remark,
|
||||
CreatedAt: ir.CreatedAt,
|
||||
})
|
||||
}
|
||||
return &types.ListInboundResp{Total: rpcResp.Total, List: list}, nil
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ConfirmPlanLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewConfirmPlanLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ConfirmPlanLogic {
|
||||
return &ConfirmPlanLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ConfirmPlanLogic) ConfirmPlan(req *types.ConfirmPlanReq) error {
|
||||
_, err := l.svcCtx.ProductionRpc.ConfirmPlan(l.ctx, &productionservice.ConfirmPlanReq{
|
||||
PlanId: req.PlanId,
|
||||
Operator: ctxdata.GetUserId(l.ctx),
|
||||
})
|
||||
return err
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CreateProductionPlanLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateProductionPlanLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateProductionPlanLogic {
|
||||
return &CreateProductionPlanLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateProductionPlanLogic) CreateProductionPlan(req *types.CreateProductionPlanReq) (*types.IdResp, error) {
|
||||
yarnRatios := make([]*productionservice.YarnRatioReq, 0, len(req.YarnRatios))
|
||||
for _, yr := range req.YarnRatios {
|
||||
yarnRatios = append(yarnRatios, &productionservice.YarnRatioReq{
|
||||
YarnName: yr.YarnName,
|
||||
Ratio: yr.Ratio,
|
||||
AmountPerMeter: yr.AmountPerMeter,
|
||||
TotalAmount: yr.TotalAmount,
|
||||
})
|
||||
}
|
||||
|
||||
processSteps := make([]*productionservice.ProcessStepReq, 0, len(req.ProcessSteps))
|
||||
for _, ps := range req.ProcessSteps {
|
||||
processSteps = append(processSteps, &productionservice.ProcessStepReq{
|
||||
StepType: ps.StepType,
|
||||
StepOrder: ps.StepOrder,
|
||||
Remark: ps.Remark,
|
||||
})
|
||||
}
|
||||
|
||||
resp, err := l.svcCtx.ProductionRpc.CreateProductionPlan(l.ctx, &productionservice.CreateProductionPlanReq{
|
||||
ProductId: req.ProductId,
|
||||
ProductName: req.ProductName,
|
||||
Color: req.Color,
|
||||
FabricCode: req.FabricCode,
|
||||
ColorCode: req.ColorCode,
|
||||
TargetQuantity: req.TargetQuantity,
|
||||
YarnUsagePerMeter: req.YarnUsagePerMeter,
|
||||
ProductionPrice: req.ProductionPrice,
|
||||
SupplierId: req.SupplierId,
|
||||
Remark: req.Remark,
|
||||
StartTime: req.StartTime,
|
||||
Creator: ctxdata.GetUserId(l.ctx),
|
||||
YarnRatios: yarnRatios,
|
||||
ProcessSteps: processSteps,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.IdResp{Id: resp.Id}, nil
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetProductionPlanLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetProductionPlanLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductionPlanLogic {
|
||||
return &GetProductionPlanLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetProductionPlanLogic) GetProductionPlan() (*types.ProductionPlanInfo, error) {
|
||||
planId := ctxdata.GetPathId(l.ctx)
|
||||
resp, err := l.svcCtx.ProductionRpc.GetProductionPlan(l.ctx, &productionservice.GetProductionPlanReq{
|
||||
PlanId: planId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return productionPlanInfoFromPB(resp), nil
|
||||
}
|
||||
@ -1,122 +0,0 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ListProductionPlanLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewListProductionPlanLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListProductionPlanLogic {
|
||||
return &ListProductionPlanLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ListProductionPlanLogic) ListProductionPlan(req *types.ListProductionPlanReq) (*types.ListProductionPlanResp, error) {
|
||||
rpcResp, err := l.svcCtx.ProductionRpc.ListProductionPlan(l.ctx, &productionservice.ListProductionPlanReq{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Status: req.Status,
|
||||
ProductName: req.ProductName,
|
||||
PlanCode: req.PlanCode,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := make([]types.ProductionPlanInfo, 0, len(rpcResp.List))
|
||||
for _, p := range rpcResp.List {
|
||||
list = append(list, *productionPlanInfoFromPB(p))
|
||||
}
|
||||
return &types.ListProductionPlanResp{Total: rpcResp.Total, List: list}, nil
|
||||
}
|
||||
|
||||
func productionPlanInfoFromPB(p *productionservice.ProductionPlanInfo) *types.ProductionPlanInfo {
|
||||
if p == nil {
|
||||
return &types.ProductionPlanInfo{}
|
||||
}
|
||||
|
||||
yarnRatios := make([]types.YarnRatioInfo, 0, len(p.YarnRatios))
|
||||
for _, yr := range p.YarnRatios {
|
||||
yarnRatios = append(yarnRatios, types.YarnRatioInfo{
|
||||
RatioId: yr.RatioId,
|
||||
PlanId: yr.PlanId,
|
||||
YarnName: yr.YarnName,
|
||||
Ratio: yr.Ratio,
|
||||
AmountPerMeter: yr.AmountPerMeter,
|
||||
TotalAmount: yr.TotalAmount,
|
||||
CreatedAt: yr.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
processSteps := make([]types.ProcessStepInfo, 0, len(p.ProcessSteps))
|
||||
for _, ps := range p.ProcessSteps {
|
||||
processSteps = append(processSteps, types.ProcessStepInfo{
|
||||
StepId: ps.StepId,
|
||||
PlanId: ps.PlanId,
|
||||
StepType: ps.StepType,
|
||||
StepOrder: ps.StepOrder,
|
||||
Status: ps.Status,
|
||||
OperatorId: ps.OperatorId,
|
||||
CompletedAt: ps.CompletedAt,
|
||||
Remark: ps.Remark,
|
||||
CreatedAt: ps.CreatedAt,
|
||||
UpdatedAt: ps.UpdatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
inboundRecords := make([]types.InboundRecordInfo, 0, len(p.InboundRecords))
|
||||
for _, ir := range p.InboundRecords {
|
||||
inboundRecords = append(inboundRecords, types.InboundRecordInfo{
|
||||
RecordId: ir.RecordId,
|
||||
TenantId: ir.TenantId,
|
||||
PlanId: ir.PlanId,
|
||||
ProductId: ir.ProductId,
|
||||
BatchNo: ir.BatchNo,
|
||||
Quantity: ir.Quantity,
|
||||
Rolls: ir.Rolls,
|
||||
PricePerMeter: ir.PricePerMeter,
|
||||
OperatorId: ir.OperatorId,
|
||||
Remark: ir.Remark,
|
||||
CreatedAt: ir.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.ProductionPlanInfo{
|
||||
PlanId: p.PlanId,
|
||||
TenantId: p.TenantId,
|
||||
PlanCode: p.PlanCode,
|
||||
ProductId: p.ProductId,
|
||||
ProductName: p.ProductName,
|
||||
Color: p.Color,
|
||||
FabricCode: p.FabricCode,
|
||||
ColorCode: p.ColorCode,
|
||||
TargetQuantity: p.TargetQuantity,
|
||||
CompletedQuantity: p.CompletedQuantity,
|
||||
YarnUsagePerMeter: p.YarnUsagePerMeter,
|
||||
ProductionPrice: p.ProductionPrice,
|
||||
SupplierId: p.SupplierId,
|
||||
Status: p.Status,
|
||||
Remark: p.Remark,
|
||||
StartTime: p.StartTime,
|
||||
Creator: p.Creator,
|
||||
Operator: p.Operator,
|
||||
CreatedAt: p.CreatedAt,
|
||||
UpdatedAt: p.UpdatedAt,
|
||||
YarnRatios: yarnRatios,
|
||||
ProcessSteps: processSteps,
|
||||
InboundRecords: inboundRecords,
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CompleteStepLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCompleteStepLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CompleteStepLogic {
|
||||
return &CompleteStepLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CompleteStepLogic) CompleteStep(req *types.GatewayCompleteStepReq) error {
|
||||
_, err := l.svcCtx.ProductionRpc.CompleteStep(l.ctx, &productionservice.CompleteStepReq{
|
||||
PlanId: req.PlanId,
|
||||
StepType: req.StepType,
|
||||
OperatorId: ctxdata.GetUserId(l.ctx),
|
||||
})
|
||||
return err
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ClickShareLinkLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewClickShareLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ClickShareLinkLogic {
|
||||
return &ClickShareLinkLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ClickShareLinkLogic) ClickShareLink(req *types.GatewayClickShareLinkReq) error {
|
||||
_, err := l.svcCtx.ProductionRpc.ClickShareLink(l.ctx, &productionservice.ClickShareLinkReq{
|
||||
ShortCode: req.ShortCode,
|
||||
})
|
||||
return err
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ConfirmShareLinkLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewConfirmShareLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ConfirmShareLinkLogic {
|
||||
return &ConfirmShareLinkLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ConfirmShareLinkLogic) ConfirmShareLink(req *types.GatewayConfirmShareLinkReq) error {
|
||||
_, err := l.svcCtx.ProductionRpc.ConfirmShareLink(l.ctx, &productionservice.ConfirmShareLinkReq{
|
||||
ShortCode: req.ShortCode,
|
||||
Token: req.Token,
|
||||
FactoryTenantId: ctxdata.GetTenantId(l.ctx),
|
||||
})
|
||||
return err
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
)
|
||||
|
||||
func productionPlanInfoFromPB(p *productionservice.ProductionPlanInfo) *types.ProductionPlanInfo {
|
||||
if p == nil {
|
||||
return &types.ProductionPlanInfo{}
|
||||
}
|
||||
|
||||
yarnRatios := make([]types.YarnRatioInfo, 0, len(p.YarnRatios))
|
||||
for _, yr := range p.YarnRatios {
|
||||
yarnRatios = append(yarnRatios, types.YarnRatioInfo{
|
||||
RatioId: yr.RatioId,
|
||||
PlanId: yr.PlanId,
|
||||
YarnName: yr.YarnName,
|
||||
Ratio: yr.Ratio,
|
||||
AmountPerMeter: yr.AmountPerMeter,
|
||||
TotalAmount: yr.TotalAmount,
|
||||
CreatedAt: yr.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
processSteps := make([]types.ProcessStepInfo, 0, len(p.ProcessSteps))
|
||||
for _, ps := range p.ProcessSteps {
|
||||
processSteps = append(processSteps, types.ProcessStepInfo{
|
||||
StepId: ps.StepId,
|
||||
PlanId: ps.PlanId,
|
||||
StepType: ps.StepType,
|
||||
StepOrder: ps.StepOrder,
|
||||
Status: ps.Status,
|
||||
OperatorId: ps.OperatorId,
|
||||
CompletedAt: ps.CompletedAt,
|
||||
Remark: ps.Remark,
|
||||
CreatedAt: ps.CreatedAt,
|
||||
UpdatedAt: ps.UpdatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
inboundRecords := make([]types.InboundRecordInfo, 0, len(p.InboundRecords))
|
||||
for _, ir := range p.InboundRecords {
|
||||
inboundRecords = append(inboundRecords, types.InboundRecordInfo{
|
||||
RecordId: ir.RecordId,
|
||||
TenantId: ir.TenantId,
|
||||
PlanId: ir.PlanId,
|
||||
ProductId: ir.ProductId,
|
||||
BatchNo: ir.BatchNo,
|
||||
Quantity: ir.Quantity,
|
||||
Rolls: ir.Rolls,
|
||||
PricePerMeter: ir.PricePerMeter,
|
||||
OperatorId: ir.OperatorId,
|
||||
Remark: ir.Remark,
|
||||
CreatedAt: ir.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.ProductionPlanInfo{
|
||||
PlanId: p.PlanId,
|
||||
TenantId: p.TenantId,
|
||||
PlanCode: p.PlanCode,
|
||||
ProductId: p.ProductId,
|
||||
ProductName: p.ProductName,
|
||||
Color: p.Color,
|
||||
FabricCode: p.FabricCode,
|
||||
ColorCode: p.ColorCode,
|
||||
TargetQuantity: p.TargetQuantity,
|
||||
CompletedQuantity: p.CompletedQuantity,
|
||||
YarnUsagePerMeter: p.YarnUsagePerMeter,
|
||||
ProductionPrice: p.ProductionPrice,
|
||||
SupplierId: p.SupplierId,
|
||||
Status: p.Status,
|
||||
Remark: p.Remark,
|
||||
StartTime: p.StartTime,
|
||||
Creator: p.Creator,
|
||||
Operator: p.Operator,
|
||||
CreatedAt: p.CreatedAt,
|
||||
UpdatedAt: p.UpdatedAt,
|
||||
YarnRatios: yarnRatios,
|
||||
ProcessSteps: processSteps,
|
||||
InboundRecords: inboundRecords,
|
||||
}
|
||||
}
|
||||
|
||||
func shareLinkInfoFromPB(s *productionservice.ShareLinkInfo) *types.ShareLinkInfoResp {
|
||||
if s == nil {
|
||||
return &types.ShareLinkInfoResp{}
|
||||
}
|
||||
return &types.ShareLinkInfoResp{
|
||||
LinkId: s.LinkId,
|
||||
TenantId: s.TenantId,
|
||||
PlanId: s.PlanId,
|
||||
ShortCode: s.ShortCode,
|
||||
Token: s.Token,
|
||||
FactoryType: s.FactoryType,
|
||||
HideSensitive: s.HideSensitive,
|
||||
Status: s.Status,
|
||||
ClickCount: s.ClickCount,
|
||||
ClickedAt: s.ClickedAt,
|
||||
RespondedAt: s.RespondedAt,
|
||||
RejectReason: s.RejectReason,
|
||||
ExpiresAt: s.ExpiresAt,
|
||||
CreatedBy: s.CreatedBy,
|
||||
CreatedAt: s.CreatedAt,
|
||||
UpdatedAt: s.UpdatedAt,
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CreateShareLinkLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateShareLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateShareLinkLogic {
|
||||
return &CreateShareLinkLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateShareLinkLogic) CreateShareLink(req *types.GatewayCreateShareLinkReq) (*types.ShareLinkInfoResp, error) {
|
||||
resp, err := l.svcCtx.ProductionRpc.CreateShareLink(l.ctx, &productionservice.CreateShareLinkReq{
|
||||
PlanId: req.PlanId,
|
||||
FactoryType: req.FactoryType,
|
||||
HideSensitive: req.HideSensitive,
|
||||
ExpiresHours: req.ExpiresHours,
|
||||
CreatedBy: ctxdata.GetUserId(l.ctx),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return shareLinkInfoFromPB(resp), nil
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/pkg/ctxdata"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetShareLinkPlanViewLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetShareLinkPlanViewLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetShareLinkPlanViewLogic {
|
||||
return &GetShareLinkPlanViewLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetShareLinkPlanViewLogic) GetShareLinkPlanView() (*types.ShareLinkPlanViewResp, error) {
|
||||
shortCode := ctxdata.GetPathId(l.ctx)
|
||||
resp, err := l.svcCtx.ProductionRpc.GetShareLinkPlanView(l.ctx, &productionservice.GetShareLinkReq{
|
||||
ShortCode: shortCode,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &types.ShareLinkPlanViewResp{}
|
||||
if resp.Plan != nil {
|
||||
plan := productionPlanInfoFromPB(resp.Plan)
|
||||
result.Plan = plan
|
||||
}
|
||||
if resp.Link != nil {
|
||||
result.Link = shareLinkInfoFromPB(resp.Link)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"muyu-apiserver/gateway/internal/svc"
|
||||
"muyu-apiserver/gateway/internal/types"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type RejectShareLinkLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewRejectShareLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RejectShareLinkLogic {
|
||||
return &RejectShareLinkLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *RejectShareLinkLogic) RejectShareLink(req *types.GatewayRejectShareLinkReq) error {
|
||||
_, err := l.svcCtx.ProductionRpc.RejectShareLink(l.ctx, &productionservice.RejectShareLinkReq{
|
||||
ShortCode: req.ShortCode,
|
||||
Token: req.Token,
|
||||
RejectReason: req.RejectReason,
|
||||
})
|
||||
return err
|
||||
}
|
||||
@ -13,7 +13,6 @@ import (
|
||||
pkgcasbin "muyu-apiserver/pkg/casbin"
|
||||
"muyu-apiserver/pkg/tenantctx"
|
||||
"muyu-apiserver/rpc/inventory/inventoryservice"
|
||||
"muyu-apiserver/rpc/production/productionservice"
|
||||
"muyu-apiserver/rpc/purchase/purchaseservice"
|
||||
"muyu-apiserver/rpc/system/systemservice"
|
||||
)
|
||||
@ -26,7 +25,6 @@ type ServiceContext struct {
|
||||
SystemRpc systemservice.SystemService
|
||||
InventoryRpc inventoryservice.InventoryService
|
||||
PurchaseRpc purchaseservice.PurchaseService
|
||||
ProductionRpc productionservice.ProductionService
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
@ -64,6 +62,5 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
SystemRpc: systemservice.NewSystemService(zrpc.MustNewClient(c.SystemRpc, zrpc.WithUnaryClientInterceptor(tenantctx.UnaryClientInterceptor()))),
|
||||
InventoryRpc: inventoryservice.NewInventoryService(zrpc.MustNewClient(c.InventoryRpc, zrpc.WithUnaryClientInterceptor(tenantctx.UnaryClientInterceptor()))),
|
||||
PurchaseRpc: purchaseservice.NewPurchaseService(zrpc.MustNewClient(c.PurchaseRpc, zrpc.WithUnaryClientInterceptor(tenantctx.UnaryClientInterceptor()))),
|
||||
ProductionRpc: productionservice.NewProductionService(zrpc.MustNewClient(c.ProductionRpc, zrpc.WithUnaryClientInterceptor(tenantctx.UnaryClientInterceptor()))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,12 +38,9 @@ type CreateProductReq struct {
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Spec string `json:"spec,optional"`
|
||||
Color string `json:"color,optional"`
|
||||
ColorNo string `json:"colorNo,optional"`
|
||||
ProductCode string `json:"productCode,optional"`
|
||||
SalesPrice string `json:"salesPrice,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
Pans []PanInput `json:"pans,optional"`
|
||||
InitialBatch ProductBatchInput `json:"initialBatch,optional"`
|
||||
}
|
||||
|
||||
type CreateRoleReq struct {
|
||||
@ -117,8 +114,6 @@ type ListProductReq struct {
|
||||
ProductName string `form:"productName,optional"`
|
||||
Spec string `form:"spec,optional"`
|
||||
Color string `form:"color,optional"`
|
||||
ColorNo string `form:"colorNo,optional"`
|
||||
ProductCode string `form:"productCode,optional"`
|
||||
Status int64 `form:"status,optional,default=-1"`
|
||||
}
|
||||
|
||||
@ -235,8 +230,6 @@ type ProductInfo struct {
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
Spec string `json:"spec"`
|
||||
Color string `json:"color"`
|
||||
ColorNo string `json:"colorNo"`
|
||||
ProductCode string `json:"productCode"`
|
||||
SalesPrice string `json:"salesPrice"`
|
||||
Remark string `json:"remark"`
|
||||
Status int64 `json:"status"`
|
||||
@ -254,8 +247,6 @@ type BoltInfo struct {
|
||||
type PanInfo struct {
|
||||
PanId string `json:"panId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchId string `json:"batchId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
Name string `json:"name"`
|
||||
Position string `json:"position"`
|
||||
SortOrder int64 `json:"sortOrder"`
|
||||
@ -268,7 +259,6 @@ type PanInput struct {
|
||||
Name string `json:"name"`
|
||||
Position string `json:"position,optional"`
|
||||
BoltLengths []string `json:"boltLengths,optional"`
|
||||
BatchId string `json:"batchId,optional"`
|
||||
}
|
||||
|
||||
type ListPanResp struct {
|
||||
@ -314,8 +304,6 @@ type ColorDetailItem struct {
|
||||
ProductId string `json:"productId"`
|
||||
ProductName string `json:"productName"`
|
||||
Color string `json:"color"`
|
||||
ColorNo string `json:"colorNo"`
|
||||
ProductCode string `json:"productCode"`
|
||||
Spec string `json:"spec"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
PanCount int64 `json:"panCount"`
|
||||
@ -323,7 +311,6 @@ type ColorDetailItem struct {
|
||||
TotalLengthM string `json:"totalLengthM"`
|
||||
Locations string `json:"locations"`
|
||||
SalesPrice string `json:"salesPrice"`
|
||||
BatchCount int64 `json:"batchCount"`
|
||||
}
|
||||
|
||||
type ListColorDetailReq struct {
|
||||
@ -334,96 +321,9 @@ type ColorDetailResp struct {
|
||||
List []ColorDetailItem `json:"list"`
|
||||
}
|
||||
|
||||
type YarnInfo struct {
|
||||
YarnId string `json:"yarnId"`
|
||||
YarnName string `json:"yarnName"`
|
||||
Color string `json:"color"`
|
||||
WeightGM string `json:"weightGM"`
|
||||
SupplierId string `json:"supplierId"`
|
||||
SupplierName string `json:"supplierName"`
|
||||
DyeFactory string `json:"dyeFactory"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
Remark string `json:"remark"`
|
||||
Status int64 `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type CreateYarnReq struct {
|
||||
YarnName string `json:"yarnName"`
|
||||
Color string `json:"color,optional"`
|
||||
WeightGM string `json:"weightGM"`
|
||||
SupplierId string `json:"supplierId"`
|
||||
DyeFactory string `json:"dyeFactory,optional"`
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
|
||||
type UpdateYarnReq struct {
|
||||
YarnName string `json:"yarnName"`
|
||||
Color string `json:"color,optional"`
|
||||
WeightGM string `json:"weightGM"`
|
||||
SupplierId string `json:"supplierId"`
|
||||
DyeFactory string `json:"dyeFactory,optional"`
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
Status int64 `json:"status,optional,default=1"`
|
||||
}
|
||||
|
||||
type ListYarnReq struct {
|
||||
Page int64 `form:"page,default=1"`
|
||||
PageSize int64 `form:"pageSize,default=20"`
|
||||
YarnName string `form:"yarnName,optional"`
|
||||
SupplierId string `form:"supplierId,optional"`
|
||||
Status int64 `form:"status,optional,default=-1"`
|
||||
}
|
||||
|
||||
type ListYarnResp struct {
|
||||
Total int64 `json:"total"`
|
||||
List []YarnInfo `json:"list"`
|
||||
}
|
||||
|
||||
type ProductBatchInput struct {
|
||||
BatchNo string `json:"batchNo,optional"`
|
||||
YarnRatio string `json:"yarnRatio,optional"`
|
||||
WarpWeightGM string `json:"warpWeightGM,optional"`
|
||||
WeftWeightGM string `json:"weftWeightGM,optional"`
|
||||
ProductionProcess string `json:"productionProcess,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
|
||||
type ProductBatchInfo struct {
|
||||
BatchId string `json:"batchId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
YarnRatio string `json:"yarnRatio"`
|
||||
WarpWeightGM string `json:"warpWeightGM"`
|
||||
WeftWeightGM string `json:"weftWeightGM"`
|
||||
ProductionProcess string `json:"productionProcess"`
|
||||
Remark string `json:"remark"`
|
||||
Status int64 `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type CreateProductBatchReq struct {
|
||||
Batch ProductBatchInput `json:"batch"`
|
||||
}
|
||||
|
||||
type UpdateProductBatchReq struct {
|
||||
Batch ProductBatchInput `json:"batch"`
|
||||
Status int64 `json:"status,optional,default=1"`
|
||||
}
|
||||
|
||||
type ListProductBatchResp struct {
|
||||
List []ProductBatchInfo `json:"list"`
|
||||
}
|
||||
|
||||
type PanListItem struct {
|
||||
PanId string `json:"panId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchId string `json:"batchId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
Name string `json:"name"`
|
||||
Position string `json:"position"`
|
||||
ProductName string `json:"productName"`
|
||||
@ -584,7 +484,6 @@ type UpdateProductReq struct {
|
||||
ImageUrl string `json:"imageUrl,optional"`
|
||||
Spec string `json:"spec,optional"`
|
||||
Color string `json:"color,optional"`
|
||||
ColorNo string `json:"colorNo,optional"`
|
||||
SalesPrice string `json:"salesPrice,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
@ -960,192 +859,3 @@ type PurchaseStatsByProductItem struct {
|
||||
type PurchaseStatsByProductResp struct {
|
||||
List []PurchaseStatsByProductItem `json:"list"`
|
||||
}
|
||||
|
||||
// ─── Production Plan ────────────────────────────────────────────────────────
|
||||
|
||||
type GatewayYarnRatioReq struct {
|
||||
YarnName string `json:"yarnName"`
|
||||
Ratio string `json:"ratio"`
|
||||
AmountPerMeter string `json:"amountPerMeter,optional"`
|
||||
TotalAmount string `json:"totalAmount,optional"`
|
||||
}
|
||||
|
||||
type GatewayProcessStepReq struct {
|
||||
StepType string `json:"stepType"`
|
||||
StepOrder int64 `json:"stepOrder"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
|
||||
type CreateProductionPlanReq struct {
|
||||
ProductId string `json:"productId"`
|
||||
ProductName string `json:"productName"`
|
||||
Color string `json:"color,optional"`
|
||||
FabricCode string `json:"fabricCode,optional"`
|
||||
ColorCode string `json:"colorCode,optional"`
|
||||
TargetQuantity string `json:"targetQuantity"`
|
||||
YarnUsagePerMeter string `json:"yarnUsagePerMeter,optional"`
|
||||
ProductionPrice string `json:"productionPrice,optional"`
|
||||
SupplierId string `json:"supplierId,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
StartTime string `json:"startTime,optional"`
|
||||
YarnRatios []GatewayYarnRatioReq `json:"yarnRatios,optional"`
|
||||
ProcessSteps []GatewayProcessStepReq `json:"processSteps,optional"`
|
||||
}
|
||||
|
||||
type ListProductionPlanReq struct {
|
||||
Page int64 `form:"page,default=1"`
|
||||
PageSize int64 `form:"pageSize,default=20"`
|
||||
Status int64 `form:"status,optional,default=-1"`
|
||||
ProductName string `form:"productName,optional"`
|
||||
PlanCode string `form:"planCode,optional"`
|
||||
}
|
||||
|
||||
type YarnRatioInfo struct {
|
||||
RatioId string `json:"ratioId"`
|
||||
PlanId string `json:"planId"`
|
||||
YarnName string `json:"yarnName"`
|
||||
Ratio string `json:"ratio"`
|
||||
AmountPerMeter string `json:"amountPerMeter"`
|
||||
TotalAmount string `json:"totalAmount"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
}
|
||||
|
||||
type ProcessStepInfo struct {
|
||||
StepId string `json:"stepId"`
|
||||
PlanId string `json:"planId"`
|
||||
StepType string `json:"stepType"`
|
||||
StepOrder int64 `json:"stepOrder"`
|
||||
Status int64 `json:"status"`
|
||||
OperatorId string `json:"operatorId"`
|
||||
CompletedAt string `json:"completedAt"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type InboundRecordInfo struct {
|
||||
RecordId string `json:"recordId"`
|
||||
TenantId string `json:"tenantId"`
|
||||
PlanId string `json:"planId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
Quantity string `json:"quantity"`
|
||||
Rolls int64 `json:"rolls"`
|
||||
PricePerMeter string `json:"pricePerMeter"`
|
||||
OperatorId string `json:"operatorId"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
}
|
||||
|
||||
type ProductionPlanInfo struct {
|
||||
PlanId string `json:"planId"`
|
||||
TenantId string `json:"tenantId"`
|
||||
PlanCode string `json:"planCode"`
|
||||
ProductId string `json:"productId"`
|
||||
ProductName string `json:"productName"`
|
||||
Color string `json:"color"`
|
||||
FabricCode string `json:"fabricCode"`
|
||||
ColorCode string `json:"colorCode"`
|
||||
TargetQuantity string `json:"targetQuantity"`
|
||||
CompletedQuantity string `json:"completedQuantity"`
|
||||
YarnUsagePerMeter string `json:"yarnUsagePerMeter"`
|
||||
ProductionPrice string `json:"productionPrice"`
|
||||
SupplierId string `json:"supplierId"`
|
||||
Status int64 `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
StartTime string `json:"startTime"`
|
||||
Creator string `json:"creator"`
|
||||
Operator string `json:"operator"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
YarnRatios []YarnRatioInfo `json:"yarnRatios"`
|
||||
ProcessSteps []ProcessStepInfo `json:"processSteps"`
|
||||
InboundRecords []InboundRecordInfo `json:"inboundRecords"`
|
||||
}
|
||||
|
||||
type ListProductionPlanResp struct {
|
||||
Total int64 `json:"total"`
|
||||
List []ProductionPlanInfo `json:"list"`
|
||||
}
|
||||
|
||||
type ConfirmPlanReq struct {
|
||||
PlanId string `json:"planId"`
|
||||
}
|
||||
|
||||
// ─── Share Link ─────────────────────────────────────────────────────────────
|
||||
|
||||
type GatewayCreateShareLinkReq struct {
|
||||
PlanId string `json:"planId"`
|
||||
FactoryType string `json:"factoryType,optional"`
|
||||
HideSensitive int64 `json:"hideSensitive,optional"`
|
||||
ExpiresHours int64 `json:"expiresHours,optional"`
|
||||
}
|
||||
|
||||
type ShareLinkInfoResp struct {
|
||||
LinkId string `json:"linkId"`
|
||||
TenantId string `json:"tenantId"`
|
||||
PlanId string `json:"planId"`
|
||||
ShortCode string `json:"shortCode"`
|
||||
Token string `json:"token"`
|
||||
FactoryType string `json:"factoryType"`
|
||||
HideSensitive int64 `json:"hideSensitive"`
|
||||
Status int64 `json:"status"`
|
||||
ClickCount int64 `json:"clickCount"`
|
||||
ClickedAt string `json:"clickedAt"`
|
||||
RespondedAt string `json:"respondedAt"`
|
||||
RejectReason string `json:"rejectReason"`
|
||||
ExpiresAt string `json:"expiresAt"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type ShareLinkPlanViewResp struct {
|
||||
Plan *ProductionPlanInfo `json:"plan"`
|
||||
Link *ShareLinkInfoResp `json:"link"`
|
||||
}
|
||||
|
||||
type GatewayConfirmShareLinkReq struct {
|
||||
ShortCode string `json:"shortCode"`
|
||||
Token string `json:"token,optional"`
|
||||
}
|
||||
|
||||
type GatewayRejectShareLinkReq struct {
|
||||
ShortCode string `json:"shortCode"`
|
||||
Token string `json:"token,optional"`
|
||||
RejectReason string `json:"rejectReason,optional"`
|
||||
}
|
||||
|
||||
type GatewayClickShareLinkReq struct {
|
||||
ShortCode string `json:"shortCode"`
|
||||
}
|
||||
|
||||
// ─── Process Step ───────────────────────────────────────────────────────────
|
||||
|
||||
type GatewayCompleteStepReq struct {
|
||||
PlanId string `json:"planId"`
|
||||
StepType string `json:"stepType"`
|
||||
}
|
||||
|
||||
// ─── Inbound ────────────────────────────────────────────────────────────────
|
||||
|
||||
type GatewayCreateInboundReq struct {
|
||||
PlanId string `json:"planId"`
|
||||
ProductId string `json:"productId"`
|
||||
BatchNo string `json:"batchNo,optional"`
|
||||
Quantity string `json:"quantity"`
|
||||
Rolls int64 `json:"rolls,optional"`
|
||||
PricePerMeter string `json:"pricePerMeter,optional"`
|
||||
Remark string `json:"remark,optional"`
|
||||
}
|
||||
|
||||
type GatewayListInboundReq struct {
|
||||
PlanId string `form:"planId,optional"`
|
||||
Page int64 `form:"page,default=1"`
|
||||
PageSize int64 `form:"pageSize,default=20"`
|
||||
}
|
||||
|
||||
type ListInboundResp struct {
|
||||
Total int64 `json:"total"`
|
||||
List []InboundRecordInfo `json:"list"`
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@ -66,7 +66,6 @@ require (
|
||||
github.com/microsoft/go-mssqldb v1.9.5 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mozillazg/go-pinyin v0.21.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@ -189,8 +189,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/mozillazg/go-pinyin v0.21.0 h1:Wo8/NT45z7P3er/9YSLHA3/kjZzbLz5hR7i+jGeIGao=
|
||||
github.com/mozillazg/go-pinyin v0.21.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
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)
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
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) {
|
||||
var list []*InvProductBolt
|
||||
query := fmt.Sprintf(
|
||||
"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` "+
|
||||
"SELECT b.`id`, b.`bolt_id`, b.`pan_id`, b.`length_m`, b.`sort_order`, b.`tenant_id`, b.`created_at`, b.`updated_at` "+
|
||||
"FROM %s b INNER JOIN `inv_product_pan` p ON b.`pan_id` = p.`pan_id` "+
|
||||
"WHERE p.`product_id` = ? ORDER BY p.`sort_order`, b.`sort_order`", m.table)
|
||||
err := m.conn.QueryRowsCtx(ctx, &list, query, productId)
|
||||
|
||||
@ -33,14 +33,11 @@ type ColorDetail struct {
|
||||
ProductId string `db:"product_id"`
|
||||
ProductName string `db:"product_name"`
|
||||
Color string `db:"color"`
|
||||
ColorNo string `db:"color_no"`
|
||||
ProductCode string `db:"product_code"`
|
||||
Spec string `db:"spec"`
|
||||
ImageUrl string `db:"image_url"`
|
||||
SalesPrice float64 `db:"sales_price"`
|
||||
PanCount int64 `db:"pan_count"`
|
||||
BoltCount int64 `db:"bolt_count"`
|
||||
BatchCount int64 `db:"batch_count"`
|
||||
TotalLengthM float64 `db:"total_length_m"`
|
||||
Locations string `db:"locations"`
|
||||
}
|
||||
@ -48,13 +45,11 @@ type ColorDetail struct {
|
||||
type (
|
||||
InvProductModel interface {
|
||||
invProductModel
|
||||
FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color, colorNo, productCode string, status int64) ([]*InvProduct, int64, error)
|
||||
FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color string, status int64) ([]*InvProduct, int64, error)
|
||||
FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error)
|
||||
FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, error)
|
||||
FindOneByTenantProductCode(ctx context.Context, tenantId, productCode string) (*InvProduct, error)
|
||||
FindGroupByColor(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
||||
FindGroupByLocation(ctx context.Context, tenantId string) ([]StockGroupResult, error)
|
||||
NextColorNo(ctx context.Context, tenantId, productName string) (string, error)
|
||||
BulkInsert(ctx context.Context, products []*InvProduct) (int64, error)
|
||||
}
|
||||
|
||||
@ -84,16 +79,15 @@ func (m *customInvProductModel) BulkInsert(ctx context.Context, products []*InvP
|
||||
}
|
||||
batch := products[i:end]
|
||||
|
||||
placeholder := "(" + strings.Repeat("?,", 11) + "?)"
|
||||
placeholder := "(" + strings.Repeat("?,", 9) + "?)"
|
||||
placeholders := make([]string, len(batch))
|
||||
args := make([]interface{}, 0, len(batch)*12)
|
||||
args := make([]interface{}, 0, len(batch)*10)
|
||||
|
||||
for j, p := range batch {
|
||||
placeholders[j] = placeholder
|
||||
args = append(args,
|
||||
p.ProductId, p.ProductName, p.ImageUrl, p.Spec, p.Color,
|
||||
p.ColorNo, p.ProductCode, p.SalesPrice, p.Remark, p.Status,
|
||||
p.TenantId, p.DeletedAt,
|
||||
p.SalesPrice, p.Remark, p.Status, p.TenantId, p.DeletedAt,
|
||||
)
|
||||
}
|
||||
|
||||
@ -111,7 +105,7 @@ func (m *customInvProductModel) BulkInsert(ctx context.Context, products []*InvP
|
||||
return totalAffected, nil
|
||||
}
|
||||
|
||||
func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color, colorNo, productCode string, status int64) ([]*InvProduct, int64, error) {
|
||||
func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, page, pageSize int64, productName, spec, color string, status int64) ([]*InvProduct, int64, error) {
|
||||
where := "WHERE deleted_at IS NULL AND tenant_id = ?"
|
||||
args := []interface{}{tenantId}
|
||||
|
||||
@ -127,14 +121,6 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p
|
||||
where += " AND color = ?"
|
||||
args = append(args, color)
|
||||
}
|
||||
if colorNo != "" {
|
||||
where += " AND color_no LIKE ?"
|
||||
args = append(args, "%"+colorNo+"%")
|
||||
}
|
||||
if productCode != "" {
|
||||
where += " AND product_code LIKE ?"
|
||||
args = append(args, "%"+productCode+"%")
|
||||
}
|
||||
if status >= 0 {
|
||||
where += " AND status = ?"
|
||||
args = append(args, status)
|
||||
@ -158,27 +144,6 @@ func (m *customInvProductModel) FindList(ctx context.Context, tenantId string, p
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
func (m *customInvProductModel) FindOneByTenantProductCode(ctx context.Context, tenantId, productCode string) (*InvProduct, error) {
|
||||
var resp InvProduct
|
||||
query := fmt.Sprintf("SELECT %s FROM %s WHERE tenant_id = ? AND product_code = ? AND deleted_at IS NULL LIMIT 1", invProductRows, m.table)
|
||||
err := m.QueryRowNoCacheCtx(ctx, &resp, query, tenantId, productCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (m *customInvProductModel) NextColorNo(ctx context.Context, tenantId, productName string) (string, error) {
|
||||
var next int64
|
||||
query := fmt.Sprintf(`SELECT COALESCE(MAX(CAST(color_no AS UNSIGNED)), 0) + 1
|
||||
FROM %s
|
||||
WHERE tenant_id = ? AND product_name = ? AND deleted_at IS NULL AND color_no REGEXP '^[0-9]+$'`, m.table)
|
||||
if err := m.QueryRowNoCacheCtx(ctx, &next, query, tenantId, productName); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%02d", next), nil
|
||||
}
|
||||
|
||||
func (m *customInvProductModel) FindProductSummary(ctx context.Context, tenantId string) ([]*ProductSummary, error) {
|
||||
var list []*ProductSummary
|
||||
query := `SELECT p.product_name, p.spec,
|
||||
@ -186,8 +151,8 @@ func (m *customInvProductModel) FindProductSummary(ctx context.Context, tenantId
|
||||
COUNT(DISTINCT pan.pan_id) AS total_pan_count,
|
||||
COUNT(bolt.bolt_id) AS total_bolt_count,
|
||||
COALESCE(SUM(bolt.length_m), 0) AS total_length_m,
|
||||
COALESCE(GROUP_CONCAT(DISTINCT p.color), '') AS colors,
|
||||
COALESCE(GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position), '') AS locations
|
||||
GROUP_CONCAT(DISTINCT p.color) AS colors,
|
||||
GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position) AS locations
|
||||
FROM ` + m.table + ` p
|
||||
LEFT JOIN ` + "`inv_product_pan`" + ` pan ON pan.product_id = p.product_id
|
||||
LEFT JOIN ` + "`inv_product_bolt`" + ` bolt ON bolt.pan_id = pan.pan_id
|
||||
@ -235,18 +200,11 @@ func (m *customInvProductModel) FindGroupByLocation(ctx context.Context, tenantI
|
||||
|
||||
func (m *customInvProductModel) FindColorDetail(ctx context.Context, tenantId, productName string) ([]*ColorDetail, error) {
|
||||
var list []*ColorDetail
|
||||
query := `SELECT p.product_id, p.product_name, p.color, p.color_no, p.product_code, p.spec, p.image_url, p.sales_price,
|
||||
query := `SELECT p.product_id, p.product_name, p.color, p.spec, p.image_url, p.sales_price,
|
||||
COUNT(DISTINCT pan.pan_id) AS pan_count,
|
||||
COUNT(bolt.bolt_id) AS bolt_count,
|
||||
(
|
||||
SELECT COUNT(DISTINCT batch.batch_id)
|
||||
FROM ` + "`inv_product_batch`" + ` batch
|
||||
WHERE batch.product_id = p.product_id
|
||||
AND batch.tenant_id = p.tenant_id
|
||||
AND batch.deleted_at IS NULL
|
||||
) AS batch_count,
|
||||
COALESCE(SUM(bolt.length_m), 0) AS total_length_m,
|
||||
COALESCE(GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position), '') AS locations
|
||||
GROUP_CONCAT(DISTINCT pan.position ORDER BY pan.position) AS locations
|
||||
FROM ` + m.table + ` p
|
||||
LEFT JOIN ` + "`inv_product_pan`" + ` pan ON pan.product_id = p.product_id
|
||||
LEFT JOIN ` + "`inv_product_bolt`" + ` bolt ON bolt.pan_id = pan.pan_id
|
||||
|
||||
@ -27,7 +27,6 @@ var (
|
||||
cacheInvProductIdPrefix = "cache:invProduct:id:"
|
||||
cacheInvProductProductIdPrefix = "cache:invProduct:productId:"
|
||||
cacheInvProductProductNamePrefix = "cache:invProduct:productName:"
|
||||
cacheInvProductProductCodePrefix = "cache:invProduct:productCode:"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -36,7 +35,6 @@ type (
|
||||
FindOne(ctx context.Context, id int64) (*InvProduct, error)
|
||||
FindOneByProductId(ctx context.Context, productId string) (*InvProduct, error)
|
||||
FindOneByProductName(ctx context.Context, productName string) (*InvProduct, error)
|
||||
FindOneByProductCode(ctx context.Context, productCode string) (*InvProduct, error)
|
||||
Update(ctx context.Context, data *InvProduct) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
}
|
||||
@ -53,9 +51,8 @@ type (
|
||||
ImageUrl string `db:"image_url"`
|
||||
Spec string `db:"spec"`
|
||||
Color string `db:"color"`
|
||||
ColorNo string `db:"color_no"`
|
||||
ProductCode string `db:"product_code"`
|
||||
SalesPrice float64 `db:"sales_price"`
|
||||
CostPrice float64 `db:"cost_price"`
|
||||
Remark sql.NullString `db:"remark"`
|
||||
Status int64 `db:"status"`
|
||||
TenantId string `db:"tenant_id"`
|
||||
@ -81,11 +78,10 @@ func (m *defaultInvProductModel) Delete(ctx context.Context, id int64) error {
|
||||
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, id)
|
||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||
invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode)
|
||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||
return conn.ExecCtx(ctx, query, id)
|
||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey)
|
||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -126,26 +122,6 @@ func (m *defaultInvProductModel) FindOneByProductId(ctx context.Context, product
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultInvProductModel) FindOneByProductCode(ctx context.Context, productCode string) (*InvProduct, error) {
|
||||
invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, productCode)
|
||||
var resp InvProduct
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, invProductProductCodeKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) {
|
||||
query := fmt.Sprintf("select %s from %s where `product_code` = ? limit 1", invProductRows, m.table)
|
||||
if err := conn.QueryRowCtx(ctx, &resp, query, productCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Id, nil
|
||||
}, m.queryPrimary)
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultInvProductModel) FindOneByProductName(ctx context.Context, productName string) (*InvProduct, error) {
|
||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, productName)
|
||||
var resp InvProduct
|
||||
@ -170,11 +146,10 @@ func (m *defaultInvProductModel) Insert(ctx context.Context, data *InvProduct) (
|
||||
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id)
|
||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||
invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode)
|
||||
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, invProductRowsExpectAutoSet)
|
||||
return conn.ExecCtx(ctx, query, data.ProductId, data.ProductName, data.ImageUrl, data.Spec, data.Color, data.ColorNo, data.ProductCode, data.SalesPrice, data.Remark, data.Status, data.TenantId, data.DeletedAt)
|
||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey)
|
||||
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.CostPrice, data.Remark, data.Status, data.TenantId, data.DeletedAt)
|
||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
@ -187,11 +162,10 @@ func (m *defaultInvProductModel) Update(ctx context.Context, newData *InvProduct
|
||||
invProductIdKey := fmt.Sprintf("%s%v", cacheInvProductIdPrefix, data.Id)
|
||||
invProductProductIdKey := fmt.Sprintf("%s%v", cacheInvProductProductIdPrefix, data.ProductId)
|
||||
invProductProductNameKey := fmt.Sprintf("%s%v", cacheInvProductProductNamePrefix, data.ProductName)
|
||||
invProductProductCodeKey := fmt.Sprintf("%s%v", cacheInvProductProductCodePrefix, data.ProductCode)
|
||||
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, invProductRowsWithPlaceHolder)
|
||||
return conn.ExecCtx(ctx, query, newData.ProductId, newData.ProductName, newData.ImageUrl, newData.Spec, newData.Color, newData.ColorNo, newData.ProductCode, newData.SalesPrice, newData.Remark, newData.Status, newData.TenantId, newData.DeletedAt, newData.Id)
|
||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey, invProductProductCodeKey)
|
||||
return conn.ExecCtx(ctx, query, newData.ProductId, newData.ProductName, newData.ImageUrl, newData.Spec, newData.Color, newData.SalesPrice, newData.CostPrice, newData.Remark, newData.Status, newData.TenantId, newData.DeletedAt, newData.Id)
|
||||
}, invProductIdKey, invProductProductIdKey, invProductProductNameKey)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@ -1,451 +0,0 @@
|
||||
package model
|
||||
|
||||
// Integration tests for InvProduct model against the real dev database.
|
||||
// These tests guard against model/schema drift (e.g. missing or extra columns).
|
||||
//
|
||||
// Run with the dev DB reachable:
|
||||
// go test ./model/ -run TestInvProduct -v
|
||||
// Skip in CI where DB is unavailable:
|
||||
// go test ./model/ -short
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
const testDSN = "root:muyu2026@tcp(127.0.0.1:13306)/muyu_wms?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai"
|
||||
|
||||
func newTestProductModel(t *testing.T) InvProductModel {
|
||||
t.Helper()
|
||||
conn := sqlx.NewMysql(testDSN)
|
||||
cacheConf := cache.CacheConf{{RedisConf: redis.RedisConf{Host: "127.0.0.1:6379", Type: "node"}, Weight: 100}}
|
||||
return NewInvProductModel(conn, cacheConf)
|
||||
}
|
||||
|
||||
func uniqueID(prefix string) string {
|
||||
return fmt.Sprintf("%s_%d", prefix, time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// TestInvProductInsert verifies that Insert succeeds against the live DB schema.
|
||||
// This catches model/schema drift like the cost_price column removal.
|
||||
func TestInvProductInsert(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
m := newTestProductModel(t)
|
||||
ctx := context.Background()
|
||||
|
||||
p := &InvProduct{
|
||||
ProductId: uniqueID("pid"),
|
||||
ProductName: uniqueID("test_product"),
|
||||
ImageUrl: "",
|
||||
Spec: "100cm",
|
||||
Color: "red",
|
||||
ColorNo: "01",
|
||||
ProductCode: uniqueID("TPC"),
|
||||
SalesPrice: 99.9,
|
||||
Remark: sql.NullString{String: "test remark", Valid: true},
|
||||
Status: 1,
|
||||
TenantId: "t_default_001",
|
||||
}
|
||||
|
||||
result, err := m.Insert(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert failed: %v", err)
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
if id == 0 {
|
||||
t.Fatal("expected non-zero LastInsertId")
|
||||
}
|
||||
t.Logf("inserted product id=%d", id)
|
||||
|
||||
// cleanup
|
||||
t.Cleanup(func() { _ = m.Delete(ctx, id) })
|
||||
}
|
||||
|
||||
// TestInvProductFindOne verifies Insert + FindOne round-trip.
|
||||
func TestInvProductFindOne(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
m := newTestProductModel(t)
|
||||
ctx := context.Background()
|
||||
|
||||
p := &InvProduct{
|
||||
ProductId: uniqueID("pid"),
|
||||
ProductName: uniqueID("test_product"),
|
||||
Spec: "200cm",
|
||||
Color: "blue",
|
||||
ColorNo: "01",
|
||||
ProductCode: uniqueID("TPC"),
|
||||
SalesPrice: 49.5,
|
||||
Status: 1,
|
||||
TenantId: "t_default_001",
|
||||
}
|
||||
|
||||
res, err := m.Insert(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
id, _ := res.LastInsertId()
|
||||
t.Cleanup(func() { _ = m.Delete(ctx, id) })
|
||||
|
||||
got, err := m.FindOne(ctx, id)
|
||||
if err != nil {
|
||||
t.Fatalf("FindOne: %v", err)
|
||||
}
|
||||
if got.ProductName != p.ProductName {
|
||||
t.Errorf("ProductName: got %q, want %q", got.ProductName, p.ProductName)
|
||||
}
|
||||
if got.SalesPrice != p.SalesPrice {
|
||||
t.Errorf("SalesPrice: got %v, want %v", got.SalesPrice, p.SalesPrice)
|
||||
}
|
||||
}
|
||||
|
||||
// TestInvProductUpdate verifies Update writes back correctly.
|
||||
func TestInvProductUpdate(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
m := newTestProductModel(t)
|
||||
ctx := context.Background()
|
||||
|
||||
p := &InvProduct{
|
||||
ProductId: uniqueID("pid"),
|
||||
ProductName: uniqueID("test_product"),
|
||||
Spec: "50cm",
|
||||
Color: "green",
|
||||
ColorNo: "01",
|
||||
ProductCode: uniqueID("TPC"),
|
||||
SalesPrice: 10.0,
|
||||
Status: 1,
|
||||
TenantId: "t_default_001",
|
||||
}
|
||||
res, err := m.Insert(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
id, _ := res.LastInsertId()
|
||||
t.Cleanup(func() { _ = m.Delete(ctx, id) })
|
||||
|
||||
got, err := m.FindOne(ctx, id)
|
||||
if err != nil {
|
||||
t.Fatalf("FindOne: %v", err)
|
||||
}
|
||||
got.SalesPrice = 25.0
|
||||
got.Remark = sql.NullString{String: "updated", Valid: true}
|
||||
|
||||
if err := m.Update(ctx, got); err != nil {
|
||||
t.Fatalf("Update: %v", err)
|
||||
}
|
||||
|
||||
updated, err := m.FindOne(ctx, id)
|
||||
if err != nil {
|
||||
t.Fatalf("FindOne after Update: %v", err)
|
||||
}
|
||||
if updated.SalesPrice != 25.0 {
|
||||
t.Errorf("SalesPrice after update: got %v, want 25.0", updated.SalesPrice)
|
||||
}
|
||||
if updated.Remark.String != "updated" {
|
||||
t.Errorf("Remark after update: got %q, want \"updated\"", updated.Remark.String)
|
||||
}
|
||||
}
|
||||
|
||||
// TestInvProductBulkInsert verifies BulkInsert (used by the import flow).
|
||||
func TestInvProductBulkInsert(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
m := newTestProductModel(t)
|
||||
ctx := context.Background()
|
||||
|
||||
ids := make([]int64, 0, 3)
|
||||
products := make([]*InvProduct, 3)
|
||||
for i := range products {
|
||||
products[i] = &InvProduct{
|
||||
ProductId: uniqueID(fmt.Sprintf("bulk_pid_%d", i)),
|
||||
ProductName: uniqueID(fmt.Sprintf("bulk_product_%d", i)),
|
||||
Spec: "10cm",
|
||||
Color: "white",
|
||||
ColorNo: fmt.Sprintf("%02d", i+1),
|
||||
ProductCode: uniqueID(fmt.Sprintf("BTPC%d", i)),
|
||||
SalesPrice: float64(i+1) * 5.0,
|
||||
Status: 1,
|
||||
TenantId: "t_default_001",
|
||||
}
|
||||
}
|
||||
|
||||
affected, err := m.BulkInsert(ctx, products)
|
||||
if err != nil {
|
||||
t.Fatalf("BulkInsert: %v", err)
|
||||
}
|
||||
if affected != 3 {
|
||||
t.Errorf("BulkInsert: affected=%d, want 3", affected)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
for _, p := range products {
|
||||
row, err := m.FindOneByProductId(ctx, p.ProductId)
|
||||
if err == nil {
|
||||
_ = m.Delete(ctx, row.Id)
|
||||
}
|
||||
}
|
||||
_ = ids
|
||||
})
|
||||
}
|
||||
|
||||
// TestInvProductSchemaColumns queries information_schema to assert the DB columns
|
||||
// match what the InvProduct struct declares. Fails immediately on any mismatch.
|
||||
func TestInvProductSchemaColumns(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
db, err := sql.Open("mysql", testDSN)
|
||||
if err != nil {
|
||||
t.Fatalf("open db: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
rows, err := db.QueryContext(context.Background(),
|
||||
"SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='inv_product' ORDER BY ORDINAL_POSITION")
|
||||
if err != nil {
|
||||
t.Fatalf("query schema: %v", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
dbCols := map[string]bool{}
|
||||
for rows.Next() {
|
||||
var col string
|
||||
if err := rows.Scan(&col); err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
dbCols[col] = true
|
||||
}
|
||||
|
||||
// Columns that the InvProduct struct declares (via db tags).
|
||||
structCols := []string{
|
||||
"id", "product_id", "product_name", "image_url", "spec", "color",
|
||||
"color_no", "product_code", "sales_price", "remark", "status", "tenant_id",
|
||||
"created_at", "updated_at", "deleted_at",
|
||||
}
|
||||
|
||||
for _, col := range structCols {
|
||||
if !dbCols[col] {
|
||||
t.Errorf("struct declares column %q but it does NOT exist in inv_product", col)
|
||||
}
|
||||
}
|
||||
|
||||
// Also check for DB columns not in the struct (forward-drift guard).
|
||||
structSet := map[string]bool{}
|
||||
for _, c := range structCols {
|
||||
structSet[c] = true
|
||||
}
|
||||
for col := range dbCols {
|
||||
if !structSet[col] {
|
||||
t.Logf("WARNING: DB column %q exists but is not in the InvProduct struct", col)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFindProductSummaryNoPans guards against the GROUP_CONCAT NULL scan bug:
|
||||
// when a product has no pans, the LEFT JOIN produces NULL for pan.position and
|
||||
// GROUP_CONCAT over all-NULL values returns NULL, which cannot be scanned into a
|
||||
// Go string. The fix wraps both GROUP_CONCAT calls with COALESCE(..., '').
|
||||
func TestFindProductSummaryNoPans(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
m := newTestProductModel(t)
|
||||
ctx := context.Background()
|
||||
|
||||
p := &InvProduct{
|
||||
ProductId: uniqueID("pid_nopan"),
|
||||
ProductName: uniqueID("nopan_product"),
|
||||
Spec: "50cm",
|
||||
Color: "red",
|
||||
ColorNo: "01",
|
||||
ProductCode: uniqueID("TPC"),
|
||||
SalesPrice: 99.0,
|
||||
Status: 1,
|
||||
TenantId: "t_default_001",
|
||||
}
|
||||
res, err := m.Insert(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
id, _ := res.LastInsertId()
|
||||
t.Cleanup(func() { _ = m.Delete(ctx, id) })
|
||||
|
||||
list, err := m.FindProductSummary(ctx, "t_default_001")
|
||||
if err != nil {
|
||||
t.Fatalf("FindProductSummary returned error for product with no pans: %v", err)
|
||||
}
|
||||
|
||||
var found *ProductSummary
|
||||
for _, s := range list {
|
||||
if s.ProductName == p.ProductName {
|
||||
found = s
|
||||
break
|
||||
}
|
||||
}
|
||||
if found == nil {
|
||||
t.Fatalf("product %q not found in summary (len=%d)", p.ProductName, len(list))
|
||||
}
|
||||
if found.ColorCount != 1 {
|
||||
t.Errorf("ColorCount: got %d, want 1", found.ColorCount)
|
||||
}
|
||||
if found.TotalPanCount != 0 {
|
||||
t.Errorf("TotalPanCount: got %d, want 0", found.TotalPanCount)
|
||||
}
|
||||
if found.Locations != "" {
|
||||
t.Errorf("Locations: got %q, want empty string", found.Locations)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFindColorDetailNoPans is the same NULL guard for the color-detail query.
|
||||
func TestFindColorDetailNoPans(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
|
||||
m := newTestProductModel(t)
|
||||
ctx := context.Background()
|
||||
|
||||
p := &InvProduct{
|
||||
ProductId: uniqueID("pid_color"),
|
||||
ProductName: uniqueID("color_nopan_product"),
|
||||
Spec: "80cm",
|
||||
Color: "blue",
|
||||
ColorNo: "01",
|
||||
ProductCode: uniqueID("TPC"),
|
||||
SalesPrice: 50.0,
|
||||
Status: 1,
|
||||
TenantId: "t_default_001",
|
||||
}
|
||||
res, err := m.Insert(ctx, p)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
id, _ := res.LastInsertId()
|
||||
t.Cleanup(func() { _ = m.Delete(ctx, id) })
|
||||
|
||||
list, err := m.FindColorDetail(ctx, "t_default_001", p.ProductName)
|
||||
if err != nil {
|
||||
t.Fatalf("FindColorDetail returned error for product with no pans: %v", err)
|
||||
}
|
||||
if len(list) != 1 {
|
||||
t.Fatalf("expected 1 color detail row, got %d", len(list))
|
||||
}
|
||||
if list[0].Color != "blue" {
|
||||
t.Errorf("Color: got %q, want %q", list[0].Color, "blue")
|
||||
}
|
||||
if 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,8 +15,6 @@ var _ InvProductPanModel = (*customInvProductPanModel)(nil)
|
||||
type PanListItem struct {
|
||||
PanId string `db:"pan_id"`
|
||||
ProductId string `db:"product_id"`
|
||||
BatchId string `db:"batch_id"`
|
||||
BatchNo string `db:"batch_no"`
|
||||
Name string `db:"name"`
|
||||
Position string `db:"position"`
|
||||
ProductName string `db:"product_name"`
|
||||
@ -32,7 +30,6 @@ type (
|
||||
DeleteByProductId(ctx context.Context, productId string) error
|
||||
BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) error
|
||||
FindPanList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*PanListItem, int64, error)
|
||||
CountByBatchId(ctx context.Context, batchId string) (int64, error)
|
||||
}
|
||||
|
||||
customInvProductPanModel struct {
|
||||
@ -82,14 +79,13 @@ func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId str
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.batch_id, COALESCE(batch.batch_no, '') AS batch_no,
|
||||
pan.name, pan.position, p.product_name,
|
||||
query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.name, pan.position,
|
||||
p.product_name,
|
||||
COALESCE(GROUP_CONCAT(DISTINCT b.color ORDER BY b.color SEPARATOR ', '), '') AS colors,
|
||||
COUNT(b.bolt_id) AS bolt_count,
|
||||
COALESCE(SUM(b.length_m), 0) AS total_length_m
|
||||
FROM %s pan
|
||||
JOIN inv_product p ON p.product_id = pan.product_id
|
||||
LEFT JOIN inv_product_batch batch ON batch.batch_id = pan.batch_id AND batch.deleted_at IS NULL
|
||||
LEFT JOIN inv_product_bolt b ON b.pan_id = pan.pan_id
|
||||
%s
|
||||
GROUP BY pan.pan_id
|
||||
@ -104,15 +100,6 @@ func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId str
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
func (m *customInvProductPanModel) CountByBatchId(ctx context.Context, batchId string) (int64, error) {
|
||||
var total int64
|
||||
query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `batch_id` = ?", m.table)
|
||||
if err := m.conn.QueryRowCtx(ctx, &total, query, batchId); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
func (m *customInvProductPanModel) BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) error {
|
||||
return m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
delQuery := fmt.Sprintf("DELETE FROM %s WHERE `product_id` = ?", m.table)
|
||||
@ -122,12 +109,12 @@ func (m *customInvProductPanModel) BulkReplace(ctx context.Context, productId, t
|
||||
if len(pans) == 0 {
|
||||
return nil
|
||||
}
|
||||
placeholder := "(?, ?, ?, ?, ?, ?, ?)"
|
||||
placeholder := "(?, ?, ?, ?, ?, ?)"
|
||||
placeholders := make([]string, len(pans))
|
||||
args := make([]interface{}, 0, len(pans)*7)
|
||||
args := make([]interface{}, 0, len(pans)*6)
|
||||
for i, p := range pans {
|
||||
placeholders[i] = placeholder
|
||||
args = append(args, p.PanId, productId, p.BatchId, p.Name, p.Position, p.SortOrder, tenantId)
|
||||
args = append(args, p.PanId, productId, p.Name, p.Position, p.SortOrder, tenantId)
|
||||
}
|
||||
insQuery := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", m.table, invProductPanRowsExpectAutoSet, strings.Join(placeholders, ","))
|
||||
_, err := session.ExecCtx(ctx, insQuery, args...)
|
||||
|
||||
@ -37,7 +37,6 @@ type (
|
||||
Id int64 `db:"id"`
|
||||
PanId string `db:"pan_id"`
|
||||
ProductId string `db:"product_id"`
|
||||
BatchId string `db:"batch_id"`
|
||||
Name string `db:"name"`
|
||||
Position string `db:"position"`
|
||||
SortOrder int64 `db:"sort_order"`
|
||||
@ -55,8 +54,8 @@ func newInvProductPanModel(conn sqlx.SqlConn) *defaultInvProductPanModel {
|
||||
}
|
||||
|
||||
func (m *defaultInvProductPanModel) Insert(ctx context.Context, data *InvProductPan) (sql.Result, error) {
|
||||
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?)", m.table, invProductPanRowsExpectAutoSet)
|
||||
return m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.BatchId, data.Name, data.Position, data.SortOrder, data.TenantId)
|
||||
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?)", m.table, invProductPanRowsExpectAutoSet)
|
||||
return m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.Name, data.Position, data.SortOrder, data.TenantId)
|
||||
}
|
||||
|
||||
func (m *defaultInvProductPanModel) FindOne(ctx context.Context, id int64) (*InvProductPan, error) {
|
||||
@ -81,7 +80,7 @@ func (m *defaultInvProductPanModel) FindOneByPanId(ctx context.Context, panId st
|
||||
|
||||
func (m *defaultInvProductPanModel) Update(ctx context.Context, data *InvProductPan) error {
|
||||
query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, invProductPanRowsWithPlaceHolder)
|
||||
_, err := m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.BatchId, data.Name, data.Position, data.SortOrder, data.TenantId, data.Id)
|
||||
_, err := m.conn.ExecCtx(ctx, query, data.PanId, data.ProductId, data.Name, data.Position, data.SortOrder, data.TenantId, data.Id)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@ -1,82 +0,0 @@
|
||||
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)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user