一、技术栈

  • 后端:ASP.NET Core 8 WebAPI
  • 数据库:SQL Server
  • ORM:Entity Framework Core
  • 架构:三层(控制器→服务→仓储)

二、项目目录结构

plaintext

WMS.WebAPI          // 接口层 控制器
WMS.Service         // 业务逻辑层
WMS.Repository     // 数据访问层
WMS.Entity          // 实体、DTO、模型

三、第一步:数据库表(直接执行 SQL)

1. 物料表

sql

CREATE TABLE Material(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    MaterialCode NVARCHAR(50) NOT NULL,
    MaterialName NVARCHAR(100) NOT NULL,
    Spec NVARCHAR(100),
    Unit NVARCHAR(20)
);

2. 仓库库位表

sql

CREATE TABLE WarehouseLocation(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    LocCode NVARCHAR(50) NOT NULL,
    LocName NVARCHAR(100),
    WarehouseCode NVARCHAR(50)
);

3. 库存表

sql

CREATE TABLE Inventory(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    Qty DECIMAL(18,2) DEFAULT 0
);

4. 入库单表

sql

CREATE TABLE InStockOrder(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    OrderNo NVARCHAR(50) NOT NULL,
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    InQty DECIMAL(18,2),
    CreateTime DATETIME DEFAULT GETDATE()
);

四、第二步:实体类 Entity

Material.cs

csharp

运行

namespace WMS.Entity
{
    public class Material
    {
        public int Id { get; set; }
        public string MaterialCode { get; set; } = string.Empty;
        public string MaterialName { get; set; } = string.Empty;
        public string? Spec { get; set; }
        public string? Unit { get; set; }
    }
}

Inventory.cs

csharp

运行

namespace WMS.Entity
{
    public class Inventory
    {
        public int Id { get; set; }
        public string MaterialCode { get; set; } = string.Empty;
        public string LocCode { get; set; } = string.Empty;
        public string BatchNo { get; set; } = string.Empty;
        public decimal Qty { get; set; }
    }
}

InStockOrder.cs

csharp

运行

namespace WMS.Entity
{
    public class InStockOrder
    {
        public int Id { get; set; }
        public string OrderNo { get; set; } = string.Empty;
        public string MaterialCode { get; set; } = string.Empty;
        public string LocCode { get; set; } = string.Empty;
        public string BatchNo { get; set; } = string.Empty;
        public decimal InQty { get; set; }
        public DateTime CreateTime { get; set; }
    }
}

五、第三步:DTO 入参模型

csharp

运行

namespace WMS.Entity
{
    public class InStockDto
    {
        public string MaterialCode { get; set; } = string.Empty;
        public string LocCode { get; set; } = string.Empty;
        public string BatchNo { get; set; } = string.Empty;
        public decimal InQty { get; set; }
    }
}

六、第四步:EF 数据库上下文

csharp

运行

using Microsoft.EntityFrameworkCore;
using WMS.Entity;

namespace WMS.Repository
{
    public class WmsDbContext : DbContext
    {
        public WmsDbContext(DbContextOptions<WmsDbContext> options) : base(options) { }

        public DbSet<Material> Material { get; set; }
        public DbSet<WarehouseLocation> WarehouseLocation { get; set; }
        public DbSet<Inventory> Inventory { get; set; }
        public DbSet<InStockOrder> InStockOrder { get; set; }
    }
}

七、第五步:入库 接口控制器(可直接用)

csharp

运行

using Microsoft.AspNetCore.Mvc;
using WMS.Entity;
using WMS.Repository;
using Microsoft.EntityFrameworkCore;

namespace WMS.WebAPI.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class InStockController : ControllerBase
    {
        private readonly WmsDbContext _db;
        public InStockController(WmsDbContext db)
        {
            _db = db;
        }

        // 提交入库、自动加库存
        [HttpPost("Create")]
        public async Task<IActionResult> Create([FromBody] InStockDto dto)
        {
            // 1. 生成入库单号
            string orderNo = "RK" + DateTime.Now.ToString("yyyyMMddHHmmss");

            // 2. 新增入库单
            var order = new InStockOrder
            {
                OrderNo = orderNo,
                MaterialCode = dto.MaterialCode,
                LocCode = dto.LocCode,
                BatchNo = dto.BatchNo,
                InQty = dto.InQty,
                CreateTime = DateTime.Now
            };
            _db.InStockOrder.Add(order);

            // 3. 更新库存:有则累加,无则新增
            var inv = await _db.Inventory
                .FirstOrDefaultAsync(x => x.MaterialCode == dto.MaterialCode 
                                       && x.LocCode == dto.LocCode 
                                       && x.BatchNo == dto.BatchNo);

            if (inv == null)
            {
                _db.Inventory.Add(new Inventory
                {
                    MaterialCode = dto.MaterialCode,
                    LocCode = dto.LocCode,
                    BatchNo = dto.BatchNo,
                    Qty = dto.InQty
                });
            }
            else
            {
                inv.Qty += dto.InQty;
            }

            await _db.SaveChangesAsync();
            return Ok(new { Code = 200, Msg = "入库成功", OrderNo = orderNo });
        }
    }
}

八、第六步:Program.cs 配置

csharp

运行

var builder = WebApplication.CreateBuilder(args);

// 注册控制器
builder.Services.AddControllers();
// 注册EF SQL Server
builder.Services.AddDbContext<WmsDbContext>(opt =>
{
    opt.UseSqlServer(builder.Configuration.GetConnectionString("WmsConn"));
});

var app = builder.Build();

app.MapControllers();
app.Run();

九、appsettings.json 连接字符串

json

"ConnectionStrings": {
  "WmsConn": "Server=.;Database=WMSDB;Trusted_Connection=True;TrustServerCertificate=True"
}

直接能用的功能

  1. 物料、库位、库存、入库单 基础表齐全
  2. 调用 /api/InStock/Create 即可完成入库 + 自动加库存
  3. 标准 WebAPI 接口,可给 PDA、前端、ERP 直接对接

基于上面 WMS 项目,直接复制就能用,不用改架构。

一、先补 2 张必备数据表(执行 SQL)

出库单表

sql

CREATE TABLE OutStockOrder(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    OrderNo NVARCHAR(50) NOT NULL,
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    OutQty DECIMAL(18,2),
    CreateTime DATETIME DEFAULT GETDATE()
);

仓库库位表

sql

CREATE TABLE WarehouseLocation(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    LocCode NVARCHAR(50) NOT NULL,
    LocName NVARCHAR(100),
    WarehouseCode NVARCHAR(50)
);

二、新增实体类

OutStockOrder.cs

csharp

运行

namespace WMS.Entity
{
    public class OutStockOrder
    {
        public int Id { get; set; }
        public string OrderNo { get; set; } = string.Empty;
        public string MaterialCode { get; set; } = string.Empty;
        public string LocCode { get; set; } = string.Empty;
        public string BatchNo { get; set; } = string.Empty;
        public decimal OutQty { get; set; }
        public DateTime CreateTime { get; set; }
    }
}

WarehouseLocation.cs

csharp

运行

namespace WMS.Entity
{
    public class WarehouseLocation
    {
        public int Id { get; set; }
        public string LocCode { get; set; } = string.Empty;
        public string LocName { get; set; } = string.Empty;
        public string WarehouseCode { get; set; } = string.Empty;
    }
}

三、新增 DTO

出库入参 DTO

csharp

运行

namespace WMS.Entity
{
    public class OutStockDto
    {
        public string MaterialCode { get; set; } = string.Empty;
        public string LocCode { get; set; } = string.Empty;
        public string BatchNo { get; set; } = string.Empty;
        public decimal OutQty { get; set; }
    }
}

库存分页查询 DTO

csharp

运行

namespace WMS.Entity
{
    public class InventoryQueryDto
    {
        public string? MaterialCode { get; set; }
        public string? LocCode { get; set; }
        public int PageIndex { get; set; } = 1;
        public int PageSize { get; set; } = 10;
    }
}

四、新增 出库控制器 OutStockController

自动校验库存是否充足 → 生成出库单 → 扣减库存

csharp

运行

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using WMS.Entity;
using WMS.Repository;

namespace WMS.WebAPI.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class OutStockController : ControllerBase
    {
        private readonly WmsDbContext _db;
        public OutStockController(WmsDbContext db)
        {
            _db = db;
        }

        [HttpPost("Create")]
        public async Task<IActionResult> Create([FromBody] OutStockDto dto)
        {
            // 1. 查当前库存
            var inv = await _db.Inventory
                .FirstOrDefaultAsync(x => x.MaterialCode == dto.MaterialCode
                                        && x.LocCode == dto.LocCode
                                        && x.BatchNo == dto.BatchNo);

            if (inv == null || inv.Qty < dto.OutQty)
            {
                return Ok(new { Code = 500, Msg = "库存不足,无法出库" });
            }

            // 2. 生成出库单号
            string orderNo = "CK" + DateTime.Now.ToString("yyyyMMddHHmmss");

            // 3. 新增出库单
            var outOrder = new OutStockOrder
            {
                OrderNo = orderNo,
                MaterialCode = dto.MaterialCode,
                LocCode = dto.LocCode,
                BatchNo = dto.BatchNo,
                OutQty = dto.OutQty,
                CreateTime = DateTime.Now
            };
            _db.OutStockOrder.Add(outOrder);

            // 4. 扣减库存
            inv.Qty -= dto.OutQty;

            // 库存为0可选择删除该行,这里保留记录
            await _db.SaveChangesAsync();

            return Ok(new { Code = 200, Msg = "出库成功", OrderNo = orderNo });
        }
    }
}

五、库存分页查询接口 InventoryController

支持按物料编码、库位模糊查询 + 分页

csharp

运行

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using WMS.Entity;
using WMS.Repository;

namespace WMS.WebAPI.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class InventoryController : ControllerBase
    {
        private readonly WmsDbContext _db;
        public InventoryController(WmsDbContext db)
        {
            _db = db;
        }

        [HttpPost("PageList")]
        public async Task<IActionResult> PageList([FromBody] InventoryQueryDto dto)
        {
            var query = _db.Inventory.AsQueryable();

            // 条件过滤
            if (!string.IsNullOrEmpty(dto.MaterialCode))
            {
                query = query.Where(x => x.MaterialCode.Contains(dto.MaterialCode));
            }
            if (!string.IsNullOrEmpty(dto.LocCode))
            {
                query = query.Where(x => x.LocCode.Contains(dto.LocCode));
            }

            // 分页
            var total = await query.CountAsync();
            var list = await query
                .Skip((dto.PageIndex - 1) * dto.PageSize)
                .Take(dto.PageSize)
                .ToListAsync();

            return Ok(new
            {
                Code = 200,
                Total = total,
                List = list
            });
        }
    }
}

六、更新数据库上下文 WmsDbContext

补上新增 DbSet

csharp

运行

public DbSet<OutStockOrder> OutStockOrder { get; set; }
public DbSet<WarehouseLocation> WarehouseLocation { get; set; }

七、现在整套 WMS 具备能力

  1. 物料、库位、库存、入库单、出库单 完整表结构
  2. 入库接口:生成单据 + 自动加库存
  3. 出库接口:库存校验 + 生成单据 + 自动扣库存
  4. 库存分页查询:条件筛选、分页返回
  5. 标准 WebAPI,可对接:PDA、Vue 前端、ERP、WCS

下一步我可以再给你

  1. 盘点接口(盘点差异调整库存)
  2. 移库接口(从 A 库位转到 B 库位)
  3. 金蝶 ERP 对接调用示例代码
  4. 整套项目分层完整版(接口层、服务层、仓储层拆分)

一、先执行:全套数据库 SQL(一次建完所有表)

sql

-- 物料表
CREATE TABLE Material(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    MaterialCode NVARCHAR(50) NOT NULL,
    MaterialName NVARCHAR(100) NOT NULL,
    Spec NVARCHAR(100),
    Unit NVARCHAR(20)
);

-- 仓库库位表
CREATE TABLE WarehouseLocation(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    LocCode NVARCHAR(50) NOT NULL,
    LocName NVARCHAR(100),
    WarehouseCode NVARCHAR(50)
);

-- 库存表
CREATE TABLE Inventory(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    Qty DECIMAL(18,2) DEFAULT 0
);

-- 入库单表
CREATE TABLE InStockOrder(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    OrderNo NVARCHAR(50) NOT NULL,
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    InQty DECIMAL(18,2),
    CreateTime DATETIME DEFAULT GETDATE()
);

-- 出库单表
CREATE TABLE OutStockOrder(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    OrderNo NVARCHAR(50) NOT NULL,
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    OutQty DECIMAL(18,2),
    CreateTime DATETIME DEFAULT GETDATE()
);

-- 盘点单表
CREATE TABLE StockCheck(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    CheckNo NVARCHAR(50),
    MaterialCode NVARCHAR(50),
    LocCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    SystemQty DECIMAL(18,2),
    CheckQty DECIMAL(18,2),
    DiffQty DECIMAL(18,2),
    CreateTime DATETIME DEFAULT GETDATE()
);

-- 移库单表
CREATE TABLE MoveStock(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    MoveNo NVARCHAR(50),
    MaterialCode NVARCHAR(50),
    BatchNo NVARCHAR(50),
    FromLoc NVARCHAR(50),
    ToLoc NVARCHAR(50),
    MoveQty DECIMAL(18,2),
    CreateTime DATETIME DEFAULT GETDATE()
);

二、完整实体类 Entity(全部复制)

1. Material.cs

csharp

运行

public class Material
{
    public int Id { get; set; }
    public string MaterialCode { get; set; } = string.Empty;
    public string MaterialName { get; set; } = string.Empty;
    public string? Spec { get; set; }
    public string? Unit { get; set; }
}

2. WarehouseLocation.cs

csharp

运行

public class WarehouseLocation
{
    public int Id { get; set; }
    public string LocCode { get; set; } = string.Empty;
    public string LocName { get; set; } = string.Empty;
    public string WarehouseCode { get; set; } = string.Empty;
}

3. Inventory.cs

csharp

运行

public class Inventory
{
    public int Id { get; set; }
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal Qty { get; set; }
}

4. InStockOrder.cs

csharp

运行

public class InStockOrder
{
    public int Id { get; set; }
    public string OrderNo { get; set; } = string.Empty;
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal InQty { get; set; }
    public DateTime CreateTime { get; set; }
}

5. OutStockOrder.cs

csharp

运行

public class OutStockOrder
{
    public int Id { get; set; }
    public string OrderNo { get; set; } = string.Empty;
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal OutQty { get; set; }
    public DateTime CreateTime { get; set; }
}

6. StockCheck.cs

csharp

运行

public class StockCheck
{
    public int Id { get; set; }
    public string CheckNo { get; set; } = string.Empty;
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal SystemQty { get; set; }
    public decimal CheckQty { get; set; }
    public decimal DiffQty { get; set; }
    public DateTime CreateTime { get; set; }
}

7. MoveStock.cs

csharp

运行

public class MoveStock
{
    public int Id { get; set; }
    public string MoveNo { get; set; } = string.Empty;
    public string MaterialCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public string FromLoc { get; set; } = string.Empty;
    public string ToLoc { get; set; } = string.Empty;
    public decimal MoveQty { get; set; }
    public DateTime CreateTime { get; set; }
}

三、DTO 模型(全部复制)

1. InStockDto.cs

csharp

运行

public class InStockDto
{
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal InQty { get; set; }
}

2. OutStockDto.cs

csharp

运行

public class OutStockDto
{
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal OutQty { get; set; }
}

3. InventoryQueryDto.cs

csharp

运行

public class InventoryQueryDto
{
    public string? MaterialCode { get; set; }
    public string? LocCode { get; set; }
    public int PageIndex { get; set; } = 1;
    public int PageSize { get; set; } = 10;
}

4. StockCheckDto.cs

csharp

运行

public class StockCheckDto
{
    public string MaterialCode { get; set; } = string.Empty;
    public string LocCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public decimal CheckQty { get; set; }
}

5. MoveStockDto.cs

csharp

运行

public class MoveStockDto
{
    public string MaterialCode { get; set; } = string.Empty;
    public string BatchNo { get; set; } = string.Empty;
    public string FromLoc { get; set; } = string.Empty;
    public string ToLoc { get; set; } = string.Empty;
    public decimal MoveQty { get; set; }
}

四、数据库上下文 WmsDbContext.cs

csharp

运行

using Microsoft.EntityFrameworkCore;

public class WmsDbContext : DbContext
{
    public WmsDbContext(DbContextOptions<WmsDbContext> options) : base(options) { }

    public DbSet<Material> Material { get; set; }
    public DbSet<WarehouseLocation> WarehouseLocation { get; set; }
    public DbSet<Inventory> Inventory { get; set; }
    public DbSet<InStockOrder> InStockOrder { get; set; }
    public DbSet<OutStockOrder> OutStockOrder { get; set; }
    public DbSet<StockCheck> StockCheck { get; set; }
    public DbSet<MoveStock> MoveStock { get; set; }
}

五、全套控制器(7 大核心接口,直接复制

1. 入库控制器 InStockController

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class InStockController : ControllerBase
{
    private readonly WmsDbContext _db;
    public InStockController(WmsDbContext db) => _db = db;

    [HttpPost("Create")]
    public async Task<IActionResult> Create(InStockDto dto)
    {
        string orderNo = "RK" + DateTime.Now.ToString("yyyyMMddHHmmss");
        _db.InStockOrder.Add(new InStockOrder
        {
            OrderNo = orderNo,
            MaterialCode = dto.MaterialCode,
            LocCode = dto.LocCode,
            BatchNo = dto.BatchNo,
            InQty = dto.InQty,
            CreateTime = DateTime.Now
        });

        var inv = await _db.Inventory.FirstOrDefaultAsync(x =>
            x.MaterialCode == dto.MaterialCode &&
            x.LocCode == dto.LocCode &&
            x.BatchNo == dto.BatchNo);

        if (inv == null)
            _db.Inventory.Add(new Inventory { MaterialCode = dto.MaterialCode, LocCode = dto.LocCode, BatchNo = dto.BatchNo, Qty = dto.InQty });
        else
            inv.Qty += dto.InQty;

        await _db.SaveChangesAsync();
        return Ok(new { Code = 200, Msg = "入库成功", OrderNo = orderNo });
    }
}

2. 出库控制器 OutStockController

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class OutStockController : ControllerBase
{
    private readonly WmsDbContext _db;
    public OutStockController(WmsDbContext db) => _db = db;

    [HttpPost("Create")]
    public async Task<IActionResult> Create(OutStockDto dto)
    {
        var inv = await _db.Inventory.FirstOrDefaultAsync(x =>
            x.MaterialCode == dto.MaterialCode &&
            x.LocCode == dto.LocCode &&
            x.BatchNo == dto.BatchNo);

        if (inv == null || inv.Qty < dto.OutQty)
            return Ok(new { Code = 500, Msg = "库存不足" });

        string orderNo = "CK" + DateTime.Now.ToString("yyyyMMddHHmmss");
        _db.OutStockOrder.Add(new OutStockOrder
        {
            OrderNo = orderNo,
            MaterialCode = dto.MaterialCode,
            LocCode = dto.LocCode,
            BatchNo = dto.BatchNo,
            OutQty = dto.OutQty,
            CreateTime = DateTime.Now
        });

        inv.Qty -= dto.OutQty;
        await _db.SaveChangesAsync();
        return Ok(new { Code = 200, Msg = "出库成功", OrderNo = orderNo });
    }
}

3. 库存查询 InventoryController

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class InventoryController : ControllerBase
{
    private readonly WmsDbContext _db;
    public InventoryController(WmsDbContext db) => _db = db;

    [HttpPost("PageList")]
    public async Task<IActionResult> PageList(InventoryQueryDto dto)
    {
        var query = _db.Inventory.AsQueryable();
        if (!string.IsNullOrEmpty(dto.MaterialCode)) query = query.Where(x => x.MaterialCode.Contains(dto.MaterialCode));
        if (!string.IsNullOrEmpty(dto.LocCode)) query = query.Where(x => x.LocCode.Contains(dto.LocCode));

        var total = await query.CountAsync();
        var list = await query.Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync();
        return Ok(new { Code = 200, Total = total, List = list });
    }
}

4. 盘点控制器 StockCheckController

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class StockCheckController : ControllerBase
{
    private readonly WmsDbContext _db;
    public StockCheckController(WmsDbContext db) => _db = db;

    [HttpPost("Create")]
    public async Task<IActionResult> Create(StockCheckDto dto)
    {
        var inv = await _db.Inventory.FirstOrDefaultAsync(x =>
            x.MaterialCode == dto.MaterialCode &&
            x.LocCode == dto.LocCode &&
            x.BatchNo == dto.BatchNo);

        decimal sysQty = inv?.Qty ?? 0;
        decimal diff = dto.CheckQty - sysQty;

        var check = new StockCheck
        {
            CheckNo = "PD" + DateTime.Now.ToString("yyyyMMddHHmmss"),
            MaterialCode = dto.MaterialCode,
            LocCode = dto.LocCode,
            BatchNo = dto.BatchNo,
            SystemQty = sysQty,
            CheckQty = dto.CheckQty,
            DiffQty = diff,
            CreateTime = DateTime.Now
        };
        _db.StockCheck.Add(check);

        if (inv != null) inv.Qty = dto.CheckQty;
        else _db.Inventory.Add(new Inventory { MaterialCode = dto.MaterialCode, LocCode = dto.LocCode, BatchNo = dto.BatchNo, Qty = dto.CheckQty });

        await _db.SaveChangesAsync();
        return Ok(new { Code = 200, Msg = "盘点完成" });
    }
}

5. 移库控制器 MoveStockController

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class MoveStockController : ControllerBase
{
    private readonly WmsDbContext _db;
    public MoveStockController(WmsDbContext db) => _db = db;

    [HttpPost("Create")]
    public async Task<IActionResult> Create(MoveStockDto dto)
    {
        var fromInv = await _db.Inventory.FirstOrDefaultAsync(x =>
            x.MaterialCode == dto.MaterialCode &&
            x.LocCode == dto.FromLoc &&
            x.BatchNo == dto.BatchNo);

        if (fromInv == null || fromInv.Qty < dto.MoveQty)
            return Ok(new { Code = 500, Msg = "源库位库存不足" });

        string moveNo = "YK" + DateTime.Now.ToString("yyyyMMddHHmmss");
        _db.MoveStock.Add(new MoveStock
        {
            MoveNo = moveNo,
            MaterialCode = dto.MaterialCode,
            BatchNo = dto.BatchNo,
            FromLoc = dto.FromLoc,
            ToLoc = dto.ToLoc,
            MoveQty = dto.MoveQty,
            CreateTime = DateTime.Now
        });

        fromInv.Qty -= dto.MoveQty;

        var toInv = await _db.Inventory.FirstOrDefaultAsync(x =>
            x.MaterialCode == dto.MaterialCode &&
            x.LocCode == dto.ToLoc &&
            x.BatchNo == dto.BatchNo);

        if (toInv == null)
            _db.Inventory.Add(new Inventory { MaterialCode = dto.MaterialCode, LocCode = dto.ToLoc, BatchNo = dto.BatchNo, Qty = dto.MoveQty });
        else
            toInv.Qty += dto.MoveQty;

        await _db.SaveChangesAsync();
        return Ok(new { Code = 200, Msg = "移库成功", MoveNo = moveNo });
    }
}

6. 物料控制器 MaterialController

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class MaterialController : ControllerBase
{
    private readonly WmsDbContext _db;
    public MaterialController(WmsDbContext db) => _db = db;

    [HttpGet("List")]
    public async Task<IActionResult> List() => Ok(await _db.Material.ToListAsync());

    [HttpPost("Add")]
    public async Task<IActionResult> Add(Material model)
    {
        _db.Material.Add(model);
        await _db.SaveChangesAsync();
        return Ok("添加成功");
    }
}

7. ERP 对接通用接口(给金蝶 / 用友 / SAP)

csharp

运行

[ApiController]
[Route("api/[controller]")]
public class ErpController : ControllerBase
{
    [HttpPost("SyncInStock")]
    public IActionResult SyncInStock(object data)
    {
        // 在这里写对接ERP逻辑
        return Ok(new { Code = 200, Msg = "ERP同步成功" });
    }

    [HttpPost("SyncOutStock")]
    public IActionResult SyncOutStock(object data)
    {
        return Ok(new { Code = 200, Msg = "ERP同步成功" });
    }
}

六、Program.cs 完整配置

csharp

运行

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<WmsDbContext>(opt =>
    opt.UseSqlServer(builder.Configuration.GetConnectionString("WmsConn")));

var app = builder.Build();
app.MapControllers();
app.Run();

七、appsettings.json 连接字符串

json

{
  "ConnectionStrings": {
    "WmsConn": "Server=.;Database=WMSDB;Trusted_Connection=True;TrustServerCertificate=True"
  }
}

🎯 这套代码你现在拥有的功能

✅ 入库 + 自动增加库存✅ 出库 + 库存校验 + 扣减库存✅ 库存查询 + 分页 + 筛选✅ 盘点单 + 自动调整库存✅ 移库单 + 库位库存转移✅ 物料管理✅ ERP 对接接口(金蝶 / 用友 / SAP)✅ 标准 WebAPI,可给 PDA / 前端 / 上位机调用

更多推荐