低空智控平台 后端go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

130 lines
4.8 KiB

package service
import (
"errors"
"time"
"gorm.io/gorm"
"laic-backend/common"
"laic-backend/model"
"laic-backend/tool"
"laic-backend/vo"
)
type InvoiceService struct{}
var DefaultInvoiceService = &InvoiceService{}
func (s *InvoiceService) ListProfiles(userID int64) ([]model.InvoiceProfile, *common.BusiError) {
var profiles []model.InvoiceProfile
if err := common.DB.Where("user_id = ?", userID).Order("is_default DESC, id DESC").Find(&profiles).Error; err != nil {
return nil, common.ErrInternal
}
return profiles, nil
}
func (s *InvoiceService) SaveProfile(userID, profileID int64, req *vo.InvoiceProfileReq) (*model.InvoiceProfile, *common.BusiError) {
var profile model.InvoiceProfile
if profileID > 0 {
if err := common.DB.Where("id = ? AND user_id = ?", profileID, userID).First(&profile).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, common.ErrNotFound
}
return nil, common.ErrInternal
}
} else {
id, err := tool.NextID()
if err != nil {
return nil, common.ErrInternal
}
profile = model.InvoiceProfile{ID: id, UserID: userID, CreatedAt: time.Now()}
}
profile.Title, profile.TaxpayerNumber, profile.Email, profile.IsDefault, profile.UpdatedAt = req.Title, req.TaxpayerNumber, req.Email, req.IsDefault, time.Now()
if err := common.DB.Transaction(func(tx *gorm.DB) error {
if req.IsDefault {
if err := tx.Model(&model.InvoiceProfile{}).Where("user_id = ?", userID).Update("is_default", false).Error; err != nil {
return err
}
}
return tx.Save(&profile).Error
}).Error; err != nil {
return nil, common.ErrInternal
}
return &profile, nil
}
func (s *InvoiceService) DeleteProfile(userID, profileID int64) *common.BusiError {
result := common.DB.Where("id = ? AND user_id = ?", profileID, userID).Delete(&model.InvoiceProfile{})
if result.Error != nil {
return common.ErrInternal
}
if result.RowsAffected == 0 {
return common.ErrNotFound
}
return nil
}
func (s *InvoiceService) ListEligibleOrders(userID int64) ([]model.TrafficOrder, *common.BusiError) {
var orders []model.TrafficOrder
if err := common.DB.Where("user_id = ? AND pay_status = ? AND NOT EXISTS (SELECT 1 FROM invoice_request WHERE invoice_request.order_id = traffic_order.id)", userID, "paid").Order("paid_at DESC").Find(&orders).Error; err != nil {
return nil, common.ErrInternal
}
return orders, nil
}
func (s *InvoiceService) CreateRequest(userID int64, req *vo.InvoiceRequestCreateReq) (*model.InvoiceRequest, *common.BusiError) {
var profile model.InvoiceProfile
if err := common.DB.Where("user_id = ? AND is_default = ?", userID, true).First(&profile).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, common.NewBusiError(common.ParamError, "请先设置默认发票资料")
}
return nil, common.ErrInternal
}
var order model.TrafficOrder
if err := common.DB.Where("id = ? AND user_id = ? AND pay_status = ?", req.OrderID, userID, "paid").First(&order).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, common.ErrOrderNotFound
}
return nil, common.ErrInternal
}
id, err := tool.NextID()
if err != nil {
return nil, common.ErrInternal
}
request := &model.InvoiceRequest{ID: id, UserID: userID, OrderID: order.ID, Amount: order.TotalPrice, Title: profile.Title, TaxpayerNumber: profile.TaxpayerNumber, Email: profile.Email, Status: "pending", RequestedAt: time.Now()}
if err := common.DB.Create(request).Error; err != nil {
if code, _ := common.ParseError(err); code == 1062 {
return nil, common.NewBusiError(common.ParamError, "该订单已申请发票")
}
return nil, common.ErrInternal
}
return request, nil
}
func (s *InvoiceService) ListRequests(userID int64) ([]model.InvoiceRequest, *common.BusiError) {
var requests []model.InvoiceRequest
if err := common.DB.Where("user_id = ?", userID).Order("requested_at DESC").Find(&requests).Error; err != nil {
return nil, common.ErrInternal
}
return requests, nil
}
func (s *InvoiceService) ReviewRequest(requestID int64, req *vo.InvoiceReviewReq) (*model.InvoiceRequest, *common.BusiError) {
if req.Status != "issued" && req.Status != "rejected" {
return nil, common.ErrParam
}
var request model.InvoiceRequest
if err := common.DB.Where("id = ? AND status = ?", requestID, "pending").First(&request).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, common.ErrNotFound
}
return nil, common.ErrInternal
}
now := time.Now()
if err := common.DB.Model(&request).Updates(map[string]any{"status": req.Status, "invoice_number": req.InvoiceNumber, "admin_remark": req.AdminRemark, "processed_at": now}).Error; err != nil {
return nil, common.ErrInternal
}
request.Status, request.InvoiceNumber, request.AdminRemark, request.ProcessedAt = req.Status, req.InvoiceNumber, req.AdminRemark, &now
return &request, nil
}