Compare commits
2 Commits
5410181e77
...
041856dc8c
| Author | SHA1 | Date | |
|---|---|---|---|
| 041856dc8c | |||
| 7cdb66cbe4 |
@@ -1,71 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// PackageSnapshot 套餐快照,记录换卡时的套餐信息
|
||||
type PackageSnapshot struct {
|
||||
PackageID uint `json:"package_id"` // 套餐ID
|
||||
PackageName string `json:"package_name"` // 套餐名称
|
||||
PackageType string `json:"package_type"` // 套餐类型
|
||||
DataQuota int64 `json:"data_quota"` // 流量额度(KB)
|
||||
DataUsed int64 `json:"data_used"` // 已使用流量(KB)
|
||||
ValidFrom time.Time `json:"valid_from"` // 生效时间
|
||||
ValidTo time.Time `json:"valid_to"` // 失效时间
|
||||
Price int64 `json:"price"` // 套餐价格(分)
|
||||
RemainingDays int `json:"remaining_days"` // 剩余天数
|
||||
TransferReason string `json:"transfer_reason,omitempty"` // 转移原因
|
||||
}
|
||||
|
||||
// Value 实现 driver.Valuer 接口
|
||||
func (p PackageSnapshot) Value() (driver.Value, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// Scan 实现 sql.Scanner 接口
|
||||
func (p *PackageSnapshot) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
bytes, ok := value.([]byte)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(bytes, p)
|
||||
}
|
||||
|
||||
// CardReplacementRecord 换卡记录模型
|
||||
// 记录物联卡更换历史,包含套餐快照便于追溯
|
||||
// 支持损坏、丢失、故障等多种换卡原因,需要审批流程
|
||||
type CardReplacementRecord struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
ReplacementNo string `gorm:"column:replacement_no;type:varchar(50);not null;uniqueIndex:idx_card_replacement_no,where:deleted_at IS NULL;comment:换卡单号" json:"replacement_no"`
|
||||
OldCardID uint `gorm:"column:old_card_id;not null;index:idx_card_replacement_old_card;comment:老卡ID" json:"old_card_id"`
|
||||
OldIccid string `gorm:"column:old_iccid;type:varchar(50);not null;comment:老卡ICCID" json:"old_iccid"`
|
||||
NewCardID uint `gorm:"column:new_card_id;not null;index:idx_card_replacement_new_card;comment:新卡ID" json:"new_card_id"`
|
||||
NewIccid string `gorm:"column:new_iccid;type:varchar(50);not null;comment:新卡ICCID" json:"new_iccid"`
|
||||
OldOwnerType string `gorm:"column:old_owner_type;type:varchar(20);not null;index:idx_card_replacement_old_owner,priority:1;comment:老卡所有者类型" json:"old_owner_type"`
|
||||
OldOwnerID uint `gorm:"column:old_owner_id;not null;index:idx_card_replacement_old_owner,priority:2;comment:老卡所有者ID" json:"old_owner_id"`
|
||||
OldAgentID *uint `gorm:"column:old_agent_id;comment:老卡代理ID" json:"old_agent_id,omitempty"`
|
||||
NewOwnerType string `gorm:"column:new_owner_type;type:varchar(20);not null;index:idx_card_replacement_new_owner,priority:1;comment:新卡所有者类型" json:"new_owner_type"`
|
||||
NewOwnerID uint `gorm:"column:new_owner_id;not null;index:idx_card_replacement_new_owner,priority:2;comment:新卡所有者ID" json:"new_owner_id"`
|
||||
NewAgentID *uint `gorm:"column:new_agent_id;comment:新卡代理ID" json:"new_agent_id,omitempty"`
|
||||
PackageSnapshot *PackageSnapshot `gorm:"column:package_snapshot;type:jsonb;comment:套餐快照" json:"package_snapshot,omitempty"`
|
||||
ReplacementReason string `gorm:"column:replacement_reason;type:varchar(20);not null;comment:换卡原因 damaged-损坏 lost-丢失 malfunction-故障 upgrade-升级 other-其他" json:"replacement_reason"`
|
||||
Remark *string `gorm:"column:remark;type:text;comment:备注" json:"remark,omitempty"`
|
||||
Status int `gorm:"column:status;type:int;not null;default:1;index:idx_card_replacement_status;comment:换卡状态 1-待审批 2-已通过 3-已拒绝 4-已完成" json:"status"`
|
||||
ApprovedBy *uint `gorm:"column:approved_by;comment:审批人ID" json:"approved_by,omitempty"`
|
||||
ApprovedAt *time.Time `gorm:"column:approved_at;comment:审批时间" json:"approved_at,omitempty"`
|
||||
CompletedAt *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at,omitempty"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (CardReplacementRecord) TableName() string {
|
||||
return "tb_card_replacement_record"
|
||||
}
|
||||
@@ -52,24 +52,3 @@ type CommissionWithdrawalSetting struct {
|
||||
func (CommissionWithdrawalSetting) TableName() string {
|
||||
return "tb_commission_withdrawal_setting"
|
||||
}
|
||||
|
||||
// PaymentMerchantSetting 收款商户设置模型
|
||||
// 配置支付参数(支付宝、微信等收款账户)
|
||||
type PaymentMerchantSetting struct {
|
||||
gorm.Model
|
||||
BaseModel `gorm:"embedded"`
|
||||
UserID uint `gorm:"column:user_id;index;not null;comment:用户ID" json:"user_id"`
|
||||
MerchantType string `gorm:"column:merchant_type;type:varchar(20);comment:商户类型 alipay-支付宝 wechat-微信 bank-银行卡" json:"merchant_type"`
|
||||
AccountName string `gorm:"column:account_name;type:varchar(255);comment:账户名称" json:"account_name"`
|
||||
AccountNumber string `gorm:"column:account_number;type:varchar(255);comment:账号" json:"account_number"`
|
||||
BankName string `gorm:"column:bank_name;type:varchar(255);comment:银行名称(仅银行卡)" json:"bank_name"`
|
||||
BankBranch string `gorm:"column:bank_branch;type:varchar(255);comment:开户行(仅银行卡)" json:"bank_branch"`
|
||||
IsVerified bool `gorm:"column:is_verified;type:boolean;default:false;comment:是否已验证" json:"is_verified"`
|
||||
IsDefault bool `gorm:"column:is_default;type:boolean;default:false;comment:是否默认账户" json:"is_default"`
|
||||
Status int `gorm:"column:status;type:int;default:1;comment:状态 0=禁用 1=启用" json:"status"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (PaymentMerchantSetting) TableName() string {
|
||||
return "tb_payment_merchant_setting"
|
||||
}
|
||||
|
||||
@@ -469,23 +469,6 @@ func (s *Service) generateRechargeNo() string {
|
||||
return fmt.Sprintf("%s%s%06d", constants.AgentRechargeOrderPrefix, timestamp, randomNum)
|
||||
}
|
||||
|
||||
func agentRechargeStatusName(status int) string {
|
||||
switch status {
|
||||
case constants.RechargeStatusPending:
|
||||
return "待支付"
|
||||
case constants.RechargeStatusPaid:
|
||||
return "已支付"
|
||||
case constants.RechargeStatusCompleted:
|
||||
return "已完成"
|
||||
case constants.RechargeStatusClosed:
|
||||
return "已关闭"
|
||||
case constants.RechargeStatusRefunded:
|
||||
return "已退款"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// toResponse 将模型转换为响应 DTO
|
||||
func toResponse(record *model.AgentRechargeRecord, shopName string) *dto.AgentRechargeResponse {
|
||||
resp := &dto.AgentRechargeResponse{
|
||||
@@ -497,7 +480,7 @@ func toResponse(record *model.AgentRechargeRecord, shopName string) *dto.AgentRe
|
||||
Amount: record.Amount,
|
||||
PaymentMethod: record.PaymentMethod,
|
||||
Status: record.Status,
|
||||
StatusName: agentRechargeStatusName(record.Status),
|
||||
StatusName: constants.GetRechargeStatusName(record.Status),
|
||||
CreatedAt: record.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
UpdatedAt: record.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ func (s *Service) buildWithdrawalRequestItem(r *model.CommissionWithdrawalReques
|
||||
Fee: r.Fee,
|
||||
ActualAmount: r.ActualAmount,
|
||||
Status: r.Status,
|
||||
StatusName: getWithdrawalStatusName(r.Status),
|
||||
StatusName: constants.GetWithdrawalStatusName(r.Status),
|
||||
ShopID: r.ShopID,
|
||||
ShopName: shopName,
|
||||
ShopHierarchy: shopHierarchy,
|
||||
@@ -402,21 +402,6 @@ func (s *Service) buildWithdrawalRequestItem(r *model.CommissionWithdrawalReques
|
||||
}
|
||||
}
|
||||
|
||||
func getWithdrawalStatusName(status int) string {
|
||||
switch status {
|
||||
case constants.WithdrawalStatusPending:
|
||||
return "待审核"
|
||||
case constants.WithdrawalStatusApproved:
|
||||
return "已通过"
|
||||
case constants.WithdrawalStatusRejected:
|
||||
return "已拒绝"
|
||||
case constants.WithdrawalStatusPaid:
|
||||
return "已到账"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
func containsSubstring(s, substr string) bool {
|
||||
for i := 0; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
|
||||
@@ -131,7 +131,7 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateEnterpriseReq) (*dt
|
||||
District: enterprise.District,
|
||||
Address: enterprise.Address,
|
||||
Status: enterprise.Status,
|
||||
StatusName: getStatusName(enterprise.Status),
|
||||
StatusName: constants.GetStatusName(enterprise.Status),
|
||||
CreatedAt: enterprise.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
AccountID: account.ID,
|
||||
@@ -345,7 +345,7 @@ func (s *Service) List(ctx context.Context, req *dto.EnterpriseListReq) (*dto.En
|
||||
District: e.District,
|
||||
Address: e.Address,
|
||||
Status: e.Status,
|
||||
StatusName: getStatusName(e.Status),
|
||||
StatusName: constants.GetStatusName(e.Status),
|
||||
CreatedAt: e.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
}
|
||||
@@ -357,10 +357,3 @@ func (s *Service) List(ctx context.Context, req *dto.EnterpriseListReq) (*dto.En
|
||||
Size: opts.PageSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getStatusName(status int) string {
|
||||
if status == constants.StatusEnabled {
|
||||
return "启用"
|
||||
}
|
||||
return "禁用"
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ func (s *Service) AllocateCardsPreview(ctx context.Context, enterpriseID uint, r
|
||||
IotCardID: card.ID,
|
||||
MSISDN: card.MSISDN,
|
||||
CarrierID: card.CarrierID,
|
||||
StatusName: getCardStatusName(card.Status),
|
||||
StatusName: constants.GetIotCardStatusName(card.Status),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -305,9 +305,9 @@ func (s *Service) ListCards(ctx context.Context, enterpriseID uint, req *dto.Ent
|
||||
CarrierName: card.CarrierName,
|
||||
PackageName: packageNameMap[card.ID],
|
||||
Status: card.Status,
|
||||
StatusName: getCardStatusName(card.Status),
|
||||
StatusName: constants.GetIotCardStatusName(card.Status),
|
||||
NetworkStatus: card.NetworkStatus,
|
||||
NetworkStatusName: getNetworkStatusName(card.NetworkStatus),
|
||||
NetworkStatusName: constants.GetNetworkStatusName(card.NetworkStatus),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -377,25 +377,3 @@ func (s *Service) updateCardNetworkStatus(ctx context.Context, enterpriseID, car
|
||||
Where("id = ?", cardID).
|
||||
Update("network_status", networkStatus).Error
|
||||
}
|
||||
|
||||
func getCardStatusName(status int) string {
|
||||
switch status {
|
||||
case 1:
|
||||
return "在库"
|
||||
case 2:
|
||||
return "已分销"
|
||||
case 3:
|
||||
return "已激活"
|
||||
case 4:
|
||||
return "已停用"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
func getNetworkStatusName(status int) string {
|
||||
if status == 1 {
|
||||
return "开机"
|
||||
}
|
||||
return "停机"
|
||||
}
|
||||
|
||||
@@ -523,7 +523,7 @@ func (s *Service) GetDeviceDetail(ctx context.Context, deviceID uint) (*dto.Ente
|
||||
MSISDN: card.MSISDN,
|
||||
CarrierName: carrierMap[card.CarrierID],
|
||||
NetworkStatus: card.NetworkStatus,
|
||||
NetworkStatusName: getNetworkStatusName(card.NetworkStatus),
|
||||
NetworkStatusName: constants.GetNetworkStatusName(card.NetworkStatus),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -602,10 +602,3 @@ func (s *Service) validateCardOperation(ctx context.Context, deviceID, cardID ui
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getNetworkStatusName(status int) string {
|
||||
if status == 1 {
|
||||
return "开机"
|
||||
}
|
||||
return "停机"
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ func (s *Service) buildWithdrawalRequestItem(r *model.CommissionWithdrawalReques
|
||||
Fee: r.Fee,
|
||||
ActualAmount: r.ActualAmount,
|
||||
Status: r.Status,
|
||||
StatusName: getWithdrawalStatusName(r.Status),
|
||||
StatusName: constants.GetWithdrawalStatusName(r.Status),
|
||||
ShopID: r.ShopID,
|
||||
ShopName: shopName,
|
||||
ShopHierarchy: shopHierarchy,
|
||||
@@ -443,7 +443,7 @@ func (s *Service) ListShopCommissionRecords(ctx context.Context, shopID uint, re
|
||||
BalanceAfter: r.BalanceAfter,
|
||||
CommissionSource: r.CommissionSource,
|
||||
Status: r.Status,
|
||||
StatusName: getCommissionStatusName(r.Status),
|
||||
StatusName: constants.GetCommissionRecordStatusName(r.Status),
|
||||
OrderID: r.OrderID,
|
||||
OrderNo: r.OrderNo,
|
||||
VirtualNo: r.VirtualNo,
|
||||
@@ -672,7 +672,7 @@ func (s *Service) CreateWithdrawalRequest(ctx context.Context, shopID uint, req
|
||||
Fee: withdrawalRequest.Fee,
|
||||
ActualAmount: withdrawalRequest.ActualAmount,
|
||||
Status: withdrawalRequest.Status,
|
||||
StatusName: getWithdrawalStatusName(withdrawalRequest.Status),
|
||||
StatusName: constants.GetWithdrawalStatusName(withdrawalRequest.Status),
|
||||
CreatedAt: withdrawalRequest.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
}, nil
|
||||
}
|
||||
@@ -823,38 +823,6 @@ func (s *Service) ResolveCommissionRecord(ctx context.Context, recordID uint, re
|
||||
})
|
||||
}
|
||||
|
||||
// getWithdrawalStatusName 获取提现状态名称
|
||||
func getWithdrawalStatusName(status int) string {
|
||||
switch status {
|
||||
case constants.WithdrawalStatusPending:
|
||||
return "待审核"
|
||||
case constants.WithdrawalStatusApproved:
|
||||
return "已通过"
|
||||
case constants.WithdrawalStatusRejected:
|
||||
return "已拒绝"
|
||||
case constants.WithdrawalStatusPaid:
|
||||
return "已到账"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// getCommissionStatusName 获取佣金状态名称
|
||||
func getCommissionStatusName(status int) string {
|
||||
switch status {
|
||||
case constants.CommissionStatusFrozen:
|
||||
return "已冻结"
|
||||
case constants.CommissionStatusUnfreezing:
|
||||
return "解冻中"
|
||||
case constants.CommissionStatusReleased:
|
||||
return "已发放"
|
||||
case constants.CommissionStatusInvalid:
|
||||
return "已失效"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// generateWithdrawalNo 生成提现单号
|
||||
func generateWithdrawalNo() string {
|
||||
now := time.Now()
|
||||
|
||||
68
migrations/README.md
Normal file
68
migrations/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 数据库迁移说明
|
||||
|
||||
## 当前结构
|
||||
|
||||
```
|
||||
migrations/
|
||||
├── 000114_squash_baseline.up.sql ← ⚠️ 待创建(见下方说明)
|
||||
├── 000114_squash_baseline.down.sql ← ⚠️ 待创建
|
||||
├── 000115_init_data.up.sql ← 初始化数据(轮询配置 + purchase_role 回填)
|
||||
├── 000115_init_data.down.sql
|
||||
├── 000116_remove_legacy_commission_fields.up.sql ← 删除废弃分佣字段
|
||||
├── 000116_remove_legacy_commission_fields.down.sql
|
||||
└── archive/ ← 已归档的历史迁移(000000~000113)
|
||||
```
|
||||
|
||||
## ⚠️ 发布前必做:生成 000114 squash 基线
|
||||
|
||||
**背景**:历史迁移(000000-000113)已归档,但尚未生成汇总基线文件。
|
||||
现有测试环境的表是在 migrate 工具之外创建的,不受影响。
|
||||
但全新环境(本地搭建、CI、生产首次部署)必须有 000114 才能通过 `migrate up` 建表。
|
||||
|
||||
**执行时机**:正式发布前,确认 schema 已稳定后执行一次。
|
||||
|
||||
**步骤**:
|
||||
|
||||
1. 安装 PostgreSQL 客户端(若未安装):
|
||||
```bash
|
||||
brew install libpq
|
||||
export PATH="/opt/homebrew/opt/libpq/bin:$PATH"
|
||||
```
|
||||
|
||||
2. 生成 schema 基线(仅 DDL,不含数据):
|
||||
```bash
|
||||
PGPASSWORD=<密码> pg_dump \
|
||||
--schema-only --no-owner --no-acl \
|
||||
-h <host> -U <user> -d <dbname> \
|
||||
> migrations/000114_squash_baseline.up.sql
|
||||
```
|
||||
|
||||
3. 在生成的 `000114_squash_baseline.up.sql` 头部加上注释(参考其他迁移文件格式)。
|
||||
|
||||
4. 创建 `000114_squash_baseline.down.sql`(删除所有表):
|
||||
```sql
|
||||
-- 回滚:删除所有业务表(谨慎执行)
|
||||
DROP TABLE IF EXISTS tb_wechat_config CASCADE;
|
||||
DROP TABLE IF EXISTS tb_tag CASCADE;
|
||||
-- ... 其他表(按依赖倒序)
|
||||
```
|
||||
|
||||
5. 找 AI 协助完成 down.sql 和验证步骤(在全新数据库执行 `migrate up` 验证链路)。
|
||||
|
||||
6. 更新 `scripts/reset_db.sh` 中的注释,确认脚本可用。
|
||||
|
||||
## 迁移链路(目标状态)
|
||||
|
||||
```
|
||||
全新数据库
|
||||
└─ migrate up
|
||||
├─ 000114: 建表(squash 基线)
|
||||
├─ 000115: 写初始化数据
|
||||
└─ 000116: 删除废弃字段
|
||||
```
|
||||
|
||||
## 现有测试环境说明
|
||||
|
||||
测试环境的表通过历史方式创建,`schema_migrations` 中仅记录版本 116。
|
||||
对正在运行的服务**没有影响**。
|
||||
若需在测试库补齐迁移记录,可手动运行 `migrate up`(000115 全部幂等,安全)。
|
||||
@@ -231,25 +231,10 @@ const (
|
||||
WithdrawalMethodBank = "bank" // 银行卡
|
||||
)
|
||||
|
||||
// 商户类型([预留] 用于未来商户管理功能,待产品规划)
|
||||
const (
|
||||
MerchantTypeAlipay = "alipay" // 支付宝([预留])
|
||||
MerchantTypeWechat = "wechat" // 微信([预留])
|
||||
MerchantTypeBank = "bank" // 银行卡([预留])
|
||||
)
|
||||
|
||||
// ========================================
|
||||
// 5. 系统管理常量
|
||||
// ========================================
|
||||
|
||||
// 换卡申请状态([预留] 用于换卡申请功能,待产品规划)
|
||||
const (
|
||||
ReplacementStatusPending = 1 // 待处理([预留])
|
||||
ReplacementStatusApproved = 2 // 已通过([预留])
|
||||
ReplacementStatusRejected = 3 // 已拒绝([预留])
|
||||
ReplacementStatusCompleted = 4 // 已完成([预留])
|
||||
)
|
||||
|
||||
// ========================================
|
||||
// 运营商编码
|
||||
// ========================================
|
||||
@@ -261,15 +246,6 @@ const (
|
||||
CarrierCodeCBN = "CBN" // 广电
|
||||
)
|
||||
|
||||
// 换货原因([预留] 用于换卡原因管理功能,待产品规划)
|
||||
const (
|
||||
ReplacementReasonDamaged = "damaged" // 损坏([预留])
|
||||
ReplacementReasonLost = "lost" // 丢失([预留])
|
||||
ReplacementReasonMalfunction = "malfunction" // 故障([预留])
|
||||
ReplacementReasonUpgrade = "upgrade" // 升级([预留])
|
||||
ReplacementReasonOther = "other" // 其他([预留])
|
||||
)
|
||||
|
||||
// ========================================
|
||||
// 状态名称映射函数
|
||||
// ========================================
|
||||
@@ -412,16 +388,3 @@ func GetWithdrawalStatusName(status int) string {
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// GetEnterpriseCardAuthStatusName 获取企业卡授权状态名称
|
||||
// 对应 EnterpriseCardAuthStatus* 常量:0=已回收, 1=有效
|
||||
func GetEnterpriseCardAuthStatusName(status int) string {
|
||||
switch status {
|
||||
case EnterpriseCardAuthStatusRevoked:
|
||||
return "已回收"
|
||||
case EnterpriseCardAuthStatusValid:
|
||||
return "有效"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,15 @@ fi
|
||||
DB_DSN="postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=disable"
|
||||
ADMIN_DSN="postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/postgres?sslmode=disable"
|
||||
|
||||
# 检查 squash 基线文件是否存在(发布前必须生成,参见 migrations/README.md)
|
||||
if [ ! -f "migrations/000114_squash_baseline.up.sql" ]; then
|
||||
echo "❌ 错误:migrations/000114_squash_baseline.up.sql 不存在!"
|
||||
echo ""
|
||||
echo "全新数据库需要 squash 基线文件才能通过 migrate up 建表。"
|
||||
echo "请参考 migrations/README.md 的「发布前必做」章节生成该文件。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "警告:即将清空数据库 ${DB_NAME}(${DB_HOST}:${DB_PORT}),5 秒后继续..."
|
||||
echo "按 Ctrl+C 取消"
|
||||
sleep 5
|
||||
|
||||
Reference in New Issue
Block a user