Files
agent-bot 8c2dd49e80
CI / go-vet (pull_request) Successful in 14s
CI / short-tests-report (pull_request) Failing after 35s
CI / backup-restore-drill (pull_request) Successful in 33s
CI / web (pull_request) Successful in 32s
refactor(squad): quote preparation moves to Core via TaskPreparer hook
KTD1 fourth step:
- squad.Options.TaskPreparer + TaskPreparation (Attachment + Backfills +
  MirrorTemplateToOutput); squad stays sole writer of its workspace files
- CDO quote calc/xlsx/backfill implementation moves to bizdev
  (quote_preparer.go); squad/quote_backfill.go relocated to bizdev
- arch path rule enforced the boundary: bizdev may not name/write
  output.md; mirroring decided squad-side via flag
- squad -> quote import eliminated; engine.go delegations now local
- verified: build/vet/arch green, squad+bizdev short tests pass
2026-09-29 06:16:19 +00:00

84 lines
2.6 KiB
Go

package bizdev
import (
"fmt"
"strconv"
"strings"
"chat-agent-system/internal/quote"
)
// FormatMoney 格式化金额用于 Markdown 表格展示
func FormatMoney(v float64) string {
if v == 0 {
return "0"
}
if v == float64(int64(v)) {
return strconv.FormatInt(int64(v), 10)
}
return strconv.FormatFloat(v, 'f', 2, 64)
}
// RenderCDOQuoteTable 将 quote.Summary 转换为标准 Markdown 表格
func RenderCDOQuoteTable(summary *quote.Summary) string {
var b strings.Builder
b.WriteString("| 报价代码 | 服务内容 | 人数 | 人年 | 成本 | 加Buffer20% | 加毛利40% | 加税7% | 设备设施等费用 | 税后价格 |\n")
b.WriteString("|---|---|---:|---:|---:|---:|---:|---:|---:|---:|\n")
var totalPersonYear, totalCost, totalBuffer, totalMargin, totalTax float64
for _, line := range summary.Lines {
fmt.Fprintf(&b, "| %s | %s | — | %s | %s | %s | %s | %s | — | %s |\n",
line.Code, line.Name,
FormatMoney(line.PersonYear),
FormatMoney(line.Cost),
FormatMoney(line.Buffer),
FormatMoney(line.Margin),
FormatMoney(line.Tax),
FormatMoney(line.Price),
)
totalPersonYear += line.PersonYear
totalCost += line.Cost
totalBuffer += line.Buffer
totalMargin += line.Margin
totalTax += line.Tax
}
fmt.Fprintf(&b, "| | **总计** | — | **%s** | **%s** | **%s** | **%s** | **%s** | — | **%s** |\n",
FormatMoney(totalPersonYear),
FormatMoney(totalCost),
FormatMoney(totalBuffer),
FormatMoney(totalMargin),
FormatMoney(totalTax),
FormatMoney(summary.TotalPrice),
)
return b.String()
}
// BackfillCDOQuoteMarkdown 将计算结果回填到 cdo_quote 模板中
func BackfillCDOQuoteMarkdown(body string, summary *quote.Summary) string {
conclusion := fmt.Sprintf(
"按公司 CDO 定价核算模板计算,税后合计 **%s 元**(含 Buffer 20%%、毛利 40%%、税 7%%)。数字与配套 Excel「报价模型」一致。",
FormatMoney(summary.TotalPrice),
)
body = replaceSection(body, "## 结论", conclusion)
tableIntro := "表中「人年」列与 Excel 模板同一列,对应模型投入人月合计(工时/160)。\n\n"
body = replaceSection(body, "## 报价模型", tableIntro+RenderCDOQuoteTable(summary))
return body
}
func replaceSection(body, heading, content string) string {
start := strings.Index(body, heading)
if start == -1 {
return body
}
rest := body[start+len(heading):]
nextHeading := strings.Index(rest, "\n## ")
if nextHeading == -1 {
return body[:start] + heading + "\n\n" + content + "\n"
}
end := start + len(heading) + nextHeading
return body[:start] + heading + "\n\n" + content + "\n" + body[end:]
}