forked from free-lancers/electricity_bill_calc_service
		
	feat(topup):基本完成商户充值记录的数据库操作部分。
This commit is contained in:
		
							
								
								
									
										22
									
								
								model/top_up.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								model/top_up.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | package model | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"electricity_bill_calc/types" | ||||||
|  |  | ||||||
|  | 	"github.com/shopspring/decimal" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type TopUp struct { | ||||||
|  | 	TopUpCode              string          `json:"topUpCode" db:"top_up_code"` | ||||||
|  | 	Park                   string          `json:"parkId" db:"park_id"` | ||||||
|  | 	Tenement               string          `json:"tenementId" db:"tenement_id"` | ||||||
|  | 	TenementName           string          `json:"tenementName" db:"tenement_name"` | ||||||
|  | 	Meter                  string          `json:"meterId" db:"meter_id"` | ||||||
|  | 	MeterAddress           *string         `json:"meterAddress" db:"meter_address"` | ||||||
|  | 	ToppedUpAt             types.DateTime  `json:"toppedUpAt" db:"topped_up_at"` | ||||||
|  | 	Amount                 decimal.Decimal `json:"amount" db:"amount"` | ||||||
|  | 	PaymentType            int16           `json:"paymentType" db:"payment_type"` | ||||||
|  | 	SuccessfulSynchronized bool            `json:"successfulSynchronized" db:"successful_synchronized"` | ||||||
|  | 	SynchronizedAt         *types.DateTime `json:"synchronizedAt" db:"synchronized_at"` | ||||||
|  | 	CancelledAt            *types.DateTime `json:"cancelledAt" db:"cancelled_at"` | ||||||
|  | } | ||||||
							
								
								
									
										186
									
								
								repository/top_up.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								repository/top_up.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | |||||||
|  | package repository | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"electricity_bill_calc/cache" | ||||||
|  | 	"electricity_bill_calc/config" | ||||||
|  | 	"electricity_bill_calc/global" | ||||||
|  | 	"electricity_bill_calc/logger" | ||||||
|  | 	"electricity_bill_calc/model" | ||||||
|  | 	"electricity_bill_calc/tools/serial" | ||||||
|  | 	"electricity_bill_calc/types" | ||||||
|  | 	"electricity_bill_calc/vo" | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	"github.com/doug-martin/goqu/v9" | ||||||
|  | 	_ "github.com/doug-martin/goqu/v9/dialect/postgres" | ||||||
|  | 	"github.com/georgysavva/scany/v2/pgxscan" | ||||||
|  | 	"go.uber.org/zap" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type _TopUpRepository struct { | ||||||
|  | 	log *zap.Logger | ||||||
|  | 	ds  goqu.DialectWrapper | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var TopUpRepository = _TopUpRepository{ | ||||||
|  | 	log: logger.Named("Repository", "TopUp"), | ||||||
|  | 	ds:  goqu.Dialect("postgres"), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 检索符合条件的商户充值记录 | ||||||
|  | func (tur _TopUpRepository) ListTopUps(pid string, startDate, endDate *types.Date, keyword *string, page uint) ([]*model.TopUp, int64, error) { | ||||||
|  | 	tur.log.Info("查询符合条件的商户充值记录", zap.String("Park", pid), logger.DateFieldp("StartDate", startDate), logger.DateFieldp("EndDate", endDate), zap.Stringp("keyword", keyword), zap.Uint("page", page)) | ||||||
|  | 	cacheConditions := []string{ | ||||||
|  | 		pid, | ||||||
|  | 		cache.NullableStringKey(keyword), | ||||||
|  | 		cache.NullableConditionKey(startDate), | ||||||
|  | 		cache.NullableConditionKey(endDate), | ||||||
|  | 		fmt.Sprintf("%d", page), | ||||||
|  | 	} | ||||||
|  | 	if topUps, total, err := cache.RetrievePagedSearch[[]*model.TopUp]("top_ups", cacheConditions...); err == nil && topUps != nil && len(*topUps) > 0 { | ||||||
|  | 		tur.log.Info("从缓存中获取到商户充值记录", zap.Int("Count", len(*topUps)), zap.Int64("Total", total)) | ||||||
|  | 		return *topUps, total, nil | ||||||
|  | 	} | ||||||
|  | 	ctx, cancel := global.TimeoutContext() | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
|  | 	topUpQuery := tur.ds. | ||||||
|  | 		From(goqu.T("tenement_top_ups").As("t")). | ||||||
|  | 		LeftJoin(goqu.T("tenement").As("te"), goqu.On(goqu.I("te.id").Eq(goqu.I("t.tenement_id")), goqu.I("te.park_id").Eq(goqu.I("t.park_id")))). | ||||||
|  | 		LeftJoin(goqu.T("meter").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("t.meter_id")), goqu.I("m.park_id").Eq(goqu.I("t.park_id")))). | ||||||
|  | 		Select("t.*", goqu.I("te.full_name").As("tenement_name"), goqu.I("m.address").As("meter_address")). | ||||||
|  | 		Where(goqu.I("t.park_id").Eq(pid)) | ||||||
|  | 	countQuery := tur.ds. | ||||||
|  | 		From(goqu.T("tenement_top_ups").As("t")). | ||||||
|  | 		LeftJoin(goqu.T("tenement").As("te"), goqu.On(goqu.I("te.id").Eq(goqu.I("t.tenement_id")), goqu.I("te.park_id").Eq(goqu.I("t.park_id")))). | ||||||
|  | 		LeftJoin(goqu.T("meter").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("t.meter_id")), goqu.I("m.park_id").Eq(goqu.I("t.park_id")))). | ||||||
|  | 		Select(goqu.COUNT("t.*")). | ||||||
|  | 		Where(goqu.I("t.park_id").Eq(pid)) | ||||||
|  |  | ||||||
|  | 	if keyword != nil && len(*keyword) > 0 { | ||||||
|  | 		pattern := fmt.Sprintf("%%%s%%", *keyword) | ||||||
|  | 		topUpQuery = topUpQuery.Where(goqu.Or( | ||||||
|  | 			goqu.I("te.full_name").ILike(pattern), | ||||||
|  | 			goqu.I("te.short_name").ILike(pattern), | ||||||
|  | 			goqu.I("te.abbr").ILike(pattern), | ||||||
|  | 			goqu.I("m.code").ILike(pattern), | ||||||
|  | 			goqu.I("m.address").ILike(pattern), | ||||||
|  | 		)) | ||||||
|  | 		countQuery = countQuery.Where(goqu.Or( | ||||||
|  | 			goqu.I("te.full_name").ILike(pattern), | ||||||
|  | 			goqu.I("te.short_name").ILike(pattern), | ||||||
|  | 			goqu.I("te.abbr").ILike(pattern), | ||||||
|  | 			goqu.I("m.code").ILike(pattern), | ||||||
|  | 			goqu.I("m.address").ILike(pattern), | ||||||
|  | 		)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if startDate != nil { | ||||||
|  | 		topUpQuery = topUpQuery.Where(goqu.I("t.topped_up_at").Gte(startDate.ToBeginningOfDate())) | ||||||
|  | 		countQuery = countQuery.Where(goqu.I("t.topped_up_at").Gte(startDate.ToBeginningOfDate())) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if endDate != nil { | ||||||
|  | 		topUpQuery = topUpQuery.Where(goqu.I("t.topped_up_at").Lte(endDate.ToEndingOfDate())) | ||||||
|  | 		countQuery = countQuery.Where(goqu.I("t.topped_up_at").Lte(endDate.ToEndingOfDate())) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	startRow := (page - 1) * config.ServiceSettings.ItemsPageSize | ||||||
|  | 	topUpQuery = topUpQuery.Order(goqu.I("t.topped_up_at").Desc()).Offset(startRow).Limit(config.ServiceSettings.ItemsPageSize) | ||||||
|  |  | ||||||
|  | 	topUpSql, topUpArgs, _ := topUpQuery.Prepared(true).ToSQL() | ||||||
|  | 	countSql, countArgs, _ := countQuery.Prepared(true).ToSQL() | ||||||
|  |  | ||||||
|  | 	var ( | ||||||
|  | 		topUps []*model.TopUp = make([]*model.TopUp, 0) | ||||||
|  | 		total  int64          = 0 | ||||||
|  | 	) | ||||||
|  | 	if err := pgxscan.Select(ctx, global.DB, &topUps, topUpSql, topUpArgs...); err != nil { | ||||||
|  | 		tur.log.Error("查询商户充值记录失败", zap.Error(err)) | ||||||
|  | 		return topUps, 0, err | ||||||
|  | 	} | ||||||
|  | 	if err := pgxscan.Get(ctx, global.DB, &total, countSql, countArgs...); err != nil { | ||||||
|  | 		tur.log.Error("查询商户充值记录总数失败", zap.Error(err)) | ||||||
|  | 		return topUps, 0, err | ||||||
|  | 	} | ||||||
|  | 	cache.CachePagedSearch(topUps, total, []string{fmt.Sprintf("top_up:%s", pid), fmt.Sprintf("tenement:%s", pid), fmt.Sprintf("meter:%s", pid)}, "top_ups", cacheConditions...) | ||||||
|  | 	return topUps, total, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 取得一个充值记录的详细信息 | ||||||
|  | func (tur _TopUpRepository) GetTopUp(pid, topUpCode string) (*model.TopUp, error) { | ||||||
|  | 	tur.log.Info("查询充值记录", zap.String("Park", pid), zap.String("TopUpCode", topUpCode)) | ||||||
|  | 	if topUp, err := cache.RetrieveEntity[model.TopUp]("top_up", topUpCode); err == nil && topUp != nil { | ||||||
|  | 		tur.log.Info("从缓存中获取到充值记录") | ||||||
|  | 		return topUp, err | ||||||
|  | 	} | ||||||
|  | 	ctx, cancel := global.TimeoutContext() | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
|  | 	topUpSql, topUpArgs, _ := tur.ds. | ||||||
|  | 		From(goqu.T("tenement_top_ups").As("t")). | ||||||
|  | 		LeftJoin(goqu.T("tenement").As("te"), goqu.On(goqu.I("te.id").Eq(goqu.I("t.tenement_id")), goqu.I("te.park_id").Eq(goqu.I("t.park_id")))). | ||||||
|  | 		LeftJoin(goqu.T("meter").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("t.meter_id")), goqu.I("m.park_id").Eq(goqu.I("t.park_id")))). | ||||||
|  | 		Select("t.*", goqu.I("te.full_name").As("tenement_name"), goqu.I("m.address").As("meter_address")). | ||||||
|  | 		Where(goqu.I("t.park_id").Eq(pid), goqu.I("t.top_up_code").Eq(topUpCode)). | ||||||
|  | 		Prepared(true).ToSQL() | ||||||
|  |  | ||||||
|  | 	var topUp model.TopUp | ||||||
|  | 	if err := pgxscan.Get(ctx, global.DB, &topUp, topUpSql, topUpArgs...); err != nil { | ||||||
|  | 		tur.log.Error("查询充值记录失败", zap.Error(err)) | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	cache.CacheEntity(&topUp, []string{fmt.Sprintf("top_up:%s", pid), fmt.Sprintf("tenement:%s", pid), fmt.Sprintf("meter:%s", pid)}, "top_up", topUpCode) | ||||||
|  | 	return &topUp, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 创建一条新的充值记录 | ||||||
|  | func (tur _TopUpRepository) CreateTopUp(pid string, form *vo.TopUpCreationForm) error { | ||||||
|  | 	tur.log.Info("创建一条新的充值记录", zap.String("Park", pid), zap.String("Tenement", form.Tenement), zap.String("Meter", form.Meter)) | ||||||
|  | 	ctx, cancel := global.TimeoutContext() | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
|  | 	serial.StringSerialRequestChan <- 1 | ||||||
|  | 	topUpCode := serial.Prefix("U", <-serial.StringSerialResponseChan) | ||||||
|  | 	topUpTime := types.Now() | ||||||
|  | 	topUpSql, topUpArgs, _ := tur.ds. | ||||||
|  | 		Insert("tenement_top_ups"). | ||||||
|  | 		Cols("top_up_code", "park_id", "tenement_id", "meter_id", "topped_up_at", "amount", "payment_type"). | ||||||
|  | 		Vals(goqu.Vals{ | ||||||
|  | 			topUpCode, | ||||||
|  | 			pid, | ||||||
|  | 			form.Tenement, | ||||||
|  | 			form.Meter, | ||||||
|  | 			topUpTime, | ||||||
|  | 			form.Amount, | ||||||
|  | 			model.PAYMENT_CASH, | ||||||
|  | 		}). | ||||||
|  | 		Prepared(true).ToSQL() | ||||||
|  |  | ||||||
|  | 	if _, err := global.DB.Exec(ctx, topUpSql, topUpArgs...); err != nil { | ||||||
|  | 		tur.log.Error("创建充值记录失败", zap.Error(err)) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	cache.AbolishRelation(fmt.Sprintf("top_ups:%s", pid)) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 删除一条充值记录 | ||||||
|  | func (tur _TopUpRepository) DeleteTopUp(pid, topUpCode string) error { | ||||||
|  | 	tur.log.Info("删除一条充值记录", zap.String("Park", pid), zap.String("TopUpCode", topUpCode)) | ||||||
|  | 	ctx, cancel := global.TimeoutContext() | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
|  | 	topUpSql, topUpArgs, _ := tur.ds. | ||||||
|  | 		Update("tenement_top_ups"). | ||||||
|  | 		Set(goqu.Record{"cancelled_at": types.Now()}). | ||||||
|  | 		Where(goqu.I("park_id").Eq(pid), goqu.I("top_up_code").Eq(topUpCode)). | ||||||
|  | 		Prepared(true).ToSQL() | ||||||
|  |  | ||||||
|  | 	if _, err := global.DB.Exec(ctx, topUpSql, topUpArgs...); err != nil { | ||||||
|  | 		tur.log.Error("删除充值记录失败", zap.Error(err)) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	cache.AbolishRelation(fmt.Sprintf("top_ups:%s", pid)) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								vo/top_up.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vo/top_up.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | package vo | ||||||
|  |  | ||||||
|  | import "github.com/shopspring/decimal" | ||||||
|  |  | ||||||
|  | type TopUpCreationForm struct { | ||||||
|  | 	Tenement string          `json:"tenement"` | ||||||
|  | 	Meter    string          `json:"meter"` | ||||||
|  | 	Amount   decimal.Decimal `json:"amount"` | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user