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