Unverified Commit d3062b2e authored by Wesley Liddick's avatar Wesley Liddick Committed by GitHub
Browse files

Merge pull request #434 from DuckyProject/feat/announcement-system-pr-upstream

feat(announcements): admin/user announcement system
parents b7777fb4 9bee0a20
......@@ -14,6 +14,8 @@ import (
"entgo.io/ent/dialect/sql"
"github.com/Wei-Shaw/sub2api/ent/account"
"github.com/Wei-Shaw/sub2api/ent/accountgroup"
"github.com/Wei-Shaw/sub2api/ent/announcement"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/predicate"
......@@ -29,6 +31,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/userattributedefinition"
"github.com/Wei-Shaw/sub2api/ent/userattributevalue"
"github.com/Wei-Shaw/sub2api/ent/usersubscription"
"github.com/Wei-Shaw/sub2api/internal/domain"
)
 
const (
......@@ -43,6 +46,8 @@ const (
TypeAPIKey = "APIKey"
TypeAccount = "Account"
TypeAccountGroup = "AccountGroup"
TypeAnnouncement = "Announcement"
TypeAnnouncementRead = "AnnouncementRead"
TypeGroup = "Group"
TypePromoCode = "PromoCode"
TypePromoCodeUsage = "PromoCodeUsage"
......@@ -3833,6 +3838,1671 @@ func (m *AccountGroupMutation) ResetEdge(name string) error {
return fmt.Errorf("unknown AccountGroup edge %s", name)
}
 
// AnnouncementMutation represents an operation that mutates the Announcement nodes in the graph.
type AnnouncementMutation struct {
config
op Op
typ string
id *int64
title *string
content *string
status *string
targeting *domain.AnnouncementTargeting
starts_at *time.Time
ends_at *time.Time
created_by *int64
addcreated_by *int64
updated_by *int64
addupdated_by *int64
created_at *time.Time
updated_at *time.Time
clearedFields map[string]struct{}
reads map[int64]struct{}
removedreads map[int64]struct{}
clearedreads bool
done bool
oldValue func(context.Context) (*Announcement, error)
predicates []predicate.Announcement
}
var _ ent.Mutation = (*AnnouncementMutation)(nil)
// announcementOption allows management of the mutation configuration using functional options.
type announcementOption func(*AnnouncementMutation)
// newAnnouncementMutation creates new mutation for the Announcement entity.
func newAnnouncementMutation(c config, op Op, opts ...announcementOption) *AnnouncementMutation {
m := &AnnouncementMutation{
config: c,
op: op,
typ: TypeAnnouncement,
clearedFields: make(map[string]struct{}),
}
for _, opt := range opts {
opt(m)
}
return m
}
// withAnnouncementID sets the ID field of the mutation.
func withAnnouncementID(id int64) announcementOption {
return func(m *AnnouncementMutation) {
var (
err error
once sync.Once
value *Announcement
)
m.oldValue = func(ctx context.Context) (*Announcement, error) {
once.Do(func() {
if m.done {
err = errors.New("querying old values post mutation is not allowed")
} else {
value, err = m.Client().Announcement.Get(ctx, id)
}
})
return value, err
}
m.id = &id
}
}
// withAnnouncement sets the old Announcement of the mutation.
func withAnnouncement(node *Announcement) announcementOption {
return func(m *AnnouncementMutation) {
m.oldValue = func(context.Context) (*Announcement, error) {
return node, nil
}
m.id = &node.ID
}
}
// Client returns a new `ent.Client` from the mutation. If the mutation was
// executed in a transaction (ent.Tx), a transactional client is returned.
func (m AnnouncementMutation) Client() *Client {
client := &Client{config: m.config}
client.init()
return client
}
// Tx returns an `ent.Tx` for mutations that were executed in transactions;
// it returns an error otherwise.
func (m AnnouncementMutation) Tx() (*Tx, error) {
if _, ok := m.driver.(*txDriver); !ok {
return nil, errors.New("ent: mutation is not running in a transaction")
}
tx := &Tx{config: m.config}
tx.init()
return tx, nil
}
// ID returns the ID value in the mutation. Note that the ID is only available
// if it was provided to the builder or after it was returned from the database.
func (m *AnnouncementMutation) ID() (id int64, exists bool) {
if m.id == nil {
return
}
return *m.id, true
}
// IDs queries the database and returns the entity ids that match the mutation's predicate.
// That means, if the mutation is applied within a transaction with an isolation level such
// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
// or updated by the mutation.
func (m *AnnouncementMutation) IDs(ctx context.Context) ([]int64, error) {
switch {
case m.op.Is(OpUpdateOne | OpDeleteOne):
id, exists := m.ID()
if exists {
return []int64{id}, nil
}
fallthrough
case m.op.Is(OpUpdate | OpDelete):
return m.Client().Announcement.Query().Where(m.predicates...).IDs(ctx)
default:
return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
}
}
// SetTitle sets the "title" field.
func (m *AnnouncementMutation) SetTitle(s string) {
m.title = &s
}
// Title returns the value of the "title" field in the mutation.
func (m *AnnouncementMutation) Title() (r string, exists bool) {
v := m.title
if v == nil {
return
}
return *v, true
}
// OldTitle returns the old "title" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldTitle(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldTitle is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldTitle requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldTitle: %w", err)
}
return oldValue.Title, nil
}
// ResetTitle resets all changes to the "title" field.
func (m *AnnouncementMutation) ResetTitle() {
m.title = nil
}
// SetContent sets the "content" field.
func (m *AnnouncementMutation) SetContent(s string) {
m.content = &s
}
// Content returns the value of the "content" field in the mutation.
func (m *AnnouncementMutation) Content() (r string, exists bool) {
v := m.content
if v == nil {
return
}
return *v, true
}
// OldContent returns the old "content" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldContent(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldContent is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldContent requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldContent: %w", err)
}
return oldValue.Content, nil
}
// ResetContent resets all changes to the "content" field.
func (m *AnnouncementMutation) ResetContent() {
m.content = nil
}
// SetStatus sets the "status" field.
func (m *AnnouncementMutation) SetStatus(s string) {
m.status = &s
}
// Status returns the value of the "status" field in the mutation.
func (m *AnnouncementMutation) Status() (r string, exists bool) {
v := m.status
if v == nil {
return
}
return *v, true
}
// OldStatus returns the old "status" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldStatus(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldStatus is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldStatus requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldStatus: %w", err)
}
return oldValue.Status, nil
}
// ResetStatus resets all changes to the "status" field.
func (m *AnnouncementMutation) ResetStatus() {
m.status = nil
}
// SetTargeting sets the "targeting" field.
func (m *AnnouncementMutation) SetTargeting(dt domain.AnnouncementTargeting) {
m.targeting = &dt
}
// Targeting returns the value of the "targeting" field in the mutation.
func (m *AnnouncementMutation) Targeting() (r domain.AnnouncementTargeting, exists bool) {
v := m.targeting
if v == nil {
return
}
return *v, true
}
// OldTargeting returns the old "targeting" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldTargeting(ctx context.Context) (v domain.AnnouncementTargeting, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldTargeting is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldTargeting requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldTargeting: %w", err)
}
return oldValue.Targeting, nil
}
// ClearTargeting clears the value of the "targeting" field.
func (m *AnnouncementMutation) ClearTargeting() {
m.targeting = nil
m.clearedFields[announcement.FieldTargeting] = struct{}{}
}
// TargetingCleared returns if the "targeting" field was cleared in this mutation.
func (m *AnnouncementMutation) TargetingCleared() bool {
_, ok := m.clearedFields[announcement.FieldTargeting]
return ok
}
// ResetTargeting resets all changes to the "targeting" field.
func (m *AnnouncementMutation) ResetTargeting() {
m.targeting = nil
delete(m.clearedFields, announcement.FieldTargeting)
}
// SetStartsAt sets the "starts_at" field.
func (m *AnnouncementMutation) SetStartsAt(t time.Time) {
m.starts_at = &t
}
// StartsAt returns the value of the "starts_at" field in the mutation.
func (m *AnnouncementMutation) StartsAt() (r time.Time, exists bool) {
v := m.starts_at
if v == nil {
return
}
return *v, true
}
// OldStartsAt returns the old "starts_at" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldStartsAt(ctx context.Context) (v *time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldStartsAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldStartsAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldStartsAt: %w", err)
}
return oldValue.StartsAt, nil
}
// ClearStartsAt clears the value of the "starts_at" field.
func (m *AnnouncementMutation) ClearStartsAt() {
m.starts_at = nil
m.clearedFields[announcement.FieldStartsAt] = struct{}{}
}
// StartsAtCleared returns if the "starts_at" field was cleared in this mutation.
func (m *AnnouncementMutation) StartsAtCleared() bool {
_, ok := m.clearedFields[announcement.FieldStartsAt]
return ok
}
// ResetStartsAt resets all changes to the "starts_at" field.
func (m *AnnouncementMutation) ResetStartsAt() {
m.starts_at = nil
delete(m.clearedFields, announcement.FieldStartsAt)
}
// SetEndsAt sets the "ends_at" field.
func (m *AnnouncementMutation) SetEndsAt(t time.Time) {
m.ends_at = &t
}
// EndsAt returns the value of the "ends_at" field in the mutation.
func (m *AnnouncementMutation) EndsAt() (r time.Time, exists bool) {
v := m.ends_at
if v == nil {
return
}
return *v, true
}
// OldEndsAt returns the old "ends_at" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldEndsAt(ctx context.Context) (v *time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldEndsAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldEndsAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldEndsAt: %w", err)
}
return oldValue.EndsAt, nil
}
// ClearEndsAt clears the value of the "ends_at" field.
func (m *AnnouncementMutation) ClearEndsAt() {
m.ends_at = nil
m.clearedFields[announcement.FieldEndsAt] = struct{}{}
}
// EndsAtCleared returns if the "ends_at" field was cleared in this mutation.
func (m *AnnouncementMutation) EndsAtCleared() bool {
_, ok := m.clearedFields[announcement.FieldEndsAt]
return ok
}
// ResetEndsAt resets all changes to the "ends_at" field.
func (m *AnnouncementMutation) ResetEndsAt() {
m.ends_at = nil
delete(m.clearedFields, announcement.FieldEndsAt)
}
// SetCreatedBy sets the "created_by" field.
func (m *AnnouncementMutation) SetCreatedBy(i int64) {
m.created_by = &i
m.addcreated_by = nil
}
// CreatedBy returns the value of the "created_by" field in the mutation.
func (m *AnnouncementMutation) CreatedBy() (r int64, exists bool) {
v := m.created_by
if v == nil {
return
}
return *v, true
}
// OldCreatedBy returns the old "created_by" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldCreatedBy(ctx context.Context) (v *int64, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCreatedBy is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldCreatedBy requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldCreatedBy: %w", err)
}
return oldValue.CreatedBy, nil
}
// AddCreatedBy adds i to the "created_by" field.
func (m *AnnouncementMutation) AddCreatedBy(i int64) {
if m.addcreated_by != nil {
*m.addcreated_by += i
} else {
m.addcreated_by = &i
}
}
// AddedCreatedBy returns the value that was added to the "created_by" field in this mutation.
func (m *AnnouncementMutation) AddedCreatedBy() (r int64, exists bool) {
v := m.addcreated_by
if v == nil {
return
}
return *v, true
}
// ClearCreatedBy clears the value of the "created_by" field.
func (m *AnnouncementMutation) ClearCreatedBy() {
m.created_by = nil
m.addcreated_by = nil
m.clearedFields[announcement.FieldCreatedBy] = struct{}{}
}
// CreatedByCleared returns if the "created_by" field was cleared in this mutation.
func (m *AnnouncementMutation) CreatedByCleared() bool {
_, ok := m.clearedFields[announcement.FieldCreatedBy]
return ok
}
// ResetCreatedBy resets all changes to the "created_by" field.
func (m *AnnouncementMutation) ResetCreatedBy() {
m.created_by = nil
m.addcreated_by = nil
delete(m.clearedFields, announcement.FieldCreatedBy)
}
// SetUpdatedBy sets the "updated_by" field.
func (m *AnnouncementMutation) SetUpdatedBy(i int64) {
m.updated_by = &i
m.addupdated_by = nil
}
// UpdatedBy returns the value of the "updated_by" field in the mutation.
func (m *AnnouncementMutation) UpdatedBy() (r int64, exists bool) {
v := m.updated_by
if v == nil {
return
}
return *v, true
}
// OldUpdatedBy returns the old "updated_by" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldUpdatedBy(ctx context.Context) (v *int64, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldUpdatedBy is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldUpdatedBy requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldUpdatedBy: %w", err)
}
return oldValue.UpdatedBy, nil
}
// AddUpdatedBy adds i to the "updated_by" field.
func (m *AnnouncementMutation) AddUpdatedBy(i int64) {
if m.addupdated_by != nil {
*m.addupdated_by += i
} else {
m.addupdated_by = &i
}
}
// AddedUpdatedBy returns the value that was added to the "updated_by" field in this mutation.
func (m *AnnouncementMutation) AddedUpdatedBy() (r int64, exists bool) {
v := m.addupdated_by
if v == nil {
return
}
return *v, true
}
// ClearUpdatedBy clears the value of the "updated_by" field.
func (m *AnnouncementMutation) ClearUpdatedBy() {
m.updated_by = nil
m.addupdated_by = nil
m.clearedFields[announcement.FieldUpdatedBy] = struct{}{}
}
// UpdatedByCleared returns if the "updated_by" field was cleared in this mutation.
func (m *AnnouncementMutation) UpdatedByCleared() bool {
_, ok := m.clearedFields[announcement.FieldUpdatedBy]
return ok
}
// ResetUpdatedBy resets all changes to the "updated_by" field.
func (m *AnnouncementMutation) ResetUpdatedBy() {
m.updated_by = nil
m.addupdated_by = nil
delete(m.clearedFields, announcement.FieldUpdatedBy)
}
// SetCreatedAt sets the "created_at" field.
func (m *AnnouncementMutation) SetCreatedAt(t time.Time) {
m.created_at = &t
}
// CreatedAt returns the value of the "created_at" field in the mutation.
func (m *AnnouncementMutation) CreatedAt() (r time.Time, exists bool) {
v := m.created_at
if v == nil {
return
}
return *v, true
}
// OldCreatedAt returns the old "created_at" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldCreatedAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
}
return oldValue.CreatedAt, nil
}
// ResetCreatedAt resets all changes to the "created_at" field.
func (m *AnnouncementMutation) ResetCreatedAt() {
m.created_at = nil
}
// SetUpdatedAt sets the "updated_at" field.
func (m *AnnouncementMutation) SetUpdatedAt(t time.Time) {
m.updated_at = &t
}
// UpdatedAt returns the value of the "updated_at" field in the mutation.
func (m *AnnouncementMutation) UpdatedAt() (r time.Time, exists bool) {
v := m.updated_at
if v == nil {
return
}
return *v, true
}
// OldUpdatedAt returns the old "updated_at" field's value of the Announcement entity.
// If the Announcement object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldUpdatedAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err)
}
return oldValue.UpdatedAt, nil
}
// ResetUpdatedAt resets all changes to the "updated_at" field.
func (m *AnnouncementMutation) ResetUpdatedAt() {
m.updated_at = nil
}
// AddReadIDs adds the "reads" edge to the AnnouncementRead entity by ids.
func (m *AnnouncementMutation) AddReadIDs(ids ...int64) {
if m.reads == nil {
m.reads = make(map[int64]struct{})
}
for i := range ids {
m.reads[ids[i]] = struct{}{}
}
}
// ClearReads clears the "reads" edge to the AnnouncementRead entity.
func (m *AnnouncementMutation) ClearReads() {
m.clearedreads = true
}
// ReadsCleared reports if the "reads" edge to the AnnouncementRead entity was cleared.
func (m *AnnouncementMutation) ReadsCleared() bool {
return m.clearedreads
}
// RemoveReadIDs removes the "reads" edge to the AnnouncementRead entity by IDs.
func (m *AnnouncementMutation) RemoveReadIDs(ids ...int64) {
if m.removedreads == nil {
m.removedreads = make(map[int64]struct{})
}
for i := range ids {
delete(m.reads, ids[i])
m.removedreads[ids[i]] = struct{}{}
}
}
// RemovedReads returns the removed IDs of the "reads" edge to the AnnouncementRead entity.
func (m *AnnouncementMutation) RemovedReadsIDs() (ids []int64) {
for id := range m.removedreads {
ids = append(ids, id)
}
return
}
// ReadsIDs returns the "reads" edge IDs in the mutation.
func (m *AnnouncementMutation) ReadsIDs() (ids []int64) {
for id := range m.reads {
ids = append(ids, id)
}
return
}
// ResetReads resets all changes to the "reads" edge.
func (m *AnnouncementMutation) ResetReads() {
m.reads = nil
m.clearedreads = false
m.removedreads = nil
}
// Where appends a list predicates to the AnnouncementMutation builder.
func (m *AnnouncementMutation) Where(ps ...predicate.Announcement) {
m.predicates = append(m.predicates, ps...)
}
// WhereP appends storage-level predicates to the AnnouncementMutation builder. Using this method,
// users can use type-assertion to append predicates that do not depend on any generated package.
func (m *AnnouncementMutation) WhereP(ps ...func(*sql.Selector)) {
p := make([]predicate.Announcement, len(ps))
for i := range ps {
p[i] = ps[i]
}
m.Where(p...)
}
// Op returns the operation name.
func (m *AnnouncementMutation) Op() Op {
return m.op
}
// SetOp allows setting the mutation operation.
func (m *AnnouncementMutation) SetOp(op Op) {
m.op = op
}
// Type returns the node type of this mutation (Announcement).
func (m *AnnouncementMutation) Type() string {
return m.typ
}
// Fields returns all fields that were changed during this mutation. Note that in
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *AnnouncementMutation) Fields() []string {
fields := make([]string, 0, 10)
if m.title != nil {
fields = append(fields, announcement.FieldTitle)
}
if m.content != nil {
fields = append(fields, announcement.FieldContent)
}
if m.status != nil {
fields = append(fields, announcement.FieldStatus)
}
if m.targeting != nil {
fields = append(fields, announcement.FieldTargeting)
}
if m.starts_at != nil {
fields = append(fields, announcement.FieldStartsAt)
}
if m.ends_at != nil {
fields = append(fields, announcement.FieldEndsAt)
}
if m.created_by != nil {
fields = append(fields, announcement.FieldCreatedBy)
}
if m.updated_by != nil {
fields = append(fields, announcement.FieldUpdatedBy)
}
if m.created_at != nil {
fields = append(fields, announcement.FieldCreatedAt)
}
if m.updated_at != nil {
fields = append(fields, announcement.FieldUpdatedAt)
}
return fields
}
// Field returns the value of a field with the given name. The second boolean
// return value indicates that this field was not set, or was not defined in the
// schema.
func (m *AnnouncementMutation) Field(name string) (ent.Value, bool) {
switch name {
case announcement.FieldTitle:
return m.Title()
case announcement.FieldContent:
return m.Content()
case announcement.FieldStatus:
return m.Status()
case announcement.FieldTargeting:
return m.Targeting()
case announcement.FieldStartsAt:
return m.StartsAt()
case announcement.FieldEndsAt:
return m.EndsAt()
case announcement.FieldCreatedBy:
return m.CreatedBy()
case announcement.FieldUpdatedBy:
return m.UpdatedBy()
case announcement.FieldCreatedAt:
return m.CreatedAt()
case announcement.FieldUpdatedAt:
return m.UpdatedAt()
}
return nil, false
}
// OldField returns the old value of the field from the database. An error is
// returned if the mutation operation is not UpdateOne, or the query to the
// database failed.
func (m *AnnouncementMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
switch name {
case announcement.FieldTitle:
return m.OldTitle(ctx)
case announcement.FieldContent:
return m.OldContent(ctx)
case announcement.FieldStatus:
return m.OldStatus(ctx)
case announcement.FieldTargeting:
return m.OldTargeting(ctx)
case announcement.FieldStartsAt:
return m.OldStartsAt(ctx)
case announcement.FieldEndsAt:
return m.OldEndsAt(ctx)
case announcement.FieldCreatedBy:
return m.OldCreatedBy(ctx)
case announcement.FieldUpdatedBy:
return m.OldUpdatedBy(ctx)
case announcement.FieldCreatedAt:
return m.OldCreatedAt(ctx)
case announcement.FieldUpdatedAt:
return m.OldUpdatedAt(ctx)
}
return nil, fmt.Errorf("unknown Announcement field %s", name)
}
// SetField sets the value of a field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *AnnouncementMutation) SetField(name string, value ent.Value) error {
switch name {
case announcement.FieldTitle:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetTitle(v)
return nil
case announcement.FieldContent:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetContent(v)
return nil
case announcement.FieldStatus:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetStatus(v)
return nil
case announcement.FieldTargeting:
v, ok := value.(domain.AnnouncementTargeting)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetTargeting(v)
return nil
case announcement.FieldStartsAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetStartsAt(v)
return nil
case announcement.FieldEndsAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetEndsAt(v)
return nil
case announcement.FieldCreatedBy:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetCreatedBy(v)
return nil
case announcement.FieldUpdatedBy:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetUpdatedBy(v)
return nil
case announcement.FieldCreatedAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetCreatedAt(v)
return nil
case announcement.FieldUpdatedAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetUpdatedAt(v)
return nil
}
return fmt.Errorf("unknown Announcement field %s", name)
}
// AddedFields returns all numeric fields that were incremented/decremented during
// this mutation.
func (m *AnnouncementMutation) AddedFields() []string {
var fields []string
if m.addcreated_by != nil {
fields = append(fields, announcement.FieldCreatedBy)
}
if m.addupdated_by != nil {
fields = append(fields, announcement.FieldUpdatedBy)
}
return fields
}
// AddedField returns the numeric value that was incremented/decremented on a field
// with the given name. The second boolean return value indicates that this field
// was not set, or was not defined in the schema.
func (m *AnnouncementMutation) AddedField(name string) (ent.Value, bool) {
switch name {
case announcement.FieldCreatedBy:
return m.AddedCreatedBy()
case announcement.FieldUpdatedBy:
return m.AddedUpdatedBy()
}
return nil, false
}
// AddField adds the value to the field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *AnnouncementMutation) AddField(name string, value ent.Value) error {
switch name {
case announcement.FieldCreatedBy:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddCreatedBy(v)
return nil
case announcement.FieldUpdatedBy:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddUpdatedBy(v)
return nil
}
return fmt.Errorf("unknown Announcement numeric field %s", name)
}
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *AnnouncementMutation) ClearedFields() []string {
var fields []string
if m.FieldCleared(announcement.FieldTargeting) {
fields = append(fields, announcement.FieldTargeting)
}
if m.FieldCleared(announcement.FieldStartsAt) {
fields = append(fields, announcement.FieldStartsAt)
}
if m.FieldCleared(announcement.FieldEndsAt) {
fields = append(fields, announcement.FieldEndsAt)
}
if m.FieldCleared(announcement.FieldCreatedBy) {
fields = append(fields, announcement.FieldCreatedBy)
}
if m.FieldCleared(announcement.FieldUpdatedBy) {
fields = append(fields, announcement.FieldUpdatedBy)
}
return fields
}
// FieldCleared returns a boolean indicating if a field with the given name was
// cleared in this mutation.
func (m *AnnouncementMutation) FieldCleared(name string) bool {
_, ok := m.clearedFields[name]
return ok
}
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *AnnouncementMutation) ClearField(name string) error {
switch name {
case announcement.FieldTargeting:
m.ClearTargeting()
return nil
case announcement.FieldStartsAt:
m.ClearStartsAt()
return nil
case announcement.FieldEndsAt:
m.ClearEndsAt()
return nil
case announcement.FieldCreatedBy:
m.ClearCreatedBy()
return nil
case announcement.FieldUpdatedBy:
m.ClearUpdatedBy()
return nil
}
return fmt.Errorf("unknown Announcement nullable field %s", name)
}
// ResetField resets all changes in the mutation for the field with the given name.
// It returns an error if the field is not defined in the schema.
func (m *AnnouncementMutation) ResetField(name string) error {
switch name {
case announcement.FieldTitle:
m.ResetTitle()
return nil
case announcement.FieldContent:
m.ResetContent()
return nil
case announcement.FieldStatus:
m.ResetStatus()
return nil
case announcement.FieldTargeting:
m.ResetTargeting()
return nil
case announcement.FieldStartsAt:
m.ResetStartsAt()
return nil
case announcement.FieldEndsAt:
m.ResetEndsAt()
return nil
case announcement.FieldCreatedBy:
m.ResetCreatedBy()
return nil
case announcement.FieldUpdatedBy:
m.ResetUpdatedBy()
return nil
case announcement.FieldCreatedAt:
m.ResetCreatedAt()
return nil
case announcement.FieldUpdatedAt:
m.ResetUpdatedAt()
return nil
}
return fmt.Errorf("unknown Announcement field %s", name)
}
// AddedEdges returns all edge names that were set/added in this mutation.
func (m *AnnouncementMutation) AddedEdges() []string {
edges := make([]string, 0, 1)
if m.reads != nil {
edges = append(edges, announcement.EdgeReads)
}
return edges
}
// AddedIDs returns all IDs (to other nodes) that were added for the given edge
// name in this mutation.
func (m *AnnouncementMutation) AddedIDs(name string) []ent.Value {
switch name {
case announcement.EdgeReads:
ids := make([]ent.Value, 0, len(m.reads))
for id := range m.reads {
ids = append(ids, id)
}
return ids
}
return nil
}
// RemovedEdges returns all edge names that were removed in this mutation.
func (m *AnnouncementMutation) RemovedEdges() []string {
edges := make([]string, 0, 1)
if m.removedreads != nil {
edges = append(edges, announcement.EdgeReads)
}
return edges
}
// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
// the given name in this mutation.
func (m *AnnouncementMutation) RemovedIDs(name string) []ent.Value {
switch name {
case announcement.EdgeReads:
ids := make([]ent.Value, 0, len(m.removedreads))
for id := range m.removedreads {
ids = append(ids, id)
}
return ids
}
return nil
}
// ClearedEdges returns all edge names that were cleared in this mutation.
func (m *AnnouncementMutation) ClearedEdges() []string {
edges := make([]string, 0, 1)
if m.clearedreads {
edges = append(edges, announcement.EdgeReads)
}
return edges
}
// EdgeCleared returns a boolean which indicates if the edge with the given name
// was cleared in this mutation.
func (m *AnnouncementMutation) EdgeCleared(name string) bool {
switch name {
case announcement.EdgeReads:
return m.clearedreads
}
return false
}
// ClearEdge clears the value of the edge with the given name. It returns an error
// if that edge is not defined in the schema.
func (m *AnnouncementMutation) ClearEdge(name string) error {
switch name {
}
return fmt.Errorf("unknown Announcement unique edge %s", name)
}
// ResetEdge resets all changes to the edge with the given name in this mutation.
// It returns an error if the edge is not defined in the schema.
func (m *AnnouncementMutation) ResetEdge(name string) error {
switch name {
case announcement.EdgeReads:
m.ResetReads()
return nil
}
return fmt.Errorf("unknown Announcement edge %s", name)
}
// AnnouncementReadMutation represents an operation that mutates the AnnouncementRead nodes in the graph.
type AnnouncementReadMutation struct {
config
op Op
typ string
id *int64
read_at *time.Time
created_at *time.Time
clearedFields map[string]struct{}
announcement *int64
clearedannouncement bool
user *int64
cleareduser bool
done bool
oldValue func(context.Context) (*AnnouncementRead, error)
predicates []predicate.AnnouncementRead
}
var _ ent.Mutation = (*AnnouncementReadMutation)(nil)
// announcementreadOption allows management of the mutation configuration using functional options.
type announcementreadOption func(*AnnouncementReadMutation)
// newAnnouncementReadMutation creates new mutation for the AnnouncementRead entity.
func newAnnouncementReadMutation(c config, op Op, opts ...announcementreadOption) *AnnouncementReadMutation {
m := &AnnouncementReadMutation{
config: c,
op: op,
typ: TypeAnnouncementRead,
clearedFields: make(map[string]struct{}),
}
for _, opt := range opts {
opt(m)
}
return m
}
// withAnnouncementReadID sets the ID field of the mutation.
func withAnnouncementReadID(id int64) announcementreadOption {
return func(m *AnnouncementReadMutation) {
var (
err error
once sync.Once
value *AnnouncementRead
)
m.oldValue = func(ctx context.Context) (*AnnouncementRead, error) {
once.Do(func() {
if m.done {
err = errors.New("querying old values post mutation is not allowed")
} else {
value, err = m.Client().AnnouncementRead.Get(ctx, id)
}
})
return value, err
}
m.id = &id
}
}
// withAnnouncementRead sets the old AnnouncementRead of the mutation.
func withAnnouncementRead(node *AnnouncementRead) announcementreadOption {
return func(m *AnnouncementReadMutation) {
m.oldValue = func(context.Context) (*AnnouncementRead, error) {
return node, nil
}
m.id = &node.ID
}
}
// Client returns a new `ent.Client` from the mutation. If the mutation was
// executed in a transaction (ent.Tx), a transactional client is returned.
func (m AnnouncementReadMutation) Client() *Client {
client := &Client{config: m.config}
client.init()
return client
}
// Tx returns an `ent.Tx` for mutations that were executed in transactions;
// it returns an error otherwise.
func (m AnnouncementReadMutation) Tx() (*Tx, error) {
if _, ok := m.driver.(*txDriver); !ok {
return nil, errors.New("ent: mutation is not running in a transaction")
}
tx := &Tx{config: m.config}
tx.init()
return tx, nil
}
// ID returns the ID value in the mutation. Note that the ID is only available
// if it was provided to the builder or after it was returned from the database.
func (m *AnnouncementReadMutation) ID() (id int64, exists bool) {
if m.id == nil {
return
}
return *m.id, true
}
// IDs queries the database and returns the entity ids that match the mutation's predicate.
// That means, if the mutation is applied within a transaction with an isolation level such
// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
// or updated by the mutation.
func (m *AnnouncementReadMutation) IDs(ctx context.Context) ([]int64, error) {
switch {
case m.op.Is(OpUpdateOne | OpDeleteOne):
id, exists := m.ID()
if exists {
return []int64{id}, nil
}
fallthrough
case m.op.Is(OpUpdate | OpDelete):
return m.Client().AnnouncementRead.Query().Where(m.predicates...).IDs(ctx)
default:
return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
}
}
// SetAnnouncementID sets the "announcement_id" field.
func (m *AnnouncementReadMutation) SetAnnouncementID(i int64) {
m.announcement = &i
}
// AnnouncementID returns the value of the "announcement_id" field in the mutation.
func (m *AnnouncementReadMutation) AnnouncementID() (r int64, exists bool) {
v := m.announcement
if v == nil {
return
}
return *v, true
}
// OldAnnouncementID returns the old "announcement_id" field's value of the AnnouncementRead entity.
// If the AnnouncementRead object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementReadMutation) OldAnnouncementID(ctx context.Context) (v int64, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldAnnouncementID is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldAnnouncementID requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldAnnouncementID: %w", err)
}
return oldValue.AnnouncementID, nil
}
// ResetAnnouncementID resets all changes to the "announcement_id" field.
func (m *AnnouncementReadMutation) ResetAnnouncementID() {
m.announcement = nil
}
// SetUserID sets the "user_id" field.
func (m *AnnouncementReadMutation) SetUserID(i int64) {
m.user = &i
}
// UserID returns the value of the "user_id" field in the mutation.
func (m *AnnouncementReadMutation) UserID() (r int64, exists bool) {
v := m.user
if v == nil {
return
}
return *v, true
}
// OldUserID returns the old "user_id" field's value of the AnnouncementRead entity.
// If the AnnouncementRead object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementReadMutation) OldUserID(ctx context.Context) (v int64, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldUserID is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldUserID requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldUserID: %w", err)
}
return oldValue.UserID, nil
}
// ResetUserID resets all changes to the "user_id" field.
func (m *AnnouncementReadMutation) ResetUserID() {
m.user = nil
}
// SetReadAt sets the "read_at" field.
func (m *AnnouncementReadMutation) SetReadAt(t time.Time) {
m.read_at = &t
}
// ReadAt returns the value of the "read_at" field in the mutation.
func (m *AnnouncementReadMutation) ReadAt() (r time.Time, exists bool) {
v := m.read_at
if v == nil {
return
}
return *v, true
}
// OldReadAt returns the old "read_at" field's value of the AnnouncementRead entity.
// If the AnnouncementRead object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementReadMutation) OldReadAt(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldReadAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldReadAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldReadAt: %w", err)
}
return oldValue.ReadAt, nil
}
// ResetReadAt resets all changes to the "read_at" field.
func (m *AnnouncementReadMutation) ResetReadAt() {
m.read_at = nil
}
// SetCreatedAt sets the "created_at" field.
func (m *AnnouncementReadMutation) SetCreatedAt(t time.Time) {
m.created_at = &t
}
// CreatedAt returns the value of the "created_at" field in the mutation.
func (m *AnnouncementReadMutation) CreatedAt() (r time.Time, exists bool) {
v := m.created_at
if v == nil {
return
}
return *v, true
}
// OldCreatedAt returns the old "created_at" field's value of the AnnouncementRead entity.
// If the AnnouncementRead object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *AnnouncementReadMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldCreatedAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
}
return oldValue.CreatedAt, nil
}
// ResetCreatedAt resets all changes to the "created_at" field.
func (m *AnnouncementReadMutation) ResetCreatedAt() {
m.created_at = nil
}
// ClearAnnouncement clears the "announcement" edge to the Announcement entity.
func (m *AnnouncementReadMutation) ClearAnnouncement() {
m.clearedannouncement = true
m.clearedFields[announcementread.FieldAnnouncementID] = struct{}{}
}
// AnnouncementCleared reports if the "announcement" edge to the Announcement entity was cleared.
func (m *AnnouncementReadMutation) AnnouncementCleared() bool {
return m.clearedannouncement
}
// AnnouncementIDs returns the "announcement" edge IDs in the mutation.
// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
// AnnouncementID instead. It exists only for internal usage by the builders.
func (m *AnnouncementReadMutation) AnnouncementIDs() (ids []int64) {
if id := m.announcement; id != nil {
ids = append(ids, *id)
}
return
}
// ResetAnnouncement resets all changes to the "announcement" edge.
func (m *AnnouncementReadMutation) ResetAnnouncement() {
m.announcement = nil
m.clearedannouncement = false
}
// ClearUser clears the "user" edge to the User entity.
func (m *AnnouncementReadMutation) ClearUser() {
m.cleareduser = true
m.clearedFields[announcementread.FieldUserID] = struct{}{}
}
// UserCleared reports if the "user" edge to the User entity was cleared.
func (m *AnnouncementReadMutation) UserCleared() bool {
return m.cleareduser
}
// UserIDs returns the "user" edge IDs in the mutation.
// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
// UserID instead. It exists only for internal usage by the builders.
func (m *AnnouncementReadMutation) UserIDs() (ids []int64) {
if id := m.user; id != nil {
ids = append(ids, *id)
}
return
}
// ResetUser resets all changes to the "user" edge.
func (m *AnnouncementReadMutation) ResetUser() {
m.user = nil
m.cleareduser = false
}
// Where appends a list predicates to the AnnouncementReadMutation builder.
func (m *AnnouncementReadMutation) Where(ps ...predicate.AnnouncementRead) {
m.predicates = append(m.predicates, ps...)
}
// WhereP appends storage-level predicates to the AnnouncementReadMutation builder. Using this method,
// users can use type-assertion to append predicates that do not depend on any generated package.
func (m *AnnouncementReadMutation) WhereP(ps ...func(*sql.Selector)) {
p := make([]predicate.AnnouncementRead, len(ps))
for i := range ps {
p[i] = ps[i]
}
m.Where(p...)
}
// Op returns the operation name.
func (m *AnnouncementReadMutation) Op() Op {
return m.op
}
// SetOp allows setting the mutation operation.
func (m *AnnouncementReadMutation) SetOp(op Op) {
m.op = op
}
// Type returns the node type of this mutation (AnnouncementRead).
func (m *AnnouncementReadMutation) Type() string {
return m.typ
}
// Fields returns all fields that were changed during this mutation. Note that in
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *AnnouncementReadMutation) Fields() []string {
fields := make([]string, 0, 4)
if m.announcement != nil {
fields = append(fields, announcementread.FieldAnnouncementID)
}
if m.user != nil {
fields = append(fields, announcementread.FieldUserID)
}
if m.read_at != nil {
fields = append(fields, announcementread.FieldReadAt)
}
if m.created_at != nil {
fields = append(fields, announcementread.FieldCreatedAt)
}
return fields
}
// Field returns the value of a field with the given name. The second boolean
// return value indicates that this field was not set, or was not defined in the
// schema.
func (m *AnnouncementReadMutation) Field(name string) (ent.Value, bool) {
switch name {
case announcementread.FieldAnnouncementID:
return m.AnnouncementID()
case announcementread.FieldUserID:
return m.UserID()
case announcementread.FieldReadAt:
return m.ReadAt()
case announcementread.FieldCreatedAt:
return m.CreatedAt()
}
return nil, false
}
// OldField returns the old value of the field from the database. An error is
// returned if the mutation operation is not UpdateOne, or the query to the
// database failed.
func (m *AnnouncementReadMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
switch name {
case announcementread.FieldAnnouncementID:
return m.OldAnnouncementID(ctx)
case announcementread.FieldUserID:
return m.OldUserID(ctx)
case announcementread.FieldReadAt:
return m.OldReadAt(ctx)
case announcementread.FieldCreatedAt:
return m.OldCreatedAt(ctx)
}
return nil, fmt.Errorf("unknown AnnouncementRead field %s", name)
}
// SetField sets the value of a field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *AnnouncementReadMutation) SetField(name string, value ent.Value) error {
switch name {
case announcementread.FieldAnnouncementID:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetAnnouncementID(v)
return nil
case announcementread.FieldUserID:
v, ok := value.(int64)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetUserID(v)
return nil
case announcementread.FieldReadAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetReadAt(v)
return nil
case announcementread.FieldCreatedAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetCreatedAt(v)
return nil
}
return fmt.Errorf("unknown AnnouncementRead field %s", name)
}
// AddedFields returns all numeric fields that were incremented/decremented during
// this mutation.
func (m *AnnouncementReadMutation) AddedFields() []string {
var fields []string
return fields
}
// AddedField returns the numeric value that was incremented/decremented on a field
// with the given name. The second boolean return value indicates that this field
// was not set, or was not defined in the schema.
func (m *AnnouncementReadMutation) AddedField(name string) (ent.Value, bool) {
switch name {
}
return nil, false
}
// AddField adds the value to the field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *AnnouncementReadMutation) AddField(name string, value ent.Value) error {
switch name {
}
return fmt.Errorf("unknown AnnouncementRead numeric field %s", name)
}
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *AnnouncementReadMutation) ClearedFields() []string {
return nil
}
// FieldCleared returns a boolean indicating if a field with the given name was
// cleared in this mutation.
func (m *AnnouncementReadMutation) FieldCleared(name string) bool {
_, ok := m.clearedFields[name]
return ok
}
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *AnnouncementReadMutation) ClearField(name string) error {
return fmt.Errorf("unknown AnnouncementRead nullable field %s", name)
}
// ResetField resets all changes in the mutation for the field with the given name.
// It returns an error if the field is not defined in the schema.
func (m *AnnouncementReadMutation) ResetField(name string) error {
switch name {
case announcementread.FieldAnnouncementID:
m.ResetAnnouncementID()
return nil
case announcementread.FieldUserID:
m.ResetUserID()
return nil
case announcementread.FieldReadAt:
m.ResetReadAt()
return nil
case announcementread.FieldCreatedAt:
m.ResetCreatedAt()
return nil
}
return fmt.Errorf("unknown AnnouncementRead field %s", name)
}
// AddedEdges returns all edge names that were set/added in this mutation.
func (m *AnnouncementReadMutation) AddedEdges() []string {
edges := make([]string, 0, 2)
if m.announcement != nil {
edges = append(edges, announcementread.EdgeAnnouncement)
}
if m.user != nil {
edges = append(edges, announcementread.EdgeUser)
}
return edges
}
// AddedIDs returns all IDs (to other nodes) that were added for the given edge
// name in this mutation.
func (m *AnnouncementReadMutation) AddedIDs(name string) []ent.Value {
switch name {
case announcementread.EdgeAnnouncement:
if id := m.announcement; id != nil {
return []ent.Value{*id}
}
case announcementread.EdgeUser:
if id := m.user; id != nil {
return []ent.Value{*id}
}
}
return nil
}
// RemovedEdges returns all edge names that were removed in this mutation.
func (m *AnnouncementReadMutation) RemovedEdges() []string {
edges := make([]string, 0, 2)
return edges
}
// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
// the given name in this mutation.
func (m *AnnouncementReadMutation) RemovedIDs(name string) []ent.Value {
return nil
}
// ClearedEdges returns all edge names that were cleared in this mutation.
func (m *AnnouncementReadMutation) ClearedEdges() []string {
edges := make([]string, 0, 2)
if m.clearedannouncement {
edges = append(edges, announcementread.EdgeAnnouncement)
}
if m.cleareduser {
edges = append(edges, announcementread.EdgeUser)
}
return edges
}
// EdgeCleared returns a boolean which indicates if the edge with the given name
// was cleared in this mutation.
func (m *AnnouncementReadMutation) EdgeCleared(name string) bool {
switch name {
case announcementread.EdgeAnnouncement:
return m.clearedannouncement
case announcementread.EdgeUser:
return m.cleareduser
}
return false
}
// ClearEdge clears the value of the edge with the given name. It returns an error
// if that edge is not defined in the schema.
func (m *AnnouncementReadMutation) ClearEdge(name string) error {
switch name {
case announcementread.EdgeAnnouncement:
m.ClearAnnouncement()
return nil
case announcementread.EdgeUser:
m.ClearUser()
return nil
}
return fmt.Errorf("unknown AnnouncementRead unique edge %s", name)
}
// ResetEdge resets all changes to the edge with the given name in this mutation.
// It returns an error if the edge is not defined in the schema.
func (m *AnnouncementReadMutation) ResetEdge(name string) error {
switch name {
case announcementread.EdgeAnnouncement:
m.ResetAnnouncement()
return nil
case announcementread.EdgeUser:
m.ResetUser()
return nil
}
return fmt.Errorf("unknown AnnouncementRead edge %s", name)
}
// GroupMutation represents an operation that mutates the Group nodes in the graph.
type GroupMutation struct {
config
......@@ -14376,6 +16046,9 @@ type UserMutation struct {
assigned_subscriptions map[int64]struct{}
removedassigned_subscriptions map[int64]struct{}
clearedassigned_subscriptions bool
announcement_reads map[int64]struct{}
removedannouncement_reads map[int64]struct{}
clearedannouncement_reads bool
allowed_groups map[int64]struct{}
removedallowed_groups map[int64]struct{}
clearedallowed_groups bool
......@@ -15290,6 +16963,60 @@ func (m *UserMutation) ResetAssignedSubscriptions() {
m.removedassigned_subscriptions = nil
}
 
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by ids.
func (m *UserMutation) AddAnnouncementReadIDs(ids ...int64) {
if m.announcement_reads == nil {
m.announcement_reads = make(map[int64]struct{})
}
for i := range ids {
m.announcement_reads[ids[i]] = struct{}{}
}
}
// ClearAnnouncementReads clears the "announcement_reads" edge to the AnnouncementRead entity.
func (m *UserMutation) ClearAnnouncementReads() {
m.clearedannouncement_reads = true
}
// AnnouncementReadsCleared reports if the "announcement_reads" edge to the AnnouncementRead entity was cleared.
func (m *UserMutation) AnnouncementReadsCleared() bool {
return m.clearedannouncement_reads
}
// RemoveAnnouncementReadIDs removes the "announcement_reads" edge to the AnnouncementRead entity by IDs.
func (m *UserMutation) RemoveAnnouncementReadIDs(ids ...int64) {
if m.removedannouncement_reads == nil {
m.removedannouncement_reads = make(map[int64]struct{})
}
for i := range ids {
delete(m.announcement_reads, ids[i])
m.removedannouncement_reads[ids[i]] = struct{}{}
}
}
// RemovedAnnouncementReads returns the removed IDs of the "announcement_reads" edge to the AnnouncementRead entity.
func (m *UserMutation) RemovedAnnouncementReadsIDs() (ids []int64) {
for id := range m.removedannouncement_reads {
ids = append(ids, id)
}
return
}
// AnnouncementReadsIDs returns the "announcement_reads" edge IDs in the mutation.
func (m *UserMutation) AnnouncementReadsIDs() (ids []int64) {
for id := range m.announcement_reads {
ids = append(ids, id)
}
return
}
// ResetAnnouncementReads resets all changes to the "announcement_reads" edge.
func (m *UserMutation) ResetAnnouncementReads() {
m.announcement_reads = nil
m.clearedannouncement_reads = false
m.removedannouncement_reads = nil
}
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by ids.
func (m *UserMutation) AddAllowedGroupIDs(ids ...int64) {
if m.allowed_groups == nil {
......@@ -15908,7 +17635,7 @@ func (m *UserMutation) ResetField(name string) error {
 
// AddedEdges returns all edge names that were set/added in this mutation.
func (m *UserMutation) AddedEdges() []string {
edges := make([]string, 0, 8)
edges := make([]string, 0, 9)
if m.api_keys != nil {
edges = append(edges, user.EdgeAPIKeys)
}
......@@ -15921,6 +17648,9 @@ func (m *UserMutation) AddedEdges() []string {
if m.assigned_subscriptions != nil {
edges = append(edges, user.EdgeAssignedSubscriptions)
}
if m.announcement_reads != nil {
edges = append(edges, user.EdgeAnnouncementReads)
}
if m.allowed_groups != nil {
edges = append(edges, user.EdgeAllowedGroups)
}
......@@ -15964,6 +17694,12 @@ func (m *UserMutation) AddedIDs(name string) []ent.Value {
ids = append(ids, id)
}
return ids
case user.EdgeAnnouncementReads:
ids := make([]ent.Value, 0, len(m.announcement_reads))
for id := range m.announcement_reads {
ids = append(ids, id)
}
return ids
case user.EdgeAllowedGroups:
ids := make([]ent.Value, 0, len(m.allowed_groups))
for id := range m.allowed_groups {
......@@ -15994,7 +17730,7 @@ func (m *UserMutation) AddedIDs(name string) []ent.Value {
 
// RemovedEdges returns all edge names that were removed in this mutation.
func (m *UserMutation) RemovedEdges() []string {
edges := make([]string, 0, 8)
edges := make([]string, 0, 9)
if m.removedapi_keys != nil {
edges = append(edges, user.EdgeAPIKeys)
}
......@@ -16007,6 +17743,9 @@ func (m *UserMutation) RemovedEdges() []string {
if m.removedassigned_subscriptions != nil {
edges = append(edges, user.EdgeAssignedSubscriptions)
}
if m.removedannouncement_reads != nil {
edges = append(edges, user.EdgeAnnouncementReads)
}
if m.removedallowed_groups != nil {
edges = append(edges, user.EdgeAllowedGroups)
}
......@@ -16050,6 +17789,12 @@ func (m *UserMutation) RemovedIDs(name string) []ent.Value {
ids = append(ids, id)
}
return ids
case user.EdgeAnnouncementReads:
ids := make([]ent.Value, 0, len(m.removedannouncement_reads))
for id := range m.removedannouncement_reads {
ids = append(ids, id)
}
return ids
case user.EdgeAllowedGroups:
ids := make([]ent.Value, 0, len(m.removedallowed_groups))
for id := range m.removedallowed_groups {
......@@ -16080,7 +17825,7 @@ func (m *UserMutation) RemovedIDs(name string) []ent.Value {
 
// ClearedEdges returns all edge names that were cleared in this mutation.
func (m *UserMutation) ClearedEdges() []string {
edges := make([]string, 0, 8)
edges := make([]string, 0, 9)
if m.clearedapi_keys {
edges = append(edges, user.EdgeAPIKeys)
}
......@@ -16093,6 +17838,9 @@ func (m *UserMutation) ClearedEdges() []string {
if m.clearedassigned_subscriptions {
edges = append(edges, user.EdgeAssignedSubscriptions)
}
if m.clearedannouncement_reads {
edges = append(edges, user.EdgeAnnouncementReads)
}
if m.clearedallowed_groups {
edges = append(edges, user.EdgeAllowedGroups)
}
......@@ -16120,6 +17868,8 @@ func (m *UserMutation) EdgeCleared(name string) bool {
return m.clearedsubscriptions
case user.EdgeAssignedSubscriptions:
return m.clearedassigned_subscriptions
case user.EdgeAnnouncementReads:
return m.clearedannouncement_reads
case user.EdgeAllowedGroups:
return m.clearedallowed_groups
case user.EdgeUsageLogs:
......@@ -16156,6 +17906,9 @@ func (m *UserMutation) ResetEdge(name string) error {
case user.EdgeAssignedSubscriptions:
m.ResetAssignedSubscriptions()
return nil
case user.EdgeAnnouncementReads:
m.ResetAnnouncementReads()
return nil
case user.EdgeAllowedGroups:
m.ResetAllowedGroups()
return nil
......
......@@ -15,6 +15,12 @@ type Account func(*sql.Selector)
// AccountGroup is the predicate function for accountgroup builders.
type AccountGroup func(*sql.Selector)
// Announcement is the predicate function for announcement builders.
type Announcement func(*sql.Selector)
// AnnouncementRead is the predicate function for announcementread builders.
type AnnouncementRead func(*sql.Selector)
// Group is the predicate function for group builders.
type Group func(*sql.Selector)
......
......@@ -7,6 +7,8 @@ import (
"github.com/Wei-Shaw/sub2api/ent/account"
"github.com/Wei-Shaw/sub2api/ent/accountgroup"
"github.com/Wei-Shaw/sub2api/ent/announcement"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/promocode"
......@@ -210,6 +212,56 @@ func init() {
accountgroupDescCreatedAt := accountgroupFields[3].Descriptor()
// accountgroup.DefaultCreatedAt holds the default value on creation for the created_at field.
accountgroup.DefaultCreatedAt = accountgroupDescCreatedAt.Default.(func() time.Time)
announcementFields := schema.Announcement{}.Fields()
_ = announcementFields
// announcementDescTitle is the schema descriptor for title field.
announcementDescTitle := announcementFields[0].Descriptor()
// announcement.TitleValidator is a validator for the "title" field. It is called by the builders before save.
announcement.TitleValidator = func() func(string) error {
validators := announcementDescTitle.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(title string) error {
for _, fn := range fns {
if err := fn(title); err != nil {
return err
}
}
return nil
}
}()
// announcementDescContent is the schema descriptor for content field.
announcementDescContent := announcementFields[1].Descriptor()
// announcement.ContentValidator is a validator for the "content" field. It is called by the builders before save.
announcement.ContentValidator = announcementDescContent.Validators[0].(func(string) error)
// announcementDescStatus is the schema descriptor for status field.
announcementDescStatus := announcementFields[2].Descriptor()
// announcement.DefaultStatus holds the default value on creation for the status field.
announcement.DefaultStatus = announcementDescStatus.Default.(string)
// announcement.StatusValidator is a validator for the "status" field. It is called by the builders before save.
announcement.StatusValidator = announcementDescStatus.Validators[0].(func(string) error)
// announcementDescCreatedAt is the schema descriptor for created_at field.
announcementDescCreatedAt := announcementFields[8].Descriptor()
// announcement.DefaultCreatedAt holds the default value on creation for the created_at field.
announcement.DefaultCreatedAt = announcementDescCreatedAt.Default.(func() time.Time)
// announcementDescUpdatedAt is the schema descriptor for updated_at field.
announcementDescUpdatedAt := announcementFields[9].Descriptor()
// announcement.DefaultUpdatedAt holds the default value on creation for the updated_at field.
announcement.DefaultUpdatedAt = announcementDescUpdatedAt.Default.(func() time.Time)
// announcement.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
announcement.UpdateDefaultUpdatedAt = announcementDescUpdatedAt.UpdateDefault.(func() time.Time)
announcementreadFields := schema.AnnouncementRead{}.Fields()
_ = announcementreadFields
// announcementreadDescReadAt is the schema descriptor for read_at field.
announcementreadDescReadAt := announcementreadFields[2].Descriptor()
// announcementread.DefaultReadAt holds the default value on creation for the read_at field.
announcementread.DefaultReadAt = announcementreadDescReadAt.Default.(func() time.Time)
// announcementreadDescCreatedAt is the schema descriptor for created_at field.
announcementreadDescCreatedAt := announcementreadFields[3].Descriptor()
// announcementread.DefaultCreatedAt holds the default value on creation for the created_at field.
announcementread.DefaultCreatedAt = announcementreadDescCreatedAt.Default.(func() time.Time)
groupMixin := schema.Group{}.Mixin()
groupMixinHooks1 := groupMixin[1].Hooks()
group.Hooks[0] = groupMixinHooks1[0]
......
......@@ -4,7 +4,7 @@ package schema
import (
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
......@@ -111,7 +111,7 @@ func (Account) Fields() []ent.Field {
// status: 账户状态,如 "active", "error", "disabled"
field.String("status").
MaxLen(20).
Default(service.StatusActive),
Default(domain.StatusActive),
// error_message: 错误信息,记录账户异常时的详细信息
field.String("error_message").
......
package schema
import (
"time"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// Announcement holds the schema definition for the Announcement entity.
//
// 删除策略:硬删除(已读记录通过外键级联删除)
type Announcement struct {
ent.Schema
}
func (Announcement) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "announcements"},
}
}
func (Announcement) Fields() []ent.Field {
return []ent.Field{
field.String("title").
MaxLen(200).
NotEmpty().
Comment("公告标题"),
field.String("content").
SchemaType(map[string]string{dialect.Postgres: "text"}).
NotEmpty().
Comment("公告内容(支持 Markdown)"),
field.String("status").
MaxLen(20).
Default(domain.AnnouncementStatusDraft).
Comment("状态: draft, active, archived"),
field.JSON("targeting", domain.AnnouncementTargeting{}).
Optional().
SchemaType(map[string]string{dialect.Postgres: "jsonb"}).
Comment("展示条件(JSON 规则)"),
field.Time("starts_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}).
Comment("开始展示时间(为空表示立即生效)"),
field.Time("ends_at").
Optional().
Nillable().
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}).
Comment("结束展示时间(为空表示永久生效)"),
field.Int64("created_by").
Optional().
Nillable().
Comment("创建人用户ID(管理员)"),
field.Int64("updated_by").
Optional().
Nillable().
Comment("更新人用户ID(管理员)"),
field.Time("created_at").
Immutable().
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
}
}
func (Announcement) Edges() []ent.Edge {
return []ent.Edge{
edge.To("reads", AnnouncementRead.Type),
}
}
func (Announcement) Indexes() []ent.Index {
return []ent.Index{
index.Fields("status"),
index.Fields("created_at"),
index.Fields("starts_at"),
index.Fields("ends_at"),
}
}
package schema
import (
"time"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// AnnouncementRead holds the schema definition for the AnnouncementRead entity.
//
// 记录用户对公告的已读状态(首次已读时间)。
type AnnouncementRead struct {
ent.Schema
}
func (AnnouncementRead) Annotations() []schema.Annotation {
return []schema.Annotation{
entsql.Annotation{Table: "announcement_reads"},
}
}
func (AnnouncementRead) Fields() []ent.Field {
return []ent.Field{
field.Int64("announcement_id"),
field.Int64("user_id"),
field.Time("read_at").
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}).
Comment("用户首次已读时间"),
field.Time("created_at").
Immutable().
Default(time.Now).
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
}
}
func (AnnouncementRead) Edges() []ent.Edge {
return []ent.Edge{
edge.From("announcement", Announcement.Type).
Ref("reads").
Field("announcement_id").
Unique().
Required(),
edge.From("user", User.Type).
Ref("announcement_reads").
Field("user_id").
Unique().
Required(),
}
}
func (AnnouncementRead) Indexes() []ent.Index {
return []ent.Index{
index.Fields("announcement_id"),
index.Fields("user_id"),
index.Fields("read_at"),
index.Fields("announcement_id", "user_id").Unique(),
}
}
......@@ -2,7 +2,7 @@ package schema
import (
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect/entsql"
......@@ -45,7 +45,7 @@ func (APIKey) Fields() []ent.Field {
Nillable(),
field.String("status").
MaxLen(20).
Default(service.StatusActive),
Default(domain.StatusActive),
field.JSON("ip_whitelist", []string{}).
Optional().
Comment("Allowed IPs/CIDRs, e.g. [\"192.168.1.100\", \"10.0.0.0/8\"]"),
......
......@@ -2,7 +2,7 @@ package schema
import (
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
......@@ -49,15 +49,15 @@ func (Group) Fields() []ent.Field {
Default(false),
field.String("status").
MaxLen(20).
Default(service.StatusActive),
Default(domain.StatusActive),
// Subscription-related fields (added by migration 003)
field.String("platform").
MaxLen(50).
Default(service.PlatformAnthropic),
Default(domain.PlatformAnthropic),
field.String("subscription_type").
MaxLen(20).
Default(service.SubscriptionTypeStandard),
Default(domain.SubscriptionTypeStandard),
field.Float("daily_limit_usd").
Optional().
Nillable().
......
......@@ -3,7 +3,7 @@ package schema
import (
"time"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
......@@ -49,7 +49,7 @@ func (PromoCode) Fields() []ent.Field {
Comment("已使用次数"),
field.String("status").
MaxLen(20).
Default(service.PromoCodeStatusActive).
Default(domain.PromoCodeStatusActive).
Comment("状态: active, disabled"),
field.Time("expires_at").
Optional().
......
......@@ -3,7 +3,7 @@ package schema
import (
"time"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
......@@ -41,13 +41,13 @@ func (RedeemCode) Fields() []ent.Field {
Unique(),
field.String("type").
MaxLen(20).
Default(service.RedeemTypeBalance),
Default(domain.RedeemTypeBalance),
field.Float("value").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
Default(0),
field.String("status").
MaxLen(20).
Default(service.StatusUnused),
Default(domain.StatusUnused),
field.Int64("used_by").
Optional().
Nillable(),
......
......@@ -2,7 +2,7 @@ package schema
import (
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
......@@ -43,7 +43,7 @@ func (User) Fields() []ent.Field {
NotEmpty(),
field.String("role").
MaxLen(20).
Default(service.RoleUser),
Default(domain.RoleUser),
field.Float("balance").
SchemaType(map[string]string{dialect.Postgres: "decimal(20,8)"}).
Default(0),
......@@ -51,7 +51,7 @@ func (User) Fields() []ent.Field {
Default(5),
field.String("status").
MaxLen(20).
Default(service.StatusActive),
Default(domain.StatusActive),
// Optional profile fields (added later; default '' in DB migration)
field.String("username").
......@@ -81,6 +81,7 @@ func (User) Edges() []ent.Edge {
edge.To("redeem_codes", RedeemCode.Type),
edge.To("subscriptions", UserSubscription.Type),
edge.To("assigned_subscriptions", UserSubscription.Type),
edge.To("announcement_reads", AnnouncementRead.Type),
edge.To("allowed_groups", Group.Type).
Through("user_allowed_groups", UserAllowedGroup.Type),
edge.To("usage_logs", UsageLog.Type),
......
......@@ -4,7 +4,7 @@ import (
"time"
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/domain"
"entgo.io/ent"
"entgo.io/ent/dialect"
......@@ -44,7 +44,7 @@ func (UserSubscription) Fields() []ent.Field {
SchemaType(map[string]string{dialect.Postgres: "timestamptz"}),
field.String("status").
MaxLen(20).
Default(service.SubscriptionStatusActive),
Default(domain.SubscriptionStatusActive),
field.Time("daily_window_start").
Optional().
......
......@@ -20,6 +20,10 @@ type Tx struct {
Account *AccountClient
// AccountGroup is the client for interacting with the AccountGroup builders.
AccountGroup *AccountGroupClient
// Announcement is the client for interacting with the Announcement builders.
Announcement *AnnouncementClient
// AnnouncementRead is the client for interacting with the AnnouncementRead builders.
AnnouncementRead *AnnouncementReadClient
// Group is the client for interacting with the Group builders.
Group *GroupClient
// PromoCode is the client for interacting with the PromoCode builders.
......@@ -180,6 +184,8 @@ func (tx *Tx) init() {
tx.APIKey = NewAPIKeyClient(tx.config)
tx.Account = NewAccountClient(tx.config)
tx.AccountGroup = NewAccountGroupClient(tx.config)
tx.Announcement = NewAnnouncementClient(tx.config)
tx.AnnouncementRead = NewAnnouncementReadClient(tx.config)
tx.Group = NewGroupClient(tx.config)
tx.PromoCode = NewPromoCodeClient(tx.config)
tx.PromoCodeUsage = NewPromoCodeUsageClient(tx.config)
......
......@@ -61,6 +61,8 @@ type UserEdges struct {
Subscriptions []*UserSubscription `json:"subscriptions,omitempty"`
// AssignedSubscriptions holds the value of the assigned_subscriptions edge.
AssignedSubscriptions []*UserSubscription `json:"assigned_subscriptions,omitempty"`
// AnnouncementReads holds the value of the announcement_reads edge.
AnnouncementReads []*AnnouncementRead `json:"announcement_reads,omitempty"`
// AllowedGroups holds the value of the allowed_groups edge.
AllowedGroups []*Group `json:"allowed_groups,omitempty"`
// UsageLogs holds the value of the usage_logs edge.
......@@ -73,7 +75,7 @@ type UserEdges struct {
UserAllowedGroups []*UserAllowedGroup `json:"user_allowed_groups,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [9]bool
loadedTypes [10]bool
}
// APIKeysOrErr returns the APIKeys value or an error if the edge
......@@ -112,10 +114,19 @@ func (e UserEdges) AssignedSubscriptionsOrErr() ([]*UserSubscription, error) {
return nil, &NotLoadedError{edge: "assigned_subscriptions"}
}
// AnnouncementReadsOrErr returns the AnnouncementReads value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) AnnouncementReadsOrErr() ([]*AnnouncementRead, error) {
if e.loadedTypes[4] {
return e.AnnouncementReads, nil
}
return nil, &NotLoadedError{edge: "announcement_reads"}
}
// AllowedGroupsOrErr returns the AllowedGroups value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) AllowedGroupsOrErr() ([]*Group, error) {
if e.loadedTypes[4] {
if e.loadedTypes[5] {
return e.AllowedGroups, nil
}
return nil, &NotLoadedError{edge: "allowed_groups"}
......@@ -124,7 +135,7 @@ func (e UserEdges) AllowedGroupsOrErr() ([]*Group, error) {
// UsageLogsOrErr returns the UsageLogs value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) UsageLogsOrErr() ([]*UsageLog, error) {
if e.loadedTypes[5] {
if e.loadedTypes[6] {
return e.UsageLogs, nil
}
return nil, &NotLoadedError{edge: "usage_logs"}
......@@ -133,7 +144,7 @@ func (e UserEdges) UsageLogsOrErr() ([]*UsageLog, error) {
// AttributeValuesOrErr returns the AttributeValues value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) AttributeValuesOrErr() ([]*UserAttributeValue, error) {
if e.loadedTypes[6] {
if e.loadedTypes[7] {
return e.AttributeValues, nil
}
return nil, &NotLoadedError{edge: "attribute_values"}
......@@ -142,7 +153,7 @@ func (e UserEdges) AttributeValuesOrErr() ([]*UserAttributeValue, error) {
// PromoCodeUsagesOrErr returns the PromoCodeUsages value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) PromoCodeUsagesOrErr() ([]*PromoCodeUsage, error) {
if e.loadedTypes[7] {
if e.loadedTypes[8] {
return e.PromoCodeUsages, nil
}
return nil, &NotLoadedError{edge: "promo_code_usages"}
......@@ -151,7 +162,7 @@ func (e UserEdges) PromoCodeUsagesOrErr() ([]*PromoCodeUsage, error) {
// UserAllowedGroupsOrErr returns the UserAllowedGroups value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) UserAllowedGroupsOrErr() ([]*UserAllowedGroup, error) {
if e.loadedTypes[8] {
if e.loadedTypes[9] {
return e.UserAllowedGroups, nil
}
return nil, &NotLoadedError{edge: "user_allowed_groups"}
......@@ -313,6 +324,11 @@ func (_m *User) QueryAssignedSubscriptions() *UserSubscriptionQuery {
return NewUserClient(_m.config).QueryAssignedSubscriptions(_m)
}
// QueryAnnouncementReads queries the "announcement_reads" edge of the User entity.
func (_m *User) QueryAnnouncementReads() *AnnouncementReadQuery {
return NewUserClient(_m.config).QueryAnnouncementReads(_m)
}
// QueryAllowedGroups queries the "allowed_groups" edge of the User entity.
func (_m *User) QueryAllowedGroups() *GroupQuery {
return NewUserClient(_m.config).QueryAllowedGroups(_m)
......
......@@ -51,6 +51,8 @@ const (
EdgeSubscriptions = "subscriptions"
// EdgeAssignedSubscriptions holds the string denoting the assigned_subscriptions edge name in mutations.
EdgeAssignedSubscriptions = "assigned_subscriptions"
// EdgeAnnouncementReads holds the string denoting the announcement_reads edge name in mutations.
EdgeAnnouncementReads = "announcement_reads"
// EdgeAllowedGroups holds the string denoting the allowed_groups edge name in mutations.
EdgeAllowedGroups = "allowed_groups"
// EdgeUsageLogs holds the string denoting the usage_logs edge name in mutations.
......@@ -91,6 +93,13 @@ const (
AssignedSubscriptionsInverseTable = "user_subscriptions"
// AssignedSubscriptionsColumn is the table column denoting the assigned_subscriptions relation/edge.
AssignedSubscriptionsColumn = "assigned_by"
// AnnouncementReadsTable is the table that holds the announcement_reads relation/edge.
AnnouncementReadsTable = "announcement_reads"
// AnnouncementReadsInverseTable is the table name for the AnnouncementRead entity.
// It exists in this package in order to avoid circular dependency with the "announcementread" package.
AnnouncementReadsInverseTable = "announcement_reads"
// AnnouncementReadsColumn is the table column denoting the announcement_reads relation/edge.
AnnouncementReadsColumn = "user_id"
// AllowedGroupsTable is the table that holds the allowed_groups relation/edge. The primary key declared below.
AllowedGroupsTable = "user_allowed_groups"
// AllowedGroupsInverseTable is the table name for the Group entity.
......@@ -335,6 +344,20 @@ func ByAssignedSubscriptions(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOp
}
}
// ByAnnouncementReadsCount orders the results by announcement_reads count.
func ByAnnouncementReadsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newAnnouncementReadsStep(), opts...)
}
}
// ByAnnouncementReads orders the results by announcement_reads terms.
func ByAnnouncementReads(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newAnnouncementReadsStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByAllowedGroupsCount orders the results by allowed_groups count.
func ByAllowedGroupsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
......@@ -432,6 +455,13 @@ func newAssignedSubscriptionsStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.O2M, false, AssignedSubscriptionsTable, AssignedSubscriptionsColumn),
)
}
func newAnnouncementReadsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(AnnouncementReadsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, AnnouncementReadsTable, AnnouncementReadsColumn),
)
}
func newAllowedGroupsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
......
......@@ -952,6 +952,29 @@ func HasAssignedSubscriptionsWith(preds ...predicate.UserSubscription) predicate
})
}
// HasAnnouncementReads applies the HasEdge predicate on the "announcement_reads" edge.
func HasAnnouncementReads() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, AnnouncementReadsTable, AnnouncementReadsColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasAnnouncementReadsWith applies the HasEdge predicate on the "announcement_reads" edge with a given conditions (other predicates).
func HasAnnouncementReadsWith(preds ...predicate.AnnouncementRead) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := newAnnouncementReadsStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasAllowedGroups applies the HasEdge predicate on the "allowed_groups" edge.
func HasAllowedGroups() predicate.User {
return predicate.User(func(s *sql.Selector) {
......
......@@ -11,6 +11,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
......@@ -269,6 +270,21 @@ func (_c *UserCreate) AddAssignedSubscriptions(v ...*UserSubscription) *UserCrea
return _c.AddAssignedSubscriptionIDs(ids...)
}
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by IDs.
func (_c *UserCreate) AddAnnouncementReadIDs(ids ...int64) *UserCreate {
_c.mutation.AddAnnouncementReadIDs(ids...)
return _c
}
// AddAnnouncementReads adds the "announcement_reads" edges to the AnnouncementRead entity.
func (_c *UserCreate) AddAnnouncementReads(v ...*AnnouncementRead) *UserCreate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _c.AddAnnouncementReadIDs(ids...)
}
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by IDs.
func (_c *UserCreate) AddAllowedGroupIDs(ids ...int64) *UserCreate {
_c.mutation.AddAllowedGroupIDs(ids...)
......@@ -618,6 +634,22 @@ func (_c *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := _c.mutation.AnnouncementReadsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := _c.mutation.AllowedGroupsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
......
......@@ -13,6 +13,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/predicate"
......@@ -36,6 +37,7 @@ type UserQuery struct {
withRedeemCodes *RedeemCodeQuery
withSubscriptions *UserSubscriptionQuery
withAssignedSubscriptions *UserSubscriptionQuery
withAnnouncementReads *AnnouncementReadQuery
withAllowedGroups *GroupQuery
withUsageLogs *UsageLogQuery
withAttributeValues *UserAttributeValueQuery
......@@ -166,6 +168,28 @@ func (_q *UserQuery) QueryAssignedSubscriptions() *UserSubscriptionQuery {
return query
}
// QueryAnnouncementReads chains the current query on the "announcement_reads" edge.
func (_q *UserQuery) QueryAnnouncementReads() *AnnouncementReadQuery {
query := (&AnnouncementReadClient{config: _q.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := _q.prepareQuery(ctx); err != nil {
return nil, err
}
selector := _q.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, selector),
sqlgraph.To(announcementread.Table, announcementread.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, user.AnnouncementReadsTable, user.AnnouncementReadsColumn),
)
fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryAllowedGroups chains the current query on the "allowed_groups" edge.
func (_q *UserQuery) QueryAllowedGroups() *GroupQuery {
query := (&GroupClient{config: _q.config}).Query()
......@@ -472,6 +496,7 @@ func (_q *UserQuery) Clone() *UserQuery {
withRedeemCodes: _q.withRedeemCodes.Clone(),
withSubscriptions: _q.withSubscriptions.Clone(),
withAssignedSubscriptions: _q.withAssignedSubscriptions.Clone(),
withAnnouncementReads: _q.withAnnouncementReads.Clone(),
withAllowedGroups: _q.withAllowedGroups.Clone(),
withUsageLogs: _q.withUsageLogs.Clone(),
withAttributeValues: _q.withAttributeValues.Clone(),
......@@ -527,6 +552,17 @@ func (_q *UserQuery) WithAssignedSubscriptions(opts ...func(*UserSubscriptionQue
return _q
}
// WithAnnouncementReads tells the query-builder to eager-load the nodes that are connected to
// the "announcement_reads" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *UserQuery) WithAnnouncementReads(opts ...func(*AnnouncementReadQuery)) *UserQuery {
query := (&AnnouncementReadClient{config: _q.config}).Query()
for _, opt := range opts {
opt(query)
}
_q.withAnnouncementReads = query
return _q
}
// WithAllowedGroups tells the query-builder to eager-load the nodes that are connected to
// the "allowed_groups" edge. The optional arguments are used to configure the query builder of the edge.
func (_q *UserQuery) WithAllowedGroups(opts ...func(*GroupQuery)) *UserQuery {
......@@ -660,11 +696,12 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
var (
nodes = []*User{}
_spec = _q.querySpec()
loadedTypes = [9]bool{
loadedTypes = [10]bool{
_q.withAPIKeys != nil,
_q.withRedeemCodes != nil,
_q.withSubscriptions != nil,
_q.withAssignedSubscriptions != nil,
_q.withAnnouncementReads != nil,
_q.withAllowedGroups != nil,
_q.withUsageLogs != nil,
_q.withAttributeValues != nil,
......@@ -723,6 +760,13 @@ func (_q *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
return nil, err
}
}
if query := _q.withAnnouncementReads; query != nil {
if err := _q.loadAnnouncementReads(ctx, query, nodes,
func(n *User) { n.Edges.AnnouncementReads = []*AnnouncementRead{} },
func(n *User, e *AnnouncementRead) { n.Edges.AnnouncementReads = append(n.Edges.AnnouncementReads, e) }); err != nil {
return nil, err
}
}
if query := _q.withAllowedGroups; query != nil {
if err := _q.loadAllowedGroups(ctx, query, nodes,
func(n *User) { n.Edges.AllowedGroups = []*Group{} },
......@@ -887,6 +931,36 @@ func (_q *UserQuery) loadAssignedSubscriptions(ctx context.Context, query *UserS
}
return nil
}
func (_q *UserQuery) loadAnnouncementReads(ctx context.Context, query *AnnouncementReadQuery, nodes []*User, init func(*User), assign func(*User, *AnnouncementRead)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[int64]*User)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
if len(query.ctx.Fields) > 0 {
query.ctx.AppendFieldOnce(announcementread.FieldUserID)
}
query.Where(predicate.AnnouncementRead(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(user.AnnouncementReadsColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.UserID
node, ok := nodeids[fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "user_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
return nil
}
func (_q *UserQuery) loadAllowedGroups(ctx context.Context, query *GroupQuery, nodes []*User, init func(*User), assign func(*User, *Group)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[int64]*User)
......
......@@ -11,6 +11,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/predicate"
......@@ -301,6 +302,21 @@ func (_u *UserUpdate) AddAssignedSubscriptions(v ...*UserSubscription) *UserUpda
return _u.AddAssignedSubscriptionIDs(ids...)
}
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by IDs.
func (_u *UserUpdate) AddAnnouncementReadIDs(ids ...int64) *UserUpdate {
_u.mutation.AddAnnouncementReadIDs(ids...)
return _u
}
// AddAnnouncementReads adds the "announcement_reads" edges to the AnnouncementRead entity.
func (_u *UserUpdate) AddAnnouncementReads(v ...*AnnouncementRead) *UserUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.AddAnnouncementReadIDs(ids...)
}
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by IDs.
func (_u *UserUpdate) AddAllowedGroupIDs(ids ...int64) *UserUpdate {
_u.mutation.AddAllowedGroupIDs(ids...)
......@@ -450,6 +466,27 @@ func (_u *UserUpdate) RemoveAssignedSubscriptions(v ...*UserSubscription) *UserU
return _u.RemoveAssignedSubscriptionIDs(ids...)
}
// ClearAnnouncementReads clears all "announcement_reads" edges to the AnnouncementRead entity.
func (_u *UserUpdate) ClearAnnouncementReads() *UserUpdate {
_u.mutation.ClearAnnouncementReads()
return _u
}
// RemoveAnnouncementReadIDs removes the "announcement_reads" edge to AnnouncementRead entities by IDs.
func (_u *UserUpdate) RemoveAnnouncementReadIDs(ids ...int64) *UserUpdate {
_u.mutation.RemoveAnnouncementReadIDs(ids...)
return _u
}
// RemoveAnnouncementReads removes "announcement_reads" edges to AnnouncementRead entities.
func (_u *UserUpdate) RemoveAnnouncementReads(v ...*AnnouncementRead) *UserUpdate {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.RemoveAnnouncementReadIDs(ids...)
}
// ClearAllowedGroups clears all "allowed_groups" edges to the Group entity.
func (_u *UserUpdate) ClearAllowedGroups() *UserUpdate {
_u.mutation.ClearAllowedGroups()
......@@ -852,6 +889,51 @@ func (_u *UserUpdate) sqlSave(ctx context.Context) (_node int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _u.mutation.AnnouncementReadsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.RemovedAnnouncementReadsIDs(); len(nodes) > 0 && !_u.mutation.AnnouncementReadsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.AnnouncementReadsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _u.mutation.AllowedGroupsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
......@@ -1330,6 +1412,21 @@ func (_u *UserUpdateOne) AddAssignedSubscriptions(v ...*UserSubscription) *UserU
return _u.AddAssignedSubscriptionIDs(ids...)
}
// AddAnnouncementReadIDs adds the "announcement_reads" edge to the AnnouncementRead entity by IDs.
func (_u *UserUpdateOne) AddAnnouncementReadIDs(ids ...int64) *UserUpdateOne {
_u.mutation.AddAnnouncementReadIDs(ids...)
return _u
}
// AddAnnouncementReads adds the "announcement_reads" edges to the AnnouncementRead entity.
func (_u *UserUpdateOne) AddAnnouncementReads(v ...*AnnouncementRead) *UserUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.AddAnnouncementReadIDs(ids...)
}
// AddAllowedGroupIDs adds the "allowed_groups" edge to the Group entity by IDs.
func (_u *UserUpdateOne) AddAllowedGroupIDs(ids ...int64) *UserUpdateOne {
_u.mutation.AddAllowedGroupIDs(ids...)
......@@ -1479,6 +1576,27 @@ func (_u *UserUpdateOne) RemoveAssignedSubscriptions(v ...*UserSubscription) *Us
return _u.RemoveAssignedSubscriptionIDs(ids...)
}
// ClearAnnouncementReads clears all "announcement_reads" edges to the AnnouncementRead entity.
func (_u *UserUpdateOne) ClearAnnouncementReads() *UserUpdateOne {
_u.mutation.ClearAnnouncementReads()
return _u
}
// RemoveAnnouncementReadIDs removes the "announcement_reads" edge to AnnouncementRead entities by IDs.
func (_u *UserUpdateOne) RemoveAnnouncementReadIDs(ids ...int64) *UserUpdateOne {
_u.mutation.RemoveAnnouncementReadIDs(ids...)
return _u
}
// RemoveAnnouncementReads removes "announcement_reads" edges to AnnouncementRead entities.
func (_u *UserUpdateOne) RemoveAnnouncementReads(v ...*AnnouncementRead) *UserUpdateOne {
ids := make([]int64, len(v))
for i := range v {
ids[i] = v[i].ID
}
return _u.RemoveAnnouncementReadIDs(ids...)
}
// ClearAllowedGroups clears all "allowed_groups" edges to the Group entity.
func (_u *UserUpdateOne) ClearAllowedGroups() *UserUpdateOne {
_u.mutation.ClearAllowedGroups()
......@@ -1911,6 +2029,51 @@ func (_u *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _u.mutation.AnnouncementReadsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.RemovedAnnouncementReadsIDs(); len(nodes) > 0 && !_u.mutation.AnnouncementReadsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := _u.mutation.AnnouncementReadsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.AnnouncementReadsTable,
Columns: []string{user.AnnouncementReadsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(announcementread.FieldID, field.TypeInt64),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if _u.mutation.AllowedGroupsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
......
package domain
import (
"strings"
"time"
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
)
const (
AnnouncementStatusDraft = "draft"
AnnouncementStatusActive = "active"
AnnouncementStatusArchived = "archived"
)
const (
AnnouncementConditionTypeSubscription = "subscription"
AnnouncementConditionTypeBalance = "balance"
)
const (
AnnouncementOperatorIn = "in"
AnnouncementOperatorGT = "gt"
AnnouncementOperatorGTE = "gte"
AnnouncementOperatorLT = "lt"
AnnouncementOperatorLTE = "lte"
AnnouncementOperatorEQ = "eq"
)
var (
ErrAnnouncementNotFound = infraerrors.NotFound("ANNOUNCEMENT_NOT_FOUND", "announcement not found")
ErrAnnouncementInvalidTarget = infraerrors.BadRequest("ANNOUNCEMENT_INVALID_TARGET", "invalid announcement targeting rules")
)
type AnnouncementTargeting struct {
// AnyOf 表示 OR:任意一个条件组满足即可展示。
AnyOf []AnnouncementConditionGroup `json:"any_of,omitempty"`
}
type AnnouncementConditionGroup struct {
// AllOf 表示 AND:组内所有条件都满足才算命中该组。
AllOf []AnnouncementCondition `json:"all_of,omitempty"`
}
type AnnouncementCondition struct {
// Type: subscription | balance
Type string `json:"type"`
// Operator:
// - subscription: in
// - balance: gt/gte/lt/lte/eq
Operator string `json:"operator"`
// subscription 条件:匹配的订阅套餐(group_id)
GroupIDs []int64 `json:"group_ids,omitempty"`
// balance 条件:比较阈值
Value float64 `json:"value,omitempty"`
}
func (t AnnouncementTargeting) Matches(balance float64, activeSubscriptionGroupIDs map[int64]struct{}) bool {
// 空规则:展示给所有用户
if len(t.AnyOf) == 0 {
return true
}
for _, group := range t.AnyOf {
if len(group.AllOf) == 0 {
// 空条件组不命中(避免 OR 中出现无条件 “全命中”)
continue
}
allMatched := true
for _, cond := range group.AllOf {
if !cond.Matches(balance, activeSubscriptionGroupIDs) {
allMatched = false
break
}
}
if allMatched {
return true
}
}
return false
}
func (c AnnouncementCondition) Matches(balance float64, activeSubscriptionGroupIDs map[int64]struct{}) bool {
switch c.Type {
case AnnouncementConditionTypeSubscription:
if c.Operator != AnnouncementOperatorIn {
return false
}
if len(c.GroupIDs) == 0 {
return false
}
if len(activeSubscriptionGroupIDs) == 0 {
return false
}
for _, gid := range c.GroupIDs {
if _, ok := activeSubscriptionGroupIDs[gid]; ok {
return true
}
}
return false
case AnnouncementConditionTypeBalance:
switch c.Operator {
case AnnouncementOperatorGT:
return balance > c.Value
case AnnouncementOperatorGTE:
return balance >= c.Value
case AnnouncementOperatorLT:
return balance < c.Value
case AnnouncementOperatorLTE:
return balance <= c.Value
case AnnouncementOperatorEQ:
return balance == c.Value
default:
return false
}
default:
return false
}
}
func (t AnnouncementTargeting) NormalizeAndValidate() (AnnouncementTargeting, error) {
normalized := AnnouncementTargeting{AnyOf: make([]AnnouncementConditionGroup, 0, len(t.AnyOf))}
// 允许空 targeting(展示给所有用户)
if len(t.AnyOf) == 0 {
return normalized, nil
}
if len(t.AnyOf) > 50 {
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
}
for _, g := range t.AnyOf {
if len(g.AllOf) == 0 {
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
}
if len(g.AllOf) > 50 {
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
}
group := AnnouncementConditionGroup{AllOf: make([]AnnouncementCondition, 0, len(g.AllOf))}
for _, c := range g.AllOf {
cond := AnnouncementCondition{
Type: strings.TrimSpace(c.Type),
Operator: strings.TrimSpace(c.Operator),
Value: c.Value,
}
for _, gid := range c.GroupIDs {
if gid <= 0 {
return AnnouncementTargeting{}, ErrAnnouncementInvalidTarget
}
cond.GroupIDs = append(cond.GroupIDs, gid)
}
if err := cond.validate(); err != nil {
return AnnouncementTargeting{}, err
}
group.AllOf = append(group.AllOf, cond)
}
normalized.AnyOf = append(normalized.AnyOf, group)
}
return normalized, nil
}
func (c AnnouncementCondition) validate() error {
switch c.Type {
case AnnouncementConditionTypeSubscription:
if c.Operator != AnnouncementOperatorIn {
return ErrAnnouncementInvalidTarget
}
if len(c.GroupIDs) == 0 {
return ErrAnnouncementInvalidTarget
}
return nil
case AnnouncementConditionTypeBalance:
switch c.Operator {
case AnnouncementOperatorGT, AnnouncementOperatorGTE, AnnouncementOperatorLT, AnnouncementOperatorLTE, AnnouncementOperatorEQ:
return nil
default:
return ErrAnnouncementInvalidTarget
}
default:
return ErrAnnouncementInvalidTarget
}
}
type Announcement struct {
ID int64
Title string
Content string
Status string
Targeting AnnouncementTargeting
StartsAt *time.Time
EndsAt *time.Time
CreatedBy *int64
UpdatedBy *int64
CreatedAt time.Time
UpdatedAt time.Time
}
func (a *Announcement) IsActiveAt(now time.Time) bool {
if a == nil {
return false
}
if a.Status != AnnouncementStatusActive {
return false
}
if a.StartsAt != nil && now.Before(*a.StartsAt) {
return false
}
if a.EndsAt != nil && !now.Before(*a.EndsAt) {
// ends_at 语义:到点即下线
return false
}
return true
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment