作者 Your Name

Merge branch 'test' into master

正在显示 34 个修改的文件 包含 2396 行增加606 行删除

要显示太多修改。

为保证性能只显示 34 of 34+ 个文件。

@@ -3,6 +3,7 @@ module gitlab.fjmaimaimai.com/mmm-go/partnermg @@ -3,6 +3,7 @@ module gitlab.fjmaimaimai.com/mmm-go/partnermg
3 go 1.14 3 go 1.14
4 4
5 require ( 5 require (
  6 + github.com/360EntSecGroup-Skylar/excelize/v2 v2.3.1
6 github.com/GeeTeam/gt3-golang-sdk v0.0.0-20200116043922-446ca8a507d2 7 github.com/GeeTeam/gt3-golang-sdk v0.0.0-20200116043922-446ca8a507d2
7 github.com/Shopify/sarama v1.23.1 8 github.com/Shopify/sarama v1.23.1
8 github.com/ajg/form v1.5.1 // indirect 9 github.com/ajg/form v1.5.1 // indirect
1 package service 1 package service
2 2
3 -import (  
4 - "fmt"  
5 -  
6 - "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/businessBonus/command"  
7 - "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/businessBonus/query"  
8 - "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/factory"  
9 - "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain"  
10 - "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/infrastructure/dao"  
11 - "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib"  
12 -)  
13 -  
14 type BusinessBonusService struct { 3 type BusinessBonusService struct {
15 } 4 }
16 5
@@ -20,160 +9,160 @@ func NewBusinessBonusService(option map[string]interface{}) *BusinessBonusServic @@ -20,160 +9,160 @@ func NewBusinessBonusService(option map[string]interface{}) *BusinessBonusServic
20 } 9 }
21 10
22 // ListBusinessBonus 列表 11 // ListBusinessBonus 列表
23 -func (srv BusinessBonusService) ListBusinessBonus(queryOption query.ListBusinessBonusQuery) (int, interface{}, error) {  
24 - var (  
25 - transactionContext, _ = factory.CreateTransactionContext(nil)  
26 - err error  
27 - )  
28 - if err = transactionContext.StartTransaction(); err != nil {  
29 - return 0, nil, err  
30 - }  
31 - defer func() {  
32 - transactionContext.RollbackTransaction()  
33 - }() 12 +// func (srv BusinessBonusService) ListBusinessBonus(queryOption query.ListBusinessBonusQuery) (int, interface{}, error) {
  13 +// var (
  14 +// transactionContext, _ = factory.CreateTransactionContext(nil)
  15 +// err error
  16 +// )
  17 +// if err = transactionContext.StartTransaction(); err != nil {
  18 +// return 0, nil, err
  19 +// }
  20 +// defer func() {
  21 +// transactionContext.RollbackTransaction()
  22 +// }()
34 23
35 - var (  
36 - bonusDaoao *dao.BusinessBonusDao  
37 - )  
38 - if bonusDaoao, err = factory.CreateBusinessBonusDao(map[string]interface{}{  
39 - "transactionContext": transactionContext,  
40 - }); err != nil {  
41 - return 0, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())  
42 - }  
43 - result, err := bonusDaoao.SearchBusinessBonus(queryOption.PartnerId, queryOption.PartnerNameMatch,  
44 - queryOption.CompanyId, queryOption.Limit, queryOption.Offset)  
45 - if err != nil {  
46 - return 0, nil, err  
47 - }  
48 - cnt, err := bonusDaoao.CountBusinessBonus(queryOption.PartnerId, queryOption.PartnerNameMatch,  
49 - queryOption.CompanyId, queryOption.Limit, queryOption.Offset)  
50 - if err != nil {  
51 - return 0, nil, err  
52 - }  
53 - err = transactionContext.CommitTransaction() 24 +// var (
  25 +// bonusDaoao *dao.BusinessBonusDao
  26 +// )
  27 +// if bonusDaoao, err = factory.CreateBusinessBonusDao(map[string]interface{}{
  28 +// "transactionContext": transactionContext,
  29 +// }); err != nil {
  30 +// return 0, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
  31 +// }
  32 +// result, err := bonusDaoao.SearchBusinessBonus(queryOption.PartnerId, queryOption.PartnerNameMatch,
  33 +// queryOption.CompanyId, queryOption.Limit, queryOption.Offset)
  34 +// if err != nil {
  35 +// return 0, nil, err
  36 +// }
  37 +// cnt, err := bonusDaoao.CountBusinessBonus(queryOption.PartnerId, queryOption.PartnerNameMatch,
  38 +// queryOption.CompanyId, queryOption.Limit, queryOption.Offset)
  39 +// if err != nil {
  40 +// return 0, nil, err
  41 +// }
  42 +// err = transactionContext.CommitTransaction()
54 43
55 - returnData := []map[string]interface{}{}  
56 - for _, v := range result {  
57 - m := map[string]interface{}{  
58 - "id": v.Id,  
59 - "uncollectedDividends": v.BonusNot,  
60 - "receiveDividends": v.BonusHas,  
61 - "dividendsReceivable": v.Bonus,  
62 - "stateOfPayment": v.BonusStatus,  
63 - "stateOfPaymentName": domain.DescribeBusinessBonusStatus(v.BonusStatus),  
64 - "partner": v.PartnerName,  
65 - "updateTime": "",  
66 - }  
67 - if !v.UpdateAt.IsZero() {  
68 - m["updateTime"] = v.UpdateAt.Local().Format("2006-01-02 15:04:05")  
69 - }  
70 - returnData = append(returnData, m)  
71 - }  
72 - return cnt, returnData, nil  
73 -} 44 +// returnData := []map[string]interface{}{}
  45 +// for _, v := range result {
  46 +// m := map[string]interface{}{
  47 +// "id": v.Id,
  48 +// "uncollectedDividends": v.BonusNot,
  49 +// "receiveDividends": v.BonusHas,
  50 +// "dividendsReceivable": v.Bonus,
  51 +// "stateOfPayment": v.BonusStatus,
  52 +// "stateOfPaymentName": domain.DescribeBusinessBonusStatus(v.BonusStatus),
  53 +// "partner": v.PartnerName,
  54 +// "updateTime": "",
  55 +// }
  56 +// if !v.UpdateAt.IsZero() {
  57 +// m["updateTime"] = v.UpdateAt.Local().Format("2006-01-02 15:04:05")
  58 +// }
  59 +// returnData = append(returnData, m)
  60 +// }
  61 +// return cnt, returnData, nil
  62 +// }
74 63
75 -func (srv BusinessBonusService) UpdateBusinessBonus(cmd command.UpdateBusinessBonusCommand) error {  
76 - var (  
77 - transactionContext, _ = factory.CreateTransactionContext(nil)  
78 - err error  
79 - )  
80 - if err = transactionContext.StartTransaction(); err != nil {  
81 - return err  
82 - }  
83 - defer func() {  
84 - transactionContext.RollbackTransaction()  
85 - }()  
86 - var (  
87 - bonusRespository domain.BusinessBonusRepository  
88 - bonusData *domain.BusinessBonus  
89 - )  
90 - if bonusRespository, err = factory.CreateBusinessBonusRepository(map[string]interface{}{  
91 - "transactionContext": transactionContext,  
92 - }); err != nil {  
93 - return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())  
94 - }  
95 - bonusData, err = bonusRespository.FindOne(domain.BusinessBonusFindOneQuery{  
96 - Id: cmd.Id, CompanyId: cmd.CompanyId,  
97 - })  
98 - if err != nil {  
99 - e := fmt.Sprintf("获取业务分红(id=%d;company_id=%d)数据失败:%s", cmd.Id, cmd.CompanyId, err)  
100 - return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)  
101 - }  
102 - bonusData.Bonus = cmd.Bonus  
103 - switch cmd.BonusStatus {  
104 - case domain.BUSINESS_BONUS_HAS_PAY:  
105 - bonusData.BusinessBonusPayStatus.PayPartnerBonus(bonusData)  
106 - case domain.BUSINESS_BONUS_WAIT_PAY:  
107 - bonusData.BusinessBonusPayStatus.WartPayPartnerBonus(bonusData)  
108 - case domain.BUSINESS_BONUS_NULL_PAY:  
109 - bonusData.BusinessBonusPayStatus.NullPayPartnerBonus(bonusData)  
110 - default:  
111 - return lib.ThrowError(lib.BUSINESS_ERROR, "支付状态错误")  
112 - }  
113 - err = bonusRespository.Edit(bonusData)  
114 - if err != nil {  
115 - e := fmt.Sprintf("更新业务分红(id=%d)数据失败:%s", bonusData.Id, err)  
116 - return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)  
117 - }  
118 - err = transactionContext.CommitTransaction()  
119 - return nil  
120 -} 64 +// func (srv BusinessBonusService) UpdateBusinessBonus(cmd command.UpdateBusinessBonusCommand) error {
  65 +// var (
  66 +// transactionContext, _ = factory.CreateTransactionContext(nil)
  67 +// err error
  68 +// )
  69 +// if err = transactionContext.StartTransaction(); err != nil {
  70 +// return err
  71 +// }
  72 +// defer func() {
  73 +// transactionContext.RollbackTransaction()
  74 +// }()
  75 +// var (
  76 +// bonusRespository domain.BusinessBonusRepository
  77 +// bonusData *domain.BusinessBonus
  78 +// )
  79 +// if bonusRespository, err = factory.CreateBusinessBonusRepository(map[string]interface{}{
  80 +// "transactionContext": transactionContext,
  81 +// }); err != nil {
  82 +// return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
  83 +// }
  84 +// bonusData, err = bonusRespository.FindOne(domain.BusinessBonusFindOneQuery{
  85 +// Id: cmd.Id, CompanyId: cmd.CompanyId,
  86 +// })
  87 +// if err != nil {
  88 +// e := fmt.Sprintf("获取业务分红(id=%d;company_id=%d)数据失败:%s", cmd.Id, cmd.CompanyId, err)
  89 +// return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
  90 +// }
  91 +// bonusData.Bonus = cmd.Bonus
  92 +// switch cmd.BonusStatus {
  93 +// case domain.BUSINESS_BONUS_HAS_PAY:
  94 +// bonusData.BusinessBonusPayStatus.PayPartnerBonus(bonusData)
  95 +// case domain.BUSINESS_BONUS_WAIT_PAY:
  96 +// bonusData.BusinessBonusPayStatus.WartPayPartnerBonus(bonusData)
  97 +// case domain.BUSINESS_BONUS_NULL_PAY:
  98 +// bonusData.BusinessBonusPayStatus.NullPayPartnerBonus(bonusData)
  99 +// default:
  100 +// return lib.ThrowError(lib.BUSINESS_ERROR, "支付状态错误")
  101 +// }
  102 +// err = bonusRespository.Edit(bonusData)
  103 +// if err != nil {
  104 +// e := fmt.Sprintf("更新业务分红(id=%d)数据失败:%s", bonusData.Id, err)
  105 +// return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
  106 +// }
  107 +// err = transactionContext.CommitTransaction()
  108 +// return nil
  109 +// }
121 110
122 //GetBusinessBonus 获取详情 111 //GetBusinessBonus 获取详情
123 -func (srv BusinessBonusService) GetBusinessBonus(queryOption query.GetBusinessBonusQuery) (map[string]interface{}, error) { 112 +// func (srv BusinessBonusService) GetBusinessBonus(queryOption query.GetBusinessBonusQuery) (map[string]interface{}, error) {
124 113
125 - var (  
126 - transactionContext, _ = factory.CreateTransactionContext(nil)  
127 - err error  
128 - )  
129 - if err = transactionContext.StartTransaction(); err != nil {  
130 - return nil, err  
131 - }  
132 - defer func() {  
133 - transactionContext.RollbackTransaction()  
134 - }()  
135 - var (  
136 - bonusRespository domain.BusinessBonusRepository  
137 - partnerInfoRepository domain.PartnerInfoRepository  
138 - bonusData *domain.BusinessBonus  
139 - partnerData *domain.PartnerInfo  
140 - )  
141 - if bonusRespository, err = factory.CreateBusinessBonusRepository(map[string]interface{}{  
142 - "transactionContext": transactionContext,  
143 - }); err != nil {  
144 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())  
145 - }  
146 - bonusData, err = bonusRespository.FindOne(domain.BusinessBonusFindOneQuery{  
147 - Id: queryOption.Id, CompanyId: queryOption.CompanyId,  
148 - })  
149 - if err != nil {  
150 - e := fmt.Sprintf("获取业务分红(id=%d;company_id=%d)数据失败:%s", queryOption.Id, queryOption.CompanyId, err)  
151 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)  
152 - }  
153 - if partnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{  
154 - "transactionContext": transactionContext,  
155 - }); err != nil {  
156 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())  
157 - }  
158 - partnerData, err = partnerInfoRepository.FindOne(domain.PartnerFindOneQuery{UserId: bonusData.PartnerInfoId})  
159 - if err != nil {  
160 - e := fmt.Sprintf("获取合伙人(id=%d)数据失败:%s", bonusData.PartnerInfoId, err)  
161 - return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)  
162 - }  
163 - err = transactionContext.CommitTransaction()  
164 - returnData := map[string]interface{}{  
165 - "partner": partnerData.Partner.PartnerName,  
166 - "dividendsReceivable": bonusData.Bonus,  
167 - "receiveDividends": bonusData.BonusHas,  
168 - "uncollectedDividends": bonusData.BonusNot,  
169 - "updateTime": "",  
170 - "stateOfPayment": bonusData.BonusStatus,  
171 - "stateOfPaymentName": domain.DescribeBusinessBonusStatus(bonusData.BonusStatus),  
172 - "id": bonusData.Id,  
173 - }  
174 - if !bonusData.UpdateAt.IsZero() {  
175 - returnData["updateTime"] = bonusData.UpdateAt.Local().Format("2006-01-02 15:04:05")  
176 - } 114 +// var (
  115 +// transactionContext, _ = factory.CreateTransactionContext(nil)
  116 +// err error
  117 +// )
  118 +// if err = transactionContext.StartTransaction(); err != nil {
  119 +// return nil, err
  120 +// }
  121 +// defer func() {
  122 +// transactionContext.RollbackTransaction()
  123 +// }()
  124 +// var (
  125 +// bonusRespository domain.BusinessBonusRepository
  126 +// partnerInfoRepository domain.PartnerInfoRepository
  127 +// bonusData *domain.BusinessBonus
  128 +// partnerData *domain.PartnerInfo
  129 +// )
  130 +// if bonusRespository, err = factory.CreateBusinessBonusRepository(map[string]interface{}{
  131 +// "transactionContext": transactionContext,
  132 +// }); err != nil {
  133 +// return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
  134 +// }
  135 +// bonusData, err = bonusRespository.FindOne(domain.BusinessBonusFindOneQuery{
  136 +// Id: queryOption.Id, CompanyId: queryOption.CompanyId,
  137 +// })
  138 +// if err != nil {
  139 +// e := fmt.Sprintf("获取业务分红(id=%d;company_id=%d)数据失败:%s", queryOption.Id, queryOption.CompanyId, err)
  140 +// return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
  141 +// }
  142 +// if partnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
  143 +// "transactionContext": transactionContext,
  144 +// }); err != nil {
  145 +// return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
  146 +// }
  147 +// partnerData, err = partnerInfoRepository.FindOne(domain.PartnerFindOneQuery{UserId: bonusData.PartnerInfoId})
  148 +// if err != nil {
  149 +// e := fmt.Sprintf("获取合伙人(id=%d)数据失败:%s", bonusData.PartnerInfoId, err)
  150 +// return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
  151 +// }
  152 +// err = transactionContext.CommitTransaction()
  153 +// returnData := map[string]interface{}{
  154 +// "partner": partnerData.Partner.PartnerName,
  155 +// "dividendsReceivable": bonusData.Bonus,
  156 +// "receiveDividends": bonusData.BonusHas,
  157 +// "uncollectedDividends": bonusData.BonusNot,
  158 +// "updateTime": "",
  159 +// "stateOfPayment": bonusData.BonusStatus,
  160 +// "stateOfPaymentName": domain.DescribeBusinessBonusStatus(bonusData.BonusStatus),
  161 +// "id": bonusData.Id,
  162 +// }
  163 +// if !bonusData.UpdateAt.IsZero() {
  164 +// returnData["updateTime"] = bonusData.UpdateAt.Local().Format("2006-01-02 15:04:05")
  165 +// }
177 166
178 - return returnData, nil  
179 -} 167 +// return returnData, nil
  168 +// }
@@ -19,4 +19,6 @@ type CreateOrderCommand struct { @@ -19,4 +19,6 @@ type CreateOrderCommand struct {
19 //货品 19 //货品
20 Goods []OrderGoodData `json:"goods"` 20 Goods []OrderGoodData `json:"goods"`
21 CompanyId int64 `json:"companyId"` 21 CompanyId int64 `json:"companyId"`
  22 +
  23 + PartnerCategory int64 `json:"partner_category"`
22 } 24 }
@@ -20,4 +20,6 @@ type UpdateOrderCommand struct { @@ -20,4 +20,6 @@ type UpdateOrderCommand struct {
20 //货品 20 //货品
21 Goods []OrderGoodData `json:"goods"` 21 Goods []OrderGoodData `json:"goods"`
22 CompanyId int64 `json:"companyId"` 22 CompanyId int64 `json:"companyId"`
  23 +
  24 + PartnerCategory int64 `json:"partner_category"`
23 } 25 }
@@ -2,19 +2,17 @@ package query @@ -2,19 +2,17 @@ package query
2 2
3 //ListOrderQuery 获取用户列表 3 //ListOrderQuery 获取用户列表
4 type ListOrderBaseQuery struct { 4 type ListOrderBaseQuery struct {
5 - //合伙人id  
6 - PartnerId int64 `json:"partnerId" `  
7 - //订单编号  
8 - OrderCode string `json:"order_code"`  
9 // 查询偏离量 5 // 查询偏离量
10 Offset int `json:"offset" ` 6 Offset int `json:"offset" `
11 // 查询限制 7 // 查询限制
12 Limit int `json:"limit"` 8 Limit int `json:"limit"`
13 //发货单号 9 //发货单号
14 - DeliveryCode string `json:"deliveryCode"` 10 + PartnerOrCode string `json:"partnerOrCode"`
15 CompanyId int64 `json:"companyId"` 11 CompanyId int64 `json:"companyId"`
16 -  
17 //订单类型 12 //订单类型
18 OrderType int `json:"orderType"` 13 OrderType int `json:"orderType"`
19 - PartnerOrCode string `json:"partner_or_code"` 14 + //合伙人分类
  15 + PartnerCategory int `json:"partnerCategory"`
  16 + UpdateTimeBegin string `json:"updateTimeBegin"`
  17 + UpdateTimeEnd string `json:"updateTimeEnd"`
20 } 18 }
@@ -6,7 +6,8 @@ type ListOrderBonusQuery struct { @@ -6,7 +6,8 @@ type ListOrderBonusQuery struct {
6 // 查询限制 6 // 查询限制
7 Limit int `json:"limit"` 7 Limit int `json:"limit"`
8 CompanyId int64 `json:"companyId"` 8 CompanyId int64 `json:"companyId"`
  9 + PartnerCategory int `json:"partnerCategory"`
9 //订单类型 10 //订单类型
10 OrderType int `json:"orderType"` 11 OrderType int `json:"orderType"`
11 - PartnerOrCode string `json:"partner_or_code"` 12 + PartnerOrCode string `json:"partnerOrCode"`
12 } 13 }
@@ -29,7 +29,8 @@ func NewOrderInfoService(option map[string]interface{}) *OrderInfoService { @@ -29,7 +29,8 @@ func NewOrderInfoService(option map[string]interface{}) *OrderInfoService {
29 } 29 }
30 30
31 // PageListOrderBase 获取订单列表 31 // PageListOrderBase 获取订单列表
32 -func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrderBaseQuery) ([]domain.OrderBase, int, error) { 32 +func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrderBaseQuery) ([]map[string]interface{}, int, error) {
  33 + var err error
33 transactionContext, err := factory.CreateTransactionContext(nil) 34 transactionContext, err := factory.CreateTransactionContext(nil)
34 if err != nil { 35 if err != nil {
35 return nil, 0, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 36 return nil, 0, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
@@ -41,28 +42,24 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder @@ -41,28 +42,24 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder
41 transactionContext.RollbackTransaction() 42 transactionContext.RollbackTransaction()
42 }() 43 }()
43 var ( 44 var (
44 - orderRepository domain.OrderBaseRepository  
45 - orders []domain.OrderBase 45 + orderDao *dao.OrderBaseDao
  46 + orders []models.OrderBase
46 cnt int 47 cnt int
47 ) 48 )
48 49
49 - if value, err := factory.CreateOrderBaseRepository(map[string]interface{}{ 50 + if orderDao, err = factory.CreateOrderBaseDao(map[string]interface{}{
50 "transactionContext": transactionContext, 51 "transactionContext": transactionContext,
51 }); err != nil { 52 }); err != nil {
52 return nil, 0, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 53 return nil, 0, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
53 - } else {  
54 - orderRepository = value  
55 - }  
56 - query := domain.OrderBaseFindQuery{  
57 - PartnerId: listOrderQuery.PartnerId,  
58 - OrderCode: listOrderQuery.OrderCode,  
59 - Offset: listOrderQuery.Offset,  
60 - Limit: listOrderQuery.Limit,  
61 - OrderType: listOrderQuery.OrderType,  
62 - DeliveryCode: listOrderQuery.DeliveryCode,  
63 - CompanyId: listOrderQuery.CompanyId,  
64 } 54 }
65 - orders, cnt, err = orderRepository.Find(query) 55 + orders, cnt, err = orderDao.OrderListByCondition(
  56 + listOrderQuery.CompanyId,
  57 + listOrderQuery.OrderType,
  58 + listOrderQuery.PartnerOrCode,
  59 + [2]string{listOrderQuery.UpdateTimeBegin, listOrderQuery.UpdateTimeEnd},
  60 + listOrderQuery.PartnerCategory,
  61 + listOrderQuery.Limit, listOrderQuery.Offset,
  62 + )
66 if err != nil { 63 if err != nil {
67 return nil, 0, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 64 return nil, 0, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
68 } 65 }
@@ -72,6 +69,9 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder @@ -72,6 +69,9 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder
72 }); err != nil { 69 }); err != nil {
73 return nil, 0, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 70 return nil, 0, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
74 } 71 }
  72 +
  73 + orderDataReturn := make([]map[string]interface{}, 0)
  74 +
75 for i := range orders { 75 for i := range orders {
76 partnerData := &domain.PartnerInfo{} 76 partnerData := &domain.PartnerInfo{}
77 partnerData, err = PartnerInfoRepository.FindOne(domain.PartnerFindOneQuery{ 77 partnerData, err = PartnerInfoRepository.FindOne(domain.PartnerFindOneQuery{
@@ -79,12 +79,35 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder @@ -79,12 +79,35 @@ func (service OrderInfoService) PageListOrderBase(listOrderQuery query.ListOrder
79 }) 79 })
80 if err != nil { 80 if err != nil {
81 logs.Error("获取合伙(id=%d)失败%s", orders[i].PartnerId, err) 81 logs.Error("获取合伙(id=%d)失败%s", orders[i].PartnerId, err)
82 - } else {  
83 - orders[i].PartnerInfo = partnerData.Partner  
84 } 82 }
  83 + listIndex := listOrderQuery.Offset + (1 + i)
  84 + m := map[string]interface{}{
  85 + "index": listIndex,
  86 + "createTime": orders[i].CreateTime.Local().Format("2006-01-02 15:04:05"),
  87 + "updateTime": orders[i].UpdateTime.Local().Format("2006-01-02 15:04:05"),
  88 + "buyer": orders[i].Buyer.BuyerName,
  89 + "id": orders[i].Id,
  90 + "orderId": orders[i].OrderCode,
  91 + "shipmentsId": orders[i].DeliveryCode,
  92 + "partner": partnerData.Partner.PartnerName,
  93 + "orderNum": orders[i].PlanOrderCount,
  94 + "orderPrice": orders[i].PlanOrderAmount,
  95 + "orderDist": orders[i].RegionInfo.RegionName,
  96 + "quantityControl": "",
  97 + "priceControl": "",
  98 + "status": orders[i].IsDisable,
  99 + "partnerCategory": orders[i].PartnerCategory.Name,
  100 + }
  101 + if orders[i].UseOrderCount >= 0 {
  102 + m["quantityControl"] = fmt.Sprint(orders[i].UseOrderCount)
  103 + }
  104 + if orders[i].UseOrderAmount >= 0 {
  105 + m["priceControl"] = fmt.Sprint(orders[i].UseOrderAmount)
  106 + }
  107 + orderDataReturn = append(orderDataReturn, m)
85 } 108 }
86 transactionContext.CommitTransaction() 109 transactionContext.CommitTransaction()
87 - return orders, cnt, nil 110 + return orderDataReturn, cnt, nil
88 } 111 }
89 112
90 //GetOrderDetail 获取订单详情 113 //GetOrderDetail 获取订单详情
@@ -202,11 +225,11 @@ func (service OrderInfoService) CreateNewOrder(cmd command.CreateOrderCommand) ( @@ -202,11 +225,11 @@ func (service OrderInfoService) CreateNewOrder(cmd command.CreateOrderCommand) (
202 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 225 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
203 } 226 }
204 //检查order_code是否重复 227 //检查order_code是否重复
205 - // if ok, err := orderBaseDao.OrderCodeExist(cmd.OrderCode); err != nil {  
206 - // return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())  
207 - // } else if ok {  
208 - // return nil, lib.ThrowError(lib.BUSINESS_ERROR, "订单号已存在")  
209 - // } 228 + if ok, err := orderBaseDao.OrderCodeExist(cmd.OrderCode, cmd.PartnerCategory, cmd.PartnerId); err != nil {
  229 + return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
  230 + } else if ok {
  231 + return nil, lib.ThrowError(lib.BUSINESS_ERROR, "订单号已存在")
  232 + }
210 //检查delivery_code是否重复 233 //检查delivery_code是否重复
211 if len(cmd.DeliveryCode) > 0 { 234 if len(cmd.DeliveryCode) > 0 {
212 if ok, err := orderBaseDao.DeliveryCodeExist(cmd.DeliveryCode, cmd.CompanyId); err != nil { 235 if ok, err := orderBaseDao.DeliveryCodeExist(cmd.DeliveryCode, cmd.CompanyId); err != nil {
@@ -229,6 +252,32 @@ func (service OrderInfoService) CreateNewOrder(cmd command.CreateOrderCommand) ( @@ -229,6 +252,32 @@ func (service OrderInfoService) CreateNewOrder(cmd command.CreateOrderCommand) (
229 SalesmanBonusPercent: cmd.SalesmanBonusPercent, 252 SalesmanBonusPercent: cmd.SalesmanBonusPercent,
230 CompanyId: cmd.CompanyId, 253 CompanyId: cmd.CompanyId,
231 } 254 }
  255 + var categoryRepository domain.PartnerCategoryRepository
  256 + if categoryRepository, err = factory.CreatePartnerCategoryRepository(map[string]interface{}{
  257 + "transactionContext": transactionContext,
  258 + }); err != nil {
  259 + return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
  260 + }
  261 + var cmdPartnerCategoryOk bool
  262 + for _, v := range partnerData.PartnerCategoryInfos {
  263 + if v.Id == cmd.PartnerCategory {
  264 + _, categorys, err := categoryRepository.Find(domain.PartnerCategoryFindQuery{
  265 + Ids: []int64{v.Id},
  266 + })
  267 + if err != nil {
  268 + e := fmt.Sprintf("获取合伙人分类数据失败:%s", err)
  269 + return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
  270 + }
  271 + if len(categorys) > 0 {
  272 + newOrder.PartnerCategory = categorys[0]
  273 + cmdPartnerCategoryOk = true
  274 + }
  275 + break
  276 + }
  277 + }
  278 + if !cmdPartnerCategoryOk {
  279 + return nil, lib.ThrowError(lib.BUSINESS_ERROR, "合伙人类型选择错误")
  280 + }
232 var orderGoods []domain.OrderGood 281 var orderGoods []domain.OrderGood
233 for _, good := range cmd.Goods { 282 for _, good := range cmd.Goods {
234 m := domain.NewOrderGood() 283 m := domain.NewOrderGood()
@@ -378,13 +427,15 @@ func (service OrderInfoService) UpdateOrderData(cmd command.UpdateOrderCommand) @@ -378,13 +427,15 @@ func (service OrderInfoService) UpdateOrderData(cmd command.UpdateOrderCommand)
378 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 427 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
379 } 428 }
380 //检查order_code是否重复 429 //检查order_code是否重复
381 - // if ok, err := orderBaseDao.OrderCodeExist(cmd.OrderCode, cmd.Id); err != nil {  
382 - // return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())  
383 - // } else if ok {  
384 - // return nil, lib.ThrowError(lib.BUSINESS_ERROR, "订单号已存在")  
385 - // } 430 + if oldOrderData.OrderCode != cmd.OrderCode || cmd.PartnerCategory != oldOrderData.PartnerCategory.Id {
  431 + if ok, err := orderBaseDao.OrderCodeExist(cmd.OrderCode, cmd.PartnerCategory, cmd.PartnerId); err != nil {
  432 + return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
  433 + } else if ok {
  434 + return nil, lib.ThrowError(lib.BUSINESS_ERROR, "订单号已存在")
  435 + }
  436 + }
386 //检查delivery_code是否重复 437 //检查delivery_code是否重复
387 - if len(cmd.DeliveryCode) > 0 { 438 + if cmd.DeliveryCode != oldOrderData.DeliveryCode {
388 if ok, err := orderBaseDao.DeliveryCodeExist(cmd.DeliveryCode, cmd.CompanyId, cmd.Id); err != nil { 439 if ok, err := orderBaseDao.DeliveryCodeExist(cmd.DeliveryCode, cmd.CompanyId, cmd.Id); err != nil {
389 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 440 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
390 } else if ok { 441 } else if ok {
@@ -418,6 +469,16 @@ func (service OrderInfoService) UpdateOrderData(cmd command.UpdateOrderCommand) @@ -418,6 +469,16 @@ func (service OrderInfoService) UpdateOrderData(cmd command.UpdateOrderCommand)
418 } 469 }
419 newOrderGoods = append(newOrderGoods, m) 470 newOrderGoods = append(newOrderGoods, m)
420 } 471 }
  472 + var cmdPartnerCategoryOk bool
  473 + for _, v := range partnerData.PartnerCategoryInfos {
  474 + if v.Id == cmd.PartnerCategory {
  475 + oldOrderData.PartnerCategory = v
  476 + cmdPartnerCategoryOk = true
  477 + }
  478 + }
  479 + if !cmdPartnerCategoryOk {
  480 + return nil, lib.ThrowError(lib.BUSINESS_ERROR, "合伙人类型选择错误")
  481 + }
421 oldOrderData.OrderCode = cmd.OrderCode 482 oldOrderData.OrderCode = cmd.OrderCode
422 oldOrderData.DeliveryCode = cmd.DeliveryCode 483 oldOrderData.DeliveryCode = cmd.DeliveryCode
423 oldOrderData.Buyer.BuyerName = cmd.BuyerName 484 oldOrderData.Buyer.BuyerName = cmd.BuyerName
@@ -744,6 +805,7 @@ func (service OrderInfoService) PageListOrderBonus(listOrderQuery query.ListOrde @@ -744,6 +805,7 @@ func (service OrderInfoService) PageListOrderBonus(listOrderQuery query.ListOrde
744 listOrderQuery.CompanyId, 805 listOrderQuery.CompanyId,
745 listOrderQuery.OrderType, 806 listOrderQuery.OrderType,
746 listOrderQuery.PartnerOrCode, 807 listOrderQuery.PartnerOrCode,
  808 + listOrderQuery.PartnerCategory,
747 listOrderQuery.Limit, 809 listOrderQuery.Limit,
748 listOrderQuery.Offset, 810 listOrderQuery.Offset,
749 ) 811 )
@@ -804,7 +866,9 @@ func (service OrderInfoService) PageListOrderBonus(listOrderQuery query.ListOrde @@ -804,7 +866,9 @@ func (service OrderInfoService) PageListOrderBonus(listOrderQuery query.ListOrde
804 hasBonusPercent = true 866 hasBonusPercent = true
805 } 867 }
806 } 868 }
  869 + listIndex := listOrderQuery.Offset + (1 + i)
807 listItem := map[string]interface{}{ 870 listItem := map[string]interface{}{
  871 + "index": listIndex,
808 "updateTime": orders[i].UpdateTime.Local().Format("2006-01-02 15:04:05"), 872 "updateTime": orders[i].UpdateTime.Local().Format("2006-01-02 15:04:05"),
809 "id": orders[i].Id, 873 "id": orders[i].Id,
810 "shipmentsId": orders[i].DeliveryCode, 874 "shipmentsId": orders[i].DeliveryCode,
@@ -1178,3 +1242,82 @@ func (service OrderInfoService) UpdateOrderRemarkBonus(orderId int64, adminId in @@ -1178,3 +1242,82 @@ func (service OrderInfoService) UpdateOrderRemarkBonus(orderId int64, adminId in
1178 } 1242 }
1179 return nil 1243 return nil
1180 } 1244 }
  1245 +
  1246 +func (service OrderInfoService) ListOrderBonusForExcel(listOrderQuery query.ListOrderBonusQuery) ([]map[string]string, [][2]string, error) {
  1247 + transactionContext, err := factory.CreateTransactionContext(nil)
  1248 + if err != nil {
  1249 + return nil, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
  1250 + }
  1251 + if err = transactionContext.StartTransaction(); err != nil {
  1252 + return nil, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
  1253 + }
  1254 + defer func() {
  1255 + transactionContext.RollbackTransaction()
  1256 + }()
  1257 + var (
  1258 + orderBaseDao *dao.OrderBaseDao
  1259 + )
  1260 +
  1261 + if orderBaseDao, err = factory.CreateOrderBaseDao(map[string]interface{}{
  1262 + "transactionContext": transactionContext,
  1263 + }); err != nil {
  1264 + return nil, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
  1265 + }
  1266 + result, err := orderBaseDao.OrderBonusListForExcel(
  1267 + listOrderQuery.CompanyId,
  1268 + listOrderQuery.OrderType,
  1269 + listOrderQuery.PartnerOrCode,
  1270 + listOrderQuery.PartnerCategory,
  1271 + )
  1272 + if err != nil {
  1273 + return nil, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
  1274 + }
  1275 +
  1276 + err = transactionContext.CommitTransaction()
  1277 + if err != nil {
  1278 + return nil, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
  1279 + }
  1280 + var resultMaps []map[string]string
  1281 + for i := range result {
  1282 + m := map[string]string{
  1283 + "num": fmt.Sprint(i + 1),
  1284 + "order_type": domain.GetOrderBaseTypeName(result[i].OrderType),
  1285 + "order_code": result[i].OrderCode,
  1286 + "delivery_code": result[i].DeliveryCode,
  1287 + "partner_name": result[i].PartnerName,
  1288 + "bonus_status": "",
  1289 + "update_time": result[i].UpdateTime,
  1290 + "partner_bonus": fmt.Sprint(result[i].PartnerBonus),
  1291 + "partner_bonus_has": fmt.Sprint(result[i].PartnerBonusHas),
  1292 + "partner_bonus_not": fmt.Sprint(result[i].PartnerBonusNot),
  1293 + "partner_bonus_expense": fmt.Sprint(result[i].PartnerBonusExpense),
  1294 + }
  1295 + if result[i].HasBonusPercent == 0 {
  1296 + m["partner_bonus"] = "-"
  1297 + m["partner_bonus_has"] = "-"
  1298 + m["partner_bonus_not"] = "-"
  1299 + m["partner_bonus_expense"] = "-"
  1300 + }
  1301 + switch result[i].BonusStatus {
  1302 + case domain.OrderGoodWaitPay:
  1303 + m["bonus_status"] = "等待支付分红"
  1304 + case domain.OrderGoodHasPay:
  1305 + m["bonus_status"] = "已支付分红"
  1306 + }
  1307 + resultMaps = append(resultMaps, m)
  1308 + }
  1309 + column := [][2]string{
  1310 + [2]string{"num", "序号"},
  1311 + [2]string{"order_type", "订单类型"},
  1312 + [2]string{"order_code", "订单号"},
  1313 + [2]string{"delivery_code", "发货单号"},
  1314 + [2]string{"partner_name", "合伙人"},
  1315 + [2]string{"bonus_status", "支付状态"},
  1316 + [2]string{"update_time", "最后操作时间"},
  1317 + [2]string{"partner_bonus", "应收分红"},
  1318 + [2]string{"partner_bonus_has", "已收分红"},
  1319 + [2]string{"partner_bonus_not", "未收分红"},
  1320 + [2]string{"partner_bonus_expense", "分红支出"},
  1321 + }
  1322 + return resultMaps, column, nil
  1323 +}
@@ -250,6 +250,7 @@ func (s SyncOrderService) copyOrderBestshopToOrderBase(orderBestshop *domain.Ord @@ -250,6 +250,7 @@ func (s SyncOrderService) copyOrderBestshopToOrderBase(orderBestshop *domain.Ord
250 orderbase.Goods = ordergoods 250 orderbase.Goods = ordergoods
251 orderbase.PartnerId = partnerData.Partner.Id 251 orderbase.PartnerId = partnerData.Partner.Id
252 orderbase.CompanyId = partnerData.CompanyId 252 orderbase.CompanyId = partnerData.CompanyId
  253 + orderbase.PartnerCategory = domain.PartnerCategory{Id: 1, Name: "事业合伙人"} // 默认设定为事业合伙人订单
253 orderbase.Compute() 254 orderbase.Compute()
254 err = orderBaseRepository.Save(&orderbase) 255 err = orderBaseRepository.Save(&orderbase)
255 if err != nil { 256 if err != nil {
@@ -20,6 +20,7 @@ type CompanyBaseApplet struct { @@ -20,6 +20,7 @@ type CompanyBaseApplet struct {
20 Name string `json:"name"` 20 Name string `json:"name"`
21 URL string `json:"url"` 21 URL string `json:"url"`
22 Id string `json:"id"` 22 Id string `json:"id"`
  23 + ImageUrl string `json:"imageUrl"`
23 } 24 }
24 25
25 //企业平台的公司基础数据 26 //企业平台的公司基础数据
@@ -117,6 +118,7 @@ func (service SyncCompanyService) addCompany(data CompanytData) error { @@ -117,6 +118,7 @@ func (service SyncCompanyService) addCompany(data CompanytData) error {
117 Name: v.Name, 118 Name: v.Name,
118 URL: v.URL, 119 URL: v.URL,
119 Id: v.Id, 120 Id: v.Id,
  121 + ImageUrl: v.ImageUrl,
120 } 122 }
121 applets = append(applets, app) 123 applets = append(applets, app)
122 } 124 }
@@ -210,6 +212,7 @@ func (service SyncCompanyService) updateCompany(data CompanytData) error { @@ -210,6 +212,7 @@ func (service SyncCompanyService) updateCompany(data CompanytData) error {
210 Name: v.Name, 212 Name: v.Name,
211 URL: v.URL, 213 URL: v.URL,
212 Id: v.Id, 214 Id: v.Id,
  215 + ImageUrl: v.ImageUrl,
213 } 216 }
214 applets = append(applets, app) 217 applets = append(applets, app)
215 } 218 }
1 package service 1 package service
2 2
3 import ( 3 import (
4 - "errors"  
5 -  
6 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/unifiedUserCenter/command" 4 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/unifiedUserCenter/command"
7 ) 5 )
8 6
@@ -30,7 +28,7 @@ func NewSyncAction(cmd command.SyncCallbackCommand) error { @@ -30,7 +28,7 @@ func NewSyncAction(cmd command.SyncCallbackCommand) error {
30 ok bool 28 ok bool
31 ) 29 )
32 if action, ok = actionMap[cmd.Module]; !ok { 30 if action, ok = actionMap[cmd.Module]; !ok {
33 - return errors.New("module cannot found") 31 + return nil
34 } 32 }
35 return action.DoAction(cmd.Action, cmd.Data) 33 return action.DoAction(cmd.Action, cmd.Data)
36 } 34 }
@@ -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{"192.168.190.136:9092"}, 17 + Servers: []string{""},
18 ConsumerId: "partnermg_local", 18 ConsumerId: "partnermg_local",
19 } 19 }
20 if os.Getenv("KAFKA_HOST") != "" { 20 if os.Getenv("KAFKA_HOST") != "" {
@@ -21,6 +21,7 @@ type CompanyApplets struct { @@ -21,6 +21,7 @@ type CompanyApplets struct {
21 Name string `json:"name"` 21 Name string `json:"name"`
22 URL string `json:"url"` 22 URL string `json:"url"`
23 Id string `json:"id"` 23 Id string `json:"id"`
  24 + ImageUrl string `json:"imageUrl"`
24 } 25 }
25 26
26 // 公司信息 27 // 公司信息
@@ -114,6 +114,8 @@ type OrderBase struct { @@ -114,6 +114,8 @@ type OrderBase struct {
114 DataFrom OrderDataFrom `json:"dataFrom"` 114 DataFrom OrderDataFrom `json:"dataFrom"`
115 //备注 115 //备注
116 Remark OrderBaseRemark `json:"remark"` 116 Remark OrderBaseRemark `json:"remark"`
  117 +
  118 + PartnerCategory PartnerCategory `json:"partnerCategory"`
117 } 119 }
118 120
119 //GetCurrentPartnerBonus 获取当前合伙人应收分红 121 //GetCurrentPartnerBonus 获取当前合伙人应收分红
@@ -4,7 +4,6 @@ import ( @@ -4,7 +4,6 @@ import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/go-pg/pg/v10/orm" 6 "github.com/go-pg/pg/v10/orm"
7 -  
8 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain" 7 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain"
9 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/infrastructure/pg/models" 8 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/infrastructure/pg/models"
10 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/infrastructure/pg/transaction" 9 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/infrastructure/pg/transaction"
@@ -24,13 +23,15 @@ func NewOrderBaseDao(transactionContext *transaction.TransactionContext) (*Order @@ -24,13 +23,15 @@ func NewOrderBaseDao(transactionContext *transaction.TransactionContext) (*Order
24 } 23 }
25 } 24 }
26 25
27 -func (dao OrderBaseDao) OrderCodeExist(code string, notId ...int64) (bool, error) { 26 +//OrderCodeExist 检查order_code是否重复
  27 +//
  28 +func (dao OrderBaseDao) OrderCodeExist(code string, partnerCategory int64, partnerId int64) (bool, error) {
28 tx := dao.transactionContext.GetDB() 29 tx := dao.transactionContext.GetDB()
29 m := &models.OrderBase{} 30 m := &models.OrderBase{}
30 - query := tx.Model(m).Where("order_code=?", code)  
31 - if len(notId) > 0 {  
32 - query = query.WhereIn("id not in(?)", notId)  
33 - } 31 + query := tx.Model(m).
  32 + Where("order_code=?", code).
  33 + Where("partner_id=?", partnerId).
  34 + Where(`partner_category @>'{"id":?}'`, partnerCategory)
34 ok, err := query.Exists() 35 ok, err := query.Exists()
35 return ok, err 36 return ok, err
36 } 37 }
@@ -49,7 +50,8 @@ func (dao OrderBaseDao) DeliveryCodeExist(code string, companyId int64, notId .. @@ -49,7 +50,8 @@ func (dao OrderBaseDao) DeliveryCodeExist(code string, companyId int64, notId ..
49 //OrderListByCondition 根据条件获取订单分红列表 50 //OrderListByCondition 根据条件获取订单分红列表
50 //orderType 订单类型 51 //orderType 订单类型
51 //partnerOrCode 合伙人姓名或订单号或发货单号 52 //partnerOrCode 合伙人姓名或订单号或发货单号
52 -func (dao OrderBaseDao) OrderBonusListByCondition(companyId int64, orderType int, partnerOrCode string, limit, offset int) ([]models.OrderBase, int, error) { 53 +func (dao OrderBaseDao) OrderBonusListByCondition(companyId int64, orderType int, partnerOrCode string,
  54 + partnerCategory int, limit, offset int) ([]models.OrderBase, int, error) {
53 tx := dao.transactionContext.GetDB() 55 tx := dao.transactionContext.GetDB()
54 var orders []models.OrderBase 56 var orders []models.OrderBase
55 query := tx.Model(&orders).Where("order_base.company_id=?", companyId) 57 query := tx.Model(&orders).Where("order_base.company_id=?", companyId)
@@ -58,6 +60,9 @@ func (dao OrderBaseDao) OrderBonusListByCondition(companyId int64, orderType int @@ -58,6 +60,9 @@ func (dao OrderBaseDao) OrderBonusListByCondition(companyId int64, orderType int
58 } else { 60 } else {
59 query = query.Where("order_base.order_type<>?", domain.OrderIntention) 61 query = query.Where("order_base.order_type<>?", domain.OrderIntention)
60 } 62 }
  63 + if partnerCategory > 0 {
  64 + query = query.Where(`order_base.partner_category@>'{"id":?}'`, partnerCategory)
  65 + }
61 if len(partnerOrCode) > 0 { 66 if len(partnerOrCode) > 0 {
62 query = query.Join("LEFT JOIN partner_info as p ON order_base.partner_id=p.id"). 67 query = query.Join("LEFT JOIN partner_info as p ON order_base.partner_id=p.id").
63 WhereGroup(func(q *orm.Query) (*orm.Query, error) { 68 WhereGroup(func(q *orm.Query) (*orm.Query, error) {
@@ -74,3 +79,128 @@ func (dao OrderBaseDao) OrderBonusListByCondition(companyId int64, orderType int @@ -74,3 +79,128 @@ func (dao OrderBaseDao) OrderBonusListByCondition(companyId int64, orderType int
74 cnt, err := query.SelectAndCount() 79 cnt, err := query.SelectAndCount()
75 return orders, cnt, err 80 return orders, cnt, err
76 } 81 }
  82 +
  83 +//CustomOrderBonusForExcel 导出分红列表所用的结构
  84 +type CustomOrderBonusForExcel struct {
  85 + OrderId int64
  86 + OrderType int
  87 + OrderCode string
  88 + BonusStatus int
  89 + DeliveryCode string
  90 + UpdateTime string
  91 + PartnerBonus float64
  92 + PartnerBonusHas float64
  93 + PartnerBonusNot float64
  94 + PartnerBonusExpense float64
  95 + HasBonusPercent int
  96 + PartnerName string
  97 +}
  98 +
  99 +//OrderBonusListForExcel 导出分红列表所用
  100 +//@param companyId 公司id
  101 +//@param orderType 订单类型
  102 +//@param partnerOrCode 合伙人姓名或订单号或发货单号
  103 +//@param partnerCategory 合伙人类型id
  104 +//@return result 查询结果数据
  105 +func (dao OrderBaseDao) OrderBonusListForExcel(companyId int64, orderType int, partnerOrCode string,
  106 + partnerCategory int) (result []CustomOrderBonusForExcel, err error) {
  107 + //导出分红列表所用的sql
  108 + sqlStr := `SELECT
  109 + t1.ID AS order_id,
  110 + t1.order_type,
  111 + t1.order_code,
  112 + t1.delivery_code,
  113 + t1.bonus_status,
  114 + to_char(t1.update_time AT TIME ZONE 'CCT' ,'YYYY-MM-DD HH24:MI:SS') AS update_time,
  115 + (CASE
  116 + WHEN t1.use_partner_bonus>0
  117 + THEN
  118 + t1.use_partner_bonus
  119 + ELSE
  120 + t1.plan_partner_bonus
  121 + END) AS partner_bonus,
  122 + t1.partner_bonus_has,
  123 + t1.partner_bonus_not,
  124 + t1.partner_bonus_expense,
  125 + tt1.has_bonus_percent,
  126 + t2.partner_name
  127 + FROM
  128 + order_base AS t1
  129 + LEFT JOIN partner_info AS t2 ON t1.partner_id = t2."id"
  130 + LEFT JOIN (
  131 + SELECT COUNT ( * ) AS has_bonus_percent, t3.order_id
  132 + FROM "order_good" AS t3
  133 + WHERE t3.partner_bonus_percent >= 0
  134 + GROUP BY t3.order_id
  135 + ) AS tt1 ON t1."id" = tt1.order_id
  136 + WHERE 1=1 `
  137 + sqlStr += ` AND t1.company_id = ? `
  138 + param := []interface{}{companyId}
  139 + if orderType > 0 {
  140 + param = append(param, orderType)
  141 + sqlStr += ` AND t1.order_type=? `
  142 + } else {
  143 + param = append(param, domain.OrderIntention)
  144 + sqlStr += ` AND t1.order_type<>? `
  145 + }
  146 + if len(partnerOrCode) > 0 {
  147 + sqlStr += ` AND (t1.order_code like ? OR t1.delivery_code like ? OR t2.partner_name like ? )`
  148 + likeParam := "%" + partnerOrCode + "%"
  149 + param = append(param, likeParam, likeParam, likeParam)
  150 + }
  151 + if partnerCategory > 0 {
  152 + sqlStr += ` AND t1.partner_category @>'{"id":?}'`
  153 + param = append(param, partnerCategory)
  154 + }
  155 + sqlStr += ` ORDER BY t1.update_time DESC limit 10000 `
  156 + tx := dao.transactionContext.GetDB()
  157 + _, err = tx.Query(&result, sqlStr, param...)
  158 +
  159 + if err != nil {
  160 + return result, err
  161 + }
  162 + return result, nil
  163 +}
  164 +
  165 +//OrderListByCondition 获取实际订单列表
  166 +//@param companyId 公司id
  167 +//@param orderType 订单类型
  168 +//@param partnerOrCode 合伙人姓名或订单号或发货单号
  169 +//@param partnerCategory 合伙人类型id
  170 +//@param updateTime 订单更新时间范围"[开始时间,结束时间]",时间格式"2006-01-02 15:04:05+07"
  171 +func (dao OrderBaseDao) OrderListByCondition(companyId int64, orderType int, partnerOrCode string,
  172 + updateTime [2]string, partnerCategory int, limit, offset int) ([]models.OrderBase, int, error) {
  173 + tx := dao.transactionContext.GetDB()
  174 + var orders []models.OrderBase
  175 + query := tx.Model(&orders).Where("order_base.company_id=?", companyId)
  176 + if orderType > 0 {
  177 + query = query.Where("order_base.order_type=?", orderType)
  178 + } else {
  179 + query = query.Where("order_base.order_type<>?", domain.OrderIntention)
  180 + }
  181 + if partnerCategory > 0 {
  182 + query = query.Where(`order_base.partner_category@>'{"id":?}'`, partnerCategory)
  183 + }
  184 + if len(updateTime[0]) > 0 {
  185 + query = query.Where(`order_base.update_time>=?`, updateTime[0])
  186 + }
  187 + if len(updateTime[1]) > 0 {
  188 + query = query.Where(`order_base.update_time<=?`, updateTime[1])
  189 + }
  190 + if len(partnerOrCode) > 0 {
  191 + query = query.Join("LEFT JOIN partner_info as p ON order_base.partner_id=p.id").
  192 + WhereGroup(func(q *orm.Query) (*orm.Query, error) {
  193 + q = q.WhereOr("order_base.order_code like ? ", "%"+partnerOrCode+"%").
  194 + WhereOr("order_base.delivery_code like ? ", "%"+partnerOrCode+"%").
  195 + WhereOr("p.partner_name like ? ", "%"+partnerOrCode+"%")
  196 + return q, nil
  197 + })
  198 + }
  199 + query = query.Order("order_base.update_time DESC").
  200 + Offset(offset).
  201 + Limit(limit)
  202 +
  203 + cnt, err := query.SelectAndCount()
  204 + return orders, cnt, err
  205 +
  206 +}
@@ -67,6 +67,8 @@ type OrderBase struct { @@ -67,6 +67,8 @@ type OrderBase struct {
67 DataFrom domain.OrderDataFrom `` 67 DataFrom domain.OrderDataFrom ``
68 //备注 68 //备注
69 Remark domain.OrderBaseRemark `` 69 Remark domain.OrderBaseRemark ``
  70 + //合伙人类型
  71 + PartnerCategory domain.PartnerCategory ``
70 } 72 }
71 73
72 var _ pg.BeforeUpdateHook = (*OrderBase)(nil) 74 var _ pg.BeforeUpdateHook = (*OrderBase)(nil)
@@ -44,6 +44,7 @@ func (reponsitory OrderBaseRepository) transformPgModelToDomainModel(orderModel @@ -44,6 +44,7 @@ func (reponsitory OrderBaseRepository) transformPgModelToDomainModel(orderModel
44 CompanyId: orderModel.CompanyId, 44 CompanyId: orderModel.CompanyId,
45 DataFrom: orderModel.DataFrom, 45 DataFrom: orderModel.DataFrom,
46 Remark: orderModel.Remark, 46 Remark: orderModel.Remark,
  47 + PartnerCategory: orderModel.PartnerCategory,
47 } 48 }
48 return order, nil 49 return order, nil
49 } 50 }
@@ -65,7 +66,7 @@ func (repository OrderBaseRepository) Save(orderInfo *domain.OrderBase) error { @@ -65,7 +66,7 @@ func (repository OrderBaseRepository) Save(orderInfo *domain.OrderBase) error {
65 PartnerBonusExpense: orderInfo.OrderCompute.PartnerBonusExpense, IsDisable: orderInfo.IsDisable, 66 PartnerBonusExpense: orderInfo.OrderCompute.PartnerBonusExpense, IsDisable: orderInfo.IsDisable,
66 CreateTime: orderInfo.CreateTime, BonusStatus: orderInfo.BonusStatus, 67 CreateTime: orderInfo.CreateTime, BonusStatus: orderInfo.BonusStatus,
67 CompanyId: orderInfo.CompanyId, DataFrom: orderInfo.DataFrom, 68 CompanyId: orderInfo.CompanyId, DataFrom: orderInfo.DataFrom,
68 - Remark: orderInfo.Remark, 69 + Remark: orderInfo.Remark, PartnerCategory: orderInfo.PartnerCategory,
69 } 70 }
70 if m.Id == 0 { 71 if m.Id == 0 {
71 _, err = tx.Model(m). 72 _, err = tx.Model(m).
  1 +package exceltool
  2 +
  3 +import (
  4 + "errors"
  5 + "fmt"
  6 + "math/rand"
  7 + "time"
  8 +
  9 + excelize "github.com/360EntSecGroup-Skylar/excelize/v2"
  10 +)
  11 +
  12 +type ExcelHead struct {
  13 + Name string
  14 + Key string
  15 +}
  16 +
  17 +//ExcelMaker 构建excel文档
  18 +type ExcelMaker struct {
  19 + Xlsx *excelize.File
  20 + fileName string
  21 + header []ExcelHead
  22 +}
  23 +
  24 +//NewExcelMaker ....
  25 +func NewExcelMaker() *ExcelMaker {
  26 + return &ExcelMaker{
  27 + Xlsx: excelize.NewFile(),
  28 + }
  29 +}
  30 +
  31 +func (e *ExcelMaker) SetListHead(h []ExcelHead) {
  32 + e.header = h
  33 +}
  34 +
  35 +func (e *ExcelMaker) SetFileName(n string) {
  36 + e.fileName = n
  37 +}
  38 +
  39 +func (e *ExcelMaker) GetFileName() string {
  40 + return e.fileName
  41 +}
  42 +
  43 +//MakeListExcel 根据列表形式的数据创建excel文档
  44 +//@sourData []map[string]string; 原始数据,要输入excel文档的数据
  45 +func (e *ExcelMaker) MakeListExcel(sourData []map[string]string) (err error) {
  46 + if len(e.header) == 0 {
  47 + return errors.New("xlsHeader 数据格式错误")
  48 + }
  49 + headEn := []string{} //数据字段英文名
  50 + headCn := []string{} //excel字段中文描述
  51 + alphaSlice := []string{} //excel列字母索引
  52 + for key, val := range e.header {
  53 + headEn = append(headEn, val.Key)
  54 + headCn = append(headCn, val.Name)
  55 + alpha, _ := excelize.ColumnNumberToName(key + 1)
  56 + // alpha := ToAlphaString(key)
  57 + alphaSlice = append(alphaSlice, alpha)
  58 + }
  59 +
  60 + //设置excel文档第一行的字段中文描述
  61 + for index := range headCn {
  62 + //索引转列名,索引从0开始
  63 + cellAlpha := fmt.Sprintf("%s%d", alphaSlice[index], 1) // 单元格行坐标从1开始,如:a1,指第一行a列。
  64 + e.Xlsx.SetCellStr("Sheet1", cellAlpha, headCn[index])
  65 +
  66 + }
  67 + //从excel第二行开始设置实际数据的值
  68 + for key1 := range sourData {
  69 + for i := 0; i < len(headEn); i++ {
  70 + cellAlpha := fmt.Sprintf("%s%d", alphaSlice[i], key1+2) // 单元格行坐标从1开始,如:a1,指第一行a列。
  71 + e.Xlsx.SetCellStr("Sheet1", cellAlpha, sourData[key1][headEn[i]])
  72 + }
  73 + }
  74 + e.SetFileName(GetRandomString(8) + ".xlsx")
  75 + return nil
  76 +}
  77 +
  78 +//GetRandomString 生成随机字符串
  79 +func GetRandomString(lenght int) string {
  80 + str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  81 + bytes := []byte(str)
  82 + result := []byte{}
  83 + r := rand.New(rand.NewSource(time.Now().UnixNano()))
  84 + for i := 0; i < lenght; i++ {
  85 + result = append(result, bytes[r.Intn(len(bytes))])
  86 + }
  87 + return string(result)
  88 +}
  89 +
  90 +func ToAlphaString(value int) string {
  91 + if value < 0 {
  92 + return ""
  93 + }
  94 + var ans string
  95 + i := value + 1
  96 + for i > 0 {
  97 + ans = string((i-1)%26+65) + ans
  98 + i = (i - 1) / 26
  99 + }
  100 + return ans
  101 +}
@@ -8,12 +8,15 @@ import ( @@ -8,12 +8,15 @@ import (
8 "strconv" 8 "strconv"
9 "strings" 9 "strings"
10 10
  11 + "github.com/astaxie/beego/context"
  12 +
11 "github.com/astaxie/beego" 13 "github.com/astaxie/beego"
12 "github.com/astaxie/beego/logs" 14 "github.com/astaxie/beego/logs"
13 15
14 userQuery "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/users/query" 16 userQuery "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/users/query"
15 userService "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/users/service" 17 userService "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/users/service"
16 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib" 18 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib"
  19 + "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib/exceltool"
17 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/port/beego/protocol" 20 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/port/beego/protocol"
18 ) 21 )
19 22
@@ -206,3 +209,17 @@ func (controller *BaseController) GetUserCompany() int64 { @@ -206,3 +209,17 @@ func (controller *BaseController) GetUserCompany() int64 {
206 } 209 }
207 return uid 210 return uid
208 } 211 }
  212 +
  213 +func (controller *BaseController) ResponseExcelByFile(ctx *context.Context, excelMaker *exceltool.ExcelMaker) error {
  214 + fname := excelMaker.GetFileName()
  215 + ctx.Output.Header("Content-Disposition", "attachment; filename="+fname)
  216 + ctx.Output.Header("Content-Description", "File Transfer")
  217 + ctx.Output.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  218 + ctx.Output.Header("Content-Transfer-Encoding", "binary")
  219 + ctx.Output.Header("Expires", "0")
  220 + ctx.Output.Header("Cache-Control", "must-revalidate")
  221 + ctx.Output.Header("Pragma", "public")
  222 + //跳过保存文件,直接写入ctx.ResponseWriter
  223 + excelMaker.Xlsx.Write(ctx.ResponseWriter)
  224 + return nil
  225 +}
1 package controllers 1 package controllers
2 2
3 import ( 3 import (
4 - "errors"  
5 -  
6 - "github.com/astaxie/beego/logs"  
7 - businessCommand "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/businessBonus/command"  
8 - businessQuery "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/businessBonus/query"  
9 - businessService "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/businessBonus/service"  
10 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain" 4 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain"
11 ) 5 )
12 6
@@ -24,95 +18,95 @@ func (c *BusinessBonusController) Prepare() { @@ -24,95 +18,95 @@ func (c *BusinessBonusController) Prepare() {
24 } 18 }
25 } 19 }
26 20
27 -func (c *BusinessBonusController) ListBusinessBonus() {  
28 - type Parameter struct {  
29 - PageNumber int `json:"pageNumber"`  
30 - Partner int64 `json:"partner"`  
31 - PageSize int `json:"pageSize"`  
32 - SearchText string `json:"searchText"`  
33 - }  
34 - var (  
35 - param Parameter  
36 - err error  
37 - )  
38 - if err = c.BindJsonData(&param); err != nil {  
39 - logs.Error(err)  
40 - c.ResponseError(errors.New("json数据解析失败"))  
41 - return  
42 - }  
43 - if param.PageSize == 0 {  
44 - param.PageSize = 20  
45 - }  
46 - if param.PageNumber == 0 {  
47 - param.PageNumber = 1  
48 - }  
49 - companyId := c.GetUserCompany()  
50 - srv := businessService.NewBusinessBonusService(nil)  
51 - cnt, result, err := srv.ListBusinessBonus(businessQuery.ListBusinessBonusQuery{  
52 - CompanyId: companyId,  
53 - Limit: param.PageSize,  
54 - Offset: param.PageSize * (param.PageNumber - 1),  
55 - PartnerId: param.Partner,  
56 - })  
57 - if err != nil {  
58 - c.ResponseError(err)  
59 - return  
60 - }  
61 - c.ResponsePageList(result, cnt, param.PageNumber)  
62 -} 21 +// func (c *BusinessBonusController) ListBusinessBonus() {
  22 +// type Parameter struct {
  23 +// PageNumber int `json:"pageNumber"`
  24 +// Partner int64 `json:"partner"`
  25 +// PageSize int `json:"pageSize"`
  26 +// SearchText string `json:"searchText"`
  27 +// }
  28 +// var (
  29 +// param Parameter
  30 +// err error
  31 +// )
  32 +// if err = c.BindJsonData(&param); err != nil {
  33 +// logs.Error(err)
  34 +// c.ResponseError(errors.New("json数据解析失败"))
  35 +// return
  36 +// }
  37 +// if param.PageSize == 0 {
  38 +// param.PageSize = 20
  39 +// }
  40 +// if param.PageNumber == 0 {
  41 +// param.PageNumber = 1
  42 +// }
  43 +// companyId := c.GetUserCompany()
  44 +// srv := businessService.NewBusinessBonusService(nil)
  45 +// cnt, result, err := srv.ListBusinessBonus(businessQuery.ListBusinessBonusQuery{
  46 +// CompanyId: companyId,
  47 +// Limit: param.PageSize,
  48 +// Offset: param.PageSize * (param.PageNumber - 1),
  49 +// PartnerId: param.Partner,
  50 +// })
  51 +// if err != nil {
  52 +// c.ResponseError(err)
  53 +// return
  54 +// }
  55 +// c.ResponsePageList(result, cnt, param.PageNumber)
  56 +// }
63 57
64 -func (c *BusinessBonusController) UpdateBusinessBonus() {  
65 - type Parameter struct {  
66 - Id int64 `json:"id"`  
67 - DividendsReceivable float64 `json:"dividendsReceivable"`  
68 - StateOfPayment int8 `json:"stateOfPayment"`  
69 - }  
70 - var (  
71 - param Parameter  
72 - err error  
73 - )  
74 - if err = c.BindJsonData(&param); err != nil {  
75 - logs.Error(err)  
76 - c.ResponseError(errors.New("json数据解析失败"))  
77 - return  
78 - }  
79 - companyId := c.GetUserCompany()  
80 - srv := businessService.NewBusinessBonusService(nil)  
81 - err = srv.UpdateBusinessBonus(businessCommand.UpdateBusinessBonusCommand{  
82 - CompanyId: companyId,  
83 - Id: param.Id,  
84 - Bonus: param.DividendsReceivable,  
85 - BonusStatus: param.StateOfPayment,  
86 - })  
87 - if err != nil {  
88 - c.ResponseError(err)  
89 - return  
90 - }  
91 - c.ResponseData(nil)  
92 -} 58 +// func (c *BusinessBonusController) UpdateBusinessBonus() {
  59 +// type Parameter struct {
  60 +// Id int64 `json:"id"`
  61 +// DividendsReceivable float64 `json:"dividendsReceivable"`
  62 +// StateOfPayment int8 `json:"stateOfPayment"`
  63 +// }
  64 +// var (
  65 +// param Parameter
  66 +// err error
  67 +// )
  68 +// if err = c.BindJsonData(&param); err != nil {
  69 +// logs.Error(err)
  70 +// c.ResponseError(errors.New("json数据解析失败"))
  71 +// return
  72 +// }
  73 +// companyId := c.GetUserCompany()
  74 +// srv := businessService.NewBusinessBonusService(nil)
  75 +// err = srv.UpdateBusinessBonus(businessCommand.UpdateBusinessBonusCommand{
  76 +// CompanyId: companyId,
  77 +// Id: param.Id,
  78 +// Bonus: param.DividendsReceivable,
  79 +// BonusStatus: param.StateOfPayment,
  80 +// })
  81 +// if err != nil {
  82 +// c.ResponseError(err)
  83 +// return
  84 +// }
  85 +// c.ResponseData(nil)
  86 +// }
93 87
94 -func (c *BusinessBonusController) GetBusinessBonus() {  
95 - type Parameter struct {  
96 - Id int64 `json:"id"`  
97 - }  
98 - var (  
99 - param Parameter  
100 - err error  
101 - )  
102 - if err = c.BindJsonData(&param); err != nil {  
103 - logs.Error(err)  
104 - c.ResponseError(errors.New("json数据解析失败"))  
105 - return  
106 - }  
107 - companyId := c.GetUserCompany()  
108 - srv := businessService.NewBusinessBonusService(nil)  
109 - data, err := srv.GetBusinessBonus(businessQuery.GetBusinessBonusQuery{  
110 - Id: param.Id,  
111 - CompanyId: companyId,  
112 - })  
113 - if err != nil {  
114 - c.ResponseError(err)  
115 - return  
116 - }  
117 - c.ResponseData(data)  
118 -} 88 +// func (c *BusinessBonusController) GetBusinessBonus() {
  89 +// type Parameter struct {
  90 +// Id int64 `json:"id"`
  91 +// }
  92 +// var (
  93 +// param Parameter
  94 +// err error
  95 +// )
  96 +// if err = c.BindJsonData(&param); err != nil {
  97 +// logs.Error(err)
  98 +// c.ResponseError(errors.New("json数据解析失败"))
  99 +// return
  100 +// }
  101 +// companyId := c.GetUserCompany()
  102 +// srv := businessService.NewBusinessBonusService(nil)
  103 +// data, err := srv.GetBusinessBonus(businessQuery.GetBusinessBonusQuery{
  104 +// Id: param.Id,
  105 +// CompanyId: companyId,
  106 +// })
  107 +// if err != nil {
  108 +// c.ResponseError(err)
  109 +// return
  110 +// }
  111 +// c.ResponseData(data)
  112 +// }
@@ -36,12 +36,20 @@ func (c *CommonController) GetPartnerList() { @@ -36,12 +36,20 @@ func (c *CommonController) GetPartnerList() {
36 } 36 }
37 resp := []map[string]interface{}{} 37 resp := []map[string]interface{}{}
38 for i := range partners { 38 for i := range partners {
  39 + categorys := []map[string]interface{}{}
  40 + for _, vv := range partners[i].PartnerCategoryInfos {
  41 + c := map[string]interface{}{
  42 + "id": vv.Id,
  43 + "name": vv.Name,
  44 + }
  45 + categorys = append(categorys, c)
  46 + }
39 m := map[string]interface{}{ 47 m := map[string]interface{}{
40 "id": partners[i].Partner.Id, 48 "id": partners[i].Partner.Id,
41 "account": partners[i].Partner.Account, 49 "account": partners[i].Partner.Account,
42 "partnerName": partners[i].Partner.PartnerName, 50 "partnerName": partners[i].Partner.PartnerName,
  51 + "categorys": categorys,
43 } 52 }
44 -  
45 resp = append(resp, m) 53 resp = append(resp, m)
46 } 54 }
47 c.ResponseData(resp) 55 c.ResponseData(resp)
@@ -10,6 +10,7 @@ import ( @@ -10,6 +10,7 @@ import (
10 orderQuery "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/orderinfo/query" 10 orderQuery "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/orderinfo/query"
11 orderService "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/orderinfo/service" 11 orderService "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/application/orderinfo/service"
12 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain" 12 "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/domain"
  13 + "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib/exceltool"
13 ) 14 )
14 15
15 //OrderDividendController 订单分红管理 16 //OrderDividendController 订单分红管理
@@ -35,6 +36,7 @@ func (c *OrderDividendController) PageListOrderDividend() { @@ -35,6 +36,7 @@ func (c *OrderDividendController) PageListOrderDividend() {
35 OrderType int `json:"orderType"` 36 OrderType int `json:"orderType"`
36 PageSize int `json:"pageSize"` 37 PageSize int `json:"pageSize"`
37 PageNumber int `json:"pageNumber"` 38 PageNumber int `json:"pageNumber"`
  39 + PartnerCategoryId int `json:"partnerCategoryId"`
38 } 40 }
39 var ( 41 var (
40 param Parameter 42 param Parameter
@@ -65,6 +67,7 @@ func (c *OrderDividendController) PageListOrderDividend() { @@ -65,6 +67,7 @@ func (c *OrderDividendController) PageListOrderDividend() {
65 Limit: param.PageSize, 67 Limit: param.PageSize,
66 Offset: (param.PageNumber - 1) * param.PageSize, 68 Offset: (param.PageNumber - 1) * param.PageSize,
67 CompanyId: companyId, 69 CompanyId: companyId,
  70 + PartnerCategory: param.PartnerCategoryId,
68 }) 71 })
69 if err != nil { 72 if err != nil {
70 c.ResponseError(err) 73 c.ResponseError(err)
@@ -147,6 +150,8 @@ func (c *OrderDividendController) OrderDividendDetail() { @@ -147,6 +150,8 @@ func (c *OrderDividendController) OrderDividendDetail() {
147 "partner": orderinfo.PartnerInfo.PartnerName, 150 "partner": orderinfo.PartnerInfo.PartnerName,
148 "id": orderinfo.Id, 151 "id": orderinfo.Id,
149 "orderId": orderinfo.OrderCode, 152 "orderId": orderinfo.OrderCode,
  153 + "partnerCategoryId": orderinfo.PartnerCategory.Id,
  154 + "partnerCategoryName": orderinfo.PartnerCategory.Name,
150 } 155 }
151 dividendCount := map[string]interface{}{ 156 dividendCount := map[string]interface{}{
152 "orderNum": orderinfo.OrderCompute.PlanOrderCount, 157 "orderNum": orderinfo.OrderCompute.PlanOrderCount,
@@ -399,3 +404,55 @@ func (c *OrderDividendController) EditOrderRemarkBonusForBestshop() { @@ -399,3 +404,55 @@ func (c *OrderDividendController) EditOrderRemarkBonusForBestshop() {
399 c.ResponseData(nil) 404 c.ResponseData(nil)
400 return 405 return
401 } 406 }
  407 +
  408 +func (c *OrderDividendController) ListOrderBonusForExcel() {
  409 + type Parameter struct {
  410 + SearchWord string `json:"searchWord"`
  411 + OrderType int `json:"orderType"`
  412 + PageSize int `json:"pageSize"`
  413 + PageNumber int `json:"pageNumber"`
  414 + PartnerCategoryId int `json:"partnerCategoryId"`
  415 + }
  416 + var (
  417 + param Parameter
  418 + err error
  419 + )
  420 + if err = c.BindJsonData(&param); err != nil {
  421 + logs.Error(err)
  422 + c.ResponseError(errors.New("json数据解析失败"))
  423 + return
  424 + }
  425 + if !(param.OrderType == 0 ||
  426 + param.OrderType == domain.OrderReal ||
  427 + param.OrderType == domain.OrderTypeBestShop) {
  428 + c.ResponseError(errors.New("参数异常"))
  429 + return
  430 + }
  431 +
  432 + companyId := c.GetUserCompany()
  433 + orderSrv := orderService.NewOrderInfoService(nil)
  434 + dataResult, column, err := orderSrv.ListOrderBonusForExcel(
  435 + orderQuery.ListOrderBonusQuery{
  436 + OrderType: param.OrderType,
  437 + PartnerOrCode: param.SearchWord,
  438 + CompanyId: companyId,
  439 + PartnerCategory: param.PartnerCategoryId,
  440 + })
  441 + if err != nil {
  442 + c.ResponseError(err)
  443 + return
  444 + }
  445 + var excelHeaders []exceltool.ExcelHead
  446 + for i := range column {
  447 + h := exceltool.ExcelHead{
  448 + Key: column[i][0],
  449 + Name: column[i][1],
  450 + }
  451 + excelHeaders = append(excelHeaders, h)
  452 + }
  453 + excelMaker := exceltool.NewExcelMaker()
  454 + excelMaker.SetListHead(excelHeaders)
  455 + excelMaker.MakeListExcel(dataResult)
  456 + c.ResponseExcelByFile(c.Ctx, excelMaker)
  457 + return
  458 +}
@@ -33,140 +33,140 @@ func (c *OrderInfoController) Prepare() { @@ -33,140 +33,140 @@ func (c *OrderInfoController) Prepare() {
33 } 33 }
34 34
35 //PageListOrderPurpose 分页获取意向订单列表 35 //PageListOrderPurpose 分页获取意向订单列表
36 -func (c *OrderInfoController) PageListOrderPurpose() {  
37 - type Parameter struct {  
38 - SearchText string `json:"searchText"`  
39 - Partner int64 `json:"partner"`  
40 - PageSize int `json:"pageSize"`  
41 - PageNumber int `json:"pageNumber"`  
42 - }  
43 - var (  
44 - param Parameter  
45 - err error  
46 - )  
47 - if err = c.BindJsonData(&param); err != nil {  
48 - logs.Error(err)  
49 - c.ResponseError(errors.New("json数据解析失败"))  
50 - return  
51 - }  
52 - if param.PageNumber == 0 {  
53 - param.PageNumber = 1  
54 - }  
55 - if param.PageSize == 0 {  
56 - param.PageSize = 20  
57 - }  
58 - companyId := c.GetUserCompany()  
59 - orderSrv := orderService.NewOrderInfoService(nil)  
60 - orderinfos, cnt, err := orderSrv.PageListOrderBase(orderQuery.ListOrderBaseQuery{  
61 - PartnerId: param.Partner,  
62 - OrderCode: param.SearchText,  
63 - OrderType: domain.OrderIntention,  
64 - Limit: param.PageSize,  
65 - Offset: (param.PageNumber - 1) * param.PageSize,  
66 - CompanyId: companyId,  
67 - })  
68 - if err != nil {  
69 - c.ResponseError(err)  
70 - return  
71 - }  
72 - rsp := []map[string]interface{}{}  
73 - for i := range orderinfos {  
74 - orderinfo := orderinfos[i]  
75 - m := map[string]interface{}{  
76 - "createTime": orderinfo.CreateTime.Local().Format("2006-01-02 15:04:05"),  
77 - "updateTime": orderinfo.UpdateTime.Local().Format("2006-01-02 15:04:05"),  
78 - "buyer": orderinfo.Buyer.BuyerName,  
79 - "id": orderinfo.Id,  
80 - "orderId": orderinfo.OrderCode,  
81 - "partner": orderinfo.PartnerInfo.PartnerName,  
82 - "orderNum": orderinfo.OrderCompute.PlanOrderCount,  
83 - "orderPrice": orderinfo.OrderCompute.PlanOrderAmount,  
84 - "orderDist": orderinfo.RegionInfo.RegionName,  
85 - }  
86 - rsp = append(rsp, m)  
87 - }  
88 - c.ResponsePageList(rsp, cnt, param.PageNumber)  
89 -} 36 +// func (c *OrderInfoController) PageListOrderPurpose() {
  37 +// type Parameter struct {
  38 +// SearchText string `json:"searchText"`
  39 +// Partner int64 `json:"partner"`
  40 +// PageSize int `json:"pageSize"`
  41 +// PageNumber int `json:"pageNumber"`
  42 +// }
  43 +// var (
  44 +// param Parameter
  45 +// err error
  46 +// )
  47 +// if err = c.BindJsonData(&param); err != nil {
  48 +// logs.Error(err)
  49 +// c.ResponseError(errors.New("json数据解析失败"))
  50 +// return
  51 +// }
  52 +// if param.PageNumber == 0 {
  53 +// param.PageNumber = 1
  54 +// }
  55 +// if param.PageSize == 0 {
  56 +// param.PageSize = 20
  57 +// }
  58 +// companyId := c.GetUserCompany()
  59 +// orderSrv := orderService.NewOrderInfoService(nil)
  60 +// orderinfos, cnt, err := orderSrv.PageListOrderBase(orderQuery.ListOrderBaseQuery{
  61 +// PartnerId: param.Partner,
  62 +// OrderCode: param.SearchText,
  63 +// OrderType: domain.OrderIntention,
  64 +// Limit: param.PageSize,
  65 +// Offset: (param.PageNumber - 1) * param.PageSize,
  66 +// CompanyId: companyId,
  67 +// })
  68 +// if err != nil {
  69 +// c.ResponseError(err)
  70 +// return
  71 +// }
  72 +// rsp := []map[string]interface{}{}
  73 +// for i := range orderinfos {
  74 +// orderinfo := orderinfos[i]
  75 +// m := map[string]interface{}{
  76 +// "createTime": orderinfo.CreateTime.Local().Format("2006-01-02 15:04:05"),
  77 +// "updateTime": orderinfo.UpdateTime.Local().Format("2006-01-02 15:04:05"),
  78 +// "buyer": orderinfo.Buyer.BuyerName,
  79 +// "id": orderinfo.Id,
  80 +// "orderId": orderinfo.OrderCode,
  81 +// "partner": orderinfo.PartnerInfo.PartnerName,
  82 +// "orderNum": orderinfo.OrderCompute.PlanOrderCount,
  83 +// "orderPrice": orderinfo.OrderCompute.PlanOrderAmount,
  84 +// "orderDist": orderinfo.RegionInfo.RegionName,
  85 +// }
  86 +// rsp = append(rsp, m)
  87 +// }
  88 +// c.ResponsePageList(rsp, cnt, param.PageNumber)
  89 +// }
90 90
91 //GetOrderPurpose 获取意向订单详情 91 //GetOrderPurpose 获取意向订单详情
92 -func (c *OrderInfoController) GetOrderPurpose() {  
93 - type Parameter struct {  
94 - Id string `json:"id"`  
95 - }  
96 - var (  
97 - param Parameter  
98 - err error  
99 - )  
100 - if err = c.BindJsonData(&param); err != nil {  
101 - logs.Error(err)  
102 - c.ResponseError(errors.New("json数据解析失败"))  
103 - return  
104 - }  
105 - orderid, _ := strconv.ParseInt(param.Id, 10, 64)  
106 - companyId := c.GetUserCompany()  
107 - orderSrv := orderService.NewOrderInfoService(nil)  
108 - orderinfo, err := orderSrv.GetOrderDetail(orderQuery.GetOrderQuery{  
109 - OrderId: orderid,  
110 - CompanyId: companyId,  
111 - })  
112 - if err != nil {  
113 - c.ResponseError(err)  
114 - return  
115 - }  
116 - if orderinfo.OrderType != domain.OrderIntention {  
117 - c.ResponseError(errors.New("参数错误"))  
118 - return  
119 - }  
120 - allGoods := []map[string]interface{}{}  
121 - for _, v := range orderinfo.Goods {  
122 - m := map[string]interface{}{  
123 - "id": v.Id,  
124 - "productName": v.GoodName,  
125 - "orderNum": v.PlanGoodNumber,  
126 - "univalence": v.Price,  
127 - "partnerRatio": v.PartnerBonusPercent,  
128 - "orderPrice": v.GoodCompute.PlanAmount,  
129 - }  
130 - allGoods = append(allGoods, m)  
131 - }  
132 - rsp := map[string]interface{}{  
133 - "buyer": orderinfo.Buyer.BuyerName,  
134 - "id": orderinfo.Id,  
135 - "partnerID": orderinfo.PartnerInfo.Id,  
136 - "partner": orderinfo.PartnerInfo.PartnerName,  
137 - "orderDist": orderinfo.RegionInfo.RegionName,  
138 - "orderId": orderinfo.OrderCode,  
139 - "product": allGoods,  
140 - "commissionProportion": orderinfo.SalesmanBonusPercent,  
141 - "orderNumCount": orderinfo.OrderCompute.PlanOrderCount,  
142 - "orderAmountAdjustmentCount": orderinfo.OrderCompute.PlanOrderAmount,  
143 - }  
144 - c.ResponseData(rsp)  
145 -} 92 +// func (c *OrderInfoController) GetOrderPurpose() {
  93 +// type Parameter struct {
  94 +// Id string `json:"id"`
  95 +// }
  96 +// var (
  97 +// param Parameter
  98 +// err error
  99 +// )
  100 +// if err = c.BindJsonData(&param); err != nil {
  101 +// logs.Error(err)
  102 +// c.ResponseError(errors.New("json数据解析失败"))
  103 +// return
  104 +// }
  105 +// orderid, _ := strconv.ParseInt(param.Id, 10, 64)
  106 +// companyId := c.GetUserCompany()
  107 +// orderSrv := orderService.NewOrderInfoService(nil)
  108 +// orderinfo, err := orderSrv.GetOrderDetail(orderQuery.GetOrderQuery{
  109 +// OrderId: orderid,
  110 +// CompanyId: companyId,
  111 +// })
  112 +// if err != nil {
  113 +// c.ResponseError(err)
  114 +// return
  115 +// }
  116 +// if orderinfo.OrderType != domain.OrderIntention {
  117 +// c.ResponseError(errors.New("参数错误"))
  118 +// return
  119 +// }
  120 +// allGoods := []map[string]interface{}{}
  121 +// for _, v := range orderinfo.Goods {
  122 +// m := map[string]interface{}{
  123 +// "id": v.Id,
  124 +// "productName": v.GoodName,
  125 +// "orderNum": v.PlanGoodNumber,
  126 +// "univalence": v.Price,
  127 +// "partnerRatio": v.PartnerBonusPercent,
  128 +// "orderPrice": v.GoodCompute.PlanAmount,
  129 +// }
  130 +// allGoods = append(allGoods, m)
  131 +// }
  132 +// rsp := map[string]interface{}{
  133 +// "buyer": orderinfo.Buyer.BuyerName,
  134 +// "id": orderinfo.Id,
  135 +// "partnerID": orderinfo.PartnerInfo.Id,
  136 +// "partner": orderinfo.PartnerInfo.PartnerName,
  137 +// "orderDist": orderinfo.RegionInfo.RegionName,
  138 +// "orderId": orderinfo.OrderCode,
  139 +// "product": allGoods,
  140 +// "commissionProportion": orderinfo.SalesmanBonusPercent,
  141 +// "orderNumCount": orderinfo.OrderCompute.PlanOrderCount,
  142 +// "orderAmountAdjustmentCount": orderinfo.OrderCompute.PlanOrderAmount,
  143 +// }
  144 +// c.ResponseData(rsp)
  145 +// }
146 146
147 //RemoveOrderPurpose 删除意向订单 147 //RemoveOrderPurpose 删除意向订单
148 -func (c *OrderInfoController) RemoveOrderPurpose() {  
149 - type Parameter struct {  
150 - Id int64 `json:"id"`  
151 - }  
152 - var (  
153 - param Parameter  
154 - err error  
155 - )  
156 - if err = c.BindJsonData(&param); err != nil {  
157 - logs.Error(err)  
158 - c.ResponseError(errors.New("json数据解析失败"))  
159 - return  
160 - }  
161 - companyId := c.GetUserCompany()  
162 - orderSrv := orderService.NewOrderInfoService(nil)  
163 - err = orderSrv.DeleteOrder(param.Id, companyId)  
164 - if err != nil {  
165 - c.ResponseError(err)  
166 - return  
167 - }  
168 - c.ResponseData(nil)  
169 -} 148 +// func (c *OrderInfoController) RemoveOrderPurpose() {
  149 +// type Parameter struct {
  150 +// Id int64 `json:"id"`
  151 +// }
  152 +// var (
  153 +// param Parameter
  154 +// err error
  155 +// )
  156 +// if err = c.BindJsonData(&param); err != nil {
  157 +// logs.Error(err)
  158 +// c.ResponseError(errors.New("json数据解析失败"))
  159 +// return
  160 +// }
  161 +// companyId := c.GetUserCompany()
  162 +// orderSrv := orderService.NewOrderInfoService(nil)
  163 +// err = orderSrv.DeleteOrder(param.Id, companyId)
  164 +// if err != nil {
  165 +// c.ResponseError(err)
  166 +// return
  167 +// }
  168 +// c.ResponseData(nil)
  169 +// }
170 170
171 //postPurposeOrderDetail 请求添加/更新的订单数据 171 //postPurposeOrderDetail 请求添加/更新的订单数据
172 type postPurposeOrderDetail struct { 172 type postPurposeOrderDetail struct {
@@ -252,92 +252,92 @@ func (postData *postOrderGood) Valid() error { @@ -252,92 +252,92 @@ func (postData *postOrderGood) Valid() error {
252 return nil 252 return nil
253 } 253 }
254 254
255 -//UpdateOrderPurpose 更新意向订单  
256 -func (c *OrderInfoController) UpdateOrderPurpose() {  
257 - //用与适配前端定义的数据结构  
258 - var (  
259 - param postPurposeOrderDetail  
260 - err error  
261 - )  
262 - if err = c.BindJsonData(&param); err != nil {  
263 - logs.Error(err)  
264 - c.ResponseError(errors.New("json数据解析失败"))  
265 - return  
266 - }  
267 -  
268 - if err := param.Valid(); err != nil {  
269 - c.ResponseError(err)  
270 - return  
271 - }  
272 - if param.Id == 0 {  
273 - err = c.addOrderPurpose(param)  
274 - } else {  
275 - err = c.editOrderPurpose(param)  
276 - }  
277 - if err != nil {  
278 - c.ResponseError(err)  
279 - }  
280 - c.ResponseData(nil)  
281 - return  
282 -}  
283 -  
284 -func (c *OrderInfoController) addOrderPurpose(param postPurposeOrderDetail) error {  
285 -  
286 - newGoods := []orderCmd.OrderGoodData{}  
287 - for _, v := range param.Product {  
288 - g := orderCmd.OrderGoodData{  
289 - GoodName: v.ProductName,  
290 - PlanGoodNumber: v.OrderNum,  
291 - Price: v.Univalence,  
292 - PartnerBonusPercent: v.PartnerRatio,  
293 - }  
294 - newGoods = append(newGoods, g)  
295 - }  
296 - companyId := c.GetUserCompany()  
297 - createcmd := orderCmd.CreateOrderCommand{  
298 - OrderType: domain.OrderIntention,  
299 - OrderCode: param.OrderId,  
300 - DeliveryCode: "",  
301 - BuyerName: param.BuyerName,  
302 - OrderRegion: param.OrderDist,  
303 - PartnerId: param.PartnerId,  
304 - SalesmanBonusPercent: param.CommissionProportion,  
305 - Goods: newGoods,  
306 - CompanyId: companyId,  
307 - }  
308 - orderSrv := orderService.NewOrderInfoService(nil)  
309 - _, err := orderSrv.CreateNewOrder(createcmd)  
310 - return err  
311 -}  
312 -  
313 -func (c *OrderInfoController) editOrderPurpose(param postPurposeOrderDetail) error {  
314 - orderSrv := orderService.NewOrderInfoService(nil)  
315 - newGoods := []orderCmd.OrderGoodData{}  
316 - for _, v := range param.Product {  
317 - g := orderCmd.OrderGoodData{  
318 - GoodName: v.ProductName,  
319 - PlanGoodNumber: v.OrderNum,  
320 - Price: v.Univalence,  
321 - PartnerBonusPercent: v.PartnerRatio,  
322 - }  
323 - newGoods = append(newGoods, g)  
324 - }  
325 - companyId := c.GetUserCompany()  
326 - updatecmd := orderCmd.UpdateOrderCommand{  
327 - Id: param.Id,  
328 - OrderType: domain.OrderIntention,  
329 - OrderCode: param.OrderId,  
330 - DeliveryCode: "",  
331 - BuyerName: param.BuyerName,  
332 - OrderRegion: param.OrderDist,  
333 - PartnerId: param.PartnerId,  
334 - SalesmanBonusPercent: param.CommissionProportion,  
335 - Goods: newGoods,  
336 - CompanyId: companyId,  
337 - }  
338 - _, err := orderSrv.UpdateOrderData(updatecmd)  
339 - return err  
340 -} 255 +// //UpdateOrderPurpose 更新意向订单
  256 +// func (c *OrderInfoController) UpdateOrderPurpose() {
  257 +// //用与适配前端定义的数据结构
  258 +// var (
  259 +// param postPurposeOrderDetail
  260 +// err error
  261 +// )
  262 +// if err = c.BindJsonData(&param); err != nil {
  263 +// logs.Error(err)
  264 +// c.ResponseError(errors.New("json数据解析失败"))
  265 +// return
  266 +// }
  267 +
  268 +// if err := param.Valid(); err != nil {
  269 +// c.ResponseError(err)
  270 +// return
  271 +// }
  272 +// if param.Id == 0 {
  273 +// err = c.addOrderPurpose(param)
  274 +// } else {
  275 +// err = c.editOrderPurpose(param)
  276 +// }
  277 +// if err != nil {
  278 +// c.ResponseError(err)
  279 +// }
  280 +// c.ResponseData(nil)
  281 +// return
  282 +// }
  283 +
  284 +// func (c *OrderInfoController) addOrderPurpose(param postPurposeOrderDetail) error {
  285 +
  286 +// newGoods := []orderCmd.OrderGoodData{}
  287 +// for _, v := range param.Product {
  288 +// g := orderCmd.OrderGoodData{
  289 +// GoodName: v.ProductName,
  290 +// PlanGoodNumber: v.OrderNum,
  291 +// Price: v.Univalence,
  292 +// PartnerBonusPercent: v.PartnerRatio,
  293 +// }
  294 +// newGoods = append(newGoods, g)
  295 +// }
  296 +// companyId := c.GetUserCompany()
  297 +// createcmd := orderCmd.CreateOrderCommand{
  298 +// OrderType: domain.OrderIntention,
  299 +// OrderCode: param.OrderId,
  300 +// DeliveryCode: "",
  301 +// BuyerName: param.BuyerName,
  302 +// OrderRegion: param.OrderDist,
  303 +// PartnerId: param.PartnerId,
  304 +// SalesmanBonusPercent: param.CommissionProportion,
  305 +// Goods: newGoods,
  306 +// CompanyId: companyId,
  307 +// }
  308 +// orderSrv := orderService.NewOrderInfoService(nil)
  309 +// _, err := orderSrv.CreateNewOrder(createcmd)
  310 +// return err
  311 +// }
  312 +
  313 +// func (c *OrderInfoController) editOrderPurpose(param postPurposeOrderDetail) error {
  314 +// orderSrv := orderService.NewOrderInfoService(nil)
  315 +// newGoods := []orderCmd.OrderGoodData{}
  316 +// for _, v := range param.Product {
  317 +// g := orderCmd.OrderGoodData{
  318 +// GoodName: v.ProductName,
  319 +// PlanGoodNumber: v.OrderNum,
  320 +// Price: v.Univalence,
  321 +// PartnerBonusPercent: v.PartnerRatio,
  322 +// }
  323 +// newGoods = append(newGoods, g)
  324 +// }
  325 +// companyId := c.GetUserCompany()
  326 +// updatecmd := orderCmd.UpdateOrderCommand{
  327 +// Id: param.Id,
  328 +// OrderType: domain.OrderIntention,
  329 +// OrderCode: param.OrderId,
  330 +// DeliveryCode: "",
  331 +// BuyerName: param.BuyerName,
  332 +// OrderRegion: param.OrderDist,
  333 +// PartnerId: param.PartnerId,
  334 +// SalesmanBonusPercent: param.CommissionProportion,
  335 +// Goods: newGoods,
  336 +// CompanyId: companyId,
  337 +// }
  338 +// _, err := orderSrv.UpdateOrderData(updatecmd)
  339 +// return err
  340 +// }
341 341
342 type postOrderPurposeDelivery struct { 342 type postOrderPurposeDelivery struct {
343 ShipmentsId string `json:"shipmentsId"` //发货单号 343 ShipmentsId string `json:"shipmentsId"` //发货单号
@@ -364,57 +364,58 @@ func (postData *postOrderPurposeDelivery) Valid() error { @@ -364,57 +364,58 @@ func (postData *postOrderPurposeDelivery) Valid() error {
364 } 364 }
365 365
366 //OrderPurposeDelivery 发货 意向订单转实发单 366 //OrderPurposeDelivery 发货 意向订单转实发单
367 -func (c *OrderInfoController) OrderPurposeDelivery() {  
368 - //用与适配前端定义的数据结构  
369 -  
370 - var (  
371 - param postOrderPurposeDelivery  
372 - err error  
373 - )  
374 - if err = c.BindJsonData(&param); err != nil {  
375 - logs.Error(err)  
376 - c.ResponseError(errors.New("json数据解析失败"))  
377 - return  
378 - }  
379 - param.ShipmentsId = strings.TrimSpace(param.ShipmentsId)  
380 - orderid, _ := strconv.ParseInt(param.Id, 10, 64)  
381 - if orderid <= 0 {  
382 - c.ResponseError(errors.New("参数错误"))  
383 - return  
384 - }  
385 - if err = param.Valid(); err != nil {  
386 - c.ResponseError(err)  
387 - return  
388 - }  
389 - goods := []orderCmd.OrderGoodData{}  
390 - for _, v := range param.ProductDetail {  
391 - g := orderCmd.OrderGoodData{  
392 - Id: v.Id, GoodName: v.ProductName, PlanGoodNumber: v.OrderNum,  
393 - Price: v.Univalence, PartnerBonusPercent: v.PartnerRatio,  
394 - }  
395 - goods = append(goods, g)  
396 - }  
397 - companyId := c.GetUserCompany()  
398 - deliveryCommand := orderCmd.OrderDeliveryCommand{  
399 - OrderId: orderid, DeliveryCode: param.ShipmentsId,  
400 - DeliveryTime: time.Now(), Goods: goods, CompanyId: companyId,  
401 - }  
402 - orderSrv := orderService.NewOrderInfoService(nil)  
403 - err = orderSrv.Delivery(deliveryCommand)  
404 - if err != nil {  
405 - c.ResponseError(err)  
406 - }  
407 - c.ResponseData(nil)  
408 - return  
409 -} 367 +// func (c *OrderInfoController) OrderPurposeDelivery() {
  368 +// //用与适配前端定义的数据结构
  369 +
  370 +// var (
  371 +// param postOrderPurposeDelivery
  372 +// err error
  373 +// )
  374 +// if err = c.BindJsonData(&param); err != nil {
  375 +// logs.Error(err)
  376 +// c.ResponseError(errors.New("json数据解析失败"))
  377 +// return
  378 +// }
  379 +// param.ShipmentsId = strings.TrimSpace(param.ShipmentsId)
  380 +// orderid, _ := strconv.ParseInt(param.Id, 10, 64)
  381 +// if orderid <= 0 {
  382 +// c.ResponseError(errors.New("参数错误"))
  383 +// return
  384 +// }
  385 +// if err = param.Valid(); err != nil {
  386 +// c.ResponseError(err)
  387 +// return
  388 +// }
  389 +// goods := []orderCmd.OrderGoodData{}
  390 +// for _, v := range param.ProductDetail {
  391 +// g := orderCmd.OrderGoodData{
  392 +// Id: v.Id, GoodName: v.ProductName, PlanGoodNumber: v.OrderNum,
  393 +// Price: v.Univalence, PartnerBonusPercent: v.PartnerRatio,
  394 +// }
  395 +// goods = append(goods, g)
  396 +// }
  397 +// companyId := c.GetUserCompany()
  398 +// deliveryCommand := orderCmd.OrderDeliveryCommand{
  399 +// OrderId: orderid, DeliveryCode: param.ShipmentsId,
  400 +// DeliveryTime: time.Now(), Goods: goods, CompanyId: companyId,
  401 +// }
  402 +// orderSrv := orderService.NewOrderInfoService(nil)
  403 +// err = orderSrv.Delivery(deliveryCommand)
  404 +// if err != nil {
  405 +// c.ResponseError(err)
  406 +// }
  407 +// c.ResponseData(nil)
  408 +// return
  409 +// }
410 410
411 //PageListOrderReal 获取实发订单列表 411 //PageListOrderReal 获取实发订单列表
412 func (c *OrderInfoController) PageListOrderReal() { 412 func (c *OrderInfoController) PageListOrderReal() {
413 type Parameter struct { 413 type Parameter struct {
414 SearchText string `json:"searchText"` 414 SearchText string `json:"searchText"`
415 - Partner int64 `json:"partner"` 415 + PartnerCategory int `json:"PartnerCategory"`
416 PageSize int `json:"pageSize"` 416 PageSize int `json:"pageSize"`
417 PageNumber int `json:"pageNumber"` 417 PageNumber int `json:"pageNumber"`
  418 + UpdateTime []string `json:"updateTime"`
418 } 419 }
419 var ( 420 var (
420 param Parameter 421 param Parameter
@@ -431,47 +432,49 @@ func (c *OrderInfoController) PageListOrderReal() { @@ -431,47 +432,49 @@ func (c *OrderInfoController) PageListOrderReal() {
431 if param.PageSize == 0 { 432 if param.PageSize == 0 {
432 param.PageSize = 20 433 param.PageSize = 20
433 } 434 }
  435 + var (
  436 + updateTimeBegin string
  437 + updateTimeEnd string
  438 + )
  439 + if len(param.UpdateTime) > 0 {
  440 + if len(param.UpdateTime[0]) > 0 {
  441 + t, err := time.ParseInLocation("2006-01-02", param.UpdateTime[0], time.Local)
  442 + if err != nil {
  443 + c.ResponseError(errors.New("UpdateTimeBegin 时间格式错误"))
  444 + return
  445 + }
  446 + updateTimeBegin = t.Format("2006-01-02 15:04:05-07")
  447 + }
  448 + }
  449 + if len(param.UpdateTime) > 1 {
  450 + if len(param.UpdateTime[1]) > 0 {
  451 + t, err := time.ParseInLocation("2006-01-02", param.UpdateTime[1], time.Local)
  452 + if err != nil {
  453 + c.ResponseError(errors.New("UpdateTimeEnd 时间格式错误"))
  454 + return
  455 + }
  456 + //设定时间边界
  457 + t = t.Add(86399 * time.Second)
  458 + updateTimeEnd = t.Format("2006-01-02 15:04:05-07")
  459 + }
  460 + }
434 companyId := c.GetUserCompany() 461 companyId := c.GetUserCompany()
435 orderSrv := orderService.NewOrderInfoService(nil) 462 orderSrv := orderService.NewOrderInfoService(nil)
436 orderinfos, cnt, err := orderSrv.PageListOrderBase(orderQuery.ListOrderBaseQuery{ 463 orderinfos, cnt, err := orderSrv.PageListOrderBase(orderQuery.ListOrderBaseQuery{
437 - PartnerId: param.Partner,  
438 - DeliveryCode: param.SearchText, 464 + PartnerOrCode: param.SearchText,
439 OrderType: domain.OrderReal, 465 OrderType: domain.OrderReal,
440 Limit: param.PageSize, 466 Limit: param.PageSize,
441 Offset: (param.PageNumber - 1) * param.PageSize, 467 Offset: (param.PageNumber - 1) * param.PageSize,
442 CompanyId: companyId, 468 CompanyId: companyId,
  469 + PartnerCategory: param.PartnerCategory,
  470 + UpdateTimeBegin: updateTimeBegin,
  471 + UpdateTimeEnd: updateTimeEnd,
443 }) 472 })
444 if err != nil { 473 if err != nil {
445 c.ResponseError(err) 474 c.ResponseError(err)
446 return 475 return
447 } 476 }
448 - rsp := []map[string]interface{}{}  
449 - for i := range orderinfos {  
450 - orderinfo := orderinfos[i]  
451 - m := map[string]interface{}{  
452 - "createTime": orderinfo.CreateTime.Local().Format("2006-01-02 15:04:05"),  
453 - "updateTime": orderinfo.UpdateTime.Local().Format("2006-01-02 15:04:05"),  
454 - "buyer": orderinfo.Buyer.BuyerName,  
455 - "id": orderinfo.Id,  
456 - "orderId": orderinfo.OrderCode,  
457 - "shipmentsId": orderinfo.DeliveryCode,  
458 - "partner": orderinfo.PartnerInfo.PartnerName,  
459 - "orderNum": orderinfo.OrderCompute.PlanOrderCount,  
460 - "orderPrice": orderinfo.OrderCompute.PlanOrderAmount,  
461 - "orderDist": orderinfo.RegionInfo.RegionName,  
462 - "quantityControl": "",  
463 - "priceControl": "",  
464 - "status": orderinfo.IsDisable,  
465 - }  
466 - if orderinfo.OrderCompute.UseOrderCount >= 0 {  
467 - m["quantityControl"] = fmt.Sprint(orderinfo.OrderCompute.UseOrderCount)  
468 - }  
469 - if orderinfo.OrderCompute.UseOrderAmount >= 0 {  
470 - m["priceControl"] = fmt.Sprint(orderinfo.OrderCompute.UseOrderAmount)  
471 - }  
472 - rsp = append(rsp, m)  
473 - }  
474 - c.ResponsePageList(rsp, cnt, param.PageNumber) 477 + c.ResponsePageList(orderinfos, cnt, param.PageNumber)
475 return 478 return
476 } 479 }
477 480
@@ -544,6 +547,8 @@ func (c *OrderInfoController) GetOrderReal() { @@ -544,6 +547,8 @@ func (c *OrderInfoController) GetOrderReal() {
544 "product": allGoods, 547 "product": allGoods,
545 "create_time": orderinfo.CreateTime.Local().Format("2006-01-02 15:04:06"), 548 "create_time": orderinfo.CreateTime.Local().Format("2006-01-02 15:04:06"),
546 "update_time": orderinfo.UpdateTime.Local().Format("2006-01-02 15:04:06"), 549 "update_time": orderinfo.UpdateTime.Local().Format("2006-01-02 15:04:06"),
  550 + "partnerCategoryId": orderinfo.PartnerCategory.Id,
  551 + "partnerCategoryName": orderinfo.PartnerCategory.Name,
547 } 552 }
548 if orderinfo.OrderCompute.UseOrderAmount >= 0 { 553 if orderinfo.OrderCompute.UseOrderAmount >= 0 {
549 rsp["orderNumCountControl"] = fmt.Sprint(orderinfo.OrderCompute.UseOrderCount) 554 rsp["orderNumCountControl"] = fmt.Sprint(orderinfo.OrderCompute.UseOrderCount)
@@ -558,6 +563,7 @@ func (c *OrderInfoController) GetOrderReal() { @@ -558,6 +563,7 @@ func (c *OrderInfoController) GetOrderReal() {
558 //实际订单 563 //实际订单
559 type postRealOrderDetail struct { 564 type postRealOrderDetail struct {
560 postPurposeOrderDetail 565 postPurposeOrderDetail
  566 + PartnerCategoryId int64 `json:"partnerCategoryId"`
561 ShipmentsId string `json:"shipmentsId"` //发货单号 567 ShipmentsId string `json:"shipmentsId"` //发货单号
562 } 568 }
563 569
@@ -623,6 +629,7 @@ func (c *OrderInfoController) addOrderReal(param postRealOrderDetail) error { @@ -623,6 +629,7 @@ func (c *OrderInfoController) addOrderReal(param postRealOrderDetail) error {
623 SalesmanBonusPercent: param.CommissionProportion, 629 SalesmanBonusPercent: param.CommissionProportion,
624 Goods: newGoods, 630 Goods: newGoods,
625 CompanyId: companyId, 631 CompanyId: companyId,
  632 + PartnerCategory: param.PartnerCategoryId,
626 } 633 }
627 _, err := orderSrv.CreateNewOrder(createcmd) 634 _, err := orderSrv.CreateNewOrder(createcmd)
628 return err 635 return err
@@ -652,6 +659,7 @@ func (c *OrderInfoController) editOrderReal(param postRealOrderDetail) error { @@ -652,6 +659,7 @@ func (c *OrderInfoController) editOrderReal(param postRealOrderDetail) error {
652 SalesmanBonusPercent: param.CommissionProportion, 659 SalesmanBonusPercent: param.CommissionProportion,
653 Goods: newGoods, 660 Goods: newGoods,
654 CompanyId: companyId, 661 CompanyId: companyId,
  662 + PartnerCategory: param.PartnerCategoryId,
655 } 663 }
656 orderSrv := orderService.NewOrderInfoService(nil) 664 orderSrv := orderService.NewOrderInfoService(nil)
657 _, err := orderSrv.UpdateOrderData(updatecmd) 665 _, err := orderSrv.UpdateOrderData(updatecmd)
@@ -275,8 +275,10 @@ func (c *PartnerInfoController) ListPartnerInfo() { @@ -275,8 +275,10 @@ func (c *PartnerInfoController) ListPartnerInfo() {
275 return 275 return
276 } 276 }
277 resp := []map[string]interface{}{} 277 resp := []map[string]interface{}{}
  278 + indexBegin := query.Offset
278 for i := range partners { 279 for i := range partners {
279 m := map[string]interface{}{ 280 m := map[string]interface{}{
  281 + "index": indexBegin + (i + 1),
280 "id": partners[i].Partner.Id, 282 "id": partners[i].Partner.Id,
281 "account": partners[i].Partner.Account, 283 "account": partners[i].Partner.Account,
282 "partnerName": partners[i].Partner.PartnerName, 284 "partnerName": partners[i].Partner.PartnerName,
@@ -33,17 +33,17 @@ func init() { @@ -33,17 +33,17 @@ func init() {
33 beego.NSRouter("/mini-program/modify", &controllers.OrderDividendController{}, "POST:EditOrderDividendForBestshop"), 33 beego.NSRouter("/mini-program/modify", &controllers.OrderDividendController{}, "POST:EditOrderDividendForBestshop"),
34 beego.NSRouter("/mini-program/payDividends", &controllers.OrderDividendController{}, "POST:PayOrderGoodBonusForBestshop"), 34 beego.NSRouter("/mini-program/payDividends", &controllers.OrderDividendController{}, "POST:PayOrderGoodBonusForBestshop"),
35 beego.NSRouter("/mini-program/remarks", &controllers.OrderDividendController{}, "POST:EditOrderRemarkBonusForBestshop"), 35 beego.NSRouter("/mini-program/remarks", &controllers.OrderDividendController{}, "POST:EditOrderRemarkBonusForBestshop"),
36 -  
37 - beego.NSRouter("/business/detail", &controllers.BusinessBonusController{}, "POST:GetBusinessBonus"),  
38 - beego.NSRouter("/business/edit", &controllers.BusinessBonusController{}, "POST:UpdateBusinessBonus"),  
39 - beego.NSRouter("/business/list", &controllers.BusinessBonusController{}, "POST:ListBusinessBonus"), 36 + beego.NSRouter("/list/excel", &controllers.OrderDividendController{}, "POST:ListOrderBonusForExcel"),
  37 + // beego.NSRouter("/business/detail", &controllers.BusinessBonusController{}, "POST:GetBusinessBonus"),
  38 + // beego.NSRouter("/business/edit", &controllers.BusinessBonusController{}, "POST:UpdateBusinessBonus"),
  39 + // beego.NSRouter("/business/list", &controllers.BusinessBonusController{}, "POST:ListBusinessBonus"),
40 ), 40 ),
41 beego.NSNamespace("/order", 41 beego.NSNamespace("/order",
42 - beego.NSRouter("/purpose/list", &controllers.OrderInfoController{}, "POST:PageListOrderPurpose"),  
43 - beego.NSRouter("/purpose/update", &controllers.OrderInfoController{}, "POST:UpdateOrderPurpose"),  
44 - beego.NSRouter("/purpose/detail", &controllers.OrderInfoController{}, "POST:GetOrderPurpose"),  
45 - beego.NSRouter("/purpose/del", &controllers.OrderInfoController{}, "POST:RemoveOrderPurpose"),  
46 - beego.NSRouter("/purpose/sendout", &controllers.OrderInfoController{}, "POST:OrderPurposeDelivery"), 42 + // beego.NSRouter("/purpose/list", &controllers.OrderInfoController{}, "POST:PageListOrderPurpose"),
  43 + // beego.NSRouter("/purpose/update", &controllers.OrderInfoController{}, "POST:UpdateOrderPurpose"),
  44 + // beego.NSRouter("/purpose/detail", &controllers.OrderInfoController{}, "POST:GetOrderPurpose"),
  45 + // beego.NSRouter("/purpose/del", &controllers.OrderInfoController{}, "POST:RemoveOrderPurpose"),
  46 + // beego.NSRouter("/purpose/sendout", &controllers.OrderInfoController{}, "POST:OrderPurposeDelivery"),
47 beego.NSRouter("/actual/list", &controllers.OrderInfoController{}, "POST:PageListOrderReal"), 47 beego.NSRouter("/actual/list", &controllers.OrderInfoController{}, "POST:PageListOrderReal"),
48 beego.NSRouter("/actual/detail", &controllers.OrderInfoController{}, "POST:GetOrderReal"), 48 beego.NSRouter("/actual/detail", &controllers.OrderInfoController{}, "POST:GetOrderReal"),
49 beego.NSRouter("/actual/del", &controllers.OrderInfoController{}, "POST:RemoveOrderReal"), 49 beego.NSRouter("/actual/del", &controllers.OrderInfoController{}, "POST:RemoveOrderReal"),
  1 +~$*.xlsx
  2 +test/Test*.xlsx
  3 +*.out
  4 +*.test
  5 +.idea
  1 +language: go
  2 +
  3 +install:
  4 + - go get -d -t -v ./... && go build -v ./...
  5 +
  6 +go:
  7 + - 1.11.x
  8 + - 1.12.x
  9 + - 1.13.x
  10 + - 1.14.x
  11 + - 1.15.x
  12 +
  13 +os:
  14 + - linux
  15 + - osx
  16 +
  17 +env:
  18 + jobs:
  19 + - GOARCH=amd64
  20 + - GOARCH=386
  21 +
  22 +script:
  23 + - env GO111MODULE=on go vet ./...
  24 + - env GO111MODULE=on go test -v -race ./... -coverprofile=coverage.txt -covermode=atomic
  25 +
  26 +after_success:
  27 + - bash <(curl -s https://codecov.io/bash)
  1 +# Contributor Covenant Code of Conduct
  2 +
  3 +## Our Pledge
  4 +
  5 +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
  6 +
  7 +## Our Standards
  8 +
  9 +Examples of behavior that contributes to creating a positive environment include:
  10 +
  11 +* Using welcoming and inclusive language
  12 +* Being respectful of differing viewpoints and experiences
  13 +* Gracefully accepting constructive criticism
  14 +* Focusing on what is best for the community
  15 +* Showing empathy towards other community members
  16 +
  17 +Examples of unacceptable behavior by participants include:
  18 +
  19 +* The use of sexualized language or imagery and unwelcome sexual attention or advances
  20 +* Trolling, insulting/derogatory comments, and personal or political attacks
  21 +* Public or private harassment
  22 +* Publishing others' private information, such as a physical or electronic address, without explicit permission
  23 +* Other conduct which could reasonably be considered inappropriate in a professional setting
  24 +
  25 +## Our Responsibilities
  26 +
  27 +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
  28 +
  29 +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
  30 +
  31 +## Scope
  32 +
  33 +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
  34 +
  35 +## Enforcement
  36 +
  37 +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [xuri.me](https://xuri.me). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
  38 +
  39 +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
  40 +
  41 +## Attribution
  42 +
  43 +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct][version]
  44 +
  45 +[homepage]: https://www.contributor-covenant.org
  46 +[version]: https://www.contributor-covenant.org/version/2/0/code_of_conduct
  1 +# Contributing to excelize
  2 +
  3 +Want to hack on excelize? Awesome! This page contains information about reporting issues as well as some tips and
  4 +guidelines useful to experienced open source contributors. Finally, make sure
  5 +you read our [community guidelines](#community-guidelines) before you
  6 +start participating.
  7 +
  8 +## Topics
  9 +
  10 +* [Reporting Security Issues](#reporting-security-issues)
  11 +* [Design and Cleanup Proposals](#design-and-cleanup-proposals)
  12 +* [Reporting Issues](#reporting-other-issues)
  13 +* [Quick Contribution Tips and Guidelines](#quick-contribution-tips-and-guidelines)
  14 +* [Community Guidelines](#community-guidelines)
  15 +
  16 +## Reporting security issues
  17 +
  18 +The excelize maintainers take security seriously. If you discover a security
  19 +issue, please bring it to their attention right away!
  20 +
  21 +Please **DO NOT** file a public issue, instead send your report privately to
  22 +[xuri.me](https://xuri.me).
  23 +
  24 +Security reports are greatly appreciated and we will publicly thank you for it.
  25 +We currently do not offer a paid security bounty program, but are not
  26 +ruling it out in the future.
  27 +
  28 +## Reporting other issues
  29 +
  30 +A great way to contribute to the project is to send a detailed report when you
  31 +encounter an issue. We always appreciate a well-written, thorough bug report,
  32 +and will thank you for it!
  33 +
  34 +Check that [our issue database](https://github.com/360EntSecGroup-Skylar/excelize/issues)
  35 +doesn't already include that problem or suggestion before submitting an issue.
  36 +If you find a match, you can use the "subscribe" button to get notified on
  37 +updates. Do *not* leave random "+1" or "I have this too" comments, as they
  38 +only clutter the discussion, and don't help resolving it. However, if you
  39 +have ways to reproduce the issue or have additional information that may help
  40 +resolving the issue, please leave a comment.
  41 +
  42 +When reporting issues, always include the output of `go env`.
  43 +
  44 +Also include the steps required to reproduce the problem if possible and
  45 +applicable. This information will help us review and fix your issue faster.
  46 +When sending lengthy log-files, consider posting them as a gist [https://gist.github.com](https://gist.github.com).
  47 +Don't forget to remove sensitive data from your logfiles before posting (you can
  48 +replace those parts with "REDACTED").
  49 +
  50 +## Quick contribution tips and guidelines
  51 +
  52 +This section gives the experienced contributor some tips and guidelines.
  53 +
  54 +### Pull requests are always welcome
  55 +
  56 +Not sure if that typo is worth a pull request? Found a bug and know how to fix
  57 +it? Do it! We will appreciate it. Any significant improvement should be
  58 +documented as [a GitHub issue](https://github.com/360EntSecGroup-Skylar/excelize/issues) before
  59 +anybody starts working on it.
  60 +
  61 +We are always thrilled to receive pull requests. We do our best to process them
  62 +quickly. If your pull request is not accepted on the first try,
  63 +don't get discouraged!
  64 +
  65 +### Design and cleanup proposals
  66 +
  67 +You can propose new designs for existing excelize features. You can also design
  68 +entirely new features. We really appreciate contributors who want to refactor or
  69 +otherwise cleanup our project.
  70 +
  71 +We try hard to keep excelize lean and focused. Excelize can't do everything for
  72 +everybody. This means that we might decide against incorporating a new feature.
  73 +However, there might be a way to implement that feature *on top of* excelize.
  74 +
  75 +### Conventions
  76 +
  77 +Fork the repository and make changes on your fork in a feature branch:
  78 +
  79 +* If it's a bug fix branch, name it XXXX-something where XXXX is the number of
  80 + the issue.
  81 +* If it's a feature branch, create an enhancement issue to announce
  82 + your intentions, and name it XXXX-something where XXXX is the number of the
  83 + issue.
  84 +
  85 +Submit unit tests for your changes. Go has a great test framework built in; use
  86 +it! Take a look at existing tests for inspiration. Run the full test on your branch before
  87 +submitting a pull request.
  88 +
  89 +Update the documentation when creating or modifying features. Test your
  90 +documentation changes for clarity, concision, and correctness, as well as a
  91 +clean documentation build.
  92 +
  93 +Write clean code. Universally formatted code promotes ease of writing, reading,
  94 +and maintenance. Always run `gofmt -s -w file.go` on each changed file before
  95 +committing your changes. Most editors have plug-ins that do this automatically.
  96 +
  97 +Pull request descriptions should be as clear as possible and include a reference
  98 +to all the issues that they address.
  99 +
  100 +### Successful Changes
  101 +
  102 +Before contributing large or high impact changes, make the effort to coordinate
  103 +with the maintainers of the project before submitting a pull request. This
  104 +prevents you from doing extra work that may or may not be merged.
  105 +
  106 +Large PRs that are just submitted without any prior communication are unlikely
  107 +to be successful.
  108 +
  109 +While pull requests are the methodology for submitting changes to code, changes
  110 +are much more likely to be accepted if they are accompanied by additional
  111 +engineering work. While we don't define this explicitly, most of these goals
  112 +are accomplished through communication of the design goals and subsequent
  113 +solutions. Often times, it helps to first state the problem before presenting
  114 +solutions.
  115 +
  116 +Typically, the best methods of accomplishing this are to submit an issue,
  117 +stating the problem. This issue can include a problem statement and a
  118 +checklist with requirements. If solutions are proposed, alternatives should be
  119 +listed and eliminated. Even if the criteria for elimination of a solution is
  120 +frivolous, say so.
  121 +
  122 +Larger changes typically work best with design documents. These are focused on
  123 +providing context to the design at the time the feature was conceived and can
  124 +inform future documentation contributions.
  125 +
  126 +### Commit Messages
  127 +
  128 +Commit messages must start with a capitalized and short summary
  129 +written in the imperative, followed by an optional, more detailed explanatory
  130 +text which is separated from the summary by an empty line.
  131 +
  132 +Commit messages should follow best practices, including explaining the context
  133 +of the problem and how it was solved, including in caveats or follow up changes
  134 +required. They should tell the story of the change and provide readers
  135 +understanding of what led to it.
  136 +
  137 +In practice, the best approach to maintaining a nice commit message is to
  138 +leverage a `git add -p` and `git commit --amend` to formulate a solid
  139 +changeset. This allows one to piece together a change, as information becomes
  140 +available.
  141 +
  142 +If you squash a series of commits, don't just submit that. Re-write the commit
  143 +message, as if the series of commits was a single stroke of brilliance.
  144 +
  145 +That said, there is no requirement to have a single commit for a PR, as long as
  146 +each commit tells the story. For example, if there is a feature that requires a
  147 +package, it might make sense to have the package in a separate commit then have
  148 +a subsequent commit that uses it.
  149 +
  150 +Remember, you're telling part of the story with the commit message. Don't make
  151 +your chapter weird.
  152 +
  153 +### Review
  154 +
  155 +Code review comments may be added to your pull request. Discuss, then make the
  156 +suggested modifications and push additional commits to your feature branch. Post
  157 +a comment after pushing. New commits show up in the pull request automatically,
  158 +but the reviewers are notified only when you comment.
  159 +
  160 +Pull requests must be cleanly rebased on top of master without multiple branches
  161 +mixed into the PR.
  162 +
  163 +**Git tip**: If your PR no longer merges cleanly, use `rebase master` in your
  164 +feature branch to update your pull request rather than `merge master`.
  165 +
  166 +Before you make a pull request, squash your commits into logical units of work
  167 +using `git rebase -i` and `git push -f`. A logical unit of work is a consistent
  168 +set of patches that should be reviewed together: for example, upgrading the
  169 +version of a vendored dependency and taking advantage of its now available new
  170 +feature constitute two separate units of work. Implementing a new function and
  171 +calling it in another file constitute a single logical unit of work. The very
  172 +high majority of submissions should have a single commit, so if in doubt: squash
  173 +down to one.
  174 +
  175 +After every commit, make sure the test passes. Include documentation
  176 +changes in the same pull request so that a revert would remove all traces of
  177 +the feature or fix.
  178 +
  179 +Include an issue reference like `Closes #XXXX` or `Fixes #XXXX` in commits that
  180 +close an issue. Including references automatically closes the issue on a merge.
  181 +
  182 +Please see the [Coding Style](#coding-style) for further guidelines.
  183 +
  184 +### Merge approval
  185 +
  186 +The excelize maintainers use LGTM (Looks Good To Me) in comments on the code review to
  187 +indicate acceptance.
  188 +
  189 +### Sign your work
  190 +
  191 +The sign-off is a simple line at the end of the explanation for the patch. Your
  192 +signature certifies that you wrote the patch or otherwise have the right to pass
  193 +it on as an open-source patch. The rules are pretty simple: if you can certify
  194 +the below (from [developercertificate.org](http://developercertificate.org/)):
  195 +
  196 +```text
  197 +Developer Certificate of Origin
  198 +Version 1.1
  199 +
  200 +Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
  201 +1 Letterman Drive
  202 +Suite D4700
  203 +San Francisco, CA, 94129
  204 +
  205 +Everyone is permitted to copy and distribute verbatim copies of this
  206 +license document, but changing it is not allowed.
  207 +
  208 +Developer's Certificate of Origin 1.1
  209 +
  210 +By making a contribution to this project, I certify that:
  211 +
  212 +(a) The contribution was created in whole or in part by me and I
  213 + have the right to submit it under the open source license
  214 + indicated in the file; or
  215 +
  216 +(b) The contribution is based upon previous work that, to the best
  217 + of my knowledge, is covered under an appropriate open source
  218 + license and I have the right under that license to submit that
  219 + work with modifications, whether created in whole or in part
  220 + by me, under the same open source license (unless I am
  221 + permitted to submit under a different license), as indicated
  222 + in the file; or
  223 +
  224 +(c) The contribution was provided directly to me by some other
  225 + person who certified (a), (b) or (c) and I have not modified
  226 + it.
  227 +
  228 +(d) I understand and agree that this project and the contribution
  229 + are public and that a record of the contribution (including all
  230 + personal information I submit with it, including my sign-off) is
  231 + maintained indefinitely and may be redistributed consistent with
  232 + this project or the open source license(s) involved.
  233 +```
  234 +
  235 +Then you just add a line to every git commit message:
  236 +
  237 +```text
  238 +Signed-off-by: Ri Xu https://xuri.me
  239 +```
  240 +
  241 +Use your real name (sorry, no pseudonyms or anonymous contributions.)
  242 +
  243 +If you set your `user.name` and `user.email` git configs, you can sign your
  244 +commit automatically with `git commit -s`.
  245 +
  246 +### How can I become a maintainer
  247 +
  248 +First, all maintainers have 3 things
  249 +
  250 +* They share responsibility in the project's success.
  251 +* They have made a long-term, recurring time investment to improve the project.
  252 +* They spend that time doing whatever needs to be done, not necessarily what
  253 + is the most interesting or fun.
  254 +
  255 +Maintainers are often under-appreciated, because their work is harder to appreciate.
  256 +It's easy to appreciate a really cool and technically advanced feature. It's harder
  257 +to appreciate the absence of bugs, the slow but steady improvement in stability,
  258 +or the reliability of a release process. But those things distinguish a good
  259 +project from a great one.
  260 +
  261 +Don't forget: being a maintainer is a time investment. Make sure you
  262 +will have time to make yourself available. You don't have to be a
  263 +maintainer to make a difference on the project!
  264 +
  265 +If you want to become a meintainer, contact [xuri.me](https://xuri.me) and given a introduction of you.
  266 +
  267 +## Community guidelines
  268 +
  269 +We want to keep the community awesome, growing and collaborative. We need
  270 +your help to keep it that way. To help with this we've come up with some general
  271 +guidelines for the community as a whole:
  272 +
  273 +* Be nice: Be courteous, respectful and polite to fellow community members:
  274 + no regional, racial, gender, or other abuse will be tolerated. We like
  275 + nice people way better than mean ones!
  276 +
  277 +* Encourage diversity and participation: Make everyone in our community feel
  278 + welcome, regardless of their background and the extent of their
  279 + contributions, and do everything possible to encourage participation in
  280 + our community.
  281 +
  282 +* Keep it legal: Basically, don't get us in trouble. Share only content that
  283 + you own, do not share private or sensitive information, and don't break
  284 + the law.
  285 +
  286 +* Stay on topic: Make sure that you are posting to the correct channel and
  287 + avoid off-topic discussions. Remember when you update an issue or respond
  288 + to an email you are potentially sending to a large number of people. Please
  289 + consider this before you update. Also remember that nobody likes spam.
  290 +
  291 +* Don't send email to the maintainers: There's no need to send email to the
  292 + maintainers to ask them to investigate an issue or to take a look at a
  293 + pull request. Instead of sending an email, GitHub mentions should be
  294 + used to ping maintainers to review a pull request, a proposal or an
  295 + issue.
  296 +
  297 +### Guideline violations — 3 strikes method
  298 +
  299 +The point of this section is not to find opportunities to punish people, but we
  300 +do need a fair way to deal with people who are making our community suck.
  301 +
  302 +1. First occurrence: We'll give you a friendly, but public reminder that the
  303 + behavior is inappropriate according to our guidelines.
  304 +
  305 +2. Second occurrence: We will send you a private message with a warning that
  306 + any additional violations will result in removal from the community.
  307 +
  308 +3. Third occurrence: Depending on the violation, we may need to delete or ban
  309 + your account.
  310 +
  311 +**Notes:**
  312 +
  313 +* Obvious spammers are banned on first occurrence. If we don't do this, we'll
  314 + have spam all over the place.
  315 +
  316 +* Violations are forgiven after 6 months of good behavior, and we won't hold a
  317 + grudge.
  318 +
  319 +* People who commit minor infractions will get some education, rather than
  320 + hammering them in the 3 strikes process.
  321 +
  322 +* The rules apply equally to everyone in the community, no matter how much
  323 + you've contributed.
  324 +
  325 +* Extreme violations of a threatening, abusive, destructive or illegal nature
  326 + will be addressed immediately and are not subject to 3 strikes or forgiveness.
  327 +
  328 +* Contact [xuri.me](https://xuri.me) to report abuse or appeal violations. In the case of
  329 + appeals, we know that mistakes happen, and we'll work with you to come up with a
  330 + fair solution if there has been a misunderstanding.
  331 +
  332 +## Coding Style
  333 +
  334 +Unless explicitly stated, we follow all coding guidelines from the Go
  335 +community. While some of these standards may seem arbitrary, they somehow seem
  336 +to result in a solid, consistent codebase.
  337 +
  338 +It is possible that the code base does not currently comply with these
  339 +guidelines. We are not looking for a massive PR that fixes this, since that
  340 +goes against the spirit of the guidelines. All new contributions should make a
  341 +best effort to clean up and make the code base better than they left it.
  342 +Obviously, apply your best judgement. Remember, the goal here is to make the
  343 +code base easier for humans to navigate and understand. Always keep that in
  344 +mind when nudging others to comply.
  345 +
  346 +The rules:
  347 +
  348 +1. All code should be formatted with `gofmt -s`.
  349 +2. All code should pass the default levels of
  350 + [`golint`](https://github.com/golang/lint).
  351 +3. All code should follow the guidelines covered in [Effective
  352 + Go](http://golang.org/doc/effective_go.html) and [Go Code Review
  353 + Comments](https://github.com/golang/go/wiki/CodeReviewComments).
  354 +4. Comment the code. Tell us the why, the history and the context.
  355 +5. Document _all_ declarations and methods, even private ones. Declare
  356 + expectations, caveats and anything else that may be important. If a type
  357 + gets exported, having the comments already there will ensure it's ready.
  358 +6. Variable name length should be proportional to its context and no longer.
  359 + `noCommaALongVariableNameLikeThisIsNotMoreClearWhenASimpleCommentWouldDo`.
  360 + In practice, short methods will have short variable names and globals will
  361 + have longer names.
  362 +7. No underscores in package names. If you need a compound name, step back,
  363 + and re-examine why you need a compound name. If you still think you need a
  364 + compound name, lose the underscore.
  365 +8. No utils or helpers packages. If a function is not general enough to
  366 + warrant its own package, it has not been written generally enough to be a
  367 + part of a util package. Just leave it unexported and well-documented.
  368 +9. All tests should run with `go test` and outside tooling should not be
  369 + required. No, we don't need another unit testing framework. Assertion
  370 + packages are acceptable if they provide _real_ incremental value.
  371 +10. Even though we call these "rules" above, they are actually just
  372 + guidelines. Since you've read all the rules, you now know that.
  373 +
  374 +If you are having trouble getting into the mood of idiomatic Go, we recommend
  375 +reading through [Effective Go](https://golang.org/doc/effective_go.html). The
  376 +[Go Blog](https://blog.golang.org) is also a great resource. Drinking the
  377 +kool-aid is a lot easier than going thirsty.
  378 +
  379 +## Code Review Comments and Effective Go Guidelines
  380 +
  381 +[CodeLingo](https://codelingo.io) automatically checks every pull request against the following guidelines from [Effective Go](https://golang.org/doc/effective_go.html) and [Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
  382 +
  383 +### Package Comment
  384 +
  385 +Every package should have a package comment, a block comment preceding the package clause.
  386 +For multi-file packages, the package comment only needs to be present in one file, and any one will do.
  387 +The package comment should introduce the package and provide information relevant to the package as a
  388 +whole. It will appear first on the godoc page and should set up the detailed documentation that follows.
  389 +
  390 +### Single Method Interface Name
  391 +
  392 +By convention, one-method interfaces are named by the method name plus an -er suffix
  393 +or similar modification to construct an agent noun: Reader, Writer, Formatter, CloseNotifier etc.
  394 +
  395 +There are a number of such names and it's productive to honor them and the function names they capture.
  396 +Read, Write, Close, Flush, String and so on have canonical signatures and meanings. To avoid confusion,
  397 +don't give your method one of those names unless it has the same signature and meaning. Conversely,
  398 +if your type implements a method with the same meaning as a method on a well-known type, give it the
  399 +same name and signature; call your string-converter method String not ToString.
  400 +
  401 +### Avoid Annotations in Comments
  402 +
  403 +Comments do not need extra formatting such as banners of stars. The generated output
  404 +may not even be presented in a fixed-width font, so don't depend on spacing for alignment—godoc,
  405 +like gofmt, takes care of that. The comments are uninterpreted plain text, so HTML and other
  406 +annotations such as _this_ will reproduce verbatim and should not be used. One adjustment godoc
  407 +does do is to display indented text in a fixed-width font, suitable for program snippets.
  408 +The package comment for the fmt package uses this to good effect.
  409 +
  410 +### Comment First Word as Subject
  411 +
  412 +Doc comments work best as complete sentences, which allow a wide variety of automated presentations.
  413 +The first sentence should be a one-sentence summary that starts with the name being declared.
  414 +
  415 +### Good Package Name
  416 +
  417 +It's helpful if everyone using the package can use the same name
  418 +to refer to its contents, which implies that the package name should
  419 +be good: short, concise, evocative. By convention, packages are
  420 +given lower case, single-word names; there should be no need for
  421 +underscores or mixedCaps. Err on the side of brevity, since everyone
  422 +using your package will be typing that name. And don't worry about
  423 +collisions a priori. The package name is only the default name for
  424 +imports; it need not be unique across all source code, and in the
  425 +rare case of a collision the importing package can choose a different
  426 +name to use locally. In any case, confusion is rare because the file
  427 +name in the import determines just which package is being used.
  428 +
  429 +### Avoid Renaming Imports
  430 +
  431 +Avoid renaming imports except to avoid a name collision; good package names
  432 +should not require renaming. In the event of collision, prefer to rename the
  433 +most local or project-specific import.
  434 +
  435 +### Context as First Argument
  436 +
  437 +Values of the context.Context type carry security credentials, tracing information,
  438 +deadlines, and cancellation signals across API and process boundaries. Go programs
  439 +pass Contexts explicitly along the entire function call chain from incoming RPCs
  440 +and HTTP requests to outgoing requests.
  441 +
  442 +Most functions that use a Context should accept it as their first parameter.
  443 +
  444 +### Do Not Discard Errors
  445 +
  446 +Do not discard errors using _ variables. If a function returns an error,
  447 +check it to make sure the function succeeded. Handle the error, return it, or,
  448 +in truly exceptional situations, panic.
  449 +
  450 +### Go Error Format
  451 +
  452 +Error strings should not be capitalized (unless beginning with proper nouns
  453 +or acronyms) or end with punctuation, since they are usually printed following
  454 +other context. That is, use fmt.Errorf("something bad") not fmt.Errorf("Something bad"),
  455 +so that log.Printf("Reading %s: %v", filename, err) formats without a spurious
  456 +capital letter mid-message. This does not apply to logging, which is implicitly
  457 +line-oriented and not combined inside other messages.
  458 +
  459 +### Use Crypto Rand
  460 +
  461 +Do not use package math/rand to generate keys, even
  462 +throwaway ones. Unseeded, the generator is completely predictable.
  463 +Seeded with time.Nanoseconds(), there are just a few bits of entropy.
  464 +Instead, use crypto/rand's Reader, and if you need text, print to
  465 +hexadecimal or base64.
  1 +BSD 3-Clause License
  2 +
  3 +Copyright (c) 2016-2020 The excelize Authors.
  4 +All rights reserved.
  5 +
  6 +Redistribution and use in source and binary forms, with or without
  7 +modification, are permitted provided that the following conditions are met:
  8 +
  9 +* Redistributions of source code must retain the above copyright notice, this
  10 + list of conditions and the following disclaimer.
  11 +
  12 +* Redistributions in binary form must reproduce the above copyright notice,
  13 + this list of conditions and the following disclaimer in the documentation
  14 + and/or other materials provided with the distribution.
  15 +
  16 +* Neither the name of the copyright holder nor the names of its
  17 + contributors may be used to endorse or promote products derived from
  18 + this software without specific prior written permission.
  19 +
  20 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  24 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1 +# PR Details
  2 +
  3 +<!--- Provide a general summary of your changes in the Title above -->
  4 +
  5 +## Description
  6 +
  7 +<!--- Describe your changes in detail -->
  8 +
  9 +## Related Issue
  10 +
  11 +<!--- This project only accepts pull requests related to open issues -->
  12 +<!--- If suggesting a new feature or change, please discuss it in an issue first -->
  13 +<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
  14 +<!--- Please link to the issue here: -->
  15 +
  16 +## Motivation and Context
  17 +
  18 +<!--- Why is this change required? What problem does it solve? -->
  19 +
  20 +## How Has This Been Tested
  21 +
  22 +<!--- Please describe in detail how you tested your changes. -->
  23 +<!--- Include details of your testing environment, and the tests you ran to -->
  24 +<!--- see how your change affects other areas of the code, etc. -->
  25 +
  26 +## Types of changes
  27 +
  28 +<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
  29 +
  30 +- [ ] Docs change / refactoring / dependency upgrade
  31 +- [ ] Bug fix (non-breaking change which fixes an issue)
  32 +- [ ] New feature (non-breaking change which adds functionality)
  33 +- [ ] Breaking change (fix or feature that would cause existing functionality to change)
  34 +
  35 +## Checklist
  36 +
  37 +<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
  38 +<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
  39 +
  40 +- [ ] My code follows the code style of this project.
  41 +- [ ] My change requires a change to the documentation.
  42 +- [ ] I have updated the documentation accordingly.
  43 +- [ ] I have read the **CONTRIBUTING** document.
  44 +- [ ] I have added tests to cover my changes.
  45 +- [ ] All new and existing tests passed.
  1 +<p align="center"><img width="650" src="./excelize.svg" alt="Excelize logo"></p>
  2 +
  3 +<p align="center">
  4 + <a href="https://travis-ci.org/360EntSecGroup-Skylar/excelize"><img src="https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master" alt="Build Status"></a>
  5 + <a href="https://codecov.io/gh/360EntSecGroup-Skylar/excelize"><img src="https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
  6 + <a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
  7 + <a href="https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
  8 + <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
  9 + <a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
  10 +</p>
  11 +
  12 +# Excelize
  13 +
  14 +## Introduction
  15 +
  16 +Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLSX / XLSM / XLTM files. Supports reading and writing spreadsheet documents generated by Microsoft Excel&trade; 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.10 or later. The full API docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc) and [docs reference](https://xuri.me/excelize/).
  17 +
  18 +## Basic Usage
  19 +
  20 +### Installation
  21 +
  22 +```bash
  23 +go get github.com/360EntSecGroup-Skylar/excelize
  24 +```
  25 +
  26 +- If your package management with [Go Modules](https://blog.golang.org/using-go-modules), please install with following command.
  27 +
  28 +```bash
  29 +go get github.com/360EntSecGroup-Skylar/excelize/v2
  30 +```
  31 +
  32 +### Create spreadsheet
  33 +
  34 +Here is a minimal example usage that will create spreadsheet file.
  35 +
  36 +```go
  37 +package main
  38 +
  39 +import (
  40 + "fmt"
  41 +
  42 + "github.com/360EntSecGroup-Skylar/excelize"
  43 +)
  44 +
  45 +func main() {
  46 + f := excelize.NewFile()
  47 + // Create a new sheet.
  48 + index := f.NewSheet("Sheet2")
  49 + // Set value of a cell.
  50 + f.SetCellValue("Sheet2", "A2", "Hello world.")
  51 + f.SetCellValue("Sheet1", "B2", 100)
  52 + // Set active sheet of the workbook.
  53 + f.SetActiveSheet(index)
  54 + // Save xlsx file by the given path.
  55 + if err := f.SaveAs("Book1.xlsx"); err != nil {
  56 + fmt.Println(err)
  57 + }
  58 +}
  59 +```
  60 +
  61 +### Reading spreadsheet
  62 +
  63 +The following constitutes the bare to read a spreadsheet document.
  64 +
  65 +```go
  66 +package main
  67 +
  68 +import (
  69 + "fmt"
  70 +
  71 + "github.com/360EntSecGroup-Skylar/excelize"
  72 +)
  73 +
  74 +func main() {
  75 + f, err := excelize.OpenFile("Book1.xlsx")
  76 + if err != nil {
  77 + fmt.Println(err)
  78 + return
  79 + }
  80 + // Get value from cell by given worksheet name and axis.
  81 + cell, err := f.GetCellValue("Sheet1", "B2")
  82 + if err != nil {
  83 + fmt.Println(err)
  84 + return
  85 + }
  86 + fmt.Println(cell)
  87 + // Get all the rows in the Sheet1.
  88 + rows, err := f.GetRows("Sheet1")
  89 + for _, row := range rows {
  90 + for _, colCell := range row {
  91 + fmt.Print(colCell, "\t")
  92 + }
  93 + fmt.Println()
  94 + }
  95 +}
  96 +```
  97 +
  98 +### Add chart to spreadsheet file
  99 +
  100 +With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your worksheet at all.
  101 +
  102 +<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p>
  103 +
  104 +```go
  105 +package main
  106 +
  107 +import (
  108 + "fmt"
  109 +
  110 + "github.com/360EntSecGroup-Skylar/excelize"
  111 +)
  112 +
  113 +func main() {
  114 + categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
  115 + values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
  116 + f := excelize.NewFile()
  117 + for k, v := range categories {
  118 + f.SetCellValue("Sheet1", k, v)
  119 + }
  120 + for k, v := range values {
  121 + f.SetCellValue("Sheet1", k, v)
  122 + }
  123 + if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`); err != nil {
  124 + fmt.Println(err)
  125 + return
  126 + }
  127 + // Save xlsx file by the given path.
  128 + if err := f.SaveAs("Book1.xlsx"); err != nil {
  129 + fmt.Println(err)
  130 + }
  131 +}
  132 +```
  133 +
  134 +### Add picture to spreadsheet file
  135 +
  136 +```go
  137 +package main
  138 +
  139 +import (
  140 + "fmt"
  141 + _ "image/gif"
  142 + _ "image/jpeg"
  143 + _ "image/png"
  144 +
  145 + "github.com/360EntSecGroup-Skylar/excelize"
  146 +)
  147 +
  148 +func main() {
  149 + f, err := excelize.OpenFile("Book1.xlsx")
  150 + if err != nil {
  151 + fmt.Println(err)
  152 + return
  153 + }
  154 + // Insert a picture.
  155 + if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
  156 + fmt.Println(err)
  157 + }
  158 + // Insert a picture to worksheet with scaling.
  159 + if err := f.AddPicture("Sheet1", "D2", "image.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
  160 + fmt.Println(err)
  161 + }
  162 + // Insert a picture offset in the cell with printing support.
  163 + if err := f.AddPicture("Sheet1", "H2", "image.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`); err != nil {
  164 + fmt.Println(err)
  165 + }
  166 + // Save the xlsx file with the origin path.
  167 + if err = f.Save(); err != nil {
  168 + fmt.Println(err)
  169 + }
  170 +}
  171 +```
  172 +
  173 +## Contributing
  174 +
  175 +Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change. XML is compliant with [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](http://www.ecma-international.org/publications/standards/Ecma-376.htm).
  176 +
  177 +## Licenses
  178 +
  179 +This program is under the terms of the BSD 3-Clause License. See [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause).
  180 +
  181 +The Excel logo is a trademark of [Microsoft Corporation](https://aka.ms/trademarks-usage). This artwork is an adaptation.
  182 +
  183 +gopher.{ai,svg,png} was created by [Takuya Ueda](https://twitter.com/tenntenn). Licensed under the [Creative Commons 3.0 Attributions license](http://creativecommons.org/licenses/by/3.0/).
  1 +<p align="center"><img width="650" src="./excelize.svg" alt="Excelize logo"></p>
  2 +
  3 +<p align="center">
  4 + <a href="https://travis-ci.org/360EntSecGroup-Skylar/excelize"><img src="https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master" alt="Build Status"></a>
  5 + <a href="https://codecov.io/gh/360EntSecGroup-Skylar/excelize"><img src="https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
  6 + <a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
  7 + <a href="https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
  8 + <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
  9 + <a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
  10 +</p>
  11 +
  12 +# Excelize
  13 +
  14 +## 简介
  15 +
  16 +Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel&trade; 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.10 或更高版本,完整的 API 使用文档请访问 [go.dev](https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc) 或查看 [参考文档](https://xuri.me/excelize/)
  17 +
  18 +## 快速上手
  19 +
  20 +### 安装
  21 +
  22 +```bash
  23 +go get github.com/360EntSecGroup-Skylar/excelize
  24 +```
  25 +
  26 +- 如果您使用 [Go Modules](https://blog.golang.org/using-go-modules) 管理软件包,请使用下面的命令来安装最新版本。
  27 +
  28 +```bash
  29 +go get github.com/360EntSecGroup-Skylar/excelize/v2
  30 +```
  31 +
  32 +### 创建 Excel 文档
  33 +
  34 +下面是一个创建 Excel 文档的简单例子:
  35 +
  36 +```go
  37 +package main
  38 +
  39 +import (
  40 + "fmt"
  41 +
  42 + "github.com/360EntSecGroup-Skylar/excelize"
  43 +)
  44 +
  45 +func main() {
  46 + f := excelize.NewFile()
  47 + // 创建一个工作表
  48 + index := f.NewSheet("Sheet2")
  49 + // 设置单元格的值
  50 + f.SetCellValue("Sheet2", "A2", "Hello world.")
  51 + f.SetCellValue("Sheet1", "B2", 100)
  52 + // 设置工作簿的默认工作表
  53 + f.SetActiveSheet(index)
  54 + // 根据指定路径保存文件
  55 + if err := f.SaveAs("Book1.xlsx"); err != nil {
  56 + fmt.Println(err)
  57 + }
  58 +}
  59 +```
  60 +
  61 +### 读取 Excel 文档
  62 +
  63 +下面是读取 Excel 文档的例子:
  64 +
  65 +```go
  66 +package main
  67 +
  68 +import (
  69 + "fmt"
  70 +
  71 + "github.com/360EntSecGroup-Skylar/excelize"
  72 +)
  73 +
  74 +func main() {
  75 + f, err := excelize.OpenFile("Book1.xlsx")
  76 + if err != nil {
  77 + fmt.Println(err)
  78 + return
  79 + }
  80 + // 获取工作表中指定单元格的值
  81 + cell, err := f.GetCellValue("Sheet1", "B2")
  82 + if err != nil {
  83 + fmt.Println(err)
  84 + return
  85 + }
  86 + fmt.Println(cell)
  87 + // 获取 Sheet1 上所有单元格
  88 + rows, err := f.GetRows("Sheet1")
  89 + for _, row := range rows {
  90 + for _, colCell := range row {
  91 + fmt.Print(colCell, "\t")
  92 + }
  93 + fmt.Println()
  94 + }
  95 +}
  96 +```
  97 +
  98 +### 在 Excel 文档中创建图表
  99 +
  100 +使用 Excelize 生成图表十分简单,仅需几行代码。您可以根据工作表中的已有数据构建图表,或向工作表中添加数据并创建图表。
  101 +
  102 +<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p>
  103 +
  104 +```go
  105 +package main
  106 +
  107 +import (
  108 + "fmt"
  109 +
  110 + "github.com/360EntSecGroup-Skylar/excelize"
  111 +)
  112 +
  113 +func main() {
  114 + categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
  115 + values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
  116 + f := excelize.NewFile()
  117 + for k, v := range categories {
  118 + f.SetCellValue("Sheet1", k, v)
  119 + }
  120 + for k, v := range values {
  121 + f.SetCellValue("Sheet1", k, v)
  122 + }
  123 + if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`); err != nil {
  124 + fmt.Println(err)
  125 + return
  126 + }
  127 + // 根据指定路径保存文件
  128 + if err := f.SaveAs("Book1.xlsx"); err != nil {
  129 + fmt.Println(err)
  130 + }
  131 +}
  132 +```
  133 +
  134 +### 向 Excel 文档中插入图片
  135 +
  136 +```go
  137 +package main
  138 +
  139 +import (
  140 + "fmt"
  141 + _ "image/gif"
  142 + _ "image/jpeg"
  143 + _ "image/png"
  144 +
  145 + "github.com/360EntSecGroup-Skylar/excelize"
  146 +)
  147 +
  148 +func main() {
  149 + f, err := excelize.OpenFile("Book1.xlsx")
  150 + if err != nil {
  151 + fmt.Println(err)
  152 + return
  153 + }
  154 + // 插入图片
  155 + if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
  156 + fmt.Println(err)
  157 + }
  158 + // 在工作表中插入图片,并设置图片的缩放比例
  159 + if err := f.AddPicture("Sheet1", "D2", "image.jpg", `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
  160 + fmt.Println(err)
  161 + }
  162 + // 在工作表中插入图片,并设置图片的打印属性
  163 + if err := f.AddPicture("Sheet1", "H2", "image.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`); err != nil {
  164 + fmt.Println(err)
  165 + }
  166 + // 保存文件
  167 + if err = f.Save(); err != nil {
  168 + fmt.Println(err)
  169 + }
  170 +}
  171 +```
  172 +
  173 +## 社区合作
  174 +
  175 +欢迎您为此项目贡献代码,提出建议或问题、修复 Bug 以及参与讨论对新功能的想法。 XML 符合标准: [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](http://www.ecma-international.org/publications/standards/Ecma-376.htm)
  176 +
  177 +## 开源许可
  178 +
  179 +本项目遵循 BSD 3-Clause 开源许可协议,访问 [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) 查看许可协议文件。
  180 +
  181 +Excel 徽标是 [Microsoft Corporation](https://aka.ms/trademarks-usage) 的商标,项目的图片是一种改编。
  182 +
  183 +gopher.{ai,svg,png} 由 [Takuya Ueda](https://twitter.com/tenntenn) 创作,遵循 [Creative Commons 3.0 Attributions license](http://creativecommons.org/licenses/by/3.0/) 创作共用授权条款。
  1 +# Security Policy
  2 +
  3 +## Supported Versions
  4 +
  5 +We will dive into any security-related issue as long as your Excelize version is still supported by us. When reporting an issue, include as much information as possible, but no need to fill fancy forms or answer tedious questions. Just tell us what you found, how to reproduce it, and any concerns you have about it. We will respond as soon as possible and follow up with any missing information.
  6 +
  7 +## Reporting a Vulnerability
  8 +
  9 +Please e-mail us directly at `xuri.me@gmail.com` or use the security issue template on GitHub. In general, public disclosure is made after the issue has been fully identified and a patch is ready to be released. A security issue gets the highest priority assigned and a reply regarding the vulnerability is given within a typical 24 hours. Thank you!
  1 +// Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of
  2 +// this source code is governed by a BSD-style license that can be found in
  3 +// the LICENSE file.
  4 +//
  5 +// Package excelize providing a set of functions that allow you to write to
  6 +// and read from XLSX / XLSM / XLTM files. Supports reading and writing
  7 +// spreadsheet documents generated by Microsoft Exce™ 2007 and later. Supports
  8 +// complex components by high compatibility, and provided streaming API for
  9 +// generating or reading data from a worksheet with huge amounts of data. This
  10 +// library needs Go version 1.10 or later.
  11 +
  12 +package excelize
  13 +
  14 +import (
  15 + "errors"
  16 + "strings"
  17 +)
  18 +
  19 +type adjustDirection bool
  20 +
  21 +const (
  22 + columns adjustDirection = false
  23 + rows adjustDirection = true
  24 +)
  25 +
  26 +// adjustHelper provides a function to adjust rows and columns dimensions,
  27 +// hyperlinks, merged cells and auto filter when inserting or deleting rows or
  28 +// columns.
  29 +//
  30 +// sheet: Worksheet name that we're editing
  31 +// column: Index number of the column we're inserting/deleting before
  32 +// row: Index number of the row we're inserting/deleting before
  33 +// offset: Number of rows/column to insert/delete negative values indicate deletion
  34 +//
  35 +// TODO: adjustPageBreaks, adjustComments, adjustDataValidations, adjustProtectedCells
  36 +//
  37 +func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
  38 + xlsx, err := f.workSheetReader(sheet)
  39 + if err != nil {
  40 + return err
  41 + }
  42 + if dir == rows {
  43 + f.adjustRowDimensions(xlsx, num, offset)
  44 + } else {
  45 + f.adjustColDimensions(xlsx, num, offset)
  46 + }
  47 + f.adjustHyperlinks(xlsx, sheet, dir, num, offset)
  48 + if err = f.adjustMergeCells(xlsx, dir, num, offset); err != nil {
  49 + return err
  50 + }
  51 + if err = f.adjustAutoFilter(xlsx, dir, num, offset); err != nil {
  52 + return err
  53 + }
  54 + if err = f.adjustCalcChain(dir, num, offset); err != nil {
  55 + return err
  56 + }
  57 + checkSheet(xlsx)
  58 + _ = checkRow(xlsx)
  59 +
  60 + if xlsx.MergeCells != nil && len(xlsx.MergeCells.Cells) == 0 {
  61 + xlsx.MergeCells = nil
  62 + }
  63 +
  64 + return nil
  65 +}
  66 +
  67 +// adjustColDimensions provides a function to update column dimensions when
  68 +// inserting or deleting rows or columns.
  69 +func (f *File) adjustColDimensions(xlsx *xlsxWorksheet, col, offset int) {
  70 + for rowIdx := range xlsx.SheetData.Row {
  71 + for colIdx, v := range xlsx.SheetData.Row[rowIdx].C {
  72 + cellCol, cellRow, _ := CellNameToCoordinates(v.R)
  73 + if col <= cellCol {
  74 + if newCol := cellCol + offset; newCol > 0 {
  75 + xlsx.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
  76 + }
  77 + }
  78 + }
  79 + }
  80 +}
  81 +
  82 +// adjustRowDimensions provides a function to update row dimensions when
  83 +// inserting or deleting rows or columns.
  84 +func (f *File) adjustRowDimensions(xlsx *xlsxWorksheet, row, offset int) {
  85 + for i := range xlsx.SheetData.Row {
  86 + r := &xlsx.SheetData.Row[i]
  87 + if newRow := r.R + offset; r.R >= row && newRow > 0 {
  88 + f.ajustSingleRowDimensions(r, newRow)
  89 + }
  90 + }
  91 +}
  92 +
  93 +// ajustSingleRowDimensions provides a function to ajust single row dimensions.
  94 +func (f *File) ajustSingleRowDimensions(r *xlsxRow, num int) {
  95 + r.R = num
  96 + for i, col := range r.C {
  97 + colName, _, _ := SplitCellName(col.R)
  98 + r.C[i].R, _ = JoinCellName(colName, num)
  99 + }
  100 +}
  101 +
  102 +// adjustHyperlinks provides a function to update hyperlinks when inserting or
  103 +// deleting rows or columns.
  104 +func (f *File) adjustHyperlinks(xlsx *xlsxWorksheet, sheet string, dir adjustDirection, num, offset int) {
  105 + // short path
  106 + if xlsx.Hyperlinks == nil || len(xlsx.Hyperlinks.Hyperlink) == 0 {
  107 + return
  108 + }
  109 +
  110 + // order is important
  111 + if offset < 0 {
  112 + for i := len(xlsx.Hyperlinks.Hyperlink) - 1; i >= 0; i-- {
  113 + linkData := xlsx.Hyperlinks.Hyperlink[i]
  114 + colNum, rowNum, _ := CellNameToCoordinates(linkData.Ref)
  115 +
  116 + if (dir == rows && num == rowNum) || (dir == columns && num == colNum) {
  117 + f.deleteSheetRelationships(sheet, linkData.RID)
  118 + if len(xlsx.Hyperlinks.Hyperlink) > 1 {
  119 + xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink[:i],
  120 + xlsx.Hyperlinks.Hyperlink[i+1:]...)
  121 + } else {
  122 + xlsx.Hyperlinks = nil
  123 + }
  124 + }
  125 + }
  126 + }
  127 +
  128 + if xlsx.Hyperlinks == nil {
  129 + return
  130 + }
  131 +
  132 + for i := range xlsx.Hyperlinks.Hyperlink {
  133 + link := &xlsx.Hyperlinks.Hyperlink[i] // get reference
  134 + colNum, rowNum, _ := CellNameToCoordinates(link.Ref)
  135 +
  136 + if dir == rows {
  137 + if rowNum >= num {
  138 + link.Ref, _ = CoordinatesToCellName(colNum, rowNum+offset)
  139 + }
  140 + } else {
  141 + if colNum >= num {
  142 + link.Ref, _ = CoordinatesToCellName(colNum+offset, rowNum)
  143 + }
  144 + }
  145 + }
  146 +}
  147 +
  148 +// adjustAutoFilter provides a function to update the auto filter when
  149 +// inserting or deleting rows or columns.
  150 +func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) error {
  151 + if xlsx.AutoFilter == nil {
  152 + return nil
  153 + }
  154 +
  155 + coordinates, err := f.areaRefToCoordinates(xlsx.AutoFilter.Ref)
  156 + if err != nil {
  157 + return err
  158 + }
  159 + x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
  160 +
  161 + if (dir == rows && y1 == num && offset < 0) || (dir == columns && x1 == num && x2 == num) {
  162 + xlsx.AutoFilter = nil
  163 + for rowIdx := range xlsx.SheetData.Row {
  164 + rowData := &xlsx.SheetData.Row[rowIdx]
  165 + if rowData.R > y1 && rowData.R <= y2 {
  166 + rowData.Hidden = false
  167 + }
  168 + }
  169 + return nil
  170 + }
  171 +
  172 + coordinates = f.adjustAutoFilterHelper(dir, coordinates, num, offset)
  173 + x1, y1, x2, y2 = coordinates[0], coordinates[1], coordinates[2], coordinates[3]
  174 +
  175 + if xlsx.AutoFilter.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
  176 + return err
  177 + }
  178 + return nil
  179 +}
  180 +
  181 +// adjustAutoFilterHelper provides a function for adjusting auto filter to
  182 +// compare and calculate cell axis by the given adjust direction, operation
  183 +// axis and offset.
  184 +func (f *File) adjustAutoFilterHelper(dir adjustDirection, coordinates []int, num, offset int) []int {
  185 + if dir == rows {
  186 + if coordinates[1] >= num {
  187 + coordinates[1] += offset
  188 + }
  189 + if coordinates[3] >= num {
  190 + coordinates[3] += offset
  191 + }
  192 + } else {
  193 + if coordinates[2] >= num {
  194 + coordinates[2] += offset
  195 + }
  196 + }
  197 + return coordinates
  198 +}
  199 +
  200 +// areaRefToCoordinates provides a function to convert area reference to a
  201 +// pair of coordinates.
  202 +func (f *File) areaRefToCoordinates(ref string) ([]int, error) {
  203 + rng := strings.Split(ref, ":")
  204 + return areaRangeToCoordinates(rng[0], rng[1])
  205 +}
  206 +
  207 +// areaRangeToCoordinates provides a function to convert cell range to a
  208 +// pair of coordinates.
  209 +func areaRangeToCoordinates(firstCell, lastCell string) ([]int, error) {
  210 + coordinates := make([]int, 4)
  211 + var err error
  212 + coordinates[0], coordinates[1], err = CellNameToCoordinates(firstCell)
  213 + if err != nil {
  214 + return coordinates, err
  215 + }
  216 + coordinates[2], coordinates[3], err = CellNameToCoordinates(lastCell)
  217 + return coordinates, err
  218 +}
  219 +
  220 +// sortCoordinates provides a function to correct the coordinate area, such
  221 +// correct C1:B3 to B1:C3.
  222 +func sortCoordinates(coordinates []int) error {
  223 + if len(coordinates) != 4 {
  224 + return errors.New("coordinates length must be 4")
  225 + }
  226 + if coordinates[2] < coordinates[0] {
  227 + coordinates[2], coordinates[0] = coordinates[0], coordinates[2]
  228 + }
  229 + if coordinates[3] < coordinates[1] {
  230 + coordinates[3], coordinates[1] = coordinates[1], coordinates[3]
  231 + }
  232 + return nil
  233 +}
  234 +
  235 +// coordinatesToAreaRef provides a function to convert a pair of coordinates
  236 +// to area reference.
  237 +func (f *File) coordinatesToAreaRef(coordinates []int) (string, error) {
  238 + if len(coordinates) != 4 {
  239 + return "", errors.New("coordinates length must be 4")
  240 + }
  241 + firstCell, err := CoordinatesToCellName(coordinates[0], coordinates[1])
  242 + if err != nil {
  243 + return "", err
  244 + }
  245 + lastCell, err := CoordinatesToCellName(coordinates[2], coordinates[3])
  246 + if err != nil {
  247 + return "", err
  248 + }
  249 + return firstCell + ":" + lastCell, err
  250 +}
  251 +
  252 +// adjustMergeCells provides a function to update merged cells when inserting
  253 +// or deleting rows or columns.
  254 +func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) error {
  255 + if xlsx.MergeCells == nil {
  256 + return nil
  257 + }
  258 +
  259 + for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
  260 + areaData := xlsx.MergeCells.Cells[i]
  261 + coordinates, err := f.areaRefToCoordinates(areaData.Ref)
  262 + if err != nil {
  263 + return err
  264 + }
  265 + x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
  266 + if dir == rows {
  267 + if y1 == num && y2 == num && offset < 0 {
  268 + f.deleteMergeCell(xlsx, i)
  269 + i--
  270 + }
  271 + y1 = f.adjustMergeCellsHelper(y1, num, offset)
  272 + y2 = f.adjustMergeCellsHelper(y2, num, offset)
  273 + } else {
  274 + if x1 == num && x2 == num && offset < 0 {
  275 + f.deleteMergeCell(xlsx, i)
  276 + i--
  277 + }
  278 + x1 = f.adjustMergeCellsHelper(x1, num, offset)
  279 + x2 = f.adjustMergeCellsHelper(x2, num, offset)
  280 + }
  281 + if x1 == x2 && y1 == y2 {
  282 + f.deleteMergeCell(xlsx, i)
  283 + i--
  284 + }
  285 + if areaData.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
  286 + return err
  287 + }
  288 + }
  289 + return nil
  290 +}
  291 +
  292 +// adjustMergeCellsHelper provides a function for adjusting merge cells to
  293 +// compare and calculate cell axis by the given pivot, operation axis and
  294 +// offset.
  295 +func (f *File) adjustMergeCellsHelper(pivot, num, offset int) int {
  296 + if pivot >= num {
  297 + pivot += offset
  298 + if pivot < 1 {
  299 + return 1
  300 + }
  301 + return pivot
  302 + }
  303 + return pivot
  304 +}
  305 +
  306 +// deleteMergeCell provides a function to delete merged cell by given index.
  307 +func (f *File) deleteMergeCell(sheet *xlsxWorksheet, idx int) {
  308 + if len(sheet.MergeCells.Cells) > idx {
  309 + sheet.MergeCells.Cells = append(sheet.MergeCells.Cells[:idx], sheet.MergeCells.Cells[idx+1:]...)
  310 + sheet.MergeCells.Count = len(sheet.MergeCells.Cells)
  311 + }
  312 +}
  313 +
  314 +// adjustCalcChain provides a function to update the calculation chain when
  315 +// inserting or deleting rows or columns.
  316 +func (f *File) adjustCalcChain(dir adjustDirection, num, offset int) error {
  317 + if f.CalcChain == nil {
  318 + return nil
  319 + }
  320 + for index, c := range f.CalcChain.C {
  321 + colNum, rowNum, err := CellNameToCoordinates(c.R)
  322 + if err != nil {
  323 + return err
  324 + }
  325 + if dir == rows && num <= rowNum {
  326 + if newRow := rowNum + offset; newRow > 0 {
  327 + f.CalcChain.C[index].R, _ = CoordinatesToCellName(colNum, newRow)
  328 + }
  329 + }
  330 + if dir == columns && num <= colNum {
  331 + if newCol := colNum + offset; newCol > 0 {
  332 + f.CalcChain.C[index].R, _ = CoordinatesToCellName(newCol, rowNum)
  333 + }
  334 + }
  335 + }
  336 + return nil
  337 +}