什么是SPU、SKU、ARPU


 

什么是SPU、SKU、ARPU
這是一篇存檔性筆記,我自己存檔一下對這3個詞的理解。如果你已經明了了這3個詞的意思,請直接忽略之
首先,搞清楚商品與單品的區別。例如,iphone是一個單品,但是在淘寶上當很多商家同時出售這個產品的時候,iphone就是一個商品了。
商品:淘寶叫item,京東叫product,商品特指與商家有關的商品,每個商品有一個商家編碼,每個商品下面有多個顏色,款式,可以有多個SKU。

SPU = Standard Product Unit (標准化產品單元)

SPU是商品信息聚合的最小單位,是一組可復用、易檢索的標准化信息的集合,該集合描述了一個產品的特性。通俗點講,屬性值、特性相同的商品就可以稱為一個SPU。
例如,iphone4就是一個SPU,N97也是一個SPU,這個與商家無關,與顏色、款式、套餐也無關。以化妝品為例,下圖是拍拍商城給出的SPU信息:


在商品信息電子化過程中,商品的特性可以由多個“屬性及對應的屬性值對”進行描述。“屬性及對應的屬性值對”完全相同的商品,可以抽象成為一個SPU。同 時,這些“屬性及對應的屬性值對”也在SPU中固化下來,逐步標准化。基於SPU的商品信息結構,可以實現豐富的應用,比如商品信息與資訊、評論、以及其 它SPU的整合。

P.s:從這個意義上講,我認為比較購物的產品庫以SPU為標准來建立是最合適的。
SKU=stock keeping unit(庫存量單位)

SKU即庫存進出計量的單位, 可以是以件、盒、托盤等為單位。在服裝、鞋類商品中使用最多最普遍。 例如紡織品中一個SKU通常表示:規格、顏色、款式。

也有人解釋說SKU就是庫存的最小單位,在服裝行業,正常情況是“單款單色單碼”,國內品牌有把“單款單色”當做一個SKU、也有把“單款”的幾個色當一個SKU、也有把一塊面料的幾個個款式當一個SKU,這些都是誤讀。

同時,引申出另外一個概念:SKC:單款、單色。如果一定要打比方的話:SKC是一個桔子,SKU是一瓣桔子,但不管怎么說,一個桔子是桔子,一瓣桔子也是桔子。

不過,SKU是物理上不可分割的最小存貨單元。在使用時要根據不同業態,不同管 理模式來處理。比如一香煙是50條,一條里有十盒,一盒中有20支,這些單位就要根據不同的需要來設定SKU。比如倉儲批發式大賣場,一定是按照一箱來設 定的。普通大賣場一定是按照條來設定的。煙酒專賣店一定是按照盒來設定的。過去上海等地的街邊小店一定是按一支來設定的。這樣一支就是煙的最小零售單位。 但要根據自己的業態和服務模式來設定。

P.s:關於什么是SKU、SKC,可以參考阿福先生的這篇博客。

【總結一下】:SPU是標准化產品單元,區分品種;SKU是庫存量單位,區分單品;商品特指與商家有關的商品,可對應多個SKU。

ARPU=Average Revenue Per User(每用戶平均收入)

ARPU注重的是一個時間段內運營商從每個用戶所得到的利潤。因此,高端的用戶越多,ARPU越高。在這個時間段里,從運營商的運營情況來看,ARPU值高說明利潤高,這段時間效益好。

http://www.ikent.me/blog/3017

 

首先說一說什么是SKU

SKU=Stock Keeping Unit(庫存量單位),即庫存進出計量的基本單元,可以是以件,盒,托盤等為單位。
SKU這是對於大型連鎖超市DC(配送中心)物流管理的一個必要的方法。現在已經被引申為產品統一編號的簡稱,每種產品均對應有唯一的SKU號。
單品:對一種商品而言,當其品牌、型號、配置、等級、花色、包裝容量、單位、生產日期、保質期、用途、價格、產地等屬性中任一屬性與其他商品存在不同時,可稱為一個單品。
https://baike.baidu.com/item/SKU/5016808?fr=aladdin

類似京東上面,未來人類S5這個台筆記本

 
 

都是S5這個型號,但是因為CPU,顯卡,內存,硬盤等不同,價格也不一樣。CPU,顯卡,內存,硬盤等屬性組合成的一個唯一的商品,就可以用一個SKU來表示,像圖上就有10個SKU。一系列的SKU可以歸到一個SPU下進行管理。


那么一個SKU是怎么生成的呢?下面結合自己的一些經驗,說說一些電商平台的大致產品結構以及SKU的生成方式。

1.阿里速賣通平台,阿里國際站

這兩個平台同一個爸爸,基本差不多。要創建一個商品需要先選一個類目,類目下面掛了一堆的屬性,屬性上又掛了一堆的屬性值。屬性分為銷售屬性和非銷售屬性(銷售屬性就是類似顏色,尺寸這些單個SKU獨有的,非銷售屬性就是多個SKU共有的,比如同一個品牌型號“未來人類S5”)。非銷售屬性有必填和非必填,可以是單選,多選,文本等。銷售屬性就是構成SKU的關鍵。比如說有銷售屬性顏色和尺寸,顏色屬性下有很多屬性值(紅,黃,藍等等),尺寸(1,2,3,4等等)也是。當顏色選了紅,黃,尺寸選了1,2,那么就應該生成2x2=4個SKU,每個SKU有各自的價格,庫存等。保存SKU的時候會與對應的銷售屬性相關聯。
大致的數據模型如下

 
 

當然,實際比這更加復雜(比如產品的圖片,單個SKU的圖片,多個SKU共同的圖片,非銷售屬性可以自定義添加分類不具有的。。。)

2.eBay
跟上面兩個平台類似,創建一個產品也要先選一個分類,分類下面也是有很多屬性,屬性有很多屬性值。。。,不同的地方是eBay沒有區分銷售屬性和非銷售屬性(或者說全部是非銷售屬性),也允許添加自定義屬性和屬性值。eBay上SKU是手動添加的,SKU上的屬性(SKU上的屬性暫且都叫做銷售屬性)也是自定義的。比如說添加了一個SKU A,價格和數量這兩個是必須的,還可以手動加個顏色屬性,然后填上屬性值紅色。當然,若果增加一個SKU B,那么這個SKU也會有顏色這個屬性,屬性值可以自定義。最后校驗這些SKU的屬性值組合起來是否唯一。

 
 

這樣的優勢就是可以隨意控制SKU的數量,如果按照上面兩個平台的規則,這里應該有4x4x1=16個SKU。這樣自由度更高會不會使結構更加復雜呢?當然是NO,用上面的數據模型就可以搞定

 
 

3.Lazada,Linio平台
國際慣例,先選一個類目,類目下面一堆屬性,有必填和非必填,屬性下一堆屬性值。最大的區別就是,一個產品只有一個SKU,屬性不支持自定義。比如說要添加一個商品,有兩種顏色,那么只能創建兩個產品,這兩個產品可能只有圖片不一樣(顏色不一樣,可能沒有顏色這個屬性來選)

 
 

4.Wish平台
比較奇特,沒有分類,產品有固定的屬性,比如標題,描述,運費等。一個產品下可以有多個SKU,SKU的生成取決於固定的兩大類屬性,兩個大類為:顏色和尺寸。比如顏色這個屬性就是歸類於顏色這個類,其他的屬性(品牌,型號,容量等等歸為尺寸這個大類)。尺寸類的屬性值支持自定義,但只能選一個尺寸類屬性(比如選了品牌就不能選容量,選了品牌后可以添加任意值)。兩類屬性不是必須同時存在,比如顏色選了紅,可以不選尺寸類的屬性,反之也一樣。

 
 

忘記說了,一個SKU是靠一串唯一編碼來標識的,比如1234A,1234B。一般來說一個平台下不會存在兩個相同的SKU,或這一個店鋪下不會存在兩個相同的SKU。

大致的邏輯和數據模型就這些,接下來說說開發實現方面。

數據庫大致就依靠上面的數據模型進行設計,編輯的時候,后端按照這些關聯關系取出數據給到前端(我這邊前后端未分離,頁面還是后端渲染,但我還是把數據格式化為JSON再渲染到前端),保存的時候再進行相關的邏輯校驗。因為后端的一些邏輯操作涉及后公司內部的業務,這里就不細說了。說說前端的具體細節,以速賣通的為例,用的是vue,前端拿到的數據如下

 
屬性數據,(變量properties)
 
sku數據(變量skus)

實現后的粗糙界面

 
 
data: { properties: properties, skus: skus } 

遍歷properties,得到材質,顏色,發貨地,套餐這些屬性對象,接着遍歷這些對象里的values屬性,得到屬性值對象,根據屬性對象的selectedValues判斷屬性值是否選上(因為我是后端渲染的js變量,所以初始化的時候selectedValues里的數據直接引用的屬性值對象,如果是非后端渲染的話,要根據skus里的屬性和屬性值去初始化selectedValues的數據,並且存的是屬性值對象的引用)

<tr v-for="(index,item) in properties">
        <td><strong>{{item.Name}}:</strong></td>
        <td>

            <label v-for="value in item.values"><input type="checkbox" :value="value" v-model="item.selectedValues"/>{{value.Name}}</label>

            <table class="list_table" v-if="item.Name!='發貨地'&&item.selectedValues.length>0">
                <tbody>
                <tr>
                    <th>{{item.Name}}</th>
                    <th>自定義名稱</th>
                    <th v-if="item.Name=='顏色'">圖片(無圖片可以不填)</th>
                </tr>

                <tr v-for="selectedValue in item.selectedValues">
                    <td>{{selectedValue.Name}}</td>
                    <td>
                        <input type="text" v-model="selectedValue.DefinitionName" maxlength="20"/>
                    </td>
                    <td v-if="item.Name=='顏色'">
                        <div style="float: left">
                            <input type="file"  style="width: 63px;"/>
                        </div>
                        <div style="float: right">
                            <a href="" rel="link" target="_blank">
                                ![](selectedValue.ImageUrl)
                            </a>
                        </div>
                    </td>
                </tr>

                </tbody>
            </table>
        </td>
    </tr>

 

因為selectedValues通過v-model綁定,當選中或取消一個屬性值的時候后,selectedValues也會隨着改變,selectedValues里的數據是直接引用屬性值而不是拷貝一份數據,所以修改selectedValues中的數據也會直接反映到屬性值上,實現了屬性值的自定義。

那么怎么根據選中的屬性值生成SKU呢?
SKU表格處的表頭是要根據選中的屬性動態更新的,可以這樣做

<tr>
      <th v-for="item in properties" v-if="item.selectedValues.length>0">{{item.Name}}</th>
      <th><span class="c_red">*</span>零售價</th>
      <th><span class="c_red">*</span>庫存</th>
      <th>商品編碼</th>
 </tr>

 

如果屬性里的屬性值都沒有被選中(selectedValues.length==0),就不在表頭顯示這個屬性。

SKU的初始顯示

<tr v-for="sku in skus">
        <td v-for="item in properties" v-if="item.selectedValues.length>0">{{getValueName(sku,item)}}</td>
        <td>US $<input type="text" v-model="sku.SkuPrice" class="w50" maxlength="9"/><span name="productUnitTips"></span></td>
        <td><input type="text" v-model="sku.StockQuantity" class="w50" maxlength="9"/></td>
        <td><input type="text" v-model="sku.SkuCode" class="w180" maxlength="20"/></td>
</tr>

 

也是利用selectedValues.length讓SKU的屬性值列數與表頭列數保持一致。因為SKU對象里的保存的是屬性值Id和屬性Id,需要一個方法去獲取屬性值的值

getValueName: function (sku, property) {
                var valueName = "";
                $.each(sku.values,
                        function () {
                            var _this = this;
                            if (this.propertyId == property.Id) {
                                $.each(property.selectedValues, function () {
                                    if (_this.valueId == this.Id) {
                                        valueName = this.Name;
                                        return false;
                                    }
                                });
                            }
                        });
                return valueName;

            }

 

你沒有看錯,這是JQ。。。

接下來就是SKU表格的更新了,我的做法是變更整塊區域,就是給skus重新賦值。賦的新值從哪來呢?

將選中的屬性值放到一個數組中

               var ori = [];
                $.each(vm.properties,
                        function (index, item) {
                            var selectValues = this.selectedValues;
                            if (selectValues.length > 0) {
                                ori.push(selectValues);
                            }
                        });

 

得到這種結構的數組

[
  [
    {
      'PropertyId': 10,
      'Id': 477,
      'Name': '鋁',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 10,
      'Id': 529,
      'Name': '帆布',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 200000828,
      'Id': 201655809,
      'Name': '殼+貼膜',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655810,
      'Name': '殼+掛繩',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ]
]

 

求笛卡爾積后(后面有求笛卡爾積參考鏈接)

var ret = descartes(ori);
[
  [
    {
      'PropertyId': 10,
      'Id': 477,
      'Name': '鋁',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655809,
      'Name': '殼+貼膜',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 10,
      'Id': 477,
      'Name': '鋁',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655810,
      'Name': '殼+掛繩',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 10,
      'Id': 529,
      'Name': '帆布',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655809,
      'Name': '殼+貼膜',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ],
  [
    {
      'PropertyId': 10,
      'Id': 529,
      'Name': '帆布',
      'DefinitionName': '',
      'ImageUrl': ''
    },
    {
      'PropertyId': 200000828,
      'Id': 201655810,
      'Name': '殼+掛繩',
      'DefinitionName': '',
      'ImageUrl': ''
    }
  ]
]

 

大前端也用上了算法有木有,這里需要弄明白拿到的是什么數據,需要的是什么數據,然后就去想實現就OK了。
想要的數據已經拿到,重新構建skus

         for (var i = 0; i < ret.length; i++) {
                    var sku = {SkuCode: "", SkuPrice: "", StockQuantity: ""};
                    sku.values = [];
                    $.each(ret[i],
                            function () {
                                sku.values.push({propertyId: this.PropertyId, valueId: this.Id});
                            });
                    vmSkus.push(sku);
            }

 

到此,更新SKU表格的代碼已經實現,數據驅動視圖更新,很清晰。但是什么時候去觸發這個更新呢(何時去重新構建skus)? 很簡單嘛,就是勾選或取消勾選屬性值的時候去觸發更新操作。勾選或取消勾選我們能直接從selectedValues.length上得到反饋,然后使用vue 的watch就可以實現了。但是selectedValues是properties數組中元素的一個屬性,vue的watch是無法用在數組元素的某一個字段上的(至少目前我發現是這樣的),那么暴力一點,直接watch整個properties數組並且加上deep:true。這樣是可以實現,但是當修改自定義屬性的時候也會觸發變更(業務會提刀來見的)。

最終解決方案

computed:{
            allCheckedLength:function(){
               var length=0;
                $.each(this.properties,function(){
                    length+=this.selectedValues.length;
                });
               return length;
            }
  }
watch: {
            'allCheckedLength': {
                handler: 'reBuild'
            }
        }

 

reBuild就是重新構建的方法。



作者:若邪Y
鏈接:https://www.jianshu.com/p/1aa9bc5a1158
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM