first commit
This commit is contained in:
248
backend/internal/calendar/custom_dates.go
Normal file
248
backend/internal/calendar/custom_dates.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package calendar
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
var ErrCustomDateNotFound = errors.New("custom date not found")
|
||||
|
||||
type CustomDate struct {
|
||||
ID string `json:"id"`
|
||||
ClientID *string `json:"client_id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Date string `json:"date"`
|
||||
RecursAnnually bool `json:"recurs_annually"`
|
||||
Visibility string `json:"visibility"`
|
||||
Category string `json:"category"`
|
||||
CreatedBy *string `json:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (s Store) ListCustomDatesByYear(ctx context.Context, year int, clientID string, viewerUserID string) ([]CustomDate, error) {
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT
|
||||
id::text,
|
||||
client_id::text,
|
||||
name,
|
||||
description,
|
||||
CASE
|
||||
WHEN recurs_annually THEN make_date(
|
||||
$1,
|
||||
EXTRACT(MONTH FROM date)::int,
|
||||
LEAST(
|
||||
EXTRACT(DAY FROM date)::int,
|
||||
EXTRACT(DAY FROM (date_trunc('month', make_date($1, EXTRACT(MONTH FROM date)::int, 1)) + interval '1 month - 1 day'))::int
|
||||
)
|
||||
)::text
|
||||
ELSE date::text
|
||||
END,
|
||||
recurs_annually,
|
||||
visibility,
|
||||
category,
|
||||
created_by::text,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM commemorative_dates
|
||||
WHERE (
|
||||
(date >= make_date($1, 1, 1) AND date < make_date($1 + 1, 1, 1))
|
||||
OR (recurs_annually AND date < make_date($1 + 1, 1, 1))
|
||||
)
|
||||
AND ($2 = '' OR client_id IS NULL OR client_id::text = $2)
|
||||
AND (
|
||||
$3 = ''
|
||||
OR (
|
||||
visibility = 'client'
|
||||
AND (
|
||||
client_id IS NULL
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM client_users
|
||||
WHERE client_users.client_id = commemorative_dates.client_id
|
||||
AND client_users.user_id = $3::uuid
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
ORDER BY date ASC, name ASC
|
||||
`, year, clientID, viewerUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
dates := []CustomDate{}
|
||||
for rows.Next() {
|
||||
date, err := scanCustomDate(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dates = append(dates, date)
|
||||
}
|
||||
|
||||
return dates, rows.Err()
|
||||
}
|
||||
|
||||
func (s Store) CreateCustomDate(ctx context.Context, input CreateCustomDateInput) (CustomDate, error) {
|
||||
row := s.db.QueryRow(ctx, `
|
||||
INSERT INTO commemorative_dates (
|
||||
client_id,
|
||||
name,
|
||||
description,
|
||||
date,
|
||||
recurs_annually,
|
||||
visibility,
|
||||
category,
|
||||
created_by
|
||||
)
|
||||
VALUES (NULLIF($1, '')::uuid, $2, $3, $4, $5, $6, $7, NULLIF($8, '')::uuid)
|
||||
RETURNING
|
||||
id::text,
|
||||
client_id::text,
|
||||
name,
|
||||
description,
|
||||
date::text,
|
||||
recurs_annually,
|
||||
visibility,
|
||||
category,
|
||||
created_by::text,
|
||||
created_at,
|
||||
updated_at
|
||||
`,
|
||||
input.ClientID,
|
||||
input.Name,
|
||||
input.Description,
|
||||
input.Date,
|
||||
input.RecursAnnually,
|
||||
input.Visibility,
|
||||
input.Category,
|
||||
input.CreatedBy,
|
||||
)
|
||||
|
||||
return scanCustomDate(row)
|
||||
}
|
||||
|
||||
type UpdateCustomDateInput struct {
|
||||
ID string
|
||||
ClientID string
|
||||
Name string
|
||||
Description string
|
||||
Date string
|
||||
RecursAnnually bool
|
||||
Visibility string
|
||||
}
|
||||
|
||||
func (s Store) UpdateCustomDate(ctx context.Context, input UpdateCustomDateInput) (CustomDate, error) {
|
||||
row := s.db.QueryRow(ctx, `
|
||||
UPDATE commemorative_dates
|
||||
SET
|
||||
client_id = NULLIF($2, '')::uuid,
|
||||
name = $3,
|
||||
description = $4,
|
||||
date = $5::date,
|
||||
recurs_annually = $6,
|
||||
visibility = $7,
|
||||
updated_at = now()
|
||||
WHERE id = $1::uuid
|
||||
AND category != 'feriados-brasil'
|
||||
RETURNING
|
||||
id::text,
|
||||
client_id::text,
|
||||
name,
|
||||
description,
|
||||
date::text,
|
||||
recurs_annually,
|
||||
visibility,
|
||||
category,
|
||||
created_by::text,
|
||||
created_at,
|
||||
updated_at
|
||||
`, input.ID, input.ClientID, input.Name, input.Description, input.Date, input.RecursAnnually, input.Visibility)
|
||||
|
||||
return scanCustomDate(row)
|
||||
}
|
||||
|
||||
func (s Store) DeleteCustomDate(ctx context.Context, id string) error {
|
||||
command, err := s.db.Exec(ctx, `
|
||||
DELETE FROM commemorative_dates
|
||||
WHERE id = $1::uuid
|
||||
AND category != 'feriados-brasil'
|
||||
`, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if command.RowsAffected() == 0 {
|
||||
return ErrCustomDateNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Store) UpsertExternalCommemorativeDates(ctx context.Context, dates []ExternalCommemorativeDate) error {
|
||||
for _, date := range dates {
|
||||
if date.Name == "" || date.Date == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := s.db.Exec(ctx, `
|
||||
INSERT INTO commemorative_dates (
|
||||
client_id,
|
||||
name,
|
||||
description,
|
||||
date,
|
||||
recurs_annually,
|
||||
visibility,
|
||||
category
|
||||
)
|
||||
VALUES (NULL, $1, $2, $3::date, false, 'client', 'feriados-brasil')
|
||||
ON CONFLICT DO NOTHING
|
||||
`, date.Name, date.Description, date.Date); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateCustomDateInput struct {
|
||||
ClientID string
|
||||
Name string
|
||||
Description string
|
||||
Date string
|
||||
RecursAnnually bool
|
||||
Visibility string
|
||||
Category string
|
||||
CreatedBy string
|
||||
}
|
||||
|
||||
type customDateScanner interface {
|
||||
Scan(dest ...any) error
|
||||
}
|
||||
|
||||
func scanCustomDate(row customDateScanner) (CustomDate, error) {
|
||||
var date CustomDate
|
||||
err := row.Scan(
|
||||
&date.ID,
|
||||
&date.ClientID,
|
||||
&date.Name,
|
||||
&date.Description,
|
||||
&date.Date,
|
||||
&date.RecursAnnually,
|
||||
&date.Visibility,
|
||||
&date.Category,
|
||||
&date.CreatedBy,
|
||||
&date.CreatedAt,
|
||||
&date.UpdatedAt,
|
||||
)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return CustomDate{}, ErrCustomDateNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return CustomDate{}, err
|
||||
}
|
||||
return date, nil
|
||||
}
|
||||
Reference in New Issue
Block a user