283 lines
8.8 KiB
Go
283 lines
8.8 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"server/models"
|
|
|
|
"github.com/beego/beego/v2/client/orm"
|
|
beego "github.com/beego/beego/v2/server/web"
|
|
)
|
|
|
|
// BackendCrmProjectController CRM 项目管理
|
|
type BackendCrmProjectController struct {
|
|
beego.Controller
|
|
}
|
|
|
|
type projectPayload struct {
|
|
ProjectName string `json:"project_name"`
|
|
ProjectNo string `json:"project_no"`
|
|
CustomerID uint64 `json:"customer_id"`
|
|
CustomerName string `json:"customer_name"`
|
|
OwnerUserID string `json:"owner_user_id"`
|
|
OwnerUserName string `json:"owner_user_name"`
|
|
Industry string `json:"industry"`
|
|
Amount float64 `json:"amount"`
|
|
Status int8 `json:"status"`
|
|
StartDate string `json:"start_date"`
|
|
EndDate string `json:"end_date"`
|
|
ContactPerson string `json:"contact_person"`
|
|
ContactPosition string `json:"contact_position"`
|
|
ContactPhone string `json:"contact_phone"`
|
|
Address string `json:"address"`
|
|
Remark string `json:"remark"`
|
|
}
|
|
|
|
// List GET /backend/crm/project/list
|
|
func (c *BackendCrmProjectController) List() {
|
|
claims, err := pipelineClaims(&c.Controller)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 401, 401, err.Error())
|
|
return
|
|
}
|
|
page, _ := c.GetInt("page", 1)
|
|
pageSize, _ := c.GetInt("pageSize", 20)
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 || pageSize > 100 {
|
|
pageSize = 20
|
|
}
|
|
keyword := strings.TrimSpace(c.GetString("keyword"))
|
|
status := strings.TrimSpace(c.GetString("status"))
|
|
ownerID := strings.TrimSpace(c.GetString("owner_user_id"))
|
|
|
|
tenantID := pipelineTenantID(claims)
|
|
cond := orm.NewCondition().And("tenant_id", tenantID).And("delete_time__isnull", true)
|
|
if keyword != "" {
|
|
kw := orm.NewCondition().
|
|
Or("project_name__contains", keyword).
|
|
Or("project_no__contains", keyword).
|
|
Or("customer_name__contains", keyword)
|
|
cond = cond.AndCond(kw)
|
|
}
|
|
if status != "" {
|
|
cond = cond.And("status", status)
|
|
}
|
|
if ownerID != "" {
|
|
cond = cond.And("owner_user_id", ownerID)
|
|
}
|
|
qs := models.Orm.QueryTable(new(models.TenantCrmProject)).SetCond(cond)
|
|
|
|
total, _ := qs.Count()
|
|
var list []models.TenantCrmProject
|
|
if total > 0 {
|
|
_, _ = qs.OrderBy("-id").Offset((page - 1) * pageSize).Limit(pageSize).All(&list)
|
|
}
|
|
pipelineOk(&c.Controller, map[string]interface{}{
|
|
"list": list, "total": total, "page": page, "pageSize": pageSize,
|
|
})
|
|
}
|
|
|
|
// Detail GET /backend/crm/project/:id
|
|
func (c *BackendCrmProjectController) Detail() {
|
|
claims, err := pipelineClaims(&c.Controller)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 401, 401, err.Error())
|
|
return
|
|
}
|
|
id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
|
if id == 0 {
|
|
pipelineErr(&c.Controller, 400, 400, "无效的ID")
|
|
return
|
|
}
|
|
var proj models.TenantCrmProject
|
|
err = models.Orm.QueryTable(new(models.TenantCrmProject)).
|
|
Filter("id", id).Filter("tenant_id", pipelineTenantID(claims)).
|
|
Filter("delete_time__isnull", true).One(&proj)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 404, 404, "项目未找到")
|
|
return
|
|
}
|
|
pipelineOk(&c.Controller, proj)
|
|
}
|
|
|
|
// Create POST /backend/crm/project
|
|
func (c *BackendCrmProjectController) Create() {
|
|
claims, err := pipelineClaims(&c.Controller)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 401, 401, err.Error())
|
|
return
|
|
}
|
|
raw, _ := io.ReadAll(c.Ctx.Request.Body)
|
|
var p projectPayload
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
|
return
|
|
}
|
|
if strings.TrimSpace(p.ProjectName) == "" {
|
|
pipelineErr(&c.Controller, 400, 400, "项目名称不能为空")
|
|
return
|
|
}
|
|
|
|
tenantID := pipelineTenantID(claims)
|
|
var custIDVal *uint64
|
|
customerName := strings.TrimSpace(p.CustomerName)
|
|
if p.CustomerID > 0 {
|
|
var cust models.TenantCrmCustomer
|
|
if err := models.Orm.QueryTable(new(models.TenantCrmCustomer)).
|
|
Filter("id", p.CustomerID).Filter("tenant_id", tenantID).
|
|
Filter("delete_time__isnull", true).One(&cust); err == nil {
|
|
cid := cust.ID
|
|
custIDVal = &cid
|
|
customerName = cust.CustomerName
|
|
}
|
|
}
|
|
status := p.Status
|
|
if status == 0 {
|
|
status = 1
|
|
}
|
|
now := time.Now()
|
|
proj := models.TenantCrmProject{
|
|
TenantID: tenantID,
|
|
ProjectName: strings.TrimSpace(p.ProjectName),
|
|
ProjectNo: strings.TrimSpace(p.ProjectNo),
|
|
CustomerID: custIDVal,
|
|
CustomerName: customerName,
|
|
OwnerUserID: firstNonEmpty(p.OwnerUserID, pipelineUID(claims)),
|
|
OwnerUserName: firstNonEmpty(p.OwnerUserName, claims.Username),
|
|
Industry: strings.TrimSpace(p.Industry),
|
|
Amount: p.Amount,
|
|
Status: status,
|
|
StartDate: parsePipelineDate(p.StartDate),
|
|
EndDate: parsePipelineDate(p.EndDate),
|
|
ContactPerson: strings.TrimSpace(p.ContactPerson),
|
|
ContactPosition: strings.TrimSpace(p.ContactPosition),
|
|
ContactPhone: strings.TrimSpace(p.ContactPhone),
|
|
Address: strings.TrimSpace(p.Address),
|
|
Remark: p.Remark,
|
|
CreateUserID: pipelineUID(claims),
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
}
|
|
id, err := models.Orm.Insert(&proj)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error())
|
|
return
|
|
}
|
|
crmWriteLog(tenantID, 3, uint64(id), "create", "创建项目:"+proj.ProjectName, claims)
|
|
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
|
}
|
|
|
|
// Update PUT /backend/crm/project/:id
|
|
func (c *BackendCrmProjectController) Update() {
|
|
claims, err := pipelineClaims(&c.Controller)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 401, 401, err.Error())
|
|
return
|
|
}
|
|
id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
|
if id == 0 {
|
|
pipelineErr(&c.Controller, 400, 400, "无效的ID")
|
|
return
|
|
}
|
|
raw, _ := io.ReadAll(c.Ctx.Request.Body)
|
|
var p projectPayload
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
|
return
|
|
}
|
|
tenantID := pipelineTenantID(claims)
|
|
var proj models.TenantCrmProject
|
|
if err := models.Orm.QueryTable(new(models.TenantCrmProject)).
|
|
Filter("id", id).Filter("tenant_id", tenantID).
|
|
Filter("delete_time__isnull", true).One(&proj); err != nil {
|
|
pipelineErr(&c.Controller, 404, 404, "项目未找到")
|
|
return
|
|
}
|
|
if strings.TrimSpace(p.ProjectName) == "" {
|
|
pipelineErr(&c.Controller, 400, 400, "项目名称不能为空")
|
|
return
|
|
}
|
|
|
|
proj.ProjectName = strings.TrimSpace(p.ProjectName)
|
|
proj.ProjectNo = strings.TrimSpace(p.ProjectNo)
|
|
if p.CustomerID > 0 {
|
|
var cust models.TenantCrmCustomer
|
|
if err := models.Orm.QueryTable(new(models.TenantCrmCustomer)).
|
|
Filter("id", p.CustomerID).Filter("tenant_id", tenantID).
|
|
Filter("delete_time__isnull", true).One(&cust); err == nil {
|
|
cid := cust.ID
|
|
proj.CustomerID = &cid
|
|
proj.CustomerName = cust.CustomerName
|
|
}
|
|
} else if strings.TrimSpace(p.CustomerName) != "" {
|
|
proj.CustomerName = strings.TrimSpace(p.CustomerName)
|
|
}
|
|
if strings.TrimSpace(p.OwnerUserID) != "" {
|
|
proj.OwnerUserID = strings.TrimSpace(p.OwnerUserID)
|
|
}
|
|
if strings.TrimSpace(p.OwnerUserName) != "" {
|
|
proj.OwnerUserName = strings.TrimSpace(p.OwnerUserName)
|
|
}
|
|
proj.Industry = strings.TrimSpace(p.Industry)
|
|
proj.Amount = p.Amount
|
|
if p.Status != 0 {
|
|
proj.Status = p.Status
|
|
}
|
|
proj.StartDate = parsePipelineDate(p.StartDate)
|
|
proj.EndDate = parsePipelineDate(p.EndDate)
|
|
proj.ContactPerson = strings.TrimSpace(p.ContactPerson)
|
|
proj.ContactPosition = strings.TrimSpace(p.ContactPosition)
|
|
proj.ContactPhone = strings.TrimSpace(p.ContactPhone)
|
|
proj.Address = strings.TrimSpace(p.Address)
|
|
proj.Remark = p.Remark
|
|
proj.UpdateTime = time.Now()
|
|
|
|
if _, err := models.Orm.Update(&proj); err != nil {
|
|
pipelineErr(&c.Controller, 500, 500, "更新失败: "+err.Error())
|
|
return
|
|
}
|
|
crmWriteLog(tenantID, 3, proj.ID, "update", "更新项目:"+proj.ProjectName, claims)
|
|
pipelineOk(&c.Controller, map[string]interface{}{"id": proj.ID})
|
|
}
|
|
|
|
// Delete DELETE /backend/crm/project/:id
|
|
func (c *BackendCrmProjectController) Delete() {
|
|
claims, err := pipelineClaims(&c.Controller)
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 401, 401, err.Error())
|
|
return
|
|
}
|
|
id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
|
if id == 0 {
|
|
pipelineErr(&c.Controller, 400, 400, "无效的ID")
|
|
return
|
|
}
|
|
tenantID := pipelineTenantID(claims)
|
|
var proj models.TenantCrmProject
|
|
if err := models.Orm.QueryTable(new(models.TenantCrmProject)).
|
|
Filter("id", id).Filter("tenant_id", tenantID).
|
|
Filter("delete_time__isnull", true).One(&proj); err != nil {
|
|
pipelineErr(&c.Controller, 404, 404, "项目未找到")
|
|
return
|
|
}
|
|
if !canDeleteCrmRecord(claims, proj.CreateUserID) {
|
|
pipelineErr(&c.Controller, 403, 403, "只有创建人、租户管理员或平台管理员可以删除该项目")
|
|
return
|
|
}
|
|
now := time.Now()
|
|
_, err = models.Orm.QueryTable(new(models.TenantCrmProject)).
|
|
Filter("id", id).Filter("tenant_id", tenantID).
|
|
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
|
if err != nil {
|
|
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
|
return
|
|
}
|
|
pipelineOk(&c.Controller, nil)
|
|
}
|