345 lines
11 KiB
Go
345 lines
11 KiB
Go
package outbound
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchinput/excel"
|
|
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
|
|
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
)
|
|
|
|
type ExcelParseResult struct {
|
|
Rows []*Row
|
|
SubmitParam *model.TSimCardOutboundSubmitParam
|
|
}
|
|
|
|
type consistencyValue struct {
|
|
rowNo int
|
|
normalized string
|
|
}
|
|
|
|
func excelHeaders() []string {
|
|
return []string{
|
|
"ICCID",
|
|
"MSISDN",
|
|
"IMSI",
|
|
"客户/机构",
|
|
"套餐",
|
|
"套餐开始时间",
|
|
"购买时长(年)",
|
|
"赠送时长(月)",
|
|
"订单金额",
|
|
"线下合同/销售/走账已完成",
|
|
"备注",
|
|
}
|
|
}
|
|
|
|
func excelRequiredHeaders() []string {
|
|
return []string{"ICCID"}
|
|
}
|
|
|
|
func ParseExcelFile(ctx context.Context, filePath string) (*ExcelParseResult, error) {
|
|
parsedRows, err := excel.ParseFile(ctx, filePath, excel.ParseOptions{
|
|
RequiredHeaders: excelRequiredHeaders(),
|
|
SingleSheet: true,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return buildExcelParseResult(parsedRows), nil
|
|
}
|
|
|
|
func ParseExcelReader(ctx context.Context, reader io.Reader) (*ExcelParseResult, error) {
|
|
parsedRows, err := excel.ParseReader(ctx, reader, excel.ParseOptions{
|
|
RequiredHeaders: excelRequiredHeaders(),
|
|
SingleSheet: true,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return buildExcelParseResult(parsedRows), nil
|
|
}
|
|
|
|
func buildExcelParseResult(parsedRows []excel.ParsedRow) *ExcelParseResult {
|
|
rows := make([]*Row, 0, len(parsedRows))
|
|
consistentCustomerAgentId := consistencyValue{}
|
|
consistentPackageCode := consistencyValue{}
|
|
consistentPackageBeginTime := consistencyValue{}
|
|
consistentDurationYears := consistencyValue{}
|
|
consistentDurationMonthPart := consistencyValue{}
|
|
consistentGiftDurationYears := consistencyValue{}
|
|
consistentGiftDurationMonthPart := consistencyValue{}
|
|
consistentAmount := consistencyValue{}
|
|
consistentOfflineContractCompleted := consistencyValue{}
|
|
consistentRemark := consistencyValue{}
|
|
|
|
for _, parsed := range parsedRows {
|
|
row := &Row{
|
|
RowNo: parsed.RowNo,
|
|
Iccid: excel.Field(parsed, "ICCID"),
|
|
Msisdn: excel.Field(parsed, "MSISDN"),
|
|
Imsi: excel.Field(parsed, "IMSI"),
|
|
// 出库不再配置测试期、沉默期;1 表示否。
|
|
HasTestPeriod: 1,
|
|
HasSilentPeriod: 1,
|
|
}
|
|
|
|
parseRequiredPositiveInt(row, excelField(parsed, "customerAgentId"), "客户/机构", func(value int) {
|
|
row.CustomerAgentId = int64(value)
|
|
checkConsistency(row, "客户/机构", strconv.FormatInt(row.CustomerAgentId, 10), &consistentCustomerAgentId)
|
|
})
|
|
|
|
row.PackageCode = strings.TrimSpace(excelField(parsed, "packageCode"))
|
|
if row.PackageCode == "" {
|
|
row.AddReason("套餐不能为空")
|
|
} else {
|
|
checkConsistency(row, "套餐", row.PackageCode, &consistentPackageCode)
|
|
}
|
|
|
|
parseRequiredDateTime(row, excelField(parsed, "packageBeginTime"), "套餐开始时间", func(value *gtime.Time) {
|
|
row.PackageBeginTime = value
|
|
checkConsistency(row, "套餐开始时间", formatTime(value), &consistentPackageBeginTime)
|
|
})
|
|
|
|
parseExcelDuration(row, parsed, &consistentDurationYears, &consistentDurationMonthPart)
|
|
|
|
parseExcelGiftDuration(row, parsed, &consistentGiftDurationYears, &consistentGiftDurationMonthPart)
|
|
|
|
parseRequiredAmount(row, excelField(parsed, "amount"), func(value string) {
|
|
row.Amount = value
|
|
checkConsistency(row, "订单金额", value, &consistentAmount)
|
|
})
|
|
|
|
parseRequiredBool(row, excelField(parsed, "offlineContractCompleted"), "线下合同/销售/走账已完成", func(value bool) {
|
|
row.OfflineContractCompleted = value
|
|
checkConsistency(row, "线下合同/销售/走账已完成", strconv.FormatBool(value), &consistentOfflineContractCompleted)
|
|
})
|
|
|
|
row.Remark = strings.TrimSpace(excelField(parsed, "remark"))
|
|
checkConsistency(row, "备注", row.Remark, &consistentRemark)
|
|
|
|
rows = append(rows, row)
|
|
}
|
|
|
|
result := &ExcelParseResult{Rows: rows}
|
|
if hasInvalidRows(rows) {
|
|
return result
|
|
}
|
|
result.SubmitParam = &model.TSimCardOutboundSubmitParam{
|
|
CustomerAgentId: rows[0].CustomerAgentId,
|
|
PackageCode: rows[0].PackageCode,
|
|
PackageBeginTime: rows[0].PackageBeginTime,
|
|
DurationYears: rows[0].DurationYears,
|
|
DurationMonthPart: rows[0].DurationMonthPart,
|
|
DurationMonths: rows[0].DurationMonths,
|
|
GiftDurationYears: rows[0].GiftDurationYears,
|
|
GiftDurationMonthPart: rows[0].GiftDurationMonthPart,
|
|
GiftDurationMonths: rows[0].GiftDurationMonths,
|
|
HasTestPeriod: 1,
|
|
HasSilentPeriod: 1,
|
|
Amount: rows[0].Amount,
|
|
OfflineContractCompleted: rows[0].OfflineContractCompleted,
|
|
Remark: rows[0].Remark,
|
|
BuyerNote: rows[0].Remark,
|
|
AdminNote: rows[0].Remark,
|
|
}
|
|
return result
|
|
}
|
|
|
|
func excelField(row excel.ParsedRow, name string) string {
|
|
for _, alias := range excelFieldAliases(name) {
|
|
if value := strings.TrimSpace(excel.Field(row, alias)); value != "" {
|
|
return value
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func excelFieldAliases(name string) []string {
|
|
switch name {
|
|
case "customerAgentId":
|
|
return []string{"客户/机构", "客户/机构ID", "客户ID", "customerAgentId"}
|
|
case "packageCode":
|
|
return []string{"套餐", "套餐编码", "packageCode"}
|
|
case "packageBeginTime":
|
|
return []string{"套餐开始时间", "packageBeginTime"}
|
|
case "durationYears":
|
|
return []string{"购买时长(年)", "套餐购买时长(年)", "durationYears"}
|
|
case "durationMonthPart":
|
|
return []string{"购买时长(月)", "套餐购买时长(月)", "durationMonthPart"}
|
|
case "durationMonths":
|
|
return []string{"durationMonths"}
|
|
case "giftDurationYears":
|
|
return []string{"赠送时长(年)", "giftDurationYears"}
|
|
case "giftDurationMonthPart":
|
|
return []string{"赠送时长(月)", "giftDurationMonthPart"}
|
|
case "giftDurationMonths":
|
|
return []string{"giftDurationMonths"}
|
|
case "amount":
|
|
return []string{"订单金额", "amount"}
|
|
case "offlineContractCompleted":
|
|
return []string{"线下合同/销售/走账已完成", "是否走线下", "offlineContractCompleted"}
|
|
case "remark":
|
|
return []string{"备注", "remark", "buyerNote", "adminNote"}
|
|
default:
|
|
return []string{name}
|
|
}
|
|
}
|
|
|
|
func parseExcelDuration(row *Row, parsed excel.ParsedRow, consistentYears, consistentMonthPart *consistencyValue) {
|
|
yearsRaw := excelField(parsed, "durationYears")
|
|
monthPartRaw := excelField(parsed, "durationMonthPart")
|
|
if strings.TrimSpace(yearsRaw) != "" || strings.TrimSpace(monthPartRaw) != "" {
|
|
parseOptionalNonNegativeInt(row, yearsRaw, "购买时长(年)", 0, func(value int) {
|
|
row.DurationYears = value
|
|
checkConsistency(row, "购买时长(年)", strconv.Itoa(value), consistentYears)
|
|
})
|
|
parseOptionalMonthPart(row, monthPartRaw, "购买时长(月)", func(value int) {
|
|
row.DurationMonthPart = value
|
|
checkConsistency(row, "购买时长(月)", strconv.Itoa(value), consistentMonthPart)
|
|
})
|
|
row.DurationMonths = row.DurationYears*12 + row.DurationMonthPart
|
|
if row.DurationMonths <= 0 {
|
|
row.AddReason("购买时长必须大于0")
|
|
}
|
|
return
|
|
}
|
|
parseRequiredPositiveInt(row, excelField(parsed, "durationMonths"), "套餐购买时长(月)", func(value int) {
|
|
row.DurationMonths = value
|
|
row.DurationYears = value / 12
|
|
row.DurationMonthPart = value % 12
|
|
checkConsistency(row, "套餐购买时长(月)", strconv.Itoa(value), consistentMonthPart)
|
|
})
|
|
}
|
|
|
|
func parseExcelGiftDuration(row *Row, parsed excel.ParsedRow, consistentYears, consistentMonthPart *consistencyValue) {
|
|
yearsRaw := excelField(parsed, "giftDurationYears")
|
|
monthPartRaw := excelField(parsed, "giftDurationMonthPart")
|
|
if strings.TrimSpace(yearsRaw) != "" || strings.TrimSpace(monthPartRaw) != "" {
|
|
parseOptionalNonNegativeInt(row, yearsRaw, "赠送时长(年)", 0, func(value int) {
|
|
row.GiftDurationYears = value
|
|
checkConsistency(row, "赠送时长(年)", strconv.Itoa(value), consistentYears)
|
|
})
|
|
parseOptionalMonthPart(row, monthPartRaw, "赠送时长(月)", func(value int) {
|
|
row.GiftDurationMonthPart = value
|
|
checkConsistency(row, "赠送时长(月)", strconv.Itoa(value), consistentMonthPart)
|
|
})
|
|
row.GiftDurationMonths = row.GiftDurationYears*12 + row.GiftDurationMonthPart
|
|
return
|
|
}
|
|
parseOptionalNonNegativeInt(row, excelField(parsed, "giftDurationMonths"), "赠送时长(月)", 0, func(value int) {
|
|
row.GiftDurationMonths = value
|
|
row.GiftDurationYears = value / 12
|
|
row.GiftDurationMonthPart = value % 12
|
|
checkConsistency(row, "赠送时长(月)", strconv.Itoa(value), consistentMonthPart)
|
|
})
|
|
}
|
|
|
|
func checkConsistency(row *Row, field, normalized string, base *consistencyValue) {
|
|
if row == nil || !row.Valid() {
|
|
return
|
|
}
|
|
if base.rowNo == 0 {
|
|
base.rowNo = row.RowNo
|
|
base.normalized = normalized
|
|
return
|
|
}
|
|
if base.normalized != normalized {
|
|
row.AddReason(fmt.Sprintf("%s与第%d行不一致", field, base.rowNo))
|
|
}
|
|
}
|
|
|
|
func parseRequiredPositiveInt(row *Row, raw, field string, apply func(value int)) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
row.AddReason(field + "不能为空")
|
|
return
|
|
}
|
|
value, err := excel.ParsePositiveInt(raw)
|
|
if err != nil {
|
|
row.AddReason(field + "格式不正确")
|
|
return
|
|
}
|
|
apply(value)
|
|
}
|
|
|
|
func parseOptionalNonNegativeInt(row *Row, raw, field string, defaultValue int, apply func(value int)) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
apply(defaultValue)
|
|
return
|
|
}
|
|
value, err := excel.ParseNonNegativeInt(raw)
|
|
if err != nil {
|
|
row.AddReason(field + "格式不正确")
|
|
return
|
|
}
|
|
apply(value)
|
|
}
|
|
|
|
func parseOptionalMonthPart(row *Row, raw, field string, apply func(value int)) {
|
|
parseOptionalNonNegativeInt(row, raw, field, 0, func(value int) {
|
|
if value > 11 {
|
|
row.AddReason(field + "必须在0到11之间")
|
|
return
|
|
}
|
|
apply(value)
|
|
})
|
|
}
|
|
|
|
func parseOptionalAmount(row *Row, raw string, apply func(value string)) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
apply("")
|
|
return
|
|
}
|
|
value, err := excel.ParseAmount(raw)
|
|
if err != nil {
|
|
row.AddReason("订单金额格式不正确")
|
|
return
|
|
}
|
|
apply(fmt.Sprintf("%.2f", value))
|
|
}
|
|
|
|
func parseRequiredAmount(row *Row, raw string, apply func(value string)) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
row.AddReason("订单金额不能为空")
|
|
return
|
|
}
|
|
parseOptionalAmount(row, raw, apply)
|
|
}
|
|
|
|
func parseRequiredBool(row *Row, raw, field string, apply func(value bool)) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
row.AddReason(field + "不能为空")
|
|
return
|
|
}
|
|
value, err := excel.ParseBool(raw)
|
|
if err != nil {
|
|
row.AddReason(field + "格式不正确")
|
|
return
|
|
}
|
|
apply(value)
|
|
}
|
|
|
|
func parseRequiredDateTime(row *Row, raw, field string, apply func(value *gtime.Time)) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
row.AddReason(field + "不能为空")
|
|
return
|
|
}
|
|
value, err := excel.ParseDateTime(raw)
|
|
if err != nil {
|
|
row.AddReason(field + "格式不正确")
|
|
return
|
|
}
|
|
apply(value)
|
|
}
|