增加招投标模块
This commit is contained in:
@@ -0,0 +1,812 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// =============================================================
|
||||
// CRM 招投标管理 - 子表 CRUD(统一接口)
|
||||
// =============================================================
|
||||
//
|
||||
// 每个子表控制器提供统一的接口:
|
||||
// - List 按外键 bid_id / tender_id 列出
|
||||
// - Create 新增(关联外键由请求体传入)
|
||||
// - Delete 软删除
|
||||
// - Update 更新(用于文件改名、任务进度等)
|
||||
// =============================================================
|
||||
|
||||
// ------------------------------ 投标文件 ------------------------------
|
||||
|
||||
// BackendCrmBiddingBidFileController 投标文件
|
||||
type BackendCrmBiddingBidFileController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// bidFilePayload
|
||||
type bidFilePayload struct {
|
||||
BidID uint64 `json:"bid_id"`
|
||||
FileType string `json:"file_type"`
|
||||
FileName string `json:"file_name"`
|
||||
FileURL string `json:"file_url"`
|
||||
FileSize uint64 `json:"file_size"`
|
||||
FileExt string `json:"file_ext"`
|
||||
Version string `json:"version"`
|
||||
UploadUserID string `json:"upload_user_id"`
|
||||
UploadUserName string `json:"upload_user_name"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// List GET /backend/crm/bidding/bid-file/list?bid_id=1
|
||||
func (c *BackendCrmBiddingBidFileController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
bidID, _ := c.GetInt64("bid_id")
|
||||
if bidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingBidFile
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidFile)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("bid_id", bidID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Create POST /backend/crm/bidding/bid-file
|
||||
func (c *BackendCrmBiddingBidFileController) 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 bidFilePayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.BidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(p.FileName) == "" || strings.TrimSpace(p.FileURL) == "" {
|
||||
pipelineErr(&c.Controller, 400, 400, "文件信息不完整")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
row := models.TenantCrmBiddingBidFile{
|
||||
TenantID: pipelineTenantID(claims),
|
||||
BidID: p.BidID,
|
||||
FileType: firstNonEmpty(p.FileType, "1"),
|
||||
FileName: strings.TrimSpace(p.FileName),
|
||||
FileURL: strings.TrimSpace(p.FileURL),
|
||||
FileSize: p.FileSize,
|
||||
FileExt: strings.TrimSpace(p.FileExt),
|
||||
Version: firstNonEmpty(p.Version, "1.0"),
|
||||
UploadUserID: firstNonEmpty(p.UploadUserID, pipelineUID(claims)),
|
||||
UploadUserName: firstNonEmpty(p.UploadUserName, resolveUserName(claims)),
|
||||
Remark: p.Remark,
|
||||
CreateTime: now,
|
||||
UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "上传失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "上传投标文件", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Delete DELETE /backend/crm/bidding/bid-file/:id
|
||||
func (c *BackendCrmBiddingBidFileController) 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
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidFile)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
var delRow models.TenantCrmBiddingBidFile
|
||||
_ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidFile)).Filter("id", id).One(&delRow)
|
||||
crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标文件", claims)
|
||||
pipelineOk(&c.Controller, nil)
|
||||
}
|
||||
|
||||
// ------------------------------ 投标任务 ------------------------------
|
||||
|
||||
// BackendCrmBiddingBidTaskController 投标任务
|
||||
type BackendCrmBiddingBidTaskController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type bidTaskPayload struct {
|
||||
BidID uint64 `json:"bid_id"`
|
||||
TaskName string `json:"task_name"`
|
||||
TaskType string `json:"task_type"`
|
||||
Content string `json:"content"`
|
||||
OwnerUserID string `json:"owner_user_id"`
|
||||
OwnerUserName string `json:"owner_user_name"`
|
||||
StartDate string `json:"start_date"`
|
||||
EndDate string `json:"end_date"`
|
||||
Status int8 `json:"status"`
|
||||
Progress int8 `json:"progress"`
|
||||
Files string `json:"files"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// List
|
||||
func (c *BackendCrmBiddingBidTaskController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
bidID, _ := c.GetInt64("bid_id")
|
||||
if bidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingBidTask
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("bid_id", bidID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Create
|
||||
func (c *BackendCrmBiddingBidTaskController) 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 bidTaskPayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.BidID == 0 || strings.TrimSpace(p.TaskName) == "" {
|
||||
pipelineErr(&c.Controller, 400, 400, "任务信息不完整")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
row := models.TenantCrmBiddingBidTask{
|
||||
TenantID: pipelineTenantID(claims),
|
||||
BidID: p.BidID,
|
||||
TaskName: strings.TrimSpace(p.TaskName),
|
||||
TaskType: firstNonEmpty(p.TaskType, "1"),
|
||||
Content: p.Content,
|
||||
OwnerUserID: firstNonEmpty(p.OwnerUserID, pipelineUID(claims)),
|
||||
OwnerUserName: firstNonEmpty(p.OwnerUserName, resolveUserName(claims)),
|
||||
StartDate: parsePipelineDate(p.StartDate),
|
||||
EndDate: parsePipelineDate(p.EndDate),
|
||||
Status: p.Status,
|
||||
Progress: p.Progress,
|
||||
Files: p.Files,
|
||||
Remark: p.Remark,
|
||||
CreateUserID: pipelineUID(claims),
|
||||
CreateUserName: resolveUserName(claims),
|
||||
CreateTime: now,
|
||||
UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "新建投标任务", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Update
|
||||
func (c *BackendCrmBiddingBidTaskController) 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 bidTaskPayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
var row models.TenantCrmBiddingBidTask
|
||||
if err := models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("delete_time__isnull", true).One(&row); err != nil {
|
||||
pipelineErr(&c.Controller, 404, 404, "任务未找到")
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(p.TaskName) != "" {
|
||||
row.TaskName = strings.TrimSpace(p.TaskName)
|
||||
}
|
||||
if strings.TrimSpace(p.TaskType) != "" {
|
||||
row.TaskType = p.TaskType
|
||||
}
|
||||
row.Content = p.Content
|
||||
if strings.TrimSpace(p.OwnerUserID) != "" {
|
||||
row.OwnerUserID = strings.TrimSpace(p.OwnerUserID)
|
||||
row.OwnerUserName = strings.TrimSpace(p.OwnerUserName)
|
||||
}
|
||||
row.StartDate = parsePipelineDate(p.StartDate)
|
||||
row.EndDate = parsePipelineDate(p.EndDate)
|
||||
row.Status = p.Status
|
||||
row.Progress = p.Progress
|
||||
row.Files = p.Files
|
||||
row.Remark = p.Remark
|
||||
row.UpdateTime = time.Now()
|
||||
if _, err := models.Orm.Update(&row); err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "更新失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, row.BidID, "update", "更新投标任务", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": row.ID})
|
||||
}
|
||||
|
||||
// Delete
|
||||
func (c *BackendCrmBiddingBidTaskController) 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
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
var delRow models.TenantCrmBiddingBidTask
|
||||
_ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)).Filter("id", id).One(&delRow)
|
||||
crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标任务", claims)
|
||||
pipelineOk(&c.Controller, nil)
|
||||
}
|
||||
|
||||
// ------------------------------ 投标结果 ------------------------------
|
||||
|
||||
// BackendCrmBiddingBidResultController 投标结果
|
||||
type BackendCrmBiddingBidResultController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// List
|
||||
func (c *BackendCrmBiddingBidResultController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
bidID, _ := c.GetInt64("bid_id")
|
||||
if bidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingBidResult
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidResult)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("bid_id", bidID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Detail
|
||||
func (c *BackendCrmBiddingBidResultController) 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 row models.TenantCrmBiddingBidResult
|
||||
err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidResult)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("delete_time__isnull", true).One(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 404, 404, "投标结果未找到")
|
||||
return
|
||||
}
|
||||
pipelineOk(&c.Controller, row)
|
||||
}
|
||||
|
||||
// ------------------------------ 投标报价 ------------------------------
|
||||
|
||||
// BackendCrmBiddingBidQuoteController 投标报价
|
||||
type BackendCrmBiddingBidQuoteController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type bidQuotePayload struct {
|
||||
BidID uint64 `json:"bid_id"`
|
||||
QuoteName string `json:"quote_name"`
|
||||
TotalAmount float64 `json:"total_amount"`
|
||||
Currency string `json:"currency"`
|
||||
TaxRate float64 `json:"tax_rate"`
|
||||
ValidDate string `json:"valid_date"`
|
||||
Products string `json:"products"`
|
||||
CostAnalysis string `json:"cost_analysis"`
|
||||
ProfitRate float64 `json:"profit_rate"`
|
||||
Status int8 `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// List
|
||||
func (c *BackendCrmBiddingBidQuoteController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
bidID, _ := c.GetInt64("bid_id")
|
||||
if bidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingBidQuote
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidQuote)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("bid_id", bidID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Create
|
||||
func (c *BackendCrmBiddingBidQuoteController) 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 bidQuotePayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.BidID == 0 || strings.TrimSpace(p.QuoteName) == "" {
|
||||
pipelineErr(&c.Controller, 400, 400, "报价信息不完整")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
row := models.TenantCrmBiddingBidQuote{
|
||||
TenantID: pipelineTenantID(claims),
|
||||
BidID: p.BidID,
|
||||
QuoteName: strings.TrimSpace(p.QuoteName),
|
||||
TotalAmount: p.TotalAmount,
|
||||
Currency: firstNonEmpty(p.Currency, "CNY"),
|
||||
TaxRate: p.TaxRate,
|
||||
ValidDate: parsePipelineDate(p.ValidDate),
|
||||
Products: p.Products,
|
||||
CostAnalysis: p.CostAnalysis,
|
||||
ProfitRate: p.ProfitRate,
|
||||
Status: 1,
|
||||
SubmitUserID: pipelineUID(claims),
|
||||
SubmitUserName: resolveUserName(claims),
|
||||
SubmitTime: &now,
|
||||
Remark: p.Remark,
|
||||
CreateTime: now,
|
||||
UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "新建投标报价", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Delete
|
||||
func (c *BackendCrmBiddingBidQuoteController) 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
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidQuote)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
var delRow models.TenantCrmBiddingBidQuote
|
||||
_ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidQuote)).Filter("id", id).One(&delRow)
|
||||
crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标报价", claims)
|
||||
pipelineOk(&c.Controller, nil)
|
||||
}
|
||||
|
||||
// ------------------------------ 投标竞争对手 ------------------------------
|
||||
|
||||
// BackendCrmBiddingBidCompetitorController
|
||||
type BackendCrmBiddingBidCompetitorController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type bidCompetitorPayload struct {
|
||||
BidID uint64 `json:"bid_id"`
|
||||
CompetitorName string `json:"competitor_name"`
|
||||
CompetitorType int8 `json:"competitor_type"`
|
||||
QuoteAmount float64 `json:"quote_amount"`
|
||||
Advantages string `json:"advantages"`
|
||||
Weaknesses string `json:"weaknesses"`
|
||||
Source string `json:"source"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// List
|
||||
func (c *BackendCrmBiddingBidCompetitorController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
bidID, _ := c.GetInt64("bid_id")
|
||||
if bidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingBidCompetitor
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidCompetitor)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("bid_id", bidID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Create
|
||||
func (c *BackendCrmBiddingBidCompetitorController) 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 bidCompetitorPayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.BidID == 0 || strings.TrimSpace(p.CompetitorName) == "" {
|
||||
pipelineErr(&c.Controller, 400, 400, "竞争对手信息不完整")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
row := models.TenantCrmBiddingBidCompetitor{
|
||||
TenantID: pipelineTenantID(claims),
|
||||
BidID: p.BidID,
|
||||
CompetitorName: strings.TrimSpace(p.CompetitorName),
|
||||
CompetitorType: firstNonEmptyInt8(p.CompetitorType, 1),
|
||||
QuoteAmount: p.QuoteAmount,
|
||||
Advantages: p.Advantages,
|
||||
Weaknesses: p.Weaknesses,
|
||||
Source: strings.TrimSpace(p.Source),
|
||||
Remark: p.Remark,
|
||||
CreateUserID: pipelineUID(claims),
|
||||
CreateUserName: resolveUserName(claims),
|
||||
CreateTime: now,
|
||||
UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "新增竞争对手", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Delete
|
||||
func (c *BackendCrmBiddingBidCompetitorController) 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
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidCompetitor)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
var delRow models.TenantCrmBiddingBidCompetitor
|
||||
_ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidCompetitor)).Filter("id", id).One(&delRow)
|
||||
crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除竞争对手", claims)
|
||||
pipelineOk(&c.Controller, nil)
|
||||
}
|
||||
|
||||
// ------------------------------ 投标费用 ------------------------------
|
||||
|
||||
// BackendCrmBiddingBidExpenseController
|
||||
type BackendCrmBiddingBidExpenseController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type bidExpensePayload struct {
|
||||
BidID uint64 `json:"bid_id"`
|
||||
ExpenseType int8 `json:"expense_type"`
|
||||
ExpenseName string `json:"expense_name"`
|
||||
Amount float64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
PaymentStatus int8 `json:"payment_status"`
|
||||
PaymentDate string `json:"payment_date"`
|
||||
Description string `json:"description"`
|
||||
VoucherURL string `json:"voucher_url"`
|
||||
}
|
||||
|
||||
// List
|
||||
func (c *BackendCrmBiddingBidExpenseController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
bidID, _ := c.GetInt64("bid_id")
|
||||
if bidID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "bid_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingBidExpense
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidExpense)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("bid_id", bidID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Create
|
||||
func (c *BackendCrmBiddingBidExpenseController) 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 bidExpensePayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.BidID == 0 || strings.TrimSpace(p.ExpenseName) == "" {
|
||||
pipelineErr(&c.Controller, 400, 400, "费用信息不完整")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
row := models.TenantCrmBiddingBidExpense{
|
||||
TenantID: pipelineTenantID(claims),
|
||||
BidID: p.BidID,
|
||||
ExpenseType: firstNonEmptyInt8(p.ExpenseType, 1),
|
||||
ExpenseName: strings.TrimSpace(p.ExpenseName),
|
||||
Amount: p.Amount,
|
||||
Currency: firstNonEmpty(p.Currency, "CNY"),
|
||||
PaymentStatus: p.PaymentStatus,
|
||||
PaymentDate: parsePipelineDateTime(p.PaymentDate),
|
||||
Description: p.Description,
|
||||
VoucherURL: strings.TrimSpace(p.VoucherURL),
|
||||
CreateUserID: pipelineUID(claims),
|
||||
CreateUserName: resolveUserName(claims),
|
||||
CreateTime: now,
|
||||
UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "登记投标费用", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Delete
|
||||
func (c *BackendCrmBiddingBidExpenseController) 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
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidExpense)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
var delRow models.TenantCrmBiddingBidExpense
|
||||
_ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidExpense)).Filter("id", id).One(&delRow)
|
||||
crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标费用", claims)
|
||||
pipelineOk(&c.Controller, nil)
|
||||
}
|
||||
|
||||
// ------------------------------ 招标文件 ------------------------------
|
||||
|
||||
// BackendCrmBiddingTenderFileController 招标文件
|
||||
type BackendCrmBiddingTenderFileController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type tenderFilePayload struct {
|
||||
TenderID uint64 `json:"tender_id"`
|
||||
FileType string `json:"file_type"`
|
||||
FileName string `json:"file_name"`
|
||||
FileURL string `json:"file_url"`
|
||||
FileSize uint64 `json:"file_size"`
|
||||
FileExt string `json:"file_ext"`
|
||||
UploadUserID string `json:"upload_user_id"`
|
||||
UploadUserName string `json:"upload_user_name"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// List
|
||||
func (c *BackendCrmBiddingTenderFileController) List() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
tenderID, _ := c.GetInt64("tender_id")
|
||||
if tenderID == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "tender_id 必填")
|
||||
return
|
||||
}
|
||||
var list []models.TenantCrmBiddingTenderFile
|
||||
_, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingTenderFile)).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Filter("tender_id", tenderID).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("-id").All(&list)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"list": list})
|
||||
}
|
||||
|
||||
// Create
|
||||
func (c *BackendCrmBiddingTenderFileController) 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 tenderFilePayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.TenderID == 0 || strings.TrimSpace(p.FileName) == "" || strings.TrimSpace(p.FileURL) == "" {
|
||||
pipelineErr(&c.Controller, 400, 400, "文件信息不完整")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
row := models.TenantCrmBiddingTenderFile{
|
||||
TenantID: pipelineTenantID(claims),
|
||||
TenderID: p.TenderID,
|
||||
FileType: firstNonEmpty(p.FileType, "1"),
|
||||
FileName: strings.TrimSpace(p.FileName),
|
||||
FileURL: strings.TrimSpace(p.FileURL),
|
||||
FileSize: p.FileSize,
|
||||
FileExt: strings.TrimSpace(p.FileExt),
|
||||
UploadUserID: firstNonEmpty(p.UploadUserID, pipelineUID(claims)),
|
||||
UploadUserName: firstNonEmpty(p.UploadUserName, resolveUserName(claims)),
|
||||
Remark: p.Remark,
|
||||
CreateTime: now,
|
||||
UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "上传失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(pipelineTenantID(claims), 5, p.TenderID, "create", "上传招标文件", claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Delete
|
||||
func (c *BackendCrmBiddingTenderFileController) 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
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.TenantCrmBiddingTenderFile)).
|
||||
Filter("id", id).
|
||||
Filter("tenant_id", pipelineTenantID(claims)).
|
||||
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
||||
if err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
var delRow models.TenantCrmBiddingTenderFile
|
||||
_ = models.Orm.QueryTable(new(models.TenantCrmBiddingTenderFile)).Filter("id", id).One(&delRow)
|
||||
crmWriteLog(pipelineTenantID(claims), 5, delRow.TenderID, "delete", "删除招标文件", claims)
|
||||
pipelineOk(&c.Controller, nil)
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// 工具函数
|
||||
// =====================================================================
|
||||
|
||||
// firstNonEmptyInt8 返回第一个非零的 int8
|
||||
func firstNonEmptyInt8(v, def int8) int8 {
|
||||
if v == 0 {
|
||||
return def
|
||||
}
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user