Constraint: 切换 main 前必须保存当前七月分支全部项目进展,套餐生效提案仅属于 Iteration/7-11。 Rejected: 将七月套餐修复直接移植到 main | 两个分支的可靠投递架构不同。 Confidence: medium Scope-risk: broad Directive: 不得将本提交整体 cherry-pick 到 main;main 套餐热修必须基于其纯 Asynq 代码独立实施。 Tested: git diff --check;openspec validate fix-package-activation-starvation --strict。 Not-tested: 按用户要求未运行自动化测试;go build ./... 因当前审计改造中的 Enterprise 模型字面量和 role.recordFailure 参数类型错误未通过。
589 lines
21 KiB
Go
589 lines
21 KiB
Go
package enterprise
|
|
|
|
import (
|
|
"context"
|
|
stderrors "errors"
|
|
|
|
accessauditapp "github.com/break/junhong_cmp_fiber/internal/application/accessaudit"
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
|
"github.com/break/junhong_cmp_fiber/internal/store"
|
|
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
|
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
|
"golang.org/x/crypto/bcrypt"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
type Service struct {
|
|
db *gorm.DB
|
|
enterpriseStore *postgres.EnterpriseStore
|
|
shopStore *postgres.ShopStore
|
|
accountStore *postgres.AccountStore
|
|
accessAudit accessauditapp.Writer
|
|
}
|
|
|
|
// New 创建企业生命周期服务。
|
|
func New(
|
|
db *gorm.DB,
|
|
enterpriseStore *postgres.EnterpriseStore,
|
|
shopStore *postgres.ShopStore,
|
|
accountStore *postgres.AccountStore,
|
|
accessAudit accessauditapp.Writer,
|
|
) *Service {
|
|
return &Service{
|
|
db: db,
|
|
enterpriseStore: enterpriseStore,
|
|
shopStore: shopStore,
|
|
accountStore: accountStore,
|
|
accessAudit: accessAudit,
|
|
}
|
|
}
|
|
|
|
func (s *Service) Create(ctx context.Context, req *dto.CreateEnterpriseReq) (*dto.CreateEnterpriseResp, error) {
|
|
currentUserID := middleware.GetUserIDFromContext(ctx)
|
|
if currentUserID == 0 {
|
|
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
|
}
|
|
if s.db == nil || s.accessAudit == nil {
|
|
return nil, errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
|
}
|
|
|
|
enterprise := &model.Enterprise{
|
|
EnterpriseName: req.EnterpriseName, EnterpriseCode: req.EnterpriseCode, OwnerShopID: req.OwnerShopID,
|
|
LegalPerson: req.LegalPerson, ContactName: req.ContactName, ContactPhone: req.ContactPhone,
|
|
BusinessLicense: req.BusinessLicense, Province: req.Province, City: req.City,
|
|
District: req.District, Address: req.Address, Status: constants.StatusEnabled,
|
|
}
|
|
enterprise.Creator = currentUserID
|
|
enterprise.Updater = currentUserID
|
|
if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeEnterprise {
|
|
err := errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
|
return nil, err
|
|
}
|
|
if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeAgent && req.OwnerShopID == nil {
|
|
err := errors.New(errors.CodeForbidden, "代理账号不能创建平台主管企业")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
|
return nil, err
|
|
}
|
|
|
|
if req.EnterpriseCode != "" {
|
|
existing, _ := s.enterpriseStore.GetByCode(ctx, req.EnterpriseCode)
|
|
if existing != nil {
|
|
err := errors.New(errors.CodeEnterpriseCodeExists, "企业编号已存在")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
existingAccount, _ := s.accountStore.GetByPhone(ctx, req.LoginPhone)
|
|
if existingAccount != nil {
|
|
err := errors.New(errors.CodePhoneExists, "手机号已被使用")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
|
return nil, err
|
|
}
|
|
|
|
var ownerShop *model.Shop
|
|
if req.OwnerShopID != nil {
|
|
if err := middleware.CanManageShop(ctx, *req.OwnerShopID); err != nil {
|
|
err = errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
|
return nil, err
|
|
}
|
|
var err error
|
|
ownerShop, err = s.shopStore.GetByID(ctx, *req.OwnerShopID)
|
|
if err != nil {
|
|
err = errors.New(errors.CodeShopNotFound, "归属店铺不存在或无效")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, nil, nil, err)
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
appErr := errors.Wrap(errors.CodeInternalError, err, "密码加密失败")
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", enterprise, ownerShop, nil, appErr)
|
|
return nil, appErr
|
|
}
|
|
|
|
var account *model.Account
|
|
|
|
err = s.db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.WithContext(ctx).Create(enterprise).Error; err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "创建企业失败")
|
|
}
|
|
|
|
account = &model.Account{
|
|
Username: req.EnterpriseName,
|
|
Phone: req.LoginPhone,
|
|
Password: string(hashedPassword),
|
|
UserType: constants.UserTypeEnterprise,
|
|
EnterpriseID: &enterprise.ID,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
account.Creator = currentUserID
|
|
account.Updater = currentUserID
|
|
|
|
if err := tx.WithContext(ctx).Create(account).Error; err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "创建企业账号失败")
|
|
}
|
|
|
|
return s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
|
ActionCode: constants.AuditActionEnterpriseCreated, Summary: "创建企业", OperatorID: currentUserID,
|
|
Enterprise: enterprise, Shop: ownerShop,
|
|
Accounts: []accessauditapp.AccountChange{{
|
|
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
|
AfterData: map[string]any{"status": account.Status, "credentials_configured": true},
|
|
}},
|
|
AfterData: enterpriseProfileData(enterprise),
|
|
})
|
|
})
|
|
|
|
if err != nil {
|
|
failureEnterprise := *enterprise
|
|
failureEnterprise.ID = 0
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseCreated, "创建企业失败", &failureEnterprise, ownerShop, nil, err)
|
|
return nil, err
|
|
}
|
|
|
|
ownerShopName := ""
|
|
if ownerShop != nil {
|
|
ownerShopName = ownerShop.ShopName
|
|
}
|
|
|
|
return &dto.CreateEnterpriseResp{
|
|
Enterprise: dto.EnterpriseItem{
|
|
ID: enterprise.ID,
|
|
EnterpriseName: enterprise.EnterpriseName,
|
|
EnterpriseCode: enterprise.EnterpriseCode,
|
|
OwnerShopID: enterprise.OwnerShopID,
|
|
OwnerShopName: ownerShopName,
|
|
LegalPerson: enterprise.LegalPerson,
|
|
ContactName: enterprise.ContactName,
|
|
ContactPhone: enterprise.ContactPhone,
|
|
LoginPhone: req.LoginPhone,
|
|
BusinessLicense: enterprise.BusinessLicense,
|
|
Province: enterprise.Province,
|
|
City: enterprise.City,
|
|
District: enterprise.District,
|
|
Address: enterprise.Address,
|
|
Status: enterprise.Status,
|
|
StatusName: constants.GetStatusName(enterprise.Status),
|
|
CreatedAt: enterprise.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
},
|
|
AccountID: account.ID,
|
|
}, nil
|
|
}
|
|
|
|
// Update 更新企业信息
|
|
func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateEnterpriseRequest) (*model.Enterprise, error) {
|
|
currentUserID := middleware.GetUserIDFromContext(ctx)
|
|
if currentUserID == 0 {
|
|
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
|
}
|
|
if s.db == nil || s.accessAudit == nil {
|
|
return nil, errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
|
}
|
|
if err := middleware.CanManageEnterprise(ctx, id, s.enterpriseStore); err != nil {
|
|
return nil, errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
|
}
|
|
|
|
var enterprise *model.Enterprise
|
|
var before *model.Enterprise
|
|
var ownerShop *model.Shop
|
|
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
locked, err := lockEnterprise(ctx, tx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
beforeValue := *locked
|
|
before = &beforeValue
|
|
enterprise = locked
|
|
ownerShop = loadEnterpriseOwnerShop(tx, locked.OwnerShopID)
|
|
if req.EnterpriseCode != nil && *req.EnterpriseCode != locked.EnterpriseCode {
|
|
var count int64
|
|
if err := tx.Model(&model.Enterprise{}).Where("enterprise_code = ? AND id <> ?", *req.EnterpriseCode, id).Count(&count).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "检查企业编号失败")
|
|
}
|
|
if count > 0 {
|
|
return errors.New(errors.CodeEnterpriseCodeExists, "企业编号已存在")
|
|
}
|
|
locked.EnterpriseCode = *req.EnterpriseCode
|
|
}
|
|
applyEnterpriseUpdate(locked, req)
|
|
locked.Updater = currentUserID
|
|
if err := tx.Save(locked).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "更新企业失败")
|
|
}
|
|
if !enterpriseProfileChanged(before, locked) {
|
|
return nil
|
|
}
|
|
if err := s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
|
ActionCode: constants.AuditActionEnterpriseUpdated, Summary: "更新企业基础资料", OperatorID: currentUserID,
|
|
Enterprise: locked, Shop: ownerShop,
|
|
BeforeData: enterpriseProfileData(before), AfterData: enterpriseProfileData(locked),
|
|
}); err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "写入企业更新审计失败")
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
if before != nil {
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseUpdated, "更新企业基础资料失败", before, ownerShop, nil, err)
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return enterprise, nil
|
|
}
|
|
|
|
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
|
currentUserID := middleware.GetUserIDFromContext(ctx)
|
|
if currentUserID == 0 {
|
|
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
|
}
|
|
if s.db == nil || s.accessAudit == nil {
|
|
return errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
|
}
|
|
if err := middleware.CanManageEnterprise(ctx, id, s.enterpriseStore); err != nil {
|
|
return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
|
}
|
|
|
|
var before *model.Enterprise
|
|
var ownerShop *model.Shop
|
|
var accounts []*model.Account
|
|
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
enterprise, err := lockEnterprise(ctx, tx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
beforeValue := *enterprise
|
|
before = &beforeValue
|
|
ownerShop = loadEnterpriseOwnerShop(tx, enterprise.OwnerShopID)
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("enterprise_id = ?", id).Find(&accounts).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "查询企业账号失败")
|
|
}
|
|
enterprise.Status = status
|
|
enterprise.Updater = currentUserID
|
|
if err := tx.Save(enterprise).Error; err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "更新企业状态失败")
|
|
}
|
|
|
|
if err := tx.Model(&model.Account{}).
|
|
Where("enterprise_id = ?", id).
|
|
Updates(map[string]interface{}{
|
|
"status": status,
|
|
"updater": currentUserID,
|
|
}).Error; err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "同步更新企业账号状态失败")
|
|
}
|
|
if before.Status == status {
|
|
return nil
|
|
}
|
|
accountChanges := make([]accessauditapp.AccountChange, 0, len(accounts))
|
|
for _, account := range accounts {
|
|
accountChanges = append(accountChanges, accessauditapp.AccountChange{
|
|
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
|
BeforeData: map[string]any{"status": account.Status}, AfterData: map[string]any{"status": status},
|
|
})
|
|
}
|
|
if err := s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
|
ActionCode: constants.AuditActionEnterpriseStatusUpdated, Summary: "更新企业状态", OperatorID: currentUserID,
|
|
Enterprise: enterprise, Shop: ownerShop, Accounts: accountChanges,
|
|
BeforeData: map[string]any{"status": before.Status}, AfterData: map[string]any{"status": status},
|
|
}); err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "写入企业状态审计失败")
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
if before != nil {
|
|
s.recordFailure(ctx, constants.AuditActionEnterpriseStatusUpdated, "更新企业状态失败", before, ownerShop, accounts, err)
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) UpdatePassword(ctx context.Context, id uint, password string) error {
|
|
currentUserID := middleware.GetUserIDFromContext(ctx)
|
|
if currentUserID == 0 {
|
|
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
|
}
|
|
|
|
if s.db == nil || s.accessAudit == nil {
|
|
return errors.New(errors.CodeInvalidStatus, "企业审计接缝未配置")
|
|
}
|
|
if err := middleware.CanManageEnterprise(ctx, id, s.enterpriseStore); err != nil {
|
|
return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
|
}
|
|
enterprise, err := s.enterpriseStore.GetByID(ctx, id)
|
|
if err != nil {
|
|
return errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
|
}
|
|
var ownerShop *model.Shop
|
|
if enterprise.OwnerShopID != nil {
|
|
ownerShop, _ = s.shopStore.GetByID(ctx, *enterprise.OwnerShopID)
|
|
}
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
appErr := errors.Wrap(errors.CodeInternalError, err, "密码加密失败")
|
|
s.recordFailure(ctx, constants.AuditActionEnterprisePasswordUpdated, "更新企业账号密码失败", enterprise, ownerShop, nil, appErr)
|
|
return appErr
|
|
}
|
|
|
|
var accounts []*model.Account
|
|
err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
enterprise, err = lockEnterprise(ctx, tx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ownerShop = loadEnterpriseOwnerShop(tx, enterprise.OwnerShopID)
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("enterprise_id = ?", id).Find(&accounts).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "查询企业账号失败")
|
|
}
|
|
if err := tx.Model(&model.Account{}).Where("enterprise_id = ?", id).Updates(map[string]interface{}{
|
|
"password": string(hashedPassword), "updater": currentUserID,
|
|
}).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "更新企业账号密码失败")
|
|
}
|
|
accountChanges := make([]accessauditapp.AccountChange, 0, len(accounts))
|
|
for _, account := range accounts {
|
|
accountChanges = append(accountChanges, accessauditapp.AccountChange{
|
|
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
|
BeforeData: map[string]any{"credentials_configured": account.Password != ""},
|
|
AfterData: map[string]any{"credentials_configured": true, "state": "changed"},
|
|
})
|
|
}
|
|
if err := s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
|
|
ActionCode: constants.AuditActionEnterprisePasswordUpdated, Summary: "更新企业账号密码", OperatorID: currentUserID,
|
|
Enterprise: enterprise, Shop: ownerShop, Accounts: accountChanges,
|
|
BeforeData: map[string]any{"credentials_configured": len(accounts) > 0},
|
|
AfterData: map[string]any{"credentials_configured": len(accounts) > 0, "state": "changed"},
|
|
}); err != nil {
|
|
return errors.Wrap(errors.CodeInternalError, err, "写入企业改密审计失败")
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
if enterprise != nil {
|
|
s.recordFailure(ctx, constants.AuditActionEnterprisePasswordUpdated, "更新企业账号密码失败", enterprise, ownerShop, accounts, err)
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func applyEnterpriseUpdate(enterprise *model.Enterprise, req *dto.UpdateEnterpriseRequest) {
|
|
if req.EnterpriseName != nil {
|
|
enterprise.EnterpriseName = *req.EnterpriseName
|
|
}
|
|
if req.LegalPerson != nil {
|
|
enterprise.LegalPerson = *req.LegalPerson
|
|
}
|
|
if req.ContactName != nil {
|
|
enterprise.ContactName = *req.ContactName
|
|
}
|
|
if req.ContactPhone != nil {
|
|
enterprise.ContactPhone = *req.ContactPhone
|
|
}
|
|
if req.BusinessLicense != nil {
|
|
enterprise.BusinessLicense = *req.BusinessLicense
|
|
}
|
|
if req.Province != nil {
|
|
enterprise.Province = *req.Province
|
|
}
|
|
if req.City != nil {
|
|
enterprise.City = *req.City
|
|
}
|
|
if req.District != nil {
|
|
enterprise.District = *req.District
|
|
}
|
|
if req.Address != nil {
|
|
enterprise.Address = *req.Address
|
|
}
|
|
}
|
|
|
|
func enterpriseProfileData(enterprise *model.Enterprise) map[string]any {
|
|
return map[string]any{
|
|
"enterprise_name": enterprise.EnterpriseName, "enterprise_code": enterprise.EnterpriseCode,
|
|
"owner_shop_id": enterprise.OwnerShopID, "legal_person": enterprise.LegalPerson,
|
|
"contact_name": enterprise.ContactName, "contact_phone": enterprise.ContactPhone,
|
|
"business_license": enterprise.BusinessLicense, "province": enterprise.Province,
|
|
"city": enterprise.City, "district": enterprise.District, "address": enterprise.Address,
|
|
"status": enterprise.Status,
|
|
}
|
|
}
|
|
|
|
func enterpriseProfileChanged(before, after *model.Enterprise) bool {
|
|
return before.EnterpriseName != after.EnterpriseName || before.EnterpriseCode != after.EnterpriseCode ||
|
|
before.LegalPerson != after.LegalPerson || before.ContactName != after.ContactName ||
|
|
before.ContactPhone != after.ContactPhone || before.BusinessLicense != after.BusinessLicense ||
|
|
before.Province != after.Province || before.City != after.City || before.District != after.District ||
|
|
before.Address != after.Address
|
|
}
|
|
|
|
func lockEnterprise(ctx context.Context, tx *gorm.DB, id uint) (*model.Enterprise, error) {
|
|
var enterprise model.Enterprise
|
|
query := middleware.ApplyOwnerShopFilter(ctx, tx.WithContext(ctx).Where("id = ?", id))
|
|
if err := query.Clauses(clause.Locking{Strength: "UPDATE"}).First(&enterprise).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
|
}
|
|
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询企业失败")
|
|
}
|
|
return &enterprise, nil
|
|
}
|
|
|
|
func loadEnterpriseOwnerShop(tx *gorm.DB, ownerShopID *uint) *model.Shop {
|
|
if ownerShopID == nil {
|
|
return nil
|
|
}
|
|
var shop model.Shop
|
|
if err := tx.Unscoped().First(&shop, *ownerShopID).Error; err != nil {
|
|
return nil
|
|
}
|
|
return &shop
|
|
}
|
|
|
|
func (s *Service) recordFailure(
|
|
ctx context.Context,
|
|
actionCode, summary string,
|
|
enterprise *model.Enterprise,
|
|
ownerShop *model.Shop,
|
|
accounts []*model.Account,
|
|
originalErr error,
|
|
) {
|
|
accountChanges := make([]accessauditapp.AccountChange, 0, len(accounts))
|
|
for _, account := range accounts {
|
|
accountChanges = append(accountChanges, accessauditapp.AccountChange{
|
|
Account: account, Role: constants.AuditResourceRoleEnterpriseAccount,
|
|
})
|
|
}
|
|
accessauditapp.RecordFailure(ctx, s.db, s.accessAudit, accessauditapp.ChangeAudit{
|
|
ActionCode: actionCode, Summary: summary, Result: enterpriseAuditFailureResult(originalErr),
|
|
OperatorID: middleware.GetUserIDFromContext(ctx), Enterprise: enterprise, Shop: ownerShop,
|
|
Accounts: accountChanges, SubjectVisibility: constants.AuditSubjectInternalOnly,
|
|
}, originalErr)
|
|
}
|
|
|
|
func enterpriseAuditFailureResult(err error) string {
|
|
var appErr *errors.AppError
|
|
if stderrors.As(err, &appErr) {
|
|
switch appErr.Code {
|
|
case errors.CodeForbidden, errors.CodeInvalidParam, errors.CodeNotFound, errors.CodeEnterpriseNotFound,
|
|
errors.CodeEnterpriseCodeExists, errors.CodePhoneExists, errors.CodeShopNotFound:
|
|
return constants.AuditResultDenied
|
|
}
|
|
}
|
|
return constants.AuditResultFailed
|
|
}
|
|
|
|
func (s *Service) GetByID(ctx context.Context, id uint) (*model.Enterprise, error) {
|
|
enterprise, err := s.enterpriseStore.GetByID(ctx, id)
|
|
if err != nil {
|
|
return nil, errors.New(errors.CodeEnterpriseNotFound, "企业不存在")
|
|
}
|
|
return enterprise, nil
|
|
}
|
|
|
|
func (s *Service) List(ctx context.Context, req *dto.EnterpriseListReq) (*dto.EnterprisePageResult, error) {
|
|
opts := &store.QueryOptions{
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
}
|
|
if opts.Page == 0 {
|
|
opts.Page = 1
|
|
}
|
|
if opts.PageSize == 0 {
|
|
opts.PageSize = constants.DefaultPageSize
|
|
}
|
|
|
|
filters := make(map[string]interface{})
|
|
if req.EnterpriseName != "" {
|
|
filters["enterprise_name"] = req.EnterpriseName
|
|
}
|
|
if req.ContactPhone != "" {
|
|
filters["contact_phone"] = req.ContactPhone
|
|
}
|
|
if req.OwnerShopID != nil {
|
|
filters["owner_shop_id"] = *req.OwnerShopID
|
|
}
|
|
if req.Status != nil {
|
|
filters["status"] = *req.Status
|
|
}
|
|
|
|
enterprises, total, err := s.enterpriseStore.List(ctx, opts, filters)
|
|
if err != nil {
|
|
return nil, errors.Wrap(errors.CodeInternalError, err, "查询企业列表失败")
|
|
}
|
|
|
|
enterpriseIDs := make([]uint, 0, len(enterprises))
|
|
shopIDs := make([]uint, 0)
|
|
for _, e := range enterprises {
|
|
enterpriseIDs = append(enterpriseIDs, e.ID)
|
|
if e.OwnerShopID != nil {
|
|
shopIDs = append(shopIDs, *e.OwnerShopID)
|
|
}
|
|
}
|
|
|
|
accountMap := make(map[uint]string)
|
|
if len(enterpriseIDs) > 0 {
|
|
var accounts []model.Account
|
|
s.db.WithContext(ctx).Where("enterprise_id IN ?", enterpriseIDs).Find(&accounts)
|
|
for _, acc := range accounts {
|
|
if acc.EnterpriseID != nil {
|
|
accountMap[*acc.EnterpriseID] = acc.Phone
|
|
}
|
|
}
|
|
}
|
|
|
|
shopMap := make(map[uint]string)
|
|
if len(shopIDs) > 0 {
|
|
var shops []model.Shop
|
|
// 使用 Unscoped() 包含已删除的店铺,确保能显示店铺名称
|
|
s.db.WithContext(ctx).Unscoped().Where("id IN ?", shopIDs).Find(&shops)
|
|
for _, shop := range shops {
|
|
shopMap[shop.ID] = shop.ShopName
|
|
}
|
|
}
|
|
|
|
items := make([]dto.EnterpriseItem, 0, len(enterprises))
|
|
for _, e := range enterprises {
|
|
ownerShopName := ""
|
|
if e.OwnerShopID != nil {
|
|
ownerShopName = shopMap[*e.OwnerShopID]
|
|
}
|
|
items = append(items, dto.EnterpriseItem{
|
|
ID: e.ID,
|
|
EnterpriseName: e.EnterpriseName,
|
|
EnterpriseCode: e.EnterpriseCode,
|
|
OwnerShopID: e.OwnerShopID,
|
|
OwnerShopName: ownerShopName,
|
|
LegalPerson: e.LegalPerson,
|
|
ContactName: e.ContactName,
|
|
ContactPhone: e.ContactPhone,
|
|
LoginPhone: accountMap[e.ID],
|
|
BusinessLicense: e.BusinessLicense,
|
|
Province: e.Province,
|
|
City: e.City,
|
|
District: e.District,
|
|
Address: e.Address,
|
|
Status: e.Status,
|
|
StatusName: constants.GetStatusName(e.Status),
|
|
CreatedAt: e.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
})
|
|
}
|
|
|
|
return &dto.EnterprisePageResult{
|
|
Items: items,
|
|
Total: total,
|
|
Page: opts.Page,
|
|
Size: opts.PageSize,
|
|
}, nil
|
|
}
|