Compare commits
4 Commits
290d7f6701
...
24f0fe6efa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24f0fe6efa | ||
|
|
8d7500610e | ||
|
|
0c8133c802 | ||
|
|
d8f6968f64 |
@ -2,12 +2,13 @@ package database
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type LogAds struct {
|
type ContentLog struct {
|
||||||
ID string `gorm:"primaryKey;not null" json:"id"`
|
ID string `gorm:"primaryKey;not null" json:"id"`
|
||||||
ContentID string `gorm:"not null" json:"content_id"`
|
ContentID string `gorm:"not null" json:"content_id"`
|
||||||
UserID string `gorm:"default:null" json:"user_id"`
|
UserID string `gorm:"default:null" json:"user_id"`
|
||||||
IP string `gorm:"default:null" json:"ip"`
|
IP string `gorm:"default:null" json:"ip"`
|
||||||
UserAgent string `gorm:"default:null" json:"user_agent"`
|
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"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||||
}
|
}
|
||||||
@ -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"`
|
|
||||||
}
|
|
||||||
@ -55,7 +55,6 @@ func (db *DB) Migrate() error {
|
|||||||
&Tag{},
|
&Tag{},
|
||||||
&Category{},
|
&Category{},
|
||||||
&Ads{},
|
&Ads{},
|
||||||
&LogAds{},
|
&ContentLog{},
|
||||||
&LogNews{},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@ func (a *accessor) GetAll() ([]adsdomain.AdsResponse, error) {
|
|||||||
var ads []adsdomain.AdsResponse
|
var ads []adsdomain.AdsResponse
|
||||||
|
|
||||||
if err := a.db.Table("ads").
|
if err := a.db.Table("ads").
|
||||||
Select("ads.*, COUNT(log_ads.content_id) as clicked").
|
Select("ads.*, COUNT(content_logs.content_id) as clicked").
|
||||||
Joins("LEFT JOIN log_ads ON log_ads.content_id = ads.id").
|
Joins("LEFT JOIN content_logs ON content_logs.content_id = ads.id").
|
||||||
Group("ads.id").
|
Group("ads.id").
|
||||||
Scan(&ads).Error; err != nil {
|
Scan(&ads).Error; err != nil {
|
||||||
return ads, fmt.Errorf("failed to get all ads: %v", err)
|
return ads, fmt.Errorf("failed to get all ads: %v", err)
|
||||||
|
|||||||
@ -7,10 +7,11 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *accessor) CreateLogAds(spec logsdomain.LogsSpec) error {
|
func (a *accessor) CreateLog(spec logsdomain.LogsSpec) error {
|
||||||
newSpec := database.LogAds{
|
newSpec := database.ContentLog{
|
||||||
ID: uuid.NewString(),
|
ID: uuid.NewString(),
|
||||||
ContentID: spec.ContentID,
|
ContentID: spec.ContentID,
|
||||||
|
Category: spec.Category,
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.UserID != nil {
|
if spec.UserID != nil {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ type accessor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Log interface {
|
type Log interface {
|
||||||
CreateLogAds(logsdomain.LogsSpec) error
|
CreateLog(logsdomain.LogsSpec) error
|
||||||
GetAllLogAds(string) ([]adsdomain.Ads, error)
|
GetAllLogAds(string) ([]adsdomain.Ads, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,24 @@
|
|||||||
package newsrepository
|
package newsrepository
|
||||||
|
|
||||||
import newsdomain "legalgo-BE-go/internal/domain/news"
|
import (
|
||||||
|
newsdomain "legalgo-BE-go/internal/domain/news"
|
||||||
|
timeutils "legalgo-BE-go/internal/utilities/time_utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type is_active string
|
||||||
|
|
||||||
|
const (
|
||||||
|
active is_active = "true"
|
||||||
|
notActive is_active = "false"
|
||||||
|
)
|
||||||
|
|
||||||
func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, error) {
|
func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, error) {
|
||||||
var news []newsdomain.News
|
var news []newsdomain.News
|
||||||
query := a.db.
|
query := a.db.
|
||||||
Preload("Tags").
|
Preload("Tags").
|
||||||
Preload("Categories").
|
Preload("Categories").
|
||||||
Preload("Author")
|
Preload("Author").
|
||||||
|
Joins("LEFT JOIN content_logs ON content_logs.content_id = news.id")
|
||||||
|
|
||||||
if len(filter.Category) > 0 {
|
if len(filter.Category) > 0 {
|
||||||
query = query.Joins("JOIN news_categories nc ON nc.news_id = news.id").
|
query = query.Joins("JOIN news_categories nc ON nc.news_id = news.id").
|
||||||
@ -19,6 +30,15 @@ func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, erro
|
|||||||
Where("nt.tag_id IN (?)", filter.Tags)
|
Where("nt.tag_id IN (?)", filter.Tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if filter.Active == string(active) {
|
||||||
|
query = query.Where("news.live_at <= ?", timeutils.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
query.
|
||||||
|
Select("news.*, COUNT(content_logs.content_id) as clicked").
|
||||||
|
Group("news.id").
|
||||||
|
Order("news.created_at DESC")
|
||||||
|
|
||||||
if err := query.
|
if err := query.
|
||||||
Find(&news).Error; err != nil {
|
Find(&news).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import (
|
|||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
"legalgo-BE-go/internal/utilities/utils"
|
"legalgo-BE-go/internal/utilities/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
@ -58,17 +57,11 @@ func CreateLogAds(
|
|||||||
specReq.UserID = &userDetail.ID
|
specReq.UserID = &userDetail.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := r.RemoteAddr
|
if ip := r.Header.Get("X-Ip-Address"); ip != "" {
|
||||||
|
|
||||||
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
|
|
||||||
ip = strings.Split(forwarded, ",")[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip != "" {
|
|
||||||
specReq.IP = &ip
|
specReq.IP = &ip
|
||||||
}
|
}
|
||||||
|
|
||||||
if userAgent := r.UserAgent(); userAgent != "" {
|
if userAgent := r.Header.Get("X-User-Agent"); userAgent != "" {
|
||||||
specReq.UserAgent = &userAgent
|
specReq.UserAgent = &userAgent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,8 +23,13 @@ func GetAll(
|
|||||||
|
|
||||||
category := query.Get("categories")
|
category := query.Get("categories")
|
||||||
tags := query.Get("tags")
|
tags := query.Get("tags")
|
||||||
|
activeOnly := query.Get("active")
|
||||||
|
|
||||||
news, err = newsSvc.GetAll(category, tags)
|
news, err = newsSvc.GetAll(newsdomain.Filter{
|
||||||
|
Category: category,
|
||||||
|
Tags: tags,
|
||||||
|
Active: activeOnly,
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
package newshttp
|
package newshttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
logsdomain "legalgo-BE-go/internal/domain/logs"
|
||||||
|
logssvc "legalgo-BE-go/internal/services/logs"
|
||||||
newssvc "legalgo-BE-go/internal/services/news"
|
newssvc "legalgo-BE-go/internal/services/news"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
|
"legalgo-BE-go/internal/utilities/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
@ -11,6 +14,7 @@ import (
|
|||||||
func GetBySlug(
|
func GetBySlug(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
newsSvc newssvc.News,
|
newsSvc newssvc.News,
|
||||||
|
logSvc logssvc.Log,
|
||||||
) {
|
) {
|
||||||
router.Get("/news/{slug}", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/news/{slug}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@ -29,6 +33,38 @@ func GetBySlug(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userDetail, _ := utils.GetTokenDetail(r)
|
||||||
|
|
||||||
|
if userDetail.Role != "staff" {
|
||||||
|
var specReq logsdomain.LogsSpec
|
||||||
|
|
||||||
|
specReq.ContentID = news.ID
|
||||||
|
|
||||||
|
if userDetail.ID != "" {
|
||||||
|
specReq.UserID = &userDetail.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip := r.Header.Get("X-Ip-Address"); ip != "" {
|
||||||
|
specReq.IP = &ip
|
||||||
|
}
|
||||||
|
|
||||||
|
if userAgent := r.Header.Get("X-User-Agent"); 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)
|
response.RespondJsonSuccess(ctx, w, news)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,11 @@ type LogsRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LogsSpec struct {
|
type LogsSpec struct {
|
||||||
ContentID string `json:"content_id" validate:"required"`
|
ContentID string `json:"content_id" validate:"required"`
|
||||||
IP *string `json:"ip"`
|
IP *string
|
||||||
UserID *string `json:"user_id"`
|
UserID *string
|
||||||
UserAgent *string `json:"user_agent"`
|
UserAgent *string
|
||||||
|
Category string
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogResponse struct {
|
type LogResponse struct {
|
||||||
|
|||||||
@ -35,6 +35,7 @@ type News struct {
|
|||||||
LiveAt time.Time `json:"live_at"`
|
LiveAt time.Time `json:"live_at"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
Clicked int64 `json:"clicked"`
|
||||||
|
|
||||||
Author Staff `json:"author"`
|
Author Staff `json:"author"`
|
||||||
}
|
}
|
||||||
@ -50,7 +51,12 @@ type NewsUpdate struct {
|
|||||||
LiveAt time.Time `json:"live_at"`
|
LiveAt time.Time `json:"live_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Filter struct {
|
||||||
|
Category, Tags, Active string
|
||||||
|
}
|
||||||
|
|
||||||
type NewsFilter struct {
|
type NewsFilter struct {
|
||||||
Tags []string
|
Tags []string
|
||||||
Category []string
|
Category []string
|
||||||
|
Active string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (i *impl) CreateLogAds(spec logsdomain.LogsSpec) error {
|
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)
|
return fmt.Errorf("failed to create ads log: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
internal/services/logs/create_logs_news.go
Normal file
15
internal/services/logs/create_logs_news.go
Normal 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
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ type impl struct {
|
|||||||
|
|
||||||
type Log interface {
|
type Log interface {
|
||||||
CreateLogAds(logsdomain.LogsSpec) error
|
CreateLogAds(logsdomain.LogsSpec) error
|
||||||
|
CreateLogNews(logsdomain.LogsSpec) error
|
||||||
GetAllLogAds(string) ([]adsdomain.Ads, error)
|
GetAllLogAds(string) ([]adsdomain.Ads, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,15 +5,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i *impl) GetAll(categoriesCode, tagCodes string) ([]newsdomain.News, error) {
|
func (i *impl) GetAll(filter newsdomain.Filter) ([]newsdomain.News, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
categories := []string{}
|
categories := []string{}
|
||||||
tags := []string{}
|
tags := []string{}
|
||||||
news := []newsdomain.News{}
|
news := []newsdomain.News{}
|
||||||
|
|
||||||
tagCodeArr := strings.Split(tagCodes, " ")
|
tagCodeArr := strings.Split(filter.Tags, " ")
|
||||||
categoryCodeArr := strings.Split(categoriesCode, " ")
|
categoryCodeArr := strings.Split(filter.Category, " ")
|
||||||
|
|
||||||
if len(tagCodeArr) > 0 && tagCodeArr[0] != "" {
|
if len(tagCodeArr) > 0 && tagCodeArr[0] != "" {
|
||||||
tags, err = i.tagRepo.GetIDsByCodes(tagCodeArr)
|
tags, err = i.tagRepo.GetIDsByCodes(tagCodeArr)
|
||||||
@ -37,9 +37,10 @@ func (i *impl) GetAll(categoriesCode, tagCodes string) ([]newsdomain.News, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := newsdomain.NewsFilter{
|
filterSpec := newsdomain.NewsFilter{
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
Category: categories,
|
Category: categories,
|
||||||
|
Active: filter.Active,
|
||||||
}
|
}
|
||||||
return i.newsRepo.GetAll(filter)
|
return i.newsRepo.GetAll(filterSpec)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ type impl struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type News interface {
|
type News interface {
|
||||||
GetAll(string, string) ([]newsdomain.News, error)
|
GetAll(filter newsdomain.Filter) ([]newsdomain.News, error)
|
||||||
GetBySlug(string) (*newsdomain.News, error)
|
GetBySlug(string) (*newsdomain.News, error)
|
||||||
Create(newsdomain.NewsReq, string) error
|
Create(newsdomain.NewsReq, string) error
|
||||||
Update(string, newsdomain.NewsUpdate) error
|
Update(string, newsdomain.NewsUpdate) error
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user