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