fix(#24):修复获取到指定核算报表中的分页公摊表计的核算信息问题
This commit is contained in:
parent
845bd75348
commit
bfa7ac1508
|
@ -204,7 +204,7 @@ func replaceMeter(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
err := service.MeterService.ReplaceMeter(parkId, meterId, &replacementForm.OldReading, replacementForm.NewMeter.Code, replacementForm.NewMeter.Ratio, &replacementForm.NewMeter.Reading)
|
err := service.MeterService.ReplaceMeter(parkId, meterId, &replacementForm.OldReading, replacementForm.NewMeter.Code, replacementForm.NewMeter.Ratio, &replacementForm.NewMeter.Reading)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
meterLog.Error("更换表计出错", zap.Error(err))
|
meterLog.Error("更换表计出错1111", zap.Error(err))
|
||||||
return result.Error(500, err.Error())
|
return result.Error(500, err.Error())
|
||||||
}
|
}
|
||||||
return result.Success("更换成功")
|
return result.Success("更换成功")
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _MeterRepository struct {
|
type _MeterRepository struct {
|
||||||
|
@ -215,6 +216,7 @@ func (mr _MeterRepository) ListMetersByIDs(pid string, ids []string) ([]*model.M
|
||||||
|
|
||||||
// 获取指定表计的详细信息
|
// 获取指定表计的详细信息
|
||||||
func (mr _MeterRepository) FetchMeterDetail(pid, code string) (*model.MeterDetail, error) {
|
func (mr _MeterRepository) FetchMeterDetail(pid, code string) (*model.MeterDetail, error) {
|
||||||
|
log.Println("获取指定标记的详细信息,1111111111111111")
|
||||||
mr.log.Info("获取指定表计的详细信息", zap.String("park id", pid), zap.String("meter code", code))
|
mr.log.Info("获取指定表计的详细信息", zap.String("park id", pid), zap.String("meter code", code))
|
||||||
ctx, cancel := global.TimeoutContext()
|
ctx, cancel := global.TimeoutContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -231,7 +233,7 @@ func (mr _MeterRepository) FetchMeterDetail(pid, code string) (*model.MeterDetai
|
||||||
goqu.I("m.code").Eq(code),
|
goqu.I("m.code").Eq(code),
|
||||||
).
|
).
|
||||||
Prepared(true).ToSQL()
|
Prepared(true).ToSQL()
|
||||||
|
log.Println("111111111111111111111111", meterSql)
|
||||||
if err := pgxscan.Get(ctx, global.DB, &meter, meterSql, meterArgs...); err != nil {
|
if err := pgxscan.Get(ctx, global.DB, &meter, meterSql, meterArgs...); err != nil {
|
||||||
mr.log.Error("查询表计信息失败", zap.Error(err))
|
mr.log.Error("查询表计信息失败", zap.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -242,6 +244,7 @@ func (mr _MeterRepository) FetchMeterDetail(pid, code string) (*model.MeterDetai
|
||||||
|
|
||||||
// 创建一条新的表计信息
|
// 创建一条新的表计信息
|
||||||
func (mr _MeterRepository) CreateMeter(tx pgx.Tx, ctx context.Context, pid string, meter vo.MeterCreationForm) (bool, error) {
|
func (mr _MeterRepository) CreateMeter(tx pgx.Tx, ctx context.Context, pid string, meter vo.MeterCreationForm) (bool, error) {
|
||||||
|
log.Println("创建一条新的表记55555555555555555555")
|
||||||
mr.log.Info("创建一条新的表计信息", zap.String("park id", pid), zap.String("meter code", meter.Code))
|
mr.log.Info("创建一条新的表计信息", zap.String("park id", pid), zap.String("meter code", meter.Code))
|
||||||
//timeNow := types.Now()
|
//timeNow := types.Now()
|
||||||
|
|
||||||
|
@ -252,7 +255,8 @@ func (mr _MeterRepository) CreateMeter(tx pgx.Tx, ctx context.Context, pid strin
|
||||||
"attached_at", "created_at", "last_modified_at",
|
"attached_at", "created_at", "last_modified_at",
|
||||||
).
|
).
|
||||||
Vals(
|
Vals(
|
||||||
goqu.Vals{pid, meter.Code, meter.Address, meter.Ratio, meter.Seq, meter.MeterType, meter.Building, meter.OnFloor, meter.Area, meter.Enabled,
|
goqu.Vals{pid, meter.Code, meter.Address, meter.Ratio, meter.Seq, meter.MeterType, meter.Building, meter.OnFloor,
|
||||||
|
meter.Area, meter.Enabled,
|
||||||
meter.Reading.ReadAt, meter.Reading.ReadAt, meter.Reading.ReadAt,
|
meter.Reading.ReadAt, meter.Reading.ReadAt, meter.Reading.ReadAt,
|
||||||
},
|
},
|
||||||
).
|
).
|
||||||
|
@ -263,6 +267,7 @@ func (mr _MeterRepository) CreateMeter(tx pgx.Tx, ctx context.Context, pid strin
|
||||||
mr.log.Error("创建表计信息失败", zap.Error(err))
|
mr.log.Error("创建表计信息失败", zap.Error(err))
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
log.Println("555555555555", meterSql)
|
||||||
return ok.RowsAffected() > 0, nil
|
return ok.RowsAffected() > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,6 +310,7 @@ func (mr _MeterRepository) CreateOrUpdateMeter(tx pgx.Tx, ctx context.Context, p
|
||||||
|
|
||||||
// 记录一条表计的抄表信息
|
// 记录一条表计的抄表信息
|
||||||
func (mr _MeterRepository) RecordReading(tx pgx.Tx, ctx context.Context, pid, code string, meterType int16, ratio decimal.Decimal, reading *vo.MeterReadingForm) (bool, error) {
|
func (mr _MeterRepository) RecordReading(tx pgx.Tx, ctx context.Context, pid, code string, meterType int16, ratio decimal.Decimal, reading *vo.MeterReadingForm) (bool, error) {
|
||||||
|
log.Println("记录一条表记的抄表信息22222222222222222222")
|
||||||
mr.log.Info("记录一条表计的抄表信息", zap.String("park id", pid), zap.String("meter code", code))
|
mr.log.Info("记录一条表计的抄表信息", zap.String("park id", pid), zap.String("meter code", code))
|
||||||
readAt := tools.DefaultTo(reading.ReadAt, types.Now())
|
readAt := tools.DefaultTo(reading.ReadAt, types.Now())
|
||||||
readingSql, readingArgs, _ := mr.ds.
|
readingSql, readingArgs, _ := mr.ds.
|
||||||
|
@ -316,6 +322,7 @@ func (mr _MeterRepository) RecordReading(tx pgx.Tx, ctx context.Context, pid, co
|
||||||
goqu.Vals{pid, code, readAt, meterType, ratio, reading.Overall, reading.Critical, reading.Peak, reading.Flat, reading.Valley},
|
goqu.Vals{pid, code, readAt, meterType, ratio, reading.Overall, reading.Critical, reading.Peak, reading.Flat, reading.Valley},
|
||||||
).
|
).
|
||||||
Prepared(true).ToSQL()
|
Prepared(true).ToSQL()
|
||||||
|
log.Println("22222222222222222222", readingSql)
|
||||||
|
|
||||||
ok, err := tx.Exec(ctx, readingSql, readingArgs...)
|
ok, err := tx.Exec(ctx, readingSql, readingArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -391,6 +398,7 @@ func (mr _MeterRepository) ListMeterCodes(pid string) ([]string, error) {
|
||||||
|
|
||||||
// 解除指定园区中指定表计的使用
|
// 解除指定园区中指定表计的使用
|
||||||
func (mr _MeterRepository) DetachMeter(tx pgx.Tx, ctx context.Context, pid, code string) (bool, error) {
|
func (mr _MeterRepository) DetachMeter(tx pgx.Tx, ctx context.Context, pid, code string) (bool, error) {
|
||||||
|
log.Println("解除指定园区的指定表记使用33333333333333333333")
|
||||||
mr.log.Info("解除指定园区中指定表计的使用", zap.String("park id", pid), zap.String("meter code", code))
|
mr.log.Info("解除指定园区中指定表计的使用", zap.String("park id", pid), zap.String("meter code", code))
|
||||||
timeNow := types.Now()
|
timeNow := types.Now()
|
||||||
meterSql, meterArgs, _ := mr.ds.
|
meterSql, meterArgs, _ := mr.ds.
|
||||||
|
@ -406,7 +414,7 @@ func (mr _MeterRepository) DetachMeter(tx pgx.Tx, ctx context.Context, pid, code
|
||||||
goqu.I("code").Eq(code),
|
goqu.I("code").Eq(code),
|
||||||
).
|
).
|
||||||
Prepared(true).ToSQL()
|
Prepared(true).ToSQL()
|
||||||
|
log.Println("3333333333333333", meterSql)
|
||||||
ok, err := tx.Exec(ctx, meterSql, meterArgs...)
|
ok, err := tx.Exec(ctx, meterSql, meterArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mr.log.Error("解除表计使用失败", zap.Error(err))
|
mr.log.Error("解除表计使用失败", zap.Error(err))
|
||||||
|
@ -468,6 +476,7 @@ func (mr _MeterRepository) BindMeter(tx pgx.Tx, ctx context.Context, pid, master
|
||||||
|
|
||||||
// 解除两个表计之间的关联
|
// 解除两个表计之间的关联
|
||||||
func (mr _MeterRepository) UnbindMeter(tx pgx.Tx, ctx context.Context, pid, masterMeter, slaveMeter string) (bool, error) {
|
func (mr _MeterRepository) UnbindMeter(tx pgx.Tx, ctx context.Context, pid, masterMeter, slaveMeter string) (bool, error) {
|
||||||
|
log.Println("解除两个标记之间的关系》》》》》》》》》》》》》》》》》》》》》》》4444444444")
|
||||||
mr.log.Info("解除两个表计之间的关联", zap.String("master meter code", masterMeter), zap.String("slave meter code", slaveMeter))
|
mr.log.Info("解除两个表计之间的关联", zap.String("master meter code", masterMeter), zap.String("slave meter code", slaveMeter))
|
||||||
relationSql, relationArgs, _ := mr.ds.
|
relationSql, relationArgs, _ := mr.ds.
|
||||||
Update(goqu.T("meter_relations")).
|
Update(goqu.T("meter_relations")).
|
||||||
|
@ -483,7 +492,7 @@ func (mr _MeterRepository) UnbindMeter(tx pgx.Tx, ctx context.Context, pid, mast
|
||||||
goqu.I("revoked_at").IsNull(),
|
goqu.I("revoked_at").IsNull(),
|
||||||
).
|
).
|
||||||
Prepared(true).ToSQL()
|
Prepared(true).ToSQL()
|
||||||
|
log.Println("4444444444444444", relationSql)
|
||||||
ok, err := tx.Exec(ctx, relationSql, relationArgs...)
|
ok, err := tx.Exec(ctx, relationSql, relationArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mr.log.Error("解除表计关系失败", zap.Error(err))
|
mr.log.Error("解除表计关系失败", zap.Error(err))
|
||||||
|
|
|
@ -402,19 +402,23 @@ func (rr _ReportRepository) ListPublicMetersInReport(rid string, page uint, keyw
|
||||||
|
|
||||||
// 检索指定核算报表中公摊表计的核算记录
|
// 检索指定核算报表中公摊表计的核算记录
|
||||||
func (rr _ReportRepository) ListPooledMetersInReport(rid string, page uint, keyword *string) ([]*model.ReportDetailedPooledConsumption, int64, error) {
|
func (rr _ReportRepository) ListPooledMetersInReport(rid string, page uint, keyword *string) ([]*model.ReportDetailedPooledConsumption, int64, error) {
|
||||||
|
|
||||||
rr.log.Info("检索指定核算报表中公摊表计的核算记录", zap.String("Report", rid))
|
rr.log.Info("检索指定核算报表中公摊表计的核算记录", zap.String("Report", rid))
|
||||||
ctx, cancel := global.TimeoutContext()
|
ctx, cancel := global.TimeoutContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
reportQuery := rr.ds.
|
reportQuery := rr.ds.
|
||||||
From(goqu.T("report_pooled_consumption").As("r")).
|
From(goqu.T("report_pooled_consumption").As("r")).
|
||||||
|
Join(
|
||||||
|
goqu.T("report").As("ri"), goqu.On(goqu.I("ri.id").Eq(goqu.I("r.report_id")))).
|
||||||
Join(goqu.T("meter_04kv").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("r.pooled_meter_id")))).
|
Join(goqu.T("meter_04kv").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("r.pooled_meter_id")))).
|
||||||
Join(goqu.T("park").As("p"), goqu.On(goqu.I("p.id").Eq(goqu.I("m.park_id")))).
|
Join(goqu.T("park").As("p"), goqu.On(goqu.I("p.id").Eq(goqu.I("ri.park_id")))).
|
||||||
LeftJoin(goqu.T("park_building").As("b"), goqu.On(goqu.I("b.id").Eq(goqu.I("m.building")))).
|
LeftJoin(goqu.T("park_building").As("b"), goqu.On(goqu.I("b.id").Eq(goqu.I("m.building")))).
|
||||||
Select(
|
Select(
|
||||||
goqu.I("r.*"), goqu.I("m.*"), goqu.I("b.name").As("building_name"), goqu.I("p.public_pooled"),
|
goqu.I("r.*"), goqu.I("m.*"), goqu.I("b.name").As("building_name"), goqu.I("p.public_pooled"),
|
||||||
).
|
).
|
||||||
Where(goqu.I("r.report_id").Eq(rid))
|
Where(goqu.I("r.report_id").Eq(rid))
|
||||||
|
reportQuery = reportQuery.Where(goqu.I("m.park_id").Eq(goqu.I("p.id")))
|
||||||
countQuery := rr.ds.
|
countQuery := rr.ds.
|
||||||
From(goqu.T("report_pooled_consumption").As("r")).
|
From(goqu.T("report_pooled_consumption").As("r")).
|
||||||
Join(goqu.T("meter_04kv").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("r.pooled_meter_id")))).
|
Join(goqu.T("meter_04kv").As("m"), goqu.On(goqu.I("m.code").Eq(goqu.I("r.pooled_meter_id")))).
|
||||||
|
|
134
service/meter.go
134
service/meter.go
|
@ -363,16 +363,16 @@ func (ms _MeterService) ReplaceMeter(
|
||||||
|
|
||||||
// 步骤6:将旧表计的部分信息赋予新表计
|
// 步骤6:将旧表计的部分信息赋予新表计
|
||||||
newMeterCreationForm := vo.MeterCreationForm{
|
newMeterCreationForm := vo.MeterCreationForm{
|
||||||
Code: newMeterCode,
|
Code: newMeterCode,
|
||||||
Address: oldMeter.Address,
|
Address: oldMeter.Address,
|
||||||
MeterType: oldMeter.MeterType,
|
MeterType: oldMeter.MeterType,
|
||||||
Ratio: newMeterRatio,
|
Ratio: newMeterRatio,
|
||||||
Seq: oldMeter.Seq,
|
Seq: oldMeter.Seq,
|
||||||
Enabled: oldMeter.Enabled,
|
Enabled: oldMeter.Enabled,
|
||||||
Building: oldMeter.Building,
|
Building: oldMeter.Building,
|
||||||
OnFloor: oldMeter.OnFloor,
|
OnFloor: oldMeter.OnFloor,
|
||||||
Area: oldMeter.Area,
|
Area: oldMeter.Area,
|
||||||
Reading: *newMeterReading,
|
Reading: *newMeterReading,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 步骤7:将新表计写入系统
|
// 步骤7:将新表计写入系统
|
||||||
|
@ -444,6 +444,118 @@ func (ms _MeterService) ReplaceMeter(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//func replaceMeter(
|
||||||
|
// pid string,
|
||||||
|
// oldMeterCode string,
|
||||||
|
// oldMeterReading *MeterReadingForm,
|
||||||
|
// newMeterCode string,
|
||||||
|
// newMeterRatio *big.Float,
|
||||||
|
// newMeterReading *MeterReadingForm,
|
||||||
|
//) (bool, error) {
|
||||||
|
// ctx := context.Background()
|
||||||
|
// tx, err := PostgresPool{}.begin(ctx)
|
||||||
|
// if err != nil {
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤1:获取旧表计的信息
|
||||||
|
// oldMeter, err := repositories{}.meter_fetch_meter_detail(pid, oldMeterCode)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
// if oldMeter == nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, fmt.Errorf("要替换的旧表计不存在")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤2:将旧表计的读数写入读数表
|
||||||
|
// err = repositories{}.meter_record_reading(tx, pid, oldMeterCode, oldMeter.MeterType, oldMeter.Ratio, oldMeterReading)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤3: 将旧表计从系统中移除
|
||||||
|
// err = repositories{}.meter_detach_meter(tx, pid, oldMeterCode)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤4: 获取旧表计的关联信息
|
||||||
|
// var oldMeterAssociations []*MeterRelation
|
||||||
|
// if oldMeter.MeterType == Pooling {
|
||||||
|
// oldMeterAssociations, err = repositories{}.meter_list_pooled_meter_relations(pid, oldMeterCode)
|
||||||
|
// } else {
|
||||||
|
// oldMeterAssociations, err = repositories{}.meter_list_meter_relations(pid, oldMeterCode)
|
||||||
|
// }
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤5: 将旧表计的关联信息全部置为解除
|
||||||
|
// for _, relation := range oldMeterAssociations {
|
||||||
|
// err = repositories{}.meter_unbind_meter(tx, pid, relation.MasterMeter, relation.SlaveMeter)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤6: 将旧表计的部分信息赋予新表计
|
||||||
|
// newMeterCreationForm := &MeterCreationForm{
|
||||||
|
// Code: newMeterCode,
|
||||||
|
// Address: oldMeter.Address,
|
||||||
|
// MeterType: oldMeter.MeterType,
|
||||||
|
// Ratio: newMeterRatio,
|
||||||
|
// Seq: oldMeter.Seq,
|
||||||
|
// // Assign other fields
|
||||||
|
// Reading: newMeterReading,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤7: 将新表计写入系统
|
||||||
|
// err = repositories{}.meter_create_meter(tx, pid, newMeterCreationForm)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤8: 将新表计的读数写入读数表
|
||||||
|
// err = repositories{}.meter_record_reading(tx, pid, newMeterCode, oldMeter.MeterType, newMeterRatio, newMeterReading)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 步骤9: 将旧表计的关联信息复制一份并赋予新表计
|
||||||
|
// if oldMeter.MeterType == Pooling {
|
||||||
|
// for _, relation := range oldMeterAssociations {
|
||||||
|
// err = repositories{}.meter_bind_meter(tx, pid, newMeterCode, relation.SlaveMeter)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for _, relation := range oldMeterAssociations {
|
||||||
|
// err = repositories{}.meter_bind_meter(tx, pid, relation.MasterMeter, newMeterCode)
|
||||||
|
// if err != nil {
|
||||||
|
// tx.rollback(ctx)
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// err = tx.commit(ctx)
|
||||||
|
// if err != nil {
|
||||||
|
// return false, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return true, nil
|
||||||
|
//}
|
||||||
|
|
||||||
// 列出园区中指定公摊表计下的所有关联表计
|
// 列出园区中指定公摊表计下的所有关联表计
|
||||||
func (ms _MeterService) ListPooledMeterRelations(pid, masterMeter string) ([]*model.MeterDetail, error) {
|
func (ms _MeterService) ListPooledMeterRelations(pid, masterMeter string) ([]*model.MeterDetail, error) {
|
||||||
ms.log.Info("列出园区中指定公摊表计下的所有关联表计", zap.String("park id", pid), zap.String("meter code", masterMeter))
|
ms.log.Info("列出园区中指定公摊表计下的所有关联表计", zap.String("park id", pid), zap.String("meter code", masterMeter))
|
||||||
|
@ -783,4 +895,4 @@ func (ms _MeterService) BatchImportReadings(pid string, file *multipart.FileHead
|
||||||
// newMeterCode string, newMeterRatio decimal.Decimal, newMeterDisplayRatio decimal.Decimal,
|
// newMeterCode string, newMeterRatio decimal.Decimal, newMeterDisplayRatio decimal.Decimal,
|
||||||
// newMeterReading vo.NewMeterForReplacingForm) {
|
// newMeterReading vo.NewMeterForReplacingForm) {
|
||||||
//
|
//
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -12,9 +12,9 @@ Server:
|
||||||
ReadTimeout: 60
|
ReadTimeout: 60
|
||||||
WriteTimeout: 60
|
WriteTimeout: 60
|
||||||
Redis:
|
Redis:
|
||||||
Host: 127.0.0.1
|
Host: 192.168.88.129
|
||||||
Port: 6379
|
Port: 6379
|
||||||
Password:
|
Password: 123456
|
||||||
DB: 1
|
DB: 1
|
||||||
Service:
|
Service:
|
||||||
MaxSessionLife: 2h
|
MaxSessionLife: 2h
|
||||||
|
|
Loading…
Reference in New Issue
Block a user