更新
This commit is contained in:
1 parent
5718a00e31
commit
1850ac640e
226 files changed
+37772
-12071
No files matched your search
@@ -0,0 +1,529 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
erp "server/services/erp"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
// ERP 往来账/收付款核心(两端共用):/backend/erp/finance* 与 /api/erp/finance* 都调这里,
|
||||
// 未收未付、账龄、核销余额等口径只算一次,手机端不会看到与 Web 端不一致的应收应付。
|
||||
|
||||
// erpBillFilter 往来账查询条件
|
||||
type erpBillFilter struct {
|
||||
BillType string
|
||||
PartnerID uint64
|
||||
PartnerType string
|
||||
SourceDocID uint64
|
||||
SettleState string // open|part|done
|
||||
Keyword string
|
||||
DateFrom string
|
||||
DateTo string
|
||||
}
|
||||
|
||||
// erpBillListCore 往来账列表 + 未结余额合计
|
||||
func erpBillListCore(a erpActor, f erpBillFilter, page, pageSize int) ([]map[string]interface{}, int64, map[string]float64, int, string) {
|
||||
qs := models.Orm.QueryTable(new(models.ErpPartnerBill)).Filter("tenant_id", a.Tid)
|
||||
if f.BillType != "" {
|
||||
qs = qs.Filter("bill_type", f.BillType)
|
||||
}
|
||||
if f.PartnerID > 0 {
|
||||
qs = qs.Filter("partner_id", f.PartnerID)
|
||||
}
|
||||
if f.PartnerType != "" {
|
||||
qs = qs.Filter("partner_type", f.PartnerType)
|
||||
}
|
||||
if f.SourceDocID > 0 {
|
||||
qs = qs.Filter("source_doc_id", f.SourceDocID)
|
||||
}
|
||||
switch f.SettleState {
|
||||
case "open":
|
||||
qs = qs.Filter("status__lt", 2)
|
||||
case "part":
|
||||
qs = qs.Filter("status", 1)
|
||||
case "done":
|
||||
qs = qs.Filter("status", 2)
|
||||
}
|
||||
if f.Keyword != "" {
|
||||
cond := orm.NewCondition().
|
||||
Or("partner_name__contains", f.Keyword).
|
||||
Or("source_doc_no__contains", f.Keyword)
|
||||
qs = qs.SetCond(qs.GetCond().AndCond(cond))
|
||||
}
|
||||
for _, d := range []struct {
|
||||
raw string
|
||||
cond string
|
||||
}{{f.DateFrom, "bill_date__gte"}, {f.DateTo, "bill_date__lte"}} {
|
||||
if strings.TrimSpace(d.raw) == "" {
|
||||
continue
|
||||
}
|
||||
if t, e := time.ParseInLocation("2006-01-02", strings.TrimSpace(d.raw), time.Local); e == nil {
|
||||
qs = qs.Filter(d.cond, t)
|
||||
}
|
||||
}
|
||||
|
||||
total, _ := qs.Count()
|
||||
var rows []models.ErpPartnerBill
|
||||
if _, err := qs.OrderBy("-bill_date", "-id").Limit(pageSize, (page-1)*pageSize).All(&rows); err != nil {
|
||||
return nil, 0, nil, 500, "查询失败: " + err.Error()
|
||||
}
|
||||
// 摘要区合计:未收/未付总额与本页余额
|
||||
var openRecv, openPay float64
|
||||
var allRows []models.ErpPartnerBill
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpPartnerBill)).
|
||||
Filter("tenant_id", a.Tid).Filter("status__lt", 2).
|
||||
All(&allRows, "bill_type", "amount", "settled_amount")
|
||||
for _, b := range allRows {
|
||||
bal := b.Amount - b.SettledAmount
|
||||
if b.BillType == models.ErpBillReceivable {
|
||||
openRecv += bal
|
||||
} else {
|
||||
openPay += bal
|
||||
}
|
||||
}
|
||||
out := make([]map[string]interface{}, 0, len(rows))
|
||||
now := time.Now()
|
||||
for _, b := range rows {
|
||||
bal := round2f(b.Amount - b.SettledAmount)
|
||||
overdue := 0
|
||||
if b.DueDate != nil && b.Status < 2 {
|
||||
d := int(b.DueDate.Sub(now).Hours() / 24)
|
||||
if d < 0 {
|
||||
overdue = -d
|
||||
}
|
||||
}
|
||||
out = append(out, map[string]interface{}{
|
||||
"bill": b, "balance": bal, "overdue_days": overdue,
|
||||
"status_label": erpBillStatusLabel(b.Status),
|
||||
})
|
||||
}
|
||||
return out, total, map[string]float64{
|
||||
"open_receivable": round2f(openRecv), "open_payable": round2f(openPay),
|
||||
}, 200, ""
|
||||
}
|
||||
|
||||
// erpBillDetailCore 往来账详情(含核销记录与原单据)
|
||||
func erpBillDetailCore(a erpActor, id uint64) (map[string]interface{}, int, string) {
|
||||
if id == 0 {
|
||||
return nil, 400, "无效的ID"
|
||||
}
|
||||
var bill models.ErpPartnerBill
|
||||
if err := models.Orm.QueryTable(new(models.ErpPartnerBill)).
|
||||
Filter("id", id).Filter("tenant_id", a.Tid).One(&bill); err != nil {
|
||||
return nil, 404, "往来账未找到"
|
||||
}
|
||||
var settles []models.ErpFundSettle
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpFundSettle)).
|
||||
Filter("tenant_id", a.Tid).Filter("partner_bill_id", id).OrderBy("-id").All(&settles)
|
||||
fundIDs := make([]uint64, 0, len(settles))
|
||||
for _, s := range settles {
|
||||
fundIDs = append(fundIDs, s.FundBillID)
|
||||
}
|
||||
fundMap := map[uint64]models.ErpFundBill{}
|
||||
if len(fundIDs) > 0 {
|
||||
var funds []models.ErpFundBill
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpFundBill)).
|
||||
Filter("id__in", fundIDs).All(&funds, "id", "fund_no", "fund_type", "biz_date", "pay_method")
|
||||
for _, fn := range funds {
|
||||
fundMap[fn.ID] = fn
|
||||
}
|
||||
}
|
||||
items := erpDocItems(models.Orm, bill.SourceDocID)
|
||||
return map[string]interface{}{
|
||||
"bill": bill,
|
||||
"balance": round2f(bill.Amount - bill.SettledAmount),
|
||||
"settles": settles,
|
||||
"funds": fundMap,
|
||||
"doc_items": items,
|
||||
}, 200, ""
|
||||
}
|
||||
|
||||
// erpPartnerAging 单个往来单位的账龄分布
|
||||
type erpPartnerAging struct {
|
||||
PartnerID uint64 `json:"partner_id"`
|
||||
PartnerName string `json:"partner_name"`
|
||||
BillType int8 `json:"bill_type"`
|
||||
Total float64 `json:"total"`
|
||||
Buckets map[string]float64 `json:"buckets"`
|
||||
}
|
||||
|
||||
// erpAgingCore 账龄分析(按未结余额分桶)
|
||||
func erpAgingCore(a erpActor) (map[string]interface{}, int, string) {
|
||||
buckets := []struct {
|
||||
Label string `json:"label"`
|
||||
Min int `json:"min"`
|
||||
Max int `json:"max"`
|
||||
}{
|
||||
{"未到期", -99999, 0}, {"1-30天", 1, 30}, {"31-60天", 31, 60},
|
||||
{"61-90天", 61, 90}, {"90天以上", 91, 99999},
|
||||
}
|
||||
agg := map[string]*erpPartnerAging{}
|
||||
var bills []models.ErpPartnerBill
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpPartnerBill)).
|
||||
Filter("tenant_id", a.Tid).Filter("status__lt", 2).
|
||||
All(&bills, "partner_id", "partner_name", "bill_type", "amount", "settled_amount", "due_date", "bill_date")
|
||||
now := time.Now()
|
||||
sum := map[string]map[string]float64{}
|
||||
for _, b := range bills {
|
||||
// 分组必须带上 bill_type:同一客商既挂应收又挂应付时,只按 partner 归并
|
||||
// 会把两种账期混进行里,导致 list 合计与 summary(按单据类型分)对不上。
|
||||
key := b.PartnerType + ":" + fmt.Sprintf("%d:%d", b.PartnerID, b.BillType)
|
||||
pa := agg[key]
|
||||
if pa == nil {
|
||||
pa = &erpPartnerAging{
|
||||
PartnerID: b.PartnerID, PartnerName: b.PartnerName, BillType: b.BillType,
|
||||
Buckets: map[string]float64{},
|
||||
}
|
||||
agg[key] = pa
|
||||
}
|
||||
ref := b.DueDate
|
||||
if ref == nil {
|
||||
ref = &b.BillDate
|
||||
}
|
||||
days := int(now.Sub(*ref).Hours() / 24)
|
||||
label := buckets[0].Label
|
||||
for _, bk := range buckets {
|
||||
if days >= bk.Min && days <= bk.Max {
|
||||
label = bk.Label
|
||||
break
|
||||
}
|
||||
}
|
||||
bal := round2f(b.Amount - b.SettledAmount)
|
||||
pa.Total = round2f(pa.Total + bal)
|
||||
pa.Buckets[label] = round2f(pa.Buckets[label] + bal)
|
||||
bt := "receivable"
|
||||
if b.BillType == models.ErpBillPayable {
|
||||
bt = "payable"
|
||||
}
|
||||
if sum[bt] == nil {
|
||||
sum[bt] = map[string]float64{}
|
||||
}
|
||||
sum[bt][label] = round2f(sum[bt][label] + bal)
|
||||
}
|
||||
list := make([]*erpPartnerAging, 0, len(agg))
|
||||
for _, pa := range agg {
|
||||
list = append(list, pa)
|
||||
}
|
||||
return map[string]interface{}{"list": list, "summary": sum, "buckets": buckets}, 200, ""
|
||||
}
|
||||
|
||||
// erpFundFilter 收付款单查询条件
|
||||
type erpFundFilter struct {
|
||||
FundType string
|
||||
Status string
|
||||
PartnerID uint64
|
||||
Keyword string
|
||||
DateFrom string
|
||||
DateTo string
|
||||
}
|
||||
|
||||
// erpFundListCore 收付款单列表
|
||||
func erpFundListCore(a erpActor, f erpFundFilter, page, pageSize int) ([]models.ErpFundBill, int64, int, string) {
|
||||
qs := models.Orm.QueryTable(new(models.ErpFundBill)).
|
||||
Filter("tenant_id", a.Tid).Filter("delete_time__isnull", true)
|
||||
if f.FundType != "" {
|
||||
qs = qs.Filter("fund_type", f.FundType)
|
||||
}
|
||||
if f.Status != "" {
|
||||
qs = qs.Filter("status", f.Status)
|
||||
}
|
||||
if f.PartnerID > 0 {
|
||||
qs = qs.Filter("partner_id", f.PartnerID)
|
||||
}
|
||||
if f.Keyword != "" {
|
||||
cond := orm.NewCondition().
|
||||
Or("fund_no__contains", f.Keyword).
|
||||
Or("partner_name__contains", f.Keyword)
|
||||
qs = qs.SetCond(qs.GetCond().AndCond(cond))
|
||||
}
|
||||
for _, d := range []struct {
|
||||
raw string
|
||||
cond string
|
||||
}{{f.DateFrom, "biz_date__gte"}, {f.DateTo, "biz_date__lte"}} {
|
||||
if strings.TrimSpace(d.raw) == "" {
|
||||
continue
|
||||
}
|
||||
if t, e := time.ParseInLocation("2006-01-02", strings.TrimSpace(d.raw), time.Local); e == nil {
|
||||
qs = qs.Filter(d.cond, t)
|
||||
}
|
||||
}
|
||||
total, _ := qs.Count()
|
||||
var rows []models.ErpFundBill
|
||||
if _, err := qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&rows); err != nil {
|
||||
return nil, 0, 500, "查询失败: " + err.Error()
|
||||
}
|
||||
return rows, total, 200, ""
|
||||
}
|
||||
|
||||
// erpFundDetailCore 收付款单详情(含核销明细与对应往来账)
|
||||
func erpFundDetailCore(a erpActor, id uint64) (map[string]interface{}, int, string) {
|
||||
if id == 0 {
|
||||
return nil, 400, "无效的ID"
|
||||
}
|
||||
var fund models.ErpFundBill
|
||||
if err := models.Orm.QueryTable(new(models.ErpFundBill)).
|
||||
Filter("id", id).Filter("tenant_id", a.Tid).
|
||||
Filter("delete_time__isnull", true).One(&fund); err != nil {
|
||||
return nil, 404, "收付款单未找到"
|
||||
}
|
||||
var settles []models.ErpFundSettle
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpFundSettle)).
|
||||
Filter("fund_bill_id", id).OrderBy("id").All(&settles)
|
||||
billIDs := make([]uint64, 0, len(settles))
|
||||
for _, s := range settles {
|
||||
billIDs = append(billIDs, s.PartnerBillID)
|
||||
}
|
||||
bills := []models.ErpPartnerBill{}
|
||||
if len(billIDs) > 0 {
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpPartnerBill)).
|
||||
Filter("id__in", billIDs).All(&bills)
|
||||
}
|
||||
fund.Settles = settles
|
||||
return map[string]interface{}{"fund": fund, "bills": bills}, 200, ""
|
||||
}
|
||||
|
||||
// erpFundSaveCore 新建/修改收付款草稿(草稿态才可改,确认后只能作废重开)
|
||||
func erpFundSaveCore(a erpActor, p erpFundPayload) (uint64, string, int, string) {
|
||||
tid := a.Tid
|
||||
if p.FundType < models.ErpFundReceive || p.FundType > models.ErpFundExpense {
|
||||
return 0, "", 400, "收付款方式无效"
|
||||
}
|
||||
if p.Amount <= 0 {
|
||||
return 0, "", 400, "金额必须大于0"
|
||||
}
|
||||
if (p.FundType == models.ErpFundReceive || p.FundType == models.ErpFundPay) && p.PartnerID == 0 {
|
||||
return 0, "", 400, "收款/付款必须选择往来单位"
|
||||
}
|
||||
partnerType := ""
|
||||
if p.FundType == models.ErpFundReceive {
|
||||
partnerType = "customer"
|
||||
} else if p.FundType == models.ErpFundPay {
|
||||
partnerType = "supplier"
|
||||
}
|
||||
name := erpPartnerName(partnerType, p.PartnerID)
|
||||
if p.PartnerID > 0 && name == "" {
|
||||
return 0, "", 400, erpPartnerLabel(partnerType) + "不存在"
|
||||
}
|
||||
bizDate := time.Now()
|
||||
if p.BizDate != "" {
|
||||
if t, e := time.ParseInLocation("2006-01-02", p.BizDate, time.Local); e == nil {
|
||||
bizDate = t
|
||||
}
|
||||
}
|
||||
method := strings.TrimSpace(p.PayMethod)
|
||||
if method == "" {
|
||||
method = "cash"
|
||||
}
|
||||
now := time.Now()
|
||||
if p.ID > 0 {
|
||||
var fund models.ErpFundBill
|
||||
if err := models.Orm.QueryTable(new(models.ErpFundBill)).
|
||||
Filter("id", p.ID).Filter("tenant_id", tid).
|
||||
Filter("delete_time__isnull", true).One(&fund); err != nil {
|
||||
return 0, "", 404, "收付款单未找到"
|
||||
}
|
||||
if fund.Status != 0 {
|
||||
return 0, "", 400, "已确认的收付款单不可修改"
|
||||
}
|
||||
if _, err := models.Orm.QueryTable(new(models.ErpFundBill)).Filter("id", p.ID).
|
||||
Update(orm.Params{
|
||||
"fund_type": p.FundType, "partner_type": partnerType, "partner_id": p.PartnerID,
|
||||
"partner_name": name, "amount": p.Amount, "pay_method": method,
|
||||
"pay_account": p.PayAccount, "biz_date": bizDate, "remark": p.Remark,
|
||||
"update_time": now,
|
||||
}); err != nil {
|
||||
return 0, "", 500, "保存失败: " + err.Error()
|
||||
}
|
||||
return p.ID, fund.FundNo, 200, ""
|
||||
}
|
||||
no, e := erp.GenerateFundNo(tid, p.FundType)
|
||||
if e != nil {
|
||||
return 0, "", 500, e.Error()
|
||||
}
|
||||
fund := models.ErpFundBill{
|
||||
TenantID: tid, FundNo: no, FundType: p.FundType,
|
||||
PartnerType: partnerType, PartnerID: p.PartnerID, PartnerName: name,
|
||||
Amount: p.Amount, PayMethod: method, PayAccount: p.PayAccount,
|
||||
BizDate: bizDate, Status: 0, Remark: p.Remark,
|
||||
CreateUserID: fmt.Sprintf("%d", a.UID), CreateUserName: a.Name,
|
||||
CreateTime: now, UpdateTime: now,
|
||||
}
|
||||
id, err := models.Orm.Insert(&fund)
|
||||
if err != nil {
|
||||
return 0, "", 500, "创建失败: " + err.Error()
|
||||
}
|
||||
return uint64(id), no, 200, ""
|
||||
}
|
||||
|
||||
// erpFundConfirmCore 确认收付款并核销;settles 为空时按到期日自动 FIFO
|
||||
func erpFundConfirmCore(a erpActor, id uint64, settles []erp.SettleItem) (int, string) {
|
||||
if id == 0 {
|
||||
return 400, "无效的ID"
|
||||
}
|
||||
if err := erp.ConfirmFundBill(id, a.Tid, settles, a.Name); err != nil {
|
||||
return 400, err.Error()
|
||||
}
|
||||
return 200, ""
|
||||
}
|
||||
|
||||
// erpFundVoidCore 作废收付款单(已核销的往来账余额同步回滚)
|
||||
func erpFundVoidCore(a erpActor, id uint64) (int, string) {
|
||||
if id == 0 {
|
||||
return 400, "无效的ID"
|
||||
}
|
||||
if err := erp.VoidFundBill(id, a.Tid); err != nil {
|
||||
return 400, err.Error()
|
||||
}
|
||||
return 200, ""
|
||||
}
|
||||
|
||||
// erpFundDeleteCore 删除收付款单,仅草稿可删
|
||||
func erpFundDeleteCore(a erpActor, id uint64) (int, string) {
|
||||
if id == 0 {
|
||||
return 400, "无效的ID"
|
||||
}
|
||||
var fund models.ErpFundBill
|
||||
if err := models.Orm.QueryTable(new(models.ErpFundBill)).
|
||||
Filter("id", id).Filter("tenant_id", a.Tid).
|
||||
Filter("delete_time__isnull", true).One(&fund); err != nil {
|
||||
return 404, "收付款单未找到"
|
||||
}
|
||||
if fund.Status != 0 {
|
||||
return 400, "只有草稿状态的收付款单可以删除"
|
||||
}
|
||||
now := time.Now()
|
||||
if _, err := models.Orm.QueryTable(new(models.ErpFundBill)).Filter("id", id).
|
||||
Update(orm.Params{"delete_time": now, "update_time": now}); err != nil {
|
||||
return 500, "删除失败: " + err.Error()
|
||||
}
|
||||
return 200, ""
|
||||
}
|
||||
|
||||
// erpFundOpenBillsCore 收款/付款时可核销的往来账(前端据此勾选)
|
||||
func erpFundOpenBillsCore(a erpActor, fundType int8, partnerID uint64) ([]map[string]interface{}, int, string) {
|
||||
billType := int8(models.ErpBillReceivable)
|
||||
if fundType == 2 {
|
||||
billType = models.ErpBillPayable
|
||||
}
|
||||
qs := models.Orm.QueryTable(new(models.ErpPartnerBill)).
|
||||
Filter("tenant_id", a.Tid).Filter("bill_type", billType).
|
||||
Filter("status__lt", 2).Filter("amount__gt", 0)
|
||||
if partnerID > 0 {
|
||||
qs = qs.Filter("partner_id", partnerID)
|
||||
}
|
||||
var rows []models.ErpPartnerBill
|
||||
_, _ = qs.OrderBy("due_date", "bill_date", "id").Limit(200).All(&rows)
|
||||
out := make([]map[string]interface{}, 0, len(rows))
|
||||
for _, b := range rows {
|
||||
out = append(out, map[string]interface{}{
|
||||
"id": b.ID, "source_doc_no": b.SourceDocNo, "bill_date": b.BillDate,
|
||||
"due_date": b.DueDate, "amount": b.Amount, "settled_amount": b.SettledAmount,
|
||||
"balance": round2f(b.Amount - b.SettledAmount), "partner_name": b.PartnerName,
|
||||
})
|
||||
}
|
||||
return out, 200, ""
|
||||
}
|
||||
|
||||
// erpCashDayRow 按日汇总的资金流水
|
||||
type erpCashDayRow struct {
|
||||
Date string `json:"date"`
|
||||
In float64 `json:"in"`
|
||||
Out float64 `json:"out"`
|
||||
Net float64 `json:"net"`
|
||||
}
|
||||
|
||||
// erpCashFlowCore 资金流水(只统计实际收付,不含单据生成的往来账)
|
||||
func erpCashFlowCore(a erpActor, from, to time.Time) (map[string]interface{}, int, string) {
|
||||
var rows []models.ErpFundBill
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpFundBill)).
|
||||
Filter("tenant_id", a.Tid).Filter("status", 1).
|
||||
Filter("biz_date__gte", from).Filter("biz_date__lte", to).
|
||||
OrderBy("biz_date", "id").All(&rows)
|
||||
|
||||
days := map[string]*erpCashDayRow{}
|
||||
var totalIn, totalOut float64
|
||||
for _, f := range rows {
|
||||
d := f.BizDate.Format("2006-01-02")
|
||||
if days[d] == nil {
|
||||
days[d] = &erpCashDayRow{Date: d}
|
||||
}
|
||||
if f.FundType == models.ErpFundReceive || f.FundType == models.ErpFundOtherIn {
|
||||
days[d].In = round2f(days[d].In + f.Amount)
|
||||
totalIn += f.Amount
|
||||
} else {
|
||||
days[d].Out = round2f(days[d].Out + f.Amount)
|
||||
totalOut += f.Amount
|
||||
}
|
||||
}
|
||||
list := make([]*erpCashDayRow, 0, len(days))
|
||||
keys := make([]string, 0, len(days))
|
||||
for k := range days {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
r := days[k]
|
||||
r.Net = round2f(r.In - r.Out)
|
||||
list = append(list, r)
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"list": list, "total_in": round2f(totalIn), "total_out": round2f(totalOut),
|
||||
"net": round2f(totalIn - totalOut),
|
||||
}, 200, ""
|
||||
}
|
||||
|
||||
// erpPartnerSumRow 往来单位对账汇总行
|
||||
type erpPartnerSumRow struct {
|
||||
PartnerID uint64 `json:"partner_id"`
|
||||
PartnerType string `json:"partner_type"`
|
||||
PartnerName string `json:"partner_name"`
|
||||
RecvTotal float64 `json:"recv_total"`
|
||||
RecvOpen float64 `json:"recv_open"`
|
||||
PayTotal float64 `json:"pay_total"`
|
||||
PayOpen float64 `json:"pay_open"`
|
||||
LastBillDate string `json:"last_bill_date"`
|
||||
}
|
||||
|
||||
// erpPartnerSummaryCore 往来单位对账汇总(partnerType 为空=不限)
|
||||
func erpPartnerSummaryCore(a erpActor, partnerType string) (map[string]interface{}, int, string) {
|
||||
var bills []models.ErpPartnerBill
|
||||
_, _ = models.Orm.QueryTable(new(models.ErpPartnerBill)).
|
||||
Filter("tenant_id", a.Tid).All(&bills)
|
||||
m := map[string]*erpPartnerSumRow{}
|
||||
for _, b := range bills {
|
||||
k := b.PartnerType + ":" + fmt.Sprintf("%d", b.PartnerID)
|
||||
r := m[k]
|
||||
if r == nil {
|
||||
r = &erpPartnerSumRow{PartnerID: b.PartnerID, PartnerType: b.PartnerType, PartnerName: b.PartnerName}
|
||||
m[k] = r
|
||||
}
|
||||
if b.BillDate.Format("2006-01-02") > r.LastBillDate {
|
||||
r.LastBillDate = b.BillDate.Format("2006-01-02")
|
||||
}
|
||||
if b.BillType == models.ErpBillReceivable {
|
||||
r.RecvTotal = round2f(r.RecvTotal + b.Amount)
|
||||
if b.Status < 2 {
|
||||
r.RecvOpen = round2f(r.RecvOpen + b.Amount - b.SettledAmount)
|
||||
}
|
||||
} else {
|
||||
r.PayTotal = round2f(r.PayTotal + b.Amount)
|
||||
if b.Status < 2 {
|
||||
r.PayOpen = round2f(r.PayOpen + b.Amount - b.SettledAmount)
|
||||
}
|
||||
}
|
||||
}
|
||||
list := make([]*erpPartnerSumRow, 0, len(m))
|
||||
for _, r := range m {
|
||||
if partnerType != "" && r.PartnerType != partnerType {
|
||||
continue
|
||||
}
|
||||
list = append(list, r)
|
||||
}
|
||||
return map[string]interface{}{"list": list}, 200, ""
|
||||
}
|
||||
Reference in new issue
Block a user