451 lines
10 KiB
Go
451 lines
10 KiB
Go
package handler
|
||
|
||
import (
|
||
"errors"
|
||
"strconv"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/wmms/wmms/internal/middleware"
|
||
"github.com/wmms/wmms/internal/model"
|
||
"github.com/wmms/wmms/internal/repository"
|
||
"github.com/wmms/wmms/internal/service"
|
||
"github.com/wmms/wmms/pkg/response"
|
||
)
|
||
|
||
func organizationID(c *gin.Context) (int64, bool) {
|
||
id := middleware.GetCurrentOrganizationID(c)
|
||
if id <= 0 {
|
||
response.BadRequest(c, "请选择有效的公司")
|
||
return 0, false
|
||
}
|
||
return id, true
|
||
}
|
||
|
||
func pathID(c *gin.Context) (int64, bool) {
|
||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||
if err != nil || id <= 0 {
|
||
response.BadRequest(c, "invalid id")
|
||
return 0, false
|
||
}
|
||
return id, true
|
||
}
|
||
|
||
func bind(c *gin.Context, value interface{}) bool {
|
||
if err := c.ShouldBindJSON(value); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
func (h *Handler) ListOrganizations(c *gin.Context) {
|
||
items, err := h.organizationSvc.List()
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
func (h *Handler) ListRoles(c *gin.Context) {
|
||
items, err := h.organizationSvc.ListRoles()
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
func (h *Handler) ListPermissions(c *gin.Context) {
|
||
items, err := h.organizationSvc.ListPermissions()
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
func (h *Handler) UpdateRole(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var req model.UpdateRoleRequest
|
||
if !bind(c, &req) {
|
||
return
|
||
}
|
||
if err := h.organizationSvc.UpdateRole(id, &req); err != nil {
|
||
if errors.Is(err, service.ErrProtectedRole) {
|
||
response.Error(c, 409, err.Error())
|
||
return
|
||
}
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.SuccessWithMessage(c, "Role updated successfully", nil)
|
||
}
|
||
func (h *Handler) CreateOrganization(c *gin.Context) {
|
||
var item model.Organization
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
if err := h.organizationSvc.Create(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Organization created successfully", item)
|
||
}
|
||
func (h *Handler) UpdateOrganization(c *gin.Context) {
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.Organization
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID = id
|
||
if err := h.organizationSvc.Update(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|
||
|
||
func (h *Handler) ListMaterialCategories(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, err := h.masterDataSvc.ListCategories(orgID)
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
func (h *Handler) CreateMaterialCategory(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.MaterialCategory
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.OrganizationID = orgID
|
||
if err := h.masterDataSvc.CreateCategory(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Material category created successfully", item)
|
||
}
|
||
func (h *Handler) UpdateMaterialCategory(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.MaterialCategory
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID, item.OrganizationID = id, orgID
|
||
if err := h.masterDataSvc.UpdateCategory(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|
||
|
||
func (h *Handler) ListUnits(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, err := h.masterDataSvc.ListUnits(orgID)
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
func (h *Handler) CreateUnit(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.Unit
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.OrganizationID = orgID
|
||
if err := h.masterDataSvc.CreateUnit(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Unit created successfully", item)
|
||
}
|
||
func (h *Handler) UpdateUnit(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.Unit
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID, item.OrganizationID = id, orgID
|
||
if err := h.masterDataSvc.UpdateUnit(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|
||
|
||
func (h *Handler) ListCodeRules(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, err := h.masterDataSvc.ListCodeRules(orgID)
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
|
||
// GetNextMaterialCode 预览按小类规则自动生成的物料编码。新增物料的人要用它
|
||
// 填表,所以只要求登录,不要求管理员。
|
||
func (h *Handler) GetNextMaterialCode(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
categoryID, err := strconv.ParseInt(c.Query("category_id"), 10, 64)
|
||
if err != nil || categoryID <= 0 {
|
||
response.BadRequest(c, "invalid category_id")
|
||
return
|
||
}
|
||
next, err := h.masterDataSvc.NextMaterialCode(orgID, categoryID)
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, next)
|
||
}
|
||
func (h *Handler) CreateCodeRule(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.CodeRule
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.OrganizationID = orgID
|
||
if err := h.masterDataSvc.CreateCodeRule(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Code rule created successfully", item)
|
||
}
|
||
func (h *Handler) UpdateCodeRule(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.CodeRule
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID, item.OrganizationID = id, orgID
|
||
if err := h.masterDataSvc.UpdateCodeRule(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|
||
|
||
func (h *Handler) ListPartners(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
// 分页参数的默认值与上限跟物料等列表接口保持一致,前端不必记两套规则
|
||
limit := 20
|
||
offset := 0
|
||
if l := c.Query("limit"); l != "" {
|
||
if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 {
|
||
limit = parsed
|
||
if limit > 100 {
|
||
limit = 100
|
||
}
|
||
}
|
||
}
|
||
if o := c.Query("offset"); o != "" {
|
||
if parsed, err := strconv.Atoi(o); err == nil && parsed >= 0 {
|
||
offset = parsed
|
||
}
|
||
}
|
||
|
||
items, total, err := h.partnerSvc.List(orgID, c.Query("role"), limit, offset, c.Query("category"))
|
||
if err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
if items == nil {
|
||
items = []model.BusinessPartner{}
|
||
}
|
||
response.PaginatedSuccess(c, items, limit, offset, total)
|
||
}
|
||
func (h *Handler) CreatePartner(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.BusinessPartner
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.OrganizationID = orgID
|
||
if err := h.partnerSvc.Create(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Partner created successfully", item)
|
||
}
|
||
func (h *Handler) UpdatePartner(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.BusinessPartner
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID, item.OrganizationID = id, orgID
|
||
if err := h.partnerSvc.Update(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|
||
|
||
func (h *Handler) ListWarehouses(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
items, err := h.warehouseSvc.List(orgID)
|
||
if err != nil {
|
||
response.InternalError(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, items)
|
||
}
|
||
func (h *Handler) CreateWarehouse(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.Warehouse
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.OrganizationID = orgID
|
||
if err := h.warehouseSvc.Create(&item); err != nil {
|
||
// 每公司最多一个仓库:唯一约束冲突回 409 并给出可操作提示,而不是笼统的 400。
|
||
if errors.Is(err, repository.ErrDuplicateWarehouse) {
|
||
response.Error(c, 409, err.Error())
|
||
return
|
||
}
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Warehouse created successfully", item)
|
||
}
|
||
func (h *Handler) UpdateWarehouse(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
id, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.Warehouse
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID, item.OrganizationID = id, orgID
|
||
if err := h.warehouseSvc.Update(&item); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|
||
func (h *Handler) CreateWarehouseLocation(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
warehouseID, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
var item model.WarehouseLocation
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.WarehouseID = warehouseID
|
||
if err := h.warehouseSvc.CreateLocation(&item, orgID); err != nil {
|
||
// 每仓库最多一个库位:唯一约束冲突回 409,仓库不属于本公司仍回 400。
|
||
if errors.Is(err, repository.ErrDuplicateLocation) {
|
||
response.Error(c, 409, err.Error())
|
||
return
|
||
}
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Created(c, "Location created successfully", item)
|
||
}
|
||
func (h *Handler) UpdateWarehouseLocation(c *gin.Context) {
|
||
orgID, ok := organizationID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
warehouseID, ok := pathID(c)
|
||
if !ok {
|
||
return
|
||
}
|
||
locationID, err := strconv.ParseInt(c.Param("locationId"), 10, 64)
|
||
if err != nil || locationID <= 0 {
|
||
response.BadRequest(c, "invalid location id")
|
||
return
|
||
}
|
||
var item model.WarehouseLocation
|
||
if !bind(c, &item) {
|
||
return
|
||
}
|
||
item.ID, item.WarehouseID = locationID, warehouseID
|
||
if err := h.warehouseSvc.UpdateLocation(&item, orgID); err != nil {
|
||
response.BadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, item)
|
||
}
|