
# 2 litemall基础系统

目前litemall基础系统主要由litemall数据库、litemall-db模块和litemall-os-api模块组成。

## 2.1 litemall.sql

litemall.sql数据库基于nideshop中的[nideshop.sql](https://github.com/tumobi/nideshop/blob/master/nideshop.sql)数据库，然后在实际开发过程中进行了调整和修改:

* 删除了一些目前不必要的表；
* 删除了表中一些目前不必要的字段；
* 行政区域数据litemall_region没有采用原nideshop中的数据，而是采用了[Administrative-divisions-of-China](https://github.com/modood/Administrative-divisions-of-China)；
* 表中的某些字段采用JSON；
* 表中的日期或时间字段采用DATE、DATETIME；
* 字段的数据类型粗粒度化，例如避免MEDIUMINT，而是INT；
* 表的数据做了清理、调整和补充（假数据）。

具体不同可以比较litemall-db模块下sql文件夹中nideshop.sql和litemall.sql。

以下讨论一些关键性设计

注意：
> 以下设计基于个人理解，很可能存在不合理或者与实际系统不符合的地方。

### 2.1.1 商品和货品设计

这里商品存在商品，商品属性，商品规格，货品四种表

商品表是一种商品的基本信息，主要包括商品介绍，商品图片，商品所属类目，商品品牌商等；

商品参数表其实也是商品的基本信息，但是由于是一对多关系，因此不能直接保存在商品表中（虽然采用JSON也可以但是不合理），
因此采用独立的商品参数表，通常是商品的一些公共基本商品参数；

商品规格表是商品进一步区分货品的标识，例如同样一款衣服，基本信息一致，基本属性一致，但是在尺寸这个属性上可以
把衣服区分成多个货品，而且造成对应的数量和价格不一致。商品规格可以看着是商品属性，但具有特殊特征。

商品规格和规格值存在以下几种关系：

* 单一规格和单一规格值，最常见的，即当前商品存在一种货品；
* 单一规格和多个规格值，较常见，即当前商品基于某个规格存在多种货品，通常价格都是相同的，当然也可能不相同；
* 多个规格和单一规格值，可以简化成第一种情况，或者采用第四种情况，通常实际情况下不常见；
* 多个规格和多个规格值，通常是两种规格或者三种规格较为常见，而且对应的价格不完全相同。

货品则是最终面向用户购买的商品标识，存在多个规格值、数量和价格。

因此这里一个商品表项，存在（至少0个）多个商品属性表项目，存在（至少一个）多个商品规格表项，
存在（至少一个）多个货品表项。

举例如下：

* 一个商品“2018春季衣服商品编号1111111”，
* 存在两个商品参数，
  * 属性名称“面向人群”，属性值“男士”
  * 属性名称“面料”，属性值“100%棉”
* 存在两种规格共八个商品规格项，
  * 规格名称“尺寸”，规则值“S”
  * 规格名称“尺寸”，规则值“M”
  * 规格名称“尺寸”，规则值“L”
  * 规格名称“尺寸”，规则值“XL”
  * 规格名称“尺寸”，规则值“XXL”
  * 规格名称“颜色”，规格值“蓝色”
  * 规格名称“颜色”，规格值“灰色”
  * 规格名称“颜色”，规格值“黑色”
* 存在15个货品（尺寸*颜色=15个货品)
  * 货品“S蓝”，数量 100， 价格 100
  * 货品“M蓝”，数量 100， 价格 100
  * 货品“L蓝”，数量 100， 价格 100
  * 货品“XL蓝”，数量 100， 价格 100
  * 货品“XXL蓝”，数量 100， 价格 100
  * 货品“S灰”，数量 100， 价格 100
  * 货品“M灰”，数量 100， 价格 100
  * 货品“L灰”，数量 100， 价格 100
  * 货品“XL灰”，数量 100， 价格 100
  * 货品“XXL灰”，数量 100， 价格 100
  * 货品“S黑”，数量 100， 价格 100
  * 货品“M黑”，数量 100， 价格 100
  * 货品“L黑”，数量 100， 价格 100
  * 货品“XL黑”，数量 0， 价格 100
  * 货品“XXL黑”，数量 0， 价格 100
  
以下是一些细节的讨论：

* 商品表中可能存在数量和价格属性，而货品中也存在数量和价格属性，目前设计这样：
  * 商品表的价格应该和某个货品的价格一样，通常应该是所有货品价格的最小值，或者基本款式的价格；
  * 商品表中的数量和价格应该仅用于展示，而不能用于最终的订单价格计算；
  * 商品表的数量应该设置成所有货品数量的总和；
  * 在管理后台添加商品时，如果管理员不填写商品表的数量和价格属性，则自动填写合适的值；如果填写，则使用显示。
  * 当小商城中，用户查看商品详情时，初始显示商品表的价格，而如果用户选择具体规格后，则商品
    详情里面的价格需要自动切换到该规格的价格。
* 商品规格可以存在规格图片，效果是规格名称前放置规格图片
* 货品也可以存在货品图片，效果是所有规格选定以后对应的货品有货，则在货品价格前放置货品图片
* 如果商品是两种规格，分别是M个和N个规格值，那么通常应该是`M*N`个货品，但是有些货品可能天然不存在。
  那么，此时数据库如何来设计，是允许少于`M*N`个项，还是必须等于`M*N`个，而不存在货品的数量设置为0？
  * 

注意：

> 这里的设计可能与实际项目设计不一致，但是目前是可行的。
> 商品的中文用语“商品”和英语用语“goods”，货品的中文用语“货品”和英语用语“product”可能是不正确的。

### 2.1.2 用户和微信用户设计

目前准备支持用户普通账号登录和微信登录两种方式，两种登录方式仅仅采用一个litemall-user表可能不是很合适。此外，如果进一步支持其他多种第三方登录，那么这里需要重新设计。

### 2.1.3 行政区域设计
 
原nideship.sql中存在region数据，但是litemall.sql的region数据则来自
[Administrative-divisions-of-China](https://github.com/modood/Administrative-divisions-of-China)项目。从该项目中导入数据到litemall.sql的litemall-province、litemall-city、litemall-area和litemall-street四个表，然后重新生成一个新的litemall-region表。

### 2.1.4 订单设计

订单信息主要由基本信息、商品信息、地址信息、费用信息、快递信息、支付信息和其他信息组成。

* 基本信息
订单创建时的一些基本信息。

* 商品信息
由于订单可以存在多个商品，因此订单的商品信息是由独立的订单商品表记录（可能更应该称为货品）。

* 费用信息

* 快递信息
目前快递信息仅仅记录快递公司、快递单号、快递发出时间、快递接收时间。而如果快递过程中如果存在一些异常，例如物品丢失，则目前系统难以处理。关于快递费的计算，目前采取简单方式，即满88元则免费，否则10元。

* 支付信息


* 其他信息

#### 2.1.4.1 订单状态

![](pic2/2-1.png)

订单分成几种基本的状态：

* 下单
状态码101，此时订单生成，记录订单编号、收货地址信息、订单商品信息和订单相关费用信息；
* 付款
状态码201，此时用户微信支付付款，系统记录微信支付订单号、支付时间、支付状态；
* 发货
状态码301，此时商场已经发货，系统记录快递公司、快递单号、快递发送时间。
当快递公司反馈用户签收后，系统记录快递到达时间。
* 收货
状态码401，当用户收到货以后点击确认收货，系统记录确认时间。
此时，用户可以评价订单商品。

除了这几种正常状态以外，还存在一些非普通的状态：

* 订单取消
状态码102，用户在生产订单以后未付款之前，点击取消按钮，系统记录结束时间
* 订单取消并退款
状态码202，用户付款以后未发货前，点击取消按钮，系统记录结束时间和退款信息
* 系统自动确认收货
状态码402，快递反馈商场用户已签收，但是用户却不点击确认收货按钮，
此时系统在快递到达时间的一段时间后，自动确认收货。
用户不能再点击确认收货按钮，但是可以评价订单商品

当然，以上的基本状态和非普通状态，和实际项目相比仍然相对简单。

此外，当订单状态码是102、202、401、402时，订单可以设置删除状态，此时
用户查看自己订单信息时将看不到这些“已删除”的订单。


#### 2.1.4.2 状态码所支持的操作

不同的状态码下面，用户能够进行的操作是：

* 101
此时，用户可以“订单支付”、“订单取消”
* 102
此时，用户可以“订单删除”
* 201
此时，用户可以“订单取消”（并退款）
* 202
此时，用户可以“订单删除”
* 301
此时，用户可以“确认收货”
* 401
此时，用户可以“订单删除”、“评价”、“再次购买”
* 402
此时，用户可以“订单删除”、“评价”、“再次购买”

#### 2.1.4.3 售后处理

目前不支持售后或退货相关业务。

#### 2.1.4.4 黑名单

从一些资料看，如果用户订单多次取消，应该加入黑名单。
目前不支持。

## 2.2 litemall-db

技术：
* Spring Boot 1.5.10
* MySQL
* Druid
* Mybatis
* PageHelper
* Mybatis Generator
* Mybatis Generator非官方插件mybatis-generator-plugin
  
因为litemall-db是一个业务模块，并不对外直接服务，因此无需使用Spring MVC。

![](./pic2/2-2.png)

这里litemall-db模块可以分成以下几种代码：

* mybatis generator自动化代码
* 业务代码
* 安全代码
* JSON支持代码
* 配置代码

### 2.2.1 自动化代码

通过mybatis generator插件可以自动生成三种代码:

* src文件夹`domain` Java代码
* src文件夹`dao` Java代码
* resources文件夹`dao` Mapper代码

这里的代码封装了对数据库的操作，因此用户不需要直接操作sql代码，而是直接操作Java代码即可完成对数据库的访问处理。

当然，为了达到数据库访问效率，用户也可以自定义mapper文件和对应的Java代码，但是至少目前这里不采用。例如，当需要访问两个表的数据时，这里是在业务层通过Java代码遍历的形式来访问两个表。

### 2.2.2 业务代码

基于2.2.1的代码，业务代码处理一些具体业务相关的操作，对其他模块提供具体的服务。

### 2.2.3 安全代码

### 2.2.4 JSON支持代码

### 2.2.5 配置代码

采用Java注解的方式来完成一些特定的配置操作。

## 2.3 litemall-os-api

对象存储服务目前的目标是支持图片的上传下载。

作为后台模块之一，litemall-os-api并没有对应的前端模块，而只是在litemall-admin模块
的对象存储页面中允许管理员修改。

### 2.3.1 业务

支持服务：

* 列表
* 创建
* 修改
* 读取
* 删除
* 下载，即下载对象数据文件
* 访问，即直接访问对象数据

### 2.3.2 安全

警告
> 目前这里没有任何安全机制，这意味着任何人如果知道对象存储服务的地址，都可以直接存储访问对象数据。

这样简化的目的是对象存储服务建议最终采用云服务，因此这里仅仅实现一个简单的服务面向测试开发。

如果用户需要局域网部署，那么这里需要加入一定的安全机制。
