作者 陈志颖

fix:冲突

@@ -25,3 +25,4 @@ @@ -25,3 +25,4 @@
25 25
26 /*.exe~ 26 /*.exe~
27 /logs 27 /logs
  28 +download
@@ -7,6 +7,7 @@ require ( @@ -7,6 +7,7 @@ require (
7 github.com/Shopify/sarama v1.23.1 7 github.com/Shopify/sarama v1.23.1
8 github.com/ajg/form v1.5.1 // indirect 8 github.com/ajg/form v1.5.1 // indirect
9 github.com/astaxie/beego v1.12.2 9 github.com/astaxie/beego v1.12.2
  10 + github.com/beego/beego/v2 v2.0.1
10 github.com/bsm/sarama-cluster v2.1.15+incompatible 11 github.com/bsm/sarama-cluster v2.1.15+incompatible
11 github.com/dgrijalva/jwt-go v3.2.0+incompatible 12 github.com/dgrijalva/jwt-go v3.2.0+incompatible
12 github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect 13 github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect
@@ -7,14 +7,25 @@ type ListOrderBaseQuery struct { @@ -7,14 +7,25 @@ type ListOrderBaseQuery struct {
7 // 查询限制 7 // 查询限制
8 Limit int `json:"limit"` 8 Limit int `json:"limit"`
9 //发货单号 9 //发货单号
10 - PartnerOrCode string `json:"partnerOrCode"`  
11 - CompanyId int64 `json:"companyId"` 10 + //PartnerOrCode string `json:"partnerOrCode"`
  11 + //合伙人姓名
  12 + PartnerName string `json:"partnerName"`
  13 + //订单号
  14 + OrderCode string `json:"orderCode"`
  15 + //发货单号
  16 + DeliveryCode string `json:"deliveryCode"`
  17 + //公司id
  18 + CompanyId int64 `json:"companyId"`
12 //订单类型 19 //订单类型
13 OrderType int `json:"orderType"` 20 OrderType int `json:"orderType"`
14 //合伙人分类 21 //合伙人分类
15 - PartnerCategory int `json:"partnerCategory"` 22 + PartnerCategory int `json:"partnerCategory"`
  23 + //更新时间开始
16 UpdateTimeBegin string `json:"updateTimeBegin"` 24 UpdateTimeBegin string `json:"updateTimeBegin"`
17 - UpdateTimeEnd string `json:"updateTimeEnd"` 25 + //更新时间截止
  26 + UpdateTimeEnd string `json:"updateTimeEnd"`
  27 + //创建时间开始
18 CreateTimeBegin string `json:"createTimeBegin"` 28 CreateTimeBegin string `json:"createTimeBegin"`
19 - CreateTimeEnd string `json:"createTimeEnd"` 29 + //创建时间截止
  30 + CreateTimeEnd string `json:"createTimeEnd"`
20 } 31 }
@@ -26,7 +26,13 @@ func NewOrderInfoService(option map[string]interface{}) *OrderInfoService { @@ -26,7 +26,13 @@ func NewOrderInfoService(option map[string]interface{}) *OrderInfoService {
26 return newAdminUserService 26 return newAdminUserService
27 } 27 }
28 28
29 -// PageListOrderBase 获取订单列表 29 +/**
  30 + * @Author SteveChan
  31 + * @Description // 获取订单列表
  32 + * @Date 22:05 2021/1/10
  33 + * @Param
  34 + * @return
  35 + **/
30 func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrderBaseQuery) ([]map[string]interface{}, int, error) { 36 func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrderBaseQuery) ([]map[string]interface{}, int, error) {
31 var err error 37 var err error
32 transactionContext, err := factory.CreateTransactionContext(nil) 38 transactionContext, err := factory.CreateTransactionContext(nil)
@@ -53,7 +59,9 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder @@ -53,7 +59,9 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder
53 orders, cnt, err = orderDao.OrderListByCondition( 59 orders, cnt, err = orderDao.OrderListByCondition(
54 listOrderQuery.CompanyId, 60 listOrderQuery.CompanyId,
55 listOrderQuery.OrderType, 61 listOrderQuery.OrderType,
56 - listOrderQuery.PartnerOrCode, 62 + listOrderQuery.PartnerName, // 合伙人姓名
  63 + listOrderQuery.OrderCode, // 订单号
  64 + listOrderQuery.DeliveryCode, // 发货单号
57 [2]string{listOrderQuery.UpdateTimeBegin, listOrderQuery.UpdateTimeEnd}, 65 [2]string{listOrderQuery.UpdateTimeBegin, listOrderQuery.UpdateTimeEnd},
58 [2]string{listOrderQuery.CreateTimeBegin, listOrderQuery.CreateTimeEnd}, 66 [2]string{listOrderQuery.CreateTimeBegin, listOrderQuery.CreateTimeEnd},
59 listOrderQuery.PartnerCategory, 67 listOrderQuery.PartnerCategory,
@@ -865,6 +873,13 @@ func (service OrderInfoService) ListOrderBonusForExcel(listOrderQuery query.List @@ -865,6 +873,13 @@ func (service OrderInfoService) ListOrderBonusForExcel(listOrderQuery query.List
865 return resultMaps, column, nil 873 return resultMaps, column, nil
866 } 874 }
867 875
  876 +/**
  877 + * @Author SteveChan
  878 + * @Description // 导出订单数据
  879 + * @Date 22:05 2021/1/10
  880 + * @Param
  881 + * @return
  882 + **/
868 func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrderBaseQuery) ([]map[string]string, [][2]string, error) { 883 func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrderBaseQuery) ([]map[string]string, [][2]string, error) {
869 transactionContext, err := factory.CreateTransactionContext(nil) 884 transactionContext, err := factory.CreateTransactionContext(nil)
870 if err != nil { 885 if err != nil {
@@ -876,6 +891,7 @@ func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrder @@ -876,6 +891,7 @@ func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrder
876 defer func() { 891 defer func() {
877 transactionContext.RollbackTransaction() 892 transactionContext.RollbackTransaction()
878 }() 893 }()
  894 +
879 var ( 895 var (
880 orderBaseDao *dao.OrderBaseDao 896 orderBaseDao *dao.OrderBaseDao
881 ) 897 )
@@ -887,7 +903,9 @@ func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrder @@ -887,7 +903,9 @@ func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrder
887 } 903 }
888 ordersData, err := orderBaseDao.OrderListForExcel( 904 ordersData, err := orderBaseDao.OrderListForExcel(
889 listOrderQuery.CompanyId, 905 listOrderQuery.CompanyId,
890 - listOrderQuery.PartnerOrCode, 906 + listOrderQuery.PartnerName, // 合伙人姓名
  907 + listOrderQuery.OrderCode, // 订单号
  908 + listOrderQuery.DeliveryCode, // 发货单号
891 [2]string{listOrderQuery.UpdateTimeBegin, listOrderQuery.UpdateTimeEnd}, 909 [2]string{listOrderQuery.UpdateTimeBegin, listOrderQuery.UpdateTimeEnd},
892 [2]string{listOrderQuery.CreateTimeBegin, listOrderQuery.CreateTimeEnd}, 910 [2]string{listOrderQuery.CreateTimeBegin, listOrderQuery.CreateTimeEnd},
893 listOrderQuery.PartnerCategory, 911 listOrderQuery.PartnerCategory,
@@ -944,28 +962,29 @@ func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrder @@ -944,28 +962,29 @@ func (service OrderInfoService) ListOrderForExcel(listOrderQuery query.ListOrder
944 962
945 /** 963 /**
946 * @Author SteveChan 964 * @Author SteveChan
947 - * @Description // 批量导入创建订单 965 + * @Description //TODO 批量导入创建订单
948 * @Date 11:00 2021/1/7 966 * @Date 11:00 2021/1/7
949 * @Param 967 * @Param
950 * @return 968 * @return
951 **/ 969 **/
952 -func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*command.CreateOrderCommand) ([]interface{}, error) { 970 +func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*command.CreateOrderCommand) ([]*domain.ImportInfo, error) {
953 // 事务初始化 971 // 事务初始化
954 var ( 972 var (
955 transactionContext, _ = factory.CreateTransactionContext(nil) 973 transactionContext, _ = factory.CreateTransactionContext(nil)
956 err error 974 err error
957 - failureDataList []interface{} // 错误数据返回 975 + errorDataList []*domain.ImportInfo // 错误数据返回
958 ) 976 )
959 977
960 // 循环校验命令 978 // 循环校验命令
961 for _, cmd := range createOrderCommands { 979 for _, cmd := range createOrderCommands {
962 if err = cmd.Valid(); err != nil { 980 if err = cmd.Valid(); err != nil {
963 // 返回信息 0: 订单号, 1: 发货单号, 2: 客户名称, 3: 订单区域, 4: 编号, 5: 合伙人, 6: 类型, 7: 业务抽成比例, 8: 产品名称, 9: 数量, 10: 单价, 11: 合伙人分红比例 981 // 返回信息 0: 订单号, 1: 发货单号, 2: 客户名称, 3: 订单区域, 4: 编号, 5: 合伙人, 6: 类型, 7: 业务抽成比例, 8: 产品名称, 9: 数量, 10: 单价, 11: 合伙人分红比例
964 - row := []interface{}{  
965 - lib.ThrowError(lib.BUSINESS_ERROR, err.Error()), // 错误信息  
966 - cmd.LineNumbers, // 错误影响的行 982 + row := &domain.ImportInfo{
  983 + Error: lib.ThrowError(lib.BUSINESS_ERROR, err.Error()), // 错误信息
  984 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  985 + GoodLine: map[int]interface{}{},
967 } 986 }
968 - failureDataList = append(failureDataList, row) 987 + errorDataList = append(errorDataList, row)
969 continue 988 continue
970 } 989 }
971 } 990 }
@@ -987,6 +1006,7 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co @@ -987,6 +1006,7 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co
987 categoryRepository domain.PartnerCategoryRepository 1006 categoryRepository domain.PartnerCategoryRepository
988 orderBaseDao *dao.OrderBaseDao 1007 orderBaseDao *dao.OrderBaseDao
989 ) 1008 )
  1009 +
990 // 合伙人信息仓储初始化 1010 // 合伙人信息仓储初始化
991 if PartnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{ 1011 if PartnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
992 "transactionContext": transactionContext, 1012 "transactionContext": transactionContext,
@@ -1028,26 +1048,55 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co @@ -1028,26 +1048,55 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co
1028 var partnerData *domain.PartnerInfo 1048 var partnerData *domain.PartnerInfo
1029 partnerData, err = PartnerInfoRepository.FindOne(domain.PartnerFindOneQuery{UserId: cmd.PartnerId}) 1049 partnerData, err = PartnerInfoRepository.FindOne(domain.PartnerFindOneQuery{UserId: cmd.PartnerId})
1030 if err != nil { 1050 if err != nil {
1031 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("检索合伙人数据失败")) 1051 + row := &domain.ImportInfo{
  1052 + Error: lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("检索合伙人数据失败")),
  1053 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1054 + GoodLine: map[int]interface{}{},
  1055 + }
  1056 + errorDataList = append(errorDataList, row)
  1057 + continue
1032 } 1058 }
1033 1059
1034 // 批量校验订单 1060 // 批量校验订单
1035 if ok, err := orderBaseDao.CheckOrderExist(cmd.CompanyId, cmd.OrderCode, cmd.DeliveryCode, 1061 if ok, err := orderBaseDao.CheckOrderExist(cmd.CompanyId, cmd.OrderCode, cmd.DeliveryCode,
1036 cmd.PartnerCategory, cmd.PartnerId, 0); err != nil { 1062 cmd.PartnerCategory, cmd.PartnerId, 0); err != nil {
1037 - return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 1063 + row := &domain.ImportInfo{
  1064 + Error: lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()),
  1065 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1066 + GoodLine: map[int]interface{}{},
  1067 + }
  1068 + errorDataList = append(errorDataList, row)
  1069 + continue
1038 } else if ok { 1070 } else if ok {
1039 - return nil, lib.ThrowError(lib.BUSINESS_ERROR, "订单已存在") 1071 + row := &domain.ImportInfo{
  1072 + Error: lib.ThrowError(lib.BUSINESS_ERROR, "订单已存在"),
  1073 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1074 + GoodLine: map[int]interface{}{},
  1075 + }
  1076 + errorDataList = append(errorDataList, row)
  1077 + continue
1040 } 1078 }
1041 1079
1042 // 批量校验产品 1080 // 批量校验产品
1043 var goodMap = map[string]int{} 1081 var goodMap = map[string]int{}
  1082 + goodErrMap := make(map[int]interface{}, 0)
1044 for i := range cmd.Goods { 1083 for i := range cmd.Goods {
1045 goodName := cmd.Goods[i].GoodName 1084 goodName := cmd.Goods[i].GoodName
1046 if _, ok := goodMap[goodName]; ok { 1085 if _, ok := goodMap[goodName]; ok {
1047 - return nil, lib.ThrowError(lib.BUSINESS_ERROR, "订单中货品重复已存在") 1086 + goodErrMap[cmd.Goods[i].LineNumber] = lib.ThrowError(lib.BUSINESS_ERROR, "订单中货品重复已存在")
  1087 + continue
1048 } 1088 }
1049 goodMap[goodName] = 1 1089 goodMap[goodName] = 1
1050 } 1090 }
  1091 + if len(goodErrMap) > 0 {
  1092 + row := &domain.ImportInfo{
  1093 + Error: lib.ThrowError(lib.BUSINESS_ERROR, "订单中货品重复已存在"),
  1094 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1095 + GoodLine: goodErrMap, // 错误产品行号记录
  1096 + }
  1097 + errorDataList = append(errorDataList, row)
  1098 + continue
  1099 + }
1051 1100
1052 newOrder := &domain.OrderBase{ 1101 newOrder := &domain.OrderBase{
1053 OrderType: cmd.OrderType, OrderCode: cmd.OrderCode, 1102 OrderType: cmd.OrderType, OrderCode: cmd.OrderCode,
@@ -1083,12 +1132,19 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co @@ -1083,12 +1132,19 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co
1083 } 1132 }
1084 } 1133 }
1085 if !cmdPartnerCategoryOk { 1134 if !cmdPartnerCategoryOk {
1086 - return nil, lib.ThrowError(lib.BUSINESS_ERROR, "合伙人类型选择错误") 1135 + row := &domain.ImportInfo{
  1136 + Error: lib.ThrowError(lib.BUSINESS_ERROR, "合伙人类型选择错误"),
  1137 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1138 + GoodLine: map[int]interface{}{},
  1139 + }
  1140 + errorDataList = append(errorDataList, row)
  1141 + continue
1087 } 1142 }
1088 1143
1089 // 订单产品分红核算 1144 // 订单产品分红核算
1090 var orderGoods []domain.OrderGood 1145 var orderGoods []domain.OrderGood
1091 - for _, good := range cmd.Goods { 1146 + orderGoodErrMap := make(map[int]interface{}, 0)
  1147 + for i, good := range cmd.Goods {
1092 m := domain.NewOrderGood() 1148 m := domain.NewOrderGood()
1093 m.OrderId = 0 1149 m.OrderId = 0
1094 m.GoodName = good.GoodName 1150 m.GoodName = good.GoodName
@@ -1097,28 +1153,54 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co @@ -1097,28 +1153,54 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co
1097 m.PartnerBonusPercent = good.PartnerBonusPercent 1153 m.PartnerBonusPercent = good.PartnerBonusPercent
1098 m.Remark = good.Remark 1154 m.Remark = good.Remark
1099 m.CompanyId = cmd.CompanyId 1155 m.CompanyId = cmd.CompanyId
  1156 +
1100 err = m.Compute() 1157 err = m.Compute()
1101 if err != nil { 1158 if err != nil {
1102 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("核算订单中商品的数值失败:%s", err)) 1159 + orderGoodErrMap[cmd.Goods[i].LineNumber] = lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("核算订单中商品的数值失败:%s", err))
  1160 + continue
1103 } 1161 }
  1162 +
1104 err = m.CurrentBonusStatus.WartPayPartnerBonus(&m) 1163 err = m.CurrentBonusStatus.WartPayPartnerBonus(&m)
1105 if err != nil { 1164 if err != nil {
1106 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("核算订单中商品的分红数值失败:%s", err)) 1165 + orderGoodErrMap[cmd.Goods[i].LineNumber] = lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("核算订单中商品的分红数值失败:%s", err))
  1166 + continue
1107 } 1167 }
  1168 +
1108 orderGoods = append(orderGoods, m) 1169 orderGoods = append(orderGoods, m)
1109 } 1170 }
  1171 + if len(orderGoodErrMap) > 0 {
  1172 + row := &domain.ImportInfo{
  1173 + Error: lib.ThrowError(lib.BUSINESS_ERROR, "核算订单中商品错误"),
  1174 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1175 + GoodLine: orderGoodErrMap, // 错误产品行号记录
  1176 + }
  1177 + errorDataList = append(errorDataList, row)
  1178 + continue
  1179 + }
1110 1180
1111 newOrder.Goods = orderGoods 1181 newOrder.Goods = orderGoods
1112 1182
1113 err = newOrder.Compute() 1183 err = newOrder.Compute()
1114 if err != nil { 1184 if err != nil {
1115 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("核算订单中合计的数值失败:%s", err)) 1185 + row := &domain.ImportInfo{
  1186 + Error: lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("核算订单中合计的数值失败:%s", err)),
  1187 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1188 + GoodLine: map[int]interface{}{},
  1189 + }
  1190 + errorDataList = append(errorDataList, row)
  1191 + continue
1116 } 1192 }
1117 1193
1118 // 保存订单数据 1194 // 保存订单数据
1119 err = orderBaseRepository.Save(newOrder) 1195 err = orderBaseRepository.Save(newOrder)
1120 if err != nil { 1196 if err != nil {
1121 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("保存订单数据失败:%s", err)) 1197 + row := &domain.ImportInfo{
  1198 + Error: lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("保存订单数据失败:%s", err)),
  1199 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1200 + GoodLine: map[int]interface{}{},
  1201 + }
  1202 + errorDataList = append(errorDataList, row)
  1203 + continue
1122 } 1204 }
1123 1205
1124 for i := range newOrder.Goods { 1206 for i := range newOrder.Goods {
@@ -1128,22 +1210,27 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co @@ -1128,22 +1210,27 @@ func (service OrderInfoService) CreateNewOrderByImport(createOrderCommands []*co
1128 // 保存订单产品 1210 // 保存订单产品
1129 err = orderGoodRepository.Save(orderGoods) 1211 err = orderGoodRepository.Save(orderGoods)
1130 if err != nil { 1212 if err != nil {
1131 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("保存订单中的商品数据失败:%s", err)) 1213 + row := &domain.ImportInfo{
  1214 + Error: lib.ThrowError(lib.INTERNAL_SERVER_ERROR, fmt.Sprintf("保存订单中的商品数据失败:%s", err)),
  1215 + LineNumbers: cmd.LineNumbers, // 错误影响的行
  1216 + GoodLine: map[int]interface{}{},
  1217 + }
  1218 + errorDataList = append(errorDataList, row)
  1219 + continue
1132 } 1220 }
1133 -  
1134 newOrder.Goods = orderGoods 1221 newOrder.Goods = orderGoods
1135 } 1222 }
1136 1223
1137 - if len(failureDataList) == 0 { 1224 + if len(errorDataList) == 0 {
1138 // 完成事务 1225 // 完成事务
1139 err = transactionContext.CommitTransaction() 1226 err = transactionContext.CommitTransaction()
1140 if err != nil { 1227 if err != nil {
1141 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 1228 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
1142 } 1229 }
1143 - return failureDataList, nil 1230 + return errorDataList, nil
1144 } 1231 }
1145 1232
1146 - return failureDataList, nil 1233 + return errorDataList, nil
1147 } 1234 }
1148 1235
1149 /** 1236 /**
@@ -6,6 +6,7 @@ const SERVICE_NAME = "partnermg" @@ -6,6 +6,7 @@ const SERVICE_NAME = "partnermg"
6 6
7 var LOG_LEVEL = "debug" 7 var LOG_LEVEL = "debug"
8 var LOG_File = "./logs/partnermg.log" 8 var LOG_File = "./logs/partnermg.log"
  9 +var IMPORT_EXCEL = "./download/订单数据模板.xlsx"
9 var Log_PREFIX = "[partnermg_dev]" 10 var Log_PREFIX = "[partnermg_dev]"
10 var ( 11 var (
11 UCENTER_HOST = "https://suplus-ucenter-test.fjmaimaimai.com" //统一用户中心地址 12 UCENTER_HOST = "https://suplus-ucenter-test.fjmaimaimai.com" //统一用户中心地址
@@ -14,7 +14,7 @@ var KafkaCfg KafkaConfig @@ -14,7 +14,7 @@ var KafkaCfg KafkaConfig
14 14
15 func init() { 15 func init() {
16 KafkaCfg = KafkaConfig{ 16 KafkaCfg = KafkaConfig{
17 - Servers: []string{"106.52.15.41:9092"}, 17 + Servers: []string{"127.0.0.1:9092"},
18 ConsumerId: "partnermg_dev", 18 ConsumerId: "partnermg_dev",
19 } 19 }
20 if os.Getenv("KAFKA_HOST") != "" { 20 if os.Getenv("KAFKA_HOST") != "" {
@@ -314,6 +314,17 @@ type OrderBaseFindQuery struct { @@ -314,6 +314,17 @@ type OrderBaseFindQuery struct {
314 CompanyId int64 314 CompanyId int64
315 } 315 }
316 316
  317 +// 导入错误信息
  318 +type ImportInfo struct {
  319 + Error error
  320 + LineNumbers []int
  321 + GoodLine map[int]interface{}
  322 +}
  323 +
  324 +// 导入产品错误信息
  325 +type GoodErrInfo struct {
  326 +}
  327 +
317 type OrderBaseRepository interface { 328 type OrderBaseRepository interface {
318 Save(order *OrderBase) error 329 Save(order *OrderBase) error
319 FindOne(qureyOptions OrderBaseFindOneQuery) (*OrderBase, error) 330 FindOne(qureyOptions OrderBaseFindOneQuery) (*OrderBase, error)
@@ -186,7 +186,7 @@ func (dao OrderBaseDao) OrderBonusListForExcel(companyId int64, orderType int, p @@ -186,7 +186,7 @@ func (dao OrderBaseDao) OrderBonusListForExcel(companyId int64, orderType int, p
186 //@param partnerCategory 合伙人类型id 186 //@param partnerCategory 合伙人类型id
187 //@param updateTime 订单更新时间范围"[开始时间,结束时间]",时间格式"2006-01-02 15:04:05+07" 187 //@param updateTime 订单更新时间范围"[开始时间,结束时间]",时间格式"2006-01-02 15:04:05+07"
188 //@param createTime 订单的创建时间范围"[开始时间,结束时间]" 时间格式"2006-01-02 15:04:05+07" 188 //@param createTime 订单的创建时间范围"[开始时间,结束时间]" 时间格式"2006-01-02 15:04:05+07"
189 -func (dao OrderBaseDao) OrderListByCondition(companyId int64, orderType int, partnerOrCode string, 189 +func (dao OrderBaseDao) OrderListByCondition(companyId int64, orderType int, partnerName string, orderCode string, deliveryCode string,
190 updateTime [2]string, createTime [2]string, partnerCategory int, limit, offset int) ([]models.OrderBase, int, error) { 190 updateTime [2]string, createTime [2]string, partnerCategory int, limit, offset int) ([]models.OrderBase, int, error) {
191 tx := dao.transactionContext.GetDB() 191 tx := dao.transactionContext.GetDB()
192 var orders []models.OrderBase 192 var orders []models.OrderBase
@@ -211,16 +211,25 @@ func (dao OrderBaseDao) OrderListByCondition(companyId int64, orderType int, par @@ -211,16 +211,25 @@ func (dao OrderBaseDao) OrderListByCondition(companyId int64, orderType int, par
211 if len(createTime[1]) > 0 { 211 if len(createTime[1]) > 0 {
212 query = query.Where(`order_base.create_time<=?`, createTime[1]) 212 query = query.Where(`order_base.create_time<=?`, createTime[1])
213 } 213 }
214 -  
215 - if len(partnerOrCode) > 0 { 214 + if len(partnerName) > 0 {
216 query = query.Join("LEFT JOIN partner_info as p ON order_base.partner_id=p.id"). 215 query = query.Join("LEFT JOIN partner_info as p ON order_base.partner_id=p.id").
217 - WhereGroup(func(q *orm.Query) (*orm.Query, error) {  
218 - q = q.WhereOr("order_base.order_code like ? ", "%"+partnerOrCode+"%").  
219 - WhereOr("order_base.delivery_code like ? ", "%"+partnerOrCode+"%").  
220 - WhereOr("p.partner_name like ? ", "%"+partnerOrCode+"%")  
221 - return q, nil  
222 - }) 216 + Where("p.partner_name like ? ", "%"+partnerName+"%")
  217 + }
  218 + if len(orderCode) > 0 {
  219 + query = query.Where("order_base.order_code like ? ", "%"+orderCode+"%")
223 } 220 }
  221 + if len(deliveryCode) > 0 {
  222 + query = query.Where("order_base.delivery_code like ? ", "%"+deliveryCode+"%")
  223 + }
  224 + //if len(partnerOrCode) > 0 {
  225 + // query = query.Join("LEFT JOIN partner_info as p ON order_base.partner_id=p.id").
  226 + // WhereGroup(func(q *orm.Query) (*orm.Query, error) {
  227 + // q = q.WhereOr("order_base.order_code like ? ", "%"+partnerOrCode+"%").
  228 + // WhereOr("order_base.delivery_code like ? ", "%"+partnerOrCode+"%").
  229 + // WhereOr("p.partner_name like ? ", "%"+partnerOrCode+"%")
  230 + // return q, nil
  231 + // })
  232 + //}
224 query = query.Order("order_base.create_time DESC"). 233 query = query.Order("order_base.create_time DESC").
225 Offset(offset). 234 Offset(offset).
226 Limit(limit) 235 Limit(limit)
@@ -253,7 +262,7 @@ type CustomOrderListForExcel struct { @@ -253,7 +262,7 @@ type CustomOrderListForExcel struct {
253 //@param partnerCategory 合伙人类型id 262 //@param partnerCategory 合伙人类型id
254 //@param updateTime 订单更新时间范围"[开始时间,结束时间]",时间格式"2006-01-02 15:04:05+07" 263 //@param updateTime 订单更新时间范围"[开始时间,结束时间]",时间格式"2006-01-02 15:04:05+07"
255 //@param createTime 订单的创建时间范围"[开始时间,结束时间]" 时间格式"2006-01-02 15:04:05+07" 264 //@param createTime 订单的创建时间范围"[开始时间,结束时间]" 时间格式"2006-01-02 15:04:05+07"
256 -func (dao OrderBaseDao) OrderListForExcel(companyId int64, partnerOrCode string, 265 +func (dao OrderBaseDao) OrderListForExcel(companyId int64, partnerName string, orderCode string, deliveryCode string,
257 updateTime [2]string, createTime [2]string, partnerCategory int) ( 266 updateTime [2]string, createTime [2]string, partnerCategory int) (
258 result []CustomOrderListForExcel, err error) { 267 result []CustomOrderListForExcel, err error) {
259 sqlstr := ` 268 sqlstr := `
@@ -269,12 +278,26 @@ func (dao OrderBaseDao) OrderListForExcel(companyId int64, partnerOrCode string, @@ -269,12 +278,26 @@ func (dao OrderBaseDao) OrderListForExcel(companyId int64, partnerOrCode string,
269 WHERE 1=1 AND t1.order_type = 1 AND t1.company_id=? 278 WHERE 1=1 AND t1.order_type = 1 AND t1.company_id=?
270 ` 279 `
271 params := []interface{}{companyId} 280 params := []interface{}{companyId}
272 - if len(partnerOrCode) > 0 {  
273 - like := "%" + partnerOrCode + "%"  
274 - params = append(params, like, like, like)  
275 - sqlstr += " AND (t1.order_code like ? OR t1.delivery_code like ? OR t2.partner_name like ? ) " 281 + //if len(partnerOrCode) > 0 {
  282 + // like := "%" + partnerOrCode + "%"
  283 + // params = append(params, like, like, like)
  284 + // sqlstr += " AND (t1.order_code like ? OR t1.delivery_code like ? OR t2.partner_name like ? ) "
  285 + //}
  286 + if len(partnerName) > 0 {
  287 + like := "%" + partnerName + "%"
  288 + params = append(params, like)
  289 + sqlstr += ` AND t2.partner_name like ? `
  290 + }
  291 + if len(orderCode) > 0 {
  292 + like := "%" + orderCode + "%"
  293 + params = append(params, like)
  294 + sqlstr += ` AND t1.order_code like ? `
  295 + }
  296 + if len(deliveryCode) > 0 {
  297 + like := "%" + deliveryCode + "%"
  298 + params = append(params, like)
  299 + sqlstr += ` AND t1.delivery_code like ? `
276 } 300 }
277 -  
278 if partnerCategory > 0 { 301 if partnerCategory > 0 {
279 params = append(params, partnerCategory) 302 params = append(params, partnerCategory)
280 sqlstr += ` AND t1.partner_category@>'{"id":?}' ` 303 sqlstr += ` AND t1.partner_category@>'{"id":?}' `
@@ -3,9 +3,9 @@ package controllers @@ -3,9 +3,9 @@ package controllers
3 import ( 3 import (
4 "crypto/md5" 4 "crypto/md5"
5 "encoding/hex" 5 "encoding/hex"
6 - "encoding/json"  
7 "errors" 6 "errors"
8 "fmt" 7 "fmt"
  8 + "github.com/beego/beego/v2/client/httplib"
9 "path" 9 "path"
10 "regexp" 10 "regexp"
11 "strconv" 11 "strconv"
@@ -70,6 +70,7 @@ func (postData *postPurposeOrderDetail) Valid() error { @@ -70,6 +70,7 @@ func (postData *postPurposeOrderDetail) Valid() error {
70 } 70 }
71 if postData.PartnerId == 0 { 71 if postData.PartnerId == 0 {
72 return lib.ThrowError(lib.ARG_ERROR, "合伙人信息必填") 72 return lib.ThrowError(lib.ARG_ERROR, "合伙人信息必填")
  73 +
73 } 74 }
74 if len(postData.OrderDist) == 0 { 75 if len(postData.OrderDist) == 0 {
75 return lib.ThrowError(lib.ARG_ERROR, "订单区域必填") 76 return lib.ThrowError(lib.ARG_ERROR, "订单区域必填")
@@ -149,10 +150,19 @@ func (postData *postOrderPurposeDelivery) Valid() error { @@ -149,10 +150,19 @@ func (postData *postOrderPurposeDelivery) Valid() error {
149 return nil 150 return nil
150 } 151 }
151 152
152 -//PageListOrderReal 获取实发订单列表 153 +/**
  154 + * @Author SteveChan
  155 + * @Description // 获取实发订单列表,修改搜索条件
  156 + * @Date 20:23 2021/1/10
  157 + * @Param
  158 + * @return
  159 + **/
153 func (c *OrderInfoController) PageListOrderReal() { 160 func (c *OrderInfoController) PageListOrderReal() {
154 type Parameter struct { 161 type Parameter struct {
155 - SearchText string `json:"searchText"` 162 + //SearchText string `json:"searchText"`
  163 + PartnerName string `json:"partnerName"` // 合伙人姓名
  164 + OrderCode string `json:"orderCode"` // 订单号
  165 + DeliveryCode string `json:"deliveryCode"` // 发货单号
156 PartnerCategory int `json:"PartnerCategory"` 166 PartnerCategory int `json:"PartnerCategory"`
157 PageSize int `json:"pageSize"` 167 PageSize int `json:"pageSize"`
158 PageNumber int `json:"pageNumber"` 168 PageNumber int `json:"pageNumber"`
@@ -230,7 +240,10 @@ func (c *OrderInfoController) PageListOrderReal() { @@ -230,7 +240,10 @@ func (c *OrderInfoController) PageListOrderReal() {
230 companyId := c.GetUserCompany() 240 companyId := c.GetUserCompany()
231 orderSrv := orderService.NewOrderInfoService(nil) 241 orderSrv := orderService.NewOrderInfoService(nil)
232 orderinfos, cnt, err := orderSrv.PageListOrderBase(orderQuery.ListOrderBaseQuery{ 242 orderinfos, cnt, err := orderSrv.PageListOrderBase(orderQuery.ListOrderBaseQuery{
233 - PartnerOrCode: param.SearchText, 243 + //PartnerOrCode: param.SearchText,
  244 + PartnerName: param.PartnerName,
  245 + OrderCode: param.OrderCode,
  246 + DeliveryCode: param.DeliveryCode,
234 OrderType: domain.OrderReal, 247 OrderType: domain.OrderReal,
235 Limit: param.PageSize, 248 Limit: param.PageSize,
236 Offset: (param.PageNumber - 1) * param.PageSize, 249 Offset: (param.PageNumber - 1) * param.PageSize,
@@ -514,7 +527,10 @@ func (c *OrderInfoController) RemoveOrderReal() { @@ -514,7 +527,10 @@ func (c *OrderInfoController) RemoveOrderReal() {
514 //ListOrderForExcel excel 导出实际订单的列表 527 //ListOrderForExcel excel 导出实际订单的列表
515 func (c *OrderInfoController) ListOrderForExcel() { 528 func (c *OrderInfoController) ListOrderForExcel() {
516 type Parameter struct { 529 type Parameter struct {
517 - SearchText string `json:"searchText"` 530 + //SearchText string `json:"searchText"`
  531 + PartnerName string `json:"partnerName"` // 合伙人姓名
  532 + OrderCode string `json:"orderCode"` // 订单号
  533 + DeliveryCode string `json:"deliveryCode"` // 发货单号
518 PartnerCategory int `json:"PartnerCategory"` 534 PartnerCategory int `json:"PartnerCategory"`
519 UpdateTime []string `json:"updateTime"` 535 UpdateTime []string `json:"updateTime"`
520 CreateTime []string `json:"createTime"` 536 CreateTime []string `json:"createTime"`
@@ -584,7 +600,10 @@ func (c *OrderInfoController) ListOrderForExcel() { @@ -584,7 +600,10 @@ func (c *OrderInfoController) ListOrderForExcel() {
584 companyId := c.GetUserCompany() 600 companyId := c.GetUserCompany()
585 orderSrv := orderService.NewOrderInfoService(nil) 601 orderSrv := orderService.NewOrderInfoService(nil)
586 orderinfos, columns, err := orderSrv.ListOrderForExcel(orderQuery.ListOrderBaseQuery{ 602 orderinfos, columns, err := orderSrv.ListOrderForExcel(orderQuery.ListOrderBaseQuery{
587 - PartnerOrCode: param.SearchText, 603 + //PartnerOrCode: param.SearchText,
  604 + PartnerName: param.PartnerName,
  605 + OrderCode: param.OrderCode,
  606 + DeliveryCode: param.DeliveryCode,
588 OrderType: domain.OrderReal, 607 OrderType: domain.OrderReal,
589 CompanyId: companyId, 608 CompanyId: companyId,
590 PartnerCategory: param.PartnerCategory, 609 PartnerCategory: param.PartnerCategory,
@@ -614,6 +633,56 @@ func (c *OrderInfoController) ListOrderForExcel() { @@ -614,6 +633,56 @@ func (c *OrderInfoController) ListOrderForExcel() {
614 633
615 /** 634 /**
616 * @Author SteveChan 635 * @Author SteveChan
  636 + * @Description // 下载导入模板
  637 + * @Date 16:48 2021/1/8
  638 + * @Param
  639 + * @return
  640 + **/
  641 +func (c *OrderInfoController) DownloadTemplate() {
  642 + type Parameter struct {
  643 + TYPE string `json:"type"`
  644 + }
  645 +
  646 + var (
  647 + param Parameter
  648 + err error
  649 + )
  650 +
  651 + if err = c.BindJsonData(&param); err != nil {
  652 + logs.Error(err)
  653 + c.ResponseError(errors.New("json数据解析失败"))
  654 + return
  655 + }
  656 +
  657 + // 校验类型编码
  658 + if param.TYPE != "PARTNER_ORDER_FILE" {
  659 + c.ResponseError(errors.New("类型编码错误"))
  660 + }
  661 +
  662 + // 获取导入模板
  663 + req := httplib.Get("http://suplus-file-dev.fjmaimaimai.com/upload/file/2021010803305336443.xlsx")
  664 + err = req.ToFile(constant.IMPORT_EXCEL)
  665 + if err != nil {
  666 + logs.Error("could not save to file: ", err)
  667 + }
  668 +
  669 + // 返回字段定义
  670 + ret := map[string]interface{}{}
  671 +
  672 + resp, err := req.Response()
  673 + if err != nil {
  674 + logs.Error("could not get response: ", err)
  675 + } else {
  676 + logs.Info(resp)
  677 + ret = map[string]interface{}{
  678 + "url": "http://" + c.Ctx.Request.Host + "/download/订单数据模板.xlsx",
  679 + }
  680 + c.ResponseData(ret)
  681 + }
  682 +}
  683 +
  684 +/**
  685 + * @Author SteveChan
617 * @Description //TODO 导入excel订单 686 * @Description //TODO 导入excel订单
618 * @Date 10:52 2021/1/6 687 * @Date 10:52 2021/1/6
619 * @Param 688 * @Param
@@ -621,17 +690,20 @@ func (c *OrderInfoController) ListOrderForExcel() { @@ -621,17 +690,20 @@ func (c *OrderInfoController) ListOrderForExcel() {
621 **/ 690 **/
622 func (c *OrderInfoController) ImportOrderFromExcel() { 691 func (c *OrderInfoController) ImportOrderFromExcel() {
623 // 获取参数 692 // 获取参数
624 - where := c.GetString("where") 693 + typeCode := c.GetString("type")
625 file, h, _ := c.GetFile("file") 694 file, h, _ := c.GetFile("file")
626 -  
627 companyId := c.GetUserCompany() 695 companyId := c.GetUserCompany()
628 696
629 // Json数据解析 697 // Json数据解析
630 - jsonMap := make(map[string]interface{})  
631 - err := json.Unmarshal([]byte(where), &jsonMap)  
632 - if err != nil {  
633 - logs.Error(err)  
634 - c.ResponseError(errors.New("json数据解析失败")) 698 + //jsonMap := make(map[string]interface{})
  699 + //err := json.Unmarshal([]byte(where), &jsonMap)
  700 + //if err != nil {
  701 + // logs.Error(err)
  702 + // c.ResponseError(errors.New("json数据解析失败"))
  703 + //}
  704 +
  705 + if typeCode != "PARTNER_ORDER_IMPORT" {
  706 + c.ResponseError(errors.New("类型编码错误"))
635 } 707 }
636 708
637 // 返回字段定义 709 // 返回字段定义
@@ -678,7 +750,7 @@ func (c *OrderInfoController) ImportOrderFromExcel() { @@ -678,7 +750,7 @@ func (c *OrderInfoController) ImportOrderFromExcel() {
678 var tmpRow = row 750 var tmpRow = row
679 var myRow []string 751 var myRow []string
680 for j, cell := range row { 752 for j, cell := range row {
681 - if j != 8 { // 业务员抽成比例不校验 753 + if j != 8 { // 业务员抽成比例非必填
682 if cell == "" || cell == " " { // 空字符串填充 754 if cell == "" || cell == " " { // 空字符串填充
683 tmpRow[j] = "null" 755 tmpRow[j] = "null"
684 nullFlag = true 756 nullFlag = true
@@ -728,11 +800,13 @@ func (c *OrderInfoController) ImportOrderFromExcel() { @@ -728,11 +800,13 @@ func (c *OrderInfoController) ImportOrderFromExcel() {
728 var myRow []string 800 var myRow []string
729 for j, cell := range row { 801 for j, cell := range row {
730 switch j { 802 switch j {
731 - case 0, 1, 2, 3, 4, 5, 8: // 订单号、发货单号、客户名称、订单区域、编号、合伙人、产品名称 803 + case 0, 1, 2, 3, 4, 5, 8: // 订单号、发货单号、客户名称、订单区域、编号、合伙人、产品名称长度校验
732 { 804 {
733 - if len(cell) > 50 { 805 + cellStr := strings.TrimSpace(cell)
  806 + lenCellStr := utf8.RuneCountInString(cellStr)
  807 + if lenCellStr > 50 {
734 var tmpRow []string 808 var tmpRow []string
735 - tmpRow = append(tmpRow, tableHeader[j+2]+"长度超过50,请重新输入") // 错误信息 809 + tmpRow = append(tmpRow, tableHeader[j+2]+"长度超过50,请重新输入") // 错误信息
736 s := strconv.Itoa(i + 1) 810 s := strconv.Itoa(i + 1)
737 tmpRow = append(tmpRow, s) // 行号 811 tmpRow = append(tmpRow, s) // 行号
738 tmpRow = append(tmpRow, row...) // 错误行数据 812 tmpRow = append(tmpRow, row...) // 错误行数据
@@ -752,50 +826,76 @@ func (c *OrderInfoController) ImportOrderFromExcel() { @@ -752,50 +826,76 @@ func (c *OrderInfoController) ImportOrderFromExcel() {
752 } 826 }
753 case 7: // 业务员抽成比例,非必填,精确到小数点后两位 827 case 7: // 业务员抽成比例,非必填,精确到小数点后两位
754 { 828 {
  829 + var (
  830 + typeErrFlag bool
  831 + lenErrFlag bool
  832 + ratioErrFlag bool
  833 + )
755 if len(cell) > 0 { 834 if len(cell) > 0 {
756 - _, err := strconv.ParseFloat(cell, 64) 835 + // 参数类型转换
  836 + shareRatio, err := strconv.ParseFloat(cell, 64)
757 if err != nil { 837 if err != nil {
  838 + typeErrFlag = true
  839 + }
  840 +
  841 + // 比例不能超过100%
  842 + if shareRatio > 100 {
  843 + ratioErrFlag = true
  844 + }
  845 +
  846 + // 长度校验
  847 + regexpStr := `^(100|[1-9]\d|\d)(.\d{1,2})?$`
  848 + ok := regexp.MustCompile(regexpStr).MatchString(cell)
  849 + if !ok {
  850 + lenErrFlag = true
  851 + }
  852 +
  853 + if typeErrFlag || lenErrFlag || ratioErrFlag {
758 var tmpRow []string 854 var tmpRow []string
759 tmpRow = append(tmpRow, "业务员抽成比例格式错误,请输入正确的业务员抽成比例比例,保留两位小数") // 错误信息 855 tmpRow = append(tmpRow, "业务员抽成比例格式错误,请输入正确的业务员抽成比例比例,保留两位小数") // 错误信息
760 s := strconv.Itoa(i + 1) 856 s := strconv.Itoa(i + 1)
761 tmpRow = append(tmpRow, s) // 行号 857 tmpRow = append(tmpRow, s) // 行号
762 tmpRow = append(tmpRow, row...) // 错误行数据 858 tmpRow = append(tmpRow, row...) // 错误行数据
763 myRow = tmpRow 859 myRow = tmpRow
  860 + typeErrFlag = false
  861 + lenErrFlag = false
  862 + ratioErrFlag = false
764 } 863 }
765 - //if isOk, _ := regexp.MatchString("^(.[0-9]{0,1,2})?$", cell); !isOk { // 最多两位小数  
766 - // var tmpRow []string  
767 - // tmpRow = append(tmpRow, "业务员员抽成比例格式错误,请输入正确的单价,保留两位小数") // 错误信息  
768 - // s := strconv.Itoa(i + 1)  
769 - // tmpRow = append(tmpRow, s) // 行号  
770 - // tmpRow = append(tmpRow, row...) // 错误行数据  
771 - // myRow = tmpRow  
772 - //}  
773 } 864 }
774 } 865 }
775 case 9: // 数量不超过16位正整数 866 case 9: // 数量不超过16位正整数
776 { 867 {
777 - _, err := strconv.ParseInt(cell, 10, 64) 868 + var (
  869 + typeErrFlag bool
  870 + lenErrFlag bool
  871 + )
  872 +
  873 + //参数类型转换
  874 + orderNum, err := strconv.ParseInt(cell, 10, 64)
778 if err != nil { 875 if err != nil {
779 - var tmpRow []string  
780 - tmpRow = append(tmpRow, "数量须为整数,请重新填写") // 错误信息  
781 - s := strconv.Itoa(i + 1)  
782 - tmpRow = append(tmpRow, s) // 行号  
783 - tmpRow = append(tmpRow, row...) // 错误行数据  
784 - myRow = tmpRow 876 + typeErrFlag = true
  877 + }
  878 +
  879 + // 长度校验
  880 + if orderNum > 1e16 {
  881 + lenErrFlag = true
785 } 882 }
786 883
787 - if len(cell) > 16 { 884 + if typeErrFlag || lenErrFlag {
788 var tmpRow []string 885 var tmpRow []string
789 tmpRow = append(tmpRow, "数量长度超过最大限制十六位整数,请重新填写") // 错误信息 886 tmpRow = append(tmpRow, "数量长度超过最大限制十六位整数,请重新填写") // 错误信息
790 s := strconv.Itoa(i + 1) 887 s := strconv.Itoa(i + 1)
791 tmpRow = append(tmpRow, s) // 行号 888 tmpRow = append(tmpRow, s) // 行号
792 tmpRow = append(tmpRow, row...) // 错误行数据 889 tmpRow = append(tmpRow, row...) // 错误行数据
793 myRow = tmpRow 890 myRow = tmpRow
  891 + typeErrFlag = false
  892 + lenErrFlag = false
794 } 893 }
795 } 894 }
796 case 10: // 单价,精确到小数点后两位,小数点左侧最多可输入16位数字 895 case 10: // 单价,精确到小数点后两位,小数点左侧最多可输入16位数字
797 { 896 {
798 - _, err := strconv.ParseFloat(cell, 64) 897 + // 参数类型转换
  898 + univalent, err := strconv.ParseFloat(cell, 64)
799 if err != nil { 899 if err != nil {
800 var tmpRow []string 900 var tmpRow []string
801 tmpRow = append(tmpRow, "单价格式错误,请输入正确的单价,保留两位小数点,小数点前面不能超过十六位数字") // 错误信息 901 tmpRow = append(tmpRow, "单价格式错误,请输入正确的单价,保留两位小数点,小数点前面不能超过十六位数字") // 错误信息
@@ -804,34 +904,53 @@ func (c *OrderInfoController) ImportOrderFromExcel() { @@ -804,34 +904,53 @@ func (c *OrderInfoController) ImportOrderFromExcel() {
804 tmpRow = append(tmpRow, row...) // 错误行数据 904 tmpRow = append(tmpRow, row...) // 错误行数据
805 myRow = tmpRow 905 myRow = tmpRow
806 } 906 }
807 - //if isOk, _ := regexp.MatchString("^d{1,16}(.[0-9]{0,1,2})?$", cell); !isOk { // 非负的16位整数最多两位小数  
808 - // var tmpRow []string  
809 - // tmpRow = append(tmpRow, "单价格式错误,请输入正确的单价,保留两位小数点,小数点前面不能超过十六位数字") // 错误信息  
810 - // s := strconv.Itoa(i + 1)  
811 - // tmpRow = append(tmpRow, s) // 行号  
812 - // tmpRow = append(tmpRow, row...) // 错误行数据  
813 - // myRow = tmpRow  
814 - //} 907 + // 长度校验
  908 + if univalent >= 1e16 {
  909 + var tmpRow []string
  910 + tmpRow = append(tmpRow, "单价格式错误,请输入正确的单价,保留两位小数点,小数点前面不能超过十六位数字") // 错误信息
  911 + s := strconv.Itoa(i + 1)
  912 + tmpRow = append(tmpRow, s) // 行号
  913 + tmpRow = append(tmpRow, row...) // 错误行数据
  914 + myRow = tmpRow
  915 + }
815 } 916 }
816 case 11: // 合伙人分红比例,精确到小数点后两位 917 case 11: // 合伙人分红比例,精确到小数点后两位
817 { 918 {
818 - _, err := strconv.ParseFloat(cell, 64) 919 + var (
  920 + typeErrFlag bool
  921 + lenErrFlag bool
  922 + ratioErrFlag bool
  923 + )
  924 +
  925 + //参数类型转换
  926 + partnerRatio, err := strconv.ParseFloat(cell, 64)
819 if err != nil { 927 if err != nil {
  928 + typeErrFlag = true
  929 + }
  930 +
  931 + // 合伙人分红比例超额
  932 + if partnerRatio > 100 {
  933 + ratioErrFlag = true
  934 + }
  935 +
  936 + // 长度判断
  937 + regexpStr := `^(100|[1-9]\d|\d)(.\d{1,2})?$`
  938 + ok := regexp.MustCompile(regexpStr).MatchString(cell)
  939 + if !ok {
  940 + lenErrFlag = true
  941 + }
  942 +
  943 + if typeErrFlag || lenErrFlag || ratioErrFlag {
820 var tmpRow []string 944 var tmpRow []string
821 tmpRow = append(tmpRow, "合伙人分红比例格式错误,请输入正确的合伙人分红比例,保留两位小数") // 错误信息 945 tmpRow = append(tmpRow, "合伙人分红比例格式错误,请输入正确的合伙人分红比例,保留两位小数") // 错误信息
822 s := strconv.Itoa(i + 1) 946 s := strconv.Itoa(i + 1)
823 tmpRow = append(tmpRow, s) // 行号 947 tmpRow = append(tmpRow, s) // 行号
824 tmpRow = append(tmpRow, row...) // 错误行数据 948 tmpRow = append(tmpRow, row...) // 错误行数据
825 myRow = tmpRow 949 myRow = tmpRow
  950 + typeErrFlag = false
  951 + lenErrFlag = false
  952 + ratioErrFlag = false
826 } 953 }
827 - //if isOk, _ := regexp.MatchString("^(.[0-9]{1,2})?$", cell); !isOk { // 最多两位小数  
828 - // var tmpRow []string  
829 - // tmpRow = append(tmpRow, "合伙人分红比例错误,请输入正确的合伙人分红比例,保留两位小数") // 错误信息  
830 - // s := strconv.Itoa(i + 1)  
831 - // tmpRow = append(tmpRow, s) // 行号  
832 - // tmpRow = append(tmpRow, row...) // 错误行数据  
833 - // myRow = tmpRow  
834 - //}  
835 } 954 }
836 } 955 }
837 } 956 }
@@ -888,11 +1007,12 @@ func (c *OrderInfoController) ImportOrderFromExcel() { @@ -888,11 +1007,12 @@ func (c *OrderInfoController) ImportOrderFromExcel() {
888 PlanGoodNumber: int(amount), 1007 PlanGoodNumber: int(amount),
889 Price: price, 1008 Price: price,
890 PartnerBonusPercent: percent, 1009 PartnerBonusPercent: percent,
  1010 + LineNumber: i,
891 }, 1011 },
892 }, 1012 },
893 CompanyId: companyId, 1013 CompanyId: companyId,
894 PartnerCategory: 1, 1014 PartnerCategory: 1,
895 - LineNumbers: []int{i}, 1015 + LineNumbers: []int{i}, // 记录行号
896 } 1016 }
897 1017
898 // 获取partnerId 1018 // 获取partnerId
@@ -952,17 +1072,37 @@ func (c *OrderInfoController) ImportOrderFromExcel() { @@ -952,17 +1072,37 @@ func (c *OrderInfoController) ImportOrderFromExcel() {
952 // 新增成功记录计数 1072 // 新增成功记录计数
953 var successDataCount int64 1073 var successDataCount int64
954 1074
955 - // 新增错误信息  
956 - var createError error  
957 -  
958 // 批量新增订单 1075 // 批量新增订单
959 - failureDataList, createError = orderSrv.CreateNewOrderByImport(createOrderCommands) 1076 + errorDataList, createError := orderSrv.CreateNewOrderByImport(createOrderCommands)
960 if createError != nil { 1077 if createError != nil {
961 c.ResponseError(createError) 1078 c.ResponseError(createError)
962 return 1079 return
963 } else { 1080 } else {
964 - if len(failureDataList) > 0 { // 导入失败返回 1081 + if len(errorDataList) > 0 { // 导入失败返回
965 successDataCount = 0 1082 successDataCount = 0
  1083 + // 错误记录处理
  1084 + for _, errorData := range errorDataList {
  1085 + if len(errorData.GoodLine) == 0 { // 订单错误
  1086 + for _, line := range errorData.LineNumbers {
  1087 + var tmpRow []string
  1088 + tmpRow = append(tmpRow, errorData.Error.Error()) // 错误信息
  1089 + s := strconv.Itoa(line + 1)
  1090 + tmpRow = append(tmpRow, s) // 行号
  1091 + tmpRow = append(tmpRow, rows[line]...) // 错误行数据
  1092 + failureDataList = append(failureDataList, tmpRow)
  1093 + }
  1094 + } else if len(errorData.GoodLine) > 0 { // 订单产品错误
  1095 + for line := range errorData.GoodLine {
  1096 + var tmpRow []string
  1097 + tmpRow = append(tmpRow, errorData.Error.Error()) // 错误信息
  1098 + s := strconv.Itoa(line + 1)
  1099 + tmpRow = append(tmpRow, s) // 行号
  1100 + tmpRow = append(tmpRow, rows[line]...) // 错误行数据
  1101 + failureDataList = append(failureDataList, tmpRow)
  1102 + }
  1103 + }
  1104 + }
  1105 +
966 ret = map[string]interface{}{ 1106 ret = map[string]interface{}{
967 "successCount": successDataCount, 1107 "successCount": successDataCount,
968 "fail": map[string]interface{}{ 1108 "fail": map[string]interface{}{
@@ -6,6 +6,10 @@ import ( @@ -6,6 +6,10 @@ import (
6 ) 6 )
7 7
8 func init() { 8 func init() {
  9 + // 导入相关
  10 + beego.Router("/fileImportTemplate", &controllers.OrderInfoController{}, "POST:DownloadTemplate") // 下载导入模板
  11 + beego.Router("/fileImport", &controllers.OrderInfoController{}, "POST:ImportOrderFromExcel") // 导入订单数据
  12 +
9 adminRouter := beego.NewNamespace("/v1", 13 adminRouter := beego.NewNamespace("/v1",
10 beego.NSNamespace("/auth", 14 beego.NSNamespace("/auth",
11 beego.NSRouter("/login", &controllers.AdminLoginController{}, "POST:Login"), 15 beego.NSRouter("/login", &controllers.AdminLoginController{}, "POST:Login"),
@@ -35,12 +39,11 @@ func init() { @@ -35,12 +39,11 @@ func init() {
35 beego.NSRouter("/list/excel", &controllers.OrderDividendController{}, "POST:ListOrderBonusForExcel"), 39 beego.NSRouter("/list/excel", &controllers.OrderDividendController{}, "POST:ListOrderBonusForExcel"),
36 ), 40 ),
37 beego.NSNamespace("/order", 41 beego.NSNamespace("/order",
38 - beego.NSRouter("/actual/list", &controllers.OrderInfoController{}, "POST:PageListOrderReal"), // 返归订单列表  
39 - beego.NSRouter("/actual/list/excel", &controllers.OrderInfoController{}, "POST:ListOrderForExcel"), // 导出excel  
40 - beego.NSRouter("/actual/import/excel", &controllers.OrderInfoController{}, "POST:ImportOrderFromExcel"), // 导入订单数据  
41 - beego.NSRouter("/actual/detail", &controllers.OrderInfoController{}, "POST:GetOrderReal"), // 查看实际订单详情  
42 - beego.NSRouter("/actual/del", &controllers.OrderInfoController{}, "POST:RemoveOrderReal"), // 删除实际订单  
43 - beego.NSRouter("/actual/update", &controllers.OrderInfoController{}, "POST:UpdateOrderReal"), // 新增实际订单 42 + beego.NSRouter("/actual/list", &controllers.OrderInfoController{}, "POST:PageListOrderReal"), // 返归订单列表
  43 + beego.NSRouter("/actual/list/excel", &controllers.OrderInfoController{}, "POST:ListOrderForExcel"), // 导出订单记录
  44 + beego.NSRouter("/actual/detail", &controllers.OrderInfoController{}, "POST:GetOrderReal"), // 查看实际订单详情
  45 + beego.NSRouter("/actual/del", &controllers.OrderInfoController{}, "POST:RemoveOrderReal"), // 删除实际订单
  46 + beego.NSRouter("/actual/update", &controllers.OrderInfoController{}, "POST:UpdateOrderReal"), // 新增实际订单
44 beego.NSRouter("/actual/close", &controllers.OrderInfoController{}, "POST:OrderDisable"), 47 beego.NSRouter("/actual/close", &controllers.OrderInfoController{}, "POST:OrderDisable"),
45 ), 48 ),
46 beego.NSNamespace("/common", 49 beego.NSNamespace("/common",
@@ -20,4 +20,7 @@ func init() { @@ -20,4 +20,7 @@ func init() {
20 http.ServeFile(ctx.ResponseWriter, ctx.Request, constant.LOG_File) 20 http.ServeFile(ctx.ResponseWriter, ctx.Request, constant.LOG_File)
21 return 21 return
22 }) 22 })
  23 +
  24 + // 静态文件路径映射
  25 + beego.SetStaticPath("/download", "download")
23 } 26 }
  1 +Copyright 2014 astaxie
  2 +
  3 +Licensed under the Apache License, Version 2.0 (the "License");
  4 +you may not use this file except in compliance with the License.
  5 +You may obtain a copy of the License at
  6 +
  7 + http://www.apache.org/licenses/LICENSE-2.0
  8 +
  9 +Unless required by applicable law or agreed to in writing, software
  10 +distributed under the License is distributed on an "AS IS" BASIS,
  11 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +See the License for the specific language governing permissions and
  13 +limitations under the License.
  1 +# httplib
  2 +
  3 +httplib is an libs help you to curl remote url.
  4 +
  5 +# How to use?
  6 +
  7 +## GET
  8 +
  9 +you can use Get to crawl data.
  10 +
  11 + import "github.com/beego/beego/v2/httplib"
  12 +
  13 + str, err := httplib.Get("http://beego.me/").String()
  14 + if err != nil {
  15 + // error
  16 + }
  17 + fmt.Println(str)
  18 +
  19 +## POST
  20 +
  21 +POST data to remote url
  22 +
  23 + req := httplib.Post("http://beego.me/")
  24 + req.Param("username","astaxie")
  25 + req.Param("password","123456")
  26 + str, err := req.String()
  27 + if err != nil {
  28 + // error
  29 + }
  30 + fmt.Println(str)
  31 +
  32 +## Set timeout
  33 +
  34 +The default timeout is `60` seconds, function prototype:
  35 +
  36 + SetTimeout(connectTimeout, readWriteTimeout time.Duration)
  37 +
  38 +Example:
  39 +
  40 + // GET
  41 + httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)
  42 +
  43 + // POST
  44 + httplib.Post("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)
  45 +
  46 +## Debug
  47 +
  48 +If you want to debug the request info, set the debug on
  49 +
  50 + httplib.Get("http://beego.me/").Debug(true)
  51 +
  52 +## Set HTTP Basic Auth
  53 +
  54 + str, err := Get("http://beego.me/").SetBasicAuth("user", "passwd").String()
  55 + if err != nil {
  56 + // error
  57 + }
  58 + fmt.Println(str)
  59 +
  60 +## Set HTTPS
  61 +
  62 +If request url is https, You can set the client support TSL:
  63 +
  64 + httplib.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
  65 +
  66 +More info about the `tls.Config` please visit http://golang.org/pkg/crypto/tls/#Config
  67 +
  68 +## Set HTTP Version
  69 +
  70 +some servers need to specify the protocol version of HTTP
  71 +
  72 + httplib.Get("http://beego.me/").SetProtocolVersion("HTTP/1.1")
  73 +
  74 +## Set Cookie
  75 +
  76 +some http request need setcookie. So set it like this:
  77 +
  78 + cookie := &http.Cookie{}
  79 + cookie.Name = "username"
  80 + cookie.Value = "astaxie"
  81 + httplib.Get("http://beego.me/").SetCookie(cookie)
  82 +
  83 +## Upload file
  84 +
  85 +httplib support mutil file upload, use `req.PostFile()`
  86 +
  87 + req := httplib.Post("http://beego.me/")
  88 + req.Param("username","astaxie")
  89 + req.PostFile("uploadfile1", "httplib.pdf")
  90 + str, err := req.String()
  91 + if err != nil {
  92 + // error
  93 + }
  94 + fmt.Println(str)
  95 +
  96 +See godoc for further documentation and examples.
  97 +
  98 +* [godoc.org/github.com/beego/beego/v2/httplib](https://godoc.org/github.com/beego/beego/v2/httplib)
  1 +// Copyright 2020 beego
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package httplib
  16 +
  17 +import (
  18 + "context"
  19 + "net/http"
  20 +)
  21 +
  22 +type FilterChain func(next Filter) Filter
  23 +
  24 +type Filter func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error)
  1 +// Copyright 2014 beego Author. All Rights Reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +// Package httplib is used as http.Client
  16 +// Usage:
  17 +//
  18 +// import "github.com/beego/beego/v2/httplib"
  19 +//
  20 +// b := httplib.Post("http://beego.me/")
  21 +// b.Param("username","astaxie")
  22 +// b.Param("password","123456")
  23 +// b.PostFile("uploadfile1", "httplib.pdf")
  24 +// b.PostFile("uploadfile2", "httplib.txt")
  25 +// str, err := b.String()
  26 +// if err != nil {
  27 +// t.Fatal(err)
  28 +// }
  29 +// fmt.Println(str)
  30 +//
  31 +// more docs http://beego.me/docs/module/httplib.md
  32 +package httplib
  33 +
  34 +import (
  35 + "bytes"
  36 + "compress/gzip"
  37 + "context"
  38 + "crypto/tls"
  39 + "encoding/json"
  40 + "encoding/xml"
  41 + "io"
  42 + "io/ioutil"
  43 + "log"
  44 + "mime/multipart"
  45 + "net"
  46 + "net/http"
  47 + "net/http/cookiejar"
  48 + "net/http/httputil"
  49 + "net/url"
  50 + "os"
  51 + "path"
  52 + "strings"
  53 + "sync"
  54 + "time"
  55 +
  56 + "gopkg.in/yaml.v2"
  57 +)
  58 +
  59 +var defaultSetting = BeegoHTTPSettings{
  60 + UserAgent: "beegoServer",
  61 + ConnectTimeout: 60 * time.Second,
  62 + ReadWriteTimeout: 60 * time.Second,
  63 + Gzip: true,
  64 + DumpBody: true,
  65 +}
  66 +
  67 +var defaultCookieJar http.CookieJar
  68 +var settingMutex sync.Mutex
  69 +
  70 +// it will be the last filter and execute request.Do
  71 +var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
  72 + return req.doRequest(ctx)
  73 +}
  74 +
  75 +// createDefaultCookie creates a global cookiejar to store cookies.
  76 +func createDefaultCookie() {
  77 + settingMutex.Lock()
  78 + defer settingMutex.Unlock()
  79 + defaultCookieJar, _ = cookiejar.New(nil)
  80 +}
  81 +
  82 +// SetDefaultSetting overwrites default settings
  83 +func SetDefaultSetting(setting BeegoHTTPSettings) {
  84 + settingMutex.Lock()
  85 + defer settingMutex.Unlock()
  86 + defaultSetting = setting
  87 +}
  88 +
  89 +// NewBeegoRequest returns *BeegoHttpRequest with specific method
  90 +func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest {
  91 + var resp http.Response
  92 + u, err := url.Parse(rawurl)
  93 + if err != nil {
  94 + log.Println("Httplib:", err)
  95 + }
  96 + req := http.Request{
  97 + URL: u,
  98 + Method: method,
  99 + Header: make(http.Header),
  100 + Proto: "HTTP/1.1",
  101 + ProtoMajor: 1,
  102 + ProtoMinor: 1,
  103 + }
  104 + return &BeegoHTTPRequest{
  105 + url: rawurl,
  106 + req: &req,
  107 + params: map[string][]string{},
  108 + files: map[string]string{},
  109 + setting: defaultSetting,
  110 + resp: &resp,
  111 + }
  112 +}
  113 +
  114 +// Get returns *BeegoHttpRequest with GET method.
  115 +func Get(url string) *BeegoHTTPRequest {
  116 + return NewBeegoRequest(url, "GET")
  117 +}
  118 +
  119 +// Post returns *BeegoHttpRequest with POST method.
  120 +func Post(url string) *BeegoHTTPRequest {
  121 + return NewBeegoRequest(url, "POST")
  122 +}
  123 +
  124 +// Put returns *BeegoHttpRequest with PUT method.
  125 +func Put(url string) *BeegoHTTPRequest {
  126 + return NewBeegoRequest(url, "PUT")
  127 +}
  128 +
  129 +// Delete returns *BeegoHttpRequest DELETE method.
  130 +func Delete(url string) *BeegoHTTPRequest {
  131 + return NewBeegoRequest(url, "DELETE")
  132 +}
  133 +
  134 +// Head returns *BeegoHttpRequest with HEAD method.
  135 +func Head(url string) *BeegoHTTPRequest {
  136 + return NewBeegoRequest(url, "HEAD")
  137 +}
  138 +
  139 +// BeegoHTTPSettings is the http.Client setting
  140 +type BeegoHTTPSettings struct {
  141 + ShowDebug bool
  142 + UserAgent string
  143 + ConnectTimeout time.Duration
  144 + ReadWriteTimeout time.Duration
  145 + TLSClientConfig *tls.Config
  146 + Proxy func(*http.Request) (*url.URL, error)
  147 + Transport http.RoundTripper
  148 + CheckRedirect func(req *http.Request, via []*http.Request) error
  149 + EnableCookie bool
  150 + Gzip bool
  151 + DumpBody bool
  152 + Retries int // if set to -1 means will retry forever
  153 + RetryDelay time.Duration
  154 + FilterChains []FilterChain
  155 +}
  156 +
  157 +// BeegoHTTPRequest provides more useful methods than http.Request for requesting a url.
  158 +type BeegoHTTPRequest struct {
  159 + url string
  160 + req *http.Request
  161 + params map[string][]string
  162 + files map[string]string
  163 + setting BeegoHTTPSettings
  164 + resp *http.Response
  165 + body []byte
  166 + dump []byte
  167 +}
  168 +
  169 +// GetRequest returns the request object
  170 +func (b *BeegoHTTPRequest) GetRequest() *http.Request {
  171 + return b.req
  172 +}
  173 +
  174 +// Setting changes request settings
  175 +func (b *BeegoHTTPRequest) Setting(setting BeegoHTTPSettings) *BeegoHTTPRequest {
  176 + b.setting = setting
  177 + return b
  178 +}
  179 +
  180 +// SetBasicAuth sets the request's Authorization header to use HTTP Basic Authentication with the provided username and password.
  181 +func (b *BeegoHTTPRequest) SetBasicAuth(username, password string) *BeegoHTTPRequest {
  182 + b.req.SetBasicAuth(username, password)
  183 + return b
  184 +}
  185 +
  186 +// SetEnableCookie sets enable/disable cookiejar
  187 +func (b *BeegoHTTPRequest) SetEnableCookie(enable bool) *BeegoHTTPRequest {
  188 + b.setting.EnableCookie = enable
  189 + return b
  190 +}
  191 +
  192 +// SetUserAgent sets User-Agent header field
  193 +func (b *BeegoHTTPRequest) SetUserAgent(useragent string) *BeegoHTTPRequest {
  194 + b.setting.UserAgent = useragent
  195 + return b
  196 +}
  197 +
  198 +// Debug sets show debug or not when executing request.
  199 +func (b *BeegoHTTPRequest) Debug(isdebug bool) *BeegoHTTPRequest {
  200 + b.setting.ShowDebug = isdebug
  201 + return b
  202 +}
  203 +
  204 +// Retries sets Retries times.
  205 +// default is 0 (never retry)
  206 +// -1 retry indefinitely (forever)
  207 +// Other numbers specify the exact retry amount
  208 +func (b *BeegoHTTPRequest) Retries(times int) *BeegoHTTPRequest {
  209 + b.setting.Retries = times
  210 + return b
  211 +}
  212 +
  213 +// RetryDelay sets the time to sleep between reconnection attempts
  214 +func (b *BeegoHTTPRequest) RetryDelay(delay time.Duration) *BeegoHTTPRequest {
  215 + b.setting.RetryDelay = delay
  216 + return b
  217 +}
  218 +
  219 +// DumpBody sets the DumbBody field
  220 +func (b *BeegoHTTPRequest) DumpBody(isdump bool) *BeegoHTTPRequest {
  221 + b.setting.DumpBody = isdump
  222 + return b
  223 +}
  224 +
  225 +// DumpRequest returns the DumpRequest
  226 +func (b *BeegoHTTPRequest) DumpRequest() []byte {
  227 + return b.dump
  228 +}
  229 +
  230 +// SetTimeout sets connect time out and read-write time out for BeegoRequest.
  231 +func (b *BeegoHTTPRequest) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *BeegoHTTPRequest {
  232 + b.setting.ConnectTimeout = connectTimeout
  233 + b.setting.ReadWriteTimeout = readWriteTimeout
  234 + return b
  235 +}
  236 +
  237 +// SetTLSClientConfig sets TLS connection configuration if visiting HTTPS url.
  238 +func (b *BeegoHTTPRequest) SetTLSClientConfig(config *tls.Config) *BeegoHTTPRequest {
  239 + b.setting.TLSClientConfig = config
  240 + return b
  241 +}
  242 +
  243 +// Header adds header item string in request.
  244 +func (b *BeegoHTTPRequest) Header(key, value string) *BeegoHTTPRequest {
  245 + b.req.Header.Set(key, value)
  246 + return b
  247 +}
  248 +
  249 +// SetHost set the request host
  250 +func (b *BeegoHTTPRequest) SetHost(host string) *BeegoHTTPRequest {
  251 + b.req.Host = host
  252 + return b
  253 +}
  254 +
  255 +// SetProtocolVersion sets the protocol version for incoming requests.
  256 +// Client requests always use HTTP/1.1.
  257 +func (b *BeegoHTTPRequest) SetProtocolVersion(vers string) *BeegoHTTPRequest {
  258 + if len(vers) == 0 {
  259 + vers = "HTTP/1.1"
  260 + }
  261 +
  262 + major, minor, ok := http.ParseHTTPVersion(vers)
  263 + if ok {
  264 + b.req.Proto = vers
  265 + b.req.ProtoMajor = major
  266 + b.req.ProtoMinor = minor
  267 + }
  268 +
  269 + return b
  270 +}
  271 +
  272 +// SetCookie adds a cookie to the request.
  273 +func (b *BeegoHTTPRequest) SetCookie(cookie *http.Cookie) *BeegoHTTPRequest {
  274 + b.req.Header.Add("Cookie", cookie.String())
  275 + return b
  276 +}
  277 +
  278 +// SetTransport sets the transport field
  279 +func (b *BeegoHTTPRequest) SetTransport(transport http.RoundTripper) *BeegoHTTPRequest {
  280 + b.setting.Transport = transport
  281 + return b
  282 +}
  283 +
  284 +// SetProxy sets the HTTP proxy
  285 +// example:
  286 +//
  287 +// func(req *http.Request) (*url.URL, error) {
  288 +// u, _ := url.ParseRequestURI("http://127.0.0.1:8118")
  289 +// return u, nil
  290 +// }
  291 +func (b *BeegoHTTPRequest) SetProxy(proxy func(*http.Request) (*url.URL, error)) *BeegoHTTPRequest {
  292 + b.setting.Proxy = proxy
  293 + return b
  294 +}
  295 +
  296 +// SetCheckRedirect specifies the policy for handling redirects.
  297 +//
  298 +// If CheckRedirect is nil, the Client uses its default policy,
  299 +// which is to stop after 10 consecutive requests.
  300 +func (b *BeegoHTTPRequest) SetCheckRedirect(redirect func(req *http.Request, via []*http.Request) error) *BeegoHTTPRequest {
  301 + b.setting.CheckRedirect = redirect
  302 + return b
  303 +}
  304 +
  305 +// SetFilters will use the filter as the invocation filters
  306 +func (b *BeegoHTTPRequest) SetFilters(fcs ...FilterChain) *BeegoHTTPRequest {
  307 + b.setting.FilterChains = fcs
  308 + return b
  309 +}
  310 +
  311 +// AddFilters adds filter
  312 +func (b *BeegoHTTPRequest) AddFilters(fcs ...FilterChain) *BeegoHTTPRequest {
  313 + b.setting.FilterChains = append(b.setting.FilterChains, fcs...)
  314 + return b
  315 +}
  316 +
  317 +// Param adds query param in to request.
  318 +// params build query string as ?key1=value1&key2=value2...
  319 +func (b *BeegoHTTPRequest) Param(key, value string) *BeegoHTTPRequest {
  320 + if param, ok := b.params[key]; ok {
  321 + b.params[key] = append(param, value)
  322 + } else {
  323 + b.params[key] = []string{value}
  324 + }
  325 + return b
  326 +}
  327 +
  328 +// PostFile adds a post file to the request
  329 +func (b *BeegoHTTPRequest) PostFile(formname, filename string) *BeegoHTTPRequest {
  330 + b.files[formname] = filename
  331 + return b
  332 +}
  333 +
  334 +// Body adds request raw body.
  335 +// Supports string and []byte.
  336 +func (b *BeegoHTTPRequest) Body(data interface{}) *BeegoHTTPRequest {
  337 + switch t := data.(type) {
  338 + case string:
  339 + bf := bytes.NewBufferString(t)
  340 + b.req.Body = ioutil.NopCloser(bf)
  341 + b.req.ContentLength = int64(len(t))
  342 + case []byte:
  343 + bf := bytes.NewBuffer(t)
  344 + b.req.Body = ioutil.NopCloser(bf)
  345 + b.req.ContentLength = int64(len(t))
  346 + }
  347 + return b
  348 +}
  349 +
  350 +// XMLBody adds the request raw body encoded in XML.
  351 +func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) {
  352 + if b.req.Body == nil && obj != nil {
  353 + byts, err := xml.Marshal(obj)
  354 + if err != nil {
  355 + return b, err
  356 + }
  357 + b.req.Body = ioutil.NopCloser(bytes.NewReader(byts))
  358 + b.req.ContentLength = int64(len(byts))
  359 + b.req.Header.Set("Content-Type", "application/xml")
  360 + }
  361 + return b, nil
  362 +}
  363 +
  364 +// YAMLBody adds the request raw body encoded in YAML.
  365 +func (b *BeegoHTTPRequest) YAMLBody(obj interface{}) (*BeegoHTTPRequest, error) {
  366 + if b.req.Body == nil && obj != nil {
  367 + byts, err := yaml.Marshal(obj)
  368 + if err != nil {
  369 + return b, err
  370 + }
  371 + b.req.Body = ioutil.NopCloser(bytes.NewReader(byts))
  372 + b.req.ContentLength = int64(len(byts))
  373 + b.req.Header.Set("Content-Type", "application/x+yaml")
  374 + }
  375 + return b, nil
  376 +}
  377 +
  378 +// JSONBody adds the request raw body encoded in JSON.
  379 +func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error) {
  380 + if b.req.Body == nil && obj != nil {
  381 + byts, err := json.Marshal(obj)
  382 + if err != nil {
  383 + return b, err
  384 + }
  385 + b.req.Body = ioutil.NopCloser(bytes.NewReader(byts))
  386 + b.req.ContentLength = int64(len(byts))
  387 + b.req.Header.Set("Content-Type", "application/json")
  388 + }
  389 + return b, nil
  390 +}
  391 +
  392 +func (b *BeegoHTTPRequest) buildURL(paramBody string) {
  393 + // build GET url with query string
  394 + if b.req.Method == "GET" && len(paramBody) > 0 {
  395 + if strings.Contains(b.url, "?") {
  396 + b.url += "&" + paramBody
  397 + } else {
  398 + b.url = b.url + "?" + paramBody
  399 + }
  400 + return
  401 + }
  402 +
  403 + // build POST/PUT/PATCH url and body
  404 + if (b.req.Method == "POST" || b.req.Method == "PUT" || b.req.Method == "PATCH" || b.req.Method == "DELETE") && b.req.Body == nil {
  405 + // with files
  406 + if len(b.files) > 0 {
  407 + pr, pw := io.Pipe()
  408 + bodyWriter := multipart.NewWriter(pw)
  409 + go func() {
  410 + for formname, filename := range b.files {
  411 + fileWriter, err := bodyWriter.CreateFormFile(formname, filename)
  412 + if err != nil {
  413 + log.Println("Httplib:", err)
  414 + }
  415 + fh, err := os.Open(filename)
  416 + if err != nil {
  417 + log.Println("Httplib:", err)
  418 + }
  419 + // iocopy
  420 + _, err = io.Copy(fileWriter, fh)
  421 + fh.Close()
  422 + if err != nil {
  423 + log.Println("Httplib:", err)
  424 + }
  425 + }
  426 + for k, v := range b.params {
  427 + for _, vv := range v {
  428 + bodyWriter.WriteField(k, vv)
  429 + }
  430 + }
  431 + bodyWriter.Close()
  432 + pw.Close()
  433 + }()
  434 + b.Header("Content-Type", bodyWriter.FormDataContentType())
  435 + b.req.Body = ioutil.NopCloser(pr)
  436 + b.Header("Transfer-Encoding", "chunked")
  437 + return
  438 + }
  439 +
  440 + // with params
  441 + if len(paramBody) > 0 {
  442 + b.Header("Content-Type", "application/x-www-form-urlencoded")
  443 + b.Body(paramBody)
  444 + }
  445 + }
  446 +}
  447 +
  448 +func (b *BeegoHTTPRequest) getResponse() (*http.Response, error) {
  449 + if b.resp.StatusCode != 0 {
  450 + return b.resp, nil
  451 + }
  452 + resp, err := b.DoRequest()
  453 + if err != nil {
  454 + return nil, err
  455 + }
  456 + b.resp = resp
  457 + return resp, nil
  458 +}
  459 +
  460 +// DoRequest executes client.Do
  461 +func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) {
  462 + return b.DoRequestWithCtx(context.Background())
  463 +}
  464 +
  465 +func (b *BeegoHTTPRequest) DoRequestWithCtx(ctx context.Context) (resp *http.Response, err error) {
  466 +
  467 + root := doRequestFilter
  468 + if len(b.setting.FilterChains) > 0 {
  469 + for i := len(b.setting.FilterChains) - 1; i >= 0; i-- {
  470 + root = b.setting.FilterChains[i](root)
  471 + }
  472 + }
  473 + return root(ctx, b)
  474 +}
  475 +
  476 +func (b *BeegoHTTPRequest) doRequest(ctx context.Context) (resp *http.Response, err error) {
  477 + var paramBody string
  478 + if len(b.params) > 0 {
  479 + var buf bytes.Buffer
  480 + for k, v := range b.params {
  481 + for _, vv := range v {
  482 + buf.WriteString(url.QueryEscape(k))
  483 + buf.WriteByte('=')
  484 + buf.WriteString(url.QueryEscape(vv))
  485 + buf.WriteByte('&')
  486 + }
  487 + }
  488 + paramBody = buf.String()
  489 + paramBody = paramBody[0 : len(paramBody)-1]
  490 + }
  491 +
  492 + b.buildURL(paramBody)
  493 + urlParsed, err := url.Parse(b.url)
  494 + if err != nil {
  495 + return nil, err
  496 + }
  497 +
  498 + b.req.URL = urlParsed
  499 +
  500 + trans := b.setting.Transport
  501 +
  502 + if trans == nil {
  503 + // create default transport
  504 + trans = &http.Transport{
  505 + TLSClientConfig: b.setting.TLSClientConfig,
  506 + Proxy: b.setting.Proxy,
  507 + Dial: TimeoutDialer(b.setting.ConnectTimeout, b.setting.ReadWriteTimeout),
  508 + MaxIdleConnsPerHost: 100,
  509 + }
  510 + } else {
  511 + // if b.transport is *http.Transport then set the settings.
  512 + if t, ok := trans.(*http.Transport); ok {
  513 + if t.TLSClientConfig == nil {
  514 + t.TLSClientConfig = b.setting.TLSClientConfig
  515 + }
  516 + if t.Proxy == nil {
  517 + t.Proxy = b.setting.Proxy
  518 + }
  519 + if t.Dial == nil {
  520 + t.Dial = TimeoutDialer(b.setting.ConnectTimeout, b.setting.ReadWriteTimeout)
  521 + }
  522 + }
  523 + }
  524 +
  525 + var jar http.CookieJar
  526 + if b.setting.EnableCookie {
  527 + if defaultCookieJar == nil {
  528 + createDefaultCookie()
  529 + }
  530 + jar = defaultCookieJar
  531 + }
  532 +
  533 + client := &http.Client{
  534 + Transport: trans,
  535 + Jar: jar,
  536 + }
  537 +
  538 + if b.setting.UserAgent != "" && b.req.Header.Get("User-Agent") == "" {
  539 + b.req.Header.Set("User-Agent", b.setting.UserAgent)
  540 + }
  541 +
  542 + if b.setting.CheckRedirect != nil {
  543 + client.CheckRedirect = b.setting.CheckRedirect
  544 + }
  545 +
  546 + if b.setting.ShowDebug {
  547 + dump, err := httputil.DumpRequest(b.req, b.setting.DumpBody)
  548 + if err != nil {
  549 + log.Println(err.Error())
  550 + }
  551 + b.dump = dump
  552 + }
  553 + // retries default value is 0, it will run once.
  554 + // retries equal to -1, it will run forever until success
  555 + // retries is setted, it will retries fixed times.
  556 + // Sleeps for a 400ms between calls to reduce spam
  557 + for i := 0; b.setting.Retries == -1 || i <= b.setting.Retries; i++ {
  558 + resp, err = client.Do(b.req)
  559 + if err == nil {
  560 + break
  561 + }
  562 + time.Sleep(b.setting.RetryDelay)
  563 + }
  564 + return resp, err
  565 +}
  566 +
  567 +// String returns the body string in response.
  568 +// Calls Response inner.
  569 +func (b *BeegoHTTPRequest) String() (string, error) {
  570 + data, err := b.Bytes()
  571 + if err != nil {
  572 + return "", err
  573 + }
  574 +
  575 + return string(data), nil
  576 +}
  577 +
  578 +// Bytes returns the body []byte in response.
  579 +// Calls Response inner.
  580 +func (b *BeegoHTTPRequest) Bytes() ([]byte, error) {
  581 + if b.body != nil {
  582 + return b.body, nil
  583 + }
  584 + resp, err := b.getResponse()
  585 + if err != nil {
  586 + return nil, err
  587 + }
  588 + if resp.Body == nil {
  589 + return nil, nil
  590 + }
  591 + defer resp.Body.Close()
  592 + if b.setting.Gzip && resp.Header.Get("Content-Encoding") == "gzip" {
  593 + reader, err := gzip.NewReader(resp.Body)
  594 + if err != nil {
  595 + return nil, err
  596 + }
  597 + b.body, err = ioutil.ReadAll(reader)
  598 + return b.body, err
  599 + }
  600 + b.body, err = ioutil.ReadAll(resp.Body)
  601 + return b.body, err
  602 +}
  603 +
  604 +// ToFile saves the body data in response to one file.
  605 +// Calls Response inner.
  606 +func (b *BeegoHTTPRequest) ToFile(filename string) error {
  607 + resp, err := b.getResponse()
  608 + if err != nil {
  609 + return err
  610 + }
  611 + if resp.Body == nil {
  612 + return nil
  613 + }
  614 + defer resp.Body.Close()
  615 + err = pathExistAndMkdir(filename)
  616 + if err != nil {
  617 + return err
  618 + }
  619 + f, err := os.Create(filename)
  620 + if err != nil {
  621 + return err
  622 + }
  623 + defer f.Close()
  624 + _, err = io.Copy(f, resp.Body)
  625 + return err
  626 +}
  627 +
  628 +// Check if the file directory exists. If it doesn't then it's created
  629 +func pathExistAndMkdir(filename string) (err error) {
  630 + filename = path.Dir(filename)
  631 + _, err = os.Stat(filename)
  632 + if err == nil {
  633 + return nil
  634 + }
  635 + if os.IsNotExist(err) {
  636 + err = os.MkdirAll(filename, os.ModePerm)
  637 + if err == nil {
  638 + return nil
  639 + }
  640 + }
  641 + return err
  642 +}
  643 +
  644 +// ToJSON returns the map that marshals from the body bytes as json in response.
  645 +// Calls Response inner.
  646 +func (b *BeegoHTTPRequest) ToJSON(v interface{}) error {
  647 + data, err := b.Bytes()
  648 + if err != nil {
  649 + return err
  650 + }
  651 + return json.Unmarshal(data, v)
  652 +}
  653 +
  654 +// ToXML returns the map that marshals from the body bytes as xml in response .
  655 +// Calls Response inner.
  656 +func (b *BeegoHTTPRequest) ToXML(v interface{}) error {
  657 + data, err := b.Bytes()
  658 + if err != nil {
  659 + return err
  660 + }
  661 + return xml.Unmarshal(data, v)
  662 +}
  663 +
  664 +// ToYAML returns the map that marshals from the body bytes as yaml in response .
  665 +// Calls Response inner.
  666 +func (b *BeegoHTTPRequest) ToYAML(v interface{}) error {
  667 + data, err := b.Bytes()
  668 + if err != nil {
  669 + return err
  670 + }
  671 + return yaml.Unmarshal(data, v)
  672 +}
  673 +
  674 +// Response executes request client gets response manually.
  675 +func (b *BeegoHTTPRequest) Response() (*http.Response, error) {
  676 + return b.getResponse()
  677 +}
  678 +
  679 +// TimeoutDialer returns functions of connection dialer with timeout settings for http.Transport Dial field.
  680 +func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) {
  681 + return func(netw, addr string) (net.Conn, error) {
  682 + conn, err := net.DialTimeout(netw, addr, cTimeout)
  683 + if err != nil {
  684 + return nil, err
  685 + }
  686 + err = conn.SetDeadline(time.Now().Add(rwTimeout))
  687 + return conn, err
  688 + }
  689 +}
@@ -23,6 +23,9 @@ github.com/astaxie/beego/plugins/cors @@ -23,6 +23,9 @@ github.com/astaxie/beego/plugins/cors
23 github.com/astaxie/beego/session 23 github.com/astaxie/beego/session
24 github.com/astaxie/beego/toolbox 24 github.com/astaxie/beego/toolbox
25 github.com/astaxie/beego/utils 25 github.com/astaxie/beego/utils
  26 +# github.com/beego/beego/v2 v2.0.1
  27 +## explicit
  28 +github.com/beego/beego/v2/client/httplib
26 # github.com/beorn7/perks v1.0.1 29 # github.com/beorn7/perks v1.0.1
27 github.com/beorn7/perks/quantile 30 github.com/beorn7/perks/quantile
28 # github.com/bsm/sarama-cluster v2.1.15+incompatible 31 # github.com/bsm/sarama-cluster v2.1.15+incompatible
@@ -283,7 +286,7 @@ golang.org/x/text/secure/bidirule @@ -283,7 +286,7 @@ golang.org/x/text/secure/bidirule
283 golang.org/x/text/transform 286 golang.org/x/text/transform
284 golang.org/x/text/unicode/bidi 287 golang.org/x/text/unicode/bidi
285 golang.org/x/text/unicode/norm 288 golang.org/x/text/unicode/norm
286 -# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 289 +# golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
287 golang.org/x/xerrors 290 golang.org/x/xerrors
288 golang.org/x/xerrors/internal 291 golang.org/x/xerrors/internal
289 # google.golang.org/protobuf v1.25.0 292 # google.golang.org/protobuf v1.25.0