This commit is contained in:
2025-12-29 16:13:55 +08:00
parent 8e1319ac39
commit d2d3e589f0
14 changed files with 544 additions and 26 deletions

View File

@@ -77,6 +77,10 @@ service main {
// 获取代理统计数据
@handler AdminGetAgentStatistics
get /statistics (AdminGetAgentStatisticsReq) returns (AdminGetAgentStatisticsResp)
// 获取代理链接产品统计
@handler AdminGetAgentLinkProductStatistics
get /agent-link/product-statistics (AdminGetAgentLinkProductStatisticsReq) returns (AdminGetAgentLinkProductStatisticsResp)
}
type (
@@ -426,6 +430,8 @@ type (
AdminGetWithdrawalStatisticsResp {
TotalWithdrawalAmount float64 `json:"total_withdrawal_amount"` // 总提现金额
TodayWithdrawalAmount float64 `json:"today_withdrawal_amount"` // 今日提现金额
TotalActualAmount float64 `json:"total_actual_amount"` // 总实际到账金额
TotalTaxAmount float64 `json:"total_tax_amount"` // 总扣税金额
}
// 获取代理订单统计数据请求
@@ -447,4 +453,19 @@ type (
TotalAgentCount int64 `json:"total_agent_count"` // 总代理数
TodayAgentCount int64 `json:"today_agent_count"` // 今日新增代理数
}
// 获取代理链接产品统计请求
AdminGetAgentLinkProductStatisticsReq {
}
// 代理链接产品统计列表项
AgentLinkProductStatisticsItem {
ProductName string `json:"product_name"` // 产品名称
LinkCount int64 `json:"link_count"` // 推广链接数量
}
// 获取代理链接产品统计响应
AdminGetAgentLinkProductStatisticsResp {
Items []AgentLinkProductStatisticsItem `json:"items"` // 列表数据
}
)

View File

@@ -47,6 +47,14 @@ service main {
@doc "获取收入和利润统计数据"
@handler AdminGetRevenueStatistics
get /revenue-statistics (AdminGetRevenueStatisticsReq) returns (AdminGetRevenueStatisticsResp)
@doc "获取订单来源统计数据"
@handler AdminGetOrderSourceStatistics
get /source-statistics (AdminGetOrderSourceStatisticsReq) returns (AdminGetOrderSourceStatisticsResp)
@doc "获取订单统计数据"
@handler AdminGetOrderStatistics
get /statistics (AdminGetOrderStatisticsReq) returns (AdminGetOrderStatisticsResp)
}
type (
@@ -204,4 +212,36 @@ type (
TotalProfitAmount float64 `json:"total_profit_amount"` // 总利润金额
TodayProfitAmount float64 `json:"today_profit_amount"` // 今日利润金额
}
// 获取订单来源统计数据请求
AdminGetOrderSourceStatisticsReq {
}
// 订单来源统计项
OrderSourceStatisticsItem {
ProductName string `json:"product_name"` // 产品名称
OrderCount int64 `json:"order_count"` // 订单数量
}
// 获取订单来源统计数据响应
AdminGetOrderSourceStatisticsResp {
Items []OrderSourceStatisticsItem `json:"items"` // 订单来源统计列表
}
// 获取订单统计数据请求
AdminGetOrderStatisticsReq {
Dimension string `form:"dimension"` // 时间维度day-日(当月1号到今天)month-月(今年1月到当月)year-年(过去5年)all-全部(按日统计)
}
// 订单统计项
OrderStatisticsItem {
Date string `json:"date"` // 日期
Count int64 `json:"count"` // 订单数量
Amount float64 `json:"amount"` // 订单金额
}
// 获取订单统计数据响应
AdminGetOrderStatisticsResp {
Items []OrderStatisticsItem `json:"items"` // 订单统计列表
}
)

View File

@@ -0,0 +1,29 @@
package admin_agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/main/api/internal/logic/admin_agent"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func AdminGetAgentLinkProductStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AdminGetAgentLinkProductStatisticsReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := admin_agent.NewAdminGetAgentLinkProductStatisticsLogic(r.Context(), svcCtx)
resp, err := l.AdminGetAgentLinkProductStatistics(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,30 @@
package admin_order
import (
"net/http"
"tydata-server/app/main/api/internal/logic/admin_order"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
"github.com/zeromicro/go-zero/rest/httpx"
)
func AdminGetOrderSourceStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AdminGetOrderSourceStatisticsReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := admin_order.NewAdminGetOrderSourceStatisticsLogic(r.Context(), svcCtx)
resp, err := l.AdminGetOrderSourceStatistics(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,29 @@
package admin_order
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/main/api/internal/logic/admin_order"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func AdminGetOrderStatisticsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AdminGetOrderStatisticsReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := admin_order.NewAdminGetOrderStatisticsLogic(r.Context(), svcCtx)
resp, err := l.AdminGetOrderStatistics(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -52,6 +52,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/agent-link/list",
Handler: admin_agent.AdminGetAgentLinkListHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/agent-link/product-statistics",
Handler: admin_agent.AdminGetAgentLinkProductStatisticsHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/agent-membership-config/list",
@@ -348,6 +353,18 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/revenue-statistics",
Handler: admin_order.AdminGetRevenueStatisticsHandler(serverCtx),
},
{
// 获取订单来源统计数据
Method: http.MethodGet,
Path: "/source-statistics",
Handler: admin_order.AdminGetOrderSourceStatisticsHandler(serverCtx),
},
{
// 获取订单统计数据
Method: http.MethodGet,
Path: "/statistics",
Handler: admin_order.AdminGetOrderStatisticsHandler(serverCtx),
},
{
// 更新订单
Method: http.MethodPut,

View File

@@ -0,0 +1,100 @@
package admin_agent
import (
"context"
"fmt"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"github.com/Masterminds/squirrel"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetAgentLinkProductStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetAgentLinkProductStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetAgentLinkProductStatisticsLogic {
return &AdminGetAgentLinkProductStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetAgentLinkProductStatisticsLogic) AdminGetAgentLinkProductStatistics(req *types.AdminGetAgentLinkProductStatisticsReq) (resp *types.AdminGetAgentLinkProductStatisticsResp, err error) {
// 构建查询
query := squirrel.Select(
"p.product_name",
"COUNT(al.id) as link_count",
).
From("agent_link al").
Join("product p ON al.product_id = p.id").
Where(squirrel.Eq{"al.del_state": 0}).
Where(squirrel.Eq{"p.del_state": 0}).
GroupBy("p.product_name").
OrderBy("link_count DESC")
// 执行查询
sql, args, err := query.ToSql()
if err != nil {
return nil, err
}
type Result struct {
ProductName string `db:"product_name"`
LinkCount int64 `db:"link_count"`
}
var results []Result
// 使用模型的方法执行查询
// 通过反射获取底层的QueryRowsNoCacheCtx方法避免直接类型断言
if agentLinkModel, ok := l.svcCtx.AgentLinkModel.(interface {
QueryRowsNoCacheCtx(ctx context.Context, v interface{}, query string, args ...interface{}) error
}); ok {
err = agentLinkModel.QueryRowsNoCacheCtx(l.ctx, &results, sql, args...)
} else {
// 如果无法使用模型的方法,则使用原始的连接方式(安全地获取连接)
if cachedConn, ok := l.svcCtx.AgentLinkModel.(interface {
GetConn() interface{}
}); ok {
conn := cachedConn.GetConn()
if sqlxConn, ok := conn.(interface {
QueryRowsCtx(ctx context.Context, v interface{}, query string, args ...interface{}) error
}); ok {
err = sqlxConn.QueryRowsCtx(l.ctx, &results, sql, args...)
} else {
return nil, fmt.Errorf("无法获取数据库连接")
}
} else {
return nil, fmt.Errorf("无法获取数据库连接")
}
}
if err != nil {
return nil, err
}
// 处理空结果
if len(results) == 0 {
return &types.AdminGetAgentLinkProductStatisticsResp{
Items: []types.AgentLinkProductStatisticsItem{},
}, nil
}
// 转换为返回结果
items := make([]types.AgentLinkProductStatisticsItem, 0, len(results))
for _, r := range results {
items = append(items, types.AgentLinkProductStatisticsItem{
ProductName: r.ProductName,
LinkCount: r.LinkCount,
})
}
return &types.AdminGetAgentLinkProductStatisticsResp{
Items: items,
}, nil
}

View File

@@ -50,10 +50,26 @@ func (l *AdminGetWithdrawalStatisticsLogic) AdminGetWithdrawalStatistics(req *ty
return nil, fmt.Errorf("查询今日提现金额失败: %w", err)
}
// 查询总实际到账金额status=2表示成功
totalActualAmount, err := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, totalBuilder, "actual_amount")
if err != nil {
logx.Errorf("查询总实际到账金额失败: %v", err)
return nil, fmt.Errorf("查询总实际到账金额失败: %w", err)
}
// 查询总扣税金额status=2表示成功
totalTaxAmount, err := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, totalBuilder, "tax_amount")
if err != nil {
logx.Errorf("查询总扣税金额失败: %v", err)
return nil, fmt.Errorf("查询总扣税金额失败: %w", err)
}
// 构建响应
resp = &types.AdminGetWithdrawalStatisticsResp{
TotalWithdrawalAmount: totalWithdrawalAmount,
TodayWithdrawalAmount: todayWithdrawalAmount,
TotalActualAmount: totalActualAmount,
TotalTaxAmount: totalTaxAmount,
}
return resp, nil

View File

@@ -0,0 +1,87 @@
package admin_order
import (
"context"
"fmt"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetOrderSourceStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetOrderSourceStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderSourceStatisticsLogic {
return &AdminGetOrderSourceStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetOrderSourceStatisticsLogic) AdminGetOrderSourceStatistics(req *types.AdminGetOrderSourceStatisticsReq) (resp *types.AdminGetOrderSourceStatisticsResp, err error) {
// 查询所有有产品ID的订单
builder := l.svcCtx.OrderModel.SelectBuilder()
builder = builder.Where("product_id IS NOT NULL")
// 获取所有符合条件的订单
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, builder, "id DESC")
if err != nil {
logx.Errorf("查询订单列表失败: %v", err)
return nil, fmt.Errorf("查询订单列表失败: %w", err)
}
logx.Infof("获取到订单数量: %d", len(orders))
// 统计每个产品的订单数量
productCountMap := make(map[int64]int64)
for _, order := range orders {
productCountMap[order.ProductId]++
}
// 构建返回结果
items := make([]types.OrderSourceStatisticsItem, 0, len(productCountMap))
for productId, count := range productCountMap {
// 获取产品信息
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, productId)
if err != nil {
logx.Errorf("查询产品信息失败 productId=%d, err=%v", productId, err)
// 如果查询失败,使用默认值
items = append(items, types.OrderSourceStatisticsItem{
ProductName: "未知产品",
OrderCount: count,
})
continue
}
items = append(items, types.OrderSourceStatisticsItem{
ProductName: product.ProductName,
OrderCount: count,
})
}
// 按订单数量降序排序
for i := 0; i < len(items)-1; i++ {
for j := i + 1; j < len(items); j++ {
if items[i].OrderCount < items[j].OrderCount {
items[i], items[j] = items[j], items[i]
}
}
}
logx.Infof("查询到订单来源统计数据: %d 个产品,订单总数: %d", len(items), len(orders))
return &types.AdminGetOrderSourceStatisticsResp{
Items: items,
}, nil
}
// 定义结果结构体
type OrderSourceResult struct {
ProductName string `db:"product_name"`
OrderCount int64 `db:"order_count"`
}

View File

@@ -0,0 +1,106 @@
package admin_order
import (
"context"
"fmt"
"time"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetOrderStatisticsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetOrderStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderStatisticsLogic {
return &AdminGetOrderStatisticsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetOrderStatisticsLogic) AdminGetOrderStatistics(req *types.AdminGetOrderStatisticsReq) (resp *types.AdminGetOrderStatisticsResp, err error) {
// 获取当前时间
now := time.Now()
var startTime, endTime time.Time
// 根据时间维度设置时间范围和格式
switch req.Dimension {
case "day":
// 日当月1号到今天
startTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
case "month":
// 月今年1月到当月
startTime = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, now.Location())
endTime = time.Date(now.Year(), now.Month(), 1, 23, 59, 59, 999999999, now.Location()).AddDate(0, 1, -1)
case "year":
// 年过去5年
startTime = time.Date(now.Year()-5, 1, 1, 0, 0, 0, 0, now.Location())
endTime = time.Date(now.Year(), 12, 31, 23, 59, 59, 999999999, now.Location())
case "all":
// 全部:所有时间,但按日统计
startTime = time.Date(2020, 1, 1, 0, 0, 0, 0, now.Location()) // 假设从2020年开始
endTime = now
default:
// 默认为日
startTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
}
// 构建查询条件
builder := l.svcCtx.OrderModel.SelectBuilder().
Where("create_time >= ? AND create_time <= ?", startTime, endTime).
Where("status = ?", "paid") // 只统计已支付的订单
// 查询所有符合条件的订单
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, builder, "create_time ASC")
if err != nil {
logx.Errorf("查询订单统计数据失败: %v", err)
return nil, fmt.Errorf("查询订单统计数据失败: %w", err)
}
// 按日期分组统计
dateMap := make(map[string]*types.OrderStatisticsItem)
for _, order := range orders {
var dateKey string
if req.Dimension == "year" {
dateKey = order.CreateTime.Format("2006")
} else if req.Dimension == "month" {
dateKey = order.CreateTime.Format("2006-01")
} else {
dateKey = order.CreateTime.Format("2006-01-02")
}
if item, exists := dateMap[dateKey]; exists {
item.Count++
item.Amount += order.Amount
} else {
dateMap[dateKey] = &types.OrderStatisticsItem{
Date: dateKey,
Count: 1,
Amount: order.Amount,
}
}
}
// 转换为切片
items := make([]types.OrderStatisticsItem, 0, len(dateMap))
for date := range dateMap {
items = append(items, *dateMap[date])
}
// 构建响应
resp = &types.AdminGetOrderStatisticsResp{
Items: items,
}
return resp, nil
}

View File

@@ -80,13 +80,13 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
return findAgentProductConfigModelErr
}
// 平台底价成本
PlatformCostAmount, platformCostErr := l.PlatformCost(transCtx, agentID, agentProductConfigModel, session)
PlatformCostAmount, platformCostErr := l.PlatformCost(transCtx, agentID, order.Id, agentProductConfigModel, session)
if platformCostErr != nil {
return platformCostErr
}
// 平台提价成本
PlatformPricingAmount, platformPricingErr := l.PlatformPricing(transCtx, agentID, order.Amount, agentProductConfigModel, session)
PlatformPricingAmount, platformPricingErr := l.PlatformPricing(transCtx, agentID, order.Id, order.Amount, agentProductConfigModel, session)
if platformPricingErr != nil {
return platformPricingErr
}
@@ -227,10 +227,11 @@ func (l *AgentService) AncestorCommission(ctx context.Context, descendantId int6
}
// PlatformCost 平台底价成本
func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, orderID int64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
costAgentPlatformDeductionModel := model.AgentPlatformDeduction{
AgentId: agentID,
OrderId: orderID,
Amount: agentProductConfigModel.CostPrice,
Type: model.AgentDeductionTypeCost,
}
@@ -243,7 +244,7 @@ func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, agentPro
}
// PlatformPricing 平台提价成本
func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, pricing float64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, orderID int64, pricing float64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
// 2. 计算平台提价成本
if pricing > agentProductConfigModel.PricingStandard {
// 超出部分
@@ -254,6 +255,7 @@ func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, prici
pricingAgentPlatformDeductionModel := model.AgentPlatformDeduction{
AgentId: agentID,
OrderId: orderID,
Amount: overpricingCost,
Type: model.AgentDeductionTypePricing,
}
@@ -384,7 +386,7 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
// 获取各等级的奖励金额
var vipRewardAmount float64
var svipRewardAmount float64
if agentMembershipConfigModel.LowerConvertVipReward.Valid {
vipRewardAmount = agentMembershipConfigModel.LowerConvertVipReward.Float64
}
@@ -500,7 +502,7 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
return nil
}
rewardAmount := withdrawAmount * rewardRatio
if rewardAmount > 0 {
// 创建奖励记录
agentRewards := model.AgentRewards{

View File

@@ -239,6 +239,13 @@ type AdminGetAgentLinkListResp struct {
Items []AgentLinkListItem `json:"items"` // 列表数据
}
type AdminGetAgentLinkProductStatisticsReq struct {
}
type AdminGetAgentLinkProductStatisticsResp struct {
Items []AgentLinkProductStatisticsItem `json:"items"` // 列表数据
}
type AdminGetAgentListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
@@ -495,6 +502,21 @@ type AdminGetOrderListResp struct {
Items []OrderListItem `json:"items"` // 列表
}
type AdminGetOrderSourceStatisticsReq struct {
}
type AdminGetOrderSourceStatisticsResp struct {
Items []OrderSourceStatisticsItem `json:"items"` // 订单来源统计列表
}
type AdminGetOrderStatisticsReq struct {
Dimension string `form:"dimension"` // 时间维度day-日(当月1号到今天)month-月(今年1月到当月)year-年(过去5年)all-全部(按日统计)
}
type AdminGetOrderStatisticsResp struct {
Items []OrderStatisticsItem `json:"items"` // 订单统计列表
}
type AdminGetPlatformUserDetailReq struct {
Id int64 `path:"id"` // 用户ID
}
@@ -678,6 +700,8 @@ type AdminGetWithdrawalStatisticsReq struct {
type AdminGetWithdrawalStatisticsResp struct {
TotalWithdrawalAmount float64 `json:"total_withdrawal_amount"` // 总提现金额
TodayWithdrawalAmount float64 `json:"today_withdrawal_amount"` // 今日提现金额
TotalActualAmount float64 `json:"total_actual_amount"` // 总实际到账金额
TotalTaxAmount float64 `json:"total_tax_amount"` // 总扣税金额
}
type AdminLoginReq struct {
@@ -1014,6 +1038,11 @@ type AgentLinkListItem struct {
CreateTime string `json:"create_time"` // 创建时间
}
type AgentLinkProductStatisticsItem struct {
ProductName string `json:"product_name"` // 产品名称
LinkCount int64 `json:"link_count"` // 推广链接数量
}
type AgentListItem struct {
Id int64 `json:"id"` // 主键
UserId int64 `json:"user_id"` // 用户ID
@@ -1697,6 +1726,17 @@ type OrderListItem struct {
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态not_agent-非代理订单success-处理成功failed-处理失败pending-待处理
}
type OrderSourceStatisticsItem struct {
ProductName string `json:"product_name"` // 产品名称
OrderCount int64 `json:"order_count"` // 订单数量
}
type OrderStatisticsItem struct {
Date string `json:"date"` // 日期
Count int64 `json:"count"` // 订单数量
Amount float64 `json:"amount"` // 订单金额
}
type PaymentCheckReq struct {
OrderNo string `json:"order_no" validate:"required"`
}