23 KiB
23 KiB
到货交接单和出货交接单模块规格说明
1. 需求概述
在系统中增加两个新模块:到货交接单和出货交接单,用于记录和管理货物的交接过程。
1.1 到货交接单
- 交接单号:唯一标识
- 头程物流商送达时间:物流商送达时间
- 收货时间:实际收货时间
- POD:图片链接,多张用逗号隔开
- 备注:交接备注信息
- 创建人:创建该交接单的用户
- 创建时间:交接单创建时间
- 修改时间:交接单最后修改时间
1.2 出货交接单
- 交接单号:唯一标识,格式如 BOL-GOFO-202
- 大包数:大包数量
- 小包数:小包数量
- 渠道:物流渠道
- 交货时间:实际交货时间
- POD:图片链接,多张用逗号隔开
- 备注:交接备注信息
- 创建人:创建该交接单的用户
- 创建时间:交接单创建时间
- 修改时间:交接单最后修改时间
2. 技术方案
2.1 数据库设计
2.1.1 到货交接单表 (arrival_handover_forms)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
Id |
INT |
PRIMARY KEY, AUTO_INCREMENT |
主键ID |
HandoverNumber |
VARCHAR(100) |
NOT NULL, UNIQUE |
交接单号 |
LogisticsProviderArrivalTime |
DATETIME |
NULL |
头程物流商送达时间 |
ReceiptTime |
DATETIME |
NULL |
收货时间 |
POD |
TEXT |
NULL |
图片链接,多张用逗号隔开 |
Remarks |
TEXT |
NULL |
备注 |
Creator |
VARCHAR(50) |
NOT NULL |
创建人 |
CreatedAt |
DATETIME |
NOT NULL |
创建时间 |
UpdatedAt |
DATETIME |
NOT NULL |
修改时间 |
2.1.2 出货交接单表 (shipping_handover_forms)
| 字段名 | 数据类型 | 约束 | 描述 |
|---|---|---|---|
Id |
INT |
PRIMARY KEY, AUTO_INCREMENT |
主键ID |
HandoverNumber |
VARCHAR(100) |
NOT NULL, UNIQUE |
交接单号 |
BigBagCount |
INT |
NOT NULL |
大包数 |
SmallBagCount |
INT |
NOT NULL |
小包数 |
Channel |
VARCHAR(100) |
NOT NULL |
渠道 |
DeliveryTime |
DATETIME |
NULL |
交货时间 |
POD |
TEXT |
NULL |
图片链接,多张用逗号隔开 |
Remarks |
TEXT |
NULL |
备注 |
Creator |
VARCHAR(50) |
NOT NULL |
创建人 |
CreatedAt |
DATETIME |
NOT NULL |
创建时间 |
UpdatedAt |
DATETIME |
NOT NULL |
修改时间 |
2.2 模型设计
2.2.1 到货交接单模型 (ArrivalHandoverFormEntity)
using System;
using SqlSugar;
namespace MDL.Models
{
[SugarTable("arrival_handover_forms")]
public class ArrivalHandoverFormEntity
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[SugarColumn(Length = 100, IsNullable = false, IsUnique = true)]
public string HandoverNumber { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? LogisticsProviderArrivalTime { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? ReceiptTime { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string POD { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string Remarks { get; set; }
[SugarColumn(Length = 50, IsNullable = false)]
public string Creator { get; set; }
[SugarColumn(IsNullable = false)]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
[SugarColumn(IsNullable = false)]
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
}
2.2.2 出货交接单模型 (ShippingHandoverFormEntity)
using System;
using SqlSugar;
namespace MDL.Models
{
[SugarTable("shipping_handover_forms")]
public class ShippingHandoverFormEntity
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[SugarColumn(Length = 100, IsNullable = false, IsUnique = true)]
public string HandoverNumber { get; set; }
[SugarColumn(IsNullable = false)]
public int BigBagCount { get; set; }
[SugarColumn(IsNullable = false)]
public int SmallBagCount { get; set; }
[SugarColumn(Length = 100, IsNullable = false)]
public string Channel { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? DeliveryTime { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string POD { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string Remarks { get; set; }
[SugarColumn(Length = 50, IsNullable = false)]
public string Creator { get; set; }
[SugarColumn(IsNullable = false)]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
[SugarColumn(IsNullable = false)]
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
}
2.3 仓库设计
2.3.1 到货交接单仓库接口 (IArrivalHandoverFormRepository)
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface IArrivalHandoverFormRepository
{
Task<int> InsertAsync(ArrivalHandoverFormEntity form);
Task<ArrivalHandoverFormEntity> GetByIdAsync(int id);
Task<ArrivalHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber);
Task<List<ArrivalHandoverFormEntity>> GetAllAsync();
Task<int> UpdateAsync(ArrivalHandoverFormEntity form);
Task<int> DeleteAsync(int id);
Task<bool> ExistsByHandoverNumberAsync(string handoverNumber);
Task<(List<ArrivalHandoverFormEntity> Forms, int TotalCount)> GetArrivalHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string creator);
}
}
2.3.2 出货交接单仓库接口 (IShippingHandoverFormRepository)
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface IShippingHandoverFormRepository
{
Task<int> InsertAsync(ShippingHandoverFormEntity form);
Task<ShippingHandoverFormEntity> GetByIdAsync(int id);
Task<ShippingHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber);
Task<List<ShippingHandoverFormEntity>> GetAllAsync();
Task<int> UpdateAsync(ShippingHandoverFormEntity form);
Task<int> DeleteAsync(int id);
Task<bool> ExistsByHandoverNumberAsync(string handoverNumber);
Task<(List<ShippingHandoverFormEntity> Forms, int TotalCount)> GetShippingHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string channel,
string creator);
}
}
2.4 服务设计
2.4.1 到货交接单服务接口 (IArrivalHandoverFormService)
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace BLL.Interfaces
{
public interface IArrivalHandoverFormService
{
Task<int> CreateArrivalHandoverFormAsync(ArrivalHandoverFormEntity form);
Task<ArrivalHandoverFormEntity> GetArrivalHandoverFormByIdAsync(int id);
Task<ArrivalHandoverFormEntity> GetArrivalHandoverFormByNumberAsync(string handoverNumber);
Task<List<ArrivalHandoverFormEntity>> GetAllArrivalHandoverFormsAsync();
Task<int> UpdateArrivalHandoverFormAsync(ArrivalHandoverFormEntity form);
Task<int> DeleteArrivalHandoverFormAsync(int id);
Task<string> GenerateArrivalHandoverNumberAsync();
Task<(List<ArrivalHandoverFormEntity> Forms, int TotalCount)> GetArrivalHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string creator);
}
}
2.4.2 出货交接单服务接口 (IShippingHandoverFormService)
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace BLL.Interfaces
{
public interface IShippingHandoverFormService
{
Task<int> CreateShippingHandoverFormAsync(ShippingHandoverFormEntity form);
Task<ShippingHandoverFormEntity> GetShippingHandoverFormByIdAsync(int id);
Task<ShippingHandoverFormEntity> GetShippingHandoverFormByNumberAsync(string handoverNumber);
Task<List<ShippingHandoverFormEntity>> GetAllShippingHandoverFormsAsync();
Task<int> UpdateShippingHandoverFormAsync(ShippingHandoverFormEntity form);
Task<int> DeleteShippingHandoverFormAsync(int id);
Task<string> GenerateShippingHandoverNumberAsync();
Task<(List<ShippingHandoverFormEntity> Forms, int TotalCount)> GetShippingHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string channel,
string creator);
}
}
2.5 控制器设计
2.5.1 到货交接单控制器 (ArrivalHandoverFormController)
using BLL.Interfaces;
using MDL.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
namespace CONTROLLER.Controllers
{
[Route("api/arrival-handover")]
[ApiController]
public class ArrivalHandoverFormController : ControllerBase
{
private readonly IArrivalHandoverFormService _arrivalHandoverFormService;
public ArrivalHandoverFormController(IArrivalHandoverFormService arrivalHandoverFormService)
{
_arrivalHandoverFormService = arrivalHandoverFormService;
}
[HttpPost("create")]
public async Task<IActionResult> CreateArrivalHandoverForm([FromBody] ArrivalHandoverFormEntity form)
{
try
{
if (string.IsNullOrEmpty(form.HandoverNumber))
{
form.HandoverNumber = await _arrivalHandoverFormService.GenerateArrivalHandoverNumberAsync();
}
form.CreatedAt = DateTime.UtcNow;
form.UpdatedAt = DateTime.UtcNow;
var result = await _arrivalHandoverFormService.CreateArrivalHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get/{id}")]
public async Task<IActionResult> GetArrivalHandoverFormById(int id)
{
try
{
var form = await _arrivalHandoverFormService.GetArrivalHandoverFormByIdAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get-by-number/{handoverNumber}")]
public async Task<IActionResult> GetArrivalHandoverFormByNumber(string handoverNumber)
{
try
{
var form = await _arrivalHandoverFormService.GetArrivalHandoverFormByNumberAsync(handoverNumber);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("list")]
public async Task<IActionResult> GetArrivalHandoverForms(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string sortBy = "CreatedAt",
[FromQuery] string sortOrder = "desc",
[FromQuery] string handoverNumber = "",
[FromQuery] string creator = "")
{
try
{
var (forms, totalCount) = await _arrivalHandoverFormService.GetArrivalHandoverFormsBatchAsync(
page, pageSize, sortBy, sortOrder, handoverNumber, creator);
return Ok(new
{
code = 0,
message = "success",
data = new
{
forms,
totalCount
}
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpPut("update")]
public async Task<IActionResult> UpdateArrivalHandoverForm([FromBody] ArrivalHandoverFormEntity form)
{
try
{
form.UpdatedAt = DateTime.UtcNow;
var result = await _arrivalHandoverFormService.UpdateArrivalHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpDelete("delete/{id}")]
public async Task<IActionResult> DeleteArrivalHandoverForm(int id)
{
try
{
var result = await _arrivalHandoverFormService.DeleteArrivalHandoverFormAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("generate-number")]
public async Task<IActionResult> GenerateArrivalHandoverNumber()
{
try
{
var number = await _arrivalHandoverFormService.GenerateArrivalHandoverNumberAsync();
return Ok(new
{
code = 0,
message = "success",
data = number
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
}
}
2.5.2 出货交接单控制器 (ShippingHandoverFormController)
using BLL.Interfaces;
using MDL.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
namespace CONTROLLER.Controllers
{
[Route("api/shipping-handover")]
[ApiController]
public class ShippingHandoverFormController : ControllerBase
{
private readonly IShippingHandoverFormService _shippingHandoverFormService;
public ShippingHandoverFormController(IShippingHandoverFormService shippingHandoverFormService)
{
_shippingHandoverFormService = shippingHandoverFormService;
}
[HttpPost("create")]
public async Task<IActionResult> CreateShippingHandoverForm([FromBody] ShippingHandoverFormEntity form)
{
try
{
if (string.IsNullOrEmpty(form.HandoverNumber))
{
form.HandoverNumber = await _shippingHandoverFormService.GenerateShippingHandoverNumberAsync();
}
form.CreatedAt = DateTime.UtcNow;
form.UpdatedAt = DateTime.UtcNow;
var result = await _shippingHandoverFormService.CreateShippingHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get/{id}")]
public async Task<IActionResult> GetShippingHandoverFormById(int id)
{
try
{
var form = await _shippingHandoverFormService.GetShippingHandoverFormByIdAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get-by-number/{handoverNumber}")]
public async Task<IActionResult> GetShippingHandoverFormByNumber(string handoverNumber)
{
try
{
var form = await _shippingHandoverFormService.GetShippingHandoverFormByNumberAsync(handoverNumber);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("list")]
public async Task<IActionResult> GetShippingHandoverForms(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string sortBy = "CreatedAt",
[FromQuery] string sortOrder = "desc",
[FromQuery] string handoverNumber = "",
[FromQuery] string channel = "",
[FromQuery] string creator = "")
{
try
{
var (forms, totalCount) = await _shippingHandoverFormService.GetShippingHandoverFormsBatchAsync(
page, pageSize, sortBy, sortOrder, handoverNumber, channel, creator);
return Ok(new
{
code = 0,
message = "success",
data = new
{
forms,
totalCount
}
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpPut("update")]
public async Task<IActionResult> UpdateShippingHandoverForm([FromBody] ShippingHandoverFormEntity form)
{
try
{
form.UpdatedAt = DateTime.UtcNow;
var result = await _shippingHandoverFormService.UpdateShippingHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpDelete("delete/{id}")]
public async Task<IActionResult> DeleteShippingHandoverForm(int id)
{
try
{
var result = await _shippingHandoverFormService.DeleteShippingHandoverFormAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("generate-number")]
public async Task<IActionResult> GenerateShippingHandoverNumber()
{
try
{
var number = await _shippingHandoverFormService.GenerateShippingHandoverNumberAsync();
return Ok(new
{
code = 0,
message = "success",
data = number
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
}
}
3. 数据库SQL脚本
3.1 到货交接单表创建脚本
CREATE TABLE IF NOT EXISTS `arrival_handover_forms` (
`Id` INT NOT NULL AUTO_INCREMENT,
`HandoverNumber` VARCHAR(100) NOT NULL,
`LogisticsProviderArrivalTime` DATETIME NULL,
`ReceiptTime` DATETIME NULL,
`POD` TEXT NULL,
`Remarks` TEXT NULL,
`Creator` VARCHAR(50) NOT NULL,
`CreatedAt` DATETIME NOT NULL,
`UpdatedAt` DATETIME NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE INDEX `UQ_HandoverNumber` (`HandoverNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.2 出货交接单表创建脚本
CREATE TABLE IF NOT EXISTS `shipping_handover_forms` (
`Id` INT NOT NULL AUTO_INCREMENT,
`HandoverNumber` VARCHAR(100) NOT NULL,
`BigBagCount` INT NOT NULL,
`SmallBagCount` INT NOT NULL,
`Channel` VARCHAR(100) NOT NULL,
`DeliveryTime` DATETIME NULL,
`POD` TEXT NULL,
`Remarks` TEXT NULL,
`Creator` VARCHAR(50) NOT NULL,
`CreatedAt` DATETIME NOT NULL,
`UpdatedAt` DATETIME NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE INDEX `UQ_HandoverNumber` (`HandoverNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
4. 实现计划
- 创建模型类:在MDL项目中创建ArrivalHandoverFormEntity和ShippingHandoverFormEntity
- 创建仓库接口:在DAL项目中创建IArrivalHandoverFormRepository和IShippingHandoverFormRepository
- 实现仓库类:在DAL项目中实现ArrivalHandoverFormRepository和ShippingHandoverFormRepository
- 创建服务接口:在BLL项目中创建IArrivalHandoverFormService和IShippingHandoverFormService
- 实现服务类:在BLL项目中实现ArrivalHandoverFormService和ShippingHandoverFormService
- 创建控制器:在CONTROLLER项目中创建ArrivalHandoverFormController和ShippingHandoverFormController
- 更新依赖注入:在Program.cs中注册新的服务和仓库
- 测试API:验证所有CRUD操作是否正常工作
5. 验收标准
- 数据库表结构正确创建
- 所有API接口正常工作
- 交接单号生成规则正确
- POD字段支持多个图片链接(用逗号隔开)
- 分页查询功能正常
- 所有CRUD操作返回正确的响应格式