Automatic merge from release/2.7.0 -> release/2.8.0

* commit '5ac89a79127872e2904eaf7b81b772d1348d654e':
  add skus util function test
  soldout skus fix & add more comment
This commit is contained in:
周有松
2019-03-14 15:49:46 +08:00
4 changed files with 140 additions and 1 deletions
+69
View File
@@ -940,3 +940,72 @@ func (manager *SServerSkuManager) newFromCloudSku(ctx context.Context, userCred
return nil
}
// sku标记为soldout状态。
func (manager *SServerSkuManager) MarkAsSoldout(id string) error {
if len(id) == 0 {
log.Debugf("MarkAsSoldout sku id should not be emtpy")
return nil
}
isku, err := manager.FetchById(id)
if err != nil {
return err
}
sku, ok := isku.(*SServerSku)
if !ok {
return fmt.Errorf("%s is not a sku object", id)
}
_, err = manager.TableSpec().Update(sku, func() error {
sku.PrepaidStatus = SkuStatusSoldout
sku.PostpaidStatus = SkuStatusSoldout
return nil
})
if err != nil {
return err
}
return nil
}
// sku标记为soldout状态。
func (manager *SServerSkuManager) MarkAllAsSoldout(ids []string) error {
var err error
for _, id := range ids {
err = manager.MarkAsSoldout(id)
if err != nil {
return err
}
}
return nil
}
// 获取同一个zone下所有Available状态的sku id
func (manager *SServerSkuManager) FetchAllAvailableSkuIdByZoneId(zoneId string) ([]string, error) {
q := manager.Query()
if len(zoneId) == 0 {
return nil, fmt.Errorf("FetchAllAvailableSkuIdByZoneId zone id should not be emtpy")
}
skus := make([]SServerSku, 0)
q = q.Equals("zone_id", zoneId)
q = q.Filter(sqlchemy.OR(
sqlchemy.Equals(q.Field("prepaid_status"), SkuStatusAvailable),
sqlchemy.Equals(q.Field("postpaid_status"), SkuStatusAvailable)))
err := q.All(&skus)
if err != nil {
return nil, err
}
ids := make([]string, len(skus))
for i := range skus {
ids[i] = skus[i].GetId()
}
return ids, nil
}
+34
View File
@@ -0,0 +1,34 @@
package skus
import (
"reflect"
"testing"
)
func Test_diff(t *testing.T) {
type args struct {
origins []string
compares []string
}
tests := []struct {
name string
args args
want []string
}{
{
name: "Test array diff",
args: args{
origins: []string{"1", "2", "3"},
compares: []string{"2", "3", "5"},
},
want: []string{"1"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := diff(tt.args.origins, tt.args.compares); !reflect.DeepEqual(got, tt.want) {
t.Errorf("diff() = %v, want %v", got, tt.want)
}
})
}
}
+32 -1
View File
@@ -8,6 +8,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -174,6 +175,14 @@ func (self *SkusZone) doUpdate(odata *SServerSku, sku jsonutils.JSONObject) erro
func (self *SkusZone) SyncToLocalDB() error {
log.Debugf("SkusZone %s start sync.", self.ExternalZoneId)
// 更新已经soldout的sku
localIds, err := models.ServerSkuManager.FetchAllAvailableSkuIdByZoneId(self.ZoneId)
if err != nil {
return err
}
// 本次已被更新的sku id
updatedIds := make([]string, 0)
for _, sku := range self.skus {
name, _ := sku.GetString("name")
@@ -199,10 +208,20 @@ func (self *SkusZone) SyncToLocalDB() error {
if err := self.doUpdate(odata, sku); err != nil {
return err
}
updatedIds = append(updatedIds, odata.Id)
}
}
defer log.Debugf("SkusZone %s sync to local db.total %d,created %d,updated %d", self.ExternalZoneId, self.total, self.created, self.updated)
// 处理已经下架的sku: 将本次未更新且处于available状态的sku置为soldout状态
abandonIds := diff(localIds, updatedIds)
log.Debugf("SyncToLocalDB abandon sku %s", abandonIds)
err = models.ServerSkuManager.MarkAllAsSoldout(abandonIds)
if err != nil {
return err
}
defer log.Debugf("SkusZone %s sync to local db.total %d,created %d,updated %d. abandoned %d", self.ExternalZoneId, self.total, self.created, self.updated, len(abandonIds))
return nil
}
@@ -358,3 +377,15 @@ func syncSkusByRegion(region *SCloudregion) error {
return nil
}
// 找出origins中存在,但是compares中不存在的element
func diff(origins, compares []string) []string {
ret := make([]string, 0)
for _, o := range origins {
if !utils.IsInStringArray(o, compares) && len(o) > 0 {
ret = append(ret, o)
}
}
return ret
}
+5
View File
@@ -1,5 +1,10 @@
package modules
/*
添加新manager注意事项:
1. version字段 -- 在endpoint中注册的url如果携带版本。例如http://x.x.x.x/api/v1,那么必须标注对应version字段。否者可能导致yunionapi报资源not found的错误。
*/
func NewResourceManager(serviceType string, keyword, keywordPlural string,
columns, adminColumns []string) ResourceManager {
return ResourceManager{