Files
zsp-project/backend/internal/service/zsp_finances_service.go
2026-06-03 20:59:39 +08:00

336 lines
10 KiB
Go
Executable File

package service
import (
"time"
"github.com/rovina/zsp-backend/internal/dto"
"github.com/rovina/zsp-backend/internal/model"
"github.com/rovina/zsp-backend/internal/repository"
"gorm.io/gorm"
)
type ZSPFinancesService interface {
CreateFreightCharge(req *dto.ZSPFreightChargesCreateRequest) error
GetFreightCharge(id string) (*model.ZSPFreightCharges, error)
ListFreightCharges() ([]model.ZSPFreightCharges, error)
UpdateFreightCharge(id string, req *dto.ZSPFreightChargesUpdateRequest) error
DeleteFreightCharge(id string) error
CreateMiscCharge(req *dto.ZSPMiscChargesCreateRequest) error
GetMiscCharge(id string) (*model.ZSPMiscCharges, error)
ListMiscCharges() ([]model.ZSPMiscCharges, error)
UpdateMiscCharge(id string, req *dto.ZSPMiscChargesUpdateRequest) error
DeleteMiscCharge(id string) error
CreateServiceFee(req *dto.ZSPServiceFeesCreateRequest) error
GetServiceFee(id string) (*model.ZSPServiceFees, error)
ListServiceFees() ([]model.ZSPServiceFees, error)
UpdateServiceFee(id string, req *dto.ZSPServiceFeesUpdateRequest) error
DeleteServiceFee(id string) error
CreateCostBreakdown(req *dto.ZSPCostBreakdownCreateRequest) error
GetCostBreakdown(id string) (*model.ZSPCostBreakdown, error)
ListCostBreakdowns(businessID string) ([]model.ZSPCostBreakdown, error)
UpdateCostBreakdown(id string, req *dto.ZSPCostBreakdownUpdateRequest) error
DeleteCostBreakdown(id string) error
CreateProfitRecord(req *dto.ZSPProfitRecordCreateRequest) error
GetProfitRecord(id string) (*model.ZSPProfitRecord, error)
ListProfitRecords(filters map[string]string) ([]model.ZSPProfitRecord, error)
UpdateProfitRecord(id string, req *dto.ZSPProfitRecordUpdateRequest) error
DeleteProfitRecord(id string) error
}
type zspFinancesService struct {
repo repository.ZSPFinancesRepository
}
func NewZSPFinancesService(db *gorm.DB) ZSPFinancesService {
return &zspFinancesService{repo: repository.NewZSPFinancesRepository(db)}
}
// ============ 货代费用 ============
func (s *zspFinancesService) CreateFreightCharge(req *dto.ZSPFreightChargesCreateRequest) error {
currency := req.Currency
if currency == "" {
currency = "CNY"
}
charge := model.ZSPFreightCharges{
BillOfLading: req.BillOfLading,
ContractNumber: req.ContractNumber,
ExpenseItem: req.ExpenseItem,
Amount: req.Amount,
Currency: currency,
PaymentDate: parseDate(req.PaymentDate),
FreightCompanyName: req.FreightCompanyName,
Remark: req.Remark,
CreateTime: time.Now(),
UpdateTime: time.Now(),
}
return s.repo.CreateFreightCharge(&charge)
}
func (s *zspFinancesService) GetFreightCharge(id string) (*model.ZSPFreightCharges, error) {
return s.repo.GetFreightCharge(id)
}
func (s *zspFinancesService) ListFreightCharges() ([]model.ZSPFreightCharges, error) {
return s.repo.ListFreightCharges()
}
func (s *zspFinancesService) UpdateFreightCharge(id string, req *dto.ZSPFreightChargesUpdateRequest) error {
charge, err := s.repo.GetFreightCharge(id)
if err != nil {
return err
}
if req.BillOfLading != "" {
charge.BillOfLading = req.BillOfLading
}
if req.ContractNumber != "" {
charge.ContractNumber = req.ContractNumber
}
if req.ExpenseItem != "" {
charge.ExpenseItem = req.ExpenseItem
}
if req.Amount != 0 {
charge.Amount = req.Amount
}
if req.Currency != "" {
charge.Currency = req.Currency
}
if req.PaymentDate != "" {
charge.PaymentDate = parseDate(req.PaymentDate)
}
if req.FreightCompanyName != "" {
charge.FreightCompanyName = req.FreightCompanyName
}
charge.Remark = req.Remark
charge.UpdateTime = time.Now()
return s.repo.UpdateFreightCharge(charge)
}
func (s *zspFinancesService) DeleteFreightCharge(id string) error {
return s.repo.DeleteFreightCharge(id)
}
// ============ 杂费 ============
func (s *zspFinancesService) CreateMiscCharge(req *dto.ZSPMiscChargesCreateRequest) error {
currency := req.Currency
if currency == "" {
currency = "CNY"
}
charge := model.ZSPMiscCharges{
BillOfLading: req.BillOfLading,
ContractNumber: req.ContractNumber,
ExpenseItem: req.ExpenseItem,
Amount: req.Amount,
Currency: currency,
PaymentDate: parseDate(req.PaymentDate),
CompanyName: req.CompanyName,
Remark: req.Remark,
CreateTime: time.Now(),
UpdateTime: time.Now(),
}
return s.repo.CreateMiscCharge(&charge)
}
func (s *zspFinancesService) GetMiscCharge(id string) (*model.ZSPMiscCharges, error) {
return s.repo.GetMiscCharge(id)
}
func (s *zspFinancesService) ListMiscCharges() ([]model.ZSPMiscCharges, error) {
return s.repo.ListMiscCharges()
}
func (s *zspFinancesService) UpdateMiscCharge(id string, req *dto.ZSPMiscChargesUpdateRequest) error {
charge, err := s.repo.GetMiscCharge(id)
if err != nil {
return err
}
if req.BillOfLading != "" {
charge.BillOfLading = req.BillOfLading
}
if req.ContractNumber != "" {
charge.ContractNumber = req.ContractNumber
}
if req.ExpenseItem != "" {
charge.ExpenseItem = req.ExpenseItem
}
if req.Amount != 0 {
charge.Amount = req.Amount
}
if req.Currency != "" {
charge.Currency = req.Currency
}
if req.PaymentDate != "" {
charge.PaymentDate = parseDate(req.PaymentDate)
}
if req.CompanyName != "" {
charge.CompanyName = req.CompanyName
}
charge.Remark = req.Remark
charge.UpdateTime = time.Now()
return s.repo.UpdateMiscCharge(charge)
}
func (s *zspFinancesService) DeleteMiscCharge(id string) error {
return s.repo.DeleteMiscCharge(id)
}
// ============ 服务费 ============
func (s *zspFinancesService) CreateServiceFee(req *dto.ZSPServiceFeesCreateRequest) error {
currency := req.Currency
if currency == "" {
currency = "CNY"
}
fee := model.ZSPServiceFees{
BillOfLading: req.BillOfLading,
ContractNumber: req.ContractNumber,
Name: req.Name,
Amount: req.Amount,
Currency: currency,
Date: parseDate(req.Date),
Remark: req.Remark,
CreateTime: time.Now(),
UpdateTime: time.Now(),
}
return s.repo.CreateServiceFee(&fee)
}
func (s *zspFinancesService) GetServiceFee(id string) (*model.ZSPServiceFees, error) {
return s.repo.GetServiceFee(id)
}
func (s *zspFinancesService) ListServiceFees() ([]model.ZSPServiceFees, error) {
return s.repo.ListServiceFees()
}
func (s *zspFinancesService) UpdateServiceFee(id string, req *dto.ZSPServiceFeesUpdateRequest) error {
fee, err := s.repo.GetServiceFee(id)
if err != nil {
return err
}
if req.BillOfLading != "" {
fee.BillOfLading = req.BillOfLading
}
if req.ContractNumber != "" {
fee.ContractNumber = req.ContractNumber
}
if req.Name != "" {
fee.Name = req.Name
}
if req.Amount != 0 {
fee.Amount = req.Amount
}
if req.Currency != "" {
fee.Currency = req.Currency
}
if req.Date != "" {
fee.Date = parseDate(req.Date)
}
fee.Remark = req.Remark
fee.UpdateTime = time.Now()
return s.repo.UpdateServiceFee(fee)
}
func (s *zspFinancesService) DeleteServiceFee(id string) error {
return s.repo.DeleteServiceFee(id)
}
// ============ 成本构成 ============
func (s *zspFinancesService) CreateCostBreakdown(req *dto.ZSPCostBreakdownCreateRequest) error {
breakdown := model.ZSPCostBreakdown{
BusinessID: req.BusinessID,
BusinessType: req.BusinessType,
TotalCost: 0,
CreateTime: time.Now(),
UpdateTime: time.Now(),
}
return s.repo.CreateCostBreakdown(&breakdown)
}
func (s *zspFinancesService) GetCostBreakdown(id string) (*model.ZSPCostBreakdown, error) {
return s.repo.GetCostBreakdown(id)
}
func (s *zspFinancesService) ListCostBreakdowns(businessID string) ([]model.ZSPCostBreakdown, error) {
return s.repo.ListCostBreakdowns(businessID)
}
func (s *zspFinancesService) UpdateCostBreakdown(id string, req *dto.ZSPCostBreakdownUpdateRequest) error {
breakdown, err := s.repo.GetCostBreakdown(id)
if err != nil {
return err
}
breakdown.FreightChargeTotal = req.FreightChargeTotal
breakdown.MiscChargeTotal = req.MiscChargeTotal
breakdown.ServiceFeeTotal = req.ServiceFeeTotal
breakdown.TotalCost = req.FreightChargeTotal + req.MiscChargeTotal + req.ServiceFeeTotal
breakdown.UpdateTime = time.Now()
return s.repo.UpdateCostBreakdown(breakdown)
}
func (s *zspFinancesService) DeleteCostBreakdown(id string) error {
return s.repo.DeleteCostBreakdown(id)
}
// ============ 利润记录 ============
func (s *zspFinancesService) CreateProfitRecord(req *dto.ZSPProfitRecordCreateRequest) error {
record := model.ZSPProfitRecord{
BusinessID: req.BusinessID,
BusinessType: req.BusinessType,
Revenue: req.Revenue,
TotalCost: req.TotalCost,
Profit: req.Revenue - req.TotalCost,
ProfitRate: calculateProfitRate(req.Revenue, req.TotalCost),
RecordDate: parseDate(req.RecordDate),
Remark: req.Remark,
CreateTime: time.Now(),
UpdateTime: time.Now(),
}
return s.repo.CreateProfitRecord(&record)
}
func (s *zspFinancesService) GetProfitRecord(id string) (*model.ZSPProfitRecord, error) {
return s.repo.GetProfitRecord(id)
}
func (s *zspFinancesService) ListProfitRecords(filters map[string]string) ([]model.ZSPProfitRecord, error) {
return s.repo.ListProfitRecords(filters)
}
func (s *zspFinancesService) UpdateProfitRecord(id string, req *dto.ZSPProfitRecordUpdateRequest) error {
record, err := s.repo.GetProfitRecord(id)
if err != nil {
return err
}
record.Revenue = req.Revenue
record.TotalCost = req.TotalCost
record.Profit = req.Revenue - req.TotalCost
record.ProfitRate = calculateProfitRate(req.Revenue, req.TotalCost)
record.Remark = req.Remark
record.UpdateTime = time.Now()
return s.repo.UpdateProfitRecord(id, record)
}
func (s *zspFinancesService) DeleteProfitRecord(id string) error {
return s.repo.DeleteProfitRecord(id)
}
// ============ 辅助函数 ============
func parseDate(dateStr string) time.Time {
t, err := time.Parse("2006-01-02", dateStr)
if err != nil {
return time.Time{}
}
return t
}
func calculateProfitRate(revenue, totalCost float64) float64 {
if revenue == 0 {
return 0
}
return (revenue - totalCost) / revenue * 100
}