fix: improvement logs and record news access

This commit is contained in:
ericprd 2025-03-20 11:11:08 +08:00
parent 290d7f6701
commit d8f6968f64
13 changed files with 81 additions and 25 deletions

View File

@ -2,12 +2,13 @@ package database
import "time"
type LogAds struct {
type ContentLog struct {
ID string `gorm:"primaryKey;not null" json:"id"`
ContentID string `gorm:"not null" json:"content_id"`
UserID string `gorm:"default:null" json:"user_id"`
IP string `gorm:"default:null" json:"ip"`
UserAgent string `gorm:"default:null" json:"user_agent"`
Category string `gorm:"not null" json:"category"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}

View File

@ -1,11 +0,0 @@
package database
import "time"
type LogNews struct {
ID string `gorm:"primaryKey;not null" json:"id"`
NewsID string `gorm:"not null" json:"news_id"`
UserID string `gorm:"not null" json:"user_id"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}

View File

@ -55,7 +55,6 @@ func (db *DB) Migrate() error {
&Tag{},
&Category{},
&Ads{},
&LogAds{},
&LogNews{},
&ContentLog{},
)
}

View File

@ -9,8 +9,8 @@ func (a *accessor) GetAll() ([]adsdomain.AdsResponse, error) {
var ads []adsdomain.AdsResponse
if err := a.db.Table("ads").
Select("ads.*, COUNT(log_ads.content_id) as clicked").
Joins("LEFT JOIN log_ads ON log_ads.content_id = ads.id").
Select("ads.*, COUNT(content_logs.content_id) as clicked").
Joins("LEFT JOIN content_logs ON content_logs.content_id = ads.id").
Group("ads.id").
Scan(&ads).Error; err != nil {
return ads, fmt.Errorf("failed to get all ads: %v", err)

View File

@ -7,10 +7,11 @@ import (
"github.com/google/uuid"
)
func (a *accessor) CreateLogAds(spec logsdomain.LogsSpec) error {
newSpec := database.LogAds{
func (a *accessor) CreateLog(spec logsdomain.LogsSpec) error {
newSpec := database.ContentLog{
ID: uuid.NewString(),
ContentID: spec.ContentID,
Category: spec.Category,
}
if spec.UserID != nil {

View File

@ -11,7 +11,7 @@ type accessor struct {
}
type Log interface {
CreateLogAds(logsdomain.LogsSpec) error
CreateLog(logsdomain.LogsSpec) error
GetAllLogAds(string) ([]adsdomain.Ads, error)
}

View File

@ -7,7 +7,8 @@ func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, erro
query := a.db.
Preload("Tags").
Preload("Categories").
Preload("Author")
Preload("Author").
Joins("LEFT JOIN content_logs ON content_logs.content_id = news.id")
if len(filter.Category) > 0 {
query = query.Joins("JOIN news_categories nc ON nc.news_id = news.id").
@ -19,6 +20,11 @@ func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, erro
Where("nt.tag_id IN (?)", filter.Tags)
}
query.
Select("news.*, COUNT(content_logs.content_id) as clicked").
Group("news.id").
Order("news.created_at DESC")
if err := query.
Find(&news).Error; err != nil {
return nil, err

View File

@ -1,9 +1,13 @@
package newshttp
import (
logsdomain "legalgo-BE-go/internal/domain/logs"
logssvc "legalgo-BE-go/internal/services/logs"
newssvc "legalgo-BE-go/internal/services/news"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"strings"
"github.com/go-chi/chi/v5"
)
@ -11,6 +15,7 @@ import (
func GetBySlug(
router chi.Router,
newsSvc newssvc.News,
logSvc logssvc.Log,
) {
router.Get("/news/{slug}", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
@ -29,6 +34,42 @@ func GetBySlug(
return
}
var specReq logsdomain.LogsSpec
specReq.ContentID = news.ID
userDetail, _ := utils.GetTokenDetail(r)
if userDetail.ID != "" {
specReq.UserID = &userDetail.ID
}
ip := r.RemoteAddr
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
ip = strings.Split(forwarded, ",")[0]
}
if ip != "" {
specReq.IP = &ip
}
if userAgent := r.UserAgent(); userAgent != "" {
specReq.UserAgent = &userAgent
}
if err := logSvc.CreateLogNews(specReq); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, news)
})
}

View File

@ -9,10 +9,11 @@ type LogsRequest struct {
}
type LogsSpec struct {
ContentID string `json:"content_id" validate:"required"`
IP *string `json:"ip"`
UserID *string `json:"user_id"`
UserAgent *string `json:"user_agent"`
ContentID string `json:"content_id" validate:"required"`
IP *string
UserID *string
UserAgent *string
Category string
}
type LogResponse struct {

View File

@ -35,6 +35,7 @@ type News struct {
LiveAt time.Time `json:"live_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Clicked int64 `json:"clicked"`
Author Staff `json:"author"`
}

View File

@ -6,7 +6,8 @@ import (
)
func (i *impl) CreateLogAds(spec logsdomain.LogsSpec) error {
if err := i.logsRepo.CreateLogAds(spec); err != nil {
spec.Category = "ads"
if err := i.logsRepo.CreateLog(spec); err != nil {
return fmt.Errorf("failed to create ads log: %v", err)
}

View File

@ -0,0 +1,15 @@
package logssvc
import (
"fmt"
logsdomain "legalgo-BE-go/internal/domain/logs"
)
func (i *impl) CreateLogNews(spec logsdomain.LogsSpec) error {
spec.Category = "news"
if err := i.logsRepo.CreateLog(spec); err != nil {
return fmt.Errorf("failed to create news log: %v", err)
}
return nil
}

View File

@ -12,6 +12,7 @@ type impl struct {
type Log interface {
CreateLogAds(logsdomain.LogsSpec) error
CreateLogNews(logsdomain.LogsSpec) error
GetAllLogAds(string) ([]adsdomain.Ads, error)
}