本节我们进行用户模块中最后一个功能用例--用户地址信息维护的开发,用户信息维护这个用例展开后其实还有下面这些子个用例--每个子用例对应一个具体的功能接口。
本文大纲
我们项目中这五个功能都已经实现,但是在文章里全展开说一遍篇幅就太长了,所以我们在教程中主要抓重点。
文章里我把新增、查看收货地址列表和更新收货地址这三个功能的实现过程详细讲一下,剩余的两个功能:查看单个地址信息和删除地址信息比较简单,代码中也有详细的注释,大家可以直接看项目的代码,另外我会把这两个功能的cURL放上来,方便大家在本地测试。
此外我还会把项目中常用的MySQL事务的形式和怎么用好GORM的事务功能做了讲解,避免让大家在开发项目时写冤枉代码。
新增收货地址
收货地址的设置相信大家平时使用淘宝、京东、拼多多的时候都设置过。它的整体流程不复杂,唯一有一点需要注意的是如果新加的收货地址要设置成默认地址,像这张图这样。
图片
此时要确认之前有无默认地址,有则把原来的默认地址设置为非默认。
功能实现
因为我们还没有为用户收货信息创建Model 类型,所以我们先创建 Model 在 dal/model 目录新建 user_address.go 在其中创建 Model 。
// UserAddress 用户收货信息表
type UserAddress struct {
ID int64 `gorm:"column:id;primary_key;AUTO_INCREMENT"` // 收货信息ID
UserId int64 `gorm:"column:user_id;NOT NULL"` // 用户ID
UserName string `gorm:"column:user_name;NOT NULL"` // 收货人姓名
UserPhone string `gorm:"column:user_phone;NOT NULL"` // 收货人手机号
Default int `gorm:"column:default;default:0;NOT NULL"` // 是否为默认收货信息 0-非默认 1-是默认
ProvinceName string `gorm:"column:province_name;NOT NULL"` // 省
CityName string `gorm:"column:city_name;NOT NULL"` // 城
RegionName string `gorm:"column:region_name;NOT NULL"` // 区/县
DetailAddress string `gorm:"column:detail_address;NOT NULL"` // 收件详细地址(街道/楼宇/单元)
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"` // 删除状态 0-未删除 1-已删除
CreatedAt time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP;NOT NULL"`// 添加时间
UpdatedAt time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;NOT NULL"`// 修改时间
}
func (m *UserAddress) TableName() string {
return"user_address"
}
接下来我们先定义好请求数据对象和领域数据对象,明确后面服务方法该怎么操作数据。
在api/request/user.go 中定义请求对象。
type UserAddress struct {
UserName string `json:"user_name" binding:"required"`
UserPhone string `json:"user_phone" binding:"required"`
Default int `json:"default" binding:"notallow=0 1"`
ProvinceName string `json:"province_name" binding:"required"`
CityName string `json:"city_name" binding:"required"`
RegionName string `json:"region_name" binding:"required"`
DetailAddress string `json:"detail_address" binding:"required"`
}
开发功能时Controller 会把客户端的请求数据绑定到请求对象上,同时会根据这里指定的验证规则进行字段值的验证。
在 logic/do/user.go 中定义领域对象。
type UserAddressInfo struct {
ID int64
UserId int64
UserName string
UserPhone string
Default int
ProvinceName string
CityName string
RegionName string
DetailAddress string
IsDel int
CreatedAt time.Time
UpdatedAt time.Time
}
同理应用服务会把请求数据对象转换成领域对象给到领域服务,让它完成添加用户收货地址的核心逻辑。
新增用户收货地址功能有两个主要的逻辑分支:
- 新增非默认收货地址
- 新增默认收货地址,因为收货地址有且只有一个默认地址,所有当新加的收货地址是默认地址时,要确认之前有无默认地址,有则把原来的默认地址设置为非默认的。
我们把这部分逻辑封装在创建收货地址的Dao方法中,主要是因为涉及更新多条记录时要用到事务提交,我们在这里封装好了,领域服务中的逻辑会更简单,不用关心事务管理这些数据库层面的事情。