| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- package repository
- import (
- "context"
- dbent "github.com/Wei-Shaw/sub2api/ent"
- "github.com/Wei-Shaw/sub2api/ent/userattributedefinition"
- "github.com/Wei-Shaw/sub2api/ent/userattributevalue"
- "github.com/Wei-Shaw/sub2api/internal/service"
- )
- // UserAttributeDefinitionRepository implementation
- type userAttributeDefinitionRepository struct {
- client *dbent.Client
- }
- // NewUserAttributeDefinitionRepository creates a new repository instance
- func NewUserAttributeDefinitionRepository(client *dbent.Client) service.UserAttributeDefinitionRepository {
- return &userAttributeDefinitionRepository{client: client}
- }
- func (r *userAttributeDefinitionRepository) Create(ctx context.Context, def *service.UserAttributeDefinition) error {
- client := clientFromContext(ctx, r.client)
- created, err := client.UserAttributeDefinition.Create().
- SetKey(def.Key).
- SetName(def.Name).
- SetDescription(def.Description).
- SetType(string(def.Type)).
- SetOptions(toEntOptions(def.Options)).
- SetRequired(def.Required).
- SetValidation(toEntValidation(def.Validation)).
- SetPlaceholder(def.Placeholder).
- SetEnabled(def.Enabled).
- Save(ctx)
- if err != nil {
- return translatePersistenceError(err, nil, service.ErrAttributeKeyExists)
- }
- def.ID = created.ID
- def.DisplayOrder = created.DisplayOrder
- def.CreatedAt = created.CreatedAt
- def.UpdatedAt = created.UpdatedAt
- return nil
- }
- func (r *userAttributeDefinitionRepository) GetByID(ctx context.Context, id int64) (*service.UserAttributeDefinition, error) {
- client := clientFromContext(ctx, r.client)
- e, err := client.UserAttributeDefinition.Query().
- Where(userattributedefinition.IDEQ(id)).
- Only(ctx)
- if err != nil {
- return nil, translatePersistenceError(err, service.ErrAttributeDefinitionNotFound, nil)
- }
- return defEntityToService(e), nil
- }
- func (r *userAttributeDefinitionRepository) GetByKey(ctx context.Context, key string) (*service.UserAttributeDefinition, error) {
- client := clientFromContext(ctx, r.client)
- e, err := client.UserAttributeDefinition.Query().
- Where(userattributedefinition.KeyEQ(key)).
- Only(ctx)
- if err != nil {
- return nil, translatePersistenceError(err, service.ErrAttributeDefinitionNotFound, nil)
- }
- return defEntityToService(e), nil
- }
- func (r *userAttributeDefinitionRepository) Update(ctx context.Context, def *service.UserAttributeDefinition) error {
- client := clientFromContext(ctx, r.client)
- updated, err := client.UserAttributeDefinition.UpdateOneID(def.ID).
- SetName(def.Name).
- SetDescription(def.Description).
- SetType(string(def.Type)).
- SetOptions(toEntOptions(def.Options)).
- SetRequired(def.Required).
- SetValidation(toEntValidation(def.Validation)).
- SetPlaceholder(def.Placeholder).
- SetDisplayOrder(def.DisplayOrder).
- SetEnabled(def.Enabled).
- Save(ctx)
- if err != nil {
- return translatePersistenceError(err, service.ErrAttributeDefinitionNotFound, service.ErrAttributeKeyExists)
- }
- def.UpdatedAt = updated.UpdatedAt
- return nil
- }
- func (r *userAttributeDefinitionRepository) Delete(ctx context.Context, id int64) error {
- client := clientFromContext(ctx, r.client)
- _, err := client.UserAttributeDefinition.Delete().
- Where(userattributedefinition.IDEQ(id)).
- Exec(ctx)
- return translatePersistenceError(err, service.ErrAttributeDefinitionNotFound, nil)
- }
- func (r *userAttributeDefinitionRepository) List(ctx context.Context, enabledOnly bool) ([]service.UserAttributeDefinition, error) {
- client := clientFromContext(ctx, r.client)
- q := client.UserAttributeDefinition.Query()
- if enabledOnly {
- q = q.Where(userattributedefinition.EnabledEQ(true))
- }
- entities, err := q.Order(dbent.Asc(userattributedefinition.FieldDisplayOrder)).All(ctx)
- if err != nil {
- return nil, err
- }
- result := make([]service.UserAttributeDefinition, 0, len(entities))
- for _, e := range entities {
- result = append(result, *defEntityToService(e))
- }
- return result, nil
- }
- func (r *userAttributeDefinitionRepository) UpdateDisplayOrders(ctx context.Context, orders map[int64]int) error {
- tx, err := r.client.Tx(ctx)
- if err != nil {
- return err
- }
- defer func() { _ = tx.Rollback() }()
- for id, order := range orders {
- if _, err := tx.UserAttributeDefinition.UpdateOneID(id).
- SetDisplayOrder(order).
- Save(ctx); err != nil {
- return translatePersistenceError(err, service.ErrAttributeDefinitionNotFound, nil)
- }
- }
- return tx.Commit()
- }
- func (r *userAttributeDefinitionRepository) ExistsByKey(ctx context.Context, key string) (bool, error) {
- client := clientFromContext(ctx, r.client)
- return client.UserAttributeDefinition.Query().
- Where(userattributedefinition.KeyEQ(key)).
- Exist(ctx)
- }
- // UserAttributeValueRepository implementation
- type userAttributeValueRepository struct {
- client *dbent.Client
- }
- // NewUserAttributeValueRepository creates a new repository instance
- func NewUserAttributeValueRepository(client *dbent.Client) service.UserAttributeValueRepository {
- return &userAttributeValueRepository{client: client}
- }
- func (r *userAttributeValueRepository) GetByUserID(ctx context.Context, userID int64) ([]service.UserAttributeValue, error) {
- client := clientFromContext(ctx, r.client)
- entities, err := client.UserAttributeValue.Query().
- Where(userattributevalue.UserIDEQ(userID)).
- All(ctx)
- if err != nil {
- return nil, err
- }
- result := make([]service.UserAttributeValue, 0, len(entities))
- for _, e := range entities {
- result = append(result, service.UserAttributeValue{
- ID: e.ID,
- UserID: e.UserID,
- AttributeID: e.AttributeID,
- Value: e.Value,
- CreatedAt: e.CreatedAt,
- UpdatedAt: e.UpdatedAt,
- })
- }
- return result, nil
- }
- func (r *userAttributeValueRepository) GetByUserIDs(ctx context.Context, userIDs []int64) ([]service.UserAttributeValue, error) {
- if len(userIDs) == 0 {
- return []service.UserAttributeValue{}, nil
- }
- client := clientFromContext(ctx, r.client)
- entities, err := client.UserAttributeValue.Query().
- Where(userattributevalue.UserIDIn(userIDs...)).
- All(ctx)
- if err != nil {
- return nil, err
- }
- result := make([]service.UserAttributeValue, 0, len(entities))
- for _, e := range entities {
- result = append(result, service.UserAttributeValue{
- ID: e.ID,
- UserID: e.UserID,
- AttributeID: e.AttributeID,
- Value: e.Value,
- CreatedAt: e.CreatedAt,
- UpdatedAt: e.UpdatedAt,
- })
- }
- return result, nil
- }
- func (r *userAttributeValueRepository) UpsertBatch(ctx context.Context, userID int64, inputs []service.UpdateUserAttributeInput) error {
- if len(inputs) == 0 {
- return nil
- }
- tx, err := r.client.Tx(ctx)
- if err != nil {
- return err
- }
- defer func() { _ = tx.Rollback() }()
- for _, input := range inputs {
- // Use upsert (ON CONFLICT DO UPDATE)
- err := tx.UserAttributeValue.Create().
- SetUserID(userID).
- SetAttributeID(input.AttributeID).
- SetValue(input.Value).
- OnConflictColumns(userattributevalue.FieldUserID, userattributevalue.FieldAttributeID).
- UpdateValue().
- UpdateUpdatedAt().
- Exec(ctx)
- if err != nil {
- return err
- }
- }
- return tx.Commit()
- }
- func (r *userAttributeValueRepository) DeleteByAttributeID(ctx context.Context, attributeID int64) error {
- client := clientFromContext(ctx, r.client)
- _, err := client.UserAttributeValue.Delete().
- Where(userattributevalue.AttributeIDEQ(attributeID)).
- Exec(ctx)
- return err
- }
- func (r *userAttributeValueRepository) DeleteByUserID(ctx context.Context, userID int64) error {
- client := clientFromContext(ctx, r.client)
- _, err := client.UserAttributeValue.Delete().
- Where(userattributevalue.UserIDEQ(userID)).
- Exec(ctx)
- return err
- }
- // Helper functions for entity to service conversion
- func defEntityToService(e *dbent.UserAttributeDefinition) *service.UserAttributeDefinition {
- if e == nil {
- return nil
- }
- return &service.UserAttributeDefinition{
- ID: e.ID,
- Key: e.Key,
- Name: e.Name,
- Description: e.Description,
- Type: service.UserAttributeType(e.Type),
- Options: toServiceOptions(e.Options),
- Required: e.Required,
- Validation: toServiceValidation(e.Validation),
- Placeholder: e.Placeholder,
- DisplayOrder: e.DisplayOrder,
- Enabled: e.Enabled,
- CreatedAt: e.CreatedAt,
- UpdatedAt: e.UpdatedAt,
- }
- }
- // Type conversion helpers (map types <-> service types)
- func toEntOptions(opts []service.UserAttributeOption) []map[string]any {
- if opts == nil {
- return []map[string]any{}
- }
- result := make([]map[string]any, len(opts))
- for i, o := range opts {
- result[i] = map[string]any{"value": o.Value, "label": o.Label}
- }
- return result
- }
- func toServiceOptions(opts []map[string]any) []service.UserAttributeOption {
- if opts == nil {
- return []service.UserAttributeOption{}
- }
- result := make([]service.UserAttributeOption, len(opts))
- for i, o := range opts {
- result[i] = service.UserAttributeOption{
- Value: getString(o, "value"),
- Label: getString(o, "label"),
- }
- }
- return result
- }
- func toEntValidation(v service.UserAttributeValidation) map[string]any {
- result := map[string]any{}
- if v.MinLength != nil {
- result["min_length"] = *v.MinLength
- }
- if v.MaxLength != nil {
- result["max_length"] = *v.MaxLength
- }
- if v.Min != nil {
- result["min"] = *v.Min
- }
- if v.Max != nil {
- result["max"] = *v.Max
- }
- if v.Pattern != nil {
- result["pattern"] = *v.Pattern
- }
- if v.Message != nil {
- result["message"] = *v.Message
- }
- return result
- }
- func toServiceValidation(v map[string]any) service.UserAttributeValidation {
- result := service.UserAttributeValidation{}
- if val := getInt(v, "min_length"); val != nil {
- result.MinLength = val
- }
- if val := getInt(v, "max_length"); val != nil {
- result.MaxLength = val
- }
- if val := getInt(v, "min"); val != nil {
- result.Min = val
- }
- if val := getInt(v, "max"); val != nil {
- result.Max = val
- }
- if val := getStringPtr(v, "pattern"); val != nil {
- result.Pattern = val
- }
- if val := getStringPtr(v, "message"); val != nil {
- result.Message = val
- }
- return result
- }
- // Helper functions for type conversion
- func getString(m map[string]any, key string) string {
- if v, ok := m[key]; ok {
- if s, ok := v.(string); ok {
- return s
- }
- }
- return ""
- }
- func getStringPtr(m map[string]any, key string) *string {
- if v, ok := m[key]; ok {
- if s, ok := v.(string); ok {
- return &s
- }
- }
- return nil
- }
- func getInt(m map[string]any, key string) *int {
- if v, ok := m[key]; ok {
- switch n := v.(type) {
- case int:
- return &n
- case int64:
- i := int(n)
- return &i
- case float64:
- i := int(n)
- return &i
- }
- }
- return nil
- }
|