Files
yunzerwebsiteallinone/go/controllers/backend_crm_bidding_sub.go
T
2026-09-24 17:06:46 +08:00

812 lines
26 KiB
Go

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
}