diff --git a/service/meter04kv.go b/service/meter04kv.go index 1ed540f..a4a23a4 100644 --- a/service/meter04kv.go +++ b/service/meter04kv.go @@ -1,62 +1,73 @@ package service import ( + "context" + "database/sql" "electricity_bill_calc/cache" "electricity_bill_calc/config" "electricity_bill_calc/excel" "electricity_bill_calc/global" + "electricity_bill_calc/logger" "electricity_bill_calc/model" "fmt" "strconv" mapset "github.com/deckarep/golang-set/v2" "github.com/samber/lo" - "xorm.io/builder" - "xorm.io/xorm" + "github.com/uptrace/bun" + "go.uber.org/zap" ) -type _Meter04kVService struct{} +type _Meter04kVService struct { + l *zap.Logger +} -var Meter04kVService _Meter04kVService +var Meter04kVService = _Meter04kVService{ + l: logger.Named("Service", "Meter04KV"), +} func (_Meter04kVService) ListMeterDetail(park, keyword string, page int) ([]model.Meter04KV, int64, error) { - var condition = make([]string, 0) - cond := builder.NewCond().And(builder.Eq{"park_id": park}) + var ( + condition = make([]string, 0) + meters = make([]model.Meter04KV, 0) + ) + cond := global.DB.NewSelect().Model(&meters). + Where("park_id = ?", park) condition = append(condition, park, strconv.Itoa(page)) if len(keyword) > 0 { - cond = cond.And( - builder.Like{"address", keyword}. - Or(builder.Like{"customer_name", keyword}). - Or(builder.Like{"code", keyword}). - Or(builder.Like{"contact_name", keyword}). - Or(builder.Like{"contact_phone", keyword})) + keywordCond := "%" + keyword + "%" + cond = cond.WhereGroup(" and ", func(q *bun.SelectQuery) *bun.SelectQuery { + return q.Where("address like ?", keywordCond). + WhereOr("code like ?", keywordCond). + WhereOr("customer_name like ?", keywordCond). + WhereOr("contact_name like ?", keywordCond). + WhereOr("contact_phone like ?", keywordCond) + }) condition = append(condition, keyword) } - var ( - total int64 - err error - ) if cachedTotal, err := cache.RetreiveCount("meter_04kv", condition...); cachedTotal != -1 && err == nil { - total = cachedTotal - } else { - total, err = global.DBConn.Where(cond).NoAutoCondition().Count(new(model.Meter04KV)) - if err != nil { - return make([]model.Meter04KV, 0), -1, err + if cachedMeters, _ := cache.RetreiveSearch[[]model.Meter04KV]("meter_04kv", condition...); cachedMeters != nil { + return *cachedMeters, cachedTotal, nil } - cache.CacheCount([]string{"meter_04kv", "park"}, "meter_04kv", total, condition...) } - var meters = make([]model.Meter04KV, 0) + + ctx, cancel := global.TimeoutContext() + defer cancel() startItem := (page - 1) * config.ServiceSettings.ItemsPageSize - if cachedMeters, _ := cache.RetreiveSearch[[]model.Meter04KV]("meter_04kv", condition...); cachedMeters != nil { - return *cachedMeters, total, nil - } - err = global.DBConn. - Where(cond). - Limit(config.ServiceSettings.ItemsPageSize, startItem). - Asc("seq", "code"). - Find(&meters) - cache.CacheSearch(meters, []string{"meter_04kv", "park"}, "meter_04kv", condition...) - return meters, total, err + total, err := cond. + Order("seq asc", "code asc"). + Limit(config.ServiceSettings.ItemsPageSize). + Offset(startItem). + ScanAndCount(ctx) + + relations := lo.Map(meters, func(m model.Meter04KV, _ int) string { + return fmt.Sprintf("meter_04kv:%s:%s", m.ParkId, m.Code) + }) + relations = append(relations, "meter_04kv", "park") + + cache.CacheCount(relations, "meter_04kv", int64(total), condition...) + cache.CacheSearch(meters, relations, "meter_04kv", condition...) + return meters, int64(total), err } func (_Meter04kVService) Get04kVMeterDetail(park, code string) (*model.Meter04KV, error) { @@ -64,19 +75,24 @@ func (_Meter04kVService) Get04kVMeterDetail(park, code string) (*model.Meter04KV return cachedMeter, nil } var meter = new(model.Meter04KV) - has, err := global.DBConn.Where(builder.Eq{"code": code, "park_id": park}).NoAutoCondition().Get(meter) + ctx, cancel := global.TimeoutContext() + defer cancel() + err := global.DB.NewSelect().Model(&meter). + Where("code = ?", code). + Where("park_id = ?", park). + Scan(ctx) if err != nil { return nil, err } - if !has { + if meter == nil { return nil, nil } - cache.CacheEntity(meter, []string{fmt.Sprintf("meter_04kv_%s_%s", park, code), "park"}, "meter_04kv", fmt.Sprintf("%s_%s", park, code)) + cache.CacheEntity(meter, []string{fmt.Sprintf("meter_04kv:%s:%s", park, code), "park"}, "meter_04kv", fmt.Sprintf("%s_%s", park, code)) return meter, nil } -func (_Meter04kVService) insertNewMeter(tx *xorm.Session, meter model.Meter04KV) error { - _, err := tx.Insert(meter) +func (_Meter04kVService) insertNewMeter(tx *bun.Tx, ctx *context.Context, meter model.Meter04KV) error { + _, err := tx.NewInsert().Model(&meter).Exec(*ctx) if err != nil { tx.Rollback() } @@ -84,28 +100,28 @@ func (_Meter04kVService) insertNewMeter(tx *xorm.Session, meter model.Meter04KV) return err } -func (_Meter04kVService) updateMeter(tx *xorm.Session, meter model.Meter04KV) error { - _, err := tx. - Where(builder.Eq{"code": meter.Code, "park_id": meter.ParkId}). - Cols("address", "customer_name", "contact_name", "contact_phone", "ratio", "seq", "public_meter", "dilute", "enabled"). - NoAutoCondition(). - Update(meter) +func (_Meter04kVService) updateMeter(tx *bun.Tx, ctx *context.Context, meter model.Meter04KV) error { + _, err := tx.NewUpdate().Model(meter). + Where("code = ?", meter.Code). + Where("park_id = ?", meter.ParkId). + Column("address", "customer_name", "contact_name", "contact_phone", "ratio", "seq", "public_meter", "dilute", "enabled"). + Exec(*ctx) if err != nil { tx.Rollback() } - cache.AbolishRelation("meter_04kv") - cache.AbolishRelation(fmt.Sprintf("meter_04kv_%s_%s", meter.ParkId, meter.Code)) + cache.AbolishRelation(fmt.Sprintf("meter_04kv:%s:%s", meter.ParkId, meter.Code)) return err } func (m _Meter04kVService) CreateSingleMeter(meter model.Meter04KV) error { - tx := global.DBConn.NewSession() - if err := tx.Begin(); err != nil { + ctx, cancel := global.TimeoutContext() + defer cancel() + tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{}) + if err != nil { return err } - defer tx.Close() - err := m.insertNewMeter(tx, meter) + err = m.insertNewMeter(&tx, &ctx, meter) if err != nil { return err } @@ -115,18 +131,19 @@ func (m _Meter04kVService) CreateSingleMeter(meter model.Meter04KV) error { return err } cache.AbolishRelation("meter_04kv") - cache.AbolishRelation(fmt.Sprintf("meter_04kv_%s_%s", meter.ParkId, meter.Code)) + cache.AbolishRelation(fmt.Sprintf("meter_04kv:%s:%s", meter.ParkId, meter.Code)) return nil } func (m _Meter04kVService) UpdateSingleMeter(meter *model.Meter04KV) error { - tx := global.DBConn.NewSession() - if err := tx.Begin(); err != nil { + ctx, cancel := global.TimeoutContext() + defer cancel() + tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{}) + if err != nil { return err } - defer tx.Close() - err := m.updateMeter(tx, *meter) + err = m.updateMeter(&tx, &ctx, *meter) if err != nil { return err } @@ -135,8 +152,7 @@ func (m _Meter04kVService) UpdateSingleMeter(meter *model.Meter04KV) error { tx.Rollback() return err } - cache.AbolishRelation("meter_04kv") - cache.AbolishRelation(fmt.Sprintf("meter_04kv_%s_%s", meter.ParkId, meter.Code)) + cache.AbolishRelation(fmt.Sprintf("meter_04kv:%s:%s", meter.ParkId, meter.Code)) return nil } @@ -162,25 +178,30 @@ func (m _Meter04kVService) BatchCreateMeter(meters []model.Meter04KV) error { } parkId, _ := parkIds.Pop() + ctx, cancel := global.TimeoutContext() + defer cancel() + allMeterCodes := make([]string, 0) - err := global.DBConn.Table(&model.Meter04KV{}).Where(builder.Eq{"park_id": parkId}).Select("code").Find(&allMeterCodes) + err := global.DB.NewSelect().Model((*model.Meter04KV)(nil)). + Where("park_id = ?", parkId). + Column("code"). + Scan(ctx, &allMeterCodes) if err != nil { return err } meterCodes := mapset.NewSet(allMeterCodes...) - tx := global.DBConn.NewSession() - if err := tx.Begin(); err != nil { + tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{}) + if err != nil { return err } - defer tx.Close() for _, meter := range meters { var err error if meterCodes.Contains(meter.Code) { - err = m.updateMeter(tx, meter) + err = m.updateMeter(&tx, &ctx, meter) } else { - err = m.insertNewMeter(tx, meter) + err = m.insertNewMeter(&tx, &ctx, meter) } if err != nil { return err