material_manage_system/internal/handler/admin_master.go
2026-10-09 10:38:02 +08:00

451 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}